diff options
author | Sergei Golubchik <serg@mariadb.org> | 2021-02-23 13:01:27 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2021-02-23 13:06:22 +0100 |
commit | f33e57a9e66f7e1790cb84b141381bb668e281a0 (patch) | |
tree | 31bb1c5bd8e0addc9e994a1bb42b4703c37f7ed8 /sql | |
parent | 1a0526e2f294acdcac829672794ee1fe708eb2b3 (diff) | |
parent | 245d33db4e0586df4fe28362fb002cef0151a1c9 (diff) | |
download | mariadb-git-f33e57a9e66f7e1790cb84b141381bb668e281a0.tar.gz |
Merge branch '10.4' into 10.5
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 5 | ||||
-rw-r--r-- | sql/item_subselect.cc | 28 | ||||
-rw-r--r-- | sql/item_subselect.h | 3 | ||||
-rw-r--r-- | sql/lock.cc | 17 | ||||
-rw-r--r-- | sql/log.cc | 5 | ||||
-rw-r--r-- | sql/signal_handler.cc | 3 | ||||
-rw-r--r-- | sql/sql_acl.cc | 42 | ||||
-rw-r--r-- | sql/sql_admin.cc | 4 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 33 | ||||
-rw-r--r-- | sql/sql_show.cc | 10 | ||||
-rw-r--r-- | sql/sql_statistics.cc | 93 | ||||
-rw-r--r-- | sql/sql_statistics.h | 11 | ||||
-rw-r--r-- | sql/sql_truncate.cc | 23 | ||||
-rw-r--r-- | sql/sql_tvc.cc | 27 | ||||
-rw-r--r-- | sql/sql_update.cc | 18 | ||||
-rw-r--r-- | sql/structs.h | 2 | ||||
-rw-r--r-- | sql/table.cc | 4 | ||||
-rw-r--r-- | sql/table.h | 2 | ||||
-rw-r--r-- | sql/wsrep_mysqld.cc | 17 | ||||
-rw-r--r-- | sql/wsrep_mysqld.h | 2 | ||||
-rw-r--r-- | sql/wsrep_sst.cc | 62 | ||||
-rw-r--r-- | sql/wsrep_var.cc | 20 |
23 files changed, 293 insertions, 140 deletions
diff --git a/sql/item.cc b/sql/item.cc index a21bd490272..f818a9f02e7 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9370,8 +9370,9 @@ bool Item_default_value::fix_fields(THD *thd, Item **items) memcpy((void *)def_field, (void *)field_arg->field, field_arg->field->size_of()); def_field->reset_fields(); - // If non-constant default value expression - if (def_field->default_value && def_field->default_value->flags) + // If non-constant default value expression or a blob + if (def_field->default_value && + (def_field->default_value->flags || def_field->flags & BLOB_FLAG)) { uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length()); if (!newptr) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 7916bcb45a9..76dbe06c50e 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -278,7 +278,11 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref) { if (sl->tvc) { - wrap_tvc_into_select(thd, sl); + if (!(sl= wrap_tvc_into_select(thd, sl))) + { + res= TRUE; + goto end; + } } } @@ -382,7 +386,7 @@ bool Item_subselect::mark_as_eliminated_processor(void *arg) bool Item_subselect::eliminate_subselect_processor(void *arg) { unit->item= NULL; - unit->exclude_from_tree(); + unit->exclude(); eliminated= TRUE; return FALSE; } @@ -451,6 +455,26 @@ bool Item_subselect::mark_as_dependent(THD *thd, st_select_lex *select, /* + @brief + Update the table bitmaps for the outer references used within a subquery +*/ + +bool Item_subselect::update_table_bitmaps_processor(void *arg) +{ + List_iterator<Ref_to_outside> it(upper_refs); + Ref_to_outside *upper; + + while ((upper= it++)) + { + if (upper->item && + upper->item->walk(&Item::update_table_bitmaps_processor, FALSE, arg)) + return TRUE; + } + return FALSE; +} + + +/* Adjust attributes after our parent select has been merged into grandparent DESCRIPTION diff --git a/sql/item_subselect.h b/sql/item_subselect.h index a346def72f1..b5894041320 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -256,6 +256,7 @@ public: @retval FALSE otherwise */ bool is_expensive_processor(void *arg) override { return is_expensive(); } + bool update_table_bitmaps_processor(void *arg) override; /** Get the SELECT_LEX structure associated with this Item. @@ -277,7 +278,7 @@ public: Item* build_clone(THD *thd) override { return 0; } Item* get_copy(THD *thd) override { return 0; } - bool wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl); + st_select_lex *wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl); friend class select_result_interceptor; friend class Item_in_optimizer; diff --git a/sql/lock.cc b/sql/lock.cc index ff215795604..5d502755541 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -746,6 +746,9 @@ static int unlock_external(THD *thd, TABLE **table,uint count) - GET_LOCK_STORE_LOCKS : Store lock info in TABLE - GET_LOCK_SKIP_SEQUENCES : Ignore sequences (for temporary unlock) - GET_LOCK_ON_THD : Store lock in thd->mem_root + + Temporary tables are not locked (as these are single user), except for + TRANSACTIONAL_TMP_TABLES as locking is needed to handle transactions. */ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags) @@ -762,8 +765,8 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags) { TABLE *t= table_ptr[i]; - if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE && - t->s->tmp_table != INTERNAL_TMP_TABLE && + if ((likely(!t->s->tmp_table) || + (t->s->tmp_table == TRANSACTIONAL_TMP_TABLE)) && (!(flags & GET_LOCK_SKIP_SEQUENCES) || t->s->sequence == 0)) { lock_count+= t->file->lock_count(); @@ -792,13 +795,13 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags) for (i=0 ; i < count ; i++) { - TABLE *table; + TABLE *table= table_ptr[i]; enum thr_lock_type lock_type; THR_LOCK_DATA **locks_start; - table= table_ptr[i]; - if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE || - table->s->tmp_table == INTERNAL_TMP_TABLE || - ((flags & GET_LOCK_SKIP_SEQUENCES) && table->s->sequence)) + + if (!((likely(!table->s->tmp_table) || + (table->s->tmp_table == TRANSACTIONAL_TMP_TABLE)) && + (!(flags & GET_LOCK_SKIP_SEQUENCES) || table->s->sequence == 0))) continue; lock_type= table->reginfo.lock_type; DBUG_ASSERT(lock_type != TL_WRITE_DEFAULT && lock_type != TL_READ_DEFAULT); diff --git a/sql/log.cc b/sql/log.cc index d6b47ff3aa6..3b1322035eb 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6591,8 +6591,9 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) MDL_REQUEST_INIT(&mdl_request, MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT, MDL_EXPLICIT); - thd->mdl_context.acquire_lock(&mdl_request, - thd->variables.lock_wait_timeout); + if (thd->mdl_context.acquire_lock(&mdl_request, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(1); thd->backup_commit_lock= &mdl_request; if ((res= thd->wait_for_prior_commit())) diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index 5e3f32eae4e..79bc32cbf19 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -15,6 +15,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #include "mariadb.h" +#include "my_dbug.h" #include <signal.h> //#include "sys_vars.h" @@ -120,8 +121,8 @@ extern "C" sig_handler handle_fatal_signal(int sig) my_safe_printf_stderr("Fatal " SIGNAL_FMT " while backtracing\n", sig); goto end; } - segfaulted = 1; + DBUG_PRINT("error", ("handling fatal signal")); curr_time= my_time(0); localtime_r(&curr_time, &tm); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 2e1b74bb3ce..4ae27a7e3ce 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -9052,6 +9052,16 @@ static bool print_grants_for_role(THD *thd, ACL_ROLE * role) } +static void append_auto_expiration_policy(ACL_USER *acl_user, String *r) { + if (!acl_user->password_lifetime) + r->append(STRING_WITH_LEN(" PASSWORD EXPIRE NEVER")); + else if (acl_user->password_lifetime > 0) + { + r->append(STRING_WITH_LEN(" PASSWORD EXPIRE INTERVAL ")); + r->append_longlong(acl_user->password_lifetime); + r->append(STRING_WITH_LEN(" DAY")); + } +} bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) { @@ -9111,14 +9121,8 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) if (acl_user->password_expired) result.append(STRING_WITH_LEN(" PASSWORD EXPIRE")); - else if (!acl_user->password_lifetime) - result.append(STRING_WITH_LEN(" PASSWORD EXPIRE NEVER")); - else if (acl_user->password_lifetime > 0) - { - result.append(STRING_WITH_LEN(" PASSWORD EXPIRE INTERVAL ")); - result.append_longlong(acl_user->password_lifetime); - result.append(STRING_WITH_LEN(" DAY")); - } + else + append_auto_expiration_policy(acl_user, &result); protocol->prepare_for_resend(); protocol->store(result.ptr(), result.length(), result.charset()); @@ -9126,6 +9130,28 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) { error= true; } + + /* MDEV-24114 - PASSWORD EXPIRE and PASSWORD EXPIRE [NEVER | INTERVAL X DAY] + are two different mechanisms. To make sure a tool can restore the state + of a user account, including both the manual expiration state of the + account and the automatic expiration policy attached to it, we should + print two statements here, a CREATE USER (printed above) and an ALTER USER */ + if (acl_user->password_expired && acl_user->password_lifetime > -1) { + result.length(0); + result.append("ALTER USER "); + append_identifier(thd, &result, username, strlen(username)); + result.append('@'); + append_identifier(thd, &result, acl_user->host.hostname, + acl_user->hostname_length); + append_auto_expiration_policy(acl_user, &result); + protocol->prepare_for_resend(); + protocol->store(result.ptr(), result.length(), result.charset()); + if (protocol->write()) + { + error= true; + } + } + my_eof(thd); end: diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 7c1f8596ece..ee7226afd0b 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1454,7 +1454,9 @@ bool Sql_cmd_optimize_table::execute(THD *thd) /* Presumably, OPTIMIZE and binlog writing doesn't require synchronization */ + thd->get_stmt_da()->set_overwrite_status(true); res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + thd->get_stmt_da()->set_overwrite_status(false); } m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; @@ -1486,7 +1488,9 @@ bool Sql_cmd_repair_table::execute(THD *thd) /* Presumably, REPAIR and binlog writing doesn't require synchronization */ + thd->get_stmt_da()->set_overwrite_status(true); res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + thd->get_stmt_da()->set_overwrite_status(false); } m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 10b71781ce4..be288ebaf3b 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -530,7 +530,7 @@ struct LEX_MASTER_INFO } host= user= password= log_file_name= ssl_key= ssl_cert= ssl_ca= - ssl_capath= ssl_cipher= relay_log_name= 0; + ssl_capath= ssl_cipher= ssl_crl= ssl_crlpath= relay_log_name= NULL; pos= relay_log_pos= server_id= port= connect_retry= 0; heartbeat_period= 0; ssl= ssl_verify_server_cert= heartbeat_opt= diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ceb298aefc6..2f88d4f9217 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1172,22 +1172,6 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num, FALSE, SELECT_ACL, SELECT_ACL, FALSE)) DBUG_RETURN(-1); - /* - Permanently remove redundant parts from the query if - 1) This is a subquery - 2) This is the first time this query is optimized (since the - transformation is permanent - 3) Not normalizing a view. Removal should take place when a - query involving a view is optimized, not when the view - is created - */ - if (select_lex->master_unit()->item && // 1) - select_lex->first_cond_optimization && // 2) - !thd->lex->is_view_context_analysis()) // 3) - { - remove_redundant_subquery_clauses(select_lex); - } - /* System Versioning: handle FOR SYSTEM_TIME clause. */ if (select_lex->vers_setup_conds(thd, tables_list) < 0) DBUG_RETURN(-1); @@ -1269,6 +1253,23 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num, &hidden_group_fields, &select_lex->select_n_reserved)) DBUG_RETURN(-1); + + /* + Permanently remove redundant parts from the query if + 1) This is a subquery + 2) This is the first time this query is optimized (since the + transformation is permanent + 3) Not normalizing a view. Removal should take place when a + query involving a view is optimized, not when the view + is created + */ + if (select_lex->master_unit()->item && // 1) + select_lex->first_cond_optimization && // 2) + !thd->lex->is_view_context_analysis()) // 3) + { + remove_redundant_subquery_clauses(select_lex); + } + /* Resolve the ORDER BY that was skipped, then remove it. */ if (skip_order_by && select_lex != select_lex->master_unit()->global_parameters()) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 6fe45fe2de3..b043f83c72c 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -8657,6 +8657,16 @@ bool get_schema_tables_result(JOIN *join, if (table_list->schema_table->fill_table == 0) continue; + /* + Do not fill in tables thare are marked as JT_CONST as these will never + be read and they also don't have a tab->read_record.table set! + This can happen with queries like + SELECT * FROM t1 LEFT JOIN (t1 AS t1b JOIN INFORMATION_SCHEMA.ROUTINES) + ON (t1b.a IS NULL); + */ + if (tab->type == JT_CONST) + continue; + /* skip I_S optimizations specific to get_all_tables */ if (lex->describe && (table_list->schema_table->fill_table != get_all_tables)) diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 72a55bfa86b..821448740e7 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -1021,14 +1021,14 @@ public: void store_stat_fields() { - char buff[MAX_FIELD_WIDTH]; - String val(buff, sizeof(buff), &my_charset_bin); + StringBuffer<MAX_FIELD_WIDTH> val; MY_BITMAP *old_map= dbug_tmp_use_all_columns(stat_table, &stat_table->read_set); for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++) { Field *stat_field= stat_table->field[i]; - if (table_field->collected_stats->is_null(i)) + Column_statistics *stats= table_field->collected_stats; + if (stats->is_null(i)) stat_field->set_null(); else { @@ -1041,47 +1041,37 @@ public: and move this implementation there */ if (table_field->type() == MYSQL_TYPE_BIT) - stat_field->store(table_field->collected_stats->min_value->val_int(),true); + stat_field->store(stats->min_value->val_int(),true); else - { - Field *field= table_field->collected_stats->min_value; - field->store_to_statistical_minmax_field(stat_field, &val); - } + stats->min_value->store_to_statistical_minmax_field(stat_field, &val); break; } case COLUMN_STAT_MAX_VALUE: { if (table_field->type() == MYSQL_TYPE_BIT) - stat_field->store(table_field->collected_stats->max_value->val_int(),true); + stat_field->store(stats->max_value->val_int(),true); else - { - Field *field= table_field->collected_stats->max_value; - field->store_to_statistical_minmax_field(stat_field, &val); - } + stats->max_value->store_to_statistical_minmax_field(stat_field, &val); break; } case COLUMN_STAT_NULLS_RATIO: - stat_field->store(table_field->collected_stats->get_nulls_ratio()); + stat_field->store(stats->get_nulls_ratio()); break; case COLUMN_STAT_AVG_LENGTH: - stat_field->store(table_field->collected_stats->get_avg_length()); + stat_field->store(stats->get_avg_length()); break; case COLUMN_STAT_AVG_FREQUENCY: - stat_field->store(table_field->collected_stats->get_avg_frequency()); + stat_field->store(stats->get_avg_frequency()); break; case COLUMN_STAT_HIST_SIZE: - stat_field->store(table_field->collected_stats->histogram.get_size()); + stat_field->store(stats->histogram.get_size()); break; case COLUMN_STAT_HIST_TYPE: - stat_field->store(table_field->collected_stats->histogram.get_type() + - 1); + stat_field->store(stats->histogram.get_type() + 1); break; case COLUMN_STAT_HISTOGRAM: - const char * col_histogram= - (const char *) (table_field->collected_stats->histogram.get_values()); - stat_field->store(col_histogram, - table_field->collected_stats->histogram.get_size(), - &my_charset_bin); + stat_field->store((char *)stats->histogram.get_values(), + stats->histogram.get_size(), &my_charset_bin); break; } } @@ -1139,14 +1129,20 @@ public: { Field *field= table_field->read_stats->min_value; field->set_notnull(); - field->store_from_statistical_minmax_field(stat_field, &val); + if (table_field->type() == MYSQL_TYPE_BIT) + field->store(stat_field->val_int(), true); + else + field->store_from_statistical_minmax_field(stat_field, &val); break; } case COLUMN_STAT_MAX_VALUE: { Field *field= table_field->read_stats->max_value; field->set_notnull(); - field->store_from_statistical_minmax_field(stat_field, &val); + if (table_field->type() == MYSQL_TYPE_BIT) + field->store(stat_field->val_int(), true); + else + field->store_from_statistical_minmax_field(stat_field, &val); break; } case COLUMN_STAT_NULLS_RATIO: @@ -2101,20 +2097,24 @@ void create_min_max_statistical_fields_for_table_share(THD *thd, int alloc_statistics_for_table(THD* thd, TABLE *table) { Field **field_ptr; - uint fields; DBUG_ENTER("alloc_statistics_for_table"); + uint columns= 0; + for (field_ptr= table->field; *field_ptr; field_ptr++) + { + if (bitmap_is_set(table->read_set, (*field_ptr)->field_index)) + columns++; + } Table_statistics *table_stats= (Table_statistics *) alloc_root(&table->mem_root, sizeof(Table_statistics)); - fields= table->s->fields ; Column_statistics_collected *column_stats= (Column_statistics_collected *) alloc_root(&table->mem_root, sizeof(Column_statistics_collected) * - (fields+1)); + columns); uint keys= table->s->keys; Index_statistics *index_stats= @@ -2125,16 +2125,6 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) ulonglong *idx_avg_frequency= (ulonglong*) alloc_root(&table->mem_root, sizeof(ulonglong) * key_parts); - if (table->file->ha_rnd_init(TRUE)) - DBUG_RETURN(1); - table->file->ha_rnd_end(); - - uint columns= 0; - for (field_ptr= table->field; *field_ptr; field_ptr++) - { - if (bitmap_is_set(table->read_set, (*field_ptr)->field_index)) - columns++; - } uint hist_size= thd->variables.histogram_size; Histogram_type hist_type= (Histogram_type) (thd->variables.histogram_type); uchar *histogram= NULL; @@ -2156,19 +2146,17 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) table_stats->idx_avg_frequency= idx_avg_frequency; table_stats->histograms= histogram; - memset(column_stats, 0, sizeof(Column_statistics) * (fields+1)); + memset(column_stats, 0, sizeof(Column_statistics) * columns); - for (field_ptr= table->field; *field_ptr; field_ptr++, column_stats++) + for (field_ptr= table->field; *field_ptr; field_ptr++) { - (*field_ptr)->collected_stats= column_stats; - (*field_ptr)->collected_stats->max_value= NULL; - (*field_ptr)->collected_stats->min_value= NULL; if (bitmap_is_set(table->read_set, (*field_ptr)->field_index)) { column_stats->histogram.set_size(hist_size); column_stats->histogram.set_type(hist_type); column_stats->histogram.set_values(histogram); histogram+= hist_size; + (*field_ptr)->collected_stats= column_stats++; } } @@ -2663,7 +2651,7 @@ int collect_statistics_for_table(THD *thd, TABLE *table) for (field_ptr= table->field; *field_ptr; field_ptr++) { table_field= *field_ptr; - if (!bitmap_is_set(table->read_set, table_field->field_index)) + if (!table_field->collected_stats) continue; table_field->collected_stats->init(thd, table_field); } @@ -2688,7 +2676,7 @@ int collect_statistics_for_table(THD *thd, TABLE *table) for (field_ptr= table->field; *field_ptr; field_ptr++) { table_field= *field_ptr; - if (!bitmap_is_set(table->read_set, table_field->field_index)) + if (!table_field->collected_stats) continue; if ((rc= table_field->collected_stats->add())) break; @@ -2718,7 +2706,7 @@ int collect_statistics_for_table(THD *thd, TABLE *table) for (field_ptr= table->field; *field_ptr; field_ptr++) { table_field= *field_ptr; - if (!bitmap_is_set(table->read_set, table_field->field_index)) + if (!table_field->collected_stats) continue; bitmap_set_bit(table->write_set, table_field->field_index); if (!rc) @@ -2822,7 +2810,7 @@ int update_statistics_for_table(THD *thd, TABLE *table) for (Field **field_ptr= table->field; *field_ptr; field_ptr++) { Field *table_field= *field_ptr; - if (!bitmap_is_set(table->read_set, table_field->field_index)) + if (!table_field->collected_stats) continue; restore_record(stat_table, s->default_values); column_stat.set_key_fields(table_field); @@ -3757,6 +3745,7 @@ double get_column_range_cardinality(Field *field, if (!table->stats_is_read) return tab_records; + THD *thd= table->in_use; double col_nulls= tab_records * col_stats->get_nulls_ratio(); double col_non_nulls= tab_records - col_nulls; @@ -3787,7 +3776,7 @@ double get_column_range_cardinality(Field *field, col_stats->min_max_values_are_provided()) { Histogram *hist= &col_stats->histogram; - if (hist->is_available()) + if (hist->is_usable(thd)) { store_key_image_to_rec(field, (uchar *) min_endp->key, field->key_length()); @@ -3831,10 +3820,10 @@ double get_column_range_cardinality(Field *field, max_mp_pos= 1.0; Histogram *hist= &col_stats->histogram; - if (!hist->is_available()) - sel= (max_mp_pos - min_mp_pos); - else + if (hist->is_usable(thd)) sel= hist->range_selectivity(min_mp_pos, max_mp_pos); + else + sel= (max_mp_pos - min_mp_pos); res= col_non_nulls * sel; set_if_bigger(res, col_stats->get_avg_frequency()); } diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h index 20ecf06bfee..35b3aa33acc 100644 --- a/sql/sql_statistics.h +++ b/sql/sql_statistics.h @@ -239,6 +239,17 @@ public: bool is_available() { return get_size() > 0 && get_values(); } + /* + This function checks that histograms should be usable only when + 1) the level of optimizer_use_condition_selectivity > 3 + 2) histograms have been collected + */ + bool is_usable(THD *thd) + { + return thd->variables.optimizer_use_condition_selectivity > 3 && + is_available(); + } + void set_value(uint i, double val) { switch (type) { diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 5e89c4d19ee..2bf99993a50 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -427,20 +427,23 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) bool hton_can_recreate; #ifdef WITH_WSREP - if (WSREP(thd)) + if (WSREP(thd) && wsrep_thd_is_local(thd)) { wsrep::key_array keys; - wsrep_append_fk_parent_table(thd, table_ref, &keys); - if (keys.empty()) + /* Do not start TOI if table is not found */ + if (!wsrep_append_fk_parent_table(thd, table_ref, &keys)) { - WSREP_TO_ISOLATION_BEGIN_IF(table_ref->db.str, table_ref->table_name.str, NULL) + if (keys.empty()) { - DBUG_RETURN(TRUE); - } - } else { - WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, table_ref, &keys) - { - DBUG_RETURN(TRUE); + WSREP_TO_ISOLATION_BEGIN_IF(table_ref->db.str, table_ref->table_name.str, NULL) + { + DBUG_RETURN(TRUE); + } + } else { + WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, table_ref, &keys) + { + DBUG_RETURN(TRUE); + } } } } diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index 9a7084cdca2..e8a201aecfc 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -372,6 +372,13 @@ int table_value_constr::save_explain_data_intern(THD *thd, if (select_lex->master_unit()->derived) explain->connection_type= Explain_node::EXPLAIN_NODE_DERIVED; + for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); + unit; + unit= unit->next_unit()) + { + explain->add_child(unit->first_select()->select_number); + } + output->add_node(explain); if (select_lex->is_top_level_node()) @@ -396,9 +403,14 @@ bool table_value_constr::optimize(THD *thd) thd->lex->explain && // for "SET" command in SPs. (!thd->lex->explain->get_select(select_lex->select_number))) { - return save_explain_data_intern(thd, thd->lex->explain); + if (save_explain_data_intern(thd, thd->lex->explain)) + return true; } - return 0; + + if (select_lex->optimize_unflattened_subqueries(true)) + return true; + + return false; } @@ -811,11 +823,12 @@ st_select_lex *wrap_tvc_with_tail(THD *thd, st_select_lex *tvc_sl) SELECT * FROM (VALUES (v1), ... (vn)) tvc_x and replaces the subselect with the result of the transformation. - @retval false if successfull - true otherwise + @retval wrapping select if successful + 0 otherwise */ -bool Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl) +st_select_lex * +Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl) { LEX *lex= thd->lex; /* SELECT_LEX object where the transformation is performed */ @@ -826,12 +839,12 @@ bool Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl) if (engine->engine_type() == subselect_engine::SINGLE_SELECT_ENGINE) ((subselect_single_select_engine *) engine)->change_select(wrapper_sl); lex->current_select= wrapper_sl; - return false; + return wrapper_sl; } else { lex->current_select= parent_select; - return true; + return 0; } } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 76a7dc47745..35ceeeff43a 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -3050,14 +3050,18 @@ bool multi_update::send_eof() DBUG_ASSERT(trans_safe || !updated || thd->transaction->stmt.modified_non_trans_table); - if (likely(local_error != 0)) - error_handled= TRUE; // to force early leave from ::abort_result_set() - - if (unlikely(local_error > 0)) // if the above log write did not fail ... + if (unlikely(local_error)) { - /* Safety: If we haven't got an error before (can happen in do_updates) */ - my_message(ER_UNKNOWN_ERROR, "An error occurred in multi-table update", - MYF(0)); + error_handled= TRUE; // to force early leave from ::abort_result_set() + if (thd->killed == NOT_KILLED && !thd->get_stmt_da()->is_set()) + { + /* + No error message was sent and query was not killed (in which case + mysql_execute_command() will send the error mesage). + */ + my_message(ER_UNKNOWN_ERROR, "An error occurred in multi-table update", + MYF(0)); + } DBUG_RETURN(TRUE); } diff --git a/sql/structs.h b/sql/structs.h index 76129f2abf7..bcd38ffbdd6 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -92,7 +92,7 @@ class engine_option_value; struct ha_index_option_struct; typedef struct st_key { - uint key_length; /* Tot length of key */ + uint key_length; /* total length of user defined key parts */ ulong flags; /* dupp key and pack flags */ uint user_defined_key_parts; /* How many key_parts */ uint usable_key_parts; /* Should normally be = user_defined_key_parts */ diff --git a/sql/table.cc b/sql/table.cc index 4f65dbd65f4..f4bdbdeac5a 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2943,7 +2943,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, key_part->key_part_flag|= field->key_part_flag(); uint16 key_part_length_bytes= field->key_part_length_bytes(); key_part->store_length+= key_part_length_bytes; - keyinfo->key_length+= key_part_length_bytes; + if (i < keyinfo->user_defined_key_parts) + keyinfo->key_length+= key_part_length_bytes; if (i == 0 && key != primary_key) field->flags |= (((keyinfo->flags & HA_NOSAME || @@ -3037,7 +3038,6 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, set_if_bigger(share->max_key_length,keyinfo->key_length+ keyinfo->user_defined_key_parts); - share->total_key_length+= keyinfo->key_length; /* MERGE tables do not have unique indexes. But every key could be an unique index on the underlying MyISAM table. (Bug #10400) diff --git a/sql/table.h b/sql/table.h index 53f385be7fd..9eefd915844 100644 --- a/sql/table.h +++ b/sql/table.h @@ -815,7 +815,7 @@ struct TABLE_SHARE uint rec_buff_length; /* Size of table->record[] buffer */ uint keys, key_parts; uint ext_key_parts; /* Total number of key parts in extended keys */ - uint max_key_length, max_unique_length, total_key_length; + uint max_key_length, max_unique_length; uint uniques; /* Number of UNIQUE index */ uint db_create_options; /* Create options from database */ uint db_options_in_use; /* Options in use */ diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index aa6a7a2ca63..f14bf06800a 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1261,10 +1261,17 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr) key_arr->keys_len= 0; } -void +/*! + * @param thd thread + * @param tables list of tables + * @param keys prepared keys + + * @return true if parent table append was successfull, otherwise false. +*/ +bool wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* keys) { - if (!WSREP(thd) || !WSREP_CLIENT(thd)) return; + bool fail= false; TABLE_LIST *table; thd->release_transactional_locks(); @@ -1275,6 +1282,8 @@ wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* key open_tables(thd, &tables, &counter, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL)) { WSREP_DEBUG("unable to open table for FK checks for %s", thd->query()); + fail= true; + goto exit; } for (table= tables; table; table= table->next_local) @@ -1296,14 +1305,18 @@ wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* key } } +exit: /* close the table and release MDL locks */ close_thread_tables(thd); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); for (table= tables; table; table= table->next_local) { table->table= NULL; + table->next_global= NULL; table->mdl_request.ticket= NULL; } + + return fail; } /*! diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 73ee5d7b4c1..28c012a607c 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -216,7 +216,7 @@ wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout); extern void wsrep_last_committed_id (wsrep_gtid_t* gtid); extern int wsrep_check_opts(); extern void wsrep_prepend_PATH (const char* path); -void wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* table, wsrep::key_array* keys); +extern bool wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* table, wsrep::key_array* keys); /* Other global variables */ extern wsrep_seqno_t wsrep_locked_seqno; diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index dc51c06bcc3..f6ed684b3ea 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -772,8 +772,20 @@ static size_t estimate_cmd_len (bool* extra_args) char c; while ((c = *arg++) != 0) { - /* A whitespace or a single quote requires double quotation marks: */ - if (isspace(c) || c == '\'') + /* + Space, single quote, ampersand, and I/O redirection characters + require text to be enclosed in double quotes: + */ + if (isspace(c) || c == '\'' || c == '&' || c == '|' || +#ifdef __WIN__ + c == '>' || c == '<') +#else + /* + The semicolon is used to separate shell commands, so it must be + enclosed in double quotes as well: + */ + c == '>' || c == '<' || c == ';') +#endif { quotation= true; } @@ -796,10 +808,19 @@ static size_t estimate_cmd_len (bool* extra_args) while ((c = *arg++) != 0) { /* - A whitespace or a single quote requires double - quotation marks: + Space, single quote, ampersand, and I/O redirection characters + require text to be enclosed in double quotes: + */ + if (isspace(c) || c == '\'' || c == '&' || c == '|' || +#ifdef __WIN__ + c == '>' || c == '<') +#else + /* + The semicolon is used to separate shell commands, so it must be + enclosed in double quotes as well: */ - if (isspace(c) || c == '\'') + c == '>' || c == '<' || c == ';') +#endif { quotation= true; } @@ -880,8 +901,20 @@ static void copy_orig_argv (char* cmd_str) char c; while ((c = *arg_scan++) != 0) { - /* A whitespace or a single quote requires double quotation marks: */ - if (isspace(c) || c == '\'') + /* + Space, single quote, ampersand, and I/O redirection characters + require text to be enclosed in double quotes: + */ + if (isspace(c) || c == '\'' || c == '&' || c == '|' || +#ifdef __WIN__ + c == '>' || c == '<') +#else + /* + The semicolon is used to separate shell commands, so it must be + enclosed in double quotes as well: + */ + c == '>' || c == '<' || c == ';') +#endif { quotation= true; } @@ -955,10 +988,19 @@ static void copy_orig_argv (char* cmd_str) while ((c = *arg_scan++) != 0) { /* - A whitespace or a single quote requires double - quotation marks: + Space, single quote, ampersand, and I/O redirection characters + require text to be enclosed in double quotes: + */ + if (isspace(c) || c == '\'' || c == '&' || c == '|' || +#ifdef __WIN__ + c == '>' || c == '<') +#else + /* + The semicolon is used to separate shell commands, so it must be + enclosed in double quotes as well: */ - if (isspace(c) || c == '\'') + c == '>' || c == '<' || c == ';') +#endif { quotation= true; } diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 3a3f3b8c3b7..9ba8f081c83 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -497,15 +497,21 @@ bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var) bool wsrep_provider_options_update(sys_var *self, THD* thd, enum_var_type type) { - enum wsrep::provider::status ret= - Wsrep_server_state::instance().provider().options(wsrep_provider_options); - if (ret) + if (wsrep_provider_options) { - WSREP_ERROR("Set options returned %d", ret); - refresh_provider_options(); - return true; + enum wsrep::provider::status ret= + Wsrep_server_state::instance().provider().options(wsrep_provider_options); + if (ret) + { + WSREP_ERROR("Set options returned %d", ret); + goto err; + } + + return refresh_provider_options(); } - return refresh_provider_options(); +err: + refresh_provider_options(); + return true; } void wsrep_provider_options_init(const char* value) |