summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/main/table_value_constr.result42
-rw-r--r--mysql-test/main/table_value_constr.test46
-rw-r--r--sql/sql_tvc.cc8
3 files changed, 94 insertions, 2 deletions
diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result
index 1d1cd054556..7ff5fb7fa5e 100644
--- a/mysql-test/main/table_value_constr.result
+++ b/mysql-test/main/table_value_constr.result
@@ -3100,4 +3100,46 @@ select * from (values (3),(7),(1) union values (2),(4) order by 1 limit 2) as dt
1
2
drop table t1;
+#
+# MDEV-23182: Server crashes in
+# Item::fix_fields_if_needed / table_value_constr::prepare upon 2nd execution of PS
+#
+SET @save_in_predicate_conversion_threshold=@@in_predicate_conversion_threshold;
+SET in_predicate_conversion_threshold=2;
+CREATE TABLE t1 (c VARCHAR(10)) DEFAULT CHARSET=utf8;
+PREPARE stmt FROM "SELECT * FROM t1 WHERE c IN ('10','20')";
+EXECUTE stmt;
+c
+# Without the patch second execution of the prepared statement 'stmt'
+# results in crash.
+EXECUTE stmt;
+c
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+# Check that the query without conversion doesn't crash server
+CREATE TABLE t1 (c VARCHAR(10));
+PREPARE stmt FROM "SELECT * FROM t1 WHERE c IN ('10','20')";
+EXECUTE stmt;
+c
+EXECUTE stmt;
+c
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+# Test case for a row expression in the left part of the IN clause
+CREATE TABLE t1 (a VARCHAR(3), b VARCHAR(3)) DEFAULT CHARSET=utf8;
+PREPARE stmt FROM "SELECT * FROM t1 WHERE (a, b) IN (('10', '10'), ('20', '20'))";
+EXECUTE stmt;
+a b
+EXECUTE stmt;
+a b
+DROP TABLE t1;
+# Check that the query without conversion is handled successfully
+CREATE TABLE t1 (a VARCHAR(3), b VARCHAR(3));
+PREPARE stmt FROM "SELECT * FROM t1 WHERE (a, b) IN (('10', '10'), ('20', '20'))";
+EXECUTE stmt;
+a b
+EXECUTE stmt;
+a b
+DROP TABLE t1;
+SET @@in_predicate_conversion_threshold = @save_in_predicate_conversion_threshold;
End of 10.3 tests
diff --git a/mysql-test/main/table_value_constr.test b/mysql-test/main/table_value_constr.test
index d13962579cc..673e7dcdc6e 100644
--- a/mysql-test/main/table_value_constr.test
+++ b/mysql-test/main/table_value_constr.test
@@ -1650,4 +1650,50 @@ select * from (values (3),(7),(1) union values (2),(4) order by 1 limit 2) as dt
drop table t1;
+--echo #
+--echo # MDEV-23182: Server crashes in
+--echo # Item::fix_fields_if_needed / table_value_constr::prepare upon 2nd execution of PS
+--echo #
+SET @save_in_predicate_conversion_threshold=@@in_predicate_conversion_threshold;
+SET in_predicate_conversion_threshold=2;
+
+CREATE TABLE t1 (c VARCHAR(10)) DEFAULT CHARSET=utf8;
+PREPARE stmt FROM "SELECT * FROM t1 WHERE c IN ('10','20')";
+EXECUTE stmt;
+--echo # Without the patch second execution of the prepared statement 'stmt'
+--echo # results in crash.
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+
+DROP TABLE t1;
+
+--echo # Check that the query without conversion doesn't crash server
+CREATE TABLE t1 (c VARCHAR(10));
+PREPARE stmt FROM "SELECT * FROM t1 WHERE c IN ('10','20')";
+EXECUTE stmt;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+
+DROP TABLE t1;
+
+--echo # Test case for a row expression in the left part of the IN clause
+CREATE TABLE t1 (a VARCHAR(3), b VARCHAR(3)) DEFAULT CHARSET=utf8;
+PREPARE stmt FROM "SELECT * FROM t1 WHERE (a, b) IN (('10', '10'), ('20', '20'))";
+
+EXECUTE stmt;
+EXECUTE stmt;
+
+DROP TABLE t1;
+
+--echo # Check that the query without conversion is handled successfully
+CREATE TABLE t1 (a VARCHAR(3), b VARCHAR(3));
+PREPARE stmt FROM "SELECT * FROM t1 WHERE (a, b) IN (('10', '10'), ('20', '20'))";
+
+EXECUTE stmt;
+EXECUTE stmt;
+
+DROP TABLE t1;
+
+SET @@in_predicate_conversion_threshold = @save_in_predicate_conversion_threshold;
+
--echo End of 10.3 tests
diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc
index 96c5223ee6a..3866b7c9352 100644
--- a/sql/sql_tvc.cc
+++ b/sql/sql_tvc.cc
@@ -539,7 +539,10 @@ bool Item_func_in::create_value_list_for_tvc(THD *thd,
if (is_list_of_rows)
{
- Item_row *row_list= (Item_row *)(args[i]);
+ Item_row *row_list= (Item_row *)(args[i]->build_clone(thd));
+
+ if (!row_list)
+ return true;
for (uint j=0; j < row_list->cols(); j++)
{
@@ -561,7 +564,8 @@ bool Item_func_in::create_value_list_for_tvc(THD *thd,
sprintf(col_name, "_col_%i", 1);
args[i]->set_name(thd, col_name, strlen(col_name), thd->charset());
}
- if (tvc_value->push_back(args[i]->real_item()))
+ Item *arg_clone= args[i]->build_clone(thd);
+ if (!arg_clone || tvc_value->push_back(arg_clone))
return true;
}