From 80067a69feaeb5df30abb1bfaf7d4e713ccbf027 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Mon, 10 Feb 2025 22:22:39 +0200 Subject: [PATCH] MDEV-36057: Assertion failure on 2nd execution of parameterized PS Followup to fix for MDEV-35318: In Prepared_statement::execute_loop(), if we enter this function with lex->needs_reprepare=true, we need to re-prepare the statement. We also need to call set_parameters() to get PS parameter values. We failed to do this and that's the bug. Note that we need to also handle the other reprepare scenario: when we get into Prepared_statement::execute_loop(), call set_parameters() and then hit a "DDL was changed" error with reprepare_observer, we should NOT call set_parameters() again. The parameters have already been transferred to the reprepared statement in Prepared_statement::reprepare()|swap_parameter_array(). --- mysql-test/main/create.result | 12 ++++++++++++ mysql-test/main/create.test | 14 ++++++++++++++ sql/sql_prepare.cc | 7 +++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/create.result b/mysql-test/main/create.result index 55521c18b76..46d8d68121c 100644 --- a/mysql-test/main/create.result +++ b/mysql-test/main/create.result @@ -2116,4 +2116,16 @@ Warnings: Note 1051 Unknown table 'test.tmp' DROP PROCEDURE sp1; DROP TABLE t; +# +# MDEV-36057: Assertion failure or unexpected outcome upon 2nd execution +# of parameterized PS (continues the above) +# +CREATE TABLE t (a INT); +INSERT INTO t VALUES (1),(2); +PREPARE stmt FROM 'UPDATE t SET a = 3 WHERE a IN (SELECT "" UNION SELECT ?)'; +EXECUTE stmt USING 4; +ERROR 22007: Truncated incorrect DECIMAL value: '' +EXECUTE stmt USING 4; +ERROR 22007: Truncated incorrect DECIMAL value: '' +DROP TABLE t; # End of 11.7 Test diff --git a/mysql-test/main/create.test b/mysql-test/main/create.test index 1213c8be6e0..bb0c6347f2e 100644 --- a/mysql-test/main/create.test +++ b/mysql-test/main/create.test @@ -1987,4 +1987,18 @@ call sp1(); DROP PROCEDURE sp1; DROP TABLE t; +--echo # +--echo # MDEV-36057: Assertion failure or unexpected outcome upon 2nd execution +--echo # of parameterized PS (continues the above) +--echo # +CREATE TABLE t (a INT); +INSERT INTO t VALUES (1),(2); + +PREPARE stmt FROM 'UPDATE t SET a = 3 WHERE a IN (SELECT "" UNION SELECT ?)'; +--error ER_TRUNCATED_WRONG_VALUE +EXECUTE stmt USING 4; +--error ER_TRUNCATED_WRONG_VALUE +EXECUTE stmt USING 4; +DROP TABLE t; + --echo # End of 11.7 Test diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 1fa872b8d55..0488b6de558 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -4390,6 +4390,7 @@ Prepared_statement::execute_loop(String *expanded_query, Reprepare_observer reprepare_observer; bool error; iterations= FALSE; + bool params_are_set= false; /* - In mysql_sql_stmt_execute() we hide all "external" Items @@ -4415,8 +4416,10 @@ Prepared_statement::execute_loop(String *expanded_query, return TRUE; } - if (set_parameters(expanded_query, packet, packet_end)) +reexecute: + if (!params_are_set && set_parameters(expanded_query, packet, packet_end)) return TRUE; + params_are_set= true; #ifdef WITH_WSREP if (thd->wsrep_delayed_BF_abort) { @@ -4424,7 +4427,7 @@ Prepared_statement::execute_loop(String *expanded_query, return TRUE; } #endif /* WITH_WSREP */ -reexecute: + // Make sure that reprepare() did not create any new Items. DBUG_ASSERT(thd->free_list == NULL);