diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-09-11 21:31:03 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-09-11 21:31:03 +0300 |
commit | 1bf3e8ab43e982953d7534db902020d321364afb (patch) | |
tree | 7de4aaac9f947d4302cd4edbb5677da8917ade71 /sql | |
parent | f5bebaf1d6a0ff2fca9b342ed5910b9d34a276bb (diff) | |
parent | 4901f31c13f91e130f077f2f77b32c40b0036e32 (diff) | |
download | mariadb-git-1bf3e8ab43e982953d7534db902020d321364afb.tar.gz |
Merge 10.3 into 10.4
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 8 | ||||
-rw-r--r-- | sql/field.h | 1 | ||||
-rw-r--r-- | sql/filesort.cc | 4 | ||||
-rw-r--r-- | sql/handler.cc | 43 | ||||
-rw-r--r-- | sql/handler.h | 1 | ||||
-rw-r--r-- | sql/item.cc | 2 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 19 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 1 | ||||
-rw-r--r-- | sql/item_windowfunc.h | 2 | ||||
-rw-r--r-- | sql/key.cc | 3 | ||||
-rw-r--r-- | sql/multi_range_read.cc | 13 | ||||
-rw-r--r-- | sql/mysqld.cc | 22 | ||||
-rw-r--r-- | sql/opt_range.cc | 26 | ||||
-rw-r--r-- | sql/opt_range.h | 5 | ||||
-rw-r--r-- | sql/opt_range_mrr.cc | 54 | ||||
-rw-r--r-- | sql/protocol.cc | 8 | ||||
-rw-r--r-- | sql/sql_class.h | 6 | ||||
-rw-r--r-- | sql/sql_delete.cc | 14 | ||||
-rw-r--r-- | sql/sql_lex.cc | 6 | ||||
-rw-r--r-- | sql/sql_parse.cc | 1 | ||||
-rw-r--r-- | sql/sql_select.cc | 18 | ||||
-rw-r--r-- | sql/sql_sequence.cc | 5 | ||||
-rw-r--r-- | sql/sql_show.cc | 52 | ||||
-rw-r--r-- | sql/sql_statistics.h | 2 | ||||
-rw-r--r-- | sql/sql_time.cc | 2 | ||||
-rw-r--r-- | sql/sql_tvc.h | 2 | ||||
-rw-r--r-- | sql/sql_union.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 42 | ||||
-rw-r--r-- | sql/sql_yacc_ora.yy | 42 | ||||
-rw-r--r-- | sql/sys_vars.cc | 10 | ||||
-rw-r--r-- | sql/table.cc | 5 | ||||
-rw-r--r-- | sql/wsrep_mysqld.h | 1 | ||||
-rw-r--r-- | sql/wsrep_sst.cc | 50 | ||||
-rw-r--r-- | sql/wsrep_var.cc | 10 |
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, ¤t_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) { |