summaryrefslogtreecommitdiff
path: root/sql/sql_db.cc
diff options
context:
space:
mode:
authorunknown <anozdrin/alik@ibm.opbmk>2007-08-31 20:42:14 +0400
committerunknown <anozdrin/alik@ibm.opbmk>2007-08-31 20:42:14 +0400
commit7e0ad09edff587dadc3e9855fc81e1b7de8f2199 (patch)
tree38c6a445d870a736939fb8fa36bb8dc40fb08e20 /sql/sql_db.cc
parent3edb630197ae42353905325e9d1c8e78d329c23a (diff)
downloadmariadb-git-7e0ad09edff587dadc3e9855fc81e1b7de8f2199.tar.gz
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. mysql-test/include/query_cache_sql_prepare.inc: The first part of the test case for BUG#25843. mysql-test/r/query_cache_ps_no_prot.result: Update result file. mysql-test/r/query_cache_ps_ps_prot.result: Update result file. mysql-test/suite/rpl/r/rpl_ps.result: Update result file. mysql-test/suite/rpl/t/rpl_ps.test: The second part of the test case for BUG#25843. sql/mysql_priv.h: Added mysql_opt_change_db() prototype. sql/sp.cc: 1. Polishing; 2. sp_use_new_db() has been removed; 3. Use mysql_opt_change_db() instead of sp_use_new_db(). sql/sp.h: sp_use_new_db() has been removed. This function has nothing to do with a) sp and b) *new* database. It was merely "switch the current database if needed". sql/sp_head.cc: 1. Polishing. 2. Use mysql_opt_change_db() instead of sp_use_new_db(). sql/sql_class.cc: Move THD::{db, db_length} into Statement. sql/sql_class.h: Move THD::{db, db_length} into Statement. sql/sql_db.cc: Introduce mysql_opt_change_db() as a replacement (and inspired by) sp_use_new_db(). sql/sql_prepare.cc: 1. Remember the current database in Prepared_statement::prepare(). 2. Switch/restore the current database in Prepared_statement::execute().
Diffstat (limited to 'sql/sql_db.cc')
-rw-r--r--sql/sql_db.cc98
1 files changed, 97 insertions, 1 deletions
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 207c48b45f0..228c56afb13 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -1350,8 +1350,67 @@ static void mysql_change_db_impl(THD *thd,
}
+
+/**
+ Backup the current database name before switch.
+
+ @param[in] thd thread handle
+ @param[in, out] saved_db_name IN: "str" points to a buffer where to store
+ the old database name, "length" contains the
+ buffer size
+ OUT: if the current (default) database is
+ not NULL, its name is copied to the
+ buffer pointed at by "str"
+ and "length" is updated accordingly.
+ Otherwise "str" is set to NULL and
+ "length" is set to 0.
+*/
+
+static void backup_current_db_name(THD *thd,
+ LEX_STRING *saved_db_name)
+{
+ if (!thd->db)
+ {
+ /* No current (default) database selected. */
+
+ saved_db_name->str= NULL;
+ saved_db_name->length= 0;
+ }
+ else
+ {
+ strmake(saved_db_name->str, thd->db, saved_db_name->length);
+ saved_db_name->length= thd->db_length;
+ }
+}
+
+
+/**
+ Return TRUE if db1_name is equal to db2_name, FALSE otherwise.
+
+ The function allows to compare database names according to the MySQL
+ rules. The database names db1 and db2 are equal if:
+ - db1 is NULL and db2 is NULL;
+ or
+ - db1 is not-NULL, db2 is not-NULL, db1 is equal (ignoring case) to
+ db2 in system character set (UTF8).
+*/
+
+static inline bool
+cmp_db_names(const char *db1_name,
+ const char *db2_name)
+{
+ return
+ /* db1 is NULL and db2 is NULL */
+ !db1_name && !db2_name ||
+
+ /* db1 is not-NULL, db2 is not-NULL, db1 == db2. */
+ db1_name && db2_name &&
+ my_strcasecmp(system_charset_info, db1_name, db2_name) == 0;
+}
+
+
/**
- @brief Change the current database and its attributes.
+ @brief Change the current database and its attributes unconditionally.
@param thd thread handle
@param new_db_name database name
@@ -1568,6 +1627,43 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
}
+/**
+ Change the current database and its attributes if needed.
+
+ @param thd thread handle
+ @param new_db_name database name
+ @param[in, out] saved_db_name IN: "str" points to a buffer where to store
+ the old database name, "length" contains the
+ buffer size
+ OUT: if the current (default) database is
+ not NULL, its name is copied to the
+ buffer pointed at by "str"
+ and "length" is updated accordingly.
+ Otherwise "str" is set to NULL and
+ "length" is set to 0.
+ @param force_switch @see mysql_change_db()
+ @param[out] cur_db_changed out-flag to indicate whether the current
+ database has been changed (valid only if
+ the function suceeded)
+*/
+
+bool mysql_opt_change_db(THD *thd,
+ const LEX_STRING *new_db_name,
+ LEX_STRING *saved_db_name,
+ bool force_switch,
+ bool *cur_db_changed)
+{
+ *cur_db_changed= !cmp_db_names(thd->db, new_db_name->str);
+
+ if (!*cur_db_changed)
+ return FALSE;
+
+ backup_current_db_name(thd, saved_db_name);
+
+ return mysql_change_db(thd, new_db_name, force_switch);
+}
+
+
static int
lock_databases(THD *thd, const char *db1, uint length1,
const char *db2, uint length2)