From 98ff15531f2c6d4d84c7ed5bac563182625c3eb4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jun 2005 11:15:29 -0400 Subject: BUG#10442 Fix replication slave crash when a query with multiupdate and subselects is used. sql/sql_parse.cc: BUG#10442 Fix crash on replication slave by making sure that table list is filled out before it is used. --- sql/sql_parse.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sql') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c107203b548..81fcc30dd08 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1943,6 +1943,14 @@ mysql_execute_command(THD *thd) if (tables || &lex->select_lex != lex->all_selects_list) mysql_reset_errors(thd); + /* When subselects or time_zone info is used in a query + * we create a new TABLE_LIST containing all referenced tables + * and set local variable 'tables' to point to this list. */ + if ((&lex->select_lex != lex->all_selects_list || + lex->time_zone_tables_used) && + lex->unit.create_total_list(thd, lex, &tables)) + DBUG_VOID_RETURN; + #ifdef HAVE_REPLICATION if (thd->slave_thread) { @@ -1993,14 +2001,6 @@ mysql_execute_command(THD *thd) } #endif /* !HAVE_REPLICATION */ - /* When subselects or time_zone info is used in a query - * we create a new TABLE_LIST containing all referenced tables - * and set local variable 'tables' to point to this list. */ - if ((&lex->select_lex != lex->all_selects_list || - lex->time_zone_tables_used) && - lex->unit.create_total_list(thd, lex, &tables)) - DBUG_VOID_RETURN; - /* When option readonly is set deny operations which change tables. Except for the replication thread and the 'super' users. -- cgit v1.2.1 From 7b1ec027325870da62d0a6b36eeb04b03bd0f576 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 04:24:21 -0700 Subject: group_by.result, group_by.test: Added a test case for bug #11295. item_buff.cc: Fixed bug #11295. This a correction for the patch of bug #11088 that takes into account a possible NULL values of the BLOB column. sql/item_buff.cc: Fixed bug #11295. This a correction for the patch of bug #11088 that takes into account a possible NULL values of the BLOB column. mysql-test/t/group_by.test: Added a test case for bug #11295. mysql-test/r/group_by.result: Added a test case for bug #11295. --- sql/item_buff.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/item_buff.cc b/sql/item_buff.cc index f5e77862e1d..8298ce2cfb7 100644 --- a/sql/item_buff.cc +++ b/sql/item_buff.cc @@ -51,8 +51,8 @@ bool Item_str_buff::cmp(void) String *res; bool tmp; - res=item->val_str(&tmp_value); - res->length(min(res->length(), value.alloced_length())); + if ((res=item->val_str(&tmp_value))) + res->length(min(res->length(), value.alloced_length())); if (null_value != item->null_value) { if ((null_value= item->null_value)) -- cgit v1.2.1 From 8e45c0572bf6503b1fd126428aac203c90c949b7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 22:24:58 +0400 Subject: Fix bug #10886 - INSERT ... SELECT ... ON DUPLICATE KEY UPDATE produces bad results Temporary field wasn't restored to default values after ON DUPLICATE KEY UPDATE event, which results in wrong data being inserted in new record. sql/sql_insert.cc: Fix bug #10886 - INSERT ... SELECT ... ON DUPLICATE KEY UPDATE produces bad results mysql-test/t/insert_select.test: Test case for bug #10886 - INSERT ... SELECT ... ON DUPLICATE KEY UPDATE produces bad results mysql-test/r/insert_select.result: Test case for bug #10886 - INSERT ... SELECT ... ON DUPLICATE KEY UPDATE produces bad results --- sql/sql_insert.cc | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 718e6b00ddc..1b3c58032f2 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1625,11 +1625,22 @@ bool select_insert::send_data(List &values) store_values(values); error=thd->net.report_error || write_record(table,&info); thd->count_cuted_fields= CHECK_FIELD_IGNORE; - if (!error && table->next_number_field) // Clear for next record + + if (!error) { - table->next_number_field->reset(); - if (! last_insert_id && thd->insert_id_used) - last_insert_id=thd->insert_id(); + /* + Restore fields of the record since it is possible that they were + changed by ON DUPLICATE KEY UPDATE clause. + */ + if (info.handle_duplicates == DUP_UPDATE) + restore_record(table, default_values); + + if (table->next_number_field) // Clear for next record + { + table->next_number_field->reset(); + if (! last_insert_id && thd->insert_id_used) + last_insert_id=thd->insert_id(); + } } DBUG_RETURN(error); } -- cgit v1.2.1 From d785fc60ab902842bf68bfb827120b8015700a98 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 15:40:58 -0400 Subject: BUG#10442 Minor changes from code review mysql-test/r/rpl_multi_update3.result: Changes from code review mysql-test/t/rpl_multi_update3.test: Changes from code review sql/sql_parse.cc: Changes from code review --- sql/sql_parse.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 81fcc30dd08..4d339fc6a0e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1943,9 +1943,11 @@ mysql_execute_command(THD *thd) if (tables || &lex->select_lex != lex->all_selects_list) mysql_reset_errors(thd); - /* When subselects or time_zone info is used in a query - * we create a new TABLE_LIST containing all referenced tables - * and set local variable 'tables' to point to this list. */ + /* + When subselects or time_zone info is used in a query + we create a new TABLE_LIST containing all referenced tables + and set local variable 'tables' to point to this list. + */ if ((&lex->select_lex != lex->all_selects_list || lex->time_zone_tables_used) && lex->unit.create_total_list(thd, lex, &tables)) -- cgit v1.2.1 From a6c7fb455ae6114ae53be58c49d4ef7dbdcd5e3e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 07:18:42 +0400 Subject: Fix bug #9728 decreased functionality in "on duplicate key update" Remove changes made by bug fix #8147. They strips list of insert_table_list to only insert table, which results in error reported in bug #9728. Added flag to Item to resolve ambigous fields reported in bug #8147. sql/item.h: Fix bug#9728 decreased functionality in "on duplicate key update". sql/item.cc: Fix bug#9728 decreased functionality in "on duplicate key update" sql/sql_parse.cc: Fix bug#9728 decreased functionality in "on duplicate key update" sql/sql_base.cc: Fix bug#9728 decreased functionality in "on duplicate key update". sql/sql_yacc.yy: Fix bug#9728 decreased functionality in "on duplicate key update" mysql-test/t/insert_select.test: Test case for bug#9728 Decreased functionality in "on duplicate key update". mysql-test/r/insert_select.result: Test case for bug#9728 Decreased functionality in "on duplicate key update". --- sql/item.cc | 4 +++- sql/item.h | 11 +++++++++++ sql/sql_base.cc | 7 +++++-- sql/sql_parse.cc | 9 +++------ sql/sql_yacc.yy | 15 +++++++++++++++ 5 files changed, 37 insertions(+), 9 deletions(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index c96794ff482..9c5bf499d11 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -65,6 +65,7 @@ Item::Item(): place == IN_HAVING) thd->lex->current_select->select_n_having_items++; } + item_flags= 0; } /* @@ -83,7 +84,8 @@ Item::Item(THD *thd, Item *item): unsigned_flag(item->unsigned_flag), with_sum_func(item->with_sum_func), fixed(item->fixed), - collation(item->collation) + collation(item->collation), + item_flags(item->item_flags) { next= thd->free_list; // Put in free list thd->free_list= this; diff --git a/sql/item.h b/sql/item.h index 8de2adeb730..d9a40cbdfb6 100644 --- a/sql/item.h +++ b/sql/item.h @@ -107,6 +107,11 @@ public: typedef bool (Item::*Item_processor)(byte *arg); +/* + See comments for sql_yacc.yy: insert_update_elem rule + */ +#define MY_ITEM_PREFER_1ST_TABLE 1 + class Item { Item(const Item &); /* Prevent use of these */ void operator=(Item &); @@ -142,6 +147,7 @@ public: my_bool with_sum_func; my_bool fixed; /* If item fixed with fix_fields */ DTCollation collation; + uint8 item_flags; /* Flags on how item should be processed */ // alloc & destruct is done as start of select using sql_alloc Item(); @@ -327,6 +333,11 @@ public: cleanup(); delete this; } + virtual bool set_flags_processor(byte *args) + { + this->item_flags|= *((uint8*)args); + return true; + } }; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e3c0efb83b8..84c03bee917 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2086,7 +2086,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, return (Field*) 0; } bool allow_rowid= tables && !tables->next; // Only one table - for (; tables ; tables=tables->next) + uint table_idx= 0; + for (; tables ; tables=tables->next, table_idx++) { if (!tables->table) { @@ -2114,7 +2115,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, name,thd->where); return (Field*) 0; } - found=field; + found= field; + if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE) + break; } } if (found) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4d339fc6a0e..233104c9a90 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2856,17 +2856,14 @@ unsent_create_error: if ((res= open_and_lock_tables(thd, tables))) break; - TABLE *table= tables->table; /* Skip first table, which is the table we are inserting in */ select_lex->table_list.first= (byte*) first_local_table->next; - tables= (TABLE_LIST *) select_lex->table_list.first; - first_local_table->next= 0; if (!(res= mysql_prepare_insert(thd, tables, first_local_table, - table, lex->field_list, 0, + tables->table, lex->field_list, 0, lex->update_list, lex->value_list, lex->duplicates)) && - (result= new select_insert(table, &lex->field_list, + (result= new select_insert(tables->table, &lex->field_list, &lex->update_list, &lex->value_list, lex->duplicates, lex->ignore))) { @@ -2879,7 +2876,7 @@ unsent_create_error: /* revert changes for SP */ lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; delete result; - table->insert_values= 0; + tables->table->insert_values= 0; if (thd->net.report_error) res= -1; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index bc21649fe54..460234de156 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4239,9 +4239,24 @@ insert_update_elem: simple_ident equal expr_or_default { LEX *lex= Lex; + uint8 tmp= MY_ITEM_PREFER_1ST_TABLE; if (lex->update_list.push_back($1) || lex->value_list.push_back($3)) YYABORT; + /* + INSERT INTO a1(a) SELECT b1.a FROM b1 ON DUPLICATE KEY + UPDATE a= a + b1.b + + Set MY_ITEM_PREFER_1ST_TABLE flag to $1 and $3 items + to prevent find_field_in_tables() doing further item searching + if it finds item occurence in first table in insert_table_list. + This allows to avoid ambiguity in resolving 'a' field in + example above. + */ + $1->walk(&Item::set_flags_processor, + (byte *) &tmp); + $3->walk(&Item::set_flags_processor, + (byte *) &tmp); }; opt_low_priority: -- cgit v1.2.1 From 256c99fdb282512d87f5e6db59cc207024bd06c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 22:58:44 +0400 Subject: item.h: Fix for fix for bug#9728 decreased functionality in "on duplicate key update" Have to return false to set flag for whole expression. sql/item.h: Fix for fix for bug#9728 decreased functionality in "on duplicate key update" Have to return false to set flag for whole expression. --- sql/item.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item.h b/sql/item.h index d9a40cbdfb6..82ab5a66cfb 100644 --- a/sql/item.h +++ b/sql/item.h @@ -336,7 +336,7 @@ public: virtual bool set_flags_processor(byte *args) { this->item_flags|= *((uint8*)args); - return true; + return false; } }; -- cgit v1.2.1