summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2018-09-14 08:47:22 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2018-09-14 08:47:22 +0200
commit28f08d3753eb10a1393a63e6c581d43aad9f93b9 (patch)
tree86c9df8c3fb6d4ebd99d431697c84f06ef242989 /sql
parent38665893087e20c3ad65d5b0e227a75185a4865e (diff)
parentf1bcfbb4373e40dda2c18c137f76fc6ff32e1a45 (diff)
downloadmariadb-git-28f08d3753eb10a1393a63e6c581d43aad9f93b9.tar.gz
Merge branch '10.1' into 10.2
Diffstat (limited to 'sql')
-rw-r--r--sql/events.cc2
-rw-r--r--sql/field.cc17
-rw-r--r--sql/handler.cc4
-rw-r--r--sql/item.cc10
-rw-r--r--sql/log.cc8
-rw-r--r--sql/log_event.cc5
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/mysqld.h1
-rw-r--r--sql/opt_range.cc27
-rw-r--r--sql/sql_alter.cc20
-rw-r--r--sql/sql_base.cc160
-rw-r--r--sql/sql_base.h6
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_plugin_services.ic3
-rw-r--r--sql/sql_reload.cc13
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/sql_statistics.cc3
-rw-r--r--sql/sql_statistics.h29
-rw-r--r--sql/sql_table.cc64
-rw-r--r--sql/sql_trigger.cc8
-rw-r--r--sql/sql_truncate.cc2
-rw-r--r--sql/table.cc7
-rw-r--r--sql/table.h25
-rw-r--r--sql/table_cache.cc2
-rw-r--r--sql/wsrep_dummy.cc3
-rw-r--r--sql/wsrep_hton.cc9
-rw-r--r--sql/wsrep_mysqld.cc295
-rw-r--r--sql/wsrep_mysqld.h5
-rw-r--r--sql/wsrep_sst.cc53
-rw-r--r--sql/wsrep_sst.h1
-rw-r--r--sql/wsrep_var.cc4
31 files changed, 570 insertions, 222 deletions
diff --git a/sql/events.cc b/sql/events.cc
index 69894c85f68..e914dba1009 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -462,6 +462,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);
if (lock_object_name(thd, MDL_key::EVENT,
@@ -591,6 +592,7 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
if (check_access(thd, EVENT_ACL, dbname.str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
+
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/*
diff --git a/sql/field.cc b/sql/field.cc
index 9ca9663f066..a1a8ca41698 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -9815,13 +9815,18 @@ void Column_definition::create_length_to_internal_length(void)
}
break;
case MYSQL_TYPE_NEWDECIMAL:
- key_length= pack_length=
- my_decimal_get_binary_size(my_decimal_length_to_precision((uint)length,
- decimals,
- flags &
- UNSIGNED_FLAG),
- decimals);
+ {
+ /*
+ This code must be identical to code in
+ Field_new_decimal::Field_new_decimal as otherwise the record layout
+ gets out of sync.
+ */
+ uint precision= my_decimal_length_to_precision((uint)length, decimals,
+ flags & UNSIGNED_FLAG);
+ set_if_smaller(precision, DECIMAL_MAX_PRECISION);
+ key_length= pack_length= my_decimal_get_binary_size(precision, decimals);
break;
+ }
default:
key_length= pack_length= calc_pack_length(sql_type, (uint)length);
break;
diff --git a/sql/handler.cc b/sql/handler.cc
index 36babb96415..da41daf2440 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -21,6 +21,7 @@
*/
#include <my_global.h>
+#include <inttypes.h>
#include "sql_priv.h"
#include "unireg.h"
#include "rpl_handler.h"
@@ -4384,6 +4385,7 @@ handler::ha_create_partitioning_metadata(const char *name,
(!old_name && strcmp(name, table_share->path.str)));
+ mark_trx_read_write();
return create_partitioning_metadata(name, old_name, action_flag);
}
@@ -6188,7 +6190,7 @@ void ha_fake_trx_id(THD *thd)
if (thd->wsrep_ws_handle.trx_id != WSREP_UNDEFINED_TRX_ID)
{
- WSREP_DEBUG("fake trx id skipped: %lu", thd->wsrep_ws_handle.trx_id);
+ WSREP_DEBUG("fake trx id skipped: %" PRIu64, thd->wsrep_ws_handle.trx_id);
DBUG_VOID_RETURN;
}
diff --git a/sql/item.cc b/sql/item.cc
index 7d8baf81d3b..af8d431fbc2 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9356,13 +9356,11 @@ void Item_trigger_field::cleanup()
Item_result item_cmp_type(Item_result a,Item_result b)
{
- if (a == STRING_RESULT && b == STRING_RESULT)
- return STRING_RESULT;
- if (a == INT_RESULT && b == INT_RESULT)
- return INT_RESULT;
- else if (a == ROW_RESULT || b == ROW_RESULT)
+ if (a == b)
+ return a;
+ if (a == ROW_RESULT || b == ROW_RESULT)
return ROW_RESULT;
- else if (a == TIME_RESULT || b == TIME_RESULT)
+ if (a == TIME_RESULT || b == TIME_RESULT)
return TIME_RESULT;
if ((a == INT_RESULT || a == DECIMAL_RESULT) &&
(b == INT_RESULT || b == DECIMAL_RESULT))
diff --git a/sql/log.cc b/sql/log.cc
index fa1fe3d808c..053c0f16c6c 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1668,14 +1668,14 @@ static int binlog_close_connection(handlerton *hton, THD *thd)
uchar *buf;
size_t len=0;
wsrep_write_cache_buf(cache, &buf, &len);
- WSREP_WARN("binlog trx cache not empty (%lu bytes) @ connection close %lld",
- (ulong) len, (longlong) thd->thread_id);
+ WSREP_WARN("binlog trx cache not empty (%zu bytes) @ connection close %lld",
+ len, (longlong) thd->thread_id);
if (len > 0) wsrep_dump_rbr_buf(thd, buf, len);
cache = cache_mngr->get_binlog_cache_log(false);
wsrep_write_cache_buf(cache, &buf, &len);
- WSREP_WARN("binlog stmt cache not empty (%lu bytes) @ connection close %lld",
- (ulong) len, (longlong) thd->thread_id);
+ WSREP_WARN("binlog stmt cache not empty (%zu bytes) @ connection close %lld",
+ len, (longlong) thd->thread_id);
if (len > 0) wsrep_dump_rbr_buf(thd, buf, len);
}
#endif /* WITH_WSREP */
diff --git a/sql/log_event.cc b/sql/log_event.cc
index ff3efcc62a3..04a616d0006 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -8727,11 +8727,6 @@ User_var_log_event(const char* buf, uint event_len,
we keep the flags set to UNDEF_F.
*/
size_t bytes_read= (val + val_len) - buf_start;
- if (bytes_read > size_t(event_len))
- {
- error= true;
- goto err;
- }
if ((data_written - bytes_read) > 0)
{
flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index dee7ac56833..b8bb63c4259 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -799,6 +799,7 @@ char *master_info_file;
char *relay_log_info_file, *report_user, *report_password, *report_host;
char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
char *opt_logname, *opt_slow_logname, *opt_bin_logname;
+char *opt_binlog_index_name=0;
/* Static variables */
@@ -808,7 +809,6 @@ my_bool opt_expect_abort= 0, opt_bootstrap= 0;
static my_bool opt_myisam_log;
static int cleanup_done;
static ulong opt_specialflag;
-static char *opt_binlog_index_name;
char *mysql_home_ptr, *pidfile_name_ptr;
/** Initial command line arguments (count), after load_defaults().*/
static int defaults_argc;
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 2604121a9f1..b02bd9fb1f6 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -172,6 +172,7 @@ extern uint protocol_version, mysqld_port, dropping_tables;
extern ulong delay_key_write_options;
extern char *opt_logname, *opt_slow_logname, *opt_bin_logname,
*opt_relay_logname;
+extern char *opt_binlog_index_name;
extern char *opt_backup_history_logname, *opt_backup_progress_logname,
*opt_backup_settings_name;
extern const char *log_output_str;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 2c015c1a5da..b67661e1c8a 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2727,13 +2727,19 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param,
for (field_ptr= table->field; *field_ptr; field_ptr++)
{
- if (bitmap_is_set(used_fields, (*field_ptr)->field_index))
+ Column_statistics* col_stats= (*field_ptr)->read_stats;
+ if (bitmap_is_set(used_fields, (*field_ptr)->field_index)
+ && col_stats && !col_stats->no_stat_values_provided()
+ && !((*field_ptr)->type() == MYSQL_TYPE_GEOMETRY))
parts++;
}
KEY_PART *key_part;
uint keys= 0;
+ if (!parts)
+ return TRUE;
+
if (!(key_part= (KEY_PART *) alloc_root(param->mem_root,
sizeof(KEY_PART) * parts)))
return TRUE;
@@ -2745,6 +2751,9 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param,
if (bitmap_is_set(used_fields, (*field_ptr)->field_index))
{
Field *field= *field_ptr;
+ if (field->type() == MYSQL_TYPE_GEOMETRY)
+ continue;
+
uint16 store_length;
uint16 max_key_part_length= (uint16) table->file->max_key_part_length();
key_part->key= keys;
@@ -2902,7 +2911,18 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
table->cond_selectivity= 1.0;
- if (!*cond || table_records == 0)
+ if (table_records == 0)
+ DBUG_RETURN(FALSE);
+
+ QUICK_SELECT_I *quick;
+ if ((quick=table->reginfo.join_tab->quick) &&
+ quick->get_type() == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
+ {
+ table->cond_selectivity*= (quick->records/table_records);
+ DBUG_RETURN(FALSE);
+ }
+
+ if (!*cond)
DBUG_RETURN(FALSE);
if (table->pos_in_table_list->schema_table)
@@ -3019,7 +3039,8 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
*/
if (thd->variables.optimizer_use_condition_selectivity > 2 &&
- !bitmap_is_clear_all(used_fields))
+ !bitmap_is_clear_all(used_fields) &&
+ thd->variables.use_stat_tables > 0)
{
PARAM param;
MEM_ROOT alloc;
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index dbb138ed9ab..c8bc3952b61 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -306,12 +306,17 @@ bool Sql_cmd_alter_table::execute(THD *thd)
thd->enable_slow_log= opt_log_slow_admin_statements;
#ifdef WITH_WSREP
- if ((!thd->is_current_stmt_binlog_format_row() ||
+ if (WSREP(thd) &&
+ (!thd->is_current_stmt_binlog_format_row() ||
!thd->find_temporary_table(first_table)))
{
- WSREP_TO_ISOLATION_BEGIN(((lex->name.str) ? select_lex->db : NULL),
- ((lex->name.str) ? lex->name.str : NULL),
- first_table);
+ WSREP_TO_ISOLATION_BEGIN_ALTER(((lex->name.str) ? select_lex->db : NULL),
+ ((lex->name.str) ? lex->name.str : NULL),
+ first_table,
+ &alter_info);
+
+ thd->variables.auto_increment_offset = 1;
+ thd->variables.auto_increment_increment = 1;
}
#endif /* WITH_WSREP */
@@ -324,11 +329,12 @@ bool Sql_cmd_alter_table::execute(THD *thd)
lex->ignore);
DBUG_RETURN(result);
-
#ifdef WITH_WSREP
error:
- WSREP_WARN("ALTER TABLE isolation failure");
- DBUG_RETURN(TRUE);
+ {
+ WSREP_WARN("ALTER TABLE isolation failure");
+ DBUG_RETURN(TRUE);
+ }
#endif /* WITH_WSREP */
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index cae5b4a3f7d..52474116fa6 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -411,9 +411,10 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables,
for (TABLE_LIST *table_list= tables_to_reopen; table_list;
table_list= table_list->next_global)
{
+ int err;
/* A check that the table was locked for write is done by the caller. */
TABLE *table= find_table_for_mdl_upgrade(thd, table_list->db,
- table_list->table_name, TRUE);
+ table_list->table_name, &err);
/* May return NULL if this table has already been closed via an alias. */
if (! table)
@@ -1461,6 +1462,66 @@ open_table_get_mdl_lock(THD *thd, Open_table_context *ot_ctx,
/**
+ Check if the given table is actually a VIEW that was LOCK-ed
+
+ @param thd Thread context.
+ @param t Table to check.
+
+ @retval TRUE The 't'-table is a locked view
+ needed to remedy problem before retrying again.
+ @retval FALSE 't' was not locked, not a VIEW or an error happened.
+*/
+bool is_locked_view(THD *thd, TABLE_LIST *t)
+{
+ DBUG_ENTER("check_locked_view");
+ /*
+ Is this table a view and not a base table?
+ (it is work around to allow to open view with locked tables,
+ real fix will be made after definition cache will be made)
+
+ Since opening of view which was not explicitly locked by LOCK
+ TABLES breaks metadata locking protocol (potentially can lead
+ to deadlocks) it should be disallowed.
+ */
+ if (thd->mdl_context.is_lock_owner(MDL_key::TABLE,
+ t->db, t->table_name,
+ MDL_SHARED))
+ {
+ char path[FN_REFLEN + 1];
+ build_table_filename(path, sizeof(path) - 1,
+ t->db, t->table_name, reg_ext, 0);
+ /*
+ Note that we can't be 100% sure that it is a view since it's
+ possible that we either simply have not found unused TABLE
+ instance in THD::open_tables list or were unable to open table
+ during prelocking process (in this case in theory we still
+ should hold shared metadata lock on it).
+ */
+ if (dd_frm_is_view(thd, path))
+ {
+ /*
+ If parent_l of the table_list is non null then a merge table
+ has this view as child table, which is not supported.
+ */
+ if (t->parent_l)
+ {
+ my_error(ER_WRONG_MRG_TABLE, MYF(0));
+ DBUG_RETURN(FALSE);
+ }
+
+ if (!tdc_open_view(thd, t, CHECK_METADATA_VERSION))
+ {
+ DBUG_ASSERT(t->view != 0);
+ DBUG_RETURN(TRUE); // VIEW
+ }
+ }
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
Open a base table.
@param thd Thread context.
@@ -1608,49 +1669,10 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
DBUG_PRINT("info",("Using locked table"));
goto reset;
}
- /*
- Is this table a view and not a base table?
- (it is work around to allow to open view with locked tables,
- real fix will be made after definition cache will be made)
- Since opening of view which was not explicitly locked by LOCK
- TABLES breaks metadata locking protocol (potentially can lead
- to deadlocks) it should be disallowed.
- */
- if (thd->mdl_context.is_lock_owner(MDL_key::TABLE,
- table_list->db,
- table_list->table_name,
- MDL_SHARED))
- {
- char path[FN_REFLEN + 1];
- build_table_filename(path, sizeof(path) - 1,
- table_list->db, table_list->table_name, reg_ext, 0);
- /*
- Note that we can't be 100% sure that it is a view since it's
- possible that we either simply have not found unused TABLE
- instance in THD::open_tables list or were unable to open table
- during prelocking process (in this case in theory we still
- should hold shared metadata lock on it).
- */
- if (dd_frm_is_view(thd, path))
- {
- /*
- If parent_l of the table_list is non null then a merge table
- has this view as child table, which is not supported.
- */
- if (table_list->parent_l)
- {
- my_error(ER_WRONG_MRG_TABLE, MYF(0));
- DBUG_RETURN(true);
- }
+ if (is_locked_view(thd, table_list))
+ DBUG_RETURN(FALSE); // VIEW
- if (!tdc_open_view(thd, table_list, CHECK_METADATA_VERSION))
- {
- DBUG_ASSERT(table_list->view != 0);
- DBUG_RETURN(FALSE); // VIEW
- }
- }
- }
/*
No table in the locked tables list. In case of explicit LOCK TABLES
this can happen if a user did not include the table into the list.
@@ -2003,8 +2025,9 @@ TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name)
@param thd Thread context
@param db Database name.
@param table_name Name of table.
- @param no_error Don't emit error if no suitable TABLE
- instance were found.
+ @param p_error In the case of an error (when the function returns NULL)
+ the error number is stored there.
+ If the p_error is NULL, function launches the error itself.
@note This function checks if the connection holds a global IX
metadata lock. If no such lock is found, it is not safe to
@@ -2017,15 +2040,15 @@ TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name)
*/
TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
- const char *table_name, bool no_error)
+ const char *table_name, int *p_error)
{
TABLE *tab= find_locked_table(thd->open_tables, db, table_name);
+ int error;
if (!tab)
{
- if (!no_error)
- my_error(ER_TABLE_NOT_LOCKED, MYF(0), table_name);
- return NULL;
+ error= ER_TABLE_NOT_LOCKED;
+ goto err_exit;
}
/*
@@ -2037,9 +2060,8 @@ TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
if (!thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "",
MDL_INTENTION_EXCLUSIVE))
{
- if (!no_error)
- my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_name);
- return NULL;
+ error= ER_TABLE_NOT_LOCKED_FOR_WRITE;
+ goto err_exit;
}
while (tab->mdl_ticket != NULL &&
@@ -2047,10 +2069,21 @@ TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
(tab= find_locked_table(tab->next, db, table_name)))
continue;
- if (!tab && !no_error)
- my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_name);
+ if (unlikely(!tab))
+ {
+ error= ER_TABLE_NOT_LOCKED_FOR_WRITE;
+ goto err_exit;
+ }
return tab;
+
+err_exit:
+ if (p_error)
+ *p_error= error;
+ else
+ my_error(error, MYF(0), table_name);
+
+ return NULL;
}
@@ -3816,7 +3849,7 @@ open_tables_check_upgradable_mdl(THD *thd, TABLE_LIST *tables_start,
Note that find_table_for_mdl_upgrade() will report an error if
no suitable ticket is found.
*/
- if (!find_table_for_mdl_upgrade(thd, table->db, table->table_name, false))
+ if (!find_table_for_mdl_upgrade(thd, table->db, table->table_name, NULL))
return TRUE;
}
@@ -4213,8 +4246,9 @@ handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
@note this can be changed to use a hash, instead of scanning the linked
list, if the performance of this function will ever become an issue
*/
-static bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_STRING *db,
- LEX_STRING *table, thr_lock_type lock_type)
+
+bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_STRING *db,
+ LEX_STRING *table, thr_lock_type lock_type)
{
for (; tl; tl= tl->next_global )
{
@@ -6673,10 +6707,22 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
result= FALSE;
-err:
if (arena)
thd->restore_active_arena(arena, &backup);
DBUG_RETURN(result);
+
+err:
+ /*
+ Actually we failed to build join columns list, so we have to
+ clear it to avoid problems with half-build join on next run.
+ The list was created in mark_common_columns().
+ */
+ table_ref_1->remove_join_columns();
+ table_ref_2->remove_join_columns();
+
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 4f99111cbd9..37cc9e8e8f1 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -125,6 +125,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
MYSQL_OPEN_GET_NEW_TABLE |\
MYSQL_OPEN_HAS_MDL_LOCK)
+bool is_locked_view(THD *thd, TABLE_LIST *t);
bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx);
bool get_key_map_from_key_list(key_map *map, TABLE *table,
@@ -140,6 +141,8 @@ thr_lock_type read_lock_type_for_table(THD *thd,
my_bool mysql_rm_tmp_tables(void);
void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
const MDL_savepoint &start_of_statement_svp);
+bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_STRING *db,
+ LEX_STRING *table, thr_lock_type lock_type);
TABLE_LIST *find_table_in_list(TABLE_LIST *table,
TABLE_LIST *TABLE_LIST::*link,
const char *db_name,
@@ -295,7 +298,8 @@ bool tdc_open_view(THD *thd, TABLE_LIST *table_list, uint flags);
TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
const char *table_name,
- bool no_error);
+ int *p_error);
+void mark_tmp_table_for_reuse(TABLE *table);
int dynamic_column_error_message(enum_dyncol_func_result rc);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index dd16200539d..3231c4b730f 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -7797,7 +7797,9 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
"WAIT_FOR wsrep_retry_autocommit_continue";
DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act)));
});
+ WSREP_DEBUG("Retry autocommit query: %s", thd->query());
}
+
mysql_parse(thd, rawbuf, length, parser_state, is_com_multi,
is_next_command);
diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic
index ea6aefa5993..801e7d5e41f 100644
--- a/sql/sql_plugin_services.ic
+++ b/sql/sql_plugin_services.ic
@@ -179,7 +179,8 @@ static struct wsrep_service_st wsrep_handler = {
wsrep_thd_ws_handle,
wsrep_trx_is_aborting,
wsrep_trx_order_before,
- wsrep_unlock_rollback
+ wsrep_unlock_rollback,
+ wsrep_set_data_home_dir
};
static struct thd_specifics_service_st thd_specifics_handler=
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index ce3ff5964e2..ac66f7e9609 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -289,9 +289,18 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
*/
if (tables)
{
+ int err;
for (TABLE_LIST *t= tables; t; t= t->next_local)
- if (!find_table_for_mdl_upgrade(thd, t->db, t->table_name, false))
- return 1;
+ if (!find_table_for_mdl_upgrade(thd, t->db, t->table_name, &err))
+ {
+ if (is_locked_view(thd, t))
+ t->next_local= t->next_global;
+ else
+ {
+ my_error(err, MYF(0), t->table_name);
+ return 1;
+ }
+ }
}
else
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 0124a782de0..3ec1a1b6e04 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -25446,7 +25446,7 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str,
const char *t_alias= alias;
str->append(' ');
- if (lower_case_table_names== 1)
+ if (lower_case_table_names == 1)
{
if (alias && alias[0])
{
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index ae72b828ae3..787dcd129b8 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -3278,6 +3278,9 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
{
TABLE_SHARE *table_share= tl->table->s;
+ if (table_share && !(table_share->table_category == TABLE_CATEGORY_USER))
+ continue;
+
if (table_share &&
table_share->stats_cb.stats_can_be_read &&
!table_share->stats_cb.stats_is_read)
diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h
index 28d5cd46760..64322623ab3 100644
--- a/sql/sql_statistics.h
+++ b/sql/sql_statistics.h
@@ -345,12 +345,17 @@ private:
public:
Histogram histogram;
+
+ uint32 no_values_provided_bitmap()
+ {
+ return
+ ((1 << (COLUMN_STAT_HISTOGRAM-COLUMN_STAT_COLUMN_NAME))-1) <<
+ (COLUMN_STAT_COLUMN_NAME+1);
+ }
void set_all_nulls()
{
- column_stat_nulls=
- ((1 << (COLUMN_STAT_HISTOGRAM-COLUMN_STAT_COLUMN_NAME))-1) <<
- (COLUMN_STAT_COLUMN_NAME+1);
+ column_stat_nulls= no_values_provided_bitmap();
}
void set_not_null(uint stat_field_no)
@@ -396,8 +401,22 @@ public:
bool min_max_values_are_provided()
{
return !is_null(COLUMN_STAT_MIN_VALUE) &&
- !is_null(COLUMN_STAT_MIN_VALUE);
- }
+ !is_null(COLUMN_STAT_MAX_VALUE);
+ }
+ /*
+ This function checks whether the values for the fields of the statistical
+ tables that were NULL by DEFAULT for a column have changed or not.
+
+ @retval
+ TRUE: Statistics are not present for a column
+ FALSE: Statisitics are present for a column
+ */
+ bool no_stat_values_provided()
+ {
+ if (column_stat_nulls == no_values_provided_bitmap())
+ return true;
+ return false;
+ }
};
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index dbcab9bb870..4aed06e3590 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2073,7 +2073,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
in its elements.
*/
table->table= find_table_for_mdl_upgrade(thd, table->db,
- table->table_name, false);
+ table->table_name, NULL);
if (!table->table)
DBUG_RETURN(true);
table->mdl_request.ticket= table->table->mdl_ticket;
@@ -3402,6 +3402,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
thd->change_item_tree(&sql_field->default_value->expr, item);
}
+ /* Virtual fields are always NULL */
+ if (sql_field->vcol_info)
+ sql_field->flags&= ~NOT_NULL_FLAG;
+
if (sql_field->default_value &&
sql_field->default_value->expr->basic_const_item() &&
(sql_field->sql_type == MYSQL_TYPE_SET ||
@@ -9481,8 +9485,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
Table can be found in the list of open tables in THD::all_temp_tables
list.
*/
- tbl.table= thd->find_temporary_table(&tbl);
+ if ((tbl.table= thd->find_temporary_table(&tbl)) == NULL)
+ goto err_new_table_cleanup;
new_table= tbl.table;
+ DBUG_ASSERT(new_table);
}
else
{
@@ -9495,9 +9501,59 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
alter_ctx.get_tmp_path(),
alter_ctx.new_db, alter_ctx.tmp_name,
true);
+ if (!new_table)
+ goto err_new_table_cleanup;
+
+ /*
+ Normally, an attempt to modify an FK parent table will cause
+ FK children to be prelocked, so the table-being-altered cannot
+ be modified by a cascade FK action, because ALTER holds a lock
+ and prelocking will wait.
+
+ But if a new FK is being added by this very ALTER, then the target
+ table is not locked yet (it's a temporary table). So, we have to
+ lock FK parents explicitly.
+ */
+ if (alter_info->flags & Alter_info::ADD_FOREIGN_KEY)
+ {
+ List <FOREIGN_KEY_INFO> fk_list;
+ List_iterator<FOREIGN_KEY_INFO> fk_list_it(fk_list);
+ FOREIGN_KEY_INFO *fk;
+
+ /* tables_opened can be > 1 only for MERGE tables */
+ DBUG_ASSERT(tables_opened == 1);
+ DBUG_ASSERT(&table_list->next_global == thd->lex->query_tables_last);
+
+ new_table->file->get_foreign_key_list(thd, &fk_list);
+ while ((fk= fk_list_it++))
+ {
+ if (lower_case_table_names)
+ {
+ char buf[NAME_LEN];
+ uint len;
+ strmake_buf(buf, fk->referenced_db->str);
+ len = my_casedn_str(files_charset_info, buf);
+ thd->make_lex_string(fk->referenced_db, buf, len);
+ strmake_buf(buf, fk->referenced_table->str);
+ len = my_casedn_str(files_charset_info, buf);
+ thd->make_lex_string(fk->referenced_table, buf, len);
+ }
+ if (table_already_fk_prelocked(table_list, fk->referenced_db,
+ fk->referenced_table, TL_READ_NO_INSERT))
+ continue;
+
+ TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
+ tl->init_one_table_for_prelocking(fk->referenced_db->str, fk->referenced_db->length,
+ fk->referenced_table->str, fk->referenced_table->length,
+ NULL, TL_READ_NO_INSERT, false, NULL, 0,
+ &thd->lex->query_tables_last);
+ }
+
+ if (open_tables(thd, &table_list->next_global, &tables_opened, 0,
+ &alter_prelocking_strategy))
+ goto err_new_table_cleanup;
+ }
}
- if (!new_table)
- goto err_new_table_cleanup;
/*
Note: In case of MERGE table, we do not attach children. We do not
copy data for MERGE tables. Only the children have data.
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 01ceb34a577..ba4a2725ced 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -514,7 +514,11 @@ 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);
+
+#ifdef WITH_WSREP
+ if (thd->wsrep_exec_mode == LOCAL_STATE)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+#endif
/* We should have only one table in table list. */
DBUG_ASSERT(tables->next_global == 0);
@@ -542,7 +546,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
/* Under LOCK TABLES we must only accept write locked tables. */
if (!(tables->table= find_table_for_mdl_upgrade(thd, tables->db,
tables->table_name,
- FALSE)))
+ NULL)))
goto end;
}
else
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 9a54b4f947f..57cb6df55ca 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -302,7 +302,7 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref,
if (thd->locked_tables_mode)
{
if (!(table= find_table_for_mdl_upgrade(thd, table_ref->db,
- table_ref->table_name, FALSE)))
+ table_ref->table_name, NULL)))
DBUG_RETURN(TRUE);
*hton_can_recreate= ha_check_storage_engine_flag(table->s->db_type(),
diff --git a/sql/table.cc b/sql/table.cc
index efcca431e93..585cb13a86c 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -431,6 +431,7 @@ void TABLE_SHARE::destroy()
ha_share= NULL; // Safety
}
+ delete_stat_values_for_table_share(this);
free_root(&stats_cb.mem_root, MYF(0));
stats_cb.stats_can_be_read= FALSE;
stats_cb.stats_is_read= FALSE;
@@ -8471,3 +8472,9 @@ LEX_CSTRING *fk_option_name(enum_fk_option opt)
};
return names + opt;
}
+
+bool fk_modifies_child(enum_fk_option opt)
+{
+ static bool can_write[]= { false, false, true, true, false, true };
+ return can_write[opt];
+}
diff --git a/sql/table.h b/sql/table.h
index c0cca1026ea..fc3102fc9a5 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1507,6 +1507,7 @@ typedef struct st_foreign_key_info
} FOREIGN_KEY_INFO;
LEX_CSTRING *fk_option_name(enum_fk_option opt);
+bool fk_modifies_child(enum_fk_option opt);
#define MY_I_S_MAYBE_NULL 1U
#define MY_I_S_UNSIGNED 2U
@@ -1755,6 +1756,14 @@ struct TABLE_LIST
const char *alias_arg,
enum thr_lock_type lock_type_arg)
{
+ enum enum_mdl_type mdl_type;
+ if (lock_type_arg >= TL_WRITE_ALLOW_WRITE)
+ mdl_type= MDL_SHARED_WRITE;
+ else if (lock_type_arg == TL_READ_NO_INSERT)
+ mdl_type= MDL_SHARED_NO_WRITE;
+ else
+ mdl_type= MDL_SHARED_READ;
+
bzero((char*) this, sizeof(*this));
db= (char*) db_name_arg;
db_length= db_length_arg;
@@ -1762,10 +1771,7 @@ struct TABLE_LIST
table_name_length= table_name_length_arg;
alias= (char*) (alias_arg ? alias_arg : table_name_arg);
lock_type= lock_type_arg;
- mdl_request.init(MDL_key::TABLE, db, table_name,
- (lock_type >= TL_WRITE_ALLOW_WRITE) ?
- MDL_SHARED_WRITE : MDL_SHARED_READ,
- MDL_TRANSACTION);
+ mdl_request.init(MDL_key::TABLE, db, table_name, mdl_type, MDL_TRANSACTION);
}
inline void init_one_table_for_prelocking(const char *db_name_arg,
@@ -1792,6 +1798,7 @@ struct TABLE_LIST
*last_ptr= &next_global;
}
+
/*
List of tables local to a subquery (used by SQL_I_List). Considers
views as leaves (unlike 'next_leaf' below). Created at parse time
@@ -2402,6 +2409,16 @@ struct TABLE_LIST
void check_pushable_cond_for_table(Item *cond);
Item *build_pushable_cond_for_table(THD *thd, Item *cond);
+ void remove_join_columns()
+ {
+ if (join_columns)
+ {
+ join_columns->empty();
+ join_columns= NULL;
+ is_join_columns_complete= FALSE;
+ }
+ }
+
private:
bool prep_check_option(THD *thd, uint8 check_opt_type);
bool prep_where(THD *thd, Item **conds, bool no_where_clause);
diff --git a/sql/table_cache.cc b/sql/table_cache.cc
index 7be5f5f771b..eeb100a5319 100644
--- a/sql/table_cache.cc
+++ b/sql/table_cache.cc
@@ -50,7 +50,6 @@
#include "lf.h"
#include "table.h"
#include "sql_base.h"
-#include "sql_statistics.h"
/** Configuration. */
@@ -973,7 +972,6 @@ void tdc_release_share(TABLE_SHARE *share)
}
if (share->tdc->flushed || tdc_records() > tdc_size)
{
- delete_stat_values_for_table_share(share);
mysql_mutex_unlock(&LOCK_unused_shares);
tdc_delete_share_from_hash(share->tdc);
DBUG_VOID_RETURN;
diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc
index 0aa7f9b0aad..5837ab4bed5 100644
--- a/sql/wsrep_dummy.cc
+++ b/sql/wsrep_dummy.cc
@@ -130,3 +130,6 @@ int wsrep_trx_is_aborting(THD *)
void wsrep_unlock_rollback()
{ }
+
+void wsrep_set_data_home_dir(const char *)
+{ }
diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc
index 1ef4465f173..e3da6a79f26 100644
--- a/sql/wsrep_hton.cc
+++ b/sql/wsrep_hton.cc
@@ -24,6 +24,8 @@
#include <cstdlib>
#include "debug_sync.h"
+extern handlerton *binlog_hton;
+extern int binlog_close_connection(handlerton *hton, THD *thd);
extern ulonglong thd_to_trx_id(THD *thd);
extern "C" int thd_binlog_format(const MYSQL_THD thd);
@@ -171,7 +173,10 @@ wsrep_close_connection(handlerton* hton, THD* thd)
{
DBUG_RETURN(0);
}
- DBUG_RETURN(wsrep_binlog_close_connection (thd));
+
+ if (wsrep_emulate_bin_log && thd_get_ha_data(thd, binlog_hton) != NULL)
+ binlog_hton->close_connection (binlog_hton, thd);
+ DBUG_RETURN(0);
}
/*
@@ -262,7 +267,7 @@ static int wsrep_rollback(handlerton *hton, THD *thd, bool all)
}
if ((all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
- (thd->variables.wsrep_on && thd->wsrep_conflict_state != MUST_REPLAY))
+ thd->variables.wsrep_on && thd->wsrep_conflict_state != MUST_REPLAY)
{
if (wsrep && wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle))
{
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 326b5928366..0ddc4520cee 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -74,10 +74,7 @@ const char *wsrep_start_position;
const char *wsrep_data_home_dir;
const char *wsrep_dbug_option;
const char *wsrep_notify_cmd;
-const char *wsrep_sst_method;
-const char *wsrep_sst_receive_address;
-const char *wsrep_sst_donor;
-const char *wsrep_sst_auth;
+
my_bool wsrep_debug; // Enable debug level logging
my_bool wsrep_convert_LOCK_to_trx; // Convert locking sessions to trx
my_bool wsrep_auto_increment_control; // Control auto increment variables
@@ -89,7 +86,6 @@ my_bool wsrep_log_conflicts;
my_bool wsrep_load_data_splitting; // Commit load data every 10K intervals
my_bool wsrep_slave_UK_checks; // Slave thread does UK checks
my_bool wsrep_slave_FK_checks; // Slave thread does FK checks
-my_bool wsrep_sst_donor_rejects_queries;
my_bool wsrep_restart_slave; // Should mysql slave thread be
// restarted, when node joins back?
my_bool wsrep_desync; // De(re)synchronize the node from the
@@ -643,6 +639,9 @@ int wsrep_init()
wsrep->provider_vendor, sizeof(provider_vendor) - 1);
}
+ if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0)
+ wsrep_data_home_dir = mysql_real_data_home;
+
/* Initialize node address */
char node_addr[512]= { 0, };
size_t const node_addr_max= sizeof(node_addr) - 1;
@@ -1068,114 +1067,151 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
wsrep_buf_t* key,
size_t* key_len)
{
- if (*key_len < 2) return false;
+ if (*key_len < 2) return false;
- switch (wsrep_protocol_version)
- {
- case 0:
- *key_len= 0;
- break;
- case 1:
- case 2:
- case 3:
+ switch (wsrep_protocol_version)
+ {
+ case 0:
+ *key_len= 0;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ {
+ *key_len= 0;
+ if (db)
{
- *key_len= 0;
- if (db)
- {
- // sql_print_information("%s.%s", db, table);
- if (db)
- {
- key[*key_len].ptr= db;
- key[*key_len].len= strlen(db);
- ++(*key_len);
- if (table)
- {
- key[*key_len].ptr= table;
- key[*key_len].len= strlen(table);
- ++(*key_len);
- }
- }
- }
- break;
+ // sql_print_information("%s.%s", db, table);
+ key[*key_len].ptr= db;
+ key[*key_len].len= strlen(db);
+ ++(*key_len);
+ if (table)
+ {
+ key[*key_len].ptr= table;
+ key[*key_len].len= strlen(table);
+ ++(*key_len);
+ }
}
- default:
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
+}
+
+
+static bool wsrep_prepare_key_for_isolation(const char* db,
+ const char* table,
+ wsrep_key_arr_t* ka)
+{
+ wsrep_key_t* tmp;
+
+ if (!ka->keys)
+ tmp= (wsrep_key_t*)my_malloc((ka->keys_len + 1) * sizeof(wsrep_key_t),
+ MYF(0));
+ else
+ tmp= (wsrep_key_t*)my_realloc(ka->keys,
+ (ka->keys_len + 1) * sizeof(wsrep_key_t),
+ MYF(0));
+
+ if (!tmp)
+ {
+ WSREP_ERROR("Can't allocate memory for key_array");
+ return false;
+ }
+ ka->keys= tmp;
+ if (!(ka->keys[ka->keys_len].key_parts= (wsrep_buf_t*)
+ my_malloc(sizeof(wsrep_buf_t)*2, MYF(0))))
+ {
+ WSREP_ERROR("Can't allocate memory for key_parts");
+ return false;
+ }
+ ka->keys[ka->keys_len].key_parts_num= 2;
+ ++ka->keys_len;
+ if (!wsrep_prepare_key_for_isolation(db, table,
+ (wsrep_buf_t*)ka->keys[ka->keys_len - 1].key_parts,
+ &ka->keys[ka->keys_len - 1].key_parts_num))
+ {
+ WSREP_ERROR("Preparing keys for isolation failed");
+ return false;
+ }
+
+ return true;
+}
+
+
+static bool wsrep_prepare_keys_for_alter_add_fk(char* child_table_db,
+ Alter_info* alter_info,
+ wsrep_key_arr_t* ka)
+{
+ Key *key;
+ List_iterator<Key> key_iterator(alter_info->key_list);
+ while ((key= key_iterator++))
+ {
+ if (key->type == Key::FOREIGN_KEY)
+ {
+ Foreign_key *fk_key= (Foreign_key *)key;
+ const char *db_name= fk_key->ref_db.str;
+ const char *table_name= fk_key->ref_table.str;
+ if (!db_name)
+ {
+ db_name= child_table_db;
+ }
+ if (!wsrep_prepare_key_for_isolation(db_name, table_name, ka))
+ {
return false;
+ }
}
-
- return true;
+ }
+ return true;
}
-/* Prepare key list from db/table and table_list */
-bool wsrep_prepare_keys_for_isolation(THD* thd,
- const char* db,
- const char* table,
- const TABLE_LIST* table_list,
- wsrep_key_arr_t* ka)
+
+static bool wsrep_prepare_keys_for_isolation(THD* thd,
+ const char* db,
+ const char* table,
+ const TABLE_LIST* table_list,
+ Alter_info* alter_info,
+ wsrep_key_arr_t* ka)
{
ka->keys= 0;
ka->keys_len= 0;
if (db || table)
{
- if (!(ka->keys= (wsrep_key_t*)my_malloc(sizeof(wsrep_key_t), MYF(0))))
- {
- WSREP_ERROR("Can't allocate memory for key_array");
- goto err;
- }
- ka->keys_len= 1;
- if (!(ka->keys[0].key_parts= (wsrep_buf_t*)
- my_malloc(sizeof(wsrep_buf_t)*2, MYF(0))))
- {
- WSREP_ERROR("Can't allocate memory for key_parts");
+ if (!wsrep_prepare_key_for_isolation(db, table, ka))
goto err;
- }
- ka->keys[0].key_parts_num= 2;
- if (!wsrep_prepare_key_for_isolation(
- db, table,
- (wsrep_buf_t*)ka->keys[0].key_parts,
- &ka->keys[0].key_parts_num))
- {
- WSREP_ERROR("Preparing keys for isolation failed (1)");
- goto err;
- }
}
for (const TABLE_LIST* table= table_list; table; table= table->next_global)
{
- wsrep_key_t* tmp;
- if (ka->keys)
- tmp= (wsrep_key_t*)my_realloc(ka->keys,
- (ka->keys_len + 1) * sizeof(wsrep_key_t),
- MYF(0));
- else
- tmp= (wsrep_key_t*)my_malloc((ka->keys_len + 1) * sizeof(wsrep_key_t), MYF(0));
-
- if (!tmp)
- {
- WSREP_ERROR("Can't allocate memory for key_array");
- goto err;
- }
- ka->keys= tmp;
- if (!(ka->keys[ka->keys_len].key_parts= (wsrep_buf_t*)
- my_malloc(sizeof(wsrep_buf_t)*2, MYF(0))))
- {
- WSREP_ERROR("Can't allocate memory for key_parts");
+ if (!wsrep_prepare_key_for_isolation(table->db, table->table_name, ka))
goto err;
- }
- ka->keys[ka->keys_len].key_parts_num= 2;
- ++ka->keys_len;
- if (!wsrep_prepare_key_for_isolation(table->db, table->table_name,
- (wsrep_buf_t*)ka->keys[ka->keys_len - 1].key_parts,
- &ka->keys[ka->keys_len - 1].key_parts_num))
- {
- WSREP_ERROR("Preparing keys for isolation failed (2)");
+ }
+
+ if (alter_info && (alter_info->flags & (Alter_info::ADD_FOREIGN_KEY)))
+ {
+ if (!wsrep_prepare_keys_for_alter_add_fk(table_list->db, alter_info, ka))
goto err;
- }
}
- return 0;
+
+ return false;
+
err:
- wsrep_keys_free(ka);
- return 1;
+ wsrep_keys_free(ka);
+ return true;
+}
+
+
+/* Prepare key list from db/table and table_list */
+bool wsrep_prepare_keys_for_isolation(THD* thd,
+ const char* db,
+ const char* table,
+ const TABLE_LIST* table_list,
+ wsrep_key_arr_t* ka)
+{
+ return wsrep_prepare_keys_for_isolation(thd, db, table, table_list, NULL, ka);
}
@@ -1395,6 +1431,67 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len)
return wsrep_to_buf_helper(thd, buff.ptr(), buff.length(), buf, buf_len);
}
+/*
+ Rewrite DROP TABLE for TOI. Temporary tables are eliminated from
+ the query as they are visible only to client connection.
+
+ TODO: See comments for sql_base.cc:drop_temporary_table() and refine
+ the function to deal with transactional locked tables.
+ */
+static int wsrep_drop_table_query(THD* thd, uchar** buf, size_t* buf_len)
+{
+
+ LEX* lex= thd->lex;
+ SELECT_LEX* select_lex= &lex->select_lex;
+ TABLE_LIST* first_table= select_lex->table_list.first;
+ String buff;
+
+ DBUG_ASSERT(!lex->create_info.tmp_table());
+
+ bool found_temp_table= false;
+ for (TABLE_LIST* table= first_table; table; table= table->next_global)
+ {
+ if (thd->find_temporary_table(table->db, table->table_name))
+ {
+ found_temp_table= true;
+ break;
+ }
+ }
+
+ if (found_temp_table)
+ {
+ buff.append("DROP TABLE ");
+ if (lex->check_exists)
+ buff.append("IF EXISTS ");
+
+ for (TABLE_LIST* table= first_table; table; table= table->next_global)
+ {
+ if (!thd->find_temporary_table(table->db, table->table_name))
+ {
+ append_identifier(thd, &buff, table->db, strlen(table->db));
+ buff.append(".");
+ append_identifier(thd, &buff, table->table_name,
+ strlen(table->table_name));
+ buff.append(",");
+ }
+ }
+
+ /* Chop the last comma */
+ buff.chop();
+ buff.append(" /* generated by wsrep */");
+
+ WSREP_DEBUG("Rewrote '%s' as '%s'", thd->query(), buff.ptr());
+
+ return wsrep_to_buf_helper(thd, buff.ptr(), buff.length(), buf, buf_len);
+ }
+ else
+ {
+ return wsrep_to_buf_helper(thd, thd->query(), thd->query_length(),
+ buf, buf_len);
+ }
+}
+
+
/* Forward declarations. */
static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len);
static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
@@ -1503,7 +1600,8 @@ static const char* wsrep_get_query_or_msg(const THD* thd)
-1: TOI replication failed
*/
static int wsrep_TOI_begin(THD *thd, char *db_, char *table_,
- const TABLE_LIST* table_list)
+ const TABLE_LIST* table_list,
+ Alter_info* alter_info)
{
wsrep_status_t ret(WSREP_WARNING);
uchar* buf(0);
@@ -1538,6 +1636,9 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_,
case SQLCOM_ALTER_EVENT:
buf_err= wsrep_alter_event_query(thd, &buf, &buf_len);
break;
+ case SQLCOM_DROP_TABLE:
+ buf_err= wsrep_drop_table_query(thd, &buf, &buf_len);
+ break;
case SQLCOM_CREATE_ROLE:
if (sp_process_definer(thd))
{
@@ -1553,7 +1654,8 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_,
wsrep_key_arr_t key_arr= {0, 0};
struct wsrep_buf buff = { buf, buf_len };
if (!buf_err &&
- !wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr) &&
+ !wsrep_prepare_keys_for_isolation(thd, db_, table_,
+ table_list, alter_info, &key_arr) &&
key_arr.keys_len > 0 &&
WSREP_OK == (ret = wsrep->to_execute_start(wsrep, thd->thread_id,
key_arr.keys, key_arr.keys_len,
@@ -1696,7 +1798,8 @@ static void wsrep_RSU_end(THD *thd)
}
int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
- const TABLE_LIST* table_list)
+ const TABLE_LIST* table_list,
+ Alter_info* alter_info)
{
int ret= 0;
@@ -1752,10 +1855,10 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
{
switch (thd->variables.wsrep_OSU_method) {
case WSREP_OSU_TOI:
- ret = wsrep_TOI_begin(thd, db_, table_, table_list);
+ ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info);
break;
case WSREP_OSU_RSU:
- ret = wsrep_RSU_begin(thd, db_, table_);
+ ret= wsrep_RSU_begin(thd, db_, table_);
break;
default:
WSREP_ERROR("Unsupported OSU method: %lu",
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index c2169b56077..7f0308e10bf 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -159,7 +159,6 @@ extern "C" time_t wsrep_thd_query_start(THD *thd);
extern "C" query_id_t wsrep_thd_query_id(THD *thd);
extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
-extern "C" void wsrep_set_data_home_dir(const char *data_dir);
extern void wsrep_close_client_connections(my_bool wait_to_end);
extern int wsrep_wait_committing_connections_close(int wait_time);
@@ -291,8 +290,10 @@ extern PSI_mutex_key key_LOCK_wsrep_desync;
extern PSI_file_key key_file_wsrep_gra_log;
#endif /* HAVE_PSI_INTERFACE */
struct TABLE_LIST;
+class Alter_info;
int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
- const TABLE_LIST* table_list);
+ const TABLE_LIST* table_list,
+ Alter_info* alter_info = NULL);
void wsrep_to_isolation_end(THD *thd);
void wsrep_cleanup_transaction(THD *thd);
int wsrep_to_buf_helper(
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index 908c0c56685..3790c81d398 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -15,6 +15,7 @@
#include "wsrep_sst.h"
+#include <inttypes.h>
#include <mysqld.h>
#include <m_ctype.h>
#include <my_sys.h>
@@ -37,8 +38,14 @@ static char wsrep_defaults_file[FN_REFLEN * 2 + 10 + 30 +
sizeof(WSREP_SST_OPT_CONF_SUFFIX) +
sizeof(WSREP_SST_OPT_CONF_EXTRA)] = {0};
+const char* wsrep_sst_method = WSREP_SST_DEFAULT;
+const char* wsrep_sst_receive_address = WSREP_SST_ADDRESS_AUTO;
+const char* wsrep_sst_donor = "";
+const char* wsrep_sst_auth = NULL;
+
// container for real auth string
static const char* sst_auth_real = NULL;
+my_bool wsrep_sst_donor_rejects_queries = FALSE;
bool wsrep_sst_method_check (sys_var *self, THD* thd, set_var* var)
{
@@ -61,7 +68,6 @@ bool wsrep_sst_method_update (sys_var *self, THD* thd, enum_var_type type)
static const char* data_home_dir = NULL;
-extern "C"
void wsrep_set_data_home_dir(const char *data_dir)
{
data_home_dir= (data_dir && *data_dir) ? data_dir : NULL;
@@ -157,7 +163,7 @@ void wsrep_sst_auth_free()
bool wsrep_sst_auth_update (sys_var *self, THD* thd, enum_var_type type)
{
- return sst_auth_real_set (wsrep_sst_auth);
+ return sst_auth_real_set (wsrep_sst_auth);
}
void wsrep_sst_auth_init ()
@@ -172,9 +178,11 @@ bool wsrep_sst_donor_check (sys_var *self, THD* thd, set_var* var)
bool wsrep_sst_donor_update (sys_var *self, THD* thd, enum_var_type type)
{
- return 0;
+ return 0;
}
+static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED;
+
bool wsrep_before_SE()
{
return (wsrep_provider != NULL
@@ -218,7 +226,7 @@ bool wsrep_sst_wait ()
if (!sst_complete)
{
total_wtime += difftime(end_time, start_time);
- WSREP_DEBUG("Waiting for SST to complete. current seqno: %ld waited %f secs.", local_seqno, total_wtime);
+ WSREP_DEBUG("Waiting for SST to complete. current seqno: %" PRId64 " waited %f secs.", local_seqno, total_wtime);
service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL,
"WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime);
}
@@ -304,7 +312,7 @@ bool wsrep_sst_received (wsrep_t* const wsrep,
}
if (memcmp(&local_uuid, &uuid, sizeof(wsrep_uuid_t)) ||
- local_seqno < seqno)
+ local_seqno < seqno || seqno < 0)
{
do_update= true;
}
@@ -455,6 +463,22 @@ static int generate_binlog_opt_val(char** ret)
return 0;
}
+static int generate_binlog_index_opt_val(char** ret)
+{
+ DBUG_ASSERT(ret);
+ *ret= NULL;
+ if (opt_binlog_index_name) {
+ *ret= strcmp(opt_binlog_index_name, "0") ?
+ my_strdup(opt_binlog_index_name, MYF(0)) : my_strdup("", MYF(0));
+ }
+ else
+ {
+ *ret= my_strdup("", MYF(0));
+ }
+ if (!*ret) return -ENOMEM;
+ return 0;
+}
+
static void* sst_joiner_thread (void* a)
{
sst_thread_arg* arg= (sst_thread_arg*) a;
@@ -642,7 +666,9 @@ static ssize_t sst_prepare_other (const char* method,
}
const char* binlog_opt= "";
+ const char* binlog_index_opt= "";
char* binlog_opt_val= NULL;
+ char* binlog_index_opt_val= NULL;
int ret;
if ((ret= generate_binlog_opt_val(&binlog_opt_val)))
@@ -651,7 +677,15 @@ static ssize_t sst_prepare_other (const char* method,
ret);
return ret;
}
+
+ if ((ret= generate_binlog_index_opt_val(&binlog_index_opt_val)))
+ {
+ WSREP_ERROR("sst_prepare_other(): generate_binlog_index_opt_val() failed %d",
+ ret);
+ }
+
if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG;
+ if (strlen(binlog_index_opt_val)) binlog_index_opt= WSREP_SST_OPT_BINLOG_INDEX;
make_wsrep_defaults_file();
@@ -662,11 +696,14 @@ static ssize_t sst_prepare_other (const char* method,
WSREP_SST_OPT_DATA " '%s' "
" %s "
WSREP_SST_OPT_PARENT " '%d'"
- " %s '%s' ",
+ " %s '%s'"
+ " %s '%s'",
method, addr_in, mysql_real_data_home,
wsrep_defaults_file,
- (int)getpid(), binlog_opt, binlog_opt_val);
+ (int)getpid(), binlog_opt, binlog_opt_val,
+ binlog_index_opt, binlog_index_opt_val);
my_free(binlog_opt_val);
+ my_free(binlog_index_opt_val);
if (ret < 0 || ret >= cmd_len)
{
@@ -1432,7 +1469,7 @@ void wsrep_SE_init_wait()
if (!SE_initialized)
{
total_wtime += difftime(end_time, start_time);
- WSREP_DEBUG("Waiting for SST to complete. current seqno: %ld waited %f secs.", local_seqno, total_wtime);
+ WSREP_DEBUG("Waiting for SST to complete. current seqno: %" PRId64 " waited %f secs.", local_seqno, total_wtime);
service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL,
"WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime);
}
diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h
index 8bf6dc31464..cc0f1f5389d 100644
--- a/sql/wsrep_sst.h
+++ b/sql/wsrep_sst.h
@@ -31,6 +31,7 @@
#define WSREP_SST_OPT_CONF_EXTRA "--defaults-extra-file"
#define WSREP_SST_OPT_PARENT "--parent"
#define WSREP_SST_OPT_BINLOG "--binlog"
+#define WSREP_SST_OPT_BINLOG_INDEX "--binlog-index"
// mysqldump-specific options
#define WSREP_SST_OPT_USER "--user"
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index 9c7698aec39..bac19832ebb 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -594,7 +594,9 @@ void wsrep_node_address_init (const char* value)
static void wsrep_slave_count_change_update ()
{
- wsrep_slave_count_change += (wsrep_slave_threads - wsrep_prev_slave_threads);
+ wsrep_slave_count_change = (wsrep_slave_threads - wsrep_prev_slave_threads);
+ WSREP_DEBUG("Change on slave threads: New %lu old %lu difference %d",
+ wsrep_slave_threads, wsrep_prev_slave_threads, wsrep_slave_count_change);
wsrep_prev_slave_threads = wsrep_slave_threads;
}