Name resolution context added (BUG#6443)

This commit is contained in:
bell@sanja.is.com.ua 2005-07-01 07:05:42 +03:00
parent d8cb0cbc3f
commit d3905f3d0e
55 changed files with 1688 additions and 1069 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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
*****************************************************************************/

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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();
};

View File

@ -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;

View File

@ -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; };

View File

@ -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;

View File

@ -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();

View File

@ -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];

View File

@ -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*);

View File

@ -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);

View File

@ -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; }
};

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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));
}

View File

@ -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"

View File

@ -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;

View File

@ -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;

View File

@ -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)
{}

View File

@ -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), &not_used_item, 0, 0, 0,
&not_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);
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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();

View File

@ -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)

View File

@ -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,

View File

@ -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));
}

View File

@ -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
*/

View File

@ -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);

View File

@ -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);
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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;

View File

@ -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> &not_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);
/*

View File

@ -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
{

View File

@ -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);

View File

@ -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;

View File

@ -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
*****************************************************************************/

View File

@ -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; }
};