Commit 66481aeb authored by Sven Sandberg's avatar Sven Sandberg

BUG#39934: Slave stops for engine that only support row-based logging

Post-push fix.
Problem: After the original bugfix, if a statement is unsafe,
binlog_format=mixed, and engine is statement-only, a warning was
generated and the statement executed. However, it is a fundamental
principle of binlogging that binlog_format=mixed should guarantee
correct logging, no compromise. So correct behavior is to generate
an error and don't execute the statement.
Fix: Generate error instead of warning.
Since issue_unsafe_warnings can only generate one error message,
this allows us to simplify the code a bit too:
decide_logging_format does not have to save the error code for
issue_unsafe_warnings


mysql-test/suite/binlog/r/binlog_statement_insert_delayed.result:
  updated result file
mysql-test/suite/binlog/r/binlog_stm_ps.result:
  updated result file
mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result:
  updated result file
mysql-test/suite/binlog/r/binlog_unsafe.result:
  updated result file
mysql-test/suite/rpl/r/rpl_stm_found_rows.result:
  updated result file
mysql-test/suite/rpl/r/rpl_stm_loadfile.result:
  updated result file
mysql-test/suite/rpl_ndb/r/rpl_ndb_binlog_format_errors.result:
  updated result file
mysql-test/suite/rpl_ndb/t/rpl_ndb_binlog_format_errors.test:
  updated test:
   - ER_BINLOG_UNSAFE_AND_STMT_ENGINE is now an error.
   - added test for multiple types of unsafety
sql/share/errmsg.txt:
   - Reformulated ER_BINLOG_UNSAFE_AND_STMT_ENGINE to reflect that it
     is now an error, not a warning.
   - Added "Reason for unsafeness" to ER_BINLOG_UNSAFE_STATEMENT and
     ER_BINLOG_UNSAFE_AND_STMT_ENGINE.
sql/sql_class.cc:
  In decide_logging_format:
   - generate an error immediately in case 3, instead of scheduling a
     warning to be generated later. also updated comments accordingly
   - in case 7, there is only one unsafe warning error code now, so we
     don't need to store it in binlog_unsafe_warning_flags
     (see changes in sql_lex.h)
   - fixed compilation warning in DBUG_PRINT
  
  In issue_binlog_warning:
   - moved array of error codes to sql_lex.h (so that they are
     accessible also from decide_logging_format)
   - simplified code after the first set of bits in
     binlog_unsafe_warning_flags was removed
sql/sql_class.h:
   - got rid of enum_binlog_stmt_warning. It's not needed anymore
     since we only have one type of unsafe warning (one of them
     turned into an error)
   - updated comments accordingly
sql/sql_lex.cc:
  added initialization of the array of error codes that has been
  moved from THD::issue_unsafe_warnings to LEX.
sql/sql_lex.h:
  Moved array of error codes from THD::issue_unsafe_warnings to LEX.
parent 89f8e5ef
......@@ -13,10 +13,10 @@ master-bin.000001 # Query # # use `test`; insert delayed into t1 values (300)
master-bin.000001 # Query # # use `test`; FLUSH TABLES
insert delayed into t1 values (null),(null),(null),(null);
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted.
insert delayed into t1 values (null),(null),(400),(null);
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted.
select * from t1;
a
207
......
......@@ -11,7 +11,7 @@ prepare s from "insert into t1 select 100 limit ?";
set @a=100;
execute s using @a;
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; create table t1 (a int)
......
......@@ -4,10 +4,10 @@ CREATE TABLE t1 (a int, b int, primary key (a));
INSERT INTO t1 VALUES (1,2), (2,3);
UPDATE t1 SET b='4' WHERE a=1 LIMIT 1;
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
UPDATE t1 SET b='5' WHERE a=2 ORDER BY a LIMIT 1;
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
DROP TABLE t1;
### NOT filtered database => assertion: binlog disabled and warnings ARE NOT shown
SET SQL_LOG_BIN= 0;
......@@ -38,11 +38,11 @@ CREATE TABLE t1 (a VARCHAR(36), b VARCHAR(10));
SET GLOBAL LOG_WARNINGS = 0;
INSERT INTO t1 VALUES(UUID(), 'Bug#46265');
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
SET GLOBAL LOG_WARNINGS = 1;
INSERT INTO t1 VALUES(UUID(), 'Bug#46265');
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
DROP TABLE t1;
SET GLOBAL log_warnings = @old_log_warnings;
# Count the number of times the "Unsafe" message was printed
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -52,8 +52,8 @@ a
a
7
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
CREATE PROCEDURE just_log(sect INT, test INT, found_rows INT) BEGIN
INSERT INTO logtbl VALUES (sect,test,found_rows);
END $$
......
......@@ -10,7 +10,7 @@ CREATE TABLE test.t1 (a INT, blob_column LONGBLOB, PRIMARY KEY(a));
INSERT INTO test.t1 VALUES(1,'test');
UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=1;
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
create procedure test.p1()
begin
INSERT INTO test.t1 VALUES(2,'test');
......@@ -18,7 +18,7 @@ UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=2;
end|
CALL test.p1();
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
SELECT * FROM test.t1 ORDER BY blob_column;
a blob_column
1 abase
......
......@@ -16,6 +16,10 @@ CREATE TABLE t_self_logging (a VARCHAR(100)) ENGINE = NDB;
CREATE TABLE t_row (a VARCHAR(100)) ENGINE = INNODB;
CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
CREATE TABLE t_slave_stmt (a VARCHAR(100)) ENGINE = MYISAM;
CREATE TABLE t_autoinc (a INT KEY AUTO_INCREMENT) ENGINE = MYISAM;
CREATE TABLE t_double_autoinc (a INT KEY AUTO_INCREMENT) ENGINE = MYISAM;
CREATE TRIGGER trig_autoinc BEFORE INSERT ON t_autoinc FOR EACH ROW BEGIN INSERT INTO t_stmt VALUES ('x'); END;
CREATE TRIGGER trig_double_autoinc BEFORE INSERT ON t_double_autoinc FOR EACH ROW BEGIN INSERT INTO t_autoinc VALUES (NULL); END;
CREATE DATABASE other;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
[on slave]
......@@ -64,8 +68,10 @@ SET @@global.binlog_format = MIXED;
SET @@session.binlog_format = MIXED;
* Unsafe statement and stmt-only engine
INSERT INTO t_stmt VALUES (UUID());
Warnings:
Note 1641 Unsafe statement binlogged as statement since storage engine is limited to statement-logging. Reason: Statement uses a system function whose value may differ on slave.
ERROR HY000: Cannot execute statement: binlogging of unsafe statement is impossible when storage engine is limited to statement-logging and BINLOG_FORMAT = MIXED. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
* Multi-unsafe statement and stmt-only engine
INSERT DELAYED INTO t_double_autoinc SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1;
ERROR HY000: Cannot execute statement: binlogging of unsafe statement is impossible when storage engine is limited to statement-logging and BINLOG_FORMAT = MIXED. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
---- binlog_format=statement ----
[on slave]
include/stop_slave.inc
......@@ -102,7 +108,7 @@ USE test;
* Unsafe statement and binlog_format=statement
INSERT INTO t VALUES (UUID());
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason: Statement uses a system function whose value may differ on slave.
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave.
* Same statement, but db filtered out - no message
USE other;
INSERT INTO test.t VALUES (UUID());
......@@ -119,7 +125,7 @@ set global sql_slave_skip_counter=1;
include/start_slave.inc
[on master]
==== Clean up ====
DROP TABLE t, t_self_logging, t_row, t_stmt, t_slave_stmt;
DROP TABLE t, t_self_logging, t_row, t_stmt, t_slave_stmt, t_autoinc, t_double_autoinc;
DROP DATABASE other;
SET @@global.binlog_format = @old_binlog_format;
SET @@session.binlog_format = @old_binlog_format;
......
......@@ -51,6 +51,11 @@ CREATE TABLE t_self_logging (a VARCHAR(100)) ENGINE = NDB;
CREATE TABLE t_row (a VARCHAR(100)) ENGINE = INNODB;
CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
CREATE TABLE t_slave_stmt (a VARCHAR(100)) ENGINE = MYISAM;
CREATE TABLE t_autoinc (a INT KEY AUTO_INCREMENT) ENGINE = MYISAM;
CREATE TABLE t_double_autoinc (a INT KEY AUTO_INCREMENT) ENGINE = MYISAM;
--eval CREATE TRIGGER trig_autoinc BEFORE INSERT ON t_autoinc FOR EACH ROW BEGIN INSERT INTO t_stmt VALUES ('x'); END
--eval CREATE TRIGGER trig_double_autoinc BEFORE INSERT ON t_double_autoinc FOR EACH ROW BEGIN INSERT INTO t_autoinc VALUES (NULL); END
CREATE DATABASE other;
......@@ -127,9 +132,15 @@ SET @@global.binlog_format = MIXED;
SET @@session.binlog_format = MIXED;
--echo * Unsafe statement and stmt-only engine
# This will give a warning.
--error ER_BINLOG_UNSAFE_AND_STMT_ENGINE
INSERT INTO t_stmt VALUES (UUID());
# Concatenate three unsafe values, and then concatenate NULL to
# that so that the result is NULL and we instead use autoinc.
--echo * Multi-unsafe statement and stmt-only engine
--error ER_BINLOG_UNSAFE_AND_STMT_ENGINE
INSERT DELAYED INTO t_double_autoinc SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1;
--echo ---- binlog_format=statement ----
......@@ -213,7 +224,7 @@ INSERT INTO t VALUES (UUID());
--echo ==== Clean up ====
DROP TABLE t, t_self_logging, t_row, t_stmt, t_slave_stmt;
DROP TABLE t, t_self_logging, t_row, t_stmt, t_slave_stmt, t_autoinc, t_double_autoinc;
DROP DATABASE other;
SET @@global.binlog_format = @old_binlog_format;
SET @@session.binlog_format = @old_binlog_format;
......
......@@ -6076,7 +6076,7 @@ ER_SLAVE_INCIDENT
ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT
eng "Table has no partition for some existing values"
ER_BINLOG_UNSAFE_STATEMENT
eng "Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT."
eng "Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: %s"
ER_SLAVE_FATAL_ERROR
eng "Fatal error: %s"
ER_SLAVE_RELAY_LOG_READ_FAILURE
......@@ -6211,7 +6211,7 @@ ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE
ER_BINLOG_ROW_MODE_AND_STMT_ENGINE
eng "Cannot execute statement: binlogging impossible since BINLOG_FORMAT = ROW and at least one table uses a storage engine limited to statement-logging."
ER_BINLOG_UNSAFE_AND_STMT_ENGINE
eng "Unsafe statement binlogged as statement since storage engine is limited to statement-logging."
eng "Cannot execute statement: binlogging of unsafe statement is impossible when storage engine is limited to statement-logging and BINLOG_FORMAT = MIXED. Reason for unsafeness: %s"
ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE
eng "Cannot execute row injection: binlogging impossible since at least one table uses a storage engine limited to statement-logging."
ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
......@@ -6236,7 +6236,5 @@ ER_BINLOG_UNSAFE_SYSTEM_VARIABLE
ER_BINLOG_UNSAFE_SYSTEM_FUNCTION
eng "Statement uses a system function whose value may differ on slave."
ER_BINLOG_UNSAFE_WARNING_SHORT
eng "%s Reason: %s"
ER_BINLOG_UNSAFE_WARNING_LONG
eng "%s Reason: %s Statement: %s"
ER_MESSAGE_AND_STATEMENT
eng "%s Statement: %s"
......@@ -3282,8 +3282,8 @@ void xid_cache_delete(XID_STATE *xid_state)
binlog_format * SMRSMRSMR SMRSMRSMR SMRSMRSMR
Logged format - SS-SS---- -RR-RR-RR SRRSRR-RR
Warning/Error 1 --2332444 5--5--6-- ---7--6--
Logged format - SS-S----- -RR-RR-RR SRRSRR-RR
Warning/Error 1 --2732444 5--5--6-- ---7--6--
Legend
------
......@@ -3303,8 +3303,9 @@ void xid_cache_delete(XID_STATE *xid_state)
BINLOG_FORMAT = ROW and at least one table uses a storage engine
limited to statement-logging.
3. Warning: Unsafe statement binlogged as statement since storage
engine is limited to statement-logging.
3. Error: Cannot execute statement: binlogging of unsafe statement
is impossible when storage engine is limited to statement-logging
and BINLOG_FORMAT = MIXED.
4. Error: Cannot execute row injection: binlogging impossible since
at least one table uses a storage engine limited to
......@@ -3457,17 +3458,16 @@ int THD::decide_logging_format(TABLE_LIST *tables)
else if ((unsafe_flags= lex->get_stmt_unsafe_flags()) != 0)
{
/*
3. Warning: Unsafe statement binlogged as statement since
storage engine is limited to statement-logging.
3. Error: Cannot execute statement: binlogging of unsafe
statement is impossible when storage engine is limited to
statement-logging and BINLOG_FORMAT = MIXED.
*/
binlog_unsafe_warning_flags|=
(1 << BINLOG_STMT_WARNING_UNSAFE_AND_STMT_ENGINE) |
(unsafe_flags << BINLOG_STMT_WARNING_COUNT);
DBUG_PRINT("info", ("Scheduling warning to be issued by "
"binlog_query: %s",
ER(ER_BINLOG_UNSAFE_AND_STMT_ENGINE)));
DBUG_PRINT("info", ("binlog_unsafe_warning_flags: 0x%x",
binlog_unsafe_warning_flags));
for (int unsafe_type= 0;
unsafe_type < LEX::BINLOG_STMT_UNSAFE_COUNT;
unsafe_type++)
if (unsafe_flags & (1 << unsafe_type))
my_error((error= ER_BINLOG_UNSAFE_AND_STMT_ENGINE), MYF(0),
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
}
/* log in statement format! */
}
......@@ -3499,13 +3499,11 @@ int THD::decide_logging_format(TABLE_LIST *tables)
7. Warning: Unsafe statement logged as statement due to
binlog_format = STATEMENT
*/
binlog_unsafe_warning_flags|=
(1 << BINLOG_STMT_WARNING_UNSAFE_AND_STMT_MODE) |
(unsafe_flags << BINLOG_STMT_WARNING_COUNT);
binlog_unsafe_warning_flags|= unsafe_flags;
DBUG_PRINT("info", ("Scheduling warning to be issued by "
"binlog_query: '%s'",
ER(ER_BINLOG_UNSAFE_STATEMENT)));
DBUG_PRINT("info", ("binlog_stmt_flags: 0x%x",
DBUG_PRINT("info", ("binlog_unsafe_warning_flags: 0x%x",
binlog_unsafe_warning_flags));
}
/* log in statement format! */
......@@ -3536,7 +3534,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
DBUG_PRINT("info", ("decision: no logging since "
"mysql_bin_log.is_open() = %d "
"and (options & OPTION_BIN_LOG) = 0x%llx "
"and binlog_format = %d "
"and binlog_format = %ld "
"and binlog_filter->db_ok(db) = %d",
mysql_bin_log.is_open(),
(options & OPTION_BIN_LOG),
......@@ -4037,31 +4035,11 @@ void THD::issue_unsafe_warnings()
Ensure that binlog_unsafe_warning_flags is big enough to hold all
bits. This is actually a constant expression.
*/
DBUG_ASSERT(BINLOG_STMT_WARNING_COUNT + 2 * LEX::BINLOG_STMT_UNSAFE_COUNT <=
DBUG_ASSERT(2 * LEX::BINLOG_STMT_UNSAFE_COUNT <=
sizeof(binlog_unsafe_warning_flags) * CHAR_BIT);
/**
@note The order of the elements of this array must correspond to
the order of elements in enum_binlog_stmt_unsafe.
*/
static const int explanations[LEX::BINLOG_STMT_UNSAFE_COUNT] =
{
ER_BINLOG_UNSAFE_LIMIT,
ER_BINLOG_UNSAFE_INSERT_DELAYED,
ER_BINLOG_UNSAFE_SYSTEM_TABLE,
ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS,
ER_BINLOG_UNSAFE_UDF,
ER_BINLOG_UNSAFE_SYSTEM_VARIABLE,
ER_BINLOG_UNSAFE_SYSTEM_FUNCTION
};
uint32 flags= binlog_unsafe_warning_flags;
/* No warnings (yet) for this statement. */
if (flags == 0)
DBUG_VOID_RETURN;
uint32 unsafe_type_flags= binlog_unsafe_warning_flags;
/* Get the types of unsafeness that affect the current statement. */
uint32 unsafe_type_flags= flags >> BINLOG_STMT_WARNING_COUNT;
DBUG_ASSERT((unsafe_type_flags & LEX::BINLOG_STMT_UNSAFE_ALL_FLAGS) != 0);
/*
Clear: (1) bits above BINLOG_STMT_UNSAFE_COUNT; (2) bits for
warnings that have been printed already.
......@@ -4072,18 +4050,7 @@ void THD::issue_unsafe_warnings()
if (unsafe_type_flags == 0)
DBUG_VOID_RETURN;
/* Figure out which error code to issue. */
int err;
if (binlog_unsafe_warning_flags &
(1 << BINLOG_STMT_WARNING_UNSAFE_AND_STMT_ENGINE))
err= ER_BINLOG_UNSAFE_AND_STMT_ENGINE;
else {
DBUG_ASSERT(binlog_unsafe_warning_flags &
(1 << BINLOG_STMT_WARNING_UNSAFE_AND_STMT_MODE));
err= ER_BINLOG_UNSAFE_STATEMENT;
}
DBUG_PRINT("info", ("flags: 0x%x err: %d", unsafe_type_flags, err));
DBUG_PRINT("info", ("unsafe_type_flags: 0x%x", unsafe_type_flags));
/*
For each unsafe_type, check if the statement is unsafe in this way
......@@ -4095,20 +4062,25 @@ void THD::issue_unsafe_warnings()
{
if ((unsafe_type_flags & (1 << unsafe_type)) != 0)
{
push_warning_printf(this, MYSQL_ERROR::WARN_LEVEL_NOTE, err,
ER(ER_BINLOG_UNSAFE_WARNING_SHORT),
ER(err), ER(explanations[unsafe_type]));
push_warning_printf(this, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_BINLOG_UNSAFE_STATEMENT,
ER(ER_BINLOG_UNSAFE_STATEMENT),
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
if (global_system_variables.log_warnings)
sql_print_warning(ER(ER_BINLOG_UNSAFE_WARNING_LONG),
ER(err), ER(explanations[unsafe_type]), query);
{
char buf[MYSQL_ERRMSG_SIZE * 2];
sprintf(buf, ER(ER_BINLOG_UNSAFE_STATEMENT),
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
sql_print_warning(ER(ER_MESSAGE_AND_STATEMENT), buf, query);
}
}
}
/*
Mark these unsafe types as already printed, to avoid printing
warnings for them again.
*/
binlog_unsafe_warning_flags|= unsafe_type_flags <<
(BINLOG_STMT_WARNING_COUNT + LEX::BINLOG_STMT_UNSAFE_COUNT);
binlog_unsafe_warning_flags|=
unsafe_type_flags << LEX::BINLOG_STMT_UNSAFE_COUNT;
DBUG_VOID_RETURN;
}
......
......@@ -1449,42 +1449,21 @@ private:
*/
enum_binlog_format current_stmt_binlog_format;
/**
Enumeration listing binlog-related warnings that a statement can
cause.
*/
enum enum_binlog_stmt_warning {
/* ER_BINLOG_UNSAFE_AND_STMT_ENGINE affects current stmt */
BINLOG_STMT_WARNING_UNSAFE_AND_STMT_ENGINE= 0,
/* ER_BINLOG_UNSAFE_STATEMENT affects current stmt */
BINLOG_STMT_WARNING_UNSAFE_AND_STMT_MODE,
/** The last element of this enumeration type. */
BINLOG_STMT_WARNING_COUNT
};
/**
Bit field for the state of binlog warnings.
There are three groups of bits:
There are two groups of bits:
- The low BINLOG_STMT_WARNING_COUNT bits indicate the type of
warning that the current (top-level) statement will issue. At
most one of these bits should be set (this is ensured by the
logic in decide_logging_format).
- The following Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types
of unsafeness that the current statement has.
- The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of
unsafeness that the current statement has.
- The following Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types
of unsafeness that the current statement has issued warnings
for.
Hence, this variable must be big enough to hold
BINLOG_STMT_WARNING_COUNT + 2 * Lex::BINLOG_STMT_UNSAFE_COUNT
bits. This is asserted in @c issue_unsafe_warnings().
2*Lex::BINLOG_STMT_UNSAFE_COUNT bits. This is asserted in @c
issue_unsafe_warnings().
The first and second groups of bits are set by @c
decide_logging_format() when it detects that a warning should be
......
......@@ -31,6 +31,23 @@
sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
/**
@note The order of the elements of this array must correspond to
the order of elements in enum_binlog_stmt_unsafe.
*/
const int
Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] =
{
ER_BINLOG_UNSAFE_LIMIT,
ER_BINLOG_UNSAFE_INSERT_DELAYED,
ER_BINLOG_UNSAFE_SYSTEM_TABLE,
ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS,
ER_BINLOG_UNSAFE_UDF,
ER_BINLOG_UNSAFE_SYSTEM_VARIABLE,
ER_BINLOG_UNSAFE_SYSTEM_FUNCTION
};
/* Longest standard keyword name */
#define TOCK_NAME_LENGTH 24
......
......@@ -1099,6 +1099,11 @@ public:
static const int BINLOG_STMT_UNSAFE_ALL_FLAGS=
((1 << BINLOG_STMT_UNSAFE_COUNT) - 1);
/**
Maps elements of enum_binlog_stmt_unsafe to error codes.
*/
static const int binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT];
/**
Determine if this statement is marked as unsafe.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment