MDEV-10585 EXECUTE IMMEDIATE statement
This commit is contained in:
parent
4c45b820aa
commit
e1a212ebbc
@ -6222,5 +6222,15 @@ DROP TABLE t1;
|
||||
#
|
||||
SET STORAGE_ENGINE=Default;
|
||||
#
|
||||
# MDEV-10585 EXECUTE IMMEDIATE statement
|
||||
#
|
||||
SET character_set_connection=ucs2;
|
||||
EXECUTE IMMEDIATE 'SELECT COLLATION("a")';
|
||||
COLLATION("a")
|
||||
ucs2_general_ci
|
||||
SET @stmt='SELECT COLLATION("a")';
|
||||
EXECUTE IMMEDIATE @stmt;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
|
||||
#
|
||||
# End of 10.2 tests
|
||||
#
|
||||
|
@ -275,3 +275,8 @@ set option=1;
|
||||
ERROR HY000: Unknown system variable 'option'
|
||||
set option option=1;
|
||||
ERROR HY000: Unknown system variable 'option'
|
||||
#
|
||||
# MDEV-10585 EXECUTE IMMEDIATE statement
|
||||
#
|
||||
CREATE TABLE immediate (immediate int);
|
||||
DROP TABLE immediate;
|
||||
|
@ -1374,7 +1374,7 @@ performance-schema-max-rwlock-instances -1
|
||||
performance-schema-max-socket-classes 10
|
||||
performance-schema-max-socket-instances -1
|
||||
performance-schema-max-stage-classes 150
|
||||
performance-schema-max-statement-classes 184
|
||||
performance-schema-max-statement-classes 185
|
||||
performance-schema-max-table-handles -1
|
||||
performance-schema-max-table-instances -1
|
||||
performance-schema-max-thread-classes 50
|
||||
|
@ -4289,5 +4289,218 @@ DROP TABLE t1;
|
||||
# End of MDEV-10709 Expressions as parameters to Dynamic SQL
|
||||
#
|
||||
#
|
||||
# MDEV-10585 EXECUTE IMMEDIATE statement
|
||||
#
|
||||
EXECUTE IMMEDIATE 'SELECT 1 AS a';
|
||||
a
|
||||
1
|
||||
SET @a=10;
|
||||
EXECUTE IMMEDIATE 'SELECT ? AS a' USING @a;
|
||||
a
|
||||
10
|
||||
EXECUTE IMMEDIATE 'SELECT ? AS a' USING 20;
|
||||
a
|
||||
20
|
||||
#
|
||||
# Erroneous queries
|
||||
#
|
||||
EXECUTE IMMEDIATE 'xxx';
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'xxx' at line 1
|
||||
EXECUTE IMMEDIATE 'SELECT 1' USING @a;
|
||||
ERROR HY000: Incorrect arguments to EXECUTE
|
||||
EXECUTE IMMEDIATE 'SELECT ?';
|
||||
ERROR HY000: Incorrect arguments to EXECUTE
|
||||
EXECUTE IMMEDIATE 'EXECUTE IMMEDIATE "SELECT 1"';
|
||||
ERROR HY000: This command is not supported in the prepared statement protocol yet
|
||||
EXECUTE IMMEDIATE 'PREPARE stmt FROM "SELECT 1"';
|
||||
ERROR HY000: This command is not supported in the prepared statement protocol yet
|
||||
EXECUTE IMMEDIATE 'EXECUTE stmt';
|
||||
ERROR HY000: This command is not supported in the prepared statement protocol yet
|
||||
EXECUTE IMMEDIATE 'DEALLOCATE PREPARE stmt';
|
||||
ERROR HY000: This command is not supported in the prepared statement protocol yet
|
||||
EXECUTE IMMEDIATE 'SELECT ?' USING _latin1'a'=_latin2'a';
|
||||
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation '='
|
||||
EXECUTE IMMEDIATE 'SELECT ?' USING ROW(1,2);
|
||||
ERROR 21000: Operand should contain 1 column(s)
|
||||
#
|
||||
# Testing disallowed expressions in USING
|
||||
#
|
||||
EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING (SELECT 1);
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)' at line 1
|
||||
CREATE FUNCTION f1() RETURNS VARCHAR(10) RETURN 'test';
|
||||
EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING f1();
|
||||
ERROR 42000: EXECUTE..USING does not support subqueries or stored functions
|
||||
DROP FUNCTION f1;
|
||||
#
|
||||
# DDL
|
||||
#
|
||||
EXECUTE IMMEDIATE 'CREATE TABLE t1 (a INT)';
|
||||
EXECUTE IMMEDIATE 'SHOW CREATE TABLE t1';
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
EXECUTE IMMEDIATE 'DROP TABLE t1';
|
||||
SET @stmt= 'CREATE TABLE t1 (a INT)';
|
||||
EXECUTE IMMEDIATE @stmt;
|
||||
SET @stmt= 'SHOW CREATE TABLE t1';
|
||||
EXECUTE IMMEDIATE @stmt;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
SET @stmt= 'DROP TABLE t1';
|
||||
EXECUTE IMMEDIATE @stmt;
|
||||
#
|
||||
# DDL with parameters
|
||||
#
|
||||
SET @a= 10, @b= 10.1, @c= 10e0, @d='str';
|
||||
EXECUTE IMMEDIATE
|
||||
'CREATE TABLE t1 AS SELECT ? AS a,? AS b,? AS c,? AS d'
|
||||
USING @a,@b,@c,@d;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` bigint(21) NOT NULL,
|
||||
`b` decimal(3,1) DEFAULT NULL,
|
||||
`c` double NOT NULL,
|
||||
`d` varchar(3) NOT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
EXECUTE IMMEDIATE
|
||||
'CREATE TABLE t1 AS SELECT ? AS a,? AS b,? AS c,? AS d'
|
||||
USING 10, 10.1, 10e0, 'str';
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` bigint(21) NOT NULL,
|
||||
`b` decimal(3,1) DEFAULT NULL,
|
||||
`c` double NOT NULL,
|
||||
`d` varchar(3) NOT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
EXECUTE IMMEDIATE
|
||||
'CREATE TABLE t1 AS SELECT ? AS t1,? AS t2, ? AS d1,? AS dt1, ? AS dt2'
|
||||
USING TIME'10:20:30',
|
||||
TIME'10:20:30.123',
|
||||
DATE'2001-01-01',
|
||||
TIMESTAMP'2001-01-01 10:20:30',
|
||||
TIMESTAMP'2001-01-01 10:20:30.123';
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`t1` time DEFAULT NULL,
|
||||
`t2` time(3) DEFAULT NULL,
|
||||
`d1` date DEFAULT NULL,
|
||||
`dt1` datetime DEFAULT NULL,
|
||||
`dt2` datetime(3) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Using a user variable as an EXECUTE IMMEDIATE..USING out parameter
|
||||
#
|
||||
CREATE PROCEDURE p1(OUT a INT)
|
||||
BEGIN
|
||||
SET a:= 10;
|
||||
END;
|
||||
/
|
||||
SET @a=1;
|
||||
CALL p1(@a);
|
||||
SELECT @a;
|
||||
@a
|
||||
10
|
||||
SET @a=2;
|
||||
EXECUTE IMMEDIATE 'CALL p1(?)' USING @a;
|
||||
SELECT @a;
|
||||
@a
|
||||
10
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# Using an SP variable as an EXECUTE IMMEDIATE..USING out parameter
|
||||
#
|
||||
CREATE PROCEDURE p1 (OUT a INT)
|
||||
BEGIN
|
||||
SET a=10;
|
||||
END;
|
||||
/
|
||||
CREATE PROCEDURE p2 (OUT a INT)
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE 'CALL p1(?)' USING a;
|
||||
END;
|
||||
/
|
||||
SET @a= 1;
|
||||
CALL p2(@a);
|
||||
SELECT @a;
|
||||
@a
|
||||
10
|
||||
DROP PROCEDURE p2;
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# Changing user variables
|
||||
#
|
||||
SET @a=10;
|
||||
EXECUTE IMMEDIATE 'SET @a=@a+1';
|
||||
SELECT @a;
|
||||
@a
|
||||
11
|
||||
#
|
||||
# SET STATEMENT
|
||||
#
|
||||
SET @@max_sort_length=1024;
|
||||
EXECUTE IMMEDIATE 'SET STATEMENT max_sort_length=1025 FOR SELECT @@max_sort_length';
|
||||
@@max_sort_length
|
||||
1025
|
||||
SELECT @@max_sort_length;
|
||||
@@max_sort_length
|
||||
1024
|
||||
SET @@max_sort_length=DEFAULT;
|
||||
#
|
||||
# Similar to prepared EXECUTE, IMMEDIATE is not allowed in stored functions
|
||||
#
|
||||
CREATE FUNCTION f1() RETURNS INT
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE 'DO 1';
|
||||
RETURN 1;
|
||||
END;
|
||||
$$
|
||||
ERROR 0A000: Dynamic SQL is not allowed in stored function or trigger
|
||||
#
|
||||
# Status variables
|
||||
#
|
||||
CREATE FUNCTION get_status_var(name TEXT) RETURNS INT
|
||||
RETURN (SELECT CAST(VARIABLE_VALUE AS INT)
|
||||
FROM INFORMATION_SCHEMA.SESSION_STATUS
|
||||
WHERE VARIABLE_NAME=name);
|
||||
CREATE PROCEDURE test_status_var(name TEXT)
|
||||
BEGIN
|
||||
SET @cnt0=get_status_var(name);
|
||||
EXECUTE IMMEDIATE 'DO 1';
|
||||
SET @cnt1=get_status_var(name);
|
||||
SELECT @cnt1-@cnt0 AS increment;
|
||||
END;
|
||||
$$
|
||||
# Note, EXECUTE IMMEDIATE does not increment COM_EXECUTE_SQL
|
||||
# It increments COM_EXECUTE_IMMEDIATE instead.
|
||||
CALL test_status_var('COM_EXECUTE_SQL');
|
||||
increment
|
||||
0
|
||||
CALL test_status_var('COM_EXECUTE_IMMEDIATE');
|
||||
increment
|
||||
1
|
||||
CALL test_status_var('COM_STMT_PREPARE');
|
||||
increment
|
||||
1
|
||||
CALL test_status_var('COM_STMT_EXECUTE');
|
||||
increment
|
||||
1
|
||||
CALL test_status_var('COM_STMT_CLOSE');
|
||||
increment
|
||||
1
|
||||
DROP PROCEDURE test_status_var;
|
||||
DROP FUNCTION get_status_var;
|
||||
#
|
||||
# End of MDEV-10585 EXECUTE IMMEDIATE statement
|
||||
#
|
||||
#
|
||||
# End of 10.2 tests
|
||||
#
|
||||
|
@ -103,3 +103,29 @@ master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (TIMESTAMP'2001-
|
||||
master-bin.000002 # Query # # COMMIT
|
||||
DROP TABLE t1;
|
||||
SET TIMESTAMP=DEFAULT;
|
||||
#
|
||||
# MDEV-10585 EXECUTE IMMEDIATE statement
|
||||
#
|
||||
FLUSH LOGS;
|
||||
CREATE TABLE t1 (a INT);
|
||||
EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (101)';
|
||||
SET @a=102;
|
||||
EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (?)' USING @a;
|
||||
SET @a=103;
|
||||
SET @stmt='INSERT INTO t1 VALUES (?)';
|
||||
EXECUTE IMMEDIATE @stmt USING @a;
|
||||
include/show_binlog_events.inc
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000003 # Binlog_checkpoint # # master-bin.000003
|
||||
master-bin.000003 # Gtid # # GTID #-#-#
|
||||
master-bin.000003 # Query # # use `test`; CREATE TABLE t1 (a INT)
|
||||
master-bin.000003 # Gtid # # BEGIN GTID #-#-#
|
||||
master-bin.000003 # Query # # use `test`; INSERT INTO t1 VALUES (101)
|
||||
master-bin.000003 # Query # # COMMIT
|
||||
master-bin.000003 # Gtid # # BEGIN GTID #-#-#
|
||||
master-bin.000003 # Query # # use `test`; INSERT INTO t1 VALUES (102)
|
||||
master-bin.000003 # Query # # COMMIT
|
||||
master-bin.000003 # Gtid # # BEGIN GTID #-#-#
|
||||
master-bin.000003 # Query # # use `test`; INSERT INTO t1 VALUES (103)
|
||||
master-bin.000003 # Query # # COMMIT
|
||||
DROP TABLE t1;
|
||||
|
@ -54,3 +54,19 @@ SELECT * FROM t1;
|
||||
source include/show_binlog_events.inc;
|
||||
DROP TABLE t1;
|
||||
SET TIMESTAMP=DEFAULT;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-10585 EXECUTE IMMEDIATE statement
|
||||
--echo #
|
||||
|
||||
FLUSH LOGS;
|
||||
CREATE TABLE t1 (a INT);
|
||||
EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (101)';
|
||||
SET @a=102;
|
||||
EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES (?)' USING @a;
|
||||
SET @a=103;
|
||||
SET @stmt='INSERT INTO t1 VALUES (?)';
|
||||
EXECUTE IMMEDIATE @stmt USING @a;
|
||||
--let $binlog_file = LAST
|
||||
source include/show_binlog_events.inc;
|
||||
DROP TABLE t1;
|
||||
|
@ -3021,9 +3021,9 @@ READ_ONLY YES
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES
|
||||
SESSION_VALUE NULL
|
||||
GLOBAL_VALUE 184
|
||||
GLOBAL_VALUE 185
|
||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||
DEFAULT_VALUE 184
|
||||
DEFAULT_VALUE 185
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
VARIABLE_COMMENT Maximum number of statement instruments.
|
||||
|
@ -974,6 +974,18 @@ let $coll='ucs2_nopad_bin';
|
||||
let $coll_pad='ucs2_bin';
|
||||
--source include/ctype_pad_all_engines.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-10585 EXECUTE IMMEDIATE statement
|
||||
--echo #
|
||||
SET character_set_connection=ucs2;
|
||||
EXECUTE IMMEDIATE 'SELECT COLLATION("a")';
|
||||
|
||||
# We don't support character sets with mbminlen>1 in the parser yet
|
||||
# Returning "syntax error" is fine
|
||||
SET @stmt='SELECT COLLATION("a")';
|
||||
--error ER_PARSE_ERROR
|
||||
EXECUTE IMMEDIATE @stmt;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.2 tests
|
||||
--echo #
|
||||
|
@ -173,3 +173,10 @@ drop table option;
|
||||
set option=1;
|
||||
--error 1193
|
||||
set option option=1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-10585 EXECUTE IMMEDIATE statement
|
||||
--echo #
|
||||
|
||||
CREATE TABLE immediate (immediate int);
|
||||
DROP TABLE immediate;
|
||||
|
@ -3840,6 +3840,211 @@ DROP TABLE t1;
|
||||
--echo # End of MDEV-10709 Expressions as parameters to Dynamic SQL
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-10585 EXECUTE IMMEDIATE statement
|
||||
--echo #
|
||||
|
||||
EXECUTE IMMEDIATE 'SELECT 1 AS a';
|
||||
SET @a=10;
|
||||
EXECUTE IMMEDIATE 'SELECT ? AS a' USING @a;
|
||||
EXECUTE IMMEDIATE 'SELECT ? AS a' USING 20;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Erroneous queries
|
||||
--echo #
|
||||
|
||||
--error ER_PARSE_ERROR
|
||||
EXECUTE IMMEDIATE 'xxx';
|
||||
|
||||
--error ER_WRONG_ARGUMENTS
|
||||
EXECUTE IMMEDIATE 'SELECT 1' USING @a;
|
||||
|
||||
--error ER_WRONG_ARGUMENTS
|
||||
EXECUTE IMMEDIATE 'SELECT ?';
|
||||
|
||||
--error ER_UNSUPPORTED_PS
|
||||
EXECUTE IMMEDIATE 'EXECUTE IMMEDIATE "SELECT 1"';
|
||||
|
||||
--error ER_UNSUPPORTED_PS
|
||||
EXECUTE IMMEDIATE 'PREPARE stmt FROM "SELECT 1"';
|
||||
|
||||
--error ER_UNSUPPORTED_PS
|
||||
EXECUTE IMMEDIATE 'EXECUTE stmt';
|
||||
|
||||
--error ER_UNSUPPORTED_PS
|
||||
EXECUTE IMMEDIATE 'DEALLOCATE PREPARE stmt';
|
||||
|
||||
--error ER_CANT_AGGREGATE_2COLLATIONS
|
||||
EXECUTE IMMEDIATE 'SELECT ?' USING _latin1'a'=_latin2'a';
|
||||
|
||||
--error ER_OPERAND_COLUMNS
|
||||
EXECUTE IMMEDIATE 'SELECT ?' USING ROW(1,2);
|
||||
|
||||
--echo #
|
||||
--echo # Testing disallowed expressions in USING
|
||||
--echo #
|
||||
|
||||
--error ER_PARSE_ERROR
|
||||
EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING (SELECT 1);
|
||||
|
||||
CREATE FUNCTION f1() RETURNS VARCHAR(10) RETURN 'test';
|
||||
--error ER_SUBQUERIES_NOT_SUPPORTED
|
||||
EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING f1();
|
||||
DROP FUNCTION f1;
|
||||
|
||||
--echo #
|
||||
--echo # DDL
|
||||
--echo #
|
||||
|
||||
EXECUTE IMMEDIATE 'CREATE TABLE t1 (a INT)';
|
||||
EXECUTE IMMEDIATE 'SHOW CREATE TABLE t1';
|
||||
EXECUTE IMMEDIATE 'DROP TABLE t1';
|
||||
|
||||
SET @stmt= 'CREATE TABLE t1 (a INT)';
|
||||
EXECUTE IMMEDIATE @stmt;
|
||||
SET @stmt= 'SHOW CREATE TABLE t1';
|
||||
EXECUTE IMMEDIATE @stmt;
|
||||
SET @stmt= 'DROP TABLE t1';
|
||||
EXECUTE IMMEDIATE @stmt;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # DDL with parameters
|
||||
--echo #
|
||||
|
||||
SET @a= 10, @b= 10.1, @c= 10e0, @d='str';
|
||||
EXECUTE IMMEDIATE
|
||||
'CREATE TABLE t1 AS SELECT ? AS a,? AS b,? AS c,? AS d'
|
||||
USING @a,@b,@c,@d;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
EXECUTE IMMEDIATE
|
||||
'CREATE TABLE t1 AS SELECT ? AS a,? AS b,? AS c,? AS d'
|
||||
USING 10, 10.1, 10e0, 'str';
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
EXECUTE IMMEDIATE
|
||||
'CREATE TABLE t1 AS SELECT ? AS t1,? AS t2, ? AS d1,? AS dt1, ? AS dt2'
|
||||
USING TIME'10:20:30',
|
||||
TIME'10:20:30.123',
|
||||
DATE'2001-01-01',
|
||||
TIMESTAMP'2001-01-01 10:20:30',
|
||||
TIMESTAMP'2001-01-01 10:20:30.123';
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Using a user variable as an EXECUTE IMMEDIATE..USING out parameter
|
||||
--echo #
|
||||
|
||||
DELIMITER /;
|
||||
CREATE PROCEDURE p1(OUT a INT)
|
||||
BEGIN
|
||||
SET a:= 10;
|
||||
END;
|
||||
/
|
||||
DELIMITER ;/
|
||||
SET @a=1;
|
||||
CALL p1(@a);
|
||||
SELECT @a;
|
||||
SET @a=2;
|
||||
EXECUTE IMMEDIATE 'CALL p1(?)' USING @a;
|
||||
SELECT @a;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Using an SP variable as an EXECUTE IMMEDIATE..USING out parameter
|
||||
--echo #
|
||||
|
||||
DELIMITER /;
|
||||
CREATE PROCEDURE p1 (OUT a INT)
|
||||
BEGIN
|
||||
SET a=10;
|
||||
END;
|
||||
/
|
||||
CREATE PROCEDURE p2 (OUT a INT)
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE 'CALL p1(?)' USING a;
|
||||
END;
|
||||
/
|
||||
DELIMITER ;/
|
||||
SET @a= 1;
|
||||
CALL p2(@a);
|
||||
SELECT @a;
|
||||
DROP PROCEDURE p2;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Changing user variables
|
||||
--echo #
|
||||
|
||||
SET @a=10;
|
||||
EXECUTE IMMEDIATE 'SET @a=@a+1';
|
||||
SELECT @a;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # SET STATEMENT
|
||||
--echo #
|
||||
|
||||
SET @@max_sort_length=1024;
|
||||
EXECUTE IMMEDIATE 'SET STATEMENT max_sort_length=1025 FOR SELECT @@max_sort_length';
|
||||
SELECT @@max_sort_length;
|
||||
SET @@max_sort_length=DEFAULT;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Similar to prepared EXECUTE, IMMEDIATE is not allowed in stored functions
|
||||
--echo #
|
||||
DELIMITER $$;
|
||||
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
|
||||
CREATE FUNCTION f1() RETURNS INT
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE 'DO 1';
|
||||
RETURN 1;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Status variables
|
||||
--echo #
|
||||
CREATE FUNCTION get_status_var(name TEXT) RETURNS INT
|
||||
RETURN (SELECT CAST(VARIABLE_VALUE AS INT)
|
||||
FROM INFORMATION_SCHEMA.SESSION_STATUS
|
||||
WHERE VARIABLE_NAME=name);
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE test_status_var(name TEXT)
|
||||
BEGIN
|
||||
SET @cnt0=get_status_var(name);
|
||||
EXECUTE IMMEDIATE 'DO 1';
|
||||
SET @cnt1=get_status_var(name);
|
||||
SELECT @cnt1-@cnt0 AS increment;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
--echo # Note, EXECUTE IMMEDIATE does not increment COM_EXECUTE_SQL
|
||||
--echo # It increments COM_EXECUTE_IMMEDIATE instead.
|
||||
CALL test_status_var('COM_EXECUTE_SQL');
|
||||
CALL test_status_var('COM_EXECUTE_IMMEDIATE');
|
||||
CALL test_status_var('COM_STMT_PREPARE');
|
||||
CALL test_status_var('COM_STMT_EXECUTE');
|
||||
CALL test_status_var('COM_STMT_CLOSE');
|
||||
|
||||
DROP PROCEDURE test_status_var;
|
||||
DROP FUNCTION get_status_var;
|
||||
|
||||
--echo #
|
||||
--echo # End of MDEV-10585 EXECUTE IMMEDIATE statement
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.2 tests
|
||||
--echo #
|
||||
|
@ -278,6 +278,7 @@ static SYMBOL symbols[] = {
|
||||
{ "IGNORE", SYM(IGNORE_SYM)},
|
||||
{ "IGNORE_DOMAIN_IDS", SYM(IGNORE_DOMAIN_IDS_SYM)},
|
||||
{ "IGNORE_SERVER_IDS", SYM(IGNORE_SERVER_IDS_SYM)},
|
||||
{ "IMMEDIATE", SYM(IMMEDIATE_SYM)},
|
||||
{ "IMPORT", SYM(IMPORT)},
|
||||
{ "IN", SYM(IN_SYM)},
|
||||
{ "INDEX", SYM(INDEX_SYM)},
|
||||
|
@ -3886,6 +3886,7 @@ SHOW_VAR com_status_vars[]= {
|
||||
{"drop_user", STMT_STATUS(SQLCOM_DROP_USER)},
|
||||
{"drop_view", STMT_STATUS(SQLCOM_DROP_VIEW)},
|
||||
{"empty_query", STMT_STATUS(SQLCOM_EMPTY_QUERY)},
|
||||
{"execute_immediate", STMT_STATUS(SQLCOM_EXECUTE_IMMEDIATE)},
|
||||
{"execute_sql", STMT_STATUS(SQLCOM_EXECUTE)},
|
||||
{"flush", STMT_STATUS(SQLCOM_FLUSH)},
|
||||
{"get_diagnostics", STMT_STATUS(SQLCOM_GET_DIAGNOSTICS)},
|
||||
|
@ -253,6 +253,7 @@ sp_get_flags_for_command(LEX *lex)
|
||||
statement within an IF condition.
|
||||
*/
|
||||
case SQLCOM_EXECUTE:
|
||||
case SQLCOM_EXECUTE_IMMEDIATE:
|
||||
flags= sp_head::MULTI_RESULTS | sp_head::CONTAINS_DYNAMIC_SQL;
|
||||
break;
|
||||
case SQLCOM_PREPARE:
|
||||
|
@ -95,6 +95,7 @@ enum enum_sql_command {
|
||||
SQLCOM_SHOW_GENERIC,
|
||||
SQLCOM_ALTER_USER,
|
||||
SQLCOM_SHOW_CREATE_USER,
|
||||
SQLCOM_EXECUTE_IMMEDIATE,
|
||||
|
||||
/*
|
||||
When a command is added here, be sure it's also added in mysqld.cc
|
||||
|
@ -3006,6 +3006,19 @@ public:
|
||||
void init_last_field(Column_definition *field, const char *name, CHARSET_INFO *cs);
|
||||
void set_last_field_type(const Lex_field_type_st &type);
|
||||
bool set_bincmp(CHARSET_INFO *cs, bool bin);
|
||||
|
||||
bool prepared_stmt_params_fix_fields(THD *thd)
|
||||
{
|
||||
// Fix Items in the EXECUTE..USING list
|
||||
List_iterator_fast<Item> param_it(prepared_stmt_params);
|
||||
while (Item *param= param_it++)
|
||||
{
|
||||
if (param->fix_fields(thd, 0) || param->check_cols(1))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if "KEY IF NOT EXISTS name" used outside of ALTER context
|
||||
bool check_add_key(DDL_options_st ddl)
|
||||
{
|
||||
|
@ -3377,6 +3377,11 @@ mysql_execute_command(THD *thd)
|
||||
|
||||
break;
|
||||
}
|
||||
case SQLCOM_EXECUTE_IMMEDIATE:
|
||||
{
|
||||
mysql_sql_stmt_execute_immediate(thd);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_PREPARE:
|
||||
{
|
||||
mysql_sql_stmt_prepare(thd);
|
||||
|
@ -207,6 +207,7 @@ public:
|
||||
bool execute_server_runnable(Server_runnable *server_runnable);
|
||||
/* Destroy this statement */
|
||||
void deallocate();
|
||||
bool execute_immediate(const char *query, uint query_length);
|
||||
private:
|
||||
/**
|
||||
The memory root to allocate parsed tree elements (instances of Item,
|
||||
@ -218,6 +219,7 @@ private:
|
||||
bool set_parameters(String *expanded_query,
|
||||
uchar *packet, uchar *packet_end);
|
||||
bool execute(String *expanded_query, bool open_cursor);
|
||||
void deallocate_immediate();
|
||||
bool reprepare();
|
||||
bool validate_metadata(Prepared_statement *copy);
|
||||
void swap_prepared_statement(Prepared_statement *copy);
|
||||
@ -2764,6 +2766,39 @@ void mysql_sql_stmt_prepare(THD *thd)
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
void mysql_sql_stmt_execute_immediate(THD *thd)
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
Prepared_statement *stmt;
|
||||
const char *query;
|
||||
uint query_len= 0;
|
||||
DBUG_ENTER("mysql_sql_stmt_execute_immediate");
|
||||
|
||||
if (lex->prepared_stmt_params_fix_fields(thd))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
/*
|
||||
Prepared_statement is quite large,
|
||||
let's allocate it on the heap rather than on the stack.
|
||||
*/
|
||||
if (!(query= get_dynamic_sql_string(lex, &query_len)) ||
|
||||
!(stmt= new Prepared_statement(thd)))
|
||||
DBUG_VOID_RETURN; // out of memory
|
||||
|
||||
// See comments on thd->free_list in mysql_sql_stmt_execute()
|
||||
Item *free_list_backup= thd->free_list;
|
||||
thd->free_list= NULL;
|
||||
(void) stmt->execute_immediate(query, query_len);
|
||||
thd->free_items();
|
||||
thd->free_list= free_list_backup;
|
||||
|
||||
stmt->lex->restore_set_statement_var();
|
||||
delete stmt;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reinit prepared statement/stored procedure before execution.
|
||||
|
||||
@ -3034,13 +3069,8 @@ void mysql_sql_stmt_execute(THD *thd)
|
||||
|
||||
DBUG_PRINT("info",("stmt: 0x%lx", (long) stmt));
|
||||
|
||||
// Fix all Items in the USING list
|
||||
List_iterator_fast<Item> param_it(lex->prepared_stmt_params);
|
||||
while (Item *param= param_it++)
|
||||
{
|
||||
if (param->fix_fields(thd, 0) || param->check_cols(1))
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
if (lex->prepared_stmt_params_fix_fields(thd))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
/*
|
||||
thd->free_list can already have some Items.
|
||||
@ -4401,16 +4431,58 @@ error:
|
||||
}
|
||||
|
||||
|
||||
/** Common part of DEALLOCATE PREPARE and mysqld_stmt_close. */
|
||||
/**
|
||||
Prepare, execute and clean-up a statement.
|
||||
@param query - query text
|
||||
@param length - query text length
|
||||
@retval true - the query was not executed (parse error, wrong parameters)
|
||||
@retval false - the query was prepared and executed
|
||||
|
||||
void Prepared_statement::deallocate()
|
||||
Note, if some error happened during execution, it still returns "false".
|
||||
*/
|
||||
bool Prepared_statement::execute_immediate(const char *query, uint query_len)
|
||||
{
|
||||
DBUG_ENTER("Prepared_statement::execute_immediate");
|
||||
String expanded_query;
|
||||
static LEX_STRING execute_immediate_stmt_name=
|
||||
{(char*) STRING_WITH_LEN("(immediate)") };
|
||||
|
||||
set_sql_prepare();
|
||||
name= execute_immediate_stmt_name; // for DBUG_PRINT etc
|
||||
if (prepare(query, query_len))
|
||||
DBUG_RETURN(true);
|
||||
|
||||
if (param_count != thd->lex->prepared_stmt_params.elements)
|
||||
{
|
||||
my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
|
||||
deallocate_immediate();
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
(void) execute_loop(&expanded_query, FALSE, NULL, NULL);
|
||||
deallocate_immediate();
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Common part of DEALLOCATE PREPARE, EXECUTE IMMEDIATE, mysqld_stmt_close.
|
||||
*/
|
||||
void Prepared_statement::deallocate_immediate()
|
||||
{
|
||||
/* We account deallocate in the same manner as mysqld_stmt_close */
|
||||
status_var_increment(thd->status_var.com_stmt_close);
|
||||
|
||||
/* It should now be safe to reset CHANGE MASTER parameters */
|
||||
lex_end_stage2(lex);
|
||||
}
|
||||
|
||||
|
||||
/** Common part of DEALLOCATE PREPARE and mysqld_stmt_close. */
|
||||
|
||||
void Prepared_statement::deallocate()
|
||||
{
|
||||
deallocate_immediate();
|
||||
/* Statement map calls delete stmt on erase */
|
||||
thd->stmt_map.erase(this);
|
||||
}
|
||||
|
@ -75,6 +75,7 @@ void mysqld_stmt_execute(THD *thd, char *packet, uint packet_length);
|
||||
void mysqld_stmt_close(THD *thd, char *packet);
|
||||
void mysql_sql_stmt_prepare(THD *thd);
|
||||
void mysql_sql_stmt_execute(THD *thd);
|
||||
void mysql_sql_stmt_execute_immediate(THD *thd);
|
||||
void mysql_sql_stmt_close(THD *thd);
|
||||
void mysqld_stmt_fetch(THD *thd, char *packet, uint packet_length);
|
||||
void mysqld_stmt_reset(THD *thd, char *packet);
|
||||
|
@ -1300,6 +1300,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
%token IGNORE_DOMAIN_IDS_SYM
|
||||
%token IGNORE_SYM
|
||||
%token IGNORE_SERVER_IDS_SYM
|
||||
%token IMMEDIATE_SYM /* SQL-2003-R */
|
||||
%token IMPORT
|
||||
%token INDEXES
|
||||
%token INDEX_SYM
|
||||
@ -2251,6 +2252,12 @@ execute:
|
||||
}
|
||||
execute_using
|
||||
{}
|
||||
| EXECUTE_SYM IMMEDIATE_SYM prepare_src
|
||||
{
|
||||
Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE;
|
||||
}
|
||||
execute_using
|
||||
{}
|
||||
;
|
||||
|
||||
execute_using:
|
||||
@ -14705,6 +14712,7 @@ keyword_sp:
|
||||
| ID_SYM {}
|
||||
| IDENTIFIED_SYM {}
|
||||
| IGNORE_SERVER_IDS_SYM {}
|
||||
| IMMEDIATE_SYM {} /* SQL-2003-R */
|
||||
| INVOKER_SYM {}
|
||||
| IMPORT {}
|
||||
| INDEXES {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user