summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-04-25 21:57:52 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-04-25 21:57:52 +0300
commitfbe2712705d464bf8488df249c36115e2c1f63f7 (patch)
tree274e728c719611769288afcb10f79549f6e11f8c /sql
parent62903434eb009cb0bcd5003b0a45914bd4c09886 (diff)
parenta19782522b1eac52d72f5e787b5d96f1fd1a2cb7 (diff)
downloadmariadb-git-fbe2712705d464bf8488df249c36115e2c1f63f7.tar.gz
Merge 10.4 into 10.5
The functional changes of commit 5836191c8f0658d5d75484766fdcc3d838b0a5c1 (MDEV-21168) are omitted due to MDEV-742 having addressed the issue.
Diffstat (limited to 'sql')
-rw-r--r--sql/field_comp.cc22
-rw-r--r--sql/handler.cc38
-rw-r--r--sql/item.cc8
-rw-r--r--sql/item.h19
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/lock.cc13
-rw-r--r--sql/log.cc9
-rw-r--r--sql/log_event_server.cc13
-rw-r--r--sql/mdl.cc4
-rw-r--r--sql/mysqld.cc45
-rw-r--r--sql/mysqld.h2
-rw-r--r--sql/opt_range.cc40
-rw-r--r--sql/rpl_parallel.cc2
-rw-r--r--sql/rpl_record.cc16
-rw-r--r--sql/rpl_rli.h2
-rw-r--r--sql/slave.cc15
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_lex.cc10
-rw-r--r--sql/sql_parse.cc10
-rw-r--r--sql/sql_partition.cc18
-rw-r--r--sql/sql_plugin.h2
-rw-r--r--sql/sql_reload.cc2
-rw-r--r--sql/sql_repl.cc2
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_string.h2
-rw-r--r--sql/sql_table.cc30
-rw-r--r--sql/sql_type_geom.cc2
-rw-r--r--sql/sql_update.cc6
-rw-r--r--sql/sys_vars.cc2
-rw-r--r--sql/temporary_tables.cc6
-rw-r--r--sql/wsrep_mysqld.cc46
-rw-r--r--sql/wsrep_mysqld.h22
-rw-r--r--sql/wsrep_sst.cc1
-rw-r--r--sql/wsrep_thd.cc12
-rw-r--r--sql/wsrep_trans_observer.h2
-rw-r--r--sql/wsrep_var.cc12
-rw-r--r--sql/xa.cc3
38 files changed, 285 insertions, 165 deletions
diff --git a/sql/field_comp.cc b/sql/field_comp.cc
index eb4ae42aa4d..ab97c8ccf08 100644
--- a/sql/field_comp.cc
+++ b/sql/field_comp.cc
@@ -67,10 +67,12 @@ static uint compress_zlib(THD *thd, char *to, const char *from, uint length)
stream.zfree= 0;
stream.opaque= 0;
- if (deflateInit2(&stream, level, Z_DEFLATED, wbits, 8, strategy) == Z_OK &&
- deflate(&stream, Z_FINISH) == Z_STREAM_END &&
- deflateEnd(&stream) == Z_OK)
- return (uint) (stream.next_out - (Bytef*) to);
+ if (deflateInit2(&stream, level, Z_DEFLATED, wbits, 8, strategy) == Z_OK)
+ {
+ int res= deflate(&stream, Z_FINISH);
+ if (deflateEnd(&stream) == Z_OK && res == Z_STREAM_END)
+ return (uint) (stream.next_out - (Bytef*) to);
+ }
}
return 0;
}
@@ -117,12 +119,14 @@ static int uncompress_zlib(String *to, const uchar *from, uint from_length,
stream.zfree= 0;
stream.opaque= 0;
- if (inflateInit2(&stream, wbits) == Z_OK &&
- inflate(&stream, Z_FINISH) == Z_STREAM_END &&
- inflateEnd(&stream) == Z_OK)
+ if (inflateInit2(&stream, wbits) == Z_OK)
{
- to->length(stream.total_out);
- return 0;
+ int res= inflate(&stream, Z_FINISH);
+ if (inflateEnd(&stream) == Z_OK && res == Z_STREAM_END)
+ {
+ to->length(stream.total_out);
+ return 0;
+ }
}
my_error(ER_ZLIB_Z_DATA_ERROR, MYF(0));
return 1;
diff --git a/sql/handler.cc b/sql/handler.cc
index 893453ba1c2..4f99b6e675f 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1808,7 +1808,8 @@ end:
thd->mdl_context.release_lock(mdl_request.ticket);
}
#ifdef WITH_WSREP
- if (wsrep_is_active(thd) && is_real_trans && !error && (rw_ha_count == 0) &&
+ if (wsrep_is_active(thd) && is_real_trans && !error &&
+ (rw_ha_count == 0 || all) &&
wsrep_not_committed(thd))
{
wsrep_commit_empty(thd, all);
@@ -2105,29 +2106,33 @@ int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
#ifndef DBUG_OFF
-/**
- @note
- This does not need to be multi-byte safe or anything
-*/
-static char* xid_to_str(char *buf, XID *xid)
+/** Converts XID to string.
+
+@param[out] buf output buffer
+@param[in] xid XID to convert
+
+@return pointer to converted string
+
+@note This does not need to be multi-byte safe or anything */
+static char *xid_to_str(char *buf, const XID &xid)
{
int i;
char *s=buf;
*s++='\'';
- for (i=0; i < xid->gtrid_length+xid->bqual_length; i++)
+ for (i= 0; i < xid.gtrid_length + xid.bqual_length; i++)
{
- uchar c=(uchar)xid->data[i];
+ uchar c= (uchar) xid.data[i];
/* is_next_dig is set if next character is a number */
bool is_next_dig= FALSE;
if (i < XIDDATASIZE)
{
- char ch= xid->data[i+1];
+ char ch= xid.data[i + 1];
is_next_dig= (ch >= '0' && ch <='9');
}
- if (i == xid->gtrid_length)
+ if (i == xid.gtrid_length)
{
*s++='\'';
- if (xid->bqual_length)
+ if (xid.bqual_length)
{
*s++='.';
*s++='\'';
@@ -2237,6 +2242,11 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
the prepare.
*/
my_xid wsrep_limit __attribute__((unused))= 0;
+
+ /* Note that we could call this for binlog also that
+ will not have WSREP(thd) but global wsrep on might
+ be true.
+ */
if (WSREP_ON)
wsrep_limit= wsrep_order_and_check_continuity(info->list, got);
@@ -2250,7 +2260,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
{
DBUG_EXECUTE("info",{
char buf[XIDDATASIZE*4+6];
- _db_doprnt_("ignore xid %s", xid_to_str(buf, info->list+i));
+ _db_doprnt_("ignore xid %s", xid_to_str(buf, info->list[i]));
});
xid_cache_insert(info->list + i);
info->found_foreign_xids++;
@@ -2277,7 +2287,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
{
DBUG_EXECUTE("info",{
char buf[XIDDATASIZE*4+6];
- _db_doprnt_("commit xid %s", xid_to_str(buf, info->list+i));
+ _db_doprnt_("commit xid %s", xid_to_str(buf, info->list[i]));
});
}
}
@@ -2288,7 +2298,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
{
DBUG_EXECUTE("info",{
char buf[XIDDATASIZE*4+6];
- _db_doprnt_("rollback xid %s", xid_to_str(buf, info->list+i));
+ _db_doprnt_("rollback xid %s", xid_to_str(buf, info->list[i]));
});
}
}
diff --git a/sql/item.cc b/sql/item.cc
index 4c1fe99e222..0c08169db2b 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9257,8 +9257,10 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
}
if (!(def_field= (Field*) thd->alloc(field_arg->field->size_of())))
goto error;
+ cached_field= def_field;
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)
{
@@ -9286,6 +9288,12 @@ error:
return TRUE;
}
+void Item_default_value::cleanup()
+{
+ delete cached_field; // Free cached blob data
+ cached_field= 0;
+ Item_field::cleanup();
+}
void Item_default_value::print(String *str, enum_query_type query_type)
{
diff --git a/sql/item.h b/sql/item.h
index 5eab1d049f0..3073a4d240d 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2,7 +2,7 @@
#define SQL_ITEM_INCLUDED
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
- Copyright (c) 2009, 2019, MariaDB Corporation.
+ Copyright (c) 2009, 2020, MariaDB Corporation.
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
@@ -6241,19 +6241,18 @@ class Item_default_value : public Item_field
{
void calculate();
public:
- Item *arg;
- Item_default_value(THD *thd, Name_resolution_context *context_arg)
- :Item_field(thd, context_arg),
- arg(NULL) {}
- Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a)
- :Item_field(thd, context_arg),
- arg(a) {}
+ Item *arg= nullptr;
+ Field *cached_field= nullptr;
+ Item_default_value(THD *thd, Name_resolution_context *context_arg) :
+ Item_field(thd, context_arg) {}
+ Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a) :
+ Item_field(thd, context_arg), arg(a) {}
Item_default_value(THD *thd, Name_resolution_context *context_arg, Field *a)
- :Item_field(thd, context_arg),
- arg(NULL) {}
+ :Item_field(thd, context_arg) {}
enum Type type() const { return DEFAULT_VALUE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
bool fix_fields(THD *, Item **);
+ void cleanup();
void print(String *str, enum_query_type query_type);
String *val_str(String *str);
double val_real();
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index e494e9d84e1..4bbb33d4eb7 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -729,7 +729,7 @@ bool Item_subselect::exec()
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_ERROR, "DBUG: Item_subselect::exec %.*s",
- print.length(),print.ptr());
+ print.length(),print.c_ptr());
);
/*
Do not execute subselect in case of a fatal error
diff --git a/sql/lock.cc b/sql/lock.cc
index 487f2c3115f..f427ee0e115 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -1,5 +1,6 @@
/*
Copyright (c) 2000, 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
@@ -1124,13 +1125,15 @@ void Global_read_lock::unlock_global_read_lock(THD *thd)
{
Wsrep_server_state& server_state= Wsrep_server_state::instance();
if (server_state.state() == Wsrep_server_state::s_donor ||
- (wsrep_on(thd) && server_state.state() != Wsrep_server_state::s_synced))
+ (WSREP_NNULL(thd) &&
+ server_state.state() != Wsrep_server_state::s_synced))
{
/* TODO: maybe redundant here?: */
wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
server_state.resume();
}
- else if (wsrep_on(thd) && server_state.state() == Wsrep_server_state::s_synced)
+ else if (WSREP_NNULL(thd) &&
+ server_state.state() == Wsrep_server_state::s_synced)
{
server_state.resume_and_resync();
}
@@ -1186,11 +1189,13 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
Wsrep_server_state& server_state= Wsrep_server_state::instance();
wsrep::seqno paused_seqno;
if (server_state.state() == Wsrep_server_state::s_donor ||
- (wsrep_on(thd) && server_state.state() != Wsrep_server_state::s_synced))
+ (WSREP_NNULL(thd) &&
+ server_state.state() != Wsrep_server_state::s_synced))
{
paused_seqno= server_state.pause();
}
- else if (wsrep_on(thd) && server_state.state() == Wsrep_server_state::s_synced)
+ else if (WSREP_NNULL(thd) &&
+ server_state.state() == Wsrep_server_state::s_synced)
{
paused_seqno= server_state.desync_and_pause();
}
diff --git a/sql/log.cc b/sql/log.cc
index fce768b2e4c..731bb3e98f0 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1834,7 +1834,7 @@ binlog_commit_flush_stmt_cache(THD *thd, bool all,
#ifdef WITH_WSREP
if (thd->wsrep_mysql_replicated > 0)
{
- DBUG_ASSERT(WSREP_ON);
+ DBUG_ASSERT(WSREP(thd));
WSREP_DEBUG("avoiding binlog_commit_flush_trx_cache: %d",
thd->wsrep_mysql_replicated);
return 0;
@@ -6924,14 +6924,15 @@ int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge)
int error= 0;
DBUG_ENTER("MYSQL_BIN_LOG::rotate");
- if (wsrep_to_isolation)
+#ifdef WITH_WSREP
+ if (WSREP_ON && wsrep_to_isolation)
{
- DBUG_ASSERT(WSREP_ON);
*check_purge= false;
- WSREP_DEBUG("avoiding binlog rotate due to TO isolation: %d",
+ WSREP_DEBUG("avoiding binlog rotate due to TO isolation: %d",
wsrep_to_isolation);
DBUG_RETURN(0);
}
+#endif /* WITH_WSREP */
//todo: fix the macro def and restore safe_mutex_assert_owner(&LOCK_log);
*check_purge= false;
diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc
index feb8fd643b7..9c69b67bce1 100644
--- a/sql/log_event_server.cc
+++ b/sql/log_event_server.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
- Copyright (c) 2009, 2019, MariaDB
+ Copyright (c) 2009, 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
@@ -1396,9 +1396,14 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
/*
If Query_log_event will contain non trans keyword (not BEGIN, COMMIT,
SAVEPOINT or ROLLBACK) we disable PA for this transaction.
+ Note that here WSREP(thd) might not be true e.g. when wsrep_shcema
+ is created we create tables with thd->variables.wsrep_on=false
+ to avoid replicating wsrep_schema tables to other nodes.
*/
if (WSREP_ON && !is_trans_keyword())
+ {
thd->wsrep_PA_safe= false;
+ }
#endif /* WITH_WSREP */
memset(&user, 0, sizeof(user));
@@ -2115,7 +2120,7 @@ Query_log_event::do_shall_skip(rpl_group_info *rgi)
}
}
#ifdef WITH_WSREP
- else if (WSREP_ON && wsrep_mysql_replication_bundle && opt_slave_domain_parallel_threads == 0 &&
+ else if (WSREP(thd) && wsrep_mysql_replication_bundle && opt_slave_domain_parallel_threads == 0 &&
thd->wsrep_mysql_replicated > 0 &&
(is_begin() || is_commit()))
{
@@ -2129,7 +2134,7 @@ Query_log_event::do_shall_skip(rpl_group_info *rgi)
thd->wsrep_mysql_replicated = 0;
}
}
-#endif
+#endif /* WITH_WSREP */
DBUG_RETURN(Log_event::do_shall_skip(rgi));
}
@@ -3976,7 +3981,7 @@ Xid_apply_log_event::do_shall_skip(rpl_group_info *rgi)
DBUG_RETURN(Log_event::EVENT_SKIP_COUNT);
}
#ifdef WITH_WSREP
- else if (wsrep_mysql_replication_bundle && WSREP_ON &&
+ else if (wsrep_mysql_replication_bundle && WSREP(thd) &&
opt_slave_domain_parallel_threads == 0)
{
if (++thd->wsrep_mysql_replicated < (int)wsrep_mysql_replication_bundle)
diff --git a/sql/mdl.cc b/sql/mdl.cc
index 98a9d8f0d01..287e0cb5f65 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -1242,12 +1242,12 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
wsrep_thd_is_BF(ticket->get_ctx()->get_thd(), false))
{
Ticket_iterator itw(ticket->get_lock()->m_waiting);
-
- DBUG_ASSERT(WSREP_ON);
MDL_ticket *waiting;
MDL_ticket *prev=NULL;
bool added= false;
+ DBUG_ASSERT(WSREP(ticket->get_ctx()->get_thd()));
+
while ((waiting= itw++) && !added)
{
if (!wsrep_thd_is_BF(waiting->get_ctx()->get_thd(), true))
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 97dfca47beb..f6aac3adfd8 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -54,6 +54,7 @@
#include <m_ctype.h>
#include <my_dir.h>
#include <my_bit.h>
+#include "my_cpu.h"
#include "slave.h"
#include "rpl_mi.h"
#include "sql_repl.h"
@@ -446,7 +447,7 @@ uint lower_case_table_names;
ulong tc_heuristic_recover= 0;
Atomic_counter<uint32_t> thread_count;
bool shutdown_wait_for_slaves;
-int32 slave_open_temp_tables;
+Atomic_counter<uint32_t> slave_open_temp_tables;
ulong thread_created;
ulong back_log, connect_timeout, server_id;
ulong what_to_log;
@@ -1135,6 +1136,14 @@ PSI_file_key key_file_map;
PSI_statement_info stmt_info_new_packet;
#endif
+#ifdef WITH_WSREP
+/** Whether the Galera write-set replication is enabled. A cached copy of
+global_system_variables.wsrep_on && wsrep_provider &&
+ strcmp(wsrep_provider, WSREP_NONE)
+*/
+bool WSREP_ON_;
+#endif /* WITH_WSREP */
+
#ifndef EMBEDDED_LIBRARY
void net_before_header_psi(struct st_net *net, void *thd, size_t /* unused: count */)
{
@@ -1873,6 +1882,9 @@ extern "C" void unireg_abort(int exit_code)
disable_log_notes= 1;
#ifdef WITH_WSREP
+ // Note that we do not have thd here, thus can't use
+ // WSREP(thd)
+
if (WSREP_ON &&
Wsrep_server_state::is_inited() &&
Wsrep_server_state::instance().state() != wsrep::server_state::s_disconnected)
@@ -1888,6 +1900,7 @@ extern "C" void unireg_abort(int exit_code)
sleep(1); /* so give some time to exit for those which can */
WSREP_INFO("Some threads may fail to exit.");
}
+
if (WSREP_ON)
{
/* In bootstrap mode we deinitialize wsrep here. */
@@ -1932,11 +1945,7 @@ static void mysqld_exit(int exit_code)
shutdown_performance_schema(); // we do it as late as possible
#endif
set_malloc_size_cb(NULL);
- if (opt_endinfo && global_status_var.global_memory_used)
- fprintf(stderr, "Warning: Memory not freed: %ld\n",
- (long) global_status_var.global_memory_used);
- if (!opt_debugging && !my_disable_leak_check && exit_code == 0 &&
- debug_assert_on_not_freed_memory)
+ if (global_status_var.global_memory_used)
{
#ifdef SAFEMALLOC
sf_report_leaked_memory(0);
@@ -4645,7 +4654,6 @@ static int init_default_storage_engine_impl(const char *opt_name,
return 0;
}
-
static int
init_gtid_pos_auto_engines(void)
{
@@ -4672,7 +4680,6 @@ init_gtid_pos_auto_engines(void)
return 0;
}
-
static int init_server_components()
{
DBUG_ENTER("init_server_components");
@@ -5531,7 +5538,13 @@ int mysqld_main(int argc, char **argv)
set_user(mysqld_user, user_info);
}
+#ifdef WITH_WSREP
+ WSREP_ON_= (global_system_variables.wsrep_on &&
+ wsrep_provider &&
+ strcmp(wsrep_provider, WSREP_NONE));
+
if (WSREP_ON && wsrep_check_opts()) unireg_abort(1);
+#endif
/*
The subsequent calls may take a long time : e.g. innodb log read.
@@ -6954,18 +6967,6 @@ static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff,
}
-/* How many slaves are connected to this master */
-
-static int show_slaves_connected(THD *thd, SHOW_VAR *var, char *buff)
-{
-
- var->type= SHOW_LONGLONG;
- var->value= buff;
- *((longlong*) buff)= uint32_t(binlog_dump_thread_count);
- return 0;
-}
-
-
/* How many masters this slave is connected to */
@@ -7531,9 +7532,9 @@ SHOW_VAR status_vars[]= {
{"Select_range", (char*) offsetof(STATUS_VAR, select_range_count_), SHOW_LONG_STATUS},
{"Select_range_check", (char*) offsetof(STATUS_VAR, select_range_check_count_), SHOW_LONG_STATUS},
{"Select_scan", (char*) offsetof(STATUS_VAR, select_scan_count_), SHOW_LONG_STATUS},
- {"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_INT},
+ {"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_ATOMIC_COUNTER_UINT32_T},
#ifdef HAVE_REPLICATION
- {"Slaves_connected", (char*) &show_slaves_connected, SHOW_SIMPLE_FUNC },
+ {"Slaves_connected", (char*) &binlog_dump_thread_count, SHOW_ATOMIC_COUNTER_UINT32_T},
{"Slaves_running", (char*) &show_slaves_running, SHOW_SIMPLE_FUNC },
{"Slave_connections", (char*) offsetof(STATUS_VAR, com_register_slave), SHOW_LONG_STATUS},
{"Slave_heartbeat_period", (char*) &show_heartbeat_period, SHOW_SIMPLE_FUNC},
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 2649a3ac61b..8adfda0dfec 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -221,7 +221,7 @@ extern ulong delayed_insert_timeout;
extern ulong delayed_insert_limit, delayed_queue_size;
extern ulong delayed_insert_threads, delayed_insert_writes;
extern ulong delayed_rows_in_use,delayed_insert_errors;
-extern int32 slave_open_temp_tables;
+extern Atomic_counter<uint32_t> slave_open_temp_tables;
extern ulonglong query_cache_size;
extern ulong query_cache_limit;
extern ulong query_cache_min_res_unit;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 7390345ed29..384b2d5ced2 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -356,7 +356,8 @@ QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index,
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
bool index_read_must_be_used,
bool update_tbl_stats,
- double read_time);
+ double read_time,
+ bool ror_scans_required);
static
TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree,
double read_time);
@@ -2632,7 +2633,7 @@ static int fill_used_fields_bitmap(PARAM *param)
force_quick_range is really needed.
RETURN
- -1 if impossible select (i.e. certainly no rows will be selected)
+ -1 if error or impossible select (i.e. certainly no rows will be selected)
0 if can't use quick_select
1 if found usable ranges and quick select has been successfully created.
*/
@@ -2745,7 +2746,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{
thd->no_errors=0;
free_root(&alloc,MYF(0)); // Return memory & allocator
- DBUG_RETURN(0); // Can't use range
+ DBUG_RETURN(-1); // Error
}
key_parts= param.key_parts;
@@ -2813,7 +2814,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{
thd->no_errors=0;
free_root(&alloc,MYF(0)); // Return memory & allocator
- DBUG_RETURN(0); // Can't use range
+ DBUG_RETURN(-1); // Error
}
thd->mem_root= &alloc;
@@ -2873,6 +2874,13 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
tree= NULL;
}
}
+ else if (thd->is_error())
+ {
+ thd->no_errors=0;
+ thd->mem_root= param.old_root;
+ free_root(&alloc, MYF(0));
+ DBUG_RETURN(-1);
+ }
}
if (tree)
@@ -2896,7 +2904,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
/* Get best 'range' plan and prepare data for making other plans */
if ((range_trp= get_key_scans_params(&param, tree,
only_single_index_range_scan, TRUE,
- best_read_time)))
+ best_read_time, FALSE)))
{
best_trp= range_trp;
best_read_time= best_trp->read_cost;
@@ -5050,8 +5058,8 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
double roru_index_costs;
ha_rows roru_total_records;
double roru_intersect_part= 1.0;
- double limit_read_time= read_time;
size_t n_child_scans;
+ double limit_read_time= read_time;
THD *thd= param->thd;
DBUG_ENTER("get_best_disjunct_quick");
DBUG_PRINT("info", ("Full table scan cost: %g", read_time));
@@ -5078,6 +5086,10 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
sizeof(TRP_RANGE*)*
n_child_scans)))
DBUG_RETURN(NULL);
+
+ const bool only_ror_scans_required= !optimizer_flag(param->thd,
+ OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION);
+
Json_writer_object trace_best_disjunct(thd);
Json_writer_array to_merge(thd, "indexes_to_merge");
/*
@@ -5092,7 +5104,9 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map,
"tree in SEL_IMERGE"););
Json_writer_object trace_idx(thd);
- if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time)))
+ if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE,
+ read_time,
+ only_ror_scans_required)))
{
/*
One of index scans in this index_merge is more expensive than entire
@@ -5452,7 +5466,7 @@ TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge,
index merge retrievals are not well calibrated
*/
trp= get_key_scans_params(param, *imerge->trees, FALSE, TRUE,
- read_time);
+ read_time, FALSE);
}
DBUG_RETURN(trp);
@@ -7338,6 +7352,8 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
index_read_must_be_used if TRUE, assume 'index only' option will be set
(except for clustered PK indexes)
read_time don't create read plans with cost > read_time.
+ only_ror_scans_required set to TRUE when we are only interested
+ in ROR scan
RETURN
Best range read plan
NULL if no plan found or error occurred
@@ -7346,7 +7362,8 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
bool index_read_must_be_used,
bool update_tbl_stats,
- double read_time)
+ double read_time,
+ bool only_ror_scans_required)
{
uint idx, UNINIT_VAR(best_idx);
SEL_ARG *key_to_read= NULL;
@@ -7400,8 +7417,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
found_records= check_quick_select(param, idx, read_index_only, key,
update_tbl_stats, &mrr_flags,
&buf_size, &cost, &is_ror_scan);
- if (!is_ror_scan &&
- !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION))
+ if (only_ror_scans_required && !is_ror_scan)
continue;
if (found_records != HA_POS_ERROR && tree->index_scans &&
@@ -9789,7 +9805,7 @@ key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
if (key2->next_key_part)
{
key1->use_count--; // Incremented in and_all_keys
- return and_all_keys(param, key1, key2, clone_flag);
+ return and_all_keys(param, key1, key2->next_key_part, clone_flag);
}
key2->use_count--; // Key2 doesn't have a tree
}
diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc
index 4a15dd709db..d33e26d2ecc 100644
--- a/sql/rpl_parallel.cc
+++ b/sql/rpl_parallel.cc
@@ -60,7 +60,7 @@ rpt_handle_event(rpl_parallel_thread::queued_event *qev,
rgi->last_master_timestamp= ev->when + (time_t)ev->exec_time;
err= apply_event_and_update_pos_for_parallel(ev, thd, rgi);
- thread_safe_increment64(&rli->executed_entries);
+ rli->executed_entries++;
#ifdef WITH_WSREP
if (wsrep_after_statement(thd))
{
diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc
index 29ca0931fb8..7da296b47d9 100644
--- a/sql/rpl_record.cc
+++ b/sql/rpl_record.cc
@@ -329,22 +329,6 @@ unpack_row(rpl_group_info *rgi,
(int) (pack_ptr - old_pack_ptr)));
if (!pack_ptr)
{
-#ifdef WITH_WSREP
- if (WSREP_ON)
- {
- /*
- Debug message to troubleshoot bug:
- https://mariadb.atlassian.net/browse/MDEV-4404
- Galera Node throws "Could not read field" error and drops out of cluster
- */
- WSREP_WARN("ROW event unpack field: %s metadata: 0x%x;"
- " conv_table %p conv_field %p table %s"
- " row_end: %p",
- f->field_name.str, metadata, conv_table, conv_field,
- (table_found) ? "found" : "not found", row_end
- );
- }
-#endif /* WITH_WSREP */
rgi->rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT,
rgi->gtid_info(),
"Could not read field '%s' of table '%s.%s'",
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index 5d2d33c397f..fafe8ead63d 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -347,7 +347,7 @@ public:
Number of executed events for SLAVE STATUS.
Protected by slave_executed_entries_lock
*/
- int64 executed_entries;
+ Atomic_counter<uint32_t> executed_entries;
/*
If the end of the hot relay log is made of master's events ignored by the
diff --git a/sql/slave.cc b/sql/slave.cc
index 754c8df3638..381417c353b 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -3476,7 +3476,7 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full,
{
protocol->store((uint32) mi->rli.retried_trans);
protocol->store((ulonglong) mi->rli.max_relay_log_size);
- protocol->store((uint32) mi->rli.executed_entries);
+ protocol->store(mi->rli.executed_entries);
protocol->store((uint32) mi->received_heartbeats);
protocol->store((double) mi->heartbeat_period, 3, &tmp);
protocol->store(gtid_pos->ptr(), gtid_pos->length(), &my_charset_bin);
@@ -3996,7 +3996,8 @@ apply_event_and_update_pos_apply(Log_event* ev, THD* thd, rpl_group_info *rgi,
exec_res= ev->apply_event(rgi);
#ifdef WITH_WSREP
- if (WSREP_ON) {
+ if (WSREP(thd)) {
+
if (exec_res) {
mysql_mutex_lock(&thd->LOCK_thd_data);
switch(thd->wsrep_trx().state()) {
@@ -4574,7 +4575,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
}
}
- thread_safe_increment64(&rli->executed_entries);
+ rli->executed_entries++;
#ifdef WITH_WSREP
wsrep_after_statement(thd);
#endif /* WITH_WSREP */
@@ -5650,7 +5651,7 @@ pthread_handler_t handle_slave_sql(void *arg)
if (exec_relay_log_event(thd, rli, serial_rgi))
{
#ifdef WITH_WSREP
- if (WSREP_ON)
+ if (WSREP(thd))
{
mysql_mutex_lock(&thd->LOCK_thd_data);
@@ -5668,8 +5669,10 @@ pthread_handler_t handle_slave_sql(void *arg)
if (!sql_slave_killed(serial_rgi))
{
slave_output_error_info(serial_rgi, thd);
- if (WSREP_ON && rli->last_error().number == ER_UNKNOWN_COM_ERROR)
+ if (WSREP(thd) && rli->last_error().number == ER_UNKNOWN_COM_ERROR)
+ {
wsrep_node_dropped= TRUE;
+ }
}
goto err;
}
@@ -5806,7 +5809,7 @@ err_during_init:
If slave stopped due to node going non primary, we set global flag to
trigger automatic restart of slave when node joins back to cluster.
*/
- if (WSREP_ON && wsrep_node_dropped && wsrep_restart_slave)
+ if (WSREP(thd) && wsrep_node_dropped && wsrep_restart_slave)
{
if (wsrep_ready_get())
{
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 1606e8cb7eb..e22a23d197e 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -4366,7 +4366,7 @@ restart:
}
#ifdef WITH_WSREP
- if (WSREP_ON &&
+ if (WSREP(thd) &&
wsrep_replicate_myisam &&
(*start) &&
(*start)->table &&
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 07136c10e1d..96ebfca3723 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3414,7 +3414,7 @@ public:
void awake_no_mutex(killed_state state_to_set);
void awake(killed_state state_to_set)
{
- bool wsrep_on_local= WSREP_ON;
+ bool wsrep_on_local= WSREP_NNULL(this);
/*
mutex locking order (LOCK_thd_data - LOCK_thd_kill)) requires
to grab LOCK_thd_data here
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 70cefa8e977..59990e11e71 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -8083,7 +8083,8 @@ Item *LEX::create_item_limit(THD *thd, const Lex_ident_cli_st *ca)
if (unlikely(!(item= new (thd->mem_root)
Item_splocal(thd, rh, &sa,
spv->offset, spv->type_handler(),
- pos.pos(), pos.length()))))
+ clone_spec_offset ? 0 : pos.pos(),
+ clone_spec_offset ? 0 : pos.length()))))
return NULL;
#ifdef DBUG_ASSERT_EXISTS
item->m_sp= sphead;
@@ -8183,14 +8184,15 @@ Item *LEX::create_item_ident_sp(THD *thd, Lex_ident_sys_st *name,
}
Query_fragment pos(thd, sphead, start, end);
+ uint f_pos= clone_spec_offset ? 0 : pos.pos();
+ uint f_length= clone_spec_offset ? 0 : pos.length();
Item_splocal *splocal= spv->field_def.is_column_type_ref() ?
new (thd->mem_root) Item_splocal_with_delayed_data_type(thd, rh, name,
spv->offset,
- pos.pos(),
- pos.length()) :
+ f_pos, f_length) :
new (thd->mem_root) Item_splocal(thd, rh, name,
spv->offset, spv->type_handler(),
- pos.pos(), pos.length());
+ f_pos, f_length);
if (unlikely(splocal == NULL))
return NULL;
#ifdef DBUG_ASSERT_EXISTS
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index b1756b83056..273e5b79233 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1751,7 +1751,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
mysqld_stmt_bulk_execute(thd, packet, packet_length);
#ifdef WITH_WSREP
- if (WSREP_ON)
+ if (WSREP(thd))
{
(void)wsrep_after_statement(thd);
}
@@ -1762,7 +1762,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
mysqld_stmt_execute(thd, packet, packet_length);
#ifdef WITH_WSREP
- if (WSREP_ON)
+ if (WSREP(thd))
{
(void)wsrep_after_statement(thd);
}
@@ -1820,7 +1820,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
#ifdef WITH_WSREP
- if (WSREP_ON)
+ if (WSREP(thd))
{
if (wsrep_mysql_parse(thd, thd->query(), thd->query_length(),
&parser_state,
@@ -1922,7 +1922,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
parser_state.reset(beginning_of_next_stmt, length);
#ifdef WITH_WSREP
- if (WSREP_ON)
+ if (WSREP(thd))
{
if (wsrep_mysql_parse(thd, beginning_of_next_stmt,
length, &parser_state,
@@ -3530,7 +3530,7 @@ mysql_execute_command(THD *thd)
* and dirty reads (if configured)
*/
if (!(thd->wsrep_applier) &&
- !(wsrep_ready_get() && wsrep_reject_queries == WSREP_REJECT_NONE) &&
+ !(wsrep_ready_get() && wsrep_reject_queries == WSREP_REJECT_NONE) &&
!(thd->variables.wsrep_dirty_reads &&
(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) == 0) &&
!wsrep_tables_accessible_when_detached(all_tables) &&
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index de2d5c2f253..d6c7066e655 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -5915,6 +5915,24 @@ the generated partition syntax in a correct manner.
*partition_changed= true;
}
}
+
+ // In case of PARTITION BY KEY(), check if primary key has changed
+ // System versioning also implicitly adds/removes primary key parts
+ if (alter_info->partition_flags == 0 && part_info->list_of_part_fields
+ && part_info->part_field_list.elements == 0)
+ {
+ if (alter_info->flags & (ALTER_DROP_SYSTEM_VERSIONING |
+ ALTER_ADD_SYSTEM_VERSIONING))
+ *partition_changed= true;
+
+ List_iterator<Key> it(alter_info->key_list);
+ Key *key;
+ while((key= it++) && !*partition_changed)
+ {
+ if (key->type == Key::PRIMARY)
+ *partition_changed= true;
+ }
+ }
/*
Set up partition default_engine_type either from the create_info
or from the previus table
diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h
index 8b200cfc6fd..e1360794a3b 100644
--- a/sql/sql_plugin.h
+++ b/sql/sql_plugin.h
@@ -25,7 +25,7 @@
SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, \
SHOW_HAVE, SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, \
SHOW_LONG_NOFLUSH, SHOW_LONGLONG_STATUS, SHOW_UINT32_STATUS, \
- SHOW_LEX_STRING
+ SHOW_LEX_STRING, SHOW_ATOMIC_COUNTER_UINT32_T
#include "mariadb.h"
#undef SHOW_always_last
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index ce49378204d..e7988d2c423 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -153,6 +153,8 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
if (mysql_bin_log.rotate_and_purge(true, drop_gtid_domain))
*write_to_binlog= -1;
+ /* Note that WSREP(thd) might not be true here e.g. during
+ SST. */
if (WSREP_ON)
{
/* Wait for last binlog checkpoint event to be logged. */
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index b8de0d411e0..55e5e940b19 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -3941,7 +3941,7 @@ int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len,
}
#ifdef WITH_WSREP
- if (WSREP_ON)
+ if (WSREP(thd))
{
/* RESET MASTER will initialize GTID sequence, and that would happen locally
in this node, so better reject it
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 755ae547db3..2528134f4ee 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -64,6 +64,7 @@
#endif
#include "transaction.h"
#include "opt_trace.h"
+#include "my_cpu.h"
enum enum_i_s_events_fields
{
@@ -3630,6 +3631,11 @@ const char* get_one_variable(THD *thd,
end= pos + ls->length;
break;
}
+ case SHOW_ATOMIC_COUNTER_UINT32_T:
+ end= int10_to_str(
+ static_cast<long>(*static_cast<Atomic_counter<uint32_t>*>(value)),
+ buff, 10);
+ break;
case SHOW_UNDEF:
break; // Return empty string
case SHOW_SYS: // Cannot happen
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 37225e17c1e..2d38f6d5d13 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -86,7 +86,7 @@ public:
Well_formed_prefix(CHARSET_INFO *cs, const char *str, size_t length)
:Well_formed_prefix_status(cs, str, str + length, length), m_str(str)
{ }
- Well_formed_prefix(CHARSET_INFO *cs, LEX_STRING str, size_t nchars)
+ Well_formed_prefix(CHARSET_INFO *cs, LEX_CSTRING str, size_t nchars)
:Well_formed_prefix_status(cs, str.str, str.str + str.length, nchars),
m_str(str.str)
{ }
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 86eba4a521b..e7fbae9e0f7 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4470,9 +4470,9 @@ bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len,
DBUG_ENTER("validate_comment_length");
if (comment->length == 0)
DBUG_RETURN(false);
- size_t tmp_len= system_charset_info->charpos(comment->str,
- comment->str + comment->length,
- max_len);
+
+ size_t tmp_len=
+ Well_formed_prefix(system_charset_info, *comment, max_len).length();
if (tmp_len < comment->length)
{
if (thd->is_strict_mode())
@@ -5728,9 +5728,11 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
DBUG_ENTER("mysql_create_like_table");
#ifdef WITH_WSREP
- if (WSREP_ON && !thd->wsrep_applier &&
+ if (WSREP(thd) && !thd->wsrep_applier &&
wsrep_create_like_table(thd, table, src_table, create_info))
+ {
DBUG_RETURN(res);
+ }
#endif
/*
@@ -10980,7 +10982,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
bool make_versioned= !from->versioned() && to->versioned();
bool make_unversioned= from->versioned() && !to->versioned();
bool keep_versioned= from->versioned() && to->versioned();
- bool drop_history= false; // XXX
Field *to_row_start= NULL, *to_row_end= NULL, *from_row_end= NULL;
MYSQL_TIME query_start;
DBUG_ENTER("copy_data_between_tables");
@@ -11111,10 +11112,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
{
from_row_end= from->vers_end_field();
}
- else if (keep_versioned && drop_history)
- {
- from_row_end= from->vers_end_field();
- }
if (from_row_end)
bitmap_set_bit(from->read_set, from_row_end->field_index);
@@ -11153,6 +11150,13 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
error= 1;
break;
}
+
+ if (make_unversioned)
+ {
+ if (!from_row_end->is_max())
+ continue; // Drop history rows.
+ }
+
if (unlikely(++thd->progress.counter >= time_to_report_progress))
{
time_to_report_progress+= MY_HOW_OFTEN_TO_WRITE/10;
@@ -11172,20 +11176,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
copy_ptr->do_copy(copy_ptr);
}
- if (drop_history && from_row_end && !from_row_end->is_max())
- continue;
-
if (make_versioned)
{
to_row_start->set_notnull();
to_row_start->store_time(&query_start);
to_row_end->set_max();
}
- else if (make_unversioned)
- {
- if (!from_row_end->is_max())
- continue; // Drop history rows.
- }
prev_insert_id= to->file->next_insert_id;
if (to->default_field)
diff --git a/sql/sql_type_geom.cc b/sql/sql_type_geom.cc
index 047f56d220b..d6fb06f34a5 100644
--- a/sql/sql_type_geom.cc
+++ b/sql/sql_type_geom.cc
@@ -872,7 +872,7 @@ int Field_geom::store(const char *from, size_t length, CHARSET_INFO *cs)
my_error(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, MYF(0),
Geometry::ci_collection[m_type_handler->geometry_type()]->m_name.str,
- wkt.c_ptr(),
+ wkt.c_ptr_safe(),
db, tab_name, field_name.str,
(ulong) table->in_use->get_stmt_da()->
current_row_for_warning());
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 75824d3fbcf..8e6eb4c815a 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2011, 2016, 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
@@ -2592,6 +2592,9 @@ int multi_update::send_data(List<Item> &not_used_values)
TABLE *tmp_table= tmp_tables[offset];
if (copy_funcs(tmp_table_param[offset].items_to_copy, thd))
DBUG_RETURN(1);
+ /* rowid field is NULL if join tmp table has null row from outer join */
+ if (tmp_table->field[0]->is_null())
+ continue;
/* Store regular updated fields in the row. */
DBUG_ASSERT(1 + unupdated_check_opt_tables.elements ==
tmp_table_param[offset].func_count);
@@ -2789,6 +2792,7 @@ int multi_update::do_updates()
uint field_num= 0;
do
{
+ DBUG_ASSERT(!tmp_table->field[field_num]->is_null());
String rowid;
tmp_table->field[field_num]->val_str(&rowid);
if (unlikely((local_error= tbl->file->ha_rnd_pos(tbl->record[0],
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 09a617cece1..df6f9933e36 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -6080,7 +6080,7 @@ vio_keepalive_opts opt_vio_keepalive;
static Sys_var_int Sys_keepalive_time(
"tcp_keepalive_time",
- "Timeout, in milliseconds, with no activity until the first TCP keep-alive packet is sent."
+ "Timeout, in seconds, with no activity until the first TCP keep-alive packet is sent."
"If set to 0, system dependent default is used.",
AUTO_SET GLOBAL_VAR(opt_vio_keepalive.idle),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, INT_MAX32/1000), DEFAULT(0),
diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc
index 9491a23793b..ef6f1c42434 100644
--- a/sql/temporary_tables.cc
+++ b/sql/temporary_tables.cc
@@ -1139,9 +1139,7 @@ TABLE *THD::open_temporary_table(TMP_TABLE_SHARE *share,
/* Increment Slave_open_temp_table_definitions status variable count. */
if (rgi_slave)
- {
- thread_safe_increment32(&slave_open_temp_tables);
- }
+ slave_open_temp_tables++;
DBUG_PRINT("tmptable", ("Opened table: '%s'.'%s table: %p",
table->s->db.str,
@@ -1247,7 +1245,7 @@ void THD::close_temporary_table(TABLE *table)
/* Natural invariant of temporary_tables */
DBUG_ASSERT(slave_open_temp_tables || !temporary_tables);
/* Decrement Slave_open_temp_table_definitions status variable count. */
- thread_safe_decrement32(&slave_open_temp_tables);
+ slave_open_temp_tables--;
}
DBUG_VOID_RETURN;
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 6c2f20081a7..49880b2e827 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -269,6 +269,45 @@ char* wsrep_cluster_capabilities = NULL;
wsp::Config_state *wsrep_config_state;
+void WSREP_LOG(void (*fun)(const char* fmt, ...), const char* fmt, ...)
+{
+ /* Allocate short buffer from stack. If the vsnprintf() return value
+ indicates that the message was truncated, a new buffer will be allocated
+ dynamically and the message will be reprinted. */
+ char msg[128] = {'\0'};
+ va_list arglist;
+ va_start(arglist, fmt);
+ int n= vsnprintf(msg, sizeof(msg) - 1, fmt, arglist);
+ va_end(arglist);
+ if (n < 0)
+ {
+ sql_print_warning("WSREP: Printing message failed");
+ }
+ else if (n < (int)sizeof(msg))
+ {
+ fun("WSREP: %s", msg);
+ }
+ else
+ {
+ size_t dynbuf_size= std::max(n, 4096);
+ char* dynbuf= (char*) my_malloc(PSI_NOT_INSTRUMENTED, dynbuf_size, MYF(0));
+ if (dynbuf)
+ {
+ va_start(arglist, fmt);
+ (void)vsnprintf(&dynbuf[0], dynbuf_size - 1, fmt, arglist);
+ va_end(arglist);
+ dynbuf[dynbuf_size - 1] = '\0';
+ fun("WSREP: %s", &dynbuf[0]);
+ my_free(dynbuf);
+ }
+ else
+ {
+ /* Memory allocation for vector failed, print truncated message. */
+ fun("WSREP: %s", msg);
+ }
+ }
+}
+
wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED;
wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED;
@@ -756,6 +795,7 @@ void wsrep_init_globals()
wsrep_gtid_server.seqno(gtid.seqno);
}
wsrep_init_schema();
+
if (WSREP_ON)
{
Wsrep_server_state::instance().initialized();
@@ -793,6 +833,8 @@ int wsrep_init()
global_system_variables.wsrep_on= 1;
+ WSREP_ON_= wsrep_provider && strcmp(wsrep_provider, WSREP_NONE);
+
if (wsrep_gtid_mode && opt_bin_log && !opt_log_slave_updates)
{
WSREP_ERROR("Option --log-slave-updates is required if "
@@ -2217,8 +2259,10 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
DBUG_ASSERT(wsrep_thd_is_local(thd));
DBUG_ASSERT(thd->wsrep_trx().ws_meta().seqno().is_undefined());
- if (thd->global_read_lock.is_acquired())
+ if (Wsrep_server_state::instance().desynced_on_pause())
{
+ my_message(ER_UNKNOWN_COM_ERROR,
+ "Aborting TOI: Global Read-Lock (FTWRL) in place.", MYF(0));
WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %llu",
wsrep_thd_query(thd), thd->thread_id);
return -1;
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 46ca4959741..cf2404e329e 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -19,6 +19,7 @@
#include <wsrep.h>
#ifdef WITH_WSREP
+extern bool WSREP_ON_;
#include <mysql/plugin.h>
#include "mysql/service_wsrep.h"
@@ -214,15 +215,12 @@ extern void wsrep_prepend_PATH (const char* path);
/* Other global variables */
extern wsrep_seqno_t wsrep_locked_seqno;
-#define WSREP_ON \
- ((global_system_variables.wsrep_on) && \
- wsrep_provider && \
- strcmp(wsrep_provider, WSREP_NONE))
+#define WSREP_ON unlikely(WSREP_ON_)
/* use xxxxxx_NNULL macros when thd pointer is guaranteed to be non-null to
* avoid compiler warnings (GCC 6 and later) */
-#define WSREP_NNULL(thd) \
- (thd->variables.wsrep_on && WSREP_ON)
+
+#define WSREP_NNULL(thd) (WSREP_ON && thd->variables.wsrep_on)
#define WSREP(thd) \
(thd && WSREP_NNULL(thd))
@@ -243,13 +241,9 @@ extern wsrep_seqno_t wsrep_locked_seqno;
((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \
wsrep_forced_binlog_format : my_format)
-// prefix all messages with "WSREP"
-#define WSREP_LOG(fun, ...) \
- do { \
- char msg[1024]= {'\0'}; \
- snprintf(msg, sizeof(msg) - 1, ## __VA_ARGS__); \
- fun("WSREP: %s", msg); \
- } while(0)
+/* A wrapper function for MySQL log functions. The call will prefix
+ the log message with WSREP and forward the result buffer to fun. */
+void WSREP_LOG(void (*fun)(const char* fmt, ...), const char* fmt, ...);
#define WSREP_DEBUG(...) \
if (wsrep_debug) sql_print_information( "WSREP: " __VA_ARGS__)
@@ -615,9 +609,9 @@ enum wsrep::streaming_context::fragment_unit wsrep_fragment_unit(ulong unit);
/* These macros are needed to compile MariaDB without WSREP support
* (e.g. embedded) */
+#define WSREP_ON false
#define WSREP(T) (0)
#define WSREP_NNULL(T) (0)
-#define WSREP_ON (0)
#define WSREP_EMULATE_BINLOG(thd) (0)
#define WSREP_EMULATE_BINLOG_NNULL(thd) (0)
#define WSREP_BINLOG_FORMAT(my_format) ((ulong)my_format)
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index 0bb8a9eb675..8ffcb32e10a 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -367,6 +367,7 @@ void wsrep_sst_received (THD* thd,
my_pthread_setspecific_ptr(THR_THD, NULL);
}
+ /* During sst WSREP(thd) is not yet set for joiner. */
if (WSREP_ON)
{
int const rcode(seqno < 0 ? seqno : 0);
diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc
index 94d01b273c5..0f72c132d84 100644
--- a/sql/wsrep_thd.cc
+++ b/sql/wsrep_thd.cc
@@ -320,10 +320,15 @@ int wsrep_abort_thd(THD *bf_thd_ptr, THD *victim_thd_ptr, my_bool signal)
DBUG_ENTER("wsrep_abort_thd");
THD *victim_thd= (THD *) victim_thd_ptr;
THD *bf_thd= (THD *) bf_thd_ptr;
+
mysql_mutex_lock(&victim_thd->LOCK_thd_data);
- if ( (WSREP(bf_thd) ||
- ( (WSREP_ON || bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU) &&
- wsrep_thd_is_toi(bf_thd)) ) &&
+
+ /* Note that when you use RSU node is desynced from cluster, thus WSREP(thd)
+ might not be true.
+ */
+ if ((WSREP(bf_thd) ||
+ ((WSREP_ON || bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU) &&
+ wsrep_thd_is_toi(bf_thd))) &&
victim_thd &&
!wsrep_thd_is_aborting(victim_thd))
{
@@ -337,6 +342,7 @@ int wsrep_abort_thd(THD *bf_thd_ptr, THD *victim_thd_ptr, my_bool signal)
{
WSREP_DEBUG("wsrep_abort_thd not effective: %p %p", bf_thd, victim_thd);
}
+
mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
DBUG_RETURN(1);
}
diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h
index cb58026207b..55bb7462d99 100644
--- a/sql/wsrep_trans_observer.h
+++ b/sql/wsrep_trans_observer.h
@@ -431,7 +431,7 @@ static inline void wsrep_after_apply(THD* thd)
static inline void wsrep_open(THD* thd)
{
DBUG_ENTER("wsrep_open");
- if (wsrep_on(thd))
+ if (WSREP(thd))
{
thd->wsrep_cs().open(wsrep::client_id(thd->thread_id));
thd->wsrep_cs().debug_log_level(wsrep_debug);
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index 28dbe4096f7..4fffc3ddc8a 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -91,6 +91,12 @@ static bool refresh_provider_options()
}
}
+static void wsrep_set_wsrep_on()
+{
+ WSREP_ON_= global_system_variables.wsrep_on && wsrep_provider &&
+ strcmp(wsrep_provider, WSREP_NONE);
+}
+
/* This is intentionally declared as a weak global symbol, so that
linking will succeed even if the server is built with a dynamically
linked InnoDB. */
@@ -125,6 +131,8 @@ bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type)
thd->variables.wsrep_on= global_system_variables.wsrep_on= saved_wsrep_on;
}
+ wsrep_set_wsrep_on();
+
return false;
}
@@ -418,6 +426,7 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type)
if (!rcode)
refresh_provider_options();
+ wsrep_set_wsrep_on();
mysql_mutex_lock(&LOCK_global_system_variables);
return rcode;
@@ -437,6 +446,7 @@ void wsrep_provider_init (const char* value)
if (wsrep_provider) my_free((void *)wsrep_provider);
wsrep_provider= my_strdup(PSI_INSTRUMENT_MEM, value, MYF(0));
+ wsrep_set_wsrep_on();
}
bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var)
@@ -924,6 +934,8 @@ static void export_wsrep_status_to_mysql(THD* thd)
int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff)
{
+ /* Note that we should allow show status like 'wsrep%' even
+ when WSREP(thd) is false. */
if (WSREP_ON)
{
export_wsrep_status_to_mysql(thd);
diff --git a/sql/xa.cc b/sql/xa.cc
index cde6350f38d..69e9fd70af6 100644
--- a/sql/xa.cc
+++ b/sql/xa.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2009, 2019, MariaDB Corporation.
+ Copyright (c) 2009, 2020, MariaDB Corporation.
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
@@ -19,6 +19,7 @@
#include "mariadb.h"
#include "sql_class.h"
#include "transaction.h"
+#include "my_cpu.h"
#include <pfs_transaction_provider.h>
#include <mysql/psi/mysql_transaction.h>