diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-08-28 12:22:56 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-08-28 12:22:56 +0300 |
commit | 7830fb7f45b3824c0375c00ae2cab357165904cf (patch) | |
tree | 730521737fdc48e69f7650819e9a29da6487e1f4 /sql | |
parent | b805ebd7ed49868f83e6fd3fe72a11ddacdce452 (diff) | |
parent | 55163ba1bdb1a05daadc66c41c959994231b361c (diff) | |
download | mariadb-git-7830fb7f45b3824c0375c00ae2cab357165904cf.tar.gz |
Merge 10.2 into 10.3
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.h | 46 | ||||
-rw-r--r-- | sql/handler.cc | 70 | ||||
-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 | 36 | ||||
-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 | 12 | ||||
-rw-r--r-- | sql/sql_select.cc | 13 | ||||
-rw-r--r-- | sql/sql_show.cc | 2 | ||||
-rw-r--r-- | sql/sql_statistics.h | 2 | ||||
-rw-r--r-- | sql/sql_time.cc | 2 | ||||
-rw-r--r-- | sql/sys_vars.cc | 103 | ||||
-rw-r--r-- | sql/table.cc | 3 | ||||
-rw-r--r-- | sql/wsrep_mysqld.h | 4 | ||||
-rw-r--r-- | sql/wsrep_thd.cc | 22 | ||||
-rw-r--r-- | sql/wsrep_var.cc | 6 |
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) { |