diff options
Diffstat (limited to 'sql')
| -rw-r--r-- | sql/handle_connections_win.cc | 3 | ||||
| -rw-r--r-- | sql/item.cc | 14 | ||||
| -rw-r--r-- | sql/item.h | 7 | ||||
| -rw-r--r-- | sql/item_cmpfunc.cc | 105 | ||||
| -rw-r--r-- | sql/item_cmpfunc.h | 3 | ||||
| -rw-r--r-- | sql/item_func.cc | 3 | ||||
| -rw-r--r-- | sql/item_strfunc.cc | 5 | ||||
| -rw-r--r-- | sql/log.cc | 3 | ||||
| -rw-r--r-- | sql/multi_range_read.cc | 24 | ||||
| -rw-r--r-- | sql/sp.cc | 2 | ||||
| -rw-r--r-- | sql/sp_cache.cc | 2 | ||||
| -rw-r--r-- | sql/sp_head.cc | 89 | ||||
| -rw-r--r-- | sql/sp_head.h | 33 | ||||
| -rw-r--r-- | sql/sql_lex.cc | 24 | ||||
| -rw-r--r-- | sql/sql_parse.cc | 2 | ||||
| -rw-r--r-- | sql/sql_prepare.cc | 2 | ||||
| -rw-r--r-- | sql/sql_select.cc | 34 | ||||
| -rw-r--r-- | sql/sql_show.cc | 6 | ||||
| -rw-r--r-- | sql/sql_trigger.cc | 2 | ||||
| -rw-r--r-- | sql/sql_type.cc | 2 | ||||
| -rw-r--r-- | sql/sql_type.h | 2 | ||||
| -rw-r--r-- | sql/wsrep_high_priority_service.cc | 1 | ||||
| -rw-r--r-- | sql/wsrep_server_service.cc | 6 | ||||
| -rw-r--r-- | sql/wsrep_server_service.h | 1 | ||||
| -rw-r--r-- | sql/wsrep_thd.cc | 34 | ||||
| -rw-r--r-- | sql/wsrep_thd.h | 2 | ||||
| -rw-r--r-- | sql/wsrep_var.cc | 11 |
27 files changed, 283 insertions, 139 deletions
diff --git a/sql/handle_connections_win.cc b/sql/handle_connections_win.cc index 3b29ad439ac..5db10c2fada 100644 --- a/sql/handle_connections_win.cc +++ b/sql/handle_connections_win.cc @@ -207,10 +207,11 @@ retry : &m_overlapped); DWORD last_error= ret? 0: WSAGetLastError(); - if (last_error == WSAECONNRESET) + if (last_error == WSAECONNRESET || last_error == ERROR_NETNAME_DELETED) { if (m_tp_io) CancelThreadpoolIo(m_tp_io); + closesocket(m_client_socket); goto retry; } diff --git a/sql/item.cc b/sql/item.cc index bb1aa80f642..5dd10c292f9 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7363,7 +7363,7 @@ Item *Item::build_pushable_cond(THD *thd, List<Item> equalities; Item *new_cond= NULL; if (((Item_equal *)this)->create_pushable_equalities(thd, &equalities, - checker, arg) || + checker, arg, true) || (equalities.elements == 0)) return 0; @@ -10564,3 +10564,15 @@ void Item::register_in(THD *thd) next= thd->free_list; thd->free_list= this; } + + +bool Item::cleanup_excluding_immutables_processor (void *arg) +{ + if (!(get_extraction_flag() == IMMUTABLE_FL)) + return cleanup_processor(arg); + else + { + clear_extraction_flag(); + return false; + } +} diff --git a/sql/item.h b/sql/item.h index c1f68a4f942..2ba7ba6874d 100644 --- a/sql/item.h +++ b/sql/item.h @@ -152,8 +152,10 @@ bool mark_unsupported_function(const char *w1, const char *w2, #define NO_EXTRACTION_FL (1 << 6) #define FULL_EXTRACTION_FL (1 << 7) #define DELETION_FL (1 << 8) -#define SUBSTITUTION_FL (1 << 9) -#define EXTRACTION_MASK (NO_EXTRACTION_FL | FULL_EXTRACTION_FL | DELETION_FL) +#define IMMUTABLE_FL (1 << 9) +#define SUBSTITUTION_FL (1 << 10) +#define EXTRACTION_MASK \ + (NO_EXTRACTION_FL | FULL_EXTRACTION_FL | DELETION_FL | IMMUTABLE_FL) extern const char *item_empty_name; @@ -1875,6 +1877,7 @@ public: virtual bool cleanup_processor(void *arg); virtual bool cleanup_excluding_fields_processor (void *arg) { return cleanup_processor(arg); } + bool cleanup_excluding_immutables_processor (void *arg); virtual bool cleanup_excluding_const_fields_processor (void *arg) { return cleanup_processor(arg); } virtual bool collect_item_field_processor(void *arg) { return 0; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 4090c39e5e0..b54a78aca97 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -7519,6 +7519,7 @@ Item_equal::excl_dep_on_grouping_fields(st_select_lex *sel) of the tree of the object to check if multiple equality elements can be used to create equalities @param arg parameter to be passed to the checker + @param clone_const true <=> clone the constant member if there is any @details How the method works on examples: @@ -7529,36 +7530,31 @@ Item_equal::excl_dep_on_grouping_fields(st_select_lex *sel) Example 2: It takes MULT_EQ(1,a,b) and tries to create from its elements a set of - equalities {(1=a),(1=b)}. + equalities {(a=1),(a=b)}. How it is done: - 1. The method finds the left part of the equalities to be built. It will - be the same for all equalities. It is either: - a. A constant if there is any - b. A first element in the multiple equality that satisfies - checker function + 1. If there is a constant member c the first non-constant member x for + which the function checker returns true is taken and an item for + the equality x=c is created. When constructing the equality item + the left part of the equality is always taken as a clone of x while + the right part is taken as a clone of c only if clone_const == true. - For the example 1 the left element is field 'x'. - For the example 2 it is constant '1'. + 2. After this all equalities of the form x=a (where x designates the first + non-constant member for which checker returns true and a is some other + such member of the multiplle equality) are created. When constructing + an equality item both its parts are taken as clones of x and a. - 2. If the left element is found the rest elements of the multiple equality - are checked with the checker function if they can be right parts - of equalities. - If the element can be a right part of the equality, equality is built. - It is built with the left part element found at the step 1 and - the right part element found at this step (step 2). - - Suppose for the example above that both 'a' and 'b' fields can be used - to build equalities: + Suppose in the examples above that for 'x', 'a', and 'b' the function + checker returns true. Example 1: - for 'a' field (x=a) is built - for 'b' field (x=b) is built + the equality (x=a) is built + the equality (x=b) is built Example 2: - for 'a' field (1=a) is built - for 'b' field (1=b) is built + the equality (a=1) is built + the equality (a=b) is built 3. As a result we get a set of equalities built with the elements of this multiple equality. They are saved in the equality list. @@ -7567,15 +7563,17 @@ Item_equal::excl_dep_on_grouping_fields(st_select_lex *sel) {(x=a),(x=b)} Example 2: - {(1=a),(1=b)} + {(a=1),(a=b)} @note This method is called for condition pushdown into materialized derived table/view, and IN subquery, and pushdown from HAVING into WHERE. When it is called for pushdown from HAVING the empty checker is passed. - It happens because elements of this multiple equality don't need to be - checked if they can be used to build equalities. There are no elements - that can't be used to build equalities. + This is because in this case the elements of the multiple equality don't + need to be checked if they can be used to build equalities: either all + equalities can be pushed or none of them can be pushed. + When the function is called for pushdown from HAVING the value of the + parameter clone_const is always false. In other cases it's always true. @retval true if an error occurs @retval false otherwise @@ -7584,24 +7582,42 @@ Item_equal::excl_dep_on_grouping_fields(st_select_lex *sel) bool Item_equal::create_pushable_equalities(THD *thd, List<Item> *equalities, Pushdown_checker checker, - uchar *arg) + uchar *arg, + bool clone_const) { Item *item; + Item *left_item= NULL; + Item *right_item = get_const(); Item_equal_fields_iterator it(*this); - Item *left_item = get_const(); - if (!left_item) + + while ((item=it++)) { - while ((item=it++)) - { - left_item= item; - if (checker && !((item->*checker) (arg))) - continue; - break; - } + left_item= item; + if (checker && !((item->*checker) (arg))) + continue; + break; } + if (!left_item) return false; + if (right_item) + { + Item_func_eq *eq= 0; + Item *left_item_clone= left_item->build_clone(thd); + Item *right_item_clone= !clone_const ? + right_item : right_item->build_clone(thd); + if (!left_item_clone || !right_item_clone) + return true; + eq= new (thd->mem_root) Item_func_eq(thd, + left_item_clone, + right_item_clone); + if (!eq || equalities->push_back(eq, thd->mem_root)) + return true; + if (!clone_const) + right_item->set_extraction_flag(IMMUTABLE_FL); + } + while ((item=it++)) { if (checker && !((item->*checker) (arg))) @@ -7609,15 +7625,14 @@ bool Item_equal::create_pushable_equalities(THD *thd, Item_func_eq *eq= 0; Item *left_item_clone= left_item->build_clone(thd); Item *right_item_clone= item->build_clone(thd); - if (left_item_clone && right_item_clone) - { - left_item_clone->set_item_equal(NULL); - right_item_clone->set_item_equal(NULL); - eq= new (thd->mem_root) Item_func_eq(thd, - right_item_clone, - left_item_clone); - } - if (eq && equalities->push_back(eq, thd->mem_root)) + if (!(left_item_clone && right_item_clone)) + return true; + left_item_clone->set_item_equal(NULL); + right_item_clone->set_item_equal(NULL); + eq= new (thd->mem_root) Item_func_eq(thd, + right_item_clone, + left_item_clone); + if (!eq || equalities->push_back(eq, thd->mem_root)) return true; } return false; @@ -7642,7 +7657,7 @@ bool Item_equal::create_pushable_equalities(THD *thd, Item *Item_equal::multiple_equality_transformer(THD *thd, uchar *arg) { List<Item> equalities; - if (create_pushable_equalities(thd, &equalities, 0, 0)) + if (create_pushable_equalities(thd, &equalities, 0, 0, false)) return 0; switch (equalities.elements) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index b2938ee509c..9b20fa50214 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -3198,7 +3198,8 @@ public: bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred); bool excl_dep_on_grouping_fields(st_select_lex *sel); bool create_pushable_equalities(THD *thd, List<Item> *equalities, - Pushdown_checker checker, uchar *arg); + Pushdown_checker checker, uchar *arg, + bool clone_const); /* Return the number of elements in this multiple equality */ uint elements_count() { return equal_items.elements; } friend class Item_equal_fields_iterator; diff --git a/sql/item_func.cc b/sql/item_func.cc index 70fbb3f8bf6..21ed478f24a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -123,7 +123,8 @@ Item_args::Item_args(THD *thd, const Item_args *other) arg_count= 0; return; } - memcpy(args, other->args, sizeof(Item*) * arg_count); + if (arg_count) + memcpy(args, other->args, sizeof(Item*) * arg_count); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 5082dfd119a..5fb7ee0ea61 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2651,11 +2651,10 @@ bool Item_func_format::fix_length_and_dec() { uint32 char_length= args[0]->type_handler()->Item_decimal_notation_int_digits(args[0]); uint dec= FORMAT_MAX_DECIMALS; - if (args[1]->const_item() && !args[1]->is_expensive()) + if (args[1]->const_item() && !args[1]->is_expensive() && !args[1]->null_value) { Longlong_hybrid tmp= args[1]->to_longlong_hybrid(); - if (!args[1]->null_value) - dec= tmp.to_uint(FORMAT_MAX_DECIMALS); + dec= tmp.to_uint(FORMAT_MAX_DECIMALS); } uint32 max_sep_count= (char_length / 3) + (dec ? 1 : 0) + /*sign*/1; collation.set(default_charset()); diff --git a/sql/log.cc b/sql/log.cc index c0dbfa6ba5d..bf19946210a 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -488,6 +488,7 @@ private: void truncate(my_off_t pos, bool reset_cache=0) { DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos)); + cache_log.error=0; if (pending()) { delete pending(); @@ -496,7 +497,7 @@ private: reinit_io_cache(&cache_log, WRITE_CACHE, pos, 0, reset_cache); cache_log.end_of_file= saved_max_binlog_cache_size; } - + binlog_cache_data& operator=(const binlog_cache_data& info); binlog_cache_data(const binlog_cache_data& info); }; diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc index 4fc386a0afe..7e4c2ed1f53 100644 --- a/sql/multi_range_read.cc +++ b/sql/multi_range_read.cc @@ -19,6 +19,7 @@ #include "sql_select.h" #include "key.h" #include "sql_statistics.h" +#include "rowid_filter.h" static ulonglong key_block_no(TABLE *table, uint keyno, ha_rows keyentry_pos) { @@ -709,6 +710,20 @@ int Mrr_ordered_rndpos_reader::init(handler *h_arg, is_mrr_assoc= !MY_TEST(mode & HA_MRR_NO_ASSOCIATION); index_reader_exhausted= FALSE; index_reader_needs_refill= TRUE; + + /* + Currently usage of a rowid filter within InnoDB engine is not supported + if the table is accessed by the primary key. + With optimizer switches ''mrr' and 'mrr_sort_keys' are both enabled + any access by a secondary index is converted to the rndpos access. In + InnoDB the rndpos access is always uses the primary key. + Do not use pushed rowid filter if the table is accessed actually by the + primary key. Use the rowid filter outside the engine code (see + Mrr_ordered_rndpos_reader::refill_from_index_reader). + */ + if (file->pushed_rowid_filter && file->primary_key_is_clustered()) + file->cancel_pushed_rowid_filter(); + return 0; } @@ -801,6 +816,15 @@ int Mrr_ordered_rndpos_reader::refill_from_index_reader() index_reader->position(); + /* + If the built rowid filter cannot be used at the engine level use it here. + */ + Rowid_filter *rowid_filter= + file->get_table()->reginfo.join_tab->rowid_filter; + if (rowid_filter && !file->pushed_rowid_filter && + !rowid_filter->check((char *)index_rowid)) + continue; + /* Put rowid, or {rowid, range_id} pair into the buffer */ rowid_buffer->write_ptr1= index_rowid; rowid_buffer->write_ptr2= (uchar*)&range_info; diff --git a/sql/sp.cc b/sql/sp.cc index 3768b883921..4e958aedc44 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -854,7 +854,7 @@ static sp_head *sp_compile(THD *thd, String *defstr, sql_mode_t sql_mode, if (parse_sql(thd, & parser_state, creation_ctx) || thd->lex == NULL) { sp= thd->lex->sphead; - delete sp; + sp_head::destroy(sp); sp= 0; } else diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index 99e68cd2595..e4ffbdcb155 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -283,7 +283,7 @@ uchar *hash_get_key_for_sp_head(const uchar *ptr, size_t *plen, void hash_free_sp_head(void *p) { sp_head *sp= (sp_head *)p; - delete sp; + sp_head::destroy(sp); } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 3830fe60b4e..cd5a836e8b5 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2002, 2016, Oracle and/or its affiliates. - Copyright (c) 2011, 2017, MariaDB + Copyright (c) 2011, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -450,49 +450,47 @@ check_routine_name(const LEX_CSTRING *ident) * sp_head * */ - -void * -sp_head::operator new(size_t size) throw() + +sp_head *sp_head::create(sp_package *parent, const Sp_handler *handler, + enum_sp_aggregate_type agg_type) { - DBUG_ENTER("sp_head::operator new"); MEM_ROOT own_root; + init_sql_alloc(&own_root, "sp_head", MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC, + MYF(0)); sp_head *sp; + if (!(sp= new (&own_root) sp_head(&own_root, parent, handler, agg_type))) + free_root(&own_root, MYF(0)); - init_sql_alloc(&own_root, "sp_head", - MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC, MYF(0)); - sp= (sp_head *) alloc_root(&own_root, size); - if (sp == NULL) - DBUG_RETURN(NULL); - sp->main_mem_root= own_root; - DBUG_PRINT("info", ("mem_root %p", &sp->mem_root)); - DBUG_RETURN(sp); + return sp; } -void -sp_head::operator delete(void *ptr, size_t size) throw() -{ - DBUG_ENTER("sp_head::operator delete"); - MEM_ROOT own_root; - if (ptr == NULL) - DBUG_VOID_RETURN; - - sp_head *sp= (sp_head *) ptr; - - /* Make a copy of main_mem_root as free_root will free the sp */ - own_root= sp->main_mem_root; - DBUG_PRINT("info", ("mem_root %p moved to %p", - &sp->mem_root, &own_root)); - free_root(&own_root, MYF(0)); - - DBUG_VOID_RETURN; +void sp_head::destroy(sp_head *sp) +{ + if (sp) + { + /* Make a copy of main_mem_root as free_root will free the sp */ + MEM_ROOT own_root= sp->main_mem_root; + DBUG_PRINT("info", ("mem_root %p moved to %p", + &sp->mem_root, &own_root)); + delete sp; + + + free_root(&own_root, MYF(0)); + } } +/* + * + * sp_head + * + */ -sp_head::sp_head(sp_package *parent, const Sp_handler *sph, - enum_sp_aggregate_type agg_type) - :Query_arena(&main_mem_root, STMT_INITIALIZED_FOR_SP), +sp_head::sp_head(MEM_ROOT *mem_root_arg, sp_package *parent, + const Sp_handler *sph, enum_sp_aggregate_type agg_type) + :Query_arena(NULL, STMT_INITIALIZED_FOR_SP), Database_qualified_name(&null_clex_str, &null_clex_str), + main_mem_root(*mem_root_arg), m_parent(parent), m_handler(sph), m_flags(0), @@ -523,6 +521,8 @@ sp_head::sp_head(sp_package *parent, const Sp_handler *sph, m_pcont(new (&main_mem_root) sp_pcontext()), m_cont_level(0) { + mem_root= &main_mem_root; + set_chistics_agg_type(agg_type); m_first_instance= this; m_first_free_instance= this; @@ -547,10 +547,25 @@ sp_head::sp_head(sp_package *parent, const Sp_handler *sph, } -sp_package::sp_package(LEX *top_level_lex, +sp_package *sp_package::create(LEX *top_level_lex, const sp_name *name, + const Sp_handler *sph) +{ + MEM_ROOT own_root; + init_sql_alloc(&own_root, "sp_package", MEM_ROOT_BLOCK_SIZE, + MEM_ROOT_PREALLOC, MYF(0)); + sp_package *sp; + if (!(sp= new (&own_root) sp_package(&own_root, top_level_lex, name, sph))) + free_root(&own_root, MYF(0)); + + return sp; +} + + +sp_package::sp_package(MEM_ROOT *mem_root_arg, + LEX *top_level_lex, const sp_name *name, const Sp_handler *sph) - :sp_head(NULL, sph, DEFAULT_AGGREGATE), + :sp_head(mem_root_arg, NULL, sph, DEFAULT_AGGREGATE), m_current_routine(NULL), m_top_level_lex(top_level_lex), m_rcontext(NULL), @@ -568,7 +583,7 @@ sp_package::~sp_package() m_routine_declarations.cleanup(); m_body= null_clex_str; if (m_current_routine) - delete m_current_routine->sphead; + sp_head::destroy(m_current_routine->sphead); delete m_rcontext; } @@ -825,7 +840,7 @@ sp_head::~sp_head() my_hash_free(&m_sptabs); my_hash_free(&m_sroutines); - delete m_next_cached_sp; + sp_head::destroy(m_next_cached_sp); DBUG_VOID_RETURN; } diff --git a/sql/sp_head.h b/sql/sp_head.h index 3085c248924..6cf4610c466 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -1,6 +1,7 @@ /* -*- C++ -*- */ /* Copyright (c) 2002, 2011, Oracle and/or its affiliates. + Copyright (c) 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -124,10 +125,11 @@ bool check_routine_name(const LEX_CSTRING *ident); class sp_head :private Query_arena, - public Database_qualified_name + public Database_qualified_name, + public Sql_alloc { - sp_head(const sp_head &); /**< Prevent use of these */ - void operator=(sp_head &); + sp_head(const sp_head &)= delete; + void operator=(sp_head &)= delete; protected: MEM_ROOT main_mem_root; @@ -318,14 +320,14 @@ public: */ SQL_I_List<Item_trigger_field> m_trg_table_fields; - static void * - operator new(size_t size) throw (); - - static void - operator delete(void *ptr, size_t size) throw (); - - sp_head(sp_package *parent, const Sp_handler *handler, - enum_sp_aggregate_type); +protected: + sp_head(MEM_ROOT *mem_root, sp_package *parent, const Sp_handler *handler, + enum_sp_aggregate_type agg_type); + virtual ~sp_head(); +public: + static void destroy(sp_head *sp); + static sp_head *create(sp_package *parent, const Sp_handler *handler, + enum_sp_aggregate_type agg_type); /// Initialize after we have reset mem_root void @@ -343,7 +345,6 @@ public: void set_stmt_end(THD *thd); - virtual ~sp_head(); bool execute_trigger(THD *thd, @@ -968,10 +969,16 @@ public: bool m_is_instantiated; bool m_is_cloning_routine; - sp_package(LEX *top_level_lex, +private: + sp_package(MEM_ROOT *mem_root, + LEX *top_level_lex, const sp_name *name, const Sp_handler *sph); ~sp_package(); +public: + static sp_package *create(LEX *top_level_lex, const sp_name *name, + const Sp_handler *sph); + bool add_routine_declaration(LEX *lex) { return m_routine_declarations.check_dup_qualified(lex->sphead) || diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b3ab9aa7ea7..b9a65e17a3a 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1334,7 +1334,7 @@ void lex_end_stage1(LEX *lex) } else { - delete lex->sphead; + sp_head::destroy(lex->sphead); lex->sphead= NULL; } @@ -3650,13 +3650,13 @@ void LEX::cleanup_lex_after_parse_error(THD *thd) DBUG_ASSERT(pkg == pkg->m_top_level_lex->sphead); pkg->restore_thd_mem_root(thd); LEX *top= pkg->m_top_level_lex; - delete pkg; + sp_package::destroy(pkg); thd->lex= top; thd->lex->sphead= NULL; } else { - delete thd->lex->sphead; + sp_head::destroy(thd->lex->sphead); thd->lex->sphead= NULL; } } @@ -7042,7 +7042,7 @@ sp_head *LEX::make_sp_head(THD *thd, const sp_name *name, sp_head *sp; /* Order is important here: new - reset - init */ - if (likely((sp= new sp_head(package, sph, agg_type)))) + if (likely((sp= sp_head::create(package, sph, agg_type)))) { sp->reset_thd_mem_root(thd); sp->init(this); @@ -8539,7 +8539,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(THD *thd, Item *cond) } else { - int fl= cond->excl_dep_on_grouping_fields(this) ? + int fl= cond->excl_dep_on_grouping_fields(this) && !cond->is_expensive() ? FULL_EXTRACTION_FL : NO_EXTRACTION_FL; cond->set_extraction_flag(fl); } @@ -8962,7 +8962,7 @@ sp_package *LEX::create_package_start(THD *thd, return 0; } } - if (unlikely(!(pkg= new sp_package(this, name_arg, sph)))) + if (unlikely(!(pkg= sp_package::create(this, name_arg, sph)))) return NULL; pkg->reset_thd_mem_root(thd); pkg->init(this); @@ -10394,7 +10394,7 @@ st_select_lex::build_pushable_cond_for_having_pushdown(THD *thd, Item *cond) { List_iterator<Item> li(*((Item_cond*) result)->argument_list()); Item *item; - while ((item=li++)) + while ((item= li++)) { if (attach_to_conds.push_back(item, thd->mem_root)) return true; @@ -10414,8 +10414,13 @@ st_select_lex::build_pushable_cond_for_having_pushdown(THD *thd, Item *cond) */ if (cond->type() != Item::COND_ITEM) return false; + if (((Item_cond *)cond)->functype() != Item_cond::COND_AND_FUNC) { + /* + cond is not a conjunctive formula and it cannot be pushed into WHERE. + Try to extract a formula that can be pushed. + */ Item *fix= cond->build_pushable_cond(thd, 0, 0); if (!fix) return false; @@ -10435,7 +10440,6 @@ st_select_lex::build_pushable_cond_for_having_pushdown(THD *thd, Item *cond) Item *result= item->transform(thd, &Item::multiple_equality_transformer, (uchar *)item); - if (!result) return true; if (result->type() == Item::COND_ITEM && @@ -10763,8 +10767,8 @@ Item *st_select_lex::pushdown_from_having_into_where(THD *thd, Item *having) &Item::field_transformer_for_having_pushdown, (uchar *)this); - if (item->walk(&Item:: cleanup_processor, 0, STOP_PTR) || - item->fix_fields(thd, NULL)) + if (item->walk(&Item::cleanup_excluding_immutables_processor, 0, STOP_PTR) + || item->fix_fields(thd, NULL)) { attach_to_conds.empty(); goto exit; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b9f080fdde2..f420aa01a92 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5168,7 +5168,7 @@ mysql_execute_command(THD *thd) /* Don't do it, if we are inside a SP */ if (!thd->spcont) { - delete lex->sphead; + sp_head::destroy(lex->sphead); lex->sphead= NULL; } /* lex->unit.cleanup() is called outside, no need to call it here */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 424a039a5be..29f629280b7 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3877,7 +3877,7 @@ Prepared_statement::~Prepared_statement() free_items(); if (lex) { - delete lex->sphead; + sp_head::destroy(lex->sphead); delete lex->result; delete (st_lex_local *) lex; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index bece1f9bee2..8912ec79011 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11601,6 +11601,13 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) if (i != join->const_tables && tab->use_quick != 2 && !tab->first_inner) { /* Read with cache */ + /* + TODO: the execution also gets here when we will not be using + join buffer. Review these cases and perhaps, remove this call. + (The final decision whether to use join buffer is made in + check_join_cache_usage, so we should only call make_scan_filter() + there, too). + */ if (tab->make_scan_filter()) DBUG_RETURN(1); } @@ -12577,6 +12584,9 @@ uint check_join_cache_usage(JOIN_TAB *tab, if ((tab->cache= new (root) JOIN_CACHE_BNL(join, tab, prev_cache))) { tab->icp_other_tables_ok= FALSE; + /* If make_join_select() hasn't called make_scan_filter(), do it now */ + if (!tab->cache_select && tab->make_scan_filter()) + goto no_join_cache; return (2 - MY_TEST(!prev_cache)); } goto no_join_cache; @@ -15250,12 +15260,15 @@ static int compare_fields_by_table_order(Item *field1, { int cmp= 0; bool outer_ref= 0; - Item_field *f1= (Item_field *) (field1->real_item()); - Item_field *f2= (Item_field *) (field2->real_item()); - if (field1->const_item() || f1->const_item()) + Item *field1_real= field1->real_item(); + Item *field2_real= field2->real_item(); + + if (field1->const_item() || field1_real->const_item()) return -1; - if (field2->const_item() || f2->const_item()) + if (field2->const_item() || field2_real->const_item()) return 1; + Item_field *f1= (Item_field *) field1_real; + Item_field *f2= (Item_field *) field2_real; if (f1->used_tables() & OUTER_REF_TABLE_BIT) { outer_ref= 1; @@ -23354,6 +23367,19 @@ check_reverse_order: join_read_first:join_read_last; tab->type=JT_NEXT; // Read with index_first(), index_next() + /* + Currently usage of rowid filters is not supported in InnoDB + if the table is accessed by the primary key + */ + if (tab->rowid_filter && + tab->index == table->s->primary_key && + table->file->primary_key_is_clustered()) + { + tab->range_rowid_filter_info= 0; + delete tab->rowid_filter; + tab->rowid_filter= 0; + } + if (tab->pre_idx_push_select_cond) { tab->set_cond(tab->pre_idx_push_select_cond); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 278b4ac4268..40ecb7b1fe5 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -6248,7 +6248,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, { free_table_share(&share); if (free_sp_head) - delete sp; + sp_head::destroy(sp); DBUG_RETURN(1); } } @@ -6295,7 +6295,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, } } if (free_sp_head) - delete sp; + sp_head::destroy(sp); } free_table_share(&share); DBUG_RETURN(error); @@ -6373,7 +6373,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, store_column_type(table, field, cs, 5); free_table_share(&share); if (free_sp_head) - delete sp; + sp_head::destroy(sp); } } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index f9b9e4dd4f1..5802d2c811e 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -329,7 +329,7 @@ public: Trigger::~Trigger() { - delete body; + sp_head::destroy(body); } diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 2e1d962d5e7..9e8375afd10 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -4083,7 +4083,7 @@ Type_handler_general_purpose_int::Item_decimal_notation_int_digits( /*************************************************************************/ /* - Decimal to binary digits ratio converges to log2(10) thus using 3 as + Binary to Decimal digits ratio converges to log2(10) thus using 3 as a divisor. */ uint32 diff --git a/sql/sql_type.h b/sql/sql_type.h index 7f5faffcd8d..54e06b1ec6b 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -5606,6 +5606,8 @@ public: uint32 max_display_length(const Item *item) const override { return 25; } uint32 max_display_length_for_field(const Conv_source &src) const override { return 12; } + uint32 Item_decimal_notation_int_digits(const Item *item) const override + { return 39; } uint32 calc_pack_length(uint32 length) const override { return sizeof(float); } Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc index 2bd15a5a77f..06d398baf5f 100644 --- a/sql/wsrep_high_priority_service.cc +++ b/sql/wsrep_high_priority_service.cc @@ -448,6 +448,7 @@ int Wsrep_high_priority_service::log_dummy_write_set(const wsrep::ws_handle& ws_ cs.before_rollback(); cs.after_rollback(); } + wsrep_set_SE_checkpoint(ws_meta.gtid()); ret= ret || cs.provider().commit_order_leave(ws_handle, ws_meta, err); cs.after_applying(); } diff --git a/sql/wsrep_server_service.cc b/sql/wsrep_server_service.cc index aa288e67420..d0a9b54ac1b 100644 --- a/sql/wsrep_server_service.cc +++ b/sql/wsrep_server_service.cc @@ -302,6 +302,12 @@ wsrep::gtid Wsrep_server_service::get_position(wsrep::client_service&) return wsrep_get_SE_checkpoint(); } +void Wsrep_server_service::set_position(wsrep::client_service&, + const wsrep::gtid& gtid) +{ + wsrep_set_SE_checkpoint(gtid); +} + void Wsrep_server_service::log_state_change( enum Wsrep_server_state::state prev_state, enum Wsrep_server_state::state current_state) diff --git a/sql/wsrep_server_service.h b/sql/wsrep_server_service.h index 4017c9b2d58..168e98206e3 100644 --- a/sql/wsrep_server_service.h +++ b/sql/wsrep_server_service.h @@ -61,6 +61,7 @@ public: wsrep::view get_view(wsrep::client_service&, const wsrep::id& own_id); wsrep::gtid get_position(wsrep::client_service&); + void set_position(wsrep::client_service&, const wsrep::gtid&); void log_state_change(enum wsrep::server_state::state, enum wsrep::server_state::state); diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 7f1818def73..5ae583212f3 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -84,42 +84,57 @@ static void wsrep_replication_process(THD *thd, DBUG_VOID_RETURN; } -static bool create_wsrep_THD(Wsrep_thd_args* args) +static bool create_wsrep_THD(Wsrep_thd_args* args, bool mutex_protected) { + if (!mutex_protected) + mysql_mutex_lock(&LOCK_wsrep_slave_threads); + ulong old_wsrep_running_threads= wsrep_running_threads; + DBUG_ASSERT(args->thread_type() == WSREP_APPLIER_THREAD || args->thread_type() == WSREP_ROLLBACKER_THREAD); + bool res= mysql_thread_create(args->thread_type() == WSREP_APPLIER_THREAD ? key_wsrep_applier : key_wsrep_rollbacker, args->thread_id(), &connection_attrib, start_wsrep_THD, (void*)args); + + if (res) + WSREP_ERROR("Can't create wsrep thread"); + /* if starting a thread on server startup, wait until the this thread's THD is fully initialized (otherwise a THD initialization code might try to access a partially initialized server data structure - MDEV-8208). */ - mysql_mutex_lock(&LOCK_wsrep_slave_threads); if (!mysqld_server_initialized) + { while (old_wsrep_running_threads == wsrep_running_threads) + { mysql_cond_wait(&COND_wsrep_slave_threads, &LOCK_wsrep_slave_threads); - mysql_mutex_unlock(&LOCK_wsrep_slave_threads); + } + } + + if (!mutex_protected) + mysql_mutex_unlock(&LOCK_wsrep_slave_threads); + return res; } -void wsrep_create_appliers(long threads) +bool wsrep_create_appliers(long threads, bool mutex_protected) { /* Dont' start slave threads if wsrep-provider or wsrep-cluster-address is not set. */ if (!WSREP_PROVIDER_EXISTS) { - return; + return false; } if (!wsrep_cluster_address || wsrep_cluster_address[0]== 0) { WSREP_DEBUG("wsrep_create_appliers exit due to empty address"); - return; + return false; } long wsrep_threads=0; @@ -129,11 +144,14 @@ void wsrep_create_appliers(long threads) Wsrep_thd_args* args(new Wsrep_thd_args(wsrep_replication_process, WSREP_APPLIER_THREAD, pthread_self())); - if (create_wsrep_THD(args)) + if (create_wsrep_THD(args, mutex_protected)) { WSREP_WARN("Can't create thread to manage wsrep replication"); + return true; } } + + return false; } static void wsrep_remove_streaming_fragments(THD* thd, const char* ctx) @@ -279,7 +297,7 @@ void wsrep_create_rollbacker() pthread_self())); /* create rollbacker */ - if (create_wsrep_THD(args)) + if (create_wsrep_THD(args, false)) WSREP_WARN("Can't create thread to manage wsrep rollback"); } } diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index f98c15a5a85..d24d8e6358f 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -84,7 +84,7 @@ private: int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff, enum enum_var_type scope); -void wsrep_create_appliers(long threads); +bool wsrep_create_appliers(long threads, bool mutex_protected=false); void wsrep_create_rollbacker(); bool wsrep_bf_abort(const THD*, THD*); diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 315cfe2c53e..5f76f650b34 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -594,15 +594,22 @@ static void wsrep_slave_count_change_update () bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type) { + mysql_mutex_lock(&LOCK_wsrep_slave_threads); + bool res= false; + wsrep_slave_count_change_update(); + if (wsrep_slave_count_change > 0) { WSREP_DEBUG("Creating %d applier threads, total %ld", wsrep_slave_count_change, wsrep_slave_threads); - wsrep_create_appliers(wsrep_slave_count_change); + res= wsrep_create_appliers(wsrep_slave_count_change, true); WSREP_DEBUG("Running %lu applier threads", wsrep_running_applier_threads); wsrep_slave_count_change = 0; } - return false; + + mysql_mutex_unlock(&LOCK_wsrep_slave_threads); + + return res; } bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var) |
