diff options
Diffstat (limited to 'sql')
46 files changed, 722 insertions, 383 deletions
diff --git a/sql/backup.cc b/sql/backup.cc index e89f9a108a7..539dc9c31f4 100644 --- a/sql/backup.cc +++ b/sql/backup.cc @@ -34,6 +34,7 @@ #include "sql_insert.h" // kill_delayed_threads #include "sql_handler.h" // mysql_ha_cleanup_no_free #include <my_sys.h> +#include "wsrep_mysqld.h" static const char *stage_names[]= {"START", "FLUSH", "BLOCK_DDL", "BLOCK_COMMIT", "END", 0}; @@ -255,6 +256,21 @@ static bool backup_block_ddl(THD *thd) (void) flush_tables(thd, FLUSH_NON_TRANS_TABLES); thd->clear_error(); +#ifdef WITH_WSREP + /* + We desync the node for BACKUP STAGE because applier threads + bypass backup MDL locks (see MDL_lock::can_grant_lock) + */ + if (WSREP_NNULL(thd)) + { + Wsrep_server_state &server_state= Wsrep_server_state::instance(); + if (server_state.desync_and_pause().is_undefined()) { + DBUG_RETURN(1); + } + thd->wsrep_desynced_backup_stage= true; + } +#endif /* WITH_WSREP */ + /* block new DDL's, in addition to all previous blocks We didn't do this lock above, as we wanted DDL's to be executed while @@ -319,6 +335,14 @@ bool backup_end(THD *thd) ha_end_backup(); thd->current_backup_stage= BACKUP_FINISHED; thd->mdl_context.release_lock(backup_flush_ticket); +#ifdef WITH_WSREP + if (WSREP_NNULL(thd) && thd->wsrep_desynced_backup_stage) + { + Wsrep_server_state &server_state= Wsrep_server_state::instance(); + server_state.resume_and_resync(); + thd->wsrep_desynced_backup_stage= false; + } +#endif /* WITH_WSREP */ } DBUG_RETURN(0); } diff --git a/sql/field.cc b/sql/field.cc index ab4f6a96921..71ca27c5ad0 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6399,6 +6399,7 @@ bool Field_timef::val_native(Native *to) int Field_year::store(const char *from, size_t len,CHARSET_INFO *cs) { DBUG_ASSERT(marked_for_write_or_computed()); + THD *thd= get_thd(); char *end; int error; longlong nr= cs->strntoull10rnd(from, len, 0, &end, &error); @@ -6410,7 +6411,14 @@ int Field_year::store(const char *from, size_t len,CHARSET_INFO *cs) set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); return 1; } - if (get_thd()->count_cuted_fields > CHECK_FIELD_EXPRESSION && + + if (thd->count_cuted_fields <= CHECK_FIELD_EXPRESSION && error == MY_ERRNO_EDOM) + { + *ptr= 0; + return 1; + } + + if (thd->count_cuted_fields > CHECK_FIELD_EXPRESSION && (error= check_int(cs, from, len, end, error))) { if (unlikely(error == 1) /* empty or incorrect string */) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 6b7f6a880d9..2c60a98de33 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5572,8 +5572,7 @@ int ha_partition::index_init(uint inx, bool sorted) do { for (i= 0; i < (*key_info)->user_defined_key_parts; i++) - bitmap_set_bit(table->read_set, - (*key_info)->key_part[i].field->field_index); + (*key_info)->key_part[i].field->register_field_in_read_map(); } while (*(++key_info)); } for (i= bitmap_get_first_set(&m_part_info->read_partitions); diff --git a/sql/handler.cc b/sql/handler.cc index 112ed23939e..7e5975d7477 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1686,13 +1686,27 @@ int ha_commit_trans(THD *thd, bool all) goto err; } DBUG_ASSERT(trx_start_id); +#ifdef WITH_WSREP + bool saved_wsrep_on= thd->variables.wsrep_on; + thd->variables.wsrep_on= false; +#endif TR_table trt(thd, true); if (trt.update(trx_start_id, trx_end_id)) +#ifdef WITH_WSREP + { + thd->variables.wsrep_on= saved_wsrep_on; +#endif goto err; +#ifdef WITH_WSREP + } +#endif // Here, the call will not commit inside InnoDB. It is only working // around closing thd->transaction.stmt open by TR_table::open(). if (all) commit_one_phase_2(thd, false, &thd->transaction->stmt, false); +#ifdef WITH_WSREP + thd->variables.wsrep_on= saved_wsrep_on; +#endif } } #endif diff --git a/sql/item.cc b/sql/item.cc index 6e45c6a8086..8f6bfdc6b09 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4422,13 +4422,15 @@ bool Item_param::get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) } -double Item_param::PValue::val_real() const +double Item_param::PValue::val_real(const Type_std_attributes *attr) const { switch (type_handler()->cmp_type()) { case REAL_RESULT: return real; case INT_RESULT: - return (double) integer; + return attr->unsigned_flag + ? (double) (ulonglong) integer + : (double) integer; case DECIMAL_RESULT: return m_decimal.to_double(); case STRING_RESULT: @@ -4502,7 +4504,7 @@ String *Item_param::PValue::val_str(String *str, str->set_real(real, NOT_FIXED_DEC, &my_charset_bin); return str; case INT_RESULT: - str->set(integer, &my_charset_bin); + str->set_int(integer, attr->unsigned_flag, &my_charset_bin); return str; case DECIMAL_RESULT: if (m_decimal.to_string_native(str, 0, 0, 0) <= 1) diff --git a/sql/item.h b/sql/item.h index 74ffce6153f..2720dddefd9 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3930,7 +3930,7 @@ class Item_param :public Item_basic_value, m_string.swap(other.m_string); m_string_ptr.swap(other.m_string_ptr); } - double val_real() const; + double val_real(const Type_std_attributes *attr) const; longlong val_int(const Type_std_attributes *attr) const; my_decimal *val_decimal(my_decimal *dec, const Type_std_attributes *attr); String *val_str(String *str, const Type_std_attributes *attr); @@ -4026,7 +4026,7 @@ public: double val_real() override { - return can_return_value() ? value.val_real() : 0e0; + return can_return_value() ? value.val_real(this) : 0e0; } longlong val_int() override { @@ -6448,12 +6448,15 @@ public: class Item_default_value : public Item_field { + bool vcol_assignment_ok; void calculate(); public: Item *arg= nullptr; Field *cached_field= nullptr; - Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a) : - Item_field(thd, context_arg), arg(a) {} + Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a, + bool vcol_assignment_arg) + : Item_field(thd, context_arg), + vcol_assignment_ok(vcol_assignment_arg), arg(a) {} Type type() const override { return DEFAULT_VALUE_ITEM; } bool eq(const Item *item, bool binary_cmp) const override; bool fix_fields(THD *, Item **) override; @@ -6492,6 +6495,8 @@ public: if (field && field->default_value) field->default_value->expr->update_used_tables(); } + bool vcol_assignment_allowed_value() const override + { return vcol_assignment_ok; } Field *get_tmp_table_field() override { return nullptr; } Item *get_tmp_table_item(THD *) override { return this; } Item_field *field_for_view_update() override { return nullptr; } diff --git a/sql/item_func.cc b/sql/item_func.cc index b3f60e052ae..60efc55d878 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -5863,7 +5863,7 @@ void Item_func_get_system_var::update_null_value() bool Item_func_get_system_var::fix_length_and_dec() { - char *cptr; + const char *cptr; maybe_null= TRUE; max_length= 0; @@ -5897,9 +5897,12 @@ bool Item_func_get_system_var::fix_length_and_dec() case SHOW_CHAR: case SHOW_CHAR_PTR: mysql_mutex_lock(&LOCK_global_system_variables); - cptr= var->show_type() == SHOW_CHAR ? - (char*) var->value_ptr(current_thd, var_type, &component) : - *(char**) var->value_ptr(current_thd, var_type, &component); + cptr= var->show_type() == SHOW_CHAR ? + reinterpret_cast<const char*>(var->value_ptr(current_thd, var_type, + &component)) : + *reinterpret_cast<const char* const*>(var->value_ptr(current_thd, + var_type, + &component)); if (cptr) max_length= (uint32) system_charset_info->numchars(cptr, cptr + strlen(cptr)); @@ -5911,7 +5914,10 @@ bool Item_func_get_system_var::fix_length_and_dec() case SHOW_LEX_STRING: { mysql_mutex_lock(&LOCK_global_system_variables); - LEX_STRING *ls= ((LEX_STRING*)var->value_ptr(current_thd, var_type, &component)); + const LEX_STRING *ls= + reinterpret_cast<const LEX_STRING*>(var->value_ptr(current_thd, + var_type, + &component)); max_length= (uint32) system_charset_info->numchars(ls->str, ls->str + ls->length); mysql_mutex_unlock(&LOCK_global_system_variables); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 27f00c308d4..fb359884f13 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -495,7 +495,7 @@ err: const char *histogram_types[] = {"SINGLE_PREC_HB", "DOUBLE_PREC_HB", 0}; -static TYPELIB hystorgam_types_typelib= +static TYPELIB histogram_types_typelib= { array_elements(histogram_types), "histogram_types", histogram_types, NULL}; @@ -511,7 +511,7 @@ String *Item_func_decode_histogram::val_str(String *str) tmp.length(0); if (!(res= args[0]->val_str(&tmp)) || (type= find_type(res->c_ptr_safe(), - &hystorgam_types_typelib, MYF(0))) <= 0) + &histogram_types_typelib, MYF(0))) <= 0) { null_value= 1; return 0; @@ -596,7 +596,7 @@ bool Item_func_concat::realloc_result(String *str, uint length) const as str was initially set by args[0]->val_str(str). So multiplication by 2 can overflow, if args[0] for some reasons did not limit the result to max_alloced_packet. But it's not harmful, - "str" will be realloced exactly to "length" bytes in case of overflow. + "str" will be reallocated exactly to "length" bytes in case of overflow. */ uint new_length= MY_MAX(str->alloced_length() * 2, length); return str->realloc(new_length); @@ -1510,7 +1510,7 @@ String *Item_func_insert::val_str(String *str) start--; /* - There is one exception not handled (intentionaly) by the character set + There is one exception not handled (intentionally) by the character set aggregation code. If one string is strong side and is binary, and another one is weak side and is a multi-byte character string, then we need to operate on the second string in terms on bytes when @@ -3200,6 +3200,14 @@ err: } +static String *default_pad_str(String *pad_str, CHARSET_INFO *collation) +{ + pad_str->set_charset(collation); + pad_str->length(0); + pad_str->append(" ", 1); + return pad_str; +} + bool Item_func_pad::fix_length_and_dec() { if (arg_count == 3) @@ -3215,9 +3223,7 @@ bool Item_func_pad::fix_length_and_dec() { if (agg_arg_charsets_for_string_result(collation, &args[0], 1, 1)) return TRUE; - pad_str.set_charset(collation.collation); - pad_str.length(0); - pad_str.append(" ", 1); + default_pad_str(&pad_str, collation.collation); } DBUG_ASSERT(collation.collation->mbmaxlen > 0); @@ -3240,9 +3246,9 @@ bool Item_func_pad::fix_length_and_dec() Sql_mode_dependency Item_func_rpad::value_depends_on_sql_mode() const { DBUG_ASSERT(fixed); - DBUG_ASSERT(arg_count == 3); + DBUG_ASSERT(arg_count >= 2); if (!args[1]->value_depends_on_sql_mode_const_item() || - !args[2]->value_depends_on_sql_mode_const_item()) + (arg_count == 3 && !args[2]->value_depends_on_sql_mode_const_item())) return Item_func::value_depends_on_sql_mode(); Longlong_hybrid len= args[1]->to_longlong_hybrid(); if (args[1]->null_value || len.neg()) @@ -3250,7 +3256,8 @@ Sql_mode_dependency Item_func_rpad::value_depends_on_sql_mode() const if (len.abs() > 0 && len.abs() < args[0]->max_char_length()) return Item_func::value_depends_on_sql_mode(); StringBuffer<64> padstrbuf; - String *padstr= args[2]->val_str(&padstrbuf); + String *padstr= arg_count == 3 ? args[2]->val_str(&padstrbuf) : + default_pad_str(&padstrbuf, collation.collation); if (!padstr || !padstr->length()) return Sql_mode_dependency(); // will return NULL if (padstr->lengthsp() != 0) @@ -3290,7 +3297,7 @@ String *Item_func_rpad::val_str(String *str) if ((ulonglong) count > INT_MAX32) count= INT_MAX32; /* - There is one exception not handled (intentionaly) by the character set + There is one exception not handled (intentionally) by the character set aggregation code. If one string is strong side and is binary, and another one is weak side and is a multi-byte character string, then we need to operate on the second string in terms on bytes when @@ -3383,7 +3390,7 @@ String *Item_func_lpad::val_str(String *str) count= INT_MAX32; /* - There is one exception not handled (intentionaly) by the character set + There is one exception not handled (intentionally) by the character set aggregation code. If one string is strong side and is binary, and another one is weak side and is a multi-byte character string, then we need to operate on the second string in terms on bytes when @@ -4190,7 +4197,7 @@ longlong Item_func_uncompressed_length::val_int() 5 bytes long. res->c_ptr() is not used because: - we do not need \0 terminated string to get first 4 bytes - - c_ptr() tests simbol after string end (uninitialiozed memory) which + - c_ptr() tests simbol after string end (uninitialized memory) which confuse valgrind */ return uint4korr(res->ptr()) & 0x3FFFFFFF; diff --git a/sql/key.cc b/sql/key.cc index 53f897de15f..79f1c55b61c 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -466,7 +466,7 @@ void key_unpack(String *to, TABLE *table, KEY *key) bool is_key_used(TABLE *table, uint idx, const MY_BITMAP *fields) { - table->mark_columns_used_by_index(idx, &table->tmp_set); + table->mark_index_columns(idx, &table->tmp_set); return bitmap_is_overlapping(&table->tmp_set, fields); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index cb87cb737c3..072cd42cc23 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -442,7 +442,7 @@ ulong delay_key_write_options; uint protocol_version; uint lower_case_table_names; ulong tc_heuristic_recover= 0; -Atomic_counter<uint32_t> thread_count; +Atomic_counter<uint32_t> THD_count::count, CONNECT::count; bool shutdown_wait_for_slaves; Atomic_counter<uint32_t> slave_open_temp_tables; ulong thread_created; @@ -1715,6 +1715,9 @@ static void close_connections(void) #endif end_thr_alarm(0); // Abort old alarms. + while (CONNECT::count) + my_sleep(100); + /* First signal all threads that it's time to die This will give the threads some time to gracefully abort their @@ -1741,9 +1744,9 @@ static void close_connections(void) much smaller than even 2 seconds, this is only a safety fallback against stuck threads so server shutdown is not held up forever. */ - DBUG_PRINT("info", ("thread_count: %u", uint32_t(thread_count))); + DBUG_PRINT("info", ("THD_count: %u", THD_count::value())); - for (int i= 0; (thread_count - binlog_dump_thread_count) && i < 1000; i++) + for (int i= 0; (THD_count::value() - binlog_dump_thread_count) && i < 1000; i++) my_sleep(20000); if (global_system_variables.log_warnings) @@ -1756,15 +1759,14 @@ static void close_connections(void) } #endif /* All threads has now been aborted */ - DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)", - uint32_t(thread_count))); + DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)", THD_count::value())); - while (thread_count - binlog_dump_thread_count) + while (THD_count::value() - binlog_dump_thread_count) my_sleep(1000); /* Kill phase 2 */ server_threads.iterate(kill_thread_phase_2); - for (uint64 i= 0; thread_count; i++) + for (uint64 i= 0; THD_count::value(); i++) { /* This time the warnings are emitted within the loop to provide a @@ -7694,7 +7696,7 @@ static int mysql_init_variables(void) mqh_used= 0; cleanup_done= 0; test_flags= select_errors= dropping_tables= ha_open_options=0; - thread_count= 0; + THD_count::count= CONNECT::count= 0; slave_open_temp_tables= 0; opt_endinfo= using_udf_functions= 0; opt_using_transactions= 0; diff --git a/sql/mysqld.h b/sql/mysqld.h index 8ca3a109333..142d2dbafb0 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -192,7 +192,8 @@ enum vers_system_time_t struct vers_asof_timestamp_t { ulong type; - MYSQL_TIME ltime; + my_time_t unix_time; + ulong second_part; }; enum vers_alter_history_enum @@ -756,7 +757,6 @@ extern mysql_rwlock_t LOCK_ssl_refresh; extern mysql_prlock_t LOCK_system_variables_hash; extern mysql_cond_t COND_start_thread; extern mysql_cond_t COND_manager; -extern Atomic_counter<uint32_t> thread_count; extern my_bool opt_use_ssl; extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher, diff --git a/sql/set_var.cc b/sql/set_var.cc index fe98d98fbd4..9744f0f6f39 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -231,12 +231,12 @@ bool sys_var::update(THD *thd, set_var *var) } } -uchar *sys_var::session_value_ptr(THD *thd, const LEX_CSTRING *base) +const uchar *sys_var::session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return session_var_ptr(thd); } -uchar *sys_var::global_value_ptr(THD *thd, const LEX_CSTRING *base) +const uchar *sys_var::global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return global_var_ptr(); } @@ -269,8 +269,8 @@ bool sys_var::check(THD *thd, set_var *var) return false; } -uchar *sys_var::value_ptr(THD *thd, enum_var_type type, - const LEX_CSTRING *base) +const uchar *sys_var::value_ptr(THD *thd, enum_var_type type, + const LEX_CSTRING *base) const { DBUG_ASSERT(base); if (type == OPT_GLOBAL || scope() == GLOBAL) @@ -1063,7 +1063,7 @@ int set_var_collation_client::update(THD *thd) INFORMATION_SCHEMA.SYSTEM_VARIABLES *****************************************************************************/ static void store_value_ptr(Field *field, sys_var *var, String *str, - uchar *value_ptr) + const uchar *value_ptr) { field->set_notnull(); str= var->val_str_nolock(str, field->table->in_use, value_ptr); @@ -1133,8 +1133,8 @@ int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond) fields[3]->store(origin->str, origin->length, scs); // DEFAULT_VALUE - uchar *def= var->is_readonly() && var->option.id < 0 - ? 0 : var->default_value_ptr(thd); + const uchar *def= var->is_readonly() && var->option.id < 0 + ? 0 : var->default_value_ptr(thd); if (def) store_value_ptr(fields[4], var, &strbuf, def); diff --git a/sql/set_var.h b/sql/set_var.h index 18c4dbc664e..2d538624825 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -112,7 +112,7 @@ public: virtual sys_var_pluginvar *cast_pluginvar() { return 0; } bool check(THD *thd, set_var *var); - uchar *value_ptr(THD *thd, enum_var_type type, const LEX_CSTRING *base); + const uchar *value_ptr(THD *thd, enum_var_type type, const LEX_CSTRING *base) const; /** Update the system variable with the default value from either @@ -127,7 +127,7 @@ public: String *val_str(String *str, THD *thd, enum_var_type type, const LEX_CSTRING *base); double val_real(bool *is_null, THD *thd, enum_var_type type, const LEX_CSTRING *base); - SHOW_TYPE show_type() { return show_val_type; } + SHOW_TYPE show_type() const { return show_val_type; } int scope() const { return flags & SCOPE_MASK; } virtual CHARSET_INFO *charset(THD *thd) const { @@ -211,7 +211,7 @@ public: */ virtual bool session_is_default(THD *thd) { return false; } - virtual uchar *default_value_ptr(THD *thd) + virtual const uchar *default_value_ptr(THD *thd) const { return (uchar*)&option.def_value; } virtual bool on_check_access_global(THD *thd) const; @@ -239,18 +239,18 @@ protected: It must be of show_val_type type (my_bool for SHOW_MY_BOOL, int for SHOW_INT, longlong for SHOW_LONGLONG, etc). */ - virtual uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base); - virtual uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base); + virtual const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const; + virtual const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; /** A pointer to a storage area of the variable, to the raw data. Typically it's the same as session_value_ptr(), but it's different, for example, for ENUM, that is printed as a string, but stored as a number. */ - uchar *session_var_ptr(THD *thd) + uchar *session_var_ptr(THD *thd) const { return ((uchar*)&(thd->variables)) + offset; } - uchar *global_var_ptr() + uchar *global_var_ptr() const { return ((uchar*)&global_system_variables) + offset; } void *max_var_ptr() @@ -292,6 +292,16 @@ public: /** + Structure for holding unix timestamp and high precision second part. + */ +typedef struct my_time_t_hires +{ + my_time_t unix_time; + ulong second_part; +} my_time_t_hires; + + +/** set_var_base descendant for assignments to the system variables. */ class set_var :public set_var_base @@ -309,6 +319,7 @@ public: plugin_ref *plugins; ///< for Sys_var_pluginlist Time_zone *time_zone; ///< for Sys_var_tz LEX_STRING string_value; ///< for Sys_var_charptr and others + my_time_t_hires timestamp; ///< for Sys_var_vers_asof const void *ptr; ///< for Sys_var_struct } save_result; LEX_CSTRING base; /**< for structured variables, like keycache_name.variable_name */ diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index 6aac9ac5962..0cfe55fe254 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -187,7 +187,7 @@ extern "C" sig_handler handle_fatal_signal(int sig) (uint) thread_scheduler->max_threads + (uint) extra_max_connections); - my_safe_printf_stderr("thread_count=%u\n", (uint) thread_count); + my_safe_printf_stderr("thread_count=%u\n", THD_count::value()); if (dflt_key_cache && thread_scheduler) { diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 71b5defeef8..65f053aa09b 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3252,7 +3252,6 @@ end: my_error(ER_INVALID_ROLE, MYF(0), rolename); break; case 1: - StringBuffer<1024> c_usr; LEX_CSTRING role_lex; /* First, check if current user can see mysql database. */ bool read_access= !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 1); @@ -3273,11 +3272,9 @@ end: NULL) == -1)) { /* Role is not granted but current user can see the role */ - c_usr.append(user, strlen(user)); - c_usr.append('@'); - c_usr.append(host, strlen(host)); - my_printf_error(ER_INVALID_ROLE, "User %`s has not been granted role %`s", - MYF(0), c_usr.c_ptr(), rolename); + my_printf_error(ER_INVALID_ROLE, "User %`s@%`s has not been granted role %`s", + MYF(0), thd->security_ctx->priv_user, + thd->security_ctx->priv_host, rolename); } else { @@ -9416,14 +9413,13 @@ static bool show_default_role(THD *thd, ACL_USER *acl_entry, String def_str(buff, buffsize, system_charset_info); def_str.length(0); def_str.append(STRING_WITH_LEN("SET DEFAULT ROLE ")); - def_str.append(&def_rolename); - def_str.append(" FOR '"); - def_str.append(&acl_entry->user); + append_identifier(thd, &def_str, def_rolename.str, def_rolename.length); + def_str.append(" FOR "); + append_identifier(thd, &def_str, acl_entry->user.str, acl_entry->user.length); DBUG_ASSERT(!(acl_entry->flags & IS_ROLE)); - def_str.append(STRING_WITH_LEN("'@'")); - def_str.append(acl_entry->host.hostname, acl_entry->hostname_length, - system_charset_info); - def_str.append('\''); + def_str.append('@'); + append_identifier(thd, &def_str, acl_entry->host.hostname, + acl_entry->hostname_length); protocol->prepare_for_resend(); protocol->store(def_str.ptr(),def_str.length(),def_str.charset()); if (protocol->write()) diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index ec0bc7b0111..c62e4c1669c 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -906,7 +906,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, enum enum_field_types type= (*field_ptr)->type(); if (type < MYSQL_TYPE_MEDIUM_BLOB || type > MYSQL_TYPE_BLOB) - bitmap_set_bit(tab->read_set, fields); + tab->field[fields]->register_field_in_read_map(); else push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_NO_EIS_FOR_FIELD, @@ -934,7 +934,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, enum enum_field_types type= tab->field[pos]->type(); if (type < MYSQL_TYPE_MEDIUM_BLOB || type > MYSQL_TYPE_BLOB) - bitmap_set_bit(tab->read_set, pos); + tab->field[pos]->register_field_in_read_map(); else push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_NO_EIS_FOR_FIELD, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index bb076ba9f3f..a9d7de9a9b0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6211,7 +6211,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, TABLE *table= field_to_set->table; DBUG_ASSERT(table); if (thd->column_usage == MARK_COLUMNS_READ) - bitmap_set_bit(table->read_set, field_to_set->field_index); + field_to_set->register_field_in_read_map(); else bitmap_set_bit(table->write_set, field_to_set->field_index); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8b61750ffca..31d9979b22c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1306,6 +1306,7 @@ void THD::init() wsrep_affected_rows = 0; m_wsrep_next_trx_id = WSREP_UNDEFINED_TRX_ID; wsrep_aborter = 0; + wsrep_desynced_backup_stage= false; #endif /* WITH_WSREP */ if (variables.sql_log_bin) @@ -4886,7 +4887,7 @@ MYSQL_THD create_background_thd() in THD constructor. We do not want these THDs to be counted, or waited for on shutdown. */ - thread_count--; + THD_count::count--; thd->mysys_var= (st_my_thread_var *) thd_mysysvar; thd->set_command(COM_DAEMON); @@ -4942,7 +4943,7 @@ void destroy_background_thd(MYSQL_THD thd) As we decremented it in create_background_thd(), in order for it not to go negative, we have to increment it before destructor. */ - thread_count++; + THD_count::count++; delete thd; thd_detach_thd(save_mysys_var); @@ -7071,8 +7072,8 @@ void THD::binlog_prepare_row_images(TABLE *table) { case BINLOG_ROW_IMAGE_MINIMAL: /* MINIMAL: Mark only PK */ - table->mark_columns_used_by_index(table->s->primary_key, - &table->tmp_set); + table->mark_index_columns(table->s->primary_key, + &table->tmp_set); break; case BINLOG_ROW_IMAGE_NOBLOB: /** diff --git a/sql/sql_class.h b/sql/sql_class.h index 62ce5c8a2d2..ec031bf06e6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1080,6 +1080,23 @@ public: static THD_list_iterator *iterator(); }; +/** + A counter of THDs + + It must be specified as a first base class of THD, so that increment is + done before any other THD constructors and decrement - after any other THD + destructors. + + Destructor unblocks close_conneciton() if there are no more THD's left. +*/ +struct THD_count +{ + static Atomic_counter<uint32_t> count; + static uint value() { return static_cast<uint>(count); } + THD_count() { count++; } + ~THD_count() { count--; } +}; + #ifdef MYSQL_SERVER void free_tmp_table(THD *thd, TABLE *entry); @@ -2269,22 +2286,6 @@ public: }; /** - A wrapper around thread_count. - - It must be specified as a first base class of THD, so that increment is - done before any other THD constructors and decrement - after any other THD - destructors. - - Destructor unblocks close_conneciton() if there are no more THD's left. -*/ -struct THD_count -{ - THD_count() { thread_count++; } - ~THD_count() { thread_count--; } -}; - - -/** @class THD For each client connection we create a separate thread with THD serving as a thread/connection descriptor @@ -3152,6 +3153,9 @@ public: uint server_status,open_options; enum enum_thread_type system_thread; enum backup_stages current_backup_stage; +#ifdef WITH_WSREP + bool wsrep_desynced_backup_stage; +#endif /* WITH_WSREP */ /* Current or next transaction isolation level. When a connection is established, the value is taken from diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index e0119e50eaa..999830ff67e 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1359,6 +1359,14 @@ void do_handle_one_connection(CONNECT *connect, bool put_in_cache) return; } + DBUG_EXECUTE_IF("CONNECT_wait", + { + extern MYSQL_SOCKET unix_sock; + DBUG_ASSERT(unix_sock.fd >= 0); + while (unix_sock.fd >= 0) + my_sleep(1000); + }); + /* If a thread was created to handle this connection: increment slow_launch_threads counter if it took more than @@ -1372,10 +1380,10 @@ void do_handle_one_connection(CONNECT *connect, bool put_in_cache) if (launch_time >= slow_launch_time*1000000L) statistic_increment(slow_launch_threads, &LOCK_status); } - delete connect; - /* Make THD visible in show processlist */ - server_threads.insert(thd); + server_threads.insert(thd); // Make THD visible in show processlist + + delete connect; // must be after server_threads.insert, see close_connections() thd->thr_create_utime= thr_create_utime; /* We need to set this because of time_out_user_resource_limits */ diff --git a/sql/sql_connect.h b/sql/sql_connect.h index 152bd71afd7..1a84cb56e5c 100644 --- a/sql/sql_connect.h +++ b/sql/sql_connect.h @@ -44,11 +44,20 @@ public: /* Own variables */ ulonglong prior_thr_create_utime; + static Atomic_counter<uint32_t> count; + CONNECT(MYSQL_SOCKET sock_arg, enum enum_vio_type vio_type_arg, scheduler_functions *scheduler_arg): sock(sock_arg), vio_type(vio_type_arg), scheduler(scheduler_arg), thread_id(0), - prior_thr_create_utime(0) {} - ~CONNECT() { DBUG_ASSERT(vio_type == VIO_CLOSED); } + prior_thr_create_utime(0) + { + count++; + } + ~CONNECT() + { + count--; + DBUG_ASSERT(vio_type == VIO_CLOSED); + } void close_and_delete(); void close_with_error(uint sql_errno, const char *message, uint close_error); diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 2403a6d9f17..c53ae300d0d 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -938,7 +938,8 @@ bool With_clause::prepare_unreferenced_elements(THD *thd) with_elem; with_elem= with_elem->next) { - if (!with_elem->is_referenced() && with_elem->prepare_unreferenced(thd)) + if ((with_elem->is_hanging_recursive() || !with_elem->is_referenced()) && + with_elem->prepare_unreferenced(thd)) return true; } @@ -1126,14 +1127,6 @@ st_select_lex_unit *With_element::clone_parsed_spec(LEX *old_lex, lex->unit.include_down(with_table->select_lex); lex->unit.set_slave(with_select); lex->unit.cloned_from= spec; - last_clone_select= lex->all_selects_list; - while (last_clone_select->next_select_in_list()) - last_clone_select= last_clone_select->next_select_in_list(); - old_lex->all_selects_list= - (st_select_lex*) (lex->all_selects_list-> - insert_chain_before( - (st_select_lex_node **) &(old_lex->all_selects_list), - last_clone_select)); /* Now all references to the CTE defined outside of the cloned specification @@ -1149,6 +1142,15 @@ st_select_lex_unit *With_element::clone_parsed_spec(LEX *old_lex, goto err; } + last_clone_select= lex->all_selects_list; + while (last_clone_select->next_select_in_list()) + last_clone_select= last_clone_select->next_select_in_list(); + old_lex->all_selects_list= + (st_select_lex*) (lex->all_selects_list-> + insert_chain_before( + (st_select_lex_node **) &(old_lex->all_selects_list), + last_clone_select)); + lex->sphead= NULL; // in order not to delete lex->sphead lex_end(lex); err: @@ -1323,6 +1325,7 @@ bool With_element::is_anchor(st_select_lex *sel) With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) { With_element *found= NULL; + With_clause *containing_with_clause= NULL; st_select_lex_unit *master_unit; st_select_lex *outer_sl; for (st_select_lex *sl= this; sl; sl= outer_sl) @@ -1335,6 +1338,7 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) */ With_clause *attached_with_clause= sl->get_with_clause(); if (attached_with_clause && + attached_with_clause != containing_with_clause && (found= attached_with_clause->find_table_def(table, NULL))) break; master_unit= sl->master_unit(); @@ -1342,7 +1346,7 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) With_element *with_elem= sl->get_with_element(); if (with_elem) { - With_clause *containing_with_clause= with_elem->get_owner(); + containing_with_clause= with_elem->get_owner(); With_element *barrier= containing_with_clause->with_recursive ? NULL : with_elem; if ((found= containing_with_clause->find_table_def(table, barrier))) diff --git a/sql/sql_cte.h b/sql/sql_cte.h index 44628df3ff8..4cec1240d1f 100644 --- a/sql/sql_cte.h +++ b/sql/sql_cte.h @@ -262,6 +262,8 @@ public: bool is_referenced() { return referenced; } + bool is_hanging_recursive() { return is_recursive && !rec_outer_references; } + void inc_references() { references++; } bool process_columns_of_derived_unit(THD *thd, st_select_lex_unit *unit); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 9d3444a5ac6..c1cb45d5d69 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4680,8 +4680,17 @@ select_create::prepare(List<Item> &_values, SELECT_LEX_UNIT *u) } if (!(table= create_table_from_items(thd, &values, &extra_lock, hook_ptr))) + { + if (create_info->or_replace()) + { + /* Original table was deleted. We have to log it */ + log_drop_table(thd, &create_table->db, &create_table->table_name, + thd->lex->tmp_table()); + } + /* abort() deletes table */ DBUG_RETURN(-1); + } if (create_info->tmp_table()) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 5784c10a29c..5a39b380855 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -11613,3 +11613,23 @@ bool LEX::map_data_type(const Lex_ident_sys_st &schema_name, type->set_handler(mapped); return false; } + + +bool SELECT_LEX_UNIT::explainable() const +{ + /* + EXPLAIN/ANALYZE unit, when: + (1) if it's a subquery - it's not part of eliminated WHERE/ON clause. + (2) if it's a CTE - it's not hanging (needed for execution) + (3) if it's a derived - it's not merged + if it's not 1/2/3 - it's some weird internal thing, ignore it + */ + return item ? + !item->eliminated : // (1) + with_element ? + derived && derived->derived_result && + !with_element->is_hanging_recursive(): // (2) + derived ? + derived->is_materialized_derived() : // (3) + false; +} diff --git a/sql/sql_lex.h b/sql/sql_lex.h index d0ccf19ddab..d9e29b06a91 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1022,20 +1022,7 @@ public: int save_union_explain_part2(Explain_query *output); unit_common_op common_op(); - bool explainable() const - { - /* - EXPLAIN/ANALYZE unit, when: - (1) if it's a subquery - it's not part of eliminated WHERE/ON clause. - (2) if it's a CTE - it's not hanging (needed for execution) - (3) if it's a derived - it's not merged - if it's not 1/2/3 - it's some weird internal thing, ignore it - */ - return item ? !item->eliminated : // (1) - with_element ? derived && derived->derived_result : // (2) - derived ? derived->is_materialized_derived() : // (3) - false; - } + bool explainable() const; void reset_distinct(); void fix_distinct(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 19f80606e34..64aca9fb87d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2264,11 +2264,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, size_t length= #endif my_snprintf(buff, buff_len - 1, - "Uptime: %lu Threads: %d Questions: %lu " + "Uptime: %lu Threads: %u Questions: %lu " "Slow queries: %lu Opens: %lu " "Open tables: %u Queries per second avg: %u.%03u", - uptime, - (int) thread_count, (ulong) thd->query_id, + uptime, THD_count::value(), (ulong) thd->query_id, current_global_status_var->long_query_count, current_global_status_var->opened_tables, tc_records(), @@ -5726,6 +5725,11 @@ mysql_execute_command(THD *thd) /* Begin transaction with the same isolation level. */ if (tx_chain) { +#ifdef WITH_WSREP + /* If there are pending changes after rollback we should clear them */ + if (wsrep_on(thd) && wsrep_has_changes(thd)) + wsrep_after_statement(thd); +#endif if (trans_begin(thd)) goto error; } diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 74f2e1b33f1..114b1a19af7 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -3639,6 +3639,17 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, if (part_func_value >= part_end_val && (loc_part_id < max_partition || !part_info->defined_max_value)) loc_part_id++; + if (part_info->part_type == VERSIONING_PARTITION && + part_func_value < INT_MAX32 && + loc_part_id > part_info->vers_info->hist_part->id) + { + /* + Historical query with AS OF point after the last history partition must + include last history partition because it can be overflown (contain + history rows out of right endpoint). + */ + loc_part_id= part_info->vers_info->hist_part->id; + } } else { diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 02ae08c910c..330d8b668ed 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -313,14 +313,14 @@ public: sys_var_pluginvar(sys_var_chain *chain, const char *name_arg, st_plugin_int *p, st_mysql_sys_var *plugin_var_arg); sys_var_pluginvar *cast_pluginvar() { return this; } - uchar* real_value_ptr(THD *thd, enum_var_type type); - TYPELIB* plugin_var_typelib(void); - uchar* do_value_ptr(THD *thd, enum_var_type type, const LEX_CSTRING *base); - uchar* session_value_ptr(THD *thd, const LEX_CSTRING *base) + uchar* real_value_ptr(THD *thd, enum_var_type type) const; + TYPELIB* plugin_var_typelib(void) const; + const uchar* do_value_ptr(THD *thd, enum_var_type type, const LEX_CSTRING *base) const; + const uchar* session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return do_value_ptr(thd, OPT_SESSION, base); } - uchar* global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar* global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return do_value_ptr(thd, OPT_GLOBAL, base); } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { return do_value_ptr(thd, OPT_DEFAULT, 0); } bool do_check(THD *thd, set_var *var); virtual void session_save_default(THD *thd, set_var *var) {} @@ -3423,7 +3423,7 @@ sys_var_pluginvar::sys_var_pluginvar(sys_var_chain *chain, const char *name_arg, plugin_opt_set_limits(&option, pv); } -uchar* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type) +uchar* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type) const { if (type == OPT_DEFAULT) { @@ -3497,7 +3497,7 @@ bool sys_var_pluginvar::session_is_default(THD *thd) } -TYPELIB* sys_var_pluginvar::plugin_var_typelib(void) +TYPELIB* sys_var_pluginvar::plugin_var_typelib(void) const { switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_THDLOCAL)) { case PLUGIN_VAR_ENUM: @@ -3515,12 +3515,10 @@ TYPELIB* sys_var_pluginvar::plugin_var_typelib(void) } -uchar* sys_var_pluginvar::do_value_ptr(THD *thd, enum_var_type type, - const LEX_CSTRING *base) +const uchar* sys_var_pluginvar::do_value_ptr(THD *thd, enum_var_type type, + const LEX_CSTRING *base) const { - uchar* result; - - result= real_value_ptr(thd, type); + const uchar* result= real_value_ptr(thd, type); if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM) result= (uchar*) get_type(plugin_var_typelib(), *(ulong*)result); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 70d9dd783c8..b1a5a3e7199 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1570,7 +1570,12 @@ static int mysql_test_select(Prepared_statement *stmt, if (!lex->describe && !thd->lex->analyze_stmt && !stmt->is_sql_prepare()) { /* Make copy of item list, as change_columns may change it */ - List<Item> fields(lex->first_select_lex()->item_list); + SELECT_LEX_UNIT* master_unit= unit->first_select()->master_unit(); + bool is_union_op= + master_unit->is_unit_op() || master_unit->fake_select_lex; + + List<Item> fields(is_union_op ? unit->item_list : + lex->first_select_lex()->item_list); /* Change columns if a procedure like analyse() */ if (unit->last_procedure && unit->last_procedure->change_columns(thd, fields)) @@ -1692,7 +1697,7 @@ static bool mysql_test_call_fields(Prepared_statement *stmt, while ((item= it++)) { - if (item->fix_fields_if_needed_for_scalar(thd, it.ref())) + if (item->fix_fields_if_needed(thd, it.ref())) goto err; } DBUG_RETURN(FALSE); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 80bc24cd3cd..9c76ecc5dbf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -768,7 +768,8 @@ bool vers_select_conds_t::init_from_sysvar(THD *thd) if (type != SYSTEM_TIME_UNSPECIFIED && type != SYSTEM_TIME_ALL) { DBUG_ASSERT(type == SYSTEM_TIME_AS_OF); - Datetime dt(&in.ltime); + Datetime dt(in.unix_time, in.second_part, thd->variables.time_zone); + start.item= new (thd->mem_root) Item_datetime_literal(thd, &dt, TIME_SECOND_PART_DIGITS); if (!start.item) @@ -2072,7 +2073,7 @@ JOIN::optimize_inner() sel->attach_to_conds.empty(); } } - + if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY)) { TABLE_LIST *tbl; @@ -2341,7 +2342,7 @@ int JOIN::optimize_stage2() /* Generate an execution plan from the found optimal join order. */ if (get_best_combination()) DBUG_RETURN(1); - + if (make_range_rowid_filters()) DBUG_RETURN(1); @@ -3254,8 +3255,17 @@ bool JOIN::make_aggr_tables_info() if (ht && ht->create_group_by) { - /* Check if the storage engine can intercept the query */ - Query query= {&all_fields, select_distinct, tables_list, conds, + /* + Check if the storage engine can intercept the query + + JOIN::optimize_stage2() might convert DISTINCT into GROUP BY and then + optimize away GROUP BY (group_list). In such a case, we need to notify + a storage engine supporting a group by handler of the existence of the + original DISTINCT. Thus, we set select_distinct || group_optimized_away + to Query::distinct. + */ + Query query= {&all_fields, select_distinct || group_optimized_away, + tables_list, conds, group_list, order ? order : group_list, having, &select_lex->master_unit()->lim}; group_by_handler *gbh= ht->create_group_by(thd, &query); @@ -7450,7 +7460,7 @@ best_access_path(JOIN *join, Json_writer_object trace_wrapper(thd, "best_access_path"); Json_writer_array trace_paths(thd, "considered_access_paths"); - + bitmap_clear_all(eq_join_set); loose_scan_opt.init(join, s, remaining_tables); @@ -9244,7 +9254,9 @@ static double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, table_map rem_tables) { - uint16 ref_keyuse_steps[MAX_REF_PARTS - 1]; + uint16 ref_keyuse_steps_buf[MAX_REF_PARTS]; + uint ref_keyuse_size= MAX_REF_PARTS; + uint16 *ref_keyuse_steps= ref_keyuse_steps_buf; Field *field; TABLE *table= s->table; MY_BITMAP *read_set= table->read_set; @@ -9392,6 +9404,30 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, } if (keyparts > 1) { + /* + Prepare to set ref_keyuse_steps[keyparts-2]: resize the array + if it is not large enough + */ + if (keyparts - 2 >= ref_keyuse_size) + { + uint new_size= MY_MAX(ref_keyuse_size*2, keyparts); + void *new_buf; + if (!(new_buf= my_malloc(PSI_INSTRUMENT_ME, + sizeof(*ref_keyuse_steps)*new_size, + MYF(0)))) + { + sel= 1.0; // As if no selectivity was computed + goto exit; + } + memcpy(new_buf, ref_keyuse_steps, + sizeof(*ref_keyuse_steps)*ref_keyuse_size); + if (ref_keyuse_steps != ref_keyuse_steps_buf) + my_free(ref_keyuse_steps); + + ref_keyuse_steps= (uint16*)new_buf; + ref_keyuse_size= new_size; + } + ref_keyuse_steps[keyparts-2]= (uint16)(keyuse - prev_ref_keyuse); prev_ref_keyuse= keyuse; } @@ -9446,7 +9482,9 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, sel*= table_multi_eq_cond_selectivity(join, idx, s, rem_tables, keyparts, ref_keyuse_steps); - +exit: + if (ref_keyuse_steps != ref_keyuse_steps_buf) + my_free(ref_keyuse_steps); return sel; } @@ -23932,6 +23970,12 @@ check_reverse_order: if (select->quick == save_quick) save_quick= 0; // make_reverse() consumed it select->set_quick(tmp); + /* Cancel "Range checked for each record" */ + if (tab->use_quick == 2) + { + tab->use_quick= 1; + tab->read_first_record= join_init_read_record; + } } else if (tab->type != JT_NEXT && tab->type != JT_REF_OR_NULL && tab->ref.key >= 0 && tab->ref.key_parts <= used_key_parts) @@ -23944,6 +23988,12 @@ check_reverse_order: */ tab->read_first_record= join_read_last_key; tab->read_record.read_record_func= join_read_prev_same; + /* Cancel "Range checked for each record" */ + if (tab->use_quick == 2) + { + tab->use_quick= 1; + tab->read_first_record= join_init_read_record; + } /* Cancel Pushed Index Condition, as it doesn't work for reverse scans. */ @@ -28318,7 +28368,7 @@ void JOIN::cache_const_exprs() static bool get_range_limit_read_cost(const JOIN_TAB *tab, const TABLE *table, ha_rows table_records, - uint keynr, + uint keynr, ha_rows rows_limit, double *read_time) { @@ -28401,7 +28451,7 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab, to discount it from the rows_limit: */ double rows_limit_for_quick= rows_limit * (best_rows / table_records); - + if (best_rows > rows_limit_for_quick) { /* @@ -28684,7 +28734,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, refkey_rows_estimate is E(#rows) produced by the table access strategy that was picked without regard to ORDER BY ... LIMIT. - It will be used as the source of selectivity data. + It will be used as the source of selectivity data. Use table->cond_selectivity as a better estimate which includes condition selectivity too. */ @@ -28693,7 +28743,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, // cond_selectivity=1 while refkey_rows_estimate has a better // estimate. refkey_rows_estimate= MY_MIN(refkey_rows_estimate, - ha_rows(table_records * + ha_rows(table_records * table->cond_selectivity)); } @@ -28801,7 +28851,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, { possible_key.add("usable", false); possible_key.add("cause", "cost"); - } + } } else { @@ -29646,7 +29696,7 @@ void JOIN::init_join_cache_and_keyread() tuple. */ if (!(table->file->index_flags(table->file->keyread, 0, 1) & HA_CLUSTERED_INDEX)) - table->mark_columns_used_by_index(table->file->keyread, table->read_set); + table->mark_index_columns(table->file->keyread, table->read_set); } if (tab->cache && tab->cache->init(select_options & SELECT_DESCRIBE)) revise_cache_usage(tab); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index f9546b79e6f..6ff9ef8a810 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3531,6 +3531,30 @@ ulonglong get_status_vars_version(void) } /** + A union holding a pointer to a type that can be referred by a status variable. + */ +union Any_pointer { + const void *as_void; + const uchar *as_uchar; + const char *as_char; + const char ** as_charptr; + const double *as_double; + const int * as_int; + const uint * as_uint; + const long *as_long; + const longlong *as_longlong; + const bool *as_bool; + const my_bool *as_my_bool; + const sys_var *as_sys_var; + const system_status_var *as_system_status_var; + const ha_rows *as_ha_rows; + const LEX_STRING *as_lex_cstring; + const SHOW_COMP_OPTION *as_show_comp_options; + intptr as_intptr; + Atomic_counter<uint32_t>* as_atomic_counter; +}; + +/** @brief Returns the value of a system or a status variable. @param thd [in] The handle of the current THD. @@ -3553,16 +3577,18 @@ const char* get_one_variable(THD *thd, const CHARSET_INFO **charset, char *buff, size_t *length) { - void *value= variable->value; + Any_pointer value, status_var_value; + value.as_void= variable->value; + status_var_value.as_system_status_var= status_var; const char *pos= buff; const char *end= buff; if (show_type == SHOW_SYS) { - sys_var *var= (sys_var *) value; + const sys_var *var= value.as_sys_var; show_type= var->show_type(); - value= var->value_ptr(thd, value_type, &null_clex_str); + value.as_uchar= var->value_ptr(thd, value_type, &null_clex_str); *charset= var->charset(thd); } @@ -3572,72 +3598,71 @@ const char* get_one_variable(THD *thd, */ switch (show_type) { case SHOW_DOUBLE_STATUS: - value= ((char *) status_var + (intptr) value); + value.as_char= status_var_value.as_char + value.as_intptr; /* fall through */ case SHOW_DOUBLE: /* 6 is the default precision for '%f' in sprintf() */ - end= buff + my_fcvt(*(double *) value, 6, buff, NULL); + end= buff + my_fcvt(*value.as_double, 6, buff, NULL); break; case SHOW_LONG_STATUS: - value= ((char *) status_var + (intptr) value); + value.as_char= status_var_value.as_char + value.as_intptr; /* fall through */ case SHOW_ULONG: case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status() #ifndef _WIN64 case SHOW_SIZE_T: #endif - end= int10_to_str(*(long*) value, buff, 10); + end= int10_to_str(*value.as_long, buff, 10); break; case SHOW_LONGLONG_STATUS: - value= ((char *) status_var + (intptr) value); + value.as_char= status_var_value.as_char + value.as_intptr; /* fall through */ case SHOW_ULONGLONG: #ifdef _WIN64 case SHOW_SIZE_T: #endif - end= longlong10_to_str(*(longlong*) value, buff, 10); + end= longlong10_to_str(*value.as_longlong, buff, 10); break; case SHOW_HA_ROWS: - end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10); + end= longlong10_to_str((longlong) *value.as_ha_rows, buff, 10); break; case SHOW_BOOL: - end= strmov(buff, *(bool*) value ? "ON" : "OFF"); + end= strmov(buff, *value.as_bool ? "ON" : "OFF"); break; case SHOW_MY_BOOL: - end= strmov(buff, *(my_bool*) value ? "ON" : "OFF"); + end= strmov(buff, *value.as_my_bool ? "ON" : "OFF"); break; case SHOW_UINT32_STATUS: - value= ((char *) status_var + (intptr) value); + value.as_char= status_var_value.as_char + value.as_intptr; /* fall through */ case SHOW_UINT: - end= int10_to_str((long) *(uint*) value, buff, 10); + end= int10_to_str((long) *value.as_uint, buff, 10); break; case SHOW_SINT: - end= int10_to_str((long) *(int*) value, buff, -10); + end= int10_to_str((long) *value.as_int, buff, -10); break; case SHOW_SLONG: - end= int10_to_str(*(long*) value, buff, -10); + end= int10_to_str(*value.as_long, buff, -10); break; case SHOW_SLONGLONG: - end= longlong10_to_str(*(longlong*) value, buff, -10); + end= longlong10_to_str(*value.as_longlong, buff, -10); break; case SHOW_HAVE: { - SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value; - pos= show_comp_option_name[(int) tmp]; + pos= show_comp_option_name[(int) *value.as_show_comp_options]; end= strend(pos); break; } case SHOW_CHAR: { - if (!(pos= (char*)value)) + if (!(pos= value.as_char)) pos= ""; end= strend(pos); break; } case SHOW_CHAR_PTR: { - if (!(pos= *(char**) value)) + if (!(pos= *value.as_charptr)) pos= ""; end= strend(pos); @@ -3645,17 +3670,14 @@ const char* get_one_variable(THD *thd, } case SHOW_LEX_STRING: { - LEX_STRING *ls=(LEX_STRING*)value; - if (!(pos= ls->str)) + if (!(pos= value.as_lex_cstring->str)) end= pos= ""; else - end= pos + ls->length; + end= pos + value.as_lex_cstring->length; break; } case SHOW_ATOMIC_COUNTER_UINT32_T: - end= int10_to_str( - static_cast<long>(*static_cast<Atomic_counter<uint32_t>*>(value)), - buff, 10); + end= int10_to_str(static_cast<long>(*value.as_atomic_counter), buff, 10); break; case SHOW_UNDEF: break; // Return empty string @@ -6665,6 +6687,16 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, LEX_CSTRING unknown= {STRING_WITH_LEN("?unknown field?") }; for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++) { + if (key_part->field->invisible >= INVISIBLE_SYSTEM && + DBUG_EVALUATE_IF("test_completely_invisible", 0, 1)) + { + /* + NOTE: we will get SEQ_IN_INDEX gap inside the result if this key_part + is not last (currently not possible). Though nothing is wrong with + that probably. + */ + continue; + } restore_record(table, s->default_values); table->field[0]->store(STRING_WITH_LEN("def"), cs); table->field[1]->store(db_name->str, db_name->length, cs); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 6ee51b763e0..118dcaf9d59 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -1089,6 +1089,13 @@ Datetime::Datetime(THD *thd, int *warn, const MYSQL_TIME *from, DBUG_ASSERT(is_valid_value_slow()); } +Datetime::Datetime(my_time_t unix_time, ulong second_part_arg, + const Time_zone* time_zone) +{ + time_zone->gmt_sec_to_TIME(this, unix_time); + second_part= second_part_arg; +} + bool Temporal::datetime_add_nanoseconds_or_invalidate(THD *thd, int *warn, ulong nsec) { @@ -8738,7 +8745,7 @@ bool Type_handler_string_result::Item_eq_value(THD *thd, /***************************************************************************/ -bool Type_handler_string_result::union_element_finalize(const Item * item) const +bool Type_handler_string_result::union_element_finalize(Item_type_holder* item) const { if (item->collation.derivation == DERIVATION_NONE) { @@ -9034,6 +9041,12 @@ Type_handler_timestamp_common::Item_val_native_with_conversion(THD *thd, TIME_to_native(thd, <ime, to, item->datetime_precision(thd)); } +bool Type_handler_null::union_element_finalize(Item_type_holder *item) const +{ + item->set_handler(&type_handler_string); + return false; +} + bool Type_handler_timestamp_common::Item_val_native_with_conversion_result(THD *thd, diff --git a/sql/sql_type.h b/sql/sql_type.h index f801c243171..aa1fe1a9f7e 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -74,6 +74,7 @@ class Item_func_minus; class Item_func_mul; class Item_func_div; class Item_func_mod; +class Item_type_holder; class cmp_item; class in_vector; class Type_handler_data; @@ -2454,6 +2455,8 @@ public: *(static_cast<MYSQL_TIME*>(this))= *from; DBUG_ASSERT(is_valid_datetime_slow()); } + Datetime(my_time_t unix_time, ulong second_part, + const Time_zone* time_zone); bool is_valid_datetime() const { @@ -3883,7 +3886,7 @@ public: Performs the final data type validation for a UNION element, after the regular "aggregation for result" was done. */ - virtual bool union_element_finalize(const Item * item) const + virtual bool union_element_finalize(Item_type_holder* item) const { return false; } @@ -5383,7 +5386,7 @@ public: const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const override; bool is_packable() const override { return true; } - bool union_element_finalize(const Item * item) const override; + bool union_element_finalize(Item_type_holder* item) const override; uint calc_key_length(const Column_definition &def) const override; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, @@ -6824,6 +6827,7 @@ public: Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; + bool union_element_finalize(Item_type_holder* item) const override; bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, diff --git a/sql/sql_union.cc b/sql/sql_union.cc index b88d78c0db3..b746b510140 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -30,6 +30,7 @@ #include "filesort.h" // filesort_free_buffers #include "sql_view.h" #include "sql_cte.h" +#include "item_windowfunc.h" bool mysql_union(THD *thd, LEX *lex, select_result *result, SELECT_LEX_UNIT *unit, ulong setup_tables_done_option) @@ -1687,7 +1688,8 @@ cont: Test if the aggregated data type is OK for a UNION element. E.g. in case of string data, DERIVATION_NONE is not allowed. */ - if (type->type_handler()->union_element_finalize(type)) + if (type->type() == Item::TYPE_HOLDER && type->type_handler()-> + union_element_finalize(static_cast<Item_type_holder*>(type))) goto err; } @@ -2561,7 +2563,8 @@ bool st_select_lex_unit::cleanup() { DBUG_RETURN(FALSE); } - if (with_element && with_element->is_recursive && union_result) + if (with_element && with_element->is_recursive && union_result && + with_element->rec_outer_references) { select_union_recursive *result= with_element->rec_result; if (++result->cleanup_count == with_element->rec_outer_references) @@ -2730,6 +2733,29 @@ static void cleanup_order(ORDER *order) } +static void cleanup_window_funcs(List<Item_window_func> &win_funcs) +{ + List_iterator_fast<Item_window_func> it(win_funcs); + Item_window_func *win_func; + while ((win_func= it++)) + { + Window_spec *win_spec= win_func->window_spec; + if (!win_spec) + continue; + if (win_spec->save_partition_list) + { + win_spec->partition_list= win_spec->save_partition_list; + win_spec->save_partition_list= NULL; + } + if (win_spec->save_order_list) + { + win_spec->order_list= win_spec->save_order_list; + win_spec->save_order_list= NULL; + } + } +} + + bool st_select_lex::cleanup() { bool error= FALSE; @@ -2741,6 +2767,8 @@ bool st_select_lex::cleanup() cleanup_order(group_list.first); cleanup_ftfuncs(this); + cleanup_window_funcs(window_funcs); + if (join) { List_iterator<TABLE_LIST> ti(leaf_tables); @@ -2767,7 +2795,8 @@ bool st_select_lex::cleanup() for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ; lex_unit= lex_unit->next_unit()) { - if (lex_unit->with_element && lex_unit->with_element->is_recursive) + if (lex_unit->with_element && lex_unit->with_element->is_recursive && + lex_unit->with_element->rec_outer_references) continue; error= (bool) ((uint) error | (uint) lex_unit->cleanup()); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c14585f44c5..977e459f9df 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -272,7 +272,7 @@ static void prepare_record_for_error_message(int error, TABLE *table) /* Create unique_map with all fields used by that index. */ my_bitmap_init(&unique_map, unique_map_buf, table->s->fields, FALSE); - table->mark_columns_used_by_index(keynr, &unique_map); + table->mark_index_columns(keynr, &unique_map); /* Subtract read_set and write_set. */ bitmap_subtract(&unique_map, table->read_set); diff --git a/sql/sql_window.cc b/sql/sql_window.cc index af6a73006a8..2624a5e4510 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -592,9 +592,15 @@ int compare_window_funcs_by_window_specs(Item_window_func *win_func1, Let's use only one of the lists. */ if (!win_spec1->name() && win_spec2->name()) + { + win_spec1->save_partition_list= win_spec1->partition_list; win_spec1->partition_list= win_spec2->partition_list; + } else + { + win_spec2->save_partition_list= win_spec2->partition_list; win_spec2->partition_list= win_spec1->partition_list; + } cmp= compare_order_lists(win_spec1->order_list, win_spec2->order_list); @@ -607,9 +613,15 @@ int compare_window_funcs_by_window_specs(Item_window_func *win_func1, Let's use only one of the lists. */ if (!win_spec1->name() && win_spec2->name()) + { + win_spec1->save_order_list= win_spec2->order_list; win_spec1->order_list= win_spec2->order_list; + } else + { + win_spec1->save_order_list= win_spec2->order_list; win_spec2->order_list= win_spec1->order_list; + } cmp= compare_window_frames(win_spec1->window_frame, win_spec2->window_frame); diff --git a/sql/sql_window.h b/sql/sql_window.h index 373b367b211..5e76a33dcd0 100644 --- a/sql/sql_window.h +++ b/sql/sql_window.h @@ -111,8 +111,10 @@ class Window_spec : public Sql_alloc LEX_CSTRING *window_ref; SQL_I_List<ORDER> *partition_list; + SQL_I_List<ORDER> *save_partition_list; SQL_I_List<ORDER> *order_list; + SQL_I_List<ORDER> *save_order_list; Window_frame *window_frame; @@ -123,7 +125,8 @@ class Window_spec : public Sql_alloc SQL_I_List<ORDER> *ord_list, Window_frame *win_frame) : window_names_are_checked(false), window_ref(win_ref), - partition_list(part_list), order_list(ord_list), + partition_list(part_list), save_partition_list(NULL), + order_list(ord_list), save_order_list(NULL), window_frame(win_frame), referenced_win_spec(NULL) {} virtual const char *name() { return NULL; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c9bc2bdc6a6..1f756450f3c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1448,7 +1448,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); table_wild simple_expr column_default_non_parenthesized_expr udf_expr primary_expr string_factor_expr mysql_concatenation_expr select_sublist_qualified_asterisk - expr_or_default set_expr_or_default + expr_or_ignore expr_or_ignore_or_default set_expr_or_default signed_literal expr_or_literal sp_opt_default simple_ident_nospvar @@ -2004,12 +2004,12 @@ execute_using: ; execute_params: - expr_or_default + expr_or_ignore_or_default { if (unlikely(!($$= List<Item>::make(thd->mem_root, $1)))) MYSQL_YYABORT; } - | execute_params ',' expr_or_default + | execute_params ',' expr_or_ignore_or_default { if (($$= $1)->push_back($3, thd->mem_root)) MYSQL_YYABORT; @@ -9882,7 +9882,7 @@ column_default_non_parenthesized_expr: if (unlikely(il)) my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str)); $$= new (thd->mem_root) Item_default_value(thd, Lex->current_context(), - $3); + $3, 0); if (unlikely($$ == NULL)) MYSQL_YYABORT; Lex->default_used= TRUE; @@ -12978,7 +12978,7 @@ ident_eq_list: ; ident_eq_value: - simple_ident_nospvar equal expr_or_default + simple_ident_nospvar equal expr_or_ignore_or_default { LEX *lex=Lex; if (unlikely(lex->field_list.push_back($1, thd->mem_root)) || @@ -13048,12 +13048,12 @@ opt_values_with_names: ; values: - values ',' expr_or_default + values ',' expr_or_ignore_or_default { if (unlikely(Lex->insert_list->push_back($3, thd->mem_root))) MYSQL_YYABORT; } - | expr_or_default + | expr_or_ignore_or_default { if (unlikely(Lex->insert_list->push_back($1, thd->mem_root))) MYSQL_YYABORT; @@ -13061,7 +13061,7 @@ values: ; values_with_names: - values_with_names ',' remember_name expr_or_default remember_end + values_with_names ',' remember_name expr_or_ignore_or_default remember_end { if (unlikely(Lex->insert_list->push_back($4, thd->mem_root))) MYSQL_YYABORT; @@ -13069,7 +13069,7 @@ values_with_names: if (!$4->name.str || $4->name.str == item_empty_name) $4->set_name(thd, $3, (uint) ($5 - $3), thd->charset()); } - | remember_name expr_or_default remember_end + | remember_name expr_or_ignore_or_default remember_end { if (unlikely(Lex->insert_list->push_back($2, thd->mem_root))) MYSQL_YYABORT; @@ -13079,17 +13079,21 @@ values_with_names: } ; -expr_or_default: +expr_or_ignore: expr { $$= $1;} - | DEFAULT + | IGNORE_SYM { - $$= new (thd->mem_root) Item_default_specification(thd); + $$= new (thd->mem_root) Item_ignore_specification(thd); if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | IGNORE_SYM + ; + +expr_or_ignore_or_default: + expr_or_ignore { $$= $1;} + | DEFAULT { - $$= new (thd->mem_root) Item_ignore_specification(thd); + $$= new (thd->mem_root) Item_default_specification(thd); if (unlikely($$ == NULL)) MYSQL_YYABORT; } @@ -13171,10 +13175,16 @@ update_list: ; update_elem: - simple_ident_nospvar equal expr_or_default + simple_ident_nospvar equal DEFAULT + { + Item *def= new (thd->mem_root) Item_default_value(thd, + Lex->current_context(), $1, 1); + if (!def || add_item_to_list(thd, $1) || add_value_to_list(thd, def)) + MYSQL_YYABORT; + } + | simple_ident_nospvar equal expr_or_ignore { - if (unlikely(add_item_to_list(thd, $1)) || - unlikely(add_value_to_list(thd, $3))) + if (add_item_to_list(thd, $1) || add_value_to_list(thd, $3)) MYSQL_YYABORT; } ; @@ -13185,7 +13195,7 @@ insert_update_list: ; insert_update_elem: - simple_ident_nospvar equal expr_or_default + simple_ident_nospvar equal expr_or_ignore_or_default { LEX *lex= Lex; if (unlikely(lex->update_list.push_back($1, thd->mem_root)) || @@ -14579,7 +14589,7 @@ load_data_set_list: ; load_data_set_elem: - simple_ident_nospvar equal remember_name expr_or_default remember_end + simple_ident_nospvar equal remember_name expr_or_ignore_or_default remember_end { LEX *lex= Lex; if (unlikely(lex->update_list.push_back($1, thd->mem_root)) || diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index a8e4ff2dded..d826d01edbf 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -512,11 +512,10 @@ static Sys_var_charptr_fscs Sys_my_bind_addr( READ_ONLY GLOBAL_VAR(my_bind_addr_str), CMD_LINE(REQUIRED_ARG), DEFAULT(0)); -const char *Sys_var_vers_asof::asof_keywords[]= {"DEFAULT", NULL}; static Sys_var_vers_asof Sys_vers_asof_timestamp( "system_versioning_asof", "Default value for the FOR SYSTEM_TIME AS OF clause", SESSION_VAR(vers_asof_timestamp.type), NO_CMD_LINE, - Sys_var_vers_asof::asof_keywords, DEFAULT(SYSTEM_TIME_UNSPECIFIED)); + DEFAULT(SYSTEM_TIME_UNSPECIFIED)); static const char *vers_alter_history_keywords[]= {"ERROR", "KEEP", NullS}; static Sys_var_enum Sys_vers_alter_history( @@ -1843,8 +1842,9 @@ static Sys_var_gtid_binlog_pos Sys_gtid_binlog_pos( READ_ONLY GLOBAL_VAR(opt_gtid_binlog_pos_dummy), NO_CMD_LINE); -uchar * -Sys_var_gtid_binlog_pos::global_value_ptr(THD *thd, const LEX_CSTRING *base) +const uchar * +Sys_var_gtid_binlog_pos::global_value_ptr(THD *thd, + const LEX_CSTRING *base) const { char buf[128]; String str(buf, sizeof(buf), system_charset_info); @@ -1871,8 +1871,9 @@ static Sys_var_gtid_current_pos Sys_gtid_current_pos( READ_ONLY GLOBAL_VAR(opt_gtid_current_pos_dummy), NO_CMD_LINE); -uchar * -Sys_var_gtid_current_pos::global_value_ptr(THD *thd, const LEX_CSTRING *base) +const uchar * +Sys_var_gtid_current_pos::global_value_ptr(THD *thd, + const LEX_CSTRING *base) const { String str; char *p; @@ -1952,8 +1953,9 @@ Sys_var_gtid_slave_pos::global_update(THD *thd, set_var *var) } -uchar * -Sys_var_gtid_slave_pos::global_value_ptr(THD *thd, const LEX_CSTRING *base) +const uchar * +Sys_var_gtid_slave_pos::global_value_ptr(THD *thd, + const LEX_CSTRING *base) const { String str; char *p; @@ -2076,8 +2078,9 @@ Sys_var_gtid_binlog_state::global_update(THD *thd, set_var *var) } -uchar * -Sys_var_gtid_binlog_state::global_value_ptr(THD *thd, const LEX_CSTRING *base) +const uchar * +Sys_var_gtid_binlog_state::global_value_ptr(THD *thd, + const LEX_CSTRING *base) const { char buf[512]; String str(buf, sizeof(buf), system_charset_info); @@ -2111,8 +2114,8 @@ static Sys_var_last_gtid Sys_last_gtid( export sys_var *Sys_last_gtid_ptr= &Sys_last_gtid; // for check changing -uchar * -Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_CSTRING *base) +const uchar * +Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_CSTRING *base) const { char buf[10+1+10+1+20+1]; String str(buf, sizeof(buf), system_charset_info); @@ -2286,9 +2289,10 @@ Sys_var_slave_parallel_mode::global_update(THD *thd, set_var *var) } -uchar * +const uchar * Sys_var_slave_parallel_mode::global_value_ptr(THD *thd, - const LEX_CSTRING *base_name) + const + LEX_CSTRING *base_name) const { Master_info *mi; enum_slave_parallel_mode val= @@ -5283,8 +5287,9 @@ bool Sys_var_rpl_filter::set_filter_value(const char *value, Master_info *mi) return status; } -uchar *Sys_var_rpl_filter::global_value_ptr(THD *thd, - const LEX_CSTRING *base_name) +const uchar * +Sys_var_rpl_filter::global_value_ptr(THD *thd, + const LEX_CSTRING *base_name) const { char buf[256]; String tmp(buf, sizeof(buf), &my_charset_bin); @@ -5404,7 +5409,7 @@ Sys_slave_net_timeout( */ ulonglong Sys_var_multi_source_ulonglong:: -get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset) +get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset) const { Master_info *mi; ulonglong res= 0; // Default value diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic index 2bd6ee6467d..97e3a28b67e 100644 --- a/sql/sys_vars.ic +++ b/sql/sys_vars.ic @@ -261,7 +261,7 @@ public: { var->save_result.ulonglong_value= option.def_value; } private: T get_max_var() { return *((T*) max_var_ptr()); } - uchar *default_value_ptr(THD *thd) { return (uchar*) &option.def_value; } + const uchar *default_value_ptr(THD *thd) const { return (uchar*) &option.def_value; } }; typedef Sys_var_integer<int, GET_INT, SHOW_SINT> Sys_var_int; @@ -272,25 +272,25 @@ typedef Sys_var_integer<ulonglong, GET_ULL, SHOW_ULONGLONG> Sys_var_ulonglong; typedef Sys_var_integer<long, GET_LONG, SHOW_SLONG> Sys_var_long; -template<> uchar *Sys_var_int::default_value_ptr(THD *thd) +template<> const uchar *Sys_var_int::default_value_ptr(THD *thd) const { thd->sys_var_tmp.int_value= (int)option.def_value; return (uchar*) &thd->sys_var_tmp.int_value; } -template<> uchar *Sys_var_uint::default_value_ptr(THD *thd) +template<> const uchar *Sys_var_uint::default_value_ptr(THD *thd) const { thd->sys_var_tmp.uint_value= (uint)option.def_value; return (uchar*) &thd->sys_var_tmp.uint_value; } -template<> uchar *Sys_var_long::default_value_ptr(THD *thd) +template<> const uchar *Sys_var_long::default_value_ptr(THD *thd) const { thd->sys_var_tmp.long_value= (long)option.def_value; return (uchar*) &thd->sys_var_tmp.long_value; } -template<> uchar *Sys_var_ulong::default_value_ptr(THD *thd) +template<> const uchar *Sys_var_ulong::default_value_ptr(THD *thd) const { thd->sys_var_tmp.ulong_value= (ulong)option.def_value; return (uchar*) &thd->sys_var_tmp.ulong_value; @@ -420,13 +420,13 @@ public: { var->save_result.ulonglong_value= global_var(ulong); } void global_save_default(THD *thd, set_var *var) { var->save_result.ulonglong_value= option.def_value; } - uchar *valptr(THD *thd, ulong val) - { return (uchar*)typelib.type_names[val]; } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *valptr(THD *thd, ulong val) const + { return reinterpret_cast<const uchar*>(typelib.type_names[val]); } + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, session_var(thd, ulong)); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, global_var(ulong)); } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { return valptr(thd, (ulong)option.def_value); } ulong get_max_var() { return *((ulong *) max_var_ptr()); } @@ -474,7 +474,7 @@ public: { var->save_result.ulonglong_value= (ulonglong)*(my_bool *)global_value_ptr(thd, 0); } void global_save_default(THD *thd, set_var *var) { var->save_result.ulonglong_value= option.def_value; } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { thd->sys_var_tmp.my_bool_value=(my_bool) option.def_value; return (uchar*) &thd->sys_var_tmp.my_bool_value; @@ -723,7 +723,7 @@ public: void global_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); } protected: - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return thd->security_ctx->proxy_user[0] ? (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL; @@ -738,7 +738,7 @@ public: {} protected: - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return (uchar*)thd->security_ctx->external_user; } @@ -790,7 +790,8 @@ public: } protected: - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) override; + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const override; bool set_filter_value(const char *value, Master_info *mi); }; @@ -903,7 +904,7 @@ public: { DBUG_ASSERT(FALSE); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { DBUG_ASSERT(FALSE); return NULL; @@ -981,19 +982,19 @@ public: var->save_result.string_value.str= ptr; var->save_result.string_value.length= safe_strlen(ptr); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { char buf[256]; DBUG_EXPLAIN(buf, sizeof(buf)); return (uchar*) thd->strdup(buf); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { char buf[256]; DBUG_EXPLAIN_INITIAL(buf, sizeof(buf)); return (uchar*) thd->strdup(buf); } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { return (uchar*)""; } }; #endif @@ -1069,7 +1070,7 @@ public: return keycache_update(thd, key_cache, offset, new_value); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { KEY_CACHE *key_cache= get_key_cache(base); if (!key_cache) @@ -1254,7 +1255,7 @@ public: lock, binlog_status_arg, on_check_func, on_update_func, substitute) { } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { if (thd->user_connect && thd->user_connect->user_resources.user_conn) return (uchar*) &(thd->user_connect->user_resources.user_conn); @@ -1366,13 +1367,13 @@ public: { var->save_result.ulonglong_value= global_var(ulonglong); } void global_save_default(THD *thd, set_var *var) { var->save_result.ulonglong_value= option.def_value; } - uchar *valptr(THD *thd, ulonglong val) + const uchar *valptr(THD *thd, ulonglong val) const { return (uchar*)flagset_to_string(thd, 0, val, typelib.type_names); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, session_var(thd, ulonglong)); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, global_var(ulonglong)); } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { return valptr(thd, option.def_value); } }; @@ -1480,13 +1481,13 @@ public: { var->save_result.ulonglong_value= global_var(ulonglong); } void global_save_default(THD *thd, set_var *var) { var->save_result.ulonglong_value= option.def_value; } - uchar *valptr(THD *thd, ulonglong val) - { return (uchar*)set_to_string(thd, 0, val, typelib.type_names); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *valptr(THD *thd, ulonglong val) const + { return reinterpret_cast<const uchar*>(set_to_string(thd, 0, val, typelib.type_names)); } + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, session_var(thd, ulonglong)); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, global_var(ulonglong)); } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { return valptr(thd, option.def_value); } ulonglong get_max_var() { return *((ulonglong*) max_var_ptr()); } @@ -1583,7 +1584,7 @@ public: plugin_ref plugin= global_var(plugin_ref); var->save_result.plugin= plugin ? my_plugin_lock(thd, plugin) : 0; } - plugin_ref get_default(THD *thd) + plugin_ref get_default(THD *thd) const { char *default_value= *reinterpret_cast<char**>(option.def_value); if (!default_value) @@ -1605,16 +1606,16 @@ public: var->save_result.plugin= get_default(thd); } - uchar *valptr(THD *thd, plugin_ref plugin) + uchar *valptr(THD *thd, plugin_ref plugin) const { return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str, plugin_name(plugin)->length) : 0); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, session_var(thd, plugin_ref)); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, global_var(plugin_ref)); } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { return valptr(thd, get_default(thd)); } }; @@ -1701,7 +1702,7 @@ public: plugin_ref* plugins= global_var(plugin_ref *); var->save_result.plugins= plugins ? temp_copy_engine_list(thd, plugins) : 0; } - plugin_ref *get_default(THD *thd) + plugin_ref *get_default(THD *thd) const { char *default_value= *reinterpret_cast<char**>(option.def_value); if (!default_value) @@ -1715,15 +1716,15 @@ public: var->save_result.plugins= get_default(thd); } - uchar *valptr(THD *thd, plugin_ref *plugins) + uchar *valptr(THD *thd, plugin_ref *plugins) const { - return (uchar*)pretty_print_engine_list(thd, plugins); + return reinterpret_cast<uchar*>(pretty_print_engine_list(thd, plugins)); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, session_var(thd, plugin_ref*)); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, global_var(plugin_ref*)); } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { return valptr(thd, get_default(thd)); } }; @@ -1787,16 +1788,16 @@ public: { DBUG_ASSERT(FALSE); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return debug_sync_value_ptr(thd); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { DBUG_ASSERT(FALSE); return 0; } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { return (uchar*)""; } }; #endif /* defined(ENABLED_DEBUG_SYNC) */ @@ -1872,16 +1873,16 @@ public: void global_save_default(THD *thd, set_var *var) { var->save_result.ulonglong_value= option.def_value; } - uchar *valptr(THD *thd, ulonglong val) + uchar *valptr(THD *thd, ulonglong val) const { thd->sys_var_tmp.my_bool_value= (reverse_semantics == !(val & bitmask)); return (uchar*) &thd->sys_var_tmp.my_bool_value; } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, session_var(thd, ulonglong)); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, global_var(ulonglong)); } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { thd->sys_var_tmp.my_bool_value= option.def_value != 0; return (uchar*) &thd->sys_var_tmp.my_bool_value; @@ -1940,17 +1941,17 @@ public: { var->value= 0; } void global_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { thd->sys_var_tmp.ulonglong_value= read_func(thd); return (uchar*) &thd->sys_var_tmp.ulonglong_value; } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { DBUG_ASSERT(FALSE); return 0; } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { thd->sys_var_tmp.ulonglong_value= 0; return (uchar*) &thd->sys_var_tmp.ulonglong_value; @@ -2006,18 +2007,18 @@ public: { var->value= 0; } void global_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { thd->sys_var_tmp.double_value= thd->start_time + thd->start_time_sec_part/(double)TIME_SECOND_PART_FACTOR; return (uchar*) &thd->sys_var_tmp.double_value; } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { DBUG_ASSERT(FALSE); return 0; } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { thd->sys_var_tmp.double_value= 0; return (uchar*) &thd->sys_var_tmp.double_value; @@ -2077,12 +2078,12 @@ public: } void session_save_default(THD *thd, set_var *var) { } void global_save_default(THD *thd, set_var *var) { } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { DBUG_ASSERT(FALSE); return 0; } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return (uchar*)show_comp_option_name[global_var(enum SHOW_COMP_OPTION)]; } @@ -2152,13 +2153,13 @@ public: void **default_value= reinterpret_cast<void**>(option.def_value); var->save_result.ptr= *default_value; } - uchar *valptr(THD *thd, uchar *val) + uchar *valptr(THD *thd, uchar *val) const { return val ? *(uchar**)(val+name_offset) : 0; } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, session_var(thd, uchar*)); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, global_var(uchar*)); } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { return valptr(thd, *(uchar**)option.def_value); } }; @@ -2228,9 +2229,9 @@ public: var->save_result.time_zone= *(Time_zone**)(intptr)option.def_value; } - uchar *valptr(THD *thd, Time_zone *val) - { return (uchar *)(val->get_name()->ptr()); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *valptr(THD *thd, Time_zone *val) const + { return reinterpret_cast<const uchar*>(val->get_name()->ptr()); } + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { /* This is an ugly fix for replication: we don't replicate properly queries @@ -2243,9 +2244,9 @@ public: thd->time_zone_used= 1; return valptr(thd, session_var(thd, Time_zone *)); } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return valptr(thd, global_var(Time_zone*)); } - uchar *default_value_ptr(THD *thd) + const uchar *default_value_ptr(THD *thd) const { return valptr(thd, *(Time_zone**)option.def_value); } }; @@ -2404,7 +2405,7 @@ public: /* Use value given in variable declaration */ global_save_default(thd, var); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { ulonglong *tmp, res; tmp= (ulonglong*) (((uchar*)&(thd->variables)) + offset); @@ -2412,11 +2413,11 @@ public: *tmp= res; return (uchar*) tmp; } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return session_value_ptr(thd, base); } - ulonglong get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset); + ulonglong get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset) const; bool update_variable(THD *thd, Master_info *mi) { return update_multi_source_variable_func(this, thd, mi); @@ -2464,12 +2465,12 @@ public: { DBUG_ASSERT(false); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { DBUG_ASSERT(false); return NULL; } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base); + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; }; @@ -2513,12 +2514,12 @@ public: { DBUG_ASSERT(false); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { DBUG_ASSERT(false); return NULL; } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base); + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; }; @@ -2553,13 +2554,13 @@ public: /* Record the attempt to use default so we can error. */ var->value= 0; } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { DBUG_ASSERT(false); return NULL; } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base); - uchar *default_value_ptr(THD *thd) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; + const uchar *default_value_ptr(THD *thd) const { return 0; } bool on_check_access_global(THD *thd) const { @@ -2599,13 +2600,13 @@ public: /* Record the attempt to use default so we can error. */ var->value= 0; } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { DBUG_ASSERT(false); return NULL; } - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base); - uchar *default_value_ptr(THD *thd) + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; + const uchar *default_value_ptr(THD *thd) const { return 0; } bool on_check_access_global(THD *thd) const { @@ -2654,8 +2655,8 @@ public: { DBUG_ASSERT(false); } - uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base); - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const; + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { DBUG_ASSERT(false); return NULL; @@ -2681,30 +2682,32 @@ public: SYSVAR_ASSERT(scope() == GLOBAL); } bool global_update(THD *thd, set_var *var); - uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base); + const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; }; -class Sys_var_vers_asof: public Sys_var_enum +class Sys_var_vers_asof: public sys_var { public: - static const char *asof_keywords[]; - -public: Sys_var_vers_asof(const char *name_arg, const char *comment, int flag_args, ptrdiff_t off, size_t size, - CMD_LINE getopt, const char *values[], - uint def_val) - : Sys_var_enum(name_arg, comment, flag_args, off, size, - getopt, values, def_val) + CMD_LINE getopt, uint def_val, + PolyLock *lock= NO_MUTEX_GUARD, + binlog_status_enum binlog_status_arg= VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func= NULL, + on_update_function on_update_func= NULL, + const char *substitute= NULL) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, + getopt.id, getopt.arg_type, SHOW_CHAR, def_val, lock, + binlog_status_arg, on_check_func, on_update_func, substitute) { - // setval() accepts string rather enum option.var_type= GET_STR; } virtual bool do_check(THD *thd, set_var *var) { - if (!Sys_var_enum::do_check(thd, var)) + if (!var->value) return false; + MYSQL_TIME ltime; Datetime::Options opt(TIME_CONV_NONE | TIME_NO_ZERO_IN_DATE | @@ -2712,78 +2715,92 @@ public: bool res= var->value->get_date(thd, <ime, opt); if (!res) { - var->save_result.ulonglong_value= SYSTEM_TIME_AS_OF; + uint error; + var->save_result.timestamp.unix_time= + thd->variables.time_zone->TIME_to_gmt_sec(<ime, &error); + var->save_result.timestamp.second_part= ltime.second_part; + res= error != 0; } return res; } private: - bool update(set_var *var, vers_asof_timestamp_t &out) + static bool update(THD *thd, set_var *var, vers_asof_timestamp_t *out) { - bool res= false; - out.type= static_cast<enum_var_type>(var->save_result.ulonglong_value); - if (out.type == SYSTEM_TIME_AS_OF) + if (var->value) { - if (var->value) - { - THD *thd= current_thd; - Datetime::Options opt(TIME_CONV_NONE | - TIME_NO_ZERO_IN_DATE | - TIME_NO_ZERO_DATE, thd); - /* - var->value is allowed to return DATETIME and DATE - Make sure to convert DATE to DATETIME. - */ - res= Datetime(thd, var->value, opt).copy_to_mysql_time(&out.ltime); - } - else // set DEFAULT from global var - { - out= global_var(vers_asof_timestamp_t); - res= false; - } + out->type = SYSTEM_TIME_AS_OF; + out->unix_time = var->save_result.timestamp.unix_time; + out->second_part= var->save_result.timestamp.second_part; } - return res; + return 0; + } + + static void save_default(set_var *var, vers_asof_timestamp_t *out) + { + out->type= SYSTEM_TIME_UNSPECIFIED; } public: virtual bool global_update(THD *thd, set_var *var) { - return update(var, global_var(vers_asof_timestamp_t)); + return update(thd, var, &global_var(vers_asof_timestamp_t)); } virtual bool session_update(THD *thd, set_var *var) { - return update(var, session_var(thd, vers_asof_timestamp_t)); + return update(thd, var, &session_var(thd, vers_asof_timestamp_t)); + } + + virtual bool session_is_default(THD *thd) + { + const vers_asof_timestamp_t &var= session_var(thd, vers_asof_timestamp_t); + return var.type == SYSTEM_TIME_UNSPECIFIED; + } + + virtual void session_save_default(THD *thd, set_var *var) + { + save_default(var, &session_var(thd, vers_asof_timestamp_t)); + } + virtual void global_save_default(THD *thd, set_var *var) + { + save_default(var, &global_var(vers_asof_timestamp_t)); } private: - uchar *value_ptr(THD *thd, vers_asof_timestamp_t &val) + const uchar *value_ptr(THD *thd, vers_asof_timestamp_t &val) const { + const char *value; switch (val.type) { case SYSTEM_TIME_UNSPECIFIED: - case SYSTEM_TIME_ALL: - return (uchar*) thd->strdup(asof_keywords[val.type]); + return (uchar*)"DEFAULT"; + break; case SYSTEM_TIME_AS_OF: { - uchar *buf= (uchar*) thd->alloc(MAX_DATE_STRING_REP_LENGTH); - if (buf &&!my_datetime_to_str(&val.ltime, (char*) buf, 6)) + char *buf= (char*) thd->alloc(MAX_DATE_STRING_REP_LENGTH); + MYSQL_TIME ltime; + + thd->variables.time_zone->gmt_sec_to_TIME(<ime, val.unix_time); + ltime.second_part= val.second_part; + + value= buf; + if (buf && !my_datetime_to_str(<ime, buf, 6)) { - // TODO: figure out variable name - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "system_versioning_asof_timestamp", "NULL (wrong datetime)"); - return (uchar*) thd->strdup("Error: wrong datetime"); + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, "NULL (wrong datetime)"); + value= thd->strdup("Error: wrong datetime"); } - return buf; + break; } default: - break; + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, "NULL (wrong range type)"); + value= thd->strdup("Error: wrong range type"); } - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "system_versioning_asof_timestamp", "NULL (wrong range type)"); - return (uchar*) thd->strdup("Error: wrong range type"); + return reinterpret_cast<const uchar *>(value); } public: - virtual uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) + virtual const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const { return value_ptr(thd, session_var(thd, vers_asof_timestamp_t)); } - virtual uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) + virtual const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const { return value_ptr(thd, global_var(vers_asof_timestamp_t)); } }; diff --git a/sql/table.cc b/sql/table.cc index a64df48e20d..025612ca87b 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -7105,7 +7105,7 @@ void TABLE::prepare_for_position() if ((file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && s->primary_key < MAX_KEY) { - mark_columns_used_by_index_no_reset(s->primary_key, read_set); + mark_index_columns_for_read(s->primary_key); /* signal change */ file->column_bitmaps_signal(); } @@ -7121,7 +7121,7 @@ MY_BITMAP *TABLE::prepare_for_keyread(uint index, MY_BITMAP *map) file->ha_start_keyread(index); if (map != read_set || !(file->index_flags(index, 0, 1) & HA_CLUSTERED_INDEX)) { - mark_columns_used_by_index(index, map); + mark_index_columns(index, map); column_bitmaps_set(map); } DBUG_RETURN(backup); @@ -7132,12 +7132,12 @@ MY_BITMAP *TABLE::prepare_for_keyread(uint index, MY_BITMAP *map) Mark that only fields from one key is used. Useful before keyread. */ -void TABLE::mark_columns_used_by_index(uint index, MY_BITMAP *bitmap) +void TABLE::mark_index_columns(uint index, MY_BITMAP *bitmap) { - DBUG_ENTER("TABLE::mark_columns_used_by_index"); + DBUG_ENTER("TABLE::mark_index_columns"); bitmap_clear_all(bitmap); - mark_columns_used_by_index_no_reset(index, bitmap); + mark_index_columns_no_reset(index, bitmap); DBUG_VOID_RETURN; } @@ -7145,11 +7145,11 @@ void TABLE::mark_columns_used_by_index(uint index, MY_BITMAP *bitmap) Restore to use normal column maps after key read NOTES - This reverse the change done by mark_columns_used_by_index + This reverse the change done by mark_index_columns WARNING For this to work, one must have the normal table maps in place - when calling mark_columns_used_by_index + when calling mark_index_columns */ void TABLE::restore_column_maps_after_keyread(MY_BITMAP *backup) @@ -7161,23 +7161,36 @@ void TABLE::restore_column_maps_after_keyread(MY_BITMAP *backup) DBUG_VOID_RETURN; } +static void do_mark_index_columns(TABLE *table, uint index, + MY_BITMAP *bitmap, bool read) +{ + KEY_PART_INFO *key_part= table->key_info[index].key_part; + uint key_parts= table->key_info[index].user_defined_key_parts; + for (uint k= 0; k < key_parts; k++) + if (read) + key_part[k].field->register_field_in_read_map(); + else + bitmap_set_bit(bitmap, key_part[k].fieldnr-1); + if (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX && + table->s->primary_key != MAX_KEY && table->s->primary_key != index) + do_mark_index_columns(table, table->s->primary_key, bitmap, read); +} /* mark columns used by key, but don't reset other fields */ -void TABLE::mark_columns_used_by_index_no_reset(uint index, MY_BITMAP *bitmap) +inline void TABLE::mark_index_columns_no_reset(uint index, MY_BITMAP *bitmap) { - KEY_PART_INFO *key_part= key_info[index].key_part; - KEY_PART_INFO *key_part_end= (key_part + key_info[index].user_defined_key_parts); - for (;key_part != key_part_end; key_part++) - bitmap_set_bit(bitmap, key_part->fieldnr-1); - if (file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX && - s->primary_key != MAX_KEY && s->primary_key != index) - mark_columns_used_by_index_no_reset(s->primary_key, bitmap); + do_mark_index_columns(this, index, bitmap, false); } +inline void TABLE::mark_index_columns_for_read(uint index) +{ + do_mark_index_columns(this, index, read_set, true); +} + /* Mark auto-increment fields as used fields in both read and write maps @@ -7196,7 +7209,7 @@ void TABLE::mark_auto_increment_column() bitmap_set_bit(read_set, found_next_number_field->field_index); bitmap_set_bit(write_set, found_next_number_field->field_index); if (s->next_number_keypart) - mark_columns_used_by_index_no_reset(s->next_number_index, read_set); + mark_index_columns_for_read(s->next_number_index); file->column_bitmaps_signal(); } @@ -7247,7 +7260,7 @@ void TABLE::mark_columns_needed_for_delete() file->use_hidden_primary_key(); else { - mark_columns_used_by_index_no_reset(s->primary_key, read_set); + mark_index_columns_for_read(s->primary_key); need_signal= true; } } @@ -7333,7 +7346,7 @@ void TABLE::mark_columns_needed_for_update() file->use_hidden_primary_key(); else { - mark_columns_used_by_index_no_reset(s->primary_key, read_set); + mark_index_columns_for_read(s->primary_key); need_signal= true; } } @@ -7493,7 +7506,7 @@ void TABLE::mark_columns_per_binlog_row_image() if ((my_field->flags & PRI_KEY_FLAG) || (my_field->type() != MYSQL_TYPE_BLOB)) { - bitmap_set_bit(read_set, my_field->field_index); + my_field->register_field_in_read_map(); bitmap_set_bit(rpl_write_set, my_field->field_index); } } @@ -7505,7 +7518,7 @@ void TABLE::mark_columns_per_binlog_row_image() We don't need to mark the primary key in the rpl_write_set as the binary log will include all columns read anyway. */ - mark_columns_used_by_index_no_reset(s->primary_key, read_set); + mark_index_columns_for_read(s->primary_key); if (versioned()) { // TODO: After MDEV-18432 we don't pass history rows, so remove this: diff --git a/sql/table.h b/sql/table.h index 8efab4ca70d..d063a3f27be 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1542,8 +1542,9 @@ public: MY_BITMAP *prepare_for_keyread(uint index, MY_BITMAP *map); MY_BITMAP *prepare_for_keyread(uint index) { return prepare_for_keyread(index, &tmp_set); } - void mark_columns_used_by_index(uint index, MY_BITMAP *map); - void mark_columns_used_by_index_no_reset(uint index, MY_BITMAP *map); + void mark_index_columns(uint index, MY_BITMAP *bitmap); + void mark_index_columns_no_reset(uint index, MY_BITMAP *bitmap); + void mark_index_columns_for_read(uint index); void restore_column_maps_after_keyread(MY_BITMAP *backup); void mark_auto_increment_column(void); void mark_columns_needed_for_update(void); diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index e8eb0dcc29d..088c97ddb99 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -224,6 +224,14 @@ static THD* threadpool_add_connection(CONNECT *connect, void *scheduler_data) { THD *thd= NULL; + DBUG_EXECUTE_IF("CONNECT_wait", + { + extern MYSQL_SOCKET unix_sock; + DBUG_ASSERT(unix_sock.fd >= 0); + while (unix_sock.fd >= 0) + my_sleep(1000); + }); + /* Create a new connection context: mysys_thread_var and PSI thread Store them in THD. @@ -241,10 +249,9 @@ static THD* threadpool_add_connection(CONNECT *connect, void *scheduler_data) my_thread_end(); return NULL; } - delete connect; - thd->event_scheduler.data = scheduler_data; - server_threads.insert(thd); + server_threads.insert(thd); // Make THD visible in show processlist + delete connect; // must be after server_threads.insert, see close_connections() thd->set_mysys_var(mysys_var); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index a5592fc5ae6..972876c24c2 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2390,8 +2390,8 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, if (Wsrep_server_state::instance().desynced_on_pause()) { my_message(ER_UNKNOWN_COM_ERROR, - "Aborting TOI: Global Read-Lock (FTWRL) in place.", MYF(0)); - WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %llu", + "Aborting TOI: Replication paused on node for FTWRL/BACKUP STAGE.", MYF(0)); + WSREP_DEBUG("Aborting TOI: Replication paused on node for FTWRL/BACKUP STAGE.: %s %llu", wsrep_thd_query(thd), thd->thread_id); return -1; } @@ -2735,15 +2735,13 @@ void wsrep_close_client_connections(my_bool wait_to_end, THD* except_caller_thd) */ server_threads.iterate(kill_remaining_threads, except_caller_thd); - DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)", - uint32_t(thread_count))); - WSREP_DEBUG("waiting for client connections to close: %u", - uint32_t(thread_count)); + DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)", THD_count::value())); + WSREP_DEBUG("waiting for client connections to close: %u", THD_count::value()); while (wait_to_end && server_threads.iterate(have_client_connections)) { sleep(1); - DBUG_PRINT("quit",("One thread died (count=%u)", uint32_t(thread_count))); + DBUG_PRINT("quit",("One thread died (count=%u)", THD_count::value())); } /* All client connection threads have now been aborted */ diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 15fd87eda5d..a5d292700a7 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -349,6 +349,15 @@ bool wsrep_bf_abort(const THD* bf_thd, THD* victim_thd) if (WSREP(victim_thd) && !victim_thd->wsrep_trx().active()) { WSREP_DEBUG("wsrep_bf_abort, BF abort for non active transaction"); + switch (victim_thd->wsrep_trx().state()) + { + case wsrep::transaction::s_aborting: /* fall through */ + case wsrep::transaction::s_aborted: + WSREP_DEBUG("victim thd is already aborted or in aborting state."); + return false; + default: + break; + } wsrep_start_transaction(victim_thd, victim_thd->wsrep_next_trx_id()); } |