diff options
Diffstat (limited to 'sql/table.cc')
-rw-r--r-- | sql/table.cc | 237 |
1 files changed, 209 insertions, 28 deletions
diff --git a/sql/table.cc b/sql/table.cc index a9699fe0228..2e794e1aee8 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1485,10 +1485,65 @@ void st_table_list::calc_md5(char *buffer) void st_table_list::set_ancestor() { - if (ancestor->ancestor) - ancestor->set_ancestor(); - table= ancestor->table; - ancestor->table->grant= grant; + /* process all tables of view */ + for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + { + if (tbl->ancestor) + ancestor->set_ancestor(); + tbl->table->grant= grant; + } + /* if view contain only one table, substitute TABLE of it */ + if (!ancestor->next_local) + table= ancestor->table; +} + + +/* + 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 + { + DBUG_ASSERT(tbl->view && tbl->ancestor && + tbl->ancestor->next_local); + 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 + { + DBUG_ASSERT(tbl->view && tbl->ancestor && + tbl->ancestor->next_local); + tbl->restore_want_privilege(); + } + } } @@ -1513,10 +1568,11 @@ void st_table_list::set_ancestor() bool st_table_list::setup_ancestor(THD *thd, Item **conds) { - Item **transl; + Field_translator *transl; SELECT_LEX *select= &view->select_lex; SELECT_LEX *current_select_save= thd->lex->current_select; Item *item; + TABLE_LIST *tbl; List_iterator_fast<Item> it(select->item_list); uint i= 0; bool save_set_query_id= thd->set_query_id; @@ -1524,35 +1580,53 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) bool save_allow_sum_func= thd->allow_sum_func; DBUG_ENTER("st_table_list::setup_ancestor"); - if (ancestor->ancestor && - ancestor->setup_ancestor(thd, conds)) - DBUG_RETURN(1); + for (tbl= ancestor; tbl; tbl= tbl->next_local) + { + if (tbl->ancestor && tbl->setup_ancestor(thd, conds)) + DBUG_RETURN(1); + } if (field_translation) { /* prevent look up in SELECTs tree */ thd->lex->current_select= &thd->lex->select_lex; + thd->lex->select_lex.no_wrap_view_item= 1; thd->set_query_id= 1; /* this view was prepared already on previous PS/SP execution */ - Item **end= field_translation + select->item_list.elements; - for (Item **item= field_translation; item < end; item++) + 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++) { - /* TODO: fix for several tables in VIEW */ - uint want_privilege= ancestor->table->grant.want_privilege; - /* real rights will be checked in VIEW field */ - ancestor->table->grant.want_privilege= 0; - /* aggregate function are allowed */ - thd->allow_sum_func= 1; - if (!(*item)->fixed && (*item)->fix_fields(thd, ancestor, item)) + if (!transl->item->fixed && + transl->item->fix_fields(thd, ancestor, &transl->item)) goto err; - ancestor->table->grant.want_privilege= want_privilege; + } + for (tbl= ancestor; tbl; tbl= tbl->next_local) + { + if (tbl->on_expr && !tbl->on_expr->fixed && + tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr)) + goto err; + } + if (where && !where->fixed && where->fix_fields(thd, ancestor, &where)) + goto err; + restore_want_privilege(); + + /* WHERE/ON resolved => we can rename fields */ + for (transl= field_translation; transl < end; transl++) + { + transl->item->rename((char *)transl->name); } goto ok; } /* view fields translation table */ if (!(transl= - (Item**)(thd->current_arena->alloc(select->item_list.elements * sizeof(Item*))))) + (Field_translator*)(thd->current_arena-> + alloc(select->item_list.elements * + sizeof(Field_translator))))) { DBUG_RETURN(1); } @@ -1568,22 +1642,29 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) 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++)) { - /* TODO: fix for several tables in VIEW */ - uint want_privilege= ancestor->table->grant.want_privilege; - /* real rights will be checked in VIEW field */ - ancestor->table->grant.want_privilege= 0; - /* aggregate function are allowed */ - thd->allow_sum_func= 1; + /* save original name of view column */ + char *name= item->name; if (!item->fixed && item->fix_fields(thd, ancestor, &item)) goto err; - ancestor->table->grant.want_privilege= want_privilege; - transl[i++]= item; + /* set new item get in fix fields and original column name */ + transl[i].name= name; + transl[i++].item= item; } field_translation= transl; /* TODO: sort this list? Use hash for big number of fields */ + for (tbl= ancestor; tbl; tbl= tbl->next_local) + { + if (tbl->on_expr && !tbl->on_expr->fixed && + tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr)) + goto err; + } if (where) { Item_arena *arena= thd->current_arena, backup; @@ -1653,6 +1734,8 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) 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 @@ -1661,6 +1744,15 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) check_option->fix_fields(thd, 0, &check_option)) goto err; + /* WHERE/ON resolved => we can rename fields */ + { + Field_translator *end= field_translation + select->item_list.elements; + for (transl= field_translation; transl < end; transl++) + { + transl->item->rename((char *)transl->name); + } + } + /* full text function moving to current select */ if (view->select_lex.ftfunc_list->elements) { @@ -1727,6 +1819,95 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure) } +/* + Find table in underlaying tables by mask and check that only this + table sbelong to given mask + + SYNOPSIS + st_table_list::check_single_table() + table reference on variable where to store found table + (should be 0 on call, to find table, or point to table for + unique test) + map bit mask of tables + + RETURN + 0 table not found or found only one + 1 found several tables +*/ + +bool st_table_list::check_single_table(st_table_list **table, table_map map) +{ + for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + { + if (tbl->table) + { + if (tbl->table->map & map) + { + if (*table) + return 1; + else + *table= tbl; + } + } + else + if (tbl->check_single_table(table, map)) + return 1; + } +} + + +/* + Set insert_values buffer + + SYNOPSIS + set_insert_values() + mem_root memory pool for allocating + + RETURN + FALSE - OK + TRUE - out of memory +*/ + +bool st_table_list::set_insert_values(MEM_ROOT *mem_root) +{ + if (table) + { + if (!table->insert_values && + !(table->insert_values= (byte *)alloc_root(mem_root, + table->rec_buff_length))) + return TRUE; + } + else + { + DBUG_ASSERT(view && ancestor && ancestor->next_local); + for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + if (tbl->set_insert_values(mem_root)) + return TRUE; + } + return FALSE; +} + + +/* + clear insert_values reference + + SYNOPSIS + clear_insert_values() +*/ + +void st_table_list::clear_insert_values() +{ + if (table) + table->insert_values= 0; + else + { + DBUG_ASSERT(view && ancestor && ancestor->next_local); + for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + tbl->clear_insert_values(); + } +} + + void Field_iterator_view::set(TABLE_LIST *table) { ptr= table->field_translation; @@ -1748,7 +1929,7 @@ Item *Field_iterator_table::item(THD *thd) const char *Field_iterator_view::name() { - return (*ptr)->name; + return ptr->name; } |