summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authormats@romeo.kindahl.net <>2007-05-14 14:45:38 +0200
committermats@romeo.kindahl.net <>2007-05-14 14:45:38 +0200
commit6a7925a262bbe4ab37a90a952330b3b411bc2df5 (patch)
tree0ac7772a8a7fdb3df1f3dc301bdeb9033cd2b0cc /sql
parent9064773393e3358709bd0db191b9bd63913c53dc (diff)
downloadmariadb-git-6a7925a262bbe4ab37a90a952330b3b411bc2df5.tar.gz
WL#3339 (Issue warnings when statement-based replication may fail):
Replacing binlog_row_based_if_mixed with variable binlog_stmt_flags holding several flags and adding member functions to manipulate the flags. Added code to generate a warning when an attempt to log an unsafe statement to the binary log was made. The warning is both pushed to the SHOW WARNINGS table and written to the error log. The prevent flooding the error log, the warning is just written to the error log once per open session.
Diffstat (limited to 'sql')
-rw-r--r--sql/item_create.cc4
-rw-r--r--sql/share/errmsg.txt3
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sp_head.h2
-rw-r--r--sql/sql_base.cc4
-rw-r--r--sql/sql_class.cc19
-rw-r--r--sql/sql_class.h12
-rw-r--r--sql/sql_insert.cc1
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h44
-rw-r--r--sql/sql_view.cc4
11 files changed, 79 insertions, 18 deletions
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 8ff78ef1b48..67ffbaba1ad 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -2341,7 +2341,7 @@ Create_udf_func::create(THD *thd, udf_func *udf, List<Item> *item_list)
if (item_list != NULL)
arg_count= item_list->elements;
- thd->lex->binlog_row_based_if_mixed= TRUE;
+ thd->lex->set_stmt_unsafe();
DBUG_ASSERT( (udf->type == UDFTYPE_FUNCTION)
|| (udf->type == UDFTYPE_AGGREGATE));
@@ -4527,7 +4527,7 @@ Create_func_uuid Create_func_uuid::s_singleton;
Item*
Create_func_uuid::create(THD *thd)
{
- thd->lex->binlog_row_based_if_mixed= TRUE;
+ thd->lex->set_stmt_unsafe();
return new (thd->mem_root) Item_func_uuid();
}
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 03990bbad0e..2e1240ab616 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -6059,3 +6059,6 @@ ER_SLAVE_INCIDENT
eng "The incident %s occured on the master. Message: %-.64s"
ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT
eng "Table has no partition for some existing values"
+ER_BINLOG_UNSAFE_STATEMENT
+ eng "Statement is not safe to log in statement format."
+ swe "Detta är inte säkert att logga i statement-format."
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index a2ce5111a25..6bd6360e642 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1873,7 +1873,7 @@ sp_head::restore_lex(THD *thd)
cannot switch from statement-based to row-based only for this
substatement).
*/
- if (sublex->binlog_row_based_if_mixed)
+ if (sublex->is_stmt_unsafe())
m_flags|= BINLOG_ROW_BASED_IF_MIXED;
/*
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 551707fa7bd..61407440a11 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -379,7 +379,7 @@ public:
the substatements not).
*/
if (m_flags & BINLOG_ROW_BASED_IF_MIXED)
- lex->binlog_row_based_if_mixed= TRUE;
+ lex->set_stmt_unsafe();
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 0f428da1fdb..0ec6ababab0 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3591,7 +3591,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
/*
CREATE ... SELECT UUID() locks no tables, we have to test here.
*/
- if (thd->lex->binlog_row_based_if_mixed)
+ if (thd->lex->is_stmt_unsafe())
thd->set_current_stmt_binlog_row_based_if_mixed();
if (!tables && !thd->lex->requires_prelocking())
@@ -3632,7 +3632,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED &&
has_two_write_locked_tables_with_auto_increment(tables))
{
- thd->lex->binlog_row_based_if_mixed= TRUE;
+ thd->lex->set_stmt_unsafe();
thd->set_current_stmt_binlog_row_based_if_mixed();
}
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 4ee36f5864c..3e8b43f638e 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -201,7 +201,7 @@ THD::THD()
Open_tables_state(refresh_version), rli_fake(0),
lock_id(&main_lock_id),
user_time(0), in_sub_stmt(0),
- binlog_table_maps(0),
+ binlog_table_maps(0), binlog_flags(0UL),
global_read_lock(0), is_fatal_error(0),
rand_used(0), time_zone_used(0),
arg_of_last_insert_id_function(FALSE),
@@ -2888,6 +2888,23 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype,
to how you treat this.
*/
case THD::STMT_QUERY_TYPE:
+ if (lex->is_stmt_unsafe())
+ {
+ DBUG_ASSERT(this->query != NULL);
+ push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_BINLOG_UNSAFE_STATEMENT,
+ ER(ER_BINLOG_UNSAFE_STATEMENT));
+ if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED))
+ {
+
+ char warn_buf[MYSQL_ERRMSG_SIZE];
+ my_snprintf(warn_buf, MYSQL_ERRMSG_SIZE, "%s Statement: %s",
+ ER(ER_BINLOG_UNSAFE_STATEMENT), this->query);
+ sql_print_warning(warn_buf);
+ binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED;
+ }
+ }
+
/*
The MYSQL_LOG::write() function will set the STMT_END_F flag and
flush the pending rows event if necessary.
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 3d53c19633e..7f933c331c3 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1048,6 +1048,17 @@ public:
private:
uint binlog_table_maps; // Number of table maps currently in the binlog
+
+ enum enum_binlog_flag {
+ BINLOG_FLAG_UNSAFE_STMT_PRINTED,
+ BINLOG_FLAG_COUNT
+ };
+
+ /**
+ Flags with per-thread information regarding the status of the
+ binary log.
+ */
+ uint32 binlog_flags;
public:
uint get_binlog_table_maps() const {
return binlog_table_maps;
@@ -1599,6 +1610,7 @@ public:
void restore_sub_statement_state(Sub_statement_state *backup);
void set_n_backup_active_arena(Query_arena *set, Query_arena *backup);
void restore_active_arena(Query_arena *set, Query_arena *backup);
+
inline void set_current_stmt_binlog_row_based_if_mixed()
{
/*
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index f6ae2df3750..b50568df9f6 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1533,6 +1533,7 @@ public:
Statement-based replication of INSERT DELAYED has problems with RAND()
and user vars, so in mixed mode we go to row-based.
*/
+ thd.lex->set_stmt_unsafe();
thd.set_current_stmt_binlog_row_based_if_mixed();
bzero((char*) &thd.net, sizeof(thd.net)); // Safety
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 4a162478388..685b915a8b9 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1719,7 +1719,7 @@ void Query_tables_list::reset_query_tables_list(bool init)
sroutines_list.empty();
sroutines_list_own_last= sroutines_list.next;
sroutines_list_own_elements= 0;
- binlog_row_based_if_mixed= FALSE;
+ binlog_stmt_flags= 0;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 850586c6098..7097c2de4fd 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -910,14 +910,6 @@ public:
uint sroutines_list_own_elements;
/*
- Tells if the parsing stage detected that some items require row-based
- binlogging to give a reliable binlog/replication, or if we will use
- stored functions or triggers which themselves need require row-based
- binlogging.
- */
- bool binlog_row_based_if_mixed;
-
- /*
These constructor and destructor serve for creation/destruction
of Query_tables_list instances which are used as backup storage.
*/
@@ -964,6 +956,41 @@ public:
query_tables_own_last= 0;
}
}
+
+ /**
+ Has the parser/scanner detected that this statement is unsafe?
+ */
+ inline bool is_stmt_unsafe() const {
+ return binlog_stmt_flags & (1U << BINLOG_STMT_FLAG_UNSAFE);
+ }
+
+ /**
+ Flag the current (top-level) statement as unsafe.
+
+ The flag will be reset after the statement has finished.
+
+ */
+ inline void set_stmt_unsafe() {
+ binlog_stmt_flags|= (1U << BINLOG_STMT_FLAG_UNSAFE);
+ }
+
+ inline void clear_stmt_unsafe() {
+ binlog_stmt_flags&= ~(1U << BINLOG_STMT_FLAG_UNSAFE);
+ }
+
+private:
+ enum enum_binlog_stmt_flag {
+ BINLOG_STMT_FLAG_UNSAFE,
+ BINLOG_STMT_FLAG_COUNT
+ };
+
+ /*
+ Tells if the parsing stage detected properties of the statement,
+ for example: that some items require row-based binlogging to give
+ a reliable binlog/replication, or if we will use stored functions
+ or triggers which themselves need require row-based binlogging.
+ */
+ uint32 binlog_stmt_flags;
};
@@ -1299,6 +1326,7 @@ typedef struct st_lex : public Query_tables_list
void restore_backup_query_tables_list(Query_tables_list *backup);
bool table_or_sp_used();
+
} LEX;
struct st_lex_local: public st_lex
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index c02fb7bcdc0..306c759359c 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1114,8 +1114,8 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
If the view's body needs row-based binlogging (e.g. the VIEW is created
from SELECT UUID()), the top statement also needs it.
*/
- if (lex->binlog_row_based_if_mixed)
- old_lex->binlog_row_based_if_mixed= TRUE;
+ if (lex->is_stmt_unsafe())
+ old_lex->set_stmt_unsafe();
view_is_mergeable= (table->algorithm != VIEW_ALGORITHM_TMPTABLE &&
lex->can_be_merged());
LINT_INIT(view_main_select_tables);