Commit fad1d153 authored by Rucha Deodhar's avatar Rucha Deodhar

MDEV-25460: Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())'

failed in Diagnostics_area::set_ok_status in my_ok from
mysql_sql_stmt_prepare

Analysis: Before PREPARE is executed, binlog_format is STATEMENT.
This PREPARE had SET STATEMENT which sets binlog_format to ROW. Now after
PREPARE is done we reset the binlog_format (back to STATEMENT). But we have
temporary table, it doesn't let changing binlog_format=ROW to
binlog_format=STATEMENT and gives error which goes unreported. This
unreported error eventually causes assertion failure.
Fix: Change return type for LEX::restore_set_statement_var() to bool and
make it return error state.
parent 4daf9d7c
...@@ -1921,3 +1921,28 @@ let $MYSQLD_DATADIR= `select @@datadir`; ...@@ -1921,3 +1921,28 @@ let $MYSQLD_DATADIR= `select @@datadir`;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Beginning of 10.2 test
--echo #
--echo # MDEV-25460: Assertion `!is_set() || (m_status == DA_OK_BULK &&
--echo # is_bulk_op())' failed in Diagnostics_area::set_ok_status in my_ok
--echo # from mysql_sql_stmt_prepare
--echo #
CREATE TEMPORARY TABLE a (c INT) ENGINE=InnoDB;
CREATE TABLE b (c INT) ENGINE=InnoDB;
--error ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT * FROM b';
DROP TABLE b;
DROP TEMPORARY TABLE a;
CREATE TEMPORARY TABLE t (c INT);
--error ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT 1';
DROP TEMPORARY TABLE t;
--echo #
--echo # End of 10.2 test
--echo #
...@@ -6352,3 +6352,23 @@ ROLLBACK /* added by mysqlbinlog */; ...@@ -6352,3 +6352,23 @@ ROLLBACK /* added by mysqlbinlog */;
# Cleanup. # Cleanup.
# #
DROP TABLE t1; DROP TABLE t1;
#
# Beginning of 10.2 test
#
# MDEV-25460: Assertion `!is_set() || (m_status == DA_OK_BULK &&
# is_bulk_op())' failed in Diagnostics_area::set_ok_status in my_ok
# from mysql_sql_stmt_prepare
#
CREATE TEMPORARY TABLE a (c INT) ENGINE=InnoDB;
CREATE TABLE b (c INT) ENGINE=InnoDB;
PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT * FROM b';
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
DROP TABLE b;
DROP TEMPORARY TABLE a;
CREATE TEMPORARY TABLE t (c INT);
PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT 1';
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
DROP TEMPORARY TABLE t;
#
# End of 10.2 test
#
...@@ -6393,3 +6393,29 @@ ROLLBACK /* added by mysqlbinlog */; ...@@ -6393,3 +6393,29 @@ ROLLBACK /* added by mysqlbinlog */;
# Cleanup. # Cleanup.
# #
DROP TABLE t1; DROP TABLE t1;
#
# Beginning of 10.2 test
#
# MDEV-25460: Assertion `!is_set() || (m_status == DA_OK_BULK &&
# is_bulk_op())' failed in Diagnostics_area::set_ok_status in my_ok
# from mysql_sql_stmt_prepare
#
CREATE TEMPORARY TABLE a (c INT) ENGINE=InnoDB;
Warnings:
Warning 1286 Unknown storage engine 'InnoDB'
Warning 1266 Using storage engine MyISAM for table 'a'
CREATE TABLE b (c INT) ENGINE=InnoDB;
Warnings:
Warning 1286 Unknown storage engine 'InnoDB'
Warning 1266 Using storage engine MyISAM for table 'b'
PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT * FROM b';
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
DROP TABLE b;
DROP TEMPORARY TABLE a;
CREATE TEMPORARY TABLE t (c INT);
PREPARE s FROM 'SET STATEMENT binlog_format=ROW FOR SELECT 1';
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
DROP TEMPORARY TABLE t;
#
# End of 10.2 test
#
...@@ -4766,18 +4766,19 @@ void LEX::free_arena_for_set_stmt() ...@@ -4766,18 +4766,19 @@ void LEX::free_arena_for_set_stmt()
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
void LEX::restore_set_statement_var() bool LEX::restore_set_statement_var()
{ {
bool err= false;
DBUG_ENTER("LEX::restore_set_statement_var"); DBUG_ENTER("LEX::restore_set_statement_var");
if (!old_var_list.is_empty()) if (!old_var_list.is_empty())
{ {
DBUG_PRINT("info", ("vars: %d", old_var_list.elements)); DBUG_PRINT("info", ("vars: %d", old_var_list.elements));
sql_set_variables(thd, &old_var_list, false); err= sql_set_variables(thd, &old_var_list, false);
old_var_list.empty(); old_var_list.empty();
free_arena_for_set_stmt(); free_arena_for_set_stmt();
} }
DBUG_ASSERT(!is_arena_for_set_stmt()); DBUG_ASSERT(!is_arena_for_set_stmt());
DBUG_VOID_RETURN; DBUG_RETURN(err);
} }
/* /*
......
...@@ -3094,7 +3094,7 @@ struct LEX: public Query_tables_list ...@@ -3094,7 +3094,7 @@ struct LEX: public Query_tables_list
int print_explain(select_result_sink *output, uint8 explain_flags, int print_explain(select_result_sink *output, uint8 explain_flags,
bool is_analyze, bool *printed_anything); bool is_analyze, bool *printed_anything);
void restore_set_statement_var(); bool restore_set_statement_var();
void init_last_field(Column_definition *field, const char *name, CHARSET_INFO *cs); void init_last_field(Column_definition *field, const char *name, CHARSET_INFO *cs);
void set_last_field_type(const Lex_field_type_st &type); void set_last_field_type(const Lex_field_type_st &type);
......
...@@ -4283,7 +4283,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) ...@@ -4283,7 +4283,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
Restore original values of variables modified on handling Restore original values of variables modified on handling
SET STATEMENT clause. SET STATEMENT clause.
*/ */
thd->lex->restore_set_statement_var(); error|= thd->lex->restore_set_statement_var();
/* The order is important */ /* The order is important */
lex->unit.cleanup(); lex->unit.cleanup();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment