summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/handle_connections_win.cc3
-rw-r--r--sql/item.cc14
-rw-r--r--sql/item.h7
-rw-r--r--sql/item_cmpfunc.cc105
-rw-r--r--sql/item_cmpfunc.h3
-rw-r--r--sql/item_func.cc3
-rw-r--r--sql/item_strfunc.cc5
-rw-r--r--sql/log.cc3
-rw-r--r--sql/multi_range_read.cc24
-rw-r--r--sql/sp.cc2
-rw-r--r--sql/sp_cache.cc2
-rw-r--r--sql/sp_head.cc89
-rw-r--r--sql/sp_head.h33
-rw-r--r--sql/sql_lex.cc24
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sql_select.cc34
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_trigger.cc2
-rw-r--r--sql/sql_type.cc2
-rw-r--r--sql/sql_type.h2
-rw-r--r--sql/wsrep_high_priority_service.cc1
-rw-r--r--sql/wsrep_server_service.cc6
-rw-r--r--sql/wsrep_server_service.h1
-rw-r--r--sql/wsrep_thd.cc34
-rw-r--r--sql/wsrep_thd.h2
-rw-r--r--sql/wsrep_var.cc11
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)