diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_sequence.cc | 3 | ||||
-rw-r--r-- | sql/handler.cc | 105 | ||||
-rw-r--r-- | sql/item.cc | 19 | ||||
-rw-r--r-- | sql/item.h | 5 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 28 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 32 | ||||
-rw-r--r-- | sql/item_func.h | 4 | ||||
-rw-r--r-- | sql/item_subselect.cc | 2 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 14 | ||||
-rw-r--r-- | sql/mysqld.cc | 3 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 8 | ||||
-rw-r--r-- | sql/rpl_parallel.cc | 37 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 4 | ||||
-rw-r--r-- | sql/sql_class.cc | 4 | ||||
-rw-r--r-- | sql/sql_class.h | 6 | ||||
-rw-r--r-- | sql/sql_parse.cc | 66 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 4 | ||||
-rw-r--r-- | sql/sql_show.cc | 7 | ||||
-rw-r--r-- | sql/sql_time.cc | 2 | ||||
-rw-r--r-- | sql/sql_union.cc | 2 | ||||
-rw-r--r-- | sql/sys_vars.cc | 10 | ||||
-rw-r--r-- | sql/tztime.cc | 4 | ||||
-rw-r--r-- | sql/wsrep_check_opts.cc | 3 | ||||
-rw-r--r-- | sql/wsrep_mysqld.cc | 4 | ||||
-rw-r--r-- | sql/wsrep_mysqld.h | 7 | ||||
-rw-r--r-- | sql/wsrep_sst.cc | 23 | ||||
-rw-r--r-- | sql/wsrep_var.cc | 22 | ||||
-rw-r--r-- | sql/wsrep_var.h | 1 |
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, <ime2, 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 */ |