summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/events.cc8
-rw-r--r--sql/field.cc27
-rw-r--r--sql/field.h19
-rw-r--r--sql/ha_partition.cc3
-rw-r--r--sql/handler.cc13
-rw-r--r--sql/handler.h10
-rw-r--r--sql/item_jsonfunc.cc83
-rw-r--r--sql/log.cc13
-rw-r--r--sql/log_event.cc34
-rw-r--r--sql/mysql_install_db.cc2
-rw-r--r--sql/mysql_upgrade_service.cc20
-rw-r--r--sql/opt_subselect.cc3
-rw-r--r--sql/set_var.cc48
-rw-r--r--sql/set_var.h12
-rw-r--r--sql/slave.cc2
-rw-r--r--sql/sql_acl.cc18
-rw-r--r--sql/sql_analyze_stmt.cc2
-rw-r--r--sql/sql_base.cc9
-rw-r--r--sql/sql_class.cc111
-rw-r--r--sql/sql_class.h36
-rw-r--r--sql/sql_explain.cc3
-rw-r--r--sql/sql_handler.cc1
-rw-r--r--sql/sql_insert.cc32
-rw-r--r--sql/sql_parse.cc11
-rw-r--r--sql/sql_plugin.cc3
-rw-r--r--sql/sql_repl.cc1
-rw-r--r--sql/sql_select.cc66
-rw-r--r--sql/sql_show.cc85
-rw-r--r--sql/sql_statistics.cc6
-rw-r--r--sql/sql_table.cc12
-rw-r--r--sql/sql_trigger.cc2
-rw-r--r--sql/sql_union.cc6
-rw-r--r--sql/sql_view.cc10
-rw-r--r--sql/sys_vars.cc15
-rw-r--r--sql/sys_vars.ic133
-rw-r--r--sql/sys_vars_shared.h1
-rw-r--r--sql/table.cc136
-rw-r--r--sql/table.h9
-rw-r--r--sql/wsrep_hton.cc36
-rw-r--r--sql/wsrep_mysqld.cc67
-rw-r--r--sql/wsrep_mysqld.h14
-rw-r--r--sql/wsrep_priv.h2
-rw-r--r--sql/wsrep_sst.cc73
-rw-r--r--sql/wsrep_var.cc6
44 files changed, 782 insertions, 421 deletions
diff --git a/sql/events.cc b/sql/events.cc
index 6a8695843a3..fcad115c199 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -463,8 +463,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
-
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (lock_object_name(thd, MDL_key::EVENT,
parse_data->dbname.str, parse_data->name.str))
@@ -594,8 +593,7 @@ Events::drop_event(THD *thd, const LEX_CSTRING *dbname,
if (check_access(thd, EVENT_ACL, dbname->str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
-
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/*
Turn off row binlogging of this statement and use statement-based so
@@ -621,7 +619,7 @@ Events::drop_event(THD *thd, const LEX_CSTRING *dbname,
#ifdef WITH_WSREP
error:
DBUG_RETURN(TRUE);
-#endif
+#endif /* WITH_WSREP */
}
diff --git a/sql/field.cc b/sql/field.cc
index 7c1798b983e..efc20fa37fc 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3054,6 +3054,23 @@ void Field_decimal::sql_type(String &res) const
}
+Field *Field_decimal::make_new_field(MEM_ROOT *root, TABLE *new_table,
+ bool keep_type)
+{
+ if (keep_type)
+ return Field_real::make_new_field(root, new_table, keep_type);
+
+ Field *field= new (root) Field_new_decimal(NULL, field_length,
+ maybe_null() ? (uchar*) "" : 0, 0,
+ NONE, &field_name,
+ dec, flags & ZEROFILL_FLAG,
+ unsigned_flag);
+ if (field)
+ field->init_for_make_new_field(new_table, orig_table);
+ return field;
+}
+
+
/****************************************************************************
** Field_new_decimal
****************************************************************************/
@@ -7473,15 +7490,7 @@ Field *Field_string::make_new_field(MEM_ROOT *root, TABLE *new_table,
This is done to ensure that ALTER TABLE will convert old VARCHAR fields
to now VARCHAR fields.
*/
- field->init(new_table);
- /*
- Normally orig_table is different from table only if field was
- created via ::make_new_field. Here we alter the type of field,
- so ::make_new_field is not applicable. But we still need to
- preserve the original field metadata for the client-server
- protocol.
- */
- field->orig_table= orig_table;
+ field->init_for_make_new_field(new_table, orig_table);
}
return field;
}
diff --git a/sql/field.h b/sql/field.h
index 7db9dfbdaa2..10fe59f224d 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1405,6 +1405,18 @@ public:
orig_table= table= table_arg;
set_table_name(&table_arg->alias);
}
+ void init_for_make_new_field(TABLE *new_table_arg, TABLE *orig_table_arg)
+ {
+ init(new_table_arg);
+ /*
+ Normally orig_table is different from table only if field was
+ created via ::make_new_field. Here we alter the type of field,
+ so ::make_new_field is not applicable. But we still need to
+ preserve the original field metadata for the client-server
+ protocol.
+ */
+ orig_table= orig_table_arg;
+ }
/* maximum possible display length */
virtual uint32 max_display_length() const= 0;
@@ -1892,6 +1904,7 @@ public:
unireg_check_arg, field_name_arg,
dec_arg, zero_arg, unsigned_arg)
{}
+ Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
const Type_handler *type_handler() const { return &type_handler_olddecimal; }
enum ha_base_keytype key_type() const
{ return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
@@ -3763,6 +3776,10 @@ public:
uint32 char_length() const;
uint32 octet_length() const;
uint is_equal(Create_field *new_field);
+
+ friend void TABLE::remember_blob_values(String *blob_storage);
+ friend void TABLE::restore_blob_values(String *blob_storage);
+
private:
int save_field_metadata(uchar *first_byte);
};
@@ -4343,7 +4360,7 @@ public:
length*= charset->mbmaxlen;
if (real_field_type() == MYSQL_TYPE_VARCHAR && compression_method())
length++;
- DBUG_ASSERT(length <= UINT_MAX32);
+ set_if_smaller(length, UINT_MAX32);
key_length= (uint) length;
pack_length= type_handler()->calc_pack_length((uint32) length);
}
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 0775d67a592..befcc62080e 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -5201,7 +5201,8 @@ int ha_partition::rnd_pos_by_record(uchar *record)
if (unlikely(get_part_for_buf(record, m_rec0, m_part_info, &m_last_part)))
DBUG_RETURN(1);
- DBUG_RETURN(handler::rnd_pos_by_record(record));
+ int err= m_file[m_last_part]->rnd_pos_by_record(record);
+ DBUG_RETURN(err);
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 07459d4cd8c..4f152cfd99c 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -3597,8 +3597,8 @@ void handler::print_error(int error, myf errflag)
break;
case HA_ERR_ABORTED_BY_USER:
{
- DBUG_ASSERT(table->in_use->killed);
- table->in_use->send_kill_message();
+ DBUG_ASSERT(ha_thd()->killed);
+ ha_thd()->send_kill_message();
DBUG_VOID_RETURN;
}
case HA_ERR_WRONG_MRG_TABLE_DEF:
@@ -3839,7 +3839,7 @@ void handler::print_error(int error, myf errflag)
*/
errflag|= ME_NOREFRESH;
}
- }
+ }
/* if we got an OS error from a file-based engine, specify a path of error */
if (error < HA_ERR_FIRST && bas_ext()[0])
@@ -4578,6 +4578,7 @@ handler::ha_create_partitioning_metadata(const char *name,
DBUG_ASSERT(m_lock_type == F_UNLCK ||
(!old_name && strcmp(name, table_share->path.str)));
+
return create_partitioning_metadata(name, old_name, action_flag);
}
@@ -6504,6 +6505,12 @@ void ha_fake_trx_id(THD *thd)
DBUG_VOID_RETURN;
}
+ if (thd->wsrep_ws_handle.trx_id != WSREP_UNDEFINED_TRX_ID)
+ {
+ WSREP_DEBUG("fake trx id skipped: %lu", thd->wsrep_ws_handle.trx_id);
+ DBUG_VOID_RETURN;
+ }
+
/* Try statement transaction if standard one is not set. */
THD_TRANS *trans= (thd->transaction.all.ha_list) ? &thd->transaction.all :
&thd->transaction.stmt;
diff --git a/sql/handler.h b/sql/handler.h
index 3d1b764bd14..54df7941526 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -3556,9 +3556,17 @@ public:
*/
virtual int rnd_pos_by_record(uchar *record)
{
+ int error;
DBUG_ASSERT(table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION);
+
+ error = ha_rnd_init(false);
+ if (error != 0)
+ return error;
+
position(record);
- return rnd_pos(record, ref);
+ error = ha_rnd_pos(record, ref);
+ ha_rnd_end();
+ return error;
}
virtual int read_first_row(uchar *buf, uint primary_key);
public:
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index 52042c56fcc..afcba91d57f 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -513,6 +513,10 @@ err_return:
bool Item_func_json_value::check_and_get_value(json_engine_t *je, String *res,
int *error)
{
+ CHARSET_INFO *json_cs;
+ const uchar *js;
+ uint js_len;
+
if (!json_value_scalar(je))
{
/* We only look for scalar values! */
@@ -521,7 +525,22 @@ bool Item_func_json_value::check_and_get_value(json_engine_t *je, String *res,
return true;
}
- return st_append_json(res, je->s.cs, je->value, je->value_len);
+ if (je->value_type == JSON_VALUE_TRUE ||
+ je->value_type == JSON_VALUE_FALSE)
+ {
+ json_cs= &my_charset_utf8mb4_bin;
+ js= (const uchar *) ((je->value_type == JSON_VALUE_TRUE) ? "1" : "0");
+ js_len= 1;
+ }
+ else
+ {
+ json_cs= je->s.cs;
+ js= je->value;
+ js_len= je->value_len;
+ }
+
+
+ return st_append_json(res, json_cs, js, js_len);
}
@@ -3213,34 +3232,44 @@ String *Item_func_json_format::val_json(String *str)
int Arg_comparator::compare_json_str_basic(Item *j, Item *s)
{
- String *res1,*res2;
- json_value_types type;
- char *value;
- int value_len, c_len;
- Item_func_json_extract *e= (Item_func_json_extract *) j;
-
- if ((res1= e->read_json(&value1, &type, &value, &value_len)))
- {
- if ((res2= s->val_str(&value2)))
- {
- if (type == JSON_VALUE_STRING)
- {
- if (value1.realloc_with_extra_if_needed(value_len) ||
- (c_len= json_unescape(value1.charset(), (uchar *) value,
- (uchar *) value+value_len,
- &my_charset_utf8_general_ci,
- (uchar *) value1.ptr(),
- (uchar *) (value1.ptr() + value_len))) < 0)
- goto error;
- value1.length(c_len);
- res1= &value1;
- }
+ String *js,*str;
+ int c_len;
+ json_engine_t je;
- if (set_null)
- owner->null_value= 0;
- return sortcmp(res1, res2, compare_collation());
- }
+ if ((js= j->val_str(&value1)))
+ {
+ json_scan_start(&je, js->charset(), (const uchar *) js->ptr(),
+ (const uchar *) js->ptr()+js->length());
+ if (json_read_value(&je))
+ goto error;
+ if (je.value_type == JSON_VALUE_STRING)
+ {
+ if (value2.realloc_with_extra_if_needed(je.value_len) ||
+ (c_len= json_unescape(js->charset(), je.value,
+ je.value + je.value_len,
+ &my_charset_utf8_general_ci,
+ (uchar *) value2.ptr(),
+ (uchar *) (value2.ptr() + je.value_len))) < 0)
+ goto error;
+
+ value2.length(c_len);
+ js= &value2;
+ str= &value1;
+ }
+ else
+ {
+ str= &value2;
+ }
+
+
+ if ((str= s->val_str(str)))
+ {
+ if (set_null)
+ owner->null_value= 0;
+ return sortcmp(js, str, compare_collation());
+ }
}
+
error:
if (set_null)
owner->null_value= 1;
diff --git a/sql/log.cc b/sql/log.cc
index ff4b0366b43..609f7d8e1fc 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -44,6 +44,8 @@
#include <my_dir.h>
#include <m_ctype.h> // For test_if_number
+#include <set_var.h> // for Sys_last_gtid_ptr
+
#ifdef _WIN32
#include "message.h"
#endif
@@ -2606,7 +2608,7 @@ bool MYSQL_LOG::open(
File file= -1;
my_off_t seek_offset;
bool is_fifo = false;
- int open_flags= O_CREAT | O_BINARY;
+ int open_flags= O_CREAT | O_BINARY | O_CLOEXEC;
DBUG_ENTER("MYSQL_LOG::open");
DBUG_PRINT("enter", ("log_type: %d", (int) log_type_arg));
@@ -3343,7 +3345,7 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg,
".index", opt);
if ((index_file_nr= mysql_file_open(m_key_file_log_index,
index_file_name,
- O_RDWR | O_CREAT | O_BINARY,
+ O_RDWR | O_CREAT | O_BINARY | O_CLOEXEC,
MYF(MY_WME))) < 0 ||
mysql_file_sync(index_file_nr, MYF(MY_WME)) ||
init_io_cache(&index_file, index_file_nr,
@@ -6010,7 +6012,8 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone,
}
if (err)
DBUG_RETURN(true);
- thd->last_commit_gtid= gtid;
+
+ thd->set_last_commit_gtid(gtid);
Gtid_log_event gtid_event(thd, seq_no, domain_id, standalone,
LOG_EVENT_SUPPRESS_USE_F, is_transactional,
@@ -9007,14 +9010,14 @@ int TC_LOG_MMAP::open(const char *opt_name)
tc_log_page_size= my_getpagesize();
fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME);
- if ((fd= mysql_file_open(key_file_tclog, logname, O_RDWR, MYF(0))) < 0)
+ if ((fd= mysql_file_open(key_file_tclog, logname, O_RDWR | O_CLOEXEC, MYF(0))) < 0)
{
if (my_errno != ENOENT)
goto err;
if (using_heuristic_recover())
return 1;
if ((fd= mysql_file_create(key_file_tclog, logname, CREATE_MODE,
- O_RDWR, MYF(MY_WME))) < 0)
+ O_RDWR | O_CLOEXEC, MYF(MY_WME))) < 0)
goto err;
inited=1;
file_length= opt_tc_log_size;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 4bce6fa3157..c550adea26b 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -5550,22 +5550,6 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi,
else
thd->variables.collation_database= thd->db_charset;
- {
- const CHARSET_INFO *cs= thd->charset();
- /*
- We cannot ask for parsing a statement using a character set
- without state_maps (parser internal data).
- */
- if (!cs->state_map)
- {
- rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
- ER_THD(thd, ER_SLAVE_FATAL_ERROR),
- "character_set cannot be parsed");
- thd->is_slave_error= true;
- goto end;
- }
- }
-
/*
Record any GTID in the same transaction, so slave state is
transactionally consistent.
@@ -13636,6 +13620,16 @@ void issue_long_find_row_warning(Log_event_type type,
}
+/*
+ HA_ERR_KEY_NOT_FOUND is a fatal error normally, but it's an expected
+ error in speculate optimistic mode, so use something non-fatal instead
+*/
+static int row_not_found_error(rpl_group_info *rgi)
+{
+ return rgi->speculation != rpl_group_info::SPECULATE_OPTIMISTIC
+ ? HA_ERR_KEY_NOT_FOUND : HA_ERR_RECORD_CHANGED;
+}
+
/**
Locate the current row in event's table.
@@ -13733,14 +13727,12 @@ int Rows_log_event::find_row(rpl_group_info *rgi)
int error;
DBUG_PRINT("info",("locating record using primary key (position)"));
- if (!table->file->inited &&
- (error= table->file->ha_rnd_init_with_error(0)))
- DBUG_RETURN(error);
-
error= table->file->ha_rnd_pos_by_record(table->record[0]);
if (unlikely(error))
{
DBUG_PRINT("info",("rnd_pos returns error %d",error));
+ if (error == HA_ERR_KEY_NOT_FOUND)
+ error= row_not_found_error(rgi);
table->file->print_error(error, MYF(0));
}
DBUG_RETURN(error);
@@ -13806,6 +13798,8 @@ int Rows_log_event::find_row(rpl_group_info *rgi)
HA_READ_KEY_EXACT))))
{
DBUG_PRINT("info",("no record matching the key found in the table"));
+ if (error == HA_ERR_KEY_NOT_FOUND)
+ error= row_not_found_error(rgi);
table->file->print_error(error, MYF(0));
table->file->ha_index_end();
goto end;
diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc
index 0483c7f5fbf..ce40b5edc2c 100644
--- a/sql/mysql_install_db.cc
+++ b/sql/mysql_install_db.cc
@@ -198,7 +198,7 @@ int main(int argc, char **argv)
die("database creation failed");
}
- printf("Creation of the database was successfull");
+ printf("Creation of the database was successful");
return 0;
}
diff --git a/sql/mysql_upgrade_service.cc b/sql/mysql_upgrade_service.cc
index 599f4a40ea0..1a3df4f5536 100644
--- a/sql/mysql_upgrade_service.cc
+++ b/sql/mysql_upgrade_service.cc
@@ -146,6 +146,11 @@ static void die(const char *fmt, ...)
exit(1);
}
+#define WRITE_LOG(fmt,...) {\
+ char log_buf[1024]; \
+ snprintf(log_buf,sizeof(log_buf), fmt, __VA_ARGS__);\
+ WriteFile(logfile_handle,log_buf, (DWORD)strlen(log_buf), 0 , 0);\
+}
/*
spawn-like function to run subprocesses.
@@ -187,17 +192,22 @@ static intptr_t run_tool(int wait_flag, const char *program,...)
{
char tmpdir[FN_REFLEN];
GetTempPath(FN_REFLEN, tmpdir);
- sprintf_s(logfile_path, "%s\\mysql_upgrade_service.%s.log", tmpdir,
+ sprintf_s(logfile_path, "%smysql_upgrade_service.%s.log", tmpdir,
opt_service);
- logfile_handle= CreateFile(logfile_path, GENERIC_WRITE, FILE_SHARE_READ,
- NULL, TRUNCATE_EXISTING, 0, NULL);
- if (!logfile_handle)
+ SECURITY_ATTRIBUTES attr= {0};
+ attr.nLength= sizeof(SECURITY_ATTRIBUTES);
+ attr.bInheritHandle= TRUE;
+ logfile_handle= CreateFile(logfile_path, FILE_APPEND_DATA,
+ FILE_SHARE_READ|FILE_SHARE_WRITE, &attr, CREATE_ALWAYS, 0, NULL);
+ if (logfile_handle == INVALID_HANDLE_VALUE)
{
die("Cannot open log file %s, windows error %u",
logfile_path, GetLastError());
}
}
+ WRITE_LOG("Executing %s\r\n", cmdline);
+
/* Start child process */
STARTUPINFO si= {0};
si.cb= sizeof(si);
@@ -458,7 +468,7 @@ int main(int argc, char **argv)
log("Phase 3/8: Starting mysqld for upgrade");
mysqld_process= (HANDLE)run_tool(P_NOWAIT, mysqld_path,
defaults_file_param, "--skip-networking", "--skip-grant-tables",
- "--enable-named-pipe", socket_param, NULL);
+ "--enable-named-pipe", socket_param,"--skip-slave-start", NULL);
if (mysqld_process == INVALID_HANDLE_VALUE)
{
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 1cfdcc9c9b2..7669610c696 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -5935,6 +5935,7 @@ bool JOIN::choose_tableless_subquery_plan()
functions produce empty subquery result. There is no need to further
rewrite the subquery because it will not be executed at all.
*/
+ exec_const_cond= 0;
return FALSE;
}
@@ -5966,6 +5967,6 @@ bool JOIN::choose_tableless_subquery_plan()
tmp_having= having;
}
}
- exec_const_cond= conds;
+ exec_const_cond= zero_result_cause ? 0 : conds;
return FALSE;
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index c9dfeb3e211..8ab892068b3 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -454,6 +454,22 @@ void sys_var::do_deprecated_warning(THD *thd)
@retval true on error, false otherwise (warning or ok)
*/
+
+
+bool throw_bounds_warning(THD *thd, const char *name,const char *v)
+{
+ if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
+ {
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, v);
+ return true;
+ }
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), name, v);
+ return false;
+}
+
+
bool throw_bounds_warning(THD *thd, const char *name,
bool fixed, bool is_unsigned, longlong v)
{
@@ -471,9 +487,7 @@ bool throw_bounds_warning(THD *thd, const char *name,
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
return true;
}
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), name, buf);
+ return throw_bounds_warning(thd, name, buf);
}
return false;
}
@@ -491,9 +505,7 @@ bool throw_bounds_warning(THD *thd, const char *name, bool fixed, double v)
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
return true;
}
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), name, buf);
+ return throw_bounds_warning(thd, name, buf);
}
return false;
}
@@ -1006,24 +1018,12 @@ int set_var_collation_client::update(THD *thd)
#ifndef EMBEDDED_LIBRARY
if (thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
{
- sys_var *svar;
- mysql_mutex_lock(&LOCK_plugin);
- if ((svar= find_sys_var_ex(thd, "character_set_client",
- sizeof("character_set_client") - 1,
- false, true)))
- thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
- mark_as_changed(thd, (LEX_CSTRING*)svar);
- if ((svar= find_sys_var_ex(thd, "character_set_results",
- sizeof("character_set_results") - 1,
- false, true)))
- thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
- mark_as_changed(thd, (LEX_CSTRING*)svar);
- if ((svar= find_sys_var_ex(thd, "character_set_connection",
- sizeof("character_set_connection") - 1,
- false, true)))
- thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
- mark_as_changed(thd, (LEX_CSTRING*)svar);
- mysql_mutex_unlock(&LOCK_plugin);
+ thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_client_ptr);
+ thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_results_ptr);
+ thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_connection_ptr);
}
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
#endif //EMBEDDED_LIBRARY
diff --git a/sql/set_var.h b/sql/set_var.h
index 82afb3ceea6..6097b28e76f 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -244,6 +244,12 @@ protected:
uchar *global_var_ptr()
{ return ((uchar*)&global_system_variables) + offset; }
+ void *max_var_ptr()
+ {
+ return scope() == SESSION ? (((uchar*)&max_system_variables) + offset) :
+ 0;
+ }
+
friend class Session_sysvars_tracker;
friend class Session_tracker;
};
@@ -427,7 +433,9 @@ bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode,
LEX_CSTRING *ls);
int default_regex_flags_pcre(const THD *thd);
-extern sys_var *Sys_autocommit_ptr;
+extern sys_var *Sys_autocommit_ptr, *Sys_last_gtid_ptr,
+ *Sys_character_set_client_ptr, *Sys_character_set_connection_ptr,
+ *Sys_character_set_results_ptr;
CHARSET_INFO *get_old_charset_by_name(const char *old_name);
@@ -435,6 +443,7 @@ int sys_var_init();
uint sys_var_elements();
int sys_var_add_options(DYNAMIC_ARRAY *long_options, int parse_flags);
void sys_var_end(void);
+bool check_has_super(sys_var *self, THD *thd, set_var *var);
plugin_ref *resolve_engine_list(THD *thd, const char *str_arg, size_t str_arg_len,
bool error_on_unknown_engine, bool temp_copy);
void free_engine_list(plugin_ref *list);
@@ -443,4 +452,3 @@ plugin_ref *temp_copy_engine_list(THD *thd, plugin_ref *list);
char *pretty_print_engine_list(THD *thd, plugin_ref *list);
#endif
-
diff --git a/sql/slave.cc b/sql/slave.cc
index 275db6165e9..bb1300d36e6 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -5663,7 +5663,7 @@ err_during_init:
*/
if (WSREP_ON && wsrep_node_dropped && wsrep_restart_slave)
{
- if (wsrep_ready)
+ if (wsrep_ready_get())
{
WSREP_INFO("Slave error due to node temporarily non-primary"
"SQL slave will continue");
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index aec15d38847..d00ee3e07ef 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3766,7 +3766,8 @@ bool hostname_requires_resolving(const char *hostname)
void set_authentication_plugin_from_password(const User_table& user_table,
const char* password, size_t password_length)
{
- if (password_length == SCRAMBLED_PASSWORD_CHAR_LENGTH)
+ if (password_length == SCRAMBLED_PASSWORD_CHAR_LENGTH ||
+ password_length == 0)
{
user_table.plugin()->store(native_password_plugin_name.str,
native_password_plugin_name.length,
@@ -3821,13 +3822,16 @@ static bool update_user_table(THD *thd, const User_table& user_table,
DBUG_RETURN(1); /* purecov: deadcode */
}
store_record(table,record[1]);
- /* If the password column is missing, we use the
- authentication_string column. */
- if (user_table.password())
- user_table.password()->store(new_password, new_password_len, system_charset_info);
- else
+
+ if (user_table.plugin())
+ {
set_authentication_plugin_from_password(user_table, new_password,
new_password_len);
+ new_password_len= 0;
+ }
+
+ if (user_table.password())
+ user_table.password()->store(new_password, new_password_len, system_charset_info);
if (unlikely(error= table->file->ha_update_row(table->record[1],
@@ -7540,7 +7544,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
INSERT_ACL : SELECT_ACL);
}
- if (tl->with ||
+ if (tl->with || !tl->db.str ||
(tl->select_lex &&
(tl->with= tl->select_lex->find_table_def_in_with_clauses(tl))))
continue;
diff --git a/sql/sql_analyze_stmt.cc b/sql/sql_analyze_stmt.cc
index 2c09772bd66..b66d69334f0 100644
--- a/sql/sql_analyze_stmt.cc
+++ b/sql/sql_analyze_stmt.cc
@@ -45,7 +45,7 @@ void Filesort_tracker::print_json_members(Json_writer *writer)
else if (r_limit == 0)
writer->add_str(varied_str);
else
- writer->add_ll((longlong) rint(r_limit/get_r_loops()));
+ writer->add_ll((longlong) rint(r_limit));
}
writer->add_member("r_used_priority_queue");
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 80939cbe59b..490f21aa950 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1572,6 +1572,12 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
DBUG_RETURN(true);
}
+ if (!table_list->db.str)
+ {
+ my_error(ER_NO_DB_ERROR, MYF(0));
+ DBUG_RETURN(true);
+ }
+
key_length= get_table_def_key(table_list, &key);
/*
@@ -5601,6 +5607,9 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, si
column reference. See create_view_field() for details.
*/
item= nj_col->create_item(thd);
+ if (!item)
+ DBUG_RETURN(NULL);
+
/*
*ref != NULL means that *ref contains the item that we need to
replace. If the item was aliased by the user, set the alias to
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 718d2424463..e3884922587 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -519,100 +519,6 @@ extern "C"
}
-/**
- Dumps a text description of a thread, its security context
- (user, host) and the current query.
-
- @param thd thread context
- @param buffer pointer to preferred result buffer
- @param length length of buffer
- @param max_query_len how many chars of query to copy (0 for all)
-
- @return Pointer to string
-*/
-
-extern "C"
-char *thd_get_error_context_description(THD *thd, char *buffer,
- unsigned int length,
- unsigned int max_query_len)
-{
- String str(buffer, length, &my_charset_latin1);
- const Security_context *sctx= &thd->main_security_ctx;
- char header[256];
- size_t len;
-
- /*
- The pointers thd->query and thd->proc_info might change since they are
- being modified concurrently. This is acceptable for proc_info since its
- values doesn't have to very accurate and the memory it points to is static,
- but we need to attempt a snapshot on the pointer values to avoid using NULL
- values. The pointer to thd->query however, doesn't point to static memory
- and has to be protected by thd->LOCK_thd_data or risk pointing to
- uninitialized memory.
- */
- const char *proc_info= thd->proc_info;
-
- len= my_snprintf(header, sizeof(header),
- "MySQL thread id %u, OS thread handle %lu, query id %llu",
- (uint)thd->thread_id, (ulong) thd->real_id, (ulonglong) thd->query_id);
- str.length(0);
- str.append(header, len);
-
- if (sctx->host)
- {
- str.append(' ');
- str.append(sctx->host);
- }
-
- if (sctx->ip)
- {
- str.append(' ');
- str.append(sctx->ip);
- }
-
- if (sctx->user)
- {
- str.append(' ');
- str.append(sctx->user);
- }
-
- if (proc_info)
- {
- str.append(' ');
- str.append(proc_info);
- }
-
- /* Don't wait if LOCK_thd_data is used as this could cause a deadlock */
- if (!mysql_mutex_trylock(&thd->LOCK_thd_data))
- {
- if (thd->query())
- {
- if (max_query_len < 1)
- len= thd->query_length();
- else
- len= MY_MIN(thd->query_length(), max_query_len);
- str.append('\n');
- str.append(thd->query(), len);
- }
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-
- if (str.c_ptr_safe() == buffer)
- return buffer;
-
- /*
- We have to copy the new string to the destination buffer because the string
- was reallocated to a larger buffer to be able to fit.
- */
- DBUG_ASSERT(buffer != NULL);
- length= MY_MIN(str.length(), length-1);
- memcpy(buffer, str.c_ptr_quick(), length);
- /* Make sure that the new string is null terminated */
- buffer[length]= '\0';
- return buffer;
-}
-
-
#if MARIA_PLUGIN_INTERFACE_VERSION < 0x0200
/**
TODO: This function is for API compatibility, remove it eventually.
@@ -1305,7 +1211,7 @@ void THD::init(bool skip_lock)
bzero((char *) &org_status_var, sizeof(org_status_var));
status_in_global= 0;
start_bytes_received= 0;
- last_commit_gtid.seq_no= 0;
+ m_last_commit_gtid.seq_no= 0;
last_stmt= NULL;
/* Reset status of last insert id */
arg_of_last_insert_id_function= FALSE;
@@ -7352,6 +7258,21 @@ THD::signal_wakeup_ready()
mysql_cond_signal(&COND_wakeup_ready);
}
+void THD::set_last_commit_gtid(rpl_gtid &gtid)
+{
+#ifndef EMBEDDED_LIBRARY
+ bool changed_gtid= (m_last_commit_gtid.seq_no != gtid.seq_no);
+#endif
+ m_last_commit_gtid= gtid;
+#ifndef EMBEDDED_LIBRARY
+ if (changed_gtid &&
+ session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
+ {
+ session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(this, (LEX_CSTRING*)Sys_last_gtid_ptr);
+ }
+#endif
+}
void
wait_for_commit::reinit()
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7a854e0c217..359d5f93a1f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3211,6 +3211,7 @@ public:
query_id_t first_query_id;
} binlog_evt_union;
+ mysql_cond_t COND_wsrep_thd;
/**
Internal parser state.
Note that since the parser is not re-entrant, we keep only one parser
@@ -4179,18 +4180,33 @@ public:
{
if (db.str == NULL)
{
- my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
- return TRUE;
+ /*
+ No default database is set. In this case if it's guaranteed that
+ no CTE can be used in the statement then we can throw an error right
+ now at the parser stage. Otherwise the decision about throwing such
+ a message must be postponed until a post-parser stage when we are able
+ to resolve all CTE names as we don't need this message to be thrown
+ for any CTE references.
+ */
+ if (!lex->with_clauses_list)
+ {
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
+ return TRUE;
+ }
+ /* This will allow to throw an error later for non-CTE references */
+ to->str= NULL;
+ to->length= 0;
+ return FALSE;
}
+
to->str= strmake(db.str, db.length);
to->length= db.length;
return to->str == NULL; /* True on error */
}
/* Get db name or "". Use for printing current db */
const char *get_db()
- {
- return db.str ? db.str : "";
- }
+ { return safe_str(db.str); }
+
thd_scheduler event_scheduler;
public:
@@ -4557,7 +4573,13 @@ public:
The GTID assigned to the last commit. If no GTID was assigned to any commit
so far, this is indicated by last_commit_gtid.seq_no == 0.
*/
- rpl_gtid last_commit_gtid;
+private:
+ rpl_gtid m_last_commit_gtid;
+
+public:
+ rpl_gtid get_last_commit_gtid() { return m_last_commit_gtid; }
+ void set_last_commit_gtid(rpl_gtid &gtid);
+
LF_PINS *tdc_hash_pins;
LF_PINS *xid_hash_pins;
@@ -6353,8 +6375,6 @@ inline int handler::ha_ft_read(uchar *buf)
inline int handler::ha_rnd_pos_by_record(uchar *buf)
{
int error= rnd_pos_by_record(buf);
- if (!error)
- update_rows_read();
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc
index 5d977c6d5c2..1c45b05ccc5 100644
--- a/sql/sql_explain.cc
+++ b/sql/sql_explain.cc
@@ -1693,7 +1693,7 @@ void Explain_table_access::print_explain_json(Explain_query *query,
{
/* Get r_filtered value from filesort */
if (pre_join_sort->tracker.get_r_loops())
- writer->add_double(pre_join_sort->tracker.get_r_filtered());
+ writer->add_double(pre_join_sort->tracker.get_r_filtered()*100);
else
writer->add_null();
}
@@ -2516,4 +2516,3 @@ void Explain_range_checked_fer::print_json(Json_writer *writer,
writer->end_object();
}
}
-
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index c2f161d507d..69ea04a170c 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -1031,6 +1031,7 @@ SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables,
if (!(handler= mysql_ha_find_handler(thd, &tables->alias)))
DBUG_RETURN(0);
tables->table= handler->table; // This is used by fix_fields
+ handler->table->pos_in_table_list= tables;
if (mysql_ha_fix_cond_and_key(handler, mode, keyname, key_expr,
ha_rkey_mode, cond, 1))
DBUG_RETURN(0);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 715d128c68f..52a465f7613 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -4574,12 +4574,44 @@ bool select_create::send_eof()
*/
if (!table->s->tmp_table)
{
+#ifdef WITH_WSREP
+ if (WSREP_ON)
+ {
+ /*
+ append table level exclusive key for CTAS
+ */
+ wsrep_key_arr_t key_arr= {0, 0};
+ wsrep_prepare_keys_for_isolation(thd,
+ create_table->db.str,
+ create_table->table_name.str,
+ table_list,
+ &key_arr);
+ int rcode = wsrep->append_key(
+ wsrep,
+ &thd->wsrep_ws_handle,
+ key_arr.keys, //&wkey,
+ key_arr.keys_len,
+ WSREP_KEY_EXCLUSIVE,
+ false);
+ wsrep_keys_free(&key_arr);
+ if (rcode) {
+ DBUG_PRINT("wsrep", ("row key failed: %d", rcode));
+ WSREP_ERROR("Appending table key for CTAS failed: %s, %d",
+ (wsrep_thd_query(thd)) ?
+ wsrep_thd_query(thd) : "void", rcode);
+ return true;
+ }
+ /* If commit fails, we should be able to reset the OK status. */
+ thd->get_stmt_da()->set_overwrite_status(TRUE);
+ }
+#endif /* WITH_WSREP */
trans_commit_stmt(thd);
if (!(thd->variables.option_bits & OPTION_GTID_BEGIN))
trans_commit_implicit(thd);
#ifdef WITH_WSREP
if (WSREP_ON)
{
+ thd->get_stmt_da()->set_overwrite_status(FALSE);
mysql_mutex_lock(&thd->LOCK_thd_data);
if (thd->wsrep_conflict_state != NO_CONFLICT)
{
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index a1307fb0b09..a1cacbd35a2 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3689,6 +3689,7 @@ mysql_execute_command(THD *thd)
{
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
execute_show_status(thd, all_tables);
+
break;
}
case SQLCOM_SHOW_EXPLAIN:
@@ -4753,7 +4754,7 @@ end_with_restore_list:
case SQLCOM_INSERT_SELECT:
{
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
- select_result *sel_result;
+ select_insert *sel_result;
bool explain= MY_TEST(lex->describe);
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (WSREP_CLIENT(thd) &&
@@ -6753,11 +6754,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
THD_STAGE_INFO(thd, stage_checking_permissions);
if (unlikely((!db || !db[0]) && !thd->db.str && !dont_check_global_grants))
{
- DBUG_PRINT("error",("No database"));
- if (!no_errors)
- my_message(ER_NO_DB_ERROR, ER_THD(thd, ER_NO_DB_ERROR),
- MYF(0)); /* purecov: tested */
- DBUG_RETURN(TRUE); /* purecov: tested */
+ DBUG_RETURN(FALSE); // CTE reference or an error later
}
if (likely((db != NULL) && (db != any_db)))
@@ -8384,7 +8381,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
lex->add_to_query_tables(ptr);
// Pure table aliases do not need to be locked:
- if (!MY_TEST(table_options & TL_OPTION_ALIAS))
+ if (ptr->db.str && !(table_options & TL_OPTION_ALIAS))
{
ptr->mdl_request.init(MDL_key::TABLE, ptr->db.str, ptr->table_name.str,
mdl_type,
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index ac1524381c7..8c231d9b8f7 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -2156,8 +2156,7 @@ bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name,
tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_PLUGIN_NAME, 0, TL_WRITE);
if (!opt_noacl && check_table_access(thd, INSERT_ACL, &tables, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
-
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* need to open before acquiring LOCK_plugin or it will deadlock */
if (! (table = open_ltable(thd, &tables, TL_WRITE,
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index f01ec789186..4c0035b9c48 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -2572,6 +2572,7 @@ static int send_events(binlog_send_info *info, IO_CACHE* log, LOG_INFO* linfo,
linfo->pos= my_b_tell(log);
info->last_pos= my_b_tell(log);
+ log->end_of_file= end_pos;
while (linfo->pos < end_pos)
{
if (should_stop(info))
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 317a7272793..00663ee6839 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1739,10 +1739,18 @@ JOIN::optimize_inner()
if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
(!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
{ /* Impossible cond */
- DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
- "Impossible HAVING" : "Impossible WHERE"));
- zero_result_cause= having_value == Item::COND_FALSE ?
- "Impossible HAVING" : "Impossible WHERE";
+ if (unit->select_limit_cnt)
+ {
+ DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE"));
+ zero_result_cause= having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE";
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Zero limit"));
+ zero_result_cause= "Zero limit";
+ }
table_count= top_join_tab_count= 0;
error= 0;
subq_exit_fl= true;
@@ -10391,7 +10399,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
table_map current_map;
i= join->const_tables;
for (tab= first_depth_first_tab(join); tab;
- tab= next_depth_first_tab(join, tab), i++)
+ tab= next_depth_first_tab(join, tab))
{
bool is_hj;
@@ -10876,6 +10884,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
}
first_inner_tab= first_inner_tab->first_upper;
}
+ if (!tab->bush_children)
+ i++;
}
}
DBUG_RETURN(0);
@@ -26307,21 +26317,18 @@ void JOIN::set_allowed_join_cache_types()
void JOIN::save_query_plan(Join_plan_state *save_to)
{
- if (keyuse.elements)
- {
- DYNAMIC_ARRAY tmp_keyuse;
- /* Swap the current and the backup keyuse internal arrays. */
- tmp_keyuse= keyuse;
- keyuse= save_to->keyuse; /* keyuse is reset to an empty array. */
- save_to->keyuse= tmp_keyuse;
+ DYNAMIC_ARRAY tmp_keyuse;
+ /* Swap the current and the backup keyuse internal arrays. */
+ tmp_keyuse= keyuse;
+ keyuse= save_to->keyuse; /* keyuse is reset to an empty array. */
+ save_to->keyuse= tmp_keyuse;
- for (uint i= 0; i < table_count; i++)
- {
- save_to->join_tab_keyuse[i]= join_tab[i].keyuse;
- join_tab[i].keyuse= NULL;
- save_to->join_tab_checked_keys[i]= join_tab[i].checked_keys;
- join_tab[i].checked_keys.clear_all();
- }
+ for (uint i= 0; i < table_count; i++)
+ {
+ save_to->join_tab_keyuse[i]= join_tab[i].keyuse;
+ join_tab[i].keyuse= NULL;
+ save_to->join_tab_checked_keys[i]= join_tab[i].checked_keys;
+ join_tab[i].checked_keys.clear_all();
}
memcpy((uchar*) save_to->best_positions, (uchar*) best_positions,
sizeof(POSITION) * (table_count + 1));
@@ -26359,20 +26366,17 @@ void JOIN::reset_query_plan()
void JOIN::restore_query_plan(Join_plan_state *restore_from)
{
- if (restore_from->keyuse.elements)
- {
- DYNAMIC_ARRAY tmp_keyuse;
- tmp_keyuse= keyuse;
- keyuse= restore_from->keyuse;
- restore_from->keyuse= tmp_keyuse;
-
- for (uint i= 0; i < table_count; i++)
- {
- join_tab[i].keyuse= restore_from->join_tab_keyuse[i];
- join_tab[i].checked_keys= restore_from->join_tab_checked_keys[i];
- }
+ DYNAMIC_ARRAY tmp_keyuse;
+ tmp_keyuse= keyuse;
+ keyuse= restore_from->keyuse;
+ restore_from->keyuse= tmp_keyuse;
+ for (uint i= 0; i < table_count; i++)
+ {
+ join_tab[i].keyuse= restore_from->join_tab_keyuse[i];
+ join_tab[i].checked_keys= restore_from->join_tab_checked_keys[i];
}
+
memcpy((uchar*) best_positions, (uchar*) restore_from->best_positions,
sizeof(POSITION) * (table_count + 1));
/* Restore SJM nests */
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 224e6f0e411..05a1cce4175 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2707,6 +2707,9 @@ static const char *thread_state_info(THD *tmp)
return "";
return "Reading from net";
}
+#else
+ if (tmp->get_command() == COM_SLEEP)
+ return "";
#endif
if (tmp->proc_info)
@@ -10316,3 +10319,85 @@ static void get_cs_converted_string_value(THD *thd,
return;
}
#endif
+
+/**
+ Dumps a text description of a thread, its security context
+ (user, host) and the current query.
+
+ @param thd thread context
+ @param buffer pointer to preferred result buffer
+ @param length length of buffer
+ @param max_query_len how many chars of query to copy (0 for all)
+
+ @return Pointer to string
+*/
+
+extern "C"
+char *thd_get_error_context_description(THD *thd, char *buffer,
+ unsigned int length,
+ unsigned int max_query_len)
+{
+ String str(buffer, length, &my_charset_latin1);
+ const Security_context *sctx= &thd->main_security_ctx;
+ char header[256];
+ size_t len;
+
+ len= my_snprintf(header, sizeof(header),
+ "MySQL thread id %u, OS thread handle %lu, query id %llu",
+ (uint)thd->thread_id, (ulong) thd->real_id, (ulonglong) thd->query_id);
+ str.length(0);
+ str.append(header, len);
+
+ if (sctx->host)
+ {
+ str.append(' ');
+ str.append(sctx->host);
+ }
+
+ if (sctx->ip)
+ {
+ str.append(' ');
+ str.append(sctx->ip);
+ }
+
+ if (sctx->user)
+ {
+ str.append(' ');
+ str.append(sctx->user);
+ }
+
+ /* Don't wait if LOCK_thd_data is used as this could cause a deadlock */
+ if (!mysql_mutex_trylock(&thd->LOCK_thd_data))
+ {
+ if (const char *info= thread_state_info(thd))
+ {
+ str.append(' ');
+ str.append(info);
+ }
+
+ if (thd->query())
+ {
+ if (max_query_len < 1)
+ len= thd->query_length();
+ else
+ len= MY_MIN(thd->query_length(), max_query_len);
+ str.append('\n');
+ str.append(thd->query(), len);
+ }
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ }
+
+ if (str.c_ptr_safe() == buffer)
+ return buffer;
+
+ /*
+ We have to copy the new string to the destination buffer because the string
+ was reallocated to a larger buffer to be able to fit.
+ */
+ DBUG_ASSERT(buffer != NULL);
+ length= MY_MIN(str.length(), length-1);
+ memcpy(buffer, str.c_ptr_quick(), length);
+ /* Make sure that the new string is null terminated */
+ buffer[length]= '\0';
+ return buffer;
+}
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 4edcb779379..00ed7fb0202 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -3095,7 +3095,7 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
{
- if (!tl->is_view_or_derived() && tl->table)
+ if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
{
TABLE_SHARE *table_share= tl->table->s;
if (table_share &&
@@ -3107,7 +3107,7 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
{
- if (!tl->is_view_or_derived() && tl->table)
+ if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
{
TABLE_SHARE *table_share= tl->table->s;
if (table_share &&
@@ -3236,7 +3236,7 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
{
- if (!tl->is_view_or_derived() && tl->table)
+ if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
{
TABLE_SHARE *table_share= tl->table->s;
if (table_share &&
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 74a6e04b928..dbf400b53d7 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -6237,8 +6237,11 @@ drop_create_field:
continue;
/* Check if the table already has a PRIMARY KEY */
- bool dup_primary_key= key->type == Key::PRIMARY &&
- table->s->primary_key != MAX_KEY;
+ bool dup_primary_key=
+ key->type == Key::PRIMARY &&
+ table->s->primary_key != MAX_KEY &&
+ (keyname= table->s->key_info[table->s->primary_key].name.str) &&
+ my_strcasecmp(system_charset_info, keyname, primary_key_name) == 0;
if (dup_primary_key)
goto remove_key;
@@ -6337,7 +6340,6 @@ remove_key:
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
- DBUG_ASSERT(thd->work_part_info == 0);
partition_info *tab_part_info= table->part_info;
thd->work_part_info= thd->lex->part_info;
if (tab_part_info)
@@ -9054,10 +9056,6 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
{
DBUG_ENTER("mysql_alter_table");
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- thd->work_part_info= 0; // Used by partitioning
-#endif
-
/*
Check if we attempt to alter mysql.slow_log or
mysql.general_log table and return an error if
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index df3a2dc9c04..755a9a9486d 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -454,7 +454,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, MYF(0));
DBUG_RETURN(TRUE);
}
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
if (!create)
{
@@ -516,6 +515,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
if (err_status)
goto end;
}
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* We should have only one table in table list. */
DBUG_ASSERT(tables->next_global == 0);
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 266f221ca78..12035326872 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -377,7 +377,7 @@ select_unit::create_result_table(THD *thd_arg, List<Item> *column_types,
table->keys_in_use_for_query.clear_all();
for (uint i=0; i < table->s->fields; i++)
- table->field[i]->flags &= ~PART_KEY_FLAG;
+ table->field[i]->flags &= ~(PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG);
if (create_table)
{
@@ -413,7 +413,7 @@ select_union_recursive::create_result_table(THD *thd_arg,
incr_table->keys_in_use_for_query.clear_all();
for (uint i=0; i < table->s->fields; i++)
- incr_table->field[i]->flags &= ~PART_KEY_FLAG;
+ incr_table->field[i]->flags &= ~(PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG);
TABLE *rec_table= 0;
if (! (rec_table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
@@ -424,7 +424,7 @@ select_union_recursive::create_result_table(THD *thd_arg,
rec_table->keys_in_use_for_query.clear_all();
for (uint i=0; i < table->s->fields; i++)
- rec_table->field[i]->flags &= ~PART_KEY_FLAG;
+ rec_table->field[i]->flags &= ~(PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG);
if (rec_tables.push_back(rec_table))
return true;
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 783c655d007..f262daad89d 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -435,7 +435,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
goto err;
}
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/*
ignore lock specs for CREATE statement
@@ -711,14 +711,14 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
lex->link_first_table_back(view, link_to_local);
DBUG_RETURN(0);
+#ifdef WITH_WSREP
+ error:
+ res= TRUE;
+#endif /* WITH_WSREP */
err:
lex->link_first_table_back(view, link_to_local);
unit->cleanup();
DBUG_RETURN(res || thd->is_error());
-#ifdef WITH_WSREP
- error:
- DBUG_RETURN(true);
-#endif /* WITH_WSREP */
}
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index ccb7d3b29ed..28e8f3f6938 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -458,7 +458,7 @@ error_if_in_trans_or_substatement(THD *thd, int in_substatement_error,
return false;
}
-static bool check_has_super(sys_var *self, THD *thd, set_var *var)
+bool check_has_super(sys_var *self, THD *thd, set_var *var)
{
DBUG_ASSERT(self->scope() != sys_var::GLOBAL);// don't abuse check_has_super()
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -702,6 +702,8 @@ static Sys_var_struct Sys_character_set_client(
offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info),
NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_cs_client),
ON_UPDATE(fix_thd_charset));
+// for check changing
+export sys_var *Sys_character_set_client_ptr= &Sys_character_set_client;
static Sys_var_struct Sys_character_set_connection(
"character_set_connection", "The character set used for "
@@ -711,6 +713,8 @@ static Sys_var_struct Sys_character_set_connection(
offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info),
NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_charset_not_null),
ON_UPDATE(fix_thd_charset));
+// for check changing
+export sys_var *Sys_character_set_connection_ptr= &Sys_character_set_connection;
static Sys_var_struct Sys_character_set_results(
"character_set_results", "The character set used for returning "
@@ -718,6 +722,8 @@ static Sys_var_struct Sys_character_set_results(
SESSION_VAR(character_set_results), NO_CMD_LINE,
offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_charset));
+// for check changing
+export sys_var *Sys_character_set_results_ptr= &Sys_character_set_results;
static Sys_var_struct Sys_character_set_filesystem(
"character_set_filesystem", "The filesystem character set",
@@ -1907,6 +1913,8 @@ static Sys_var_last_gtid Sys_last_gtid(
"or the empty string if none.",
READ_ONLY sys_var::ONLY_SESSION, NO_CMD_LINE);
+export sys_var *Sys_last_gtid_ptr= &Sys_last_gtid; // for check changing
+
uchar *
Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_CSTRING *base)
@@ -1917,8 +1925,9 @@ Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_CSTRING *base)
bool first= true;
str.length(0);
- if ((thd->last_commit_gtid.seq_no > 0 &&
- rpl_slave_state_tostring_helper(&str, &thd->last_commit_gtid, &first)) ||
+ rpl_gtid gtid= thd->get_last_commit_gtid();
+ if ((gtid.seq_no > 0 &&
+ rpl_slave_state_tostring_helper(&str, &gtid, &first)) ||
!(p= thd->strmake(str.ptr(), str.length())))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic
index c0b7950518b..373df354268 100644
--- a/sql/sys_vars.ic
+++ b/sql/sys_vars.ic
@@ -147,9 +147,10 @@ public:
option.min_value= min_val;
option.max_value= max_val;
option.block_size= block_size;
- option.u_max_value= (uchar**)max_var_ptr();
- if (max_var_ptr())
- *max_var_ptr()= max_val;
+ if ((option.u_max_value= (uchar**) max_var_ptr()))
+ {
+ *((T*) option.u_max_value)= max_val;
+ }
global_var(T)= def_val;
SYSVAR_ASSERT(size == sizeof(T));
@@ -181,8 +182,8 @@ public:
var->save_result.ulonglong_value=
getopt_ull_limit_value(uv, &option, &unused);
- if (max_var_ptr() && (T)var->save_result.ulonglong_value > *max_var_ptr())
- var->save_result.ulonglong_value= *max_var_ptr();
+ if (max_var_ptr() && (T)var->save_result.ulonglong_value > get_max_var())
+ var->save_result.ulonglong_value= get_max_var();
fixed= fixed || var->save_result.ulonglong_value != uv;
}
@@ -198,8 +199,8 @@ public:
var->save_result.longlong_value=
getopt_ll_limit_value(v, &option, &unused);
- if (max_var_ptr() && (T)var->save_result.longlong_value > *max_var_ptr())
- var->save_result.longlong_value= *max_var_ptr();
+ if (max_var_ptr() && (T)var->save_result.longlong_value > get_max_var())
+ var->save_result.longlong_value= get_max_var();
fixed= fixed || var->save_result.longlong_value != v;
}
@@ -221,11 +222,7 @@ public:
void global_save_default(THD *thd, set_var *var)
{ var->save_result.ulonglong_value= option.def_value; }
private:
- T *max_var_ptr()
- {
- return scope() == SESSION ? (T*)(((uchar*)&max_system_variables) + offset)
- : 0;
- }
+ T get_max_var() { return *((T*) max_var_ptr()); }
uchar *default_value_ptr(THD *thd) { return (uchar*) &option.def_value; }
};
@@ -269,6 +266,9 @@ class Sys_var_typelib: public sys_var
{
protected:
TYPELIB typelib;
+ virtual bool check_maximum(THD *thd, set_var *var,
+ const char *c_val, longlong i_val)
+ { return FALSE; }
public:
Sys_var_typelib(const char *name_arg,
const char *comment, int flag_args, ptrdiff_t off,
@@ -304,17 +304,14 @@ public:
return true;
else
var->save_result.ulonglong_value--;
- }
- else
- {
- longlong tmp=var->value->val_int();
- if (tmp < 0 || tmp >= typelib.count)
- return true;
- else
- var->save_result.ulonglong_value= tmp;
+ return check_maximum(thd, var, res->ptr(), 0);
}
- return false;
+ longlong tmp=var->value->val_int();
+ if (tmp < 0 || tmp >= typelib.count)
+ return true;
+ var->save_result.ulonglong_value= tmp;
+ return check_maximum(thd, var, 0, tmp);
}
};
@@ -349,10 +346,28 @@ public:
substitute)
{
option.var_type|= GET_ENUM;
+ option.min_value= 0;
+ option.max_value= ULONG_MAX;
global_var(ulong)= def_val;
+ if ((option.u_max_value= (uchar**)max_var_ptr()))
+ {
+ *((ulong *) option.u_max_value)= ULONG_MAX;
+ }
SYSVAR_ASSERT(def_val < typelib.count);
SYSVAR_ASSERT(size == sizeof(ulong));
}
+ bool check_maximum(THD *thd, set_var *var,
+ const char *c_val, longlong i_val)
+ {
+ if (!max_var_ptr() ||
+ var->save_result.ulonglong_value <= get_max_var())
+ return FALSE;
+ var->save_result.ulonglong_value= get_max_var();
+
+ return c_val ? throw_bounds_warning(thd, name.str, c_val) :
+ throw_bounds_warning(thd, name.str, TRUE,
+ var->value->unsigned_flag, i_val);
+ }
bool session_update(THD *thd, set_var *var)
{
session_var(thd, ulong)= static_cast<ulong>(var->save_result.ulonglong_value);
@@ -375,6 +390,8 @@ public:
{ return valptr(thd, global_var(ulong)); }
uchar *default_value_ptr(THD *thd)
{ return valptr(thd, (ulong)option.def_value); }
+
+ ulong get_max_var() { return *((ulong *) max_var_ptr()); }
};
/**
@@ -1341,12 +1358,30 @@ public:
substitute)
{
option.var_type|= GET_SET;
+ option.min_value= 0;
+ option.max_value= ~0ULL;
global_var(ulonglong)= def_val;
+ if ((option.u_max_value= (uchar**)max_var_ptr()))
+ {
+ *((ulonglong*) option.u_max_value)= ~0ULL;
+ }
SYSVAR_ASSERT(typelib.count > 0);
SYSVAR_ASSERT(typelib.count <= 64);
SYSVAR_ASSERT(def_val <= my_set_bits(typelib.count));
SYSVAR_ASSERT(size == sizeof(ulonglong));
}
+ bool check_maximum(THD *thd, set_var *var,
+ const char *c_val, longlong i_val)
+ {
+ if (!max_var_ptr() ||
+ (var->save_result.ulonglong_value & ~(get_max_var())) == 0)
+ return FALSE;
+ var->save_result.ulonglong_value&= get_max_var();
+
+ return c_val ? throw_bounds_warning(thd, name.str, c_val) :
+ throw_bounds_warning(thd, name.str, TRUE,
+ var->value->unsigned_flag, i_val);
+ }
bool do_check(THD *thd, set_var *var)
{
char buff[STRING_BUFFER_USUAL_SIZE];
@@ -1354,42 +1389,38 @@ public:
if (var->value->result_type() == STRING_RESULT)
{
+ char *error;
+ uint error_len;
+ bool not_used;
+
if (!(res= var->value->val_str_ascii_revert_empty_string_is_null(thd,
&str)))
return true;
- else
- {
- char *error;
- uint error_len;
- bool not_used;
- var->save_result.ulonglong_value=
- find_set(&typelib, res->ptr(), res->length(), NULL,
- &error, &error_len, &not_used);
- /*
- note, we only issue an error if error_len > 0.
- That is even while empty (zero-length) values are considered
- errors by find_set(), these errors are ignored here
- */
- if (unlikely(error_len))
- {
- ErrConvString err(error, error_len, res->charset());
- my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
- return true;
- }
- }
- }
- else
- {
- longlong tmp=var->value->val_int();
- if ((tmp < 0 && ! var->value->unsigned_flag)
- || (ulonglong)tmp > my_set_bits(typelib.count))
+ var->save_result.ulonglong_value=
+ find_set(&typelib, res->ptr(), res->length(), NULL,
+ &error, &error_len, &not_used);
+ /*
+ note, we only issue an error if error_len > 0.
+ That is even while empty (zero-length) values are considered
+ errors by find_set(), these errors are ignored here
+ */
+ if (error_len)
+ {
+ ErrConvString err(error, error_len, res->charset());
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
return true;
- else
- var->save_result.ulonglong_value= tmp;
+ }
+ return check_maximum(thd, var, res->ptr(), 0);
}
- return false;
+ longlong tmp=var->value->val_int();
+ if ((tmp < 0 && ! var->value->unsigned_flag)
+ || (ulonglong)tmp > my_set_bits(typelib.count))
+ return true;
+
+ var->save_result.ulonglong_value= tmp;
+ return check_maximum(thd, var, 0, tmp);
}
bool session_update(THD *thd, set_var *var)
{
@@ -1413,6 +1444,8 @@ public:
{ return valptr(thd, global_var(ulonglong)); }
uchar *default_value_ptr(THD *thd)
{ return valptr(thd, option.def_value); }
+
+ ulonglong get_max_var() { return *((ulonglong*) max_var_ptr()); }
};
/**
diff --git a/sql/sys_vars_shared.h b/sql/sys_vars_shared.h
index 48154c95a72..69382974175 100644
--- a/sql/sys_vars_shared.h
+++ b/sql/sys_vars_shared.h
@@ -28,6 +28,7 @@
#include <sql_priv.h>
#include "set_var.h"
+extern bool throw_bounds_warning(THD *thd, const char *name,const char *v);
extern bool throw_bounds_warning(THD *thd, const char *name,
bool fixed, bool is_unsigned, longlong v);
extern bool throw_bounds_warning(THD *thd, const char *name, bool fixed,
diff --git a/sql/table.cc b/sql/table.cc
index 843e87c4e02..f33e90d73b8 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1849,7 +1849,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if ((uchar)field_type == (uchar)MYSQL_TYPE_VIRTUAL)
{
- DBUG_ASSERT(interval_nr); // Expect non-null expression
+ if (!interval_nr) // Expect non-null expression
+ goto err;
/*
MariaDB version 10.0 version.
The interval_id byte in the .frm file stores the length of the
@@ -2535,6 +2536,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
reg_field->vcol_info= vcol_info;
share->virtual_fields++;
share->stored_fields--;
+ if (reg_field->flags & BLOB_FLAG)
+ share->virtual_not_stored_blob_fields++;
/* Correct stored_rec_length as non stored fields are last */
recpos= (uint) (reg_field->ptr - record);
if (share->stored_rec_length >= recpos)
@@ -3494,7 +3497,7 @@ partititon_err:
}
}
- outparam->mark_columns_used_by_check_constraints();
+ outparam->mark_columns_used_by_virtual_fields();
if (db_stat)
{
@@ -5924,6 +5927,8 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
Item *item= (new (thd->mem_root)
Item_direct_view_ref(thd, context, field_ref, view->alias.str,
name, view));
+ if (!item)
+ return NULL;
/*
Force creation of nullable item for the result tmp table for outer joined
views/derived tables.
@@ -6394,11 +6399,12 @@ void TABLE::mark_columns_needed_for_delete()
Field **reg_field;
for (reg_field= field ; *reg_field ; reg_field++)
{
- if ((*reg_field)->flags & PART_KEY_FLAG)
+ Field *cur_field= *reg_field;
+ if (cur_field->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG))
{
- bitmap_set_bit(read_set, (*reg_field)->field_index);
- if ((*reg_field)->vcol_info)
- mark_virtual_col(*reg_field);
+ bitmap_set_bit(read_set, cur_field->field_index);
+ if (cur_field->vcol_info)
+ bitmap_set_bit(vcol_set, cur_field->field_index);
}
}
need_signal= true;
@@ -6767,7 +6773,8 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl
if (bitmap_is_set(write_set, tmp_vfield->field_index))
bitmap_updated|= mark_virtual_col(tmp_vfield);
else if (tmp_vfield->vcol_info->stored_in_db ||
- (tmp_vfield->flags & (PART_KEY_FLAG | FIELD_IN_PART_FUNC_FLAG)))
+ (tmp_vfield->flags & (PART_KEY_FLAG | FIELD_IN_PART_FUNC_FLAG |
+ PART_INDIRECT_KEY_FLAG)))
{
bitmap_set_bit(write_set, tmp_vfield->field_index);
mark_virtual_col(tmp_vfield);
@@ -6832,27 +6839,64 @@ bool TABLE::check_virtual_columns_marked_for_write()
/*
- Mark fields used by check constraints.
+ Mark fields used by check constraints into s->check_set.
+ Mark all fields used in an expression that is part of an index
+ with PART_INDIRECT_KEY_FLAG
+
This is done once for the TABLE_SHARE the first time the table is opened.
The marking must be done non-destructively to handle the case when
this could be run in parallely by two threads
*/
-void TABLE::mark_columns_used_by_check_constraints(void)
+void TABLE::mark_columns_used_by_virtual_fields(void)
{
MY_BITMAP *save_read_set;
- /* If there is no check constraints or if check_set is already initialized */
- if (!s->check_set || s->check_set_initialized)
+ Field **vfield_ptr;
+
+ /* If there is virtual fields are already initialized */
+ if (s->check_set_initialized)
return;
- save_read_set= read_set;
- read_set= s->check_set;
+ if (s->tmp_table == NO_TMP_TABLE)
+ mysql_mutex_lock(&s->LOCK_share);
+ if (s->check_set)
+ {
+ /* Mark fields used by check constraint */
+ save_read_set= read_set;
+ read_set= s->check_set;
+
+ for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
+ (*chk)->expr->walk(&Item::register_field_in_read_map, 1, 0);
+ read_set= save_read_set;
+ }
- for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
- (*chk)->expr->walk(&Item::register_field_in_read_map, 1, 0);
+ /*
+ mark all fields that part of a virtual indexed field with
+ PART_INDIRECT_KEY_FLAG. This is used to ensure that all fields
+ that are part of an index exits before write/delete/update.
- read_set= save_read_set;
+ As this code is only executed once per open share, it's reusing
+ existing functionality instead of adding an extra argument to
+ add_field_to_set_processor or adding another processor.
+ */
+ if (vfield)
+ {
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ if ((*vfield_ptr)->flags & PART_KEY_FLAG)
+ (*vfield_ptr)->vcol_info->expr->walk(&Item::add_field_to_set_processor,
+ 1, this);
+ }
+ for (uint i= 0 ; i < s->fields ; i++)
+ {
+ if (bitmap_is_set(&tmp_set, i))
+ field[i]->flags|= PART_INDIRECT_KEY_FLAG;
+ }
+ bitmap_clear_all(&tmp_set);
+ }
s->check_set_initialized= 1;
+ if (s->tmp_table == NO_TMP_TABLE)
+ mysql_mutex_unlock(&s->LOCK_share);
}
/* Add fields used by CHECK CONSTRAINT to read map */
@@ -6902,6 +6946,52 @@ void TABLE::move_fields(Field **ptr, const uchar *to, const uchar *from)
}
+/*
+ Store all allocated virtual fields blob values
+ Used by InnoDB when calculating virtual fields for it's own internal
+ records
+*/
+
+void TABLE::remember_blob_values(String *blob_storage)
+{
+ Field **vfield_ptr;
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ if ((*vfield_ptr)->type() == MYSQL_TYPE_BLOB &&
+ !(*vfield_ptr)->vcol_info->stored_in_db)
+ {
+ Field_blob *blob= ((Field_blob*) *vfield_ptr);
+ memcpy((void*) blob_storage, (void*) &blob->value, sizeof(blob->value));
+ blob_storage++;
+ blob->value.release();
+ }
+ }
+}
+
+
+/*
+ Restore all allocated virtual fields blob values
+ Used by InnoDB when calculating virtual fields for it's own internal
+ records
+*/
+
+void TABLE::restore_blob_values(String *blob_storage)
+{
+ Field **vfield_ptr;
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ if ((*vfield_ptr)->type() == MYSQL_TYPE_BLOB &&
+ !(*vfield_ptr)->vcol_info->stored_in_db)
+ {
+ Field_blob *blob= ((Field_blob*) *vfield_ptr);
+ blob->value.free();
+ memcpy((void*) &blob->value, (void*) blob_storage, sizeof(blob->value));
+ blob_storage++;
+ }
+ }
+}
+
+
/**
@brief
Allocate space for keys
@@ -7631,7 +7721,8 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
update= bitmap_is_set(vcol_set, vf->field_index);
break;
case VCOL_UPDATE_FOR_REPLACE:
- update= ((!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
+ update= ((!vcol_info->stored_in_db &&
+ (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
bitmap_is_set(vcol_set, vf->field_index)) ||
update_all_columns);
if (update && (vf->flags & BLOB_FLAG))
@@ -7650,7 +7741,8 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
case VCOL_UPDATE_INDEXED:
case VCOL_UPDATE_INDEXED_FOR_UPDATE:
/* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */
- update= (!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
+ update= (!vcol_info->stored_in_db &&
+ (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
!bitmap_is_set(vcol_set, vf->field_index));
swap_values= 1;
break;
@@ -8212,7 +8304,15 @@ int TABLE_LIST::fetch_number_of_rows()
{
int error= 0;
if (jtbm_subselect)
+ {
+ if (jtbm_subselect->is_jtbm_merged)
+ {
+ table->file->stats.records= (ha_rows)jtbm_subselect->jtbm_record_count;
+ set_if_bigger(table->file->stats.records, 2);
+ table->used_stat_records= table->file->stats.records;
+ }
return 0;
+ }
if (is_materialized_derived() && !fill_me)
{
table->file->stats.records= ((select_unit*)(get_unit()->result))->records;
diff --git a/sql/table.h b/sql/table.h
index ea00441fb5e..80f5e1283a3 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -687,8 +687,11 @@ struct TABLE_SHARE
*/
uint null_bytes_for_compare;
uint fields; /* number of fields */
- uint stored_fields; /* number of stored fields, purely virtual not included */
+ /* number of stored fields, purely virtual not included */
+ uint stored_fields;
uint virtual_fields; /* number of purely virtual fields */
+ /* number of purely virtual not stored blobs */
+ uint virtual_not_stored_blob_fields;
uint null_fields; /* number of null fields */
uint blob_fields; /* number of blob fields */
uint varchar_fields; /* number of varchar fields */
@@ -1377,7 +1380,7 @@ public:
bool check_virtual_columns_marked_for_read();
bool check_virtual_columns_marked_for_write();
void mark_default_fields_for_write(bool insert_fl);
- void mark_columns_used_by_check_constraints(void);
+ void mark_columns_used_by_virtual_fields(void);
void mark_check_constraint_columns_for_read(void);
int verify_constraints(bool ignore_failure);
inline void column_bitmaps_set(MY_BITMAP *read_set_arg)
@@ -1477,6 +1480,8 @@ public:
{ return (my_ptrdiff_t) (s->default_values - record[0]); }
void move_fields(Field **ptr, const uchar *to, const uchar *from);
+ void remember_blob_values(String *blob_storage);
+ void restore_blob_values(String *blob_storage);
uint actual_n_key_parts(KEY *keyinfo);
ulong actual_key_flags(KEY *keyinfo);
diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc
index 3ffd5d7706b..d4d35d752be 100644
--- a/sql/wsrep_hton.cc
+++ b/sql/wsrep_hton.cc
@@ -119,7 +119,7 @@ void wsrep_post_commit(THD* thd, bool all)
switch (thd->wsrep_exec_mode)
{
- case LOCAL_COMMIT:
+ case LOCAL_COMMIT:
{
DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED);
if (wsrep && wsrep->post_commit(wsrep, &thd->wsrep_ws_handle))
@@ -131,18 +131,30 @@ void wsrep_post_commit(THD* thd, bool all)
wsrep_cleanup_transaction(thd);
break;
}
- case LOCAL_STATE:
- {
- /*
- Non-InnoDB statements may have populated events in stmt cache => cleanup
- */
- WSREP_DEBUG("cleanup transaction for LOCAL_STATE: %s", thd->query());
- wsrep_cleanup_transaction(thd);
- break;
- }
- default: break;
+ case LOCAL_STATE:
+ {
+ /* non-InnoDB statements may have populated events in stmt cache
+ => cleanup
+ */
+ WSREP_DEBUG("cleanup transaction for LOCAL_STATE");
+ /*
+ Run post-rollback hook to clean up in the case if
+ some keys were populated for the transaction in provider
+ but during commit time there was no write set to replicate.
+ This may happen when client sets the SAVEPOINT and immediately
+ rolls back to savepoint after first operation.
+ */
+ if (all && thd->wsrep_conflict_state != MUST_REPLAY &&
+ wsrep && wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle))
+ {
+ WSREP_WARN("post_rollback fail: %llu %d",
+ (long long)thd->thread_id, thd->get_stmt_da()->status());
+ }
+ wsrep_cleanup_transaction(thd);
+ break;
+ }
+ default: break;
}
-
}
/*
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 0c051d384c9..7a90373e252 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -13,7 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
-#include "mariadb.h"
+#include "sql_plugin.h" /* wsrep_plugins_pre_init() */
#include <mysqld.h>
#include <sql_class.h>
#include <sql_parse.h>
@@ -38,7 +38,6 @@
#include <cstdlib>
#include "log_event.h"
#include <slave.h>
-#include "sql_plugin.h" /* wsrep_plugins_pre_init() */
wsrep_t *wsrep = NULL;
/*
@@ -313,8 +312,7 @@ wsrep_view_handler_cb (void* app_ctx,
if (memcmp(&cluster_uuid, &view->state_id.uuid, sizeof(wsrep_uuid_t)))
{
- memcpy((wsrep_uuid_t*)&cluster_uuid, &view->state_id.uuid,
- sizeof(cluster_uuid));
+ memcpy(&cluster_uuid, &view->state_id.uuid, sizeof(cluster_uuid));
wsrep_uuid_print (&cluster_uuid, cluster_uuid_str,
sizeof(cluster_uuid_str));
@@ -360,7 +358,7 @@ wsrep_view_handler_cb (void* app_ctx,
// version change
if (view->proto_ver != wsrep_protocol_version)
{
- my_bool wsrep_ready_saved= wsrep_ready;
+ my_bool wsrep_ready_saved= wsrep_ready_get();
wsrep_ready_set(FALSE);
WSREP_INFO("closing client connections for "
"protocol change %ld -> %d",
@@ -475,16 +473,34 @@ out:
return WSREP_CB_SUCCESS;
}
-void wsrep_ready_set (my_bool x)
+my_bool wsrep_ready_set (my_bool x)
{
WSREP_DEBUG("Setting wsrep_ready to %d", x);
if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
- if (wsrep_ready != x)
+ my_bool ret= (wsrep_ready != x);
+ if (ret)
{
wsrep_ready= x;
mysql_cond_signal (&COND_wsrep_ready);
}
mysql_mutex_unlock (&LOCK_wsrep_ready);
+ return ret;
+}
+
+my_bool wsrep_ready_get (void)
+{
+ if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
+ my_bool ret= wsrep_ready;
+ mysql_mutex_unlock (&LOCK_wsrep_ready);
+ return ret;
+}
+
+int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff)
+{
+ var->type= SHOW_MY_BOOL;
+ var->value= buff;
+ *((my_bool *)buff)= wsrep_ready_get();
+ return 0;
}
// Wait until wsrep has reached ready state
@@ -503,17 +519,8 @@ void wsrep_ready_wait ()
static void wsrep_synced_cb(void* app_ctx)
{
WSREP_INFO("Synchronized with group, ready for connections");
- bool signal_main= false;
- if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
- if (!wsrep_ready)
- {
- wsrep_ready= TRUE;
- mysql_cond_signal (&COND_wsrep_ready);
- signal_main= true;
-
- }
+ my_bool signal_main= wsrep_ready_set(TRUE);
wsrep_config_state->set(WSREP_MEMBER_SYNCED);
- mysql_mutex_unlock (&LOCK_wsrep_ready);
if (signal_main)
{
@@ -995,6 +1002,8 @@ bool wsrep_must_sync_wait (THD* thd, uint mask)
{
return (thd->variables.wsrep_sync_wait & mask) &&
thd->variables.wsrep_on &&
+ !(thd->variables.wsrep_dirty_reads &&
+ !is_update_query(thd->lex->sql_command)) &&
!thd->in_active_multi_stmt_transaction() &&
thd->wsrep_conflict_state != REPLAYING &&
thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED;
@@ -1042,17 +1051,7 @@ bool wsrep_sync_wait (THD* thd, uint mask)
return false;
}
-/*
- * Helpers to deal with TOI key arrays
- */
-typedef struct wsrep_key_arr
-{
- wsrep_key_t* keys;
- size_t keys_len;
-} wsrep_key_arr_t;
-
-
-static void wsrep_keys_free(wsrep_key_arr_t* key_arr)
+void wsrep_keys_free(wsrep_key_arr_t* key_arr)
{
for (size_t i= 0; i < key_arr->keys_len; ++i)
{
@@ -1117,11 +1116,11 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
}
/* Prepare key list from db/table and table_list */
-static bool wsrep_prepare_keys_for_isolation(THD* thd,
- const char* db,
- const char* table,
- const TABLE_LIST* table_list,
- wsrep_key_arr_t* ka)
+bool wsrep_prepare_keys_for_isolation(THD* thd,
+ const char* db,
+ const char* table,
+ const TABLE_LIST* table_list,
+ wsrep_key_arr_t* ka)
{
ka->keys= 0;
ka->keys_len= 0;
@@ -1866,7 +1865,7 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE ||
request_thd->lex->sql_command == SQLCOM_DROP_SEQUENCE)
{
- WSREP_DEBUG("DROP caused BF abort");
+ WSREP_DEBUG("DROP caused BF abort, conf %d", granted_thd->wsrep_conflict_state);
}
else if (granted_thd->wsrep_query_state == QUERY_COMMITTING)
{
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 5a13575d904..699a4daf27a 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -228,6 +228,7 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...);
#define WSREP_QUERY(thd) (thd->query())
+extern my_bool wsrep_ready_get();
extern void wsrep_ready_wait();
class Ha_trx_info;
@@ -320,6 +321,18 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
bool wsrep_node_is_donor();
bool wsrep_node_is_synced();
+typedef struct wsrep_key_arr
+{
+ wsrep_key_t* keys;
+ size_t keys_len;
+} wsrep_key_arr_t;
+bool wsrep_prepare_keys_for_isolation(THD* thd,
+ const char* db,
+ const char* table,
+ const TABLE_LIST* table_list,
+ wsrep_key_arr_t* ka);
+void wsrep_keys_free(wsrep_key_arr_t* key_arr);
+
#define WSREP_BINLOG_FORMAT(my_format) \
((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \
wsrep_forced_binlog_format : my_format)
@@ -353,6 +366,5 @@ bool wsrep_node_is_synced();
#define wsrep_thr_deinit() do {} while(0)
#define wsrep_running_threads (0)
#define WSREP_BINLOG_FORMAT(my_format) my_format
-
#endif /* WITH_WSREP */
#endif /* WSREP_MYSQLD_H */
diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h
index 97307fcc948..222a49cc2ab 100644
--- a/sql/wsrep_priv.h
+++ b/sql/wsrep_priv.h
@@ -26,7 +26,7 @@
#include <pthread.h>
#include <cstdio>
-void wsrep_ready_set (my_bool x);
+my_bool wsrep_ready_set (my_bool x);
ssize_t wsrep_sst_prepare (void** msg);
wsrep_cb_status wsrep_sst_donate_cb (void* app_ctx,
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index d19bcafb8d6..d5b0344c456 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -29,6 +29,8 @@
#include <cstdio>
#include <cstdlib>
+#include <my_service_manager.h>
+
static char wsrep_defaults_file[FN_REFLEN * 2 + 10 + 30 +
sizeof(WSREP_SST_OPT_CONF) +
sizeof(WSREP_SST_OPT_CONF_SUFFIX) +
@@ -176,6 +178,9 @@ bool wsrep_before_SE()
static bool sst_complete = false;
static bool sst_needed = false;
+#define WSREP_EXTEND_TIMEOUT_INTERVAL 30
+#define WSREP_TIMEDWAIT_SECONDS 10
+
void wsrep_sst_grab ()
{
WSREP_INFO("wsrep_sst_grab()");
@@ -187,11 +192,25 @@ void wsrep_sst_grab ()
// Wait for end of SST
bool wsrep_sst_wait ()
{
- if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort();
+ struct timespec wtime = {WSREP_TIMEDWAIT_SECONDS, 0};
+ uint32 total_wtime = 0;
+
+ if (mysql_mutex_lock (&LOCK_wsrep_sst))
+ abort();
+
+ WSREP_INFO("Waiting for SST to complete.");
+
while (!sst_complete)
{
- WSREP_INFO("Waiting for SST to complete.");
- mysql_cond_wait (&COND_wsrep_sst, &LOCK_wsrep_sst);
+ mysql_cond_timedwait (&COND_wsrep_sst, &LOCK_wsrep_sst, &wtime);
+
+ if (!sst_complete)
+ {
+ total_wtime += wtime.tv_sec;
+ WSREP_DEBUG("Waiting for SST to complete. waited %u secs.", total_wtime);
+ service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL,
+ "WSREP state transfer ongoing, current seqno: %ld", local_seqno);
+ }
}
if (local_seqno >= 0)
@@ -604,11 +623,11 @@ static ssize_t sst_prepare_other (const char* method,
ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_%s "
- WSREP_SST_OPT_ROLE" 'joiner' "
- WSREP_SST_OPT_ADDR" '%s' "
- WSREP_SST_OPT_DATA" '%s' "
+ WSREP_SST_OPT_ROLE " 'joiner' "
+ WSREP_SST_OPT_ADDR " '%s' "
+ WSREP_SST_OPT_DATA " '%s' "
" %s "
- WSREP_SST_OPT_PARENT" '%d'"
+ WSREP_SST_OPT_PARENT " '%d'"
" %s '%s' ",
method, addr_in, mysql_real_data_home,
wsrep_defaults_file,
@@ -890,13 +909,13 @@ static int sst_donate_mysqldump (const char* addr,
int ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_mysqldump "
- WSREP_SST_OPT_ADDR" '%s' "
- WSREP_SST_OPT_PORT" '%d' "
- WSREP_SST_OPT_LPORT" '%u' "
- WSREP_SST_OPT_SOCKET" '%s' "
- " '%s' "
- WSREP_SST_OPT_GTID" '%s:%lld' "
- WSREP_SST_OPT_GTID_DOMAIN_ID" '%d'"
+ WSREP_SST_OPT_ADDR " '%s' "
+ WSREP_SST_OPT_PORT " '%d' "
+ WSREP_SST_OPT_LPORT " '%u' "
+ WSREP_SST_OPT_SOCKET " '%s' "
+ " %s "
+ WSREP_SST_OPT_GTID " '%s:%lld' "
+ WSREP_SST_OPT_GTID_DOMAIN_ID " '%d'"
"%s",
addr, port, mysqld_port, mysqld_unix_port,
wsrep_defaults_file, uuid_str,
@@ -1253,14 +1272,14 @@ static int sst_donate_other (const char* method,
ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_%s "
- WSREP_SST_OPT_ROLE" 'donor' "
- WSREP_SST_OPT_ADDR" '%s' "
- WSREP_SST_OPT_SOCKET" '%s' "
- WSREP_SST_OPT_DATA" '%s' "
+ WSREP_SST_OPT_ROLE " 'donor' "
+ WSREP_SST_OPT_ADDR " '%s' "
+ WSREP_SST_OPT_SOCKET " '%s' "
+ WSREP_SST_OPT_DATA " '%s' "
" %s "
" %s '%s' "
- WSREP_SST_OPT_GTID" '%s:%lld' "
- WSREP_SST_OPT_GTID_DOMAIN_ID" '%d'"
+ WSREP_SST_OPT_GTID " '%s:%lld' "
+ WSREP_SST_OPT_GTID_DOMAIN_ID " '%d'"
"%s",
method, addr, mysqld_unix_port, mysql_real_data_home,
wsrep_defaults_file,
@@ -1346,10 +1365,22 @@ void wsrep_SE_init_grab()
void wsrep_SE_init_wait()
{
+ struct timespec wtime = {WSREP_TIMEDWAIT_SECONDS, 0};
+ uint32 total_wtime=0;
+
while (SE_initialized == false)
{
- mysql_cond_wait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init);
+ mysql_cond_timedwait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init, &wtime);
+
+ if (!SE_initialized)
+ {
+ total_wtime += wtime.tv_sec;
+ WSREP_DEBUG("Waiting for SST to complete. waited %u secs.", total_wtime);
+ service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL,
+ "WSREP SE initialization ongoing.");
+ }
}
+
mysql_mutex_unlock (&LOCK_wsrep_sst_init);
}
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index d94ac240b76..7fe120beb8e 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -47,6 +47,7 @@ int wsrep_init_vars()
linking will succeed even if the server is built with a dynamically
linked InnoDB. */
ulong innodb_lock_schedule_algorithm __attribute__((weak));
+struct handlerton* innodb_hton_ptr __attribute__((weak));
bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type)
{
@@ -62,7 +63,10 @@ bool wsrep_on_check(sys_var *self, THD* thd, set_var* var)
{
bool new_wsrep_on= (bool)var->save_result.ulonglong_value;
- if (new_wsrep_on && innodb_lock_schedule_algorithm != 0) {
+ if (check_has_super(self, thd, var))
+ return true;
+
+ if (new_wsrep_on && innodb_hton_ptr && innodb_lock_schedule_algorithm != 0) {
my_message(ER_WRONG_ARGUMENTS, " WSREP (galera) can't be enabled "
"if innodb_lock_schedule_algorithm=VATS. Please configure"
" innodb_lock_schedule_algorithm=FCFS and restart.", MYF(0));