mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Fix for BUG#25843: changing default database between PREPARE and EXECUTE
of statement breaks binlog.
There were two problems discovered by this bug:
1. Default (current) database is not fixed at the creation time.
That leads to wrong output of DATABASE() function.
2. Database attributes (@@collation_database) are not fixed at
the creation time. That leads to wrong resultset.
Binlog breakage and Query Cache wrong output happened because of
the first problem.
The fix is to remember the current database at the PREPARE-time and
set it each time at EXECUTE.
This commit is contained in:
@@ -2868,6 +2868,19 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
||||
init_param_array(this);
|
||||
lex->set_trg_event_type_for_tables();
|
||||
|
||||
/* Remember the current database. */
|
||||
|
||||
if (thd->db && thd->db_length)
|
||||
{
|
||||
db= this->strmake(thd->db, thd->db_length);
|
||||
db_length= thd->db_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
db= NULL;
|
||||
db_length= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
While doing context analysis of the query (in check_prepared_statement)
|
||||
we allocate a lot of additional memory: for open tables, JOINs, derived
|
||||
@@ -2974,6 +2987,13 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
|
||||
Query_arena *old_stmt_arena;
|
||||
bool error= TRUE;
|
||||
|
||||
char saved_cur_db_name_buf[NAME_LEN+1];
|
||||
LEX_STRING saved_cur_db_name=
|
||||
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
|
||||
bool cur_db_changed;
|
||||
|
||||
LEX_STRING stmt_db_name= { db, db_length };
|
||||
|
||||
status_var_increment(thd->status_var.com_stmt_execute);
|
||||
|
||||
/* Check if we got an error when sending long data */
|
||||
@@ -3022,6 +3042,21 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
|
||||
*/
|
||||
|
||||
thd->set_n_backup_statement(this, &stmt_backup);
|
||||
|
||||
/*
|
||||
Change the current database (if needed).
|
||||
|
||||
Force switching, because the database of the prepared statement may be
|
||||
NULL (prepared statements can be created while no current database
|
||||
selected).
|
||||
*/
|
||||
|
||||
if (mysql_opt_change_db(thd, &stmt_db_name, &saved_cur_db_name, TRUE,
|
||||
&cur_db_changed))
|
||||
goto error;
|
||||
|
||||
/* Allocate query. */
|
||||
|
||||
if (expanded_query->length() &&
|
||||
alloc_query(thd, (char*) expanded_query->ptr(),
|
||||
expanded_query->length()+1))
|
||||
@@ -3050,6 +3085,8 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
|
||||
|
||||
thd->protocol= protocol; /* activate stmt protocol */
|
||||
|
||||
/* Go! */
|
||||
|
||||
if (open_cursor)
|
||||
error= mysql_open_cursor(thd, (uint) ALWAYS_MATERIALIZED_CURSOR,
|
||||
&result, &cursor);
|
||||
@@ -3068,6 +3105,17 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Restore the current database (if changed).
|
||||
|
||||
Force switching back to the saved current database (if changed),
|
||||
because it may be NULL. In this case, mysql_change_db() would generate
|
||||
an error.
|
||||
*/
|
||||
|
||||
if (cur_db_changed)
|
||||
mysql_change_db(thd, &saved_cur_db_name, TRUE);
|
||||
|
||||
thd->protocol= &thd->protocol_text; /* use normal protocol */
|
||||
|
||||
/* Assert that if an error, no cursor is open */
|
||||
|
||||
Reference in New Issue
Block a user