diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2018-09-14 08:47:22 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2018-09-14 08:47:22 +0200 |
commit | 28f08d3753eb10a1393a63e6c581d43aad9f93b9 (patch) | |
tree | 86c9df8c3fb6d4ebd99d431697c84f06ef242989 /sql | |
parent | 38665893087e20c3ad65d5b0e227a75185a4865e (diff) | |
parent | f1bcfbb4373e40dda2c18c137f76fc6ff32e1a45 (diff) | |
download | mariadb-git-28f08d3753eb10a1393a63e6c581d43aad9f93b9.tar.gz |
Merge branch '10.1' into 10.2
Diffstat (limited to 'sql')
-rw-r--r-- | sql/events.cc | 2 | ||||
-rw-r--r-- | sql/field.cc | 17 | ||||
-rw-r--r-- | sql/handler.cc | 4 | ||||
-rw-r--r-- | sql/item.cc | 10 | ||||
-rw-r--r-- | sql/log.cc | 8 | ||||
-rw-r--r-- | sql/log_event.cc | 5 | ||||
-rw-r--r-- | sql/mysqld.cc | 2 | ||||
-rw-r--r-- | sql/mysqld.h | 1 | ||||
-rw-r--r-- | sql/opt_range.cc | 27 | ||||
-rw-r--r-- | sql/sql_alter.cc | 20 | ||||
-rw-r--r-- | sql/sql_base.cc | 160 | ||||
-rw-r--r-- | sql/sql_base.h | 6 | ||||
-rw-r--r-- | sql/sql_parse.cc | 2 | ||||
-rw-r--r-- | sql/sql_plugin_services.ic | 3 | ||||
-rw-r--r-- | sql/sql_reload.cc | 13 | ||||
-rw-r--r-- | sql/sql_select.cc | 2 | ||||
-rw-r--r-- | sql/sql_statistics.cc | 3 | ||||
-rw-r--r-- | sql/sql_statistics.h | 29 | ||||
-rw-r--r-- | sql/sql_table.cc | 64 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 8 | ||||
-rw-r--r-- | sql/sql_truncate.cc | 2 | ||||
-rw-r--r-- | sql/table.cc | 7 | ||||
-rw-r--r-- | sql/table.h | 25 | ||||
-rw-r--r-- | sql/table_cache.cc | 2 | ||||
-rw-r--r-- | sql/wsrep_dummy.cc | 3 | ||||
-rw-r--r-- | sql/wsrep_hton.cc | 9 | ||||
-rw-r--r-- | sql/wsrep_mysqld.cc | 295 | ||||
-rw-r--r-- | sql/wsrep_mysqld.h | 5 | ||||
-rw-r--r-- | sql/wsrep_sst.cc | 53 | ||||
-rw-r--r-- | sql/wsrep_sst.h | 1 | ||||
-rw-r--r-- | sql/wsrep_var.cc | 4 |
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; } |