mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
WL#4165 "Prepared statements: validation".
Add metadata validation to ~20 more SQL commands. Make sure that these commands actually work in ps-protocol, since until now they were enabled, but not carefully tested. Fixes the ml003 bug found by Matthias during internal testing of the patch.
This commit is contained in:
@ -663,6 +663,8 @@ a b c
|
||||
# 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 30
|
||||
@ -1497,6 +1499,541 @@ 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.
|
||||
=====================================================================
|
||||
drop table if exists t1;
|
||||
create table t1 (a int);
|
||||
#
|
||||
# SQLCOM_SELECT
|
||||
#
|
||||
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;
|
||||
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;
|
||||
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 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;
|
||||
|
@ -614,6 +614,8 @@ select * from t1;
|
||||
--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;
|
||||
call p_verify_reprepare_count(0);
|
||||
flush table t2;
|
||||
@ -1347,6 +1349,588 @@ drop procedure p_12093;
|
||||
deallocate prepare stmt_sf;
|
||||
deallocate prepare stmt_sp;
|
||||
|
||||
|
||||
--echo =====================================================================
|
||||
--echo Ensure that metadata validation is performed for every type of
|
||||
--echo SQL statement where it is needed.
|
||||
--echo =====================================================================
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
create table t1 (a int);
|
||||
--echo #
|
||||
--echo # SQLCOM_SELECT
|
||||
--echo #
|
||||
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);
|
||||
--echo #
|
||||
--echo # SQLCOM_CREATE_TABLE
|
||||
--echo #
|
||||
--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);
|
||||
--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;
|
||||
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;
|
||||
drop table t1;
|
||||
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;
|
||||
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;
|
||||
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 table t2;
|
||||
deallocate prepare stmt;
|
||||
|
||||
--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;
|
||||
drop table t1;
|
||||
create table t1 (x int);
|
||||
execute stmt;
|
||||
drop table t1, t2;
|
||||
deallocate prepare stmt;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_INSERT
|
||||
--echo #
|
||||
|
||||
--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;
|
||||
|
||||
drop table t1, t2;
|
||||
deallocate prepare stmt;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_INSERT_SELECT
|
||||
--echo #
|
||||
|
||||
--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 select * from t1";
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
create table t1 (x int);
|
||||
execute stmt;
|
||||
drop table t1, t2;
|
||||
deallocate prepare stmt;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_REPLACE
|
||||
--echo #
|
||||
|
||||
--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;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_REPLACE_SELECT
|
||||
--echo #
|
||||
|
||||
--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;
|
||||
|
||||
--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;
|
||||
|
||||
--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;
|
||||
drop table t1;
|
||||
create table t1 (x int);
|
||||
execute stmt;
|
||||
drop table t1, t2, t3;
|
||||
deallocate prepare stmt;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_UPDATE_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 "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);
|
||||
|
||||
--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;
|
||||
|
||||
--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;
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_SHOW_FIELDS
|
||||
--echo #
|
||||
|
||||
--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;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_SHOW_KEYS
|
||||
--echo #
|
||||
|
||||
--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;
|
||||
drop table t1;
|
||||
create table t1 (x int);
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
|
||||
--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;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_SHOW_STATUS
|
||||
--echo #
|
||||
|
||||
--disable_warnings
|
||||
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;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_SHOW_ENGINE_STATUS, SQLCOM_SHOW_ENGINE_LOGS,
|
||||
--echo # SQLCOM_SHOW_ENGINE_MUTEX, SQLCOM_SHOW_PROCESSLIST
|
||||
--echo #
|
||||
|
||||
--echo # Currently can not have a where clause, need to be covered
|
||||
--echo # with tests
|
||||
|
||||
--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 #
|
||||
|
||||
--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;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_SHOW_COLLATIONS
|
||||
--echo #
|
||||
|
||||
--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;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_SHOW_TABLE_STATUS
|
||||
--echo #
|
||||
|
||||
--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;
|
||||
drop table t1;
|
||||
create table t1 (x int);
|
||||
execute stmt;
|
||||
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;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_SHOW_OPEN_TABLES
|
||||
--echo #
|
||||
|
||||
--disable_warnings
|
||||
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;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_SHOW_STATUS_PROC
|
||||
--echo #
|
||||
|
||||
--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;
|
||||
|
||||
--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;
|
||||
drop table t1;
|
||||
create table t1 (x int);
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
|
||||
--echo #
|
||||
--echo # SQLCOM_SHOW_EVENTS
|
||||
--echo #
|
||||
|
||||
--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;
|
||||
drop table t1;
|
||||
create table t1 (x int);
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
|
||||
--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;
|
||||
drop table t1;
|
||||
create table t1 (x int);
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
|
||||
--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;
|
||||
|
||||
--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;
|
||||
drop table t1;
|
||||
create table t1 (x int);
|
||||
execute stmt;
|
||||
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;
|
||||
--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
|
||||
|
@ -695,7 +695,7 @@ const char *set_thd_proc_info(THD *thd, const char *info,
|
||||
prepare matches the type of the object we obtained from the
|
||||
table definition cache.
|
||||
|
||||
@sa check_and_update_metadata_version()
|
||||
@sa check_and_update_table_version()
|
||||
@sa Execute_observer
|
||||
@sa Prepared_statement::reprepare()
|
||||
*/
|
||||
|
@ -1068,6 +1068,7 @@ sp_head::execute(THD *thd)
|
||||
LEX *old_lex;
|
||||
Item_change_list old_change_list;
|
||||
String old_packet;
|
||||
Metadata_version_observer *save_metadata_observer= thd->m_metadata_observer;
|
||||
|
||||
Object_creation_ctx *saved_creation_ctx;
|
||||
|
||||
@ -1135,6 +1136,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_metadata_observer= 0;
|
||||
|
||||
/*
|
||||
It is also more efficient to save/restore current thd->lex once when
|
||||
@ -1297,6 +1317,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_metadata_observer= save_metadata_observer;
|
||||
|
||||
thd->stmt_arena= old_arena;
|
||||
state= EXECUTED;
|
||||
|
@ -2876,7 +2876,6 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
||||
first_successful_insert_id_in_prev_stmt;
|
||||
backup->first_successful_insert_id_in_cur_stmt=
|
||||
first_successful_insert_id_in_cur_stmt;
|
||||
backup->m_metadata_observer= m_metadata_observer;
|
||||
|
||||
if ((!lex->requires_prelocking() || is_update_query(lex->sql_command)) &&
|
||||
!current_stmt_binlog_row_based)
|
||||
@ -2896,7 +2895,6 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
||||
cuted_fields= 0;
|
||||
transaction.savepoints= 0;
|
||||
first_successful_insert_id_in_cur_stmt= 0;
|
||||
m_metadata_observer= 0;
|
||||
}
|
||||
|
||||
|
||||
@ -2945,7 +2943,6 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup)
|
||||
*/
|
||||
examined_row_count+= backup->examined_row_count;
|
||||
cuted_fields+= backup->cuted_fields;
|
||||
m_metadata_observer= backup->m_metadata_observer;
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
||||
At most 1 instance of this class is active at a time, in which
|
||||
case THD::m_metadata_observer is not NULL.
|
||||
|
||||
@sa check_and_update_metadata_version() for details of the
|
||||
@sa check_and_update_table_version() for details of the
|
||||
version tracking algorithm
|
||||
|
||||
@sa Execute_observer for details of how we detect that
|
||||
@ -847,7 +847,7 @@ public:
|
||||
to avoid spurious ER_NEED_REPREPARE errors -- system and
|
||||
INFORMATION_SCHEMA tables are not subject to metadata version
|
||||
tracking.
|
||||
@sa check_and_update_metadata_version()
|
||||
@sa check_and_update_table_version()
|
||||
*/
|
||||
Metadata_version_observer *m_metadata_observer;
|
||||
|
||||
@ -983,25 +983,6 @@ public:
|
||||
bool enable_slow_log;
|
||||
bool last_insert_id_used;
|
||||
SAVEPOINT *savepoints;
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
Metadata_version_observer *m_metadata_observer;
|
||||
};
|
||||
|
||||
|
||||
|
@ -200,19 +200,19 @@ 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;
|
||||
@ -235,19 +235,21 @@ void init_update_queries(void)
|
||||
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;
|
||||
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_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;
|
||||
@ -271,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;
|
||||
@ -279,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
|
||||
@ -289,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;
|
||||
|
||||
/*
|
||||
|
@ -1480,6 +1480,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.
|
||||
|
||||
@ -1601,6 +1638,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);
|
||||
@ -1838,7 +1886,21 @@ 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);
|
||||
if (res == 2)
|
||||
@ -1863,6 +1925,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;
|
||||
@ -1912,7 +1977,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:
|
||||
@ -3064,6 +3128,26 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
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)
|
||||
|
@ -1336,7 +1336,7 @@ struct TABLE_LIST
|
||||
(if any) with values obtained from the current table
|
||||
definition cache element.
|
||||
|
||||
@sa check_and_update_metadata_version()
|
||||
@sa check_and_update_table_version()
|
||||
*/
|
||||
inline
|
||||
bool is_metadata_version_equal(TABLE_SHARE *s) const
|
||||
@ -1349,7 +1349,7 @@ struct TABLE_LIST
|
||||
Record the value of metadata version of the corresponding
|
||||
table definition cache element in this parse tree node.
|
||||
|
||||
@sa check_and_update_metadata_version()
|
||||
@sa check_and_update_table_version()
|
||||
*/
|
||||
inline
|
||||
void set_metadata_version(TABLE_SHARE *s)
|
||||
|
Reference in New Issue
Block a user