summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/backup.cc24
-rw-r--r--sql/field.cc10
-rw-r--r--sql/ha_partition.cc3
-rw-r--r--sql/handler.cc14
-rw-r--r--sql/item.cc8
-rw-r--r--sql/item.h13
-rw-r--r--sql/item_func.cc16
-rw-r--r--sql/item_strfunc.cc33
-rw-r--r--sql/key.cc2
-rw-r--r--sql/mysqld.cc18
-rw-r--r--sql/mysqld.h4
-rw-r--r--sql/set_var.cc14
-rw-r--r--sql/set_var.h25
-rw-r--r--sql/signal_handler.cc2
-rw-r--r--sql/sql_acl.cc22
-rw-r--r--sql/sql_admin.cc4
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_class.cc9
-rw-r--r--sql/sql_class.h36
-rw-r--r--sql/sql_connect.cc14
-rw-r--r--sql/sql_connect.h13
-rw-r--r--sql/sql_cte.cc24
-rw-r--r--sql/sql_cte.h2
-rw-r--r--sql/sql_insert.cc9
-rw-r--r--sql/sql_lex.cc20
-rw-r--r--sql/sql_lex.h15
-rw-r--r--sql/sql_parse.cc10
-rw-r--r--sql/sql_partition.cc11
-rw-r--r--sql/sql_plugin.cc24
-rw-r--r--sql/sql_prepare.cc9
-rw-r--r--sql/sql_select.cc78
-rw-r--r--sql/sql_show.cc86
-rw-r--r--sql/sql_type.cc15
-rw-r--r--sql/sql_type.h8
-rw-r--r--sql/sql_union.cc35
-rw-r--r--sql/sql_update.cc2
-rw-r--r--sql/sql_window.cc12
-rw-r--r--sql/sql_window.h5
-rw-r--r--sql/sql_yacc.yy48
-rw-r--r--sql/sys_vars.cc39
-rw-r--r--sql/sys_vars.ic275
-rw-r--r--sql/table.cc53
-rw-r--r--sql/table.h5
-rw-r--r--sql/threadpool_common.cc13
-rw-r--r--sql/wsrep_mysqld.cc12
-rw-r--r--sql/wsrep_thd.cc9
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, &ltime, 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, &ltime, 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(&ltime, &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(&ltime, val.unix_time);
+ ltime.second_part= val.second_part;
+
+ value= buf;
+ if (buf && !my_datetime_to_str(&ltime, 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());
}