summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
authorunknown <mats@kindahl-laptop.dnsalias.net>2007-05-28 12:50:29 +0200
committerunknown <mats@kindahl-laptop.dnsalias.net>2007-05-28 12:50:29 +0200
commit098e15c164853fd1ba0a3f549d7a82eaa14c2816 (patch)
tree5f33520a3ea4809926952b015e31af3977e1e805 /sql/sql_base.cc
parent499a8ecd21c2542c08e273faabfffa94ebec1cfa (diff)
downloadmariadb-git-098e15c164853fd1ba0a3f549d7a82eaa14c2816.tar.gz
WL#3303 (RBR: Engine-controlled logging format):
Adding support to allow engines to tell what formats they can handle. The server will generate an error if it is not possible to log the statement according to the logging mode in effect. Adding flags to several storage engines to state what they can handle. Changes to NDB handler removing code that forces row-based mode and adding flag saying that NDB can only handle row format. Adding check that binlog flags are only used for real tables that are opened for writing. BitKeeper/deleted/.del-binlog_row_blackhole.result: Rename: mysql-test/r/binlog_row_blackhole.result -> BitKeeper/deleted/.del-binlog_row_blackhole.result BitKeeper/deleted/.del-binlog_row_blackhole.test: Rename: mysql-test/t/binlog_row_blackhole.test -> BitKeeper/deleted/.del-binlog_row_blackhole.test mysql-test/t/partition_hash.test: Adding error check for statement that might fail. sql/ha_ndbcluster.cc: Removing statements that switch to row-based format. Adding row capabilities. sql/handler.h: Adding handler/table flags to indicate that the engine is row- and/or statement-logging capable. Adding typedef for table_flags type. sql/set_var.cc: Removing code that prevents changing binlog format when NDB is active. sql/share/errmsg.txt: Adding error messages for when row- and/or statement-based logging formats cannot be used. sql/sql_base.cc: Adding business logic in lock_tables() to decide when an error should be thrown because logging is not possible. Add logic to switch to row format when that is allowed and needed. --- Binlog flags should only be checked for real tables that are opened for writing. Adding code to check that. storage/archive/ha_archive.h: Adding row- and statement-logging capabilities to engine. storage/blackhole/ha_blackhole.h: Blackhole can handle statement-format only. storage/csv/ha_tina.h: Adding row- and statement-logging capabilities to engine. storage/example/ha_example.h: For the example engine, we arbitrarily decided that it only can handle row format. storage/federated/ha_federated.h: Adding row- and statement-logging capabilities to engine. storage/heap/ha_heap.h: Heap can handle both row- and statement-based logging format. storage/myisam/ha_myisam.cc: MyISAM can handle both row- and statement-based logging format. storage/myisammrg/ha_myisammrg.h: MyISAM can handle both row- and statement-based logging format. mysql-test/r/binlog_multi_engine.result: New BitKeeper file ``mysql-test/r/binlog_multi_engine.result'' mysql-test/t/binlog_multi_engine.test: New BitKeeper file ``mysql-test/t/binlog_multi_engine.test''
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc91
1 files changed, 85 insertions, 6 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 0ec6ababab0..e2fd5ab65ce 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3585,14 +3585,93 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
in prelocked mode.
*/
DBUG_ASSERT(!thd->prelocked_mode || !thd->lex->requires_prelocking());
-
*need_reopen= FALSE;
- /*
- CREATE ... SELECT UUID() locks no tables, we have to test here.
- */
- if (thd->lex->is_stmt_unsafe())
- thd->set_current_stmt_binlog_row_based_if_mixed();
+ if (mysql_bin_log.is_open() && (thd->options | OPTION_BIN_LOG))
+ {
+ /*
+ Compute the capabilities vector for the involved storage engines
+ and mask out the flags for the binary log. Right now, the binlog
+ flags only include the capabilities of the storage engines, so
+ this is safe.
+ */
+ handler::Table_flags binlog_flags= ~handler::Table_flags();
+ DBUG_PRINT("info", ("HA_BINLOG_FLAGS: 0x%0llx",
+ (ulonglong) HA_BINLOG_FLAGS));
+ for (table= tables; table; table= table->next_global)
+ if (!table->placeholder() && table->lock_type >= TL_WRITE_ALLOW_WRITE)
+ {
+ DBUG_PRINT("info", ("table: %s; ha_table_flags: 0x%0llx",
+ table->table_name,
+ (ulonglong) table->table->file->ha_table_flags()));
+ binlog_flags &= table->table->file->ha_table_flags();
+ }
+ binlog_flags&= HA_BINLOG_FLAGS;
+ DBUG_PRINT("info", ("binlog_flags: 0x%0llx", (ulonglong) binlog_flags));
+ DBUG_PRINT("info", ("thd->variables.binlog_format: %ld",
+ thd->variables.binlog_format));
+
+ /*
+ We have three alternatives that prevent the statement from being
+ loggable:
+
+ 1. If there are no capabilities left (all flags are clear) it is
+ not possible to log the statement at all, so we roll back the
+ statement and report an error.
+
+ 2. Statement mode is set, but the capabilities indicate that
+ statement format is not possible.
+
+ 3. Row mode is set, but the capabilities indicate that row
+ format is not possible.
+
+ 4. Statement is unsafe, but the capabilities indicate that row
+ format is not possible.
+ */
+ int error= 0;
+ if (binlog_flags == 0)
+ {
+ error= ER_BINLOG_ENGINES_INCOMPATIBLE;
+ }
+ else if (thd->variables.binlog_format == BINLOG_FORMAT_STMT &&
+ (binlog_flags & HA_BINLOG_STMT_CAPABLE) == 0)
+ {
+ error= ER_BINLOG_STMT_FORMAT_FORBIDDEN;
+ }
+ else if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW ||
+ thd->lex->is_stmt_unsafe()) &&
+ (binlog_flags & HA_BINLOG_ROW_CAPABLE) == 0)
+ {
+ error= ER_BINLOG_ROW_FORMAT_FORBIDDEN;
+ }
+
+ DBUG_PRINT("info", ("error: %d", error));
+
+ if (error)
+ {
+ ha_rollback_stmt(thd);
+ my_error(error, MYF(0));
+ DBUG_RETURN(-1);
+ }
+
+ /*
+ We switch to row-based format if we are in mixed mode and one of
+ the following are true:
+
+ 1. If the statement is unsafe
+ 2. If statement format cannot be used
+
+ Observe that point to cannot be decided before the tables
+ involved in a statement has been checked, i.e., we cannot put
+ this code in reset_current_stmt_binlog_row_based(), it has to be
+ here.
+ */
+ if (thd->lex->is_stmt_unsafe() ||
+ (binlog_flags | HA_BINLOG_STMT_CAPABLE) == 0)
+ {
+ thd->set_current_stmt_binlog_row_based_if_mixed();
+ }
+ }
if (!tables && !thd->lex->requires_prelocking())
DBUG_RETURN(0);