diff options
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 214 |
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 */ |