summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2018-05-24 18:56:33 +0300
committerVicențiu Ciorbaru <vicentiu@mariadb.org>2018-05-24 18:57:52 +0300
commit494c981d232678a3ba73abbe1502ddb0f95efcdc (patch)
treed01f70d42f4928906f20c7672dc0cf6538e1647e /sql
parent72a8d29e00d4deec7c836228b54e19fa35ab7ad7 (diff)
parentbfed1bfe28980d3b1404f99a44712242a5108ef5 (diff)
downloadmariadb-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.cc4
-rw-r--r--sql/sql_admin.cc7
-rw-r--r--sql/sql_class.h19
-rw-r--r--sql/sql_handler.cc4
-rw-r--r--sql/sql_parse.cc65
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_statistics.cc3
-rw-r--r--sql/sql_table.cc29
-rw-r--r--sql/temporary_tables.cc18
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);
}