diff options
author | Rucha Deodhar <rucha.deodhar@mariadb.com> | 2021-12-15 13:59:38 +0530 |
---|---|---|
committer | Rucha Deodhar <rucha.deodhar@mariadb.com> | 2021-12-28 16:59:29 +0530 |
commit | fad1d15326651a92895c799829ff66edc37fc20f (patch) | |
tree | 42ec5b7784677b579b7655afaaaa880af270551f | |
parent | 4daf9d7c3ee05baf7643f3a866e6d3828e1bb93b (diff) | |
download | mariadb-git-fad1d15326651a92895c799829ff66edc37fc20f.tar.gz |
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.
-rw-r--r-- | mysql-test/extra/binlog_tests/mysqlbinlog_row_engine.inc | 25 | ||||
-rw-r--r-- | mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result | 20 | ||||
-rw-r--r-- | mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result | 26 | ||||
-rw-r--r-- | sql/sql_lex.cc | 7 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 2 |
6 files changed, 77 insertions, 5 deletions
diff --git a/mysql-test/extra/binlog_tests/mysqlbinlog_row_engine.inc b/mysql-test/extra/binlog_tests/mysqlbinlog_row_engine.inc index ce919550b51..874be1dac61 100644 --- a/mysql-test/extra/binlog_tests/mysqlbinlog_row_engine.inc +++ b/mysql-test/extra/binlog_tests/mysqlbinlog_row_engine.inc @@ -1921,3 +1921,28 @@ let $MYSQLD_DATADIR= `select @@datadir`; 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 # diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result index 388bec68db7..cfd89c661dc 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result @@ -6352,3 +6352,23 @@ ROLLBACK /* added by mysqlbinlog */; # Cleanup. # 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 +# diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result index 44dbbba8eab..77bb25e5971 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result @@ -6393,3 +6393,29 @@ ROLLBACK /* added by mysqlbinlog */; # Cleanup. # 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 +# diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index ed0b4b36553..125bbfe1bfd 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -4766,18 +4766,19 @@ void LEX::free_arena_for_set_stmt() 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"); if (!old_var_list.is_empty()) { 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(); free_arena_for_set_stmt(); } DBUG_ASSERT(!is_arena_for_set_stmt()); - DBUG_VOID_RETURN; + DBUG_RETURN(err); } /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index bdf52e8ef7b..5585a95f67f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3094,7 +3094,7 @@ public: int print_explain(select_result_sink *output, uint8 explain_flags, 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 set_last_field_type(const Lex_field_type_st &type); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 9339cb925e5..bb1a99d9eef 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -4283,7 +4283,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) Restore original values of variables modified on handling SET STATEMENT clause. */ - thd->lex->restore_set_statement_var(); + error|= thd->lex->restore_set_statement_var(); /* The order is important */ lex->unit.cleanup(); |