summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2005-07-01 07:05:42 +0300
committerunknown <bell@sanja.is.com.ua>2005-07-01 07:05:42 +0300
commitb4f595b95f1740b7153013431080ff77de8d867a (patch)
tree9add97047abadbc8746b2d0a892d7944e8703d4f /sql
parent6a5ba8fdc2b5c2b5d9f94049c040c24566248461 (diff)
downloadmariadb-git-b4f595b95f1740b7153013431080ff77de8d867a.tar.gz
Name resolution context added (BUG#6443)
include/my_bitmap.h: new bitmap operation mysql-test/r/view.result: added warnings Correct inserting data check (absence of default value) for view underlying tables (BUG#6443) mysql-test/t/view.test: Correct inserting data check (absence of default value) for view underlying tables (BUG#6443) mysys/my_bitmap.c: new bitmap operation sql/field.h: index of field in table added sql/item.cc: Name resolution context added table list removed from fix_fields() arguments sql/item.h: Name resolution context added table list removed from fix_fields() arguments sql/item_cmpfunc.cc: table list removed from fix_fields() arguments sql/item_cmpfunc.h: table list removed from fix_fields() arguments sql/item_func.cc: table list removed from fix_fields() arguments sql/item_func.h: table list removed from fix_fields() arguments sql/item_row.cc: table list removed from fix_fields() arguments sql/item_row.h: table list removed from fix_fields() arguments sql/item_strfunc.cc: fixed server crash on NULL argument sql/item_strfunc.h: table list removed from fix_fields() arguments sql/item_subselect.cc: table list removed from fix_fields() arguments sql/item_subselect.h: table list removed from fix_fields() arguments sql/item_sum.cc: table list removed from fix_fields() arguments sql/item_sum.h: table list removed from fix_fields() arguments sql/item_timefunc.cc: table list removed from fix_fields() arguments sql/item_timefunc.h: table list removed from fix_fields() arguments sql/item_uniq.h: table list removed from fix_fields() arguments sql/log_event.cc: Name resolution context added sql/log_event.h: Name resolution context added sql/mysql_priv.h: Name resolution context added sql/set_var.cc: table list removed from fix_fields() arguments sql/share/errmsg.txt: new error message sql/sp.cc: Name resolution context added sql/sp_head.cc: table list removed from fix_fields() arguments sql/sp_head.h: Name resolution context added sql/sql_base.cc: table list removed from fix_fields() arguments Name resolution context added sql/sql_class.cc: renamed variable sql/sql_delete.cc: Name resolution context added sql/sql_derived.cc: Name resolution context added sql/sql_do.cc: table list removed from fix_fields() arguments sql/sql_handler.cc: Name resolution context added sql/sql_help.cc: Name resolution context added sql/sql_insert.cc: Name resolution context added table list removed from fix_fields() arguments sql/sql_lex.cc: Name resolution context added sql/sql_lex.h: removed resolve mode (information stored into name resolution context) sql/sql_load.cc: table list removed from fix_fields() arguments sql/sql_olap.cc: Name resolution context added sql/sql_parse.cc: Name resolution context added sql/sql_prepare.cc: table list removed from fix_fields() arguments sql/sql_select.cc: table list removed from fix_fields() arguments sql/sql_show.cc: Name resolution context added sql/sql_trigger.cc: table list removed from fix_fields() arguments sql/sql_udf.h: table list removed from fix_fields() arguments sql/sql_union.cc: Name resolution context added sql/sql_update.cc: Name resolution context added sql/sql_view.cc: Name resolution context added sql/sql_view.h: table list removed from fix_fields() arguments sql/sql_yacc.yy: Name resolution context added sql/table.cc: Name resolution context added merged view processing moved sql/table.h: merged view processing moved
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h1
-rw-r--r--sql/item.cc514
-rw-r--r--sql/item.h227
-rw-r--r--sql/item_cmpfunc.cc31
-rw-r--r--sql/item_cmpfunc.h18
-rw-r--r--sql/item_func.cc47
-rw-r--r--sql/item_func.h76
-rw-r--r--sql/item_row.cc4
-rw-r--r--sql/item_row.h2
-rw-r--r--sql/item_strfunc.cc2
-rw-r--r--sql/item_strfunc.h6
-rw-r--r--sql/item_subselect.cc50
-rw-r--r--sql/item_subselect.h8
-rw-r--r--sql/item_sum.cc22
-rw-r--r--sql/item_sum.h70
-rw-r--r--sql/item_timefunc.cc4
-rw-r--r--sql/item_timefunc.h2
-rw-r--r--sql/item_uniq.h2
-rw-r--r--sql/log_event.cc11
-rw-r--r--sql/log_event.h3
-rw-r--r--sql/mysql_priv.h24
-rw-r--r--sql/set_var.cc8
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sp.cc10
-rw-r--r--sql/sp_head.cc8
-rw-r--r--sql/sp_head.h5
-rw-r--r--sql/sql_base.cc177
-rw-r--r--sql/sql_class.cc16
-rw-r--r--sql/sql_delete.cc7
-rw-r--r--sql/sql_derived.cc4
-rw-r--r--sql/sql_do.cc2
-rw-r--r--sql/sql_handler.cc11
-rw-r--r--sql/sql_help.cc23
-rw-r--r--sql/sql_insert.cc174
-rw-r--r--sql/sql_lex.cc54
-rw-r--r--sql/sql_lex.h45
-rw-r--r--sql/sql_load.cc20
-rw-r--r--sql/sql_olap.cc12
-rw-r--r--sql/sql_parse.cc50
-rw-r--r--sql/sql_prepare.cc57
-rw-r--r--sql/sql_select.cc51
-rw-r--r--sql/sql_show.cc41
-rw-r--r--sql/sql_trigger.cc2
-rw-r--r--sql/sql_udf.h4
-rw-r--r--sql/sql_union.cc9
-rw-r--r--sql/sql_update.cc39
-rw-r--r--sql/sql_view.cc76
-rw-r--r--sql/sql_view.h2
-rw-r--r--sql/sql_yacc.yy95
-rw-r--r--sql/table.cc474
-rw-r--r--sql/table.h49
51 files changed, 1595 insertions, 1056 deletions
diff --git a/sql/field.h b/sql/field.h
index 2b1229744c2..523cf444c30 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -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
diff --git a/sql/item.cc b/sql/item.cc
index b6f8b7ebc51..00b93cfa270 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -440,16 +440,17 @@ void Item::rename(char *new_name)
}
-Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
- const char *field_name_par)
- :orig_db_name(db_name_par), orig_table_name(table_name_par),
- orig_field_name(field_name_par),
- db_name(db_name_par), table_name(table_name_par),
- field_name(field_name_par),
+Item_ident::Item_ident(Name_resolution_context *context_arg,
+ const char *db_name_arg,const char *table_name_arg,
+ const char *field_name_arg)
+ :orig_db_name(db_name_arg), orig_table_name(table_name_arg),
+ orig_field_name(field_name_arg), context(context_arg),
+ db_name(db_name_arg), table_name(table_name_arg),
+ field_name(field_name_arg),
alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
cached_table(0), depended_from(0)
{
- name = (char*) field_name_par;
+ name = (char*) field_name_arg;
}
@@ -460,6 +461,7 @@ Item_ident::Item_ident(THD *thd, Item_ident *item)
orig_db_name(item->orig_db_name),
orig_table_name(item->orig_table_name),
orig_field_name(item->orig_field_name),
+ context(item->context),
db_name(item->db_name),
table_name(item->table_name),
field_name(item->field_name),
@@ -785,7 +787,7 @@ Item_splocal::type() const
}
-bool Item_splocal::fix_fields(THD *, struct st_table_list *, Item **)
+bool Item_splocal::fix_fields(THD *, Item **)
{
Item *it= this_item();
DBUG_ASSERT(it->fixed);
@@ -855,7 +857,8 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
uint el= fields.elements;
Item *new_item;
ref_pointer_array[el]= this;
- if (!(new_item= new Item_ref(ref_pointer_array + el, 0, name)))
+ if (!(new_item= new Item_ref(&thd->lex->current_select->context,
+ ref_pointer_array + el, 0, name)))
return; // fatal_error is set
fields.push_front(this);
ref_pointer_array[el]= this;
@@ -995,7 +998,7 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
}
Item_field::Item_field(Field *f)
- :Item_ident(NullS, *f->table_name, f->field_name),
+ :Item_ident(0, NullS, *f->table_name, f->field_name),
item_equal(0), no_const_subst(0),
have_privileges(0), any_privileges(0)
{
@@ -1007,8 +1010,9 @@ Item_field::Item_field(Field *f)
orig_table_name= orig_field_name= "";
}
-Item_field::Item_field(THD *thd, Field *f)
- :Item_ident(f->table->s->db, *f->table_name, f->field_name),
+Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
+ Field *f)
+ :Item_ident(context_arg, f->table->s->db, *f->table_name, f->field_name),
item_equal(0), no_const_subst(0),
have_privileges(0), any_privileges(0)
{
@@ -1043,6 +1047,17 @@ Item_field::Item_field(THD *thd, Field *f)
set_field(f);
}
+
+Item_field::Item_field(Name_resolution_context *context_arg,
+ const char *db_arg,const char *table_name_arg,
+ const char *field_name_arg)
+ :Item_ident(context_arg, db_arg,table_name_arg,field_name_arg),
+ field(0), result_field(0), item_equal(0), no_const_subst(0),
+ have_privileges(0), any_privileges(0)
+{
+ collation.set(DERIVATION_IMPLICIT);
+}
+
// Constructor need to process subselect with temporary tables (see Item)
Item_field::Item_field(THD *thd, Item_field *item)
:Item_ident(thd, item),
@@ -2233,7 +2248,7 @@ bool Item_param::convert_str_value(THD *thd)
return rc;
}
-bool Item_param::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+bool Item_param::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select;
@@ -2393,9 +2408,7 @@ int Item_copy_string::save_in_field(Field *field, bool no_conversions)
*/
/* ARGSUSED */
-bool Item::fix_fields(THD *thd,
- struct st_table_list *list,
- Item ** ref)
+bool Item::fix_fields(THD *thd, Item ** ref)
{
// We do not check fields which are fixed during construction
@@ -2762,7 +2775,6 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
SYNOPSIS
Item_field::fix_fields()
thd [in] current thread
- tables [in] the tables in a FROM clause
reference [in/out] view column if this item was resolved to a view column
DESCRIPTION
@@ -2808,7 +2820,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
FALSE on success
*/
-bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
+bool Item_field::fix_fields(THD *thd, Item **reference)
{
enum_parsing_place place= NO_MATTER;
DBUG_ASSERT(fixed == 0);
@@ -2821,135 +2833,129 @@ 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,
- IGNORE_EXCEPT_NON_UNIQUE,
- !any_privileges)) ==
+ if ((from_field= find_field_in_tables(thd, this, context->table_list,
+ reference,
+ IGNORE_EXCEPT_NON_UNIQUE,
+ !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.
+ 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;
- 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).
+ 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;
- 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
- */
- 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,
- reference,
- IGNORE_EXCEPT_NON_UNIQUE,
- TRUE)) !=
- not_found_field)
- {
- if (from_field)
- {
- if (from_field != view_ref_found)
- {
- prev_subselect_item->used_tables_cache|= from_field->table->map;
- prev_subselect_item->const_item_cache= 0;
- }
- else
- {
- Item::Type type= (*reference)->type();
- prev_subselect_item->used_tables_cache|=
- (*reference)->used_tables();
- prev_subselect_item->const_item_cache&=
- (*reference)->const_item();
- mark_as_dependent(thd, last, current_sel, 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
- */
- return FALSE;
- }
- }
- break;
- }
+ 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).
- /* Search in the SELECT and GROUP lists of the outer select. */
- if (outer_sel->resolve_mode == SELECT_LEX::SELECT_MODE)
+ 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 ||
+ (!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,
+ outer_context->
+ check_privileges)) !=
+ not_found_field)
+ {
+ if (from_field)
{
- if (!(ref= resolve_ref_in_select_and_group(thd, this, outer_sel)))
- return TRUE; /* Some error occurred (e.g. ambiguous names). */
- if (ref != not_found_item)
+ if (from_field != view_ref_found)
{
- DBUG_ASSERT(*ref && (*ref)->fixed);
- prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
- prev_subselect_item->const_item_cache&= (*ref)->const_item();
- break;
+ prev_subselect_item->used_tables_cache|= from_field->table->map;
+ prev_subselect_item->const_item_cache= 0;
}
- }
+ else
+ {
+ Item::Type type= (*reference)->type();
+ prev_subselect_item->used_tables_cache|=
+ (*reference)->used_tables();
+ prev_subselect_item->const_item_cache&=
+ (*reference)->const_item();
+ mark_as_dependent(thd, last_checked_context->select_lex,
+ context->select_lex, this,
+ ((type == REF_ITEM || type == FIELD_ITEM) ?
+ (Item_ident*) (*reference) :
+ 0));
+ /*
+ 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;
+ }
+ }
+ break;
+ }
- // Reference is not found => depend from outer (or just error)
- prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
- prev_subselect_item->const_item_cache= 0;
+ /* 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, select)))
+ goto error; /* Some error occurred (e.g. ambiguous names). */
+ if (ref != not_found_item)
+ {
+ DBUG_ASSERT(*ref && (*ref)->fixed);
+ prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
+ prev_subselect_item->const_item_cache&= (*ref)->const_item();
+ break;
+ }
+ }
- if (outer_sel->master_unit()->first_select()->linkage ==
- DERIVED_TABLE_TYPE)
- break; // do not look over derived table
- }
+ /*
+ 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;
}
DBUG_ASSERT(ref != 0);
if (!from_field)
- return TRUE;
+ goto error;
if (ref == not_found_item && from_field == not_found_field)
{
if (upward_lookup)
{
- // We can't say exactly what absent table or field
+ // We can't say exactly what absent table or field
my_error(ER_BAD_FIELD_ERROR, MYF(0), full_name(), thd->where);
}
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,43 +4078,33 @@ 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
HAVING or the outer SELECT does not use grouping (i.e. tables are
accessible).
- TODO:
+ TODO:
Here we could first find the field anyway, and then test this
condition, so that we can give a better error message -
ER_WRONG_FIELD_WITH_GROUP, instead of the less informative
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;
}
@@ -4526,11 +4578,27 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
{
if (field_arg->flags & NO_DEFAULT_VALUE_FLAG)
{
- 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);
+ 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
*****************************************************************************/
diff --git a/sql/item.h b/sql/item.h
index c8180b4932a..22641b8edd4 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -24,7 +24,6 @@ struct st_table_list;
void item_init(void); /* Init item functions */
class Item_field;
-
/*
"Declared Type Collation"
A combination of collation and its derivation.
@@ -218,6 +217,97 @@ struct Hybrid_type_traits_integer: public Hybrid_type_traits
static const Hybrid_type_traits_integer *instance();
};
+
+void dummy_error_processor(THD *thd, void *data);
+
+void view_error_processor(THD *thd, void *data);
+
+/*
+ Instances of Name_resolution_context store the information necesary for
+ name resolution of Items and other context analysis of a query made in
+ fix_fields().
+
+ This structure is a part of SELECT_LEX, a pointer to this structure is
+ assigned when an item is created (which happens mostly during parsing
+ (sql_yacc.yy)), but the structure itself will be initialized after parsing
+ is complete
+
+ TODO: move subquery of INSERT ... SELECT and CREATE ... SELECT to
+ separate SELECT_LEX which allow to remove tricks of changing this
+ structure before and after INSERT/CREATE and its SELECT to make correct
+ field name resolution.
+*/
+struct Name_resolution_context
+{
+ /*
+ The name resolution context to search in when an Item cannot be
+ resolved in this context (the context of an outer select)
+ */
+ Name_resolution_context *outer_context;
+
+ /*
+ List of tables used to resolve the items of this context. Usually these
+ are tables from the FROM clause of SELECT statement. The exceptions are
+ INSERT ... SELECT and CREATE ... SELECT statements, where SELECT
+ subquery is not moved to a separate SELECT_LEX. For these types of
+ statements we have to change this member dynamically to ensure correct
+ name resolution of different parts of the statement.
+ */
+ TABLE_LIST *table_list;
+
+ /*
+ SELECT_LEX item belong to, in case of merged VIEW it can differ from
+ SELECT_LEX where item was created, so we can't use table_list/field_list
+ from there
+ */
+ st_select_lex *select_lex;
+
+ /*
+ Processor of errors caused during Item name resolving, now used only to
+ hide underlying tables in errors about views (i.e. it substitute some
+ errors for views)
+ */
+ void (*error_processor)(THD *, void *);
+ void *error_processor_data;
+
+ /*
+ When TRUE items are resolved in this context both against the
+ SELECT list and this->table_list. If FALSE, items are resolved
+ only against this->table_list.
+ */
+ bool resolve_in_select_list;
+
+ /*
+ When FALSE we do not check columns right of resolving items, used to
+ prevent rights check on underlying tables of view
+ */
+ bool check_privileges;
+
+ Name_resolution_context()
+ :outer_context(0), table_list(0), select_lex(0),
+ error_processor_data(0),
+ check_privileges(TRUE)
+ {}
+
+ void init()
+ {
+ resolve_in_select_list= FALSE;
+ error_processor= &dummy_error_processor;
+ }
+
+ void resolve_in_table_list_only(TABLE_LIST *tables)
+ {
+ table_list= tables;
+ resolve_in_select_list= FALSE;
+ }
+
+ void process_error(THD *thd)
+ {
+ (*error_processor)(thd, error_processor_data);
+ }
+};
+
+
/*************************************************************************/
typedef bool (Item::*Item_processor)(byte *arg);
@@ -234,7 +324,8 @@ class Item {
Item(const Item &); /* Prevent use of these */
void operator=(Item &);
public:
- static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ { return (void*) sql_alloc((uint) size); }
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
/* Special for SP local variable assignment - reusing slots */
@@ -248,7 +339,8 @@ public:
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM,
SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER,
- PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM};
+ PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM,
+ VIEW_FIXER_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
@@ -302,7 +394,7 @@ public:
virtual void cleanup();
virtual void make_field(Send_field *field);
Field *make_string_field(TABLE *table);
- virtual bool fix_fields(THD *, struct st_table_list *, Item **);
+ virtual bool fix_fields(THD *, Item **);
/*
should be used in case where we are sure that we do not need
complete fix_fields() procedure.
@@ -554,6 +646,8 @@ public:
virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; }
virtual bool cleanup_processor(byte *arg);
virtual bool collect_item_field_processor(byte * arg) { return 0; }
+ virtual bool change_context_processor(byte *context) { return 0; }
+
virtual Item *equal_fields_propagator(byte * arg) { return this; }
virtual Item *set_no_const_sub(byte *arg) { return this; }
virtual Item *replace_equal_field(byte * arg) { return this; }
@@ -631,7 +725,7 @@ public:
Item **this_item_addr(THD *thd, Item **);
Item *this_const_item() const;
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void cleanup();
inline uint get_offset()
@@ -704,7 +798,9 @@ protected:
const char *orig_db_name;
const char *orig_table_name;
const char *orig_field_name;
+
public:
+ Name_resolution_context *context;
const char *db_name;
const char *table_name;
const char *field_name;
@@ -722,13 +818,16 @@ public:
*/
TABLE_LIST *cached_table;
st_select_lex *depended_from;
- Item_ident(const char *db_name_par,const char *table_name_par,
- const char *field_name_par);
+ Item_ident(Name_resolution_context *context_arg,
+ const char *db_name_arg, const char *table_name_arg,
+ const char *field_name_arg);
Item_ident(THD *thd, Item_ident *item);
const char *full_name() const;
void cleanup();
bool remove_dependence_processor(byte * arg);
void print(String *str);
+ virtual bool change_context_processor(byte *cntx)
+ { context= (Name_resolution_context *)cntx; return FALSE; }
};
class Item_equal;
@@ -750,12 +849,9 @@ public:
/* field need any privileges (for VIEW creation) */
bool any_privileges;
- Item_field(const char *db_par,const char *table_name_par,
- const char *field_name_par)
- :Item_ident(db_par,table_name_par,field_name_par),
- field(0), result_field(0), item_equal(0), no_const_subst(0),
- have_privileges(0), any_privileges(0)
- { collation.set(DERIVATION_IMPLICIT); }
+ Item_field(Name_resolution_context *context_arg,
+ const char *db_arg,const char *table_name_arg,
+ const char *field_name_arg);
/*
Constructor needed to process subselect with temporary tables (see Item)
*/
@@ -765,7 +861,7 @@ public:
and database names will live as long as Item_field (this is important
in prepared statements).
*/
- Item_field(THD *thd, Field *field);
+ Item_field(THD *thd, Name_resolution_context *context_arg, Field *field);
/*
If this constructor is used, fix_fields() won't work, because
db_name, table_name and column_name are unknown. It's necessary to call
@@ -785,7 +881,7 @@ public:
bool val_bool_result();
bool send(Protocol *protocol, String *str_arg);
void reset_field(Field *f);
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void make_field(Send_field *tmp_field);
int save_in_field(Field *field,bool no_conversions);
void save_org_in_field(Field *field);
@@ -946,7 +1042,7 @@ public:
bool get_time(TIME *tm);
bool get_date(TIME *tm, uint fuzzydate);
int save_in_field(Field *field, bool no_conversions);
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void set_null();
void set_int(longlong i, uint32 max_length_arg);
@@ -1317,9 +1413,11 @@ protected:
public:
Field *result_field; /* Save result here */
Item **ref;
- Item_ref(const char *db_par, const char *table_name_par,
- const char *field_name_par)
- :Item_ident(db_par, table_name_par, field_name_par), result_field(0), ref(0) {}
+ Item_ref(Name_resolution_context *context_arg,
+ const char *db_arg, const char *table_name_arg,
+ const char *field_name_arg)
+ :Item_ident(context_arg, db_arg, table_name_arg, field_name_arg),
+ result_field(0), ref(0) {}
/*
This constructor is used in two scenarios:
A) *item = NULL
@@ -1334,10 +1432,12 @@ public:
TODO we probably fix a superset of problems like in BUG#6658. Check this
with Bar, and if we have a more broader set of problems like this.
*/
- Item_ref(Item **item, const char *table_name_par, const char *field_name_par);
+ Item_ref(Name_resolution_context *context_arg, Item **item,
+ const char *table_name_arg, const char *field_name_arg);
/* Constructor need to process subselect with temporary tables (see Item) */
- Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {}
+ Item_ref(THD *thd, Item_ref *item)
+ :Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {}
enum Type type() const { return REF_ITEM; }
bool eq(const Item *item, bool binary_cmp) const
{ return ref && (*ref)->eq(item, binary_cmp); }
@@ -1354,8 +1454,8 @@ public:
my_decimal *val_decimal_result(my_decimal *);
bool val_bool_result();
bool send(Protocol *prot, String *tmp);
- void make_field(Send_field *field) { (*ref)->make_field(field); }
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ void make_field(Send_field *field);
+ bool fix_fields(THD *, Item **);
int save_in_field(Field *field, bool no_conversions);
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
@@ -1380,6 +1480,8 @@ public:
{ return (*ref)->walk(processor, arg); }
void print(String *str);
void cleanup();
+ Item_field *filed_for_view_update()
+ { return (*ref)->filed_for_view_update(); }
};
@@ -1390,9 +1492,10 @@ public:
class Item_direct_ref :public Item_ref
{
public:
- Item_direct_ref(Item **item, const char *table_name_par,
- const char *field_name_par)
- :Item_ref(item, table_name_par, field_name_par) {}
+ Item_direct_ref(Name_resolution_context *context_arg, Item **item,
+ const char *table_name_arg,
+ const char *field_name_arg)
+ :Item_ref(context_arg, item, table_name_arg, field_name_arg) {}
/* Constructor need to process subselect with temporary tables (see Item) */
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
@@ -1405,6 +1508,24 @@ public:
bool get_date(TIME *ltime,uint fuzzydate);
};
+/*
+ Class for view fields, the same as Item_direct_ref, but call fix_fields
+ of reference if it is not called yet
+*/
+class Item_direct_view_ref :public Item_direct_ref
+{
+public:
+ Item_direct_view_ref(Name_resolution_context *context_arg, Item **item,
+ const char *table_name_arg,
+ const char *field_name_arg)
+ :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg) {}
+ /* Constructor need to process subselect with temporary tables (see Item) */
+ Item_direct_view_ref(THD *thd, Item_direct_ref *item)
+ :Item_direct_ref(thd, item) {}
+
+ bool fix_fields(THD *, Item **);
+};
+
class Item_in_subselect;
@@ -1413,9 +1534,11 @@ class Item_ref_null_helper: public Item_ref
protected:
Item_in_subselect* owner;
public:
- Item_ref_null_helper(Item_in_subselect* master, Item **item,
- const char *table_name_par, const char *field_name_par):
- Item_ref(item, table_name_par, field_name_par), owner(master) {}
+ Item_ref_null_helper(Name_resolution_context *context_arg,
+ Item_in_subselect* master, Item **item,
+ const char *table_name_arg, const char *field_name_arg)
+ :Item_ref(context_arg, item, table_name_arg, field_name_arg),
+ owner(master) {}
double val_real();
longlong val_int();
String* val_str(String* s);
@@ -1429,10 +1552,11 @@ class Item_null_helper :public Item_ref_null_helper
{
Item *store;
public:
- Item_null_helper(Item_in_subselect* master, Item *item,
- const char *table_name_par, const char *field_name_par)
- :Item_ref_null_helper(master, (store= 0, &store), table_name_par,
- field_name_par),
+ Item_null_helper(Name_resolution_context *context_arg,
+ Item_in_subselect* master, Item *item,
+ const char *table_name_arg, const char *field_name_arg)
+ :Item_ref_null_helper(context_arg, master, (store= 0, &store),
+ table_name_arg, field_name_arg),
store(item)
{ ref= &store; }
void print(String *str);
@@ -1583,13 +1707,17 @@ class Item_default_value : public Item_field
{
public:
Item *arg;
- Item_default_value() :
- Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(NULL) {}
- Item_default_value(Item *a) :
- Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {}
+ Item_default_value(Name_resolution_context *context_arg)
+ :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
+ (const char *)NULL),
+ arg(NULL) {}
+ Item_default_value(Name_resolution_context *context_arg, Item *a)
+ :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
+ (const char *)NULL),
+ arg(a) {}
enum Type type() const { return DEFAULT_VALUE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void print(String *str);
int save_in_field(Field *field_arg, bool no_conversions);
table_map used_tables() const { return (table_map)0L; }
@@ -1618,10 +1746,12 @@ class Item_insert_value : public Item_field
{
public:
Item *arg;
- Item_insert_value(Item *a) :
- Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {}
+ Item_insert_value(Name_resolution_context *context_arg, Item *a)
+ :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
+ (const char *)NULL),
+ arg(a) {}
bool eq(const Item *item, bool binary_cmp) const;
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void print(String *str);
int save_in_field(Field *field_arg, bool no_conversions)
{
@@ -1683,15 +1813,17 @@ public:
/* Pointer to Table_trigger_list object for table of this trigger */
Table_triggers_list *triggers;
- Item_trigger_field(row_version_type row_ver_par,
- const char *field_name_par):
- Item_field((const char *)NULL, (const char *)NULL, field_name_par),
- row_version(row_ver_par), field_idx((uint)-1)
+ Item_trigger_field(Name_resolution_context *context_arg,
+ row_version_type row_ver_arg,
+ const char *field_name_arg)
+ :Item_field(context_arg,
+ (const char *)NULL, (const char *)NULL, field_name_arg),
+ row_version(row_ver_arg), field_idx((uint)-1)
{}
void setup_field(THD *thd, TABLE *table);
enum Type type() const { return TRIGGER_FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void print(String *str);
table_map used_tables() const { return (table_map)0L; }
void cleanup();
@@ -1880,7 +2012,7 @@ public:
Item_type_holder(THD*, Item*);
Item_result result_type() const;
- virtual enum_field_types field_type() const { return fld_type; };
+ enum_field_types field_type() const { return fld_type; };
enum Type type() const { return TYPE_HOLDER; }
double val_real();
longlong val_int();
@@ -1892,6 +2024,7 @@ public:
static enum_field_types get_real_type(Item *);
};
+
class st_select_lex;
void mark_select_range_as_dependent(THD *thd,
st_select_lex *last_select,
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 58a7f3316d7..5e08c9f9cb7 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -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;
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 7a22e76b217..16dab3c1b46 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -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; }
@@ -1033,7 +1033,7 @@ public:
void print(String *str);
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
- COND **conds);
+ COND **conds);
void top_level_item() { abort_on_null=1; }
void copy_andor_arguments(THD *thd, Item_cond *item);
bool walk(Item_processor processor, byte *arg);
@@ -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);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 1dbf28b67cb..b29074a9504 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -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;
diff --git a/sql/item_func.h b/sql/item_func.h
index e0f14ceac75..f6bc35e1617 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -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,9 +908,11 @@ 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_udf_func(udf_arg,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()
{
DBUG_ASSERT(fixed == 1);
@@ -932,9 +935,11 @@ 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_udf_func(udf_arg,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(); }
String *val_str(String *str);
@@ -946,9 +951,10 @@ 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) {}
+ :Item_udf_func(udf_arg, list) {}
longlong val_int();
double val_real();
my_decimal *val_decimal(my_decimal *);
@@ -961,9 +967,10 @@ 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) {}
+ :Item_udf_func(udf_arg, list) {}
String *val_str(String *);
double val_real()
{
@@ -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();
};
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 0c8baa332ca..9362518e6ef 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -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;
diff --git a/sql/item_row.h b/sql/item_row.h
index e6b23eebb49..6fbe7436b72 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -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; };
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 06239de1f99..40c4c501222 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -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;
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index c4beb3b08cb..b8696895047 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -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();
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index c7587686ecd..ad1c9977e5b 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -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
@@ -983,22 +985,23 @@ Item_in_subselect::single_value_transformer(JOIN *join,
comparison functions can't be changed during fix_fields()
we can assign select_lex->having here, and pass 0 as last
argument (reference) to fix_fields()
- */
- item= func->create(expr,
- new Item_null_helper(this, item,
- (char *)"<no matter>",
- (char *)"<result>"));
+ */
+ item= func->create(expr,
+ new Item_null_helper(&select_lex->context,
+ this, item,
+ (char *)"<no matter>",
+ (char *)"<result>"));
#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
if (!abort_on_null && left_expr->maybe_null)
item= new Item_cond_or(new Item_func_isnull(left_expr), item);
#endif
- select_lex->having= join->having= item;
+ select_lex->having= join->having= item;
select_lex->having_fix_field= 1;
/*
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];
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 84935429353..e05db4a00cc 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -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*);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 76f94801b49..d2f1016891b 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -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);
diff --git a/sql/item_sum.h b/sql/item_sum.h
index b9a90ee5de5..b02d18e9a55 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -98,7 +98,7 @@ public:
*/
virtual const char *func_name() const= 0;
virtual Item *result_item(Field *field)
- { return new Item_field(field);}
+ { return new Item_field(field); }
table_map used_tables() const { return ~(table_map) 0; } /* Not used */
bool const_item() const { return 0; }
bool is_null() { return null_value; }
@@ -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, List<Item> &list )
- :Item_sum( list ), udf(udf_arg)
+ 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,9 +691,10 @@ 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_udf_sum(udf_arg, list) {}
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
:Item_udf_sum(thd, item) {}
longlong val_int()
@@ -709,9 +713,10 @@ 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_udf_sum(udf_arg, list) {}
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
:Item_udf_sum(thd, item) {}
longlong val_int();
@@ -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,9 +772,10 @@ 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_udf_sum(udf_arg, list) {}
Item_sum_udf_decimal(THD *thd, Item_sum_udf_decimal *item)
:Item_udf_sum(thd, item) {}
String *val_str(String *);
@@ -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,15 +825,17 @@ 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; }
double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; }
void clear() {}
- bool add() { return 0; }
+ bool add() { return 0; }
void update_field() {}
};
@@ -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,8 +900,9 @@ 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,
- SQL_LIST *is_order,String *is_separator);
+ 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);
~Item_func_group_concat() {}
@@ -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; }
};
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 19386c15835..cac9613f1ad 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -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;
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index a6dd9f7da91..107d12e6da2 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -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();
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index e95aa35101e..c884c454dac 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -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;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 8f109f00c5f..5a612791cdd 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -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
diff --git a/sql/log_event.h b/sql/log_event.h
index b163a37e7cc..9f4681ae2c5 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -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);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 805af08b76a..ecd32ef35af 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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,
+ List_iterator<Item> *it, bool any_privileges);
+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);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 1c0de702e4e..fbf3332a37a 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -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));
}
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 7ae5130764f..747e7031530 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -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"
diff --git a/sql/sp.cc b/sql/sp.cc
index 4f89d6ba6da..f376c9b5ed2 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -676,14 +676,18 @@ db_show_routine_status(THD *thd, int type, const char *wild)
tables is not VIEW for sure => we can pass 0 as condition
*/
- setup_tables(thd, &tables, 0, &leaves, FALSE);
+ thd->lex->select_lex.context.resolve_in_table_list_only(&tables);
+ setup_tables(thd, &thd->lex->select_lex.context,
+ &tables, 0, &leaves, FALSE);
for (used_field= &used_fields[0];
used_field->field_name;
used_field++)
{
- Item_field *field= new Item_field("mysql", "proc",
+ Item_field *field= new Item_field(&thd->lex->select_lex.context,
+ "mysql", "proc",
used_field->field_name);
- if (!(used_field->field= find_field_in_tables(thd, field, &tables,
+ if (!field ||
+ !(used_field->field= find_field_in_tables(thd, field, &tables,
0, REPORT_ALL_ERRORS, 1)))
{
res= SP_INTERNAL_ERROR;
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index b2de24ca9b5..6be80568186 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -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;
diff --git a/sql/sp_head.h b/sql/sp_head.h
index aaef5a3d50e..08967bd9b4f 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -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)
{}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index d8bbb686ba2..7cc0c4fecf1 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2439,21 +2439,19 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
table_list->alias, name, item_name, (ulong) ref));
if (table_list->field_translation)
{
- uint num;
- if (table_list->schema_table_reformed)
+ Field_iterator_view field_it;
+ field_it.set(table_list);
+ DBUG_ASSERT(table_list->schema_table_reformed ||
+ (ref != 0 && table_list->view != 0));
+ for (; !field_it.end_of_fields(); field_it.next())
{
- num= thd->lex->current_select->item_list.elements;
- }
- 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 (!my_strcasecmp(system_charset_info, field_it.name(), name))
{
+ Item *item= field_it.create_item(thd);
+ if (!item)
+ {
+ DBUG_RETURN(0);
+ }
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);
- else
- *ref= trans[i].item;
- }
+ if (register_tree_change)
+ thd->change_item_tree(ref, 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,10 +3247,21 @@ 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))
- DBUG_RETURN(1);
+ 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);
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 20f48da9283..f5d45ca53f4 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -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
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 25fef8b0ad6..d83937098e2 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -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);
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index e1d701936cf..fc9d15e94c4 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -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
diff --git a/sql/sql_do.cc b/sql/sql_do.cc
index e37f3e86dda..08388dee516 100644
--- a/sql/sql_do.cc
+++ b/sql/sql_do.cc
@@ -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();
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index e905f93b860..e109600bcd0 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -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)
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 0cf8d1e93a7..3f151934e55 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -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;
@@ -718,15 +721,15 @@ bool mysqld_help(THD *thd, const char *mask)
Item *cond_cat_by_cat=
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)))
+ if (!(select= prepare_simple_select(thd, cond_topic_by_cat,
+ 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,
- tables[1].table,&error)))
+ 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,
used_fields[help_category_name].field,
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 2ce81d8815e..53c47706734 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -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)
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
- DBUG_RETURN(TRUE);
+ 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++)
@@ -1047,10 +1087,29 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry)
((*field)->flags & NO_DEFAULT_VALUE_FLAG) &&
((*field)->real_type() != FIELD_TYPE_ENUM))
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_NO_DEFAULT_FOR_FIELD,
- ER(ER_NO_DEFAULT_FOR_FIELD),
- (*field)->field_name);
+ 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));
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 08f0c3badf7..19578931d04 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -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
*/
+
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 5cf0b66598f..8fde37b0126 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -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);
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index cc25839bcc9..1ec209aba85 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -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);
}
diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc
index 831b15cf7ef..71e8fe4149f 100644
--- a/sql/sql_olap.cc
+++ b/sql/sql_olap.cc
@@ -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)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index d6a719e65f9..057d2f23ed3 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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);
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index c97cb037f15..0ffd01356b4 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -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,
- &mysql_insert_select_prepare_tester,
- OPTION_SETUP_TABLES_DONE);
+ 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;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index cf8d7b1b83c..195d34cbbe2 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -182,8 +182,8 @@ 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,
- List<Item> &all_fields,ORDER *new_order);
+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,
bool *all_order_by_fields_used);
@@ -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);
@@ -12910,8 +12913,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
thd reference to the context
expr expression to make replacement
group_list list of references to group by items
- changed out: returns 1 if item contains a replaced field item
-
+ changed out: returns 1 if item contains a replaced field item
+
DESCRIPTION
The function replaces occurrences of group by fields in expr
by ref objects for these fields unless they are under aggregate
@@ -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;
@@ -12953,8 +12957,9 @@ 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)))
+ Item *new_item;
+ 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;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 12025c82da6..72092db400d 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -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);
@@ -3495,7 +3510,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel,
ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx);
LEX_STRING db, table;
DBUG_ENTER("mysql_schema_select");
- /*
+ /*
We have to make non const db_name & table_name
because of lower_case_table_names
*/
@@ -3503,7 +3518,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel,
information_schema_name.length, 0);
make_lex_string(thd, &table, schema_table->table_name,
strlen(schema_table->table_name), 0);
- if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */
+ if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */
!sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
0, 0, TL_READ, (List<String> *) 0,
(List<String> *) 0))
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 95524a6dfbf..1272d38f729 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -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;
}
diff --git a/sql/sql_udf.h b/sql/sql_udf.h
index 4df3fe0949d..d588572a762 100644
--- a/sql/sql_udf.h
+++ b/sql/sql_udf.h
@@ -65,8 +65,8 @@ 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,
- uint arg_count,Item **args);
+ bool fix_fields(THD *thd, Item_result_field *item,
+ uint arg_count, Item **args);
void cleanup();
double val(my_bool *null_value)
{
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 6e307dda5be..c32c557a45e 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -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;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 6b9a8ddfcb6..ce4a7d6394e 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -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)
- DBUG_RETURN(1); /* purecov: inspected */
- }
+ 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);
/*
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 0b351407c13..b7b1335b107 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -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,13 +879,12 @@ 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),
- to do this we remember in end_unit the first subquery that has
+ to do this we remember in end_unit the first subquery that has
been already added.
-
+
NOTE: we do not support UNION here, so we take only one select
*/
SELECT_LEX_NODE *end_unit= table->select_lex->slave;
@@ -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
{
diff --git a/sql/sql_view.h b/sql/sql_view.h
index 4e6aaf7f477..3246dbae383 100644
--- a/sql/sql_view.h
+++ b/sql/sql_view.h
@@ -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);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 360bc421965..c06bf8f7bf0 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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;
diff --git a/sql/table.cc b/sql/table.cc
index 6677453969b..fec74c570f3 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -594,6 +594,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
goto err; /* purecov: inspected */
}
+ reg_field->field_index= i;
reg_field->comment=comment;
if (field_type == FIELD_TYPE_BIT && !f_bit_as_char(pack_flag))
{
@@ -1713,8 +1714,6 @@ void st_table_list::set_ancestor()
}
if (tbl->multitable_view)
multitable_view= TRUE;
- if (tbl->table)
- tbl->table->grant= grant;
} while ((tbl= tbl->next_local));
if (!multitable_view)
@@ -1727,68 +1726,18 @@ 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,163 +1745,114 @@ 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)
{
- 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");
-
- if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&res))
- return TRUE;
-
- for (tbl= ancestor; tbl; tbl= tbl->next_local)
+ if (!field_translation)
{
- if (tbl->ancestor &&
- tbl->setup_ancestor(thd, conds,
- (check_opt_type == VIEW_CHECK_CASCADED ?
- VIEW_CHECK_CASCADED :
- VIEW_CHECK_NONE)))
+ Field_translator *transl;
+ SELECT_LEX *select= &view->select_lex;
+ Item *item;
+ TABLE_LIST *tbl;
+ List_iterator_fast<Item> it(select->item_list);
+ uint field_count= 0;
+
+ if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&field_count))
+ {
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;
+ for (tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->ancestor &&
+ tbl->setup_ancestor(thd))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
- 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++)
+ /* Create view fields translation table */
+
+ if (!(transl=
+ (Field_translator*)(thd->current_arena->
+ alloc(select->item_list.elements *
+ sizeof(Field_translator)))))
{
- if (!transl->item->fixed &&
- transl->item->fix_fields(thd, ancestor, &transl->item))
- goto err;
+ DBUG_RETURN(TRUE);
}
- for (tbl= ancestor; tbl; tbl= tbl->next_local)
+
+ while ((item= it++))
{
- if (tbl->on_expr && !tbl->on_expr->fixed &&
- tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr))
- goto err;
+ transl[field_count].name= item->name;
+ transl[field_count++].item= item;
}
- 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();
+ field_translation= transl;
+ field_translation_end= transl + field_count;
+ /* TODO: use hash for big number of fields */
- /* WHERE/ON resolved => we can rename fields */
- for (transl= field_translation; transl < end; transl++)
+ /* full text function moving to current select */
+ if (view->select_lex.ftfunc_list->elements)
{
- transl->item->rename((char *)transl->name);
+ 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);
}
- goto ok;
}
+ DBUG_RETURN(FALSE);
+}
- /* Create view fields translation table */
- if (!(transl=
- (Field_translator*)(thd->current_arena->
- alloc(select->item_list.elements *
- sizeof(Field_translator)))))
- {
- res= TRUE;
- goto ok; // Restore thd
- }
+/*
+ Prepare where expression of view
- select_lex->no_wrap_view_item= 1;
+ 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
- /*
- Resolve all view items against ancestor table.
+ NOTE: have to be called befor CHECK OPTION preparation, because it makes
+ fix_fields for view WHERE clause
- 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;
- }
- field_translation= transl;
- /* TODO: sort this list? Use hash for big number of fields */
+ RETURN
+ FALSE - OK
+ TRUE - error
+*/
- for (tbl= ancestor; tbl; tbl= tbl->next_local)
+bool st_table_list::prep_where(THD *thd, Item **conds,
+ bool no_where_clause)
+{
+ DBUG_ENTER("st_table_list::prep_where");
+
+ for (TABLE_LIST *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 (tbl->view && tbl->prep_where(thd, conds, no_where_clause))
+ {
+ DBUG_RETURN(TRUE);
+ }
}
- if (where ||
- (check_opt_type == VIEW_CHECK_CASCADED &&
- ancestor->check_option))
- {
- Query_arena *arena= thd->current_arena, backup;
- TABLE_LIST *tbl= this;
- if (arena->is_conventional())
- arena= 0; // For easier test
-
- 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)
+ if (where)
+ {
+ if (!where->fixed && where->fix_fields(thd, &where))
{
- 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);
- }
+ 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);
- }
- }
+ *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);
}
- restore_want_privilege();
- /*
- fix_fields do not need tables, because new are only AND operation and we
- just need recollect statistics
- */
- if (check_option && !check_option->fixed &&
- check_option->fix_fields(thd, 0, &check_option))
- goto err;
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ 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)
- /* WHERE/ON resolved => we can rename fields */
+ RETURN
+ FALSE - OK
+ TRUE - error
+*/
+
+bool st_table_list::prep_check_option(THD *thd, uint8 check_opt_type)
+{
+ DBUG_ENTER("st_table_list::prep_check_option");
+
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
{
- Field_translator *end= field_translation + select->item_list.elements;
- for (transl= field_translation; transl < end; transl++)
+ /* 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)))
{
- transl->item->rename((char *)transl->name);
+ 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);
+ }
+
+ 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);
+}
+
- goto ok;
+/*
+ Hide errors which show view underlying table information
+
+ SYNOPSIS
+ st_table_list::hide_view_error()
+ thd thread handler
-err:
- res= TRUE;
+*/
+
+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
*****************************************************************************/
diff --git a/sql/table.h b/sql/table.h
index 8bc4e01852f..d0c998c4c10 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -314,9 +314,9 @@ typedef struct st_schema_table
#define JOIN_TYPE_LEFT 1
#define JOIN_TYPE_RIGHT 2
-#define VIEW_ALGORITHM_UNDEFINED 0
-#define VIEW_ALGORITHM_TMPTABLE 1
-#define VIEW_ALGORITHM_MERGE 2
+#define VIEW_ALGORITHM_UNDEFINED 0
+#define VIEW_ALGORITHM_TMPTABLE 1
+#define VIEW_ALGORITHM_MERGE 2
/* view WITH CHECK OPTION parameter options */
#define VIEW_CHECK_NONE 0
@@ -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; }
};