Skip to content

Commit e48bd47

Browse files
dmitryshulgasanja-byelkin
authored andcommitted
MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT
This patch fixes the issue with passing the DEFAULT or IGNORE values to positional parameters for some kind of SQL statements to be executed as prepared statements. The main idea of the patch is to associate an actual value being passed by the USING clause with the positional parameter represented by the Item_param class. Such association must be performed on execution of UPDATE statement in PS/SP mode. Other corner cases that results in server crash is on handling CREATE TABLE when positional parameter placed after the DEFAULT clause or CALL statement and passing either the value DEFAULT or IGNORE as an actual value for the positional parameter. This case is fixed by checking whether an error is set in diagnostics area at the function pack_vcols() on return from the function pack_expression()
1 parent 6b2cd78 commit e48bd47

16 files changed

+418
-17
lines changed

mysql-test/main/ps.result

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5815,5 +5815,123 @@ GROUP_CONCAT(@x)
58155815
0
58165816
DROP TABLE t;
58175817
#
5818+
# MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT
5819+
#
5820+
PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)';
5821+
EXECUTE stmt USING DEFAULT;
5822+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5823+
DEALLOCATE PREPARE stmt;
5824+
PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)';
5825+
EXECUTE stmt USING IGNORE;
5826+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5827+
DEALLOCATE PREPARE stmt;
5828+
EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT;
5829+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5830+
EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING IGNORE;
5831+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5832+
EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING DEFAULT;
5833+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5834+
EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING IGNORE;
5835+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5836+
CREATE PROCEDURE p1(a INT) SELECT 1;
5837+
EXECUTE IMMEDIATE 'CALL p1(?)' USING DEFAULT;
5838+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5839+
EXECUTE IMMEDIATE 'CALL p1(?)' USING IGNORE;
5840+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5841+
DROP PROCEDURE p1;
5842+
EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING DEFAULT;
5843+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5844+
EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING IGNORE;
5845+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5846+
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING DEFAULT;
5847+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5848+
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING IGNORE;
5849+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5850+
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING DEFAULT;
5851+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5852+
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING IGNORE;
5853+
ERROR HY000: Default/ignore value is not supported for such parameter usage
5854+
# multi-update and DEFAULT
5855+
CREATE TABLE t1 (a INT, b INT DEFAULT a);
5856+
INSERT into t1 VALUES (1,2),(2,3);
5857+
CREATE TABLE t2 (a INT, b INT DEFAULT a);
5858+
INSERT INTO t2 VALUES (1,10),(2,30);
5859+
UPDATE t1,t2 SET t1.b = DEFAULT, t2.b = DEFAULT WHERE t1.a=t2.a;
5860+
SELECT * FROM t1;
5861+
a b
5862+
1 1
5863+
2 2
5864+
SELECT * FROM t2;
5865+
a b
5866+
1 1
5867+
2 2
5868+
# re-check the case for Prepared Statement with parameters
5869+
TRUNCATE TABLE t1;
5870+
TRUNCATE TABLE t2;
5871+
INSERT INTO t1 VALUES (1,2),(2,3);
5872+
INSERT INTO t2 VALUES (1,10),(2,30);
5873+
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT;
5874+
SELECT * FROM t1;
5875+
a b
5876+
1 1
5877+
2 2
5878+
SELECT * FROM t2;
5879+
a b
5880+
1 1
5881+
2 2
5882+
DROP TABLE t1, t2;
5883+
# multi-update and IGNORE
5884+
CREATE TABLE t1 (a INT, b INT default a);
5885+
INSERT INTO t1 VALUES (1,2),(2,3);
5886+
CREATE TABLE t2 (a INT, b INT default a);
5887+
INSERT INTO t2 VALUES (1,10),(2,30);
5888+
UPDATE t1,t2 SET t1.b = IGNORE, t2.b = IGNORE WHERE t1.a=t2.a;
5889+
SELECT * FROM t1;
5890+
a b
5891+
1 2
5892+
2 3
5893+
SELECT * FROM t2;
5894+
a b
5895+
1 NULL
5896+
2 NULL
5897+
# re-check the case for Prepared Statement with parameters
5898+
TRUNCATE TABLE t1;
5899+
TRUNCATE TABLE t2;
5900+
INSERT INTO t1 VALUES (1,2),(2,3);
5901+
INSERT INTO t2 VALUES (1,10),(2,30);
5902+
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE;
5903+
SELECT * FROM t1;
5904+
a b
5905+
1 2
5906+
2 3
5907+
SELECT * FROM t2;
5908+
a b
5909+
1 10
5910+
2 30
5911+
DROP TABLE t1, t2;
5912+
# multi-update and DEFAULT parameter (no default)
5913+
CREATE TABLE t1 (a INT, b INT NOT NULL);
5914+
INSERT INTO t1 VALUES (1,2),(2,3);
5915+
CREATE TABLE t2 (a INT, b INT NOT NULL);
5916+
INSERT INTO t2 VALUES (1,10),(2,30);
5917+
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT;
5918+
ERROR HY000: Field 'b' doesn't have a default value
5919+
DROP TABLE t1, t2;
5920+
# multi-update and IGNORE parameter (no default)
5921+
CREATE TABLE t1 (a INT, b INT NOT NULL);
5922+
INSERT INTO t1 VALUES (1,2),(2,3);
5923+
CREATE TABLE t2 (a INT, b INT NOT NULL);
5924+
INSERT INTO t2 VALUES (1,10),(2,30);
5925+
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE;
5926+
SELECT * FROM t1;
5927+
a b
5928+
1 2
5929+
2 3
5930+
SELECT * FROM t2;
5931+
a b
5932+
1 10
5933+
2 30
5934+
DROP TABLE t1, t2;
5935+
#
58185936
# End of 10.4 tests
58195937
#

mysql-test/main/ps.test

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5243,6 +5243,125 @@ EXECUTE IMMEDIATE 'SELECT GROUP_CONCAT(@x) FROM t GROUP BY @x := f';
52435243

52445244
DROP TABLE t;
52455245

5246+
--echo #
5247+
--echo # MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT
5248+
--echo #
5249+
5250+
PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)';
5251+
--error ER_INVALID_DEFAULT_PARAM
5252+
EXECUTE stmt USING DEFAULT;
5253+
DEALLOCATE PREPARE stmt;
5254+
5255+
PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)';
5256+
--error ER_INVALID_DEFAULT_PARAM
5257+
EXECUTE stmt USING IGNORE;
5258+
DEALLOCATE PREPARE stmt;
5259+
5260+
--error ER_INVALID_DEFAULT_PARAM
5261+
EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT;
5262+
5263+
--error ER_INVALID_DEFAULT_PARAM
5264+
EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING IGNORE;
5265+
5266+
--error ER_INVALID_DEFAULT_PARAM
5267+
EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING DEFAULT;
5268+
5269+
--error ER_INVALID_DEFAULT_PARAM
5270+
EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING IGNORE;
5271+
5272+
CREATE PROCEDURE p1(a INT) SELECT 1;
5273+
--error ER_INVALID_DEFAULT_PARAM
5274+
EXECUTE IMMEDIATE 'CALL p1(?)' USING DEFAULT;
5275+
--error ER_INVALID_DEFAULT_PARAM
5276+
EXECUTE IMMEDIATE 'CALL p1(?)' USING IGNORE;
5277+
DROP PROCEDURE p1;
5278+
5279+
--error ER_INVALID_DEFAULT_PARAM
5280+
EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING DEFAULT;
5281+
--error ER_INVALID_DEFAULT_PARAM
5282+
EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING IGNORE;
5283+
5284+
--error ER_INVALID_DEFAULT_PARAM
5285+
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING DEFAULT;
5286+
--error ER_INVALID_DEFAULT_PARAM
5287+
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING IGNORE;
5288+
5289+
--error ER_INVALID_DEFAULT_PARAM
5290+
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING DEFAULT;
5291+
--error ER_INVALID_DEFAULT_PARAM
5292+
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING IGNORE;
5293+
5294+
--echo # multi-update and DEFAULT
5295+
CREATE TABLE t1 (a INT, b INT DEFAULT a);
5296+
INSERT into t1 VALUES (1,2),(2,3);
5297+
CREATE TABLE t2 (a INT, b INT DEFAULT a);
5298+
INSERT INTO t2 VALUES (1,10),(2,30);
5299+
5300+
UPDATE t1,t2 SET t1.b = DEFAULT, t2.b = DEFAULT WHERE t1.a=t2.a;
5301+
SELECT * FROM t1;
5302+
SELECT * FROM t2;
5303+
5304+
--echo # re-check the case for Prepared Statement with parameters
5305+
TRUNCATE TABLE t1;
5306+
TRUNCATE TABLE t2;
5307+
INSERT INTO t1 VALUES (1,2),(2,3);
5308+
INSERT INTO t2 VALUES (1,10),(2,30);
5309+
5310+
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT;
5311+
SELECT * FROM t1;
5312+
SELECT * FROM t2;
5313+
5314+
# Cleanup
5315+
DROP TABLE t1, t2;
5316+
5317+
--echo # multi-update and IGNORE
5318+
CREATE TABLE t1 (a INT, b INT default a);
5319+
INSERT INTO t1 VALUES (1,2),(2,3);
5320+
CREATE TABLE t2 (a INT, b INT default a);
5321+
INSERT INTO t2 VALUES (1,10),(2,30);
5322+
5323+
UPDATE t1,t2 SET t1.b = IGNORE, t2.b = IGNORE WHERE t1.a=t2.a;
5324+
SELECT * FROM t1;
5325+
SELECT * FROM t2;
5326+
5327+
--echo # re-check the case for Prepared Statement with parameters
5328+
TRUNCATE TABLE t1;
5329+
TRUNCATE TABLE t2;
5330+
INSERT INTO t1 VALUES (1,2),(2,3);
5331+
INSERT INTO t2 VALUES (1,10),(2,30);
5332+
5333+
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE;
5334+
SELECT * FROM t1;
5335+
SELECT * FROM t2;
5336+
5337+
# Cleanup
5338+
DROP TABLE t1, t2;
5339+
5340+
--echo # multi-update and DEFAULT parameter (no default)
5341+
CREATE TABLE t1 (a INT, b INT NOT NULL);
5342+
INSERT INTO t1 VALUES (1,2),(2,3);
5343+
CREATE TABLE t2 (a INT, b INT NOT NULL);
5344+
INSERT INTO t2 VALUES (1,10),(2,30);
5345+
5346+
--error ER_NO_DEFAULT_FOR_FIELD
5347+
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT;
5348+
5349+
# Cleanup
5350+
DROP TABLE t1, t2;
5351+
5352+
--echo # multi-update and IGNORE parameter (no default)
5353+
CREATE TABLE t1 (a INT, b INT NOT NULL);
5354+
INSERT INTO t1 VALUES (1,2),(2,3);
5355+
CREATE TABLE t2 (a INT, b INT NOT NULL);
5356+
INSERT INTO t2 VALUES (1,10),(2,30);
5357+
5358+
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE;
5359+
SELECT * FROM t1;
5360+
SELECT * FROM t2;
5361+
5362+
# Cleanup
5363+
DROP TABLE t1, t2;
5364+
52465365
--echo #
52475366
--echo # End of 10.4 tests
52485367
--echo #

mysql-test/main/table_value_constr.result

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2594,9 +2594,9 @@ ERROR HY000: 'ignore' is not allowed in this context
25942594
VALUES (DEFAULT);
25952595
ERROR HY000: 'default' is not allowed in this context
25962596
EXECUTE IMMEDIATE 'VALUES (?)' USING IGNORE;
2597-
ERROR HY000: 'ignore' is not allowed in this context
2597+
ERROR HY000: Default/ignore value is not supported for such parameter usage
25982598
EXECUTE IMMEDIATE 'VALUES (?)' USING DEFAULT;
2599-
ERROR HY000: 'default' is not allowed in this context
2599+
ERROR HY000: Default/ignore value is not supported for such parameter usage
26002600
#
26012601
# MDEV-24675: TVC using subqueries
26022602
#

mysql-test/main/table_value_constr.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,9 +1349,9 @@ DELIMITER ;$$
13491349
VALUES (IGNORE);
13501350
--error ER_UNKNOWN_ERROR
13511351
VALUES (DEFAULT);
1352-
--error ER_UNKNOWN_ERROR
1352+
--error ER_INVALID_DEFAULT_PARAM
13531353
EXECUTE IMMEDIATE 'VALUES (?)' USING IGNORE;
1354-
--error ER_UNKNOWN_ERROR
1354+
--error ER_INVALID_DEFAULT_PARAM
13551355
EXECUTE IMMEDIATE 'VALUES (?)' USING DEFAULT;
13561356

13571357
--echo #

sql/field.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,9 @@ bool Field::sp_prepare_and_store_item(THD *thd, Item **value)
13531353
if (!(expr_item= thd->sp_prepare_func_item(value, 1)))
13541354
goto error;
13551355

1356+
if (expr_item->check_is_evaluable_expression_or_error())
1357+
goto error;
1358+
13561359
/*
13571360
expr_item is now fixed, it's safe to call cmp_type()
13581361
*/
@@ -11424,6 +11427,30 @@ bool Field::validate_value_in_record_with_warn(THD *thd, const uchar *record)
1142411427
}
1142511428

1142611429

11430+
/**
11431+
Find which reaction should be for IGNORE value.
11432+
*/
11433+
11434+
ignore_value_reaction find_ignore_reaction(THD *thd)
11435+
{
11436+
enum_sql_command com= thd->lex->sql_command;
11437+
11438+
// All insert-like commands
11439+
if (com == SQLCOM_INSERT || com == SQLCOM_REPLACE ||
11440+
com == SQLCOM_INSERT_SELECT || com == SQLCOM_REPLACE_SELECT ||
11441+
com == SQLCOM_LOAD)
11442+
{
11443+
return IGNORE_MEANS_DEFAULT;
11444+
}
11445+
// Update commands
11446+
if (com == SQLCOM_UPDATE || com == SQLCOM_UPDATE_MULTI)
11447+
{
11448+
return IGNORE_MEANS_FIELD_VALUE;
11449+
}
11450+
return IGNORE_MEANS_ERROR;
11451+
}
11452+
11453+
1142711454
bool Field::save_in_field_default_value(bool view_error_processing)
1142811455
{
1142911456
THD *thd= table->in_use;

sql/field.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ enum enum_check_fields
6060
CHECK_FIELD_ERROR_FOR_NULL,
6161
};
6262

63+
enum ignore_value_reaction
64+
{
65+
IGNORE_MEANS_ERROR,
66+
IGNORE_MEANS_DEFAULT,
67+
IGNORE_MEANS_FIELD_VALUE
68+
};
69+
70+
ignore_value_reaction find_ignore_reaction(THD *thd);
71+
6372
/*
6473
Common declarations for Field and Item
6574
*/

0 commit comments

Comments
 (0)