diff options
author | Monty <monty@mariadb.org> | 2018-05-24 18:56:33 +0300 |
---|---|---|
committer | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2018-05-24 18:57:52 +0300 |
commit | 494c981d232678a3ba73abbe1502ddb0f95efcdc (patch) | |
tree | d01f70d42f4928906f20c7672dc0cf6538e1647e /sql | |
parent | 72a8d29e00d4deec7c836228b54e19fa35ab7ad7 (diff) | |
parent | bfed1bfe28980d3b1404f99a44712242a5108ef5 (diff) | |
download | mariadb-git-494c981d232678a3ba73abbe1502ddb0f95efcdc.tar.gz |
Merge remote-tracking branch 'origin/10.1' into 10.2
Diffstat (limited to 'sql')
-rw-r--r-- | sql/mf_iocache_encr.cc | 4 | ||||
-rw-r--r-- | sql/sql_admin.cc | 7 | ||||
-rw-r--r-- | sql/sql_class.h | 19 | ||||
-rw-r--r-- | sql/sql_handler.cc | 4 | ||||
-rw-r--r-- | sql/sql_parse.cc | 65 | ||||
-rw-r--r-- | sql/sql_rename.cc | 2 | ||||
-rw-r--r-- | sql/sql_statistics.cc | 3 | ||||
-rw-r--r-- | sql/sql_table.cc | 29 | ||||
-rw-r--r-- | sql/temporary_tables.cc | 18 |
9 files changed, 118 insertions, 33 deletions
diff --git a/sql/mf_iocache_encr.cc b/sql/mf_iocache_encr.cc index d078a183e31..879da12faa4 100644 --- a/sql/mf_iocache_encr.cc +++ b/sql/mf_iocache_encr.cc @@ -49,8 +49,8 @@ static int my_b_encr_read(IO_CACHE *info, uchar *Buffer, size_t Count) if (pos_in_file == info->end_of_file) { - info->read_pos= info->read_end= info->buffer; - info->pos_in_file= pos_in_file; + /* reading past EOF should not empty the cache */ + info->read_pos= info->read_end; info->error= 0; DBUG_RETURN(MY_TEST(Count)); } diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 3306575b845..49e14d6b013 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -426,7 +426,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt, const char *operator_name, thr_lock_type lock_type, - bool open_for_modify, + bool org_open_for_modify, bool repair_table_use_frm, uint extra_open_options, int (*prepare_func)(THD *, TABLE_LIST *, @@ -488,10 +488,11 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, for (table= tables; table; table= table->next_local) { char table_name[SAFE_NAME_LEN*2+2]; - char* db = table->db; + char *db= table->db; bool fatal_error=0; bool open_error; bool collect_eis= FALSE; + bool open_for_modify= org_open_for_modify; DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name)); strxmov(table_name, db, ".", table->table_name, NullS); @@ -1159,7 +1160,7 @@ send_result_message: } } /* Error path, a admin command failed. */ - if (thd->transaction_rollback_request) + if (thd->transaction_rollback_request || fatal_error) { /* Unlikely, but transaction rollback was requested by one of storage diff --git a/sql/sql_class.h b/sql/sql_class.h index 7302881ace2..a12015ecfe4 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4262,6 +4262,12 @@ public: /* Members related to temporary tables. */ public: + /* Opened table states. */ + enum Temporary_table_state { + TMP_TABLE_IN_USE, + TMP_TABLE_NOT_IN_USE, + TMP_TABLE_ANY + }; bool has_thd_temporary_tables(); TABLE *create_and_open_tmp_table(handlerton *hton, @@ -4271,8 +4277,10 @@ public: const char *table_name, bool open_in_engine); - TABLE *find_temporary_table(const char *db, const char *table_name); - TABLE *find_temporary_table(const TABLE_LIST *tl); + TABLE *find_temporary_table(const char *db, const char *table_name, + Temporary_table_state state= TMP_TABLE_IN_USE); + TABLE *find_temporary_table(const TABLE_LIST *tl, + Temporary_table_state state= TMP_TABLE_IN_USE); TMP_TABLE_SHARE *find_tmp_table_share_w_base_key(const char *key, uint key_length); @@ -4299,13 +4307,6 @@ private: /* Whether a lock has been acquired? */ bool m_tmp_tables_locked; - /* Opened table states. */ - enum Temporary_table_state { - TMP_TABLE_IN_USE, - TMP_TABLE_NOT_IN_USE, - TMP_TABLE_ANY - }; - bool has_temporary_tables(); uint create_tmp_table_def_key(char *key, const char *db, const char *table_name); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 4a27244f5b9..2a3454703f4 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -155,10 +155,11 @@ static void mysql_ha_close_table(SQL_HANDLER *handler) { THD *thd= handler->thd; TABLE *table= handler->table; + DBUG_ENTER("mysql_ha_close_table"); /* check if table was already closed */ if (!table) - return; + DBUG_VOID_RETURN; if (!table->s->tmp_table) { @@ -183,6 +184,7 @@ static void mysql_ha_close_table(SQL_HANDLER *handler) } my_free(handler->lock); handler->init(); + DBUG_VOID_RETURN; } /* diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f4038649745..1c36bd7bcdf 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -763,6 +763,8 @@ void init_update_queries(void) There are other statements that deal with temporary tables and open them, but which are not listed here. The thing is that the order of pre-opening temporary tables for those statements is somewhat custom. + + Note that SQLCOM_RENAME_TABLE should not be in this list! */ sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_DROP_TABLE]|= CF_PREOPEN_TMP_TABLES; @@ -776,7 +778,6 @@ void init_update_queries(void) sql_command_flags[SQLCOM_INSERT_SELECT]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_DELETE]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_DELETE_MULTI]|= CF_PREOPEN_TMP_TABLES; - sql_command_flags[SQLCOM_RENAME_TABLE]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_REPLACE_SELECT]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_SELECT]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_SET_OPTION]|= CF_PREOPEN_TMP_TABLES; @@ -6525,6 +6526,60 @@ static bool execute_show_status(THD *thd, TABLE_LIST *all_tables) } +/* + Find out if a table is a temporary table + + A table is a temporary table if it's a temporary table or + there has been before a temporary table that has been renamed + to the current name. + + Some examples: + A->B B is a temporary table if and only if A is a temp. + A->B, B->C Second B is temp if A is temp + A->B, A->C Second A can't be temp as if A was temp then B is temp + and Second A can only be a normal table. C is also not temp +*/ + +static TABLE *find_temporary_table_for_rename(THD *thd, + TABLE_LIST *first_table, + TABLE_LIST *cur_table) +{ + TABLE_LIST *table; + TABLE *res= 0; + bool found= 0; + DBUG_ENTER("find_temporary_table_for_rename"); + + /* Find last instance when cur_table is in TO part */ + for (table= first_table; + table != cur_table; + table= table->next_local->next_local) + { + TABLE_LIST *next= table->next_local; + + if (!strcmp(table->get_db_name(), cur_table->get_db_name()) && + !strcmp(table->get_table_name(), cur_table->get_table_name())) + { + /* Table was moved away, can't be same as 'table' */ + found= 1; + res= 0; // Table can't be a temporary table + } + if (!strcmp(next->get_db_name(), cur_table->get_db_name()) && + !strcmp(next->get_table_name(), cur_table->get_table_name())) + { + /* + Table has matching name with new name of this table. cur_table should + have same temporary type as this table. + */ + found= 1; + res= table->table; + } + } + if (!found) + res= thd->find_temporary_table(table, THD::TMP_TABLE_ANY); + DBUG_RETURN(res); +} + + static bool check_rename_table(THD *thd, TABLE_LIST *first_table, TABLE_LIST *all_tables) { @@ -6541,13 +6596,19 @@ static bool check_rename_table(THD *thd, TABLE_LIST *first_table, &table->next_local->grant.m_internal, 0, 0)) return 1; + + /* check if these are refering to temporary tables */ + table->table= find_temporary_table_for_rename(thd, first_table, table); + table->next_local->table= table->table; + TABLE_LIST old_list, new_list; /* we do not need initialize old_list and new_list because we will - come table[0] and table->next[0] there + copy table[0] and table->next[0] there */ old_list= table[0]; new_list= table->next_local[0]; + if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, FALSE, 1, FALSE) || (!test_all_bits(table->next_local->grant.privilege, INSERT_ACL | CREATE_ACL) && diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 1588644f0e1..4e576602a1a 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -221,7 +221,7 @@ do_rename_temporary(THD *thd, TABLE_LIST *ren_table, TABLE_LIST *new_table, new_alias= (lower_case_table_names == 2) ? new_table->alias : new_table->table_name; - if (is_temporary_table(new_table)) + if (thd->find_temporary_table(new_table, THD::TMP_TABLE_ANY)) { my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias); DBUG_RETURN(1); // This can't be skipped diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 903ebb91d01..0e4749dbe6e 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -1519,7 +1519,8 @@ public: ~Stat_table_write_iter() { - cleanup(); + /* Ensure that cleanup has been run */ + DBUG_ASSERT(rowid_buf == 0); } }; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index b01629cb1e9..853535f3d51 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5888,10 +5888,28 @@ drop_create_field: List_iterator<Alter_drop> drop_it(alter_info->drop_list); Alter_drop *drop; bool remove_drop; + ulonglong left_flags= 0; while ((drop= drop_it++)) { + ulonglong cur_flag= 0; + switch (drop->type) { + case Alter_drop::COLUMN: + cur_flag= Alter_info::ALTER_DROP_COLUMN; + break; + case Alter_drop::FOREIGN_KEY: + cur_flag= Alter_info::DROP_FOREIGN_KEY; + break; + case Alter_drop::KEY: + cur_flag= Alter_info::ALTER_DROP_INDEX; + break; + default: + break; + } if (!drop->drop_if_exists) + { + left_flags|= cur_flag; continue; + } remove_drop= TRUE; if (drop->type == Alter_drop::COLUMN) { @@ -5980,12 +5998,15 @@ drop_create_field: ER_THD(thd, ER_CANT_DROP_FIELD_OR_KEY), drop->type_name(), drop->name); drop_it.remove(); - if (alter_info->drop_list.is_empty()) - alter_info->flags&= ~(Alter_info::ALTER_DROP_COLUMN | - Alter_info::ALTER_DROP_INDEX | - Alter_info::DROP_FOREIGN_KEY); } + else + left_flags|= cur_flag; } + /* Reset state to what's left in drop list */ + alter_info->flags&= ~(Alter_info::ALTER_DROP_COLUMN | + Alter_info::ALTER_DROP_INDEX | + Alter_info::DROP_FOREIGN_KEY); + alter_info->flags|= left_flags; } /* ALTER TABLE ADD KEY IF NOT EXISTS */ diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index 8077324d202..3201b306fad 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -99,12 +99,14 @@ TABLE *THD::create_and_open_tmp_table(handlerton *hton, @param db [IN] Database name @param table_name [IN] Table name + @param state [IN] State of temp table to open @return Success Pointer to first used table instance. Failure NULL */ TABLE *THD::find_temporary_table(const char *db, - const char *table_name) + const char *table_name, + Temporary_table_state state) { DBUG_ENTER("THD::find_temporary_table"); @@ -121,7 +123,7 @@ TABLE *THD::find_temporary_table(const char *db, key_length= create_tmp_table_def_key(key, db, table_name); locked= lock_temporary_tables(); - table = find_temporary_table(key, key_length, TMP_TABLE_IN_USE); + table= find_temporary_table(key, key_length, state); if (locked) { DBUG_ASSERT(m_tmp_tables_locked); @@ -140,16 +142,12 @@ TABLE *THD::find_temporary_table(const char *db, @return Success Pointer to first used table instance. Failure NULL */ -TABLE *THD::find_temporary_table(const TABLE_LIST *tl) +TABLE *THD::find_temporary_table(const TABLE_LIST *tl, + Temporary_table_state state) { DBUG_ENTER("THD::find_temporary_table"); - - if (!has_temporary_tables()) - { - DBUG_RETURN(NULL); - } - - TABLE *table= find_temporary_table(tl->get_db_name(), tl->get_table_name()); + TABLE *table= find_temporary_table(tl->get_db_name(), tl->get_table_name(), + state); DBUG_RETURN(table); } |