mariadb/mysql-test/t/ps.test

418 lines
11 KiB
Text
Raw Normal View History

#
# SQL Syntax for Prepared Statements test
#
--disable_warnings
drop table if exists t1,t2;
--enable_warnings
create table t1
(
a int primary key,
b char(10)
);
insert into t1 values (1,'one');
insert into t1 values (2,'two');
insert into t1 values (3,'three');
insert into t1 values (4,'four');
# basic functionality
set @a=2;
prepare stmt1 from 'select * from t1 where a <= ?';
execute stmt1 using @a;
set @a=3;
execute stmt1 using @a;
# non-existant statement
--error 1243
deallocate prepare no_such_statement;
--error 1210
execute stmt1;
# Nesting ps commands is not allowed:
--error 1064
prepare stmt2 from 'prepare nested_stmt from "select 1"';
--error 1064
prepare stmt2 from 'execute stmt1';
--error 1064
prepare stmt2 from 'deallocate prepare z';
# PS insert
prepare stmt3 from 'insert into t1 values (?,?)';
set @arg1=5, @arg2='five';
execute stmt3 using @arg1, @arg2;
select * from t1 where a>3;
# PS update
prepare stmt4 from 'update t1 set a=? where b=?';
set @arg1=55, @arg2='five';
execute stmt4 using @arg1, @arg2;
select * from t1 where a>3;
# PS create/delete
prepare stmt4 from 'create table t2 (a int)';
execute stmt4;
prepare stmt4 from 'drop table t2';
execute stmt4;
# Do something that will cause error
--error 1051
execute stmt4;
# placeholders in result field names.
prepare stmt5 from 'select ? + a from t1';
set @a=1;
execute stmt5 using @a;
execute stmt5 using @no_such_var;
set @nullvar=1;
set @nullvar=NULL;
execute stmt5 using @nullvar;
set @nullvar2=NULL;
execute stmt5 using @nullvar2;
# Check that multiple SQL statements are disabled inside PREPARE
--error 1064
prepare stmt6 from 'select 1; select2';
--error 1064
prepare stmt6 from 'insert into t1 values (5,"five"); select2';
# This shouldn't parse
--error 1064
explain prepare stmt6 from 'insert into t1 values (5,"five"); select2';
create table t2
(
a int
);
insert into t2 values (0);
# parameter is NULL
set @arg00=NULL ;
prepare stmt1 from 'select 1 FROM t2 where a=?' ;
execute stmt1 using @arg00 ;
WL#1622 "SQL Syntax for Prepared Statements": Post-review fixes (1 of 2) mysql-test/r/ps.result: Added tests for PREPARE stmt1 FROM @var syntax mysql-test/t/ps.test: Added tests for PREPARE stmt1 FROM @var syntax mysys/my_error.c: Added support for "%.*s" format sql/item.cc: Removed one redundant Item_param::set_value function sql/item.h: Removed one redundant Item_param::set_value function sql/mysqld.cc: Reformmated the code sql/share/czech/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/dutch/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/english/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/estonian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/french/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/german/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/greek/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/hungarian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/italian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/japanese/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/korean/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/norwegian-ny/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/norwegian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/polish/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/portuguese/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/romanian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/russian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/slovak/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/spanish/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/swedish/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/ukrainian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/sql_class.h: SQL Prepared statements now can't be used by binary protocol commands sql/sql_lex.h: Added support for PREPARE stmt1 FROM @var syntax. sql/sql_parse.cc: Added support for PREPARE stmt1 FROM @var syntax. sql/sql_prepare.cc: Code cleanup sql/sql_yacc.yy: Added support for PREPARE stmt1 FROM @var syntax.
2004-05-21 02:27:50 +02:00
# prepare using variables:
--error 1064
prepare stmt1 from @nosuchvar;
set @ivar= 1234;
--error 1064
prepare stmt1 from @ivar;
set @fvar= 123.4567;
--error 1064
prepare stmt1 from @fvar;
set @str1 = 'select ?';
set @str2 = convert(@str1 using ucs2);
prepare stmt1 from @str2;
execute stmt1 using @ivar;
drop table t1,t2;
#
# Bug #4105: Server crash on attempt to prepare a statement with character
# set introducer
#
PREPARE stmt1 FROM "select _utf8 'A' collate utf8_bin = ?";
set @var='A';
EXECUTE stmt1 USING @var;
DEALLOCATE PREPARE stmt1;
#
# BUG#3486: FOUND_ROWS() fails inside stored procedure [and prepared statement]
#
create table t1 (id int);
prepare stmt1 from "select FOUND_ROWS()";
select SQL_CALC_FOUND_ROWS * from t1;
# Expect 0
execute stmt1;
insert into t1 values (1);
select SQL_CALC_FOUND_ROWS * from t1;
# Expect 1
execute stmt1;
# Expect 0
execute stmt1;
deallocate prepare stmt1;
drop table t1;
#
# prepared EXPLAIN
#
create table t1
(
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
c13 date, c14 datetime, c15 timestamp(14), c16 time,
c17 year, c18 bit, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
c32 set('monday', 'tuesday', 'wednesday')
) engine = MYISAM ;
create table t2 like t1;
set @stmt= ' explain SELECT (SELECT SUM(c1 + c12 + 0.0) FROM t2 where (t1.c2 - 0e-3) = t2.c2 GROUP BY t1.c15 LIMIT 1) as scalar_s, exists (select 1.0e+0 from t2 where t2.c3 * 9.0000000000 = t1.c4) as exists_s, c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s, (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s FROM t1, (select c25 x, c32 y from t2) tt WHERE x * 1 = c25 ' ;
prepare stmt1 from @stmt ;
execute stmt1 ;
execute stmt1 ;
explain SELECT (SELECT SUM(c1 + c12 + 0.0) FROM t2 where (t1.c2 - 0e-3) = t2.c2 GROUP BY t1.c15 LIMIT 1) as scalar_s, exists (select 1.0e+0 from t2 where t2.c3 * 9.0000000000 = t1.c4) as exists_s, c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s, (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s FROM t1, (select c25 x, c32 y from t2) tt WHERE x * 1 = c25;
deallocate prepare stmt1;
drop tables t1,t2;
2004-06-25 17:33:31 +02:00
#
# parameters from variables (for field creation)
#
set @arg00=1;
prepare stmt1 from ' create table t1 (m int) as select 1 as m ' ;
execute stmt1 ;
select m from t1;
drop table t1;
prepare stmt1 from ' create table t1 (m int) as select ? as m ' ;
execute stmt1 using @arg00;
select m from t1;
deallocate prepare stmt1;
drop table t1;
#
# eq() for parameters
#
create table t1 (id int(10) unsigned NOT NULL default '0',
name varchar(64) NOT NULL default '',
PRIMARY KEY (id), UNIQUE KEY `name` (`name`));
insert into t1 values (1,'1'),(2,'2'),(3,'3'),(4,'4'),(5,'5'),(6,'6'),(7,'7');
prepare stmt1 from 'select name from t1 where id=? or id=?';
set @id1=1,@id2=6;
execute stmt1 using @id1, @id2;
select name from t1 where id=1 or id=6;
deallocate prepare stmt1;
drop table t1;
#
# SHOW TABLE STATUS test
#
create table t1 ( a int primary key, b varchar(30)) engine = MYISAM ;
prepare stmt1 from ' show table status from test like ''t1%'' ';
--replace_column 8 4294967295 12 # 13 # 14 #
execute stmt1;
--replace_column 8 4294967295 12 # 13 # 14 #
show table status from test like 't1%' ;
deallocate prepare stmt1 ;
drop table t1;
Fix for bug#4912 "mysqld crashs in case a statement is executed a second time". The bug was caused by incompatibility of negations elimination algorithm and PS: during first statement execute a subtree with negation was replaced with equivalent subtree without NOTs. The problem was that although this transformation was permanent, items of the new subtree were created in execute-local memory. The patch adds means to check if it is the first execute of a prepared statement, and if this is the case, to allocate items in memory of the prepared statement. The implementation: - backports Item_arena from 5.0 - adds Item_arena::is_stmt_prepare(), Item_arena::is_first_stmt_execute(). - deletes THD::allocate_temporary_pool_for_ps_preparing(), THD::free_temporary_pool_for_ps_preparing(); they were redundant. and adds a few invariants: - thd->free_list never contains junk (= freed items) - thd->current_arena is never null. If there is no prepared statement, it points at the thd. The rest of the patch contains mainly mechanical changes and cleanups. mysql-test/r/ps.result: Test results updated (test case for Bug#4912) mysql-test/t/ps.test: A test case for Bug#4912 "mysqld crashs in case a statement is executed a second time" sql/item_cmpfunc.cc: current_statement -> current_arena sql/item_subselect.cc: Statement -> Item_arena, current_statement -> current_arena sql/item_subselect.h: Item_subselect does not need to save thd->current_statement. sql/item_sum.cc: Statement -> Item_arena sql/item_sum.h: Statement -> Item_arena sql/mysql_priv.h: Statement -> Item_arena sql/sql_base.cc: current_statement -> current_arena sql/sql_class.cc: - Item_arena - convenient set_n_backup_statement, restore_backup_statement (nice idea, Sanja) sql/sql_class.h: - Item_arena: backport from 5.0 - allocate_temporary_pool_for_ps_preparing, free_temporary_pool_for_ps_preparing removed. sql/sql_derived.cc: current_statement -> current_arena sql/sql_lex.cc: current_statement -> current_arena sql/sql_parse.cc: Deploy invariant that thd->free_list never contains junk items (backport from 5.0). sql/sql_prepare.cc: - backporting Item_arena - no need to allocate_temporary_pool_for_ps_preparing(). sql/sql_select.cc: Fix for bug#4912 "mysqld crashs in case a statement is executed a second time": if this is the first execute of a prepared statement, negation elimination is done in memory of the prepared statement. sql/sql_union.cc: Backporting Item_arena from 5.0.
2004-08-21 00:02:46 +02:00
#
# Bug#4912 "mysqld crashs in case a statement is executed a second time":
Fix for Bug#5034 "prepared "select 1 into @arg15", second execute crashes server": we were deleting lex->result after each execute, but prepared statements assumed that it's left intact. The fix adds cleanup() method to select_result hierarchy, so that result objects can be reused. Plus we now need to delete result objects more wisely. mysql-test/r/ps.result: Test results fixed: test case for bug#5034 mysql-test/t/ps.test: A test case for bug#5034, few followups sql/sql_class.cc: - fix warning in THD::THD - implementation of cleanup() for select_result hierarchy - select_export::send_eof was identical to select_dump::send_eof: moved to the base class select_to_file. - Statement::end_statement() to end lex, free items, and delete possible select_result sql/sql_class.h: - select_result::cleanup() declaration - sql/sql_insert.cc: - implementation of select_insert::cleanup(): currently we always create a new instance of select_insert/ select_create on each execute. sql/sql_lex.cc: - with more complicated logic of freeing lex->result it's easier to have it non-zero only if it points to a valid result. sql/sql_lex.h: Now st_lex::st_lex is not empty. sql/sql_parse.cc: mysql_execute_command(): - delete select_result *result only if it was created in this function. - use end_statement() to cleanup lex and thd in the end of each statement. - no need to save THD::lock if this is explain. This save apparently left from times when derived tables were materialized here, not in open_and_lock_tables. sql/sql_prepare.cc: - call result->cleanup() in reset_stmt_for_execute - now Statement is responsible for freeing its lex->result. sql/sql_select.cc: handle_select(): - don't delete result, it might be needed for next executions - result is never null
2004-08-24 18:17:11 +02:00
# negation elimination should work once and not break prepared statements
Fix for bug#4912 "mysqld crashs in case a statement is executed a second time". The bug was caused by incompatibility of negations elimination algorithm and PS: during first statement execute a subtree with negation was replaced with equivalent subtree without NOTs. The problem was that although this transformation was permanent, items of the new subtree were created in execute-local memory. The patch adds means to check if it is the first execute of a prepared statement, and if this is the case, to allocate items in memory of the prepared statement. The implementation: - backports Item_arena from 5.0 - adds Item_arena::is_stmt_prepare(), Item_arena::is_first_stmt_execute(). - deletes THD::allocate_temporary_pool_for_ps_preparing(), THD::free_temporary_pool_for_ps_preparing(); they were redundant. and adds a few invariants: - thd->free_list never contains junk (= freed items) - thd->current_arena is never null. If there is no prepared statement, it points at the thd. The rest of the patch contains mainly mechanical changes and cleanups. mysql-test/r/ps.result: Test results updated (test case for Bug#4912) mysql-test/t/ps.test: A test case for Bug#4912 "mysqld crashs in case a statement is executed a second time" sql/item_cmpfunc.cc: current_statement -> current_arena sql/item_subselect.cc: Statement -> Item_arena, current_statement -> current_arena sql/item_subselect.h: Item_subselect does not need to save thd->current_statement. sql/item_sum.cc: Statement -> Item_arena sql/item_sum.h: Statement -> Item_arena sql/mysql_priv.h: Statement -> Item_arena sql/sql_base.cc: current_statement -> current_arena sql/sql_class.cc: - Item_arena - convenient set_n_backup_statement, restore_backup_statement (nice idea, Sanja) sql/sql_class.h: - Item_arena: backport from 5.0 - allocate_temporary_pool_for_ps_preparing, free_temporary_pool_for_ps_preparing removed. sql/sql_derived.cc: current_statement -> current_arena sql/sql_lex.cc: current_statement -> current_arena sql/sql_parse.cc: Deploy invariant that thd->free_list never contains junk items (backport from 5.0). sql/sql_prepare.cc: - backporting Item_arena - no need to allocate_temporary_pool_for_ps_preparing(). sql/sql_select.cc: Fix for bug#4912 "mysqld crashs in case a statement is executed a second time": if this is the first execute of a prepared statement, negation elimination is done in memory of the prepared statement. sql/sql_union.cc: Backporting Item_arena from 5.0.
2004-08-21 00:02:46 +02:00
#
create table t1(a varchar(2), b varchar(3));
prepare stmt1 from "select a, b from t1 where (not (a='aa' and b < 'zzz'))";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
Fix for Bug#5034 "prepared "select 1 into @arg15", second execute crashes server": we were deleting lex->result after each execute, but prepared statements assumed that it's left intact. The fix adds cleanup() method to select_result hierarchy, so that result objects can be reused. Plus we now need to delete result objects more wisely. mysql-test/r/ps.result: Test results fixed: test case for bug#5034 mysql-test/t/ps.test: A test case for bug#5034, few followups sql/sql_class.cc: - fix warning in THD::THD - implementation of cleanup() for select_result hierarchy - select_export::send_eof was identical to select_dump::send_eof: moved to the base class select_to_file. - Statement::end_statement() to end lex, free items, and delete possible select_result sql/sql_class.h: - select_result::cleanup() declaration - sql/sql_insert.cc: - implementation of select_insert::cleanup(): currently we always create a new instance of select_insert/ select_create on each execute. sql/sql_lex.cc: - with more complicated logic of freeing lex->result it's easier to have it non-zero only if it points to a valid result. sql/sql_lex.h: Now st_lex::st_lex is not empty. sql/sql_parse.cc: mysql_execute_command(): - delete select_result *result only if it was created in this function. - use end_statement() to cleanup lex and thd in the end of each statement. - no need to save THD::lock if this is explain. This save apparently left from times when derived tables were materialized here, not in open_and_lock_tables. sql/sql_prepare.cc: - call result->cleanup() in reset_stmt_for_execute - now Statement is responsible for freeing its lex->result. sql/sql_select.cc: handle_select(): - don't delete result, it might be needed for next executions - result is never null
2004-08-24 18:17:11 +02:00
drop table t1;
#
# Bug#5034 "prepared "select 1 into @arg15", second execute crashes
# server".
# Check that descendands of select_result can be reused in prepared
# statements or are correctly created and deleted on each execute
#
Fix for bug#4912 "mysqld crashs in case a statement is executed a second time". The bug was caused by incompatibility of negations elimination algorithm and PS: during first statement execute a subtree with negation was replaced with equivalent subtree without NOTs. The problem was that although this transformation was permanent, items of the new subtree were created in execute-local memory. The patch adds means to check if it is the first execute of a prepared statement, and if this is the case, to allocate items in memory of the prepared statement. The implementation: - backports Item_arena from 5.0 - adds Item_arena::is_stmt_prepare(), Item_arena::is_first_stmt_execute(). - deletes THD::allocate_temporary_pool_for_ps_preparing(), THD::free_temporary_pool_for_ps_preparing(); they were redundant. and adds a few invariants: - thd->free_list never contains junk (= freed items) - thd->current_arena is never null. If there is no prepared statement, it points at the thd. The rest of the patch contains mainly mechanical changes and cleanups. mysql-test/r/ps.result: Test results updated (test case for Bug#4912) mysql-test/t/ps.test: A test case for Bug#4912 "mysqld crashs in case a statement is executed a second time" sql/item_cmpfunc.cc: current_statement -> current_arena sql/item_subselect.cc: Statement -> Item_arena, current_statement -> current_arena sql/item_subselect.h: Item_subselect does not need to save thd->current_statement. sql/item_sum.cc: Statement -> Item_arena sql/item_sum.h: Statement -> Item_arena sql/mysql_priv.h: Statement -> Item_arena sql/sql_base.cc: current_statement -> current_arena sql/sql_class.cc: - Item_arena - convenient set_n_backup_statement, restore_backup_statement (nice idea, Sanja) sql/sql_class.h: - Item_arena: backport from 5.0 - allocate_temporary_pool_for_ps_preparing, free_temporary_pool_for_ps_preparing removed. sql/sql_derived.cc: current_statement -> current_arena sql/sql_lex.cc: current_statement -> current_arena sql/sql_parse.cc: Deploy invariant that thd->free_list never contains junk items (backport from 5.0). sql/sql_prepare.cc: - backporting Item_arena - no need to allocate_temporary_pool_for_ps_preparing(). sql/sql_select.cc: Fix for bug#4912 "mysqld crashs in case a statement is executed a second time": if this is the first execute of a prepared statement, negation elimination is done in memory of the prepared statement. sql/sql_union.cc: Backporting Item_arena from 5.0.
2004-08-21 00:02:46 +02:00
Fix for Bug#5034 "prepared "select 1 into @arg15", second execute crashes server": we were deleting lex->result after each execute, but prepared statements assumed that it's left intact. The fix adds cleanup() method to select_result hierarchy, so that result objects can be reused. Plus we now need to delete result objects more wisely. mysql-test/r/ps.result: Test results fixed: test case for bug#5034 mysql-test/t/ps.test: A test case for bug#5034, few followups sql/sql_class.cc: - fix warning in THD::THD - implementation of cleanup() for select_result hierarchy - select_export::send_eof was identical to select_dump::send_eof: moved to the base class select_to_file. - Statement::end_statement() to end lex, free items, and delete possible select_result sql/sql_class.h: - select_result::cleanup() declaration - sql/sql_insert.cc: - implementation of select_insert::cleanup(): currently we always create a new instance of select_insert/ select_create on each execute. sql/sql_lex.cc: - with more complicated logic of freeing lex->result it's easier to have it non-zero only if it points to a valid result. sql/sql_lex.h: Now st_lex::st_lex is not empty. sql/sql_parse.cc: mysql_execute_command(): - delete select_result *result only if it was created in this function. - use end_statement() to cleanup lex and thd in the end of each statement. - no need to save THD::lock if this is explain. This save apparently left from times when derived tables were materialized here, not in open_and_lock_tables. sql/sql_prepare.cc: - call result->cleanup() in reset_stmt_for_execute - now Statement is responsible for freeing its lex->result. sql/sql_select.cc: handle_select(): - don't delete result, it might be needed for next executions - result is never null
2004-08-24 18:17:11 +02:00
prepare stmt1 from "select 1 into @var";
execute stmt1;
execute stmt1;
prepare stmt1 from "create table t1 select 1 as i";
execute stmt1;
drop table t1;
execute stmt1;
prepare stmt1 from "insert into t1 select i from t1";
execute stmt1;
execute stmt1;
prepare stmt1 from "select * from t1 into outfile 'f1.txt'";
execute stmt1;
deallocate prepare stmt1;
drop table t1;
#
# BUG#5242 "Prepared statement names are case sensitive"
#
prepare stmt1 from 'select 1';
prepare STMT1 from 'select 2';
execute sTmT1;
deallocate prepare StMt1;
--error 1243
deallocate prepare Stmt1;
# also check that statement names are in right charset.
set names utf8;
prepare `ü` from 'select 1234';
execute `ü` ;
set names latin1;
execute `<60>`;
set names default;
#
# BUG#4368 "select * from t1 where a like ?" crashes server if a is in utf8
# and ? is in latin1
# Check that Item converting latin1 to utf8 (for LIKE function) is created
# in memory of prepared statement.
#
create table t1 (a varchar(10)) charset=utf8;
insert into t1 (a) values ('yahoo');
set character_set_connection=latin1;
prepare stmt from 'select a from t1 where a like ?';
set @var='google';
execute stmt using @var;
execute stmt using @var;
deallocate prepare stmt;
drop table t1;
#
# BUG#5510 "inserting Null in AutoIncrement primary key Column Fails"
# (prepared statements)
# The cause: misuse of internal MySQL 'Field' API.
#
create table t1 (a bigint(20) not null primary key auto_increment);
insert into t1 (a) values (null);
select * from t1;
prepare stmt from "insert into t1 (a) values (?)";
set @var=null;
execute stmt using @var;
select * from t1;
drop table t1;
#
# check the same for timestamps
#
create table t1 (a timestamp not null);
prepare stmt from "insert into t1 (a) values (?)";
execute stmt using @var;
--disable_result_log
select * from t1;
--enable_result_log
deallocate prepare stmt;
drop table t1;
#
# BUG#5688 "Upgraded 4.1.5 Server seg faults" # (prepared statements)
# The test case speaks for itself.
# Just another place where we used wrong memory root for Items created
# during statement prepare.
#
prepare stmt from "select 'abc' like convert('abc' using utf8)";
execute stmt;
execute stmt;
deallocate prepare stmt;
A fix for Bug#5748 "Prepared statement with BETWEEN and bigint values crashes mysqld": implementation for a generic item tree modifications registry. Every item tree modification which should be rolled back for subsequent execution of a prepared statement or stored procedure should be saved in the registry. All such modifications are rolled back at once during cleanup stage of PS. Actual fix for the bug just adds a call to register modifications to convert_constant_item. Post review fixes implemented. mysql-test/r/ps.result: A fix for bug#5748, test results fixed. mysql-test/t/ps.test: A test case for Bug#5748 "Prepared statement with BETWEEN and bigint values crashes mysqld" sql/item.cc: Fix for Bug#5748 "Prepared statement with BETWEEN and bigint values crashes mysqld": First step in removing up item-specific cleanups: now all such tree modifications should be done using the genericm mechanism implemented in this changeset. sql/item.h: Fix for Bug#5748 "Prepared statement with BETWEEN and bigint values crashes mysqld": no need for an item-specific change record any more. sql/item_cmpfunc.cc: A fix for Bug#5748 "Prepared statement with BETWEEN and bigint values crashes mysqld": register item tree transformation performed by convert_constant_item. sql/sql_class.cc: Implementation for item tree transformations registry. sql/sql_class.h: Declarations, necessary for the tree transformations registry. sql/sql_parse.cc: Assert that the item tree transformations registry is not used for conventional execution. sql/sql_prepare.cc: Use of the item tree modifications registry in prepared statements: rollback all modifications in the end of statement prepare and execute. Also we now always set thd->current_arena to be able to determine that this is an execution of prepared statement inside the registry code. tests/client_test.c: A typo fixed.
2004-10-08 00:21:19 +02:00
#
# BUG#5748 "Prepared statement with BETWEEN and bigint values crashes
# mysqld". Just another place where an item tree modification must be
# rolled back.
#
create table t1 ( a bigint );
prepare stmt from 'select a from t1 where a between ? and ?';
set @a=1;
execute stmt using @a, @a;
execute stmt using @a, @a;
execute stmt using @a, @a;
drop table t1;
deallocate prepare stmt;
A fix and test case for Bug#5987 "subselect in bool function crashes server (prepared statements)": the bug was that all boolean items always recovered its original arguments at statement cleanup stage. This collided with Item_subselect::select_transformer, which tries to permanently change the item tree to use a transformed subselect instead of original one. So we had this call sequence for prepare: mysql_stmt_prepare -> JOIN::prepare -> Item_subselect::fix_fields -> the item tree gets transformed -> Item_bool_rowready_func2::cleanup, item tree is recovered to original state, while it shouldn't have been; mysql_stmt_execute -> attempts to execute a broken tree -> crash. Now instead of bluntly recovering all arguments of bool functions in Item_bool_rowready_func2::cleanup, we recover only those which were changed, and do it in one place. There still would exist a possibility for a collision with subselect tranformation, if permanent and temporary changes were performed at the same stage. But fortunately subselect transformation is always done first, so it doesn't conflict with the optimization done by propogate_cond_constants. Now we have: mysql_stmt_prepare -> JOIN::prepare -> subselect transformation permanently changes the tree -> cleanup doesn't recover anything, because nothing was registered for recovery. mysql_stmt_execute -> JOIN::prepare (the tree is already transformed, so it doesn't change), JOIN::optimize -> propogate_cond_constants -> temporary changes the item tree with constants -> JOIN::execute -> cleanup -> the changes done by propogate_cond_constants are recovered, as they were registered for recovery. mysql-test/r/ps.result: Bug#5987: test results fixed. mysql-test/t/ps.test: A test for bug#5987 "subselect in bool function crashes server (prepared statements)" sql/item.cc: resolve_const_item is now responsible to register all changes of the item tree for recovery sql/item.h: resolve_const_item signagture changed sql/item_cmpfunc.h: Arguments of boolean functions are now recovered using the centralized registry of THD. sql/sql_class.cc: It's crucial to add new items to the beginning of the recovery list, so that the recovery is performed in LIFO mode: otherwise if we change one node of a tree twice, it will be recovered to some intermediate state. sql/sql_select.cc: change_cond_ref_to_const and propogate_cond_constants are now responsible to register all changes of the item tree for recovery. The recovery is done using the centralized THD registry of changed tree items.
2004-10-10 00:39:22 +02:00
#
# Bug #5987 subselect in bool function crashes server (prepared statements):
# don't overwrite transformed subselects with old arguments of a bool
# function.
#
create table t1 (a int);
prepare stmt from "select * from t1 where 1 > (1 in (SELECT * FROM t1))";
execute stmt;
execute stmt;
execute stmt;
drop table t1;
deallocate prepare stmt;
#
# Test case for Bug#6042 "constants propogation works only once (prepared
# statements): check that the query plan changes whenever we change
# placeholder value.
#
create table t1 (a int, b int);
insert into t1 (a, b) values (1,1), (1,2), (2,1), (2,2);
prepare stmt from
"explain select * from t1 where t1.a=2 and t1.a=t1.b and t1.b > 1 + ?";
--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
set @v=5;
execute stmt using @v;
--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
set @v=0;
execute stmt using @v;
--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
set @v=5;
execute stmt using @v;
drop table t1;
deallocate prepare stmt;
A fix and test case for Bug#5985 ""prepare stmt from "select rand(?)" crashes server." The fix makes Item_func_rand prepared-statements aware plus it fixes the case when RAND is used in prepared statements and replication is on (as well as several similar issues). Until now we did not reset THD before every execution of a prepared statement, so if some execution had set thd->time_zone_used or thd->rand_used they would not be reset until next mysql_parse. Some of post-review fixes done. mysql-test/r/ps.result: A test case for Bug#5985: test results fixed. mysql-test/t/ps.test: A test case for Bug#5985 "prepare stmt from "select rand(?)" crashes server." sql/item_func.cc: Actual fix for Bug#5985: Item_func_rand rewritten to be prepared statements aware. sql/item_func.h: Actual fix for Bug#5985: Item_func_rand rewritten to be prepared statements aware. sql/mysql_priv.h: We need a separate call to reset THD state before every execute of a prepared statement. Otherwise things like THD->user_var_events are never cleaned up and bloat binary log (as the list of events grows from execution to execution). sql/sql_class.cc: Statement::end_statement -> THD::end_statement() (a leftover from some design change which is not to pushed now, but the leftover is to be pushed). sql/sql_class.h: Statement::end_statement -> THD::end_statement() (a leftover from some design change which is not to pushed now, but the leftover is to be pushed). sql/sql_lex.cc: Move the part responsible for initializing LEX from mysql_init_query to lex_start. sql/sql_lex.h: All lex-related initialization is now in lex_start. Move thd->select_number to lex->select_number to be able to use it easily in lex_start. sql/sql_parse.cc: Split mysql_init_query into two functions: mysql_reset_thd_for_next_query, which is used in PS and conventional execution, and lex_start, used only when we want to parse something. Fix init_connect to use initialized THD. sql/sql_prepare.cc: Deploy mysql_reset_thd_for_next_query to reset THD state before execution of a prepared statement. Normally this should have been added to just one place, but we have to reset thd before assigning placeholders from variables, thus we can't do that in execute_stmt (yuck).
2004-10-14 00:53:59 +02:00
#
# A test case for Bug#5985 prepare stmt from "select rand(?)" crashes
# server. Check that Item_func_rand is prepared-statements friendly.
#
create table t1 (a int);
insert into t1 (a) values (1), (2), (3), (4);
set @precision=10000000000;
--replace_column 1 - 3 -
select rand(),
cast(rand(10)*@precision as unsigned integer),
cast(rand(a)*@precision as unsigned integer) from t1;
prepare stmt from
"select rand(),
cast(rand(10)*@precision as unsigned integer),
cast(rand(a)*@precision as unsigned integer),
cast(rand(?)*@precision as unsigned integer) from t1";
set @var=1;
--replace_column 1 - 3 -
execute stmt using @var;
set @var=2;
--replace_column 1 -
execute stmt using @var;
set @var=3;
--replace_column 1 -
execute stmt using @var;
drop table t1;
deallocate prepare stmt;
2004-10-22 12:47:35 +02:00
#
# A test case for Bug#6050 "EXECUTE stmt reports ambiguous fieldnames with
# identical tables from different schemata"
# Check that field name resolving in prepared statements works OK.
#
create database mysqltest1;
create table t1 (a int);
create table mysqltest1.t1 (a int);
select * from t1, mysqltest1.t1;
prepare stmt from "select * from t1, mysqltest1.t1";
execute stmt;
execute stmt;
execute stmt;
drop table t1;
drop table mysqltest1.t1;
drop database mysqltest1;
deallocate prepare stmt;
select '1.1' as a, '1.2' as a UNION SELECT '2.1', '2.2';
prepare stmt from
"select '1.1' as a, '1.2' as a UNION SELECT '2.1', '2.2'";
execute stmt;
execute stmt;
execute stmt;
deallocate prepare stmt;