summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
authorunknown <mats@kindahl-laptop.dnsalias.net>2007-06-12 22:02:46 +0200
committerunknown <mats@kindahl-laptop.dnsalias.net>2007-06-12 22:02:46 +0200
commit492ebf924b40ac847201fa6dc3cb44731dbac210 (patch)
treee252590c0287c7b25e8b7d291290be7d7a77d932 /sql/sql_base.cc
parente319a0493461000f9eeabceed7f2c5d57cfc44cd (diff)
parentccbada0864161294ca351b2a9b6cfac5d4ce6153 (diff)
downloadmariadb-git-492ebf924b40ac847201fa6dc3cb44731dbac210.tar.gz
Merge kindahl-laptop.dnsalias.net:/home/bkroot/mysql-5.1-rpl
into kindahl-laptop.dnsalias.net:/home/bk/b23051-mysql-5.1-rpl BitKeeper/deleted/.del-binlog_row_blackhole.result: Auto merged sql/ha_ndbcluster.cc: Auto merged sql/handler.cc: Auto merged sql/mysql_priv.h: Auto merged sql/sql_base.cc: Auto merged sql/share/errmsg.txt: Auto merged storage/blackhole/ha_blackhole.h: Auto merged storage/innobase/handler/ha_innodb.cc: Auto merged storage/innobase/handler/ha_innodb.h: Auto merged storage/myisam/ha_myisam.cc: Auto merged mysql-test/t/partition_hash.test: Manual merge sql/handler.h: Manual merge sql/set_var.cc: Manual merge sql/sql_class.h: Manual merge sql/sql_insert.cc: Manual merge sql/sql_parse.cc: Manual merge
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc128
1 files changed, 119 insertions, 9 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 1986c09b2d2..ed58ed21bbd 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3948,6 +3948,121 @@ static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table)
}
+/**
+ Decide on logging format to use for the statement.
+
+ 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.
+
+ We now 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.
+
+ If we are in MIXED mode, we then decide what logging format to use:
+
+ 1. If the statement is unsafe, row-based logging is used.
+
+ 2. If statement-based logging is not possible, row-based logging is
+ used.
+
+ 3. Otherwise, statement-based logging is used.
+
+ @param thd Client thread
+ @param tables Tables involved in the query
+ */
+
+int decide_logging_format(THD *thd, TABLE_LIST *tables)
+{
+ if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG))
+ {
+ handler::Table_flags binlog_flags= ~handler::Table_flags();
+ for (TABLE_LIST *table= tables; table; table= table->next_global)
+ if (!table->placeholder() && table->lock_type >= TL_WRITE_ALLOW_WRITE)
+ {
+#define FLAGSTR(S,F) ((S) & (F) ? #F " " : "")
+#ifndef DBUG_OFF
+ ulonglong flags= table->table->file->ha_table_flags();
+ DBUG_PRINT("info", ("table: %s; ha_table_flags: %s%s",
+ table->table_name,
+ FLAGSTR(flags, HA_BINLOG_STMT_CAPABLE),
+ FLAGSTR(flags, HA_BINLOG_ROW_CAPABLE)));
+#endif
+ binlog_flags &= table->table->file->ha_table_flags();
+ }
+ binlog_flags&= HA_BINLOG_FLAGS;
+ DBUG_PRINT("info", ("binlog_flags: %s%s",
+ FLAGSTR(binlog_flags, HA_BINLOG_STMT_CAPABLE),
+ FLAGSTR(binlog_flags, HA_BINLOG_ROW_CAPABLE)));
+ DBUG_PRINT("info", ("thd->variables.binlog_format: %ld",
+ thd->variables.binlog_format));
+
+ int error= 0;
+ if (binlog_flags == 0)
+ {
+ my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0),
+ "Statement cannot be logged to the binary log in"
+ " row-based nor statement-based format");
+ }
+ else if (thd->variables.binlog_format == BINLOG_FORMAT_STMT &&
+ (binlog_flags & HA_BINLOG_STMT_CAPABLE) == 0)
+ {
+ my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0),
+ "Statement-based format required for this statement,"
+ " but not allowed by this combination of engines");
+ }
+ else if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW ||
+ thd->lex->is_stmt_unsafe()) &&
+ (binlog_flags & HA_BINLOG_ROW_CAPABLE) == 0)
+ {
+ my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0),
+ "Row-based format required for this statement,"
+ " but not allowed by this combination of engines");
+ }
+
+ DBUG_PRINT("info", ("error: %d", error));
+
+ if (error)
+ {
+ ha_rollback_stmt(thd);
+ 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();
+ }
+ }
+
+ return 0;
+}
+
/*
Lock all tables in list
@@ -3986,17 +4101,10 @@ 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 (!tables && !thd->lex->requires_prelocking())
- DBUG_RETURN(0);
+ DBUG_RETURN(decide_logging_format(thd, tables));
/*
We need this extra check for thd->prelocked_mode because we want to avoid
@@ -4049,6 +4157,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
}
DBUG_RETURN(-1);
}
+
if (thd->lex->requires_prelocking() &&
thd->lex->sql_command != SQLCOM_LOCK_TABLES)
{
@@ -4115,7 +4224,8 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
thd->prelocked_mode= PRELOCKED_UNDER_LOCK_TABLES;
}
}
- DBUG_RETURN(0);
+
+ DBUG_RETURN(decide_logging_format(thd, tables));
}