summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2018-05-24 11:08:02 +0300
committerMonty <monty@mariadb.org>2018-05-24 11:08:02 +0300
commite744c687ca2c2523b63d5ac0066276a6cb3e932f (patch)
tree7d3fbd9457d9a6f074d4c8dbb925fcb65730e135 /sql
parent5797cbaf4ab93cdae191486c6c82be79b83c56d2 (diff)
parenta816aa066e5c879a92819d694a93d245e6ec6e47 (diff)
downloadmariadb-git-e744c687ca2c2523b63d5ac0066276a6cb3e932f.tar.gz
Merge remote-tracking branch 'origin/10.0' into 10.1
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_admin.cc11
-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
6 files changed, 100 insertions, 14 deletions
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index ef7a2e82338..be23cd3341b 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -302,7 +302,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 *,
@@ -365,10 +365,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);
@@ -406,8 +407,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/*
CHECK TABLE command is allowed for views as well. Check on alter flags
- to differentiate from ALTER TABLE...CHECK PARTITION on which view is not
- allowed.
+ to differentiate from ALTER TABLE...CHECK PARTITION on which view is
+ not allowed.
*/
if (lex->alter_info.flags & Alter_info::ALTER_ADMIN_PARTITION ||
view_operator_func == NULL)
@@ -1102,7 +1103,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_handler.cc b/sql/sql_handler.cc
index 662fa33dc9f..8aee34a484d 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)
{
@@ -184,6 +185,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 b4a26fa734d..55673ba2713 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -520,6 +520,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;
@@ -533,7 +535,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;
@@ -5995,6 +5996,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= find_temporary_table(thd, table);
+ DBUG_RETURN(res);
+}
+
+
static bool check_rename_table(THD *thd, TABLE_LIST *first_table,
TABLE_LIST *all_tables)
{
@@ -6011,13 +6066,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 35222bce949..4c164a3a621 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -222,7 +222,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 (find_temporary_table(thd, new_table))
{
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 2a97c37e477..b7ccbb5c212 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -1518,7 +1518,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 72488fc870f..31da585443a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5835,10 +5835,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)
{
@@ -5915,12 +5933,15 @@ drop_create_field:
ER_THD(thd, ER_CANT_DROP_FIELD_OR_KEY),
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 */