From 78f47b1b1080833241860c6213854fe04487ff12 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Oct 2006 11:26:50 -0400 Subject: [PATCH 1/3] Bug#19660 mysqldump --single-transaction should be with CONSISTENT SNAPSHOT client/mysqldump.c: Bug#19660 mysqldump --single-transaction should be with CONSISTENT SNAPSHOT - Remove old BEGIN syntax and replace with START TRANSATION. Add CONSISTENT SNAPSHOT option for servers that support it. --- client/mysqldump.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 3445a23eb5e..c55e4157394 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2407,7 +2407,7 @@ static int do_reset_master(MYSQL *mysql_con) } -static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now) +static int start_transaction(MYSQL *mysql_con) { /* We use BEGIN for old servers. --single-transaction --master-data will fail @@ -2422,10 +2422,8 @@ static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now) "SET SESSION TRANSACTION ISOLATION " "LEVEL REPEATABLE READ") || mysql_query_with_error_report(mysql_con, 0, - consistent_read_now ? "START TRANSACTION " - "WITH CONSISTENT SNAPSHOT" : - "BEGIN")); + "/*!40100 WITH CONSISTENT SNAPSHOT */")); } @@ -2652,7 +2650,7 @@ int main(int argc, char **argv) if ((opt_lock_all_tables || opt_master_data) && do_flush_tables_read_lock(sock)) goto err; - if (opt_single_transaction && start_transaction(sock, test(opt_master_data))) + if (opt_single_transaction && start_transaction(sock)) goto err; if (opt_delete_master_logs && do_reset_master(sock)) goto err; From aaef575f9f360e03f344d55f5f14aacff382ce2c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Oct 2006 10:49:39 -0400 Subject: [PATCH 2/3] Bug #19024- SHOW COUNT(*) WARNINGS not return Errors The server variable warning_count should include the number of warnings, errors and notes according to the manual mysql-test/r/user_var.result: Added warning_count results. mysql-test/t/user_var.test: Added test case for warning_count. sql/set_var.cc: Added number errors to warning_count. --- mysql-test/r/user_var.result | 9 +++++++++ mysql-test/t/user_var.test | 10 +++++++++- sql/set_var.cc | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 1664a907c99..90954fc1ede 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -215,6 +215,7 @@ select @@version; select @@global.version; @@global.version # +End of 4.1 tests set @first_var= NULL; create table t1 select @first_var; show create table t1; @@ -301,3 +302,11 @@ select @var; @var 3 drop table t1; +insert into city 'blah'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''blah'' at line 1 +SHOW COUNT(*) WARNINGS; +@@session.warning_count +1 +SHOW COUNT(*) ERRORS; +@@session.error_count +1 diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index 644ca506eba..65ca1b2c1b7 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -144,6 +144,8 @@ select @@version; --replace_column 1 # select @@global.version; +--echo End of 4.1 tests + # Bug #6598: problem with cast(NULL as signed integer); # @@ -210,4 +212,10 @@ select @var:=f2 from t1 group by f1 order by f2 desc limit 1; select @var; drop table t1; -# End of 4.1 tests +# +# Bug#19024 - SHOW COUNT(*) WARNINGS not return Errors +# +--error 1064 +insert into city 'blah'; +SHOW COUNT(*) WARNINGS; +SHOW COUNT(*) ERRORS; diff --git a/sql/set_var.cc b/sql/set_var.cc index c667e2f2bcc..dd41256a7cc 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2917,6 +2917,7 @@ static byte *get_warning_count(THD *thd) { thd->sys_var_tmp.long_value= (thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] + + thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] + thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]); return (byte*) &thd->sys_var_tmp.long_value; } From f60ea28841ee37627e1997850ad0a5c5bd311bc2 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Oct 2006 11:19:23 -0400 Subject: [PATCH 3/3] Bug#19356: Assert on undefined @uservar in prepared statement execute The executing code had a safety assertion so that it refused to free Items that it didn't create. However, there is a case, undefined user variables, which would put Items into the list to be freed. Instead, do something that is more risky in expectation that the code will be refactored soon, as Kostja wants to do: Remove the assertions from prepare() and execute(). Put one assertion at a higher level, before stmt->set_params_from_vars(), which may then create new to-be-freed Items . mysql-test/r/ps_11bugs.result: Create tests to prove that undefined variables work, as keys and not, and that variables explicitly assigned to Null work. mysql-test/t/ps_11bugs.test: Create tests to prove that undefined variables work, as keys and not, and that variables explicitly assigned to Null work. sql/sql_prepare.cc: Move a safety assertion up one level and higher, because there is legitimately a case where thd->free_list is not NULL going into Prepared_statement::{prepare,execute} methods. Kostja plans to refactor this code so that it is both safe and works. (Now it works, but isn't very safe.) --- BitKeeper/etc/collapsed | 2 ++ mysql-test/r/ps_11bugs.result | 33 +++++++++++++++++++++++++++++++++ mysql-test/t/ps_11bugs.test | 34 ++++++++++++++++++++++++++++++++++ sql/sql_prepare.cc | 33 +++++++++++++++++++++++++++------ 4 files changed, 96 insertions(+), 6 deletions(-) diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed index d4d681937a2..7a682f9b2c0 100644 --- a/BitKeeper/etc/collapsed +++ b/BitKeeper/etc/collapsed @@ -2,3 +2,5 @@ 44ec850ac2k4y2Omgr92GiWPBAVKGQ 44edb86b1iE5knJ97MbliK_3lCiAXA 44f33f3aj5KW5qweQeekY1LU0E9ZCg +45214442pBGT9KuZEGixBH71jTzbOA +45214a07hVsIGwvwa-WrO-jpeaSwVw diff --git a/mysql-test/r/ps_11bugs.result b/mysql-test/r/ps_11bugs.result index c849c25d646..ebe161f46b3 100644 --- a/mysql-test/r/ps_11bugs.result +++ b/mysql-test/r/ps_11bugs.result @@ -130,3 +130,36 @@ prepare st_18492 from 'select * from t1 where 3 in (select (1+1) union select 1) execute st_18492; a drop table t1; +create table t1 (a int, b varchar(4)); +create table t2 (a int, b varchar(4), primary key(a)); +prepare stmt1 from 'insert into t1 (a, b) values (?, ?)'; +prepare stmt2 from 'insert into t2 (a, b) values (?, ?)'; +set @intarg= 11; +set @varchararg= '2222'; +execute stmt1 using @intarg, @varchararg; +execute stmt2 using @intarg, @varchararg; +set @intarg= 12; +execute stmt1 using @intarg, @UNDEFINED; +execute stmt2 using @intarg, @UNDEFINED; +set @intarg= 13; +execute stmt1 using @UNDEFINED, @varchararg; +execute stmt2 using @UNDEFINED, @varchararg; +ERROR 23000: Column 'a' cannot be null +set @intarg= 14; +set @nullarg= Null; +execute stmt1 using @UNDEFINED, @nullarg; +execute stmt2 using @nullarg, @varchararg; +ERROR 23000: Column 'a' cannot be null +select * from t1; +a b +11 2222 +12 NULL +NULL 2222 +NULL NULL +select * from t2; +a b +11 2222 +12 NULL +drop table t1; +drop table t2; +End of 5.0 tests. diff --git a/mysql-test/t/ps_11bugs.test b/mysql-test/t/ps_11bugs.test index ff1c87f3bd8..515bcc03c1a 100644 --- a/mysql-test/t/ps_11bugs.test +++ b/mysql-test/t/ps_11bugs.test @@ -144,3 +144,37 @@ prepare st_18492 from 'select * from t1 where 3 in (select (1+1) union select 1) execute st_18492; drop table t1; + +# +# Bug#19356: Assertion failure with undefined @uservar in prepared statement execution +# +create table t1 (a int, b varchar(4)); +create table t2 (a int, b varchar(4), primary key(a)); + +prepare stmt1 from 'insert into t1 (a, b) values (?, ?)'; +prepare stmt2 from 'insert into t2 (a, b) values (?, ?)'; + +set @intarg= 11; +set @varchararg= '2222'; +execute stmt1 using @intarg, @varchararg; +execute stmt2 using @intarg, @varchararg; +set @intarg= 12; +execute stmt1 using @intarg, @UNDEFINED; +execute stmt2 using @intarg, @UNDEFINED; +set @intarg= 13; +execute stmt1 using @UNDEFINED, @varchararg; +--error 1048 +execute stmt2 using @UNDEFINED, @varchararg; +set @intarg= 14; +set @nullarg= Null; +execute stmt1 using @UNDEFINED, @nullarg; +--error 1048 +execute stmt2 using @nullarg, @varchararg; + +select * from t1; +select * from t2; + +drop table t1; +drop table t2; + +--echo End of 5.0 tests. diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 32f0ca6859d..9e321411863 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2248,6 +2248,14 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length) #endif if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(),QUERY_PRIOR); + + /* + If the free_list is not empty, we'll wrongly free some externally + allocated items when cleaning up after validation of the prepared + statement. + */ + DBUG_ASSERT(thd->free_list == NULL); + error= stmt->execute(&expanded_query, test(flags & (ulong) CURSOR_TYPE_READ_ONLY)); if (!(specialflag & SPECIAL_NO_PRIOR)) @@ -2310,6 +2318,13 @@ void mysql_sql_stmt_execute(THD *thd) DBUG_PRINT("info",("stmt: %p", stmt)); + /* + If the free_list is not empty, we'll wrongly free some externally + allocated items when cleaning up after validation of the prepared + statement. + */ + DBUG_ASSERT(thd->free_list == NULL); + if (stmt->set_params_from_vars(stmt, lex->prepared_stmt_params, &expanded_query)) goto set_params_data_err; @@ -2788,12 +2803,12 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) external changes when cleaning up after validation. */ DBUG_ASSERT(thd->change_list.is_empty()); - /* - If the free_list is not empty, we'll wrongly free some externally - allocated items when cleaning up after validation of the prepared - statement. + + /* + The only case where we should have items in the thd->free_list is + after stmt->set_params_from_vars(), which may in some cases create + Item_null objects. */ - DBUG_ASSERT(thd->free_list == NULL); if (error == 0) error= check_prepared_statement(this, name.str != 0); @@ -2891,7 +2906,13 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) allocated items when cleaning up after execution of this statement. */ DBUG_ASSERT(thd->change_list.is_empty()); - DBUG_ASSERT(thd->free_list == NULL); + + /* + The only case where we should have items in the thd->free_list is + after stmt->set_params_from_vars(), which may in some cases create + Item_null objects. + */ + thd->set_n_backup_statement(this, &stmt_backup); if (expanded_query->length() && alloc_query(thd, (char*) expanded_query->ptr(),