summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am7
-rw-r--r--include/my_global.h2
-rw-r--r--include/my_sys.h3
-rw-r--r--libmysqld/lib_sql.cc2
-rw-r--r--mysql-test/r/grant.result6
-rw-r--r--mysql-test/r/log_state.result21
-rw-r--r--mysql-test/r/ps_1general.result19
-rw-r--r--mysql-test/r/ps_ddl.result5099
-rw-r--r--mysql-test/r/ps_ddl1.result482
-rw-r--r--mysql-test/r/query_cache_merge.result1
-rw-r--r--mysql-test/r/trigger.result1
-rw-r--r--mysql-test/r/variables.result10
-rw-r--r--mysql-test/t/disabled.def1
-rw-r--r--mysql-test/t/grant.test6
-rw-r--r--mysql-test/t/log_state.test28
-rw-r--r--mysql-test/t/ps_1general.test5
-rw-r--r--mysql-test/t/ps_ddl.test2650
-rw-r--r--mysql-test/t/ps_ddl1.test398
-rw-r--r--mysql-test/t/query_cache_merge.test10
-rw-r--r--mysql-test/t/trigger.test7
-rw-r--r--mysql-test/t/variables.test17
-rw-r--r--mysys/my_alloc.c2
-rw-r--r--sql/item.cc43
-rw-r--r--sql/item.h1
-rw-r--r--sql/my_decimal.h8
-rw-r--r--sql/mysql_priv.h40
-rw-r--r--sql/mysqld.cc15
-rw-r--r--sql/opt_range.cc3
-rw-r--r--sql/set_var.cc70
-rw-r--r--sql/set_var.h18
-rw-r--r--sql/share/errmsg.txt7
-rw-r--r--sql/sp.cc204
-rw-r--r--sql/sp.h3
-rw-r--r--sql/sp_head.cc21
-rw-r--r--sql/sql_acl.cc7
-rw-r--r--sql/sql_base.cc200
-rw-r--r--sql/sql_class.cc16
-rw-r--r--sql/sql_class.h78
-rw-r--r--sql/sql_cursor.cc3
-rw-r--r--sql/sql_parse.cc81
-rw-r--r--sql/sql_prepare.cc638
-rw-r--r--sql/sql_table.cc3
-rw-r--r--sql/sql_update.cc6
-rw-r--r--sql/sql_yacc.yy14
-rw-r--r--sql/table.h130
-rw-r--r--storage/myisam/mi_create.c1
-rw-r--r--tests/mysql_client_test.c121
47 files changed, 5535 insertions, 4973 deletions
diff --git a/Makefile.am b/Makefile.am
index 60b4f9bd07c..55f54476212 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -66,7 +66,7 @@ tags:
test-pl test-force-pl test-full-pl test-force-full-pl test-force-pl-mem \
test-unit test-ps test-nr test-pr test-ns test-binlog-statement \
test-ext-funcs test-ext-rpl test-ext-partitions test-ext-jp \
- test-ext-stress test-ext test-embedded \
+ test-ext-stress test-ext test-embedded test-reprepare \
test-fast test-fast-cursor test-fast-view test-fast-prepare \
test-full-qa
@@ -111,6 +111,11 @@ test-embedded:
echo "no program found for 'embedded' tests - skipped testing" ; \
fi
+test-reprepare:
+ cd mysql-test ; \
+ @PERL@ ./mysql-test-run.pl $(force) $(mem) --ps-protocol \
+ --mysqld=--debug=+d,reprepare_each_statement
+
test: test-unit test-ns test-pr
test-full: test test-nr test-ps
diff --git a/include/my_global.h b/include/my_global.h
index a9e381ee66f..6cfc4d67305 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -570,7 +570,7 @@ typedef unsigned short ushort;
#define CMP_NUM(a,b) (((a) < (b)) ? -1 : ((a) == (b)) ? 0 : 1)
#define sgn(a) (((a) < 0) ? -1 : ((a) > 0) ? 1 : 0)
-#define swap_variables(t, a, b) { register t dummy; dummy= a; a= b; b= dummy; }
+#define swap_variables(t, a, b) { t dummy; dummy= a; a= b; b= dummy; }
#define test(a) ((a) ? 1 : 0)
#define set_if_bigger(a,b) do { if ((a) < (b)) (a)=(b); } while(0)
#define set_if_smaller(a,b) do { if ((a) > (b)) (a)=(b); } while(0)
diff --git a/include/my_sys.h b/include/my_sys.h
index eccb61f5b29..09c768cadb7 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -90,6 +90,9 @@ extern int NEAR my_errno; /* Last error in mysys */
#define ME_COLOUR1 ((1 << ME_HIGHBYTE)) /* Possibly error-colours */
#define ME_COLOUR2 ((2 << ME_HIGHBYTE))
#define ME_COLOUR3 ((3 << ME_HIGHBYTE))
+#define ME_FATALERROR 1024 /* Fatal statement error */
+#define ME_NO_WARNING_FOR_ERROR 2048 /* Don't push a warning for error */
+#define ME_NO_SP_HANDLER 4096 /* Don't call stored routine error handlers */
/* Bits in last argument to fn_format */
#define MY_REPLACE_DIR 1 /* replace dir in name with 'dir' */
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 5cce8c6147c..591b76f61ad 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -285,7 +285,7 @@ static int emb_stmt_execute(MYSQL_STMT *stmt)
my_bool res;
int4store(header, stmt->stmt_id);
- header[4]= (uchar)stmt->flags;
+ header[4]= (uchar) stmt->flags;
thd= (THD*)stmt->mysql->thd;
thd->client_param_count= stmt->param_count;
thd->client_params= stmt->params;
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result
index a56cce50259..16be3eb966d 100644
--- a/mysql-test/r/grant.result
+++ b/mysql-test/r/grant.result
@@ -1218,6 +1218,12 @@ DROP USER mysqltest_1@localhost;
DROP DATABASE db27878;
use test;
DROP TABLE t1;
+#
+# Bug#33275 Server crash when creating temporary table mysql.user
+#
+CREATE TEMPORARY TABLE mysql.user (id INT);
+FLUSH PRIVILEGES;
+DROP TABLE mysql.user;
drop table if exists test;
Warnings:
Note 1051 Unknown table 'test'
diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result
index 8ecfe3b2094..c293956148f 100644
--- a/mysql-test/r/log_state.result
+++ b/mysql-test/r/log_state.result
@@ -249,4 +249,25 @@ set global slow_query_log_file= NULL;
ERROR 42000: Variable 'slow_query_log_file' can't be set to the value of 'NULL'
set global general_log_file= @old_general_log_file;
set global slow_query_log_file= @old_slow_query_log_file;
+
+# --
+# -- Bug#32748: Inconsistent handling of assignments to
+# -- general_log_file/slow_query_log_file.
+# --
+
+SET @general_log_file_saved = @@global.general_log_file;
+SET @slow_query_log_file_saved = @@global.slow_query_log_file;
+
+SET GLOBAL general_log_file = 'bug32748.query.log';
+SET GLOBAL slow_query_log_file = 'bug32748.slow.log';
+
+SHOW VARIABLES LIKE '%log_file';
+Variable_name Value
+general_log_file bug32748.query.log
+slow_query_log_file bug32748.slow.log
+
+SET GLOBAL general_log_file = @general_log_file_saved;
+SET GLOBAL slow_query_log_file = @slow_query_log_file_saved;
+
+# -- End of Bug#32748.
End of 5.1 tests
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index 1c5f0e4dfd6..33849eefe7a 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -143,32 +143,32 @@ b char(30)
);
insert into t5( a, b, c) values( 9, 'recreated table', 9);
execute stmt2 ;
-a b c
-9 recreated table 9
+a c b
+9 9 recreated table
drop table t5 ;
create table t5
(
a int primary key,
b char(30),
c int,
-d timestamp default current_timestamp
+d timestamp default '2008-02-23 09:23:45'
);
insert into t5( a, b, c) values( 9, 'recreated table', 9);
execute stmt2 ;
-a b c
-9 recreated table 9
+a b c d
+9 recreated table 9 2008-02-23 09:23:45
drop table t5 ;
create table t5
(
a int primary key,
-d timestamp default current_timestamp,
+d timestamp default '2008-02-23 09:23:45',
b char(30),
c int
);
insert into t5( a, b, c) values( 9, 'recreated table', 9);
execute stmt2 ;
-a b c
-9 recreated table 9
+a d b c
+9 2008-02-23 09:23:45 recreated table 9
drop table t5 ;
create table t5
(
@@ -189,7 +189,8 @@ f3 int
);
insert into t5( f1, f2, f3) values( 9, 'recreated table', 9);
execute stmt2 ;
-ERROR 42S22: Unknown column 'test.t5.a' in 'field list'
+f1 f2 f3
+9 recreated table 9
drop table t5 ;
prepare stmt1 from ' select * from t1 where a <= 2 ' ;
execute stmt1 ;
diff --git a/mysql-test/r/ps_ddl.result b/mysql-test/r/ps_ddl.result
index 531d29d219e..9e1db062368 100644
--- a/mysql-test/r/ps_ddl.result
+++ b/mysql-test/r/ps_ddl.result
@@ -1,543 +1,252 @@
-SELECT VARIABLE_VALUE from
-INFORMATION_SCHEMA.SESSION_STATUS where variable_name='COM_STMT_REPREPARE'
-into @base_count ;
-set @expected = 0;
+drop temporary table if exists t1, t2, t3;
+drop table if exists t1, t2, t3;
+drop procedure if exists p_verify_reprepare_count;
+drop procedure if exists p1;
+drop function if exists f1;
+drop view if exists v1, v2;
+create procedure p_verify_reprepare_count(expected int)
+begin
+declare old_reprepare_count int default @reprepare_count;
+select variable_value from
+information_schema.session_status where
+variable_name='com_stmt_reprepare'
+ into @reprepare_count;
+if old_reprepare_count + expected <> @reprepare_count then
+select concat("Expected: ", expected,
+", actual: ", @reprepare_count - old_reprepare_count)
+as "ERROR";
+else
+select '' as "SUCCESS";
+end if;
+end|
+set @reprepare_count= 0;
+flush status;
=====================================================================
-Testing 1: NOTHING -> TABLE transitions
+Part 1: NOTHING -> TABLE transitions
=====================================================================
-drop table if exists t1;
-prepare stmt from 'select * from t1';
+prepare stmt from "select * from t1";
ERROR 42S02: Table 'test.t1' doesn't exist
=====================================================================
-Testing 2: NOTHING -> TEMPORARY TABLE transitions
+Part 2: NOTHING -> TEMPORARY TABLE transitions
=====================================================================
=====================================================================
-Testing 3: NOTHING -> VIEW transitions
+Part 3: NOTHING -> VIEW transitions
=====================================================================
=====================================================================
-Testing 4: TABLE -> NOTHING transitions
+Part 4: TABLE -> NOTHING transitions
=====================================================================
-drop table if exists t4;
-create table t4(a int);
-prepare stmt from 'select * from t4';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t4;
-execute stmt;
-ERROR 42S02: Table 'test.t4' doesn't exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-ERROR 42S02: Table 'test.t4' doesn't exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+# Test 4-a: select ... from <table>
+create table t1 (a int);
+prepare stmt from "select * from t1";
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+execute stmt;
+ERROR 42S02: Table 'test.t1' doesn't exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+ERROR 42S02: Table 'test.t1' doesn't exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+deallocate prepare stmt;
+# Test 4-b: TABLE -> NOTHING by renaming the table
+create table t1 (a int);
+prepare stmt from "select * from t1";
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+rename table t1 to t2;
+execute stmt;
+ERROR 42S02: Table 'test.t1' doesn't exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+ERROR 42S02: Table 'test.t1' doesn't exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+deallocate prepare stmt;
+drop table t2;
=====================================================================
-Testing 5: TABLE -> TABLE (DDL) transitions
+Part 5: TABLE -> TABLE (DDL) transitions
=====================================================================
-drop table if exists t5;
-create table t5(a int);
-prepare stmt from 'select a from t5';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t5 add column (b int);
-set @expected = @expected + 1;
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t5;
+create table t1 (a int);
+prepare stmt from "select a from t1";
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+alter table t1 add column (b int);
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+deallocate prepare stmt;
=====================================================================
-Testing 6: TABLE -> TABLE (TRIGGER) transitions
+Part 6: TABLE -> TABLE (TRIGGER) transitions
=====================================================================
-drop table if exists t6;
-create table t6(a int);
-prepare stmt from 'insert into t6(a) value (?)';
+# Test 6-a: adding a relevant trigger
+create table t1 (a int);
+prepare stmt from "insert into t1 (a) value (?)";
set @val=1;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
+create trigger t1_bi before insert on t1 for each row
+set @message= new.a;
set @val=2;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-create trigger t6_bi before insert on t6 for each row
-begin
-set @message= "t6_bi";
-end
-$$
-set @message="none";
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select @message;
+@message
+2
set @val=3;
-set @expected = @expected + 1;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
select @message;
@message
-t6_bi
+3
+prepare stmt from "insert into t1 (a) value (?)";
set @val=4;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
select @message;
@message
-t6_bi
-prepare stmt from 'insert into t6(a) value (?)';
-set @message="none";
+4
+# Test 6-b: adding an irrelevant trigger
+create trigger t1_bd before delete on t1 for each row
+set @message= old.a;
set @val=5;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(1);
+SUCCESS
+
select @message;
@message
-t6_bi
-set @message="none";
+5
set @val=6;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
select @message;
@message
-t6_bi
-create trigger t6_bd before delete on t6 for each row
-begin
-set @message= "t6_bd";
-end
-$$
-set @message="none";
+6
+prepare stmt from "insert into t1 (a) value (?)";
set @val=7;
-set @expected = @expected + 1;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
select @message;
@message
-t6_bi
-set @message="none";
+7
+# Test 6-c: changing a relevant trigger
+drop trigger t1_bi;
+create trigger t1_bi before insert on t1 for each row
+set @message= concat("new trigger: ", new.a);
set @val=8;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(1);
+SUCCESS
+
select @message;
@message
-t6_bi
-prepare stmt from 'insert into t6(a) value (?)';
-set @message="none";
+new trigger: 8
set @val=9;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
select @message;
@message
-t6_bi
-set @message="none";
+new trigger: 9
+prepare stmt from "insert into t1 (a) value (?)";
set @val=10;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
select @message;
@message
-t6_bi
-drop trigger t6_bi;
-create trigger t6_bi before insert on t6 for each row
-begin
-set @message= "t6_bi (2)";
-end
-$$
-set @message="none";
+new trigger: 10
+# Test 6-d: changing an irrelevant trigger
+drop trigger t1_bd;
set @val=11;
-set @expected = @expected + 1;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(1);
+SUCCESS
+
select @message;
@message
-t6_bi (2)
+new trigger: 11
+Test 6-e: removing a relevant trigger
+drop trigger t1_bi;
set @val=12;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(1);
+SUCCESS
+
select @message;
@message
-t6_bi (2)
-prepare stmt from 'insert into t6(a) value (?)';
-set @message="none";
+new trigger: 11
set @val=13;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
select @message;
@message
-t6_bi (2)
-set @message="none";
+new trigger: 11
+prepare stmt from "insert into t1 (a) value (?)";
set @val=14;
execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select @message;
-@message
-t6_bi (2)
-drop trigger t6_bd;
-create trigger t6_bd before delete on t6 for each row
-begin
-set @message= "t6_bd (2)";
-end
-$$
-set @message="none";
-set @val=15;
-set @expected = @expected + 1;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select @message;
-@message
-t6_bi (2)
-set @message="none";
-set @val=16;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select @message;
-@message
-t6_bi (2)
-prepare stmt from 'insert into t6(a) value (?)';
-set @message="none";
-set @val=17;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select @message;
-@message
-t6_bi (2)
-set @message="none";
-set @val=18;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select @message;
-@message
-t6_bi (2)
-drop trigger t6_bi;
-set @message="none";
-set @val=19;
-set @expected = @expected + 1;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select @message;
-@message
-none
-set @val=20;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select @message;
-@message
-none
-prepare stmt from 'insert into t6(a) value (?)';
-set @message="none";
-set @val=21;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
select @message;
@message
-none
-set @val=22;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select @message;
-@message
-none
-drop trigger t6_bd;
-set @val=23;
-set @expected = @expected + 1;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select @message;
-@message
-none
-set @val=24;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select @message;
-@message
-none
-select * from t6 order by a;
+new trigger: 11
+select * from t1 order by a;
a
1
2
@@ -553,1443 +262,815 @@ a
12
13
14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-drop table t6;
+drop table t1;
+deallocate prepare stmt;
=====================================================================
-Testing 7: TABLE -> TABLE (TRIGGER dependencies) transitions
+Part 7: TABLE -> TABLE (TRIGGER dependencies) transitions
=====================================================================
-drop table if exists t7_proc;
-drop table if exists t7_func;
-drop table if exists t7_view;
-drop table if exists t7_table;
-drop table if exists t7_dependent_table;
-drop table if exists t7_table_trigger;
-drop table if exists t7_audit;
-drop procedure if exists audit_proc;
-drop function if exists audit_func;
-drop view if exists audit_view;
-create table t7_proc(a int);
-create table t7_func(a int);
-create table t7_view(a int);
-create table t7_table(a int);
-create table t7_table_trigger(a int);
-create table t7_audit(old_a int, new_a int, reason varchar(50));
-create table t7_dependent_table(old_a int, new_a int, reason varchar(50));
-create procedure audit_proc(a int)
-insert into t7_audit values (NULL, a, "proc v1");
-create function audit_func() returns varchar(50)
-return "func v1";
-create view audit_view as select "view v1" as reason from dual;
-create trigger t7_proc_bi before insert on t7_proc for each row
-call audit_proc(NEW.a);
-create trigger t7_func_bi before insert on t7_func for each row
-insert into t7_audit values (NULL, NEW.a, audit_func());
-create trigger t7_view_bi before insert on t7_view for each row
-insert into t7_audit values (NULL, NEW.a, (select reason from audit_view));
-create trigger t7_table_bi before insert on t7_table for each row
-insert into t7_dependent_table values (NULL, NEW.a, "dependent table");
-create trigger t7_table_trigger_bi before insert on t7_dependent_table
-for each row set NEW.reason="trigger v1";
-prepare stmt_proc from 'insert into t7_proc(a) value (?)';
-set @val=101;
-execute stmt_proc using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=102;
-execute stmt_proc using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop procedure audit_proc;
-create procedure audit_proc(a int)
-insert into t7_audit values (NULL, a, "proc v2");
-set @val=103;
-set @expected = @expected + 1;
-execute stmt_proc using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=104;
-execute stmt_proc using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-prepare stmt_func from 'insert into t7_func(a) value (?)';
-set @val=201;
-execute stmt_func using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=202;
-execute stmt_func using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop function audit_func;
-create function audit_func() returns varchar(50)
-return "func v2";
-set @val=203;
-set @expected = @expected + 1;
-execute stmt_func using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=204;
-execute stmt_func using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-prepare stmt_view from 'insert into t7_view(a) value (?)';
-set @val=301;
-execute stmt_view using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=302;
-execute stmt_view using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop view audit_view;
-create view audit_view as select "view v2" as reason from dual;
-set @val=303;
-set @expected = @expected + 1;
-execute stmt_view using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=304;
-execute stmt_view using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-prepare stmt_table from 'insert into t7_table(a) value (?)';
-set @val=401;
-execute stmt_table using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=402;
-execute stmt_table using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t7_dependent_table add column comments varchar(100) default NULL;
-set @val=403;
-set @expected = @expected + 1;
-execute stmt_table using @val;
-ERROR 21S01: Column count doesn't match value count at row 1
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=404;
-set @expected = @expected + 1;
-execute stmt_table using @val;
-ERROR 21S01: Column count doesn't match value count at row 1
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t7_dependent_table drop column comments;
-set @val=405;
-set @expected = @expected + 1;
-execute stmt_table using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=406;
-execute stmt_table using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-prepare stmt_table_trigger from 'insert into t7_table(a) value (?)';
-set @val=501;
-execute stmt_table_trigger using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=502;
-execute stmt_table_trigger using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop trigger t7_table_trigger_bi;
-create trigger t7_table_trigger_bi before insert on t7_dependent_table
-for each row set NEW.reason="trigger v2";
-set @val=503;
-set @expected = @expected + 1;
-execute stmt_table_trigger using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=504;
-execute stmt_table_trigger using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select * from t7_audit order by new_a;
-old_a new_a reason
-NULL 101 proc v1
-NULL 102 proc v1
-NULL 103 proc v2
-NULL 104 proc v2
-NULL 201 func v1
-NULL 202 func v1
-NULL 203 func v2
-NULL 204 func v2
-NULL 301 view v1
-NULL 302 view v1
-NULL 303 view v1
-NULL 304 view v1
-select * from t7_dependent_table order by new_a;
-old_a new_a reason
-NULL 401 trigger v1
-NULL 402 trigger v1
-NULL 405 trigger v1
-NULL 406 trigger v1
-NULL 501 trigger v1
-NULL 502 trigger v1
-NULL 503 trigger v2
-NULL 504 trigger v2
-drop table t7_proc;
-drop table t7_func;
-drop table t7_view;
-drop table t7_table;
-drop table t7_dependent_table;
-drop table t7_table_trigger;
-drop table t7_audit;
-drop procedure audit_proc;
-drop function audit_func;
-drop view audit_view;
+# Test 7-a: dependent PROCEDURE has changed
+#
+# Note, this scenario is not supported, subject of Bug#12093
+#
+create table t1 (a int);
+create trigger t1_ai after insert on t1 for each row
+call p1(new.a);
+create procedure p1(a int) begin end;
+prepare stmt from "insert into t1 (a) values (?)";
+set @var= 1;
+execute stmt using @var;
+drop procedure p1;
+create procedure p1 (a int) begin end;
+set @var= 2;
+execute stmt using @var;
+ERROR 42000: PROCEDURE test.p1 does not exist
+# Cleanup
+drop procedure p1;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# Test 7-b: dependent FUNCTION has changed
+#
+# Note, this scenario is not supported, subject of Bug#12093
+#
+drop trigger t1_ai;
+create trigger t1_ai after insert on t1 for each row
+select f1(new.a+1) into @var;
+create function f1 (a int) returns int return a;
+prepare stmt from "insert into t1(a) values (?)";
+set @var=3;
+execute stmt using @var;
+select @var;
+@var
+4
+drop function f1;
+create function f1 (a int) returns int return 0;
+execute stmt using @var;
+ERROR 42000: FUNCTION test.f1 does not exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop function f1;
+deallocate prepare stmt;
+# Test 7-c: dependent VIEW has changed
+#
+# Note, this scenario is not functioning correctly, see
+# Bug#33255 Trigger using views and view ddl : corrupted triggers
+# and Bug #33000 Triggers do not detect changes in meta-data.
+#
+drop trigger t1_ai;
+create table t2 (a int unique);
+create table t3 (a int unique);
+create view v1 as select a from t2;
+create trigger t1_ai after insert on t1 for each row
+insert into v1 (a) values (new.a);
+# Demonstrate that the same bug is present
+# without prepared statements
+insert into t1 (a) values (5);
+select * from t2;
+a
+5
+select * from t3;
+a
+drop view v1;
+create view v1 as select a from t3;
+insert into t1 (a) values (6);
+ERROR 42S02: Table 'test.t2' doesn't exist
+flush table t1;
+insert into t1 (a) values (6);
+select * from t2;
+a
+5
+select * from t3;
+a
+6
+prepare stmt from "insert into t1 (a) values (?)";
+set @var=7;
+execute stmt using @var;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+select * from t3;
+a
+6
+7
+select * from t2;
+a
+5
+drop view v1;
+create view v1 as select a from t2;
+set @var=8;
+execute stmt using @var;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+#
+# Sic: the insert went into t3, even though the view now
+# points at t2. This is because neither the merged view
+# nor its prelocking list are affected by view DDL
+# The binary log is of course wrong, since it is not
+# using prepared statements
+#
+select * from t2;
+a
+5
+select * from t3;
+a
+6
+7
+8
+flush table t1;
+set @var=9;
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select * from t2;
+a
+5
+9
+select * from t3;
+a
+6
+7
+8
+drop view v1;
+drop table t1,t2,t3;
+# Test 7-d: dependent TABLE has changed
+create table t1 (a int);
+create trigger t1_ai after insert on t1 for each row
+insert into t2 (a) values (new.a);
+create table t2 (a int);
+prepare stmt from "insert into t1 (a) values (?)";
+set @var=1;
+execute stmt using @var;
+alter table t2 add column comment varchar(255);
+set @var=2;
+# Since the dependent table is tracked in the prelocked
+# list of the prepared statement, invalidation happens
+# and the statement is re-prepared. This is an unnecessary
+# side effect, since the statement that *is* dependent
+# on t2 definition is inside the trigger, and it is currently
+# not reprepared (see the previous test case).
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select * from t1;
+a
+1
+2
+select * from t2;
+a comment
+1 NULL
+2 NULL
+drop table t1,t2;
+# Test 7-e: dependent TABLE TRIGGER has changed
+create table t1 (a int);
+create trigger t1_ai after insert on t1 for each row
+insert into t2 (a) values (new.a);
+create table t2 (a int unique);
+create trigger t2_ai after insert on t2 for each row
+insert into t3 (a) values (new.a);
+create table t3 (a int unique);
+create table t4 (a int unique);
+insert into t1 (a) values (1);
+select * from t1 join t2 on (t1.a=t2.a) join t3 on (t2.a=t3.a);
+a a a
+1 1 1
+drop trigger t2_ai;
+create trigger t2_ai after insert on t2 for each row
+insert into t4 (a) values (new.a);
+insert into t1 (a) values (2);
+select * from t1 join t2 on (t1.a=t2.a) join t4 on (t2.a=t4.a);
+a a a
+2 2 2
+prepare stmt from "insert into t1 (a) values (?)";
+set @var=3;
+execute stmt using @var;
+select * from t1 join t2 on (t1.a=t2.a) join t4 on (t2.a=t4.a);
+a a a
+2 2 2
+3 3 3
+drop trigger t2_ai;
+create trigger t2_ai after insert on t2 for each row
+insert into t3 (a) values (new.a);
+set @var=4;
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select * from t1 join t2 on (t1.a=t2.a) join t3 on (t2.a=t3.a);
+a a a
+1 1 1
+4 4 4
+select * from t1 join t2 on (t1.a=t2.a) join t4 on (t2.a=t4.a);
+a a a
+2 2 2
+3 3 3
+drop table t1, t2, t3, t4;
+deallocate prepare stmt;
=====================================================================
-Testing 8: TABLE -> TEMPORARY TABLE transitions
+Part 8: TABLE -> TEMPORARY TABLE transitions
=====================================================================
-drop table if exists t8;
-create table t8(a int);
-prepare stmt from 'select * from t8';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t8;
-create temporary table t8(a int);
-set @expected = @expected + 1;
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t8;
+# Test 8-a: base table used recreated as temporary table
+create table t1 (a int);
+prepare stmt from "select * from t1";
+execute stmt;
+a
+drop table t1;
+create temporary table t1 (a int);
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+deallocate prepare stmt;
+# Test 8-b: temporary table has precedence over base table with same name
+create table t1 (a int);
+prepare stmt from 'select count(*) from t1';
+execute stmt;
+count(*)
+0
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+count(*)
+0
+call p_verify_reprepare_count(0);
+SUCCESS
+
+create temporary table t1 AS SELECT 1;
+execute stmt;
+count(*)
+1
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+count(*)
+1
+call p_verify_reprepare_count(0);
+SUCCESS
+
+deallocate prepare stmt;
+drop temporary table t1;
+drop table t1;
=====================================================================
-Testing 9: TABLE -> VIEW transitions
+Part 9: TABLE -> VIEW transitions
=====================================================================
-drop table if exists t9;
-drop table if exists t9_b;
-create table t9(a int);
-create table t9_b(a int);
-prepare stmt from 'select * from t9';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t9;
-create view t9 as select * from t9_b;
-set @expected = @expected + 1;
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop view t9;
-drop table t9_b;
+create table t1 (a int);
+prepare stmt from "select * from t1";
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+create table t2 (a int);
+create view t1 as select * from t2;
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+drop view t1;
+drop table t2;
+deallocate prepare stmt;
=====================================================================
-Testing 10: TEMPORARY TABLE -> NOTHING transitions
+Part 10: TEMPORARY TABLE -> NOTHING transitions
=====================================================================
-drop temporary table if exists t10;
-create temporary table t10(a int);
-prepare stmt from 'select * from t10';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop temporary table t10;
-execute stmt;
-ERROR 42S02: Table 'test.t10' doesn't exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-ERROR 42S02: Table 'test.t10' doesn't exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+create temporary table t1 (a int);
+prepare stmt from "select * from t1";
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop temporary table t1;
+execute stmt;
+ERROR 42S02: Table 'test.t1' doesn't exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+deallocate prepare stmt;
=====================================================================
-Testing 11: TEMPORARY TABLE -> TABLE transitions
+Part 11: TEMPORARY TABLE -> TABLE transitions
=====================================================================
-drop table if exists t11;
-drop temporary table if exists t11;
-create table t11(a int);
-insert into t11(a) value (1);
-create temporary table t11(a int);
-prepare stmt from 'select * from t11';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop temporary table t11;
-set @expected = @expected + 1;
+# Test 11-a: temporary table replaced by base table
+create table t1 (a int);
+insert into t1 (a) value (1);
+create temporary table t1 (a int);
+prepare stmt from "select * from t1";
execute stmt;
a
-1
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop temporary table t1;
execute stmt;
a
1
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select * from t11;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select * from t1;
a
1
-drop table t11;
+drop table t1;
+deallocate prepare stmt;
+# Test 11-b: temporary table has precedence over base table with same name
+# temporary table disappears
+create table t1 (a int);
+create temporary table t1 as select 1 as a;
+prepare stmt from "select count(*) from t1";
+execute stmt;
+count(*)
+1
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+count(*)
+1
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop temporary table t1;
+execute stmt;
+count(*)
+0
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+count(*)
+0
+call p_verify_reprepare_count(0);
+SUCCESS
+
+deallocate prepare stmt;
+drop table t1;
=====================================================================
-Testing 12: TEMPORARY TABLE -> TEMPORARY TABLE (DDL) transitions
+Part 12: TEMPORARY TABLE -> TEMPORARY TABLE (DDL) transitions
=====================================================================
-drop temporary table if exists t12;
-create temporary table t12(a int);
-prepare stmt from 'select a from t12';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop temporary table t12;
-create temporary table t12(a int, b int);
-set @expected = @expected + 1;
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select * from t12;
+create temporary table t1 (a int);
+prepare stmt from "select a from t1";
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop temporary table t1;
+create temporary table t1 (a int, b int);
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select * from t1;
a b
-drop table t12;
+drop temporary table t1;
+deallocate prepare stmt;
=====================================================================
-Testing 13: TEMPORARY TABLE -> VIEW transitions
+Part 13: TEMPORARY TABLE -> VIEW transitions
=====================================================================
-drop temporary table if exists t13;
-drop table if exists t13_b;
-create temporary table t13(a int);
-create table t13_b(a int);
-prepare stmt from 'select * from t13';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop temporary table t13;
-create view t13 as select * from t13_b;
-set @expected = @expected + 1;
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop view t13;
-drop table t13_b;
+create temporary table t1 (a int);
+create table t2 (a int);
+prepare stmt from "select * from t1";
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop temporary table t1;
+create view t1 as select * from t2;
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+drop view t1;
+drop table t2;
+deallocate prepare stmt;
=====================================================================
-Testing 14: VIEW -> NOTHING transitions
+Part 14: VIEW -> NOTHING transitions
=====================================================================
-drop view if exists t14;
-drop table if exists t14_b;
-create table t14_b(a int);
-create view t14 as select * from t14_b;
-prepare stmt from 'select * from t14';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop view t14;
-set @expected = @expected + 1;
-execute stmt;
-ERROR 42S02: Table 'test.t14' doesn't exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @expected = @expected + 1;
-execute stmt;
-ERROR 42S02: Table 'test.t14' doesn't exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t14_b;
+create table t2 (a int);
+create view t1 as select * from t2;
+prepare stmt from "select * from t1";
+execute stmt;
+a
+drop view t1;
+execute stmt;
+ERROR 42S02: Table 'test.t1' doesn't exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+ERROR 42S02: Table 'test.t1' doesn't exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t2;
+deallocate prepare stmt;
=====================================================================
-Testing 15: VIEW -> TABLE transitions
+Part 15: VIEW -> TABLE transitions
=====================================================================
-drop view if exists t15;
-drop table if exists t15_b;
-create table t15_b(a int);
-create view t15 as select * from t15_b;
-prepare stmt from 'select * from t15';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop view t15;
-create table t15(a int);
-set @expected = @expected + 1;
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t15_b;
-drop table t15;
+create table t2 (a int);
+create view t1 as select * from t2;
+prepare stmt from "select * from t1";
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop view t1;
+create table t1 (a int);
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+drop table t2;
+drop table t1;
+deallocate prepare stmt;
=====================================================================
-Testing 16: VIEW -> TEMPORARY TABLE transitions
+Part 16: VIEW -> TEMPORARY TABLE transitions
=====================================================================
-drop view if exists t16;
-drop table if exists t16_b;
-create table t16_b(a int);
-create view t16 as select * from t16_b;
-prepare stmt from 'select * from t16';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop view t16;
-create temporary table t16(a int);
-set @expected = @expected + 1;
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t16_b;
-drop temporary table t16;
+create table t2 (a int);
+insert into t2 (a) values (1);
+create view t1 as select * from t2;
+prepare stmt from "select * from t1";
+execute stmt;
+a
+1
+call p_verify_reprepare_count(0);
+SUCCESS
+
+create temporary table t1 (a int);
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+drop view t1;
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t2;
+drop temporary table t1;
+deallocate prepare stmt;
=====================================================================
-Testing 17: VIEW -> VIEW (DDL) transitions
+Part 17: VIEW -> VIEW (DDL) transitions
=====================================================================
-drop view if exists t17;
-drop table if exists t17_b;
-create table t17_b(a int);
-insert into t17_b values (10), (20), (30);
-create view t17 as select a, 2*a as b, 3*a as c from t17_b;
-select * from t17;
-a b c
-10 20 30
-20 40 60
-30 60 90
-prepare stmt from 'select * from t17';
-execute stmt;
+create table t2 (a int);
+insert into t2 values (10), (20), (30);
+create view t1 as select a, 2*a as b, 3*a as c from t2;
+select * from t1;
a b c
10 20 30
20 40 60
30 60 90
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+prepare stmt from "select * from t1";
execute stmt;
a b c
10 20 30
20 40 60
30 60 90
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop view t17;
-create view t17 as select a, 2*a as b, 5*a as c from t17_b;
-select * from t17;
+drop view t1;
+create view t1 as select a, 2*a as b, 5*a as c from t2;
+select * from t1;
a b c
10 20 50
20 40 100
30 60 150
-set @expected = @expected + 1;
+# Currently a different result from conventional statements.
+# A view is inlined once at prepare, later on view DDL
+# does not affect prepared statement and it is not re-prepared.
+# This is reported in Bug#36002 Prepared statements: if a view
+# used in a statement is replaced, bad data
execute stmt;
a b c
-10 20 50
-20 40 100
-30 60 150
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+10 20 30
+20 40 60
+30 60 90
+call p_verify_reprepare_count(0);
+SUCCESS
+
+flush table t2;
execute stmt;
a b c
10 20 50
20 40 100
30 60 150
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t17_b;
-drop view t17;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+drop table t2;
+drop view t1;
+deallocate prepare stmt;
=====================================================================
-Testing 18: VIEW -> VIEW (VIEW dependencies) transitions
+Part 18: VIEW -> VIEW (VIEW dependencies) transitions
=====================================================================
-drop table if exists t18;
-drop table if exists t18_dependent_table;
-drop view if exists t18_func;
-drop view if exists t18_view;
-drop view if exists t18_table;
-drop function if exists view_func;
-drop view if exists view_view;
-create table t18(a int);
-insert into t18 values (1), (2), (3);
-create function view_func(x int) returns int
-return x+1;
-create view view_view as select "view v1" as reason from dual;
-create table t18_dependent_table(a int);
-create view t18_func as select a, view_func(a) as b from t18;
-create view t18_view as select a, reason as b from t18, view_view;
-create view t18_table as select * from t18;
-prepare stmt_func from 'select * from t18_func';
-execute stmt_func;
-a b
-1 2
-2 3
-3 4
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt_func;
-a b
-1 2
-2 3
-3 4
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop function view_func;
-create function view_func(x int) returns int
-return x*x;
-set @expected = @expected + 1;
-execute stmt_func;
-a b
-1 1
-2 4
-3 9
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt_func;
-a b
-1 1
-2 4
-3 9
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-prepare stmt_view from 'select * from t18_view';
-execute stmt_view;
-a b
-1 view v1
-2 view v1
-3 view v1
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt_view;
-a b
-1 view v1
-2 view v1
-3 view v1
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop view view_view;
-create view view_view as select "view v2" as reason from dual;
-set @expected = @expected + 1;
-execute stmt_view;
-a b
-1 view v2
-2 view v2
-3 view v2
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt_view;
-a b
-1 view v2
-2 view v2
-3 view v2
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-prepare stmt_table from 'select * from t18_table';
-execute stmt_table;
+# Part 18a: dependent function has changed
+create table t1 (a int);
+insert into t1 (a) values (1), (2), (3);
+create function f1() returns int return (select max(a) from t1);
+create view v1 as select f1();
+prepare stmt from "select * from v1";
+execute stmt;
+f1()
+3
+execute stmt;
+f1()
+3
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop function f1;
+create function f1() returns int return 2;
+# XXX: Bug#12093. We only get a different error
+# message because the non-existing procedure error is masked
+# by the view.
+execute stmt;
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+execute stmt;
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# Part 18b: dependent procedure has changed (referred to via a function)
+create table t2 (a int);
+insert into t2 (a) values (4), (5), (6);
+drop function f1;
+create function f1() returns int
+begin
+declare x int;
+call p1(x);
+return x;
+end|
+create procedure p1(out x int) select max(a) from t1 into x;
+prepare stmt from "select * from v1";
+execute stmt;
+f1()
+3
+execute stmt;
+f1()
+3
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop procedure p1;
+create procedure p1(out x int) select max(a) from t2 into x;
+# XXX: bug. The prelocked list is not invalidated
+# and we keep opening table t1, whereas the procedure
+# is now referring to table t2
+execute stmt;
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+call p_verify_reprepare_count(0);
+SUCCESS
+
+flush table t1;
+execute stmt;
+f1()
+6
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+f1()
+6
+# Test 18-c: dependent VIEW has changed
+drop view v1;
+create view v2 as select a from t1;
+create view v1 as select * from v2;
+prepare stmt from "select * from v1";
+execute stmt;
a
1
2
3
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt_table;
+execute stmt;
a
1
2
3
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t18 add column comments varchar(50) default NULL;
-set @expected = @expected + 1;
-execute stmt_table;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop view v2;
+create view v2 as select a from t2;
+execute stmt;
a
1
2
3
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt_table;
+execute stmt;
a
1
2
3
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t18;
-drop table t18_dependent_table;
-drop view t18_func;
-drop view t18_view;
-drop view t18_table;
-drop function view_func;
-drop view view_view;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+flush table t1;
+execute stmt;
+a
+4
+5
+6
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+4
+5
+6
+# Test 18-d: dependent TABLE has changed
+drop view v2;
+create table v2 as select * from t1;
+execute stmt;
+a
+1
+2
+3
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+1
+2
+3
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table v2;
+create table v2 (a int unique) as select * from t2;
+execute stmt;
+a
+4
+5
+6
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+4
+5
+6
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# Test 18-e: dependent TABLE trigger has changed
+prepare stmt from "insert into v1 (a) values (?)";
+set @var= 7;
+execute stmt using @var;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+create trigger v2_bi before insert on v2 for each row set @message="v2_bi";
+set @var=8;
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select @message;
+@message
+v2_bi
+drop trigger v2_bi;
+set @message=null;
+set @var=9;
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select @message;
+@message
+NULL
+create trigger v2_bi after insert on v2 for each row set @message="v2_ai";
+set @var= 10;
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select @message;
+@message
+v2_ai
+select * from v1;
+a
+4
+5
+6
+7
+8
+9
+10
+# Cleanup
+drop table if exists t1, t2, v1, v2;
+drop view if exists v1, v2;
+drop function f1;
+drop procedure p1;
+deallocate prepare stmt;
=====================================================================
-Testing 19: Special tables (INFORMATION_SCHEMA)
+Part 19: Special tables (INFORMATION_SCHEMA)
=====================================================================
-drop procedure if exists proc_19;
prepare stmt from
-'select ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE
+"select ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE
from INFORMATION_SCHEMA.ROUTINES where
- routine_name=\'proc_19\'';
-create procedure proc_19() select "hi there";
+ routine_name='p1'";
+create procedure p1() select "hi there";
execute stmt;
ROUTINE_SCHEMA ROUTINE_NAME ROUTINE_TYPE
-test proc_19 PROCEDURE
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+test p1 PROCEDURE
execute stmt;
ROUTINE_SCHEMA ROUTINE_NAME ROUTINE_TYPE
-test proc_19 PROCEDURE
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop procedure proc_19;
-create procedure proc_19() select "hi there, again";
+test p1 PROCEDURE
+drop procedure p1;
+create procedure p1() select "hi there, again";
execute stmt;
ROUTINE_SCHEMA ROUTINE_NAME ROUTINE_TYPE
-test proc_19 PROCEDURE
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+test p1 PROCEDURE
execute stmt;
ROUTINE_SCHEMA ROUTINE_NAME ROUTINE_TYPE
-test proc_19 PROCEDURE
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop procedure proc_19;
+test p1 PROCEDURE
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop procedure p1;
+deallocate prepare stmt;
=====================================================================
-Testing 20: Special tables (log tables)
+Part 20: Special tables (log tables)
=====================================================================
prepare stmt from
-'select * from mysql.general_log where argument=\'IMPOSSIBLE QUERY STRING\'';
-execute stmt;
-event_time user_host thread_id server_id command_type argument
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-event_time user_host thread_id server_id command_type argument
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-event_time user_host thread_id server_id command_type argument
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-event_time user_host thread_id server_id command_type argument
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+"select * from mysql.general_log where argument='IMPOSSIBLE QUERY STRING'";
+execute stmt;
+execute stmt;
+execute stmt;
+execute stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+deallocate prepare stmt;
=====================================================================
-Testing 21: Special tables (system tables)
+Part 21: Special tables (system tables)
=====================================================================
-drop procedure if exists proc_21;
prepare stmt from
-'select type, db, name from mysql.proc where name=\'proc_21\'';
-create procedure proc_21() select "hi there";
+"select type, db, name from mysql.proc where name='p1'";
+create procedure p1() select "hi there";
execute stmt;
type db name
-PROCEDURE test proc_21
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+PROCEDURE test p1
execute stmt;
type db name
-PROCEDURE test proc_21
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop procedure proc_21;
-create procedure proc_21() select "hi there, again";
+PROCEDURE test p1
+drop procedure p1;
+create procedure p1() select "hi there, again";
execute stmt;
type db name
-PROCEDURE test proc_21
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+PROCEDURE test p1
execute stmt;
type db name
-PROCEDURE test proc_21
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop procedure proc_21;
+PROCEDURE test p1
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop procedure p1;
+deallocate prepare stmt;
=====================================================================
-Testing 22: Special tables (views temp tables)
+Part 22: Special tables (views temp tables)
=====================================================================
-drop table if exists t22_b;
-drop view if exists t22;
-create table t22_b(a int);
-create algorithm=temptable view t22 as select a*a as a2 from t22_b;
-show create view t22;
+create table t1 (a int);
+create algorithm=temptable view v1 as select a*a as a2 from t1;
+# Using a temporary table internally should not confuse the prepared
+# statement code, and should not raise ER_PS_INVALIDATED errors
+show create view v1;
View Create View character_set_client collation_connection
-t22 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `t22` AS select (`t22_b`.`a` * `t22_b`.`a`) AS `a2` from `t22_b` latin1 latin1_swedish_ci
-prepare stmt from 'select * from t22';
-insert into t22_b values (1), (2), (3);
+v1 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (`t1`.`a` * `t1`.`a`) AS `a2` from `t1` latin1 latin1_swedish_ci
+prepare stmt from "select * from v1";
+insert into t1 values (1), (2), (3);
execute stmt;
a2
1
4
9
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
execute stmt;
a2
1
4
9
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-insert into t22_b values (4), (5), (6);
+insert into t1 values (4), (5), (6);
execute stmt;
a2
1
@@ -1998,16 +1079,6 @@ a2
16
25
36
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
execute stmt;
a2
1
@@ -2016,1333 +1087,291 @@ a2
16
25
36
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t22_b;
-drop view t22;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+drop view v1;
=====================================================================
-Testing 23: Special tables (internal join tables)
+Part 23: Special statements
=====================================================================
-drop table if exists t23_a;
-drop table if exists t23_b;
-create table t23_a(a int);
-create table t23_b(b int);
-prepare stmt from 'select * from t23_a join t23_b';
-insert into t23_a values (1), (2), (3);
-insert into t23_b values (10), (20), (30);
+# SQLCOM_ALTER_TABLE:
+create table t1 (a int);
+prepare stmt from "alter table t1 add column b int";
execute stmt;
-a b
-1 10
-2 10
-3 10
-1 20
-2 20
-3 20
-1 30
-2 30
-3 30
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+drop table t1;
+create table t1 (a1 int, a2 int);
+# t1 has changed, and it's does not lead to reprepare
execute stmt;
-a b
-1 10
-2 10
-3 10
-1 20
-2 20
-3 20
-1 30
-2 30
-3 30
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-insert into t23_a values (4);
-insert into t23_b values (40);
+alter table t1 drop column b;
execute stmt;
-a b
-1 10
-2 10
-3 10
-4 10
-1 20
-2 20
-3 20
-4 20
-1 30
-2 30
-3 30
-4 30
-1 40
-2 40
-3 40
-4 40
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+alter table t1 drop column b;
execute stmt;
-a b
-1 10
-2 10
-3 10
-4 10
-1 20
-2 20
-3 20
-4 20
-1 30
-2 30
-3 30
-4 30
-1 40
-2 40
-3 40
-4 40
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t23_a;
-drop table t23_b;
-=====================================================================
-Testing 24: Special statements
-=====================================================================
-drop table if exists t24_alter;
-create table t24_alter(a int);
-prepare stmt from 'alter table t24_alter add column b int';
-execute stmt;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t24_alter;
-create table t24_alter(a1 int, a2 int);
-execute stmt;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t24_alter drop column b;
-execute stmt;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t24_alter drop column b;
-execute stmt;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t24_alter;
-drop table if exists t24_repair;
-create table t24_repair(a int);
-insert into t24_repair values (1), (2), (3);
-prepare stmt from 'repair table t24_repair';
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+# SQLCOM_REPAIR:
+create table t1 (a int);
+insert into t1 values (1), (2), (3);
+prepare stmt from "repair table t1";
execute stmt;
Table Op Msg_type Msg_text
-test.t24_repair repair status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t24_repair;
-create table t24_repair(a1 int, a2 int);
-insert into t24_repair values (1, 10), (2, 20), (3, 30);
+test.t1 repair status OK
execute stmt;
Table Op Msg_type Msg_text
-test.t24_repair repair status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t24_repair add column b varchar(50) default NULL;
+test.t1 repair status OK
+drop table t1;
+create table t1 (a1 int, a2 int);
+insert into t1 values (1, 10), (2, 20), (3, 30);
+# t1 has changed, and it's does not lead to reprepare
execute stmt;
Table Op Msg_type Msg_text
-test.t24_repair repair status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t24_repair drop column b;
+test.t1 repair status OK
+alter table t1 add column b varchar(50) default NULL;
execute stmt;
Table Op Msg_type Msg_text
-test.t24_repair repair status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t24_repair;
-drop table if exists t24_analyze;
-create table t24_analyze(a int);
-insert into t24_analyze values (1), (2), (3);
-prepare stmt from 'analyze table t24_analyze';
+test.t1 repair status OK
+call p_verify_reprepare_count(0);
+SUCCESS
+
+alter table t1 drop column b;
execute stmt;
Table Op Msg_type Msg_text
-test.t24_analyze analyze status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t24_analyze;
-create table t24_analyze(a1 int, a2 int);
-insert into t24_analyze values (1, 10), (2, 20), (3, 30);
+test.t1 repair status OK
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# SQLCOM_ANALYZE:
+prepare stmt from "analyze table t1";
execute stmt;
Table Op Msg_type Msg_text
-test.t24_analyze analyze status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t24_analyze add column b varchar(50) default NULL;
+test.t1 analyze status OK
+drop table t1;
+create table t1 (a1 int, a2 int);
+insert into t1 values (1, 10), (2, 20), (3, 30);
+# t1 has changed, and it's not a problem
execute stmt;
Table Op Msg_type Msg_text
-test.t24_analyze analyze status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t24_analyze drop column b;
+test.t1 analyze status OK
+alter table t1 add column b varchar(50) default NULL;
execute stmt;
Table Op Msg_type Msg_text
-test.t24_analyze analyze status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t24_analyze;
-drop table if exists t24_optimize;
-create table t24_optimize(a int);
-insert into t24_optimize values (1), (2), (3);
-prepare stmt from 'optimize table t24_optimize';
+test.t1 analyze status OK
+alter table t1 drop column b;
execute stmt;
Table Op Msg_type Msg_text
-test.t24_optimize optimize status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t24_optimize;
-create table t24_optimize(a1 int, a2 int);
-insert into t24_optimize values (1, 10), (2, 20), (3, 30);
+test.t1 analyze status OK
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# SQLCOM_OPTIMIZE:
+prepare stmt from "optimize table t1";
execute stmt;
Table Op Msg_type Msg_text
-test.t24_optimize optimize status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t24_optimize add column b varchar(50) default NULL;
+test.t1 optimize status Table is already up to date
+drop table t1;
+create table t1 (a1 int, a2 int);
+insert into t1 values (1, 10), (2, 20), (3, 30);
+# t1 has changed, and it's not a problem
execute stmt;
Table Op Msg_type Msg_text
-test.t24_optimize optimize status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t24_optimize drop column b;
+test.t1 optimize status OK
+alter table t1 add column b varchar(50) default NULL;
execute stmt;
Table Op Msg_type Msg_text
-test.t24_optimize optimize status OK
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t24_optimize;
-drop procedure if exists changing_proc;
-prepare stmt from 'show create procedure changing_proc';
-execute stmt;
-ERROR 42000: PROCEDURE changing_proc does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-ERROR 42000: PROCEDURE changing_proc does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-create procedure changing_proc() begin end;
-execute stmt;
-Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-changing_proc CREATE DEFINER=`root`@`localhost` PROCEDURE `changing_proc`()
-begin end latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-changing_proc CREATE DEFINER=`root`@`localhost` PROCEDURE `changing_proc`()
-begin end latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop procedure changing_proc;
-create procedure changing_proc(x int, y int) begin end;
-execute stmt;
-Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-changing_proc CREATE DEFINER=`root`@`localhost` PROCEDURE `changing_proc`(x int, y int)
-begin end latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-changing_proc CREATE DEFINER=`root`@`localhost` PROCEDURE `changing_proc`(x int, y int)
-begin end latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop procedure changing_proc;
-execute stmt;
-ERROR 42000: PROCEDURE changing_proc does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-ERROR 42000: PROCEDURE changing_proc does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop function if exists changing_func;
-prepare stmt from 'show create function changing_func';
-execute stmt;
-ERROR 42000: FUNCTION changing_func does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-ERROR 42000: FUNCTION changing_func does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-create function changing_func() returns int return 0;
-execute stmt;
-Function sql_mode Create Function character_set_client collation_connection Database Collation
-changing_func CREATE DEFINER=`root`@`localhost` FUNCTION `changing_func`() RETURNS int(11)
-return 0 latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-Function sql_mode Create Function character_set_client collation_connection Database Collation
-changing_func CREATE DEFINER=`root`@`localhost` FUNCTION `changing_func`() RETURNS int(11)
-return 0 latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop function changing_func;
-create function changing_func(x int, y int) returns int return x+y;
-execute stmt;
-Function sql_mode Create Function character_set_client collation_connection Database Collation
-changing_func CREATE DEFINER=`root`@`localhost` FUNCTION `changing_func`(x int, y int) RETURNS int(11)
-return x+y latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-Function sql_mode Create Function character_set_client collation_connection Database Collation
-changing_func CREATE DEFINER=`root`@`localhost` FUNCTION `changing_func`(x int, y int) RETURNS int(11)
-return x+y latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop function changing_func;
-execute stmt;
-ERROR 42000: FUNCTION changing_func does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-ERROR 42000: FUNCTION changing_func does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table if exists t24_trigger;
-create table t24_trigger(a int);
-prepare stmt from 'show create trigger t24_bi;';
+test.t1 optimize status OK
+alter table t1 drop column b;
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+# SQLCOM_SHOW_CREATE_PROC:
+prepare stmt from "show create procedure p1";
+execute stmt;
+ERROR 42000: PROCEDURE p1 does not exist
+execute stmt;
+ERROR 42000: PROCEDURE p1 does not exist
+create procedure p1() begin end;
+execute stmt;
+execute stmt;
+drop procedure p1;
+create procedure p1(x int, y int) begin end;
+execute stmt;
+execute stmt;
+drop procedure p1;
+execute stmt;
+ERROR 42000: PROCEDURE p1 does not exist
+execute stmt;
+ERROR 42000: PROCEDURE p1 does not exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# SQLCOM_SHOW_CREATE_FUNC:
+prepare stmt from "show create function f1";
+execute stmt;
+ERROR 42000: FUNCTION f1 does not exist
+execute stmt;
+ERROR 42000: FUNCTION f1 does not exist
+create function f1() returns int return 0;
+execute stmt;
+execute stmt;
+drop function f1;
+create function f1(x int, y int) returns int return x+y;
+execute stmt;
+execute stmt;
+drop function f1;
+execute stmt;
+ERROR 42000: FUNCTION f1 does not exist
+execute stmt;
+ERROR 42000: FUNCTION f1 does not exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# SQLCOM_SHOW_CREATE_TRIGGER:
+create table t1 (a int);
+prepare stmt from "show create trigger t1_bi";
execute stmt;
ERROR HY000: Trigger does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
execute stmt;
ERROR HY000: Trigger does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-create trigger t24_bi before insert on t24_trigger for each row
-begin
-set @message= "t24_bi";
-end
-$$
+create trigger t1_bi before insert on t1 for each row set @message= "t1_bi";
execute stmt;
-Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
-t24_bi CREATE DEFINER=`root`@`localhost` trigger t24_bi before insert on t24_trigger for each row
-begin
-set @message= "t24_bi";
-end latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
-t24_bi CREATE DEFINER=`root`@`localhost` trigger t24_bi before insert on t24_trigger for each row
-begin
-set @message= "t24_bi";
-end latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop trigger t24_bi;
-create trigger t24_bi before insert on t24_trigger for each row
-begin
-set @message= "t24_bi (2)";
-end
-$$
-set @expected = @expected + 1;
execute stmt;
-Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
-t24_bi CREATE DEFINER=`root`@`localhost` trigger t24_bi before insert on t24_trigger for each row
-begin
-set @message= "t24_bi (2)";
-end latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
-t24_bi CREATE DEFINER=`root`@`localhost` trigger t24_bi before insert on t24_trigger for each row
-begin
-set @message= "t24_bi (2)";
-end latin1 latin1_swedish_ci latin1_swedish_ci
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop trigger t24_bi;
+drop trigger t1_bi;
+create trigger t1_bi before insert on t1 for each row set @message= "t1_bi (2)";
+execute stmt;
+execute stmt;
+drop trigger t1_bi;
execute stmt;
ERROR HY000: Trigger does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
execute stmt;
ERROR HY000: Trigger does not exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t24_trigger;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+deallocate prepare stmt;
=====================================================================
-Testing 25: Testing the strength of TABLE_SHARE version
+Part 24: Testing the strength of TABLE_SHARE version
=====================================================================
-drop table if exists t25_num_col;
-create table t25_num_col(a int);
-prepare stmt from 'select a from t25_num_col';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t25_num_col add column b varchar(50) default NULL;
-set @expected = @expected + 1;
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t25_num_col;
-drop table if exists t25_col_name;
-create table t25_col_name(a int);
-prepare stmt from 'select * from t25_col_name';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t25_col_name change a b int;
-set @expected = @expected + 1;
-execute stmt;
-ERROR HY000: Prepared statement result set has changed, rebind needed
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @expected = @expected + 1;
-execute stmt;
-ERROR HY000: Prepared statement result set has changed, rebind needed
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t25_col_name;
-drop table if exists t25_col_type;
-create table t25_col_type(a int);
-prepare stmt from 'select * from t25_col_type';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t25_col_type change a a varchar(10);
-set @expected = @expected + 1;
-execute stmt;
-ERROR HY000: Prepared statement result set has changed, rebind needed
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @expected = @expected + 1;
-execute stmt;
-ERROR HY000: Prepared statement result set has changed, rebind needed
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t25_col_type;
-drop table if exists t25_col_type_length;
-create table t25_col_type_length(a varchar(10));
-prepare stmt from 'select * from t25_col_type_length';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t25_col_type_length change a a varchar(20);
-set @expected = @expected + 1;
-execute stmt;
-ERROR HY000: Prepared statement result set has changed, rebind needed
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @expected = @expected + 1;
-execute stmt;
-ERROR HY000: Prepared statement result set has changed, rebind needed
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t25_col_type_length;
-drop table if exists t25_col_null;
-create table t25_col_null(a varchar(10));
-prepare stmt from 'select * from t25_col_null';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t25_col_null change a a varchar(10) NOT NULL;
-set @expected = @expected + 1;
-execute stmt;
-ERROR HY000: Prepared statement result set has changed, rebind needed
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @expected = @expected + 1;
-execute stmt;
-ERROR HY000: Prepared statement result set has changed, rebind needed
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t25_col_null;
-drop table if exists t25_col_default;
-create table t25_col_default(a int, b int DEFAULT 10);
-prepare stmt from 'insert into t25_col_default(a) values (?)';
-set @val=1;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=2;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t25_col_default change b b int DEFAULT 20;
-set @val=3;
-set @expected = @expected + 1;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @val=4;
-execute stmt using @val;
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-select * from t25_col_default;
-a b
-1 10
-2 10
-3 20
-4 20
-drop table t25_col_default;
-drop table if exists t25_index;
-create table t25_index(a varchar(10));
-prepare stmt from 'select * from t25_index';
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-create index i1 on t25_index(a);
-set @expected = @expected + 1;
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt;
-a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t25_index;
-drop table if exists t25_index_unique;
-create table t25_index_unique(a varchar(10), b varchar(10));
-create index i1 on t25_index_unique(a, b);
-show create table t25_index_unique;
-Table Create Table
-t25_index_unique CREATE TABLE `t25_index_unique` (
- `a` varchar(10) DEFAULT NULL,
- `b` varchar(10) DEFAULT NULL,
- KEY `i1` (`a`,`b`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-prepare stmt from 'select * from t25_index_unique';
+# Test 24-a: number of columns
+create table t1 (a int);
+prepare stmt from "select a from t1";
execute stmt;
-a b
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+alter table t1 add column b varchar(50) default NULL;
execute stmt;
-a b
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-alter table t25_index_unique drop index i1;
-create unique index i1 on t25_index_unique(a, b);
-show create table t25_index_unique;
-Table Create Table
-t25_index_unique CREATE TABLE `t25_index_unique` (
- `a` varchar(10) DEFAULT NULL,
- `b` varchar(10) DEFAULT NULL,
- UNIQUE KEY `i1` (`a`,`b`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-set @expected = @expected + 1;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
execute stmt;
-a b
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# Test 24-b: column name
+alter table t1 change b c int;
execute stmt;
-a b
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop table t25_index_unique;
-=====================================================================
-Testing reported bugs
-=====================================================================
-drop table if exists table_12093;
-drop function if exists func_12093;
-drop function if exists func_12093_unrelated;
-drop procedure if exists proc_12093;
-create table table_12093(a int);
-create function func_12093()
-returns int
-begin
-return (select count(*) from table_12093);
-end//
-create procedure proc_12093(a int)
-begin
-select * from table_12093;
-end//
-create function func_12093_unrelated() returns int return 2;
-create procedure proc_12093_unrelated() begin end;
-prepare stmt_sf from 'select func_12093();';
-prepare stmt_sp from 'call proc_12093(func_12093())';
-execute stmt_sf;
-func_12093()
-0
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt_sp;
a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop function func_12093_unrelated;
-drop procedure proc_12093_unrelated;
-execute stmt_sf;
-func_12093()
-0
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt_sp;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt_sf;
-func_12093()
-0
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-execute stmt_sp;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# Test 24-c: column type
+alter table t1 change a a varchar(10);
+execute stmt;
a
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-deallocate prepare stmt_sf;
-deallocate prepare stmt_sp;
-drop table table_12093;
-drop function func_12093;
-drop procedure proc_12093;
-drop function if exists func_21294;
-create function func_21294() returns int return 10;
-prepare stmt from "select func_21294()";
-execute stmt;
-func_21294()
-10
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop function func_21294;
-create function func_21294() returns int return 10;
-execute stmt;
-func_21294()
-10
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-drop function func_21294;
-create function func_21294() returns int return 20;
-set @expected = @expected + 1;
-execute stmt;
-func_21294()
-20
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# Test 24-d: column type length
+alter table t1 change a a varchar(20);
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# Test 24-e: column NULL property
+alter table t1 change a a varchar(20) NOT NULL;
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# Test 24-f: column DEFAULT
+alter table t1 change c c int DEFAULT 20;
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# Test 24-g: number of keys
+create unique index t1_a_idx on t1 (a);
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# Test 24-h: changing index uniqueness
+drop index t1_a_idx on t1;
+create index t1_a_idx on t1 (a);
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# Cleanup
+drop table t1;
deallocate prepare stmt;
-drop function func_21294;
+=====================================================================
+Testing reported bugs
+=====================================================================
+#
+# Bug#27420 A combination of PS and view operations cause
+# error + assertion on shutdown
+#
drop table if exists t_27420_100;
drop table if exists t_27420_101;
drop view if exists v_27420;
@@ -3353,55 +1382,36 @@ insert into t_27420_101 values (1), (2);
create view v_27420 as select t_27420_100.a X, t_27420_101.a Y
from t_27420_100, t_27420_101
where t_27420_100.a=t_27420_101.a;
-prepare stmt from 'select * from v_27420';
+prepare stmt from "select * from v_27420";
execute stmt;
X Y
1 1
2 2
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
drop view v_27420;
create table v_27420(X int, Y int);
-set @expected = @expected + 1;
execute stmt;
X Y
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(1);
+SUCCESS
+
drop table v_27420;
create table v_27420 (a int, b int, filler char(200));
-set @expected = @expected + 1;
-execute stmt;
-ERROR HY000: Prepared statement result set has changed, rebind needed
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-deallocate prepare stmt;
+execute stmt;
+a b filler
+call p_verify_reprepare_count(1);
+SUCCESS
+
drop table t_27420_100;
drop table t_27420_101;
drop table v_27420;
+deallocate prepare stmt;
+#
+# Bug#27430 Crash in subquery code when in PS and table DDL changed
+# after PREPARE
+#
drop table if exists t_27430_1;
drop table if exists t_27430_2;
create table t_27430_1 (a int not null, oref int not null, key(a));
@@ -3417,43 +1427,20 @@ insert into t_27430_2 values
(2, 2),
(1234, 3),
(1234, 4);
-prepare stmt from
-'select oref, a, a in (select a from t_27430_1 where oref=t_27430_2.oref) Z from t_27430_2';
-execute stmt;
-oref a Z
-1 1 1
-2 2 0
-3 1234 0
-4 1234 0
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+prepare stmt from
+"select oref, a, a in (select a from t_27430_1 where oref=t_27430_2.oref) Z from t_27430_2";
execute stmt;
oref a Z
1 1 1
2 2 0
3 1234 0
4 1234 0
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
drop table t_27430_1, t_27430_2;
create table t_27430_1 (a int, oref int, key(a));
-insert into t_27430_1 values
+insert into t_27430_1 values
(1, 1),
(1, NULL),
(2, 3),
@@ -3465,35 +1452,22 @@ insert into t_27430_2 values
(2,2),
(NULL, 3),
(NULL, 4);
-set @expected = @expected + 1;
-execute stmt;
-ERROR HY000: Prepared statement result set has changed, rebind needed
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-set @expected = @expected + 1;
-execute stmt;
-ERROR HY000: Prepared statement result set has changed, rebind needed
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-deallocate prepare stmt;
+execute stmt;
+oref a Z
+1 1 1
+2 2 0
+3 NULL NULL
+4 NULL 0
+call p_verify_reprepare_count(1);
+SUCCESS
+
drop table t_27430_1;
drop table t_27430_2;
+deallocate prepare stmt;
+#
+# Bug#27690 Re-execution of prepared statement after table
+# was replaced with a view crashes
+#
drop table if exists t_27690_1;
drop view if exists v_27690_1;
drop table if exists v_27690_2;
@@ -3501,66 +1475,28 @@ create table t_27690_1 (a int, b int);
insert into t_27690_1 values (1,1),(2,2);
create table v_27690_1 as select * from t_27690_1;
create table v_27690_2 as select * from t_27690_1;
-prepare stmt from 'select * from v_27690_1, v_27690_2';
+prepare stmt from "select * from v_27690_1, v_27690_2";
execute stmt;
a b a b
1 1 1 1
2 2 1 1
1 1 2 2
2 2 2 2
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
execute stmt;
a b a b
1 1 1 1
2 2 1 1
1 1 2 2
2 2 2 2
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
drop table v_27690_1;
execute stmt;
ERROR 42S02: Table 'test.v_27690_1' doesn't exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
execute stmt;
ERROR 42S02: Table 'test.v_27690_1' doesn't exist
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(0);
+SUCCESS
+
create view v_27690_1 as select A.a, A.b from t_27690_1 A, t_27690_1 B;
-set @expected = @expected + 1;
execute stmt;
a b a b
1 1 1 1
@@ -3571,16 +1507,9 @@ a b a b
2 2 2 2
1 1 2 2
2 2 2 2
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
+call p_verify_reprepare_count(1);
+SUCCESS
+
execute stmt;
a b a b
1 1 1 1
@@ -3591,17 +1520,693 @@ a b a b
2 2 2 2
1 1 2 2
2 2 2 2
-SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
-WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
-AS `CHECK`,
-(VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
-where variable_name='COM_STMT_REPREPARE' ;
-CHECK OFFSET
-PASSED 0
-deallocate prepare stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
drop table t_27690_1;
drop view v_27690_1;
drop table v_27690_2;
+deallocate prepare stmt;
+#=====================================================================
+# TODO: fix the below two bugs and modify their tests
+#
+# Bug#21294 Executing a prepared statement that executes
+# a stored function which was recreat
+#
+create function f1() returns int return 10;
+prepare stmt from "select f1()";
+execute stmt;
+f1()
+10
+drop function f1;
+create function f1() returns int return 10;
+execute stmt;
+ERROR 42000: FUNCTION test.f1 does not exist
+drop function f1;
+create function f1() returns int return 20;
+execute stmt;
+ERROR 42000: FUNCTION test.f1 does not exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop function f1;
+deallocate prepare stmt;
+#
+# Bug#12093 SP not found on second PS execution if another thread drops
+# other SP in between
+#
+drop table if exists t_12093;
+drop function if exists f_12093;
+drop function if exists f_12093_unrelated;
+drop procedure if exists p_12093;
+create table t_12093 (a int);
+create function f_12093() returns int return (select count(*) from t_12093);
+create procedure p_12093(a int) select * from t_12093;
+create function f_12093_unrelated() returns int return 2;
+create procedure p_12093_unrelated() begin end;
+prepare stmt_sf from 'select f_12093();';
+prepare stmt_sp from 'call p_12093(f_12093())';
+execute stmt_sf;
+f_12093()
+0
+execute stmt_sp;
+a
+drop function f_12093_unrelated;
+drop procedure p_12093_unrelated;
+# XXX: bug
+execute stmt_sf;
+ERROR 42000: FUNCTION test.f_12093 does not exist
+# XXX: bug
+execute stmt_sp;
+ERROR 42000: PROCEDURE test.p_12093 does not exist
+# XXX: bug
+execute stmt_sf;
+ERROR 42000: FUNCTION test.f_12093 does not exist
+# XXX: bug
+execute stmt_sp;
+ERROR 42000: PROCEDURE test.p_12093 does not exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t_12093;
+drop function f_12093;
+drop procedure p_12093;
+deallocate prepare stmt_sf;
+deallocate prepare stmt_sp;
+=====================================================================
+Ensure that metadata validation is performed for every type of
+SQL statement where it is needed.
+=====================================================================
+#
+# SQLCOM_SELECT
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "select 1 as res from dual where (1) in (select * from t1)";
+drop table t1;
+create table t1 (x int);
+execute stmt;
+res
+drop table t1;
+deallocate prepare stmt;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+#
+# SQLCOM_CREATE_TABLE
+#
+drop table if exists t1;
+drop table if exists t2;
+create table t1 (a int);
+prepare stmt from 'create table t2 as select * from t1';
+execute stmt;
+drop table t2;
+execute stmt;
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+ERROR 42S01: Table 't2' already exists
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+ERROR 42S01: Table 't2' already exists
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t2;
+create temporary table t2 (a int);
+execute stmt;
+ERROR 42S01: Table 't2' already exists
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+ERROR 42S01: Table 't2' already exists
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop temporary table t2;
+execute stmt;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t2;
+create view t2 as select 1;
+execute stmt;
+Got one of the listed errors
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+Got one of the listed errors
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop view t2;
+drop table t1;
+create table t1 (x varchar(20));
+execute stmt;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select * from t2;
+x
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t2;
+alter table t1 add column y decimal(10,3);
+execute stmt;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select * from t2;
+x y
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+deallocate prepare stmt;
+# XXX: no validation of the first table in case of
+# CREATE TEMPORARY TABLE. This is a shortcoming of the current code,
+# but since validation is not strictly necessary, nothing is done
+# about it.
+# Will be fixed as part of work on Bug#21431 "Incomplete support of
+# temporary tables"
+create table t1 (a int);
+insert into t1 (a) values (1);
+prepare stmt from "create temporary table if not exists t2 as select * from t1";
+execute stmt;
+drop table t2;
+execute stmt;
+execute stmt;
+Warnings:
+Note 1050 Table 't2' already exists
+select * from t2;
+a
+1
+1
+execute stmt;
+Warnings:
+Note 1050 Table 't2' already exists
+select * from t2;
+a
+1
+1
+1
+drop table t2;
+create temporary table t2 (a varchar(10));
+execute stmt;
+Warnings:
+Note 1050 Table 't2' already exists
+select * from t2;
+a
+1
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Warnings:
+Note 1050 Table 't2' already exists
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+Warnings:
+Note 1050 Table 't2' already exists
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+drop temporary table t2;
+drop table t2;
+deallocate prepare stmt;
+create table t1 (a int);
+prepare stmt from "create table t2 like t1";
+execute stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t2;
+drop table t1;
+execute stmt;
+ERROR 42S02: Table 'test.t1' doesn't exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+ERROR 42S02: Table 'test.t1' doesn't exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+create table t1 (x char(17));
+execute stmt;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t2;
+alter table t1 add column y time;
+execute stmt;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+select * from t2;
+x y
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+drop table t2;
+deallocate prepare stmt;
+#
+# SQLCOM_UPDATE
+#
+drop table if exists t1, t2;
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "update t2 set a=a+1 where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2;
+deallocate prepare stmt;
+#
+# SQLCOM_INSERT
+#
+drop table if exists t1, t2;
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "insert into t2 set a=((1) in (select * from t1))";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2;
+deallocate prepare stmt;
+#
+# SQLCOM_INSERT_SELECT
+#
+drop table if exists t1, t2;
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "insert into t2 select * from t1";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2;
+deallocate prepare stmt;
+#
+# SQLCOM_REPLACE
+#
+drop table if exists t1, t2;
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "replace t2 set a=((1) in (select * from t1))";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2;
+deallocate prepare stmt;
+#
+# SQLCOM_REPLACE_SELECT
+#
+drop table if exists t1, t2;
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "replace t2 select * from t1";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2;
+deallocate prepare stmt;
+#
+# SQLCOM_DELETE
+#
+drop table if exists t1, t2;
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "delete from t2 where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2;
+deallocate prepare stmt;
+#
+# SQLCOM_DELETE_MULTI
+#
+drop table if exists t1, t2, t3;
+create table t1 (a int);
+create table t2 (a int);
+create table t3 (a int);
+prepare stmt from "delete t2, t3 from t2, t3 where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2, t3;
+deallocate prepare stmt;
+#
+# SQLCOM_UPDATE_MULTI
+#
+drop table if exists t1, t2, t3;
+create table t1 (a int);
+create table t2 (a int);
+create table t3 (a int);
+prepare stmt from "update t2, t3 set t3.a=t2.a, t2.a=null where (1) in (select * from t1)";
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2, t3;
+deallocate prepare stmt;
+# Intermediate results: 8 SQLCOMs tested, 8 automatic reprepares
+call p_verify_reprepare_count(8);
+SUCCESS
+
+#
+# SQLCOM_LOAD
+#
+drop table if exists t1;
+create table t1 (a varchar(20));
+prepare stmt from "load data infile '../std_data_ln/words.dat' into table t1";
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+drop table t1;
+#
+# SQLCOM_SHOW_DATABASES
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show databases where (1) in (select * from t1)";
+execute stmt;
+Database
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Database
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_TABLES
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show tables where (1) in (select * from t1)";
+execute stmt;
+Tables_in_test
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Tables_in_test
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_FIELDS
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show fields from t1 where (1) in (select * from t1)";
+execute stmt;
+Field Type Null Key Default Extra
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Field Type Null Key Default Extra
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_KEYS
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show keys from t1 where (1) in (select * from t1)";
+execute stmt;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_VARIABLES
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show variables where (1) in (select * from t1)";
+execute stmt;
+Variable_name Value
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Variable_name Value
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_STATUS
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show status where (1) in (select * from t1)";
+execute stmt;
+Variable_name Value
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Variable_name Value
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_ENGINE_STATUS, SQLCOM_SHOW_ENGINE_LOGS,
+# SQLCOM_SHOW_ENGINE_MUTEX, SQLCOM_SHOW_PROCESSLIST
+#
+# Currently can not have a where clause, need to be covered
+# with tests
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show engine all status where (1) in (select * from t1)";
+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 'where (1) in (select * from t1)' at line 1
+prepare stmt from "show engine all logs where (1) in (select * from t1)";
+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 'where (1) in (select * from t1)' at line 1
+prepare stmt from "show engine all mutex where (1) in (select * from t1)";
+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 'where (1) in (select * from t1)' at line 1
+prepare stmt from "show processlist where (1) in (select * from t1)";
+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 'where (1) in (select * from t1)' at line 1
+drop table t1;
+#
+# SQLCOM_SHOW_CHARSETS
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show charset where (1) in (select * from t1)";
+execute stmt;
+Charset Description Default collation Maxlen
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Charset Description Default collation Maxlen
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_COLLATIONS
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show collation where (1) in (select * from t1)";
+execute stmt;
+Collation Charset Id Default Compiled Sortlen
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Collation Charset Id Default Compiled Sortlen
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_TABLE_STATUS
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show table status where (1) in (select * from t1)";
+execute stmt;
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_TRIGGERS
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show triggers where (1) in (select * from t1)";
+execute stmt;
+Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_OPEN_TABLES
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show open tables where (1) in (select * from t1)";
+execute stmt;
+Database Table In_use Name_locked
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Database Table In_use Name_locked
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_STATUS_PROC
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show procedure status where (1) in (select * from t1)";
+execute stmt;
+Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_STATUS_FUNC
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show function status where (1) in (select * from t1)";
+execute stmt;
+Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SHOW_EVENTS
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "show events where (1) in (select * from t1)";
+execute stmt;
+Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
+drop table t1;
+create table t1 (x int);
+execute stmt;
+Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_SET_OPTION
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "set @a=((1) in (select * from t1))";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_DO
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt from "do ((1) in (select * from t1))";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
+#
+# SQLCOM_CALL
+#
+drop table if exists t1;
+drop procedure if exists p1;
+create procedure p1(a int) begin end;
+create table t1 (a int);
+prepare stmt from "call p1((1) in (select * from t1))";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+drop procedure p1;
+deallocate prepare stmt;
+#
+# SQLCOM_CREATE_VIEW
+#
+drop table if exists t1;
+drop view if exists v1;
+create table t1 (a int);
+prepare stmt from "create view v1 as select * from t1";
+execute stmt;
+drop view v1;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop view v1;
+drop table t1;
+deallocate prepare stmt;
+# Intermediate result: number of reprepares matches the number
+# of tests
+call p_verify_reprepare_count(18);
+SUCCESS
+
+#
+# SQLCOM_ALTER_VIEW
+#
+drop view if exists v1;
+create view v1 as select 1;
+prepare stmt from "alter view v1 as select 2";
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+drop view v1;
+# Cleanup
+#
+drop temporary table if exists t1, t2, t3;
+drop table if exists t1, t2, t3, v1, v2;
+drop procedure if exists p_verify_reprepare_count;
+drop procedure if exists p1;
+drop function if exists f1;
+drop view if exists v1, v2;
diff --git a/mysql-test/r/ps_ddl1.result b/mysql-test/r/ps_ddl1.result
new file mode 100644
index 00000000000..87abcd90590
--- /dev/null
+++ b/mysql-test/r/ps_ddl1.result
@@ -0,0 +1,482 @@
+drop temporary table if exists t1;
+drop table if exists t1, t2;
+drop procedure if exists p_verify_reprepare_count;
+drop procedure if exists p1;
+drop function if exists f1;
+drop view if exists t1;
+drop schema if exists mysqltest;
+create procedure p_verify_reprepare_count(expected int)
+begin
+declare old_reprepare_count int default @reprepare_count;
+select variable_value from
+information_schema.session_status where
+variable_name='com_stmt_reprepare'
+ into @reprepare_count;
+if old_reprepare_count + expected <> @reprepare_count then
+select concat("Expected: ", expected,
+", actual: ", @reprepare_count - old_reprepare_count)
+as "ERROR";
+else
+select '' as "SUCCESS";
+end if;
+end|
+set @reprepare_count= 0;
+flush status;
+drop table if exists t1;
+# Column added or dropped is not within the list of selected columns
+# or table comment has changed.
+# A reprepare is probably not needed.
+create table t1 (a int, b int);
+prepare stmt from "select a from t1";
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+alter table t1 add column c int;
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+alter table t1 drop column b;
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+alter table t1 comment "My best table";
+execute stmt;
+a
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+a
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+deallocate prepare stmt;
+# Selects using the table at various positions, inser,update ...
+# + the table disappears
+create table t1 (a int);
+prepare stmt1 from "truncate t1";
+prepare stmt2 from "select 1 as my_column from t1";
+prepare stmt3 from "select 1 as my_column from (select * from t1) as t2";
+prepare stmt4 from
+"select 1 as my_column from (select 1) as t2 where exists (select 1 from t1)";
+prepare stmt5 from "select * from (select 1 as b) as t2, t1";
+prepare stmt6 from "select * from t1 union all select 1.5";
+prepare stmt7 from "select 1 as my_column union all select 1 from t1";
+prepare stmt8 from "insert into t1 values(1),(2)";
+prepare stmt9 from "update t1 set a = 3 where a = 2";
+prepare stmt10 from "delete from t1 where a = 1";
+# Attention: Result logging is disabled.
+execute stmt10;
+execute stmt9;
+execute stmt8;
+execute stmt7;
+execute stmt6;
+execute stmt5;
+execute stmt4;
+execute stmt3;
+execute stmt2;
+execute stmt1;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+execute stmt10;
+ERROR 42S02: Table 'test.t1' doesn't exist
+execute stmt9;
+ERROR 42S02: Table 'test.t1' doesn't exist
+execute stmt8;
+ERROR 42S02: Table 'test.t1' doesn't exist
+execute stmt7;
+ERROR 42S02: Table 'test.t1' doesn't exist
+execute stmt6;
+ERROR 42S02: Table 'test.t1' doesn't exist
+execute stmt5;
+ERROR 42S02: Table 'test.t1' doesn't exist
+execute stmt4;
+ERROR 42S02: Table 'test.t1' doesn't exist
+execute stmt3;
+ERROR 42S02: Table 'test.t1' doesn't exist
+execute stmt2;
+ERROR 42S02: Table 'test.t1' doesn't exist
+execute stmt1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+deallocate prepare stmt10;
+deallocate prepare stmt9;
+deallocate prepare stmt8;
+deallocate prepare stmt7;
+deallocate prepare stmt6;
+deallocate prepare stmt5;
+deallocate prepare stmt4;
+deallocate prepare stmt3;
+deallocate prepare stmt2;
+deallocate prepare stmt1;
+# Selects using the table at various positions, inser,update ...
+# + layout change (drop column) which must cause a reprepare
+create table t1 (a int, b int);
+insert into t1 values(1,1),(2,2),(3,3);
+create table t2 like t1;
+insert into t1 values(2,2);
+prepare stmt1 from "select a,b from t1";
+prepare stmt2 from "select a,b from (select * from t1) as t1";
+prepare stmt3 from "select * from t1 where a = 2 and b = 2";
+prepare stmt4 from "select * from t2 where (a,b) in (select * from t1)";
+prepare stmt5 from "select * from t1 union select * from t2";
+prepare stmt6 from "select * from t1 union all select * from t2";
+prepare stmt7 from "insert into t1 set a = 4, b = 4";
+prepare stmt8 from "insert into t1 select * from t2";
+# Attention: Result logging is disabled.
+execute stmt8;
+execute stmt7;
+execute stmt6;
+execute stmt5;
+execute stmt4;
+execute stmt3;
+execute stmt2;
+execute stmt1;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+alter table t1 drop column b;
+execute stmt8;
+ERROR 21S01: Column count doesn't match value count at row 1
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt7;
+ERROR 42S22: Unknown column 'b' in 'field list'
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt6;
+ERROR 21000: The used SELECT statements have a different number of columns
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt5;
+ERROR 21000: The used SELECT statements have a different number of columns
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt4;
+ERROR 21000: Operand should contain 2 column(s)
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt3;
+ERROR 42S22: Unknown column 'b' in 'where clause'
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt2;
+ERROR 42S22: Unknown column 'b' in 'field list'
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt1;
+ERROR 42S22: Unknown column 'b' in 'field list'
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt8;
+ERROR 21S01: Column count doesn't match value count at row 1
+call p_verify_reprepare_count(1);
+ERROR
+Expected: 1, actual: 0
+execute stmt7;
+ERROR 42S22: Unknown column 'b' in 'field list'
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt6;
+ERROR 21000: The used SELECT statements have a different number of columns
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt5;
+ERROR 21000: The used SELECT statements have a different number of columns
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt4;
+ERROR 21000: Operand should contain 2 column(s)
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt3;
+ERROR 42S22: Unknown column 'b' in 'where clause'
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt2;
+ERROR 42S22: Unknown column 'b' in 'field list'
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt1;
+ERROR 42S22: Unknown column 'b' in 'field list'
+call p_verify_reprepare_count(1);
+SUCCESS
+
+# Why does the INSERT ... SELECT does not get a reprepare or is
+# only the counter not incremented?
+execute stmt8;
+ERROR 21S01: Column count doesn't match value count at row 1
+call p_verify_reprepare_count(1);
+ERROR
+Expected: 1, actual: 0
+alter table t2 add column c int;
+execute stmt8;
+ERROR 21S01: Column count doesn't match value count at row 1
+call p_verify_reprepare_count(1);
+SUCCESS
+
+deallocate prepare stmt8;
+deallocate prepare stmt7;
+deallocate prepare stmt6;
+deallocate prepare stmt5;
+deallocate prepare stmt4;
+deallocate prepare stmt3;
+deallocate prepare stmt2;
+deallocate prepare stmt1;
+drop table t1;
+drop table t2;
+# select AVG(<col>) + optimizer uses index meets loss of the index
+create table t1 (a int, b int, primary key(b),unique index t1_unq_idx(a));
+insert into t1 set a = 0, b = 0;
+insert into t1 select a + 1, b + 1 from t1;
+insert into t1 select a + 2, b + 2 from t1;
+insert into t1 select a + 4, b + 4 from t1;
+insert into t1 select a + 8, b + 8 from t1;
+# Optimizer strategy: Possible keys = NULL , Extra = Using index
+prepare stmt from "select avg(a) from t1";
+execute stmt;
+avg(a)
+7.5000
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+avg(a)
+7.5000
+call p_verify_reprepare_count(0);
+SUCCESS
+
+alter table t1 drop index t1_unq_idx;
+# Optimizer strategy: Possible keys = NULL , Extra =
+execute stmt;
+avg(a)
+7.5000
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+avg(a)
+7.5000
+call p_verify_reprepare_count(0);
+SUCCESS
+
+# select AVG(<col>) + optimizer uses table scan meets a new index
+alter table t1 add unique index t1_unq_idx(a);
+# Optimizer strategy: Possible keys = NULL , Extra = Using index
+execute stmt;
+avg(a)
+7.5000
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+avg(a)
+7.5000
+call p_verify_reprepare_count(0);
+SUCCESS
+
+deallocate prepare stmt;
+drop table t1;
+# table replaced by not updatable view - Insert
+create table t1 (a int);
+prepare stmt from "insert into t1 values(1)";
+execute stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop table t1;
+create view t1 as select 1;
+execute stmt;
+ERROR HY000: The target table t1 of the INSERT is not insertable-into
+call p_verify_reprepare_count(1);
+SUCCESS
+
+drop view t1;
+create table t2 (a int);
+create view t1 as select * from t2 with check option;
+execute stmt;
+call p_verify_reprepare_count(1);
+SUCCESS
+
+execute stmt;
+call p_verify_reprepare_count(0);
+SUCCESS
+
+select * from t1;
+a
+1
+1
+deallocate prepare stmt;
+drop view t1;
+drop table t2;
+=====================================================================
+Some freestyle tests
+=====================================================================
+create temporary table t1 as select 1 as a;
+create procedure p1()
+begin
+drop temporary table t1;
+end|
+create function f1() returns int
+begin
+call p1();
+return 1;
+end|
+prepare stmt from "select f1() as my_column, a from t1";
+execute stmt;
+ERROR HY000: Can't reopen table: 't1'
+call p_verify_reprepare_count(0);
+SUCCESS
+
+select * from t1;
+a
+1
+prepare stmt from "select a, f1() as my_column from t1";
+execute stmt;
+ERROR HY000: Can't reopen table: 't1'
+call p_verify_reprepare_count(0);
+SUCCESS
+
+select * from t1;
+a
+1
+prepare stmt from "select f1() as my_column, count(*) from t1";
+execute stmt;
+ERROR HY000: Can't reopen table: 't1'
+call p_verify_reprepare_count(0);
+SUCCESS
+
+select * from t1;
+a
+1
+prepare stmt from "select count(*), f1() as my_column from t1";
+execute stmt;
+ERROR HY000: Can't reopen table: 't1'
+call p_verify_reprepare_count(0);
+SUCCESS
+
+select * from t1;
+a
+1
+# Execute fails, no drop of temporary table
+prepare stmt from "select 1 as my_column from (select 1) as t2
+ where exists (select f1() from t1)";
+execute stmt;
+my_column
+1
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+my_column
+1
+call p_verify_reprepare_count(0);
+SUCCESS
+
+select * from t1;
+a
+1
+# Execute drops temporary table
+prepare stmt from "select f1()";
+execute stmt;
+f1()
+1
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+ERROR 42S02: Unknown table 't1'
+call p_verify_reprepare_count(0);
+SUCCESS
+
+drop function f1;
+drop procedure p1;
+deallocate prepare stmt;
+# Execute fails, temporary table is not replaced by another
+create temporary table t1 as select 1 as a;
+create procedure p1()
+begin
+drop temporary table t1;
+create temporary table t1 as select 'abc' as a;
+end|
+create function f1() returns int
+begin
+call p1();
+return 1;
+end|
+prepare stmt from "select count(*), f1() as my_column from t1";
+execute stmt;
+ERROR HY000: Can't reopen table: 't1'
+call p_verify_reprepare_count(0);
+SUCCESS
+
+select * from t1;
+a
+1
+deallocate prepare stmt;
+prepare stmt from "call p1";
+execute stmt;
+drop procedure p1;
+create schema mysqltest;
+create procedure mysqltest.p1()
+begin
+drop schema mysqltest;
+create schema mysqltest;
+end|
+execute stmt;
+ERROR 42000: PROCEDURE test.p1 does not exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+execute stmt;
+ERROR 42000: PROCEDURE test.p1 does not exist
+call p_verify_reprepare_count(0);
+SUCCESS
+
+deallocate prepare stmt;
+drop schema mysqltest;
+drop temporary table t1;
+# Cleanup
+#
+drop temporary table if exists t1;
+drop table if exists t1, t2;
+drop procedure if exists p_verify_reprepare_count;
+drop procedure if exists p1;
+drop function if exists f1;
+drop view if exists t1;
+drop schema if exists mysqltest;
diff --git a/mysql-test/r/query_cache_merge.result b/mysql-test/r/query_cache_merge.result
index c6df4266de2..d2bbe217815 100644
--- a/mysql-test/r/query_cache_merge.result
+++ b/mysql-test/r/query_cache_merge.result
@@ -18,3 +18,4 @@ Variable_name Value
Qcache_queries_in_cache 0
drop table t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,t34,t35,t36,t37,t38,t39,t40,t41,t42,t43,t44,t45,t46,t47,t48,t49,t50,t51,t52,t53,t54,t55,t56,t57,t58,t59,t60,t61,t62,t63,t64,t65,t66,t67,t68,t69,t70,t71,t72,t73,t74,t75,t76,t77,t78,t79,t80,t81,t82,t83,t84,t85,t86,t87,t88,t89,t90,t91,t92,t93,t94,t95,t96,t97,t98,t99,t100,t101,t102,t103,t104,t105,t106,t107,t108,t109,t110,t111,t112,t113,t114,t115,t116,t117,t118,t119,t120,t121,t122,t123,t124,t125,t126,t127,t128,t129,t130,t131,t132,t133,t134,t135,t136,t137,t138,t139,t140,t141,t142,t143,t144,t145,t146,t147,t148,t149,t150,t151,t152,t153,t154,t155,t156,t157,t158,t159,t160,t161,t162,t163,t164,t165,t166,t167,t168,t169,t170,t171,t172,t173,t174,t175,t176,t177,t178,t179,t180,t181,t182,t183,t184,t185,t186,t187,t188,t189,t190,t191,t192,t193,t194,t195,t196,t197,t198,t199,t200,t201,t202,t203,t204,t205,t206,t207,t208,t209,t210,t211,t212,t213,t214,t215,t216,t217,t218,t219,t220,t221,t222,t223,t224,t225,t226,t227,t228,t229,t230,t231,t232,t233,t234,t235,t236,t237,t238,t239,t240,t241,t242,t243,t244,t245,t246,t247,t248,t249,t250,t251,t252,t253,t254,t255,t256,t257,t00;
SET @@global.query_cache_size=0;
+set @@global.table_definition_cache=@save_table_definition_cache;
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index e7f5c41513b..35d5134fa6b 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -820,7 +820,6 @@ call p1();
drop trigger t1_bi;
create trigger t1_bi after insert on t1 for each row insert into t3 values (new.id);
execute stmt1;
-ERROR 42S02: Table 'test.t3' doesn't exist
call p1();
ERROR 42S02: Table 'test.t3' doesn't exist
deallocate prepare stmt1;
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index e5c3c860c93..3f66599751d 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -1014,3 +1014,13 @@ Variable_name='table_lock_wait_timeout';
Variable_name Value
table_definition_cache #
table_lock_wait_timeout #
+
+# --
+# -- Bug#34820: log_output can be set to illegal value.
+# --
+SET GLOBAL log_output = '';
+ERROR 42000: Variable 'log_output' can't be set to the value of ''
+SET GLOBAL log_output = 0;
+ERROR 42000: Variable 'log_output' can't be set to the value of '0'
+
+# -- End of Bug#34820.
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index 85f9691e443..0f240e7eccf 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -10,7 +10,6 @@
#
##############################################################################
federated_transactions : Bug#29523 Transactions do not work
-ps_ddl : Bug#12093 2007-12-14 pending WL#4165 / WL#4166
csv_alter_table : Bug#33696 2008-01-21 pcrews no .result file - bug allows NULL columns in CSV tables
user_limits : Bug#23921 random failure of user_limits.test
status : Bug#32966 main.status fails
diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test
index d00881bad99..3fac767468e 100644
--- a/mysql-test/t/grant.test
+++ b/mysql-test/t/grant.test
@@ -1266,6 +1266,12 @@ DROP DATABASE db27878;
use test;
DROP TABLE t1;
+--echo #
+--echo # Bug#33275 Server crash when creating temporary table mysql.user
+--echo #
+CREATE TEMPORARY TABLE mysql.user (id INT);
+FLUSH PRIVILEGES;
+DROP TABLE mysql.user;
#
# Bug #33201 Crash occurs when granting update privilege on one column of a view
#
diff --git a/mysql-test/t/log_state.test b/mysql-test/t/log_state.test
index a340238b724..2fd2cabc97c 100644
--- a/mysql-test/t/log_state.test
+++ b/mysql-test/t/log_state.test
@@ -231,6 +231,34 @@ set global slow_query_log_file= NULL;
set global general_log_file= @old_general_log_file;
set global slow_query_log_file= @old_slow_query_log_file;
+###########################################################################
+
+--echo
+--echo # --
+--echo # -- Bug#32748: Inconsistent handling of assignments to
+--echo # -- general_log_file/slow_query_log_file.
+--echo # --
+
+--echo
+SET @general_log_file_saved = @@global.general_log_file;
+SET @slow_query_log_file_saved = @@global.slow_query_log_file;
+
+--echo
+SET GLOBAL general_log_file = 'bug32748.query.log';
+SET GLOBAL slow_query_log_file = 'bug32748.slow.log';
+
+--echo
+SHOW VARIABLES LIKE '%log_file';
+
+--echo
+SET GLOBAL general_log_file = @general_log_file_saved;
+SET GLOBAL slow_query_log_file = @slow_query_log_file_saved;
+
+--echo
+--echo # -- End of Bug#32748.
+
+###########################################################################
+
--echo End of 5.1 tests
--enable_ps_protocol
diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test
index 42bf39890de..95cbd908933 100644
--- a/mysql-test/t/ps_1general.test
+++ b/mysql-test/t/ps_1general.test
@@ -181,7 +181,7 @@ create table t5
a int primary key,
b char(30),
c int,
- d timestamp default current_timestamp
+ d timestamp default '2008-02-23 09:23:45'
);
insert into t5( a, b, c) values( 9, 'recreated table', 9);
execute stmt2 ;
@@ -191,7 +191,7 @@ drop table t5 ;
create table t5
(
a int primary key,
- d timestamp default current_timestamp,
+ d timestamp default '2008-02-23 09:23:45',
b char(30),
c int
);
@@ -218,7 +218,6 @@ create table t5
f3 int
);
insert into t5( f1, f2, f3) values( 9, 'recreated table', 9);
---error 1054
execute stmt2 ;
drop table t5 ;
diff --git a/mysql-test/t/ps_ddl.test b/mysql-test/t/ps_ddl.test
index c824d17063b..e19e73df3ac 100644
--- a/mysql-test/t/ps_ddl.test
+++ b/mysql-test/t/ps_ddl.test
@@ -47,1793 +47,2025 @@
# - Part 20: Special tables (log tables)
# - Part 21: Special tables (system tables)
# - Part 22: Special tables (views temp tables)
-# - Part 23: Special tables (internal join tables)
-# - Part 24: Special statements
-# - Part 25: Testing the strength of TABLE_SHARE version
-
-let $base_count = SELECT VARIABLE_VALUE from
-INFORMATION_SCHEMA.SESSION_STATUS where variable_name='COM_STMT_REPREPARE'
-into @base_count ;
-
-let $check = SELECT CASE (VARIABLE_VALUE - @base_count - @expected)
- WHEN 0 THEN "PASSED"
- ELSE "FAILED"
- END
- AS `CHECK`,
- (VARIABLE_VALUE - @base_count - @expected) AS `OFFSET`
- from INFORMATION_SCHEMA.SESSION_STATUS
- where variable_name='COM_STMT_REPREPARE' ;
-
-eval $base_count;
-set @expected = 0;
-
-# Maintainer:
-# When not expecting a re-prepare, write the test like this:
-# execute stmt;
-# eval $check;
-#
-# When expecting a re-prepare, write the test like this:
-# set @expected = @expected + 1;
-# execute stmt;
-# eval $check;
-#
+# - Part 23: Special statements
+# - Part 24: Testing the strength of TABLE_SHARE version
+--disable_warnings
+drop temporary table if exists t1, t2, t3;
+drop table if exists t1, t2, t3;
+drop procedure if exists p_verify_reprepare_count;
+drop procedure if exists p1;
+drop function if exists f1;
+drop view if exists v1, v2;
+--enable_warnings
+
+delimiter |;
+create procedure p_verify_reprepare_count(expected int)
+begin
+ declare old_reprepare_count int default @reprepare_count;
+
+ select variable_value from
+ information_schema.session_status where
+ variable_name='com_stmt_reprepare'
+ into @reprepare_count;
+
+ if old_reprepare_count + expected <> @reprepare_count then
+ select concat("Expected: ", expected,
+ ", actual: ", @reprepare_count - old_reprepare_count)
+ as "ERROR";
+ else
+ select '' as "SUCCESS";
+ end if;
+end|
+delimiter ;|
+set @reprepare_count= 0;
+flush status;
--echo =====================================================================
---echo Testing 1: NOTHING -> TABLE transitions
+--echo Part 1: NOTHING -> TABLE transitions
--echo =====================================================================
---disable_warnings
-drop table if exists t1;
---enable_warnings
-
# can not be tested since prepare failed
--error ER_NO_SUCH_TABLE
-prepare stmt from 'select * from t1';
+prepare stmt from "select * from t1";
--echo =====================================================================
---echo Testing 2: NOTHING -> TEMPORARY TABLE transitions
+--echo Part 2: NOTHING -> TEMPORARY TABLE transitions
--echo =====================================================================
# can not be tested
--echo =====================================================================
---echo Testing 3: NOTHING -> VIEW transitions
+--echo Part 3: NOTHING -> VIEW transitions
--echo =====================================================================
# can not be tested
--echo =====================================================================
---echo Testing 4: TABLE -> NOTHING transitions
+--echo Part 4: TABLE -> NOTHING transitions
--echo =====================================================================
---disable_warnings
-drop table if exists t4;
---enable_warnings
+--echo # Test 4-a: select ... from <table>
+create table t1 (a int);
-create table t4(a int);
+prepare stmt from "select * from t1";
+execute stmt;
+call p_verify_reprepare_count(0);
+execute stmt;
+call p_verify_reprepare_count(0);
+
+drop table t1;
+--error ER_NO_SUCH_TABLE
+execute stmt;
+call p_verify_reprepare_count(0);
+--error ER_NO_SUCH_TABLE
+execute stmt;
+call p_verify_reprepare_count(0);
+deallocate prepare stmt;
-prepare stmt from 'select * from t4';
+--echo # Test 4-b: TABLE -> NOTHING by renaming the table
+create table t1 (a int);
+prepare stmt from "select * from t1";
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop table t4;
+rename table t1 to t2;
--error ER_NO_SUCH_TABLE
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
--error ER_NO_SUCH_TABLE
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
+
+deallocate prepare stmt;
+drop table t2;
--echo =====================================================================
---echo Testing 5: TABLE -> TABLE (DDL) transitions
+--echo Part 5: TABLE -> TABLE (DDL) transitions
--echo =====================================================================
---disable_warnings
-drop table if exists t5;
---enable_warnings
+create table t1 (a int);
-create table t5(a int);
-
-prepare stmt from 'select a from t5';
+prepare stmt from "select a from t1";
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-alter table t5 add column (b int);
+alter table t1 add column (b int);
-set @expected = @expected + 1;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
+
+drop table t1;
+deallocate prepare stmt;
-drop table t5;
--echo =====================================================================
---echo Testing 6: TABLE -> TABLE (TRIGGER) transitions
+--echo Part 6: TABLE -> TABLE (TRIGGER) transitions
--echo =====================================================================
-#
-# Test 6-a: adding a relevant trigger
-# Test 6-b: adding an irrelevant trigger
-# Test 6-c: changing a relevant trigger
-# Test 6-d: changing an irrelevant trigger
-# Test 6-e: removing a relevant trigger
-# Test 6-f: removing an irrelevant trigger
-#
-
---disable_warnings
-drop table if exists t6;
---enable_warnings
+--echo # Test 6-a: adding a relevant trigger
-create table t6(a int);
+create table t1 (a int);
-prepare stmt from 'insert into t6(a) value (?)';
+prepare stmt from "insert into t1 (a) value (?)";
set @val=1;
execute stmt using @val;
-eval $check;
-set @val=2;
-execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(0);
# Relevant trigger: execute should reprepare
-delimiter $$;
-create trigger t6_bi before insert on t6 for each row
- begin
- set @message= "t6_bi";
- end
-$$
-delimiter ;$$
-
-set @message="none";
+create trigger t1_bi before insert on t1 for each row
+ set @message= new.a;
+
+set @val=2;
+execute stmt using @val;
+call p_verify_reprepare_count(1);
+select @message;
set @val=3;
-set @expected = @expected + 1;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(0);
select @message;
+
+prepare stmt from "insert into t1 (a) value (?)";
set @val=4;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(0);
select @message;
-prepare stmt from 'insert into t6(a) value (?)';
-set @message="none";
+--echo # Test 6-b: adding an irrelevant trigger
+
+# Unrelated trigger: reprepare may or may not happen, implementation dependent
+create trigger t1_bd before delete on t1 for each row
+ set @message= old.a;
+
set @val=5;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(1);
select @message;
-set @message="none";
set @val=6;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(0);
select @message;
-# Unrelated trigger: execute can pass of fail, implementation dependent
-delimiter $$;
-create trigger t6_bd before delete on t6 for each row
- begin
- set @message= "t6_bd";
- end
-$$
-delimiter ;$$
-
-set @message="none";
+prepare stmt from "insert into t1 (a) value (?)";
set @val=7;
-set @expected = @expected + 1;
-execute stmt using @val;
-eval $check;
-select @message;
-set @message="none";
-set @val=8;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(0);
select @message;
-prepare stmt from 'insert into t6(a) value (?)';
-set @message="none";
-set @val=9;
-execute stmt using @val;
-eval $check;
-select @message;
-set @message="none";
-set @val=10;
-execute stmt using @val;
-eval $check;
-select @message;
+--echo # Test 6-c: changing a relevant trigger
# Relevant trigger: execute should reprepare
-drop trigger t6_bi;
-delimiter $$;
-create trigger t6_bi before insert on t6 for each row
- begin
- set @message= "t6_bi (2)";
- end
-$$
-delimiter ;$$
-
-set @message="none";
-set @val=11;
-set @expected = @expected + 1;
-execute stmt using @val;
-eval $check;
-select @message;
-set @val=12;
-execute stmt using @val;
-eval $check;
-select @message;
+drop trigger t1_bi;
+create trigger t1_bi before insert on t1 for each row
+ set @message= concat("new trigger: ", new.a);
-prepare stmt from 'insert into t6(a) value (?)';
-set @message="none";
-set @val=13;
+set @val=8;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(1);
select @message;
-set @message="none";
-set @val=14;
+set @val=9;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(0);
select @message;
-# Unrelated trigger: execute can pass of fail, implementation dependent
-drop trigger t6_bd;
-delimiter $$;
-create trigger t6_bd before delete on t6 for each row
- begin
- set @message= "t6_bd (2)";
- end
-$$
-delimiter ;$$
-
-set @message="none";
-set @val=15;
-set @expected = @expected + 1;
-execute stmt using @val;
-eval $check;
-select @message;
-set @message="none";
-set @val=16;
+prepare stmt from "insert into t1 (a) value (?)";
+set @val=10;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(0);
select @message;
-prepare stmt from 'insert into t6(a) value (?)';
-set @message="none";
-set @val=17;
-execute stmt using @val;
-eval $check;
-select @message;
-set @message="none";
-set @val=18;
-execute stmt using @val;
-eval $check;
-select @message;
+--echo # Test 6-d: changing an irrelevant trigger
-drop trigger t6_bi;
+# Unrelated trigger: reprepare may or may not happen, implementation dependent
+drop trigger t1_bd;
-set @message="none";
-set @val=19;
-set @expected = @expected + 1;
-execute stmt using @val;
-eval $check;
-select @message;
-set @val=20;
+set @val=11;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(1);
select @message;
-prepare stmt from 'insert into t6(a) value (?)';
-set @message="none";
-set @val=21;
+--echo Test 6-e: removing a relevant trigger
+
+drop trigger t1_bi;
+
+set @val=12;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(1);
select @message;
-set @val=22;
+set @val=13;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(0);
select @message;
-drop trigger t6_bd;
-
-set @val=23;
-set @expected = @expected + 1;
-execute stmt using @val;
-eval $check;
-select @message;
-set @val=24;
+prepare stmt from "insert into t1 (a) value (?)";
+set @val=14;
execute stmt using @val;
-eval $check;
+call p_verify_reprepare_count(0);
select @message;
-select * from t6 order by a;
-drop table t6;
+select * from t1 order by a;
+drop table t1;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 7: TABLE -> TABLE (TRIGGER dependencies) transitions
+--echo Part 7: TABLE -> TABLE (TRIGGER dependencies) transitions
--echo =====================================================================
-#
-# Test 7-a: dependent PROCEDURE has changed
-# Test 7-b: dependent FUNCTION has changed
-# Test 7-c: dependent VIEW has changed
-# Test 7-d: dependent TABLE has changed
-# Test 7-e: dependent TABLE TRIGGER has changed
-#
-
---disable_warnings
-drop table if exists t7_proc;
-drop table if exists t7_func;
-drop table if exists t7_view;
-drop table if exists t7_table;
-drop table if exists t7_dependent_table;
-drop table if exists t7_table_trigger;
-drop table if exists t7_audit;
-drop procedure if exists audit_proc;
-drop function if exists audit_func;
-drop view if exists audit_view;
---enable_warnings
-
-create table t7_proc(a int);
-create table t7_func(a int);
-create table t7_view(a int);
-create table t7_table(a int);
-create table t7_table_trigger(a int);
-
-create table t7_audit(old_a int, new_a int, reason varchar(50));
-create table t7_dependent_table(old_a int, new_a int, reason varchar(50));
-
-create procedure audit_proc(a int)
- insert into t7_audit values (NULL, a, "proc v1");
+--echo # Test 7-a: dependent PROCEDURE has changed
+--echo #
+--echo # Note, this scenario is not supported, subject of Bug#12093
+--echo #
+
+create table t1 (a int);
+create trigger t1_ai after insert on t1 for each row
+ call p1(new.a);
+create procedure p1(a int) begin end;
+prepare stmt from "insert into t1 (a) values (?)";
+set @var= 1;
+execute stmt using @var;
+drop procedure p1;
+create procedure p1 (a int) begin end;
+set @var= 2;
+--error ER_SP_DOES_NOT_EXIST
+execute stmt using @var;
+--echo # Cleanup
+drop procedure p1;
+call p_verify_reprepare_count(0);
+
+--echo # Test 7-b: dependent FUNCTION has changed
+--echo #
+--echo # Note, this scenario is not supported, subject of Bug#12093
+--echo #
+drop trigger t1_ai;
+create trigger t1_ai after insert on t1 for each row
+ select f1(new.a+1) into @var;
+create function f1 (a int) returns int return a;
+prepare stmt from "insert into t1(a) values (?)";
+set @var=3;
+execute stmt using @var;
+select @var;
+drop function f1;
+create function f1 (a int) returns int return 0;
+--error ER_SP_DOES_NOT_EXIST
+execute stmt using @var;
+call p_verify_reprepare_count(0);
+drop function f1;
+deallocate prepare stmt;
-create function audit_func() returns varchar(50)
- return "func v1";
-
-create view audit_view as select "view v1" as reason from dual;
-
-create trigger t7_proc_bi before insert on t7_proc for each row
- call audit_proc(NEW.a);
-
-create trigger t7_func_bi before insert on t7_func for each row
- insert into t7_audit values (NULL, NEW.a, audit_func());
-
-create trigger t7_view_bi before insert on t7_view for each row
- insert into t7_audit values (NULL, NEW.a, (select reason from audit_view));
-
-create trigger t7_table_bi before insert on t7_table for each row
- insert into t7_dependent_table values (NULL, NEW.a, "dependent table");
-
-create trigger t7_table_trigger_bi before insert on t7_dependent_table
- for each row set NEW.reason="trigger v1";
-
-prepare stmt_proc from 'insert into t7_proc(a) value (?)';
-set @val=101;
-execute stmt_proc using @val;
-eval $check;
-set @val=102;
-execute stmt_proc using @val;
-eval $check;
-
-drop procedure audit_proc;
-
-create procedure audit_proc(a int)
- insert into t7_audit values (NULL, a, "proc v2");
-
-set @val=103;
-set @expected = @expected + 1;
-execute stmt_proc using @val;
-eval $check;
-set @val=104;
-execute stmt_proc using @val;
-eval $check;
-
-
-prepare stmt_func from 'insert into t7_func(a) value (?)';
-set @val=201;
-execute stmt_func using @val;
-eval $check;
-set @val=202;
-execute stmt_func using @val;
-eval $check;
-
-drop function audit_func;
-
-create function audit_func() returns varchar(50)
- return "func v2";
-
-set @val=203;
-set @expected = @expected + 1;
-execute stmt_func using @val;
-eval $check;
-set @val=204;
-execute stmt_func using @val;
-eval $check;
-
-prepare stmt_view from 'insert into t7_view(a) value (?)';
-set @val=301;
-execute stmt_view using @val;
-eval $check;
-set @val=302;
-execute stmt_view using @val;
-eval $check;
-
-drop view audit_view;
-
-create view audit_view as select "view v2" as reason from dual;
-
-# Because of Bug#33255, the wrong result is still produced for cases
-# 303 and 304, even after re-preparing the statement.
-# This is because the table trigger is cached and is not invalidated.
-
-set @val=303;
-set @expected = @expected + 1;
-execute stmt_view using @val;
-eval $check;
-set @val=304;
-execute stmt_view using @val;
-eval $check;
-
-
-prepare stmt_table from 'insert into t7_table(a) value (?)';
-set @val=401;
-execute stmt_table using @val;
-eval $check;
-set @val=402;
-execute stmt_table using @val;
-eval $check;
-
-alter table t7_dependent_table add column comments varchar(100) default NULL;
-
-set @val=403;
-set @expected = @expected + 1;
---error ER_WRONG_VALUE_COUNT_ON_ROW
-execute stmt_table using @val;
-eval $check;
-set @val=404;
-set @expected = @expected + 1;
---error ER_WRONG_VALUE_COUNT_ON_ROW
-execute stmt_table using @val;
-eval $check;
-
-alter table t7_dependent_table drop column comments;
-
-set @val=405;
-set @expected = @expected + 1;
-execute stmt_table using @val;
-eval $check;
-set @val=406;
-execute stmt_table using @val;
-eval $check;
-
-
-prepare stmt_table_trigger from 'insert into t7_table(a) value (?)';
-set @val=501;
-execute stmt_table_trigger using @val;
-eval $check;
-set @val=502;
-execute stmt_table_trigger using @val;
-eval $check;
-
-drop trigger t7_table_trigger_bi;
-
-create trigger t7_table_trigger_bi before insert on t7_dependent_table
- for each row set NEW.reason="trigger v2";
-
-set @val=503;
-set @expected = @expected + 1;
-execute stmt_table_trigger using @val;
-eval $check;
-set @val=504;
-execute stmt_table_trigger using @val;
-eval $check;
-
-select * from t7_audit order by new_a;
-
-select * from t7_dependent_table order by new_a;
-
-drop table t7_proc;
-drop table t7_func;
-drop table t7_view;
-drop table t7_table;
-drop table t7_dependent_table;
-drop table t7_table_trigger;
-drop table t7_audit;
-drop procedure audit_proc;
-drop function audit_func;
-drop view audit_view;
+--echo # Test 7-c: dependent VIEW has changed
+--echo #
+--echo # Note, this scenario is not functioning correctly, see
+--echo # Bug#33255 Trigger using views and view ddl : corrupted triggers
+--echo # and Bug #33000 Triggers do not detect changes in meta-data.
+--echo #
+drop trigger t1_ai;
+create table t2 (a int unique);
+create table t3 (a int unique);
+create view v1 as select a from t2;
+create trigger t1_ai after insert on t1 for each row
+ insert into v1 (a) values (new.a);
+
+--echo # Demonstrate that the same bug is present
+--echo # without prepared statements
+insert into t1 (a) values (5);
+select * from t2;
+select * from t3;
+drop view v1;
+create view v1 as select a from t3;
+--error ER_NO_SUCH_TABLE
+insert into t1 (a) values (6);
+flush table t1;
+insert into t1 (a) values (6);
+select * from t2;
+select * from t3;
+
+prepare stmt from "insert into t1 (a) values (?)";
+set @var=7;
+execute stmt using @var;
+call p_verify_reprepare_count(0);
+select * from t3;
+select * from t2;
+drop view v1;
+create view v1 as select a from t2;
+set @var=8;
+execute stmt using @var;
+call p_verify_reprepare_count(0);
+--echo #
+--echo # Sic: the insert went into t3, even though the view now
+--echo # points at t2. This is because neither the merged view
+--echo # nor its prelocking list are affected by view DDL
+--echo # The binary log is of course wrong, since it is not
+--echo # using prepared statements
+--echo #
+select * from t2;
+select * from t3;
+flush table t1;
+set @var=9;
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+select * from t2;
+select * from t3;
+drop view v1;
+drop table t1,t2,t3;
+
+--echo # Test 7-d: dependent TABLE has changed
+create table t1 (a int);
+create trigger t1_ai after insert on t1 for each row
+ insert into t2 (a) values (new.a);
+create table t2 (a int);
+
+prepare stmt from "insert into t1 (a) values (?)";
+set @var=1;
+execute stmt using @var;
+alter table t2 add column comment varchar(255);
+set @var=2;
+--echo # Since the dependent table is tracked in the prelocked
+--echo # list of the prepared statement, invalidation happens
+--echo # and the statement is re-prepared. This is an unnecessary
+--echo # side effect, since the statement that *is* dependent
+--echo # on t2 definition is inside the trigger, and it is currently
+--echo # not reprepared (see the previous test case).
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+select * from t1;
+select * from t2;
+drop table t1,t2;
+
+--echo # Test 7-e: dependent TABLE TRIGGER has changed
+create table t1 (a int);
+create trigger t1_ai after insert on t1 for each row
+ insert into t2 (a) values (new.a);
+create table t2 (a int unique);
+create trigger t2_ai after insert on t2 for each row
+ insert into t3 (a) values (new.a);
+create table t3 (a int unique);
+create table t4 (a int unique);
+
+insert into t1 (a) values (1);
+select * from t1 join t2 on (t1.a=t2.a) join t3 on (t2.a=t3.a);
+drop trigger t2_ai;
+create trigger t2_ai after insert on t2 for each row
+ insert into t4 (a) values (new.a);
+insert into t1 (a) values (2);
+select * from t1 join t2 on (t1.a=t2.a) join t4 on (t2.a=t4.a);
+
+prepare stmt from "insert into t1 (a) values (?)";
+set @var=3;
+execute stmt using @var;
+select * from t1 join t2 on (t1.a=t2.a) join t4 on (t2.a=t4.a);
+drop trigger t2_ai;
+create trigger t2_ai after insert on t2 for each row
+ insert into t3 (a) values (new.a);
+set @var=4;
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+select * from t1 join t2 on (t1.a=t2.a) join t3 on (t2.a=t3.a);
+select * from t1 join t2 on (t1.a=t2.a) join t4 on (t2.a=t4.a);
+
+drop table t1, t2, t3, t4;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 8: TABLE -> TEMPORARY TABLE transitions
+--echo Part 8: TABLE -> TEMPORARY TABLE transitions
--echo =====================================================================
---disable_warnings
-drop table if exists t8;
---enable_warnings
+--echo # Test 8-a: base table used recreated as temporary table
+create table t1 (a int);
-create table t8(a int);
+prepare stmt from "select * from t1";
+execute stmt;
+
+drop table t1;
+create temporary table t1 (a int);
-prepare stmt from 'select * from t8';
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
+
+drop table t1;
+deallocate prepare stmt;
-drop table t8;
-create temporary table t8(a int);
+--echo # Test 8-b: temporary table has precedence over base table with same name
+create table t1 (a int);
+prepare stmt from 'select count(*) from t1';
+execute stmt;
+call p_verify_reprepare_count(0);
+execute stmt;
+call p_verify_reprepare_count(0);
-set @expected = @expected + 1;
+create temporary table t1 AS SELECT 1;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
+
+deallocate prepare stmt;
+drop temporary table t1;
+drop table t1;
-drop table t8;
--echo =====================================================================
---echo Testing 9: TABLE -> VIEW transitions
+--echo Part 9: TABLE -> VIEW transitions
--echo =====================================================================
---disable_warnings
-drop table if exists t9;
-drop table if exists t9_b;
---enable_warnings
-
-create table t9(a int);
-create table t9_b(a int);
+create table t1 (a int);
-prepare stmt from 'select * from t9';
+prepare stmt from "select * from t1";
execute stmt;
-eval $check;
-execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop table t9;
-create view t9 as select * from t9_b;
+drop table t1;
+create table t2 (a int);
+create view t1 as select * from t2;
-set @expected = @expected + 1;
-execute stmt;
-eval $check;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
-drop view t9;
-drop table t9_b;
+drop view t1;
+drop table t2;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 10: TEMPORARY TABLE -> NOTHING transitions
+--echo Part 10: TEMPORARY TABLE -> NOTHING transitions
--echo =====================================================================
---disable_warnings
-drop temporary table if exists t10;
---enable_warnings
+create temporary table t1 (a int);
-create temporary table t10(a int);
-
-prepare stmt from 'select * from t10';
-execute stmt;
-eval $check;
+prepare stmt from "select * from t1";
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop temporary table t10;
+drop temporary table t1;
--error ER_NO_SUCH_TABLE
execute stmt;
-eval $check;
---error ER_NO_SUCH_TABLE
-execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 11: TEMPORARY TABLE -> TABLE transitions
+--echo Part 11: TEMPORARY TABLE -> TABLE transitions
--echo =====================================================================
---disable_warnings
-drop table if exists t11;
-drop temporary table if exists t11;
---enable_warnings
-
-create table t11(a int);
-insert into t11(a) value (1);
-create temporary table t11(a int);
+--echo # Test 11-a: temporary table replaced by base table
+create table t1 (a int);
+insert into t1 (a) value (1);
+create temporary table t1 (a int);
-prepare stmt from 'select * from t11';
+prepare stmt from "select * from t1";
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
+
+drop temporary table t1;
+
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
+
+select * from t1;
+drop table t1;
+deallocate prepare stmt;
-drop temporary table t11;
-set @expected = @expected + 1;
+--echo # Test 11-b: temporary table has precedence over base table with same name
+--echo # temporary table disappears
+create table t1 (a int);
+create temporary table t1 as select 1 as a;
+prepare stmt from "select count(*) from t1";
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
+
+drop temporary table t1;
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
+
+deallocate prepare stmt;
+drop table t1;
-select * from t11;
-drop table t11;
--echo =====================================================================
---echo Testing 12: TEMPORARY TABLE -> TEMPORARY TABLE (DDL) transitions
+--echo Part 12: TEMPORARY TABLE -> TEMPORARY TABLE (DDL) transitions
--echo =====================================================================
---disable_warnings
-drop temporary table if exists t12;
---enable_warnings
-
-create temporary table t12(a int);
+create temporary table t1 (a int);
-prepare stmt from 'select a from t12';
-execute stmt;
-eval $check;
+prepare stmt from "select a from t1";
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop temporary table t12;
-create temporary table t12(a int, b int);
+drop temporary table t1;
+create temporary table t1 (a int, b int);
-set @expected = @expected + 1;
execute stmt;
-eval $check;
-execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
-select * from t12;
-drop table t12;
+select * from t1;
+drop temporary table t1;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 13: TEMPORARY TABLE -> VIEW transitions
+--echo Part 13: TEMPORARY TABLE -> VIEW transitions
--echo =====================================================================
---disable_warnings
-drop temporary table if exists t13;
-drop table if exists t13_b;
---enable_warnings
-
-create temporary table t13(a int);
-create table t13_b(a int);
+create temporary table t1 (a int);
+create table t2 (a int);
-prepare stmt from 'select * from t13';
+prepare stmt from "select * from t1";
execute stmt;
-eval $check;
-execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop temporary table t13;
-create view t13 as select * from t13_b;
+drop temporary table t1;
+create view t1 as select * from t2;
-set @expected = @expected + 1;
-execute stmt;
-eval $check;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
-drop view t13;
-drop table t13_b;
+drop view t1;
+drop table t2;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 14: VIEW -> NOTHING transitions
+--echo Part 14: VIEW -> NOTHING transitions
--echo =====================================================================
---disable_warnings
-drop view if exists t14;
-drop table if exists t14_b;
---enable_warnings
+create table t2 (a int);
+create view t1 as select * from t2;
-create table t14_b(a int);
-create view t14 as select * from t14_b;
-
-prepare stmt from 'select * from t14';
-execute stmt;
-eval $check;
+prepare stmt from "select * from t1";
execute stmt;
-eval $check;
+drop view t1;
-drop view t14;
-
-set @expected = @expected + 1;
--error ER_NO_SUCH_TABLE
execute stmt;
-eval $check;
-set @expected = @expected + 1;
+call p_verify_reprepare_count(0);
--error ER_NO_SUCH_TABLE
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop table t14_b;
+drop table t2;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 15: VIEW -> TABLE transitions
+--echo Part 15: VIEW -> TABLE transitions
--echo =====================================================================
---disable_warnings
-drop view if exists t15;
-drop table if exists t15_b;
---enable_warnings
-
-create table t15_b(a int);
-create view t15 as select * from t15_b;
+create table t2 (a int);
+create view t1 as select * from t2;
-prepare stmt from 'select * from t15';
+prepare stmt from "select * from t1";
execute stmt;
-eval $check;
-execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop view t15;
-create table t15(a int);
+drop view t1;
+create table t1 (a int);
-set @expected = @expected + 1;
-execute stmt;
-eval $check;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
-drop table t15_b;
-drop table t15;
+drop table t2;
+drop table t1;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 16: VIEW -> TEMPORARY TABLE transitions
+--echo Part 16: VIEW -> TEMPORARY TABLE transitions
--echo =====================================================================
---disable_warnings
-drop view if exists t16;
-drop table if exists t16_b;
---enable_warnings
-
-create table t16_b(a int);
-create view t16 as select * from t16_b;
+create table t2 (a int);
+insert into t2 (a) values (1);
+create view t1 as select * from t2;
-prepare stmt from 'select * from t16';
-execute stmt;
-eval $check;
+prepare stmt from "select * from t1";
execute stmt;
-eval $check;
-
-drop view t16;
-create temporary table t16(a int);
+call p_verify_reprepare_count(0);
-set @expected = @expected + 1;
+create temporary table t1 (a int);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
+drop view t1;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop table t16_b;
-drop temporary table t16;
+drop table t2;
+drop temporary table t1;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 17: VIEW -> VIEW (DDL) transitions
+--echo Part 17: VIEW -> VIEW (DDL) transitions
--echo =====================================================================
---disable_warnings
-drop view if exists t17;
-drop table if exists t17_b;
---enable_warnings
-
-create table t17_b(a int);
-insert into t17_b values (10), (20), (30);
+create table t2 (a int);
+insert into t2 values (10), (20), (30);
-create view t17 as select a, 2*a as b, 3*a as c from t17_b;
-select * from t17;
+create view t1 as select a, 2*a as b, 3*a as c from t2;
+select * from t1;
-prepare stmt from 'select * from t17';
-execute stmt;
-eval $check;
+prepare stmt from "select * from t1";
execute stmt;
-eval $check;
-drop view t17;
-create view t17 as select a, 2*a as b, 5*a as c from t17_b;
-select * from t17;
+drop view t1;
+create view t1 as select a, 2*a as b, 5*a as c from t2;
+select * from t1;
-set @expected = @expected + 1;
+--echo # Currently a different result from conventional statements.
+--echo # A view is inlined once at prepare, later on view DDL
+--echo # does not affect prepared statement and it is not re-prepared.
+--echo # This is reported in Bug#36002 Prepared statements: if a view
+--echo # used in a statement is replaced, bad data
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
+flush table t2;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
-drop table t17_b;
-drop view t17;
+drop table t2;
+drop view t1;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 18: VIEW -> VIEW (VIEW dependencies) transitions
+--echo Part 18: VIEW -> VIEW (VIEW dependencies) transitions
--echo =====================================================================
-#
-# Test 18-a: dependent PROCEDURE has changed (via a trigger)
-# Test 18-b: dependent FUNCTION has changed
-# Test 18-c: dependent VIEW has changed
-# Test 18-d: dependent TABLE has changed
-# Test 18-e: dependent TABLE TRIGGER has changed
-#
-
---disable_warnings
-drop table if exists t18;
-drop table if exists t18_dependent_table;
-drop view if exists t18_func;
-drop view if exists t18_view;
-drop view if exists t18_table;
-drop function if exists view_func;
-drop view if exists view_view;
---enable_warnings
-
-# TODO: insertable view -> trigger
-# TODO: insertable view -> trigger -> proc ?
-
-create table t18(a int);
-insert into t18 values (1), (2), (3);
-
-create function view_func(x int) returns int
- return x+1;
-
-create view view_view as select "view v1" as reason from dual;
-
-create table t18_dependent_table(a int);
-
-create view t18_func as select a, view_func(a) as b from t18;
-create view t18_view as select a, reason as b from t18, view_view;
-create view t18_table as select * from t18;
+--echo # Part 18a: dependent function has changed
+create table t1 (a int);
+insert into t1 (a) values (1), (2), (3);
+create function f1() returns int return (select max(a) from t1);
+create view v1 as select f1();
+prepare stmt from "select * from v1";
+execute stmt;
+execute stmt;
+call p_verify_reprepare_count(0);
+drop function f1;
+create function f1() returns int return 2;
+--echo # XXX: Bug#12093. We only get a different error
+--echo # message because the non-existing procedure error is masked
+--echo # by the view.
+--error ER_VIEW_INVALID
+execute stmt;
+--error ER_VIEW_INVALID
+execute stmt;
+call p_verify_reprepare_count(0);
-prepare stmt_func from 'select * from t18_func';
-execute stmt_func;
-eval $check;
-execute stmt_func;
-eval $check;
+--echo # Part 18b: dependent procedure has changed (referred to via a function)
-drop function view_func;
-create function view_func(x int) returns int
- return x*x;
+create table t2 (a int);
+insert into t2 (a) values (4), (5), (6);
-set @expected = @expected + 1;
-execute stmt_func;
-eval $check;
-execute stmt_func;
-eval $check;
+drop function f1;
+delimiter |;
+create function f1() returns int
+begin
+ declare x int;
+ call p1(x);
+ return x;
+end|
+delimiter ;|
+create procedure p1(out x int) select max(a) from t1 into x;
-prepare stmt_view from 'select * from t18_view';
-execute stmt_view;
-eval $check;
-execute stmt_view;
-eval $check;
+prepare stmt from "select * from v1";
+execute stmt;
+execute stmt;
+call p_verify_reprepare_count(0);
+drop procedure p1;
+create procedure p1(out x int) select max(a) from t2 into x;
+--echo # XXX: bug. The prelocked list is not invalidated
+--echo # and we keep opening table t1, whereas the procedure
+--echo # is now referring to table t2
+--error ER_VIEW_INVALID
+execute stmt;
+call p_verify_reprepare_count(0);
+flush table t1;
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
-drop view view_view;
-create view view_view as select "view v2" as reason from dual;
+--echo # Test 18-c: dependent VIEW has changed
-set @expected = @expected + 1;
-execute stmt_view;
-eval $check;
-execute stmt_view;
-eval $check;
+drop view v1;
+create view v2 as select a from t1;
+create view v1 as select * from v2;
+prepare stmt from "select * from v1";
+execute stmt;
+execute stmt;
+call p_verify_reprepare_count(0);
+drop view v2;
+create view v2 as select a from t2;
+execute stmt;
+execute stmt;
+call p_verify_reprepare_count(0);
+flush table t1;
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+--echo # Test 18-d: dependent TABLE has changed
+drop view v2;
+create table v2 as select * from t1;
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
+drop table v2;
+create table v2 (a int unique) as select * from t2;
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
-prepare stmt_table from 'select * from t18_table';
-execute stmt_table;
-eval $check;
-execute stmt_table;
-eval $check;
+--echo # Test 18-e: dependent TABLE trigger has changed
-alter table t18 add column comments varchar(50) default NULL;
+prepare stmt from "insert into v1 (a) values (?)";
+set @var= 7;
+execute stmt using @var;
+call p_verify_reprepare_count(0);
+create trigger v2_bi before insert on v2 for each row set @message="v2_bi";
+set @var=8;
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+select @message;
+drop trigger v2_bi;
+set @message=null;
+set @var=9;
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+select @message;
+create trigger v2_bi after insert on v2 for each row set @message="v2_ai";
+set @var= 10;
+execute stmt using @var;
+call p_verify_reprepare_count(1);
+select @message;
+select * from v1;
-set @expected = @expected + 1;
-execute stmt_table;
-eval $check;
-execute stmt_table;
-eval $check;
+--echo # Cleanup
-drop table t18;
-drop table t18_dependent_table;
-drop view t18_func;
-drop view t18_view;
-drop view t18_table;
-drop function view_func;
-drop view view_view;
+--disable_warnings
+drop table if exists t1, t2, v1, v2;
+drop view if exists v1, v2;
+drop function f1;
+drop procedure p1;
+--enable_warnings
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 19: Special tables (INFORMATION_SCHEMA)
+--echo Part 19: Special tables (INFORMATION_SCHEMA)
--echo =====================================================================
---disable_warnings
-drop procedure if exists proc_19;
---enable_warnings
-
# Using a temporary table internally should not confuse the prepared
# statement code, and should not raise ER_PS_INVALIDATED errors
prepare stmt from
- 'select ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE
+ "select ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE
from INFORMATION_SCHEMA.ROUTINES where
- routine_name=\'proc_19\'';
+ routine_name='p1'";
-create procedure proc_19() select "hi there";
+create procedure p1() select "hi there";
execute stmt;
-eval $check;
execute stmt;
-eval $check;
-drop procedure proc_19;
-create procedure proc_19() select "hi there, again";
+drop procedure p1;
+create procedure p1() select "hi there, again";
execute stmt;
-eval $check;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop procedure proc_19;
+drop procedure p1;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 20: Special tables (log tables)
+--echo Part 20: Special tables (log tables)
--echo =====================================================================
prepare stmt from
- 'select * from mysql.general_log where argument=\'IMPOSSIBLE QUERY STRING\'';
+ "select * from mysql.general_log where argument='IMPOSSIBLE QUERY STRING'";
+--disable_result_log
execute stmt;
-eval $check;
execute stmt;
-eval $check;
execute stmt;
-eval $check;
execute stmt;
-eval $check;
+--enable_result_log
+call p_verify_reprepare_count(0);
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 21: Special tables (system tables)
+--echo Part 21: Special tables (system tables)
--echo =====================================================================
---disable_warnings
-drop procedure if exists proc_21;
---enable_warnings
-
prepare stmt from
- 'select type, db, name from mysql.proc where name=\'proc_21\'';
+ "select type, db, name from mysql.proc where name='p1'";
-create procedure proc_21() select "hi there";
+create procedure p1() select "hi there";
execute stmt;
-eval $check;
execute stmt;
-eval $check;
-drop procedure proc_21;
-create procedure proc_21() select "hi there, again";
+drop procedure p1;
+create procedure p1() select "hi there, again";
execute stmt;
-eval $check;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop procedure proc_21;
+drop procedure p1;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 22: Special tables (views temp tables)
+--echo Part 22: Special tables (views temp tables)
--echo =====================================================================
---disable_warnings
-drop table if exists t22_b;
-drop view if exists t22;
---enable_warnings
+create table t1 (a int);
-create table t22_b(a int);
+create algorithm=temptable view v1 as select a*a as a2 from t1;
-create algorithm=temptable view t22 as select a*a as a2 from t22_b;
+--echo # Using a temporary table internally should not confuse the prepared
+--echo # statement code, and should not raise ER_PS_INVALIDATED errors
+show create view v1;
-# Using a temporary table internally should not confuse the prepared
-# statement code, and should not raise ER_PS_INVALIDATED errors
-show create view t22;
-
-prepare stmt from 'select * from t22';
+prepare stmt from "select * from v1";
-insert into t22_b values (1), (2), (3);
+insert into t1 values (1), (2), (3);
execute stmt;
-eval $check;
execute stmt;
-eval $check;
-insert into t22_b values (4), (5), (6);
+insert into t1 values (4), (5), (6);
execute stmt;
-eval $check;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop table t22_b;
-drop view t22;
+drop table t1;
+drop view v1;
--echo =====================================================================
---echo Testing 23: Special tables (internal join tables)
+--echo Part 23: Special statements
--echo =====================================================================
---disable_warnings
-drop table if exists t23_a;
-drop table if exists t23_b;
---enable_warnings
+--echo # SQLCOM_ALTER_TABLE:
-create table t23_a(a int);
-create table t23_b(b int);
-# Using a temporary table internally should not confuse the prepared
-# statement code, and should not raise ER_PS_INVALIDATED errors
-prepare stmt from 'select * from t23_a join t23_b';
-
-insert into t23_a values (1), (2), (3);
-insert into t23_b values (10), (20), (30);
-execute stmt;
-eval $check;
-execute stmt;
-eval $check;
+create table t1 (a int);
-insert into t23_a values (4);
-insert into t23_b values (40);
+prepare stmt from "alter table t1 add column b int";
execute stmt;
-eval $check;
-execute stmt;
-eval $check;
-
-drop table t23_a;
-drop table t23_b;
-
---echo =====================================================================
---echo Testing 24: Special statements
---echo =====================================================================
-# SQLCOM_ALTER_TABLE:
+drop table t1;
+create table t1 (a1 int, a2 int);
---disable_warnings
-drop table if exists t24_alter;
---enable_warnings
-
-create table t24_alter(a int);
-
-prepare stmt from 'alter table t24_alter add column b int';
+--echo # t1 has changed, and it's does not lead to reprepare
execute stmt;
-eval $check;
-
-drop table t24_alter;
-create table t24_alter(a1 int, a2 int);
-# t24_alter has changed, and it's not a problem
+alter table t1 drop column b;
execute stmt;
-eval $check;
-alter table t24_alter drop column b;
+alter table t1 drop column b;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-alter table t24_alter drop column b;
-execute stmt;
-eval $check;
+drop table t1;
-drop table t24_alter;
+--echo # SQLCOM_REPAIR:
-# SQLCOM_REPAIR:
+create table t1 (a int);
---disable_warnings
-drop table if exists t24_repair;
---enable_warnings
+insert into t1 values (1), (2), (3);
-create table t24_repair(a int);
-insert into t24_repair values (1), (2), (3);
+prepare stmt from "repair table t1";
-prepare stmt from 'repair table t24_repair';
execute stmt;
-eval $check;
+execute stmt;
-drop table t24_repair;
-create table t24_repair(a1 int, a2 int);
-insert into t24_repair values (1, 10), (2, 20), (3, 30);
+drop table t1;
+create table t1 (a1 int, a2 int);
+insert into t1 values (1, 10), (2, 20), (3, 30);
-# t24_repair has changed, and it's not a problem
+--echo # t1 has changed, and it's does not lead to reprepare
execute stmt;
-eval $check;
-alter table t24_repair add column b varchar(50) default NULL;
+alter table t1 add column b varchar(50) default NULL;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-alter table t24_repair drop column b;
+alter table t1 drop column b;
execute stmt;
-eval $check;
-
-drop table t24_repair;
+call p_verify_reprepare_count(0);
-# SQLCOM_ANALYZE:
+--echo # SQLCOM_ANALYZE:
---disable_warnings
-drop table if exists t24_analyze;
---enable_warnings
-
-create table t24_analyze(a int);
-insert into t24_analyze values (1), (2), (3);
-
-prepare stmt from 'analyze table t24_analyze';
+prepare stmt from "analyze table t1";
execute stmt;
-eval $check;
-
-drop table t24_analyze;
-create table t24_analyze(a1 int, a2 int);
-insert into t24_analyze values (1, 10), (2, 20), (3, 30);
-# t24_analyze has changed, and it's not a problem
+drop table t1;
+create table t1 (a1 int, a2 int);
+insert into t1 values (1, 10), (2, 20), (3, 30);
+--echo # t1 has changed, and it's not a problem
execute stmt;
-eval $check;
-alter table t24_analyze add column b varchar(50) default NULL;
+alter table t1 add column b varchar(50) default NULL;
execute stmt;
-eval $check;
-alter table t24_analyze drop column b;
+alter table t1 drop column b;
execute stmt;
-eval $check;
-drop table t24_analyze;
+call p_verify_reprepare_count(0);
-# SQLCOM_OPTIMIZE:
+--echo # SQLCOM_OPTIMIZE:
---disable_warnings
-drop table if exists t24_optimize;
---enable_warnings
-
-create table t24_optimize(a int);
-insert into t24_optimize values (1), (2), (3);
-
-prepare stmt from 'optimize table t24_optimize';
+prepare stmt from "optimize table t1";
execute stmt;
-eval $check;
-drop table t24_optimize;
-create table t24_optimize(a1 int, a2 int);
-insert into t24_optimize values (1, 10), (2, 20), (3, 30);
+drop table t1;
+create table t1 (a1 int, a2 int);
+insert into t1 values (1, 10), (2, 20), (3, 30);
-# t24_optimize has changed, and it's not a problem
+--echo # t1 has changed, and it's not a problem
execute stmt;
-eval $check;
-alter table t24_optimize add column b varchar(50) default NULL;
+alter table t1 add column b varchar(50) default NULL;
execute stmt;
-eval $check;
-alter table t24_optimize drop column b;
+alter table t1 drop column b;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop table t24_optimize;
+drop table t1;
-# SQLCOM_SHOW_CREATE_PROC:
+--echo # SQLCOM_SHOW_CREATE_PROC:
---disable_warnings
-drop procedure if exists changing_proc;
---enable_warnings
-
-prepare stmt from 'show create procedure changing_proc';
+prepare stmt from "show create procedure p1";
--error ER_SP_DOES_NOT_EXIST
execute stmt;
-eval $check;
--error ER_SP_DOES_NOT_EXIST
execute stmt;
-eval $check;
-create procedure changing_proc() begin end;
+create procedure p1() begin end;
-# changing_proc has changed, and it's not a problem
+--disable_result_log
execute stmt;
-eval $check;
execute stmt;
-eval $check;
+--enable_result_log
-drop procedure changing_proc;
-create procedure changing_proc(x int, y int) begin end;
+drop procedure p1;
+create procedure p1(x int, y int) begin end;
+--disable_result_log
execute stmt;
-eval $check;
execute stmt;
-eval $check;
+--enable_result_log
-drop procedure changing_proc;
+drop procedure p1;
--error ER_SP_DOES_NOT_EXIST
execute stmt;
-eval $check;
--error ER_SP_DOES_NOT_EXIST
execute stmt;
-eval $check;
-
-# SQLCOM_SHOW_CREATE_FUNC:
+call p_verify_reprepare_count(0);
---disable_warnings
-drop function if exists changing_func;
---enable_warnings
+--echo # SQLCOM_SHOW_CREATE_FUNC:
-prepare stmt from 'show create function changing_func';
+prepare stmt from "show create function f1";
--error ER_SP_DOES_NOT_EXIST
execute stmt;
-eval $check;
--error ER_SP_DOES_NOT_EXIST
execute stmt;
-eval $check;
-create function changing_func() returns int return 0;
+create function f1() returns int return 0;
-# changing_proc has changed, and it's not a problem
+--disable_result_log
execute stmt;
-eval $check;
execute stmt;
-eval $check;
+--enable_result_log
-drop function changing_func;
-create function changing_func(x int, y int) returns int return x+y;
+drop function f1;
+create function f1(x int, y int) returns int return x+y;
+--disable_result_log
execute stmt;
-eval $check;
execute stmt;
-eval $check;
+--enable_result_log
-drop function changing_func;
+drop function f1;
--error ER_SP_DOES_NOT_EXIST
execute stmt;
-eval $check;
--error ER_SP_DOES_NOT_EXIST
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-# SQLCOM_SHOW_CREATE_TRIGGER:
+--echo # SQLCOM_SHOW_CREATE_TRIGGER:
---disable_warnings
-drop table if exists t24_trigger;
---enable_warnings
-
-create table t24_trigger(a int);
+create table t1 (a int);
-prepare stmt from 'show create trigger t24_bi;';
+prepare stmt from "show create trigger t1_bi";
--error ER_TRG_DOES_NOT_EXIST
execute stmt;
-eval $check;
--error ER_TRG_DOES_NOT_EXIST
execute stmt;
-eval $check;
-delimiter $$;
-create trigger t24_bi before insert on t24_trigger for each row
- begin
- set @message= "t24_bi";
- end
-$$
-delimiter ;$$
+create trigger t1_bi before insert on t1 for each row set @message= "t1_bi";
-# t24_bi has changed, and it's not a problem
+--disable_result_log
execute stmt;
-eval $check;
execute stmt;
-eval $check;
+--enable_result_log
+
+drop trigger t1_bi;
-drop trigger t24_bi;
-delimiter $$;
-create trigger t24_bi before insert on t24_trigger for each row
- begin
- set @message= "t24_bi (2)";
- end
-$$
-delimiter ;$$
+create trigger t1_bi before insert on t1 for each row set @message= "t1_bi (2)";
-# t24_bi has changed, and it's not a problem
-set @expected = @expected + 1;
+--disable_result_log
execute stmt;
-eval $check;
execute stmt;
-eval $check;
+--enable_result_log
-drop trigger t24_bi;
+drop trigger t1_bi;
--error ER_TRG_DOES_NOT_EXIST
execute stmt;
-eval $check;
--error ER_TRG_DOES_NOT_EXIST
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop table t24_trigger;
+drop table t1;
+deallocate prepare stmt;
--echo =====================================================================
---echo Testing 25: Testing the strength of TABLE_SHARE version
+--echo Part 24: Testing the strength of TABLE_SHARE version
--echo =====================================================================
-# Test 25-a: number of columns
+--echo # Test 24-a: number of columns
---disable_warnings
-drop table if exists t25_num_col;
---enable_warnings
-
-create table t25_num_col(a int);
+create table t1 (a int);
-prepare stmt from 'select a from t25_num_col';
-execute stmt;
-eval $check;
+prepare stmt from "select a from t1";
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-alter table t25_num_col add column b varchar(50) default NULL;
+alter table t1 add column b varchar(50) default NULL;
-set @expected = @expected + 1;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop table t25_num_col;
+--echo # Test 24-b: column name
-# Test 25-b: column name
+alter table t1 change b c int;
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
---disable_warnings
-drop table if exists t25_col_name;
---enable_warnings
+--echo # Test 24-c: column type
-create table t25_col_name(a int);
+alter table t1 change a a varchar(10);
-prepare stmt from 'select * from t25_col_name';
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
+
+--echo # Test 24-d: column type length
-alter table t25_col_name change a b int;
+alter table t1 change a a varchar(20);
-set @expected = @expected + 1;
---error ER_PS_REBIND
execute stmt;
-eval $check;
-set @expected = @expected + 1;
---error ER_PS_REBIND
+call p_verify_reprepare_count(1);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop table t25_col_name;
+--echo # Test 24-e: column NULL property
-# Test 25-c: column type
+alter table t1 change a a varchar(20) NOT NULL;
---disable_warnings
-drop table if exists t25_col_type;
---enable_warnings
-
-create table t25_col_type(a int);
-
-prepare stmt from 'select * from t25_col_type';
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
+
+--echo # Test 24-f: column DEFAULT
-alter table t25_col_type change a a varchar(10);
+alter table t1 change c c int DEFAULT 20;
-set @expected = @expected + 1;
---error ER_PS_REBIND
execute stmt;
-eval $check;
-set @expected = @expected + 1;
---error ER_PS_REBIND
+call p_verify_reprepare_count(1);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-drop table t25_col_type;
+--echo # Test 24-g: number of keys
+create unique index t1_a_idx on t1 (a);
-# Test 25-d: column type length
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
---disable_warnings
-drop table if exists t25_col_type_length;
---enable_warnings
+--echo # Test 24-h: changing index uniqueness
-create table t25_col_type_length(a varchar(10));
+drop index t1_a_idx on t1;
+create index t1_a_idx on t1 (a);
-prepare stmt from 'select * from t25_col_type_length';
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-alter table t25_col_type_length change a a varchar(20);
+--echo # Cleanup
+drop table t1;
-set @expected = @expected + 1;
---error ER_PS_REBIND
-execute stmt;
-eval $check;
-set @expected = @expected + 1;
---error ER_PS_REBIND
-execute stmt;
-eval $check;
+deallocate prepare stmt;
-drop table t25_col_type_length;
+--echo =====================================================================
+--echo Testing reported bugs
+--echo =====================================================================
-# Test 25-e: column NULL property
+--echo #
+--echo # Bug#27420 A combination of PS and view operations cause
+--echo # error + assertion on shutdown
+--echo #
--disable_warnings
-drop table if exists t25_col_null;
+drop table if exists t_27420_100;
+drop table if exists t_27420_101;
+drop view if exists v_27420;
--enable_warnings
-create table t25_col_null(a varchar(10));
+create table t_27420_100(a int);
+insert into t_27420_100 values (1), (2);
+
+create table t_27420_101(a int);
+insert into t_27420_101 values (1), (2);
+
+create view v_27420 as select t_27420_100.a X, t_27420_101.a Y
+ from t_27420_100, t_27420_101
+ where t_27420_100.a=t_27420_101.a;
+
+prepare stmt from "select * from v_27420";
-prepare stmt from 'select * from t25_col_null';
-execute stmt;
-eval $check;
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-alter table t25_col_null change a a varchar(10) NOT NULL;
+drop view v_27420;
+create table v_27420(X int, Y int);
-set @expected = @expected + 1;
---error ER_PS_REBIND
execute stmt;
-eval $check;
-set @expected = @expected + 1;
---error ER_PS_REBIND
+call p_verify_reprepare_count(1);
+
+drop table v_27420;
+# passes in 5.0, fails in 5.1, should pass
+create table v_27420 (a int, b int, filler char(200));
+
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
-drop table t25_col_null;
+drop table t_27420_100;
+drop table t_27420_101;
+drop table v_27420;
+deallocate prepare stmt;
-# Test 25-f: column DEFAULT
+--echo #
+--echo # Bug#27430 Crash in subquery code when in PS and table DDL changed
+--echo # after PREPARE
+--echo #
--disable_warnings
-drop table if exists t25_col_default;
+drop table if exists t_27430_1;
+drop table if exists t_27430_2;
--enable_warnings
-create table t25_col_default(a int, b int DEFAULT 10);
+create table t_27430_1 (a int not null, oref int not null, key(a));
+insert into t_27430_1 values
+ (1, 1),
+ (1, 1234),
+ (2, 3),
+ (2, 1234),
+ (3, 1234);
-prepare stmt from 'insert into t25_col_default(a) values (?)';
-set @val=1;
-execute stmt using @val;
-eval $check;
-set @val=2;
-execute stmt using @val;
-eval $check;
+create table t_27430_2 (a int not null, oref int not null);
+insert into t_27430_2 values
+ (1, 1),
+ (2, 2),
+ (1234, 3),
+ (1234, 4);
-alter table t25_col_default change b b int DEFAULT 20;
+prepare stmt from
+ "select oref, a, a in (select a from t_27430_1 where oref=t_27430_2.oref) Z from t_27430_2";
-set @val=3;
-# Must insert the correct default value for b
-set @expected = @expected + 1;
-execute stmt using @val;
-eval $check;
+execute stmt;
+call p_verify_reprepare_count(0);
-set @val=4;
-# Must insert the correct default value for b
-execute stmt using @val;
-eval $check;
+drop table t_27430_1, t_27430_2;
-select * from t25_col_default;
+create table t_27430_1 (a int, oref int, key(a));
+insert into t_27430_1 values
+ (1, 1),
+ (1, NULL),
+ (2, 3),
+ (2, NULL),
+ (3, NULL);
-drop table t25_col_default;
+create table t_27430_2 (a int, oref int);
+insert into t_27430_2 values
+ (1, 1),
+ (2,2),
+ (NULL, 3),
+ (NULL, 4);
-# Test 25-g: number of keys
+execute stmt;
+call p_verify_reprepare_count(1);
+
+drop table t_27430_1;
+drop table t_27430_2;
+deallocate prepare stmt;
+
+--echo #
+--echo # Bug#27690 Re-execution of prepared statement after table
+--echo # was replaced with a view crashes
+--echo #
--disable_warnings
-drop table if exists t25_index;
+drop table if exists t_27690_1;
+drop view if exists v_27690_1;
+drop table if exists v_27690_2;
--enable_warnings
-create table t25_index(a varchar(10));
+create table t_27690_1 (a int, b int);
+insert into t_27690_1 values (1,1),(2,2);
-prepare stmt from 'select * from t25_index';
-execute stmt;
-eval $check;
-execute stmt;
-eval $check;
+create table v_27690_1 as select * from t_27690_1;
+create table v_27690_2 as select * from t_27690_1;
-create index i1 on t25_index(a);
+prepare stmt from "select * from v_27690_1, v_27690_2";
-set @expected = @expected + 1;
execute stmt;
-eval $check;
execute stmt;
-eval $check;
-
-drop table t25_index;
-# Test 25-h: changing index uniqueness
+drop table v_27690_1;
---disable_warnings
-drop table if exists t25_index_unique;
---enable_warnings
+--error ER_NO_SUCH_TABLE
+execute stmt;
-create table t25_index_unique(a varchar(10), b varchar(10));
-create index i1 on t25_index_unique(a, b);
+--error ER_NO_SUCH_TABLE
+execute stmt;
+call p_verify_reprepare_count(0);
-show create table t25_index_unique;
+create view v_27690_1 as select A.a, A.b from t_27690_1 A, t_27690_1 B;
-prepare stmt from 'select * from t25_index_unique';
execute stmt;
-eval $check;
+call p_verify_reprepare_count(1);
execute stmt;
-eval $check;
+call p_verify_reprepare_count(0);
-alter table t25_index_unique drop index i1;
-create unique index i1 on t25_index_unique(a, b);
+drop table t_27690_1;
+drop view v_27690_1;
+drop table v_27690_2;
+deallocate prepare stmt;
+
+--echo #=====================================================================
+--echo # TODO: fix the below two bugs and modify their tests
+--echo #
+--echo # Bug#21294 Executing a prepared statement that executes
+--echo # a stored function which was recreat
+--echo #
-show create table t25_index_unique;
+create function f1() returns int return 10;
-set @expected = @expected + 1;
+prepare stmt from "select f1()";
execute stmt;
-eval $check;
+
+drop function f1;
+create function f1() returns int return 10;
+
+# might pass or fail, implementation dependent
+--error ER_SP_DOES_NOT_EXIST
execute stmt;
-eval $check;
-drop table t25_index_unique;
+drop function f1;
+create function f1() returns int return 20;
---echo =====================================================================
---echo Testing reported bugs
---echo =====================================================================
+--error ER_SP_DOES_NOT_EXIST
+execute stmt;
+call p_verify_reprepare_count(0);
-#
-# Bug#12093 (SP not found on second PS execution if another thread drops
-# other SP in between)
-#
+drop function f1;
+deallocate prepare stmt;
+--echo #
+--echo # Bug#12093 SP not found on second PS execution if another thread drops
+--echo # other SP in between
+--echo #
--disable_warnings
-drop table if exists table_12093;
-drop function if exists func_12093;
-drop function if exists func_12093_unrelated;
-drop procedure if exists proc_12093;
+drop table if exists t_12093;
+drop function if exists f_12093;
+drop function if exists f_12093_unrelated;
+drop procedure if exists p_12093;
--enable_warnings
-connect (con1,localhost,root,,);
+create table t_12093 (a int);
-connection default;
+create function f_12093() returns int return (select count(*) from t_12093);
-create table table_12093(a int);
+create procedure p_12093(a int) select * from t_12093;
-delimiter //;
+create function f_12093_unrelated() returns int return 2;
+create procedure p_12093_unrelated() begin end;
-create function func_12093()
-returns int
-begin
- return (select count(*) from table_12093);
-end//
-
-create procedure proc_12093(a int)
-begin
- select * from table_12093;
-end//
-
-delimiter ;//
-
-create function func_12093_unrelated() returns int return 2;
-create procedure proc_12093_unrelated() begin end;
-
-prepare stmt_sf from 'select func_12093();';
-prepare stmt_sp from 'call proc_12093(func_12093())';
+prepare stmt_sf from 'select f_12093();';
+prepare stmt_sp from 'call p_12093(f_12093())';
execute stmt_sf;
-eval $check;
execute stmt_sp;
-eval $check;
+connect (con1,localhost,root,,);
connection con1;
-drop function func_12093_unrelated;
-drop procedure proc_12093_unrelated;
+drop function f_12093_unrelated;
+drop procedure p_12093_unrelated;
connection default;
-# previously, failed with --error 1305
+--echo # XXX: bug
+--error ER_SP_DOES_NOT_EXIST
execute stmt_sf;
-eval $check;
-# previously, failed with --error 1305
+--echo # XXX: bug
+--error ER_SP_DOES_NOT_EXIST
execute stmt_sp;
-eval $check;
-# previously, failed with --error 1305
+--echo # XXX: bug
+--error ER_SP_DOES_NOT_EXIST
execute stmt_sf;
-eval $check;
-# previously, failed with --error 1305
+--echo # XXX: bug
+--error ER_SP_DOES_NOT_EXIST
execute stmt_sp;
-eval $check;
+call p_verify_reprepare_count(0);
+
+disconnect con1;
+drop table t_12093;
+drop function f_12093;
+drop procedure p_12093;
deallocate prepare stmt_sf;
deallocate prepare stmt_sp;
-disconnect con1;
-drop table table_12093;
-drop function func_12093;
-drop procedure proc_12093;
+--echo =====================================================================
+--echo Ensure that metadata validation is performed for every type of
+--echo SQL statement where it is needed.
+--echo =====================================================================
-#
-# Bug#21294 (executing a prepared statement that executes a stored function
-# which was recreat)
-#
+--echo #
+--echo # SQLCOM_SELECT
+--echo #
--disable_warnings
-drop function if exists func_21294;
+drop table if exists t1;
--enable_warnings
+create table t1 (a int);
+prepare stmt from "select 1 as res from dual where (1) in (select * from t1)";
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
+call p_verify_reprepare_count(1);
-create function func_21294() returns int return 10;
+--echo #
+--echo # SQLCOM_CREATE_TABLE
+--echo #
-prepare stmt from "select func_21294()";
+--disable_warnings
+drop table if exists t1;
+drop table if exists t2;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from 'create table t2 as select * from t1';
+execute stmt;
+drop table t2;
+execute stmt;
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+# Base table with name of table to be created exists
+--error ER_TABLE_EXISTS_ERROR
+execute stmt;
+call p_verify_reprepare_count(1);
+--error ER_TABLE_EXISTS_ERROR
+execute stmt;
+call p_verify_reprepare_count(0);
+drop table t2;
+# Temporary table with name of table to be created exists
+create temporary table t2 (a int);
+--error ER_TABLE_EXISTS_ERROR
+execute stmt;
+call p_verify_reprepare_count(1);
+--error ER_TABLE_EXISTS_ERROR
+execute stmt;
+call p_verify_reprepare_count(0);
+drop temporary table t2;
+execute stmt;
+call p_verify_reprepare_count(1);
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+drop table t2;
+# View with name of table to be created exists
+# Attention:
+# We cannot print the error message because it contains a random filename.
+# Example: 1050: Table '<some_path>/var/tmp/#sql_6979_0' already exists
+# Therefore we mangle it via
+# "--error ER_TABLE_EXISTS_ERROR,9999" (9999 is currently not used)
+# to "Got one of the listed errors".
+create view t2 as select 1;
+--error ER_TABLE_EXISTS_ERROR,9999
+execute stmt;
+call p_verify_reprepare_count(1);
+--error ER_TABLE_EXISTS_ERROR,9999
+execute stmt;
+call p_verify_reprepare_count(0);
+drop view t2;
+drop table t1;
+# Table to be used recreated (drop,create) with different layout
+create table t1 (x varchar(20));
+execute stmt;
+call p_verify_reprepare_count(1);
+select * from t2;
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+drop table t2;
+# Table to be used has a modified (alter table) layout
+alter table t1 add column y decimal(10,3);
+execute stmt;
+call p_verify_reprepare_count(1);
+select * from t2;
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+drop table t1;
+deallocate prepare stmt;
+--echo # XXX: no validation of the first table in case of
+--echo # CREATE TEMPORARY TABLE. This is a shortcoming of the current code,
+--echo # but since validation is not strictly necessary, nothing is done
+--echo # about it.
+--echo # Will be fixed as part of work on Bug#21431 "Incomplete support of
+--echo # temporary tables"
+create table t1 (a int);
+insert into t1 (a) values (1);
+prepare stmt from "create temporary table if not exists t2 as select * from t1";
+execute stmt;
+drop table t2;
+execute stmt;
+execute stmt;
+select * from t2;
execute stmt;
-eval $check;
+select * from t2;
+drop table t2;
+create temporary table t2 (a varchar(10));
+execute stmt;
+select * from t2;
+call p_verify_reprepare_count(0);
+drop table t1;
+create table t1 (x int);
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
+drop table t1;
+drop temporary table t2;
+drop table t2;
+deallocate prepare stmt;
-drop function func_21294;
-create function func_21294() returns int return 10;
+create table t1 (a int);
+prepare stmt from "create table t2 like t1";
+execute stmt;
+call p_verify_reprepare_count(0);
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+drop table t2;
+# Table to be used does not exist
+drop table t1;
+--error ER_NO_SUCH_TABLE
+execute stmt;
+call p_verify_reprepare_count(0);
+--error ER_NO_SUCH_TABLE
+execute stmt;
+call p_verify_reprepare_count(0);
+# Table to be used recreated (drop,create) with different layout
+create table t1 (x char(17));
+execute stmt;
+call p_verify_reprepare_count(1);
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+drop table t2;
+# Table to be used has a modified (alter table) layout
+alter table t1 add column y time;
+execute stmt;
+call p_verify_reprepare_count(1);
+select * from t2;
+drop table t2;
+execute stmt;
+call p_verify_reprepare_count(0);
+drop table t1;
+drop table t2;
+deallocate prepare stmt;
-# might pass or fail, implementation dependent
+
+--echo #
+--echo # SQLCOM_UPDATE
+--echo #
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "update t2 set a=a+1 where (1) in (select * from t1)";
execute stmt;
-eval $check;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2;
+deallocate prepare stmt;
-drop function func_21294;
-create function func_21294() returns int return 20;
+--echo #
+--echo # SQLCOM_INSERT
+--echo #
-set @expected = @expected + 1;
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "insert into t2 set a=((1) in (select * from t1))";
+execute stmt;
+drop table t1;
+create table t1 (x int);
execute stmt;
-eval $check;
+drop table t1, t2;
deallocate prepare stmt;
-drop function func_21294;
-#
-# Bug#27420 (A combination of PS and view operations cause error + assertion
-# on shutdown)
-#
+--echo #
+--echo # SQLCOM_INSERT_SELECT
+--echo #
--disable_warnings
-drop table if exists t_27420_100;
-drop table if exists t_27420_101;
-drop view if exists v_27420;
+drop table if exists t1, t2;
--enable_warnings
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "insert into t2 select * from t1";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2;
+deallocate prepare stmt;
-connect (con1,localhost,root,,);
+--echo #
+--echo # SQLCOM_REPLACE
+--echo #
-connection default;
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "replace t2 set a=((1) in (select * from t1))";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2;
+deallocate prepare stmt;
-create table t_27420_100(a int);
-insert into t_27420_100 values (1), (2);
+--echo #
+--echo # SQLCOM_REPLACE_SELECT
+--echo #
-create table t_27420_101(a int);
-insert into t_27420_101 values (1), (2);
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "replace t2 select * from t1";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2;
+deallocate prepare stmt;
-create view v_27420 as select t_27420_100.a X, t_27420_101.a Y
- from t_27420_100, t_27420_101
- where t_27420_100.a=t_27420_101.a;
+--echo #
+--echo # SQLCOM_DELETE
+--echo #
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+create table t1 (a int);
+create table t2 (a int);
+prepare stmt from "delete from t2 where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2;
+deallocate prepare stmt;
-prepare stmt from 'select * from v_27420';
+--echo #
+--echo # SQLCOM_DELETE_MULTI
+--echo #
+--disable_warnings
+drop table if exists t1, t2, t3;
+--enable_warnings
+create table t1 (a int);
+create table t2 (a int);
+create table t3 (a int);
+prepare stmt from "delete t2, t3 from t2, t3 where (1) in (select * from t1)";
execute stmt;
-eval $check;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2, t3;
+deallocate prepare stmt;
-connection con1;
+--echo #
+--echo # SQLCOM_UPDATE_MULTI
+--echo #
-drop view v_27420;
-create table v_27420(X int, Y int);
+--disable_warnings
+drop table if exists t1, t2, t3;
+--enable_warnings
+create table t1 (a int);
+create table t2 (a int);
+create table t3 (a int);
+prepare stmt from "update t2, t3 set t3.a=t2.a, t2.a=null where (1) in (select * from t1)";
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1, t2, t3;
+deallocate prepare stmt;
+--echo # Intermediate results: 8 SQLCOMs tested, 8 automatic reprepares
+call p_verify_reprepare_count(8);
-connection default;
+--echo #
+--echo # SQLCOM_LOAD
+--echo #
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a varchar(20));
+--error ER_UNSUPPORTED_PS
+prepare stmt from "load data infile '../std_data_ln/words.dat' into table t1";
+drop table t1;
+
+--echo #
+--echo # SQLCOM_SHOW_DATABASES
+--echo #
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show databases where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
-set @expected = @expected + 1;
+--echo #
+--echo # SQLCOM_SHOW_TABLES
+--echo #
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show tables where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
execute stmt;
-eval $check;
+drop table t1;
+deallocate prepare stmt;
-connection con1;
+--echo #
+--echo # SQLCOM_SHOW_FIELDS
+--echo #
-drop table v_27420;
-# passes in 5.0, fails in 5.1, should pass
-create table v_27420 (a int, b int, filler char(200));
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show fields from t1 where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
-connection default;
+--echo #
+--echo # SQLCOM_SHOW_KEYS
+--echo #
-set @expected = @expected + 1;
---error ER_PS_REBIND
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show keys from t1 where (1) in (select * from t1)";
execute stmt;
-eval $check;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
-disconnect con1;
+--echo #
+--echo # SQLCOM_SHOW_VARIABLES
+--echo #
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show variables where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
deallocate prepare stmt;
-drop table t_27420_100;
-drop table t_27420_101;
-drop table v_27420;
-#
-# Bug#27430 (Crash in subquery code when in PS and table DDL changed after
-# PREPARE)
-#
+--echo #
+--echo # SQLCOM_SHOW_STATUS
+--echo #
--disable_warnings
-drop table if exists t_27430_1;
-drop table if exists t_27430_2;
+drop table if exists t1;
--enable_warnings
+create table t1 (a int);
+prepare stmt from "show status where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
-create table t_27430_1 (a int not null, oref int not null, key(a));
-insert into t_27430_1 values
- (1, 1),
- (1, 1234),
- (2, 3),
- (2, 1234),
- (3, 1234);
+--echo #
+--echo # SQLCOM_SHOW_ENGINE_STATUS, SQLCOM_SHOW_ENGINE_LOGS,
+--echo # SQLCOM_SHOW_ENGINE_MUTEX, SQLCOM_SHOW_PROCESSLIST
+--echo #
-create table t_27430_2 (a int not null, oref int not null);
-insert into t_27430_2 values
- (1, 1),
- (2, 2),
- (1234, 3),
- (1234, 4);
+--echo # Currently can not have a where clause, need to be covered
+--echo # with tests
-prepare stmt from
- 'select oref, a, a in (select a from t_27430_1 where oref=t_27430_2.oref) Z from t_27430_2';
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+--error ER_PARSE_ERROR
+prepare stmt from "show engine all status where (1) in (select * from t1)";
+--error ER_PARSE_ERROR
+prepare stmt from "show engine all logs where (1) in (select * from t1)";
+--error ER_PARSE_ERROR
+prepare stmt from "show engine all mutex where (1) in (select * from t1)";
+--error ER_PARSE_ERROR
+prepare stmt from "show processlist where (1) in (select * from t1)";
+drop table t1;
+
+--echo #
+--echo # SQLCOM_SHOW_CHARSETS
+--echo #
-execute stmt;
-eval $check;
-execute stmt;
-eval $check;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show charset where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
-drop table t_27430_1, t_27430_2;
+--echo #
+--echo # SQLCOM_SHOW_COLLATIONS
+--echo #
-create table t_27430_1 (a int, oref int, key(a));
-insert into t_27430_1 values
- (1, 1),
- (1, NULL),
- (2, 3),
- (2, NULL),
- (3, NULL);
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show collation where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
-create table t_27430_2 (a int, oref int);
-insert into t_27430_2 values
- (1, 1),
- (2,2),
- (NULL, 3),
- (NULL, 4);
+--echo #
+--echo # SQLCOM_SHOW_TABLE_STATUS
+--echo #
-set @expected = @expected + 1;
---error ER_PS_REBIND
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show table status where (1) in (select * from t1)";
execute stmt;
-eval $check;
-set @expected = @expected + 1;
---error ER_PS_REBIND
+drop table t1;
+create table t1 (x int);
execute stmt;
-eval $check;
+drop table t1;
+deallocate prepare stmt;
+
+--echo #
+--echo # SQLCOM_SHOW_TRIGGERS
+--echo #
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show triggers where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
deallocate prepare stmt;
-drop table t_27430_1;
-drop table t_27430_2;
-#
-# Bug#27690 (Re-execution of prepared statement after table was replaced
-# with a view crashes)
-#
+--echo #
+--echo # SQLCOM_SHOW_OPEN_TABLES
+--echo #
--disable_warnings
-drop table if exists t_27690_1;
-drop view if exists v_27690_1;
-drop table if exists v_27690_2;
+drop table if exists t1;
--enable_warnings
+create table t1 (a int);
+prepare stmt from "show open tables where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
-create table t_27690_1 (a int, b int);
-insert into t_27690_1 values (1,1),(2,2);
+--echo #
+--echo # SQLCOM_SHOW_STATUS_PROC
+--echo #
-create table v_27690_1 as select * from t_27690_1;
-create table v_27690_2 as select * from t_27690_1;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show procedure status where (1) in (select * from t1)";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
-prepare stmt from 'select * from v_27690_1, v_27690_2';
+--echo #
+--echo # SQLCOM_SHOW_STATUS_FUNC
+--echo #
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show function status where (1) in (select * from t1)";
execute stmt;
-eval $check;
+drop table t1;
+create table t1 (x int);
execute stmt;
-eval $check;
+drop table t1;
+deallocate prepare stmt;
-drop table v_27690_1;
+--echo #
+--echo # SQLCOM_SHOW_EVENTS
+--echo #
---error ER_NO_SUCH_TABLE
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "show events where (1) in (select * from t1)";
execute stmt;
-eval $check;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
---error ER_NO_SUCH_TABLE
+--echo #
+--echo # SQLCOM_SET_OPTION
+--echo #
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "set @a=((1) in (select * from t1))";
execute stmt;
-eval $check;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
-create view v_27690_1 as select A.a, A.b from t_27690_1 A, t_27690_1 B;
+--echo #
+--echo # SQLCOM_DO
+--echo #
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "do ((1) in (select * from t1))";
+execute stmt;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop table t1;
+deallocate prepare stmt;
-set @expected = @expected + 1;
+--echo #
+--echo # SQLCOM_CALL
+--echo #
+
+--disable_warnings
+drop table if exists t1;
+drop procedure if exists p1;
+--enable_warnings
+create procedure p1(a int) begin end;
+create table t1 (a int);
+prepare stmt from "call p1((1) in (select * from t1))";
execute stmt;
-eval $check;
+drop table t1;
+create table t1 (x int);
execute stmt;
-eval $check;
+drop table t1;
+drop procedure p1;
+deallocate prepare stmt;
+--echo #
+--echo # SQLCOM_CREATE_VIEW
+--echo #
+
+--disable_warnings
+drop table if exists t1;
+drop view if exists v1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt from "create view v1 as select * from t1";
+execute stmt;
+drop view v1;
+drop table t1;
+create table t1 (x int);
+execute stmt;
+drop view v1;
+drop table t1;
deallocate prepare stmt;
-drop table t_27690_1;
-drop view v_27690_1;
-drop table v_27690_2;
+--echo # Intermediate result: number of reprepares matches the number
+--echo # of tests
+call p_verify_reprepare_count(18);
+
+--echo #
+--echo # SQLCOM_ALTER_VIEW
+--echo #
+--disable_warnings
+drop view if exists v1;
+--enable_warnings
+create view v1 as select 1;
+--error ER_UNSUPPORTED_PS
+prepare stmt from "alter view v1 as select 2";
+drop view v1;
+
+--echo # Cleanup
+--echo #
+--disable_warnings
+drop temporary table if exists t1, t2, t3;
+drop table if exists t1, t2, t3, v1, v2;
+drop procedure if exists p_verify_reprepare_count;
+drop procedure if exists p1;
+drop function if exists f1;
+drop view if exists v1, v2;
+--enable_warnings
diff --git a/mysql-test/t/ps_ddl1.test b/mysql-test/t/ps_ddl1.test
new file mode 100644
index 00000000000..0145d445a14
--- /dev/null
+++ b/mysql-test/t/ps_ddl1.test
@@ -0,0 +1,398 @@
+#
+# Testing the behavior of 'PREPARE', 'DDL', 'EXECUTE' scenarios
+#
+# There are several subtests which are probably "superfluous" because a DDL
+# statement before the EXECUTE <prepared stmt handle> contained a keyword
+# or action (Example: Alter) which causes that all prepared statements using
+# the modified object are reprepared before execution.
+# Please do not delete these subtests if they disturb. Just disable them by
+# if (0)
+# {
+# <tests to disable>
+# }.
+# There might be future optimisations of the server which decrease the amount
+# of unneeded reprepares or skip unneeded prepare steps and than these subtests
+# might become valuable.
+# Example:
+# Every preceding ALTER TABLE seems to cause a reprepare.
+# But if the ALTER only changed the table comment ...
+#
+# Created: 2008-04-18 mleich
+#
+
+--disable_warnings
+drop temporary table if exists t1;
+drop table if exists t1, t2;
+drop procedure if exists p_verify_reprepare_count;
+drop procedure if exists p1;
+drop function if exists f1;
+drop view if exists t1;
+drop schema if exists mysqltest;
+--enable_warnings
+
+delimiter |;
+create procedure p_verify_reprepare_count(expected int)
+begin
+ declare old_reprepare_count int default @reprepare_count;
+
+ select variable_value from
+ information_schema.session_status where
+ variable_name='com_stmt_reprepare'
+ into @reprepare_count;
+
+ if old_reprepare_count + expected <> @reprepare_count then
+ select concat("Expected: ", expected,
+ ", actual: ", @reprepare_count - old_reprepare_count)
+ as "ERROR";
+ else
+ select '' as "SUCCESS";
+ end if;
+end|
+delimiter ;|
+set @reprepare_count= 0;
+flush status;
+
+--disable_warnings
+drop table if exists t1;
+--disable_warnings
+
+--echo # Column added or dropped is not within the list of selected columns
+--echo # or table comment has changed.
+--echo # A reprepare is probably not needed.
+create table t1 (a int, b int);
+prepare stmt from "select a from t1";
+execute stmt;
+call p_verify_reprepare_count(0);
+alter table t1 add column c int;
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
+alter table t1 drop column b;
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
+alter table t1 comment "My best table";
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
+drop table t1;
+deallocate prepare stmt;
+
+--echo # Selects using the table at various positions, inser,update ...
+--echo # + the table disappears
+create table t1 (a int);
+# Attention:
+# "truncate" must have the first position (= executed as last prepared
+# statement), because it recreates the table which has leads to reprepare
+# (is this really needed) of all statements.
+prepare stmt1 from "truncate t1";
+prepare stmt2 from "select 1 as my_column from t1";
+prepare stmt3 from "select 1 as my_column from (select * from t1) as t2";
+prepare stmt4 from
+"select 1 as my_column from (select 1) as t2 where exists (select 1 from t1)";
+prepare stmt5 from "select * from (select 1 as b) as t2, t1";
+prepare stmt6 from "select * from t1 union all select 1.5";
+prepare stmt7 from "select 1 as my_column union all select 1 from t1";
+prepare stmt8 from "insert into t1 values(1),(2)";
+prepare stmt9 from "update t1 set a = 3 where a = 2";
+prepare stmt10 from "delete from t1 where a = 1";
+let ps_stmt_count= 10;
+--echo # Attention: Result logging is disabled.
+# Checks of correct results of statements are not the goal of this test.
+let $num= $ps_stmt_count;
+while ($num)
+{
+ --disable_result_log
+ eval execute stmt$num;
+ --enable_result_log
+ dec $num;
+}
+# There was no reprepare needed, because none of the objects has changed.
+call p_verify_reprepare_count(0);
+drop table t1;
+let $num= $ps_stmt_count;
+while ($num)
+{
+ --error ER_NO_SUCH_TABLE
+ eval execute stmt$num;
+ dec $num;
+}
+# There was no reprepare needed, because the statement is no more applicable.
+call p_verify_reprepare_count(0);
+let $num= $ps_stmt_count;
+while ($num)
+{
+ eval deallocate prepare stmt$num;
+ dec $num;
+}
+
+--echo # Selects using the table at various positions, inser,update ...
+--echo # + layout change (drop column) which must cause a reprepare
+create table t1 (a int, b int);
+insert into t1 values(1,1),(2,2),(3,3);
+create table t2 like t1;
+insert into t1 values(2,2);
+prepare stmt1 from "select a,b from t1";
+prepare stmt2 from "select a,b from (select * from t1) as t1";
+prepare stmt3 from "select * from t1 where a = 2 and b = 2";
+prepare stmt4 from "select * from t2 where (a,b) in (select * from t1)";
+prepare stmt5 from "select * from t1 union select * from t2";
+prepare stmt6 from "select * from t1 union all select * from t2";
+prepare stmt7 from "insert into t1 set a = 4, b = 4";
+prepare stmt8 from "insert into t1 select * from t2";
+let ps_stmt_count= 8;
+--echo # Attention: Result logging is disabled.
+# Checks of correct results of statements are not the goal of this test.
+let $num= $ps_stmt_count;
+while ($num)
+{
+ --disable_result_log
+ eval execute stmt$num;
+ --enable_result_log
+ dec $num;
+}
+call p_verify_reprepare_count(0);
+alter table t1 drop column b;
+--disable_abort_on_error
+let $num= $ps_stmt_count;
+while ($num)
+{
+ eval execute stmt$num;
+ # A reprepare is needed, because layout change of t1 affects statement.
+ call p_verify_reprepare_count(1);
+ dec $num;
+}
+let $num= $ps_stmt_count;
+while ($num)
+{
+ eval execute stmt$num;
+ call p_verify_reprepare_count(1);
+ dec $num;
+}
+--echo # Why does the INSERT ... SELECT does not get a reprepare or is
+--echo # only the counter not incremented?
+eval execute stmt8;
+call p_verify_reprepare_count(1);
+--enable_abort_on_error
+alter table t2 add column c int;
+--error ER_WRONG_VALUE_COUNT_ON_ROW
+eval execute stmt8;
+call p_verify_reprepare_count(1);
+let $num= $ps_stmt_count;
+while ($num)
+{
+ eval deallocate prepare stmt$num;
+ dec $num;
+}
+drop table t1;
+drop table t2;
+
+
+--echo # select AVG(<col>) + optimizer uses index meets loss of the index
+create table t1 (a int, b int, primary key(b),unique index t1_unq_idx(a));
+# We need an index which is not converted to PRIMARY KEY (becomes in
+# case of InnoDB the key used for table clustering).
+insert into t1 set a = 0, b = 0;
+insert into t1 select a + 1, b + 1 from t1;
+insert into t1 select a + 2, b + 2 from t1;
+insert into t1 select a + 4, b + 4 from t1;
+insert into t1 select a + 8, b + 8 from t1;
+# "using index" optimizer strategy is intended
+let $possible_keys=
+ query_get_value(explain select avg(a) from t1, possible_keys, 1);
+let $extra=
+ query_get_value(explain select avg(a) from t1, Extra, 1);
+--echo # Optimizer strategy: Possible keys = $possible_keys , Extra = $extra
+prepare stmt from "select avg(a) from t1";
+execute stmt;
+call p_verify_reprepare_count(0);
+execute stmt;
+call p_verify_reprepare_count(0);
+
+alter table t1 drop index t1_unq_idx;
+let $possible_keys=
+ query_get_value(explain select avg(a) from t1, possible_keys, 1);
+let $extra=
+ query_get_value(explain select avg(a) from t1, Extra, 1);
+--echo # Optimizer strategy: Possible keys = $possible_keys , Extra = $extra
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
+
+
+--echo # select AVG(<col>) + optimizer uses table scan meets a new index
+alter table t1 add unique index t1_unq_idx(a);
+let $possible_keys=
+ query_get_value(explain select avg(a) from t1, possible_keys, 1);
+let $extra=
+ query_get_value(explain select avg(a) from t1, Extra, 1);
+--echo # Optimizer strategy: Possible keys = $possible_keys , Extra = $extra
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
+
+deallocate prepare stmt;
+drop table t1;
+
+
+--echo # table replaced by not updatable view - Insert
+create table t1 (a int);
+prepare stmt from "insert into t1 values(1)";
+execute stmt;
+call p_verify_reprepare_count(0);
+
+drop table t1;
+create view t1 as select 1;
+--error ER_NON_INSERTABLE_TABLE
+execute stmt;
+call p_verify_reprepare_count(1);
+
+drop view t1;
+create table t2 (a int);
+create view t1 as select * from t2 with check option;
+execute stmt;
+call p_verify_reprepare_count(1);
+execute stmt;
+call p_verify_reprepare_count(0);
+select * from t1;
+
+deallocate prepare stmt;
+drop view t1;
+drop table t2;
+
+
+--echo =====================================================================
+--echo Some freestyle tests
+--echo =====================================================================
+
+create temporary table t1 as select 1 as a;
+delimiter |;
+create procedure p1()
+begin
+ drop temporary table t1;
+end|
+create function f1() returns int
+begin
+ call p1();
+ return 1;
+end|
+delimiter ;|
+
+prepare stmt from "select f1() as my_column, a from t1";
+--error ER_CANT_REOPEN_TABLE
+execute stmt;
+call p_verify_reprepare_count(0);
+select * from t1;
+
+prepare stmt from "select a, f1() as my_column from t1";
+--error ER_CANT_REOPEN_TABLE
+execute stmt;
+call p_verify_reprepare_count(0);
+select * from t1;
+
+prepare stmt from "select f1() as my_column, count(*) from t1";
+--error ER_CANT_REOPEN_TABLE
+execute stmt;
+call p_verify_reprepare_count(0);
+select * from t1;
+
+prepare stmt from "select count(*), f1() as my_column from t1";
+--error ER_CANT_REOPEN_TABLE
+execute stmt;
+call p_verify_reprepare_count(0);
+select * from t1;
+
+
+--echo # Execute fails, no drop of temporary table
+prepare stmt from "select 1 as my_column from (select 1) as t2
+ where exists (select f1() from t1)";
+execute stmt;
+call p_verify_reprepare_count(0);
+execute stmt;
+call p_verify_reprepare_count(0);
+select * from t1;
+
+--echo # Execute drops temporary table
+prepare stmt from "select f1()";
+execute stmt;
+call p_verify_reprepare_count(0);
+--error ER_BAD_TABLE_ERROR
+execute stmt;
+call p_verify_reprepare_count(0);
+
+drop function f1;
+drop procedure p1;
+deallocate prepare stmt;
+
+--echo # Execute fails, temporary table is not replaced by another
+create temporary table t1 as select 1 as a;
+delimiter |;
+create procedure p1()
+begin
+ drop temporary table t1;
+ create temporary table t1 as select 'abc' as a;
+end|
+create function f1() returns int
+begin
+ call p1();
+ return 1;
+end|
+delimiter ;|
+prepare stmt from "select count(*), f1() as my_column from t1";
+--error ER_CANT_REOPEN_TABLE
+execute stmt;
+call p_verify_reprepare_count(0);
+select * from t1;
+deallocate prepare stmt;
+
+prepare stmt from "call p1";
+execute stmt;
+drop procedure p1;
+create schema mysqltest;
+delimiter |;
+create procedure mysqltest.p1()
+begin
+ drop schema mysqltest;
+ create schema mysqltest;
+end|
+delimiter ;|
+--error ER_SP_DOES_NOT_EXIST
+execute stmt;
+call p_verify_reprepare_count(0);
+--error ER_SP_DOES_NOT_EXIST
+execute stmt;
+call p_verify_reprepare_count(0);
+deallocate prepare stmt;
+drop schema mysqltest;
+drop temporary table t1;
+
+
+# Bug#36089 drop temp table in SP called by function, crash
+# Note: A non prepared "select 1 from t1 having count(*) = f1();" is sufficient.
+if (0)
+{
+create temporary table t1 as select 1 as a;
+prepare stmt from "select 1 from t1 having count(*) = f1()";
+execute stmt;
+call p_verify_reprepare_count(0);
+deallocate prepare stmt;
+drop temporary table t1;
+}
+
+
+--echo # Cleanup
+--echo #
+--disable_warnings
+drop temporary table if exists t1;
+drop table if exists t1, t2;
+drop procedure if exists p_verify_reprepare_count;
+drop procedure if exists p1;
+drop function if exists f1;
+drop view if exists t1;
+drop schema if exists mysqltest;
+--enable_warnings
diff --git a/mysql-test/t/query_cache_merge.test b/mysql-test/t/query_cache_merge.test
index 36b8662f088..5247d29a83c 100644
--- a/mysql-test/t/query_cache_merge.test
+++ b/mysql-test/t/query_cache_merge.test
@@ -25,6 +25,15 @@ while ($1)
}
--enable_warnings
+#
+# In order for the test to pass in --ps-protocol, we must
+# set table_definition_cache size to at least 258 elements.
+# Otherwise table versions are bound to change between
+# prepare and execute, and we will get a constant validation
+# error. See WL#4165 for details.
+#
+set @save_table_definition_cache= @@global.table_definition_cache;
+set @@global.table_definition_cache=512;
create table t00 (a int) engine=MERGE UNION=(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,t34,t35,t36,t37,t38,t39,t40,t41,t42,t43,t44,t45,t46,t47,t48,t49,t50,t51,t52,t53,t54,t55,t56,t57,t58,t59,t60,t61,t62,t63,t64,t65,t66,t67,t68,t69,t70,t71,t72,t73,t74,t75,t76,t77,t78,t79,t80,t81,t82,t83,t84,t85,t86,t87,t88,t89,t90,t91,t92,t93,t94,t95,t96,t97,t98,t99,t100,t101,t102,t103,t104,t105,t106,t107,t108,t109,t110,t111,t112,t113,t114,t115,t116,t117,t118,t119,t120,t121,t122,t123,t124,t125,t126,t127,t128,t129,t130,t131,t132,t133,t134,t135,t136,t137,t138,t139,t140,t141,t142,t143,t144,t145,t146,t147,t148,t149,t150,t151,t152,t153,t154,t155,t156,t157,t158,t159,t160,t161,t162,t163,t164,t165,t166,t167,t168,t169,t170,t171,t172,t173,t174,t175,t176,t177,t178,t179,t180,t181,t182,t183,t184,t185,t186,t187,t188,t189,t190,t191,t192,t193,t194,t195,t196,t197,t198,t199,t200,t201,t202,t203,t204,t205,t206,t207,t208,t209,t210,t211,t212,t213,t214,t215,t216,t217,t218,t219,t220,t221,t222,t223,t224,t225,t226,t227,t228,t229,t230,t231,t232,t233,t234,t235,t236,t237,t238,t239,t240,t241,t242,t243,t244,t245,t246,t247,t248,t249,t250,t251,t252,t253,t254,t255,t256,t257) INSERT_METHOD=FIRST;
enable_query_log;
select count(*) from t00;
@@ -36,5 +45,6 @@ show status like "Qcache_queries_in_cache";
drop table t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,t34,t35,t36,t37,t38,t39,t40,t41,t42,t43,t44,t45,t46,t47,t48,t49,t50,t51,t52,t53,t54,t55,t56,t57,t58,t59,t60,t61,t62,t63,t64,t65,t66,t67,t68,t69,t70,t71,t72,t73,t74,t75,t76,t77,t78,t79,t80,t81,t82,t83,t84,t85,t86,t87,t88,t89,t90,t91,t92,t93,t94,t95,t96,t97,t98,t99,t100,t101,t102,t103,t104,t105,t106,t107,t108,t109,t110,t111,t112,t113,t114,t115,t116,t117,t118,t119,t120,t121,t122,t123,t124,t125,t126,t127,t128,t129,t130,t131,t132,t133,t134,t135,t136,t137,t138,t139,t140,t141,t142,t143,t144,t145,t146,t147,t148,t149,t150,t151,t152,t153,t154,t155,t156,t157,t158,t159,t160,t161,t162,t163,t164,t165,t166,t167,t168,t169,t170,t171,t172,t173,t174,t175,t176,t177,t178,t179,t180,t181,t182,t183,t184,t185,t186,t187,t188,t189,t190,t191,t192,t193,t194,t195,t196,t197,t198,t199,t200,t201,t202,t203,t204,t205,t206,t207,t208,t209,t210,t211,t212,t213,t214,t215,t216,t217,t218,t219,t220,t221,t222,t223,t224,t225,t226,t227,t228,t229,t230,t231,t232,t233,t234,t235,t236,t237,t238,t239,t240,t241,t242,t243,t244,t245,t246,t247,t248,t249,t250,t251,t252,t253,t254,t255,t256,t257,t00;
SET @@global.query_cache_size=0;
+set @@global.table_definition_cache=@save_table_definition_cache;
# End of 4.1 tests
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index 921c9579bfb..c57178c1928 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -997,11 +997,10 @@ call p1();
# Altering trigger forcing it use different set of tables
drop trigger t1_bi;
create trigger t1_bi after insert on t1 for each row insert into t3 values (new.id);
-# Until we implement proper mechanism for invalidation of PS/SP when table
-# or SP's are changed these two statements will fail with 'Table ... was
-# not locked' error (this mechanism should be based on the new TDC).
---error ER_NO_SUCH_TABLE
execute stmt1;
+# Until we implement proper mechanism for invalidation of SP statements
+# invoked whenever a table used in SP changes, this statement will fail with
+# 'Table ... does not exist' error.
--error ER_NO_SUCH_TABLE
call p1();
deallocate prepare stmt1;
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index 51f8d6db1db..221f46605cd 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -778,3 +778,20 @@ set global thread_cache_size =@my_thread_cache_size;
--replace_column 2 #
show global variables where Variable_name='table_definition_cache' or
Variable_name='table_lock_wait_timeout';
+
+###########################################################################
+
+--echo
+--echo # --
+--echo # -- Bug#34820: log_output can be set to illegal value.
+--echo # --
+
+--error ER_WRONG_VALUE_FOR_VAR
+SET GLOBAL log_output = '';
+
+--error ER_WRONG_VALUE_FOR_VAR
+SET GLOBAL log_output = 0;
+
+--echo
+--echo # -- End of Bug#34820.
+
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index 9203ce9c34e..2607ea57d08 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -202,7 +202,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
{
if (mem_root->error_handler)
(*mem_root->error_handler)();
- return((void*) 0); /* purecov: inspected */
+ DBUG_RETURN((void*) 0); /* purecov: inspected */
}
mem_root->block_num++;
next->next= *prev;
diff --git a/sql/item.cc b/sql/item.cc
index 76f3a818826..96408a70bdd 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -3161,6 +3161,49 @@ void Item_param::print(String *str, enum_query_type query_type)
}
+/**
+ Preserve the original parameter types and values
+ when re-preparing a prepared statement.
+
+ @details Copy parameter type information and conversion
+ function pointers from a parameter of the old statement
+ to the corresponding parameter of the new one.
+
+ Move parameter values from the old parameters to the new
+ one. We simply "exchange" the values, which allows
+ to save on allocation and character set conversion in
+ case a parameter is a string or a blob/clob.
+
+ The old parameter gets the value of this one, which
+ ensures that all memory of this parameter is freed
+ correctly.
+
+ @param[in] src parameter item of the original
+ prepared statement
+*/
+
+void
+Item_param::set_param_type_and_swap_value(Item_param *src)
+{
+ unsigned_flag= src->unsigned_flag;
+ param_type= src->param_type;
+ set_param_func= src->set_param_func;
+ item_type= src->item_type;
+ item_result_type= src->item_result_type;
+
+ collation.set(src->collation);
+ maybe_null= src->maybe_null;
+ null_value= src->null_value;
+ max_length= src->max_length;
+ decimals= src->decimals;
+ state= src->state;
+ value= src->value;
+
+ decimal_value.swap(src->decimal_value);
+ str_value.swap(src->str_value);
+ str_value_ptr.swap(src->str_value_ptr);
+}
+
/****************************************************************************
Item_copy_string
****************************************************************************/
diff --git a/sql/item.h b/sql/item.h
index cd8bb4faccb..465d6f4d54c 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1684,6 +1684,7 @@ public:
bool eq(const Item *item, bool binary_cmp) const;
/** Item is a argument to a limit clause. */
bool limit_clause_param;
+ void set_param_type_and_swap_value(Item_param *from);
};
diff --git a/sql/my_decimal.h b/sql/my_decimal.h
index e73e0d4080d..0e79f70ab4e 100644
--- a/sql/my_decimal.h
+++ b/sql/my_decimal.h
@@ -114,6 +114,14 @@ public:
bool sign() const { return decimal_t::sign; }
void sign(bool s) { decimal_t::sign= s; }
uint precision() const { return intg + frac; }
+
+ /** Swap two my_decimal values */
+ void swap(my_decimal &rhs)
+ {
+ swap_variables(my_decimal, *this, rhs);
+ /* Swap the buffer pointers back */
+ swap_variables(decimal_digit_t *, buf, rhs.buf);
+ }
};
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 69f214d95f3..0060e7873e1 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -259,6 +259,21 @@ protected:
#define USER_VARS_HASH_SIZE 16
#define TABLE_OPEN_CACHE_MIN 64
#define TABLE_OPEN_CACHE_DEFAULT 64
+#define TABLE_DEF_CACHE_DEFAULT 256
+/**
+ We must have room for at least 256 table definitions in the table
+ cache, since otherwise there is no chance prepared
+ statements that use these many tables can work.
+ Prepared statements use table definition cache ids (table_map_id)
+ as table version identifiers. If the table definition
+ cache size is less than the number of tables used in a statement,
+ the contents of the table definition cache is guaranteed to rotate
+ between a prepare and execute. This leads to stable validation
+ errors. In future we shall use more stable version identifiers,
+ for now the only solution is to ensure that the table definition
+ cache can contain at least all tables of a given statement.
+*/
+#define TABLE_DEF_CACHE_MIN 256
/*
Value of 9236 discovered through binary search 2006-09-26 on Ubuntu Dapper
@@ -670,6 +685,31 @@ const char *set_thd_proc_info(THD *thd, const char *info,
const char *calling_file,
const unsigned int calling_line);
+/**
+ Enumerate possible types of a table from re-execution
+ standpoint.
+ TABLE_LIST class has a member of this type.
+ At prepared statement prepare, this member is assigned a value
+ as of the current state of the database. Before (re-)execution
+ of a prepared statement, we check that the value recorded at
+ prepare matches the type of the object we obtained from the
+ table definition cache.
+
+ @sa check_and_update_table_version()
+ @sa Execute_observer
+ @sa Prepared_statement::reprepare()
+*/
+
+enum enum_table_ref_type
+{
+ /** Initial value set by the parser */
+ TABLE_REF_NULL= 0,
+ TABLE_REF_VIEW,
+ TABLE_REF_BASE_TABLE,
+ TABLE_REF_I_S_TABLE,
+ TABLE_REF_TMP_TABLE
+};
+
/*
External variables
*/
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 0c1ad3ffc69..e34356215e2 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1957,9 +1957,11 @@ static BOOL WINAPI console_event_handler( DWORD type )
between main thread doing initialization and CTRL-C thread doing
cleanup, which can result into crash.
*/
+#ifndef EMBEDDED_LIBRARY
if(hEventShutdown)
kill_mysql();
else
+#endif
sql_print_warning("CTRL-C ignored during startup");
DBUG_RETURN(TRUE);
}
@@ -2843,6 +2845,7 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
by the stored procedures code.
*/
if (thd->spcont &&
+ ! (MyFlags & ME_NO_SP_HANDLER) &&
thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd))
{
/*
@@ -2852,7 +2855,8 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
DBUG_RETURN(0);
}
- if (!thd->no_warnings_for_error)
+ if (!thd->no_warnings_for_error &&
+ !(MyFlags & ME_NO_WARNING_FOR_ERROR))
{
/*
Suppress infinite recursion if there a memory allocation error
@@ -3092,6 +3096,7 @@ SHOW_VAR com_status_vars[]= {
{"stmt_execute", (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS},
{"stmt_fetch", (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS},
{"stmt_prepare", (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS},
+ {"stmt_reprepare", (char*) offsetof(STATUS_VAR, com_stmt_reprepare), SHOW_LONG_STATUS},
{"stmt_reset", (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS},
{"stmt_send_long_data", (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS},
{"truncate", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS},
@@ -3180,7 +3185,7 @@ static int init_common_variables(const char *conf_file_name, int argc,
We have few debug-only commands in com_status_vars, only visible in debug
builds. for simplicity we enable the assert only in debug builds
- There are 7 Com_ variables which don't have corresponding SQLCOM_ values:
+ There are 8 Com_ variables which don't have corresponding SQLCOM_ values:
(TODO strictly speaking they shouldn't be here, should not have Com_ prefix
that is. Perhaps Stmt_ ? Comstmt_ ? Prepstmt_ ?)
@@ -3189,6 +3194,7 @@ static int init_common_variables(const char *conf_file_name, int argc,
Com_stmt_execute => com_stmt_execute
Com_stmt_fetch => com_stmt_fetch
Com_stmt_prepare => com_stmt_prepare
+ Com_stmt_reprepare => com_stmt_reprepare
Com_stmt_reset => com_stmt_reset
Com_stmt_send_long_data => com_stmt_send_long_data
@@ -3197,7 +3203,7 @@ static int init_common_variables(const char *conf_file_name, int argc,
of SQLCOM_ constants.
*/
compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
- SQLCOM_END + 7);
+ SQLCOM_END + 8);
#endif
load_defaults(conf_file_name, groups, &argc, &argv);
@@ -6766,7 +6772,8 @@ The minimum value for this variable is 4096.",
{"table_definition_cache", OPT_TABLE_DEF_CACHE,
"The number of cached table definitions.",
(uchar**) &table_def_size, (uchar**) &table_def_size,
- 0, GET_ULONG, REQUIRED_ARG, 128, 1, 512*1024L, 0, 1, 0},
+ 0, GET_ULONG, REQUIRED_ARG, TABLE_DEF_CACHE_DEFAULT, TABLE_DEF_CACHE_MIN,
+ 512*1024L, 0, 1, 0},
{"table_open_cache", OPT_TABLE_OPEN_CACHE,
"The number of cached open tables.",
(uchar**) &table_cache_size, (uchar**) &table_cache_size, 0, GET_ULONG,
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index e5709f418f7..b428909d9b7 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2314,9 +2314,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
table deletes.
*/
if ((thd->lex->sql_command != SQLCOM_DELETE))
-#ifdef NOT_USED
- if ((thd->lex->sql_command != SQLCOM_UPDATE))
-#endif
{
/*
Get best non-covering ROR-intersection plan and prepare data for
diff --git a/sql/set_var.cc b/sql/set_var.cc
index fd81dc1a867..7d9d88f0281 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -1667,6 +1667,14 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names)
strmov(buff, "NULL");
goto err;
}
+
+ if (!m_allow_empty_value &&
+ res->length() == 0)
+ {
+ buff[0]= 0;
+ goto err;
+ }
+
var->save_result.ulong_value= ((ulong)
find_set(enum_names, res->c_ptr(),
res->length(),
@@ -1682,10 +1690,19 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names)
else
{
ulonglong tmp= var->value->val_int();
- /*
- For when the enum is made to contain 64 elements, as 1ULL<<64 is
- undefined, we guard with a "count<64" test.
- */
+
+ if (!m_allow_empty_value &&
+ tmp == 0)
+ {
+ buff[0]= '0';
+ buff[1]= 0;
+ goto err;
+ }
+
+ /*
+ For when the enum is made to contain 64 elements, as 1ULL<<64 is
+ undefined, we guard with a "count<64" test.
+ */
if (unlikely((tmp >= ((ULL(1)) << enum_names->count)) &&
(enum_names->count < 64)))
{
@@ -2385,32 +2402,51 @@ static int sys_check_log_path(THD *thd, set_var *var)
MY_STAT f_stat;
String str(buff, sizeof(buff), system_charset_info), *res;
const char *log_file_str;
-
+ size_t path_length;
+
if (!(res= var->value->val_str(&str)))
goto err;
log_file_str= res->c_ptr();
bzero(&f_stat, sizeof(MY_STAT));
- (void) unpack_filename(path, log_file_str);
- if (my_stat(path, &f_stat, MYF(0)))
+ path_length= unpack_filename(path, log_file_str);
+
+ if (!path_length)
{
- /* Check if argument is a file and we have 'write' permission */
- if (!MY_S_ISREG(f_stat.st_mode) ||
- !(f_stat.st_mode & MY_S_IWRITE))
- goto err;
+ /* File name is empty. */
+
+ goto err;
}
- else
+
+ if (my_stat(path, &f_stat, MYF(0)))
{
- size_t path_length;
/*
- Check if directory exists and
- we have permission to create file & write to file
+ A file system object exists. Check if argument is a file and we have
+ 'write' permission.
*/
- (void) dirname_part(path, log_file_str, &path_length);
- if (my_access(path, (F_OK|W_OK)))
+
+ if (!MY_S_ISREG(f_stat.st_mode) ||
+ !(f_stat.st_mode & MY_S_IWRITE))
goto err;
+
+ return 0;
}
+
+ /* Get dirname of the file path. */
+ (void) dirname_part(path, log_file_str, &path_length);
+
+ /* Dirname is empty if file path is relative. */
+ if (!path_length)
+ return 0;
+
+ /*
+ Check if directory exists and we have permission to create file and
+ write to file.
+ */
+ if (my_access(path, (F_OK|W_OK)))
+ goto err;
+
return 0;
err:
diff --git a/sql/set_var.h b/sql/set_var.h
index 290d1bf0eb1..603c3114d0e 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -74,7 +74,8 @@ public:
sys_var(const char *name_arg, sys_after_update_func func= NULL,
Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG)
:name(name_arg), after_update(func), no_support_one_shot(1),
- binlog_status(binlog_status_arg)
+ binlog_status(binlog_status_arg),
+ m_allow_empty_value(TRUE)
{}
virtual ~sys_var() {}
void chain_sys_var(sys_var_chain *chain_arg)
@@ -109,8 +110,16 @@ public:
virtual bool is_readonly() const { return 0; }
virtual sys_var_pluginvar *cast_pluginvar() { return 0; }
+protected:
+ void set_allow_empty_value(bool allow_empty_value)
+ {
+ m_allow_empty_value= allow_empty_value;
+ }
+
private:
const Binlog_status_enum binlog_status;
+
+ bool m_allow_empty_value;
};
@@ -878,8 +887,11 @@ public:
sys_var_log_output(sys_var_chain *chain, const char *name_arg, ulong *value_arg,
TYPELIB *typelib, sys_after_update_func func)
:sys_var(name_arg,func), value(value_arg), enum_names(typelib)
- { chain_sys_var(chain); }
- bool check(THD *thd, set_var *var)
+ {
+ chain_sys_var(chain);
+ set_allow_empty_value(FALSE);
+ }
+ virtual bool check(THD *thd, set_var *var)
{
return check_set(thd, var, enum_names);
}
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 5b9d0ce8617..3fd35fd0c76 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -6121,8 +6121,15 @@ ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT
eng "The BINLOG statement of type `%s` was not preceded by a format description BINLOG statement."
ER_SLAVE_CORRUPT_EVENT
eng "Corrupted replication event was detected"
+
ER_LOAD_DATA_INVALID_COLUMN
eng "Invalid column reference (%-.64s) in LOAD DATA"
ER_LOG_PURGE_NO_FILE
eng "Being purged log %s was not found"
+
+ER_NEED_REPREPARE
+ eng "Prepared statement needs to be re-prepared"
+
+ER_PS_REBIND
+ eng "Prepared statement result set has changed, a rebind needed"
diff --git a/sql/sp.cc b/sql/sp.cc
index 8637174efde..a1e5e1291ae 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1076,210 +1076,6 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
}
-struct st_used_field
-{
- const char *field_name;
- uint field_length;
- enum enum_field_types field_type;
- Field *field;
-};
-
-static struct st_used_field init_fields[]=
-{
- { "Db", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0},
- { "Name", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0},
- { "Type", 9, MYSQL_TYPE_STRING, 0},
- { "Definer", USER_HOST_BUFF_SIZE, MYSQL_TYPE_STRING, 0},
- { "Modified", 0, MYSQL_TYPE_TIMESTAMP, 0},
- { "Created", 0, MYSQL_TYPE_TIMESTAMP, 0},
- { "Security_type", 1, MYSQL_TYPE_STRING, 0},
- { "Comment", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0},
- { "character_set_client", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0},
- { "collation_connection", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0},
- { "Database Collation", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0},
- { 0, 0, MYSQL_TYPE_STRING, 0}
-};
-
-
-static int
-print_field_values(THD *thd, TABLE *table,
- struct st_used_field *used_fields,
- int type, const char *wild)
-{
- Protocol *protocol= thd->protocol;
-
- if (table->field[MYSQL_PROC_MYSQL_TYPE]->val_int() == type)
- {
- String db_string;
- String name_string;
- struct st_used_field *used_field= used_fields;
-
- if (get_field(thd->mem_root, used_field->field, &db_string))
- db_string.set_ascii("", 0);
- used_field+= 1;
- get_field(thd->mem_root, used_field->field, &name_string);
-
- if (!wild || !wild[0] || !wild_compare(name_string.ptr(), wild, 0))
- {
- protocol->prepare_for_resend();
- protocol->store(&db_string);
- protocol->store(&name_string);
- for (used_field++;
- used_field->field_name;
- used_field++)
- {
- switch (used_field->field_type) {
- case MYSQL_TYPE_TIMESTAMP:
- {
- MYSQL_TIME tmp_time;
-
- bzero((char *)&tmp_time, sizeof(tmp_time));
- ((Field_timestamp *) used_field->field)->get_time(&tmp_time);
- protocol->store(&tmp_time);
- }
- break;
- default:
- {
- String tmp_string;
-
- get_field(thd->mem_root, used_field->field, &tmp_string);
- protocol->store(&tmp_string);
- }
- break;
- }
- }
- if (protocol->write())
- return SP_INTERNAL_ERROR;
- }
- }
-
- return SP_OK;
-}
-
-
-/**
- Implement SHOW STATUS statement for stored routines.
-
- @param thd Thread context.
- @param type Stored routine type
- (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION)
- @param name_pattern Stored routine name pattern.
-
- @return Error code. SP_OK is returned on success. Other SP_ constants are
- used to indicate about errors.
-*/
-
-int
-sp_show_status_routine(THD *thd, int type, const char *name_pattern)
-{
- TABLE *table;
- TABLE_LIST tables;
- int res;
- DBUG_ENTER("sp_show_status_routine");
-
- DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE ||
- type == TYPE_ENUM_FUNCTION);
-
- memset(&tables, 0, sizeof(tables));
- tables.db= (char*)"mysql";
- tables.table_name= tables.alias= (char*)"proc";
-
- if (! (table= open_ltable(thd, &tables, TL_READ, 0)))
- {
- res= SP_OPEN_TABLE_FAILED;
- goto done;
- }
- else
- {
- Item *item;
- List<Item> field_list;
- struct st_used_field *used_field;
- TABLE_LIST *leaves= 0;
- st_used_field used_fields[array_elements(init_fields)];
-
- table->use_all_columns();
- memcpy((char*) used_fields, (char*) init_fields, sizeof(used_fields));
- /* Init header */
- for (used_field= &used_fields[0];
- used_field->field_name;
- used_field++)
- {
- switch (used_field->field_type) {
- case MYSQL_TYPE_TIMESTAMP:
- item= new Item_return_date_time(used_field->field_name,
- MYSQL_TYPE_DATETIME);
- field_list.push_back(item);
- break;
- default:
- item= new Item_empty_string(used_field->field_name,
- used_field->field_length);
- field_list.push_back(item);
- break;
- }
- }
- /* Print header */
- if (thd->protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
- Protocol::SEND_EOF))
- {
- res= SP_INTERNAL_ERROR;
- goto err_case;
- }
-
- /*
- Init fields
-
- tables is not VIEW for sure => we can pass 0 as condition
- */
- thd->lex->select_lex.context.resolve_in_table_list_only(&tables);
- setup_tables(thd, &thd->lex->select_lex.context,
- &thd->lex->select_lex.top_join_list,
- &tables, &leaves, FALSE);
- for (used_field= &used_fields[0];
- used_field->field_name;
- used_field++)
- {
- Item_field *field= new Item_field(&thd->lex->select_lex.context,
- "mysql", "proc",
- used_field->field_name);
- if (!field ||
- !(used_field->field= find_field_in_tables(thd, field, &tables, NULL,
- 0, REPORT_ALL_ERRORS, 1,
- TRUE)))
- {
- res= SP_INTERNAL_ERROR;
- goto err_case1;
- }
- }
-
- table->file->ha_index_init(0, 1);
- if ((res= table->file->index_first(table->record[0])))
- {
- res= (res == HA_ERR_END_OF_FILE) ? 0 : SP_INTERNAL_ERROR;
- goto err_case1;
- }
-
- do
- {
- res= print_field_values(thd, table, used_fields, type, name_pattern);
-
- if (res)
- goto err_case1;
- }
- while (!table->file->index_next(table->record[0]));
-
- res= SP_OK;
- }
-
-err_case1:
- my_eof(thd);
-err_case:
- table->file->ha_index_end();
- close_thread_tables(thd);
-done:
- DBUG_RETURN(res);
-}
-
-
/**
Drop all routines in database 'db'
diff --git a/sql/sp.h b/sql/sp.h
index 31173e1f90c..75088ea0b83 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -49,9 +49,6 @@ bool
sp_show_create_routine(THD *thd, int type, sp_name *name);
int
-sp_show_status_routine(THD *thd, int type, const char *wild);
-
-int
sp_create_routine(THD *thd, int type, sp_head *sp);
int
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index e342a3e9451..c450c9dd25d 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1072,6 +1072,7 @@ sp_head::execute(THD *thd)
LEX *old_lex;
Item_change_list old_change_list;
String old_packet;
+ Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
Object_creation_ctx *saved_creation_ctx;
@@ -1139,6 +1140,25 @@ sp_head::execute(THD *thd)
thd->variables.sql_mode= m_sql_mode;
save_abort_on_warning= thd->abort_on_warning;
thd->abort_on_warning= 0;
+ /**
+ When inside a substatement (a stored function or trigger
+ statement), clear the metadata observer in THD, if any.
+ Remember the value of the observer here, to be able
+ to restore it when leaving the substatement.
+
+ We reset the observer to suppress errors when a substatement
+ uses temporary tables. If a temporary table does not exist
+ at start of the main statement, it's not prelocked
+ and thus is not validated with other prelocked tables.
+
+ Later on, when the temporary table is opened, metadata
+ versions mismatch, expectedly.
+
+ The proper solution for the problem is to re-validate tables
+ of substatements (Bug#12257, Bug#27011, Bug#32868, Bug#33000),
+ but it's not implemented yet.
+ */
+ thd->m_reprepare_observer= 0;
/*
It is also more efficient to save/restore current thd->lex once when
@@ -1301,6 +1321,7 @@ sp_head::execute(THD *thd)
thd->derived_tables= old_derived_tables;
thd->variables.sql_mode= save_sql_mode;
thd->abort_on_warning= save_abort_on_warning;
+ thd->m_reprepare_observer= save_reprepare_observer;
thd->stmt_arena= old_arena;
state= EXECUTED;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 92eb68dc2fa..0b33abcfba2 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -695,6 +695,8 @@ my_bool acl_reload(THD *thd)
tables[0].next_local= tables[0].next_global= tables+1;
tables[1].next_local= tables[1].next_global= tables+2;
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ;
+ tables[0].skip_temporary= tables[1].skip_temporary=
+ tables[2].skip_temporary= TRUE;
if (simple_open_n_lock_tables(thd, tables))
{
@@ -3537,7 +3539,7 @@ static my_bool grant_load_procs_priv(TABLE *p_table)
bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE;
MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**,
THR_MALLOC);
- DBUG_ENTER("grant_load");
+ DBUG_ENTER("grant_load_procs_priv");
(void) hash_init(&proc_priv_hash,system_charset_info,
0,0,0, (hash_get_key) get_grant_table,
0,0);
@@ -3721,6 +3723,7 @@ static my_bool grant_reload_procs_priv(THD *thd)
table.alias= table.table_name= (char*) "procs_priv";
table.db= (char *) "mysql";
table.lock_type= TL_READ;
+ table.skip_temporary= 1;
if (simple_open_n_lock_tables(thd, &table))
{
@@ -3786,7 +3789,7 @@ my_bool grant_reload(THD *thd)
tables[0].db= tables[1].db= (char *) "mysql";
tables[0].next_local= tables[0].next_global= tables+1;
tables[0].lock_type= tables[1].lock_type= TL_READ;
-
+ tables[0].skip_temporary= tables[1].skip_temporary= TRUE;
/*
To avoid deadlocks we should obtain table locks before
obtaining LOCK_grant rwlock.
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b680bbc1308..d25057789ac 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -345,26 +345,9 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
if (!(share= alloc_table_share(table_list, key, key_length)))
{
-#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
- pthread_mutex_unlock(&LOCK_open);
-#endif
DBUG_RETURN(0);
}
-#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
- // We need a write lock to be able to add a new entry
- pthread_mutex_unlock(&LOCK_open);
- pthread_mutex_lock(&LOCK_open);
- /* Check that another thread didn't insert the same table in between */
- if ((old_share= hash_search(&table_def_cache, (uchar*) key, key_length)))
- {
- (void) pthread_mutex_lock(&share->mutex);
- free_table_share(share);
- share= old_share;
- goto found;
- }
-#endif
-
/*
Lock mutex to be able to read table definition from file without
conflicts
@@ -388,29 +371,11 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
if (my_hash_insert(&table_def_cache, (uchar*) share))
{
-#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
- pthread_mutex_unlock(&LOCK_open);
- (void) pthread_mutex_unlock(&share->mutex);
-#endif
free_table_share(share);
DBUG_RETURN(0); // return error
}
-#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
- pthread_mutex_unlock(&LOCK_open);
-#endif
if (open_table_def(thd, share, db_flags))
{
-#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
- /*
- No such table or wrong table definition file
- Lock first the table cache and then the mutex.
- This will ensure that no other thread is using the share
- structure.
- */
- (void) pthread_mutex_unlock(&share->mutex);
- (void) pthread_mutex_lock(&LOCK_open);
- (void) pthread_mutex_lock(&share->mutex);
-#endif
*error= share->error;
(void) hash_delete(&table_def_cache, (uchar*) share);
DBUG_RETURN(0);
@@ -429,9 +394,6 @@ found:
/* We must do a lock to ensure that the structure is initialized */
(void) pthread_mutex_lock(&share->mutex);
-#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
- pthread_mutex_unlock(&LOCK_open);
-#endif
if (share->error)
{
/* Table definition contained an error */
@@ -618,52 +580,6 @@ void release_table_share(TABLE_SHARE *share, enum release_type type)
}
pthread_mutex_unlock(&share->mutex);
DBUG_VOID_RETURN;
-
-
-#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
- if (to_be_deleted)
- {
- /*
- We must try again with new locks as we must get LOCK_open
- before share->mutex
- */
- pthread_mutex_unlock(&share->mutex);
- pthread_mutex_lock(&LOCK_open);
- pthread_mutex_lock(&share->mutex);
- if (!share->ref_count)
- { // No one is using this now
- TABLE_SHARE *name_lock;
- if (share->replace_with_name_lock && (name_lock=get_name_lock(share)))
- {
- /*
- This code is execured when someone does FLUSH TABLES while on has
- locked tables.
- */
- (void) hash_search(&def_cache,(uchar*) key,key_length);
- hash_replace(&def_cache, def_cache.current_record,(uchar*) name_lock);
- }
- else
- {
- /* Remove table definition */
- hash_delete(&def_cache,(uchar*) share);
- }
- pthread_mutex_unlock(&LOCK_open);
- free_table_share(share);
- }
- else
- {
- pthread_mutex_unlock(&LOCK_open);
- if (type == RELEASE_WAIT_FOR_DROP)
- wait_for_table(share, "Waiting for close");
- else
- pthread_mutex_unlock(&share->mutex);
- }
- }
- else if (type == RELEASE_WAIT_FOR_DROP)
- wait_for_table(share, "Waiting for close");
- else
- pthread_mutex_unlock(&share->mutex);
-#endif
}
@@ -3801,6 +3717,73 @@ void assign_new_table_id(TABLE_SHARE *share)
DBUG_VOID_RETURN;
}
+
+/**
+ Compare metadata versions of an element obtained from the table
+ definition cache and its corresponding node in the parse tree.
+
+ @details If the new and the old values mismatch, invoke
+ Metadata_version_observer.
+ At prepared statement prepare, all TABLE_LIST version values are
+ NULL and we always have a mismatch. But there is no observer set
+ in THD, and therefore no error is reported. Instead, we update
+ the value in the parse tree, effectively recording the original
+ version.
+ At prepared statement execute, an observer may be installed. If
+ there is a version mismatch, we push an error and return TRUE.
+
+ For conventional execution (no prepared statements), the
+ observer is never installed.
+
+ @sa Execute_observer
+ @sa check_prepared_statement() to see cases when an observer is installed
+ @sa TABLE_LIST::is_table_ref_id_equal()
+ @sa TABLE_SHARE::get_table_ref_id()
+
+ @param[in] thd used to report errors
+ @param[in,out] tables TABLE_LIST instance created by the parser
+ Metadata version information in this object
+ is updated upon success.
+ @param[in] table_share an element from the table definition cache
+
+ @retval TRUE an error, which has been reported
+ @retval FALSE success, version in TABLE_LIST has been updated
+*/
+
+bool
+check_and_update_table_version(THD *thd,
+ TABLE_LIST *tables, TABLE_SHARE *table_share)
+{
+ if (! tables->is_table_ref_id_equal(table_share))
+ {
+ if (thd->m_reprepare_observer &&
+ thd->m_reprepare_observer->report_error(thd))
+ {
+ /*
+ Version of the table share is different from the
+ previous execution of the prepared statement, and it is
+ unacceptable for this SQLCOM. Error has been reported.
+ */
+ DBUG_ASSERT(thd->is_error());
+ return TRUE;
+ }
+ /* Always maintain the latest version and type */
+ tables->set_table_ref_id(table_share);
+ }
+
+#ifndef DBUG_OFF
+ /* Spuriously reprepare each statement. */
+ if (_db_strict_keyword_("reprepare_each_statement") &&
+ thd->m_reprepare_observer && thd->stmt_arena->is_reprepared == FALSE)
+ {
+ thd->m_reprepare_observer->report_error(thd);
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
+
/*
Load a table definition from file and open unireg table
@@ -3846,6 +3829,12 @@ retry:
if (share->is_view)
{
+ /*
+ This table is a view. Validate its metadata version: in particular,
+ that it was a view when the statement was prepared.
+ */
+ if (check_and_update_table_version(thd, table_list, share))
+ goto err;
if (table_list->i_s_requested_object & OPEN_TABLE_ONLY)
goto err;
@@ -3863,6 +3852,26 @@ retry:
release_table_share(share, RELEASE_NORMAL);
DBUG_RETURN((flags & OPEN_VIEW_NO_PARSE)? -1 : 0);
}
+ else if (table_list->view)
+ {
+ /*
+ We're trying to open a table for what was a view.
+ This can only happen during (re-)execution.
+ At prepared statement prepare the view has been opened and
+ merged into the statement parse tree. After that, someone
+ performed a DDL and replaced the view with a base table.
+ Don't try to open the table inside a prepared statement,
+ invalidate it instead.
+
+ Note, the assert below is known to fail inside stored
+ procedures (Bug#27011).
+ */
+ DBUG_ASSERT(thd->m_reprepare_observer);
+ check_and_update_table_version(thd, table_list, share);
+ /* Always an error. */
+ DBUG_ASSERT(thd->is_error());
+ goto err;
+ }
if (table_list->i_s_requested_object & OPEN_VIEW_ONLY)
goto err;
@@ -4464,8 +4473,18 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
*/
if (tables->schema_table)
{
- if (!mysql_schema_table(thd, thd->lex, tables))
+ /*
+ If this information_schema table is merged into a mergeable
+ view, ignore it for now -- it will be filled when its respective
+ TABLE_LIST is processed. This code works only during re-execution.
+ */
+ if (tables->view)
+ goto process_view_routines;
+ if (!mysql_schema_table(thd, thd->lex, tables) &&
+ !check_and_update_table_version(thd, tables, tables->table->s))
+ {
continue;
+ }
DBUG_RETURN(-1);
}
(*counter)++;
@@ -4613,6 +4632,13 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
}
tables->table->grant= tables->grant;
+ /* Check and update metadata version of a base table. */
+ if (check_and_update_table_version(thd, tables, tables->table->s))
+ {
+ result= -1;
+ goto err;
+ }
+
/* Attach MERGE children if not locked already. */
DBUG_PRINT("tcache", ("is parent: %d is child: %d",
test(tables->table->child_l),
@@ -4671,7 +4697,11 @@ process_view_routines:
error happens on a MERGE child, clear the parents TABLE reference.
*/
if (tables->parent_l)
+ {
+ if (tables->parent_l->next_global == tables->parent_l->table->child_l)
+ tables->parent_l->next_global= *tables->parent_l->table->child_last_l;
tables->parent_l->table= NULL;
+ }
tables->table= NULL;
}
DBUG_PRINT("tcache", ("returning: %d", result));
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 5ee4f3dea02..afa9777e00a 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -198,6 +198,19 @@ bool foreign_key_prefix(Key *a, Key *b)
** Thread specific functions
****************************************************************************/
+/** Push an error to the error stack and return TRUE for now. */
+
+bool
+Reprepare_observer::report_error(THD *thd)
+{
+ my_error(ER_NEED_REPREPARE, MYF(ME_NO_WARNING_FOR_ERROR|ME_NO_SP_HANDLER));
+
+ m_invalidated= TRUE;
+
+ return TRUE;
+}
+
+
Open_tables_state::Open_tables_state(ulong version_arg)
:version(version_arg), state_flags(0U)
{
@@ -2770,7 +2783,8 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup)
DBUG_ASSERT(open_tables == 0 && temporary_tables == 0 &&
handler_tables == 0 && derived_tables == 0 &&
lock == 0 && locked_tables == 0 &&
- prelocked_mode == NON_PRELOCKED);
+ prelocked_mode == NON_PRELOCKED &&
+ m_reprepare_observer == NULL);
set_open_tables_state(backup);
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 446b7f163d9..a86b4d36d00 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -23,6 +23,51 @@
#include "log.h"
#include "rpl_tblmap.h"
+/**
+ An interface that is used to take an action when
+ the locking module notices that a table version has changed
+ since the last execution. "Table" here may refer to any kind of
+ table -- a base table, a temporary table, a view or an
+ information schema table.
+
+ When we open and lock tables for execution of a prepared
+ statement, we must verify that they did not change
+ since statement prepare. If some table did change, the statement
+ parse tree *may* be no longer valid, e.g. in case it contains
+ optimizations that depend on table metadata.
+
+ This class provides an interface (a method) that is
+ invoked when such a situation takes place.
+ The implementation of the method simply reports an error, but
+ the exact details depend on the nature of the SQL statement.
+
+ At most 1 instance of this class is active at a time, in which
+ case THD::m_reprepare_observer is not NULL.
+
+ @sa check_and_update_table_version() for details of the
+ version tracking algorithm
+
+ @sa Open_tables_state::m_reprepare_observer for the life cycle
+ of metadata observers.
+*/
+
+class Reprepare_observer
+{
+public:
+ /**
+ Check if a change of metadata is OK. In future
+ the signature of this method may be extended to accept the old
+ and the new versions, but since currently the check is very
+ simple, we only need the THD to report an error.
+ */
+ bool report_error(THD *thd);
+ bool is_invalidated() const { return m_invalidated; }
+ void reset_reprepare_observer() { m_invalidated= FALSE; }
+private:
+ bool m_invalidated;
+};
+
+
class Relay_log_info;
class Query_log_event;
@@ -406,6 +451,7 @@ typedef struct system_status_var
ulong filesort_scan_count;
/* Prepared statements and binary protocol */
ulong com_stmt_prepare;
+ ulong com_stmt_reprepare;
ulong com_stmt_execute;
ulong com_stmt_send_long_data;
ulong com_stmt_fetch;
@@ -436,7 +482,7 @@ void free_tmp_table(THD *thd, TABLE *entry);
/* The following macro is to make init of Query_arena simpler */
#ifndef DBUG_OFF
-#define INIT_ARENA_DBUG_INFO is_backup_arena= 0
+#define INIT_ARENA_DBUG_INFO is_backup_arena= 0; is_reprepared= FALSE;
#else
#define INIT_ARENA_DBUG_INFO
#endif
@@ -452,6 +498,7 @@ public:
MEM_ROOT *mem_root; // Pointer to current memroot
#ifndef DBUG_OFF
bool is_backup_arena; /* True if this arena is used for backup. */
+ bool is_reprepared;
#endif
/*
The states relfects three diffrent life cycles for three
@@ -789,6 +836,20 @@ class Open_tables_state
{
public:
/**
+ As part of class THD, this member is set during execution
+ of a prepared statement. When it is set, it is used
+ by the locking subsystem to report a change in table metadata.
+
+ When Open_tables_state part of THD is reset to open
+ a system or INFORMATION_SCHEMA table, the member is cleared
+ to avoid spurious ER_NEED_REPREPARE errors -- system and
+ INFORMATION_SCHEMA tables are not subject to metadata version
+ tracking.
+ @sa check_and_update_table_version()
+ */
+ Reprepare_observer *m_reprepare_observer;
+
+ /**
List of regular tables in use by this thread. Contains temporary and
base tables that were opened with @see open_tables().
*/
@@ -891,6 +952,7 @@ public:
extra_lock= lock= locked_tables= 0;
prelocked_mode= NON_PRELOCKED;
state_flags= 0U;
+ m_reprepare_observer= NULL;
}
};
@@ -2812,6 +2874,20 @@ public:
#define CF_STATUS_COMMAND 4
#define CF_SHOW_TABLE_COMMAND 8
#define CF_WRITE_LOGS_COMMAND 16
+/**
+ Must be set for SQL statements that may contain
+ Item expressions and/or use joins and tables.
+ Indicates that the parse tree of such statement may
+ contain rule-based optimizations that depend on metadata
+ (i.e. number of columns in a table), and consequently
+ that the statement must be re-prepared whenever
+ referenced metadata changes. Must not be set for
+ statements that themselves change metadata, e.g. RENAME,
+ ALTER and other DDL, since otherwise will trigger constant
+ reprepare. Consequently, complex item expressions and
+ joins are currently prohibited in these statements.
+*/
+#define CF_REEXECUTION_FRAGILE 32
/* Functions in sql_class.cc */
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index 5c4e93d4c74..d33680e1e0b 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -111,7 +111,8 @@ class Select_materialize: public select_union
select_result *result; /**< the result object of the caller (PS or SP) */
public:
Materialized_cursor *materialized_cursor;
- Select_materialize(select_result *result_arg) :result(result_arg) {}
+ Select_materialize(select_result *result_arg)
+ :result(result_arg), materialized_cursor(0) {}
virtual bool send_fields(List<Item> &list, uint flags);
};
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index ddcec92a0d3..ee251e6511b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -200,45 +200,56 @@ void init_update_queries(void)
{
bzero((uchar*) &sql_command_flags, sizeof(sql_command_flags));
- sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND;
sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND;
sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA;
- sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_RENAME_TABLE]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_BACKUP_TABLE]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_RESTORE_TABLE]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_DROP_INDEX]= CF_CHANGES_DATA;
- sql_command_flags[SQLCOM_CREATE_VIEW]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_CREATE_VIEW]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_DROP_VIEW]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_CREATE_EVENT]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_ALTER_EVENT]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA;
- sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
- sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
- sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
- sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
- sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
- sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
- sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
- sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
-
- sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_DATABASES]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_TRIGGERS]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_EVENTS]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
+ CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
+ CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
+ CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
+ CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
+ CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
+ CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
+ CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
+ CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SELECT]= CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_DO]= CF_REEXECUTION_FRAGILE;
+
+ sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_DATABASES]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_TRIGGERS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_EVENTS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_SHOW_PLUGINS]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_FIELDS]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_KEYS]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_VARIABLES]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_CHARSETS]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_COLLATIONS]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_FIELDS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_KEYS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_VARIABLES]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_CHARSETS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_COLLATIONS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_SHOW_NEW_MASTER]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_BINLOGS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_SLAVE_HOSTS]= CF_STATUS_COMMAND;
@@ -262,7 +273,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_SHOW_PROC_CODE]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_FUNC_CODE]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND;
@@ -270,9 +281,11 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_SHOW_PROFILE]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND |
- CF_SHOW_TABLE_COMMAND);
+ CF_SHOW_TABLE_COMMAND |
+ CF_REEXECUTION_FRAGILE);
sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND |
- CF_SHOW_TABLE_COMMAND);
+ CF_SHOW_TABLE_COMMAND |
+ CF_REEXECUTION_FRAGILE);
/*
The following is used to preserver CF_ROW_COUNT during the
@@ -280,7 +293,7 @@ void init_update_queries(void)
last called (or executed) statement is preserved.
See mysql_execute_command() for how CF_ROW_COUNT is used.
*/
- sql_command_flags[SQLCOM_CALL]= CF_HAS_ROW_COUNT;
+ sql_command_flags[SQLCOM_CALL]= CF_HAS_ROW_COUNT | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_EXECUTE]= CF_HAS_ROW_COUNT;
/*
@@ -4315,20 +4328,6 @@ create_sp_error:
}
break;
}
-#ifdef NOT_USED
- case SQLCOM_SHOW_STATUS_PROC:
- {
- res= sp_show_status_routine(thd, TYPE_ENUM_PROCEDURE,
- (lex->wild ? lex->wild->ptr() : NullS));
- break;
- }
- case SQLCOM_SHOW_STATUS_FUNC:
- {
- res= sp_show_status_routine(thd, TYPE_ENUM_FUNCTION,
- (lex->wild ? lex->wild->ptr() : NullS));
- break;
- }
-#endif
#ifndef DBUG_OFF
case SQLCOM_SHOW_PROC_CODE:
case SQLCOM_SHOW_FUNC_CODE:
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 091cc18114b..3036b36f8fa 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -155,21 +155,28 @@ public:
virtual void cleanup_stmt();
bool set_name(LEX_STRING *name);
inline void close_cursor() { delete cursor; cursor= 0; }
-
+ inline bool is_in_use() { return flags & (uint) IS_IN_USE; }
+ inline bool is_protocol_text() const { return protocol == &thd->protocol_text; }
bool prepare(const char *packet, uint packet_length);
- bool execute(String *expanded_query, bool open_cursor);
+ bool execute_loop(String *expanded_query,
+ bool open_cursor,
+ uchar *packet_arg, uchar *packet_end_arg);
/* Destroy this statement */
- bool deallocate();
+ void deallocate();
private:
/**
- Store the parsed tree of a prepared statement here.
- */
- LEX main_lex;
- /**
The memory root to allocate parsed tree elements (instances of Item,
SELECT_LEX and other classes).
*/
MEM_ROOT main_mem_root;
+private:
+ bool set_db(const char *db, uint db_length);
+ bool set_parameters(String *expanded_query,
+ uchar *packet, uchar *packet_end);
+ bool execute(String *expanded_query, bool open_cursor);
+ bool reprepare();
+ bool validate_metadata(Prepared_statement *copy);
+ void swap_prepared_statement(Prepared_statement *copy);
};
@@ -198,7 +205,7 @@ inline bool is_param_null(const uchar *pos, ulong param_no)
*/
static Prepared_statement *
-find_prepared_statement(THD *thd, ulong id, const char *where)
+find_prepared_statement(THD *thd, ulong id)
{
/*
To strictly separate namespaces of SQL prepared statements and C API
@@ -208,12 +215,8 @@ find_prepared_statement(THD *thd, ulong id, const char *where)
Statement *stmt= thd->stmt_map.find(id);
if (stmt == 0 || stmt->type() != Query_arena::PREPARED_STATEMENT)
- {
- char llbuf[22];
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf), llstr(id, llbuf),
- where);
- return 0;
- }
+ return NULL;
+
return (Prepared_statement *) stmt;
}
@@ -945,6 +948,55 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt,
#endif /*!EMBEDDED_LIBRARY*/
+/**
+ Setup data conversion routines using an array of parameter
+ markers from the original prepared statement.
+ Swap the parameter data of the original prepared
+ statement to the new one.
+
+ Used only when we re-prepare a prepared statement.
+ There are two reasons for this function to exist:
+
+ 1) In the binary client/server protocol, parameter metadata
+ is sent only at first execute. Consequently, if we need to
+ reprepare a prepared statement at a subsequent execution,
+ we may not have metadata information in the packet.
+ In that case we use the parameter array of the original
+ prepared statement to setup parameter types of the new
+ prepared statement.
+
+ 2) In the binary client/server protocol, we may supply
+ long data in pieces. When the last piece is supplied,
+ we assemble the pieces and convert them from client
+ character set to the connection character set. After
+ that the parameter value is only available inside
+ the parameter, the original pieces are lost, and thus
+ we can only assign the corresponding parameter of the
+ reprepared statement from the original value.
+
+ @param[out] param_array_dst parameter markers of the new statement
+ @param[in] param_array_src parameter markers of the original
+ statement
+ @param[in] param_count total number of parameters. Is the
+ same in src and dst arrays, since
+ the statement query is the same
+
+ @return this function never fails
+*/
+
+static void
+swap_parameter_array(Item_param **param_array_dst,
+ Item_param **param_array_src,
+ uint param_count)
+{
+ Item_param **dst= param_array_dst;
+ Item_param **src= param_array_src;
+ Item_param **end= param_array_dst + param_count;
+
+ for (; dst < end; ++src, ++dst)
+ (*dst)->set_param_type_and_swap_value(*src);
+}
+
/**
Assign prepared statement parameters from user variables.
@@ -1268,7 +1320,7 @@ error:
*/
static int mysql_test_select(Prepared_statement *stmt,
- TABLE_LIST *tables, bool text_protocol)
+ TABLE_LIST *tables)
{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
@@ -1304,7 +1356,7 @@ static int mysql_test_select(Prepared_statement *stmt,
*/
if (unit->prepare(thd, 0, 0))
goto error;
- if (!lex->describe && !text_protocol)
+ if (!lex->describe && !stmt->is_protocol_text())
{
/* Make copy of item list, as change_columns may change it */
List<Item> fields(lex->select_lex.item_list);
@@ -1396,6 +1448,43 @@ error:
/**
+ Validate and prepare for execution CALL statement expressions.
+
+ @param stmt prepared statement
+ @param tables list of tables used in this query
+ @param value_list list of expressions
+
+ @retval FALSE success
+ @retval TRUE error, error message is set in THD
+*/
+
+static bool mysql_test_call_fields(Prepared_statement *stmt,
+ TABLE_LIST *tables,
+ List<Item> *value_list)
+{
+ DBUG_ENTER("mysql_test_call_fields");
+
+ List_iterator<Item> it(*value_list);
+ THD *thd= stmt->thd;
+ Item *item;
+
+ if (tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE) ||
+ open_normal_and_derived_tables(thd, tables, 0))
+ goto err;
+
+ while ((item= it++))
+ {
+ if (!item->fixed && item->fix_fields(thd, it.ref()) ||
+ item->check_cols(1))
+ goto err;
+ }
+ DBUG_RETURN(FALSE);
+err:
+ DBUG_RETURN(TRUE);
+}
+
+
+/**
Check internal SELECT of the prepared command.
@param stmt prepared statement
@@ -1516,6 +1605,17 @@ static bool mysql_test_create_table(Prepared_statement *stmt)
res= select_like_stmt_test(stmt, 0, 0);
}
+ else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
+ {
+ /*
+ Check that the source table exist, and also record
+ its metadata version. Even though not strictly necessary,
+ we validate metadata of all CREATE TABLE statements,
+ which keeps metadata validation code simple.
+ */
+ if (open_normal_and_derived_tables(stmt->thd, lex->query_tables, 0))
+ DBUG_RETURN(TRUE);
+ }
/* put tables back for PS rexecuting */
lex->link_first_table_back(create_table, link_to_local);
@@ -1712,8 +1812,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt,
TRUE error, error message is set in THD (but not sent)
*/
-static bool check_prepared_statement(Prepared_statement *stmt,
- bool text_protocol)
+static bool check_prepared_statement(Prepared_statement *stmt)
{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
@@ -1754,9 +1853,23 @@ static bool check_prepared_statement(Prepared_statement *stmt,
case SQLCOM_DELETE:
res= mysql_test_delete(stmt, tables);
break;
-
+ /* The following allow WHERE clause, so they must be tested like SELECT */
+ case SQLCOM_SHOW_DATABASES:
+ case SQLCOM_SHOW_TABLES:
+ case SQLCOM_SHOW_TRIGGERS:
+ case SQLCOM_SHOW_EVENTS:
+ case SQLCOM_SHOW_OPEN_TABLES:
+ case SQLCOM_SHOW_FIELDS:
+ case SQLCOM_SHOW_KEYS:
+ case SQLCOM_SHOW_COLLATIONS:
+ case SQLCOM_SHOW_CHARSETS:
+ case SQLCOM_SHOW_VARIABLES:
+ case SQLCOM_SHOW_STATUS:
+ case SQLCOM_SHOW_TABLE_STATUS:
+ case SQLCOM_SHOW_STATUS_PROC:
+ case SQLCOM_SHOW_STATUS_FUNC:
case SQLCOM_SELECT:
- res= mysql_test_select(stmt, tables, text_protocol);
+ res= mysql_test_select(stmt, tables);
if (res == 2)
{
/* Statement and field info has already been sent */
@@ -1779,6 +1892,9 @@ static bool check_prepared_statement(Prepared_statement *stmt,
res= mysql_test_do_fields(stmt, tables, lex->insert_list);
break;
+ case SQLCOM_CALL:
+ res= mysql_test_call_fields(stmt, tables, &lex->value_list);
+ break;
case SQLCOM_SET_OPTION:
res= mysql_test_set_fields(stmt, tables, &lex->var_list);
break;
@@ -1828,7 +1944,6 @@ static bool check_prepared_statement(Prepared_statement *stmt,
case SQLCOM_DROP_INDEX:
case SQLCOM_ROLLBACK:
case SQLCOM_TRUNCATE:
- case SQLCOM_CALL:
case SQLCOM_DROP_VIEW:
case SQLCOM_REPAIR:
case SQLCOM_ANALYZE:
@@ -1871,8 +1986,8 @@ static bool check_prepared_statement(Prepared_statement *stmt,
break;
}
if (res == 0)
- DBUG_RETURN(text_protocol? FALSE : (send_prep_stmt(stmt, 0) ||
- thd->protocol->flush()));
+ DBUG_RETURN(stmt->is_protocol_text() ?
+ FALSE : (send_prep_stmt(stmt, 0) || thd->protocol->flush()));
error:
DBUG_RETURN(TRUE);
}
@@ -2121,8 +2236,13 @@ void mysql_sql_stmt_prepare(THD *thd)
If there is a statement with the same name, remove it. It is ok to
remove old and fail to insert a new one at the same time.
*/
- if (stmt->deallocate())
+ if (stmt->is_in_use())
+ {
+ my_error(ER_PS_NO_RECURSION, MYF(0));
DBUG_VOID_RETURN;
+ }
+
+ stmt->deallocate();
}
if (! (query= get_dynamic_sql_string(lex, &query_len)) ||
@@ -2308,11 +2428,9 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
ulong flags= (ulong) packet[4];
/* Query text for binary, general or slow log, if any of them is open */
String expanded_query;
-#ifndef EMBEDDED_LIBRARY
uchar *packet_end= packet + packet_length;
-#endif
Prepared_statement *stmt;
- bool error;
+ bool open_cursor;
DBUG_ENTER("mysql_stmt_execute");
packet+= 9; /* stmt_id + 5 bytes of flags */
@@ -2320,8 +2438,13 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
/* First of all clear possible warnings from the previous command */
mysql_reset_thd_for_next_command(thd);
- if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute")))
+ if (!(stmt= find_prepared_statement(thd, stmt_id)))
+ {
+ char llbuf[22];
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf),
+ llstr(stmt_id, llbuf), "mysql_stmt_execute");
DBUG_VOID_RETURN;
+ }
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.set_query_source(stmt->query, stmt->query_length);
@@ -2332,44 +2455,12 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
sp_cache_flush_obsolete(&thd->sp_proc_cache);
sp_cache_flush_obsolete(&thd->sp_func_cache);
-#ifndef EMBEDDED_LIBRARY
- if (stmt->param_count)
- {
- uchar *null_array= packet;
- if (setup_conversion_functions(stmt, &packet, packet_end) ||
- stmt->set_params(stmt, null_array, packet, packet_end,
- &expanded_query))
- goto set_params_data_err;
- }
-#else
- /*
- In embedded library we re-install conversion routines each time
- we set params, and also we don't need to parse packet.
- So we do it in one function.
- */
- if (stmt->param_count && stmt->set_params_data(stmt, &expanded_query))
- goto set_params_data_err;
-#endif
- if (!(specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+ open_cursor= test(flags & (ulong) CURSOR_TYPE_READ_ONLY);
- /*
- 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);
+ stmt->execute_loop(&expanded_query, open_cursor, packet, packet_end);
- error= stmt->execute(&expanded_query,
- test(flags & (ulong) CURSOR_TYPE_READ_ONLY));
- if (!(specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(), WAIT_PRIOR);
DBUG_VOID_RETURN;
-set_params_data_err:
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_execute");
- reset_stmt_params(stmt);
- DBUG_VOID_RETURN;
}
@@ -2415,24 +2506,8 @@ void mysql_sql_stmt_execute(THD *thd)
DBUG_PRINT("info",("stmt: 0x%lx", (long) 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;
-
- (void) stmt->execute(&expanded_query, FALSE);
-
- DBUG_VOID_RETURN;
+ (void) stmt->execute_loop(&expanded_query, FALSE, NULL, NULL);
-set_params_data_err:
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
- reset_stmt_params(stmt);
DBUG_VOID_RETURN;
}
@@ -2458,8 +2533,13 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
/* First of all clear possible warnings from the previous command */
mysql_reset_thd_for_next_command(thd);
status_var_increment(thd->status_var.com_stmt_fetch);
- if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch")))
+ if (!(stmt= find_prepared_statement(thd, stmt_id)))
+ {
+ char llbuf[22];
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf),
+ llstr(stmt_id, llbuf), "mysql_stmt_fetch");
DBUG_VOID_RETURN;
+ }
cursor= stmt->cursor;
if (!cursor)
@@ -2520,8 +2600,13 @@ void mysql_stmt_reset(THD *thd, char *packet)
mysql_reset_thd_for_next_command(thd);
status_var_increment(thd->status_var.com_stmt_reset);
- if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset")))
+ if (!(stmt= find_prepared_statement(thd, stmt_id)))
+ {
+ char llbuf[22];
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf),
+ llstr(stmt_id, llbuf), "mysql_stmt_reset");
DBUG_VOID_RETURN;
+ }
stmt->close_cursor();
@@ -2557,15 +2642,15 @@ void mysql_stmt_close(THD *thd, char *packet)
thd->main_da.disable_status();
- if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_close")))
+ if (!(stmt= find_prepared_statement(thd, stmt_id)))
DBUG_VOID_RETURN;
/*
The only way currently a statement can be deallocated when it's
in use is from within Dynamic SQL.
*/
- DBUG_ASSERT(! (stmt->flags & (uint) Prepared_statement::IS_IN_USE));
- (void) stmt->deallocate();
+ DBUG_ASSERT(! stmt->is_in_use());
+ stmt->deallocate();
general_log_print(thd, thd->command, NullS);
DBUG_VOID_RETURN;
@@ -2592,14 +2677,15 @@ void mysql_sql_stmt_close(THD *thd)
name->str));
if (! (stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
- {
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0),
name->length, name->str, "DEALLOCATE PREPARE");
- return;
- }
-
- if (stmt->deallocate() == 0)
+ else if (stmt->is_in_use())
+ my_error(ER_PS_NO_RECURSION, MYF(0));
+ else
+ {
+ stmt->deallocate();
my_ok(thd);
+ }
}
/**
@@ -2633,17 +2719,13 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
#ifndef EMBEDDED_LIBRARY
/* Minimal size of long data packet is 6 bytes */
if (packet_length < MYSQL_LONG_DATA_HEADER)
- {
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_send_long_data");
DBUG_VOID_RETURN;
- }
#endif
stmt_id= uint4korr(packet);
packet+= 4;
- if (!(stmt=find_prepared_statement(thd, stmt_id,
- "mysql_stmt_send_long_data")))
+ if (!(stmt=find_prepared_statement(thd, stmt_id)))
DBUG_VOID_RETURN;
param_number= uint2korr(packet);
@@ -2729,7 +2811,7 @@ Select_fetch_protocol_binary::send_data(List<Item> &fields)
****************************************************************************/
Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg)
- :Statement(&main_lex, &main_mem_root,
+ :Statement(NULL, &main_mem_root,
INITIALIZED, ++thd_arg->statement_id_counter),
thd(thd_arg),
result(thd_arg),
@@ -2800,7 +2882,11 @@ Prepared_statement::~Prepared_statement()
like Item_param, don't free everything until free_items()
*/
free_items();
- delete lex->result;
+ if (lex)
+ {
+ delete lex->result;
+ delete (st_lex_local *) lex;
+ }
free_root(&main_mem_root, MYF(0));
DBUG_VOID_RETURN;
}
@@ -2836,6 +2922,34 @@ bool Prepared_statement::set_name(LEX_STRING *name_arg)
return name.str == 0;
}
+
+/**
+ Remember the current database.
+
+ We must reset/restore the current database during execution of
+ a prepared statement since it affects execution environment:
+ privileges, @@character_set_database, and other.
+
+ @return Returns an error if out of memory.
+*/
+
+bool
+Prepared_statement::set_db(const char *db_arg, uint db_length_arg)
+{
+ /* Remember the current database. */
+ if (db_arg && db_length_arg)
+ {
+ db= this->strmake(db_arg, db_length_arg);
+ db_length= db_length_arg;
+ }
+ else
+ {
+ db= NULL;
+ db_length= 0;
+ }
+ return db_arg != NULL && db == NULL;
+}
+
/**************************************************************************
Common parts of mysql_[sql]_stmt_prepare, mysql_[sql]_stmt_execute.
Essentially, these functions do all the magic of preparing/executing
@@ -2877,6 +2991,12 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
*/
status_var_increment(thd->status_var.com_stmt_prepare);
+ if (! (lex= new (mem_root) st_lex_local))
+ DBUG_RETURN(TRUE);
+
+ if (set_db(thd->db, thd->db_length))
+ DBUG_RETURN(TRUE);
+
/*
alloc_query() uses thd->memroot && thd->query, so we should call
both of backup_statement() and backup_query_arena() here.
@@ -2904,19 +3024,6 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
lex->set_trg_event_type_for_tables();
- /* Remember the current database. */
-
- if (thd->db && thd->db_length)
- {
- db= this->strmake(thd->db, thd->db_length);
- db_length= thd->db_length;
- }
- else
- {
- db= NULL;
- db_length= 0;
- }
-
/*
While doing context analysis of the query (in check_prepared_statement)
we allocate a lot of additional memory: for open tables, JOINs, derived
@@ -2940,7 +3047,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
*/
if (error == 0)
- error= check_prepared_statement(this, name.str != 0);
+ error= check_prepared_statement(this);
/*
Currently CREATE PROCEDURE/TRIGGER/EVENT are prohibited in prepared
@@ -2987,6 +3094,306 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
DBUG_RETURN(error);
}
+
+/**
+ Assign parameter values either from variables, in case of SQL PS
+ or from the execute packet.
+
+ @param expanded_query a container with the original SQL statement.
+ '?' placeholders will be replaced with
+ their values in case of success.
+ The result is used for logging and replication
+ @param packet pointer to execute packet.
+ NULL in case of SQL PS
+ @param packet_end end of the packet. NULL in case of SQL PS
+
+ @todo Use a paremeter source class family instead of 'if's, and
+ support stored procedure variables.
+
+ @retval TRUE an error occurred when assigning a parameter (likely
+ a conversion error or out of memory, or malformed packet)
+ @retval FALSE success
+*/
+
+bool
+Prepared_statement::set_parameters(String *expanded_query,
+ uchar *packet, uchar *packet_end)
+{
+ bool is_sql_ps= packet == NULL;
+ bool res= FALSE;
+
+ if (is_sql_ps)
+ {
+ /* SQL prepared statement */
+ res= set_params_from_vars(this, thd->lex->prepared_stmt_params,
+ expanded_query);
+ }
+ else if (param_count)
+ {
+#ifndef EMBEDDED_LIBRARY
+ uchar *null_array= packet;
+ res= (setup_conversion_functions(this, &packet, packet_end) ||
+ set_params(this, null_array, packet, packet_end, expanded_query));
+#else
+ /*
+ In embedded library we re-install conversion routines each time
+ we set parameters, and also we don't need to parse packet.
+ So we do it in one function.
+ */
+ res= set_params_data(this, expanded_query);
+#endif
+ }
+ if (res)
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0),
+ is_sql_ps ? "EXECUTE" : "mysql_stmt_execute");
+ reset_stmt_params(this);
+ }
+ return res;
+}
+
+
+/**
+ Execute a prepared statement. Re-prepare it a limited number
+ of times if necessary.
+
+ Try to execute a prepared statement. If there is a metadata
+ validation error, prepare a new copy of the prepared statement,
+ swap the old and the new statements, and try again.
+ If there is a validation error again, repeat the above, but
+ perform no more than MAX_REPREPARE_ATTEMPTS.
+
+ @note We have to try several times in a loop since we
+ release metadata locks on tables after prepared statement
+ prepare. Therefore, a DDL statement may sneak in between prepare
+ and execute of a new statement. If this happens repeatedly
+ more than MAX_REPREPARE_ATTEMPTS times, we give up.
+
+ In future we need to be able to keep the metadata locks between
+ prepare and execute, but right now open_and_lock_tables(), as
+ well as close_thread_tables() are buried deep inside
+ execution code (mysql_execute_command()).
+
+ @return TRUE if an error, FALSE if success
+ @retval TRUE either MAX_REPREPARE_ATTEMPTS has been reached,
+ or some general error
+ @retval FALSE successfully executed the statement, perhaps
+ after having reprepared it a few times.
+*/
+
+bool
+Prepared_statement::execute_loop(String *expanded_query,
+ bool open_cursor,
+ uchar *packet,
+ uchar *packet_end)
+{
+ const int MAX_REPREPARE_ATTEMPTS= 3;
+ Reprepare_observer reprepare_observer;
+ bool error;
+ int reprepare_attempt= 0;
+
+ if (set_parameters(expanded_query, packet, packet_end))
+ return TRUE;
+
+reexecute:
+ reprepare_observer.reset_reprepare_observer();
+
+ /*
+ 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);
+
+ /*
+ Install the metadata observer. If some metadata version is
+ different from prepare time and an observer is installed,
+ the observer method will be invoked to push an error into
+ the error stack.
+ */
+ if (sql_command_flags[lex->sql_command] &
+ CF_REEXECUTION_FRAGILE)
+ {
+ DBUG_ASSERT(thd->m_reprepare_observer == NULL);
+ thd->m_reprepare_observer = &reprepare_observer;
+ }
+
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+
+ error= execute(expanded_query, open_cursor) || thd->is_error();
+
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(), WAIT_PRIOR);
+
+ thd->m_reprepare_observer= NULL;
+
+ if (error && !thd->is_fatal_error && !thd->killed &&
+ reprepare_observer.is_invalidated() &&
+ reprepare_attempt++ < MAX_REPREPARE_ATTEMPTS)
+ {
+ DBUG_ASSERT(thd->main_da.sql_errno() == ER_NEED_REPREPARE);
+ thd->clear_error();
+
+ error= reprepare();
+
+ if (! error) /* Success */
+ goto reexecute;
+ }
+ reset_stmt_params(this);
+
+ return error;
+}
+
+
+/**
+ Reprepare this prepared statement.
+
+ Currently this is implemented by creating a new prepared
+ statement, preparing it with the original query and then
+ swapping the new statement and the original one.
+
+ @retval TRUE an error occurred. Possible errors include
+ incompatibility of new and old result set
+ metadata
+ @retval FALSE success, the statement has been reprepared
+*/
+
+bool
+Prepared_statement::reprepare()
+{
+ char saved_cur_db_name_buf[NAME_LEN+1];
+ LEX_STRING saved_cur_db_name=
+ { saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
+ LEX_STRING stmt_db_name= { db, db_length };
+ bool cur_db_changed;
+ bool error;
+
+ Prepared_statement copy(thd, &thd->protocol_text);
+
+ status_var_increment(thd->status_var.com_stmt_reprepare);
+
+ if (mysql_opt_change_db(thd, &stmt_db_name, &saved_cur_db_name, TRUE,
+ &cur_db_changed))
+ return TRUE;
+
+ error= (name.str && copy.set_name(&name) ||
+ copy.prepare(query, query_length) ||
+ validate_metadata(&copy));
+
+ if (cur_db_changed)
+ mysql_change_db(thd, &saved_cur_db_name, TRUE);
+
+ if (! error)
+ {
+ swap_prepared_statement(&copy);
+ swap_parameter_array(param_array, copy.param_array, param_count);
+#ifndef DBUG_OFF
+ is_reprepared= TRUE;
+#endif
+ /*
+ Clear possible warnings during reprepare, it has to be completely
+ transparent to the user. We use mysql_reset_errors() since
+ there were no separate query id issued for re-prepare.
+ Sic: we can't simply silence warnings during reprepare, because if
+ it's failed, we need to return all the warnings to the user.
+ */
+ mysql_reset_errors(thd, TRUE);
+ }
+ return error;
+}
+
+
+/**
+ Validate statement result set metadata (if the statement returns
+ a result set).
+
+ Currently we only check that the number of columns of the result
+ set did not change.
+ This is a helper method used during re-prepare.
+
+ @param[in] copy the re-prepared prepared statement to verify
+ the metadata of
+
+ @retval TRUE error, ER_PS_NEED_REBIND is reported
+ @retval FALSE statement return no or compatible metadata
+*/
+
+
+bool Prepared_statement::validate_metadata(Prepared_statement *copy)
+{
+ /**
+ If this is an SQL prepared statement or EXPLAIN,
+ return FALSE -- the metadata of the original SELECT,
+ if any, has not been sent to the client.
+ */
+ if (is_protocol_text() || lex->describe)
+ return FALSE;
+
+ if (lex->select_lex.item_list.elements !=
+ copy->lex->select_lex.item_list.elements)
+ {
+ /** Column counts mismatch. */
+ my_error(ER_PS_REBIND, MYF(0));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Replace the original prepared statement with a prepared copy.
+
+ This is a private helper that is used as part of statement
+ reprepare
+
+ @return This function does not return any errors.
+*/
+
+void
+Prepared_statement::swap_prepared_statement(Prepared_statement *copy)
+{
+ Statement tmp_stmt;
+
+ /* Swap memory roots. */
+ swap_variables(MEM_ROOT, main_mem_root, copy->main_mem_root);
+
+ /* Swap the arenas */
+ tmp_stmt.set_query_arena(this);
+ set_query_arena(copy);
+ copy->set_query_arena(&tmp_stmt);
+
+ /* Swap the statement parent classes */
+ tmp_stmt.set_statement(this);
+ set_statement(copy);
+ copy->set_statement(&tmp_stmt);
+
+ /* Swap ids back, we need the original id */
+ swap_variables(ulong, id, copy->id);
+ /* Swap mem_roots back, they must continue pointing at the main_mem_roots */
+ swap_variables(MEM_ROOT *, mem_root, copy->mem_root);
+ /*
+ Swap the old and the new parameters array. The old array
+ is allocated in the old arena.
+ */
+ swap_variables(Item_param **, param_array, copy->param_array);
+ /* Swap flags: this is perhaps unnecessary */
+ swap_variables(uint, flags, copy->flags);
+ /* Swap names, the old name is allocated in the wrong memory root */
+ swap_variables(LEX_STRING, name, copy->name);
+ /* Ditto */
+ swap_variables(char *, db, copy->db);
+
+ DBUG_ASSERT(db_length == copy->db_length);
+ DBUG_ASSERT(param_count == copy->param_count);
+ DBUG_ASSERT(thd == copy->thd);
+ last_error[0]= '\0';
+ last_errno= 0;
+ /* Do not swap protocols, the copy always has protocol_text */
+}
+
+
/**
Execute a prepared statement.
@@ -3149,10 +3556,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
DBUG_ASSERT(! (error && cursor));
if (! cursor)
- {
cleanup_stmt();
- reset_stmt_params(this);
- }
thd->set_statement(&stmt_backup);
thd->stmt_arena= old_stmt_arena;
@@ -3186,16 +3590,10 @@ error:
/** Common part of DEALLOCATE PREPARE and mysql_stmt_close. */
-bool Prepared_statement::deallocate()
+void Prepared_statement::deallocate()
{
/* We account deallocate in the same manner as mysql_stmt_close */
status_var_increment(thd->status_var.com_stmt_close);
- if (flags & (uint) IS_IN_USE)
- {
- my_error(ER_PS_NO_RECURSION, MYF(0));
- return TRUE;
- }
/* Statement map calls delete stmt on erase */
thd->stmt_map.erase(this);
- return FALSE;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 3ef510b8d89..7c847e0817c 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4783,9 +4783,6 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
DBUG_ENTER("mysql_create_like_table");
- /* CREATE TABLE ... LIKE is not allowed for views. */
- src_table->required_type= FRMTYPE_TABLE;
-
/*
By opening source table we guarantee that it exists and no concurrent
DDL operation will mess with it. Later we also take an exclusive
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 9d6a2b1b8c8..bfb71db22da 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -853,8 +853,9 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
Item **conds, uint order_num, ORDER *order)
{
Item *fake_conds= 0;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
TABLE *table= table_list->table;
- TABLE_LIST tables;
+#endif
List<Item> all_fields;
SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_update");
@@ -878,9 +879,6 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
table_list->register_want_access(SELECT_ACL);
#endif
- bzero((char*) &tables,sizeof(tables)); // For ORDER BY
- tables.table= table;
- tables.alias= table_list->alias;
thd->lex->allow_sum_func= 0;
if (setup_tables_and_check_access(thd, &select_lex->context,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 25549936f5a..54399c3791c 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -3582,20 +3582,30 @@ create2:
| LIKE table_ident
{
THD *thd= YYTHD;
+ TABLE_LIST *src_table;
LEX *lex= thd->lex;
lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
- if (!lex->select_lex.add_table_to_list(thd, $2, NULL, 0, TL_READ))
+ src_table= lex->select_lex.add_table_to_list(thd, $2, NULL, 0,
+ TL_READ);
+ if (! src_table)
MYSQL_YYABORT;
+ /* CREATE TABLE ... LIKE is not allowed for views. */
+ src_table->required_type= FRMTYPE_TABLE;
}
| '(' LIKE table_ident ')'
{
THD *thd= YYTHD;
+ TABLE_LIST *src_table;
LEX *lex= thd->lex;
lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
- if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0, TL_READ))
+ src_table= lex->select_lex.add_table_to_list(thd, $3, NULL, 0,
+ TL_READ);
+ if (! src_table)
MYSQL_YYABORT;
+ /* CREATE TABLE ... LIKE is not allowed for views. */
+ src_table->required_type= FRMTYPE_TABLE;
}
;
diff --git a/sql/table.h b/sql/table.h
index 0e0a35b022d..75ddaf69c10 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -438,6 +438,105 @@ typedef struct st_table_share
return table_map_id;
}
+ /**
+ Convert unrelated members of TABLE_SHARE to one enum
+ representing its type.
+
+ @todo perhaps we need to have a member instead of a function.
+ */
+ enum enum_table_ref_type get_table_ref_type() const
+ {
+ if (is_view)
+ return TABLE_REF_VIEW;
+ switch (tmp_table) {
+ case NO_TMP_TABLE:
+ return TABLE_REF_BASE_TABLE;
+ case SYSTEM_TMP_TABLE:
+ return TABLE_REF_I_S_TABLE;
+ default:
+ return TABLE_REF_TMP_TABLE;
+ }
+ }
+ /**
+ Return a table metadata version.
+ * for base tables, we return table_map_id.
+ It is assigned from a global counter incremented for each
+ new table loaded into the table definition cache (TDC).
+ * for temporary tables it's table_map_id again. But for
+ temporary tables table_map_id is assigned from
+ thd->query_id. The latter is assigned from a thread local
+ counter incremented for every new SQL statement. Since
+ temporary tables are thread-local, each temporary table
+ gets a unique id.
+ * for everything else (views, information schema tables),
+ the version id is zero.
+
+ This choice of version id is a large compromise
+ to have a working prepared statement validation in 5.1. In
+ future version ids will be persistent, as described in WL#4180.
+
+ Let's try to explain why and how this limited solution allows
+ to validate prepared statements.
+
+ Firstly, sets (in mathematical sense) of version numbers
+ never intersect for different table types. Therefore,
+ version id of a temporary table is never compared with
+ a version id of a view, and vice versa.
+
+ Secondly, for base tables, we know that each DDL flushes the
+ respective share from the TDC. This ensures that whenever
+ a table is altered or dropped and recreated, it gets a new
+ version id.
+ Unfortunately, since elements of the TDC are also flushed on
+ LRU basis, this choice of version ids leads to false positives.
+ E.g. when the TDC size is too small, we may have a SELECT
+ * FROM INFORMATION_SCHEMA.TABLES flush all its elements, which
+ in turn will lead to a validation error and a subsequent
+ reprepare of all prepared statements. This is
+ considered acceptable, since as long as prepared statements are
+ automatically reprepared, spurious invalidation is only
+ a performance hit. Besides, no better simple solution exists.
+
+ For temporary tables, using thd->query_id ensures that if
+ a temporary table was altered or recreated, a new version id is
+ assigned. This suits validation needs very well and will perhaps
+ never change.
+
+ Metadata of information schema tables never changes.
+ Thus we can safely assume 0 for a good enough version id.
+
+ Views are a special and tricky case. A view is always inlined
+ into the parse tree of a prepared statement at prepare.
+ Thus, when we execute a prepared statement, the parse tree
+ will not get modified even if the view is replaced with another
+ view. Therefore, we can safely choose 0 for version id of
+ views and effectively never invalidate a prepared statement
+ when a view definition is altered. Note, that this leads to
+ wrong binary log in statement-based replication, since we log
+ prepared statement execution in form Query_log_events
+ containing conventional statements. But since there is no
+ metadata locking for views, the very same problem exists for
+ conventional statements alone, as reported in Bug#25144. The only
+ difference between prepared and conventional execution is,
+ effectively, that for prepared statements the race condition
+ window is much wider.
+ In 6.0 we plan to support view metadata locking (WL#3726) and
+ extend table definition cache to cache views (WL#4298).
+ When this is done, views will be handled in the same fashion
+ as the base tables.
+
+ Finally, by taking into account table type, we always
+ track that a change has taken place when a view is replaced
+ with a base table, a base table is replaced with a temporary
+ table and so on.
+
+ @sa TABLE_LIST::is_table_ref_id_equal()
+ */
+ ulong get_table_ref_version() const
+ {
+ return (tmp_table == SYSTEM_TMP_TABLE || is_view) ? 0 : table_map_id;
+ }
+
} TABLE_SHARE;
@@ -1233,6 +1332,33 @@ struct TABLE_LIST
child_def_version= ~0UL;
}
+ /**
+ Compare the version of metadata from the previous execution
+ (if any) with values obtained from the current table
+ definition cache element.
+
+ @sa check_and_update_table_version()
+ */
+ inline
+ bool is_table_ref_id_equal(TABLE_SHARE *s) const
+ {
+ return (m_table_ref_type == s->get_table_ref_type() &&
+ m_table_ref_version == s->get_table_ref_version());
+ }
+
+ /**
+ Record the value of metadata version of the corresponding
+ table definition cache element in this parse tree node.
+
+ @sa check_and_update_table_version()
+ */
+ inline
+ void set_table_ref_id(TABLE_SHARE *s)
+ {
+ m_table_ref_type= s->get_table_ref_type();
+ m_table_ref_version= s->get_table_ref_version();
+ }
+
private:
bool prep_check_option(THD *thd, uint8 check_opt_type);
bool prep_where(THD *thd, Item **conds, bool no_where_clause);
@@ -1243,6 +1369,10 @@ private:
/* Remembered MERGE child def version. See top comment in ha_myisammrg.cc */
ulong child_def_version;
+ /** See comments for set_metadata_id() */
+ enum enum_table_ref_type m_table_ref_type;
+ /** See comments for set_metadata_id() */
+ ulong m_table_ref_version;
};
class Item;
diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c
index bc4dcf0bdbb..2784861f48a 100644
--- a/storage/myisam/mi_create.c
+++ b/storage/myisam/mi_create.c
@@ -634,6 +634,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
my_printf_error(0, "MyISAM table '%s' is in use "
"(most likely by a MERGE table). Try FLUSH TABLES.",
MYF(0), name + dirname_length(name));
+ my_errno= HA_ERR_TABLE_EXIST;
goto err;
}
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 0df2d4ed4a5..350c14926cd 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -11132,7 +11132,7 @@ static void test_bug4236()
int rc;
MYSQL_STMT backup;
- myheader("test_bug4296");
+ myheader("test_bug4236");
stmt= mysql_stmt_init(mysql);
@@ -17383,6 +17383,124 @@ static void test_bug28386()
DBUG_VOID_RETURN;
}
+static void test_wl4166()
+{
+ MYSQL_STMT *stmt;
+ int int_data;
+ char str_data[50];
+ char tiny_data;
+ short small_data;
+ longlong big_data;
+ float real_data;
+ double double_data;
+ ulong length[7];
+ my_bool is_null[7];
+ MYSQL_BIND my_bind[7];
+ int rc;
+ int i;
+
+ myheader("test_wl4166");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS table_4166");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "CREATE TABLE table_4166(col1 tinyint NOT NULL, "
+ "col2 varchar(15), col3 int, "
+ "col4 smallint, col5 bigint, "
+ "col6 float, col7 double, "
+ "colX varchar(10) default NULL)");
+ myquery(rc);
+
+ stmt= mysql_simple_prepare(mysql,
+ "INSERT INTO table_4166(col1, col2, col3, col4, col5, col6, col7) "
+ "VALUES(?, ?, ?, ?, ?, ?, ?)");
+ check_stmt(stmt);
+
+ verify_param_count(stmt, 7);
+
+ bzero(my_bind, sizeof(my_bind));
+ /* tinyint */
+ my_bind[0].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[0].buffer= (void *)&tiny_data;
+ /* string */
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (void *)str_data;
+ my_bind[1].buffer_length= 1000; /* Max string length */
+ /* integer */
+ my_bind[2].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[2].buffer= (void *)&int_data;
+ /* short */
+ my_bind[3].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[3].buffer= (void *)&small_data;
+ /* bigint */
+ my_bind[4].buffer_type= MYSQL_TYPE_LONGLONG;
+ my_bind[4].buffer= (void *)&big_data;
+ /* float */
+ my_bind[5].buffer_type= MYSQL_TYPE_FLOAT;
+ my_bind[5].buffer= (void *)&real_data;
+ /* double */
+ my_bind[6].buffer_type= MYSQL_TYPE_DOUBLE;
+ my_bind[6].buffer= (void *)&double_data;
+
+ for (i= 0; i < (int) array_elements(my_bind); i++)
+ {
+ my_bind[i].length= &length[i];
+ my_bind[i].is_null= &is_null[i];
+ is_null[i]= 0;
+ }
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_execute(stmt, rc);
+
+ int_data= 320;
+ small_data= 1867;
+ big_data= 1000;
+ real_data= 2;
+ double_data= 6578.001;
+
+ /* now, execute the prepared statement to insert 10 records.. */
+ for (tiny_data= 0; tiny_data < 10; tiny_data++)
+ {
+ length[1]= my_sprintf(str_data, (str_data, "MySQL%d", int_data));
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ int_data += 25;
+ small_data += 10;
+ big_data += 100;
+ real_data += 1;
+ double_data += 10.09;
+ }
+
+ /* force a re-prepare with some DDL */
+
+ rc= mysql_query(mysql,
+ "ALTER TABLE table_4166 change colX colX varchar(20) default NULL");
+ myquery(rc);
+
+ /*
+ execute the prepared statement again,
+ without changing the types of parameters already bound.
+ */
+
+ for (tiny_data= 50; tiny_data < 60; tiny_data++)
+ {
+ length[1]= my_sprintf(str_data, (str_data, "MySQL%d", int_data));
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ int_data += 25;
+ small_data += 10;
+ big_data += 100;
+ real_data += 1;
+ double_data += 10.09;
+ }
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE table_4166");
+ myquery(rc);
+
+}
+
/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -17689,6 +17807,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug31418", test_bug31418 },
{ "test_bug31669", test_bug31669 },
{ "test_bug28386", test_bug28386 },
+ { "test_wl4166", test_wl4166 },
{ 0, 0 }
};