diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-05-23 11:09:47 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-05-23 11:09:47 +0300 |
commit | 8f643e2063c9890a353149f39ef85b2cf3151fd0 (patch) | |
tree | c5468b905c8858dc1cc80ccb2072a923b28c8783 /sql | |
parent | 3aecedb2f8f99c446a5ba0b02efcf422a252c9e8 (diff) | |
parent | b61700c22104b513caa9a85e5c6529aa5f2bf4e4 (diff) | |
download | mariadb-git-8f643e2063c9890a353149f39ef85b2cf3151fd0.tar.gz |
Merge 10.1 into 10.2
Diffstat (limited to 'sql')
-rw-r--r-- | sql/discover.cc | 3 | ||||
-rw-r--r-- | sql/filesort.cc | 1 | ||||
-rw-r--r-- | sql/item_subselect.cc | 26 | ||||
-rw-r--r-- | sql/item_subselect.h | 8 | ||||
-rw-r--r-- | sql/item_sum.h | 1 | ||||
-rw-r--r-- | sql/log.cc | 7 | ||||
-rw-r--r-- | sql/mysqld.cc | 2 | ||||
-rw-r--r-- | sql/mysqld.h | 2 | ||||
-rw-r--r-- | sql/opt_range.cc | 7 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 109 | ||||
-rw-r--r-- | sql/opt_sum.cc | 9 | ||||
-rw-r--r-- | sql/rpl_mi.cc | 6 | ||||
-rw-r--r-- | sql/sql_lex.cc | 1 | ||||
-rw-r--r-- | sql/sql_lex.h | 5 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 2 | ||||
-rw-r--r-- | sql/sql_repl.cc | 6 | ||||
-rw-r--r-- | sql/sql_select.cc | 18 | ||||
-rw-r--r-- | sql/sys_vars.cc | 3 |
18 files changed, 190 insertions, 26 deletions
diff --git a/sql/discover.cc b/sql/discover.cc index d8ed718fc58..d8bf6ca79c5 100644 --- a/sql/discover.cc +++ b/sql/discover.cc @@ -89,8 +89,7 @@ int readfrm(const char *name, const uchar **frmdata, size_t *len) error= 0; err: - if (file > 0) - (void) mysql_file_close(file, MYF(MY_WME)); + (void) mysql_file_close(file, MYF(MY_WME)); err_end: /* Here when no file */ DBUG_RETURN (error); diff --git a/sql/filesort.cc b/sql/filesort.cc index baeb75b3b0b..5d5b210e62d 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -951,6 +951,7 @@ write_keys(Sort_param *param, SORT_INFO *fs_info, uint count, /* check we won't have more buffpeks than we can possibly keep in memory */ if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (ulonglong)UINT_MAX) goto err; + bzero(&buffpek, sizeof(buffpek)); buffpek.file_pos= my_b_tell(tempfile); if ((ha_rows) count > param->max_rows) count=(uint) param->max_rows; /* purecov: inspected */ diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 82fcfff70e1..3c967b6f7e5 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1440,8 +1440,9 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp, st_select_lex *select_lex): Item_exists_subselect(thd), left_expr_cache(0), first_execution(TRUE), in_strategy(SUBS_NOT_TRANSFORMED), - pushed_cond_guards(NULL), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), - is_flattenable_semijoin(FALSE), is_registered_semijoin(FALSE), + pushed_cond_guards(NULL), do_not_convert_to_sj(FALSE), is_jtbm_merged(FALSE), + is_jtbm_const_tab(FALSE), is_flattenable_semijoin(FALSE), + is_registered_semijoin(FALSE), upper_item(0) { DBUG_ENTER("Item_in_subselect::Item_in_subselect"); @@ -2599,6 +2600,27 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg) DBUG_ENTER("Item_in_subselect::inject_in_to_exists_cond"); DBUG_ASSERT(thd == join_arg->thd); + if (select_lex->min_max_opt_list.elements) + { + /* + MIN/MAX optimizations have been applied to Item_sum objects + of the subquery this subquery predicate in opt_sum_query(). + Injection of new condition invalidates this optimizations. + Thus those optimizations must be rolled back. + */ + List_iterator_fast<Item_sum> it(select_lex->min_max_opt_list); + Item_sum *item; + while ((item= it++)) + { + item->clear(); + item->reset_forced_const(); + } + if (where_item) + where_item->update_used_tables(); + if (having_item) + having_item->update_used_tables(); + } + if (where_item) { List<Item> *and_args= NULL; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 72ea63612f0..7f827bbe982 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -508,6 +508,8 @@ public: Item *left_expr_orig; /* Priority of this predicate in the convert-to-semi-join-nest process. */ int sj_convert_priority; + /* May be TRUE only for the candidates to semi-join conversion */ + bool do_not_convert_to_sj; /* Types of left_expr and subquery's select list allow to perform subquery materialization. Currently, we set this to FALSE when it as well could @@ -598,8 +600,8 @@ public: Item_in_subselect(THD *thd_arg): Item_exists_subselect(thd_arg), left_expr_cache(0), first_execution(TRUE), in_strategy(SUBS_NOT_TRANSFORMED), - pushed_cond_guards(NULL), func(NULL), is_jtbm_merged(FALSE), - is_jtbm_const_tab(FALSE), upper_item(0) {} + pushed_cond_guards(NULL), func(NULL), do_not_convert_to_sj(FALSE), + is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), upper_item(0) {} void cleanup(); subs_type substype() { return IN_SUBS; } void reset() @@ -654,6 +656,8 @@ public: */ int get_identifier(); + void block_conversion_to_sj () { do_not_convert_to_sj= TRUE; } + bool test_strategy(uchar strategy) { return MY_TEST(in_strategy & strategy); } diff --git a/sql/item_sum.h b/sql/item_sum.h index 57375b29114..852df778087 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -486,6 +486,7 @@ public: used_tables_cache= 0; const_item_cache= true; } + void reset_forced_const() { const_item_cache= false; } virtual bool const_during_execution() const { return false; } virtual void print(String *str, enum_query_type query_type); void fix_num_length_and_dec(); diff --git a/sql/log.cc b/sql/log.cc index d11b7f9f35a..e2308f46ad4 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5636,13 +5636,20 @@ int THD::binlog_write_table_map(TABLE *table, bool is_transactional, IO_CACHE *file= cache_mngr->get_binlog_cache_log(use_trans_cache(this, is_transactional)); Log_event_writer writer(file); + binlog_cache_data *cache_data= + cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional)); + if (with_annotate && *with_annotate) { Annotate_rows_log_event anno(table->in_use, is_transactional, false); /* Annotate event should be written not more than once */ *with_annotate= 0; if ((error= writer.write(&anno))) + { + if (my_errno == EFBIG) + cache_data->set_incident(); DBUG_RETURN(error); + } } if ((error= writer.write(&the_event))) DBUG_RETURN(error); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b483d92b774..5ef01d5b26f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -8249,7 +8249,7 @@ static int show_default_keycache(THD *thd, SHOW_VAR *var, char *buff, { struct st_data { KEY_CACHE_STATISTICS stats; - SHOW_VAR var[8]; + SHOW_VAR var[9]; } *data; SHOW_VAR *v; diff --git a/sql/mysqld.h b/sql/mysqld.h index 0d01779474f..c1f4cac9956 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -133,7 +133,7 @@ extern ulong slave_retried_transactions; extern ulong slave_run_triggers_for_rbr; extern ulonglong slave_type_conversions_options; extern my_bool read_only, opt_readonly; -extern my_bool lower_case_file_system; +extern MYSQL_PLUGIN_IMPORT my_bool lower_case_file_system; extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs; extern my_bool opt_secure_auth; extern const char *current_dbug_option; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index d5de96b860a..ec59c0acf86 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6955,7 +6955,10 @@ QUICK_SELECT_I *TRP_ROR_UNION::make_quick(PARAM *param, { if (!(quick= (*scan)->make_quick(param, FALSE, &quick_roru->alloc)) || quick_roru->push_quick_back(quick)) + { + delete quick_roru; DBUG_RETURN(NULL); + } } quick_roru->records= records; quick_roru->read_time= read_cost; @@ -10773,9 +10776,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, */ thd->mem_root= old_root; - if (!quick || create_err) - return 0; /* no ranges found */ - if (quick->init()) + if (!quick || create_err || quick->init()) goto err; quick->records= records; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 15b803ac49a..027d696a14f 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1005,6 +1005,25 @@ bool check_for_outer_joins(List<TABLE_LIST> *join_list) } +void find_and_block_conversion_to_sj(Item *to_find, + List_iterator_fast<Item_in_subselect> &li) +{ + if (to_find->type() != Item::SUBSELECT_ITEM || + ((Item_subselect *) to_find)->substype() != Item_subselect::IN_SUBS) + return; + Item_in_subselect *in_subq; + li.rewind(); + while ((in_subq= li++)) + { + if (in_subq == to_find) + { + in_subq->block_conversion_to_sj(); + return; + } + } +} + + /* Convert semi-join subquery predicates into semi-join join nests @@ -1057,7 +1076,6 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) Query_arena *arena, backup; Item_in_subselect *in_subq; THD *thd= join->thd; - List_iterator<TABLE_LIST> ti(join->select_lex->leaf_tables); DBUG_ENTER("convert_join_subqueries_to_semijoins"); if (join->select_lex->sj_subselects.is_empty()) @@ -1075,6 +1093,89 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) subq_sel->update_used_tables(); } + /* + Check all candidates to semi-join conversion that occur + in ON expressions of outer join. Set the flag blocking + this conversion for them. + */ + TABLE_LIST *tbl; + List_iterator<TABLE_LIST> ti(join->select_lex->leaf_tables); + while ((tbl= ti++)) + { + TABLE_LIST *embedded; + TABLE_LIST *embedding= tbl; + do + { + embedded= embedding; + bool block_conversion_to_sj= false; + if (embedded->on_expr) + { + /* + Conversion of an IN subquery predicate into semi-join + is blocked now if the predicate occurs: + - in the ON expression of an outer join + - in the ON expression of an inner join embedded directly + or indirectly in the inner nest of an outer join + */ + for (TABLE_LIST *tl= embedded; tl; tl= tl->embedding) + { + if (tl->outer_join) + { + block_conversion_to_sj= true; + break; + } + } + } + if (block_conversion_to_sj) + { + Item *cond= embedded->on_expr; + if (!cond) + ; + else if (cond->type() != Item::COND_ITEM) + find_and_block_conversion_to_sj(cond, li); + else if (((Item_cond*) cond)->functype() == + Item_func::COND_AND_FUNC) + { + Item *item; + List_iterator<Item> it(*(((Item_cond*) cond)->argument_list())); + while ((item= it++)) + { + find_and_block_conversion_to_sj(item, li); + } + } + } + embedding= embedded->embedding; + } + while (embedding && + embedding->nested_join->join_list.head() == embedded); + } + + /* + Block conversion to semi-joins for those candidates that + are encountered in the WHERE condition of the multi-table view + with CHECK OPTION if this view is used in UPDATE/DELETE. + (This limitation can be, probably, easily lifted.) + */ + li.rewind(); + while ((in_subq= li++)) + { + if (in_subq->emb_on_expr_nest != NO_JOIN_NEST && + in_subq->emb_on_expr_nest->effective_with_check) + { + in_subq->block_conversion_to_sj(); + } + } + + if (join->select_options & SELECT_STRAIGHT_JOIN) + { + /* Block conversion to semijoins for all candidates */ + li.rewind(); + while ((in_subq= li++)) + { + in_subq->block_conversion_to_sj(); + } + } + li.rewind(); /* First, convert child join's subqueries. We proceed bottom-up here */ while ((in_subq= li++)) @@ -1093,8 +1194,10 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) if (convert_join_subqueries_to_semijoins(child_join)) DBUG_RETURN(TRUE); + + in_subq->sj_convert_priority= - MY_TEST(in_subq->emb_on_expr_nest != NO_JOIN_NEST) * MAX_TABLES * 2 + + MY_TEST(in_subq->do_not_convert_to_sj) * MAX_TABLES * 2 + in_subq->is_correlated * MAX_TABLES + child_join->outer_tables; } @@ -1127,7 +1230,7 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) bool remove_item= TRUE; /* Stop processing if we've reached a subquery that's attached to the ON clause */ - if (in_subq->emb_on_expr_nest != NO_JOIN_NEST) + if (in_subq->do_not_convert_to_sj) break; if (in_subq->is_flattenable_semijoin) diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index cb1a705ad0c..ab587b8b279 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -254,6 +254,8 @@ int opt_sum_query(THD *thd, int error= 0; DBUG_ENTER("opt_sum_query"); + thd->lex->current_select->min_max_opt_list.empty(); + if (conds) where_tables= conds->used_tables(); @@ -447,7 +449,14 @@ int opt_sum_query(THD *thd, item_sum->aggregator_clear(); } else + { item_sum->reset_and_add(); + /* + Save a reference to the item for possible rollback + of the min/max optimizations for this select + */ + thd->lex->current_select->min_max_opt_list.push_back(item_sum); + } item_sum->make_const(); recalc_const_item= 1; break; diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index f30b7e161f2..15b2907c95b 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -664,7 +664,7 @@ file '%s')", fname); mi->connect_retry= (uint) connect_retry; mi->ssl= (my_bool) ssl; mi->ssl_verify_server_cert= ssl_verify_server_cert; - mi->heartbeat_period= master_heartbeat_period; + mi->heartbeat_period= MY_MIN(SLAVE_MAX_HEARTBEAT_PERIOD, master_heartbeat_period); } DBUG_PRINT("master_info",("log_file_name: %s position: %ld", mi->master_log_name, @@ -799,8 +799,8 @@ int flush_master_info(Master_info* mi, contents of file). But because of number of lines in the first line of file we don't care about this garbage. */ - char heartbeat_buf[sizeof(mi->heartbeat_period) * 4]; // buffer to suffice always - sprintf(heartbeat_buf, "%.3f", mi->heartbeat_period); + char heartbeat_buf[FLOATING_POINT_BUFFER]; + my_fcvt(mi->heartbeat_period, 3, heartbeat_buf, NULL); my_b_seek(file, 0L); my_b_printf(file, "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n" diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 1a06aa97ac0..e3ead45447f 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2097,6 +2097,7 @@ void st_select_lex::init_query() leaf_tables_prep.empty(); leaf_tables.empty(); item_list.empty(); + min_max_opt_list.empty(); join= 0; having= prep_having= where= prep_where= 0; cond_pushed_into_where= cond_pushed_into_having= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 3b45b1ad40c..face3bcc378 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -789,6 +789,11 @@ public: */ List<Item_func_match> *ftfunc_list; List<Item_func_match> ftfunc_list_alloc; + /* + The list of items to which MIN/MAX optimizations of opt_sum_query() + have been applied. Used to rollback those optimizations if it's needed. + */ + List<Item_sum> min_max_opt_list; JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */ List<TABLE_LIST> top_join_list; /* join list of the top level */ List<TABLE_LIST> *join_list; /* list for the currently parsed join */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 7de11b11ad3..cd330d8ee26 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3436,7 +3436,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) { stmt->state= Query_arena::STMT_ERROR; stmt->last_errno= thd->get_stmt_da()->sql_errno(); - strncpy(stmt->last_error, thd->get_stmt_da()->message(), MYSQL_ERRMSG_SIZE); + strmake_buf(stmt->last_error, thd->get_stmt_da()->message()); } thd->set_stmt_da(save_stmt_da); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 7c30aa38f1a..e312e9f35e4 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -3913,9 +3913,6 @@ bool mysql_show_binlog_events(THD* thd) Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - Format_description_log_event *description_event= new - Format_description_log_event(3); /* MySQL 4.0 by default */ - DBUG_ASSERT(thd->lex->sql_command == SQLCOM_SHOW_BINLOG_EVENTS || thd->lex->sql_command == SQLCOM_SHOW_RELAYLOG_EVENTS); @@ -3936,6 +3933,9 @@ bool mysql_show_binlog_events(THD* thd) binary_log= &(mi->rli.relay_log); } + Format_description_log_event *description_event= new + Format_description_log_event(3); /* MySQL 4.0 by default */ + if (binary_log->is_open()) { SELECT_LEX_UNIT *unit= &thd->lex->unit; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5e35224fe63..7bdc99cdbc2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9720,12 +9720,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) /* Step #2: Extract WHERE/ON parts */ + uint i; + for (i= join->top_join_tab_count - 1; i >= join->const_tables; i--) + { + if (!join->join_tab[i].bush_children) + break; + } + uint last_top_base_tab_idx= i; + table_map save_used_tables= 0; used_tables=((select->const_tables=join->const_table_map) | OUTER_REF_TABLE_BIT | RAND_TABLE_BIT); JOIN_TAB *tab; table_map current_map; - uint i= join->const_tables; + i= join->const_tables; for (tab= first_depth_first_tab(join); tab; tab= next_depth_first_tab(join, tab), i++) { @@ -9764,7 +9772,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) Following force including random expression in last table condition. It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5 */ - if (tab == join->join_tab + join->top_join_tab_count - 1) + if (tab == join->join_tab + last_top_base_tab_idx) current_map|= RAND_TABLE_BIT; used_tables|=current_map; @@ -9804,10 +9812,10 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) save_used_tables= 0; } else - { - tmp= make_cond_for_table(thd, cond, used_tables, current_map, i, + { + tmp= make_cond_for_table(thd, cond, used_tables, current_map, i, FALSE, FALSE); - } + } /* Add conditions added by add_not_null_conds(). */ if (tab->select_cond) add_cond_and_fix(thd, &tmp, tab->select_cond); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 209b17ff377..9ab5e42755e 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1740,7 +1740,10 @@ Sys_var_gtid_binlog_state::do_check(THD *thd, set_var *var) return true; } if (res->length() == 0) + { list= NULL; + list_len= 0; + } else if (!(list= gtid_parse_string_to_list(res->ptr(), res->length(), &list_len))) { |