Skip to content

Commit

Permalink
MDEV-16708: Unsupported commands for prepared statements
Browse files Browse the repository at this point in the history
Disable running of the statements
PREPARE FROM/EXECUTE/EXECUTE IMMEDIATE/DEALLOCATE
in PS mode. Adjust tests main.ps, main.ps_1general
  • Loading branch information
dmitryshulga authored and vuvova committed Jun 17, 2021
1 parent 3274022 commit 7586eea
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 201 deletions.
32 changes: 31 additions & 1 deletion client/mysqltest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ static const char *opt_suite_dir, *opt_overlay_dir;
static size_t suite_dir_len, overlay_dir_len;

/* Precompiled re's */
static regex_t ps_re; /* the query can be run using PS protocol */
static regex_t sp_re; /* the query can be run as a SP */
static regex_t view_re; /* the query can be run as a view*/

Expand Down Expand Up @@ -8721,7 +8722,14 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
statement already and we can't do it twice
*/
if (ps_protocol_enabled &&
complete_query)
complete_query &&
/*
Check that a statement is not one of PREPARE FROM, EXECUTE,
DEALLOCATE PREPARE (possibly prefixed with the 'SET STATEMENT ... FOR'
clause. These statement shouldn't be run using prepared statement C API.
All other statements can be run using prepared statement C API.
*/
!match_re(&ps_re, query))
run_query_stmt(cn, command, query, query_len, ds, &ds_warnings);
else
run_query_normal(cn, command, flags, query, query_len,
Expand Down Expand Up @@ -8794,6 +8802,26 @@ void init_re_comp(regex_t *re, const char* str)

void init_re(void)
{
/*
* Prior to the task MDEV-16708 a value of the string ps_re_str contained
* a regular expression to match statements that SHOULD BE run in PS mode.
* The task MDEV-16708 modifies interpretation of this regular expression
* and now it is used for matching statements that SHOULDN'T be run in
* PS mode. These statement are PREPARE FROM, EXECUTE, DEALLOCATE PREPARE
* possibly prefixed with the clause SET STATEMENT ... FOR
*/
const char *ps_re_str =
"^("
"[[:space:]]*PREPARE[[:space:]]|"
"[[:space:]]*EXECUTE[[:space:]]|"
"[[:space:]]*DEALLOCATE[[:space:]]+PREPARE[[:space:]]|"
"[[:space:]]*DROP[[:space:]]+PREPARE[[:space:]]|"
"(SET[[:space:]]+STATEMENT[[:space:]]+.+[[:space:]]+FOR[[:space:]]+)?"
"EXECUTE[[:space:]]+|"
"(SET[[:space:]]+STATEMENT[[:space:]]+.+[[:space:]]+FOR[[:space:]]+)?"
"PREPARE[[:space:]]+"
")";

/*
Filter for queries that can be run using the
Stored procedures
Expand Down Expand Up @@ -8858,6 +8886,7 @@ void init_re(void)
"^("
"[[:space:]]*SELECT[[:space:]])";

init_re_comp(&ps_re, ps_re_str);
init_re_comp(&sp_re, sp_re_str);
init_re_comp(&view_re, view_re_str);
}
Expand Down Expand Up @@ -8893,6 +8922,7 @@ int match_re(regex_t *re, char *str)

void free_re(void)
{
regfree(&ps_re);
regfree(&sp_re);
regfree(&view_re);
}
Expand Down
12 changes: 7 additions & 5 deletions mysql-test/main/ps.result
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ ERROR HY000: Unknown prepared statement handler (no_such_statement) given to DEA
execute stmt1;
ERROR HY000: Incorrect arguments to EXECUTE
prepare stmt2 from 'prepare nested_stmt from "select 1"';
ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt2 from 'execute stmt1';
ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt2 from 'deallocate prepare z';
deallocate prepare stmt2;
ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt3 from 'insert into t1 values (?,?)';
set @arg1=5, @arg2='five';
execute stmt3 using @arg1, @arg2;
Expand Down Expand Up @@ -4719,13 +4721,13 @@ ERROR HY000: Incorrect arguments to EXECUTE
EXECUTE IMMEDIATE 'SELECT ?';
ERROR HY000: Incorrect arguments to EXECUTE
EXECUTE IMMEDIATE 'EXECUTE IMMEDIATE "SELECT 1"';
1
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';
1
1
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);
Expand Down
8 changes: 7 additions & 1 deletion mysql-test/main/ps.test
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ deallocate prepare no_such_statement;
execute stmt1;

# Nesting ps commands is now allowed:
--error ER_UNSUPPORTED_PS
prepare stmt2 from 'prepare nested_stmt from "select 1"';
--error ER_UNSUPPORTED_PS
prepare stmt2 from 'execute stmt1';
--error ER_UNSUPPORTED_PS
prepare stmt2 from 'deallocate prepare z';
deallocate prepare stmt2;

# PS insert
prepare stmt3 from 'insert into t1 values (?,?)';
Expand Down Expand Up @@ -4193,12 +4195,16 @@ 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
Expand Down
3 changes: 3 additions & 0 deletions mysql-test/main/ps_1general.result
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,11 @@ drop table t5 ;
deallocate prepare stmt_do ;
deallocate prepare stmt_set ;
prepare stmt1 from ' prepare stmt2 from '' select 1 '' ' ;
ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' execute stmt2 ' ;
ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' deallocate prepare never_prepared ' ;
ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from 'alter view v1 as select 2';
prepare stmt4 from ' use test ' ;
prepare stmt3 from ' create database mysqltest ';
Expand Down
3 changes: 3 additions & 0 deletions mysql-test/main/ps_1general.test
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,11 @@ deallocate prepare stmt_do ;
deallocate prepare stmt_set ;

## nonsense like prepare of prepare,execute or deallocate
--error ER_UNSUPPORTED_PS
prepare stmt1 from ' prepare stmt2 from '' select 1 '' ' ;
--error ER_UNSUPPORTED_PS
prepare stmt1 from ' execute stmt2 ' ;
--error ER_UNSUPPORTED_PS
prepare stmt1 from ' deallocate prepare never_prepared ' ;

prepare stmt1 from 'alter view v1 as select 2';
Expand Down
87 changes: 12 additions & 75 deletions mysql-test/main/ps_missed_cmds.result
Original file line number Diff line number Diff line change
Expand Up @@ -546,59 +546,7 @@ EXECUTE stmt_1;
# Clean up
DEALLOCATE PREPARE stmt_1;
DROP PROCEDURE p1;
# Test case 15: Check that the 'PREPARE FROM' statement can be executed
# as a prepared statement.
PREPARE stmt_1 FROM 'PREPARE stmt_2 FROM "SELECT 1"';
EXECUTE stmt_1;
# Execute the same prepared statement the second time to check that
# no internal structures used for handling the 'PREPARE' statement
# were damaged.
EXECUTE stmt_1;
# Now execute the prepared statement with the name stmt_2
# It is expected that output contains the single row '1'
EXECUTE stmt_2;
1
1
# Clean up
DEALLOCATE PREPARE stmt_1;
DEALLOCATE PREPARE stmt_2;
# Test case 16: Check that the 'EXECUTE' statement can be executed
# as a prepared statement.
PREPARE stmt_1 FROM 'SELECT 1';
PREPARE stmt_2 FROM 'EXECUTE stmt_1';
# Execute the statement stmt_2. Expected result is output of one row '1'
EXECUTE stmt_2;
1
1
# Execute the same prepared statement the second time to check that
# no internal structures used for handling the 'EXECUTE' statement
# were damaged.
EXECUTE stmt_2;
1
1
# Clean up
DEALLOCATE PREPARE stmt_1;
DEALLOCATE PREPARE stmt_2;
# Test case 17: Check that the statement 'DEALLOCATE PREPARE'
# can be executed as a prepared statement.
PREPARE stmt_1 FROM 'SELECT 1';
PREPARE stmt_2 FROM 'DEALLOCATE PREPARE stmt_1';
# After the prepared statement 'stmt_2' be executed
# the prepared statement stmt_1 will be deallocated.
EXECUTE stmt_2;
# Execute the same prepared statement the second time to check that
# no internal structures used for handling the 'DEALLOCATE PREPARE'
# statement were damaged. This time invocation results in the error
# ER_UNKNOWN_STMT_HANDLER since the prepared statement stmt_1
# has just been released. So, just ignore this error.
EXECUTE stmt_2;
ERROR HY000: Unknown prepared statement handler (stmt_1) given to DEALLOCATE PREPARE
# Check that the stmt_1 doesn't no longer exist
EXECUTE stmt_1;
ERROR HY000: Unknown prepared statement handler (stmt_1) given to EXECUTE
# Clean up
DEALLOCATE PREPARE stmt_2;
# Test case 18: Check that the 'CREATE VIEW' statement can be executed
# Test case 15: Check that the 'CREATE VIEW' statement can be executed
# as a prepared statement.
# Create environment for the test case
CREATE TABLE t1 (a INT);
Expand All @@ -617,7 +565,7 @@ ERROR 42S01: Table 'v1' already exists
DEALLOCATE PREPARE stmt_1;
DROP VIEW v1;
DROP TABLE t1;
# Test case 19: Check that the 'CREATE TRIGGER' statement can be executed
# Test case 16: Check that the 'CREATE TRIGGER' statement can be executed
# as a prepared statement.
CREATE TABLE t1 (a INT);
PREPARE stmt_1 FROM 'CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW SET @a=1';
Expand All @@ -629,10 +577,10 @@ EXECUTE stmt_1;
# already exist. It is expected behaviour.
EXECUTE stmt_1;
ERROR HY000: Trigger 'test.trg1' already exists
# Test case 20: Check that the 'DROP TRIGGER' statement can be executed
# Test case 17: Check that the 'DROP TRIGGER' statement can be executed
# as a prepared statement.
# This test relies on presence of the trigger trg1 created by
# the test case 19.
# the test case 16.
PREPARE stmt_1 FROM 'DROP TRIGGER trg1';
EXECUTE stmt_1;
# Execute the same prepared statement the second time to check that
Expand All @@ -644,7 +592,7 @@ ERROR HY000: Trigger does not exist
# Clean up
DEALLOCATE PREPARE stmt_1;
DROP TABLE t1;
# Test case 21: Check that XA related SQL statements can be executed
# Test case 18: Check that XA related SQL statements can be executed
# as prepared statements.
# Create the table t1 used by XA transaction.
CREATE TABLE t1 (a INT);
Expand Down Expand Up @@ -734,7 +682,7 @@ DEALLOCATE PREPARE stmt_3;
DEALLOCATE PREPARE stmt_4;
DEALLOCATE PREPARE stmt_5;
DEALLOCATE PREPARE stmt_6;
# Test case 22: Check that the CREATE SERVER/ALTER SERVER/DROP SERVER
# Test case 19: Check that the CREATE SERVER/ALTER SERVER/DROP SERVER
# statements can be executed as prepared statements.
PREPARE stmt_1 FROM "CREATE SERVER s FOREIGN DATA WRAPPER mysql OPTIONS (USER 'u1', HOST '127.0.0.1')";
PREPARE stmt_2 FROM "ALTER SERVER s OPTIONS (USER 'u2')";
Expand Down Expand Up @@ -764,7 +712,7 @@ ERROR HY000: The foreign server name you are trying to reference does not exist.
DEALLOCATE PREPARE stmt_1;
DEALLOCATE PREPARE stmt_2;
DEALLOCATE PREPARE stmt_3;
# Test case 23: Check that the CREATE EVENT/ALTER EVENT/DROP EVENT
# Test case 20: Check that the CREATE EVENT/ALTER EVENT/DROP EVENT
# statements can be executed as a prepared statement
PREPARE stmt_1 FROM "CREATE EVENT e1 ON SCHEDULE AT CURRENT_TIMESTAMP - INTERVAL 1 DAY ON COMPLETION PRESERVE DO SET @a=1";
PREPARE stmt_2 FROM "ALTER EVENT e1 COMMENT 'New comment'";
Expand Down Expand Up @@ -802,7 +750,7 @@ ERROR HY000: Unknown event 'e1'
DEALLOCATE PREPARE stmt_1;
DEALLOCATE PREPARE stmt_2;
DEALLOCATE PREPARE stmt_3;
# Test case 24: Check that the SIGNAL and RESIGNAL statements
# Test case 21: Check that the SIGNAL and RESIGNAL statements
# can be executed as a prepared statement
PREPARE stmt_1 FROM "SIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=30001, MESSAGE_TEXT='Hello, world!'";
EXECUTE stmt_1;
Expand All @@ -822,7 +770,7 @@ EXECUTE stmt_1;
ERROR 0K000: RESIGNAL when handler not active
# Clean up
DEALLOCATE PREPARE stmt_1;
# Test case 25: Check that the 'SHOW RELAYLOG EVENTS' statement can be
# Test case 22: Check that the 'SHOW RELAYLOG EVENTS' statement can be
# executed as a prepared statement.
PREPARE stmt_1 FROM 'SHOW RELAYLOG EVENTS';
EXECUTE stmt_1;
Expand All @@ -834,7 +782,7 @@ EXECUTE stmt_1;
Log_name Pos Event_type Server_id End_log_pos Info
# Clean up
DEALLOCATE PREPARE stmt_1;
# Test case 26: Check the 'GET DIAGNOSTICS' statement
# Test case 23: Check the 'GET DIAGNOSTICS' statement
# can be executed as a prepared statement
PREPARE stmt_1 FROM 'GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT';
# Query from non existent table to fill the diagnostics area
Expand All @@ -854,18 +802,7 @@ ERROR 42S02: Table 'test.non_existent_table_1' doesn't exist
EXECUTE stmt_1;
# Clean up
DEALLOCATE PREPARE stmt_1;
# Test case 27: Check the the statement 'EXECUTE IMMEDIATE'
# can be executed as a prepared statement
PREPARE stmt_1 FROM "EXECUTE IMMEDIATE 'SELECT 1'";
EXECUTE stmt_1;
1
1
# Execute the same prepared statement the second time to check that
# no internal structures used for handling the 'EXECUTE IMMEDIATE'
# statement were damaged.
# Clean up
DEALLOCATE PREPARE stmt_1;
# Test Test case 28: Check the statements 'BACKUP'/'BACKUP UNLOCK'
# Test case 24: Check the statements 'BACKUP'/'BACKUP UNLOCK'
# can be executed as a prepared statement
CREATE TABLE t1 (a INT);
PREPARE stmt_1 FROM 'BACKUP LOCK t1';
Expand All @@ -884,7 +821,7 @@ EXECUTE stmt_2;
DROP TABLE t1;
DEALLOCATE PREPARE stmt_1;
DEALLOCATE PREPARE stmt_2;
# Test Test case 29: Check the statements 'CREATE/ALTER/DROP TABLEPSPACE'
# Test Test case 25: Check the statements 'CREATE/ALTER/DROP TABLEPSPACE'
# can be executed as a prepared statement
PREPARE stmt_1 FROM "CREATE TABLESPACE ts1 ADD DATAFILE 'ts1.ibd' ENGINE=InnoDB";
PREPARE stmt_2 FROM "ALTER TABLESPACE ts1 ADD DATAFILE 'ts1_1.ibd' ENGINE=InnoDB";
Expand Down
Loading

0 comments on commit 7586eea

Please sign in to comment.