summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc214
1 files changed, 162 insertions, 52 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 7a908120774..e6c19657abe 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -554,10 +554,10 @@ void close_temporary_tables(THD *thd)
SYNOPSIS
find_table_in_list()
- table Pointer to table list
+ table Pointer to table list
offset Offset to which list in table structure to use
- db_name Data base name
- table_name Table name
+ db_name Data base name
+ table_name Table name
NOTES:
This is called by find_table_in_local_list() and
@@ -577,13 +577,14 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
{
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
{
- if ((!strcmp(table->db, db_name) &&
- !strcmp(table->real_name, table_name)) ||
- (table->view &&
- !my_strcasecmp(table_alias_charset,
- table->table->table_cache_key, db_name) &&
- !my_strcasecmp(table_alias_charset,
- table->table->table_name, table_name)))
+ if (table->table->tmp_table == NO_TMP_TABLE &&
+ ((!strcmp(table->db, db_name) &&
+ !strcmp(table->real_name, table_name)) ||
+ (table->view &&
+ !my_strcasecmp(table_alias_charset,
+ table->table->table_cache_key, db_name) &&
+ !my_strcasecmp(table_alias_charset,
+ table->table->table_name, table_name))))
break;
}
}
@@ -591,11 +592,12 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
{
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
{
- if ((!strcmp(table->db, db_name) &&
- !strcmp(table->real_name, table_name)) ||
- (table->view &&
- !strcmp(table->table->table_cache_key, db_name) &&
- !strcmp(table->table->table_name, table_name)))
+ if (table->table->tmp_table == NO_TMP_TABLE &&
+ ((!strcmp(table->db, db_name) &&
+ !strcmp(table->real_name, table_name)) ||
+ (table->view &&
+ !strcmp(table->table->table_cache_key, db_name) &&
+ !strcmp(table->table->table_name, table_name))))
break;
}
}
@@ -2036,15 +2038,18 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
bool allow_rowid,
uint *cached_field_index_ptr)
{
+ DBUG_ENTER("find_field_in_table");
+ DBUG_PRINT("enter", ("table:%s name: %s item name %s, ref 0x%lx",
+ table_list->alias, name, item_name, (ulong)ref));
Field *fld;
if (table_list->field_translation)
{
DBUG_ASSERT(ref != 0 && table_list->view != 0);
uint num= table_list->view->select_lex.item_list.elements;
- Item **trans= table_list->field_translation;
+ Field_translator *trans= table_list->field_translation;
for (uint i= 0; i < num; i ++)
{
- if (strcmp(trans[i]->name, name) == 0)
+ if (strcmp(trans[i].name, name) == 0)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_grants_view &&
@@ -2052,22 +2057,22 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
table_list->view_db.str,
table_list->view_name.str,
name, length))
- return WRONG_GRANT;
+ DBUG_RETURN(WRONG_GRANT);
#endif
if (thd->lex->current_select->no_wrap_view_item)
- *ref= trans[i];
+ *ref= trans[i].item;
else
{
- *ref= new Item_ref(trans + i, ref, table_list->view_name.str,
+ *ref= new Item_ref(&trans[i].item, ref, table_list->view_name.str,
item_name);
/* as far as Item_ref have defined refernce it do not need tables */
if (*ref)
(*ref)->fix_fields(thd, 0, ref);
}
- return (Field*) view_ref_found;
+ DBUG_RETURN((Field*) view_ref_found);
}
}
- return 0;
+ DBUG_RETURN(0);
}
fld= find_field_in_real_table(thd, table_list->table, name, length,
check_grants_table, allow_rowid,
@@ -2081,10 +2086,10 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
table_list->view_name.str,
name, length))
{
- return WRONG_GRANT;
+ DBUG_RETURN(WRONG_GRANT);
}
#endif
- return fld;
+ DBUG_RETURN(fld);
}
@@ -2213,17 +2218,33 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
field makes some prepared query ambiguous and so erronous, but we
accept this trade off.
*/
- found= find_field_in_real_table(thd, item->cached_table->table,
- name, length,
- test(item->cached_table->
- table->grant.want_privilege) &&
- check_privileges,
- 1, &(item->cached_field_index));
+ if (item->cached_table->table)
+ {
+ found= find_field_in_real_table(thd, item->cached_table->table,
+ name, length,
+ test(item->cached_table->
+ table->grant.want_privilege) &&
+ check_privileges,
+ 1, &(item->cached_field_index));
+ }
+ else
+ {
+ TABLE_LIST *table= item->cached_table;
+ Field *find= find_field_in_table(thd, table, name, item->name, length,
+ ref,
+ (table->table &&
+ test(table->table->grant.
+ want_privilege) &&
+ check_privileges),
+ (test(table->grant.want_privilege) &&
+ check_privileges),
+ 1, &(item->cached_field_index));
+ }
if (found)
{
if (found == WRONG_GRANT)
- return (Field*) 0;
+ return (Field*) 0;
return found;
}
}
@@ -2251,7 +2272,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
found_table=1;
Field *find= find_field_in_table(thd, tables, name, item->name,
length, ref,
- (test(tables->table->grant.
+ (tables->table &&
+ test(tables->table->grant.
want_privilege) &&
check_privileges),
(test(tables->grant.want_privilege) &&
@@ -2305,7 +2327,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
bool allow_rowid= tables && !tables->next_local; // Only one table
for (; tables ; tables= tables->next_local)
{
- if (!tables->table)
+ if (!tables->table && !tables->ancestor)
{
if (report_error)
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
@@ -2315,7 +2337,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
Field *field= find_field_in_table(thd, tables, name, item->name,
length, ref,
- (test(tables->table->grant.
+ (tables->table &&
+ test(tables->table->grant.
want_privilege) &&
check_privileges),
(test(tables->grant.want_privilege) &&
@@ -2628,7 +2651,6 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
if (!item->fixed && item->fix_fields(thd, tables, it.ref()) ||
(item= *(it.ref()))->check_cols(1))
{
- select_lex->no_wrap_view_item= 0;
DBUG_RETURN(-1); /* purecov: inspected */
}
if (ref)
@@ -2643,13 +2665,45 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
/*
+ make list of leaves of join table tree
+
+ SYNOPSIS
+ make_leaves_list()
+ list pointer to pointer on list first element
+ tables table list
+
+ RETURN pointer on pointer to next_leaf of last element
+*/
+
+TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
+{
+ for (TABLE_LIST *table= tables; table; table= table->next_local)
+ {
+ if (table->view && !table->table)
+ {
+ /* it is for multi table views only, check it */
+ DBUG_ASSERT(table->ancestor->next_local);
+ list= make_leaves_list(list, table->ancestor);
+ }
+ else
+ {
+ *list= table;
+ list= &table->next_leaf;
+ }
+ }
+ return list;
+}
+
+/*
prepare tables
SYNOPSIS
setup_tables()
- thd - thread handler
- tables - tables list
- conds - condition of current SELECT (can be changed by VIEW)
+ thd - thread handler
+ tables - tables list
+ conds - condition of current SELECT (can be changed by VIEW)
+ leaves - list of join table leaves list
+ refresh - it is onle refresh for subquery
RETURN
0 ok; In this case *map will includes the choosed index
@@ -2666,16 +2720,23 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
if tables do not contain VIEWs it is OK to pass 0 as conds
*/
-bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds)
+bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
+ TABLE_LIST **leaves, bool refresh)
{
DBUG_ENTER("setup_tables");
if (!tables || tables->setup_is_done)
DBUG_RETURN(0);
tables->setup_is_done= 1;
+
+ if (!(*leaves))
+ {
+ make_leaves_list(leaves, tables);
+ }
+
uint tablenr=0;
- for (TABLE_LIST *table_list= tables;
+ for (TABLE_LIST *table_list= *leaves;
table_list;
- table_list= table_list->next_local, tablenr++)
+ table_list= table_list->next_leaf, tablenr++)
{
TABLE *table= table_list->table;
setup_table_map(table, table_list, tablenr);
@@ -2697,14 +2758,22 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds)
table->keys_in_use_for_query.subtract(map);
}
table->used_keys.intersect(table->keys_in_use_for_query);
- if (table_list->ancestor && table_list->setup_ancestor(thd, conds))
- DBUG_RETURN(1);
}
if (tablenr > MAX_TABLES)
{
my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
DBUG_RETURN(1);
}
+ if (!refresh)
+ {
+ for (TABLE_LIST *table_list= tables;
+ table_list;
+ table_list= table_list->next_local)
+ {
+ if (table_list->ancestor && table_list->setup_ancestor(thd, conds))
+ DBUG_RETURN(1);
+ }
+ }
DBUG_RETURN(0);
}
@@ -2807,9 +2876,12 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
tables->alias) &&
(!db_name || !strcmp(tables->db,db_name))))
{
+ bool view;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Ensure that we have access right to all columns */
- if (!(table->grant.privilege & SELECT_ACL) && !any_privileges)
+ if (!((table && (table->grant.privilege & SELECT_ACL) ||
+ tables->view && (tables->grant.privilege & SELECT_ACL))) &&
+ !any_privileges)
{
if (tables->view)
{
@@ -2822,6 +2894,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
}
else
{
+ DBUG_ASSERT(table != 0);
table_iter.set(tables);
if (check_grant_all_columns(thd, SELECT_ACL, &table->grant,
table->table_cache_key, table->real_name,
@@ -2830,8 +2903,17 @@ 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;
- thd->used_tables|= table->map;
last= embedded= tables;
while ((embedding= embedded->embedding) &&
@@ -2858,9 +2940,15 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
natural_join_table= embedding;
}
if (tables->field_translation)
+ {
iterator= &view_iter;
+ view= 1;
+ }
else
+ {
iterator= &table_iter;
+ view= 0;
+ }
iterator->set(tables);
for (; !iterator->end_of_fields(); iterator->next())
@@ -2880,6 +2968,11 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
(void) it->replace(item); // Replace '*'
else
it->after(item);
+ if (view && !thd->lex->current_select->no_wrap_view_item)
+ {
+ item= new Item_ref(it->ref(), NULL, tables->view_name.str,
+ field_name);
+ }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (any_privileges)
{
@@ -2945,8 +3038,12 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
}
}
- /* All fields are used */
- table->used_fields=table->fields;
+ /*
+ All fields are used in case if usual tables (in case of view used
+ fields merked in setu_tables during fix_fields of view columns
+ */
+ if (table)
+ table->used_fields=table->fields;
}
}
if (found)
@@ -2964,10 +3061,16 @@ err:
/*
-** Fix all conditions and outer join expressions
+ Fix all conditions and outer join expressions
+
+ 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,COND **conds)
+int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
{
table_map not_null_tables= 0;
SELECT_LEX *select_lex= thd->lex->current_select;
@@ -2991,7 +3094,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
}
/* Check if we are using outer joins */
- for (TABLE_LIST *table= tables; table; table= table->next_local)
+ for (TABLE_LIST *table= leaves; table; table= table->next_leaf)
{
TABLE_LIST *embedded;
TABLE_LIST *embedding= table;
@@ -3055,8 +3158,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
Field_iterator_view view_iter;
Field_iterator *iterator;
Field *t1_field, *t2_field;
- Item *item_t2;
- Item_cond_and *cond_and=new Item_cond_and();
+ Item *item_t2= 0;
+ Item_cond_and *cond_and= new Item_cond_and();
if (!cond_and) // If not out of memory
DBUG_RETURN(1);
@@ -3092,6 +3195,13 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
t2_field->query_id= thd->query_id;
t2->used_keys.intersect(t2_field->part_of_key);
}
+ else
+ {
+ DBUG_ASSERT(t2_field == view_ref_found &&
+ item_t2->type() == Item::REF_ITEM);
+ /* remove hooking to stack variable */
+ ((Item_ref*) item_t2)->hook_ptr= 0;
+ }
if ((t1_field= iterator->field()))
{
/* Mark field used for table cache */