Name resolution context added (BUG#6443)
This commit is contained in:
parent
d8cb0cbc3f
commit
d3905f3d0e
@ -45,6 +45,8 @@ extern my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size);
|
||||
extern my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit);
|
||||
extern my_bool bitmap_is_set_all(const MY_BITMAP *map);
|
||||
extern my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2);
|
||||
extern my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit);
|
||||
extern my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit);
|
||||
extern uint bitmap_set_next(MY_BITMAP *map);
|
||||
extern uint bitmap_get_first(const MY_BITMAP *map);
|
||||
extern uint bitmap_bits_set(const MY_BITMAP *map);
|
||||
|
@ -754,6 +754,8 @@ create view v1 as select * from t1;
|
||||
create view v2 as select * from t2;
|
||||
insert into v1 values (1);
|
||||
insert into v2 values (1);
|
||||
Warnings:
|
||||
Warning 1423 Field of view 'test.v2' underlying table doesn't have a default value
|
||||
create view v3 (a,b) as select v1.col1 as a, v2.col1 as b from v1, v2 where v1.col1 = v2.col1;
|
||||
select * from v3;
|
||||
a b
|
||||
@ -1850,3 +1852,16 @@ SELECT * FROM v1;
|
||||
SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1)
|
||||
dkjhgd
|
||||
drop view v1;
|
||||
set sql_mode='strict_all_tables';
|
||||
CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL) ENGINE = INNODB;
|
||||
CREATE VIEW v1 (vcol1) AS SELECT col1 FROM t1;
|
||||
CREATE VIEW v2 (vcol1) AS SELECT col1 FROM t1 WHERE col2 > 2;
|
||||
INSERT INTO t1 (col1) VALUES(12);
|
||||
ERROR HY000: Field 'col2' doesn't have a default value
|
||||
INSERT INTO v1 (vcol1) VALUES(12);
|
||||
ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default value
|
||||
INSERT INTO v2 (vcol1) VALUES(12);
|
||||
ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default value
|
||||
set sql_mode=default;
|
||||
drop view v2,v1;
|
||||
drop table t1;
|
||||
|
@ -1696,3 +1696,21 @@ drop view v1;
|
||||
CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1);
|
||||
SELECT * FROM v1;
|
||||
drop view v1;
|
||||
|
||||
#
|
||||
# Correct inserting data check (absence of default value) for view
|
||||
# underlying tables (BUG#6443)
|
||||
#
|
||||
set sql_mode='strict_all_tables';
|
||||
CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL) ENGINE = INNODB;
|
||||
CREATE VIEW v1 (vcol1) AS SELECT col1 FROM t1;
|
||||
CREATE VIEW v2 (vcol1) AS SELECT col1 FROM t1 WHERE col2 > 2;
|
||||
-- error 1364
|
||||
INSERT INTO t1 (col1) VALUES(12);
|
||||
-- error 1423
|
||||
INSERT INTO v1 (vcol1) VALUES(12);
|
||||
-- error 1423
|
||||
INSERT INTO v2 (vcol1) VALUES(12);
|
||||
set sql_mode=default;
|
||||
drop view v2,v1;
|
||||
drop table t1;
|
||||
|
@ -109,6 +109,51 @@ void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
test if bit already set and set it if it was not (thread unsafe method)
|
||||
|
||||
SYNOPSIS
|
||||
bitmap_fast_test_and_set()
|
||||
MAP bit map struct
|
||||
BIT bit number
|
||||
|
||||
RETURN
|
||||
0 bit was not set
|
||||
!=0 bit was set
|
||||
*/
|
||||
|
||||
my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit)
|
||||
{
|
||||
uchar *byte= map->bitmap + (bitmap_bit / 8);
|
||||
uchar bit= 1 << ((bitmap_bit) & 7);
|
||||
uchar res= (*byte) & bit;
|
||||
*byte|= bit;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
test if bit already set and set it if it was not (thread safe method)
|
||||
|
||||
SYNOPSIS
|
||||
bitmap_fast_test_and_set()
|
||||
map bit map struct
|
||||
bitmap_bit bit number
|
||||
|
||||
RETURN
|
||||
0 bit was not set
|
||||
!=0 bit was set
|
||||
*/
|
||||
|
||||
my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit)
|
||||
{
|
||||
my_bool res;
|
||||
DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
|
||||
bitmap_lock(map);
|
||||
res= bitmap_fast_test_and_set(map, bitmap_bit);
|
||||
bitmap_unlock(map);
|
||||
}
|
||||
|
||||
uint bitmap_set_next(MY_BITMAP *map)
|
||||
{
|
||||
uchar *bitmap=map->bitmap;
|
||||
|
@ -86,6 +86,7 @@ public:
|
||||
|
||||
utype unireg_check;
|
||||
uint32 field_length; // Length of field
|
||||
uint field_index; // field number in fields array
|
||||
uint16 flags;
|
||||
uchar null_bit; // Bit used to test null bit
|
||||
|
||||
|
406
sql/item.cc
406
sql/item.cc
@ -440,16 +440,17 @@ void Item::rename(char *new_name)
|
||||
}
|
||||
|
||||
|
||||
Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
|
||||
const char *field_name_par)
|
||||
:orig_db_name(db_name_par), orig_table_name(table_name_par),
|
||||
orig_field_name(field_name_par),
|
||||
db_name(db_name_par), table_name(table_name_par),
|
||||
field_name(field_name_par),
|
||||
Item_ident::Item_ident(Name_resolution_context *context_arg,
|
||||
const char *db_name_arg,const char *table_name_arg,
|
||||
const char *field_name_arg)
|
||||
:orig_db_name(db_name_arg), orig_table_name(table_name_arg),
|
||||
orig_field_name(field_name_arg), context(context_arg),
|
||||
db_name(db_name_arg), table_name(table_name_arg),
|
||||
field_name(field_name_arg),
|
||||
alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
|
||||
cached_table(0), depended_from(0)
|
||||
{
|
||||
name = (char*) field_name_par;
|
||||
name = (char*) field_name_arg;
|
||||
}
|
||||
|
||||
|
||||
@ -460,6 +461,7 @@ Item_ident::Item_ident(THD *thd, Item_ident *item)
|
||||
orig_db_name(item->orig_db_name),
|
||||
orig_table_name(item->orig_table_name),
|
||||
orig_field_name(item->orig_field_name),
|
||||
context(item->context),
|
||||
db_name(item->db_name),
|
||||
table_name(item->table_name),
|
||||
field_name(item->field_name),
|
||||
@ -785,7 +787,7 @@ Item_splocal::type() const
|
||||
}
|
||||
|
||||
|
||||
bool Item_splocal::fix_fields(THD *, struct st_table_list *, Item **)
|
||||
bool Item_splocal::fix_fields(THD *, Item **)
|
||||
{
|
||||
Item *it= this_item();
|
||||
DBUG_ASSERT(it->fixed);
|
||||
@ -855,7 +857,8 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
|
||||
uint el= fields.elements;
|
||||
Item *new_item;
|
||||
ref_pointer_array[el]= this;
|
||||
if (!(new_item= new Item_ref(ref_pointer_array + el, 0, name)))
|
||||
if (!(new_item= new Item_ref(&thd->lex->current_select->context,
|
||||
ref_pointer_array + el, 0, name)))
|
||||
return; // fatal_error is set
|
||||
fields.push_front(this);
|
||||
ref_pointer_array[el]= this;
|
||||
@ -995,7 +998,7 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
|
||||
}
|
||||
|
||||
Item_field::Item_field(Field *f)
|
||||
:Item_ident(NullS, *f->table_name, f->field_name),
|
||||
:Item_ident(0, NullS, *f->table_name, f->field_name),
|
||||
item_equal(0), no_const_subst(0),
|
||||
have_privileges(0), any_privileges(0)
|
||||
{
|
||||
@ -1007,8 +1010,9 @@ Item_field::Item_field(Field *f)
|
||||
orig_table_name= orig_field_name= "";
|
||||
}
|
||||
|
||||
Item_field::Item_field(THD *thd, Field *f)
|
||||
:Item_ident(f->table->s->db, *f->table_name, f->field_name),
|
||||
Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
|
||||
Field *f)
|
||||
:Item_ident(context_arg, f->table->s->db, *f->table_name, f->field_name),
|
||||
item_equal(0), no_const_subst(0),
|
||||
have_privileges(0), any_privileges(0)
|
||||
{
|
||||
@ -1043,6 +1047,17 @@ Item_field::Item_field(THD *thd, Field *f)
|
||||
set_field(f);
|
||||
}
|
||||
|
||||
|
||||
Item_field::Item_field(Name_resolution_context *context_arg,
|
||||
const char *db_arg,const char *table_name_arg,
|
||||
const char *field_name_arg)
|
||||
:Item_ident(context_arg, db_arg,table_name_arg,field_name_arg),
|
||||
field(0), result_field(0), item_equal(0), no_const_subst(0),
|
||||
have_privileges(0), any_privileges(0)
|
||||
{
|
||||
collation.set(DERIVATION_IMPLICIT);
|
||||
}
|
||||
|
||||
// Constructor need to process subselect with temporary tables (see Item)
|
||||
Item_field::Item_field(THD *thd, Item_field *item)
|
||||
:Item_ident(thd, item),
|
||||
@ -2233,7 +2248,7 @@ bool Item_param::convert_str_value(THD *thd)
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool Item_param::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
bool Item_param::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select;
|
||||
@ -2393,9 +2408,7 @@ int Item_copy_string::save_in_field(Field *field, bool no_conversions)
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
bool Item::fix_fields(THD *thd,
|
||||
struct st_table_list *list,
|
||||
Item ** ref)
|
||||
bool Item::fix_fields(THD *thd, Item ** ref)
|
||||
{
|
||||
|
||||
// We do not check fields which are fixed during construction
|
||||
@ -2762,7 +2775,6 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
|
||||
SYNOPSIS
|
||||
Item_field::fix_fields()
|
||||
thd [in] current thread
|
||||
tables [in] the tables in a FROM clause
|
||||
reference [in/out] view column if this item was resolved to a view column
|
||||
|
||||
DESCRIPTION
|
||||
@ -2808,7 +2820,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
|
||||
FALSE on success
|
||||
*/
|
||||
|
||||
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
bool Item_field::fix_fields(THD *thd, Item **reference)
|
||||
{
|
||||
enum_parsing_place place= NO_MATTER;
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
@ -2821,63 +2833,54 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
expression to 'reference', i.e. it substitute that expression instead
|
||||
of this Item_field
|
||||
*/
|
||||
if ((from_field= find_field_in_tables(thd, this, tables, reference,
|
||||
if ((from_field= find_field_in_tables(thd, this, context->table_list,
|
||||
reference,
|
||||
IGNORE_EXCEPT_NON_UNIQUE,
|
||||
!any_privileges)) ==
|
||||
!any_privileges &&
|
||||
context->check_privileges)) ==
|
||||
not_found_field)
|
||||
{
|
||||
SELECT_LEX *last= 0;
|
||||
TABLE_LIST *table_list;
|
||||
Item **ref= (Item **) not_found_item;
|
||||
SELECT_LEX *current_sel= (SELECT_LEX *) thd->lex->current_select;
|
||||
/*
|
||||
If there is an outer select, and it is not a derived table (which do
|
||||
not support the use of outer fields for now), try to resolve this
|
||||
reference in the outer select(s).
|
||||
If there is an outer contexts (outer selects, but current select is
|
||||
not derived table or view) try to resolve this reference in the
|
||||
outer contexts.
|
||||
|
||||
We treat each subselect as a separate namespace, so that different
|
||||
subselects may contain columns with the same names. The subselects are
|
||||
searched starting from the innermost.
|
||||
*/
|
||||
if (current_sel->master_unit()->first_select()->linkage !=
|
||||
DERIVED_TABLE_TYPE)
|
||||
Name_resolution_context *last_checked_context= context;
|
||||
Item **ref= (Item **) not_found_item;
|
||||
Name_resolution_context *outer_context= context->outer_context;
|
||||
for (;
|
||||
outer_context;
|
||||
outer_context= outer_context->outer_context)
|
||||
{
|
||||
SELECT_LEX_UNIT *prev_unit= current_sel->master_unit();
|
||||
SELECT_LEX *outer_sel= prev_unit->outer_select();
|
||||
for ( ; outer_sel ;
|
||||
outer_sel= (prev_unit= outer_sel->master_unit())->outer_select())
|
||||
{
|
||||
last= outer_sel;
|
||||
Item_subselect *prev_subselect_item= prev_unit->item;
|
||||
SELECT_LEX *select= outer_context->select_lex;
|
||||
Item_subselect *prev_subselect_item=
|
||||
last_checked_context->select_lex->master_unit()->item;
|
||||
last_checked_context= outer_context;
|
||||
upward_lookup= TRUE;
|
||||
|
||||
/* Search in the tables of the FROM clause of the outer select. */
|
||||
table_list= outer_sel->get_table_list();
|
||||
if (outer_sel->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
|
||||
{
|
||||
/*
|
||||
It is a primary INSERT st_select_lex => do not resolve against the
|
||||
first table.
|
||||
*/
|
||||
table_list= table_list->next_local;
|
||||
}
|
||||
place= prev_subselect_item->parsing_place;
|
||||
/*
|
||||
Check table fields only if the subquery is used somewhere out of
|
||||
HAVING, or the outer SELECT does not use grouping (i.e. tables are
|
||||
accessible).
|
||||
|
||||
In case of view, find_field_in_tables() write pointer to view
|
||||
field expression to 'reference', i.e. it substitute that
|
||||
expression instead of this Item_field
|
||||
In case of a view, find_field_in_tables() writes the pointer to
|
||||
the found view field into '*reference', in other words, it
|
||||
substitutes this Item_field with the found expression.
|
||||
*/
|
||||
if ((place != IN_HAVING ||
|
||||
(outer_sel->with_sum_func == 0 &&
|
||||
outer_sel->group_list.elements == 0)) &&
|
||||
(from_field= find_field_in_tables(thd, this, table_list,
|
||||
(!select->with_sum_func &&
|
||||
select->group_list.elements == 0)) &&
|
||||
(from_field= find_field_in_tables(thd, this,
|
||||
outer_context->table_list,
|
||||
reference,
|
||||
IGNORE_EXCEPT_NON_UNIQUE,
|
||||
TRUE)) !=
|
||||
outer_context->
|
||||
check_privileges)) !=
|
||||
not_found_field)
|
||||
{
|
||||
if (from_field)
|
||||
@ -2894,14 +2897,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
(*reference)->used_tables();
|
||||
prev_subselect_item->const_item_cache&=
|
||||
(*reference)->const_item();
|
||||
mark_as_dependent(thd, last, current_sel, this,
|
||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||
context->select_lex, this,
|
||||
((type == REF_ITEM || type == FIELD_ITEM) ?
|
||||
(Item_ident*) (*reference) :
|
||||
0));
|
||||
/*
|
||||
view reference found, we substituted it instead of this
|
||||
Item (find_field_in_tables do it by assigning new value to
|
||||
*reference), so can quit
|
||||
A reference to a view field had been found and we
|
||||
substituted it instead of this Item (find_field_in_tables
|
||||
does it by assigning the new value to *reference), so now
|
||||
we can return from this function.
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
@ -2909,11 +2914,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Search in the SELECT and GROUP lists of the outer select. */
|
||||
if (outer_sel->resolve_mode == SELECT_LEX::SELECT_MODE)
|
||||
/* Search in SELECT and GROUP lists of the outer select. */
|
||||
if (outer_context->resolve_in_select_list)
|
||||
{
|
||||
if (!(ref= resolve_ref_in_select_and_group(thd, this, outer_sel)))
|
||||
return TRUE; /* Some error occurred (e.g. ambiguous names). */
|
||||
if (!(ref= resolve_ref_in_select_and_group(thd, this, select)))
|
||||
goto error; /* Some error occurred (e.g. ambiguous names). */
|
||||
if (ref != not_found_item)
|
||||
{
|
||||
DBUG_ASSERT(*ref && (*ref)->fixed);
|
||||
@ -2923,19 +2928,18 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
}
|
||||
}
|
||||
|
||||
// Reference is not found => depend from outer (or just error)
|
||||
/*
|
||||
Reference is not found in this select => this subquery depend on
|
||||
outer select (or we just trying to find wrong identifier, in this
|
||||
case it does not matter which used tables bits we set)
|
||||
*/
|
||||
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
|
||||
prev_subselect_item->const_item_cache= 0;
|
||||
|
||||
if (outer_sel->master_unit()->first_select()->linkage ==
|
||||
DERIVED_TABLE_TYPE)
|
||||
break; // do not look over derived table
|
||||
}
|
||||
}
|
||||
|
||||
DBUG_ASSERT(ref != 0);
|
||||
if (!from_field)
|
||||
return TRUE;
|
||||
goto error;
|
||||
if (ref == not_found_item && from_field == not_found_field)
|
||||
{
|
||||
if (upward_lookup)
|
||||
@ -2945,11 +2949,13 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Call to report error
|
||||
find_field_in_tables(thd, this, tables, reference, REPORT_ALL_ERRORS,
|
||||
TRUE);
|
||||
/* Call find_field_in_tables only to report the error */
|
||||
find_field_in_tables(thd, this, context->table_list,
|
||||
reference, REPORT_ALL_ERRORS,
|
||||
!any_privileges &&
|
||||
context->check_privileges);
|
||||
}
|
||||
return TRUE;
|
||||
goto error;
|
||||
}
|
||||
else if (ref != not_found_item)
|
||||
{
|
||||
@ -2967,45 +2973,54 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
save= *ref;
|
||||
*ref= NULL; // Don't call set_properties()
|
||||
rf= (place == IN_HAVING ?
|
||||
new Item_ref(ref, (char*) table_name, (char*) field_name) :
|
||||
new Item_direct_ref(ref, (char*) table_name, (char*) field_name));
|
||||
new Item_ref(context, ref, (char*) table_name,
|
||||
(char*) field_name) :
|
||||
new Item_direct_ref(context, ref, (char*) table_name,
|
||||
(char*) field_name));
|
||||
*ref= save;
|
||||
if (!rf)
|
||||
return TRUE;
|
||||
goto error;
|
||||
thd->change_item_tree(reference, rf);
|
||||
/*
|
||||
rf is Item_ref => never substitute other items (in this case)
|
||||
during fix_fields() => we can use rf after fix_fields()
|
||||
*/
|
||||
DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
|
||||
if (rf->fix_fields(thd, tables, reference) || rf->check_cols(1))
|
||||
return TRUE;
|
||||
if (rf->fix_fields(thd, reference) || rf->check_cols(1))
|
||||
goto error;
|
||||
|
||||
mark_as_dependent(thd, last, current_sel, this, rf);
|
||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||
context->select_lex, this,
|
||||
rf);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mark_as_dependent(thd, last, current_sel, this, this);
|
||||
if (last->having_fix_field)
|
||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||
context->select_lex,
|
||||
this, this);
|
||||
if (last_checked_context->select_lex->having_fix_field)
|
||||
{
|
||||
Item_ref *rf;
|
||||
rf= new Item_ref((cached_table->db[0] ? cached_table->db : 0),
|
||||
rf= new Item_ref(context,
|
||||
(cached_table->db[0] ? cached_table->db : 0),
|
||||
(char*) cached_table->alias, (char*) field_name);
|
||||
if (!rf)
|
||||
return TRUE;
|
||||
goto error;
|
||||
thd->change_item_tree(reference, rf);
|
||||
/*
|
||||
rf is Item_ref => never substitute other items (in this case)
|
||||
during fix_fields() => we can use rf after fix_fields()
|
||||
*/
|
||||
DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
|
||||
return (rf->fix_fields(thd, tables, reference) || rf->check_cols(1));
|
||||
if (rf->fix_fields(thd, reference) || rf->check_cols(1))
|
||||
goto error;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!from_field)
|
||||
return TRUE;
|
||||
goto error;
|
||||
|
||||
/*
|
||||
if it is not expression from merged VIEW we will set this field.
|
||||
@ -3053,12 +3068,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
|
||||
"ANY", thd->priv_user, thd->host_or_ip,
|
||||
field_name, tab);
|
||||
return TRUE;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fixed= 1;
|
||||
return FALSE;
|
||||
|
||||
error:
|
||||
context->process_error(thd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@ -3922,16 +3941,17 @@ bool Item_field::send(Protocol *protocol, String *buffer)
|
||||
}
|
||||
|
||||
|
||||
Item_ref::Item_ref(Item **item, const char *table_name_par,
|
||||
const char *field_name_par)
|
||||
:Item_ident(NullS, table_name_par, field_name_par), result_field(0),
|
||||
ref(item)
|
||||
Item_ref::Item_ref(Name_resolution_context *context_arg,
|
||||
Item **item, const char *table_name_arg,
|
||||
const char *field_name_arg)
|
||||
:Item_ident(context_arg, NullS, table_name_arg, field_name_arg),
|
||||
result_field(0), ref(item)
|
||||
{
|
||||
/*
|
||||
This constructor used to create some internals references over fixed items
|
||||
*/
|
||||
DBUG_ASSERT(ref != 0);
|
||||
if (*ref)
|
||||
if (*ref && (*ref)->fixed)
|
||||
set_properties();
|
||||
}
|
||||
|
||||
@ -3942,7 +3962,6 @@ Item_ref::Item_ref(Item **item, const char *table_name_par,
|
||||
SYNOPSIS
|
||||
Item_ref::fix_fields()
|
||||
thd [in] current thread
|
||||
tables [in] the tables in a FROM clause
|
||||
reference [in/out] view column if this item was resolved to a view column
|
||||
|
||||
DESCRIPTION
|
||||
@ -3994,59 +4013,56 @@ Item_ref::Item_ref(Item **item, const char *table_name_par,
|
||||
FALSE on success
|
||||
*/
|
||||
|
||||
bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
bool Item_ref::fix_fields(THD *thd, Item **reference)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
enum_parsing_place place= NO_MATTER;
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
SELECT_LEX *current_sel= thd->lex->current_select;
|
||||
|
||||
if (!ref || ref == not_found_item)
|
||||
{
|
||||
SELECT_LEX_UNIT *prev_unit= current_sel->master_unit();
|
||||
SELECT_LEX *outer_sel= prev_unit->outer_select();
|
||||
|
||||
if (!(ref= resolve_ref_in_select_and_group(thd, this, current_sel)))
|
||||
return TRUE; /* Some error occurred (e.g. ambiguous names). */
|
||||
if (!(ref= resolve_ref_in_select_and_group(thd, this,
|
||||
context->select_lex)))
|
||||
goto error; /* Some error occurred (e.g. ambiguous names). */
|
||||
|
||||
if (ref == not_found_item) /* This reference was not resolved. */
|
||||
{
|
||||
TABLE_LIST *table_list;
|
||||
Name_resolution_context *last_checked_context= context;
|
||||
Name_resolution_context *outer_context= context->outer_context;
|
||||
Field *from_field;
|
||||
SELECT_LEX *last;
|
||||
ref= 0;
|
||||
|
||||
if (!outer_sel || (current_sel->master_unit()->first_select()->linkage ==
|
||||
DERIVED_TABLE_TYPE))
|
||||
if (!outer_context)
|
||||
{
|
||||
/* The current reference cannot be resolved in this query. */
|
||||
my_error(ER_BAD_FIELD_ERROR,MYF(0),
|
||||
this->full_name(), current_thd->where);
|
||||
return TRUE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
If there is an outer select, and it is not a derived table (which do
|
||||
not support the use of outer fields for now), try to resolve this
|
||||
reference in the outer select(s).
|
||||
If there is an outer context (select), and it is not a derived table
|
||||
(which do not support the use of outer fields for now), try to
|
||||
resolve this reference in the outer select(s).
|
||||
|
||||
We treat each subselect as a separate namespace, so that different
|
||||
subselects may contain columns with the same names. The subselects are
|
||||
searched starting from the innermost.
|
||||
*/
|
||||
from_field= (Field*) not_found_field;
|
||||
last= 0;
|
||||
|
||||
/* The following loop will always be excuted at least once */
|
||||
for ( ; outer_sel ;
|
||||
outer_sel= (prev_unit= outer_sel->master_unit())->outer_select())
|
||||
do
|
||||
{
|
||||
last= outer_sel;
|
||||
Item_subselect *prev_subselect_item= prev_unit->item;
|
||||
SELECT_LEX *select= outer_context->select_lex;
|
||||
Item_subselect *prev_subselect_item=
|
||||
last_checked_context->select_lex->master_unit()->item;
|
||||
last_checked_context= outer_context;
|
||||
|
||||
/* Search in the SELECT and GROUP lists of the outer select. */
|
||||
if (outer_sel->resolve_mode == SELECT_LEX::SELECT_MODE)
|
||||
if (outer_context->resolve_in_select_list)
|
||||
{
|
||||
if (!(ref= resolve_ref_in_select_and_group(thd, this, outer_sel)))
|
||||
return TRUE; /* Some error occurred (e.g. ambiguous names). */
|
||||
if (!(ref= resolve_ref_in_select_and_group(thd, this, select)))
|
||||
goto error; /* Some error occurred (e.g. ambiguous names). */
|
||||
if (ref != not_found_item)
|
||||
{
|
||||
DBUG_ASSERT(*ref && (*ref)->fixed);
|
||||
@ -4062,17 +4078,6 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
ref= 0;
|
||||
}
|
||||
|
||||
/* Search in the tables of the FROM clause of the outer select. */
|
||||
table_list= outer_sel->get_table_list();
|
||||
if (outer_sel->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
|
||||
{
|
||||
/*
|
||||
It is a primary INSERT st_select_lex => do not resolve against
|
||||
the first table.
|
||||
*/
|
||||
table_list= table_list->next_local;
|
||||
}
|
||||
|
||||
place= prev_subselect_item->parsing_place;
|
||||
/*
|
||||
Check table fields only if the subquery is used somewhere out of
|
||||
@ -4085,20 +4090,21 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
ER_BAD_FIELD_ERROR which we produce now.
|
||||
*/
|
||||
if ((place != IN_HAVING ||
|
||||
(!outer_sel->with_sum_func &&
|
||||
outer_sel->group_list.elements == 0)))
|
||||
(!select->with_sum_func &&
|
||||
select->group_list.elements == 0)))
|
||||
{
|
||||
/*
|
||||
In case of view, find_field_in_tables() write pointer to view
|
||||
field expression to 'reference', i.e. it substitute that
|
||||
expression instead of this Item_ref
|
||||
*/
|
||||
from_field= find_field_in_tables(thd, this, table_list,
|
||||
from_field= find_field_in_tables(thd, this,
|
||||
outer_context->table_list,
|
||||
reference,
|
||||
IGNORE_EXCEPT_NON_UNIQUE,
|
||||
TRUE);
|
||||
outer_context->check_privileges);
|
||||
if (! from_field)
|
||||
return TRUE;
|
||||
goto error;
|
||||
if (from_field == view_ref_found)
|
||||
{
|
||||
Item::Type type= (*reference)->type();
|
||||
@ -4107,7 +4113,8 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
prev_subselect_item->const_item_cache&=
|
||||
(*reference)->const_item();
|
||||
DBUG_ASSERT((*reference)->type() == REF_ITEM);
|
||||
mark_as_dependent(thd, last, current_sel, this,
|
||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||
context->select_lex, this,
|
||||
((type == REF_ITEM || type == FIELD_ITEM) ?
|
||||
(Item_ident*) (*reference) :
|
||||
0));
|
||||
@ -4130,19 +4137,18 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
|
||||
prev_subselect_item->const_item_cache= 0;
|
||||
|
||||
if (outer_sel->master_unit()->first_select()->linkage ==
|
||||
DERIVED_TABLE_TYPE)
|
||||
break; /* Do not consider derived tables. */
|
||||
}
|
||||
outer_context= outer_context->outer_context;
|
||||
} while (outer_context);
|
||||
|
||||
DBUG_ASSERT(from_field != 0 && from_field != view_ref_found);
|
||||
if (from_field != not_found_field)
|
||||
{
|
||||
Item_field* fld;
|
||||
if (!(fld= new Item_field(from_field)))
|
||||
return TRUE;
|
||||
goto error;
|
||||
thd->change_item_tree(reference, fld);
|
||||
mark_as_dependent(thd, last, thd->lex->current_select, this, fld);
|
||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||
thd->lex->current_select, this, fld);
|
||||
return FALSE;
|
||||
}
|
||||
if (ref == 0)
|
||||
@ -4150,11 +4156,12 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
/* The item was not a table field and not a reference */
|
||||
my_error(ER_BAD_FIELD_ERROR, MYF(0),
|
||||
this->full_name(), current_thd->where);
|
||||
return TRUE;
|
||||
goto error;
|
||||
}
|
||||
/* Should be checked in resolve_ref_in_select_and_group(). */
|
||||
DBUG_ASSERT(*ref && (*ref)->fixed);
|
||||
mark_as_dependent(thd, last, current_sel, this, this);
|
||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||
context->select_lex, this, this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4174,14 +4181,18 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||
name, ((*ref)->with_sum_func?
|
||||
"reference to group function":
|
||||
"forward reference in item list"));
|
||||
return TRUE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
set_properties();
|
||||
|
||||
if ((*ref)->check_cols(1))
|
||||
return TRUE;
|
||||
goto error;
|
||||
return FALSE;
|
||||
|
||||
error:
|
||||
context->process_error(thd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@ -4389,6 +4400,19 @@ int Item_ref::save_in_field(Field *to, bool no_conversions)
|
||||
}
|
||||
|
||||
|
||||
void Item_ref::make_field(Send_field *field)
|
||||
{
|
||||
(*ref)->make_field(field);
|
||||
/* Non-zero in case of a view */
|
||||
if (name)
|
||||
field->col_name= name;
|
||||
if (table_name)
|
||||
field->table_name= table_name;
|
||||
if (db_name)
|
||||
field->db_name= db_name;
|
||||
};
|
||||
|
||||
|
||||
void Item_ref_null_helper::print(String *str)
|
||||
{
|
||||
str->append("<ref_null_helper>(", 18);
|
||||
@ -4452,6 +4476,31 @@ bool Item_direct_ref::get_date(TIME *ltime,uint fuzzydate)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Prepare referenced view viewld then call usual Item_direct_ref::fix_fields
|
||||
|
||||
SYNOPSIS
|
||||
Item_direct_view_ref::fix_fields()
|
||||
thd thread handler
|
||||
reference reference on reference where this item stored
|
||||
|
||||
RETURN
|
||||
FALSE OK
|
||||
TRUE Error
|
||||
*/
|
||||
|
||||
bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference)
|
||||
{
|
||||
/* view fild reference must be defined */
|
||||
DBUG_ASSERT(*ref);
|
||||
/* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */
|
||||
if (!(*ref)->fixed &&
|
||||
((*ref)->fix_fields(thd, ref)))
|
||||
return TRUE;
|
||||
return Item_direct_ref::fix_fields(thd, reference);
|
||||
}
|
||||
|
||||
|
||||
void Item_null_helper::print(String *str)
|
||||
{
|
||||
str->append("<null_helper>(", 14);
|
||||
@ -4467,9 +4516,7 @@ bool Item_default_value::eq(const Item *item, bool binary_cmp) const
|
||||
}
|
||||
|
||||
|
||||
bool Item_default_value::fix_fields(THD *thd,
|
||||
struct st_table_list *table_list,
|
||||
Item **items)
|
||||
bool Item_default_value::fix_fields(THD *thd, Item **items)
|
||||
{
|
||||
Item *real_arg;
|
||||
Item_field *field_arg;
|
||||
@ -4481,29 +4528,34 @@ bool Item_default_value::fix_fields(THD *thd,
|
||||
fixed= 1;
|
||||
return FALSE;
|
||||
}
|
||||
if (!arg->fixed && arg->fix_fields(thd, table_list, &arg))
|
||||
return TRUE;
|
||||
if (!arg->fixed && arg->fix_fields(thd, &arg))
|
||||
goto error;
|
||||
|
||||
|
||||
real_arg= arg->real_item();
|
||||
if (real_arg->type() != FIELD_ITEM)
|
||||
{
|
||||
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name);
|
||||
return TRUE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
field_arg= (Item_field *)real_arg;
|
||||
if (field_arg->field->flags & NO_DEFAULT_VALUE_FLAG)
|
||||
{
|
||||
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name);
|
||||
return TRUE;
|
||||
goto error;
|
||||
}
|
||||
if (!(def_field= (Field*) sql_alloc(field_arg->field->size_of())))
|
||||
return TRUE;
|
||||
goto error;
|
||||
memcpy(def_field, field_arg->field, field_arg->field->size_of());
|
||||
def_field->move_field(def_field->table->s->default_values -
|
||||
def_field->table->record[0]);
|
||||
set_field(def_field);
|
||||
return FALSE;
|
||||
|
||||
error:
|
||||
context->process_error(thd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@ -4525,12 +4577,28 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
|
||||
if (!arg)
|
||||
{
|
||||
if (field_arg->flags & NO_DEFAULT_VALUE_FLAG)
|
||||
{
|
||||
if (context->error_processor == &view_error_processor)
|
||||
{
|
||||
TABLE_LIST *view= (cached_table->belong_to_view ?
|
||||
cached_table->belong_to_view :
|
||||
cached_table);
|
||||
// TODO: make correct error message
|
||||
push_warning_printf(field_arg->table->in_use,
|
||||
MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_NO_DEFAULT_FOR_VIEW_FIELD,
|
||||
ER(ER_NO_DEFAULT_FOR_VIEW_FIELD),
|
||||
view->view_db.str,
|
||||
view->view_name.str);
|
||||
}
|
||||
else
|
||||
{
|
||||
push_warning_printf(field_arg->table->in_use,
|
||||
MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_NO_DEFAULT_FOR_FIELD,
|
||||
ER(ER_NO_DEFAULT_FOR_FIELD),
|
||||
field_arg->field_name);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
field_arg->set_default();
|
||||
@ -4547,12 +4615,10 @@ bool Item_insert_value::eq(const Item *item, bool binary_cmp) const
|
||||
}
|
||||
|
||||
|
||||
bool Item_insert_value::fix_fields(THD *thd,
|
||||
struct st_table_list *table_list,
|
||||
Item **items)
|
||||
bool Item_insert_value::fix_fields(THD *thd, Item **items)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
if (!arg->fixed && arg->fix_fields(thd, table_list, &arg))
|
||||
if (!arg->fixed && arg->fix_fields(thd, &arg))
|
||||
return TRUE;
|
||||
|
||||
if (arg->type() == REF_ITEM)
|
||||
@ -4641,9 +4707,7 @@ bool Item_trigger_field::eq(const Item *item, bool binary_cmp) const
|
||||
}
|
||||
|
||||
|
||||
bool Item_trigger_field::fix_fields(THD *thd,
|
||||
TABLE_LIST *table_list,
|
||||
Item **items)
|
||||
bool Item_trigger_field::fix_fields(THD *thd, Item **items)
|
||||
{
|
||||
/*
|
||||
Since trigger is object tightly associated with TABLE object most
|
||||
@ -5411,6 +5475,34 @@ void Item_result_field::cleanup()
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
Dummy error processor used by default by Name_resolution_context
|
||||
|
||||
SYNOPSIS
|
||||
dummy_error_processor()
|
||||
|
||||
NOTE
|
||||
do nothing
|
||||
*/
|
||||
|
||||
void dummy_error_processor(THD *thd, void *data)
|
||||
{}
|
||||
|
||||
/*
|
||||
Wrapper of hide_view_error call for Name_resolution_context error processor
|
||||
|
||||
SYNOPSIS
|
||||
view_error_processor()
|
||||
|
||||
NOTE
|
||||
hide view underlying tables details in error messages
|
||||
*/
|
||||
|
||||
void view_error_processor(THD *thd, void *data)
|
||||
{
|
||||
((TABLE_LIST *)data)->hide_view_error(thd);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Instantiate templates
|
||||
*****************************************************************************/
|
||||
|
227
sql/item.h
227
sql/item.h
@ -24,7 +24,6 @@ struct st_table_list;
|
||||
void item_init(void); /* Init item functions */
|
||||
class Item_field;
|
||||
|
||||
|
||||
/*
|
||||
"Declared Type Collation"
|
||||
A combination of collation and its derivation.
|
||||
@ -218,6 +217,97 @@ struct Hybrid_type_traits_integer: public Hybrid_type_traits
|
||||
static const Hybrid_type_traits_integer *instance();
|
||||
};
|
||||
|
||||
|
||||
void dummy_error_processor(THD *thd, void *data);
|
||||
|
||||
void view_error_processor(THD *thd, void *data);
|
||||
|
||||
/*
|
||||
Instances of Name_resolution_context store the information necesary for
|
||||
name resolution of Items and other context analysis of a query made in
|
||||
fix_fields().
|
||||
|
||||
This structure is a part of SELECT_LEX, a pointer to this structure is
|
||||
assigned when an item is created (which happens mostly during parsing
|
||||
(sql_yacc.yy)), but the structure itself will be initialized after parsing
|
||||
is complete
|
||||
|
||||
TODO: move subquery of INSERT ... SELECT and CREATE ... SELECT to
|
||||
separate SELECT_LEX which allow to remove tricks of changing this
|
||||
structure before and after INSERT/CREATE and its SELECT to make correct
|
||||
field name resolution.
|
||||
*/
|
||||
struct Name_resolution_context
|
||||
{
|
||||
/*
|
||||
The name resolution context to search in when an Item cannot be
|
||||
resolved in this context (the context of an outer select)
|
||||
*/
|
||||
Name_resolution_context *outer_context;
|
||||
|
||||
/*
|
||||
List of tables used to resolve the items of this context. Usually these
|
||||
are tables from the FROM clause of SELECT statement. The exceptions are
|
||||
INSERT ... SELECT and CREATE ... SELECT statements, where SELECT
|
||||
subquery is not moved to a separate SELECT_LEX. For these types of
|
||||
statements we have to change this member dynamically to ensure correct
|
||||
name resolution of different parts of the statement.
|
||||
*/
|
||||
TABLE_LIST *table_list;
|
||||
|
||||
/*
|
||||
SELECT_LEX item belong to, in case of merged VIEW it can differ from
|
||||
SELECT_LEX where item was created, so we can't use table_list/field_list
|
||||
from there
|
||||
*/
|
||||
st_select_lex *select_lex;
|
||||
|
||||
/*
|
||||
Processor of errors caused during Item name resolving, now used only to
|
||||
hide underlying tables in errors about views (i.e. it substitute some
|
||||
errors for views)
|
||||
*/
|
||||
void (*error_processor)(THD *, void *);
|
||||
void *error_processor_data;
|
||||
|
||||
/*
|
||||
When TRUE items are resolved in this context both against the
|
||||
SELECT list and this->table_list. If FALSE, items are resolved
|
||||
only against this->table_list.
|
||||
*/
|
||||
bool resolve_in_select_list;
|
||||
|
||||
/*
|
||||
When FALSE we do not check columns right of resolving items, used to
|
||||
prevent rights check on underlying tables of view
|
||||
*/
|
||||
bool check_privileges;
|
||||
|
||||
Name_resolution_context()
|
||||
:outer_context(0), table_list(0), select_lex(0),
|
||||
error_processor_data(0),
|
||||
check_privileges(TRUE)
|
||||
{}
|
||||
|
||||
void init()
|
||||
{
|
||||
resolve_in_select_list= FALSE;
|
||||
error_processor= &dummy_error_processor;
|
||||
}
|
||||
|
||||
void resolve_in_table_list_only(TABLE_LIST *tables)
|
||||
{
|
||||
table_list= tables;
|
||||
resolve_in_select_list= FALSE;
|
||||
}
|
||||
|
||||
void process_error(THD *thd)
|
||||
{
|
||||
(*error_processor)(thd, error_processor_data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
typedef bool (Item::*Item_processor)(byte *arg);
|
||||
@ -234,7 +324,8 @@ class Item {
|
||||
Item(const Item &); /* Prevent use of these */
|
||||
void operator=(Item &);
|
||||
public:
|
||||
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
|
||||
static void *operator new(size_t size)
|
||||
{ return (void*) sql_alloc((uint) size); }
|
||||
static void *operator new(size_t size, MEM_ROOT *mem_root)
|
||||
{ return (void*) alloc_root(mem_root, (uint) size); }
|
||||
/* Special for SP local variable assignment - reusing slots */
|
||||
@ -248,7 +339,8 @@ public:
|
||||
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
|
||||
FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM,
|
||||
SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER,
|
||||
PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM};
|
||||
PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM,
|
||||
VIEW_FIXER_ITEM};
|
||||
|
||||
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
|
||||
|
||||
@ -302,7 +394,7 @@ public:
|
||||
virtual void cleanup();
|
||||
virtual void make_field(Send_field *field);
|
||||
Field *make_string_field(TABLE *table);
|
||||
virtual bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
virtual bool fix_fields(THD *, Item **);
|
||||
/*
|
||||
should be used in case where we are sure that we do not need
|
||||
complete fix_fields() procedure.
|
||||
@ -554,6 +646,8 @@ public:
|
||||
virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; }
|
||||
virtual bool cleanup_processor(byte *arg);
|
||||
virtual bool collect_item_field_processor(byte * arg) { return 0; }
|
||||
virtual bool change_context_processor(byte *context) { return 0; }
|
||||
|
||||
virtual Item *equal_fields_propagator(byte * arg) { return this; }
|
||||
virtual Item *set_no_const_sub(byte *arg) { return this; }
|
||||
virtual Item *replace_equal_field(byte * arg) { return this; }
|
||||
@ -631,7 +725,7 @@ public:
|
||||
Item **this_item_addr(THD *thd, Item **);
|
||||
Item *this_const_item() const;
|
||||
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
bool fix_fields(THD *, Item **);
|
||||
void cleanup();
|
||||
|
||||
inline uint get_offset()
|
||||
@ -704,7 +798,9 @@ protected:
|
||||
const char *orig_db_name;
|
||||
const char *orig_table_name;
|
||||
const char *orig_field_name;
|
||||
|
||||
public:
|
||||
Name_resolution_context *context;
|
||||
const char *db_name;
|
||||
const char *table_name;
|
||||
const char *field_name;
|
||||
@ -722,13 +818,16 @@ public:
|
||||
*/
|
||||
TABLE_LIST *cached_table;
|
||||
st_select_lex *depended_from;
|
||||
Item_ident(const char *db_name_par,const char *table_name_par,
|
||||
const char *field_name_par);
|
||||
Item_ident(Name_resolution_context *context_arg,
|
||||
const char *db_name_arg, const char *table_name_arg,
|
||||
const char *field_name_arg);
|
||||
Item_ident(THD *thd, Item_ident *item);
|
||||
const char *full_name() const;
|
||||
void cleanup();
|
||||
bool remove_dependence_processor(byte * arg);
|
||||
void print(String *str);
|
||||
virtual bool change_context_processor(byte *cntx)
|
||||
{ context= (Name_resolution_context *)cntx; return FALSE; }
|
||||
};
|
||||
|
||||
class Item_equal;
|
||||
@ -750,12 +849,9 @@ public:
|
||||
/* field need any privileges (for VIEW creation) */
|
||||
bool any_privileges;
|
||||
|
||||
Item_field(const char *db_par,const char *table_name_par,
|
||||
const char *field_name_par)
|
||||
:Item_ident(db_par,table_name_par,field_name_par),
|
||||
field(0), result_field(0), item_equal(0), no_const_subst(0),
|
||||
have_privileges(0), any_privileges(0)
|
||||
{ collation.set(DERIVATION_IMPLICIT); }
|
||||
Item_field(Name_resolution_context *context_arg,
|
||||
const char *db_arg,const char *table_name_arg,
|
||||
const char *field_name_arg);
|
||||
/*
|
||||
Constructor needed to process subselect with temporary tables (see Item)
|
||||
*/
|
||||
@ -765,7 +861,7 @@ public:
|
||||
and database names will live as long as Item_field (this is important
|
||||
in prepared statements).
|
||||
*/
|
||||
Item_field(THD *thd, Field *field);
|
||||
Item_field(THD *thd, Name_resolution_context *context_arg, Field *field);
|
||||
/*
|
||||
If this constructor is used, fix_fields() won't work, because
|
||||
db_name, table_name and column_name are unknown. It's necessary to call
|
||||
@ -785,7 +881,7 @@ public:
|
||||
bool val_bool_result();
|
||||
bool send(Protocol *protocol, String *str_arg);
|
||||
void reset_field(Field *f);
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
bool fix_fields(THD *, Item **);
|
||||
void make_field(Send_field *tmp_field);
|
||||
int save_in_field(Field *field,bool no_conversions);
|
||||
void save_org_in_field(Field *field);
|
||||
@ -946,7 +1042,7 @@ public:
|
||||
bool get_time(TIME *tm);
|
||||
bool get_date(TIME *tm, uint fuzzydate);
|
||||
int save_in_field(Field *field, bool no_conversions);
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
bool fix_fields(THD *, Item **);
|
||||
|
||||
void set_null();
|
||||
void set_int(longlong i, uint32 max_length_arg);
|
||||
@ -1317,9 +1413,11 @@ protected:
|
||||
public:
|
||||
Field *result_field; /* Save result here */
|
||||
Item **ref;
|
||||
Item_ref(const char *db_par, const char *table_name_par,
|
||||
const char *field_name_par)
|
||||
:Item_ident(db_par, table_name_par, field_name_par), result_field(0), ref(0) {}
|
||||
Item_ref(Name_resolution_context *context_arg,
|
||||
const char *db_arg, const char *table_name_arg,
|
||||
const char *field_name_arg)
|
||||
:Item_ident(context_arg, db_arg, table_name_arg, field_name_arg),
|
||||
result_field(0), ref(0) {}
|
||||
/*
|
||||
This constructor is used in two scenarios:
|
||||
A) *item = NULL
|
||||
@ -1334,10 +1432,12 @@ public:
|
||||
TODO we probably fix a superset of problems like in BUG#6658. Check this
|
||||
with Bar, and if we have a more broader set of problems like this.
|
||||
*/
|
||||
Item_ref(Item **item, const char *table_name_par, const char *field_name_par);
|
||||
Item_ref(Name_resolution_context *context_arg, Item **item,
|
||||
const char *table_name_arg, const char *field_name_arg);
|
||||
|
||||
/* Constructor need to process subselect with temporary tables (see Item) */
|
||||
Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {}
|
||||
Item_ref(THD *thd, Item_ref *item)
|
||||
:Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {}
|
||||
enum Type type() const { return REF_ITEM; }
|
||||
bool eq(const Item *item, bool binary_cmp) const
|
||||
{ return ref && (*ref)->eq(item, binary_cmp); }
|
||||
@ -1354,8 +1454,8 @@ public:
|
||||
my_decimal *val_decimal_result(my_decimal *);
|
||||
bool val_bool_result();
|
||||
bool send(Protocol *prot, String *tmp);
|
||||
void make_field(Send_field *field) { (*ref)->make_field(field); }
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
void make_field(Send_field *field);
|
||||
bool fix_fields(THD *, Item **);
|
||||
int save_in_field(Field *field, bool no_conversions);
|
||||
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
|
||||
enum Item_result result_type () const { return (*ref)->result_type(); }
|
||||
@ -1380,6 +1480,8 @@ public:
|
||||
{ return (*ref)->walk(processor, arg); }
|
||||
void print(String *str);
|
||||
void cleanup();
|
||||
Item_field *filed_for_view_update()
|
||||
{ return (*ref)->filed_for_view_update(); }
|
||||
};
|
||||
|
||||
|
||||
@ -1390,9 +1492,10 @@ public:
|
||||
class Item_direct_ref :public Item_ref
|
||||
{
|
||||
public:
|
||||
Item_direct_ref(Item **item, const char *table_name_par,
|
||||
const char *field_name_par)
|
||||
:Item_ref(item, table_name_par, field_name_par) {}
|
||||
Item_direct_ref(Name_resolution_context *context_arg, Item **item,
|
||||
const char *table_name_arg,
|
||||
const char *field_name_arg)
|
||||
:Item_ref(context_arg, item, table_name_arg, field_name_arg) {}
|
||||
/* Constructor need to process subselect with temporary tables (see Item) */
|
||||
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
|
||||
|
||||
@ -1405,6 +1508,24 @@ public:
|
||||
bool get_date(TIME *ltime,uint fuzzydate);
|
||||
};
|
||||
|
||||
/*
|
||||
Class for view fields, the same as Item_direct_ref, but call fix_fields
|
||||
of reference if it is not called yet
|
||||
*/
|
||||
class Item_direct_view_ref :public Item_direct_ref
|
||||
{
|
||||
public:
|
||||
Item_direct_view_ref(Name_resolution_context *context_arg, Item **item,
|
||||
const char *table_name_arg,
|
||||
const char *field_name_arg)
|
||||
:Item_direct_ref(context_arg, item, table_name_arg, field_name_arg) {}
|
||||
/* Constructor need to process subselect with temporary tables (see Item) */
|
||||
Item_direct_view_ref(THD *thd, Item_direct_ref *item)
|
||||
:Item_direct_ref(thd, item) {}
|
||||
|
||||
bool fix_fields(THD *, Item **);
|
||||
};
|
||||
|
||||
|
||||
class Item_in_subselect;
|
||||
|
||||
@ -1413,9 +1534,11 @@ class Item_ref_null_helper: public Item_ref
|
||||
protected:
|
||||
Item_in_subselect* owner;
|
||||
public:
|
||||
Item_ref_null_helper(Item_in_subselect* master, Item **item,
|
||||
const char *table_name_par, const char *field_name_par):
|
||||
Item_ref(item, table_name_par, field_name_par), owner(master) {}
|
||||
Item_ref_null_helper(Name_resolution_context *context_arg,
|
||||
Item_in_subselect* master, Item **item,
|
||||
const char *table_name_arg, const char *field_name_arg)
|
||||
:Item_ref(context_arg, item, table_name_arg, field_name_arg),
|
||||
owner(master) {}
|
||||
double val_real();
|
||||
longlong val_int();
|
||||
String* val_str(String* s);
|
||||
@ -1429,10 +1552,11 @@ class Item_null_helper :public Item_ref_null_helper
|
||||
{
|
||||
Item *store;
|
||||
public:
|
||||
Item_null_helper(Item_in_subselect* master, Item *item,
|
||||
const char *table_name_par, const char *field_name_par)
|
||||
:Item_ref_null_helper(master, (store= 0, &store), table_name_par,
|
||||
field_name_par),
|
||||
Item_null_helper(Name_resolution_context *context_arg,
|
||||
Item_in_subselect* master, Item *item,
|
||||
const char *table_name_arg, const char *field_name_arg)
|
||||
:Item_ref_null_helper(context_arg, master, (store= 0, &store),
|
||||
table_name_arg, field_name_arg),
|
||||
store(item)
|
||||
{ ref= &store; }
|
||||
void print(String *str);
|
||||
@ -1583,13 +1707,17 @@ class Item_default_value : public Item_field
|
||||
{
|
||||
public:
|
||||
Item *arg;
|
||||
Item_default_value() :
|
||||
Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(NULL) {}
|
||||
Item_default_value(Item *a) :
|
||||
Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {}
|
||||
Item_default_value(Name_resolution_context *context_arg)
|
||||
:Item_field(context_arg, (const char *)NULL, (const char *)NULL,
|
||||
(const char *)NULL),
|
||||
arg(NULL) {}
|
||||
Item_default_value(Name_resolution_context *context_arg, Item *a)
|
||||
:Item_field(context_arg, (const char *)NULL, (const char *)NULL,
|
||||
(const char *)NULL),
|
||||
arg(a) {}
|
||||
enum Type type() const { return DEFAULT_VALUE_ITEM; }
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
bool fix_fields(THD *, Item **);
|
||||
void print(String *str);
|
||||
int save_in_field(Field *field_arg, bool no_conversions);
|
||||
table_map used_tables() const { return (table_map)0L; }
|
||||
@ -1618,10 +1746,12 @@ class Item_insert_value : public Item_field
|
||||
{
|
||||
public:
|
||||
Item *arg;
|
||||
Item_insert_value(Item *a) :
|
||||
Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {}
|
||||
Item_insert_value(Name_resolution_context *context_arg, Item *a)
|
||||
:Item_field(context_arg, (const char *)NULL, (const char *)NULL,
|
||||
(const char *)NULL),
|
||||
arg(a) {}
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
bool fix_fields(THD *, Item **);
|
||||
void print(String *str);
|
||||
int save_in_field(Field *field_arg, bool no_conversions)
|
||||
{
|
||||
@ -1683,15 +1813,17 @@ public:
|
||||
/* Pointer to Table_trigger_list object for table of this trigger */
|
||||
Table_triggers_list *triggers;
|
||||
|
||||
Item_trigger_field(row_version_type row_ver_par,
|
||||
const char *field_name_par):
|
||||
Item_field((const char *)NULL, (const char *)NULL, field_name_par),
|
||||
row_version(row_ver_par), field_idx((uint)-1)
|
||||
Item_trigger_field(Name_resolution_context *context_arg,
|
||||
row_version_type row_ver_arg,
|
||||
const char *field_name_arg)
|
||||
:Item_field(context_arg,
|
||||
(const char *)NULL, (const char *)NULL, field_name_arg),
|
||||
row_version(row_ver_arg), field_idx((uint)-1)
|
||||
{}
|
||||
void setup_field(THD *thd, TABLE *table);
|
||||
enum Type type() const { return TRIGGER_FIELD_ITEM; }
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
bool fix_fields(THD *, Item **);
|
||||
void print(String *str);
|
||||
table_map used_tables() const { return (table_map)0L; }
|
||||
void cleanup();
|
||||
@ -1880,7 +2012,7 @@ public:
|
||||
Item_type_holder(THD*, Item*);
|
||||
|
||||
Item_result result_type() const;
|
||||
virtual enum_field_types field_type() const { return fld_type; };
|
||||
enum_field_types field_type() const { return fld_type; };
|
||||
enum Type type() const { return TYPE_HOLDER; }
|
||||
double val_real();
|
||||
longlong val_int();
|
||||
@ -1892,6 +2024,7 @@ public:
|
||||
static enum_field_types get_real_type(Item *);
|
||||
};
|
||||
|
||||
|
||||
class st_select_lex;
|
||||
void mark_select_range_as_dependent(THD *thd,
|
||||
st_select_lex *last_select,
|
||||
|
@ -638,11 +638,9 @@ int Arg_comparator::compare_e_row()
|
||||
}
|
||||
|
||||
|
||||
bool Item_in_optimizer::fix_left(THD *thd,
|
||||
struct st_table_list *tables,
|
||||
Item **ref)
|
||||
bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
|
||||
{
|
||||
if (!args[0]->fixed && args[0]->fix_fields(thd, tables, args) ||
|
||||
if (!args[0]->fixed && args[0]->fix_fields(thd, args) ||
|
||||
!cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
|
||||
return 1;
|
||||
|
||||
@ -679,16 +677,15 @@ bool Item_in_optimizer::fix_left(THD *thd,
|
||||
}
|
||||
|
||||
|
||||
bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
|
||||
Item ** ref)
|
||||
bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
if (fix_left(thd, tables, ref))
|
||||
if (fix_left(thd, ref))
|
||||
return TRUE;
|
||||
if (args[0]->maybe_null)
|
||||
maybe_null=1;
|
||||
|
||||
if (!args[1]->fixed && args[1]->fix_fields(thd, tables, args+1))
|
||||
if (!args[1]->fixed && args[1]->fix_fields(thd, args+1))
|
||||
return TRUE;
|
||||
Item_in_subselect * sub= (Item_in_subselect *)args[1];
|
||||
if (args[0]->cols() != sub->engine->cols())
|
||||
@ -2312,7 +2309,7 @@ void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item)
|
||||
|
||||
|
||||
bool
|
||||
Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
Item_cond::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
List_iterator<Item> li(list);
|
||||
@ -2360,7 +2357,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
|
||||
// item can be substituted in fix_fields
|
||||
if ((!item->fixed &&
|
||||
item->fix_fields(thd, tables, li.ref())) ||
|
||||
item->fix_fields(thd, li.ref())) ||
|
||||
(item= *li.ref())->check_cols(1))
|
||||
return TRUE; /* purecov: inspected */
|
||||
used_tables_cache|= item->used_tables();
|
||||
@ -2747,11 +2744,11 @@ Item_func::optimize_type Item_func_like::select_optimize() const
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
|
||||
bool Item_func_like::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
if (Item_bool_func2::fix_fields(thd, tlist, ref) ||
|
||||
escape_item->fix_fields(thd, tlist, &escape_item))
|
||||
if (Item_bool_func2::fix_fields(thd, ref) ||
|
||||
escape_item->fix_fields(thd, &escape_item))
|
||||
return TRUE;
|
||||
|
||||
if (!escape_item->const_during_execution())
|
||||
@ -2815,13 +2812,13 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
|
||||
#ifdef USE_REGEX
|
||||
|
||||
bool
|
||||
Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
Item_func_regex::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
if ((!args[0]->fixed &&
|
||||
args[0]->fix_fields(thd, tables, args)) || args[0]->check_cols(1) ||
|
||||
args[0]->fix_fields(thd, args)) || args[0]->check_cols(1) ||
|
||||
(!args[1]->fixed &&
|
||||
args[1]->fix_fields(thd,tables, args + 1)) || args[1]->check_cols(1))
|
||||
args[1]->fix_fields(thd, args + 1)) || args[1]->check_cols(1))
|
||||
return TRUE; /* purecov: inspected */
|
||||
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
|
||||
max_length= 1;
|
||||
@ -3481,7 +3478,7 @@ void Item_equal::sort(Item_field_cmpfunc cmp, void *arg)
|
||||
} while (swap);
|
||||
}
|
||||
|
||||
bool Item_equal::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
bool Item_equal::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
List_iterator_fast<Item_field> li(fields);
|
||||
Item *item;
|
||||
|
@ -108,8 +108,8 @@ public:
|
||||
Item_in_optimizer(Item *a, Item_in_subselect *b):
|
||||
Item_bool_func(a, my_reinterpret_cast(Item *)(b)), cache(0), save_cache(0)
|
||||
{}
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
bool fix_left(THD *thd, struct st_table_list *tables, Item **ref);
|
||||
bool fix_fields(THD *, Item **);
|
||||
bool fix_left(THD *thd, Item **ref);
|
||||
bool is_null();
|
||||
/*
|
||||
Item_in_optimizer item is special boolean function. On value request
|
||||
@ -502,11 +502,11 @@ public:
|
||||
String *val_str(String *str);
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
enum Item_result result_type () const { return cached_result_type; }
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
|
||||
bool fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
args[0]->top_level_item();
|
||||
return Item_func::fix_fields(thd, tlist, ref);
|
||||
return Item_func::fix_fields(thd, ref);
|
||||
}
|
||||
void fix_length_and_dec();
|
||||
uint decimal_precision() const;
|
||||
@ -961,7 +961,7 @@ public:
|
||||
optimize_type select_optimize() const;
|
||||
cond_result eq_cmp_result() const { return COND_TRUE; }
|
||||
const char *func_name() const { return "like"; }
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
};
|
||||
|
||||
#ifdef USE_REGEX
|
||||
@ -980,7 +980,7 @@ public:
|
||||
regex_compiled(0),regex_is_const(0) {}
|
||||
void cleanup();
|
||||
longlong val_int();
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
const char *func_name() const { return "regexp"; }
|
||||
void print(String *str) { print_op(str); }
|
||||
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
||||
@ -1024,7 +1024,7 @@ public:
|
||||
:Item_bool_func(), list(nlist), abort_on_null(0) {}
|
||||
bool add(Item *item) { return list.push_back(item); }
|
||||
void add_at_head(List<Item> *nlist) { list.prepand(nlist); }
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **ref);
|
||||
bool fix_fields(THD *, Item **ref);
|
||||
|
||||
enum Type type() const { return COND_ITEM; }
|
||||
List<Item>* argument_list() { return &list; }
|
||||
@ -1141,7 +1141,7 @@ public:
|
||||
void sort(Item_field_cmpfunc cmp, void *arg);
|
||||
friend class Item_equal_iterator;
|
||||
void fix_length_and_dec();
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
void update_used_tables();
|
||||
bool walk(Item_processor processor, byte *arg);
|
||||
Item *transform(Item_transformer transformer, byte *arg);
|
||||
|
@ -194,11 +194,10 @@ bool Item_func::agg_arg_charsets(DTCollation &coll,
|
||||
((Item_field *)(*arg))->no_const_subst= 1;
|
||||
/*
|
||||
We do not check conv->fixed, because Item_func_conv_charset which can
|
||||
be return by safe_charset_converter can't be fixed at creation, also
|
||||
it do not need tables (second argument) for name resolving
|
||||
be return by safe_charset_converter can't be fixed at creation
|
||||
*/
|
||||
*arg= conv;
|
||||
conv->fix_fields(thd, 0, arg);
|
||||
conv->fix_fields(thd, arg);
|
||||
}
|
||||
if (arena)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
@ -261,7 +260,6 @@ Item_func::Item_func(THD *thd, Item_func *item)
|
||||
SYNOPSIS:
|
||||
fix_fields()
|
||||
thd Thread object
|
||||
tables List of all open tables involved in the query
|
||||
ref Pointer to where this object is used. This reference
|
||||
is used if we want to replace this object with another
|
||||
one (for example in the summary functions).
|
||||
@ -290,7 +288,7 @@ Item_func::Item_func(THD *thd, Item_func *item)
|
||||
*/
|
||||
|
||||
bool
|
||||
Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
Item_func::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
Item **arg,**arg_end;
|
||||
@ -312,7 +310,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
We can't yet set item to *arg as fix_fields may change *arg
|
||||
We shouldn't call fix_fields() twice, so check 'fixed' field first
|
||||
*/
|
||||
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)))
|
||||
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
|
||||
return TRUE; /* purecov: inspected */
|
||||
item= *arg;
|
||||
|
||||
@ -2010,10 +2008,9 @@ my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_rand::fix_fields(THD *thd, struct st_table_list *tables,
|
||||
Item **ref)
|
||||
bool Item_func_rand::fix_fields(THD *thd,Item **ref)
|
||||
{
|
||||
if (Item_real_func::fix_fields(thd, tables, ref))
|
||||
if (Item_real_func::fix_fields(thd, ref))
|
||||
return TRUE;
|
||||
used_tables_cache|= RAND_TABLE_BIT;
|
||||
if (arg_count)
|
||||
@ -2604,7 +2601,7 @@ void udf_handler::cleanup()
|
||||
|
||||
|
||||
bool
|
||||
udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
|
||||
udf_handler::fix_fields(THD *thd, Item_result_field *func,
|
||||
uint arg_count, Item **arguments)
|
||||
{
|
||||
#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
|
||||
@ -2646,7 +2643,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
|
||||
arg++,i++)
|
||||
{
|
||||
if (!(*arg)->fixed &&
|
||||
(*arg)->fix_fields(thd, tables, arg))
|
||||
(*arg)->fix_fields(thd, arg))
|
||||
DBUG_RETURN(1);
|
||||
// we can't assign 'item' before, because fix_fields() can change arg
|
||||
Item *item= *arg;
|
||||
@ -3458,12 +3455,11 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
|
||||
SELECT @a:= ).
|
||||
*/
|
||||
|
||||
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
|
||||
Item **ref)
|
||||
bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
|
||||
if (Item_func::fix_fields(thd, tables, ref) ||
|
||||
if (Item_func::fix_fields(thd, ref) ||
|
||||
!(entry= get_variable(&thd->user_vars, name, 1)))
|
||||
return TRUE;
|
||||
/*
|
||||
@ -4127,11 +4123,10 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
|
||||
}
|
||||
|
||||
|
||||
bool Item_user_var_as_out_param::fix_fields(THD *thd, TABLE_LIST *tables,
|
||||
Item **ref)
|
||||
bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
if (Item::fix_fields(thd, tables, ref) ||
|
||||
if (Item::fix_fields(thd, ref) ||
|
||||
!(entry= get_variable(&thd->user_vars, name, 1)))
|
||||
return TRUE;
|
||||
entry->type= STRING_RESULT;
|
||||
@ -4314,7 +4309,7 @@ void Item_func_match::init_search(bool no_order)
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||
bool Item_func_match::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
Item *item;
|
||||
@ -4329,7 +4324,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||
modifications to find_best and auto_close as complement to auto_init code
|
||||
above.
|
||||
*/
|
||||
if (Item_func::fix_fields(thd, tlist, ref) ||
|
||||
if (Item_func::fix_fields(thd, ref) ||
|
||||
!args[0]->const_during_execution())
|
||||
{
|
||||
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
|
||||
@ -4690,8 +4685,9 @@ longlong Item_func_row_count::val_int()
|
||||
}
|
||||
|
||||
|
||||
Item_func_sp::Item_func_sp(sp_name *name)
|
||||
:Item_func(), m_name(name), m_sp(NULL), result_field(NULL)
|
||||
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name)
|
||||
:Item_func(), context(context_arg), m_name(name), m_sp(NULL),
|
||||
result_field(NULL)
|
||||
{
|
||||
maybe_null= 1;
|
||||
m_name->init_qname(current_thd);
|
||||
@ -4699,8 +4695,10 @@ Item_func_sp::Item_func_sp(sp_name *name)
|
||||
}
|
||||
|
||||
|
||||
Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
|
||||
:Item_func(list), m_name(name), m_sp(NULL), result_field(NULL)
|
||||
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
|
||||
sp_name *name, List<Item> &list)
|
||||
:Item_func(list), context(context_arg), m_name(name), m_sp(NULL),
|
||||
result_field(NULL)
|
||||
{
|
||||
maybe_null= 1;
|
||||
m_name->init_qname(current_thd);
|
||||
@ -4944,7 +4942,10 @@ Item_func_sp::fix_length_and_dec()
|
||||
}
|
||||
|
||||
if (!(field= sp_result_field()))
|
||||
{
|
||||
context->process_error(current_thd);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
decimals= field->decimals();
|
||||
max_length= field->field_length;
|
||||
maybe_null= 1;
|
||||
|
@ -116,7 +116,7 @@ public:
|
||||
Item_func(List<Item> &list);
|
||||
// Constructor used for Item_cond_and/or (see Item comment)
|
||||
Item_func(THD *thd, Item_func *item);
|
||||
bool fix_fields(THD *,struct st_table_list *, Item **ref);
|
||||
bool fix_fields(THD *, Item **ref);
|
||||
table_map used_tables() const;
|
||||
table_map not_null_tables() const;
|
||||
void update_used_tables();
|
||||
@ -630,7 +630,7 @@ public:
|
||||
const char *func_name() const { return "rand"; }
|
||||
bool const_item() const { return 0; }
|
||||
void update_used_tables();
|
||||
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
};
|
||||
|
||||
|
||||
@ -885,14 +885,15 @@ protected:
|
||||
udf_handler udf;
|
||||
|
||||
public:
|
||||
Item_udf_func(udf_func *udf_arg) :Item_func(), udf(udf_arg) {}
|
||||
Item_udf_func(udf_func *udf_arg)
|
||||
:Item_func(), udf(udf_arg) {}
|
||||
Item_udf_func(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_func(list), udf(udf_arg) {}
|
||||
const char *func_name() const { return udf.name(); }
|
||||
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
|
||||
bool fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
bool res= udf.fix_fields(thd, tables, this, arg_count, args);
|
||||
bool res= udf.fix_fields(thd, this, arg_count, args);
|
||||
used_tables_cache= udf.used_tables_cache;
|
||||
const_item_cache= udf.const_item_cache;
|
||||
fixed= 1;
|
||||
@ -907,8 +908,10 @@ public:
|
||||
class Item_func_udf_float :public Item_udf_func
|
||||
{
|
||||
public:
|
||||
Item_func_udf_float(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
|
||||
Item_func_udf_float(udf_func *udf_arg, List<Item> &list)
|
||||
Item_func_udf_float(udf_func *udf_arg)
|
||||
:Item_udf_func(udf_arg) {}
|
||||
Item_func_udf_float(udf_func *udf_arg,
|
||||
List<Item> &list)
|
||||
:Item_udf_func(udf_arg, list) {}
|
||||
longlong val_int()
|
||||
{
|
||||
@ -932,8 +935,10 @@ class Item_func_udf_float :public Item_udf_func
|
||||
class Item_func_udf_int :public Item_udf_func
|
||||
{
|
||||
public:
|
||||
Item_func_udf_int(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
|
||||
Item_func_udf_int(udf_func *udf_arg, List<Item> &list)
|
||||
Item_func_udf_int(udf_func *udf_arg)
|
||||
:Item_udf_func(udf_arg) {}
|
||||
Item_func_udf_int(udf_func *udf_arg,
|
||||
List<Item> &list)
|
||||
:Item_udf_func(udf_arg, list) {}
|
||||
longlong val_int();
|
||||
double val_real() { return (double) Item_func_udf_int::val_int(); }
|
||||
@ -946,7 +951,8 @@ public:
|
||||
class Item_func_udf_decimal :public Item_udf_func
|
||||
{
|
||||
public:
|
||||
Item_func_udf_decimal(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
|
||||
Item_func_udf_decimal(udf_func *udf_arg)
|
||||
:Item_udf_func(udf_arg) {}
|
||||
Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_udf_func(udf_arg, list) {}
|
||||
longlong val_int();
|
||||
@ -961,7 +967,8 @@ public:
|
||||
class Item_func_udf_str :public Item_udf_func
|
||||
{
|
||||
public:
|
||||
Item_func_udf_str(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
|
||||
Item_func_udf_str(udf_func *udf_arg)
|
||||
:Item_udf_func(udf_arg) {}
|
||||
Item_func_udf_str(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_udf_func(udf_arg, list) {}
|
||||
String *val_str(String *);
|
||||
@ -998,8 +1005,10 @@ public:
|
||||
class Item_func_udf_float :public Item_real_func
|
||||
{
|
||||
public:
|
||||
Item_func_udf_float(udf_func *udf_arg) :Item_real_func() {}
|
||||
Item_func_udf_float(udf_func *udf_arg, List<Item> &list) :Item_real_func(list) {}
|
||||
Item_func_udf_float(udf_func *udf_arg)
|
||||
:Item_real_func() {}
|
||||
Item_func_udf_float(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_real_func(list) {}
|
||||
double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
|
||||
};
|
||||
|
||||
@ -1007,8 +1016,10 @@ class Item_func_udf_float :public Item_real_func
|
||||
class Item_func_udf_int :public Item_int_func
|
||||
{
|
||||
public:
|
||||
Item_func_udf_int(udf_func *udf_arg) :Item_int_func() {}
|
||||
Item_func_udf_int(udf_func *udf_arg, List<Item> &list) :Item_int_func(list) {}
|
||||
Item_func_udf_int(udf_func *udf_arg)
|
||||
:Item_int_func() {}
|
||||
Item_func_udf_int(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_int_func(list) {}
|
||||
longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; }
|
||||
};
|
||||
|
||||
@ -1016,8 +1027,10 @@ public:
|
||||
class Item_func_udf_decimal :public Item_int_func
|
||||
{
|
||||
public:
|
||||
Item_func_udf_decimal(udf_func *udf_arg) :Item_int_func() {}
|
||||
Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list) :Item_int_func(list) {}
|
||||
Item_func_udf_decimal(udf_func *udf_arg)
|
||||
:Item_int_func() {}
|
||||
Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_int_func(list) {}
|
||||
my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; }
|
||||
};
|
||||
|
||||
@ -1025,8 +1038,10 @@ public:
|
||||
class Item_func_udf_str :public Item_func
|
||||
{
|
||||
public:
|
||||
Item_func_udf_str(udf_func *udf_arg) :Item_func() {}
|
||||
Item_func_udf_str(udf_func *udf_arg, List<Item> &list) :Item_func(list) {}
|
||||
Item_func_udf_str(udf_func *udf_arg)
|
||||
:Item_func() {}
|
||||
Item_func_udf_str(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_func(list) {}
|
||||
String *val_str(String *)
|
||||
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
|
||||
double val_real() { DBUG_ASSERT(fixed == 1); null_value= 1; return 0.0; }
|
||||
@ -1116,7 +1131,7 @@ public:
|
||||
bool check();
|
||||
bool update();
|
||||
enum Item_result result_type () const { return cached_result_type; }
|
||||
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
void fix_length_and_dec();
|
||||
void print(String *str);
|
||||
void print_as_stmt(String *str);
|
||||
@ -1176,7 +1191,7 @@ public:
|
||||
String *val_str(String *str);
|
||||
my_decimal *val_decimal(my_decimal *decimal_buffer);
|
||||
/* fix_fields() binds variable name with its entry structure */
|
||||
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
void print(String *str);
|
||||
void set_null_value(CHARSET_INFO* cs);
|
||||
void set_value(const char *str, uint length, CHARSET_INFO* cs);
|
||||
@ -1230,7 +1245,7 @@ public:
|
||||
const char *func_name() const { return "match"; }
|
||||
void update_used_tables() {}
|
||||
table_map not_null_tables() const { return 0; }
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
bool eq(const Item *, bool binary_cmp) const;
|
||||
/* The following should be safe, even if we compare doubles */
|
||||
longlong val_int() { DBUG_ASSERT(fixed == 1); return val_real() != 0.0; }
|
||||
@ -1302,6 +1317,7 @@ class sp_name;
|
||||
class Item_func_sp :public Item_func
|
||||
{
|
||||
private:
|
||||
Name_resolution_context *context;
|
||||
sp_name *m_name;
|
||||
mutable sp_head *m_sp;
|
||||
TABLE *dummy_table;
|
||||
@ -1314,9 +1330,10 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
Item_func_sp(sp_name *name);
|
||||
Item_func_sp(Name_resolution_context *context_arg, sp_name *name);
|
||||
|
||||
Item_func_sp(sp_name *name, List<Item> &list);
|
||||
Item_func_sp(Name_resolution_context *context_arg,
|
||||
sp_name *name, List<Item> &list);
|
||||
|
||||
virtual ~Item_func_sp()
|
||||
{}
|
||||
@ -1361,6 +1378,9 @@ public:
|
||||
return result_field->val_str(str);
|
||||
}
|
||||
|
||||
virtual bool change_context_processor(byte *cntx)
|
||||
{ context= (Name_resolution_context *)cntx; return FALSE; }
|
||||
|
||||
void fix_length_and_dec();
|
||||
|
||||
};
|
||||
|
@ -53,7 +53,7 @@ void Item_row::illegal_method_call(const char *method)
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
|
||||
bool Item_row::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
null_value= 0;
|
||||
@ -61,7 +61,7 @@ bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
|
||||
Item **arg, **arg_end;
|
||||
for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
|
||||
{
|
||||
if ((*arg)->fix_fields(thd, tabl, arg))
|
||||
if ((*arg)->fix_fields(thd, arg))
|
||||
return TRUE;
|
||||
// we can't assign 'item' before, because fix_fields() can change arg
|
||||
Item *item= *arg;
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
illegal_method_call((const char*)"val_decimal");
|
||||
return 0;
|
||||
};
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
|
||||
table_map used_tables() const { return used_tables_cache; };
|
||||
bool const_item() const { return const_item_cache; };
|
||||
|
@ -461,7 +461,7 @@ String *Item_func_des_decrypt::val_str(String *str)
|
||||
struct st_des_keyblock keyblock;
|
||||
struct st_des_keyschedule keyschedule;
|
||||
String *res= args[0]->val_str(str);
|
||||
uint length=res->length(),tail;
|
||||
uint length= 0, tail;
|
||||
|
||||
if ((null_value=args[0]->null_value))
|
||||
goto error;
|
||||
|
@ -415,12 +415,12 @@ class Item_func_make_set :public Item_str_func
|
||||
public:
|
||||
Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {}
|
||||
String *val_str(String *str);
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||
bool fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
return ((!item->fixed && item->fix_fields(thd, tlist, &item)) ||
|
||||
return ((!item->fixed && item->fix_fields(thd, &item)) ||
|
||||
item->check_cols(1) ||
|
||||
Item_func::fix_fields(thd, tlist, ref));
|
||||
Item_func::fix_fields(thd, ref));
|
||||
}
|
||||
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
|
||||
void fix_length_and_dec();
|
||||
|
@ -130,7 +130,7 @@ Item_subselect::select_transformer(JOIN *join)
|
||||
}
|
||||
|
||||
|
||||
bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
|
||||
bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
|
||||
{
|
||||
char const *save_where= thd_param->where;
|
||||
bool res;
|
||||
@ -165,7 +165,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
|
||||
substitution= 0;
|
||||
thd->where= "checking transformed subquery";
|
||||
if (!(*ref)->fixed)
|
||||
ret= (*ref)->fix_fields(thd, tables, ref);
|
||||
ret= (*ref)->fix_fields(thd, ref);
|
||||
thd->where= save_where;
|
||||
return ret;
|
||||
}
|
||||
@ -833,7 +833,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
reference, also Item_sum_(max|min) can't be fixed after creation, so
|
||||
we do not check item->fixed
|
||||
*/
|
||||
if (item->fix_fields(thd, join->tables_list, 0))
|
||||
if (item->fix_fields(thd, 0))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
/* we added aggregate function => we have to change statistic */
|
||||
count_field_types(&join->tmp_table_param, join->all_fields, 0);
|
||||
@ -862,7 +862,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
|
||||
thd->lex->current_select= up= current->return_after_parsing();
|
||||
//optimizer never use Item **ref => we can pass 0 as parameter
|
||||
if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
|
||||
if (!optimizer || optimizer->fix_left(thd, 0))
|
||||
{
|
||||
thd->lex->current_select= current;
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
@ -873,7 +873,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
As far as Item_ref_in_optimizer do not substitute itself on fix_fields
|
||||
we can use same item for all selects.
|
||||
*/
|
||||
expr= new Item_direct_ref((Item**)optimizer->get_cache(),
|
||||
expr= new Item_direct_ref(&select_lex->context,
|
||||
(Item**)optimizer->get_cache(),
|
||||
(char *)"<no matter>",
|
||||
(char *)in_left_expr_name);
|
||||
|
||||
@ -893,7 +894,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
{
|
||||
bool tmp;
|
||||
Item *item= func->create(expr,
|
||||
new Item_ref_null_helper(this,
|
||||
new Item_ref_null_helper(&select_lex->context,
|
||||
this,
|
||||
select_lex->
|
||||
ref_pointer_array,
|
||||
(char *)"<ref>",
|
||||
@ -913,7 +915,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
we do not check join->having->fixed, because Item_and (from and_items)
|
||||
or comparison function (from func->create) can't be fixed after creation
|
||||
*/
|
||||
tmp= join->having->fix_fields(thd, join->tables_list, 0);
|
||||
tmp= join->having->fix_fields(thd, 0);
|
||||
select_lex->having_fix_field= 0;
|
||||
if (tmp)
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
@ -949,7 +951,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
and_items) or comparison function (from func->create) can't be
|
||||
fixed after creation
|
||||
*/
|
||||
tmp= join->having->fix_fields(thd, join->tables_list, 0);
|
||||
tmp= join->having->fix_fields(thd, 0);
|
||||
select_lex->having_fix_field= 0;
|
||||
if (tmp)
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
@ -971,7 +973,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
we do not check join->conds->fixed, because Item_and can't be fixed
|
||||
after creation
|
||||
*/
|
||||
if (join->conds->fix_fields(thd, join->tables_list, 0))
|
||||
if (join->conds->fix_fields(thd, 0))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
}
|
||||
else
|
||||
@ -985,7 +987,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
argument (reference) to fix_fields()
|
||||
*/
|
||||
item= func->create(expr,
|
||||
new Item_null_helper(this, item,
|
||||
new Item_null_helper(&select_lex->context,
|
||||
this, item,
|
||||
(char *)"<no matter>",
|
||||
(char *)"<result>"));
|
||||
#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
|
||||
@ -998,7 +1001,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
we do not check join->having->fixed, because comparison function
|
||||
(from func->create) can't be fixed after creation
|
||||
*/
|
||||
tmp= join->having->fix_fields(thd, join->tables_list, 0);
|
||||
tmp= join->having->fix_fields(thd, 0);
|
||||
select_lex->having_fix_field= 0;
|
||||
if (tmp)
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
@ -1048,7 +1051,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
||||
SELECT_LEX *current= thd->lex->current_select, *up;
|
||||
thd->lex->current_select= up= current->return_after_parsing();
|
||||
//optimizer never use Item **ref => we can pass 0 as parameter
|
||||
if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
|
||||
if (!optimizer || optimizer->fix_left(thd, 0))
|
||||
{
|
||||
thd->lex->current_select= current;
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
@ -1071,12 +1074,14 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
||||
if (select_lex->ref_pointer_array[i]->
|
||||
check_cols(left_expr->el(i)->cols()))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
Item *func= new Item_ref_null_helper(this,
|
||||
Item *func= new Item_ref_null_helper(&select_lex->context,
|
||||
this,
|
||||
select_lex->ref_pointer_array+i,
|
||||
(char *) "<no matter>",
|
||||
(char *) "<list ref>");
|
||||
func=
|
||||
eq_creator.create(new Item_direct_ref((*optimizer->get_cache())->
|
||||
eq_creator.create(new Item_direct_ref(&select_lex->context,
|
||||
(*optimizer->get_cache())->
|
||||
addr(i),
|
||||
(char *)"<no matter>",
|
||||
(char *)in_left_expr_name),
|
||||
@ -1099,7 +1104,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
||||
join->having can't be fixed after creation, so we do not check
|
||||
join->having->fixed
|
||||
*/
|
||||
if (join->having->fix_fields(thd, join->tables_list, 0))
|
||||
if (join->having->fix_fields(thd, 0))
|
||||
{
|
||||
select_lex->having_fix_field= 0;
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
@ -1118,7 +1123,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
||||
join->conds can't be fixed after creation, so we do not check
|
||||
join->conds->fixed
|
||||
*/
|
||||
if (join->conds->fix_fields(thd, join->tables_list, 0))
|
||||
if (join->conds->fix_fields(thd, 0))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
}
|
||||
|
||||
@ -1189,8 +1194,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
|
||||
|
||||
thd->lex->current_select= up= current->return_after_parsing();
|
||||
result= (!left_expr->fixed &&
|
||||
left_expr->fix_fields(thd, up->get_table_list(),
|
||||
optimizer->arguments()));
|
||||
left_expr->fix_fields(thd, optimizer->arguments()));
|
||||
/* fix_fields can change reference to left_expr, we need reassign it */
|
||||
left_expr= optimizer->arguments()[0];
|
||||
|
||||
|
@ -92,7 +92,7 @@ public:
|
||||
val_int();
|
||||
return null_value;
|
||||
}
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
virtual bool exec();
|
||||
virtual void fix_length_and_dec();
|
||||
table_map used_tables() const;
|
||||
@ -119,9 +119,9 @@ public:
|
||||
|
||||
friend class select_subselect;
|
||||
friend class Item_in_optimizer;
|
||||
friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **);
|
||||
friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **);
|
||||
friend bool Item_param::fix_fields(THD *, TABLE_LIST *, Item **);
|
||||
friend bool Item_field::fix_fields(THD *, Item **);
|
||||
friend bool Item_ref::fix_fields(THD *, Item **);
|
||||
friend bool Item_param::fix_fields(THD *, Item **);
|
||||
friend void mark_select_range_as_dependent(THD*,
|
||||
st_select_lex*, st_select_lex*,
|
||||
Field*, Item*, Item_ident*);
|
||||
|
@ -193,7 +193,7 @@ my_decimal *Item_sum_int::val_decimal(my_decimal *decimal_value)
|
||||
|
||||
|
||||
bool
|
||||
Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
Item_sum_num::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
|
||||
@ -208,7 +208,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
maybe_null=0;
|
||||
for (uint i=0 ; i < arg_count ; i++)
|
||||
{
|
||||
if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
|
||||
if (args[i]->fix_fields(thd, args + i) || args[i]->check_cols(1))
|
||||
return TRUE;
|
||||
set_if_bigger(decimals, args[i]->decimals);
|
||||
maybe_null |= args[i]->maybe_null;
|
||||
@ -253,7 +253,7 @@ Item_sum_hybrid::Item_sum_hybrid(THD *thd, Item_sum_hybrid *item)
|
||||
}
|
||||
|
||||
bool
|
||||
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
|
||||
@ -268,7 +268,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
|
||||
// 'item' can be changed during fix_fields
|
||||
if (!item->fixed &&
|
||||
item->fix_fields(thd, tables, args) ||
|
||||
item->fix_fields(thd, args) ||
|
||||
(item= args[0])->check_cols(1))
|
||||
return TRUE;
|
||||
decimals=item->decimals;
|
||||
@ -2766,11 +2766,12 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
|
||||
*/
|
||||
|
||||
Item_func_group_concat::
|
||||
Item_func_group_concat(bool distinct_arg, List<Item> *select_list,
|
||||
Item_func_group_concat(Name_resolution_context *context_arg,
|
||||
bool distinct_arg, List<Item> *select_list,
|
||||
SQL_LIST *order_list, String *separator_arg)
|
||||
:tmp_table_param(0), warning(0),
|
||||
separator(separator_arg), tree(0), table(0),
|
||||
order(0), tables_list(0),
|
||||
order(0), context(context_arg),
|
||||
arg_count_order(order_list ? order_list->elements : 0),
|
||||
arg_count_field(select_list->elements),
|
||||
count_cut_values(0),
|
||||
@ -2826,7 +2827,7 @@ Item_func_group_concat::Item_func_group_concat(THD *thd,
|
||||
tree(item->tree),
|
||||
table(item->table),
|
||||
order(item->order),
|
||||
tables_list(item->tables_list),
|
||||
context(item->context),
|
||||
arg_count_order(item->arg_count_order),
|
||||
arg_count_field(item->arg_count_field),
|
||||
count_cut_values(item->count_cut_values),
|
||||
@ -2946,7 +2947,7 @@ bool Item_func_group_concat::add()
|
||||
|
||||
|
||||
bool
|
||||
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
Item_func_group_concat::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
uint i; /* for loop variable */
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
@ -2968,7 +2969,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
for (i=0 ; i < arg_count ; i++)
|
||||
{
|
||||
if ((!args[i]->fixed &&
|
||||
args[i]->fix_fields(thd, tables, args + i)) ||
|
||||
args[i]->fix_fields(thd, args + i)) ||
|
||||
args[i]->check_cols(1))
|
||||
return TRUE;
|
||||
if (i < arg_count_field)
|
||||
@ -2979,7 +2980,6 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
null_value= 1;
|
||||
thd->allow_sum_func= 1;
|
||||
max_length= thd->variables.group_concat_max_len;
|
||||
tables_list= tables;
|
||||
fixed= 1;
|
||||
return FALSE;
|
||||
}
|
||||
@ -3029,7 +3029,7 @@ bool Item_func_group_concat::setup(THD *thd)
|
||||
tmp table columns.
|
||||
*/
|
||||
if (arg_count_order &&
|
||||
setup_order(thd, args, tables_list, list, all_fields, *order))
|
||||
setup_order(thd, args, context->table_list, list, all_fields, *order))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
count_field_types(tmp_table_param,all_fields,0);
|
||||
|
@ -124,7 +124,7 @@ public:
|
||||
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
|
||||
Item_sum_num(List<Item> &list) :Item_sum(list) {}
|
||||
Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {}
|
||||
bool fix_fields(THD *, TABLE_LIST *, Item **);
|
||||
bool fix_fields(THD *, Item **);
|
||||
longlong val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
@ -543,7 +543,7 @@ protected:
|
||||
was_values(TRUE)
|
||||
{ collation.set(&my_charset_bin); }
|
||||
Item_sum_hybrid(THD *thd, Item_sum_hybrid *item);
|
||||
bool fix_fields(THD *, TABLE_LIST *, Item **);
|
||||
bool fix_fields(THD *, Item **);
|
||||
table_map used_tables() const { return used_table_cache; }
|
||||
bool const_item() const { return !used_table_cache; }
|
||||
|
||||
@ -660,18 +660,21 @@ protected:
|
||||
udf_handler udf;
|
||||
|
||||
public:
|
||||
Item_udf_sum(udf_func *udf_arg) :Item_sum(), udf(udf_arg) { quick_group=0;}
|
||||
Item_udf_sum(udf_func *udf_arg)
|
||||
:Item_sum(), udf(udf_arg)
|
||||
{ quick_group=0; }
|
||||
Item_udf_sum(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_sum(list), udf(udf_arg)
|
||||
{ quick_group=0;}
|
||||
Item_udf_sum(THD *thd, Item_udf_sum *item)
|
||||
:Item_sum(thd, item), udf(item->udf) { udf.not_original= TRUE; }
|
||||
:Item_sum(thd, item), udf(item->udf)
|
||||
{ udf.not_original= TRUE; }
|
||||
const char *func_name() const { return udf.name(); }
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
bool fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
fixed= 1;
|
||||
return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
|
||||
return udf.fix_fields(thd, this, this->arg_count, this->args);
|
||||
}
|
||||
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
|
||||
virtual bool have_field_update(void) const { return 0; }
|
||||
@ -688,7 +691,8 @@ public:
|
||||
class Item_sum_udf_float :public Item_udf_sum
|
||||
{
|
||||
public:
|
||||
Item_sum_udf_float(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
|
||||
Item_sum_udf_float(udf_func *udf_arg)
|
||||
:Item_udf_sum(udf_arg) {}
|
||||
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_udf_sum(udf_arg, list) {}
|
||||
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
|
||||
@ -709,7 +713,8 @@ class Item_sum_udf_float :public Item_udf_sum
|
||||
class Item_sum_udf_int :public Item_udf_sum
|
||||
{
|
||||
public:
|
||||
Item_sum_udf_int(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
|
||||
Item_sum_udf_int(udf_func *udf_arg)
|
||||
:Item_udf_sum(udf_arg) {}
|
||||
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_udf_sum(udf_arg, list) {}
|
||||
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
|
||||
@ -728,7 +733,8 @@ public:
|
||||
class Item_sum_udf_str :public Item_udf_sum
|
||||
{
|
||||
public:
|
||||
Item_sum_udf_str(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
|
||||
Item_sum_udf_str(udf_func *udf_arg)
|
||||
:Item_udf_sum(udf_arg) {}
|
||||
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_udf_sum(udf_arg,list) {}
|
||||
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
|
||||
@ -766,7 +772,8 @@ public:
|
||||
class Item_sum_udf_decimal :public Item_udf_sum
|
||||
{
|
||||
public:
|
||||
Item_sum_udf_decimal(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
|
||||
Item_sum_udf_decimal(udf_func *udf_arg)
|
||||
:Item_udf_sum(udf_arg) {}
|
||||
Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_udf_sum(udf_arg, list) {}
|
||||
Item_sum_udf_decimal(THD *thd, Item_sum_udf_decimal *item)
|
||||
@ -785,7 +792,8 @@ public:
|
||||
class Item_sum_udf_float :public Item_sum_num
|
||||
{
|
||||
public:
|
||||
Item_sum_udf_float(udf_func *udf_arg) :Item_sum_num() {}
|
||||
Item_sum_udf_float(udf_func *udf_arg)
|
||||
:Item_sum_num() {}
|
||||
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
|
||||
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
|
||||
:Item_sum_num(thd, item) {}
|
||||
@ -800,7 +808,8 @@ class Item_sum_udf_float :public Item_sum_num
|
||||
class Item_sum_udf_int :public Item_sum_num
|
||||
{
|
||||
public:
|
||||
Item_sum_udf_int(udf_func *udf_arg) :Item_sum_num() {}
|
||||
Item_sum_udf_int(udf_func *udf_arg)
|
||||
:Item_sum_num() {}
|
||||
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
|
||||
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
|
||||
:Item_sum_num(thd, item) {}
|
||||
@ -816,8 +825,10 @@ public:
|
||||
class Item_sum_udf_decimal :public Item_sum_num
|
||||
{
|
||||
public:
|
||||
Item_sum_udf_decimal(udf_func *udf_arg) :Item_sum_num() {}
|
||||
Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
|
||||
Item_sum_udf_decimal(udf_func *udf_arg)
|
||||
:Item_sum_num() {}
|
||||
Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_sum_num() {}
|
||||
Item_sum_udf_decimal(THD *thd, Item_sum_udf_float *item)
|
||||
:Item_sum_num(thd, item) {}
|
||||
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
|
||||
@ -832,8 +843,10 @@ class Item_sum_udf_decimal :public Item_sum_num
|
||||
class Item_sum_udf_str :public Item_sum_num
|
||||
{
|
||||
public:
|
||||
Item_sum_udf_str(udf_func *udf_arg) :Item_sum_num() {}
|
||||
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
|
||||
Item_sum_udf_str(udf_func *udf_arg)
|
||||
:Item_sum_num() {}
|
||||
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list)
|
||||
:Item_sum_num() {}
|
||||
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
|
||||
:Item_sum_num(thd, item) {}
|
||||
String *val_str(String *)
|
||||
@ -862,7 +875,7 @@ class Item_func_group_concat : public Item_sum
|
||||
TREE *tree;
|
||||
TABLE *table;
|
||||
ORDER **order;
|
||||
TABLE_LIST *tables_list;
|
||||
Name_resolution_context *context;
|
||||
uint arg_count_order; // total count of ORDER BY items
|
||||
uint arg_count_field; // count of arguments
|
||||
uint count_cut_values;
|
||||
@ -887,7 +900,8 @@ class Item_func_group_concat : public Item_sum
|
||||
Item_func_group_concat *group_concat_item);
|
||||
|
||||
public:
|
||||
Item_func_group_concat(bool is_distinct,List<Item> *is_select,
|
||||
Item_func_group_concat(Name_resolution_context *context_arg,
|
||||
bool is_distinct, List<Item> *is_select,
|
||||
SQL_LIST *is_order, String *is_separator);
|
||||
|
||||
Item_func_group_concat(THD *thd, Item_func_group_concat *item);
|
||||
@ -901,7 +915,7 @@ public:
|
||||
bool add();
|
||||
void reset_field() {} // not used
|
||||
void update_field() {} // not used
|
||||
bool fix_fields(THD *, TABLE_LIST *, Item **);
|
||||
bool fix_fields(THD *,Item **);
|
||||
bool setup(THD *thd);
|
||||
void make_unique();
|
||||
double val_real()
|
||||
@ -927,4 +941,6 @@ public:
|
||||
Item *copy_or_same(THD* thd);
|
||||
void no_rows_in_result() {}
|
||||
void print(String *str);
|
||||
virtual bool change_context_processor(byte *cntx)
|
||||
{ context= (Name_resolution_context *)cntx; return FALSE; }
|
||||
};
|
||||
|
@ -1753,10 +1753,10 @@ void Item_func_convert_tz::fix_length_and_dec()
|
||||
|
||||
|
||||
bool
|
||||
Item_func_convert_tz::fix_fields(THD *thd_arg, TABLE_LIST *tables_arg, Item **ref)
|
||||
Item_func_convert_tz::fix_fields(THD *thd_arg, Item **ref)
|
||||
{
|
||||
String str;
|
||||
if (Item_date_func::fix_fields(thd_arg, tables_arg, ref))
|
||||
if (Item_date_func::fix_fields(thd_arg, ref))
|
||||
return TRUE;
|
||||
|
||||
tz_tables= thd_arg->lex->time_zone_tables_used;
|
||||
|
@ -561,7 +561,7 @@ class Item_func_convert_tz :public Item_date_func
|
||||
double val_real() { return (double) val_int(); }
|
||||
String *val_str(String *str);
|
||||
const char *func_name() const { return "convert_tz"; }
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
bool fix_fields(THD *, Item **);
|
||||
void fix_length_and_dec();
|
||||
bool get_date(TIME *res, uint fuzzy_date);
|
||||
void cleanup();
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
bool add() { return 0; }
|
||||
void reset_field() {}
|
||||
void update_field() {}
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||
bool fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
fixed= 1;
|
||||
|
@ -2618,13 +2618,15 @@ void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ev
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
void Load_log_event::set_fields(const char* affected_db,
|
||||
List<Item> &field_list)
|
||||
List<Item> &field_list,
|
||||
Name_resolution_context *context)
|
||||
{
|
||||
uint i;
|
||||
const char* field = fields;
|
||||
for (i= 0; i < num_fields; i++)
|
||||
{
|
||||
field_list.push_back(new Item_field(affected_db, table_name, field));
|
||||
field_list.push_back(new Item_field(context,
|
||||
affected_db, table_name, field));
|
||||
field+= field_lens[i] + 1;
|
||||
}
|
||||
}
|
||||
@ -2789,7 +2791,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
|
||||
|
||||
ex.skip_lines = skip_lines;
|
||||
List<Item> field_list;
|
||||
set_fields(thd->db,field_list);
|
||||
thd->main_lex.select_lex.context.resolve_in_table_list_only(&tables);
|
||||
set_fields(thd->db, field_list, &thd->main_lex.select_lex.context);
|
||||
thd->variables.pseudo_thread_id= thread_id;
|
||||
List<Item> set_fields;
|
||||
if (net)
|
||||
@ -3617,7 +3620,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
|
||||
Item_func_set_user_var can't substitute something else on its place =>
|
||||
0 can be passed as last argument (reference on item)
|
||||
*/
|
||||
e.fix_fields(thd, 0, 0);
|
||||
e.fix_fields(thd, 0);
|
||||
/*
|
||||
A variable can just be considered as a table with
|
||||
a single record and with a single column. Thus, like
|
||||
|
@ -877,7 +877,8 @@ public:
|
||||
const char* table_name_arg,
|
||||
List<Item>& fields_arg, enum enum_duplicates handle_dup, bool ignore,
|
||||
bool using_trans);
|
||||
void set_fields(const char* db, List<Item> &fields_arg);
|
||||
void set_fields(const char* db, List<Item> &fields_arg,
|
||||
Name_resolution_context *context);
|
||||
const char* get_db() { return db; }
|
||||
#ifdef HAVE_REPLICATION
|
||||
void pack_info(Protocol* protocol);
|
||||
|
@ -726,7 +726,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
|
||||
List<List_item> &values, List<Item> &update_fields,
|
||||
List<Item> &update_values, enum_duplicates flag,
|
||||
bool ignore);
|
||||
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry);
|
||||
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
|
||||
TABLE_LIST *table_list);
|
||||
bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
|
||||
bool mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order,
|
||||
ha_rows rows, ulong options);
|
||||
@ -893,16 +894,29 @@ Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
|
||||
bool *unaliased);
|
||||
bool get_key_map_from_key_list(key_map *map, TABLE *table,
|
||||
List<String> *index_list);
|
||||
bool insert_fields(THD *thd,TABLE_LIST *tables,
|
||||
bool insert_fields(THD *thd, Name_resolution_context *context,
|
||||
const char *db_name, const char *table_name,
|
||||
List_iterator<Item> *it, bool any_privileges);
|
||||
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
|
||||
bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||
TABLE_LIST *tables, Item **conds,
|
||||
TABLE_LIST **leaves, bool select_insert);
|
||||
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||
List<Item> *sum_func_list, uint wild_num);
|
||||
bool setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
|
||||
bool setup_fields(THD *thd, Item** ref_pointer_array,
|
||||
List<Item> &item, bool set_query_id,
|
||||
List<Item> *sum_func_list, bool allow_sum_func);
|
||||
inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array,
|
||||
List<Item> &item, bool set_query_id,
|
||||
List<Item> *sum_func_list,
|
||||
bool allow_sum_func)
|
||||
{
|
||||
bool res;
|
||||
thd->lex->select_lex.no_wrap_view_item= TRUE;
|
||||
res= setup_fields(thd, ref_pointer_array, item, set_query_id, sum_func_list,
|
||||
allow_sum_func);
|
||||
thd->lex->select_lex.no_wrap_view_item= FALSE;
|
||||
return res;
|
||||
}
|
||||
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||
COND **conds);
|
||||
int setup_ftfuncs(SELECT_LEX* select);
|
||||
|
@ -2983,7 +2983,7 @@ int set_var::check(THD *thd)
|
||||
}
|
||||
|
||||
if ((!value->fixed &&
|
||||
value->fix_fields(thd, 0, &value)) || value->check_cols(1))
|
||||
value->fix_fields(thd, &value)) || value->check_cols(1))
|
||||
return -1;
|
||||
if (var->check_update_type(value->result_type()))
|
||||
{
|
||||
@ -3017,7 +3017,7 @@ int set_var::light_check(THD *thd)
|
||||
if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
|
||||
return 1;
|
||||
|
||||
if (value && ((!value->fixed && value->fix_fields(thd, 0, &value)) ||
|
||||
if (value && ((!value->fixed && value->fix_fields(thd, &value)) ||
|
||||
value->check_cols(1)))
|
||||
return -1;
|
||||
return 0;
|
||||
@ -3046,7 +3046,7 @@ int set_var_user::check(THD *thd)
|
||||
Item_func_set_user_var can't substitute something else on its place =>
|
||||
0 can be passed as last argument (reference on item)
|
||||
*/
|
||||
return (user_var_item->fix_fields(thd, 0, (Item**) 0) ||
|
||||
return (user_var_item->fix_fields(thd, (Item**) 0) ||
|
||||
user_var_item->check()) ? -1 : 0;
|
||||
}
|
||||
|
||||
@ -3069,7 +3069,7 @@ int set_var_user::light_check(THD *thd)
|
||||
Item_func_set_user_var can't substitute something else on its place =>
|
||||
0 can be passed as last argument (reference on item)
|
||||
*/
|
||||
return (user_var_item->fix_fields(thd, 0, (Item**) 0));
|
||||
return (user_var_item->fix_fields(thd, (Item**) 0));
|
||||
}
|
||||
|
||||
|
||||
|
@ -5358,3 +5358,5 @@ ER_STMT_HAS_NO_OPEN_CURSOR
|
||||
eng "The statement (%lu) has no open cursor."
|
||||
ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
|
||||
eng "Explicit or implicit commit is not allowed in stored function or trigger."
|
||||
ER_NO_DEFAULT_FOR_VIEW_FIELD
|
||||
eng "Field of view '%-.64s.%-.64s' underlying table doesn't have a default value"
|
||||
|
10
sql/sp.cc
10
sql/sp.cc
@ -676,14 +676,18 @@ db_show_routine_status(THD *thd, int type, const char *wild)
|
||||
|
||||
tables is not VIEW for sure => we can pass 0 as condition
|
||||
*/
|
||||
setup_tables(thd, &tables, 0, &leaves, FALSE);
|
||||
thd->lex->select_lex.context.resolve_in_table_list_only(&tables);
|
||||
setup_tables(thd, &thd->lex->select_lex.context,
|
||||
&tables, 0, &leaves, FALSE);
|
||||
for (used_field= &used_fields[0];
|
||||
used_field->field_name;
|
||||
used_field++)
|
||||
{
|
||||
Item_field *field= new Item_field("mysql", "proc",
|
||||
Item_field *field= new Item_field(&thd->lex->select_lex.context,
|
||||
"mysql", "proc",
|
||||
used_field->field_name);
|
||||
if (!(used_field->field= find_field_in_tables(thd, field, &tables,
|
||||
if (!field ||
|
||||
!(used_field->field= find_field_in_tables(thd, field, &tables,
|
||||
0, REPORT_ALL_ERRORS, 1)))
|
||||
{
|
||||
res= SP_INTERNAL_ERROR;
|
||||
|
@ -117,7 +117,7 @@ sp_prepare_func_item(THD* thd, Item **it_addr)
|
||||
DBUG_ENTER("sp_prepare_func_item");
|
||||
it_addr= it->this_item_addr(thd, it_addr);
|
||||
|
||||
if (!it->fixed && (*it_addr)->fix_fields(thd, 0, it_addr))
|
||||
if (!it->fixed && (*it_addr)->fix_fields(thd, it_addr))
|
||||
{
|
||||
DBUG_PRINT("info", ("fix_fields() failed"));
|
||||
DBUG_RETURN(NULL);
|
||||
@ -962,7 +962,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
||||
we do not check suv->fixed, because it can't be fixed after
|
||||
creation
|
||||
*/
|
||||
suv->fix_fields(thd, NULL, &item);
|
||||
suv->fix_fields(thd, &item);
|
||||
suv->fix_length_and_dec();
|
||||
suv->check();
|
||||
suv->update();
|
||||
@ -1579,8 +1579,8 @@ sp_instr_set_trigger_field::execute(THD *thd, uint *nextp)
|
||||
|
||||
DBUG_ENTER("sp_instr_set_trigger_field::execute");
|
||||
/* QQ: Still unsure what should we return in case of error 1 or -1 ? */
|
||||
if (!value->fixed && value->fix_fields(thd, 0, &value) ||
|
||||
trigger_field->fix_fields(thd, 0, 0) ||
|
||||
if (!value->fixed && value->fix_fields(thd, &value) ||
|
||||
trigger_field->fix_fields(thd, 0) ||
|
||||
(value->save_in_field(trigger_field->field, 0) < 0))
|
||||
res= -1;
|
||||
*nextp= m_ip + 1;
|
||||
|
@ -470,10 +470,11 @@ class sp_instr_set_trigger_field : public sp_instr
|
||||
|
||||
public:
|
||||
|
||||
sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx,
|
||||
sp_instr_set_trigger_field(Name_resolution_context *context_arg,
|
||||
uint ip, sp_pcontext *ctx,
|
||||
Item_trigger_field *trg_fld, Item *val)
|
||||
: sp_instr(ip, ctx),
|
||||
trigger_field(trg_fld),
|
||||
trigger_field(context_arg, trg_fld),
|
||||
value(val)
|
||||
{}
|
||||
|
||||
|
173
sql/sql_base.cc
173
sql/sql_base.cc
@ -2439,21 +2439,19 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
||||
table_list->alias, name, item_name, (ulong) ref));
|
||||
if (table_list->field_translation)
|
||||
{
|
||||
uint num;
|
||||
if (table_list->schema_table_reformed)
|
||||
Field_iterator_view field_it;
|
||||
field_it.set(table_list);
|
||||
DBUG_ASSERT(table_list->schema_table_reformed ||
|
||||
(ref != 0 && table_list->view != 0));
|
||||
for (; !field_it.end_of_fields(); field_it.next())
|
||||
{
|
||||
num= thd->lex->current_select->item_list.elements;
|
||||
if (!my_strcasecmp(system_charset_info, field_it.name(), name))
|
||||
{
|
||||
Item *item= field_it.create_item(thd);
|
||||
if (!item)
|
||||
{
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(ref != 0 && table_list->view != 0);
|
||||
num= table_list->view->select_lex.item_list.elements;
|
||||
}
|
||||
Field_translator *trans= table_list->field_translation;
|
||||
for (uint i= 0; i < num; i ++)
|
||||
{
|
||||
if (!my_strcasecmp(system_charset_info, trans[i].name, name))
|
||||
{
|
||||
if (table_list->schema_table_reformed)
|
||||
{
|
||||
/*
|
||||
@ -2462,7 +2460,7 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
||||
So we can return ->field. It is used only for
|
||||
'show & where' commands.
|
||||
*/
|
||||
DBUG_RETURN(((Item_field*) (trans[i].item))->field);
|
||||
DBUG_RETURN(((Item_field*) (field_it.item()))->field);
|
||||
}
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (check_grants_view &&
|
||||
@ -2472,26 +2470,10 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
||||
name, length))
|
||||
DBUG_RETURN(WRONG_GRANT);
|
||||
#endif
|
||||
if (thd->lex->current_select->no_wrap_view_item)
|
||||
{
|
||||
if (register_tree_change)
|
||||
thd->change_item_tree(ref, trans[i].item);
|
||||
thd->change_item_tree(ref, item);
|
||||
else
|
||||
*ref= trans[i].item;
|
||||
}
|
||||
else
|
||||
{
|
||||
Item_ref *item_ref= new Item_ref(&trans[i].item,
|
||||
table_list->view_name.str,
|
||||
item_name);
|
||||
/* as far as Item_ref have defined reference it do not need tables */
|
||||
if (register_tree_change && item_ref)
|
||||
thd->change_item_tree(ref, item_ref);
|
||||
else if (item_ref)
|
||||
*ref= item_ref;
|
||||
if (!(*ref)->fixed)
|
||||
(*ref)->fix_fields(thd, 0, ref);
|
||||
}
|
||||
*ref= item;
|
||||
DBUG_RETURN((Field*) view_ref_found);
|
||||
}
|
||||
}
|
||||
@ -3066,7 +3048,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||
*/
|
||||
it.replace(new Item_int("Not_used", (longlong) 1, 21));
|
||||
}
|
||||
else if (insert_fields(thd,tables,((Item_field*) item)->db_name,
|
||||
else if (insert_fields(thd, ((Item_field*) item)->context,
|
||||
((Item_field*) item)->db_name,
|
||||
((Item_field*) item)->table_name, &it,
|
||||
any_privileges))
|
||||
{
|
||||
@ -3102,7 +3085,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||
** Check that all given fields exists and fill struct with current data
|
||||
****************************************************************************/
|
||||
|
||||
bool setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
bool setup_fields(THD *thd, Item **ref_pointer_array,
|
||||
List<Item> &fields, bool set_query_id,
|
||||
List<Item> *sum_func_list, bool allow_sum_func)
|
||||
{
|
||||
@ -3131,7 +3114,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
Item **ref= ref_pointer_array;
|
||||
while ((item= it++))
|
||||
{
|
||||
if (!item->fixed && item->fix_fields(thd, tables, it.ref()) ||
|
||||
if (!item->fixed && item->fix_fields(thd, it.ref()) ||
|
||||
(item= *(it.ref()))->check_cols(1))
|
||||
{
|
||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||
@ -3181,6 +3164,7 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
|
||||
SYNOPSIS
|
||||
setup_tables()
|
||||
thd Thread handler
|
||||
context name resolution contest to setup table list there
|
||||
tables Table list
|
||||
conds Condition of current SELECT (can be changed by VIEW)
|
||||
leaves List of join table leaves list
|
||||
@ -3200,11 +3184,15 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
|
||||
TRUE error
|
||||
*/
|
||||
|
||||
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
|
||||
bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||
TABLE_LIST *tables, Item **conds,
|
||||
TABLE_LIST **leaves, bool select_insert)
|
||||
{
|
||||
uint tablenr= 0;
|
||||
DBUG_ENTER("setup_tables");
|
||||
|
||||
context->table_list= tables;
|
||||
|
||||
/*
|
||||
this is used for INSERT ... SELECT.
|
||||
For select we setup tables except first (and its underlying tables)
|
||||
@ -3259,11 +3247,22 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
|
||||
table_list;
|
||||
table_list= table_list->next_local)
|
||||
{
|
||||
if (table_list->ancestor &&
|
||||
table_list->setup_ancestor(thd, conds,
|
||||
table_list->effective_with_check))
|
||||
if (table_list->ancestor)
|
||||
{
|
||||
DBUG_ASSERT(table_list->view);
|
||||
Query_arena *arena= thd->current_arena, backup;
|
||||
bool res;
|
||||
if (arena->is_conventional())
|
||||
arena= 0; // For easier test
|
||||
else
|
||||
thd->set_n_backup_item_arena(arena, &backup);
|
||||
res= table_list->setup_ancestor(thd);
|
||||
if (arena)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
if (res)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -3314,7 +3313,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
|
||||
SYNOPSIS
|
||||
insert_fields()
|
||||
thd Thread handler
|
||||
tables List of tables
|
||||
context Context for name resolution
|
||||
db_name Database name in case of 'database_name.table_name.*'
|
||||
table_name Table name in case of 'table_name.*'
|
||||
it Pointer to '*'
|
||||
@ -3328,7 +3327,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
|
||||
*/
|
||||
|
||||
bool
|
||||
insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
||||
insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
const char *table_name, List_iterator<Item> *it,
|
||||
bool any_privileges)
|
||||
{
|
||||
@ -3352,7 +3351,9 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
||||
}
|
||||
|
||||
found= 0;
|
||||
for (; tables; tables= tables->next_local)
|
||||
for (TABLE_LIST *tables= context->table_list;
|
||||
tables;
|
||||
tables= tables->next_local)
|
||||
{
|
||||
Field_iterator *iterator;
|
||||
TABLE_LIST *natural_join_table;
|
||||
@ -3361,7 +3362,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
||||
TABLE_LIST *last;
|
||||
TABLE_LIST *embedding;
|
||||
TABLE *table= tables->table;
|
||||
bool alias_used= 0;
|
||||
|
||||
if (!table_name || (!my_strcasecmp(table_alias_charset, table_name,
|
||||
tables->alias) &&
|
||||
@ -3395,16 +3395,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (table)
|
||||
thd->used_tables|= table->map;
|
||||
else
|
||||
{
|
||||
view_iter.set(tables);
|
||||
for (; !view_iter.end_of_fields(); view_iter.next())
|
||||
{
|
||||
thd->used_tables|= view_iter.item(thd)->used_tables();
|
||||
}
|
||||
}
|
||||
natural_join_table= 0;
|
||||
last= embedded= tables;
|
||||
|
||||
@ -3435,8 +3425,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
||||
{
|
||||
iterator= &view_iter;
|
||||
view= 1;
|
||||
alias_used= my_strcasecmp(table_alias_charset,
|
||||
tables->table_name, tables->alias);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3445,6 +3433,10 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
||||
}
|
||||
iterator->set(tables);
|
||||
|
||||
/* for view used tables will be collected in following loop */
|
||||
if (table)
|
||||
thd->used_tables|= table->map;
|
||||
|
||||
for (; !iterator->end_of_fields(); iterator->next())
|
||||
{
|
||||
Item *not_used_item;
|
||||
@ -3457,16 +3449,10 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
||||
strlen(field_name), ¬_used_item, 0, 0, 0,
|
||||
¬_used_field_index, TRUE))
|
||||
{
|
||||
Item *item= iterator->item(thd);
|
||||
if (view && !thd->lex->current_select->no_wrap_view_item)
|
||||
{
|
||||
/*
|
||||
as far as we have view, then item point to view_iter, so we
|
||||
can use it directly for this view specific operation
|
||||
*/
|
||||
item= new Item_ref(view_iter.item_ptr(), tables->view_name.str,
|
||||
field_name);
|
||||
}
|
||||
Item *item= iterator->create_item(thd);
|
||||
if (!item)
|
||||
goto err;
|
||||
thd->used_tables|= item->used_tables();
|
||||
if (!found++)
|
||||
(void) it->replace(item); // Replace '*'
|
||||
else
|
||||
@ -3537,9 +3523,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
||||
my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0));
|
||||
else
|
||||
my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name);
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
err:
|
||||
#endif
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
@ -3550,16 +3534,25 @@ err:
|
||||
SYNOPSIS
|
||||
setup_conds()
|
||||
thd thread handler
|
||||
tables list of tables for name resolving
|
||||
leaves list of leaves of join table tree
|
||||
*/
|
||||
|
||||
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
||||
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||
COND **conds)
|
||||
{
|
||||
SELECT_LEX *select_lex= thd->lex->current_select;
|
||||
Query_arena *arena= thd->current_arena, backup;
|
||||
bool save_wrapper= thd->lex->current_select->no_wrap_view_item;
|
||||
TABLE_LIST *table= NULL; // For HP compilers
|
||||
/*
|
||||
it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX
|
||||
which belong to LEX, i.e. most up SELECT) will be updated by
|
||||
INSERT/UPDATE/LOAD
|
||||
NOTE: using this condition helps to prevent call of prepare_check_option()
|
||||
from subquery of VIEW, because tables of subquery belongs to VIEW
|
||||
(see condition before prepare_check_option() call)
|
||||
*/
|
||||
bool it_is_update= (select_lex == &thd->lex->select_lex) &&
|
||||
thd->lex->which_check_option_applicable();
|
||||
DBUG_ENTER("setup_conds");
|
||||
|
||||
if (select_lex->conds_processed_with_permanent_arena ||
|
||||
@ -3568,12 +3561,17 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
||||
|
||||
thd->set_query_id=1;
|
||||
|
||||
thd->lex->current_select->no_wrap_view_item= 0;
|
||||
for (table= tables; table; table= table->next_local)
|
||||
{
|
||||
if (table->prepare_where(thd, conds, FALSE))
|
||||
goto err_no_arena;
|
||||
}
|
||||
|
||||
select_lex->cond_count= 0;
|
||||
if (*conds)
|
||||
{
|
||||
thd->where="where clause";
|
||||
if (!(*conds)->fixed && (*conds)->fix_fields(thd, tables, conds) ||
|
||||
if (!(*conds)->fixed && (*conds)->fix_fields(thd, conds) ||
|
||||
(*conds)->check_cols(1))
|
||||
goto err_no_arena;
|
||||
}
|
||||
@ -3591,11 +3589,12 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
||||
/* Make a join an a expression */
|
||||
thd->where="on clause";
|
||||
if (!embedded->on_expr->fixed &&
|
||||
embedded->on_expr->fix_fields(thd, tables, &embedded->on_expr) ||
|
||||
embedded->on_expr->fix_fields(thd, &embedded->on_expr) ||
|
||||
embedded->on_expr->check_cols(1))
|
||||
goto err_no_arena;
|
||||
select_lex->cond_count++;
|
||||
}
|
||||
|
||||
if (embedded->natural_join)
|
||||
{
|
||||
/* Make a join of all fields wich have the same name */
|
||||
@ -3675,7 +3674,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
||||
{
|
||||
if (t2_field != view_ref_found)
|
||||
{
|
||||
if (!(item_t2= new Item_field(thd, t2_field)))
|
||||
if (!(item_t2= new Item_field(thd, &select_lex->context,
|
||||
t2_field)))
|
||||
goto err;
|
||||
/* Mark field used for table cache */
|
||||
t2_field->query_id= thd->query_id;
|
||||
@ -3687,7 +3687,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
||||
t1_field->query_id= thd->query_id;
|
||||
t1->used_keys.intersect(t1_field->part_of_key);
|
||||
}
|
||||
Item_func_eq *tmp= new Item_func_eq(iterator->item(thd),
|
||||
Item_func_eq *tmp= new Item_func_eq(iterator->create_item(thd),
|
||||
item_t2);
|
||||
if (!tmp)
|
||||
goto err;
|
||||
@ -3703,7 +3703,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
||||
{
|
||||
COND *on_expr= cond_and;
|
||||
if (!on_expr->fixed)
|
||||
on_expr->fix_fields(thd, 0, &on_expr);
|
||||
on_expr->fix_fields(thd, &on_expr);
|
||||
if (!embedded->outer_join) // Not left join
|
||||
{
|
||||
*conds= and_conds(*conds, cond_and);
|
||||
@ -3712,7 +3712,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
if (*conds && !(*conds)->fixed)
|
||||
{
|
||||
if ((*conds)->fix_fields(thd, tables, conds))
|
||||
if ((*conds)->fix_fields(thd, conds))
|
||||
goto err_no_arena;
|
||||
}
|
||||
}
|
||||
@ -3724,8 +3724,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
if (embedded->on_expr && !embedded->on_expr->fixed)
|
||||
{
|
||||
if (embedded->on_expr->fix_fields(thd, tables,
|
||||
&embedded->on_expr))
|
||||
if (embedded->on_expr->fix_fields(thd, &embedded->on_expr))
|
||||
goto err_no_arena;
|
||||
}
|
||||
}
|
||||
@ -3737,6 +3736,20 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
||||
}
|
||||
while (embedding &&
|
||||
embedding->nested_join->join_list.head() == embedded);
|
||||
|
||||
/* process CHECK OPTION */
|
||||
if (it_is_update)
|
||||
{
|
||||
TABLE_LIST *view= table->belong_to_view;
|
||||
if (!view)
|
||||
view= table;
|
||||
if (view->effective_with_check)
|
||||
{
|
||||
if (view->prepare_check_option(thd))
|
||||
goto err_no_arena;
|
||||
thd->change_item_tree(&table->check_option, view->check_option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!thd->current_arena->is_conventional())
|
||||
@ -3750,14 +3763,12 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
||||
select_lex->where= *conds;
|
||||
select_lex->conds_processed_with_permanent_arena= 1;
|
||||
}
|
||||
thd->lex->current_select->no_wrap_view_item= save_wrapper;
|
||||
DBUG_RETURN(test(thd->net.report_error));
|
||||
|
||||
err:
|
||||
if (arena)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
err_no_arena:
|
||||
thd->lex->current_select->no_wrap_view_item= save_wrapper;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
@ -1451,17 +1451,16 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
||||
(void)local_vars.push_back(new Item_splocal(mv->s, mv->offset));
|
||||
else
|
||||
{
|
||||
Item_func_set_user_var *xx = new Item_func_set_user_var(mv->s, item);
|
||||
Item_func_set_user_var *var= new Item_func_set_user_var(mv->s, item);
|
||||
/*
|
||||
Item_func_set_user_var can't substitute something else on its place =>
|
||||
0 can be passed as last argument (reference on item)
|
||||
Item_func_set_user_var can't be fixed after creation, so we do not
|
||||
check xx->fixed
|
||||
check var->fixed
|
||||
*/
|
||||
xx->fix_fields(thd, (TABLE_LIST*) thd->lex->select_lex.table_list.first,
|
||||
0);
|
||||
xx->fix_length_and_dec();
|
||||
vars.push_back(xx);
|
||||
var->fix_fields(thd, 0);
|
||||
var->fix_length_and_dec();
|
||||
vars.push_back(var);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -1538,15 +1537,19 @@ void Statement::set_statement(Statement *stmt)
|
||||
void
|
||||
Statement::set_n_backup_statement(Statement *stmt, Statement *backup)
|
||||
{
|
||||
DBUG_ENTER("Statement::set_n_backup_statement");
|
||||
backup->set_statement(this);
|
||||
set_statement(stmt);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
|
||||
{
|
||||
DBUG_ENTER("Statement::restore_backup_statement");
|
||||
stmt->set_statement(this);
|
||||
set_statement(backup);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
@ -1569,6 +1572,7 @@ void Query_arena::set_n_backup_item_arena(Query_arena *set, Query_arena *backup)
|
||||
{
|
||||
DBUG_ENTER("Query_arena::set_n_backup_item_arena");
|
||||
DBUG_ASSERT(backup->is_backup_arena == FALSE);
|
||||
|
||||
backup->set_item_arena(this);
|
||||
set_item_arena(set);
|
||||
#ifndef DBUG_OFF
|
||||
|
@ -300,7 +300,9 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
|
||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||
DBUG_ENTER("mysql_prepare_delete");
|
||||
|
||||
if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables, FALSE) ||
|
||||
if (setup_tables(thd, &thd->lex->select_lex.context,
|
||||
table_list, conds, &select_lex->leaf_tables,
|
||||
FALSE) ||
|
||||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
||||
setup_ftfuncs(select_lex))
|
||||
DBUG_RETURN(TRUE);
|
||||
@ -356,7 +358,8 @@ bool mysql_multi_delete_prepare(THD *thd)
|
||||
|
||||
lex->query_tables also point on local list of DELETE SELECT_LEX
|
||||
*/
|
||||
if (setup_tables(thd, lex->query_tables, &lex->select_lex.where,
|
||||
if (setup_tables(thd, &thd->lex->select_lex.context,
|
||||
lex->query_tables, &lex->select_lex.where,
|
||||
&lex->select_lex.leaf_tables, FALSE))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
|
@ -114,6 +114,10 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
|
||||
bool is_union= first_select->next_select() &&
|
||||
first_select->next_select()->linkage == UNION_TYPE;
|
||||
|
||||
/* prevent name resolving out of derived table */
|
||||
for (SELECT_LEX *sl= first_select; sl; sl= sl->next_select())
|
||||
sl->context.outer_context= 0;
|
||||
|
||||
if (!(derived_result= new select_union(0)))
|
||||
DBUG_RETURN(1); // out of memory
|
||||
|
||||
|
@ -24,7 +24,7 @@ bool mysql_do(THD *thd, List<Item> &values)
|
||||
List_iterator<Item> li(values);
|
||||
Item *value;
|
||||
DBUG_ENTER("mysql_do");
|
||||
if (setup_fields(thd, 0, 0, values, 0, 0, 0))
|
||||
if (setup_fields(thd, 0, values, 0, 0, 0))
|
||||
DBUG_RETURN(TRUE);
|
||||
while ((value = li++))
|
||||
value->val_int();
|
||||
|
@ -353,7 +353,9 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||
LINT_INIT(key);
|
||||
LINT_INIT(key_len);
|
||||
|
||||
list.push_front(new Item_field(NULL,NULL,"*"));
|
||||
thd->lex->select_lex.context.resolve_in_table_list_only(tables);
|
||||
list.push_front(new Item_field(&thd->lex->select_lex.context,
|
||||
NULL, NULL, "*"));
|
||||
List_iterator<Item> it(list);
|
||||
it++;
|
||||
|
||||
@ -410,7 +412,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||
tables->table=table;
|
||||
|
||||
if (cond && ((!cond->fixed &&
|
||||
cond->fix_fields(thd, tables, &cond)) || cond->check_cols(1)))
|
||||
cond->fix_fields(thd, &cond)) || cond->check_cols(1)))
|
||||
goto err0;
|
||||
|
||||
if (keyname)
|
||||
@ -422,7 +424,8 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||
}
|
||||
}
|
||||
|
||||
if (insert_fields(thd, tables, tables->db, tables->alias, &it, 0))
|
||||
if (insert_fields(thd, &thd->lex->select_lex.context,
|
||||
tables->db, tables->alias, &it, 0))
|
||||
goto err0;
|
||||
|
||||
protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
|
||||
@ -505,7 +508,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||
{
|
||||
// 'item' can be changed by fix_fields() call
|
||||
if ((!item->fixed &&
|
||||
item->fix_fields(thd, tables, it_ke.ref())) ||
|
||||
item->fix_fields(thd, it_ke.ref())) ||
|
||||
(item= *it_ke.ref())->check_cols(1))
|
||||
goto err;
|
||||
if (item->used_tables() & ~RAND_TABLE_BIT)
|
||||
|
@ -81,11 +81,14 @@ enum enum_used_fields
|
||||
static bool init_fields(THD *thd, TABLE_LIST *tables,
|
||||
struct st_find_field *find_fields, uint count)
|
||||
{
|
||||
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||
DBUG_ENTER("init_fields");
|
||||
context->resolve_in_table_list_only(tables);
|
||||
for (; count-- ; find_fields++)
|
||||
{
|
||||
/* We have to use 'new' here as field will be re_linked on free */
|
||||
Item_field *field= new Item_field("mysql", find_fields->table_name,
|
||||
Item_field *field= new Item_field(context,
|
||||
"mysql", find_fields->table_name,
|
||||
find_fields->field_name);
|
||||
if (!(find_fields->field= find_field_in_tables(thd, field, tables,
|
||||
0, REPORT_ALL_ERRORS, 1)))
|
||||
@ -544,7 +547,6 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
|
||||
prepare_simple_select()
|
||||
thd Thread handler
|
||||
cond WHERE part of select
|
||||
tables list of tables, used in WHERE
|
||||
table goal table
|
||||
|
||||
error code of error (out)
|
||||
@ -553,11 +555,11 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
|
||||
# created SQL_SELECT
|
||||
*/
|
||||
|
||||
SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables,
|
||||
SQL_SELECT *prepare_simple_select(THD *thd, Item *cond,
|
||||
TABLE *table, int *error)
|
||||
{
|
||||
if (!cond->fixed)
|
||||
cond->fix_fields(thd, tables, &cond); // can never fail
|
||||
cond->fix_fields(thd, &cond); // can never fail
|
||||
|
||||
/* Assume that no indexes cover all required fields */
|
||||
table->used_keys.clear_all();
|
||||
@ -599,7 +601,7 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
|
||||
new Item_string("\\",1,&my_charset_latin1));
|
||||
if (thd->is_fatal_error)
|
||||
return 0; // OOM
|
||||
return prepare_simple_select(thd,cond,tables,table,error);
|
||||
return prepare_simple_select(thd, cond, table, error);
|
||||
}
|
||||
|
||||
|
||||
@ -651,7 +653,8 @@ bool mysqld_help(THD *thd, const char *mask)
|
||||
|
||||
tables do not contain VIEWs => we can pass 0 as conds
|
||||
*/
|
||||
setup_tables(thd, tables, 0, &leaves, FALSE);
|
||||
setup_tables(thd, &thd->lex->select_lex.context,
|
||||
tables, 0, &leaves, FALSE);
|
||||
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
|
||||
if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
|
||||
goto error;
|
||||
@ -719,13 +722,13 @@ bool mysqld_help(THD *thd, const char *mask)
|
||||
new Item_func_equal(new Item_field(cat_cat_id),
|
||||
new Item_int((int32)category_id));
|
||||
if (!(select= prepare_simple_select(thd, cond_topic_by_cat,
|
||||
tables,tables[0].table,&error)))
|
||||
tables[0].table, &error)))
|
||||
goto error;
|
||||
get_all_items_for_category(thd,tables[0].table,
|
||||
used_fields[help_topic_name].field,
|
||||
select,&topics_list);
|
||||
delete select;
|
||||
if (!(select= prepare_simple_select(thd,cond_cat_by_cat,tables,
|
||||
if (!(select= prepare_simple_select(thd, cond_cat_by_cat,
|
||||
tables[1].table, &error)))
|
||||
goto error;
|
||||
get_all_items_for_category(thd,tables[1].table,
|
||||
|
@ -31,7 +31,7 @@ static void end_delayed_insert(THD *thd);
|
||||
extern "C" pthread_handler_decl(handle_delayed_insert,arg);
|
||||
static void unlink_blobs(register TABLE *table);
|
||||
#endif
|
||||
static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id);
|
||||
static bool check_view_insertability(THD *thd, TABLE_LIST *view);
|
||||
|
||||
/* Define to force use of my_malloc() if the allocated memory block is big */
|
||||
|
||||
@ -106,7 +106,11 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
||||
}
|
||||
else
|
||||
{ // Part field list
|
||||
TABLE_LIST *save_next;
|
||||
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||
TABLE_LIST *save_next= table_list->next_local,
|
||||
*save_context= context->table_list;
|
||||
bool save_resolve_in_select_list=
|
||||
thd->lex->select_lex.context.resolve_in_select_list;
|
||||
int res;
|
||||
if (fields.elements != values.elements)
|
||||
{
|
||||
@ -115,12 +119,15 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
||||
}
|
||||
|
||||
thd->dupp_field=0;
|
||||
thd->lex->select_lex.no_wrap_view_item= 1;
|
||||
save_next= table_list->next_local; // fields only from first table
|
||||
thd->lex->select_lex.no_wrap_view_item= TRUE;
|
||||
/* fields only from first table */
|
||||
table_list->next_local= 0;
|
||||
res= setup_fields(thd, 0, table_list, fields, 1, 0, 0);
|
||||
context->resolve_in_table_list_only(table_list);
|
||||
res= setup_fields(thd, 0, fields, 1, 0, 0);
|
||||
table_list->next_local= save_next;
|
||||
thd->lex->select_lex.no_wrap_view_item= 0;
|
||||
thd->lex->select_lex.no_wrap_view_item= FALSE;
|
||||
context->table_list= save_context;
|
||||
context->resolve_in_select_list= save_resolve_in_select_list;
|
||||
if (res)
|
||||
return -1;
|
||||
if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE)
|
||||
@ -159,7 +166,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
||||
|
||||
if (check_key_in_view(thd, table_list) ||
|
||||
(table_list->view &&
|
||||
check_view_insertability(table_list, thd->query_id)))
|
||||
check_view_insertability(thd, table_list)))
|
||||
{
|
||||
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
|
||||
return -1;
|
||||
@ -209,7 +216,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
|
||||
Check the fields we are going to modify. This will set the query_id
|
||||
of all used fields to the threads query_id.
|
||||
*/
|
||||
if (setup_fields(thd, 0, insert_table_list, update_fields, 1, 0, 0))
|
||||
if (setup_fields(thd, 0, update_fields, 1, 0, 0))
|
||||
return -1;
|
||||
|
||||
if (table->timestamp_field)
|
||||
@ -247,6 +254,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
ulonglong id;
|
||||
COPY_INFO info;
|
||||
TABLE *table= 0;
|
||||
TABLE_LIST *next_local;
|
||||
List_iterator_fast<List_item> its(values_list);
|
||||
List_item *values;
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
@ -327,7 +335,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
/* mysql_prepare_insert set table_list->table if it was not set */
|
||||
table= table_list->table;
|
||||
|
||||
// is table which we are changing used somewhere in other parts of query
|
||||
next_local= table_list->next_local;
|
||||
table_list->next_local= 0;
|
||||
thd->lex->select_lex.context.resolve_in_table_list_only(table_list);
|
||||
value_count= values->elements;
|
||||
while ((values= its++))
|
||||
{
|
||||
@ -337,10 +347,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
|
||||
goto abort;
|
||||
}
|
||||
if (setup_fields(thd, 0, table_list, *values, 0, 0, 0))
|
||||
if (setup_fields(thd, 0, *values, 0, 0, 0))
|
||||
goto abort;
|
||||
}
|
||||
its.rewind ();
|
||||
table_list->next_local= next_local;
|
||||
/*
|
||||
Fill in the given fields and dump it to the table file
|
||||
*/
|
||||
@ -387,12 +398,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
MODE_STRICT_ALL_TABLES)));
|
||||
|
||||
if ((fields.elements || !value_count) &&
|
||||
check_that_all_fields_are_given_values(thd, table))
|
||||
check_that_all_fields_are_given_values(thd, table, table_list))
|
||||
{
|
||||
/* thd->net.report_error is now set, which will abort the next loop */
|
||||
error= 1;
|
||||
}
|
||||
|
||||
if (table_list->prepare_where(thd, 0, TRUE) ||
|
||||
table_list->prepare_check_option(thd))
|
||||
error= 1;
|
||||
|
||||
while ((values= its++))
|
||||
{
|
||||
if (fields.elements || !value_count)
|
||||
@ -596,6 +611,7 @@ abort:
|
||||
|
||||
SYNOPSIS
|
||||
check_view_insertability()
|
||||
thd - thread handler
|
||||
view - reference on VIEW
|
||||
|
||||
IMPLEMENTATION
|
||||
@ -612,7 +628,7 @@ abort:
|
||||
TRUE - can't be used for insert
|
||||
*/
|
||||
|
||||
static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id)
|
||||
static bool check_view_insertability(THD * thd, TABLE_LIST *view)
|
||||
{
|
||||
uint num= view->view->select_lex.item_list.elements;
|
||||
TABLE *table= view->table;
|
||||
@ -620,15 +636,25 @@ static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id)
|
||||
*trans_end= trans_start + num;
|
||||
Field_translator *trans;
|
||||
Field **field_ptr= table->field;
|
||||
query_id_t other_query_id= query_id - 1;
|
||||
uint used_fields_buff_size= (table->s->fields + 7) / 8;
|
||||
uchar *used_fields_buff= (uchar*)thd->alloc(used_fields_buff_size);
|
||||
MY_BITMAP used_fields;
|
||||
DBUG_ENTER("check_key_in_view");
|
||||
|
||||
if (!used_fields_buff)
|
||||
DBUG_RETURN(TRUE); // EOM
|
||||
|
||||
DBUG_ASSERT(view->table != 0 && view->field_translation != 0);
|
||||
|
||||
bitmap_init(&used_fields, used_fields_buff, used_fields_buff_size * 8, 0);
|
||||
bitmap_clear_all(&used_fields);
|
||||
|
||||
view->contain_auto_increment= 0;
|
||||
/* check simplicity and prepare unique test of view */
|
||||
for (trans= trans_start; trans != trans_end; trans++)
|
||||
{
|
||||
if (!trans->item->fixed && trans->item->fix_fields(thd, &trans->item))
|
||||
return TRUE;
|
||||
Item_field *field;
|
||||
/* simple SELECT list entry (field without expression) */
|
||||
if (!(field= trans->item->filed_for_view_update()))
|
||||
@ -636,7 +662,6 @@ static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id)
|
||||
if (field->field->unireg_check == Field::NEXT_NUMBER)
|
||||
view->contain_auto_increment= 1;
|
||||
/* prepare unique test */
|
||||
field->field->query_id= other_query_id;
|
||||
/*
|
||||
remove collation (or other transparent for update function) if we have
|
||||
it
|
||||
@ -648,29 +673,12 @@ static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id)
|
||||
{
|
||||
/* Thanks to test above, we know that all columns are of type Item_field */
|
||||
Item_field *field= (Item_field *)trans->item;
|
||||
if (field->field->query_id == query_id)
|
||||
/* check fields belong to table in which we are inserting */
|
||||
if (field->field->table == table &&
|
||||
bitmap_fast_test_and_set(&used_fields, field->field->field_index))
|
||||
DBUG_RETURN(TRUE);
|
||||
field->field->query_id= query_id;
|
||||
}
|
||||
|
||||
/* VIEW contain all fields without default value */
|
||||
for (; *field_ptr; field_ptr++)
|
||||
{
|
||||
Field *field= *field_ptr;
|
||||
/* field have not default value */
|
||||
if ((field->type() == FIELD_TYPE_BLOB) &&
|
||||
(table->timestamp_field != field ||
|
||||
field->unireg_check == Field::TIMESTAMP_UN_FIELD))
|
||||
{
|
||||
for (trans= trans_start; ; trans++)
|
||||
{
|
||||
if (trans == trans_end)
|
||||
DBUG_RETURN(TRUE); // Field was not part of view
|
||||
if (((Item_field *)trans->item)->field == *field_ptr)
|
||||
break; // ok
|
||||
}
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
@ -698,7 +706,8 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
|
||||
bool insert_into_view= (table_list->view != 0);
|
||||
DBUG_ENTER("mysql_prepare_insert_check_table");
|
||||
|
||||
if (setup_tables(thd, table_list, where, &thd->lex->select_lex.leaf_tables,
|
||||
if (setup_tables(thd, &thd->lex->select_lex.context,
|
||||
table_list, where, &thd->lex->select_lex.leaf_tables,
|
||||
select_insert))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
@ -711,7 +720,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
|
||||
table_list->view_db.str, table_list->view_name.str);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
DBUG_RETURN(insert_view_fields(&fields, table_list));
|
||||
DBUG_RETURN(insert_view_fields(thd, &fields, table_list));
|
||||
}
|
||||
|
||||
DBUG_RETURN(FALSE);
|
||||
@ -741,8 +750,10 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
|
||||
enum_duplicates duplic,
|
||||
COND **where, bool select_insert)
|
||||
{
|
||||
TABLE_LIST *save_table_list= thd->lex->select_lex.context.table_list;
|
||||
bool insert_into_view= (table_list->view != 0);
|
||||
/* TODO: use this condition for 'WITH CHECK OPTION' */
|
||||
bool save_resolve_in_select_list=
|
||||
thd->lex->select_lex.context.resolve_in_select_list;
|
||||
bool res;
|
||||
TABLE_LIST *next_local;
|
||||
DBUG_ENTER("mysql_prepare_insert");
|
||||
@ -750,6 +761,26 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
|
||||
(ulong)table_list, (ulong)table,
|
||||
(int)insert_into_view));
|
||||
|
||||
/*
|
||||
For subqueries in VALUES() we should not see the table in which we are
|
||||
inserting (for INSERT ... SELECT this is done by changing table_list,
|
||||
because INSERT ... SELECT share SELECT_LEX it with SELECT.
|
||||
*/
|
||||
if (!select_insert)
|
||||
{
|
||||
for (SELECT_LEX_UNIT *un= thd->lex->select_lex.first_inner_unit();
|
||||
un;
|
||||
un= un->next_unit())
|
||||
{
|
||||
for (SELECT_LEX *sl= un->first_select();
|
||||
sl;
|
||||
sl= sl->next_select())
|
||||
{
|
||||
sl->context.outer_context= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (duplic == DUP_UPDATE)
|
||||
{
|
||||
/* it should be allocated before Item::fix_fields() */
|
||||
@ -763,29 +794,37 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
|
||||
|
||||
next_local= table_list->next_local;
|
||||
table_list->next_local= 0;
|
||||
thd->lex->select_lex.context.resolve_in_table_list_only(table_list);
|
||||
if ((values && check_insert_fields(thd, table_list, fields, *values,
|
||||
!insert_into_view)) ||
|
||||
(values && setup_fields(thd, 0, table_list, *values, 0, 0, 0)) ||
|
||||
(values && setup_fields(thd, 0, *values, 0, 0, 0)) ||
|
||||
(duplic == DUP_UPDATE &&
|
||||
((thd->lex->select_lex.no_wrap_view_item= 1,
|
||||
((thd->lex->select_lex.no_wrap_view_item= TRUE,
|
||||
(res= check_update_fields(thd, table_list, update_fields)),
|
||||
thd->lex->select_lex.no_wrap_view_item= 0,
|
||||
thd->lex->select_lex.no_wrap_view_item= FALSE,
|
||||
res) ||
|
||||
setup_fields(thd, 0, table_list, update_values, 1, 0, 0))))
|
||||
setup_fields(thd, 0, update_values, 1, 0, 0))))
|
||||
DBUG_RETURN(TRUE);
|
||||
table_list->next_local= next_local;
|
||||
|
||||
thd->lex->select_lex.context.table_list= save_table_list;
|
||||
thd->lex->select_lex.context.resolve_in_select_list=
|
||||
save_resolve_in_select_list;
|
||||
if (!table)
|
||||
table= table_list->table;
|
||||
|
||||
if (!select_insert && unique_table(table_list, table_list->next_global))
|
||||
if (!select_insert)
|
||||
{
|
||||
Item *fake_conds= 0;
|
||||
if (unique_table(table_list, table_list->next_global))
|
||||
{
|
||||
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
thd->lex->select_lex.fix_prepare_information(thd, &fake_conds);
|
||||
thd->lex->select_lex.first_execution= 0;
|
||||
}
|
||||
if (duplic == DUP_UPDATE || duplic == DUP_REPLACE)
|
||||
table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
|
||||
thd->lex->select_lex.first_execution= 0;
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
@ -1038,7 +1077,8 @@ before_trg_err:
|
||||
Check that all fields with arn't null_fields are used
|
||||
******************************************************************************/
|
||||
|
||||
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry)
|
||||
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
|
||||
TABLE_LIST *table_list)
|
||||
{
|
||||
int err= 0;
|
||||
for (Field **field=entry->field ; *field ; field++)
|
||||
@ -1046,11 +1086,30 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry)
|
||||
if ((*field)->query_id != thd->query_id &&
|
||||
((*field)->flags & NO_DEFAULT_VALUE_FLAG) &&
|
||||
((*field)->real_type() != FIELD_TYPE_ENUM))
|
||||
{
|
||||
bool view= FALSE;
|
||||
if (table_list)
|
||||
{
|
||||
table_list= (table_list->belong_to_view ?
|
||||
table_list->belong_to_view :
|
||||
table_list);
|
||||
view= (table_list->view);
|
||||
}
|
||||
if (view)
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_NO_DEFAULT_FOR_VIEW_FIELD,
|
||||
ER(ER_NO_DEFAULT_FOR_VIEW_FIELD),
|
||||
table_list->view_db.str,
|
||||
table_list->view_name.str);
|
||||
}
|
||||
else
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_NO_DEFAULT_FOR_FIELD,
|
||||
ER(ER_NO_DEFAULT_FOR_FIELD),
|
||||
(*field)->field_name);
|
||||
}
|
||||
err= 1;
|
||||
}
|
||||
}
|
||||
@ -1938,7 +1997,6 @@ bool mysql_insert_select_prepare(THD *thd)
|
||||
SELECT_LEX do not belong to INSERT statement, so we can't add WHERE
|
||||
clause if table is VIEW
|
||||
*/
|
||||
lex->query_tables->no_where_clause= 1;
|
||||
if (mysql_prepare_insert(thd, lex->query_tables,
|
||||
lex->query_tables->table, lex->field_list, 0,
|
||||
lex->update_list, lex->value_list,
|
||||
@ -1988,8 +2046,8 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par,
|
||||
int
|
||||
select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
int res;
|
||||
LEX *lex= thd->lex;
|
||||
int res;
|
||||
SELECT_LEX *lex_current_select_save= lex->current_select;
|
||||
DBUG_ENTER("select_insert::prepare");
|
||||
|
||||
@ -2043,8 +2101,11 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
(thd->variables.sql_mode &
|
||||
(MODE_STRICT_TRANS_TABLES |
|
||||
MODE_STRICT_ALL_TABLES)));
|
||||
DBUG_RETURN(fields->elements &&
|
||||
check_that_all_fields_are_given_values(thd, table));
|
||||
res= ((fields->elements &&
|
||||
check_that_all_fields_are_given_values(thd, table, table_list)) ||
|
||||
table_list->prepare_where(thd, 0, TRUE) ||
|
||||
table_list->prepare_check_option(thd));
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
||||
@ -2290,7 +2351,8 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
(thd->variables.sql_mode &
|
||||
(MODE_STRICT_TRANS_TABLES |
|
||||
MODE_STRICT_ALL_TABLES)));
|
||||
DBUG_RETURN(check_that_all_fields_are_given_values(thd, table));
|
||||
DBUG_RETURN(check_that_all_fields_are_given_values(thd, table,
|
||||
table_list));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1104,7 +1104,8 @@ void st_select_lex::init_query()
|
||||
having= where= prep_where= 0;
|
||||
olap= UNSPECIFIED_OLAP_TYPE;
|
||||
having_fix_field= 0;
|
||||
resolve_mode= NOMATTER_MODE;
|
||||
context.select_lex= this;
|
||||
context.init();
|
||||
cond_count= with_wild= 0;
|
||||
conds_processed_with_permanent_arena= 0;
|
||||
ref_pointer_array= 0;
|
||||
@ -1703,8 +1704,7 @@ bool st_lex::can_not_use_merged()
|
||||
|
||||
bool st_lex::only_view_structure()
|
||||
{
|
||||
switch(sql_command)
|
||||
{
|
||||
switch (sql_command) {
|
||||
case SQLCOM_SHOW_CREATE:
|
||||
case SQLCOM_SHOW_TABLES:
|
||||
case SQLCOM_SHOW_FIELDS:
|
||||
@ -1744,6 +1744,31 @@ bool st_lex::need_correct_ident()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Get effective type of CHECK OPTION for given view
|
||||
|
||||
SYNOPSIS
|
||||
get_effective_with_check()
|
||||
view given view
|
||||
|
||||
NOTE
|
||||
It have not sense to set CHECK OPTION for SELECT satement or subqueries,
|
||||
so we do not.
|
||||
|
||||
RETURN
|
||||
VIEW_CHECK_NONE no need CHECK OPTION
|
||||
VIEW_CHECK_LOCAL CHECK OPTION LOCAL
|
||||
VIEW_CHECK_CASCADED CHECK OPTION CASCADED
|
||||
*/
|
||||
|
||||
uint8 st_lex::get_effective_with_check(st_table_list *view)
|
||||
{
|
||||
if (view->select_lex->master_unit() == &unit &&
|
||||
which_check_option_applicable())
|
||||
return (uint8)view->with_check;
|
||||
return VIEW_CHECK_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
initialize limit counters
|
||||
@ -1804,7 +1829,8 @@ TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local)
|
||||
*/
|
||||
if ((*link_to_local= test(select_lex.table_list.first)))
|
||||
{
|
||||
select_lex.table_list.first= (byte*) first->next_local;
|
||||
select_lex.table_list.first= (byte*) (select_lex.context.table_list=
|
||||
first->next_local);
|
||||
select_lex.table_list.elements--; //safety
|
||||
first->next_local= 0;
|
||||
/*
|
||||
@ -1909,7 +1935,8 @@ void st_lex::link_first_table_back(TABLE_LIST *first,
|
||||
if (link_to_local)
|
||||
{
|
||||
first->next_local= (TABLE_LIST*) select_lex.table_list.first;
|
||||
select_lex.table_list.first= (byte*) first;
|
||||
select_lex.table_list.first=
|
||||
(byte*) select_lex.context.table_list= first;
|
||||
select_lex.table_list.elements++; //safety
|
||||
}
|
||||
}
|
||||
@ -1930,7 +1957,21 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds)
|
||||
if (!thd->current_arena->is_conventional() && first_execution)
|
||||
{
|
||||
first_execution= 0;
|
||||
prep_where= where;
|
||||
if (*conds)
|
||||
{
|
||||
prep_where= *conds;
|
||||
*conds= where= prep_where->copy_andor_structure(thd);
|
||||
}
|
||||
for (TABLE_LIST *tbl= (TABLE_LIST *)table_list.first;
|
||||
tbl;
|
||||
tbl= tbl->next_local)
|
||||
{
|
||||
if (tbl->on_expr)
|
||||
{
|
||||
tbl->prep_on_expr= tbl->on_expr;
|
||||
tbl->on_expr= tbl->on_expr->copy_andor_structure(thd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1945,3 +1986,4 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds)
|
||||
st_select_lex_unit::change_result
|
||||
are in sql_union.cc
|
||||
*/
|
||||
|
||||
|
@ -470,6 +470,7 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT;
|
||||
class st_select_lex: public st_select_lex_node
|
||||
{
|
||||
public:
|
||||
Name_resolution_context context;
|
||||
char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
|
||||
Item *where, *having; /* WHERE & HAVING clauses */
|
||||
Item *prep_where; /* saved WHERE clause for prepared statement processing */
|
||||
@ -549,27 +550,6 @@ public:
|
||||
/* exclude this select from check of unique_table() */
|
||||
bool exclude_from_table_unique_test;
|
||||
|
||||
/*
|
||||
SELECT for SELECT command st_select_lex. Used to privent scaning
|
||||
item_list of non-SELECT st_select_lex (no sense find to finding
|
||||
reference in it (all should be in tables, it is dangerouse due
|
||||
to order of fix_fields calling for non-SELECTs commands (item list
|
||||
can be not fix_fieldsd)). This value will be assigned for
|
||||
primary select (sql_yac.yy) and for any subquery and
|
||||
UNION SELECT (sql_parse.cc mysql_new_select())
|
||||
|
||||
|
||||
INSERT for primary st_select_lex structure of simple INSERT/REPLACE
|
||||
(used for name resolution, see Item_fiels & Item_ref fix_fields,
|
||||
FALSE for INSERT/REPLACE ... SELECT, because it's
|
||||
st_select_lex->table_list will be preprocessed (first table removed)
|
||||
before passing to handle_select)
|
||||
|
||||
NOMATTER for other
|
||||
*/
|
||||
enum {NOMATTER_MODE, SELECT_MODE, INSERT_MODE} resolve_mode;
|
||||
|
||||
|
||||
void init_query();
|
||||
void init_select();
|
||||
st_select_lex_unit* master_unit();
|
||||
@ -903,7 +883,30 @@ typedef struct st_lex
|
||||
bool can_not_use_merged();
|
||||
bool only_view_structure();
|
||||
bool need_correct_ident();
|
||||
uint8 get_effective_with_check(st_table_list *view);
|
||||
/*
|
||||
Is this update command where 'WHITH CHECK OPTION' clause is important
|
||||
|
||||
SYNOPSIS
|
||||
st_lex::which_check_option_applicable()
|
||||
|
||||
RETURN
|
||||
TRUE have to take 'WHITH CHECK OPTION' clause into account
|
||||
FALSE 'WHITH CHECK OPTION' clause do not need
|
||||
*/
|
||||
inline bool which_check_option_applicable()
|
||||
{
|
||||
switch (sql_command) {
|
||||
case SQLCOM_UPDATE:
|
||||
case SQLCOM_UPDATE_MULTI:
|
||||
case SQLCOM_INSERT:
|
||||
case SQLCOM_INSERT_SELECT:
|
||||
case SQLCOM_LOAD:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
inline bool requires_prelocking()
|
||||
{
|
||||
return test(query_tables_own_last);
|
||||
|
@ -149,7 +149,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
}
|
||||
if (open_and_lock_tables(thd, table_list))
|
||||
DBUG_RETURN(TRUE);
|
||||
if (setup_tables(thd, table_list, &unused_conds,
|
||||
if (setup_tables(thd, &thd->lex->select_lex.context,
|
||||
table_list, &unused_conds,
|
||||
&thd->lex->select_lex.leaf_tables, FALSE))
|
||||
DBUG_RETURN(-1);
|
||||
if (!table_list->table || // do not suport join view
|
||||
@ -159,6 +160,11 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD");
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
if (table_list->prepare_where(thd, 0, TRUE) ||
|
||||
table_list->prepare_check_option(thd))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
/*
|
||||
Let us emit an error if we are loading data to table which is used
|
||||
in subselect in SET clause like we do it for INSERT.
|
||||
@ -186,16 +192,16 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
Let us also prepare SET clause, altough it is probably empty
|
||||
in this case.
|
||||
*/
|
||||
if (setup_fields(thd, 0, table_list, set_fields, 1, 0, 0) ||
|
||||
setup_fields(thd, 0, table_list, set_values, 1, 0, 0))
|
||||
if (setup_fields(thd, 0, set_fields, 1, 0, 0) ||
|
||||
setup_fields(thd, 0, set_values, 1, 0, 0))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
else
|
||||
{ // Part field list
|
||||
/* TODO: use this conds for 'WITH CHECK OPTIONS' */
|
||||
if (setup_fields(thd, 0, table_list, fields_vars, 1, 0, 0) ||
|
||||
setup_fields(thd, 0, table_list, set_fields, 1, 0, 0) ||
|
||||
check_that_all_fields_are_given_values(thd, table))
|
||||
if (setup_fields(thd, 0, fields_vars, 1, 0, 0) ||
|
||||
setup_fields(thd, 0, set_fields, 1, 0, 0) ||
|
||||
check_that_all_fields_are_given_values(thd, table, table_list))
|
||||
DBUG_RETURN(TRUE);
|
||||
/*
|
||||
Check whenever TIMESTAMP field with auto-set feature specified
|
||||
@ -209,7 +215,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
check_that_all_fields_are_given_values() and setting use_timestamp
|
||||
since it may update query_id for some fields.
|
||||
*/
|
||||
if (setup_fields(thd, 0, table_list, set_values, 1, 0, 0))
|
||||
if (setup_fields(thd, 0, set_values, 1, 0, 0))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,8 @@ static int make_new_olap_select(LEX *lex, SELECT_LEX *select_lex, List<Item> new
|
||||
{
|
||||
not_found= 0;
|
||||
((Item_field*)new_item)->db_name=iif->db_name;
|
||||
Item_field *new_one=new Item_field(iif->db_name, iif->table_name, iif->field_name);
|
||||
Item_field *new_one=new Item_field(&select_lex->context,
|
||||
iif->db_name, iif->table_name, iif->field_name);
|
||||
privlist.push_back(new_one);
|
||||
if (add_to_list(new_select->group_list,new_one,1))
|
||||
return 1;
|
||||
@ -152,12 +153,11 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
|
||||
List<Item> all_fields(select_lex->item_list);
|
||||
|
||||
|
||||
if (setup_tables(lex->thd, (TABLE_LIST *)select_lex->table_list.first
|
||||
if (setup_tables(lex->thd, &select_lex->context,
|
||||
(TABLE_LIST *)select_lex->table_list.first
|
||||
&select_lex->where, &select_lex->leaf_tables, FALSE) ||
|
||||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
|
||||
select_lex->item_list, 1, &all_fields,1) ||
|
||||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
|
||||
item_list_copy, 1, &all_fields, 1))
|
||||
setup_fields(lex->thd, 0, select_lex->item_list, 1, &all_fields,1) ||
|
||||
setup_fields(lex->thd, 0, item_list_copy, 1, &all_fields, 1))
|
||||
return -1;
|
||||
|
||||
if (select_lex->olap == CUBE_TYPE)
|
||||
|
@ -2289,6 +2289,10 @@ mysql_execute_command(THD *thd)
|
||||
lex->first_lists_tables_same();
|
||||
/* should be assigned after making first tables same */
|
||||
all_tables= lex->query_tables;
|
||||
/* set context for commands which do not use setup_tables */
|
||||
select_lex->
|
||||
context.resolve_in_table_list_only((TABLE_LIST*)select_lex->
|
||||
table_list.first);
|
||||
|
||||
/*
|
||||
Reset warning count for each query that uses tables
|
||||
@ -2572,7 +2576,7 @@ mysql_execute_command(THD *thd)
|
||||
goto error;
|
||||
/* PURGE MASTER LOGS BEFORE 'data' */
|
||||
it= (Item *)lex->value_list.head();
|
||||
if ((!it->fixed &&it->fix_fields(lex->thd, 0, &it)) ||
|
||||
if ((!it->fixed && it->fix_fields(lex->thd, &it)) ||
|
||||
it->check_cols(1))
|
||||
{
|
||||
my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
|
||||
@ -2881,9 +2885,7 @@ mysql_execute_command(THD *thd)
|
||||
CREATE from SELECT give its SELECT_LEX for SELECT,
|
||||
and item_list belong to SELECT
|
||||
*/
|
||||
select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
|
||||
res= handle_select(thd, lex, result, 0);
|
||||
select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
|
||||
delete result;
|
||||
}
|
||||
/* reset for PS */
|
||||
@ -3222,6 +3224,8 @@ end_with_restore_list:
|
||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||
if ((res= insert_precheck(thd, all_tables)))
|
||||
break;
|
||||
/* Skip first table, which is the table we are inserting in */
|
||||
select_lex->context.table_list= first_table->next_local;
|
||||
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
|
||||
lex->update_list, lex->value_list,
|
||||
lex->duplicates, lex->ignore);
|
||||
@ -3252,18 +3256,17 @@ end_with_restore_list:
|
||||
select_lex->table_list.first= (byte*)first_table->next_local;
|
||||
|
||||
res= mysql_insert_select_prepare(thd);
|
||||
lex->select_lex.context.table_list= first_table->next_local;
|
||||
if (!res && (result= new select_insert(first_table, first_table->table,
|
||||
&lex->field_list,
|
||||
&lex->update_list, &lex->value_list,
|
||||
&lex->update_list,
|
||||
&lex->value_list,
|
||||
lex->duplicates, lex->ignore)))
|
||||
{
|
||||
/*
|
||||
insert/replace from SELECT give its SELECT_LEX for SELECT,
|
||||
and item_list belong to SELECT
|
||||
*/
|
||||
select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
|
||||
/* Skip first table, which is the table we are inserting in */
|
||||
select_lex->context.table_list= first_table->next_local;
|
||||
|
||||
res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE);
|
||||
select_lex->resolve_mode= SELECT_LEX::INSERT_MODE;
|
||||
delete result;
|
||||
}
|
||||
/* revert changes for SP */
|
||||
@ -3863,7 +3866,7 @@ end_with_restore_list:
|
||||
{
|
||||
Item *it= (Item *)lex->value_list.head();
|
||||
|
||||
if ((!it->fixed && it->fix_fields(lex->thd, 0, &it)) || it->check_cols(1))
|
||||
if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
|
||||
{
|
||||
my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
|
||||
MYF(0));
|
||||
@ -5230,16 +5233,27 @@ mysql_new_select(LEX *lex, bool move_down)
|
||||
unit->link_prev= 0;
|
||||
unit->return_to= lex->current_select;
|
||||
select_lex->include_down(unit);
|
||||
/* TODO: assign resolve_mode for fake subquery after merging with new tree */
|
||||
/*
|
||||
By default we assume that it is usual subselect and we have outer name
|
||||
resolution context, if no we will assign it to 0 later
|
||||
*/
|
||||
select_lex->context.outer_context= &select_lex->outer_select()->context;
|
||||
}
|
||||
else
|
||||
{
|
||||
Name_resolution_context *outer_context;
|
||||
if (lex->current_select->order_list.first && !lex->current_select->braces)
|
||||
{
|
||||
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
select_lex->include_neighbour(lex->current_select);
|
||||
/*
|
||||
we are not sure that we have one level of SELECTs above, so we take
|
||||
outer_context address from first select of unit
|
||||
*/
|
||||
outer_context=
|
||||
select_lex->master_unit()->first_select()->context.outer_context;
|
||||
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
||||
SELECT_LEX *fake= unit->fake_select_lex;
|
||||
if (!fake)
|
||||
@ -5256,13 +5270,23 @@ mysql_new_select(LEX *lex, bool move_down)
|
||||
fake->make_empty_select();
|
||||
fake->linkage= GLOBAL_OPTIONS_TYPE;
|
||||
fake->select_limit= 0;
|
||||
|
||||
fake->context.outer_context= outer_context;
|
||||
/* allow item list resolving in fake select for ORDER BY */
|
||||
fake->context.resolve_in_select_list= TRUE;
|
||||
fake->context.select_lex= fake;
|
||||
}
|
||||
select_lex->context.outer_context= outer_context;
|
||||
}
|
||||
|
||||
select_lex->master_unit()->global_parameters= select_lex;
|
||||
select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
|
||||
lex->current_select= select_lex;
|
||||
select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
|
||||
/*
|
||||
in subquery is SELECT query and we allow resolution of names in SELECT
|
||||
list
|
||||
*/
|
||||
select_lex->context.resolve_in_select_list= TRUE;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -963,7 +963,7 @@ static bool mysql_test_insert(Prepared_statement *stmt,
|
||||
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
|
||||
goto error;
|
||||
}
|
||||
if (setup_fields(thd, 0, table_list, *values, 0, 0, 0))
|
||||
if (setup_fields(thd, 0, *values, 0, 0, 0))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@ -1039,9 +1039,9 @@ static int mysql_test_update(Prepared_statement *stmt,
|
||||
table_list->grant.want_privilege= want_privilege;
|
||||
table_list->table->grant.want_privilege= want_privilege;
|
||||
#endif
|
||||
thd->lex->select_lex.no_wrap_view_item= 1;
|
||||
res= setup_fields(thd, 0, table_list, select->item_list, 1, 0, 0);
|
||||
thd->lex->select_lex.no_wrap_view_item= 0;
|
||||
thd->lex->select_lex.no_wrap_view_item= TRUE;
|
||||
res= setup_fields(thd, 0, select->item_list, 1, 0, 0);
|
||||
thd->lex->select_lex.no_wrap_view_item= FALSE;
|
||||
if (res)
|
||||
goto error;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
@ -1050,7 +1050,7 @@ static int mysql_test_update(Prepared_statement *stmt,
|
||||
table_list->table->grant.want_privilege=
|
||||
(SELECT_ACL & ~table_list->table->grant.privilege);
|
||||
#endif
|
||||
if (setup_fields(thd, 0, table_list, stmt->lex->value_list, 0, 0, 0))
|
||||
if (setup_fields(thd, 0, stmt->lex->value_list, 0, 0, 0))
|
||||
goto error;
|
||||
/* TODO: here we should send types of placeholders to the client. */
|
||||
DBUG_RETURN(0);
|
||||
@ -1119,6 +1119,8 @@ static bool mysql_test_select(Prepared_statement *stmt,
|
||||
SELECT_LEX_UNIT *unit= &lex->unit;
|
||||
DBUG_ENTER("mysql_test_select");
|
||||
|
||||
lex->select_lex.context.resolve_in_select_list= TRUE;
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
|
||||
if (tables)
|
||||
@ -1207,7 +1209,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt,
|
||||
|
||||
if (open_and_lock_tables(thd, tables))
|
||||
DBUG_RETURN(TRUE);
|
||||
DBUG_RETURN(setup_fields(thd, 0, 0, *values, 0, 0, 0));
|
||||
DBUG_RETURN(setup_fields(thd, 0, *values, 0, 0, 0));
|
||||
}
|
||||
|
||||
|
||||
@ -1277,6 +1279,8 @@ static bool select_like_stmt_test(Prepared_statement *stmt,
|
||||
THD *thd= stmt->thd;
|
||||
LEX *lex= stmt->lex;
|
||||
|
||||
lex->select_lex.context.resolve_in_select_list= TRUE;
|
||||
|
||||
if (specific_prepare && (*specific_prepare)(thd))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
@ -1354,9 +1358,8 @@ static bool mysql_test_create_table(Prepared_statement *stmt)
|
||||
|
||||
if (select_lex->item_list.elements)
|
||||
{
|
||||
select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
|
||||
select_lex->context.resolve_in_select_list= TRUE;
|
||||
res= select_like_stmt_test_with_open_n_lock(stmt, tables, 0, 0);
|
||||
select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
|
||||
}
|
||||
|
||||
/* put tables back for PS rexecuting */
|
||||
@ -1446,16 +1449,21 @@ error:
|
||||
|
||||
static bool mysql_insert_select_prepare_tester(THD *thd)
|
||||
{
|
||||
TABLE_LIST *first;
|
||||
bool res;
|
||||
SELECT_LEX *first_select= &thd->lex->select_lex;
|
||||
/* Skip first table, which is the table we are inserting in */
|
||||
first_select->table_list.first= (byte*)((TABLE_LIST*)first_select->
|
||||
table_list.first)->next_local;
|
||||
first_select->table_list.first= (byte*)(first=
|
||||
((TABLE_LIST*)first_select->
|
||||
table_list.first)->next_local);
|
||||
res= mysql_insert_select_prepare(thd);
|
||||
/*
|
||||
insert/replace from SELECT give its SELECT_LEX for SELECT,
|
||||
and item_list belong to SELECT
|
||||
*/
|
||||
first_select->resolve_mode= SELECT_LEX::SELECT_MODE;
|
||||
return mysql_insert_select_prepare(thd);
|
||||
thd->lex->select_lex.context.resolve_in_select_list= TRUE;
|
||||
thd->lex->select_lex.context.table_list= first;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -1493,12 +1501,12 @@ static int mysql_test_insert_select(Prepared_statement *stmt,
|
||||
first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first;
|
||||
DBUG_ASSERT(first_local_table != 0);
|
||||
|
||||
res= select_like_stmt_test_with_open_n_lock(stmt, tables,
|
||||
res=
|
||||
select_like_stmt_test_with_open_n_lock(stmt, tables,
|
||||
&mysql_insert_select_prepare_tester,
|
||||
OPTION_SETUP_TABLES_DONE);
|
||||
/* revert changes made by mysql_insert_select_prepare_tester */
|
||||
lex->select_lex.table_list.first= (byte*) first_local_table;
|
||||
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -1538,6 +1546,10 @@ static bool check_prepared_statement(Prepared_statement *stmt,
|
||||
lex->first_lists_tables_same();
|
||||
tables= lex->query_tables;
|
||||
|
||||
/* set context for commands which do not use setup_tables */
|
||||
lex->select_lex.context.resolve_in_table_list_only(select_lex->
|
||||
get_table_list());
|
||||
|
||||
switch (sql_command) {
|
||||
case SQLCOM_REPLACE:
|
||||
case SQLCOM_INSERT:
|
||||
@ -1813,18 +1825,9 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
|
||||
void init_stmt_after_parse(THD *thd, LEX *lex)
|
||||
{
|
||||
SELECT_LEX *sl= lex->all_selects_list;
|
||||
/*
|
||||
Save WHERE clause pointers, because they may be changed during query
|
||||
optimisation.
|
||||
*/
|
||||
for (; sl; sl= sl->next_select_in_list())
|
||||
{
|
||||
sl->prep_where= sl->where;
|
||||
sl->uncacheable&= ~UNCACHEABLE_PREPARE;
|
||||
}
|
||||
|
||||
for (TABLE_LIST *table= lex->query_tables; table; table= table->next_global)
|
||||
table->prep_on_expr= table->on_expr;
|
||||
for (; sl; sl= sl->next_select_in_list())
|
||||
sl->uncacheable&= ~UNCACHEABLE_PREPARE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -182,7 +182,7 @@ static void reset_cache_read(JOIN_CACHE *cache);
|
||||
static void reset_cache_write(JOIN_CACHE *cache);
|
||||
static void read_cached_record(JOIN_TAB *tab);
|
||||
static bool cmp_buffer_with_ref(JOIN_TAB *tab);
|
||||
static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
||||
static bool setup_new_fields(THD *thd, List<Item> &fields,
|
||||
List<Item> &all_fields, ORDER *new_order);
|
||||
static ORDER *create_distinct_group(THD *thd, ORDER *order,
|
||||
List<Item> &fields,
|
||||
@ -283,6 +283,7 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
|
||||
save_allow_sum_func= thd->allow_sum_func;
|
||||
thd->allow_sum_func= 0;
|
||||
res= setup_conds(thd, tables, leaves, conds);
|
||||
|
||||
thd->allow_sum_func= save_allow_sum_func;
|
||||
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
|
||||
order);
|
||||
@ -339,11 +340,12 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
/* Check that all tables, fields, conds and order are ok */
|
||||
|
||||
if ((!(select_options & OPTION_SETUP_TABLES_DONE) &&
|
||||
setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables,
|
||||
setup_tables(thd, &select_lex->context,
|
||||
tables_list, &conds, &select_lex->leaf_tables,
|
||||
FALSE)) ||
|
||||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
|
||||
select_lex->setup_ref_array(thd, og_num) ||
|
||||
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
|
||||
setup_fields(thd, (*rref_pointer_array), fields_list, 1,
|
||||
&all_fields, 1) ||
|
||||
setup_without_group(thd, (*rref_pointer_array), tables_list,
|
||||
select_lex->leaf_tables, fields_list,
|
||||
@ -359,7 +361,7 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
thd->allow_sum_func=1;
|
||||
select_lex->having_fix_field= 1;
|
||||
bool having_fix_rc= (!having->fixed &&
|
||||
(having->fix_fields(thd, tables_list, &having) ||
|
||||
(having->fix_fields(thd, &having) ||
|
||||
having->check_cols(1)));
|
||||
select_lex->having_fix_field= 0;
|
||||
if (having_fix_rc || thd->net.report_error)
|
||||
@ -432,7 +434,7 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
goto err; /* purecov: inspected */
|
||||
if (procedure)
|
||||
{
|
||||
if (setup_new_fields(thd, tables_list, fields_list, all_fields,
|
||||
if (setup_new_fields(thd, fields_list, all_fields,
|
||||
procedure->param_fields))
|
||||
goto err; /* purecov: inspected */
|
||||
if (procedure->group)
|
||||
@ -566,7 +568,7 @@ JOIN::optimize()
|
||||
Item_cond_and can't be fixed after creation, so we do not check
|
||||
conds->fixed
|
||||
*/
|
||||
conds->fix_fields(thd, tables_list, &conds);
|
||||
conds->fix_fields(thd, &conds);
|
||||
conds->change_ref_to_fields(thd, tables_list);
|
||||
conds->top_level_item();
|
||||
having= 0;
|
||||
@ -1117,7 +1119,6 @@ int
|
||||
JOIN::reinit()
|
||||
{
|
||||
DBUG_ENTER("JOIN::reinit");
|
||||
|
||||
first_record= 0;
|
||||
|
||||
if (exec_tmp_table1)
|
||||
@ -1977,6 +1978,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
bool free_join= 1;
|
||||
DBUG_ENTER("mysql_select");
|
||||
|
||||
select_lex->context.resolve_in_select_list= TRUE;
|
||||
JOIN *join;
|
||||
if (select_lex->join != 0)
|
||||
{
|
||||
@ -7445,7 +7447,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
|
||||
conds->top_level_item();
|
||||
/* conds is always a new item as both cond and on_expr existed */
|
||||
DBUG_ASSERT(!conds->fixed);
|
||||
conds->fix_fields(join->thd, 0, &conds);
|
||||
conds->fix_fields(join->thd, &conds);
|
||||
}
|
||||
else
|
||||
conds= table->on_expr;
|
||||
@ -7666,7 +7668,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
cond->fixed, also it do not need tables so we use 0 as second
|
||||
argument.
|
||||
*/
|
||||
cond->fix_fields(thd, 0, &cond);
|
||||
cond->fix_fields(thd, &cond);
|
||||
}
|
||||
thd->insert_id(0); // Clear for next request
|
||||
}
|
||||
@ -7685,7 +7687,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
cond->fixed, also it do not need tables so we use 0 as second
|
||||
argument.
|
||||
*/
|
||||
cond->fix_fields(thd, 0, &cond);
|
||||
cond->fix_fields(thd, &cond);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8208,6 +8210,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
*blob_field++= (uint) (reg_field - table->field);
|
||||
blob_count++;
|
||||
}
|
||||
new_field->field_index= (uint) (reg_field - table->field);
|
||||
*(reg_field++)= new_field;
|
||||
if (new_field->real_type() == MYSQL_TYPE_STRING ||
|
||||
new_field->real_type() == MYSQL_TYPE_VARCHAR)
|
||||
@ -8273,6 +8276,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
new_field->flags|= GROUP_FLAG;
|
||||
}
|
||||
new_field->query_id= thd->query_id;
|
||||
new_field->field_index= (uint) (reg_field - table->field);
|
||||
*(reg_field++) =new_field;
|
||||
}
|
||||
if (!--hidden_field_count)
|
||||
@ -11181,8 +11185,7 @@ static bool fix_having(JOIN *join, Item **having)
|
||||
else // This should never happen
|
||||
if (!(table->select->cond= new Item_cond_and(table->select->cond,
|
||||
sort_table_cond)) ||
|
||||
table->select->cond->fix_fields(join->thd, join->tables_list,
|
||||
&table->select->cond))
|
||||
table->select->cond->fix_fields(join->thd, &table->select->cond))
|
||||
return 1;
|
||||
table->select_cond=table->select->cond;
|
||||
table->select_cond->top_level_item();
|
||||
@ -11873,8 +11876,8 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
original field name, we should additionaly check if we have conflict
|
||||
for this name (in case if we would perform lookup in all tables).
|
||||
*/
|
||||
if (unaliased && !order_item->fixed && order_item->fix_fields(thd, tables,
|
||||
order->item))
|
||||
if (unaliased && !order_item->fixed &&
|
||||
order_item->fix_fields(thd, order->item))
|
||||
return TRUE;
|
||||
|
||||
/* Lookup the current GROUP field in the FROM clause. */
|
||||
@ -11941,7 +11944,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
arguments for which fix_fields already was called.
|
||||
*/
|
||||
if (!order_item->fixed &&
|
||||
(order_item->fix_fields(thd, tables, order->item) ||
|
||||
(order_item->fix_fields(thd, order->item) ||
|
||||
(order_item= *order->item)->check_cols(1) ||
|
||||
thd->is_fatal_error))
|
||||
return TRUE; /* Wrong field. */
|
||||
@ -12053,7 +12056,7 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
*/
|
||||
|
||||
static bool
|
||||
setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
||||
setup_new_fields(THD *thd, List<Item> &fields,
|
||||
List<Item> &all_fields, ORDER *new_field)
|
||||
{
|
||||
Item **item;
|
||||
@ -12070,7 +12073,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
||||
else
|
||||
{
|
||||
thd->where="procedure list";
|
||||
if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
|
||||
if ((*new_field->item)->fix_fields(thd, new_field->item))
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
all_fields.push_front(*new_field->item);
|
||||
new_field->item=all_fields.head_ref();
|
||||
@ -12868,7 +12871,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (!cond->fixed)
|
||||
cond->fix_fields(thd,(TABLE_LIST *) 0, (Item**)&cond);
|
||||
cond->fix_fields(thd, (Item**)&cond);
|
||||
if (join_tab->select)
|
||||
{
|
||||
error=(int) cond->add(join_tab->select->cond);
|
||||
@ -12940,6 +12943,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
|
||||
{
|
||||
if (expr->arg_count)
|
||||
{
|
||||
Name_resolution_context *context= &thd->lex->current_select->context;
|
||||
Item **arg,**arg_end;
|
||||
for (arg= expr->arguments(),
|
||||
arg_end= expr->arguments()+expr->arg_count;
|
||||
@ -12954,7 +12958,8 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
|
||||
if (item->eq(*group_tmp->item,0))
|
||||
{
|
||||
Item *new_item;
|
||||
if(!(new_item= new Item_ref(group_tmp->item, 0, item->name)))
|
||||
if(!(new_item= new Item_ref(context, group_tmp->item, 0,
|
||||
item->name)))
|
||||
return 1; // fatal_error is set
|
||||
thd->change_item_tree(arg, new_item);
|
||||
*changed= TRUE;
|
||||
|
@ -3240,11 +3240,13 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
|
||||
int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
||||
{
|
||||
ST_FIELD_INFO *field_info= schema_table->fields_info;
|
||||
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||
for ( ; field_info->field_name; field_info++)
|
||||
{
|
||||
if (field_info->old_name)
|
||||
{
|
||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
||||
Item_field *field= new Item_field(context,
|
||||
NullS, NullS, field_info->field_name);
|
||||
if (field)
|
||||
{
|
||||
field->set_name(field_info->old_name,
|
||||
@ -3264,12 +3266,14 @@ int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
||||
char tmp[128];
|
||||
LEX *lex= thd->lex;
|
||||
SELECT_LEX *sel= lex->current_select;
|
||||
Name_resolution_context *context= &sel->context;
|
||||
|
||||
if (!sel->item_list.elements)
|
||||
{
|
||||
ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
|
||||
String buffer(tmp,sizeof(tmp), system_charset_info);
|
||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
||||
Item_field *field= new Item_field(context,
|
||||
NullS, NullS, field_info->field_name);
|
||||
if (!field || add_item_to_list(thd, field))
|
||||
return 1;
|
||||
buffer.length(0);
|
||||
@ -3291,6 +3295,7 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
||||
char tmp[128];
|
||||
String buffer(tmp,sizeof(tmp), thd->charset());
|
||||
LEX *lex= thd->lex;
|
||||
Name_resolution_context *context= &lex->select_lex.context;
|
||||
|
||||
ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
|
||||
buffer.length(0);
|
||||
@ -3302,7 +3307,8 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
||||
buffer.append(lex->wild->ptr());
|
||||
buffer.append(")");
|
||||
}
|
||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
||||
Item_field *field= new Item_field(context,
|
||||
NullS, NullS, field_info->field_name);
|
||||
if (add_item_to_list(thd, field))
|
||||
return 1;
|
||||
field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
|
||||
@ -3310,7 +3316,7 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
||||
{
|
||||
field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
|
||||
field_info= &schema_table->fields_info[3];
|
||||
field= new Item_field(NullS, NullS, field_info->field_name);
|
||||
field= new Item_field(context, NullS, NullS, field_info->field_name);
|
||||
if (add_item_to_list(thd, field))
|
||||
return 1;
|
||||
field->set_name(field_info->old_name, strlen(field_info->old_name),
|
||||
@ -3325,6 +3331,8 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
||||
int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1};
|
||||
int *field_num= fields_arr;
|
||||
ST_FIELD_INFO *field_info;
|
||||
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||
|
||||
for (; *field_num >= 0; field_num++)
|
||||
{
|
||||
field_info= &schema_table->fields_info[*field_num];
|
||||
@ -3332,7 +3340,8 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
||||
*field_num == 17 ||
|
||||
*field_num == 18))
|
||||
continue;
|
||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
||||
Item_field *field= new Item_field(context,
|
||||
NullS, NullS, field_info->field_name);
|
||||
if (field)
|
||||
{
|
||||
field->set_name(field_info->old_name,
|
||||
@ -3351,10 +3360,13 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
||||
int fields_arr[]= {0, 2, 1, 3, -1};
|
||||
int *field_num= fields_arr;
|
||||
ST_FIELD_INFO *field_info;
|
||||
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||
|
||||
for (; *field_num >= 0; field_num++)
|
||||
{
|
||||
field_info= &schema_table->fields_info[*field_num];
|
||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
||||
Item_field *field= new Item_field(context,
|
||||
NullS, NullS, field_info->field_name);
|
||||
if (field)
|
||||
{
|
||||
field->set_name(field_info->old_name,
|
||||
@ -3373,10 +3385,13 @@ int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
||||
int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, -1};
|
||||
int *field_num= fields_arr;
|
||||
ST_FIELD_INFO *field_info;
|
||||
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||
|
||||
for (; *field_num >= 0; field_num++)
|
||||
{
|
||||
field_info= &schema_table->fields_info[*field_num];
|
||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
||||
Item_field *field= new Item_field(context,
|
||||
NullS, NullS, field_info->field_name);
|
||||
if (field)
|
||||
{
|
||||
field->set_name(field_info->old_name,
|
||||
@ -3442,12 +3457,11 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
|
||||
|
||||
if (table_list->field_translation)
|
||||
{
|
||||
Field_translator *end= table_list->field_translation +
|
||||
sel->item_list.elements;
|
||||
Field_translator *end= table_list->field_translation_end;
|
||||
for (transl= table_list->field_translation; transl < end; transl++)
|
||||
{
|
||||
if (!transl->item->fixed &&
|
||||
transl->item->fix_fields(thd, table_list, &transl->item))
|
||||
transl->item->fix_fields(thd, &transl->item))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
@ -3464,11 +3478,12 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
|
||||
{
|
||||
char *name= item->name;
|
||||
transl[i].item= item;
|
||||
if (!item->fixed && item->fix_fields(thd, table_list, &transl[i].item))
|
||||
if (!item->fixed && item->fix_fields(thd, &transl[i].item))
|
||||
DBUG_RETURN(1);
|
||||
transl[i++].name= name;
|
||||
}
|
||||
table_list->field_translation= transl;
|
||||
table_list->field_translation_end= transl + sel->item_list.elements;
|
||||
}
|
||||
|
||||
DBUG_RETURN(0);
|
||||
|
@ -201,7 +201,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
|
||||
{
|
||||
trg_field->setup_field(thd, table);
|
||||
if (!trg_field->fixed &&
|
||||
trg_field->fix_fields(thd, (TABLE_LIST *)0, (Item **)0))
|
||||
trg_field->fix_fields(thd, (Item **)0))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ class udf_handler :public Sql_alloc
|
||||
Item_result result_type () const
|
||||
{ return u_d ? u_d->returns : STRING_RESULT;}
|
||||
bool get_arguments();
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist,Item_result_field *item,
|
||||
bool fix_fields(THD *thd, Item_result_field *item,
|
||||
uint arg_count, Item **args);
|
||||
void cleanup();
|
||||
double val(my_bool *null_value)
|
||||
|
@ -124,6 +124,13 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd)
|
||||
fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
|
||||
(byte **)
|
||||
&result_table_list.next_local);
|
||||
for (ORDER *order= (ORDER *)global_parameters->order_list.first;
|
||||
order;
|
||||
order=order->next)
|
||||
{
|
||||
(*order->item)->walk(&Item::change_context_processor,
|
||||
(byte *) &fake_select_lex->context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -187,6 +194,8 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
||||
else
|
||||
tmp_result= sel_result;
|
||||
|
||||
sl->context.resolve_in_select_list= TRUE;
|
||||
|
||||
for (;sl; sl= sl->next_select())
|
||||
{
|
||||
bool can_skip_order_by;
|
||||
|
@ -67,6 +67,8 @@ static bool check_fields(THD *thd, List<Item> &items)
|
||||
List_iterator<Item> it(items);
|
||||
Item *item;
|
||||
Item_field *field;
|
||||
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||
|
||||
while ((item= it++))
|
||||
{
|
||||
if (!(field= item->filed_for_view_update()))
|
||||
@ -185,14 +187,8 @@ int mysql_update(THD *thd,
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
|
||||
#endif
|
||||
{
|
||||
bool res;
|
||||
select_lex->no_wrap_view_item= 1;
|
||||
res= setup_fields(thd, 0, table_list, fields, 1, 0, 0);
|
||||
select_lex->no_wrap_view_item= 0;
|
||||
if (res)
|
||||
if (setup_fields_with_no_wrap(thd, 0, fields, 1, 0, 0))
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
}
|
||||
if (table_list->view && check_fields(thd, fields))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
@ -216,7 +212,7 @@ int mysql_update(THD *thd,
|
||||
table_list->grant.want_privilege= table->grant.want_privilege=
|
||||
(SELECT_ACL & ~table->grant.privilege);
|
||||
#endif
|
||||
if (setup_fields(thd, 0, table_list, values, 1, 0, 0))
|
||||
if (setup_fields(thd, 0, values, 1, 0, 0))
|
||||
{
|
||||
free_underlaid_joins(thd, select_lex);
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
@ -557,7 +553,9 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||
tables.table= table;
|
||||
tables.alias= table_list->alias;
|
||||
|
||||
if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables, FALSE) ||
|
||||
if (setup_tables(thd, &select_lex->context,
|
||||
table_list, conds, &select_lex->leaf_tables,
|
||||
FALSE) ||
|
||||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
||||
select_lex->setup_ref_array(thd, order_num) ||
|
||||
setup_order(thd, select_lex->ref_pointer_array,
|
||||
@ -617,7 +615,6 @@ bool mysql_multi_update_prepare(THD *thd)
|
||||
TABLE_LIST *tl, *leaves;
|
||||
List<Item> *fields= &lex->select_lex.item_list;
|
||||
table_map tables_for_update;
|
||||
int res;
|
||||
bool update_view= 0;
|
||||
/*
|
||||
if this multi-update was converted from usual update, here is table
|
||||
@ -642,15 +639,12 @@ bool mysql_multi_update_prepare(THD *thd)
|
||||
call in setup_tables()).
|
||||
*/
|
||||
|
||||
if (setup_tables(thd, table_list, &lex->select_lex.where,
|
||||
if (setup_tables(thd, &lex->select_lex.context,
|
||||
table_list, &lex->select_lex.where,
|
||||
&lex->select_lex.leaf_tables, FALSE))
|
||||
DBUG_RETURN(TRUE);
|
||||
leaves= lex->select_lex.leaf_tables;
|
||||
|
||||
if ((lex->select_lex.no_wrap_view_item= 1,
|
||||
res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0),
|
||||
lex->select_lex.no_wrap_view_item= 0,
|
||||
res))
|
||||
if (setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
for (tl= table_list; tl ; tl= tl->next_local)
|
||||
@ -672,6 +666,7 @@ bool mysql_multi_update_prepare(THD *thd)
|
||||
/*
|
||||
Setup timestamp handling and locking mode
|
||||
*/
|
||||
leaves= lex->select_lex.leaf_tables;
|
||||
for (tl= leaves; tl; tl= tl->next_leaf)
|
||||
{
|
||||
TABLE *table= tl->table;
|
||||
@ -762,12 +757,10 @@ bool mysql_multi_update_prepare(THD *thd)
|
||||
for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global)
|
||||
tbl->cleanup_items();
|
||||
|
||||
if (setup_tables(thd, table_list, &lex->select_lex.where,
|
||||
if (setup_tables(thd, &lex->select_lex.context,
|
||||
table_list, &lex->select_lex.where,
|
||||
&lex->select_lex.leaf_tables, FALSE) ||
|
||||
(lex->select_lex.no_wrap_view_item= 1,
|
||||
res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0),
|
||||
lex->select_lex.no_wrap_view_item= 0,
|
||||
res))
|
||||
setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
@ -897,7 +890,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
|
||||
reference tables
|
||||
*/
|
||||
|
||||
if (setup_fields(thd, 0, all_tables, *values, 1, 0, 0))
|
||||
if (setup_fields(thd, 0, *values, 1, 0, 0))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/*
|
||||
|
@ -828,10 +828,23 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
||||
table->effective_algorithm= VIEW_ALGORITHM_MERGE;
|
||||
DBUG_PRINT("info", ("algorithm: MERGE"));
|
||||
table->updatable= (table->updatable_view != 0);
|
||||
table->effective_with_check= (uint8)table->with_check;
|
||||
|
||||
table->ancestor= view_tables;
|
||||
table->effective_with_check=
|
||||
old_lex->get_effective_with_check(table);
|
||||
|
||||
/* prepare view context */
|
||||
lex->select_lex.context.resolve_in_table_list_only(table->ancestor=
|
||||
view_tables);
|
||||
lex->select_lex.context.outer_context= 0;
|
||||
lex->select_lex.context.select_lex= table->select_lex;
|
||||
/* do not check privileges & hide errors for view underlyings */
|
||||
for (SELECT_LEX *sl= lex->all_selects_list;
|
||||
sl;
|
||||
sl= sl->next_select_in_list())
|
||||
{
|
||||
sl->context.check_privileges= FALSE;
|
||||
sl->context.error_processor= &view_error_processor;
|
||||
sl->context.error_processor_data= (void *)table;
|
||||
}
|
||||
/*
|
||||
Tables of the main select of the view should be marked as belonging
|
||||
to the same select as original view (again we can use LEX::select_lex
|
||||
@ -866,7 +879,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
||||
table->where= view_select->where;
|
||||
/*
|
||||
Add subqueries units to SELECT into which we merging current view.
|
||||
|
||||
unit(->next)* chain starts with subqueries that are used by this
|
||||
view and continues with subqueries that are used by other views.
|
||||
We must not add any subquery twice (otherwise we'll form a loop),
|
||||
@ -1058,9 +1070,9 @@ frm_type_enum mysql_frm_type(char *path)
|
||||
bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
||||
{
|
||||
TABLE *table;
|
||||
Field_translator *trans;
|
||||
Field_translator *trans, *end_of_trans;
|
||||
KEY *key_info, *key_info_end;
|
||||
uint i, elements_in_view;
|
||||
uint i;
|
||||
DBUG_ENTER("check_key_in_view");
|
||||
|
||||
/*
|
||||
@ -1077,9 +1089,24 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
||||
trans= view->field_translation;
|
||||
key_info_end= (key_info= table->key_info)+ table->s->keys;
|
||||
|
||||
elements_in_view= view->view->select_lex.item_list.elements;
|
||||
end_of_trans= view->field_translation_end;
|
||||
DBUG_ASSERT(table != 0 && view->field_translation != 0);
|
||||
|
||||
{
|
||||
/*
|
||||
We should be sure that all fields are ready to get keys from them, but
|
||||
this operation should not have influence on Field::query_id, to avoid
|
||||
marking as used fields which are not used
|
||||
*/
|
||||
bool save_set_query_id= thd->set_query_id;
|
||||
thd->set_query_id= 0;
|
||||
for (Field_translator *fld= trans; fld < end_of_trans; fld++)
|
||||
{
|
||||
if (!fld->item->fixed && fld->item->fix_fields(thd, &fld->item))
|
||||
return TRUE;
|
||||
}
|
||||
thd->set_query_id= save_set_query_id;
|
||||
}
|
||||
/* Loop over all keys to see if a unique-not-null key is used */
|
||||
for (;key_info != key_info_end ; key_info++)
|
||||
{
|
||||
@ -1091,15 +1118,15 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
||||
/* check that all key parts are used */
|
||||
for (;;)
|
||||
{
|
||||
uint k;
|
||||
for (k= 0; k < elements_in_view; k++)
|
||||
Field_translator *k;
|
||||
for (k= trans; k < end_of_trans; k++)
|
||||
{
|
||||
Item_field *field;
|
||||
if ((field= trans[k].item->filed_for_view_update()) &&
|
||||
if ((field= k->item->filed_for_view_update()) &&
|
||||
field->field == key_part->field)
|
||||
break;
|
||||
}
|
||||
if (k == elements_in_view)
|
||||
if (k == end_of_trans)
|
||||
break; // Key is not possible
|
||||
if (++key_part == key_part_end)
|
||||
DBUG_RETURN(FALSE); // Found usable key
|
||||
@ -1111,19 +1138,20 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
||||
/* check all fields presence */
|
||||
{
|
||||
Field **field_ptr;
|
||||
Field_translator *fld;
|
||||
for (field_ptr= table->field; *field_ptr; field_ptr++)
|
||||
{
|
||||
for (i= 0; i < elements_in_view; i++)
|
||||
for (fld= trans; fld < end_of_trans; fld++)
|
||||
{
|
||||
Item_field *field;
|
||||
if ((field= trans[i].item->filed_for_view_update()) &&
|
||||
if ((field= fld->item->filed_for_view_update()) &&
|
||||
field->field == *field_ptr)
|
||||
break;
|
||||
}
|
||||
if (i == elements_in_view) // If field didn't exists
|
||||
if (fld == end_of_trans) // If field didn't exists
|
||||
{
|
||||
/*
|
||||
Keys or all fields of underlying tables are not foud => we have
|
||||
Keys or all fields of underlying tables are not found => we have
|
||||
to check variable updatable_views_with_limit to decide should we
|
||||
issue an error or just a warning
|
||||
*/
|
||||
@ -1148,6 +1176,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
||||
|
||||
SYNOPSIS
|
||||
insert_view_fields()
|
||||
thd thread handler
|
||||
list list for insertion
|
||||
view view for processing
|
||||
|
||||
@ -1156,19 +1185,22 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
||||
TRUE error (is not sent to cliet)
|
||||
*/
|
||||
|
||||
bool insert_view_fields(List<Item> *list, TABLE_LIST *view)
|
||||
bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view)
|
||||
{
|
||||
uint elements_in_view= view->view->select_lex.item_list.elements;
|
||||
Field_translator *trans_end;
|
||||
Field_translator *trans;
|
||||
DBUG_ENTER("insert_view_fields");
|
||||
|
||||
if (!(trans= view->field_translation))
|
||||
DBUG_RETURN(FALSE);
|
||||
trans_end= view->field_translation_end;
|
||||
|
||||
for (uint i= 0; i < elements_in_view; i++)
|
||||
for (Field_translator *entry= trans; entry < trans_end; entry++)
|
||||
{
|
||||
Item_field *fld;
|
||||
if ((fld= trans[i].item->filed_for_view_update()))
|
||||
if (!entry->item->fixed && entry->item->fix_fields(thd, &entry->item))
|
||||
DBUG_RETURN(TRUE);
|
||||
if ((fld= entry->item->filed_for_view_update()))
|
||||
list->push_back(fld);
|
||||
else
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode);
|
||||
|
||||
bool check_key_in_view(THD *thd, TABLE_LIST * view);
|
||||
|
||||
bool insert_view_fields(List<Item> *list, TABLE_LIST *view);
|
||||
bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view);
|
||||
|
||||
frm_type_enum mysql_frm_type(char *path);
|
||||
|
||||
|
@ -1259,7 +1259,6 @@ create:
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
lex->sql_command= SQLCOM_CREATE_VIEW;
|
||||
lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
|
||||
/* first table in list is target VIEW name */
|
||||
if (!lex->select_lex.add_table_to_list(thd, $5, NULL, 0))
|
||||
YYABORT;
|
||||
@ -3383,7 +3382,6 @@ alter:
|
||||
LEX *lex= thd->lex;
|
||||
lex->sql_command= SQLCOM_CREATE_VIEW;
|
||||
lex->create_view_mode= VIEW_ALTER;
|
||||
lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
|
||||
/* first table in list is target VIEW name */
|
||||
lex->select_lex.add_table_to_list(thd, $4, NULL, 0);
|
||||
}
|
||||
@ -3941,7 +3939,6 @@ select:
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
lex->sql_command= SQLCOM_SELECT;
|
||||
lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
|
||||
}
|
||||
;
|
||||
|
||||
@ -4095,7 +4092,10 @@ select_item_list:
|
||||
| '*'
|
||||
{
|
||||
THD *thd= YYTHD;
|
||||
if (add_item_to_list(thd, new Item_field(NULL, NULL, "*")))
|
||||
if (add_item_to_list(thd,
|
||||
new Item_field(&thd->lex->current_select->
|
||||
context,
|
||||
NULL, NULL, "*")))
|
||||
YYABORT;
|
||||
(thd->lex->current_select->with_wild)++;
|
||||
};
|
||||
@ -4393,10 +4393,10 @@ simple_expr:
|
||||
my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str);
|
||||
YYABORT;
|
||||
}
|
||||
$$= new Item_default_value($3);
|
||||
$$= new Item_default_value(&Select->context, $3);
|
||||
}
|
||||
| VALUES '(' simple_ident ')'
|
||||
{ $$= new Item_insert_value($3); }
|
||||
{ $$= new Item_insert_value(&Select->context, $3); }
|
||||
| FUNC_ARG0 '(' ')'
|
||||
{
|
||||
if (!$1.symbol->create_func)
|
||||
@ -4687,15 +4687,16 @@ simple_expr:
|
||||
name->init_qname(YYTHD);
|
||||
sp_add_to_hash(&lex->spfuns, name);
|
||||
if ($5)
|
||||
$$= new Item_func_sp(name, *$5);
|
||||
$$= new Item_func_sp(&lex->current_select->context, name, *$5);
|
||||
else
|
||||
$$= new Item_func_sp(name);
|
||||
$$= new Item_func_sp(&lex->current_select->context, name);
|
||||
lex->safe_to_cache_query=0;
|
||||
}
|
||||
| IDENT_sys '(' udf_expr_list ')'
|
||||
{
|
||||
#ifdef HAVE_DLOPEN
|
||||
udf_func *udf;
|
||||
SELECT_LEX *sel= Select;
|
||||
|
||||
if (using_udf_functions && (udf=find_udf($1.str, $1.length)))
|
||||
{
|
||||
@ -4776,9 +4777,9 @@ simple_expr:
|
||||
|
||||
sp_add_to_hash(&lex->spfuns, name);
|
||||
if ($3)
|
||||
$$= new Item_func_sp(name, *$3);
|
||||
$$= new Item_func_sp(&lex->current_select->context, name, *$3);
|
||||
else
|
||||
$$= new Item_func_sp(name);
|
||||
$$= new Item_func_sp(&lex->current_select->context, name);
|
||||
lex->safe_to_cache_query=0;
|
||||
}
|
||||
}
|
||||
@ -4980,8 +4981,10 @@ sum_expr:
|
||||
opt_gconcat_separator
|
||||
')'
|
||||
{
|
||||
Select->in_sum_expr--;
|
||||
$$=new Item_func_group_concat($3,$5,Select->gorder_list,$7);
|
||||
SELECT_LEX *sel= Select;
|
||||
sel->in_sum_expr--;
|
||||
$$=new Item_func_group_concat(&sel->context, $3, $5,
|
||||
sel->gorder_list, $7);
|
||||
$5->empty();
|
||||
};
|
||||
|
||||
@ -5400,16 +5403,30 @@ using_list:
|
||||
ident
|
||||
{
|
||||
SELECT_LEX *sel= Select;
|
||||
if (!($$= new Item_func_eq(new Item_field(sel->db1, sel->table1,
|
||||
if (!($$= new Item_func_eq(new Item_field(&sel->context,
|
||||
sel->db1, sel->table1,
|
||||
$1.str),
|
||||
new Item_field(sel->db2, sel->table2,
|
||||
new Item_field(&sel->context,
|
||||
sel->db2, sel->table2,
|
||||
$1.str))))
|
||||
YYABORT;
|
||||
}
|
||||
| using_list ',' ident
|
||||
{
|
||||
SELECT_LEX *sel= Select;
|
||||
if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1)))
|
||||
if (!($$=
|
||||
new Item_cond_and(new
|
||||
Item_func_eq(new
|
||||
Item_field(&sel->context,
|
||||
sel->db1,
|
||||
sel->table1,
|
||||
$3.str),
|
||||
new
|
||||
Item_field(&sel->context,
|
||||
sel->db2,
|
||||
sel->table2,
|
||||
$3.str)),
|
||||
$1)))
|
||||
YYABORT;
|
||||
};
|
||||
|
||||
@ -5675,7 +5692,10 @@ procedure_clause:
|
||||
lex->proc_list.elements=0;
|
||||
lex->proc_list.first=0;
|
||||
lex->proc_list.next= (byte**) &lex->proc_list.first;
|
||||
if (add_proc_to_list(lex->thd, new Item_field(NULL,NULL,$2.str)))
|
||||
if (add_proc_to_list(lex->thd, new Item_field(&lex->
|
||||
current_select->
|
||||
context,
|
||||
NULL,NULL,$2.str)))
|
||||
YYABORT;
|
||||
Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||
}
|
||||
@ -5922,7 +5942,6 @@ insert:
|
||||
mysql_init_select(lex);
|
||||
/* for subselects */
|
||||
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
|
||||
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
|
||||
} insert_lock_option
|
||||
opt_ignore insert2
|
||||
{
|
||||
@ -5940,7 +5959,6 @@ replace:
|
||||
lex->sql_command = SQLCOM_REPLACE;
|
||||
lex->duplicates= DUP_REPLACE;
|
||||
mysql_init_select(lex);
|
||||
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
|
||||
}
|
||||
replace_lock_option insert2
|
||||
{
|
||||
@ -6058,7 +6076,7 @@ values:
|
||||
|
||||
expr_or_default:
|
||||
expr { $$= $1;}
|
||||
| DEFAULT {$$= new Item_default_value(); }
|
||||
| DEFAULT {$$= new Item_default_value(&Select->context); }
|
||||
;
|
||||
|
||||
opt_insert_update:
|
||||
@ -7027,15 +7045,17 @@ insert_ident:
|
||||
table_wild:
|
||||
ident '.' '*'
|
||||
{
|
||||
$$ = new Item_field(NullS,$1.str,"*");
|
||||
Lex->current_select->with_wild++;
|
||||
SELECT_LEX *sel= Select;
|
||||
$$ = new Item_field(&sel->context, NullS, $1.str, "*");
|
||||
sel->with_wild++;
|
||||
}
|
||||
| ident '.' ident '.' '*'
|
||||
{
|
||||
$$ = new Item_field((YYTHD->client_capabilities &
|
||||
SELECT_LEX *sel= Select;
|
||||
$$ = new Item_field(&sel->context, (YYTHD->client_capabilities &
|
||||
CLIENT_NO_SCHEMA ? NullS : $1.str),
|
||||
$3.str,"*");
|
||||
Lex->current_select->with_wild++;
|
||||
sel->with_wild++;
|
||||
}
|
||||
;
|
||||
|
||||
@ -7060,8 +7080,8 @@ simple_ident:
|
||||
SELECT_LEX *sel=Select;
|
||||
$$= (sel->parsing_place != IN_HAVING ||
|
||||
sel->get_in_sum_expr() > 0) ?
|
||||
(Item*) new Item_field(NullS,NullS,$1.str) :
|
||||
(Item*) new Item_ref(NullS,NullS,$1.str);
|
||||
(Item*) new Item_field(&sel->context, NullS, NullS, $1.str) :
|
||||
(Item*) new Item_ref(&sel->context, NullS, NullS, $1.str);
|
||||
}
|
||||
}
|
||||
| simple_ident_q { $$= $1; }
|
||||
@ -7073,8 +7093,8 @@ simple_ident_nospvar:
|
||||
SELECT_LEX *sel=Select;
|
||||
$$= (sel->parsing_place != IN_HAVING ||
|
||||
sel->get_in_sum_expr() > 0) ?
|
||||
(Item*) new Item_field(NullS,NullS,$1.str) :
|
||||
(Item*) new Item_ref(NullS,NullS,$1.str);
|
||||
(Item*) new Item_field(&sel->context, NullS, NullS, $1.str) :
|
||||
(Item*) new Item_ref(&sel->context, NullS, NullS, $1.str);
|
||||
}
|
||||
| simple_ident_q { $$= $1; }
|
||||
;
|
||||
@ -7111,7 +7131,8 @@ simple_ident_q:
|
||||
YYABORT;
|
||||
}
|
||||
|
||||
if (!(trg_fld= new Item_trigger_field(new_row ?
|
||||
if (!(trg_fld= new Item_trigger_field(&lex->current_select->context,
|
||||
new_row ?
|
||||
Item_trigger_field::NEW_ROW:
|
||||
Item_trigger_field::OLD_ROW,
|
||||
$3.str)))
|
||||
@ -7136,8 +7157,8 @@ simple_ident_q:
|
||||
}
|
||||
$$= (sel->parsing_place != IN_HAVING ||
|
||||
sel->get_in_sum_expr() > 0) ?
|
||||
(Item*) new Item_field(NullS,$1.str,$3.str) :
|
||||
(Item*) new Item_ref(NullS,$1.str,$3.str);
|
||||
(Item*) new Item_field(&sel->context, NullS, $1.str, $3.str) :
|
||||
(Item*) new Item_ref(&sel->context, NullS, $1.str, $3.str);
|
||||
}
|
||||
}
|
||||
| '.' ident '.' ident
|
||||
@ -7152,8 +7173,8 @@ simple_ident_q:
|
||||
}
|
||||
$$= (sel->parsing_place != IN_HAVING ||
|
||||
sel->get_in_sum_expr() > 0) ?
|
||||
(Item*) new Item_field(NullS,$2.str,$4.str) :
|
||||
(Item*) new Item_ref(NullS, $2.str, $4.str);
|
||||
(Item*) new Item_field(&sel->context, NullS, $2.str, $4.str) :
|
||||
(Item*) new Item_ref(&sel->context, NullS, $2.str, $4.str);
|
||||
}
|
||||
| ident '.' ident '.' ident
|
||||
{
|
||||
@ -7167,10 +7188,12 @@ simple_ident_q:
|
||||
}
|
||||
$$= (sel->parsing_place != IN_HAVING ||
|
||||
sel->get_in_sum_expr() > 0) ?
|
||||
(Item*) new Item_field((YYTHD->client_capabilities &
|
||||
(Item*) new Item_field(&sel->context,
|
||||
(YYTHD->client_capabilities &
|
||||
CLIENT_NO_SCHEMA ? NullS : $1.str),
|
||||
$3.str, $5.str) :
|
||||
(Item*) new Item_ref((YYTHD->client_capabilities &
|
||||
(Item*) new Item_ref(&sel->context,
|
||||
(YYTHD->client_capabilities &
|
||||
CLIENT_NO_SCHEMA ? NullS : $1.str),
|
||||
$3.str, $5.str);
|
||||
};
|
||||
@ -7720,9 +7743,11 @@ sys_option_value:
|
||||
it= new Item_null();
|
||||
}
|
||||
|
||||
if (!(trg_fld= new Item_trigger_field(Item_trigger_field::NEW_ROW,
|
||||
if (!(trg_fld= new Item_trigger_field(&lex->current_select->context,
|
||||
Item_trigger_field::NEW_ROW,
|
||||
$2.base_name.str)) ||
|
||||
!(i= new sp_instr_set_trigger_field(
|
||||
&lex->current_select->context,
|
||||
lex->sphead->instructions(), lex->spcont,
|
||||
trg_fld, it)))
|
||||
YYABORT;
|
||||
|
440
sql/table.cc
440
sql/table.cc
@ -594,6 +594,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
|
||||
goto err; /* purecov: inspected */
|
||||
}
|
||||
|
||||
reg_field->field_index= i;
|
||||
reg_field->comment=comment;
|
||||
if (field_type == FIELD_TYPE_BIT && !f_bit_as_char(pack_flag))
|
||||
{
|
||||
@ -1713,8 +1714,6 @@ void st_table_list::set_ancestor()
|
||||
}
|
||||
if (tbl->multitable_view)
|
||||
multitable_view= TRUE;
|
||||
if (tbl->table)
|
||||
tbl->table->grant= grant;
|
||||
} while ((tbl= tbl->next_local));
|
||||
|
||||
if (!multitable_view)
|
||||
@ -1726,69 +1725,19 @@ void st_table_list::set_ancestor()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Save old want_privilege and clear want_privilege
|
||||
|
||||
SYNOPSIS
|
||||
save_and_clear_want_privilege()
|
||||
*/
|
||||
|
||||
void st_table_list::save_and_clear_want_privilege()
|
||||
{
|
||||
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||
{
|
||||
if (tbl->table)
|
||||
{
|
||||
privilege_backup= tbl->table->grant.want_privilege;
|
||||
tbl->table->grant.want_privilege= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tbl->save_and_clear_want_privilege();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
restore want_privilege saved by save_and_clear_want_privilege
|
||||
|
||||
SYNOPSIS
|
||||
restore_want_privilege()
|
||||
*/
|
||||
|
||||
void st_table_list::restore_want_privilege()
|
||||
{
|
||||
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||
{
|
||||
if (tbl->table)
|
||||
tbl->table->grant.want_privilege= privilege_backup;
|
||||
else
|
||||
{
|
||||
tbl->restore_want_privilege();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup fields of placeholder of merged VIEW
|
||||
|
||||
SYNOPSIS
|
||||
st_table_list::setup_ancestor()
|
||||
thd - thread handler
|
||||
conds - condition of this JOIN
|
||||
check_opt_type - WHITH CHECK OPTION type (VIEW_CHECK_NONE,
|
||||
VIEW_CHECK_LOCAL, VIEW_CHECK_CASCADED)
|
||||
|
||||
NOTES
|
||||
ancestor is list of tables and views used by view (underlying tables/views)
|
||||
|
||||
DESCRIPTION
|
||||
It is:
|
||||
- preparing translation table for view columns (fix_fields() for every
|
||||
call and creation for first call)
|
||||
- preparing WHERE, ON and CHECK OPTION condition (fix_fields() for every
|
||||
call and merging for first call).
|
||||
- preparing translation table for view columns
|
||||
If there are underlying view(s) procedure first will be called for them.
|
||||
|
||||
RETURN
|
||||
@ -1796,87 +1745,30 @@ void st_table_list::restore_want_privilege()
|
||||
TRUE - error
|
||||
*/
|
||||
|
||||
bool st_table_list::setup_ancestor(THD *thd, Item **conds,
|
||||
uint8 check_opt_type)
|
||||
bool st_table_list::setup_ancestor(THD *thd)
|
||||
{
|
||||
DBUG_ENTER("st_table_list::setup_ancestor");
|
||||
if (!field_translation)
|
||||
{
|
||||
Field_translator *transl;
|
||||
SELECT_LEX *select= &view->select_lex;
|
||||
SELECT_LEX *current_select_save= thd->lex->current_select;
|
||||
byte *main_table_list_save= select_lex->table_list.first;
|
||||
Item *item;
|
||||
TABLE_LIST *tbl;
|
||||
List_iterator_fast<Item> it(select->item_list);
|
||||
uint i= 0;
|
||||
enum sub_select_type linkage_save=
|
||||
select_lex->master_unit()->first_select()->linkage;
|
||||
bool save_set_query_id= thd->set_query_id;
|
||||
bool save_wrapper= select_lex->no_wrap_view_item;
|
||||
bool save_allow_sum_func= thd->allow_sum_func;
|
||||
bool res= FALSE;
|
||||
DBUG_ENTER("st_table_list::setup_ancestor");
|
||||
uint field_count= 0;
|
||||
|
||||
if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&res))
|
||||
return TRUE;
|
||||
if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&field_count))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||
{
|
||||
if (tbl->ancestor &&
|
||||
tbl->setup_ancestor(thd, conds,
|
||||
(check_opt_type == VIEW_CHECK_CASCADED ?
|
||||
VIEW_CHECK_CASCADED :
|
||||
VIEW_CHECK_NONE)))
|
||||
tbl->setup_ancestor(thd))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
We have to ensure that inside the view we are not referring to any
|
||||
table outside of the view. We do it by changing the pointers used
|
||||
by fix_fields to look up tables so that only tables and views in
|
||||
view are seen. We also set linkage to DERIVED_TABLE_TYPE as a barrier
|
||||
so that we stop resolving fields as this level.
|
||||
*/
|
||||
thd->lex->current_select= select_lex;
|
||||
select_lex->table_list.first= (byte *)ancestor;
|
||||
select_lex->master_unit()->first_select()->linkage= DERIVED_TABLE_TYPE;
|
||||
|
||||
if (field_translation)
|
||||
{
|
||||
DBUG_PRINT("info", ("there are already translation table"));
|
||||
|
||||
select_lex->no_wrap_view_item= 1;
|
||||
|
||||
thd->set_query_id= 1;
|
||||
/* this view was prepared already on previous PS/SP execution */
|
||||
Field_translator *end= field_translation + select->item_list.elements;
|
||||
/* real rights will be checked in VIEW field */
|
||||
save_and_clear_want_privilege();
|
||||
/* aggregate function are allowed */
|
||||
thd->allow_sum_func= 1;
|
||||
for (transl= field_translation; transl < end; transl++)
|
||||
{
|
||||
if (!transl->item->fixed &&
|
||||
transl->item->fix_fields(thd, ancestor, &transl->item))
|
||||
goto err;
|
||||
}
|
||||
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||
{
|
||||
if (tbl->on_expr && !tbl->on_expr->fixed &&
|
||||
tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr))
|
||||
goto err;
|
||||
}
|
||||
if (where && !where->fixed && where->fix_fields(thd, ancestor, &where))
|
||||
goto err;
|
||||
if (check_option && !check_option->fixed &&
|
||||
check_option->fix_fields(thd, ancestor, &check_option))
|
||||
goto err;
|
||||
restore_want_privilege();
|
||||
|
||||
/* WHERE/ON resolved => we can rename fields */
|
||||
for (transl= field_translation; transl < end; transl++)
|
||||
{
|
||||
transl->item->rename((char *)transl->name);
|
||||
}
|
||||
goto ok;
|
||||
}
|
||||
|
||||
/* Create view fields translation table */
|
||||
@ -1886,73 +1778,81 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
|
||||
alloc(select->item_list.elements *
|
||||
sizeof(Field_translator)))))
|
||||
{
|
||||
res= TRUE;
|
||||
goto ok; // Restore thd
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
select_lex->no_wrap_view_item= 1;
|
||||
|
||||
/*
|
||||
Resolve all view items against ancestor table.
|
||||
|
||||
TODO: do it only for real used fields "on demand" to mark really
|
||||
used fields correctly.
|
||||
*/
|
||||
thd->set_query_id= 1;
|
||||
/* real rights will be checked in VIEW field */
|
||||
save_and_clear_want_privilege();
|
||||
/* aggregate function are allowed */
|
||||
thd->allow_sum_func= 1;
|
||||
while ((item= it++))
|
||||
{
|
||||
/* save original name of view column */
|
||||
char *name= item->name;
|
||||
transl[i].item= item;
|
||||
if (!item->fixed && item->fix_fields(thd, ancestor, &transl[i].item))
|
||||
goto err;
|
||||
/* set new item get in fix fields and original column name */
|
||||
transl[i++].name= name;
|
||||
transl[field_count].name= item->name;
|
||||
transl[field_count++].item= item;
|
||||
}
|
||||
field_translation= transl;
|
||||
/* TODO: sort this list? Use hash for big number of fields */
|
||||
field_translation_end= transl + field_count;
|
||||
/* TODO: use hash for big number of fields */
|
||||
|
||||
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||
/* full text function moving to current select */
|
||||
if (view->select_lex.ftfunc_list->elements)
|
||||
{
|
||||
if (tbl->on_expr && !tbl->on_expr->fixed &&
|
||||
tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr))
|
||||
goto err;
|
||||
Item_func_match *ifm;
|
||||
SELECT_LEX *current_select= thd->lex->current_select;
|
||||
List_iterator_fast<Item_func_match>
|
||||
li(*(view->select_lex.ftfunc_list));
|
||||
while ((ifm= li++))
|
||||
current_select->ftfunc_list->push_front(ifm);
|
||||
}
|
||||
if (where ||
|
||||
(check_opt_type == VIEW_CHECK_CASCADED &&
|
||||
ancestor->check_option))
|
||||
}
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Prepare where expression of view
|
||||
|
||||
SYNOPSIS
|
||||
st_table_list::prep_where()
|
||||
thd - thread handler
|
||||
conds - condition of this JOIN
|
||||
no_where_clause - do not build WHERE or ON outer qwery do not need it
|
||||
(it is INSERT), we do not need conds if this flag is set
|
||||
|
||||
NOTE: have to be called befor CHECK OPTION preparation, because it makes
|
||||
fix_fields for view WHERE clause
|
||||
|
||||
RETURN
|
||||
FALSE - OK
|
||||
TRUE - error
|
||||
*/
|
||||
|
||||
bool st_table_list::prep_where(THD *thd, Item **conds,
|
||||
bool no_where_clause)
|
||||
{
|
||||
Query_arena *arena= thd->current_arena, backup;
|
||||
TABLE_LIST *tbl= this;
|
||||
if (arena->is_conventional())
|
||||
arena= 0; // For easier test
|
||||
DBUG_ENTER("st_table_list::prep_where");
|
||||
|
||||
if (where && !where->fixed && where->fix_fields(thd, ancestor, &where))
|
||||
goto err;
|
||||
|
||||
if (arena)
|
||||
thd->set_n_backup_item_arena(arena, &backup);
|
||||
|
||||
if (check_opt_type)
|
||||
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||
{
|
||||
if (tbl->view && tbl->prep_where(thd, conds, no_where_clause))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (where)
|
||||
check_option= where->copy_andor_structure(thd);
|
||||
if (check_opt_type == VIEW_CHECK_CASCADED)
|
||||
{
|
||||
check_option= and_conds(check_option, ancestor->check_option);
|
||||
}
|
||||
if (!where->fixed && where->fix_fields(thd, &where))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
check that it is not VIEW in which we insert with INSERT SELECT
|
||||
(in this case we can't add view WHERE condition to main SELECT_LEX)
|
||||
*/
|
||||
if (where && !no_where_clause)
|
||||
if (!no_where_clause && !where_processed)
|
||||
{
|
||||
TABLE_LIST *tbl= this;
|
||||
Query_arena *arena= thd->current_arena, backup;
|
||||
arena= thd->change_arena_if_needed(&backup); // For easier test
|
||||
|
||||
/* Go up to join tree and try to find left join */
|
||||
for (; tbl; tbl= tbl->embedding)
|
||||
{
|
||||
@ -1969,72 +1869,107 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
|
||||
}
|
||||
}
|
||||
if (tbl == 0)
|
||||
{
|
||||
if (outer_join)
|
||||
{
|
||||
/*
|
||||
Store WHERE condition to ON expression for outer join, because
|
||||
we can't use WHERE to correctly execute left joins on VIEWs and
|
||||
this expression will not be moved to WHERE condition (i.e. will
|
||||
be clean correctly for PS/SP)
|
||||
*/
|
||||
on_expr= and_conds(on_expr, where);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
It is conds of JOIN, but it will be stored in
|
||||
st_select_lex::prep_where for next reexecution
|
||||
*/
|
||||
*conds= and_conds(*conds, where);
|
||||
}
|
||||
if (arena)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
where_processed= TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (arena)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
restore_want_privilege();
|
||||
|
||||
|
||||
/*
|
||||
fix_fields do not need tables, because new are only AND operation and we
|
||||
just need recollect statistics
|
||||
Prepare check option expression of table
|
||||
|
||||
SYNOPSIS
|
||||
st_table_list::prep_check_option()
|
||||
thd - thread handler
|
||||
check_opt_type - WITH CHECK OPTION type (VIEW_CHECK_NONE,
|
||||
VIEW_CHECK_LOCAL, VIEW_CHECK_CASCADED)
|
||||
we use this parameter instead of direct check of
|
||||
effective_with_check to change type of underlying
|
||||
views to VIEW_CHECK_CASCADED if outer view have
|
||||
such option and prevent processing of underlying
|
||||
view check options if outer view have just
|
||||
VIEW_CHECK_LOCAL option.
|
||||
|
||||
NOTE
|
||||
This method build check options for every call
|
||||
(usual execution or every SP/PS call)
|
||||
This method have to be called after WHERE preparation
|
||||
(st_table_list::prep_where)
|
||||
|
||||
RETURN
|
||||
FALSE - OK
|
||||
TRUE - error
|
||||
*/
|
||||
if (check_option && !check_option->fixed &&
|
||||
check_option->fix_fields(thd, 0, &check_option))
|
||||
goto err;
|
||||
|
||||
/* WHERE/ON resolved => we can rename fields */
|
||||
bool st_table_list::prep_check_option(THD *thd, uint8 check_opt_type)
|
||||
{
|
||||
Field_translator *end= field_translation + select->item_list.elements;
|
||||
for (transl= field_translation; transl < end; transl++)
|
||||
DBUG_ENTER("st_table_list::prep_check_option");
|
||||
|
||||
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||
{
|
||||
transl->item->rename((char *)transl->name);
|
||||
/* see comment of check_opt_type parameter */
|
||||
if (tbl->view &&
|
||||
tbl->prep_check_option(thd,
|
||||
((check_opt_type == VIEW_CHECK_CASCADED) ?
|
||||
VIEW_CHECK_CASCADED :
|
||||
VIEW_CHECK_NONE)))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* full text function moving to current select */
|
||||
if (view->select_lex.ftfunc_list->elements)
|
||||
if (check_opt_type)
|
||||
{
|
||||
Query_arena *arena= thd->current_arena, backup;
|
||||
if (arena->is_conventional())
|
||||
arena= 0; // For easier test
|
||||
else
|
||||
thd->set_n_backup_item_arena(arena, &backup);
|
||||
|
||||
Item_func_match *ifm;
|
||||
List_iterator_fast<Item_func_match>
|
||||
li(*(view->select_lex.ftfunc_list));
|
||||
while ((ifm= li++))
|
||||
current_select_save->ftfunc_list->push_front(ifm);
|
||||
if (arena)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
Item *item= 0;
|
||||
if (where)
|
||||
{
|
||||
DBUG_ASSERT(where->fixed);
|
||||
item= where->copy_andor_structure(thd);
|
||||
}
|
||||
if (check_opt_type == VIEW_CHECK_CASCADED)
|
||||
{
|
||||
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||
{
|
||||
if (tbl->check_option)
|
||||
item= and_conds(item, tbl->check_option);
|
||||
}
|
||||
}
|
||||
if (item)
|
||||
thd->change_item_tree(&check_option, item);
|
||||
}
|
||||
|
||||
goto ok;
|
||||
if (check_option)
|
||||
{
|
||||
const char *save_where= thd->where;
|
||||
thd->where= "check option";
|
||||
if (!check_option->fixed &&
|
||||
check_option->fix_fields(thd, &check_option) ||
|
||||
check_option->check_cols(1))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
thd->where= save_where;
|
||||
}
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
err:
|
||||
res= TRUE;
|
||||
|
||||
/*
|
||||
Hide errors which show view underlying table information
|
||||
|
||||
SYNOPSIS
|
||||
st_table_list::hide_view_error()
|
||||
thd thread handler
|
||||
|
||||
*/
|
||||
|
||||
void st_table_list::hide_view_error(THD *thd)
|
||||
{
|
||||
/* Hide "Unknown column" or "Unknown function" error */
|
||||
if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
|
||||
thd->net.last_errno == ER_SP_DOES_NOT_EXIST)
|
||||
@ -2042,15 +1977,12 @@ err:
|
||||
thd->clear_error();
|
||||
my_error(ER_VIEW_INVALID, MYF(0), view_db.str, view_name.str);
|
||||
}
|
||||
|
||||
ok:
|
||||
select_lex->no_wrap_view_item= save_wrapper;
|
||||
thd->lex->current_select= current_select_save;
|
||||
select_lex->table_list.first= main_table_list_save;
|
||||
select_lex->master_unit()->first_select()->linkage= linkage_save;
|
||||
thd->set_query_id= save_set_query_id;
|
||||
thd->allow_sum_func= save_allow_sum_func;
|
||||
DBUG_RETURN(res);
|
||||
else if (thd->net.last_errno == ER_NO_DEFAULT_FOR_FIELD)
|
||||
{
|
||||
thd->clear_error();
|
||||
// TODO: make correct error message
|
||||
my_error(ER_NO_DEFAULT_FOR_VIEW_FIELD, MYF(0), view_db.str, view_name.str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2094,9 +2026,9 @@ void st_table_list::cleanup_items()
|
||||
if (!field_translation)
|
||||
return;
|
||||
|
||||
Field_translator *end= (field_translation +
|
||||
view->select_lex.item_list.elements);
|
||||
for (Field_translator *transl= field_translation; transl < end; transl++)
|
||||
for (Field_translator *transl= field_translation;
|
||||
transl < field_translation_end;
|
||||
transl++)
|
||||
transl->item->walk(&Item::cleanup_processor, 0);
|
||||
}
|
||||
|
||||
@ -2209,8 +2141,9 @@ bool st_table_list::set_insert_values(MEM_ROOT *mem_root)
|
||||
|
||||
void Field_iterator_view::set(TABLE_LIST *table)
|
||||
{
|
||||
view= table;
|
||||
ptr= table->field_translation;
|
||||
array_end= ptr + table->view->select_lex.item_list.elements;
|
||||
array_end= table->field_translation_end;
|
||||
}
|
||||
|
||||
|
||||
@ -2220,9 +2153,9 @@ const char *Field_iterator_table::name()
|
||||
}
|
||||
|
||||
|
||||
Item *Field_iterator_table::item(THD *thd)
|
||||
Item *Field_iterator_table::create_item(THD *thd)
|
||||
{
|
||||
return new Item_field(thd, *ptr);
|
||||
return new Item_field(thd, &thd->lex->current_select->context, *ptr);
|
||||
}
|
||||
|
||||
|
||||
@ -2232,6 +2165,51 @@ const char *Field_iterator_view::name()
|
||||
}
|
||||
|
||||
|
||||
Item *Field_iterator_view::create_item(THD *thd)
|
||||
{
|
||||
return create_view_field(thd, view, &ptr->item, ptr->name);
|
||||
}
|
||||
|
||||
Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
|
||||
const char *name)
|
||||
{
|
||||
bool save_wrapper= thd->lex->select_lex.no_wrap_view_item;
|
||||
Item *field= *field_ref;
|
||||
DBUG_ENTER("create_view_field");
|
||||
|
||||
if (view->schema_table_reformed)
|
||||
{
|
||||
/*
|
||||
In case of SHOW command (schema_table_reformed set) all items are
|
||||
fixed
|
||||
*/
|
||||
DBUG_ASSERT(field && field->fixed);
|
||||
DBUG_RETURN(field);
|
||||
}
|
||||
|
||||
DBUG_ASSERT(field);
|
||||
thd->lex->current_select->no_wrap_view_item= TRUE;
|
||||
if (!field->fixed)
|
||||
{
|
||||
if (field->fix_fields(thd, field_ref))
|
||||
{
|
||||
thd->lex->current_select->no_wrap_view_item= save_wrapper;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
field= *field_ref;
|
||||
}
|
||||
thd->lex->current_select->no_wrap_view_item= save_wrapper;
|
||||
if (thd->lex->current_select->no_wrap_view_item)
|
||||
{
|
||||
DBUG_RETURN(field);
|
||||
}
|
||||
Item *item= new Item_direct_view_ref(&view->view->select_lex.context,
|
||||
field_ref, view->view_name.str,
|
||||
name);
|
||||
DBUG_RETURN(item);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
** Instansiate templates
|
||||
*****************************************************************************/
|
||||
|
43
sql/table.h
43
sql/table.h
@ -329,9 +329,13 @@ typedef struct st_schema_table
|
||||
#define VIEW_CHECK_SKIP 2
|
||||
|
||||
struct st_lex;
|
||||
struct st_table_list;
|
||||
class select_union;
|
||||
class TMP_TABLE_PARAM;
|
||||
|
||||
Item *create_view_field(THD *thd, st_table_list *view, Item **field_ref,
|
||||
const char *name);
|
||||
|
||||
struct Field_translator
|
||||
{
|
||||
Item *item;
|
||||
@ -384,6 +388,8 @@ typedef struct st_table_list
|
||||
st_select_lex *select_lex;
|
||||
st_lex *view; /* link on VIEW lex for merging */
|
||||
Field_translator *field_translation; /* array of VIEW fields */
|
||||
/* pointer to element after last one in translation table above */
|
||||
Field_translator *field_translation_end;
|
||||
/* list of ancestor(s) of this table (underlying table(s)/view(s) */
|
||||
st_table_list *ancestor;
|
||||
/* most upper view this table belongs to */
|
||||
@ -408,8 +414,7 @@ typedef struct st_table_list
|
||||
algorithm)
|
||||
*/
|
||||
uint8 effective_with_check;
|
||||
uint effective_algorithm; /* which algorithm was really used */
|
||||
uint privilege_backup; /* place for saving privileges */
|
||||
uint8 effective_algorithm; /* which algorithm was really used */
|
||||
GRANT_INFO grant;
|
||||
/* data need by some engines in query cache*/
|
||||
ulonglong engine_data;
|
||||
@ -424,7 +429,6 @@ typedef struct st_table_list
|
||||
bool updating; /* for replicate-do/ignore table */
|
||||
bool force_index; /* prefer index over table scan */
|
||||
bool ignore_leaves; /* preload only non-leaf nodes */
|
||||
bool no_where_clause; /* do not attach WHERE to SELECT */
|
||||
table_map dep_tables; /* tables the table depends on */
|
||||
table_map on_expr_dep_tables; /* tables on expression depends on */
|
||||
struct st_nested_join *nested_join; /* if the element is a nested join */
|
||||
@ -437,6 +441,8 @@ typedef struct st_table_list
|
||||
/* TRUE if this merged view contain auto_increment field */
|
||||
bool contain_auto_increment;
|
||||
bool multitable_view; /* TRUE iff this is multitable view */
|
||||
/* view where processed */
|
||||
bool where_processed;
|
||||
/* FRMTYPE_ERROR if any type is acceptable */
|
||||
enum frm_type_enum required_type;
|
||||
char timestamp_buffer[20]; /* buffer for timestamp (19+1) */
|
||||
@ -449,16 +455,32 @@ typedef struct st_table_list
|
||||
void calc_md5(char *buffer);
|
||||
void set_ancestor();
|
||||
int view_check_option(THD *thd, bool ignore_failure);
|
||||
bool setup_ancestor(THD *thd, Item **conds, uint8 check_option);
|
||||
bool setup_ancestor(THD *thd);
|
||||
void cleanup_items();
|
||||
bool placeholder() {return derived || view; }
|
||||
void print(THD *thd, String *str);
|
||||
void save_and_clear_want_privilege();
|
||||
void restore_want_privilege();
|
||||
bool check_single_table(st_table_list **table, table_map map,
|
||||
st_table_list *view);
|
||||
bool set_insert_values(MEM_ROOT *mem_root);
|
||||
void hide_view_error(THD *thd);
|
||||
st_table_list *find_underlying_table(TABLE *table);
|
||||
inline bool prepare_check_option(THD *thd)
|
||||
{
|
||||
bool res= FALSE;
|
||||
if (effective_with_check)
|
||||
res= prep_check_option(thd, effective_with_check);
|
||||
return res;
|
||||
}
|
||||
inline bool prepare_where(THD *thd, Item **conds,
|
||||
bool no_where_clause)
|
||||
{
|
||||
if (effective_algorithm == VIEW_ALGORITHM_MERGE)
|
||||
return prep_where(thd, conds, no_where_clause);
|
||||
return FALSE;
|
||||
}
|
||||
private:
|
||||
bool prep_check_option(THD *thd, uint8 check_opt_type);
|
||||
bool prep_where(THD *thd, Item **conds, bool no_where_clause);
|
||||
} TABLE_LIST;
|
||||
|
||||
class Item;
|
||||
@ -471,7 +493,7 @@ public:
|
||||
virtual void next()= 0;
|
||||
virtual bool end_of_fields()= 0; /* Return 1 at end of list */
|
||||
virtual const char *name()= 0;
|
||||
virtual Item *item(THD *)= 0;
|
||||
virtual Item *create_item(THD *)= 0;
|
||||
virtual Field *field()= 0;
|
||||
};
|
||||
|
||||
@ -486,7 +508,7 @@ public:
|
||||
void next() { ptr++; }
|
||||
bool end_of_fields() { return *ptr == 0; }
|
||||
const char *name();
|
||||
Item *item(THD *thd);
|
||||
Item *create_item(THD *thd);
|
||||
Field *field() { return *ptr; }
|
||||
};
|
||||
|
||||
@ -494,15 +516,18 @@ public:
|
||||
class Field_iterator_view: public Field_iterator
|
||||
{
|
||||
Field_translator *ptr, *array_end;
|
||||
TABLE_LIST *view;
|
||||
public:
|
||||
Field_iterator_view() :ptr(0), array_end(0) {}
|
||||
void set(TABLE_LIST *table);
|
||||
void next() { ptr++; }
|
||||
bool end_of_fields() { return ptr == array_end; }
|
||||
const char *name();
|
||||
Item *item(THD *thd) { return ptr->item; }
|
||||
Item *create_item(THD *thd);
|
||||
Item **item_ptr() {return &ptr->item; }
|
||||
Field *field() { return 0; }
|
||||
|
||||
inline Item *item() { return ptr->item; }
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user