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().
This commit is contained in:
Sergei Petrunia 2025-02-10 22:22:39 +02:00
parent 2d971709a8
commit 80067a69fe
3 changed files with 31 additions and 2 deletions

View file

@ -2116,4 +2116,16 @@ Warnings:
Note 1051 Unknown table 'test.tmp' Note 1051 Unknown table 'test.tmp'
DROP PROCEDURE sp1; DROP PROCEDURE sp1;
DROP TABLE t; 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 # End of 11.7 Test

View file

@ -1987,4 +1987,18 @@ call sp1();
DROP PROCEDURE sp1; DROP PROCEDURE sp1;
DROP TABLE t; 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 --echo # End of 11.7 Test

View file

@ -4390,6 +4390,7 @@ Prepared_statement::execute_loop(String *expanded_query,
Reprepare_observer reprepare_observer; Reprepare_observer reprepare_observer;
bool error; bool error;
iterations= FALSE; iterations= FALSE;
bool params_are_set= false;
/* /*
- In mysql_sql_stmt_execute() we hide all "external" Items - In mysql_sql_stmt_execute() we hide all "external" Items
@ -4415,8 +4416,10 @@ Prepared_statement::execute_loop(String *expanded_query,
return TRUE; return TRUE;
} }
if (set_parameters(expanded_query, packet, packet_end)) reexecute:
if (!params_are_set && set_parameters(expanded_query, packet, packet_end))
return TRUE; return TRUE;
params_are_set= true;
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (thd->wsrep_delayed_BF_abort) if (thd->wsrep_delayed_BF_abort)
{ {
@ -4424,7 +4427,7 @@ Prepared_statement::execute_loop(String *expanded_query,
return TRUE; return TRUE;
} }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
reexecute:
// Make sure that reprepare() did not create any new Items. // Make sure that reprepare() did not create any new Items.
DBUG_ASSERT(thd->free_list == NULL); DBUG_ASSERT(thd->free_list == NULL);