diff options
author | bell@sanja.is.com.ua <> | 2004-11-21 19:33:49 +0200 |
---|---|---|
committer | bell@sanja.is.com.ua <> | 2004-11-21 19:33:49 +0200 |
commit | 21eb2e2eae5387aa01f8e600180a194f1f2d6a37 (patch) | |
tree | b25b7816dbd02cb9f9d6b4b3265bab0d91d3f02e /sql | |
parent | 0ef0b030a54e7e1f233cbd735f18f64af618d819 (diff) | |
download | mariadb-git-21eb2e2eae5387aa01f8e600180a194f1f2d6a37.tar.gz |
post merge
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 5 | ||||
-rw-r--r-- | sql/mysql_priv.h | 6 | ||||
-rw-r--r-- | sql/sql_acl.cc | 2 | ||||
-rw-r--r-- | sql/sql_base.cc | 34 | ||||
-rw-r--r-- | sql/sql_insert.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 1 | ||||
-rw-r--r-- | sql/sql_load.cc | 7 | ||||
-rw-r--r-- | sql/sql_parse.cc | 8 | ||||
-rw-r--r-- | sql/sql_update.cc | 68 | ||||
-rw-r--r-- | sql/table.cc | 18 |
11 files changed, 97 insertions, 56 deletions
diff --git a/sql/item.cc b/sql/item.cc index 41203e3365c..6613d758840 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2670,11 +2670,6 @@ void Item_ref::cleanup() DBUG_ENTER("Item_ref::cleanup"); Item_ident::cleanup(); result_field= 0; - DBUG_PRINT("info", ("hook: 0x%lx(0x%lx) original item: 0x%lx", - (ulong)hook_ptr, (ulong)(hook_ptr?*hook_ptr:0), - (ulong)orig_item)); - if (hook_ptr) - *hook_ptr= orig_item; DBUG_VOID_RETURN; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 8dfc976071d..b43889b91da 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -619,8 +619,7 @@ int mysql_multi_update(THD *thd, TABLE_LIST *table_list, List<Item> *fields, List<Item> *values, COND *conds, ulong options, enum enum_duplicates handle_duplicates, - SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex, - bool converted); + SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex); int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table, List<Item> &fields, List_item *values, List<Item> &update_fields, @@ -661,7 +660,8 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, uint length, Item **ref, bool check_grants_table, bool check_grants_view, bool allow_rowid, - uint *cached_field_index_ptr); + uint *cached_field_index_ptr, + bool register_tree_change); Field * find_field_in_real_table(THD *thd, TABLE *table, const char *name, uint length, bool check_grants, bool allow_rowid, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 3e3642dd0bd..f478da9076d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2360,7 +2360,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!find_field_in_table(thd, table_list, column->column.ptr(), column->column.ptr(), column->column.length(), 0, 0, 0, 0, - &unused_field_idx)) + &unused_field_idx, FALSE)) { my_error(ER_BAD_FIELD_ERROR, MYF(0), column->column.c_ptr(), table_list->alias); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5146a140479..a15d9e4fe11 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2069,6 +2069,8 @@ const Field *view_ref_found= (Field*) 0x2; allow_rowid do allow finding of "_rowid" field? cached_field_index_ptr cached position in field list (used to speedup prepared tables field finding) + register_tree_change TRUE if ref is not stack variable and we + need register changes in item tree RETURN 0 field is not found @@ -2082,7 +2084,8 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, uint length, Item **ref, bool check_grants_table, bool check_grants_view, bool allow_rowid, - uint *cached_field_index_ptr) + uint *cached_field_index_ptr, + bool register_tree_change) { DBUG_ENTER("find_field_in_table"); DBUG_PRINT("enter", ("table:%s name: %s item name %s, ref 0x%lx", @@ -2109,10 +2112,11 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, *ref= trans[i].item; else { - Item_ref *item_ref= new Item_ref(trans[i].item, table_list->view_name.str, + 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 (item_ref) + if (register_tree_change && item_ref) { thd->change_item_tree(ref, item_ref); (*ref)->fix_fields(thd, 0, ref); @@ -2288,7 +2292,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, check_privileges), (test(table->grant.want_privilege) && check_privileges), - 1, &(item->cached_field_index)); + 1, &(item->cached_field_index), + TRUE); } if (found) { @@ -2327,7 +2332,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, check_privileges), (test(tables->grant.want_privilege) && check_privileges), - 1, &(item->cached_field_index)); + 1, &(item->cached_field_index), + TRUE); if (find) { item->cached_table= tables; @@ -2392,7 +2398,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, check_privileges), (test(tables->grant.want_privilege) && check_privileges), - allow_rowid, &(item->cached_field_index)); + allow_rowid, + &(item->cached_field_index), + TRUE); if (field) { if (field == WRONG_GRANT) @@ -3028,7 +3036,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, !find_field_in_table(thd, natural_join_table, field_name, field_name, strlen(field_name), ¬_used_item, 0, 0, 0, - ¬_used_field_index)) + ¬_used_field_index, TRUE)) { Item *item= iterator->item(thd); if (!found++) @@ -3037,7 +3045,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, it->after(item); if (view && !thd->lex->current_select->no_wrap_view_item) { - item= new Item_ref(it->ref(), NULL, tables->view_name.str, + item= new Item_ref(it->ref(), tables->view_name.str, field_name); } #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -3252,7 +3260,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) t1_field_name, strlen(t1_field_name), &item_t2, 0, 0, 0, - ¬_used_field_index))) + ¬_used_field_index, + FALSE))) { if (t2_field != view_ref_found) { @@ -3262,13 +3271,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, 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 */ diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index dfd9fd45b70..007898cd8cf 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1781,7 +1781,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) query */ if (!(thd->lex->current_select->options & OPTION_BUFFER_RESULT) && - unique_table(table_list, table_list->next_independent())) + unique_table(table_list, table_list->next_global)) { /* Using same table for INSERT and SELECT */ thd->lex->current_select->options|= OPTION_BUFFER_RESULT; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 97c5058cd61..72a955e6601 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -150,7 +150,7 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->found_colon= 0; lex->safe_to_cache_query= 1; lex->time_zone_tables_used= 0; - lex->proc_table= lex->query_tables= 0; + lex->leaf_tables_insert= lex->proc_table= lex->query_tables= 0; lex->query_tables_last= &lex->query_tables; lex->variables_used= 0; lex->select_lex.parent_lex= lex; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 7d72d8ec5e1..6853bab019f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -710,6 +710,7 @@ typedef struct st_lex uint grant, grant_tot_col, which_columns; uint fk_delete_opt, fk_update_opt, fk_match_option; uint slave_thd_opt; + uint table_count; /* used when usual update transformed in multiupdate */ uint8 describe; uint8 derived_tables; uint8 create_view_algorithm; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 40529103f00..c3a7f6ad230 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -121,9 +121,12 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table_list->lock_type= lock_type; if ((res= open_and_lock_tables(thd, table_list))) DBUG_RETURN(res); - if (setup_tables(thd, table_list, &unused_conds)) + if (setup_tables(thd, table_list, &unused_conds, + &thd->lex->select_lex.leaf_tables, 0)) DBUG_RETURN(-1); - if (!table_list->updatable || check_key_in_view(thd, table_list)) + if (!table_list->table || // do not suport join view + !table_list->updatable || // and derived tables + check_key_in_view(thd, table_list)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD"); DBUG_RETURN(-1); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 891ff5b8c7e..0f31fbdb077 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2801,7 +2801,6 @@ unsent_create_error: break; case SQLCOM_UPDATE_MULTI: { - bool converted= 0; DBUG_ASSERT(first_table == all_tables && first_table != 0); if (res != 2) { @@ -2809,17 +2808,14 @@ unsent_create_error: break; } else - { res= 0; - converted= 1; - } + res= mysql_multi_update(thd, all_tables, &select_lex->item_list, &lex->value_list, select_lex->where, select_lex->options, - lex->duplicates, unit, select_lex, - converted); + lex->duplicates, unit, select_lex); break; } case SQLCOM_REPLACE: diff --git a/sql/sql_update.cc b/sql/sql_update.cc index b60c0d95658..5f84c7435ad 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -127,6 +127,7 @@ int mysql_update(THD *thd, #ifndef NO_EMBEDDED_ACCESS_CHECKS uint want_privilege; #endif + uint table_count= 0; ulong query_id=thd->query_id, timestamp_query_id; ha_rows updated, found; key_map old_used_keys; @@ -138,17 +139,26 @@ int mysql_update(THD *thd, LINT_INIT(used_index); LINT_INIT(timestamp_query_id); - if ((error= open_and_lock_tables(thd, table_list))) - DBUG_RETURN(error); + if (open_tables(thd, table_list, &table_count)) + DBUG_RETURN(thd->net.report_error ? -1 : 1); if (table_list->table == 0) { DBUG_ASSERT(table_list->view && table_list->ancestor && table_list->ancestor->next_local); DBUG_PRINT("info", ("Switch to multi-update")); + /* pass counter value */ + thd->lex->table_count= table_count; /* convert to multiupdate */ return 2; } + + if (lock_tables(thd, table_list, table_count) || + mysql_handle_derived(thd->lex, &mysql_derived_prepare) || + (thd->fill_derived_tables() && + mysql_handle_derived(thd->lex, &mysql_derived_filling))) + DBUG_RETURN(thd->net.report_error ? -1 : 1); + thd->proc_info="init"; table= table_list->table; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); @@ -614,14 +624,25 @@ int mysql_multi_update_prepare(THD *thd) table_map tables_for_update; int res; bool update_view= 0; - uint table_count; + /* + if this multi-update was converted from usual update, here is table + counter else junk will be assigned here, but then replaced with real + count in open_tables() + */ + uint table_count= lex->table_count; const bool using_lock_tables= thd->locked_tables != 0; + bool original_multiupdate= (thd->lex->sql_command == SQLCOM_UPDATE_MULTI); DBUG_ENTER("mysql_multi_update_prepare"); /* open tables and create derived ones, but do not lock and fill them */ - if (open_tables(thd, table_list, & table_count) || + if ((original_multiupdate && open_tables(thd, table_list, & table_count)) || mysql_handle_derived(lex, &mysql_derived_prepare)) DBUG_RETURN(thd->net.report_error ? -1 : 1); + /* + setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables() + second time, but this call will do nothing (there are check for second + call in setup_tables()). + */ if (setup_tables(thd, table_list, &lex->select_lex.where, &lex->select_lex.leaf_tables, 0)) DBUG_RETURN(-1); @@ -644,11 +665,6 @@ int mysql_multi_update_prepare(THD *thd) (UPDATE_ACL & ~table->grant.privilege); } - /* - setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables() - second time, but this call will do nothing (there are check for second - call in setup_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, @@ -675,7 +691,16 @@ int mysql_multi_update_prepare(THD *thd) Setup timestamp handling and locking mode */ for (tl= leaves; tl; tl= tl->next_leaf) - + { + TABLE *table= tl->table; + TABLE_LIST *tlist= tl->belong_to_view?tl->belong_to_view:tl; + + /* We only need SELECT privilege for columns in the values list */ + tlist->grant.want_privilege= table->grant.want_privilege= + (SELECT_ACL & ~table->grant.privilege); + /* Only set timestamp column if this is not modified */ + if (table->timestamp_field && + table->timestamp_field->query_id == thd->query_id) table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; /* if table will be updated then check that it is unique */ @@ -711,6 +736,23 @@ int mysql_multi_update_prepare(THD *thd) tl->table->reginfo.lock_type= tl->lock_type; } + /* check single table update for view compound from several tables */ + for (tl= table_list; tl; tl= tl->next_local) + { + if (tl->table == 0) + { + DBUG_ASSERT(tl->view && + tl->ancestor && tl->ancestor->next_local); + TABLE_LIST *for_update= 0; + if (tl->check_single_table(&for_update, tables_for_update)) + { + my_error(ER_VIEW_MULTIUPDATE, MYF(0), + tl->view_db.str, tl->view_name.str); + DBUG_RETURN(-1); + } + } + } + opened_tables= thd->status_var.opened_tables; /* now lock and fill tables */ if (lock_tables(thd, table_list, table_count)) @@ -740,7 +782,8 @@ int mysql_multi_update_prepare(THD *thd) /* undone setup_tables() */ table_list->setup_is_done= 0; - if (setup_tables(thd, table_list, &lex->select_lex.where) || + if (setup_tables(thd, table_list, &lex->select_lex.where, + &lex->select_lex.leaf_tables, 0) || (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, @@ -765,8 +808,7 @@ int mysql_multi_update(THD *thd, COND *conds, ulong options, enum enum_duplicates handle_duplicates, - SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex, - bool converted) + SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex) { int res= 0; multi_update *result; diff --git a/sql/table.cc b/sql/table.cc index 74e35e0f2d7..71d74c3eafc 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1841,9 +1841,10 @@ void st_table_list::cleanup_items() if (!field_translation) return; - Item **end= field_translation + view->select_lex.item_list.elements; - for (Item **item= field_translation; item < end; item++) - (*item)->walk(&Item::cleanup_processor, 0); + Field_translator *end= (field_translation + + view->select_lex.item_list.elements); + for (Field_translator *transl= field_translation; transl < end; transl++) + transl->item->walk(&Item::cleanup_processor, 0); } @@ -1883,7 +1884,7 @@ 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 + table belong to given mask SYNOPSIS st_table_list::check_single_table() @@ -1893,8 +1894,8 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure) map bit mask of tables RETURN - 0 table not found or found only one - 1 found several tables + FALSE table not found or found only one + TRUE found several tables */ bool st_table_list::check_single_table(st_table_list **table, table_map map) @@ -1906,15 +1907,16 @@ bool st_table_list::check_single_table(st_table_list **table, table_map map) if (tbl->table->map & map) { if (*table) - return 1; + return TRUE; else *table= tbl; } } else if (tbl->check_single_table(table, map)) - return 1; + return TRUE; } + return FALSE; } |