Commit 151f9673 authored by Nirbhay Choubey's avatar Nirbhay Choubey

MDEV-7640: CHANGE MASTER TO doesn't work with prepared statements

When CHANGE MASTER was executed as a PS, its attributes were wrongly
getting reset toward the end of PREPARE. As a result, the subsequent
executions had no effect. Fixed by making sure that the CHANGE MASTER
attributes are preserved during the lifetime of the PS.
parent e7cb032e
#
# CHANGE MASTER TO doesn't work with prepared statements
#
CHANGE MASTER TO MASTER_HOST='host1', MASTER_USER='user1';
# Master_Host : host1
# Master_User : user1
SET @s := "CHANGE MASTER TO MASTER_HOST='host2'";
PREPARE stmt FROM @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# Master_Host : host2
# Master_User : user1
SET @s := "CHANGE MASTER TO MASTER_USER='user2'";
PREPARE stmt FROM @s;
EXECUTE stmt;
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# Master_Host : host2
# Master_User : user2
CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root';
# End of test
--source include/not_embedded.inc
--source include/have_log_bin.inc
--echo #
--echo # CHANGE MASTER TO doesn't work with prepared statements
--echo #
CHANGE MASTER TO MASTER_HOST='host1', MASTER_USER='user1';
let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1);
--echo # Master_Host : $master_host
--echo # Master_User : $master_user
SET @s := "CHANGE MASTER TO MASTER_HOST='host2'";
PREPARE stmt FROM @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1);
--echo # Master_Host : $master_host
--echo # Master_User : $master_user
SET @s := "CHANGE MASTER TO MASTER_USER='user2'";
PREPARE stmt FROM @s;
EXECUTE stmt;
# Multiple executions should not hurt.
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1);
--echo # Master_Host : $master_host
--echo # Master_User : $master_user
# Reset
CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root';
--echo # End of test
......@@ -568,6 +568,16 @@ void lex_end(LEX *lex)
DBUG_ENTER("lex_end");
DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex));
lex_end_stage1(lex);
lex_end_stage2(lex);
DBUG_VOID_RETURN;
}
void lex_end_stage1(LEX *lex)
{
DBUG_ENTER("lex_end_stage1");
/* release used plugins */
if (lex->plugins.elements) /* No function call and no mutex if no plugins. */
{
......@@ -579,6 +589,19 @@ void lex_end(LEX *lex)
delete lex->sphead;
lex->sphead= NULL;
DBUG_VOID_RETURN;
}
/*
MASTER INFO parameters (or state) is normally cleared towards the end
of a statement. But in case of PS, the state needs to be preserved during
its lifetime and should only be cleared on PS close or deallocation.
*/
void lex_end_stage2(LEX *lex)
{
DBUG_ENTER("lex_end_stage2");
/* Reset LEX_MASTER_INFO */
lex->mi.reset();
DBUG_VOID_RETURN;
......
......@@ -2947,6 +2947,8 @@ extern void lex_init(void);
extern void lex_free(void);
extern void lex_start(THD *thd);
extern void lex_end(LEX *lex);
extern void lex_end_stage1(LEX *lex);
extern void lex_end_stage2(LEX *lex);
void end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex);
int init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex);
extern int MYSQLlex(union YYSTYPE *yylval, THD *thd);
......
......@@ -3456,7 +3456,8 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
thd->mdl_context.release_transactional_locks();
}
lex_end(lex);
/* Preserve CHANGE MASTER attributes */
lex_end_stage1(lex);
cleanup_stmt();
thd->restore_backup_statement(this, &stmt_backup);
thd->stmt_arena= old_stmt_arena;
......@@ -4056,6 +4057,10 @@ void Prepared_statement::deallocate()
{
/* We account deallocate in the same manner as mysqld_stmt_close */
status_var_increment(thd->status_var.com_stmt_close);
/* It should now be safe to reset CHANGE MASTER parameters */
lex_end_stage2(lex);
/* Statement map calls delete stmt on erase */
thd->stmt_map.erase(this);
}
......
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