Details
-
Bug
-
Status: Open (View Workflow)
-
Major
-
Resolution: Unresolved
-
10.11, 11.4
-
None
Description
Bulk execution (COM_STMT_BULK_EXECUTE) of DELETE ... RETURNING crashes the server when the first parameter set needs a reprepare (for example after ALTER TABLE between prepare and execute).
How to repeat
Connector/C, array binding (STMT_ATTR_ARRAY_SIZE = 3):
mysql_query(m, "CREATE OR REPLACE TABLE tr (id INT PRIMARY KEY)"); |
mysql_query(m, "INSERT INTO tr VALUES (1),(2),(3),(4)"); |
stmt= mysql_stmt_init(m);
|
mysql_stmt_prepare(stmt, "DELETE FROM tr WHERE id=? RETURNING id", -1); |
mysql_query(m, "ALTER TABLE tr ADD COLUMN x INT"); /* forces reprepare */ |
int id[3]= {1, 2, 3}; |
unsigned int n= 3; |
MYSQL_BIND b;
|
memset(&b, 0, sizeof(b)); |
b.buffer_type= MYSQL_TYPE_LONG;
|
b.buffer= id;
|
mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &n);
|
mysql_stmt_bind_param(stmt, &b);
|
mysql_stmt_execute(stmt); /* server crashes */ |
Reproduced on 10.11 (10.11.19 debug) and 11.4 (11.4.13 debug, source revision 4813c2f0a8a79e4e4c000cc8c9447096fafe7033):
got signal 11 ;
|
sql/protocol.cc:1744(Protocol_binary::prepare_for_resend())
|
sql/sql_class.cc:3289(select_send::send_data(List<Item>&))
|
sql/sql_delete.cc:899(Sql_cmd_delete::delete_from_single_table(THD*))
|
sql/sql_delete.cc:1915(Sql_cmd_delete::execute_inner(THD*))
|
sql/sql_select.cc:34838(Sql_cmd_dml::execute(THD*))
|
sql/sql_parse.cc:4451(mysql_execute_command(THD*, bool))
|
sql/sql_prepare.cc:5119(Prepared_statement::execute(String*, bool))
|
sql/sql_prepare.cc:4697(Prepared_statement::execute_bulk_loop(String*, bool, unsigned char*, unsigned char*))
|
sql/sql_prepare.cc:3410(mysql_stmt_execute_common(...))
|
sql/sql_prepare.cc:3235(mysqld_stmt_bulk_execute(THD*, char*, unsigned int))
|
sql/sql_parse.cc:1838(dispatch_command(...))
|
Cause
The DELETE code sends the RETURNING result set metadata only if !thd->get_stmt_da()->is_set(). It uses that test to recognise the first iteration of a non-optimized bulk operation.
When the first iteration fails with ER_NEED_REPREPARE, execute_bulk_loop() calls thd->clear_error(). In bulk mode, Diagnostics_area::reset_diagnostics_area() then sets m_status= DA_OK_BULK. After the reprepare, is_set() is already true in the first iteration, so the metadata is never sent and send_data() crashes.
The "metadata already sent" state should be tracked explicitly rather than derived from the diagnostics area. MDEV-23864 uses the same guard for INSERT ... RETURNING executed per parameter set, so a fix should cover both.
Attachments
Issue Links
- relates to
-
MDEV-23864 BULK insert wrong values when command contain inner select
-
- Closed
-
-
MDEV-41511 Bulk DELETE ... RETURNING * sends rows that do not match the result set metadata when the table changes between parameter sets
-
- Open
-
-
MDEV-41512 Bulk execution loses warnings of earlier parameter sets when the statement is reprepared
-
- Open
-