From 98ff15531f2c6d4d84c7ed5bac563182625c3eb4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jun 2005 11:15:29 -0400 Subject: [PATCH 01/11] 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. --- mysql-test/r/rpl_multi_update3.result | 42 +++++++++++++++++++++++++++ mysql-test/t/rpl_multi_update3.test | 33 +++++++++++++++++++++ sql/sql_parse.cc | 16 +++++----- 3 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 mysql-test/r/rpl_multi_update3.result create mode 100644 mysql-test/t/rpl_multi_update3.test diff --git a/mysql-test/r/rpl_multi_update3.result b/mysql-test/r/rpl_multi_update3.result new file mode 100644 index 00000000000..4126ef0b5cb --- /dev/null +++ b/mysql-test/r/rpl_multi_update3.result @@ -0,0 +1,42 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t1 ( +a int unsigned not null auto_increment primary key, +b int unsigned +) ENGINE=MyISAM; +CREATE TABLE t2 ( +a int unsigned not null auto_increment primary key, +b int unsigned +) ENGINE=MyISAM; +INSERT INTO t1 VALUES (NULL, 0); +INSERT INTO t1 SELECT NULL, 0 FROM t1; +INSERT INTO t2 VALUES (NULL, 0), (NULL,1); +SELECT * FROM t1 ORDER BY a; +a b +1 0 +2 0 +SELECT * FROM t2 ORDER BY a; +a b +1 0 +2 1 +UPDATE t2, (SELECT a FROM t1) AS t SET t2.b = t.a+5 ; +SELECT * FROM t1 ORDER BY a; +a b +1 0 +2 0 +SELECT * FROM t2 ORDER BY a; +a b +1 6 +2 6 +SELECT * FROM t1 ORDER BY a; +a b +1 0 +2 0 +SELECT * FROM t2 ORDER BY a; +a b +1 6 +2 6 diff --git a/mysql-test/t/rpl_multi_update3.test b/mysql-test/t/rpl_multi_update3.test new file mode 100644 index 00000000000..ec6a0c09ae5 --- /dev/null +++ b/mysql-test/t/rpl_multi_update3.test @@ -0,0 +1,33 @@ +# Let's verify that multi-update with a subselect does not cause the slave to crash +# (BUG#10442) + +source include/master-slave.inc; + +CREATE TABLE t1 ( + a int unsigned not null auto_increment primary key, + b int unsigned +) ENGINE=MyISAM; + +CREATE TABLE t2 ( + a int unsigned not null auto_increment primary key, + b int unsigned +) ENGINE=MyISAM; + +INSERT INTO t1 VALUES (NULL, 0); +INSERT INTO t1 SELECT NULL, 0 FROM t1; + +INSERT INTO t2 VALUES (NULL, 0), (NULL,1); + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +UPDATE t2, (SELECT a FROM t1) AS t SET t2.b = t.a+5 ; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +save_master_pos; +connection slave; +sync_with_master; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + 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. From 7b1ec027325870da62d0a6b36eeb04b03bd0f576 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 04:24:21 -0700 Subject: [PATCH 02/11] 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. --- mysql-test/r/group_by.result | 10 ++++++++++ mysql-test/t/group_by.test | 15 +++++++++++++++ sql/item_buff.cc | 4 ++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index e279fca2a9d..7f78b8bda9b 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -741,3 +741,13 @@ SELECT dt DIV 1 AS f, id FROM t1 GROUP BY f; f id 20050501123000 1 DROP TABLE t1; +CREATE TABLE t1 (id varchar(20) NOT NULL); +INSERT INTO t1 VALUES ('trans1'), ('trans2'); +CREATE TABLE t2 (id varchar(20) NOT NULL, err_comment blob NOT NULL); +INSERT INTO t2 VALUES ('trans1', 'a problem'); +SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS err_comment +FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY err_comment; +COUNT(DISTINCT(t1.id)) err_comment +1 NULL +1 a problem +DROP TABLE t1, t2; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 382580cbd4e..694aa8d7411 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -565,3 +565,18 @@ INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); SELECT dt DIV 1 AS f, id FROM t1 GROUP BY f; DROP TABLE t1; + +# +# Test for bug #11295: GROUP BY a BLOB column with COUNT(DISTINCT column1) +# when the BLOB column takes NULL values +# + +CREATE TABLE t1 (id varchar(20) NOT NULL); +INSERT INTO t1 VALUES ('trans1'), ('trans2'); +CREATE TABLE t2 (id varchar(20) NOT NULL, err_comment blob NOT NULL); +INSERT INTO t2 VALUES ('trans1', 'a problem'); + +SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS err_comment + FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY err_comment; + +DROP TABLE t1, t2; 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)) From 8e45c0572bf6503b1fd126428aac203c90c949b7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 22:24:58 +0400 Subject: [PATCH 03/11] 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 --- mysql-test/r/insert_select.result | 9 +++++++++ mysql-test/t/insert_select.test | 9 +++++++++ sql/sql_insert.cc | 19 +++++++++++++++---- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index f843c6d0d18..082b7098a1a 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -625,3 +625,12 @@ select SQL_BUFFER_RESULT * from t1 WHERE (SEQ = 1); ID NO SEQ 1 1 1 drop table t1; +create table t1 (f1 int); +create table t2 (ff1 int unique, ff2 int default 1); +insert into t1 values (1),(1),(2); +insert into t2(ff1) select f1 from t1 on duplicate key update ff2=ff2+1; +select * from t2; +ff1 ff2 +1 2 +2 1 +drop table t1, t2; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index ecc83e3883b..613c97dc4f1 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -166,3 +166,12 @@ INSERT INTO t1 (SEQ, NO) SELECT "1" AS SEQ, IF(MAX(NO) IS NULL, 0, MAX(NO)) + 1 select SQL_BUFFER_RESULT * from t1 WHERE (SEQ = 1); drop table t1; +# +# Bug#10886 - Have to restore default values after update ON DUPLICATE KEY +# +create table t1 (f1 int); +create table t2 (ff1 int unique, ff2 int default 1); +insert into t1 values (1),(1),(2); +insert into t2(ff1) select f1 from t1 on duplicate key update ff2=ff2+1; +select * from t2; +drop table t1, t2; 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); } From d18ab5a0243ac431d001b59f440ed0d5b6fe4d91 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 20:25:50 +0200 Subject: [PATCH 04/11] mysql-test-run.pl: Added optional paths for finding mysqld on Windows Added language/charset options to embedded mysql_client_test mysql-test/mysql-test-run.pl: Added optional paths for finding mysqld on Windows Added language/charset options to embedded mysql_client_test --- mysql-test/mysql-test-run.pl | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 0ecc7bc6c52..4f673fe567d 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -772,7 +772,8 @@ sub executable_setup () { { if ( $glob_win32 ) { - $path_client_bindir= mtr_path_exists("$glob_basedir/client_release"); + $path_client_bindir= mtr_path_exists("$glob_basedir/client_release", + "$glob_basedir/bin"); $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-nt"); $path_language= mtr_path_exists("$glob_basedir/share/english/"); $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets"); @@ -794,7 +795,7 @@ sub executable_setup () { } else { - $exe_mysqltest= mtr_exe_exists("$glob_basedir/client/mysqltest"); + $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest"); $exe_mysql_client_test= mtr_exe_exists("$glob_basedir/tests/mysql_client_test"); } @@ -2013,6 +2014,14 @@ sub run_mysqltest ($$) { "--port=$master->[0]->{'path_myport'} " . "--socket=$master->[0]->{'path_mysock'}"; + if ( $glob_use_embedded_server ) + { + $cmdline_mysql_client_test.= + " -A --language=$path_language" . + " -A --datadir=$slave->[0]->{'path_myddir'}" . + " -A --character-sets-dir=$path_charsetsdir"; + } + my $cmdline_mysql_fix_system_tables= "$exe_mysql_fix_system_tables --no-defaults --host=localhost --user=root --password= " . "--basedir=$glob_basedir --bindir=$path_client_bindir --verbose " . @@ -2129,8 +2138,7 @@ sub run_mysqltest ($$) { # ############################################################################## -sub usage ($) -{ +sub usage ($) { print STDERR < Date: Tue, 21 Jun 2005 13:35:12 -0500 Subject: [PATCH 05/11] Bug #9148 Denial of Service my_access.c: Fixed problem where in some cases check_if_legal_filename was returning 0 for illegal names mysys/my_access.c: Fixed problem where in some cases check_if_legal_filename was returning 0 for illegal names --- mysys/my_access.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mysys/my_access.c b/mysys/my_access.c index 89e90e16f18..1b9ad6ff380 100644 --- a/mysys/my_access.c +++ b/mysys/my_access.c @@ -93,18 +93,20 @@ int check_if_legal_filename(const char *path) path+= dirname_length(path); /* To start of filename */ if (!(end= strchr(path, FN_EXTCHAR))) end= strend(path); - if (path == end || (uint) (path - end) > MAX_RESERVED_NAME_LENGTH) + if (path == end || (uint) (end - path) > MAX_RESERVED_NAME_LENGTH) DBUG_RETURN(0); /* Simplify inner loop */ for (reserved_name= reserved_names; *reserved_name; reserved_name++) { const char *name= path; - while (name != end) + const char *current_reserved_name= *reserved_name; + + while (name != end && *current_reserved_name) { - if (my_toupper(&my_charset_latin1, *path) != - my_toupper(&my_charset_latin1, *name)) + if (*current_reserved_name != my_toupper(&my_charset_latin1, *name)) break; - if (name++ == end) + current_reserved_name++; + if (++name == end) DBUG_RETURN(1); /* Found wrong path */ } } From d785fc60ab902842bf68bfb827120b8015700a98 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 15:40:58 -0400 Subject: [PATCH 06/11] 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 --- mysql-test/r/rpl_multi_update3.result | 1 + mysql-test/t/rpl_multi_update3.test | 1 + sql/sql_parse.cc | 8 +++++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/rpl_multi_update3.result b/mysql-test/r/rpl_multi_update3.result index 4126ef0b5cb..708b230b19f 100644 --- a/mysql-test/r/rpl_multi_update3.result +++ b/mysql-test/r/rpl_multi_update3.result @@ -40,3 +40,4 @@ SELECT * FROM t2 ORDER BY a; a b 1 6 2 6 +drop table t1,t2; diff --git a/mysql-test/t/rpl_multi_update3.test b/mysql-test/t/rpl_multi_update3.test index ec6a0c09ae5..b8c8ed79532 100644 --- a/mysql-test/t/rpl_multi_update3.test +++ b/mysql-test/t/rpl_multi_update3.test @@ -31,3 +31,4 @@ sync_with_master; SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; +drop table t1,t2; 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)) From a6c7fb455ae6114ae53be58c49d4ef7dbdcd5e3e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 07:18:42 +0400 Subject: [PATCH 07/11] 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". --- mysql-test/r/insert_select.result | 15 +++++++++++++++ mysql-test/t/insert_select.test | 14 ++++++++++++++ sql/item.cc | 4 +++- sql/item.h | 11 +++++++++++ sql/sql_base.cc | 7 +++++-- sql/sql_parse.cc | 9 +++------ sql/sql_yacc.yy | 15 +++++++++++++++ 7 files changed, 66 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 082b7098a1a..69eb64f08ea 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -634,3 +634,18 @@ ff1 ff2 1 2 2 1 drop table t1, t2; +create table t1 (a int unique); +create table t2 (a int, b int); +insert into t1 values (1),(2); +insert into t2 values (1,2); +select * from t1; +a +1 +2 +insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b; +select * from t1; +a +2 +3 +drop table t1; +drop table t2; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 613c97dc4f1..7402940fa52 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -175,3 +175,17 @@ insert into t1 values (1),(1),(2); insert into t2(ff1) select f1 from t1 on duplicate key update ff2=ff2+1; select * from t2; drop table t1, t2; +# +# BUGS #9728 - 'Decreased functionality in "on duplicate key update"' +# #8147 - 'a column proclaimed ambigous in INSERT ... SELECT .. ON +# DUPLICATE' +# +create table t1 (a int unique); +create table t2 (a int, b int); +insert into t1 values (1),(2); +insert into t2 values (1,2); +select * from t1; +insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b; +select * from t1; +drop table t1; +drop table t2; 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: From 2e7df19baddcf500dd89a43c81272cfcf8cfbefd Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 05:18:43 +0200 Subject: [PATCH 08/11] fix README file to be more verbose match actual situation (recomitted to push into 4.1) mysql-test/README: fix README file to be more verbose match actual situation --- mysql-test/README | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/mysql-test/README b/mysql-test/README index 65e6186613a..10d64784ed4 100644 --- a/mysql-test/README +++ b/mysql-test/README @@ -2,8 +2,17 @@ This directory contains a test suite for mysql daemon. To run the currently existing test cases, simply execute ./mysql-test-run in this directory. It will fire up the newly built mysqld and test it. -If you want to run the test with a running MySQL server use the --external -option to mysql-test-run. +If you want to run a test with a running MySQL server use the --extern +option to mysql-test-run. Please note that in this mode the test suite +expects user to specify test names to run. Otherwise it falls back to the +normal "non-extern" behaviour. The reason is that some tests +could not run with external server. Here is the sample command +to test "alias" and "analyze" tests on external server: + +mysql-test-run --extern alias analyze + +To match your setup you might also need to provide --socket, --user and +other relevant options. Note that you do not have to have to do make install, and you could actually have a co-existing MySQL installation - the tests will not From eb7e1d7257598343b5b2cc93b59dffd948f99366 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 11:18:40 +0200 Subject: [PATCH 09/11] Made upgrade compatibility in 4.1 range to latest build version ndb/src/common/util/version.c: Maybe upgrade compatibility in 4.1 range to latest build version --- ndb/src/common/util/version.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndb/src/common/util/version.c b/ndb/src/common/util/version.c index ed2e2565eea..7221dc48fa4 100644 --- a/ndb/src/common/util/version.c +++ b/ndb/src/common/util/version.c @@ -90,7 +90,7 @@ void ndbSetOwnVersion() {} #ifndef TEST_VERSION struct NdbUpGradeCompatible ndbCompatibleTable_full[] = { - { MAKE_VERSION(4,1,12), MAKE_VERSION(4,1,10), UG_Range }, + { MAKE_VERSION(4,1,NDB_VERSION_BUILD), MAKE_VERSION(4,1,10), UG_Range }, { MAKE_VERSION(4,1,10), MAKE_VERSION(4,1,9), UG_Exact }, { MAKE_VERSION(4,1,9), MAKE_VERSION(4,1,8), UG_Exact }, { MAKE_VERSION(3,5,2), MAKE_VERSION(3,5,1), UG_Exact }, From 900fe718d131434d33daf5fd01bf8250bc936bd3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 17:12:02 +0200 Subject: [PATCH 10/11] BUG#9361: Added test cases mysql-test/r/rpl_multi_update3.result: Added test cases mysql-test/t/rpl_multi_update3.test: Added test cases --- mysql-test/r/rpl_multi_update3.result | 81 ++++++++++++++++ mysql-test/t/rpl_multi_update3.test | 133 +++++++++++++++++++++++++- 2 files changed, 210 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/rpl_multi_update3.result b/mysql-test/r/rpl_multi_update3.result index 708b230b19f..1b757b1400c 100644 --- a/mysql-test/r/rpl_multi_update3.result +++ b/mysql-test/r/rpl_multi_update3.result @@ -4,6 +4,8 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; + +-------- Test for BUG#9361 -------- CREATE TABLE t1 ( a int unsigned not null auto_increment primary key, b int unsigned @@ -41,3 +43,82 @@ a b 1 6 2 6 drop table t1,t2; + +-------- Test 1 for BUG#9361 -------- +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +CREATE TABLE t1 ( +a1 char(30), +a2 int, +a3 int, +a4 char(30), +a5 char(30) +); +CREATE TABLE t2 ( +b1 int, +b2 char(30) +); +INSERT INTO t1 VALUES ('Yes', 1, NULL, 'foo', 'bar'); +INSERT INTO t2 VALUES (1, 'baz'); +UPDATE t1 a, t2 +SET a.a1 = 'No' +WHERE a.a2 = +(SELECT b1 +FROM t2 +WHERE b2 = 'baz') +AND a.a3 IS NULL +AND a.a4 = 'foo' +AND a.a5 = 'bar'; +SELECT * FROM t1; +a1 a2 a3 a4 a5 +No 1 NULL foo bar +SELECT * FROM t2; +b1 b2 +1 baz +DROP TABLE t1, t2; + +-------- Test 2 for BUG#9361 -------- +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; +CREATE TABLE t1 ( +i INT, +j INT, +x INT, +y INT, +z INT +); +CREATE TABLE t2 ( +i INT, +k INT, +x INT, +y INT, +z INT +); +CREATE TABLE t3 ( +j INT, +k INT, +x INT, +y INT, +z INT +); +INSERT INTO t1 VALUES ( 1, 2,13,14,15); +INSERT INTO t2 VALUES ( 1, 3,23,24,25); +INSERT INTO t3 VALUES ( 2, 3, 1,34,35), ( 2, 3, 1,34,36); +UPDATE t1 AS a +INNER JOIN t2 AS b +ON a.i = b.i +INNER JOIN t3 AS c +ON a.j = c.j AND b.k = c.k +SET a.x = b.x, +a.y = b.y, +a.z = ( +SELECT sum(z) +FROM t3 +WHERE y = 34 +) +WHERE b.x = 23; +SELECT * FROM t1; +i j x y z +1 2 23 24 71 +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/rpl_multi_update3.test b/mysql-test/t/rpl_multi_update3.test index b8c8ed79532..80b0603eb60 100644 --- a/mysql-test/t/rpl_multi_update3.test +++ b/mysql-test/t/rpl_multi_update3.test @@ -1,7 +1,13 @@ +source include/master-slave.inc; + +############################################################################## +# # Let's verify that multi-update with a subselect does not cause the slave to crash # (BUG#10442) - -source include/master-slave.inc; +# +--disable_query_log +SELECT '-------- Test for BUG#9361 --------' as ""; +--enable_query_log CREATE TABLE t1 ( a int unsigned not null auto_increment primary key, @@ -25,10 +31,129 @@ UPDATE t2, (SELECT a FROM t1) AS t SET t2.b = t.a+5 ; SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; -save_master_pos; +sync_slave_with_master; connection slave; -sync_with_master; SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; +connection master; drop table t1,t2; + +############################################################################## +# +# Test for BUG#9361: +# Subselects should work inside multi-updates +# +--disable_query_log +SELECT '-------- Test 1 for BUG#9361 --------' as ""; +--enable_query_log + +connection master; + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +--enable_warnings + +CREATE TABLE t1 ( + a1 char(30), + a2 int, + a3 int, + a4 char(30), + a5 char(30) +); + +CREATE TABLE t2 ( + b1 int, + b2 char(30) +); + +# Insert one row per table +INSERT INTO t1 VALUES ('Yes', 1, NULL, 'foo', 'bar'); +INSERT INTO t2 VALUES (1, 'baz'); + +# This should update the row in t1 +UPDATE t1 a, t2 + SET a.a1 = 'No' + WHERE a.a2 = + (SELECT b1 + FROM t2 + WHERE b2 = 'baz') + AND a.a3 IS NULL + AND a.a4 = 'foo' + AND a.a5 = 'bar'; + +sync_slave_with_master; +connection slave; +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; +DROP TABLE t1, t2; + +############################################################################## +# +# Second test for BUG#9361 +# + +--disable_query_log +SELECT '-------- Test 2 for BUG#9361 --------' as ""; +--enable_query_log + +connection master; + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; +--enable_warnings + +CREATE TABLE t1 ( + i INT, + j INT, + x INT, + y INT, + z INT +); + +CREATE TABLE t2 ( + i INT, + k INT, + x INT, + y INT, + z INT +); + +CREATE TABLE t3 ( + j INT, + k INT, + x INT, + y INT, + z INT +); + +INSERT INTO t1 VALUES ( 1, 2,13,14,15); +INSERT INTO t2 VALUES ( 1, 3,23,24,25); +INSERT INTO t3 VALUES ( 2, 3, 1,34,35), ( 2, 3, 1,34,36); + +UPDATE t1 AS a +INNER JOIN t2 AS b + ON a.i = b.i +INNER JOIN t3 AS c + ON a.j = c.j AND b.k = c.k +SET a.x = b.x, + a.y = b.y, + a.z = ( + SELECT sum(z) + FROM t3 + WHERE y = 34 + ) +WHERE b.x = 23; + +sync_slave_with_master; +connection slave; + +SELECT * FROM t1; + +connection master; +DROP TABLE t1, t2, t3; From 256c99fdb282512d87f5e6db59cc207024bd06c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 22:58:44 +0400 Subject: [PATCH 11/11] 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(-) 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; } };