summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-04-21 11:45:00 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-04-21 11:45:00 +0300
commit4930f9c94bb610f4d76b73a8b6b351d9fa9c5d68 (patch)
treeed6b2754116233ca8a39515c7ba06e09b2a8cdc8 /sql
parent502b769561760f35d2b612ab984906c8a4bb9b51 (diff)
parentd104fe6f734df2aebe24b3e5e3dbc189a5302920 (diff)
downloadmariadb-git-4930f9c94bb610f4d76b73a8b6b351d9fa9c5d68.tar.gz
Merge 10.5 into 10.6
Diffstat (limited to 'sql')
-rw-r--r--sql/compat56.h4
-rw-r--r--sql/events.cc12
-rw-r--r--sql/field.h8
-rw-r--r--sql/gcalc_tools.h6
-rw-r--r--sql/ha_partition.cc1
-rw-r--r--sql/item.cc18
-rw-r--r--sql/item_buff.cc4
-rw-r--r--sql/item_cmpfunc.cc10
-rw-r--r--sql/item_func.cc62
-rw-r--r--sql/item_jsonfunc.cc5
-rw-r--r--sql/item_strfunc.cc16
-rw-r--r--sql/item_strfunc.h9
-rw-r--r--sql/item_subselect.cc36
-rw-r--r--sql/item_sum.cc6
-rw-r--r--sql/item_timefunc.cc23
-rw-r--r--sql/log.cc29
-rw-r--r--sql/mf_iocache.cc2
-rw-r--r--sql/opt_split.cc2
-rw-r--r--sql/opt_subselect.cc12
-rw-r--r--sql/partition_element.h3
-rw-r--r--sql/service_wsrep.cc18
-rw-r--r--sql/signal_handler.cc6
-rw-r--r--sql/sql_acl.cc126
-rw-r--r--sql/sql_base.cc14
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_derived.cc23
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_parse.cc4
-rw-r--r--sql/sql_partition.cc2
-rw-r--r--sql/sql_reload.cc8
-rw-r--r--sql/sql_select.cc47
-rw-r--r--sql/sql_select.h97
-rw-r--r--sql/sql_sequence.cc4
-rw-r--r--sql/sql_sequence.h4
-rw-r--r--sql/sql_show.cc3
-rw-r--r--sql/sql_table.cc14
-rw-r--r--sql/sql_test.cc9
-rw-r--r--sql/sql_type_int.h14
-rw-r--r--sql/strfunc.cc16
-rw-r--r--sql/sys_vars.cc22
-rw-r--r--sql/temporary_tables.cc16
-rw-r--r--sql/wsrep_mysqld.cc26
-rw-r--r--sql/wsrep_mysqld.h1
-rw-r--r--sql/wsrep_trans_observer.h10
-rw-r--r--sql/wsrep_var.cc59
46 files changed, 544 insertions, 274 deletions
diff --git a/sql/compat56.h b/sql/compat56.h
index 347d6145048..65cd36dacfd 100644
--- a/sql/compat56.h
+++ b/sql/compat56.h
@@ -30,8 +30,8 @@
#define MY_PACKED_TIME_GET_INT_PART(x) ((x) >> 24)
#define MY_PACKED_TIME_GET_FRAC_PART(x) ((x) % (1LL << 24))
-#define MY_PACKED_TIME_MAKE(i, f) ((((longlong) (i)) << 24) + (f))
-#define MY_PACKED_TIME_MAKE_INT(i) ((((longlong) (i)) << 24))
+#define MY_PACKED_TIME_MAKE(i, f) ((((ulonglong) (i)) << 24) + (f))
+#define MY_PACKED_TIME_MAKE_INT(i) ((((ulonglong) (i)) << 24))
longlong TIME_to_longlong_datetime_packed(const MYSQL_TIME *);
longlong TIME_to_longlong_time_packed(const MYSQL_TIME *);
diff --git a/sql/events.cc b/sql/events.cc
index 33ddcdac3cb..9f0aef885df 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -662,8 +662,16 @@ Events::drop_schema_events(THD *thd, const char *db)
*/
if (event_queue)
event_queue->drop_schema_events(thd, &db_lex);
- db_repository->drop_schema_events(thd, &db_lex);
-
+ if (db_repository)
+ db_repository->drop_schema_events(thd, &db_lex);
+ else
+ {
+ if ((db_repository= new Event_db_repository))
+ {
+ db_repository->drop_schema_events(thd, &db_lex);
+ delete db_repository;
+ }
+ }
DBUG_VOID_RETURN;
}
diff --git a/sql/field.h b/sql/field.h
index d808a9b0401..ba50e0da1d7 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -4997,7 +4997,13 @@ public:
void move_field_offset(my_ptrdiff_t ptr_diff) override
{
Field::move_field_offset(ptr_diff);
- bit_ptr= ADD_TO_PTR(bit_ptr, ptr_diff, uchar*);
+
+ /*
+ clang does not like when things are added to a null pointer, even if
+ it is never referenced.
+ */
+ if (bit_ptr)
+ bit_ptr= ADD_TO_PTR(bit_ptr, ptr_diff, uchar*);
}
void hash(ulong *nr, ulong *nr2) override;
diff --git a/sql/gcalc_tools.h b/sql/gcalc_tools.h
index 77da791f0b9..e625b355d95 100644
--- a/sql/gcalc_tools.h
+++ b/sql/gcalc_tools.h
@@ -184,7 +184,11 @@ class Gcalc_result_receiver
double first_x, first_y, prev_x, prev_y;
double shape_area;
public:
- Gcalc_result_receiver() : collection_result(FALSE), n_shapes(0), n_holes(0)
+Gcalc_result_receiver() :
+ n_points(0),
+ common_shapetype(Gcalc_function::shape_point),
+ collection_result(FALSE), n_shapes(0), n_holes(0),
+ cur_shape(Gcalc_function::shape_point), shape_pos(0)
{}
int start_shape(Gcalc_function::shape_type shape);
int add_point(double x, double y);
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 5acdbe5b7e2..8eddec5511f 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -6574,6 +6574,7 @@ int ha_partition::multi_range_read_init(RANGE_SEQ_IF *seq,
DBUG_ENTER("ha_partition::multi_range_read_init");
DBUG_PRINT("enter", ("partition this: %p", this));
+ eq_range= 0;
m_seq_if= seq;
m_seq= seq->init(seq_init_param, n_ranges, mrr_mode);
if (unlikely((error= multi_range_key_create_key(seq, m_seq))))
diff --git a/sql/item.cc b/sql/item.cc
index 152f36bb9e8..5cdbf52e829 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2653,9 +2653,7 @@ Item_sp::Item_sp(THD *thd, Name_resolution_context *context_arg,
dummy_table= (TABLE*) thd->calloc(sizeof(TABLE) + sizeof(TABLE_SHARE) +
sizeof(Query_arena));
dummy_table->s= (TABLE_SHARE*) (dummy_table + 1);
- /* TODO(cvicentiu) Move this sp_query_arena in the class as a direct member.
- Currently it can not be done due to header include dependencies. */
- sp_query_arena= (Query_arena *) (dummy_table->s + 1);
+ sp_query_arena= new(dummy_table->s + 1) Query_arena();
memset(&sp_mem_root, 0, sizeof(sp_mem_root));
}
@@ -2666,7 +2664,7 @@ Item_sp::Item_sp(THD *thd, Item_sp *item):
dummy_table= (TABLE*) thd->calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE) +
sizeof(Query_arena));
dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
- sp_query_arena= (Query_arena *) (dummy_table->s + 1);
+ sp_query_arena= new(dummy_table->s + 1) Query_arena();
memset(&sp_mem_root, 0, sizeof(sp_mem_root));
}
@@ -6285,12 +6283,14 @@ Item *Item_field::replace_equal_field(THD *thd, uchar *arg)
item_equal->compare_type_handler()->cmp_type());
return const_item2;
}
- Item_field *subst=
- (Item_field *)(item_equal->get_first(param->context_tab, this));
+ Item_ident *subst=
+ (Item_ident *) (item_equal->get_first(param->context_tab, this));
if (subst)
- subst= (Item_field *) (subst->real_item());
- if (subst && !field->eq(subst->field))
- return subst;
+ {
+ Item_field *subst2= (Item_field *) (subst->real_item());
+ if (subst2 && !field->eq(subst2->field))
+ return subst2;
+ }
}
return this;
}
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index 9c96fdb1a9a..05cef6871be 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -47,9 +47,9 @@ Cached_item *new_Cached_item(THD *thd, Item *item, bool pass_through_ref)
}
switch (item->result_type()) {
case STRING_RESULT:
- return new Cached_item_str(thd, (Item_field *) item);
+ return new Cached_item_str(thd, item);
case INT_RESULT:
- return new Cached_item_int((Item_field *) item);
+ return new Cached_item_int(item);
case REAL_RESULT:
return new Cached_item_real(item);
case DECIMAL_RESULT:
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 4a134e99bfc..97c41373d12 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -5800,13 +5800,17 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
if (!res2)
return FALSE; // Null argument
- const size_t len = res2->length();
- const char* first = res2->ptr();
- const char* last = first + len - 1;
+ const size_t len= res2->length();
+
/*
len must be > 2 ('%pattern%')
heuristic: only do TurboBM for pattern_len > 2
*/
+ if (len <= 2)
+ return FALSE;
+
+ const char* first= res2->ptr();
+ const char* last= first + len - 1;
if (len > MIN_TURBOBM_PATTERN_LEN + 2 &&
*first == wild_many &&
diff --git a/sql/item_func.cc b/sql/item_func.cc
index a0ef4020aae..f308435eea7 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2009, 2020, MariaDB
+ Copyright (c) 2009, 2021, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1104,17 +1104,20 @@ double Item_func_plus::real_op()
return check_float_overflow(value);
}
+#if defined(__powerpc64__) && GCC_VERSION >= 6003 && GCC_VERSION <= 10002
+#pragma GCC push_options
+#pragma GCC optimize ("no-expensive-optimizations")
+#endif
longlong Item_func_plus::int_op()
{
longlong val0= args[0]->val_int();
longlong val1= args[1]->val_int();
- longlong res= val0 + val1;
bool res_unsigned= FALSE;
+ longlong res;
if ((null_value= args[0]->null_value || args[1]->null_value))
return 0;
-
/*
First check whether the result can be represented as a
(bool unsigned_flag, longlong value) pair, then check if it is compatible
@@ -1155,16 +1158,29 @@ longlong Item_func_plus::int_op()
{
if (val0 >=0 && val1 >= 0)
res_unsigned= TRUE;
- else if (val0 < 0 && val1 < 0 && res >= 0)
+ else if (val0 < 0 && val1 < 0 && val0 < (LONGLONG_MIN - val1))
goto err;
}
}
+
+#ifndef WITH_UBSAN
+ res= val0 + val1;
+#else
+ if (res_unsigned)
+ res= (longlong) ((ulonglong) val0 + (ulonglong) val1);
+ else
+ res= val0+val1;
+#endif /* WITH_UBSAN */
+
return check_integer_overflow(res, res_unsigned);
err:
return raise_integer_overflow();
}
+#if defined(__powerpc64__) && GCC_VERSION >= 6003 && GCC_VERSION <= 10002
+#pragma GCC pop_options
+#endif
/**
Calculate plus of two decimals.
@@ -1259,12 +1275,17 @@ double Item_func_minus::real_op()
}
+#if defined(__powerpc64__) && GCC_VERSION >= 6003 && GCC_VERSION <= 10002
+#pragma GCC push_options
+#pragma GCC optimize ("no-expensive-optimizations")
+#endif
+
longlong Item_func_minus::int_op()
{
longlong val0= args[0]->val_int();
longlong val1= args[1]->val_int();
- longlong res= val0 - val1;
bool res_unsigned= FALSE;
+ longlong res;
if ((null_value= args[0]->null_value || args[1]->null_value))
return 0;
@@ -1279,12 +1300,8 @@ longlong Item_func_minus::int_op()
if (args[1]->unsigned_flag)
{
if ((ulonglong) val0 < (ulonglong) val1)
- {
- if (res >= 0)
- goto err;
- }
- else
- res_unsigned= TRUE;
+ goto err;
+ res_unsigned= TRUE;
}
else
{
@@ -1305,23 +1322,35 @@ longlong Item_func_minus::int_op()
{
if (args[1]->unsigned_flag)
{
- if ((ulonglong) (val0 - LONGLONG_MIN) < (ulonglong) val1)
+ if (((ulonglong) val0 - (ulonglong) LONGLONG_MIN) < (ulonglong) val1)
goto err;
}
else
{
if (val0 > 0 && val1 < 0)
res_unsigned= TRUE;
- else if (val0 < 0 && val1 > 0 && res >= 0)
+ else if (val0 < 0 && val1 > 0 && val0 < (LONGLONG_MIN + val1))
goto err;
}
}
+#ifndef WITH_UBSAN
+ res= val0 - val1;
+#else
+ if (res_unsigned)
+ res= (longlong) ((ulonglong) val0 - (ulonglong) val1);
+ else
+ res= val0 - val1;
+#endif /* WITH_UBSAN */
+
return check_integer_overflow(res, res_unsigned);
err:
return raise_integer_overflow();
}
+#if defined(__powerpc64__) && GCC_VERSION >= 6003 && GCC_VERSION <= 10002
+#pragma GCC pop_options
+#endif
/**
See Item_func_plus::decimal_op for comments.
@@ -3114,10 +3143,11 @@ longlong Item_func_locate::val_int()
if (arg_count == 3)
{
- start0= start= args[2]->val_int() - 1;
+ start0= start= args[2]->val_int();
- if ((start < 0) || (start > a->length()))
+ if ((start <= 0) || (start > a->length()))
return 0;
+ start0--; start--;
/* start is now sufficiently valid to pass to charpos function */
start= a->charpos((int) start);
@@ -3281,7 +3311,7 @@ bool Item_func_find_in_set::fix_length_and_dec()
find->length(), 0);
enum_bit=0;
if (enum_value)
- enum_bit=1LL << (enum_value-1);
+ enum_bit= 1ULL << (enum_value-1);
}
}
}
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index af14734eae3..e7f2b3d8eee 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -624,8 +624,6 @@ String *Item_func_json_unquote::read_json(json_engine_t *je)
json_scan_start(je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
- je->value_type= (enum json_value_types) -1; /* To report errors right. */
-
if (json_read_value(je))
goto error;
@@ -988,7 +986,8 @@ my_decimal *Item_func_json_extract::val_decimal(my_decimal *to)
case JSON_VALUE_ARRAY:
case JSON_VALUE_FALSE:
case JSON_VALUE_NULL:
- break;
+ case JSON_VALUE_UNINITALIZED:
+ break;
};
}
int2my_decimal(E_DEC_FATAL_ERROR, 0, false/*unsigned_flag*/, to);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 5a6cb1a4c8f..3123844865f 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1496,17 +1496,18 @@ String *Item_func_insert::val_str(String *str)
null_value=0;
res=args[0]->val_str(str);
res2=args[3]->val_str(&tmp_value);
- start= args[1]->val_int() - 1;
+ start= args[1]->val_int();
length= args[2]->val_int();
if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
args[3]->null_value)
goto null; /* purecov: inspected */
- if ((start < 0) || (start > res->length()))
+ if ((start <= 0) || (start > res->length()))
return res; // Wrong param; skip insert
if ((length < 0) || (length > res->length()))
length= res->length();
+ start--;
/*
There is one exception not handled (intentionaly) by the character set
@@ -3775,13 +3776,12 @@ String *Item_func_unhex::val_str(String *str)
}
for (end=res->ptr()+res->length(); from < end ; from+=2, to++)
{
- int hex_char;
- *to= (hex_char= hexchar_to_int(from[0])) << 4;
- if ((null_value= (hex_char == -1)))
- return 0;
- *to|= hex_char= hexchar_to_int(from[1]);
- if ((null_value= (hex_char == -1)))
+ int hex_char1, hex_char2;
+ hex_char1= hexchar_to_int(from[0]);
+ hex_char2= hexchar_to_int(from[1]);
+ if ((null_value= (hex_char1 == -1 || hex_char2 == -1)))
return 0;
+ *to= (char) ((hex_char1 << 4) | hex_char2);
}
return str;
}
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 1ae62a4a6e8..36300e57f03 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -42,8 +42,13 @@ protected:
we don't want to free and potentially have to reallocate the buffer
for each call.
*/
- str_value.length(0);
- str_value.set_charset(collation.collation);
+ if (!str_value.is_alloced())
+ str_value.set("", 0, collation.collation); /* Avoid null ptrs */
+ else
+ {
+ str_value.length(0); /* Reuse allocated area */
+ str_value.set_charset(collation.collation);
+ }
return &str_value;
}
public:
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index e4e8bf2a1e8..c9afc9c1bcd 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2016, Oracle and/or its affiliates.
- Copyright (c) 2010, 2016, MariaDB
+ Copyright (c) 2010, 2021, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -685,6 +685,31 @@ bool Item_subselect::is_expensive()
}
+static
+int walk_items_for_table_list(Item_processor processor,
+ bool walk_subquery, void *argument,
+ List<TABLE_LIST>& join_list)
+{
+ List_iterator<TABLE_LIST> li(join_list);
+ int res;
+ while (TABLE_LIST *table= li++)
+ {
+ if (table->on_expr)
+ {
+ if ((res= table->on_expr->walk(processor, walk_subquery, argument)))
+ return res;
+ }
+ if (table->nested_join)
+ {
+ if ((res= walk_items_for_table_list(processor, walk_subquery, argument,
+ table->nested_join->join_list)))
+ return res;
+ }
+ }
+ return 0;
+}
+
+
bool Item_subselect::unknown_splocal_processor(void *argument)
{
SELECT_LEX *sl= unit->first_select();
@@ -770,7 +795,6 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
for (SELECT_LEX *lex= unit->first_select(); lex; lex= lex->next_select())
{
List_iterator<Item> li(lex->item_list);
- Item *item;
ORDER *order;
if (lex->where && (lex->where)->walk(processor, walk_subquery, argument))
@@ -778,14 +802,16 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
if (lex->having && (lex->having)->walk(processor, walk_subquery,
argument))
return 1;
- /* TODO: why does this walk WHERE/HAVING but not ON expressions of outer joins? */
- /* Consider walking ON epxression in walk_table_functions_for_list */
+
+ if (walk_items_for_table_list(processor, walk_subquery, argument,
+ *lex->join_list))
+ return 1;
if (walk_table_functions_for_list(processor, walk_subquery, argument,
*lex->join_list))
return 1;
- while ((item=li++))
+ while (Item *item= li++)
{
if (item->walk(processor, walk_subquery, argument))
return 1;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 7106f72e237..537eaaf8dcd 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -2639,9 +2639,9 @@ bool Item_sum_bit::add_as_window(ulonglong value)
void Item_sum_or::set_bits_from_counters()
{
ulonglong value= 0;
- for (int i= 0; i < NUM_BIT_COUNTERS; i++)
+ for (uint i= 0; i < NUM_BIT_COUNTERS; i++)
{
- value|= bit_counters[i] > 0 ? (1 << i) : 0;
+ value|= bit_counters[i] > 0 ? (1ULL << i) : 0ULL;
}
bits= value | reset_bits;
}
@@ -3887,7 +3887,7 @@ Item_func_group_concat(THD *thd, Name_resolution_context *context_arg,
arg_count_field(select_list->elements),
row_count(0),
distinct(distinct_arg),
- warning_for_row(FALSE),
+ warning_for_row(FALSE), always_null(FALSE),
force_copy_fields(0), row_limit(NULL),
offset_limit(NULL), limit_clause(limit_clause),
copy_offset_limit(0), copy_row_limit(0), original(0)
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index b8650a5c7e9..3707811f3f6 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -729,7 +729,10 @@ static bool make_date_time(const String *format, const MYSQL_TIME *l_time,
For example, '1.1' -> '1.100000'
*/
-static bool get_interval_info(const char *str, size_t length,CHARSET_INFO *cs, size_t count, ulonglong *values,
+#define MAX_DIGITS_IN_TIME_SPEC 20
+
+static bool get_interval_info(const char *str, size_t length,CHARSET_INFO *cs,
+ size_t count, ulonglong *values,
bool transform_msec)
{
const char *end=str+length;
@@ -741,11 +744,21 @@ static bool get_interval_info(const char *str, size_t length,CHARSET_INFO *cs, s
for (i=0 ; i < count ; i++)
{
- longlong value;
+ ulonglong value;
const char *start= str;
- for (value= 0; str != end && my_isdigit(cs, *str); str++)
+ const char *local_end= end;
+
+ /*
+ We limit things to 19 digits to not get an overflow. This is ok as
+ this function is meant to read up to microseconds
+ */
+ if ((local_end-str) > MAX_DIGITS_IN_TIME_SPEC)
+ local_end= str+ MAX_DIGITS_IN_TIME_SPEC;
+
+ for (value= 0; str != local_end && my_isdigit(cs, *str) ; str++)
value= value*10 + *str - '0';
- if ((field_length= (size_t)(str - start)) >= 20)
+
+ if ((field_length= (size_t)(str - start)) >= MAX_DIGITS_IN_TIME_SPEC)
return true;
values[i]= value;
while (str != end && !my_isdigit(cs,*str))
@@ -2070,9 +2083,9 @@ bool Func_handler_date_add_interval_datetime_arg0_time::
bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
{
- Item_date_add_interval *other= (Item_date_add_interval*) item;
if (!Item_func::eq(item, binary_cmp))
return 0;
+ Item_date_add_interval *other= (Item_date_add_interval*) item;
return ((int_type == other->int_type) &&
(date_sub_interval == other->date_sub_interval));
}
diff --git a/sql/log.cc b/sql/log.cc
index a31b8dd5598..be94a7f7523 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -10217,28 +10217,13 @@ int TC_LOG_BINLOG::unlog_xa_prepare(THD *thd, bool all)
uint rw_count= ha_count_rw_all(thd, &ha_info);
bool rc= false;
-#ifndef DBUG_OFF
- if (rw_count > 1)
- {
- /*
- There must be no binlog_hton used in a transaction consisting of more
- than 1 engine, *when* (at this point) this transaction has not been
- binlogged. The one exception is if there is an engine without a
- prepare method, as in this case the engine doesn't support XA and
- we have to ignore this check.
- */
- bool binlog= false, exist_hton_without_prepare= false;
- for (ha_info= thd->transaction->all.ha_list; ha_info;
- ha_info= ha_info->next())
- {
- if (ha_info->ht() == binlog_hton)
- binlog= true;
- if (!ha_info->ht()->prepare)
- exist_hton_without_prepare= true;
- }
- DBUG_ASSERT(!binlog || exist_hton_without_prepare);
- }
-#endif
+ /*
+ This transaction has not been binlogged as indicated by need_unlog.
+ Such exceptional cases include transactions with no effect to engines,
+ e.g REPLACE that does not change the dat but still the Engine
+ transaction branch claims to be rw, and few more.
+ In all such cases an empty XA-prepare group of events is bin-logged.
+ */
if (rw_count > 0)
{
/* an empty XA-prepare event group is logged */
diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc
index c9cff6ad930..877a49edbec 100644
--- a/sql/mf_iocache.cc
+++ b/sql/mf_iocache.cc
@@ -26,7 +26,7 @@
Used instead of FILE when reading or writing whole files.
This will make mf_rec_cache obsolete.
One can change info->pos_in_file to a higher value to skip bytes in file if
- also info->rc_pos is set to info->rc_end.
+ also info->read_pos is set to info->read_end.
If called through open_cached_file(), then the temporary file will
only be created if a write exeeds the file buffer or if one calls
flush_io_cache().
diff --git a/sql/opt_split.cc b/sql/opt_split.cc
index c81e1ab9e3a..c5bd8076209 100644
--- a/sql/opt_split.cc
+++ b/sql/opt_split.cc
@@ -205,7 +205,7 @@ struct SplM_field_info
struct SplM_plan_info
{
/* The cached splitting execution plan P */
- struct st_position *best_positions;
+ POSITION *best_positions;
/* The cost of the above plan */
double cost;
/* Selectivity of splitting used in P */
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 50be5817df2..582b1b8e8ef 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -3010,7 +3010,7 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
}
-void Sj_materialization_picker::set_from_prev(struct st_position *prev)
+void Sj_materialization_picker::set_from_prev(POSITION *prev)
{
if (prev->sjmat_picker.is_used)
set_empty();
@@ -3196,7 +3196,7 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
}
-void LooseScan_picker::set_from_prev(struct st_position *prev)
+void LooseScan_picker::set_from_prev(POSITION *prev)
{
if (prev->loosescan_picker.is_used)
set_empty();
@@ -3217,7 +3217,7 @@ bool LooseScan_picker::check_qep(JOIN *join,
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
- struct st_position *loose_scan_pos)
+ POSITION *loose_scan_pos)
{
POSITION *first= join->positions + first_loosescan_table;
/*
@@ -3295,7 +3295,7 @@ bool LooseScan_picker::check_qep(JOIN *join,
return FALSE;
}
-void Firstmatch_picker::set_from_prev(struct st_position *prev)
+void Firstmatch_picker::set_from_prev(POSITION *prev)
{
if (prev->firstmatch_picker.is_used)
invalidate_firstmatch_prefix();
@@ -5831,8 +5831,8 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
((Item_func *) item)->functype() == Item_func::EQ_FUNC &&
check_simple_equality(thd,
Item::Context(Item::ANY_SUBST,
- ((Item_func_equal *)item)->compare_type_handler(),
- ((Item_func_equal *)item)->compare_collation()),
+ ((Item_func_eq *)item)->compare_type_handler(),
+ ((Item_func_eq *)item)->compare_collation()),
((Item_func *)item)->arguments()[0],
((Item_func *)item)->arguments()[1],
&new_cond_equal))
diff --git a/sql/partition_element.h b/sql/partition_element.h
index ff0d0d59fc4..e0a519065cc 100644
--- a/sql/partition_element.h
+++ b/sql/partition_element.h
@@ -144,6 +144,7 @@ public:
part_min_rows(part_elem->part_min_rows),
range_value(0), partition_name(NULL),
tablespace_name(part_elem->tablespace_name),
+ log_entry(NULL),
part_comment(part_elem->part_comment),
data_file_name(part_elem->data_file_name),
index_file_name(part_elem->index_file_name),
@@ -152,6 +153,8 @@ public:
part_state(part_elem->part_state),
nodegroup_id(part_elem->nodegroup_id),
has_null_value(FALSE),
+ signed_flag(part_elem->signed_flag),
+ max_value(part_elem->max_value),
id(part_elem->id),
empty(part_elem->empty),
type(CONVENTIONAL)
diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc
index d0a96a85a60..91b1a48cad7 100644
--- a/sql/service_wsrep.cc
+++ b/sql/service_wsrep.cc
@@ -119,15 +119,23 @@ extern "C" my_bool wsrep_get_debug()
return wsrep_debug;
}
+/*
+ Test if this connection is a true local (user) connection and not
+ a replication or wsrep applier thread.
+
+ Note that this is only usable for galera (as there are other kinds
+ of system threads, and only if WSREP_NNULL() is tested by the caller.
+ */
extern "C" my_bool wsrep_thd_is_local(const THD *thd)
{
/*
- async replication IO and background threads have nothing to replicate in the cluster,
- marking them as non-local here to prevent write set population and replication
+ async replication IO and background threads have nothing to
+ replicate in the cluster, marking them as non-local here to
+ prevent write set population and replication
- async replication SQL thread, applies client transactions from mariadb master
- and will be replicated into cluster
- */
+ async replication SQL thread, applies client transactions from
+ mariadb master and will be replicated into cluster
+ */
return (
thd->system_thread != SYSTEM_THREAD_SLAVE_BACKGROUND &&
thd->system_thread != SYSTEM_THREAD_SLAVE_IO &&
diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc
index 2d3eaa609aa..6aac9ac5962 100644
--- a/sql/signal_handler.cc
+++ b/sql/signal_handler.cc
@@ -32,7 +32,7 @@
#endif
-#ifdef __APPLE__
+#if defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/sysctl.h>
#endif
@@ -54,7 +54,7 @@ extern const char *optimizer_switch_names[];
static inline void output_core_info()
{
/* proc is optional on some BSDs so it can't hurt to look */
-#if defined(HAVE_READLINK) && !defined(__APPLE__)
+#if defined(HAVE_READLINK) && !defined(__APPLE__) && !defined(__FreeBSD__)
char buff[PATH_MAX];
ssize_t len;
int fd;
@@ -85,7 +85,7 @@ static inline void output_core_info()
my_close(fd, MYF(0));
}
#endif
-#elif defined(__APPLE__)
+#elif defined(__APPLE__) || defined(__FreeBSD__)
char buff[PATH_MAX];
size_t len = sizeof(buff);
if (sysctlbyname("kern.corefile", buff, &len, NULL, 0) == 0)
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index c127bad8ef1..6e202185d06 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
- Copyright (c) 2009, 2020, MariaDB
+ Copyright (c) 2009, 2021, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -5486,7 +5486,7 @@ routine_hash_search(const char *host, const char *ip, const char *db,
const char *user, const char *tname, const Sp_handler *sph,
bool exact)
{
- return (GRANT_TABLE*)
+ return (GRANT_NAME*)
name_hash_search(sph->get_priv_hash(),
host, ip, db, user, tname, exact, TRUE);
}
@@ -5500,6 +5500,10 @@ table_hash_search(const char *host, const char *ip, const char *db,
user, tname, exact, FALSE);
}
+static bool column_priv_insert(GRANT_TABLE *grant)
+{
+ return my_hash_insert(&column_priv_hash,(uchar*) grant);
+}
static GRANT_COLUMN *
column_hash_search(GRANT_TABLE *t, const char *cname, size_t length)
@@ -5729,6 +5733,15 @@ static inline void get_grantor(THD *thd, char *grantor)
strxmov(grantor, user, "@", host, NullS);
}
+
+/**
+ Revoke rights from a grant table entry.
+
+ @return 0 ok
+ @return 1 fatal error (error given)
+ @return -1 grant table was revoked
+*/
+
static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
TABLE *table, const LEX_USER &combo,
const char *db, const char *table_name,
@@ -5753,7 +5766,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
{
my_message(ER_PASSWORD_NO_MATCH, ER_THD(thd, ER_PASSWORD_NO_MATCH),
MYF(0)); /* purecov: deadcode */
- DBUG_RETURN(-1); /* purecov: deadcode */
+ DBUG_RETURN(1); /* purecov: deadcode */
}
}
@@ -5784,7 +5797,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0),
combo.user.str, combo.host.str,
table_name); /* purecov: deadcode */
- DBUG_RETURN(-1); /* purecov: deadcode */
+ DBUG_RETURN(1); /* purecov: deadcode */
}
old_row_exists = 0;
restore_record(table,record[1]); // Get saved record
@@ -5846,13 +5859,14 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
else
{
my_hash_delete(&column_priv_hash,(uchar*) grant_table);
+ DBUG_RETURN(-1); // Entry revoked
}
DBUG_RETURN(0);
/* This should never happen */
table_error:
table->file->print_error(error,MYF(0)); /* purecov: deadcode */
- DBUG_RETURN(-1); /* purecov: deadcode */
+ DBUG_RETURN(1); /* purecov: deadcode */
}
@@ -6613,7 +6627,7 @@ static int update_role_table_columns(GRANT_TABLE *merged,
privs, cols);
merged->init_privs= merged->init_cols= NO_ACL;
update_role_columns(merged, first, last);
- my_hash_insert(&column_priv_hash,(uchar*) merged);
+ column_priv_insert(merged);
return 2;
}
else if ((privs | cols) == NO_ACL)
@@ -7078,12 +7092,12 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
result= TRUE;
continue;
}
- grant_table = new GRANT_TABLE (Str->host.str, db_name,
- Str->user.str, table_name,
- rights,
- column_priv);
+ grant_table= new (&grant_memroot) GRANT_TABLE(Str->host.str, db_name,
+ Str->user.str, table_name,
+ rights,
+ column_priv);
if (!grant_table ||
- my_hash_insert(&column_priv_hash,(uchar*) grant_table))
+ column_priv_insert(grant_table))
{
result= TRUE; /* purecov: deadcode */
continue; /* purecov: deadcode */
@@ -7126,22 +7140,24 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
/* TODO(cvicentiu) refactor replace_table_table to use Tables_priv_table
instead of TABLE directly. */
- if (replace_table_table(thd, grant_table, tables.tables_priv_table().table(),
- *Str, db_name, table_name,
- rights, column_priv, revoke_grant))
- {
- /* Should only happen if table is crashed */
- result= TRUE; /* purecov: deadcode */
- }
- else if (tables.columns_priv_table().table_exists())
+ if (tables.columns_priv_table().table_exists())
{
/* TODO(cvicentiu) refactor replace_column_table to use Columns_priv_table
instead of TABLE directly. */
if (replace_column_table(grant_table, tables.columns_priv_table().table(),
*Str, columns, db_name, table_name, rights,
revoke_grant))
- {
result= TRUE;
+ }
+ if (int res= replace_table_table(thd, grant_table,
+ tables.tables_priv_table().table(),
+ *Str, db_name, table_name,
+ rights, column_priv, revoke_grant))
+ {
+ if (res > 0)
+ {
+ /* Should only happen if table is crashed */
+ result= TRUE; /* purecov: deadcode */
}
}
if (Str->is_role())
@@ -7153,9 +7169,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
mysql_mutex_unlock(&acl_cache->lock);
if (!result) /* success */
- {
result= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
- }
mysql_rwlock_unlock(&LOCK_grant);
@@ -7847,7 +7861,7 @@ static bool grant_load(THD *thd,
if (! mem_check->ok())
delete mem_check;
- else if (my_hash_insert(&column_priv_hash,(uchar*) mem_check))
+ else if (column_priv_insert(mem_check))
{
delete mem_check;
goto end_unlock;
@@ -11339,46 +11353,44 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
{
for (counter= 0, revoked= 0 ; counter < column_priv_hash.records ; )
{
- const char *user,*host;
+ const char *user,*host;
GRANT_TABLE *grant_table=
(GRANT_TABLE*) my_hash_element(&column_priv_hash, counter);
user= grant_table->user;
host= safe_str(grant_table->host.hostname);
- if (!strcmp(lex_user->user.str,user) &&
+ if (!strcmp(lex_user->user.str,user) &&
!strcmp(lex_user->host.str, host))
- {
- /* TODO(cvicentiu) refactor replace_db_table to use
- Db_table instead of TABLE directly. */
- if (replace_table_table(thd, grant_table,
- tables.tables_priv_table().table(),
- *lex_user, grant_table->db,
- grant_table->tname, ALL_KNOWN_ACL, NO_ACL, 1))
- {
- result= -1;
- }
- else
- {
- if (!grant_table->cols)
- {
- revoked= 1;
- continue;
- }
- List<LEX_COLUMN> columns;
- /* TODO(cvicentiu) refactor replace_db_table to use
- Db_table instead of TABLE directly. */
- if (!replace_column_table(grant_table,
- tables.columns_priv_table().table(),
- *lex_user, columns, grant_table->db,
- grant_table->tname, ALL_KNOWN_ACL, 1))
- {
- revoked= 1;
- continue;
- }
- result= -1;
- }
- }
- counter++;
+ {
+ List<LEX_COLUMN> columns;
+ /* TODO(cvicentiu) refactor to use
+ Db_table instead of TABLE directly. */
+ if (replace_column_table(grant_table,
+ tables.columns_priv_table().table(),
+ *lex_user, columns,
+ grant_table->db, grant_table->tname,
+ ALL_KNOWN_ACL, 1))
+ result= -1;
+ if (int res= replace_table_table(thd, grant_table,
+ tables.tables_priv_table().table(),
+ *lex_user,
+ grant_table->db, grant_table->tname,
+ ALL_KNOWN_ACL, NO_ACL, 1))
+ {
+ if (res > 0)
+ result= -1;
+ else
+ {
+ /*
+ Entry was deleted. We have to retry the loop as the
+ hash table has probably been reorganized.
+ */
+ revoked= 1;
+ continue;
+ }
+ }
+ }
+ counter++;
}
} while (revoked);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 6f6f9da7486..894f457a83c 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -7875,11 +7875,15 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
DBUG_RETURN(1);
}
tablenr++;
- }
- if (tablenr > MAX_TABLES)
- {
- my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES));
- DBUG_RETURN(1);
+ /*
+ We test the max tables here as we setup_table_map() should not be called
+ with tablenr >= 64
+ */
+ if (tablenr > MAX_TABLES)
+ {
+ my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES));
+ DBUG_RETURN(1);
+ }
}
}
else
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index c7ad6ff90ad..9c1d1560955 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -822,7 +822,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
net.reading_or_writing= 0;
client_capabilities= 0; // minimalistic client
system_thread= NON_SYSTEM_THREAD;
- cleanup_done= free_connection_done= abort_on_warning= 0;
+ cleanup_done= free_connection_done= abort_on_warning= got_warning= 0;
peer_port= 0; // For SHOW PROCESSLIST
transaction= &default_transaction;
transaction->m_pending_rows_event= 0;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 9dddc2fc7a9..c9967b98994 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -6632,11 +6632,13 @@ public:
- The sj-materialization temporary table
- Members needed to make index lookup or a full scan of the temptable.
*/
+class POSITION;
+
class SJ_MATERIALIZATION_INFO : public Sql_alloc
{
public:
/* Optimal join sub-order */
- struct st_position *positions;
+ POSITION *positions;
uint tables; /* Number of tables in the sj-nest */
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 29741cb1adb..ecd5e7c21fe 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2002, 2011, Oracle and/or its affiliates.
- Copyright (c) 2010, 2020, MariaDB
+ Copyright (c) 2010, 2021, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -596,14 +596,20 @@ bool mysql_derived_init(THD *thd, LEX *lex, TABLE_LIST *derived)
}
-/*
+/**
@brief
- Reset the Name_resolution_context::outer_context for all ON expression
- contexts in the given nested join. Do this recursively for all nested joins
- it contains.
+ Prevent name resolution out of context of ON expressions in derived tables
+
+ @param
+ join_list list of tables used in from list of a derived
+
+ @details
+ The function sets the Name_resolution_context::outer_context to NULL
+ for all ON expressions contexts in the given join list. It does this
+ recursively for all nested joins the list contains.
*/
-static void reset_on_clauses_context(List<TABLE_LIST>& join_list)
+static void nullify_outer_context_for_on_clauses(List<TABLE_LIST>& join_list)
{
List_iterator<TABLE_LIST> li(join_list);
while (TABLE_LIST *table= li++)
@@ -611,10 +617,11 @@ static void reset_on_clauses_context(List<TABLE_LIST>& join_list)
if (table->on_context)
table->on_context->outer_context= NULL;
if (table->nested_join)
- reset_on_clauses_context(table->nested_join->join_list);
+ nullify_outer_context_for_on_clauses(table->nested_join->join_list);
}
}
+
/*
Create temporary table structure (but do not fill it)
@@ -783,7 +790,7 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
sl->context.outer_context= 0;
// And for ON clauses, if there are any
- reset_on_clauses_context(*sl->join_list);
+ nullify_outer_context_for_on_clauses(*sl->join_list);
if (!derived->is_with_table_recursive_reference() ||
(!derived->with->with_anchor &&
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 00fa2add88b..ea37b0cb100 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2971,6 +2971,7 @@ void st_select_lex::init_query()
is_service_select= 0;
parsing_place= NO_MATTER;
save_parsing_place= NO_MATTER;
+ context_analysis_place= NO_MATTER;
exclude_from_table_unique_test= no_wrap_view_item= FALSE;
nest_level= 0;
link_next= 0;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index a63b5432936..29884cd843e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -7641,6 +7641,7 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
THD *thd= lex->thd;
bool new_select= select_lex == NULL;
int old_nest_level= lex->current_select->nest_level;
+ Name_resolution_context *curr_context= lex->context_stack.head();
DBUG_ENTER("mysql_new_select");
if (new_select)
@@ -7670,7 +7671,8 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
By default we assume that it is usual subselect and we have outer name
resolution context, if no we will assign it to 0 later
*/
- select_lex->context.outer_context= &select_lex->outer_select()->context;
+
+ select_lex->context.outer_context= curr_context;
}
else
{
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 1a5ba7c320d..74f2e1b33f1 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -1505,7 +1505,7 @@ static bool check_list_constants(THD *thd, partition_info *part_info)
List_iterator<part_elem_value> list_val_it2(part_def->list_val_list);
while ((list_value= list_val_it2++))
{
- calc_value= list_value->value - type_add;
+ calc_value= list_value->value ^ type_add;
part_info->list_array[list_index].list_value= calc_value;
part_info->list_array[list_index++].partition_id= i;
}
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index 8f87d633d19..2974c770252 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -417,6 +417,14 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
{
if (reinit_ssl())
result= 1;
+#ifdef WITH_WSREP
+ if (!result &&
+ WSREP_ON && wsrep_reload_ssl())
+ {
+ my_message(ER_UNKNOWN_ERROR, "Failed to refresh WSREP SSL.", MYF(0));
+ result= 1;
+ }
+#endif
}
if (options & REFRESH_GENERIC)
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 88f3a44358c..849e0943acd 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -358,7 +358,31 @@ bool dbug_user_var_equals_int(THD *thd, const char *name, int value)
}
return FALSE;
}
-#endif
+#endif /* DBUG_OFF */
+
+/*
+ Intialize POSITION structure.
+*/
+
+POSITION::POSITION()
+{
+ table= 0;
+ records_read= cond_selectivity= read_time= 0.0;
+ prefix_record_count= 0.0;
+ key= 0;
+ use_join_buffer= 0;
+ sj_strategy= SJ_OPT_NONE;
+ n_sj_tables= 0;
+ spl_plan= 0;
+ range_rowid_filter_info= 0;
+ ref_depend_map= dups_producing_tables= 0;
+ inner_tables_handled_with_other_sjs= 0;
+ dups_weedout_picker.set_empty();
+ firstmatch_picker.set_empty();
+ loosescan_picker.set_empty();
+ sjmat_picker.set_empty();
+}
+
static void trace_table_dependencies(THD *thd,
JOIN_TAB *join_tabs, uint table_count)
@@ -1604,10 +1628,11 @@ bool JOIN::build_explain()
curr_tab->tracker= thd->lex->explain->get_union(select_nr)->
get_tmptable_read_tracker();
}
- else
+ else if (select_nr < INT_MAX)
{
- curr_tab->tracker= thd->lex->explain->get_select(select_nr)->
- get_using_temporary_read_tracker();
+ Explain_select *tmp= thd->lex->explain->get_select(select_nr);
+ if (tmp)
+ curr_tab->tracker= tmp->get_using_temporary_read_tracker();
}
}
DBUG_RETURN(0);
@@ -4970,6 +4995,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
/* The following should be optimized to only clear critical things */
bzero((void*)stat, sizeof(JOIN_TAB)* table_count);
+
/* Initialize POSITION objects */
for (i=0 ; i <= table_count ; i++)
(void) new ((char*) (join->positions + i)) POSITION;
@@ -16126,7 +16152,7 @@ static void update_const_equal_items(THD *thd, COND *cond, JOIN_TAB *tab,
Item_func::COND_AND_FUNC));
}
else if (cond->type() == Item::FUNC_ITEM &&
- ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
+ ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
{
Item_equal *item_equal= (Item_equal *) cond;
bool contained_const= item_equal->get_const() != NULL;
@@ -16321,7 +16347,7 @@ propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list,
(((Item_func*) cond)->functype() == Item_func::EQ_FUNC ||
((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC))
{
- Item_func_eq *func=(Item_func_eq*) cond;
+ Item_bool_func2 *func= dynamic_cast<Item_bool_func2*>(cond);
Item **args= func->arguments();
bool left_const= args[0]->const_item() && !args[0]->is_expensive();
bool right_const= args[1]->const_item() && !args[1]->is_expensive();
@@ -17263,7 +17289,7 @@ void propagate_new_equalities(THD *thd, Item *cond,
}
}
else if (cond->type() == Item::FUNC_ITEM &&
- ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
+ ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
{
Item_equal *equal_item;
List_iterator<Item_equal> it(*new_equalities);
@@ -17508,7 +17534,7 @@ Item_cond::remove_eq_conds(THD *thd, Item::cond_result *cond_value,
}
else if (and_level &&
new_item->type() == Item::FUNC_ITEM &&
- ((Item_cond*) new_item)->functype() ==
+ ((Item_func*) new_item)->functype() ==
Item_func::MULT_EQUAL_FUNC)
{
li.remove();
@@ -25455,8 +25481,8 @@ copy_fields(TMP_TABLE_PARAM *param)
(*ptr->do_copy)(ptr);
List_iterator_fast<Item> it(param->copy_funcs);
- Item_copy_string *item;
- while ((item = (Item_copy_string*) it++))
+ Item_copy *item;
+ while ((item= (Item_copy*) it++))
item->copy();
}
@@ -29602,6 +29628,7 @@ void unpack_to_base_table_fields(TABLE *table)
}
+
/**
@} (end of group Query_Optimizer)
*/
diff --git a/sql/sql_select.h b/sql/sql_select.h
index cf451979f8e..ff2b24fdbf7 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -700,8 +700,6 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records);
-struct st_position;
-
class Semi_join_strategy_picker
{
public:
@@ -712,7 +710,7 @@ public:
Update internal state after another table has been added to the join
prefix
*/
- virtual void set_from_prev(struct st_position *prev) = 0;
+ virtual void set_from_prev(POSITION *prev) = 0;
virtual bool check_qep(JOIN *join,
uint idx,
@@ -722,7 +720,7 @@ public:
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
- struct st_position *loose_scan_pos) = 0;
+ POSITION *loose_scan_pos) = 0;
virtual void mark_used() = 0;
@@ -753,7 +751,7 @@ public:
first_dupsweedout_table= MAX_TABLES;
is_used= FALSE;
}
- void set_from_prev(struct st_position *prev);
+ void set_from_prev(POSITION *prev);
bool check_qep(JOIN *join,
uint idx,
@@ -763,7 +761,7 @@ public:
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *stratey,
- struct st_position *loose_scan_pos);
+ POSITION *loose_scan_pos);
void mark_used() { is_used= TRUE; }
friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join);
@@ -799,7 +797,7 @@ public:
is_used= FALSE;
}
- void set_from_prev(struct st_position *prev);
+ void set_from_prev(POSITION *prev);
bool check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
@@ -808,7 +806,7 @@ public:
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
- struct st_position *loose_scan_pos);
+ POSITION *loose_scan_pos);
void mark_used() { is_used= TRUE; }
friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join);
@@ -817,6 +815,7 @@ public:
class LooseScan_picker : public Semi_join_strategy_picker
{
+public:
/* The first (i.e. driving) table we're doing loose scan for */
uint first_loosescan_table;
/*
@@ -835,14 +834,13 @@ class LooseScan_picker : public Semi_join_strategy_picker
uint loosescan_parts; /* Number of keyparts to be kept distinct */
bool is_used;
-public:
void set_empty()
{
first_loosescan_table= MAX_TABLES;
is_used= FALSE;
}
- void set_from_prev(struct st_position *prev);
+ void set_from_prev(POSITION *prev);
bool check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
@@ -851,19 +849,19 @@ public:
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
- struct st_position *loose_scan_pos);
+ POSITION *loose_scan_pos);
void mark_used() { is_used= TRUE; }
friend class Loose_scan_opt;
friend void best_access_path(JOIN *join,
JOIN_TAB *s,
table_map remaining_tables,
- const struct st_position *join_positions,
+ const POSITION *join_positions,
uint idx,
bool disable_jbuf,
double record_count,
- struct st_position *pos,
- struct st_position *loose_scan_pos);
+ POSITION *pos,
+ POSITION *loose_scan_pos);
friend bool get_best_combination(JOIN *join);
friend int setup_semijoin_loosescan(JOIN *join);
friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join);
@@ -890,7 +888,7 @@ public:
sjm_scan_last_inner= 0;
is_used= FALSE;
}
- void set_from_prev(struct st_position *prev);
+ void set_from_prev(POSITION *prev);
bool check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
@@ -899,7 +897,7 @@ public:
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
- struct st_position *loose_scan_pos);
+ POSITION *loose_scan_pos);
void mark_used() { is_used= TRUE; }
friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join);
@@ -914,8 +912,9 @@ class Rowid_filter;
Information about a position of table within a join order. Used in join
optimization.
*/
-typedef struct st_position
+class POSITION
{
+public:
/* The table that's put into join order */
JOIN_TAB *table;
@@ -927,7 +926,7 @@ typedef struct st_position
double records_read;
/* The selectivity of the pushed down conditions */
- double cond_selectivity;
+ double cond_selectivity;
/*
Cost accessing the table in course of the entire complete join execution,
@@ -936,8 +935,6 @@ typedef struct st_position
*/
double read_time;
- /* Cumulative cost and record count for the join prefix */
- Cost_estimate prefix_cost;
double prefix_record_count;
/*
@@ -946,29 +943,46 @@ typedef struct st_position
*/
KEYUSE *key;
+ /* Info on splitting plan used at this position */
+ SplM_plan_info *spl_plan;
+
+ /* Cost info for the range filter used at this position */
+ Range_rowid_filter_cost_info *range_rowid_filter_info;
+
/* If ref-based access is used: bitmap of tables this table depends on */
table_map ref_depend_map;
-
+
/*
- TRUE <=> join buffering will be used. At the moment this is based on
- *very* imprecise guesses made in best_access_path().
+ Bitmap of semi-join inner tables that are in the join prefix and for
+ which there's no provision for how to eliminate semi-join duplicates
+ they produce.
*/
- bool use_join_buffer;
-
+ table_map dups_producing_tables;
+
+ table_map inner_tables_handled_with_other_sjs;
+
+ Duplicate_weedout_picker dups_weedout_picker;
+ Firstmatch_picker firstmatch_picker;
+ LooseScan_picker loosescan_picker;
+ Sj_materialization_picker sjmat_picker;
+
+ /* Cumulative cost and record count for the join prefix */
+ Cost_estimate prefix_cost;
+
/*
Current optimization state: Semi-join strategy to be used for this
and preceding join tables.
-
+
Join optimizer sets this for the *last* join_tab in the
- duplicate-generating range. That is, in order to interpret this field,
+ duplicate-generating range. That is, in order to interpret this field,
one needs to traverse join->[best_]positions array from right to left.
When you see a join table with sj_strategy!= SJ_OPT_NONE, some other
- field (depending on the strategy) tells how many preceding positions
+ field (depending on the strategy) tells how many preceding positions
this applies to. The values of covered_preceding_positions->sj_strategy
must be ignored.
*/
enum sj_strategy_enum sj_strategy;
-
+
/*
Valid only after fix_semijoin_strategies_for_picked_join_order() call:
if sj_strategy!=SJ_OPT_NONE, this is the number of subsequent tables that
@@ -977,26 +991,12 @@ typedef struct st_position
uint n_sj_tables;
/*
- Bitmap of semi-join inner tables that are in the join prefix and for
- which there's no provision for how to eliminate semi-join duplicates
- they produce.
+ TRUE <=> join buffering will be used. At the moment this is based on
+ *very* imprecise guesses made in best_access_path().
*/
- table_map dups_producing_tables;
-
- table_map inner_tables_handled_with_other_sjs;
-
- Duplicate_weedout_picker dups_weedout_picker;
- Firstmatch_picker firstmatch_picker;
- LooseScan_picker loosescan_picker;
- Sj_materialization_picker sjmat_picker;
-
- /* Info on splitting plan used at this position */
- SplM_plan_info *spl_plan;
-
- /* Cost info for the range filter used at this position */
- Range_rowid_filter_cost_info *range_rowid_filter_info;
-
-} POSITION;
+ bool use_join_buffer;
+ POSITION();
+};
typedef Bounds_checked_array<Item_null_result*> Item_null_array;
@@ -1592,6 +1592,7 @@ public:
fields_list= fields_arg;
non_agg_fields.empty();
bzero((char*) &keyuse,sizeof(keyuse));
+ having_value= Item::COND_UNDEF;
tmp_table_param.init();
tmp_table_param.end_write_records= HA_POS_ERROR;
rollup.state= ROLLUP::STATE_NONE;
diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc
index f881f6a8cc6..307a0b29c57 100644
--- a/sql/sql_sequence.cc
+++ b/sql/sql_sequence.cc
@@ -727,8 +727,8 @@ longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
if (real_increment > 0)
{
- if (reserved_until + add_to > max_value ||
- reserved_until > max_value - add_to)
+ if (reserved_until > max_value - add_to ||
+ reserved_until + add_to > max_value)
{
reserved_until= max_value + 1;
out_of_values= res_value >= reserved_until;
diff --git a/sql/sql_sequence.h b/sql/sql_sequence.h
index 2d609d8591b..29c589e67cd 100644
--- a/sql/sql_sequence.h
+++ b/sql/sql_sequence.h
@@ -111,8 +111,8 @@ public:
{
if (real_increment > 0)
{
- if (value + real_increment > max_value ||
- value > max_value - real_increment)
+ if (value > max_value - real_increment ||
+ value + real_increment > max_value)
value= max_value + 1;
else
value+= real_increment;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index b1cc696e9fe..38b3d62d539 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -7061,8 +7061,7 @@ static bool store_trigger(THD *thd, Trigger *trigger,
(my_time_t)(trigger->create_time/100));
/* timestamp is with 6 digits */
timestamp.second_part= (trigger->create_time % 100) * 10000;
- ((Field_temporal_with_date*) table->field[16])->store_time_dec(&timestamp,
- 2);
+ table->field[16]->store_time_dec(&timestamp, 2);
}
sql_mode_string_representation(thd, trigger->sql_mode, &sql_mode_rep);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 9869de4ba5e..3643b19f8fb 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -8730,7 +8730,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
flag to allow ALTER TABLE only if the table to be altered is empty.
*/
- if (!alter_ctx->implicit_default_value_error_field &&
+ if (!alter_ctx->implicit_default_value_error_field && !def->field &&
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
def->type_handler()->validate_implicit_default_value(thd, *def))
{
@@ -8988,7 +8988,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
key_parts.push_back(new (thd->mem_root) Key_part_spec(&cfield->field_name,
key_part_length, true),
thd->mem_root);
- if (cfield->invisible < INVISIBLE_SYSTEM)
+ if (!(cfield->invisible == INVISIBLE_SYSTEM && cfield->vers_sys_field()))
user_keyparts= true;
}
if (table->s->tmp_table == NO_TMP_TABLE)
@@ -9000,6 +9000,14 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
(void) delete_statistics_for_index(thd, table, key_info, TRUE);
}
+ if (!user_keyparts && key_parts.elements)
+ {
+ /*
+ If we dropped all user key-parts we also drop implicit system fields.
+ */
+ key_parts.empty();
+ }
+
if (key_parts.elements)
{
KEY_CREATE_INFO key_create_info;
@@ -9036,7 +9044,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
key_type= Key::PRIMARY;
else
key_type= Key::UNIQUE;
- if (dropped_key_part && user_keyparts)
+ if (dropped_key_part)
{
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), dropped_key_part);
if (long_hash_key)
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index 5ea853ade0b..8c9c56f1db7 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -297,7 +297,6 @@ print_plan(JOIN* join, uint idx, double record_count, double read_time,
double current_read_time, const char *info)
{
uint i;
- POSITION pos;
JOIN_TAB *join_table;
JOIN_TAB **plan_nodes;
TABLE* table;
@@ -324,8 +323,8 @@ print_plan(JOIN* join, uint idx, double record_count, double read_time,
fputs(" POSITIONS: ", DBUG_FILE);
for (i= 0; i < idx ; i++)
{
- pos = join->positions[i];
- table= pos.table->table;
+ POSITION *pos= join->positions + i;
+ table= pos->table->table;
if (table)
fputs(table->s->table_name.str, DBUG_FILE);
fputc(' ', DBUG_FILE);
@@ -341,8 +340,8 @@ print_plan(JOIN* join, uint idx, double record_count, double read_time,
fputs("BEST_POSITIONS: ", DBUG_FILE);
for (i= 0; i < idx ; i++)
{
- pos= join->best_positions[i];
- table= pos.table->table;
+ POSITION *pos= join->best_positions + i;
+ table= pos->table->table;
if (table)
fputs(table->s->table_name.str, DBUG_FILE);
fputc(' ', DBUG_FILE);
diff --git a/sql/sql_type_int.h b/sql/sql_type_int.h
index 9fd4f0c46a0..fca00f25448 100644
--- a/sql/sql_type_int.h
+++ b/sql/sql_type_int.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, MariaDB
+/* Copyright (c) 2018, 2021, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -80,16 +80,20 @@ public:
if (is_null() || llshift.is_null())
return Longlong_null();
uint shift= (uint) llshift.value();
- ulonglong res= ((ulonglong) value()) << shift;
- return Longlong_null(shift < sizeof(longlong) * 8 ? (longlong) res : 0);
+ ulonglong res= (shift < sizeof(longlong) * 8)
+ ? ((ulonglong) value()) << shift
+ : 0;
+ return Longlong_null((longlong) res);
}
Longlong_null operator>>(const Longlong_null &llshift) const
{
if (is_null() || llshift.is_null())
return Longlong_null();
uint shift= (uint) llshift.value();
- ulonglong res= ((ulonglong) value()) >> shift;
- return Longlong_null(shift < sizeof(longlong) * 8 ? (longlong) res : 0);
+ ulonglong res= (shift < sizeof(longlong) * 8)
+ ? ((ulonglong) value()) >> shift
+ : 0;
+ return Longlong_null((longlong) res);
}
Longlong_null bit_count() const
{
diff --git a/sql/strfunc.cc b/sql/strfunc.cc
index c488ab1afbb..6c8fd24f780 100644
--- a/sql/strfunc.cc
+++ b/sql/strfunc.cc
@@ -81,14 +81,17 @@ ulonglong find_set(const TYPELIB *lib,
var_len= (uint) (pos - start);
uint find= cs ? find_type2(lib, start, var_len, cs) :
find_type(lib, start, var_len, (bool) 0);
- if (unlikely(!find && *err_len == 0))
+ if (unlikely(!find))
{
- // report the first error with length > 0
- *err_pos= (char*) start;
- *err_len= var_len;
- *set_warning= 1;
+ if (*err_len == 0)
+ {
+ // report the first error with length > 0
+ *err_pos= (char*) start;
+ *err_len= var_len;
+ *set_warning= 1;
+ }
}
- else
+ else if (find <= sizeof(longlong) * 8)
found|= 1ULL << (find - 1);
if (pos >= end)
break;
@@ -402,4 +405,3 @@ const char *flagset_to_string(THD *thd, LEX_CSTRING *result, ulonglong set,
return result->str;
}
-
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index b72d4a3c358..ebec2a203aa 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates.
- Copyright (c) 2012, 2020, MariaDB Corporation.
+ Copyright (c) 2012, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -5051,15 +5051,23 @@ static Sys_var_have Sys_have_symlink(
"--skip-symbolic-links option.",
READ_ONLY GLOBAL_VAR(have_symlink), NO_CMD_LINE);
+#if defined(__SANITIZE_ADDRESS__) || defined(WITH_UBSAN)
+
#ifdef __SANITIZE_ADDRESS__
+#define SANITIZER_MODE "ASAN"
+#else
+#define SANITIZER_MODE "UBSAN"
+#endif /* __SANITIZE_ADDRESS__ */
+
static char *have_sanitizer;
-static Sys_var_charptr_fscs Sys_have_santitizer(
+static Sys_var_charptr Sys_have_santitizer(
"have_sanitizer",
- "If the server is compiled with ASan (Address sanitizer) this will be "
- "set to ASAN",
- READ_ONLY GLOBAL_VAR(have_sanitizer), NO_CMD_LINE,
- DEFAULT("ASAN"));
-#endif
+ "If the server is compiled with sanitize (compiler option), this "
+ "variable is set to the sanitizer mode used. Possible values are "
+ "ASAN (Address sanitizer) or UBSAN (The Undefined Behavior Sanitizer).",
+ READ_ONLY GLOBAL_VAR(have_sanitizer), NO_CMD_LINE,
+ DEFAULT(SANITIZER_MODE));
+#endif /* defined(__SANITIZE_ADDRESS__) || defined(WITH_UBSAN) */
static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type);
diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc
index 1a8b5c471bd..981958abdb2 100644
--- a/sql/temporary_tables.cc
+++ b/sql/temporary_tables.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2016, 2019, MariaDB Corporation.
+ Copyright (c) 2016, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -872,10 +872,12 @@ void THD::restore_tmp_table_share(TMP_TABLE_SHARE *share)
bool THD::has_temporary_tables()
{
DBUG_ENTER("THD::has_temporary_tables");
- bool result= (rgi_slave
- ? (rgi_slave->rli->save_temporary_tables &&
- !rgi_slave->rli->save_temporary_tables->is_empty())
- : (has_thd_temporary_tables()));
+ bool result=
+#ifdef HAVE_REPLICATION
+ rgi_slave ? (rgi_slave->rli->save_temporary_tables &&
+ !rgi_slave->rli->save_temporary_tables->is_empty()) :
+#endif
+ has_thd_temporary_tables();
DBUG_RETURN(result);
}
@@ -1506,12 +1508,14 @@ bool THD::lock_temporary_tables()
DBUG_RETURN(false);
}
+#ifdef HAVE_REPLICATION
if (rgi_slave)
{
mysql_mutex_lock(&rgi_slave->rli->data_lock);
temporary_tables= rgi_slave->rli->save_temporary_tables;
m_tmp_tables_locked= true;
}
+#endif
DBUG_RETURN(m_tmp_tables_locked);
}
@@ -1532,6 +1536,7 @@ void THD::unlock_temporary_tables()
DBUG_VOID_RETURN;
}
+#ifdef HAVE_REPLICATION
if (rgi_slave)
{
rgi_slave->rli->save_temporary_tables= temporary_tables;
@@ -1539,6 +1544,7 @@ void THD::unlock_temporary_tables()
mysql_mutex_unlock(&rgi_slave->rli->data_lock);
m_tmp_tables_locked= false;
}
+#endif
DBUG_VOID_RETURN;
}
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 018b9aab3a7..1618a8b6d50 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1653,6 +1653,32 @@ exit:
return fail;
}
+bool wsrep_reload_ssl()
+{
+ try
+ {
+ std::string opts= Wsrep_server_state::instance().provider().options();
+ if (opts.find("socket.ssl_reload") == std::string::npos)
+ {
+ WSREP_DEBUG("Option `socket.ssl_reload` not found in parameters.");
+ return false;
+ }
+ const std::string reload_ssl_param("socket.ssl_reload=1");
+ enum wsrep::provider::status ret= Wsrep_server_state::instance().provider().options(reload_ssl_param);
+ if (ret)
+ {
+ WSREP_ERROR("Set options returned %d", ret);
+ return true;
+ }
+ return false;
+ }
+ catch (...)
+ {
+ WSREP_ERROR("Failed to get provider options");
+ return true;
+ }
+}
+
/*!
* @param db Database string
* @param table Table string
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 8f20eec0701..0541f2b02ad 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -233,6 +233,7 @@ extern void wsrep_last_committed_id (wsrep_gtid_t* gtid);
extern int wsrep_check_opts();
extern void wsrep_prepend_PATH (const char* path);
extern bool wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* table, wsrep::key_array* keys);
+extern bool wsrep_reload_ssl();
/* Other global variables */
extern wsrep_seqno_t wsrep_locked_seqno;
diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h
index 942363d9886..d79bfa0b39b 100644
--- a/sql/wsrep_trans_observer.h
+++ b/sql/wsrep_trans_observer.h
@@ -466,6 +466,16 @@ static inline void wsrep_close(THD* thd)
DBUG_VOID_RETURN;
}
+static inline void wsrep_cleanup(THD* thd)
+{
+ DBUG_ENTER("wsrep_cleanup");
+ if (thd->wsrep_cs().state() != wsrep::client_state::s_none)
+ {
+ thd->wsrep_cs().cleanup();
+ }
+ DBUG_VOID_RETURN;
+}
+
static inline void
wsrep_wait_rollback_complete_and_acquire_ownership(THD *thd)
{
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index e0b9ac889db..386da305a26 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -25,6 +25,7 @@
#include <my_dir.h>
#include <cstdio>
#include <cstdlib>
+#include "wsrep_trans_observer.h"
ulong wsrep_reject_queries;
@@ -102,7 +103,8 @@ void wsrep_set_wsrep_on(THD* thd)
bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type)
{
- if (var_type == OPT_GLOBAL) {
+ if (var_type == OPT_GLOBAL)
+ {
my_bool saved_wsrep_on= global_system_variables.wsrep_on;
thd->variables.wsrep_on= global_system_variables.wsrep_on;
@@ -110,15 +112,15 @@ bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type)
// If wsrep has not been inited we need to do it now
if (global_system_variables.wsrep_on && wsrep_provider && !wsrep_inited)
{
- char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider
- //when fails
-
+ // wsrep_init() rewrites provide if it fails
+ char* tmp= strdup(wsrep_provider);
mysql_mutex_unlock(&LOCK_global_system_variables);
if (wsrep_init())
{
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), tmp, my_error, "wsrep_init failed");
//rcode= true;
+ saved_wsrep_on= false;
}
free(tmp);
@@ -130,20 +132,69 @@ bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type)
wsrep_set_wsrep_on(thd);
+ if (var_type == OPT_GLOBAL)
+ {
+ if (thd->variables.wsrep_on &&
+ thd->wsrep_cs().state() == wsrep::client_state::s_none)
+ {
+ wsrep_open(thd);
+ wsrep_before_command(thd);
+ }
+ }
+
return false;
}
bool wsrep_on_check(sys_var *self, THD* thd, set_var* var)
{
+ bool new_wsrep_on= (bool)var->save_result.ulonglong_value;
+
if (check_has_super(self, thd, var))
return true;
+ if (new_wsrep_on)
+ {
+ if (!WSREP_PROVIDER_EXISTS)
+ {
+ my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) can't be enabled "
+ "if the wsrep_provider is unset or set to 'none'", MYF(0));
+ return true;
+ }
+
+ if (var->type == OPT_SESSION &&
+ !global_system_variables.wsrep_on)
+ {
+ my_message(ER_WRONG_ARGUMENTS,
+ "Can't enable @@session.wsrep_on, "
+ "while @@global.wsrep_on is disabled", MYF(0));
+ return true;
+ }
+ }
+
if (thd->in_active_multi_stmt_transaction())
{
my_error(ER_CANT_DO_THIS_DURING_AN_TRANSACTION, MYF(0));
return true;
}
+ if (var->type == OPT_GLOBAL)
+ {
+ /*
+ The global value is about to change. Cleanup
+ the transaction state and close the client
+ state. wsrep_on_update() will take care of
+ reopening it should wsrep_on be re-enabled.
+ */
+ if (global_system_variables.wsrep_on && !new_wsrep_on)
+ {
+ wsrep_commit_empty(thd, true);
+ wsrep_after_statement(thd);
+ wsrep_after_command_ignore_result(thd);
+ wsrep_close(thd);
+ wsrep_cleanup(thd);
+ }
+ }
+
return false;
}