summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-08-28 12:22:56 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-08-28 12:22:56 +0300
commit7830fb7f45b3824c0375c00ae2cab357165904cf (patch)
tree730521737fdc48e69f7650819e9a29da6487e1f4 /sql
parentb805ebd7ed49868f83e6fd3fe72a11ddacdce452 (diff)
parent55163ba1bdb1a05daadc66c41c959994231b361c (diff)
downloadmariadb-git-7830fb7f45b3824c0375c00ae2cab357165904cf.tar.gz
Merge 10.2 into 10.3
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h46
-rw-r--r--sql/handler.cc70
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item_cmpfunc.cc19
-rw-r--r--sql/item_cmpfunc.h1
-rw-r--r--sql/item_windowfunc.h2
-rw-r--r--sql/key.cc3
-rw-r--r--sql/multi_range_read.cc13
-rw-r--r--sql/mysqld.cc36
-rw-r--r--sql/opt_range.cc26
-rw-r--r--sql/opt_range.h5
-rw-r--r--sql/opt_range_mrr.cc54
-rw-r--r--sql/protocol.cc8
-rw-r--r--sql/sql_class.h12
-rw-r--r--sql/sql_select.cc13
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/sql_statistics.h2
-rw-r--r--sql/sql_time.cc2
-rw-r--r--sql/sys_vars.cc103
-rw-r--r--sql/table.cc3
-rw-r--r--sql/wsrep_mysqld.h4
-rw-r--r--sql/wsrep_thd.cc22
-rw-r--r--sql/wsrep_var.cc6
23 files changed, 408 insertions, 46 deletions
diff --git a/sql/field.h b/sql/field.h
index 10fe59f224d..0046bc11be2 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1494,6 +1494,17 @@ public:
/* Hash value */
virtual void hash(ulong *nr, ulong *nr2);
+ /**
+ Get the upper limit of the MySQL integral and floating-point type.
+
+ @return maximum allowed value for the field
+ */
+ virtual ulonglong get_max_int_value() const
+ {
+ DBUG_ASSERT(false);
+ return 0ULL;
+ }
+
/**
Checks whether a string field is part of write_set.
@@ -2115,6 +2126,11 @@ public:
*to= *from;
return from + 1;
}
+
+ virtual ulonglong get_max_int_value() const
+ {
+ return unsigned_flag ? 0xFFULL : 0x7FULL;
+ }
};
@@ -2159,6 +2175,10 @@ public:
virtual const uchar *unpack(uchar* to, const uchar *from,
const uchar *from_end, uint param_data)
{ return unpack_int16(to, from, from_end); }
+ virtual ulonglong get_max_int_value() const
+ {
+ return unsigned_flag ? 0xFFFFULL : 0x7FFFULL;
+ }
};
class Field_medium :public Field_int
@@ -2194,6 +2214,10 @@ public:
{
return Field::pack(to, from, max_length);
}
+ virtual ulonglong get_max_int_value() const
+ {
+ return unsigned_flag ? 0xFFFFFFULL : 0x7FFFFFULL;
+ }
};
@@ -2243,6 +2267,10 @@ public:
{
return unpack_int32(to, from, from_end);
}
+ virtual ulonglong get_max_int_value() const
+ {
+ return unsigned_flag ? 0xFFFFFFFFULL : 0x7FFFFFFFULL;
+ }
};
@@ -2295,6 +2323,10 @@ public:
{
return unpack_int64(to, from, from_end);
}
+ virtual ulonglong get_max_int_value() const
+ {
+ return unsigned_flag ? 0xFFFFFFFFFFFFFFFFULL : 0x7FFFFFFFFFFFFFFFULL;
+ }
void set_max();
bool is_max();
@@ -2380,6 +2412,13 @@ public:
uint32 pack_length() const { return sizeof(float); }
uint row_pack_length() const { return pack_length(); }
void sql_type(String &str) const;
+ virtual ulonglong get_max_int_value() const
+ {
+ /*
+ We use the maximum as per IEEE754-2008 standard, 2^24
+ */
+ return 0x1000000ULL;
+ }
private:
int save_field_metadata(uchar *first_byte);
};
@@ -2433,6 +2472,13 @@ public:
uint32 pack_length() const { return sizeof(double); }
uint row_pack_length() const { return pack_length(); }
void sql_type(String &str) const;
+ virtual ulonglong get_max_int_value() const
+ {
+ /*
+ We use the maximum as per IEEE754-2008 standard, 2^53
+ */
+ return 0x20000000000000ULL;
+ }
private:
int save_field_metadata(uchar *first_byte);
};
diff --git a/sql/handler.cc b/sql/handler.cc
index b8a98a0c9f5..ad9adc34a7e 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -3047,9 +3047,15 @@ compute_next_insert_id(ulonglong nr,struct system_variables *variables)
nr= nr + 1; // optimization of the formula below
else
{
+ /*
+ Calculating the number of complete auto_increment_increment extents:
+ */
nr= (((nr+ variables->auto_increment_increment -
variables->auto_increment_offset)) /
(ulonglong) variables->auto_increment_increment);
+ /*
+ Adding an offset to the auto_increment_increment extent boundary:
+ */
nr= (nr* (ulonglong) variables->auto_increment_increment +
variables->auto_increment_offset);
}
@@ -3073,6 +3079,51 @@ void handler::adjust_next_insert_id_after_explicit_value(ulonglong nr)
}
+/** @brief
+ Computes the largest number X:
+ - smaller than or equal to "nr"
+ - of the form: auto_increment_offset + N * auto_increment_increment
+ where N>=0.
+
+ SYNOPSIS
+ prev_insert_id
+ nr Number to "round down"
+ variables variables struct containing auto_increment_increment and
+ auto_increment_offset
+
+ RETURN
+ The number X if it exists, "nr" otherwise.
+*/
+inline ulonglong
+prev_insert_id(ulonglong nr, struct system_variables *variables)
+{
+ if (unlikely(nr < variables->auto_increment_offset))
+ {
+ /*
+ There's nothing good we can do here. That is a pathological case, where
+ the offset is larger than the column's max possible value, i.e. not even
+ the first sequence value may be inserted. User will receive warning.
+ */
+ DBUG_PRINT("info",("auto_increment: nr: %lu cannot honour "
+ "auto_increment_offset: %lu",
+ (ulong) nr, variables->auto_increment_offset));
+ return nr;
+ }
+ if (variables->auto_increment_increment == 1)
+ return nr; // optimization of the formula below
+ /*
+ Calculating the number of complete auto_increment_increment extents:
+ */
+ nr= (((nr - variables->auto_increment_offset)) /
+ (ulonglong) variables->auto_increment_increment);
+ /*
+ Adding an offset to the auto_increment_increment extent boundary:
+ */
+ return (nr * (ulonglong) variables->auto_increment_increment +
+ variables->auto_increment_offset);
+}
+
+
/**
Update the auto_increment field if necessary.
@@ -3309,10 +3360,23 @@ int handler::update_auto_increment()
if (unlikely(tmp)) // Out of range value in store
{
/*
- It's better to return an error here than getting a confusing
- 'duplicate key error' later.
+ first test if the query was aborted due to strict mode constraints
+ */
+ if (thd->killed == KILL_BAD_DATA ||
+ nr > table->next_number_field->get_max_int_value())
+ DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
+
+ /*
+ field refused this value (overflow) and truncated it, use the result of
+ the truncation (which is going to be inserted); however we try to
+ decrease it to honour auto_increment_* variables.
+ That will shift the left bound of the reserved interval, we don't
+ bother shifting the right bound (anyway any other value from this
+ interval will cause a duplicate key).
*/
- result= HA_ERR_AUTOINC_ERANGE;
+ nr= prev_insert_id(table->next_number_field->val_int(), variables);
+ if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
+ nr= table->next_number_field->val_int();
}
if (append)
{
diff --git a/sql/item.cc b/sql/item.cc
index f07e907db09..8fa3a0b741b 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -7794,7 +7794,7 @@ Item_direct_view_ref::derived_grouping_field_transformer_for_where(THD *thd,
void Item_field::print(String *str, enum_query_type query_type)
{
if (field && field->table->const_table &&
- !(query_type & QT_NO_DATA_EXPANSION))
+ !(query_type & (QT_NO_DATA_EXPANSION | QT_VIEW_INTERNAL)))
{
print_value(str);
return;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 37ec33c8358..4a7a44b3399 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -4982,6 +4982,19 @@ Item *Item_cond::build_clone(THD *thd)
}
+bool Item_cond::excl_dep_on_grouping_fields(st_select_lex *sel)
+{
+ List_iterator_fast<Item> li(list);
+ Item *item;
+ while ((item= li++))
+ {
+ if (!item->excl_dep_on_grouping_fields(sel))
+ return false;
+ }
+ return true;
+}
+
+
void Item_cond_and::mark_as_condition_AND_part(TABLE_LIST *embedding)
{
List_iterator<Item> li(list);
@@ -5118,7 +5131,11 @@ longlong Item_func_isnull::val_int()
void Item_func_isnull::print(String *str, enum_query_type query_type)
{
- args[0]->print_parenthesised(str, query_type, precedence());
+ if (const_item() && !args[0]->maybe_null &&
+ !(query_type & (QT_NO_DATA_EXPANSION | QT_VIEW_INTERNAL)))
+ str->append("/*always not null*/ 1");
+ else
+ args[0]->print_parenthesised(str, query_type, precedence());
str->append(STRING_WITH_LEN(" is null"));
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 599d638d601..b34bf1dde19 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -2952,6 +2952,7 @@ public:
Item_transformer transformer, uchar *arg_t);
bool eval_not_null_tables(void *opt_arg);
Item *build_clone(THD *thd);
+ bool excl_dep_on_grouping_fields(st_select_lex *sel);
};
template <template<class> class LI, class T> class Item_equal_iterator;
diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h
index 48851da7d96..b3e23748246 100644
--- a/sql/item_windowfunc.h
+++ b/sql/item_windowfunc.h
@@ -1085,6 +1085,8 @@ public:
case Item_sum::DENSE_RANK_FUNC:
case Item_sum::PERCENT_RANK_FUNC:
case Item_sum::CUME_DIST_FUNC:
+ case Item_sum::LAG_FUNC:
+ case Item_sum::LEAD_FUNC:
case Item_sum::PERCENTILE_CONT_FUNC:
case Item_sum::PERCENTILE_DISC_FUNC:
return true;
diff --git a/sql/key.cc b/sql/key.cc
index 34196a973c5..9ad1103fbe8 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -146,7 +146,8 @@ void key_copy(uchar *to_key, const uchar *from_record, KEY *key_info,
{
key_length-= HA_KEY_BLOB_LENGTH;
length= MY_MIN(key_length, key_part->length);
- uint bytes= key_part->field->get_key_image(to_key, length, Field::itRAW);
+ uint bytes= key_part->field->get_key_image(to_key, length,
+ key_info->flags & HA_SPATIAL ? Field::itMBR : Field::itRAW);
if (with_zerofill && bytes < length)
bzero((char*) to_key + bytes, length - bytes);
to_key+= HA_KEY_BLOB_LENGTH;
diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc
index cf587ef4acd..d6952e71899 100644
--- a/sql/multi_range_read.cc
+++ b/sql/multi_range_read.cc
@@ -18,6 +18,7 @@
#include <my_bit.h>
#include "sql_select.h"
#include "key.h"
+#include "sql_statistics.h"
/****************************************************************************
* Default MRR implementation (MRR to non-MRR converter)
@@ -64,7 +65,12 @@ handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
ha_rows rows, total_rows= 0;
uint n_ranges=0;
THD *thd= table->in_use;
+ uint limit= thd->variables.eq_range_index_dive_limit;
+ bool use_statistics_for_eq_range= eq_ranges_exceeds_limit(seq,
+ seq_init_param,
+ limit);
+
/* Default MRR implementation doesn't need buffer */
*bufsz= 0;
@@ -88,8 +94,15 @@ handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
min_endp= range.start_key.length? &range.start_key : NULL;
max_endp= range.end_key.length? &range.end_key : NULL;
}
+ int keyparts_used= my_count_bits(range.start_key.keypart_map);
if ((range.range_flag & UNIQUE_RANGE) && !(range.range_flag & NULL_RANGE))
rows= 1; /* there can be at most one row */
+ else if (use_statistics_for_eq_range &&
+ !(range.range_flag & NULL_RANGE) &&
+ (range.range_flag & EQ_RANGE) &&
+ table->key_info[keyno].actual_rec_per_key(keyparts_used - 1) > 0.5)
+ rows=
+ (ha_rows) table->key_info[keyno].actual_rec_per_key(keyparts_used - 1);
else
{
if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 1a3ff53be6f..d2084a8d073 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1493,9 +1493,9 @@ static NTService Service; ///< Service object for WinNT
#endif /* __WIN__ */
#ifdef _WIN32
+#include <sddl.h> /* ConvertStringSecurityDescriptorToSecurityDescriptor */
static char pipe_name[512];
static SECURITY_ATTRIBUTES saPipeSecurity;
-static SECURITY_DESCRIPTOR sdPipeDescriptor;
static HANDLE hPipe = INVALID_HANDLE_VALUE;
#endif
@@ -2750,21 +2750,20 @@ static void network_init(void)
strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\",
mysqld_unix_port, NullS);
- bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity));
- bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor));
- if (!InitializeSecurityDescriptor(&sdPipeDescriptor,
- SECURITY_DESCRIPTOR_REVISION))
+ /*
+ Create a security descriptor for pipe.
+ - Use low integrity level, so that it is possible to connect
+ from any process.
+ - Give Everyone read/write access to pipe.
+ */
+ if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
+ "S:(ML;; NW;;; LW) D:(A;; FRFW;;; WD)",
+ SDDL_REVISION_1, &saPipeSecurity.lpSecurityDescriptor, NULL))
{
sql_perror("Can't start server : Initialize security descriptor");
unireg_abort(1);
}
- if (!SetSecurityDescriptorDacl(&sdPipeDescriptor, TRUE, NULL, FALSE))
- {
- sql_perror("Can't start server : Set security descriptor");
- unireg_abort(1);
- }
saPipeSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
- saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
saPipeSecurity.bInheritHandle = FALSE;
if ((hPipe= CreateNamedPipe(pipe_name,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
@@ -4390,6 +4389,20 @@ static int init_common_variables()
DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
server_version, SYSTEM_TYPE,MACHINE_TYPE));
+#ifdef WITH_WSREP
+ /*
+ We need to initialize auxiliary variables, that will be
+ further keep the original values of auto-increment options
+ as they set by the user. These variables used to restore
+ user-defined values of the auto-increment options after
+ setting of the wsrep_auto_increment_control to 'OFF'.
+ */
+ global_system_variables.saved_auto_increment_increment=
+ global_system_variables.auto_increment_increment;
+ global_system_variables.saved_auto_increment_offset=
+ global_system_variables.auto_increment_offset;
+#endif /* WITH_WSREP */
+
#ifdef HAVE_LINUX_LARGE_PAGES
/* Initialize large page size */
if (opt_large_pages)
@@ -7007,6 +7020,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg)
connect->host= my_localhost;
create_new_thread(connect);
}
+ LocalFree(saPipeSecurity.lpSecurityDescriptor);
CloseHandle(connectOverlapped.hEvent);
DBUG_LEAVE;
decrement_handler_count();
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index f10d6dbcfcc..0b29fcd2f11 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -14645,6 +14645,32 @@ void QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths(String *key_names,
}
+/* Check whether the number for equality ranges exceeds the set threshold */
+
+bool eq_ranges_exceeds_limit(RANGE_SEQ_IF *seq, void *seq_init_param,
+ uint limit)
+{
+ KEY_MULTI_RANGE range;
+ range_seq_t seq_it;
+ uint count = 0;
+
+ if (limit == 0)
+ {
+ /* 'Statistics instead of index dives' feature is turned off */
+ return false;
+ }
+ seq_it= seq->init(seq_init_param, 0, 0);
+ while (!seq->next(seq_it, &range))
+ {
+ if ((range.range_flag & EQ_RANGE) && !(range.range_flag & NULL_RANGE))
+ {
+ if (++count >= limit)
+ return true;
+ }
+ }
+ return false;
+}
+
#ifndef DBUG_OFF
static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
diff --git a/sql/opt_range.h b/sql/opt_range.h
index bd85a12d4a1..d5416988b88 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -242,7 +242,7 @@ public:
Number of children of this element in the RB-tree, plus 1 for this
element itself.
*/
- uint16 elements;
+ uint32 elements;
/*
Valid only for elements which are RB-tree roots: Number of times this
RB-tree is referred to (it is referred by SEL_ARG::next_key_part or by
@@ -1724,6 +1724,9 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond);
+bool eq_ranges_exceeds_limit(RANGE_SEQ_IF *seq, void *seq_init_param,
+ uint limit);
+
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond);
#endif
diff --git a/sql/opt_range_mrr.cc b/sql/opt_range_mrr.cc
index 515d94e8748..2981c8182ea 100644
--- a/sql/opt_range_mrr.cc
+++ b/sql/opt_range_mrr.cc
@@ -72,6 +72,7 @@ typedef struct st_sel_arg_range_seq
range_seq_t sel_arg_range_seq_init(void *init_param, uint n_ranges, uint flags)
{
SEL_ARG_RANGE_SEQ *seq= (SEL_ARG_RANGE_SEQ*)init_param;
+ seq->param->range_count=0;
seq->at_start= TRUE;
seq->stack[0].key_tree= NULL;
seq->stack[0].min_key= seq->param->min_key;
@@ -272,25 +273,44 @@ walk_up_n_right:
key_info= NULL;
else
key_info= &seq->param->table->key_info[seq->real_keyno];
-
+
/*
- Conditions below:
- (1) - range analysis is used for estimating condition selectivity
- (2) - This is a unique key, and we have conditions for all its
- user-defined key parts.
- (3) - The table uses extended keys, this key covers all components,
- and we have conditions for all key parts.
+ This is an equality range (keypart_0=X and ... and keypart_n=Z) if
+ (1) - There are no flags indicating open range (e.g.,
+ "keypart_x > y") or GIS.
+ (2) - The lower bound and the upper bound of the range has the
+ same value (min_key == max_key).
*/
- if (!(cur->min_key_flag & ~NULL_RANGE) && !cur->max_key_flag &&
- (!key_info || // (1)
- ((uint)key_tree->part+1 == key_info->user_defined_key_parts && // (2)
- key_info->flags & HA_NOSAME) || // (2)
- ((key_info->flags & HA_EXT_NOSAME) && // (3)
- (uint)key_tree->part+1 == key_info->ext_key_parts) // (3)
- ) &&
- range->start_key.length == range->end_key.length &&
- !memcmp(seq->param->min_key,seq->param->max_key,range->start_key.length))
- range->range_flag= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE);
+ const uint is_open_range =
+ (NO_MIN_RANGE | NO_MAX_RANGE | NEAR_MIN | NEAR_MAX | GEOM_FLAG);
+ const bool is_eq_range_pred =
+ !(cur->min_key_flag & is_open_range) && // (1)
+ !(cur->max_key_flag & is_open_range) && // (1)
+ range->start_key.length == range->end_key.length && // (2)
+ !memcmp(seq->param->min_key, seq->param->max_key, // (2)
+ range->start_key.length);
+
+ if (is_eq_range_pred)
+ {
+ range->range_flag = EQ_RANGE;
+
+ /*
+ Conditions below:
+ (1) - Range analysis is used for estimating condition selectivity
+ (2) - This is a unique key, and we have conditions for all its
+ user-defined key parts.
+ (3) - The table uses extended keys, this key covers all components,
+ and we have conditions for all key parts.
+ */
+ if (
+ !key_info || // (1)
+ ((uint)key_tree->part+1 == key_info->user_defined_key_parts && // (2)
+ key_info->flags & HA_NOSAME) || // (2)
+ ((key_info->flags & HA_EXT_NOSAME) && // (3)
+ (uint)key_tree->part+1 == key_info->ext_key_parts) // (3)
+ )
+ range->range_flag |= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE);
+ }
if (seq->param->is_ror_scan)
{
diff --git a/sql/protocol.cc b/sql/protocol.cc
index d29d2fe853d..c4c243ea166 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -711,7 +711,7 @@ uchar *net_store_data(uchar *to, const uchar *from, size_t length)
uchar *net_store_data(uchar *to,int32 from)
{
- char buff[20];
+ char buff[22];
uint length=(uint) (int10_to_str(from,buff,10)-buff);
to=net_store_length_fast(to,length);
memcpy(to,buff,length);
@@ -1137,7 +1137,7 @@ bool Protocol_text::store_tiny(longlong from)
DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
field_pos++;
#endif
- char buff[20];
+ char buff[22];
return net_store_data((uchar*) buff,
(size_t) (int10_to_str((int) from, buff, -10) - buff));
}
@@ -1151,7 +1151,7 @@ bool Protocol_text::store_short(longlong from)
field_types[field_pos] == MYSQL_TYPE_SHORT);
field_pos++;
#endif
- char buff[20];
+ char buff[22];
return net_store_data((uchar*) buff,
(size_t) (int10_to_str((int) from, buff, -10) -
buff));
@@ -1166,7 +1166,7 @@ bool Protocol_text::store_long(longlong from)
field_types[field_pos] == MYSQL_TYPE_LONG);
field_pos++;
#endif
- char buff[20];
+ char buff[22];
return net_store_data((uchar*) buff,
(size_t) (int10_to_str((long int)from, buff,
(from <0)?-10:10)-buff));
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 026ef4d1118..e2aed01ef3b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -581,6 +581,18 @@ typedef struct system_variables
ha_rows max_join_size;
ha_rows expensive_subquery_limit;
ulong auto_increment_increment, auto_increment_offset;
+#ifdef WITH_WSREP
+ /*
+ Variables with stored values of the auto_increment_increment
+ and auto_increment_offset options that are will be needed when
+ wsrep_auto_increment_control will be set to 'OFF', because the
+ setting it to 'ON' leads to overwriting of the original values
+ (which are set by the user) by calculated values (which are
+ based on the cluster's size):
+ */
+ ulong saved_auto_increment_increment, saved_auto_increment_offset;
+#endif /* WITH_WSREP */
+ uint eq_range_index_dive_limit;
ulong column_compression_zlib_strategy;
ulong lock_wait_timeout;
ulong join_cache_level;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index c3df580f1b7..7ff29bb081c 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1682,8 +1682,7 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
}
- if (thd->lex->sql_command == SQLCOM_SELECT &&
- optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
+ if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
{
TABLE_LIST *tbl;
List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
@@ -1880,6 +1879,14 @@ JOIN::optimize_inner()
error= 1;
DBUG_RETURN(1);
}
+ if (!group_list)
+ {
+ /* The output has only one row */
+ order=0;
+ simple_order=1;
+ group_optimized_away= 1;
+ select_distinct=0;
+ }
}
/* Calculate how to do the join */
@@ -6522,7 +6529,7 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab)
Item_field *cur_item;
key_map possible_keys(0);
- if (join->group_list || join->simple_group)
+ if (join->group_list)
{ /* Collect all query fields referenced in the GROUP clause. */
for (cur_group= join->group_list; cur_group; cur_group= cur_group->next)
(*cur_group->item)->walk(&Item::collect_item_field_processor, 0,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 6feaafbe0c7..33b28afd734 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2610,7 +2610,7 @@ static int show_create_view(THD *thd, TABLE_LIST *table, String *buff)
We can't just use table->query, because our SQL_MODE may trigger
a different syntax, like when ANSI_QUOTES is defined.
*/
- table->view->unit.print(buff, enum_query_type(QT_ORDINARY |
+ table->view->unit.print(buff, enum_query_type(QT_VIEW_INTERNAL |
QT_ITEM_ORIGINAL_FUNC_NULLIF));
if (table->with_check != VIEW_CHECK_NONE)
diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h
index c2700eaee41..714a9075f92 100644
--- a/sql/sql_statistics.h
+++ b/sql/sql_statistics.h
@@ -21,7 +21,7 @@ enum enum_use_stat_tables_mode
{
NEVER,
COMPLEMENTARY,
- PEFERABLY,
+ PREFERABLY,
} Use_stat_tables_mode;
typedef
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index c748cd54415..35ef1e50c36 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -264,7 +264,7 @@ bool get_date_from_daynr(long daynr,uint *ret_year,uint *ret_month,
ulong convert_period_to_month(ulong period)
{
ulong a,b;
- if (period == 0)
+ if (period == 0 || period > 999912)
return 0L;
if ((a=period/100) < YY_PART_YEAR)
a+=2000;
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 8858259c863..4cf62d457df 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -349,13 +349,56 @@ static Sys_var_long Sys_pfs_connect_attrs_size(
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
+#ifdef WITH_WSREP
+
+/*
+ We need to keep the original values set by the user, as they will
+ be lost if wsrep_auto_increment_control set to 'ON':
+*/
+static bool update_auto_increment_increment (sys_var *self, THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.saved_auto_increment_increment=
+ global_system_variables.auto_increment_increment;
+ else
+ thd->variables.saved_auto_increment_increment=
+ thd->variables.auto_increment_increment;
+ return false;
+}
+
+#endif /* WITH_WSREP */
+
static Sys_var_ulong Sys_auto_increment_increment(
"auto_increment_increment",
"Auto-increment columns are incremented by this",
SESSION_VAR(auto_increment_increment),
CMD_LINE(OPT_ARG),
VALID_RANGE(1, 65535), DEFAULT(1), BLOCK_SIZE(1),
+#ifdef WITH_WSREP
+ NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(0),
+ ON_UPDATE(update_auto_increment_increment));
+#else
NO_MUTEX_GUARD, IN_BINLOG);
+#endif /* WITH_WSREP */
+
+#ifdef WITH_WSREP
+
+/*
+ We need to keep the original values set by the user, as they will
+ be lost if wsrep_auto_increment_control set to 'ON':
+*/
+static bool update_auto_increment_offset (sys_var *self, THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.saved_auto_increment_offset=
+ global_system_variables.auto_increment_offset;
+ else
+ thd->variables.saved_auto_increment_offset=
+ thd->variables.auto_increment_offset;
+ return false;
+}
+
+#endif /* WITH_WSREP */
static Sys_var_ulong Sys_auto_increment_offset(
"auto_increment_offset",
@@ -364,7 +407,12 @@ static Sys_var_ulong Sys_auto_increment_offset(
SESSION_VAR(auto_increment_offset),
CMD_LINE(OPT_ARG),
VALID_RANGE(1, 65535), DEFAULT(1), BLOCK_SIZE(1),
+#ifdef WITH_WSREP
+ NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(0),
+ ON_UPDATE(update_auto_increment_offset));
+#else
NO_MUTEX_GUARD, IN_BINLOG);
+#endif /* WITH_WSREP */
static Sys_var_mybool Sys_automatic_sp_privileges(
"automatic_sp_privileges",
@@ -2671,6 +2719,16 @@ static Sys_var_ulong Sys_div_precincrement(
SESSION_VAR(div_precincrement), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0, DECIMAL_MAX_SCALE), DEFAULT(4), BLOCK_SIZE(1));
+static Sys_var_uint Sys_eq_range_index_dive_limit(
+ "eq_range_index_dive_limit",
+ "The optimizer will use existing index statistics instead of "
+ "doing index dives for equality ranges if the number of equality "
+ "ranges for the index is larger than or equal to this number. "
+ "If set to 0, index dives are always used.",
+ SESSION_VAR(eq_range_index_dive_limit), CMD_LINE(REQUIRED_ARG),
+ VALID_RANGE(0, UINT_MAX32), DEFAULT(0),
+ BLOCK_SIZE(1));
+
static Sys_var_ulong Sys_range_alloc_block_size(
"range_alloc_block_size",
"Allocation block size for storing ranges during optimization",
@@ -5325,11 +5383,54 @@ static Sys_var_ulong Sys_wsrep_retry_autocommit(
SESSION_VAR(wsrep_retry_autocommit), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0, 10000), DEFAULT(1), BLOCK_SIZE(1));
+static bool update_wsrep_auto_increment_control (sys_var *self, THD *thd, enum_var_type type)
+{
+ if (wsrep_auto_increment_control)
+ {
+ /*
+ The variables that control auto increment shall be calculated
+ automaticaly based on the size of the cluster. This usually done
+ within the wsrep_view_handler_cb callback. However, if the user
+ manually sets the value of wsrep_auto_increment_control to 'ON',
+ then we should to re-calculate these variables again (because
+ these values may be required before wsrep_view_handler_cb will
+ be re-invoked, which is rarely invoked if the cluster stays in
+ the stable state):
+ */
+ global_system_variables.auto_increment_increment=
+ wsrep_cluster_size ? wsrep_cluster_size : 1;
+ global_system_variables.auto_increment_offset=
+ wsrep_local_index >= 0 ? wsrep_local_index + 1 : 1;
+ thd->variables.auto_increment_increment=
+ global_system_variables.auto_increment_increment;
+ thd->variables.auto_increment_offset=
+ global_system_variables.auto_increment_offset;
+ }
+ else
+ {
+ /*
+ We must restore the last values of the variables that
+ are explicitly specified by the user:
+ */
+ global_system_variables.auto_increment_increment=
+ global_system_variables.saved_auto_increment_increment;
+ global_system_variables.auto_increment_offset=
+ global_system_variables.saved_auto_increment_offset;
+ thd->variables.auto_increment_increment=
+ thd->variables.saved_auto_increment_increment;
+ thd->variables.auto_increment_offset=
+ thd->variables.saved_auto_increment_offset;
+ }
+ return false;
+}
+
static Sys_var_mybool Sys_wsrep_auto_increment_control(
"wsrep_auto_increment_control", "To automatically control the "
"assignment of autoincrement variables",
GLOBAL_VAR(wsrep_auto_increment_control),
- CMD_LINE(OPT_ARG), DEFAULT(TRUE));
+ CMD_LINE(OPT_ARG), DEFAULT(TRUE),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
+ ON_UPDATE(update_wsrep_auto_increment_control));
static Sys_var_mybool Sys_wsrep_drupal_282555_workaround(
"wsrep_drupal_282555_workaround", "Enable a workaround to handle the "
diff --git a/sql/table.cc b/sql/table.cc
index 4aef9aad4fc..5eb789b779b 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -6900,7 +6900,10 @@ void TABLE::mark_columns_used_by_virtual_fields(void)
for (uint i= 0 ; i < s->fields ; i++)
{
if (bitmap_is_set(&tmp_set, i))
+ {
+ s->field[i]->flags|= PART_INDIRECT_KEY_FLAG;
field[i]->flags|= PART_INDIRECT_KEY_FLAG;
+ }
}
bitmap_clear_all(&tmp_set);
}
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 699a4daf27a..d7b490d879e 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -160,6 +160,10 @@ extern "C" query_id_t wsrep_thd_query_id(THD *thd);
extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
+extern "C" void wsrep_thd_auto_increment_variables(THD*,
+ unsigned long long *offset,
+ unsigned long long *increment);
+
extern void wsrep_close_client_connections(my_bool wait_to_end);
extern int wsrep_wait_committing_connections_close(int wait_time);
extern void wsrep_close_applier(THD *thd);
diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc
index ce6d9688cb3..a83ea4ce1c6 100644
--- a/sql/wsrep_thd.cc
+++ b/sql/wsrep_thd.cc
@@ -676,3 +676,25 @@ bool wsrep_thd_has_explicit_locks(THD *thd)
assert(thd);
return thd->mdl_context.has_explicit_locks();
}
+
+/*
+ Get auto increment variables for THD. Use global settings for
+ applier threads.
+ */
+extern "C"
+void wsrep_thd_auto_increment_variables(THD* thd,
+ unsigned long long* offset,
+ unsigned long long* increment)
+{
+ if (thd->wsrep_exec_mode == REPL_RECV &&
+ thd->wsrep_conflict_state != REPLAYING)
+ {
+ *offset= global_system_variables.auto_increment_offset;
+ *increment= global_system_variables.auto_increment_increment;
+ }
+ else
+ {
+ *offset= thd->variables.auto_increment_offset;
+ *increment= thd->variables.auto_increment_increment;
+ }
+}
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index aaae487b2e2..bc43b844a35 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -619,6 +619,12 @@ bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var)
return true;
}
+ if (thd->global_read_lock.is_acquired())
+ {
+ my_message (ER_CANNOT_USER, "Global read lock acquired. Can't set 'wsrep_desync'", MYF(0));
+ return true;
+ }
+
bool new_wsrep_desync= (bool) var->save_result.ulonglong_value;
if (wsrep_desync == new_wsrep_desync) {
if (new_wsrep_desync) {