summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorguilhem@mysql.com <>2004-06-09 16:07:01 +0200
committerguilhem@mysql.com <>2004-06-09 16:07:01 +0200
commit2b20e84ff8c5df05c42d3dfedf0b38649fea8308 (patch)
tree1003fd9ceb90dc1ddeb6db7ff4e98d8da2cc51c4 /sql
parentc75b24a73a0852daafec21d3c9cadd3cbe892c9d (diff)
downloadmariadb-git-2b20e84ff8c5df05c42d3dfedf0b38649fea8308.tar.gz
Making DROP TABLE IF EXISTS, DROP DATABASE IF EXISTS, DELETE FROM, UPDATE be logged to
binlog even if they changed nothing, and a test for this. This is useful when users use these commands to clean up their master and slave by issuing one command on master (assume master and slave have slightly different data for some reason and you want to clean up both). Note that I have not changed multi-table DELETE and multi-table UPDATE because their error-reporting mechanism is more complicated.
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_db.cc72
-rw-r--r--sql/sql_delete.cc12
-rw-r--r--sql/sql_table.cc24
-rw-r--r--sql/sql_update.cc6
4 files changed, 63 insertions, 51 deletions
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 48c355b6cd9..9db2198268a 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -358,15 +358,25 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
{
error= -1;
my_error(ER_DB_DROP_EXISTS,MYF(0),db);
+ goto exit;
}
else
- {
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
- if (!silent)
- send_ok(thd,0);
+ }
+ else
+ {
+ pthread_mutex_lock(&LOCK_open);
+ remove_db_from_cache(db);
+ pthread_mutex_unlock(&LOCK_open);
+
+ error= -1;
+ if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0)) >= 0)
+ {
+ ha_drop_database(path);
+ query_cache_invalidate1(db);
+ error = 0;
}
- goto exit;
}
if (lower_case_table_names)
{
@@ -375,42 +385,30 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
my_casedn_str(files_charset_info, tmp_db);
db= tmp_db;
}
-
- pthread_mutex_lock(&LOCK_open);
- remove_db_from_cache(db);
- pthread_mutex_unlock(&LOCK_open);
-
- error = -1;
- if ((deleted=mysql_rm_known_files(thd, dirp, db, path,0)) >= 0 && thd)
+ if (!silent && deleted>=0 && thd)
{
- ha_drop_database(path);
- query_cache_invalidate1(db);
- if (!silent)
+ const char *query;
+ ulong query_length;
+ if (!thd->query)
{
- const char *query;
- ulong query_length;
- if (!thd->query)
- {
- /* The client used the old obsolete mysql_drop_db() call */
- query= path;
- query_length = (uint) (strxmov(path,"drop database `", db, "`",
- NullS)- path);
- }
- else
- {
- query=thd->query;
- query_length=thd->query_length;
- }
- mysql_update_log.write(thd, query, query_length);
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, query, query_length, 0);
- thd->clear_error();
- mysql_bin_log.write(&qinfo);
- }
- send_ok(thd,(ulong) deleted);
+ /* The client used the old obsolete mysql_drop_db() call */
+ query= path;
+ query_length= (uint) (strxmov(path, "drop database `", db, "`",
+ NullS) - path);
+ }
+ else
+ {
+ query =thd->query;
+ query_length= thd->query_length;
+ }
+ mysql_update_log.write(thd, query, query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, query, query_length, 0);
+ thd->clear_error();
+ mysql_bin_log.write(&qinfo);
}
- error = 0;
+ send_ok(thd, (ulong) deleted);
}
exit:
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index f21dbb10712..48497636186 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -199,7 +199,15 @@ cleanup:
transactional_table= table->file->has_transactions();
log_delayed= (transactional_table || table->tmp_table);
- if (deleted && (error <= 0 || !transactional_table))
+ /*
+ We write to the binary log even if we deleted no row, because maybe the
+ user is using this command to ensure that a table is clean on master *and
+ on slave*. Think of the case of a user having played separately with the
+ master's table and slave's table and wanting to take a fresh identical
+ start now.
+ error < 0 means "really no error". error <= 0 means "maybe some error".
+ */
+ if ((deleted || (error < 0)) && (error <= 0 || !transactional_table))
{
mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
@@ -544,6 +552,8 @@ bool multi_delete::send_eof()
rows and we succeeded, or also in an error case when there
was a non-transaction-safe table involved, since
modifications in it cannot be rolled back.
+ Note that if we deleted nothing we don't write to the binlog (TODO:
+ fix this).
*/
if (deleted && (error <= 0 || normal_tables))
{
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 8682b98a69a..bdff1f52d04 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -254,7 +254,17 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
}
thd->tmp_table_used= tmp_table_deleted;
- if (some_tables_deleted || tmp_table_deleted)
+ error= 0;
+ if (wrong_tables.length())
+ {
+ if (!foreign_key_error)
+ my_error(ER_BAD_TABLE_ERROR,MYF(0), wrong_tables.c_ptr());
+ else
+ my_error(ER_ROW_IS_REFERENCED, MYF(0));
+ error= 1;
+ }
+
+ if (some_tables_deleted || tmp_table_deleted || !error)
{
query_cache_invalidate3(thd, tables, 0);
if (!dont_log_query)
@@ -262,7 +272,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- thd->clear_error();
+ if (!error)
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
tmp_table_deleted && !some_tables_deleted);
mysql_bin_log.write(&qinfo);
@@ -271,15 +282,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
unlock_table_names(thd, tables);
- error= 0;
- if (wrong_tables.length())
- {
- if (!foreign_key_error)
- my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr());
- else
- my_error(ER_ROW_IS_REFERENCED,MYF(0));
- error= 1;
- }
DBUG_RETURN(error);
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 2428aac2da5..9436db6c3b9 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -331,7 +331,7 @@ int mysql_update(THD *thd,
transactional_table= table->file->has_transactions();
log_delayed= (transactional_table || table->tmp_table);
- if (updated && (error <= 0 || !transactional_table))
+ if ((updated || (error < 0)) && (error <= 0 || !transactional_table))
{
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
@@ -1092,7 +1092,9 @@ bool multi_update::send_eof()
/*
Write the SQL statement to the binlog if we updated
rows and we succeeded or if we updated some non
- transacational tables
+ transacational tables.
+ Note that if we updated nothing we don't write to the binlog (TODO:
+ fix this).
*/
if (updated && (local_error <= 0 || !trans_safe))