summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-09-11 21:31:03 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-09-11 21:31:03 +0300
commit1bf3e8ab43e982953d7534db902020d321364afb (patch)
tree7de4aaac9f947d4302cd4edbb5677da8917ade71 /sql
parentf5bebaf1d6a0ff2fca9b342ed5910b9d34a276bb (diff)
parent4901f31c13f91e130f077f2f77b32c40b0036e32 (diff)
downloadmariadb-git-1bf3e8ab43e982953d7534db902020d321364afb.tar.gz
Merge 10.3 into 10.4
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc8
-rw-r--r--sql/field.h1
-rw-r--r--sql/filesort.cc4
-rw-r--r--sql/handler.cc43
-rw-r--r--sql/handler.h1
-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.cc22
-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.h6
-rw-r--r--sql/sql_delete.cc14
-rw-r--r--sql/sql_lex.cc6
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--sql/sql_select.cc18
-rw-r--r--sql/sql_sequence.cc5
-rw-r--r--sql/sql_show.cc52
-rw-r--r--sql/sql_statistics.h2
-rw-r--r--sql/sql_time.cc2
-rw-r--r--sql/sql_tvc.h2
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_yacc.yy42
-rw-r--r--sql/sql_yacc_ora.yy42
-rw-r--r--sql/sys_vars.cc10
-rw-r--r--sql/table.cc5
-rw-r--r--sql/wsrep_mysqld.h1
-rw-r--r--sql/wsrep_sst.cc50
-rw-r--r--sql/wsrep_var.cc10
34 files changed, 413 insertions, 69 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 549fc157da9..743f12f3cc9 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -7120,7 +7120,9 @@ int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr)
void Field_string::sort_string(uchar *to,uint length)
{
- IF_DBUG(size_t tmp= ,)
+#ifdef DBUG_ASSERT_EXISTS
+ size_t tmp=
+#endif
field_charset->coll->strnxfrm(field_charset,
to, length,
char_length() *
@@ -7526,7 +7528,7 @@ void Field_varstring::sort_string(uchar *to,uint length)
length-= length_bytes;
}
-#ifndef DBUG_OFF
+#ifdef DBUG_ASSERT_EXISTS
size_t rc=
#endif
field_charset->coll->strnxfrm(field_charset, to, length,
@@ -8394,7 +8396,7 @@ void Field_blob::sort_string(uchar *to,uint length)
store_bigendian(buf.length(), to + length, packlength);
}
-#ifndef DBUG_OFF
+#ifdef DBUG_ASSERT_EXISTS
size_t rc=
#endif
field_charset->coll->strnxfrm(field_charset, to, length, length,
diff --git a/sql/field.h b/sql/field.h
index 8b080a0d06f..ed61afe01eb 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -2390,7 +2390,6 @@ public:
{
return unpack_int64(to, from, from_end);
}
-
void set_max();
bool is_max();
};
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 1855430b944..6901cee043f 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -1004,7 +1004,9 @@ Type_handler_string_result::make_sort_key(uchar *to, Item *item,
if (use_strnxfrm(cs))
{
- IF_DBUG(size_t tmp_length= ,)
+#ifdef DBUG_ASSERT_EXISTS
+ size_t tmp_length=
+#endif
cs->coll->strnxfrm(cs, to, sort_field->length,
item->max_char_length() *
cs->strxfrm_multiply,
diff --git a/sql/handler.cc b/sql/handler.cc
index e45607cad66..943722af3b3 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -74,7 +74,7 @@ KEY_CREATE_INFO default_key_create_info=
ulong total_ha= 0;
/* number of storage engines (from handlertons[]) that support 2pc */
ulong total_ha_2pc= 0;
-#ifndef DBUG_OFF
+#ifdef DBUG_ASSERT_EXISTS
/*
Number of non-mandatory 2pc handlertons whose initialization failed
to estimate total_ha_2pc value under supposition of the failures
@@ -661,7 +661,7 @@ err_deinit:
(void) plugin->plugin->deinit(NULL);
err:
-#ifndef DBUG_OFF
+#ifdef DBUG_ASSERT_EXISTS
if (hton->prepare && hton->state == SHOW_OPTION_YES)
failed_ha_2pc++;
#endif
@@ -3073,6 +3073,45 @@ 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
+ nr= (((nr - variables->auto_increment_offset)) /
+ (ulonglong) variables->auto_increment_increment);
+ return (nr * (ulonglong) variables->auto_increment_increment +
+ variables->auto_increment_offset);
+}
+
+
/**
Update the auto_increment field if necessary.
diff --git a/sql/handler.h b/sql/handler.h
index f1080d56bb9..68a54cc207a 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -950,6 +950,7 @@ enum enum_schema_tables
SCH_ALL_PLUGINS,
SCH_APPLICABLE_ROLES,
SCH_CHARSETS,
+ SCH_CHECK_CONSTRAINTS,
SCH_COLLATIONS,
SCH_COLLATION_CHARACTER_SET_APPLICABILITY,
SCH_COLUMNS,
diff --git a/sql/item.cc b/sql/item.cc
index 7171a95c21d..f6198e1df68 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -7637,7 +7637,7 @@ Item_direct_view_ref::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 189b315ede6..fb6d99b9498 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -4984,6 +4984,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);
@@ -5120,7 +5133,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 e58644c1699..db1075b1936 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -2964,6 +2964,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 3ed6846bde9..acb7532f922 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1476,9 +1476,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
@@ -2711,21 +2711,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,
@@ -6965,6 +6964,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 107c0d8ed89..7faae008dab 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -14829,6 +14829,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 29004fe24e4..7eee9283989 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 64ce52049d0..30622fde577 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -581,6 +581,7 @@ typedef struct system_variables
ha_rows max_join_size;
ha_rows expensive_subquery_limit;
ulong auto_increment_increment, auto_increment_offset;
+ uint eq_range_index_dive_limit;
ulong column_compression_zlib_strategy;
ulong lock_wait_timeout;
ulong join_cache_level;
@@ -5023,7 +5024,8 @@ protected:
SELECT_LEX_UNIT *unit;
/* Something used only by the parser: */
public:
- select_result(THD *thd_arg): select_result_sink(thd_arg) {}
+ ha_rows est_records; /* estimated number of records in the result */
+ select_result(THD *thd_arg): select_result_sink(thd_arg), est_records(0) {}
void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; }
virtual ~select_result() {};
/**
@@ -5595,7 +5597,6 @@ public:
TMP_TABLE_PARAM tmp_table_param;
int write_err; /* Error code from the last send_data->ha_write_row call. */
TABLE *table;
- ha_rows records;
select_unit(THD *thd_arg):
select_result_interceptor(thd_arg),
@@ -5633,7 +5634,6 @@ public:
curr_sel= UINT_MAX;
step= UNION_TYPE;
write_err= 0;
- records= 0;
}
void change_select();
};
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 80ee4a22419..326f2a64bbe 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -323,12 +323,16 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
DBUG_ASSERT(table);
DBUG_ASSERT(!conds || thd->stmt_arena->is_stmt_execute());
- if (select_lex->vers_setup_conds(thd, table_list))
- DBUG_RETURN(TRUE);
- DBUG_ASSERT(!conds);
- conds= table_list->on_expr;
- table_list->on_expr= NULL;
+ // conds could be cached from previous SP call
+ if (!conds)
+ {
+ if (select_lex->vers_setup_conds(thd, table_list))
+ DBUG_RETURN(TRUE);
+
+ conds= table_list->on_expr;
+ table_list->on_expr= NULL;
+ }
}
if (mysql_handle_list_of_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT))
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 20b1eb413cf..bff6dfb0e05 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -4765,18 +4765,18 @@ void SELECT_LEX::increase_derived_records(ha_rows records)
return;
}
- select_unit *result= (select_unit*)unit->result;
+ select_result *result= unit->result;
switch (linkage)
{
case INTERSECT_TYPE:
// result of intersect can't be more then one of components
- set_if_smaller(result->records, records);
+ set_if_smaller(result->est_records, records);
case EXCEPT_TYPE:
// in worse case none of record will be removed
break;
default:
// usual UNION
- result->records+= records;
+ result->est_records+= records;
break;
}
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 147147f0191..201cb4f1dbe 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2565,6 +2565,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
case SCH_TABLE_NAMES:
case SCH_TABLES:
+ case SCH_CHECK_CONSTRAINTS:
case SCH_VIEWS:
case SCH_TRIGGERS:
case SCH_EVENTS:
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 7a8631a4ac1..3b927510c80 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1701,8 +1701,7 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
}
- if (thd->lex->sql_command == SQLCOM_SELECT &&
- optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
+ if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
{
TABLE_LIST *tbl;
List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
@@ -1727,8 +1726,7 @@ JOIN::optimize_inner()
DBUG_RETURN(TRUE);
}
- 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);
@@ -1925,6 +1923,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 */
@@ -3811,7 +3817,7 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
If there is SELECT in this statement with the same number it must be the
same SELECT
*/
- DBUG_ASSERT(select_lex->select_number == UINT_MAX ||
+ DBUG_SLOW_ASSERT(select_lex->select_number == UINT_MAX ||
select_lex->select_number == INT_MAX ||
!output ||
!output->get_select(select_lex->select_number) ||
@@ -6577,7 +6583,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_sequence.cc b/sql/sql_sequence.cc
index baaa4571c9e..1ed0bb38e64 100644
--- a/sql/sql_sequence.cc
+++ b/sql/sql_sequence.cc
@@ -542,7 +542,8 @@ void sequence_definition::adjust_values(longlong next_value)
if ((real_increment= global_system_variables.auto_increment_increment)
!= 1)
- offset= global_system_variables.auto_increment_offset;
+ offset= (global_system_variables.auto_increment_offset %
+ global_system_variables.auto_increment_increment);
/*
Ensure that next_free_value has the right offset, so that we
@@ -564,7 +565,7 @@ void sequence_definition::adjust_values(longlong next_value)
else
{
next_free_value+= to_add;
- DBUG_ASSERT(next_free_value % real_increment == offset);
+ DBUG_ASSERT(llabs(next_free_value % real_increment) == offset);
}
}
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index e8f42003691..ea6ef7d86fb 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2616,7 +2616,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)
@@ -6795,6 +6795,42 @@ store_constraints(THD *thd, TABLE *table, const LEX_CSTRING *db_name,
return schema_table_store_record(thd, table);
}
+static int get_check_constraints_record(THD *thd, TABLE_LIST *tables,
+ TABLE *table, bool res,
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
+{
+ DBUG_ENTER("get_check_constraints_record");
+ if (res)
+ {
+ if (thd->is_error())
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
+ thd->get_stmt_da()->sql_errno(),
+ thd->get_stmt_da()->message());
+ thd->clear_error();
+ DBUG_RETURN(0);
+ }
+ else if (!tables->view)
+ {
+ if (tables->table->s->table_check_constraints)
+ {
+ for (uint i= 0; i < tables->table->s->table_check_constraints; i++)
+ {
+ StringBuffer<MAX_FIELD_WIDTH> str(system_charset_info);
+ Virtual_column_info *check= tables->table->check_constraints[i];
+ restore_record(table, s->default_values);
+ table->field[0]->store(STRING_WITH_LEN("def"), system_charset_info);
+ table->field[1]->store(db_name->str, db_name->length, system_charset_info);
+ table->field[2]->store(check->name.str, check->name.length, system_charset_info);
+ table->field[3]->store(table_name->str, table_name->length, system_charset_info);
+ check->print(&str);
+ table->field[4]->store(str.ptr(), str.length(), system_charset_info);
+ schema_table_store_record(thd, table);
+ }
+ }
+ }
+ DBUG_RETURN(res);
+}
static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
@@ -9715,6 +9751,18 @@ ST_FIELD_INFO spatial_ref_sys_fields_info[]=
#endif /*HAVE_SPATIAL*/
+ST_FIELD_INFO check_constraints_fields_info[]=
+{
+ {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+ {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
+ OPEN_FULL_TABLE},
+ {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
+ OPEN_FULL_TABLE},
+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+ {"CHECK_CLAUSE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
+ OPEN_FULL_TABLE},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
+};
/*
Description of ST_FIELD_INFO in table.h
@@ -9730,6 +9778,8 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_schema_applicable_roles, 0, 0, -1, -1, 0, 0},
{"CHARACTER_SETS", charsets_fields_info, 0,
fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0},
+ {"CHECK_CONSTRAINTS", check_constraints_fields_info, 0,
+ get_all_tables, 0, get_check_constraints_record, 1, 2, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
{"COLLATIONS", collation_fields_info, 0,
fill_schema_collation, make_old_format, 0, -1, -1, 0, 0},
{"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info,
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 430eb192052..c1300c78ad9 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/sql_tvc.h b/sql/sql_tvc.h
index 420311cccb2..128cc883dd8 100644
--- a/sql/sql_tvc.h
+++ b/sql/sql_tvc.h
@@ -50,6 +50,8 @@ public:
have_query_plan(QEP_NOT_PRESENT_YET), explain(0),
select_options(select_options_arg)
{ };
+
+ ha_rows get_records() { return lists_of_values.elements; }
bool prepare(THD *thd_arg, SELECT_LEX *sl,
select_result *tmp_result,
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index be987b82cba..29ea427842f 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -1321,6 +1321,8 @@ bool st_select_lex_unit::optimize()
thd->lex->current_select= lex_select_save;
DBUG_RETURN(TRUE);
}
+ if (derived)
+ sl->increase_derived_records(sl->tvc->get_records());
continue;
}
thd->lex->current_select= sl;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index cf894325ba5..cc22908ec4b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1996,6 +1996,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
preload_list preload_list_or_parts preload_keys preload_keys_parts
select_item_list select_item values_list no_braces
delete_limit_clause fields opt_values values
+ no_braces_with_names opt_values_with_names values_with_names
procedure_list procedure_list2 procedure_item
field_def handler opt_generated_always
opt_ignore opt_column opt_restrict
@@ -13156,7 +13157,7 @@ insert_values:
values_list:
values_list ',' no_braces
- | no_braces
+ | no_braces_with_names
;
ident_eq_list:
@@ -13209,11 +13210,31 @@ no_braces:
}
;
+no_braces_with_names:
+ '('
+ {
+ if (unlikely(!(Lex->insert_list= new (thd->mem_root) List_item)))
+ MYSQL_YYABORT;
+ }
+ opt_values_with_names ')'
+ {
+ LEX *lex=Lex;
+ if (unlikely(lex->many_values.push_back(lex->insert_list,
+ thd->mem_root)))
+ MYSQL_YYABORT;
+ }
+ ;
+
opt_values:
/* empty */ {}
| values
;
+opt_values_with_names:
+ /* empty */ {}
+ | values_with_names
+ ;
+
values:
values ',' expr_or_default
{
@@ -13227,6 +13248,25 @@ values:
}
;
+values_with_names:
+ values_with_names ',' remember_name expr_or_default remember_end
+ {
+ if (unlikely(Lex->insert_list->push_back($4, thd->mem_root)))
+ MYSQL_YYABORT;
+ // give some name in case of using in table value constuctor (TVC)
+ if (!$4->name.str || $4->name.str == item_empty_name)
+ $4->set_name(thd, $3, (uint) ($5 - $3), thd->charset());
+ }
+ | remember_name expr_or_default remember_end
+ {
+ if (unlikely(Lex->insert_list->push_back($2, thd->mem_root)))
+ MYSQL_YYABORT;
+ // give some name in case of using in table value constuctor (TVC)
+ if (!$2->name.str || $2->name.str == item_empty_name)
+ $2->set_name(thd, $1, (uint) ($3 - $1), thd->charset());
+ }
+ ;
+
expr_or_default:
expr { $$= $1;}
| DEFAULT
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index ef12b9c0c53..d4838590075 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -1487,6 +1487,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
assign_to_keycache_parts
preload_list preload_list_or_parts preload_keys preload_keys_parts
select_item_list select_item values_list no_braces
+ no_braces_with_names opt_values_with_names values_with_names
delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
field_def handler opt_generated_always
@@ -13384,7 +13385,7 @@ insert_values:
values_list:
values_list ',' no_braces
- | no_braces
+ | no_braces_with_names
;
ident_eq_list:
@@ -13437,11 +13438,31 @@ no_braces:
}
;
+no_braces_with_names:
+ '('
+ {
+ if (unlikely(!(Lex->insert_list= new (thd->mem_root) List_item)))
+ MYSQL_YYABORT;
+ }
+ opt_values_with_names ')'
+ {
+ LEX *lex=Lex;
+ if (unlikely(lex->many_values.push_back(lex->insert_list,
+ thd->mem_root)))
+ MYSQL_YYABORT;
+ }
+ ;
+
opt_values:
/* empty */ {}
| values
;
+opt_values_with_names:
+ /* empty */ {}
+ | values_with_names
+ ;
+
values:
values ',' expr_or_default
{
@@ -13455,6 +13476,25 @@ values:
}
;
+values_with_names:
+ values_with_names ',' remember_name expr_or_default remember_end
+ {
+ if (unlikely(Lex->insert_list->push_back($4, thd->mem_root)))
+ MYSQL_YYABORT;
+ // give some name in case of using in table value constuctor (TVC)
+ if (!$4->name.str || $4->name.str == item_empty_name)
+ $4->set_name(thd, $3, (uint) ($5 - $3), thd->charset());
+ }
+ | remember_name expr_or_default remember_end
+ {
+ if (unlikely(Lex->insert_list->push_back($2, thd->mem_root)))
+ MYSQL_YYABORT;
+ // give some name in case of using in table value constuctor (TVC)
+ if (!$2->name.str || $2->name.str == item_empty_name)
+ $2->set_name(thd, $1, (uint) ($3 - $1), thd->charset());
+ }
+ ;
+
expr_or_default:
expr { $$= $1;}
| DEFAULT
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 37ae2fbb68a..6d2dbbf646e 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2672,6 +2672,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",
diff --git a/sql/table.cc b/sql/table.cc
index b0468be17f2..de5a71f6af1 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -6885,7 +6885,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);
}
@@ -8335,7 +8338,7 @@ int TABLE_LIST::fetch_number_of_rows()
}
if (is_materialized_derived() && !fill_me)
{
- table->file->stats.records= ((select_unit*)(get_unit()->result))->records;
+ table->file->stats.records= get_unit()->result->est_records;
set_if_bigger(table->file->stats.records, 2);
table->used_stat_records= table->file->stats.records;
}
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 699a4daf27a..6aa8a68f222 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -159,6 +159,7 @@ extern "C" time_t wsrep_thd_query_start(THD *thd);
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_set_data_home_dir(const char *data_dir);
extern void wsrep_close_client_connections(my_bool wait_to_end);
extern int wsrep_wait_committing_connections_close(int wait_time);
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index 8816a31330e..0a1d95f30b8 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -58,6 +58,13 @@ bool wsrep_sst_method_update (sys_var *self, THD* thd, enum_var_type type)
return 0;
}
+static const char* data_home_dir = NULL;
+
+extern "C"
+void wsrep_set_data_home_dir(const char *data_dir)
+{
+ data_home_dir= (data_dir && *data_dir) ? data_dir : NULL;
+}
static void make_wsrep_defaults_file()
{
@@ -595,6 +602,29 @@ static int sst_append_auth_env(wsp::env& env, const char* sst_auth)
return -env.error();
}
+#define DATA_HOME_DIR_ENV "INNODB_DATA_HOME_DIR"
+
+static int sst_append_data_dir(wsp::env& env, const char* data_dir)
+{
+ int const data_dir_size= strlen(DATA_HOME_DIR_ENV) + 1 /* = */
+ + (data_dir ? strlen(data_dir) : 0) + 1 /* \0 */;
+
+ wsp::string data_dir_str(data_dir_size); // for automatic cleanup on return
+ if (!data_dir_str()) return -ENOMEM;
+
+ int ret= snprintf(data_dir_str(), data_dir_size, "%s=%s",
+ DATA_HOME_DIR_ENV, data_dir ? data_dir : "");
+
+ if (ret < 0 || ret >= data_dir_size)
+ {
+ WSREP_ERROR("sst_append_data_dir(): snprintf() failed: %d", ret);
+ return (ret < 0 ? ret : -EMSGSIZE);
+ }
+
+ env.append(data_dir_str());
+ return -env.error();
+}
+
static ssize_t sst_prepare_other (const char* method,
const char* sst_auth,
const char* addr_in,
@@ -656,6 +686,16 @@ static ssize_t sst_prepare_other (const char* method,
return ret;
}
+ if (data_home_dir)
+ {
+ if ((ret= sst_append_data_dir(env, data_home_dir)))
+ {
+ WSREP_ERROR("sst_prepare_other(): appending data "
+ "directory failed: %d", ret);
+ return ret;
+ }
+ }
+
pthread_t tmp;
sst_thread_arg arg(cmd_str(), env());
mysql_mutex_lock (&arg.lock);
@@ -1347,6 +1387,16 @@ wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx,
return WSREP_CB_FAILURE;
}
+ if (data_home_dir)
+ {
+ if ((ret= sst_append_data_dir(env, data_home_dir)))
+ {
+ WSREP_ERROR("wsrep_sst_donate_cb(): appending data "
+ "directory failed: %d", ret);
+ return WSREP_CB_FAILURE;
+ }
+ }
+
if (!strcmp (WSREP_SST_MYSQLDUMP, method))
{
ret = sst_donate_mysqldump(data, &current_gtid->uuid, uuid_str,
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index 7fe120beb8e..bc43b844a35 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -594,7 +594,9 @@ void wsrep_node_address_init (const char* value)
static void wsrep_slave_count_change_update ()
{
- wsrep_slave_count_change += (wsrep_slave_threads - wsrep_prev_slave_threads);
+ wsrep_slave_count_change = (wsrep_slave_threads - wsrep_prev_slave_threads);
+ WSREP_DEBUG("Change on slave threads: New %lu old %lu difference %lu",
+ wsrep_slave_threads, wsrep_prev_slave_threads, wsrep_slave_count_change);
wsrep_prev_slave_threads = wsrep_slave_threads;
}
@@ -617,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) {