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;
|
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
|
# End of 10.2 tests
|
||||||
#
|
#
|
||||||
|
@ -275,3 +275,8 @@ set option=1;
|
|||||||
ERROR HY000: Unknown system variable 'option'
|
ERROR HY000: Unknown system variable 'option'
|
||||||
set option option=1;
|
set option option=1;
|
||||||
ERROR HY000: Unknown system variable 'option'
|
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-classes 10
|
||||||
performance-schema-max-socket-instances -1
|
performance-schema-max-socket-instances -1
|
||||||
performance-schema-max-stage-classes 150
|
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-handles -1
|
||||||
performance-schema-max-table-instances -1
|
performance-schema-max-table-instances -1
|
||||||
performance-schema-max-thread-classes 50
|
performance-schema-max-thread-classes 50
|
||||||
|
@ -4289,5 +4289,218 @@ DROP TABLE t1;
|
|||||||
# End of MDEV-10709 Expressions as parameters to Dynamic SQL
|
# 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
|
# 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
|
master-bin.000002 # Query # # COMMIT
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
SET TIMESTAMP=DEFAULT;
|
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;
|
source include/show_binlog_events.inc;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
SET TIMESTAMP=DEFAULT;
|
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
|
COMMAND_LINE_ARGUMENT REQUIRED
|
||||||
VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES
|
VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES
|
||||||
SESSION_VALUE NULL
|
SESSION_VALUE NULL
|
||||||
GLOBAL_VALUE 184
|
GLOBAL_VALUE 185
|
||||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||||
DEFAULT_VALUE 184
|
DEFAULT_VALUE 185
|
||||||
VARIABLE_SCOPE GLOBAL
|
VARIABLE_SCOPE GLOBAL
|
||||||
VARIABLE_TYPE BIGINT UNSIGNED
|
VARIABLE_TYPE BIGINT UNSIGNED
|
||||||
VARIABLE_COMMENT Maximum number of statement instruments.
|
VARIABLE_COMMENT Maximum number of statement instruments.
|
||||||
|
@ -974,6 +974,18 @@ let $coll='ucs2_nopad_bin';
|
|||||||
let $coll_pad='ucs2_bin';
|
let $coll_pad='ucs2_bin';
|
||||||
--source include/ctype_pad_all_engines.inc
|
--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 #
|
||||||
--echo # End of 10.2 tests
|
--echo # End of 10.2 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -173,3 +173,10 @@ drop table option;
|
|||||||
set option=1;
|
set option=1;
|
||||||
--error 1193
|
--error 1193
|
||||||
set option option=1;
|
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 # End of MDEV-10709 Expressions as parameters to Dynamic SQL
|
||||||
--echo #
|
--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 #
|
||||||
--echo # End of 10.2 tests
|
--echo # End of 10.2 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -278,6 +278,7 @@ static SYMBOL symbols[] = {
|
|||||||
{ "IGNORE", SYM(IGNORE_SYM)},
|
{ "IGNORE", SYM(IGNORE_SYM)},
|
||||||
{ "IGNORE_DOMAIN_IDS", SYM(IGNORE_DOMAIN_IDS_SYM)},
|
{ "IGNORE_DOMAIN_IDS", SYM(IGNORE_DOMAIN_IDS_SYM)},
|
||||||
{ "IGNORE_SERVER_IDS", SYM(IGNORE_SERVER_IDS_SYM)},
|
{ "IGNORE_SERVER_IDS", SYM(IGNORE_SERVER_IDS_SYM)},
|
||||||
|
{ "IMMEDIATE", SYM(IMMEDIATE_SYM)},
|
||||||
{ "IMPORT", SYM(IMPORT)},
|
{ "IMPORT", SYM(IMPORT)},
|
||||||
{ "IN", SYM(IN_SYM)},
|
{ "IN", SYM(IN_SYM)},
|
||||||
{ "INDEX", SYM(INDEX_SYM)},
|
{ "INDEX", SYM(INDEX_SYM)},
|
||||||
|
@ -3886,6 +3886,7 @@ SHOW_VAR com_status_vars[]= {
|
|||||||
{"drop_user", STMT_STATUS(SQLCOM_DROP_USER)},
|
{"drop_user", STMT_STATUS(SQLCOM_DROP_USER)},
|
||||||
{"drop_view", STMT_STATUS(SQLCOM_DROP_VIEW)},
|
{"drop_view", STMT_STATUS(SQLCOM_DROP_VIEW)},
|
||||||
{"empty_query", STMT_STATUS(SQLCOM_EMPTY_QUERY)},
|
{"empty_query", STMT_STATUS(SQLCOM_EMPTY_QUERY)},
|
||||||
|
{"execute_immediate", STMT_STATUS(SQLCOM_EXECUTE_IMMEDIATE)},
|
||||||
{"execute_sql", STMT_STATUS(SQLCOM_EXECUTE)},
|
{"execute_sql", STMT_STATUS(SQLCOM_EXECUTE)},
|
||||||
{"flush", STMT_STATUS(SQLCOM_FLUSH)},
|
{"flush", STMT_STATUS(SQLCOM_FLUSH)},
|
||||||
{"get_diagnostics", STMT_STATUS(SQLCOM_GET_DIAGNOSTICS)},
|
{"get_diagnostics", STMT_STATUS(SQLCOM_GET_DIAGNOSTICS)},
|
||||||
|
@ -253,6 +253,7 @@ sp_get_flags_for_command(LEX *lex)
|
|||||||
statement within an IF condition.
|
statement within an IF condition.
|
||||||
*/
|
*/
|
||||||
case SQLCOM_EXECUTE:
|
case SQLCOM_EXECUTE:
|
||||||
|
case SQLCOM_EXECUTE_IMMEDIATE:
|
||||||
flags= sp_head::MULTI_RESULTS | sp_head::CONTAINS_DYNAMIC_SQL;
|
flags= sp_head::MULTI_RESULTS | sp_head::CONTAINS_DYNAMIC_SQL;
|
||||||
break;
|
break;
|
||||||
case SQLCOM_PREPARE:
|
case SQLCOM_PREPARE:
|
||||||
|
@ -95,6 +95,7 @@ enum enum_sql_command {
|
|||||||
SQLCOM_SHOW_GENERIC,
|
SQLCOM_SHOW_GENERIC,
|
||||||
SQLCOM_ALTER_USER,
|
SQLCOM_ALTER_USER,
|
||||||
SQLCOM_SHOW_CREATE_USER,
|
SQLCOM_SHOW_CREATE_USER,
|
||||||
|
SQLCOM_EXECUTE_IMMEDIATE,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
When a command is added here, be sure it's also added in mysqld.cc
|
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 init_last_field(Column_definition *field, const char *name, CHARSET_INFO *cs);
|
||||||
void set_last_field_type(const Lex_field_type_st &type);
|
void set_last_field_type(const Lex_field_type_st &type);
|
||||||
bool set_bincmp(CHARSET_INFO *cs, bool bin);
|
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
|
// Check if "KEY IF NOT EXISTS name" used outside of ALTER context
|
||||||
bool check_add_key(DDL_options_st ddl)
|
bool check_add_key(DDL_options_st ddl)
|
||||||
{
|
{
|
||||||
|
@ -3377,6 +3377,11 @@ mysql_execute_command(THD *thd)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SQLCOM_EXECUTE_IMMEDIATE:
|
||||||
|
{
|
||||||
|
mysql_sql_stmt_execute_immediate(thd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SQLCOM_PREPARE:
|
case SQLCOM_PREPARE:
|
||||||
{
|
{
|
||||||
mysql_sql_stmt_prepare(thd);
|
mysql_sql_stmt_prepare(thd);
|
||||||
|
@ -207,6 +207,7 @@ public:
|
|||||||
bool execute_server_runnable(Server_runnable *server_runnable);
|
bool execute_server_runnable(Server_runnable *server_runnable);
|
||||||
/* Destroy this statement */
|
/* Destroy this statement */
|
||||||
void deallocate();
|
void deallocate();
|
||||||
|
bool execute_immediate(const char *query, uint query_length);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
The memory root to allocate parsed tree elements (instances of Item,
|
The memory root to allocate parsed tree elements (instances of Item,
|
||||||
@ -218,6 +219,7 @@ private:
|
|||||||
bool set_parameters(String *expanded_query,
|
bool set_parameters(String *expanded_query,
|
||||||
uchar *packet, uchar *packet_end);
|
uchar *packet, uchar *packet_end);
|
||||||
bool execute(String *expanded_query, bool open_cursor);
|
bool execute(String *expanded_query, bool open_cursor);
|
||||||
|
void deallocate_immediate();
|
||||||
bool reprepare();
|
bool reprepare();
|
||||||
bool validate_metadata(Prepared_statement *copy);
|
bool validate_metadata(Prepared_statement *copy);
|
||||||
void swap_prepared_statement(Prepared_statement *copy);
|
void swap_prepared_statement(Prepared_statement *copy);
|
||||||
@ -2764,6 +2766,39 @@ void mysql_sql_stmt_prepare(THD *thd)
|
|||||||
DBUG_VOID_RETURN;
|
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.
|
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));
|
DBUG_PRINT("info",("stmt: 0x%lx", (long) stmt));
|
||||||
|
|
||||||
// Fix all Items in the USING list
|
if (lex->prepared_stmt_params_fix_fields(thd))
|
||||||
List_iterator_fast<Item> param_it(lex->prepared_stmt_params);
|
DBUG_VOID_RETURN;
|
||||||
while (Item *param= param_it++)
|
|
||||||
{
|
|
||||||
if (param->fix_fields(thd, 0) || param->check_cols(1))
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
thd->free_list can already have some Items.
|
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 */
|
/* We account deallocate in the same manner as mysqld_stmt_close */
|
||||||
status_var_increment(thd->status_var.com_stmt_close);
|
status_var_increment(thd->status_var.com_stmt_close);
|
||||||
|
|
||||||
/* It should now be safe to reset CHANGE MASTER parameters */
|
/* It should now be safe to reset CHANGE MASTER parameters */
|
||||||
lex_end_stage2(lex);
|
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 */
|
/* Statement map calls delete stmt on erase */
|
||||||
thd->stmt_map.erase(this);
|
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 mysqld_stmt_close(THD *thd, char *packet);
|
||||||
void mysql_sql_stmt_prepare(THD *thd);
|
void mysql_sql_stmt_prepare(THD *thd);
|
||||||
void mysql_sql_stmt_execute(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 mysql_sql_stmt_close(THD *thd);
|
||||||
void mysqld_stmt_fetch(THD *thd, char *packet, uint packet_length);
|
void mysqld_stmt_fetch(THD *thd, char *packet, uint packet_length);
|
||||||
void mysqld_stmt_reset(THD *thd, char *packet);
|
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_DOMAIN_IDS_SYM
|
||||||
%token IGNORE_SYM
|
%token IGNORE_SYM
|
||||||
%token IGNORE_SERVER_IDS_SYM
|
%token IGNORE_SERVER_IDS_SYM
|
||||||
|
%token IMMEDIATE_SYM /* SQL-2003-R */
|
||||||
%token IMPORT
|
%token IMPORT
|
||||||
%token INDEXES
|
%token INDEXES
|
||||||
%token INDEX_SYM
|
%token INDEX_SYM
|
||||||
@ -2251,6 +2252,12 @@ execute:
|
|||||||
}
|
}
|
||||||
execute_using
|
execute_using
|
||||||
{}
|
{}
|
||||||
|
| EXECUTE_SYM IMMEDIATE_SYM prepare_src
|
||||||
|
{
|
||||||
|
Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE;
|
||||||
|
}
|
||||||
|
execute_using
|
||||||
|
{}
|
||||||
;
|
;
|
||||||
|
|
||||||
execute_using:
|
execute_using:
|
||||||
@ -14705,6 +14712,7 @@ keyword_sp:
|
|||||||
| ID_SYM {}
|
| ID_SYM {}
|
||||||
| IDENTIFIED_SYM {}
|
| IDENTIFIED_SYM {}
|
||||||
| IGNORE_SERVER_IDS_SYM {}
|
| IGNORE_SERVER_IDS_SYM {}
|
||||||
|
| IMMEDIATE_SYM {} /* SQL-2003-R */
|
||||||
| INVOKER_SYM {}
|
| INVOKER_SYM {}
|
||||||
| IMPORT {}
|
| IMPORT {}
|
||||||
| INDEXES {}
|
| INDEXES {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user