summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_sequence.cc3
-rw-r--r--sql/handler.cc105
-rw-r--r--sql/item.cc19
-rw-r--r--sql/item.h5
-rw-r--r--sql/item_cmpfunc.cc28
-rw-r--r--sql/item_cmpfunc.h32
-rw-r--r--sql/item_func.h4
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/item_timefunc.cc14
-rw-r--r--sql/mysqld.cc3
-rw-r--r--sql/opt_subselect.cc8
-rw-r--r--sql/rpl_parallel.cc37
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/sql_class.cc4
-rw-r--r--sql/sql_class.h6
-rw-r--r--sql/sql_parse.cc66
-rw-r--r--sql/sql_prepare.cc4
-rw-r--r--sql/sql_show.cc7
-rw-r--r--sql/sql_time.cc2
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sys_vars.cc10
-rw-r--r--sql/tztime.cc4
-rw-r--r--sql/wsrep_check_opts.cc3
-rw-r--r--sql/wsrep_mysqld.cc4
-rw-r--r--sql/wsrep_mysqld.h7
-rw-r--r--sql/wsrep_sst.cc23
-rw-r--r--sql/wsrep_var.cc22
-rw-r--r--sql/wsrep_var.h1
28 files changed, 239 insertions, 190 deletions
diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc
index 4afa2168b8d..93f6f32d473 100644
--- a/sql/ha_sequence.cc
+++ b/sql/ha_sequence.cc
@@ -259,8 +259,7 @@ int ha_sequence::write_row(uchar *buf)
sequence->copy(&tmp_seq);
rows_changed++;
/* We have to do the logging while we hold the sequence mutex */
- if (table->file->check_table_binlog_row_based(1))
- error= binlog_log_row(table, 0, buf, log_func);
+ error= binlog_log_row(table, 0, buf, log_func);
row_already_logged= 1;
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 7662d68e51f..e5362c7cf9c 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -5899,29 +5899,6 @@ bool handler::check_table_binlog_row_based_internal(bool binlog_row)
{
THD *thd= table->in_use;
-#ifdef WITH_WSREP
- /* only InnoDB tables will be replicated through binlog emulation */
- if (binlog_row &&
- ((WSREP_EMULATE_BINLOG(thd) &&
- table->file->partition_ht()->db_type != DB_TYPE_INNODB) ||
- (thd->wsrep_ignore_table == true)))
- return 0;
-
- /* enforce wsrep_max_ws_rows */
- if (WSREP(thd) && table->s->tmp_table == NO_TMP_TABLE)
- {
- thd->wsrep_affected_rows++;
- if (wsrep_max_ws_rows &&
- thd->wsrep_exec_mode != REPL_RECV &&
- thd->wsrep_affected_rows > wsrep_max_ws_rows)
- {
- trans_rollback_stmt(thd) || trans_rollback(thd);
- my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0));
- return ER_ERROR_DURING_COMMIT;
- }
- }
-#endif
-
return (table->s->can_do_row_logging &&
thd->is_current_stmt_binlog_format_row() &&
/*
@@ -6030,12 +6007,10 @@ static int write_locked_table_maps(THD *thd)
}
-static int check_wsrep_max_ws_rows();
-
-int binlog_log_row(TABLE* table,
- const uchar *before_record,
- const uchar *after_record,
- Log_func *log_func)
+static int binlog_log_row_internal(TABLE* table,
+ const uchar *before_record,
+ const uchar *after_record,
+ Log_func *log_func)
{
bool error= 0;
THD *const thd= table->in_use;
@@ -6059,17 +6034,42 @@ int binlog_log_row(TABLE* table,
bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
table->file->has_transactions();
error= (*log_func)(thd, table, has_trans, before_record, after_record);
-
- /*
- Now that the record has been logged, increment wsrep_affected_rows and
- also check whether its within the allowable limits (wsrep_max_ws_rows).
- */
- if (error == 0)
- error= check_wsrep_max_ws_rows();
}
return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
}
+int binlog_log_row(TABLE* table, const uchar *before_record,
+ const uchar *after_record, Log_func *log_func)
+{
+#ifdef WITH_WSREP
+ THD *const thd= table->in_use;
+
+ /* only InnoDB tables will be replicated through binlog emulation */
+ if ((WSREP_EMULATE_BINLOG(thd) &&
+ table->file->partition_ht()->db_type != DB_TYPE_INNODB) ||
+ (thd->wsrep_ignore_table == true))
+ return 0;
+
+ /* enforce wsrep_max_ws_rows */
+ if (WSREP(thd) && table->s->tmp_table == NO_TMP_TABLE)
+ {
+ thd->wsrep_affected_rows++;
+ if (wsrep_max_ws_rows &&
+ thd->wsrep_exec_mode != REPL_RECV &&
+ thd->wsrep_affected_rows > wsrep_max_ws_rows)
+ {
+ trans_rollback_stmt(thd) || trans_rollback(thd);
+ my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0));
+ return ER_ERROR_DURING_COMMIT;
+ }
+ }
+#endif
+
+ if (!table->file->check_table_binlog_row_based(1))
+ return 0;
+ return binlog_log_row_internal(table, before_record, after_record, log_func);
+}
+
int handler::ha_external_lock(THD *thd, int lock_type)
{
@@ -6175,30 +6175,6 @@ int handler::ha_reset()
}
-static int check_wsrep_max_ws_rows()
-{
-#ifdef WITH_WSREP
- if (wsrep_max_ws_rows)
- {
- THD *thd= current_thd;
-
- if (!WSREP(thd))
- return 0;
-
- thd->wsrep_affected_rows++;
- if (thd->wsrep_exec_mode != REPL_RECV &&
- thd->wsrep_affected_rows > wsrep_max_ws_rows)
- {
- trans_rollback_stmt(thd) || trans_rollback(thd);
- my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0));
- return ER_ERROR_DURING_COMMIT;
- }
- }
-#endif /* WITH_WSREP */
- return 0;
-}
-
-
int handler::ha_write_row(uchar *buf)
{
int error;
@@ -6219,8 +6195,7 @@ int handler::ha_write_row(uchar *buf)
if (likely(!error) && !row_already_logged)
{
rows_changed++;
- if (table->file->check_table_binlog_row_based(1))
- error= binlog_log_row(table, 0, buf, log_func);
+ error= binlog_log_row(table, 0, buf, log_func);
}
DEBUG_SYNC_C("ha_write_row_end");
DBUG_RETURN(error);
@@ -6252,8 +6227,7 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
if (likely(!error) && !row_already_logged)
{
rows_changed++;
- if (table->file->check_table_binlog_row_based(1))
- error= binlog_log_row(table, old_data, new_data, log_func);
+ error= binlog_log_row(table, old_data, new_data, log_func);
}
return error;
}
@@ -6308,8 +6282,7 @@ int handler::ha_delete_row(const uchar *buf)
if (likely(!error))
{
rows_changed++;
- if (table->file->check_table_binlog_row_based(1))
- error= binlog_log_row(table, buf, 0, log_func);
+ error= binlog_log_row(table, buf, 0, log_func);
}
return error;
}
diff --git a/sql/item.cc b/sql/item.cc
index 215c1450a3c..b955e4372e9 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -149,19 +149,21 @@ bool Item::get_time_with_conversion(THD *thd, MYSQL_TIME *ltime,
- truncate the YYYYMMDD part
- add (MM*33+DD)*24 to hours
- add (MM*31+DD)*24 to hours
- Let's return NULL here, to disallow equal field propagation.
+ Let's return TRUE here, to disallow equal field propagation.
Note, If we start to use this method in more pieces of the code other
- than eqial field propagation, we should probably return
- NULL only if some flag in fuzzydate is set.
+ than equal field propagation, we should probably return
+ TRUE only if some flag in fuzzydate is set.
*/
- return (null_value= true);
+ return true;
}
if (datetime_to_time_with_warn(thd, ltime, &ltime2, TIME_SECOND_PART_DIGITS))
{
/*
- Time difference between CURRENT_DATE and ltime
- did not fit into the supported TIME range
+ If the time difference between CURRENT_DATE and ltime
+ did not fit into the supported TIME range, then we set the
+ difference to the maximum possible value in the supported TIME range
*/
+ DBUG_ASSERT(0);
return (null_value= true);
}
*ltime= ltime2;
@@ -10042,7 +10044,7 @@ double Item_cache_temporal::val_real()
}
-bool Item_cache_temporal::cache_value()
+bool Item_cache_temporal::cache_value()
{
if (!example)
return false;
@@ -10071,12 +10073,11 @@ bool Item_cache_temporal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
if (!has_value())
{
bzero((char*) ltime,sizeof(*ltime));
- return 1;
+ return true;
}
unpack_time(value, ltime, mysql_timestamp_type());
return 0;
-
}
diff --git a/sql/item.h b/sql/item.h
index 06720a33cf8..860a1fb1bde 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -27,6 +27,7 @@
#include "sql_const.h" /* RAND_TABLE_BIT, MAX_FIELD_NAME */
#include "field.h" /* Derivation */
#include "sql_type.h"
+#include "sql_time.h"
C_MODE_START
#include <ma_dyncol.h>
@@ -4404,7 +4405,7 @@ class Item_date_literal_for_invalid_dates: public Item_date_literal
Item_date_literal_for_invalid_dates::get_date()
(unlike the regular Item_date_literal::get_date())
- does not check the result for NO_ZERO_IN_DATE and NO_ZER_DATE,
+ does not check the result for NO_ZERO_IN_DATE and NO_ZERO_DATE,
always returns success (false), and does not produce error/warning messages.
We need these _for_invalid_dates classes to be able to rewrite:
@@ -6057,7 +6058,7 @@ public:
virtual Item *get_item() { return example; }
virtual bool cache_value()= 0;
bool basic_const_item() const
- { return MY_TEST(example && example->basic_const_item()); }
+ { return example && example->basic_const_item(); }
virtual void clear() { null_value= TRUE; value_cached= FALSE; }
bool is_null() { return !has_value(); }
virtual bool is_expensive()
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 6e19cfcdf80..89aa307486e 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -34,7 +34,6 @@
#include "sql_time.h" // make_truncated_value_warning
#include "sql_base.h" // dynamic_column_error_message
-
/**
find an temporal type (item) that others will be converted to
for the purpose of comparison.
@@ -42,7 +41,7 @@
this is the type that will be used in warnings like
"Incorrect <<TYPE>> value".
*/
-Item *find_date_time_item(Item **args, uint nargs, uint col)
+static Item *find_date_time_item(Item **args, uint nargs, uint col)
{
Item *date_arg= 0, **arg, **arg_end;
for (arg= args, arg_end= args + nargs; arg != arg_end ; arg++)
@@ -3067,22 +3066,12 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref)
/**
Check if (*place) and new_value points to different Items and call
THD::change_item_tree() if needed.
-
- This function is a workaround for implementation deficiency in
- Item_func_case. The problem there is that the 'args' attribute contains
- Items from different expressions.
-
- The function must not be used elsewhere and will be remove eventually.
*/
-static void change_item_tree_if_needed(THD *thd,
- Item **place,
- Item *new_value)
+static void change_item_tree_if_needed(THD *thd, Item **place, Item *new_value)
{
- if (*place == new_value)
- return;
-
- thd->change_item_tree(place, new_value);
+ if (new_value && *place != new_value)
+ thd->change_item_tree(place, new_value);
}
@@ -3270,10 +3259,11 @@ Item* Item_func_case_simple::propagate_equal_fields(THD *thd,
for (uint i= 0; i < arg_count; i++)
{
/*
- Even "i" values cover items that are in a comparison context:
- CASE x0 WHEN x1 .. WHEN x2 .. WHEN x3 ..
- Odd "i" values cover items that are not in comparison:
- CASE ... THEN y1 ... THEN y2 ... THEN y3 ... ELSE y4 END
+ These arguments are in comparison.
+ Allow invariants of the same value during propagation.
+ Note, as we pass ANY_SUBST, none of the WHEN arguments will be
+ replaced to zero-filled constants (only IDENTITY_SUBST allows this).
+ Such a change for WHEN arguments would require rebuilding cmp_items.
*/
Item *new_item= 0;
if (i == 0) // Then CASE (the switch) argument
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 4caf7e4622d..3d11a226d07 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -363,6 +363,7 @@ public:
bool is_null();
longlong val_int();
void cleanup();
+ enum Functype functype() const { return IN_OPTIMIZER_FUNC; }
const char *func_name() const { return "<in_optimizer>"; }
Item_cache **get_cache() { return &cache; }
void keep_top_level_cache();
@@ -380,6 +381,8 @@ public:
void reset_cache() { cache= NULL; }
virtual void print(String *str, enum_query_type query_type);
void restore_first_argument();
+ Item* get_wrapped_in_subselect_item()
+ { return args[1]; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_in_optimizer>(thd, this); }
};
@@ -550,14 +553,13 @@ public:
clone->cmp.comparators= 0;
}
return clone;
- }
-
+ }
};
/**
XOR inherits from Item_bool_func because it is not optimized yet.
Later, when XOR is optimized, it needs to inherit from
- Item_cond instead. See WL#5800.
+ Item_cond instead. See WL#5800.
*/
class Item_func_xor :public Item_bool_func
{
@@ -1195,7 +1197,7 @@ class Item_func_nullif :public Item_func_case_expression
The left "a" is in a comparison and can be replaced by:
- Item_func::convert_const_compared_to_int_field()
- agg_item_set_converter() in set_cmp_func()
- - Arg_comparator::cache_converted_constant() in set_cmp_func()
+ - cache_converted_constant() in set_cmp_func()
Both "a"s are subject to equal fields propagation and can be replaced by:
- Item_field::propagate_equal_fields(ANY_SUBST) for the left "a"
@@ -1395,9 +1397,6 @@ public:
/*
Class to represent a vector of constant DATE/DATETIME values.
- Values are obtained with help of the get_datetime_value() function.
- If the left item is a constant one then its value is cached in the
- lval_cache variable.
*/
class in_temporal :public in_longlong
{
@@ -1538,6 +1537,13 @@ public:
{
value_res= item->val_str(&value);
m_null_value= item->null_value;
+ // Make sure to cache the result String inside "value"
+ if (value_res && value_res != &value)
+ {
+ if (value.copy(*value_res))
+ value.set("", 0, item->collation.collation);
+ value_res= &value;
+ }
}
int cmp_not_null(const Value *val)
{
@@ -1602,9 +1608,6 @@ public:
/*
Compare items in the DATETIME context.
- Values are obtained with help of the get_datetime_value() function.
- If the left item is a constant one then its value is cached in the
- lval_cache variable.
*/
class cmp_item_temporal: public cmp_item_scalar
{
@@ -3115,6 +3118,11 @@ public:
void sort(Item_field_cmpfunc compare, void *arg);
void fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
+ void cleanup()
+ {
+ delete eval_item;
+ eval_item= NULL;
+ }
void update_used_tables();
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
bool link_item_fields,
@@ -3405,10 +3413,6 @@ inline bool is_cond_or(Item *item)
Item *and_expressions(Item *a, Item *b, Item **org_item);
-longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
- enum_field_types f_type, bool *is_null);
-
-
class Comp_creator
{
public:
diff --git a/sql/item_func.h b/sql/item_func.h
index fb775b36ca4..f33b936d8c7 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -74,7 +74,8 @@ public:
NOW_FUNC, NOW_UTC_FUNC, SYSDATE_FUNC, TRIG_COND_FUNC,
SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC,
EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC,
- NEG_FUNC, GSYSVAR_FUNC, DYNCOL_FUNC, JSON_EXTRACT_FUNC };
+ NEG_FUNC, GSYSVAR_FUNC, IN_OPTIMIZER_FUNC, DYNCOL_FUNC,
+ JSON_EXTRACT_FUNC };
enum Type type() const { return FUNC_ITEM; }
virtual enum Functype functype() const { return UNKNOWN_FUNC; }
Item_func(THD *thd): Item_func_or_sum(thd)
@@ -3128,7 +3129,6 @@ public:
Item *get_system_var(THD *thd, enum_var_type var_type,
const LEX_CSTRING *name, const LEX_CSTRING *component);
extern bool check_reserved_words(const LEX_CSTRING *name);
-Item *find_date_time_item(Item **args, uint nargs, uint col);
double my_double_round(double value, longlong dec, bool dec_unsigned,
bool truncate);
bool eval_const_cond(COND *cond);
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index a8051ccd469..6378e9b76bf 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1819,7 +1819,7 @@ Item_in_subselect::single_value_transformer(JOIN *join)
Item* join_having= join->having ? join->having : join->tmp_having;
if (!(join_having || select_lex->with_sum_func ||
select_lex->group_list.elements) &&
- select_lex->table_list.elements == 0 &&
+ select_lex->table_list.elements == 0 && !join->conds &&
!select_lex->master_unit()->is_unit_op())
{
Item *where_item= (Item*) select_lex->item_list.head();
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index f612b4d6aa2..5f4a489fca1 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -714,7 +714,7 @@ static bool get_interval_info(const char *str, size_t length,CHARSET_INFO *cs, s
{
const char *end=str+length;
uint i;
- int msec_length= 0;
+ size_t field_length= 0;
while (str != end && !my_isdigit(cs,*str))
str++;
@@ -725,7 +725,8 @@ static bool get_interval_info(const char *str, size_t length,CHARSET_INFO *cs, s
const char *start= str;
for (value= 0; str != end && my_isdigit(cs, *str); str++)
value= value*10 + *str - '0';
- msec_length= 6 - (int)(str - start);
+ if ((field_length= (size_t)(str - start)) >= 20)
+ return true;
values[i]= value;
while (str != end && !my_isdigit(cs,*str))
str++;
@@ -740,8 +741,13 @@ static bool get_interval_info(const char *str, size_t length,CHARSET_INFO *cs, s
}
}
- if (transform_msec && msec_length > 0)
- values[count - 1] *= (long) log_10_int[msec_length];
+ if (transform_msec && field_length > 0)
+ {
+ if (field_length < 6)
+ values[count - 1] *= log_10_int[6 - field_length];
+ else if (field_length > 6)
+ values[count - 1] /= log_10_int[field_length - 6];
+ }
return (str != end);
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 60ad41eed39..0eee10d5e7a 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -5757,8 +5757,7 @@ int mysqld_main(int argc, char **argv)
orig_argc= argc;
orig_argv= argv;
my_getopt_use_args_separator= TRUE;
- if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv))
- return 1;
+ load_defaults_or_exit(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv);
my_getopt_use_args_separator= FALSE;
defaults_argc= argc;
defaults_argv= argv;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index eff28d0c27d..a723980ad50 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -848,8 +848,10 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
Make sure that create_tmp_table will not fail due to too long keys.
See MDEV-7122. This check is performed inside create_tmp_table also and
we must do it so that we know the table has keys created.
+ Make sure that the length of the key for the temp_table is atleast
+ greater than 0.
*/
- if (total_key_length > tmp_table_max_key_length() ||
+ if (!total_key_length || total_key_length > tmp_table_max_key_length() ||
elements > tmp_table_max_key_parts())
DBUG_RETURN(FALSE);
@@ -979,6 +981,10 @@ bool check_for_outer_joins(List<TABLE_LIST> *join_list)
void find_and_block_conversion_to_sj(Item *to_find,
List_iterator_fast<Item_in_subselect> &li)
{
+ if (to_find->type() == Item::FUNC_ITEM &&
+ ((Item_func*)to_find)->functype() == Item_func::IN_OPTIMIZER_FUNC)
+ to_find= ((Item_in_optimizer*)to_find)->get_wrapped_in_subselect_item();
+
if (to_find->type() != Item::SUBSELECT_ITEM ||
((Item_subselect *) to_find)->substype() != Item_subselect::IN_SUBS)
return;
diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc
index b2b13c5467b..9f8a3450716 100644
--- a/sql/rpl_parallel.cc
+++ b/sql/rpl_parallel.cc
@@ -229,6 +229,14 @@ finish_event_group(rpl_parallel_thread *rpt, uint64 sub_id,
entry->stop_on_error_sub_id= sub_id;
mysql_mutex_unlock(&entry->LOCK_parallel_entry);
+ DBUG_EXECUTE_IF("rpl_parallel_simulate_wait_at_retry", {
+ if (rgi->current_gtid.seq_no == 1000) {
+ DBUG_ASSERT(entry->stop_on_error_sub_id == sub_id);
+ debug_sync_set_action(thd,
+ STRING_WITH_LEN("now WAIT_FOR proceed_by_1000"));
+ }
+ });
+
if (rgi->killed_for_retry == rpl_group_info::RETRY_KILL_PENDING)
wait_for_pending_deadlock_kill(thd, rgi);
thd->clear_error();
@@ -722,6 +730,14 @@ do_retry:
rgi->killed_for_retry= rpl_group_info::RETRY_KILL_KILLED;
thd->set_killed(KILL_CONNECTION);
});
+ DBUG_EXECUTE_IF("rpl_parallel_simulate_wait_at_retry", {
+ if (rgi->current_gtid.seq_no == 1001) {
+ debug_sync_set_action(thd,
+ STRING_WITH_LEN("rpl_parallel_simulate_wait_at_retry WAIT_FOR proceed_by_1001"));
+ }
+ DEBUG_SYNC(thd, "rpl_parallel_simulate_wait_at_retry");
+ });
+
rgi->cleanup_context(thd, 1);
wait_for_pending_deadlock_kill(thd, rgi);
thd->reset_killed();
@@ -745,7 +761,26 @@ do_retry:
for (;;)
{
mysql_mutex_lock(&entry->LOCK_parallel_entry);
- register_wait_for_prior_event_group_commit(rgi, entry);
+ if (entry->stop_on_error_sub_id == (uint64) ULONGLONG_MAX ||
+#ifndef DBUG_OFF
+ (DBUG_EVALUATE_IF("simulate_mdev_12746", 1, 0)) ||
+#endif
+ rgi->gtid_sub_id < entry->stop_on_error_sub_id)
+ {
+ register_wait_for_prior_event_group_commit(rgi, entry);
+ }
+ else
+ {
+ /*
+ A failure of a preceeding "parent" transaction may not be
+ seen by the current one through its own worker_error.
+ Such induced error gets set by ourselves now.
+ */
+ err= rgi->worker_error= 1;
+ my_error(ER_PRIOR_COMMIT_FAILED, MYF(0));
+ mysql_mutex_unlock(&entry->LOCK_parallel_entry);
+ goto err;
+ }
mysql_mutex_unlock(&entry->LOCK_parallel_entry);
/*
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index c725bf39eb0..c55c1c4187c 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -1807,7 +1807,7 @@ ER_NORMAL_SHUTDOWN
cze "%s (%s): normální ukončení"
dan "%s (%s): Normal nedlukning"
nla "%s (%s): Normaal afgesloten "
- eng "%s (%s): Normal shutdown"
+ eng "%s (initiated by: %s): Normal shutdown"
est "%s (%s): MariaDB lõpetas"
fre "%s (%s): Arrêt normal du serveur"
ger "%s (%s): Normal heruntergefahren"
@@ -1822,7 +1822,7 @@ ER_NORMAL_SHUTDOWN
pol "%s (%s): Standardowe zakończenie działania"
por "%s (%s): 'Shutdown' normal"
rum "%s (%s): Terminare normala"
- rus "%s (%s): Корректная остановка"
+ rus "%s (инициирована пользователем: %s): Корректная остановка"
serbian "%s (%s): Normalno gašenje"
slo "%s (%s): normálne ukončenie"
spa "%s (%s): Apagado normal"
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b3b2c8233bf..9e6eb1fc0e2 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2898,15 +2898,19 @@ Item_change_list::check_and_register_item_tree_change(Item **place,
void Item_change_list::rollback_item_tree_changes()
{
+ DBUG_ENTER("THD::rollback_item_tree_changes");
I_List_iterator<Item_change_record> it(change_list);
Item_change_record *change;
while ((change= it++))
{
+ DBUG_PRINT("info", ("Rollback: %p (%p) <- %p",
+ *change->place, change->place, change->old_value));
*change->place= change->old_value;
}
/* We can forget about changes memory: it's allocated in runtime memroot */
change_list.empty();
+ DBUG_VOID_RETURN;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 79370510e67..61d80003046 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -6114,11 +6114,15 @@ public:
sent by the user (ie: stored procedure).
*/
#define CF_SKIP_QUESTIONS (1U << 1)
-
+#ifdef WITH_WSREP
/**
Do not check that wsrep snapshot is ready before allowing this command
*/
#define CF_SKIP_WSREP_CHECK (1U << 2)
+#else
+#define CF_SKIP_WSREP_CHECK 0
+#endif /* WITH_WSREP */
+
/**
Do not allow it for COM_MULTI batch
*/
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f5fe955375d..b89d78874f5 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
- Copyright (c) 2008, 2017, MariaDB
+ Copyright (c) 2008, 2018, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -501,6 +501,7 @@ void init_update_queries(void)
server_command_flags[COM_SHUTDOWN]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_SLEEP]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_TIME]= CF_SKIP_WSREP_CHECK;
+ server_command_flags[COM_INIT_DB]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_END]= CF_SKIP_WSREP_CHECK;
for (uint i= COM_MDB_GAP_BEG; i <= COM_MDB_GAP_END; i++)
{
@@ -514,6 +515,8 @@ void init_update_queries(void)
server_command_flags[COM_QUERY]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_SET_OPTION]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_STMT_PREPARE]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK;
+ server_command_flags[COM_STMT_EXECUTE]= CF_SKIP_WSREP_CHECK;
+ server_command_flags[COM_STMT_FETCH]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_STMT_CLOSE]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK;
server_command_flags[COM_STMT_RESET]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK;
server_command_flags[COM_STMT_EXECUTE]= CF_SKIP_WSREP_CHECK;
@@ -1168,21 +1171,21 @@ static enum enum_server_command fetch_command(THD *thd, char *packet)
}
-#ifndef EMBEDDED_LIBRARY
-
#ifdef WITH_WSREP
-static bool wsrep_node_is_ready(THD *thd)
+static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables)
{
- if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready)
+ for (const TABLE_LIST *table= tables; table; table= table->next_global)
{
- my_message(ER_UNKNOWN_COM_ERROR,
- "WSREP has not yet prepared node for application use",
- MYF(0));
- return false;
+ TABLE_CATEGORY c;
+ LEX_CSTRING db= table->db, tn= table->table_name;
+ c= get_table_category(&db, &tn);
+ if (c != TABLE_CATEGORY_INFORMATION && c != TABLE_CATEGORY_PERFORMANCE)
+ return false;
}
return true;
}
-#endif
+#endif /* WITH_WSREP */
+#ifndef EMBEDDED_LIBRARY
/**
Read one command from connection and execute it (query or simple command).
@@ -1359,8 +1362,9 @@ bool do_command(THD *thd)
/*
Bail out if DB snapshot has not been installed.
*/
- if (!(server_command_flags[command] & CF_SKIP_WSREP_CHECK) &&
- !wsrep_node_is_ready(thd))
+ if (thd->variables.wsrep_on && !thd->wsrep_applier &&
+ (!wsrep_ready || wsrep_reject_queries != WSREP_REJECT_NONE) &&
+ (server_command_flags[command] & CF_SKIP_WSREP_CHECK) == 0)
{
thd->protocol->end_statement();
@@ -3437,20 +3441,23 @@ mysql_execute_command(THD *thd)
}
/*
- Bail out if DB snapshot has not been installed. SET and SHOW commands,
- however, are always allowed.
- Select query is also allowed if it does not access any table.
- We additionally allow all other commands that do not change data in
- case wsrep_dirty_reads is enabled.
- */
- if (lex->sql_command != SQLCOM_SET_OPTION &&
- !wsrep_is_show_query(lex->sql_command) &&
- !(thd->variables.wsrep_dirty_reads &&
- !is_update_query(lex->sql_command)) &&
- !(lex->sql_command == SQLCOM_SELECT &&
- !all_tables) &&
- !wsrep_node_is_ready(thd))
+ * Bail out if DB snapshot has not been installed. We however,
+ * allow SET and SHOW queries and reads from information schema
+ * and dirty reads (if configured)
+ */
+ if (thd->variables.wsrep_on &&
+ !thd->wsrep_applier &&
+ !(wsrep_ready && wsrep_reject_queries == WSREP_REJECT_NONE) &&
+ !(thd->variables.wsrep_dirty_reads &&
+ (sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) == 0) &&
+ !wsrep_tables_accessible_when_detached(all_tables) &&
+ lex->sql_command != SQLCOM_SET_OPTION &&
+ !wsrep_is_show_query(lex->sql_command))
+ {
+ my_message(ER_UNKNOWN_COM_ERROR,
+ "WSREP has not yet prepared node for application use", MYF(0));
goto error;
+ }
}
#endif /* WITH_WSREP */
status_var_increment(thd->status_var.com_stat[lex->sql_command]);
@@ -6059,9 +6066,6 @@ end_with_restore_list:
sp_head *sp;
const Sp_handler *sph= Sp_handler::handler(lex->sql_command);
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
-#ifdef WITH_WSREP
- if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error;
-#endif /* WITH_WSREP */
if (sph->sp_resolve_package_routine(thd, thd->lex->sphead,
lex->spname, &sph, &pkgname))
return true;
@@ -7840,7 +7844,6 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
thd->wsrep_conflict_state == CERT_FAILURE)
{
thd->reset_for_next_command();
- thd->reset_killed();
if (is_autocommit &&
thd->lex->sql_command != SQLCOM_SELECT &&
(thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit))
@@ -7870,17 +7873,18 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
thd->variables.wsrep_retry_autocommit, thd->query());
my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction",
MYF(0));
- thd->reset_killed();
thd->wsrep_conflict_state= NO_CONFLICT;
if (thd->wsrep_conflict_state != REPLAYING)
thd->wsrep_retry_counter= 0; // reset
}
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ thd->reset_killed();
}
else
{
set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
- mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
/* If retry is requested clean up explain structure */
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 22b8640d9ee..24f3cc66c6b 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -4623,6 +4623,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
Statement stmt_backup;
Query_arena *old_stmt_arena;
bool error= TRUE;
+ bool qc_executed= FALSE;
char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db_name=
@@ -4745,6 +4746,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
thd->lex->sql_command= SQLCOM_SELECT;
status_var_increment(thd->status_var.com_stat[SQLCOM_SELECT]);
thd->update_stats();
+ qc_executed= TRUE;
}
}
@@ -4783,7 +4785,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
thd->set_statement(&stmt_backup);
thd->stmt_arena= old_stmt_arena;
- if (state == Query_arena::STMT_PREPARED)
+ if (state == Query_arena::STMT_PREPARED && !qc_executed)
state= Query_arena::STMT_EXECUTED;
if (error == 0 && this->lex->sql_command == SQLCOM_CALL)
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 545f8111237..a64b8cbf18a 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -3836,6 +3836,13 @@ extern ST_SCHEMA_TABLE schema_tables[];
bool schema_table_store_record(THD *thd, TABLE *table)
{
int error;
+
+ if (thd->killed)
+ {
+ thd->send_kill_message();
+ return 1;
+ }
+
if ((error= table->file->ha_write_tmp_row(table->record[0])))
{
TMP_TABLE_PARAM *param= table->pos_in_table_list->schema_table_param;
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index 02731914d52..c748cd54415 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -1033,6 +1033,8 @@ bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type,
ltime->day= 0;
return 0;
}
+ else if (ltime->neg)
+ goto invalid_date;
if (int_type != INTERVAL_DAY)
ltime->time_type= MYSQL_TIMESTAMP_DATETIME; // Return full date
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 857c9a117f5..0149c2848c2 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -976,7 +976,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
*/
if (sl == first_sl)
{
- if (is_recursive)
+ if (with_element)
{
if (derived->with->rename_columns_of_derived_unit(thd, this))
goto err;
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index c144eb593a0..524ce974681 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates.
- Copyright (c) 2012, 2017, MariaDB Corporation.
+ Copyright (c) 2012, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -5416,6 +5416,14 @@ static Sys_var_mybool Sys_wsrep_desync (
ON_CHECK(wsrep_desync_check),
ON_UPDATE(wsrep_desync_update));
+static const char *wsrep_reject_queries_names[]= { "NONE", "ALL", "ALL_KILL", NullS };
+static Sys_var_enum Sys_wsrep_reject_queries(
+ "wsrep_reject_queries", "Variable to set to reject queries",
+ GLOBAL_VAR(wsrep_reject_queries), CMD_LINE(OPT_ARG),
+ wsrep_reject_queries_names, DEFAULT(WSREP_REJECT_NONE),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
+ ON_UPDATE(wsrep_reject_queries_update));
+
static const char *wsrep_binlog_format_names[]=
{"MIXED", "STATEMENT", "ROW", "NONE", NullS};
static Sys_var_enum Sys_wsrep_forced_binlog_format(
diff --git a/sql/tztime.cc b/sql/tztime.cc
index f7e2dcbefb8..277709ad9e9 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -2677,9 +2677,7 @@ main(int argc, char **argv)
char **default_argv;
MY_INIT(argv[0]);
- if (load_defaults("my",load_default_groups,&argc,&argv))
- exit(1);
-
+ load_defaults_or_exit("my", load_default_groups, &argc, &argv);
default_argv= argv;
if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
diff --git a/sql/wsrep_check_opts.cc b/sql/wsrep_check_opts.cc
index bf4ce7c9d90..0b7a9ca6252 100644
--- a/sql/wsrep_check_opts.cc
+++ b/sql/wsrep_check_opts.cc
@@ -50,7 +50,7 @@ int wsrep_check_opts()
(!strcasecmp(my_bind_addr_str, "127.0.0.1") ||
!strcasecmp(my_bind_addr_str, "localhost")))
{
- WSREP_ERROR("wsrep_sst_method is set to 'mysqldump' yet "
+ WSREP_WARN("wsrep_sst_method is set to 'mysqldump' yet "
"mysqld bind_address is set to '%s', which makes it "
"impossible to receive state transfer from another "
"node, since mysqld won't accept such connections. "
@@ -58,7 +58,6 @@ int wsrep_check_opts()
"set bind_address to allow mysql client connections "
"from other cluster members (e.g. 0.0.0.0).",
my_bind_addr_str);
- return 1;
}
}
else
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 91a77c65604..def52cb2675 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -394,7 +394,7 @@ wsrep_view_handler_cb (void* app_ctx,
if (!wsrep_before_SE())
{
WSREP_DEBUG("[debug]: closing client connections for PRIM");
- wsrep_close_client_connections(TRUE);
+ wsrep_close_client_connections(FALSE);
}
ssize_t const req_len= wsrep_sst_prepare (sst_req);
@@ -2373,7 +2373,7 @@ extern "C" void wsrep_thd_set_query_state(
void wsrep_thd_set_conflict_state(THD *thd, enum wsrep_conflict_state state)
{
- thd->wsrep_conflict_state= state;
+ if (WSREP(thd)) thd->wsrep_conflict_state= state;
}
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 2cb35db01b7..c6b1f42ce14 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -80,6 +80,7 @@ extern const char* wsrep_notify_cmd;
extern long wsrep_max_protocol_version;
extern ulong wsrep_forced_binlog_format;
extern my_bool wsrep_desync;
+extern ulong wsrep_reject_queries;
extern my_bool wsrep_replicate_myisam;
extern ulong wsrep_mysql_replication_bundle;
extern my_bool wsrep_restart_slave;
@@ -91,6 +92,12 @@ extern bool wsrep_new_cluster;
extern bool wsrep_gtid_mode;
extern uint32 wsrep_gtid_domain_id;
+enum enum_wsrep_reject_types {
+ WSREP_REJECT_NONE, /* nothing rejected */
+ WSREP_REJECT_ALL, /* reject all queries, with UNKNOWN_COMMAND error */
+ WSREP_REJECT_ALL_KILL /* kill existing connections and reject all queries*/
+};
+
enum enum_wsrep_OSU_method {
WSREP_OSU_TOI,
WSREP_OSU_RSU,
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index 41044085625..d19bcafb8d6 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -78,37 +78,14 @@ static void make_wsrep_defaults_file()
}
-// TODO: Improve address verification.
-static bool sst_receive_address_check (const char* str)
-{
- if (!strncasecmp(str, "127.0.0.1", strlen("127.0.0.1")) ||
- !strncasecmp(str, "localhost", strlen("localhost")))
- {
- return 1;
- }
-
- return 0;
-}
-
bool wsrep_sst_receive_address_check (sys_var *self, THD* thd, set_var* var)
{
- char addr_buf[FN_REFLEN];
-
if ((! var->save_result.string_value.str) ||
(var->save_result.string_value.length > (FN_REFLEN - 1))) // safety
{
goto err;
}
- memcpy(addr_buf, var->save_result.string_value.str,
- var->save_result.string_value.length);
- addr_buf[var->save_result.string_value.length]= 0;
-
- if (sst_receive_address_check(addr_buf))
- {
- goto err;
- }
-
return 0;
err:
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index ffa969a811c..d94ac240b76 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -26,6 +26,7 @@
#include <cstdio>
#include <cstdlib>
+ulong wsrep_reject_queries;
static long wsrep_prev_slave_threads = wsrep_slave_threads;
@@ -413,6 +414,27 @@ void wsrep_provider_options_init(const char* value)
wsrep_provider_options = (value) ? my_strdup(value, MYF(0)) : NULL;
}
+bool wsrep_reject_queries_update(sys_var *self, THD* thd, enum_var_type type)
+{
+ switch (wsrep_reject_queries) {
+ case WSREP_REJECT_NONE:
+ WSREP_INFO("Allowing client queries due to manual setting");
+ break;
+ case WSREP_REJECT_ALL:
+ WSREP_INFO("Rejecting client queries due to manual setting");
+ break;
+ case WSREP_REJECT_ALL_KILL:
+ wsrep_close_client_connections(FALSE);
+ WSREP_INFO("Rejecting client queries and killing connections due to manual setting");
+ break;
+ default:
+ WSREP_INFO("Unknown value for wsrep_reject_queries: %lu",
+ wsrep_reject_queries);
+ return true;
+ }
+ return false;
+}
+
static int wsrep_cluster_address_verify (const char* cluster_address_str)
{
/* There is no predefined address format, it depends on provider. */
diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h
index b9051b29843..7d3ff50f1d2 100644
--- a/sql/wsrep_var.h
+++ b/sql/wsrep_var.h
@@ -92,6 +92,7 @@ extern bool wsrep_desync_update UPDATE_ARGS;
extern bool wsrep_max_ws_size_check CHECK_ARGS;
extern bool wsrep_max_ws_size_update UPDATE_ARGS;
+extern bool wsrep_reject_queries_update UPDATE_ARGS;
#else /* WITH_WSREP */