mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Added IF EXISTS to RENAME TABLE and ALTER TABLE
This commit is contained in:
@ -3244,3 +3244,22 @@ drop table t1;
|
|||||||
#
|
#
|
||||||
# End of 10.5 tests
|
# End of 10.5 tests
|
||||||
#
|
#
|
||||||
|
#
|
||||||
|
# ALTER TABLE IF EXISTS
|
||||||
|
#
|
||||||
|
create table t1 (a int);
|
||||||
|
alter table if exists t1 add column b int;
|
||||||
|
alter table if exists t2 add column c int;
|
||||||
|
Warnings:
|
||||||
|
Error 1146 Table 'test.t2' doesn't exist
|
||||||
|
alter table if exists t9 rename t1;
|
||||||
|
Warnings:
|
||||||
|
Error 1146 Table 'test.t9' doesn't exist
|
||||||
|
alter table if exists t1 rename t2;
|
||||||
|
show create table t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE `t2` (
|
||||||
|
`a` int(11) DEFAULT NULL,
|
||||||
|
`b` int(11) DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
drop table t2;
|
||||||
|
@ -2456,3 +2456,15 @@ drop table t1;
|
|||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.5 tests
|
--echo # End of 10.5 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # ALTER TABLE IF EXISTS
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
create table t1 (a int);
|
||||||
|
alter table if exists t1 add column b int;
|
||||||
|
alter table if exists t2 add column c int;
|
||||||
|
alter table if exists t9 rename t1;
|
||||||
|
alter table if exists t1 rename t2;
|
||||||
|
show create table t2;
|
||||||
|
drop table t2;
|
||||||
|
@ -528,9 +528,11 @@ drop table if exists new_t2;
|
|||||||
prepare stmt3 from ' rename table t2 to new_t2 ';
|
prepare stmt3 from ' rename table t2 to new_t2 ';
|
||||||
execute stmt3;
|
execute stmt3;
|
||||||
execute stmt3;
|
execute stmt3;
|
||||||
|
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||||
|
create table t2 like new_t2;
|
||||||
|
execute stmt3;
|
||||||
ERROR 42S01: Table 'new_t2' already exists
|
ERROR 42S01: Table 'new_t2' already exists
|
||||||
rename table new_t2 to t2;
|
drop table new_t2,t2;
|
||||||
drop table t2;
|
|
||||||
prepare stmt1 from ' rename table t5 to t6, t7 to t8 ' ;
|
prepare stmt1 from ' rename table t5 to t6, t7 to t8 ' ;
|
||||||
create table t5 (a int) ;
|
create table t5 (a int) ;
|
||||||
execute stmt1 ;
|
execute stmt1 ;
|
||||||
@ -538,7 +540,7 @@ ERROR 42S02: Table 'test.t7' doesn't exist
|
|||||||
create table t7 (a int) ;
|
create table t7 (a int) ;
|
||||||
execute stmt1 ;
|
execute stmt1 ;
|
||||||
execute stmt1 ;
|
execute stmt1 ;
|
||||||
ERROR 42S01: Table 't6' already exists
|
ERROR 42S02: Table 'test.t5' doesn't exist
|
||||||
rename table t6 to t5, t8 to t7 ;
|
rename table t6 to t5, t8 to t7 ;
|
||||||
execute stmt1 ;
|
execute stmt1 ;
|
||||||
drop table t6, t8 ;
|
drop table t6, t8 ;
|
||||||
|
@ -576,10 +576,12 @@ drop table if exists new_t2;
|
|||||||
--enable_warnings
|
--enable_warnings
|
||||||
prepare stmt3 from ' rename table t2 to new_t2 ';
|
prepare stmt3 from ' rename table t2 to new_t2 ';
|
||||||
execute stmt3;
|
execute stmt3;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
execute stmt3;
|
||||||
|
create table t2 like new_t2;
|
||||||
--error ER_TABLE_EXISTS_ERROR
|
--error ER_TABLE_EXISTS_ERROR
|
||||||
execute stmt3;
|
execute stmt3;
|
||||||
rename table new_t2 to t2;
|
drop table new_t2,t2;
|
||||||
drop table t2;
|
|
||||||
## RENAME more than on TABLE within one statement
|
## RENAME more than on TABLE within one statement
|
||||||
# cases derived from client_test.c: test_rename()
|
# cases derived from client_test.c: test_rename()
|
||||||
prepare stmt1 from ' rename table t5 to t6, t7 to t8 ' ;
|
prepare stmt1 from ' rename table t5 to t6, t7 to t8 ' ;
|
||||||
@ -590,7 +592,7 @@ create table t7 (a int) ;
|
|||||||
# rename, t5 -> t6 and t7 -> t8
|
# rename, t5 -> t6 and t7 -> t8
|
||||||
execute stmt1 ;
|
execute stmt1 ;
|
||||||
# rename must fail, t5 and t7 does not exist t6 and t8 already exist
|
# rename must fail, t5 and t7 does not exist t6 and t8 already exist
|
||||||
--error ER_TABLE_EXISTS_ERROR
|
--error ER_NO_SUCH_TABLE
|
||||||
execute stmt1 ;
|
execute stmt1 ;
|
||||||
rename table t6 to t5, t8 to t7 ;
|
rename table t6 to t5, t8 to t7 ;
|
||||||
# rename, t5 -> t6 and t7 -> t8
|
# rename, t5 -> t6 and t7 -> t8
|
||||||
|
@ -148,3 +148,28 @@ create table t1 (a int) engine=memory;
|
|||||||
rename table t1 to non_existent.t2;
|
rename table t1 to non_existent.t2;
|
||||||
ERROR 42000: Unknown database 'non_existent'
|
ERROR 42000: Unknown database 'non_existent'
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# Test rename IF EXISTS
|
||||||
|
#
|
||||||
|
rename table if exists t1 to t2;
|
||||||
|
Warnings:
|
||||||
|
Note 1146 Table 'test.t1' doesn't exist
|
||||||
|
alter table if exists t1 rename to t2;
|
||||||
|
Warnings:
|
||||||
|
Error 1146 Table 'test.t1' doesn't exist
|
||||||
|
create table t2 (a int);
|
||||||
|
alter table if exists t1 rename to t2;
|
||||||
|
Warnings:
|
||||||
|
Error 1146 Table 'test.t1' doesn't exist
|
||||||
|
rename table if exists t1 to t2;
|
||||||
|
Warnings:
|
||||||
|
Note 1146 Table 'test.t1' doesn't exist
|
||||||
|
create table t1 (a int);
|
||||||
|
rename table if exists t1 to t2;
|
||||||
|
ERROR 42S01: Table 't2' already exists
|
||||||
|
alter table if exists t1 rename to t2;
|
||||||
|
ERROR 42S01: Table 't2' already exists
|
||||||
|
drop table t2;
|
||||||
|
rename table if exists t1 to t2;
|
||||||
|
alter table if exists t2 rename to t1;
|
||||||
|
drop table t1;
|
||||||
|
@ -148,3 +148,21 @@ create table t1 (a int) engine=memory;
|
|||||||
--error ER_BAD_DB_ERROR
|
--error ER_BAD_DB_ERROR
|
||||||
rename table t1 to non_existent.t2;
|
rename table t1 to non_existent.t2;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Test rename IF EXISTS
|
||||||
|
--echo #
|
||||||
|
rename table if exists t1 to t2;
|
||||||
|
alter table if exists t1 rename to t2;
|
||||||
|
create table t2 (a int);
|
||||||
|
alter table if exists t1 rename to t2;
|
||||||
|
rename table if exists t1 to t2;
|
||||||
|
create table t1 (a int);
|
||||||
|
--error ER_TABLE_EXISTS_ERROR
|
||||||
|
rename table if exists t1 to t2;
|
||||||
|
--error ER_TABLE_EXISTS_ERROR
|
||||||
|
alter table if exists t1 rename to t2;
|
||||||
|
drop table t2;
|
||||||
|
rename table if exists t1 to t2;
|
||||||
|
alter table if exists t2 rename to t1;
|
||||||
|
drop table t1;
|
||||||
|
@ -13,7 +13,7 @@ t1 CREATE TABLE `t1` (
|
|||||||
RENAME TABLE t2 TO t1;
|
RENAME TABLE t2 TO t1;
|
||||||
ERROR 42S01: Table 't1' already exists
|
ERROR 42S01: Table 't1' already exists
|
||||||
RENAME TABLE t3 TO t1;
|
RENAME TABLE t3 TO t1;
|
||||||
ERROR 42S01: Table 't1' already exists
|
ERROR 42S02: Table 'test.t3' doesn't exist
|
||||||
RENAME TABLE t3 TO doesnotexist.t1;
|
RENAME TABLE t3 TO doesnotexist.t1;
|
||||||
ERROR 42S02: Table 'test.t3' doesn't exist
|
ERROR 42S02: Table 'test.t3' doesn't exist
|
||||||
SHOW TABLES;
|
SHOW TABLES;
|
||||||
|
@ -7,9 +7,9 @@ SHOW TABLES;
|
|||||||
let $ENGINE=`select variable_value from information_schema.global_variables where variable_name='STORAGE_ENGINE'`;
|
let $ENGINE=`select variable_value from information_schema.global_variables where variable_name='STORAGE_ENGINE'`;
|
||||||
--replace_result $ENGINE ENGINE " PAGE_CHECKSUM=0" "" " PAGE_CHECKSUM=1" ""
|
--replace_result $ENGINE ENGINE " PAGE_CHECKSUM=0" "" " PAGE_CHECKSUM=1" ""
|
||||||
SHOW CREATE TABLE t1;
|
SHOW CREATE TABLE t1;
|
||||||
--error 1050
|
--error ER_TABLE_EXISTS_ERROR
|
||||||
RENAME TABLE t2 TO t1;
|
RENAME TABLE t2 TO t1;
|
||||||
--error 1050
|
--error ER_NO_SUCH_TABLE
|
||||||
RENAME TABLE t3 TO t1;
|
RENAME TABLE t3 TO t1;
|
||||||
--error 1146
|
--error 1146
|
||||||
RENAME TABLE t3 TO doesnotexist.t1;
|
RENAME TABLE t3 TO doesnotexist.t1;
|
||||||
|
@ -5624,7 +5624,8 @@ private:
|
|||||||
*hton will be NULL.
|
*hton will be NULL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool ha_table_exists(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table_name,
|
bool ha_table_exists(THD *thd, const LEX_CSTRING *db,
|
||||||
|
const LEX_CSTRING *table_name,
|
||||||
handlerton **hton, bool *is_sequence)
|
handlerton **hton, bool *is_sequence)
|
||||||
{
|
{
|
||||||
handlerton *dummy;
|
handlerton *dummy;
|
||||||
|
@ -522,7 +522,7 @@ bool Sql_cmd_alter_table::execute(THD *thd)
|
|||||||
&alter_info,
|
&alter_info,
|
||||||
select_lex->order_list.elements,
|
select_lex->order_list.elements,
|
||||||
select_lex->order_list.first,
|
select_lex->order_list.first,
|
||||||
lex->ignore);
|
lex->ignore, lex->if_exists());
|
||||||
|
|
||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
|
@ -1805,7 +1805,7 @@ bool mysql_upgrade_db(THD *thd, const LEX_CSTRING *old_db)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((table_list= thd->lex->query_tables) &&
|
if ((table_list= thd->lex->query_tables) &&
|
||||||
(error= mysql_rename_tables(thd, table_list, 1)))
|
(error= mysql_rename_tables(thd, table_list, 1, 0)))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Failed to move all tables from the old database to the new one.
|
Failed to move all tables from the old database to the new one.
|
||||||
|
@ -4160,7 +4160,7 @@ mysql_execute_command(THD *thd)
|
|||||||
|
|
||||||
res= mysql_alter_table(thd, &first_table->db, &first_table->table_name,
|
res= mysql_alter_table(thd, &first_table->db, &first_table->table_name,
|
||||||
&create_info, first_table, &alter_info,
|
&create_info, first_table, &alter_info,
|
||||||
0, (ORDER*) 0, 0);
|
0, (ORDER*) 0, 0, lex->if_exists());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
@ -4272,7 +4272,7 @@ mysql_execute_command(THD *thd)
|
|||||||
|
|
||||||
WSREP_TO_ISOLATION_BEGIN(0, 0, first_table);
|
WSREP_TO_ISOLATION_BEGIN(0, 0, first_table);
|
||||||
|
|
||||||
if (mysql_rename_tables(thd, first_table, 0))
|
if (mysql_rename_tables(thd, first_table, 0, lex->if_exists()))
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,13 @@
|
|||||||
#include "sql_statistics.h"
|
#include "sql_statistics.h"
|
||||||
|
|
||||||
static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list,
|
static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list,
|
||||||
bool skip_error);
|
bool skip_error, bool if_exits,
|
||||||
static bool do_rename(THD *thd, TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
|
bool *force_if_exists);
|
||||||
const LEX_CSTRING *new_table_name, const LEX_CSTRING *new_table_alias,
|
static bool do_rename(THD *thd, TABLE_LIST *ren_table,
|
||||||
bool skip_error);
|
const LEX_CSTRING *new_db,
|
||||||
|
const LEX_CSTRING *new_table_name,
|
||||||
|
const LEX_CSTRING *new_table_alias,
|
||||||
|
bool skip_error, bool if_exists, bool *force_if_exists);
|
||||||
|
|
||||||
static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list);
|
static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list);
|
||||||
|
|
||||||
@ -44,10 +47,11 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list);
|
|||||||
the new name.
|
the new name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent,
|
||||||
|
bool if_exists)
|
||||||
{
|
{
|
||||||
bool error= 1;
|
bool error= 1;
|
||||||
bool binlog_error= 0;
|
bool binlog_error= 0, force_if_exists;
|
||||||
TABLE_LIST *ren_table= 0;
|
TABLE_LIST *ren_table= 0;
|
||||||
int to_table;
|
int to_table;
|
||||||
const char *rename_log_table[2]= {NULL, NULL};
|
const char *rename_log_table[2]= {NULL, NULL};
|
||||||
@ -151,7 +155,8 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
|||||||
An exclusive lock on table names is satisfactory to ensure
|
An exclusive lock on table names is satisfactory to ensure
|
||||||
no other thread accesses this table.
|
no other thread accesses this table.
|
||||||
*/
|
*/
|
||||||
if ((ren_table=rename_tables(thd,table_list,0)))
|
if ((ren_table= rename_tables(thd, table_list, 0, if_exists,
|
||||||
|
&force_if_exists)))
|
||||||
{
|
{
|
||||||
/* Rename didn't succeed; rename back the tables in reverse order */
|
/* Rename didn't succeed; rename back the tables in reverse order */
|
||||||
TABLE_LIST *table;
|
TABLE_LIST *table;
|
||||||
@ -165,7 +170,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
|||||||
table= table->next_local->next_local) ;
|
table= table->next_local->next_local) ;
|
||||||
table= table->next_local->next_local; // Skip error table
|
table= table->next_local->next_local; // Skip error table
|
||||||
/* Revert to old names */
|
/* Revert to old names */
|
||||||
rename_tables(thd, table, 1);
|
rename_tables(thd, table, 1, if_exists, &force_if_exists);
|
||||||
|
|
||||||
/* Revert the table list (for prepared statements) */
|
/* Revert the table list (for prepared statements) */
|
||||||
table_list= reverse_table_list(table_list);
|
table_list= reverse_table_list(table_list);
|
||||||
@ -246,6 +251,9 @@ do_rename_temporary(THD *thd, TABLE_LIST *ren_table, TABLE_LIST *new_table,
|
|||||||
new_table_name The new table/view name
|
new_table_name The new table/view name
|
||||||
new_table_alias The new table/view alias
|
new_table_alias The new table/view alias
|
||||||
skip_error Whether to skip error
|
skip_error Whether to skip error
|
||||||
|
if_exists Skip error, but only if the table didn't exists
|
||||||
|
force_if_exists Set to 1 if we have to log the query with 'IF EXISTS'
|
||||||
|
Otherwise don't touch the value
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
Rename a single table or a view.
|
Rename a single table or a view.
|
||||||
@ -257,13 +265,16 @@ do_rename_temporary(THD *thd, TABLE_LIST *ren_table, TABLE_LIST *new_table,
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
do_rename(THD *thd, TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
|
do_rename(THD *thd, TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
|
||||||
const LEX_CSTRING *new_table_name, const LEX_CSTRING *new_table_alias,
|
const LEX_CSTRING *new_table_name,
|
||||||
bool skip_error)
|
const LEX_CSTRING *new_table_alias,
|
||||||
|
bool skip_error, bool if_exists, bool *force_if_exists)
|
||||||
{
|
{
|
||||||
int rc= 1;
|
int rc= 1;
|
||||||
handlerton *hton;
|
handlerton *hton, *new_hton;
|
||||||
LEX_CSTRING old_alias, new_alias;
|
LEX_CSTRING old_alias, new_alias;
|
||||||
DBUG_ENTER("do_rename");
|
DBUG_ENTER("do_rename");
|
||||||
|
DBUG_PRINT("enter", ("skip_error: %d if_exists: %d", (int) skip_error,
|
||||||
|
(int) if_exists));
|
||||||
|
|
||||||
if (lower_case_table_names == 2)
|
if (lower_case_table_names == 2)
|
||||||
{
|
{
|
||||||
@ -277,13 +288,19 @@ do_rename(THD *thd, TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
|
|||||||
}
|
}
|
||||||
DBUG_ASSERT(new_alias.str);
|
DBUG_ASSERT(new_alias.str);
|
||||||
|
|
||||||
if (ha_table_exists(thd, new_db, &new_alias))
|
if (!ha_table_exists(thd, &ren_table->db, &old_alias, &hton) || !hton)
|
||||||
|
{
|
||||||
|
my_error(ER_NO_SUCH_TABLE, MYF((skip_error | if_exists) ? ME_NOTE : 0),
|
||||||
|
ren_table->db.str, old_alias.str);
|
||||||
|
DBUG_RETURN(skip_error || if_exists ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ha_table_exists(thd, new_db, &new_alias, &new_hton))
|
||||||
{
|
{
|
||||||
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias.str);
|
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias.str);
|
||||||
DBUG_RETURN(1); // This can't be skipped
|
DBUG_RETURN(1); // This can't be skipped
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ha_table_exists(thd, &ren_table->db, &old_alias, &hton) && hton)
|
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(!thd->locked_tables_mode);
|
DBUG_ASSERT(!thd->locked_tables_mode);
|
||||||
|
|
||||||
@ -335,14 +352,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
|
|||||||
rc= mysql_rename_view(thd, new_db, &new_alias, ren_table);
|
rc= mysql_rename_view(thd, new_db, &new_alias, ren_table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
DBUG_RETURN(rc && !skip_error ? 1 : 0);
|
||||||
{
|
|
||||||
my_error(ER_NO_SUCH_TABLE, MYF(0), ren_table->db.str, old_alias.str);
|
|
||||||
}
|
|
||||||
if (unlikely(rc && !skip_error))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -359,6 +369,9 @@ do_rename(THD *thd, TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
|
|||||||
thd Thread handle
|
thd Thread handle
|
||||||
table_list List of tables to rename
|
table_list List of tables to rename
|
||||||
skip_error Whether to skip errors
|
skip_error Whether to skip errors
|
||||||
|
if_exists Don't give an error if table doesn't exists
|
||||||
|
force_if_exists Set to 1 if we have to log the query with 'IF EXISTS'
|
||||||
|
Otherwise set it to 0
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
Take a table/view name from and odd list element and rename it to a
|
Take a table/view name from and odd list element and rename it to a
|
||||||
@ -371,12 +384,14 @@ do_rename(THD *thd, TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static TABLE_LIST *
|
static TABLE_LIST *
|
||||||
rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
|
rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error,
|
||||||
|
bool if_exists, bool *force_if_exists)
|
||||||
{
|
{
|
||||||
TABLE_LIST *ren_table, *new_table;
|
TABLE_LIST *ren_table, *new_table;
|
||||||
|
|
||||||
DBUG_ENTER("rename_tables");
|
DBUG_ENTER("rename_tables");
|
||||||
|
|
||||||
|
*force_if_exists= 0;
|
||||||
|
|
||||||
for (ren_table= table_list; ren_table; ren_table= new_table->next_local)
|
for (ren_table= table_list; ren_table; ren_table= new_table->next_local)
|
||||||
{
|
{
|
||||||
new_table= ren_table->next_local;
|
new_table= ren_table->next_local;
|
||||||
@ -384,7 +399,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
|
|||||||
if (is_temporary_table(ren_table) ?
|
if (is_temporary_table(ren_table) ?
|
||||||
do_rename_temporary(thd, ren_table, new_table, skip_error) :
|
do_rename_temporary(thd, ren_table, new_table, skip_error) :
|
||||||
do_rename(thd, ren_table, &new_table->db, &new_table->table_name,
|
do_rename(thd, ren_table, &new_table->db, &new_table->table_name,
|
||||||
&new_table->alias, skip_error))
|
&new_table->alias, skip_error, if_exists, force_if_exists))
|
||||||
DBUG_RETURN(ren_table);
|
DBUG_RETURN(ren_table);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
class THD;
|
class THD;
|
||||||
struct TABLE_LIST;
|
struct TABLE_LIST;
|
||||||
|
|
||||||
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent);
|
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent,
|
||||||
|
bool if_exists);
|
||||||
|
|
||||||
#endif /* SQL_RENAME_INCLUDED */
|
#endif /* SQL_RENAME_INCLUDED */
|
||||||
|
131
sql/sql_table.cc
131
sql/sql_table.cc
@ -2777,7 +2777,7 @@ bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db,
|
|||||||
delete file;
|
delete file;
|
||||||
}
|
}
|
||||||
if (!(flags & (FRM_ONLY|NO_HA_TABLE)))
|
if (!(flags & (FRM_ONLY|NO_HA_TABLE)))
|
||||||
error|= ha_delete_table(current_thd, base, path, db, table_name, 0);
|
error|= ha_delete_table(thd, base, path, db, table_name, 0);
|
||||||
|
|
||||||
if (likely(error == 0))
|
if (likely(error == 0))
|
||||||
{
|
{
|
||||||
@ -4392,8 +4392,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
/**
|
/**
|
||||||
check comment length of table, column, index and partition
|
check comment length of table, column, index and partition
|
||||||
|
|
||||||
If comment lenght is more than the standard length
|
If comment length is more than the standard length
|
||||||
truncate it and store the comment lenght upto the standard
|
truncate it and store the comment length upto the standard
|
||||||
comment length size
|
comment length size
|
||||||
|
|
||||||
@param thd Thread handle
|
@param thd Thread handle
|
||||||
@ -9467,9 +9467,40 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
|||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
TABLE_LIST *table_list,
|
TABLE_LIST *table_list,
|
||||||
Alter_info *alter_info,
|
Alter_info *alter_info,
|
||||||
uint order_num, ORDER *order, bool ignore)
|
uint order_num, ORDER *order, bool ignore,
|
||||||
|
bool if_exists)
|
||||||
{
|
{
|
||||||
bool engine_changed;
|
bool engine_changed, error;
|
||||||
|
bool no_ha_table= true; /* We have not created table in storage engine yet */
|
||||||
|
TABLE *table, *new_table;
|
||||||
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
|
bool partition_changed= false;
|
||||||
|
bool fast_alter_partition= false;
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
Create .FRM for new version of table with a temporary name.
|
||||||
|
We don't log the statement, it will be logged later.
|
||||||
|
|
||||||
|
Keep information about keys in newly created table as it
|
||||||
|
will be used later to construct Alter_inplace_info object
|
||||||
|
and by fill_alter_inplace_info() call.
|
||||||
|
*/
|
||||||
|
KEY *key_info;
|
||||||
|
uint key_count;
|
||||||
|
/*
|
||||||
|
Remember if the new definition has new VARCHAR column;
|
||||||
|
create_info->varchar will be reset in create_table_impl()/
|
||||||
|
mysql_prepare_create_table().
|
||||||
|
*/
|
||||||
|
bool varchar= create_info->varchar, table_creation_was_logged= 0;
|
||||||
|
uint tables_opened;
|
||||||
|
handlerton *new_db_type, *old_db_type;
|
||||||
|
ha_rows copied=0, deleted=0;
|
||||||
|
LEX_CUSTRING frm= {0,0};
|
||||||
|
char index_file[FN_REFLEN], data_file[FN_REFLEN];
|
||||||
|
MDL_request target_mdl_request;
|
||||||
|
MDL_ticket *mdl_ticket= 0;
|
||||||
|
Alter_table_prelocking_strategy alter_prelocking_strategy;
|
||||||
DBUG_ENTER("mysql_alter_table");
|
DBUG_ENTER("mysql_alter_table");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -9517,17 +9548,38 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
|||||||
*/
|
*/
|
||||||
table_list->required_type= TABLE_TYPE_NORMAL;
|
table_list->required_type= TABLE_TYPE_NORMAL;
|
||||||
|
|
||||||
Alter_table_prelocking_strategy alter_prelocking_strategy;
|
|
||||||
|
|
||||||
DEBUG_SYNC(thd, "alter_table_before_open_tables");
|
DEBUG_SYNC(thd, "alter_table_before_open_tables");
|
||||||
uint tables_opened;
|
|
||||||
|
|
||||||
thd->open_options|= HA_OPEN_FOR_ALTER;
|
thd->open_options|= HA_OPEN_FOR_ALTER;
|
||||||
thd->mdl_backup_ticket= 0;
|
thd->mdl_backup_ticket= 0;
|
||||||
bool error= open_tables(thd, &table_list, &tables_opened, 0,
|
error= open_tables(thd, &table_list, &tables_opened, 0,
|
||||||
&alter_prelocking_strategy);
|
&alter_prelocking_strategy);
|
||||||
thd->open_options&= ~HA_OPEN_FOR_ALTER;
|
thd->open_options&= ~HA_OPEN_FOR_ALTER;
|
||||||
|
|
||||||
|
if (unlikely(error))
|
||||||
|
{
|
||||||
|
if (if_exists)
|
||||||
|
{
|
||||||
|
int tmp_errno= thd->get_stmt_da()->sql_errno();
|
||||||
|
if (tmp_errno == ER_NO_SUCH_TABLE)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
ALTER TABLE IF EXISTS was used on not existing table
|
||||||
|
We have to log the query on a slave as the table may be a shared one
|
||||||
|
from the master and we need to ensure that the next slave can see
|
||||||
|
the statement as this slave may not have the table shared
|
||||||
|
*/
|
||||||
|
thd->clear_error();
|
||||||
|
if (thd->slave_thread &&
|
||||||
|
write_bin_log(thd, true, thd->query(), thd->query_length()))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
my_ok(thd);
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
if (WSREP(thd) &&
|
if (WSREP(thd) &&
|
||||||
(thd->lex->sql_command == SQLCOM_ALTER_TABLE ||
|
(thd->lex->sql_command == SQLCOM_ALTER_TABLE ||
|
||||||
@ -9539,10 +9591,8 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
|||||||
|
|
||||||
DEBUG_SYNC(thd, "alter_table_after_open_tables");
|
DEBUG_SYNC(thd, "alter_table_after_open_tables");
|
||||||
|
|
||||||
TABLE *table= table_list->table;
|
table= table_list->table;
|
||||||
bool versioned= table && table->versioned();
|
if (table->versioned())
|
||||||
|
|
||||||
if (versioned)
|
|
||||||
{
|
{
|
||||||
if (handlerton *hton1= create_info->db_type)
|
if (handlerton *hton1= create_info->db_type)
|
||||||
{
|
{
|
||||||
@ -9577,11 +9627,12 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
|||||||
};);
|
};);
|
||||||
#endif // WITH_WSREP
|
#endif // WITH_WSREP
|
||||||
|
|
||||||
if (unlikely(error))
|
Alter_table_ctx alter_ctx(thd, table_list, tables_opened, new_db, new_name);
|
||||||
DBUG_RETURN(true);
|
mdl_ticket= table->mdl_ticket;
|
||||||
|
|
||||||
|
table_creation_was_logged= table->s->table_creation_was_logged;
|
||||||
|
|
||||||
table->use_all_columns();
|
table->use_all_columns();
|
||||||
MDL_ticket *mdl_ticket= table->mdl_ticket;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Prohibit changing of the UNION list of a non-temporary MERGE table
|
Prohibit changing of the UNION list of a non-temporary MERGE table
|
||||||
@ -9598,10 +9649,6 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
|||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Alter_table_ctx alter_ctx(thd, table_list, tables_opened, new_db, new_name);
|
|
||||||
|
|
||||||
MDL_request target_mdl_request;
|
|
||||||
|
|
||||||
/* Check that we are not trying to rename to an existing table */
|
/* Check that we are not trying to rename to an existing table */
|
||||||
if (alter_ctx.is_table_renamed())
|
if (alter_ctx.is_table_renamed())
|
||||||
{
|
{
|
||||||
@ -9833,8 +9880,7 @@ do_continue:;
|
|||||||
my_ok(thd, 0L, 0L, alter_ctx.tmp_buff);
|
my_ok(thd, 0L, 0L, alter_ctx.tmp_buff);
|
||||||
|
|
||||||
/* We don't replicate alter table statement on temporary tables */
|
/* We don't replicate alter table statement on temporary tables */
|
||||||
if (table->s->tmp_table == NO_TMP_TABLE ||
|
if (table_creation_was_logged)
|
||||||
!thd->is_current_stmt_binlog_format_row())
|
|
||||||
{
|
{
|
||||||
if (write_bin_log(thd, true, thd->query(), thd->query_length()))
|
if (write_bin_log(thd, true, thd->query(), thd->query_length()))
|
||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
@ -9880,8 +9926,6 @@ do_continue:;
|
|||||||
/* We have to do full alter table. */
|
/* We have to do full alter table. */
|
||||||
|
|
||||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
bool partition_changed= false;
|
|
||||||
bool fast_alter_partition= false;
|
|
||||||
{
|
{
|
||||||
if (prep_alter_part_table(thd, table, alter_info, create_info,
|
if (prep_alter_part_table(thd, table, alter_info, create_info,
|
||||||
&partition_changed, &fast_alter_partition))
|
&partition_changed, &fast_alter_partition))
|
||||||
@ -10000,10 +10044,9 @@ do_continue:;
|
|||||||
It's therefore important that the assignment below is done
|
It's therefore important that the assignment below is done
|
||||||
after prep_alter_part_table.
|
after prep_alter_part_table.
|
||||||
*/
|
*/
|
||||||
handlerton *new_db_type= create_info->db_type;
|
new_db_type= create_info->db_type;
|
||||||
handlerton *old_db_type= table->s->db_type();
|
old_db_type= table->s->db_type();
|
||||||
TABLE *new_table= NULL;
|
new_table= NULL;
|
||||||
ha_rows copied=0,deleted=0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Handling of symlinked tables:
|
Handling of symlinked tables:
|
||||||
@ -10029,8 +10072,6 @@ do_continue:;
|
|||||||
Copy data.
|
Copy data.
|
||||||
Remove old table and symlinks.
|
Remove old table and symlinks.
|
||||||
*/
|
*/
|
||||||
char index_file[FN_REFLEN], data_file[FN_REFLEN];
|
|
||||||
|
|
||||||
if (!alter_ctx.is_database_changed())
|
if (!alter_ctx.is_database_changed())
|
||||||
{
|
{
|
||||||
if (create_info->index_file_name)
|
if (create_info->index_file_name)
|
||||||
@ -10058,24 +10099,6 @@ do_continue:;
|
|||||||
|
|
||||||
DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock");
|
DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock");
|
||||||
|
|
||||||
/*
|
|
||||||
Create .FRM for new version of table with a temporary name.
|
|
||||||
We don't log the statement, it will be logged later.
|
|
||||||
|
|
||||||
Keep information about keys in newly created table as it
|
|
||||||
will be used later to construct Alter_inplace_info object
|
|
||||||
and by fill_alter_inplace_info() call.
|
|
||||||
*/
|
|
||||||
KEY *key_info;
|
|
||||||
uint key_count;
|
|
||||||
/*
|
|
||||||
Remember if the new definition has new VARCHAR column;
|
|
||||||
create_info->varchar will be reset in create_table_impl()/
|
|
||||||
mysql_prepare_create_table().
|
|
||||||
*/
|
|
||||||
bool varchar= create_info->varchar;
|
|
||||||
LEX_CUSTRING frm= {0,0};
|
|
||||||
|
|
||||||
tmp_disable_binlog(thd);
|
tmp_disable_binlog(thd);
|
||||||
create_info->options|=HA_CREATE_TMP_ALTER;
|
create_info->options|=HA_CREATE_TMP_ALTER;
|
||||||
error= create_table_impl(thd, alter_ctx.db, alter_ctx.table_name,
|
error= create_table_impl(thd, alter_ctx.db, alter_ctx.table_name,
|
||||||
@ -10091,9 +10114,6 @@ do_continue:;
|
|||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remember that we have not created table in storage engine yet. */
|
|
||||||
bool no_ha_table= true;
|
|
||||||
|
|
||||||
if (alter_info->requested_algorithm != Alter_info::ALTER_TABLE_ALGORITHM_COPY)
|
if (alter_info->requested_algorithm != Alter_info::ALTER_TABLE_ALGORITHM_COPY)
|
||||||
{
|
{
|
||||||
Alter_inplace_info ha_alter_info(create_info, alter_info,
|
Alter_inplace_info ha_alter_info(create_info, alter_info,
|
||||||
@ -10313,9 +10333,7 @@ do_continue:;
|
|||||||
order_num, order, &copied, &deleted,
|
order_num, order, &copied, &deleted,
|
||||||
alter_info->keys_onoff,
|
alter_info->keys_onoff,
|
||||||
&alter_ctx))
|
&alter_ctx))
|
||||||
{
|
|
||||||
goto err_new_table_cleanup;
|
goto err_new_table_cleanup;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -11088,8 +11106,8 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy)
|
|||||||
alter_info.requested_algorithm= Alter_info::ALTER_TABLE_ALGORITHM_COPY;
|
alter_info.requested_algorithm= Alter_info::ALTER_TABLE_ALGORITHM_COPY;
|
||||||
|
|
||||||
bool res= mysql_alter_table(thd, &null_clex_str, &null_clex_str, &create_info,
|
bool res= mysql_alter_table(thd, &null_clex_str, &null_clex_str, &create_info,
|
||||||
table_list, &alter_info, 0,
|
table_list, &alter_info, 0,
|
||||||
(ORDER *) 0, 0);
|
(ORDER *) 0, 0, 0);
|
||||||
table_list->next_global= next_table;
|
table_list->next_global= next_table;
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
@ -11241,6 +11259,7 @@ err:
|
|||||||
@retval true Engine not available/supported, error has been reported.
|
@retval true Engine not available/supported, error has been reported.
|
||||||
@retval false Engine available/supported.
|
@retval false Engine available/supported.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool check_engine(THD *thd, const char *db_name,
|
bool check_engine(THD *thd, const char *db_name,
|
||||||
const char *table_name, HA_CREATE_INFO *create_info)
|
const char *table_name, HA_CREATE_INFO *create_info)
|
||||||
{
|
{
|
||||||
|
@ -217,11 +217,13 @@ bool mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
Alter_table_ctx *alter_ctx);
|
Alter_table_ctx *alter_ctx);
|
||||||
bool mysql_trans_prepare_alter_copy_data(THD *thd);
|
bool mysql_trans_prepare_alter_copy_data(THD *thd);
|
||||||
bool mysql_trans_commit_alter_copy_data(THD *thd);
|
bool mysql_trans_commit_alter_copy_data(THD *thd);
|
||||||
bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, const LEX_CSTRING *new_name,
|
bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
||||||
|
const LEX_CSTRING *new_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
TABLE_LIST *table_list,
|
TABLE_LIST *table_list,
|
||||||
Alter_info *alter_info,
|
Alter_info *alter_info,
|
||||||
uint order_num, ORDER *order, bool ignore);
|
uint order_num, ORDER *order, bool ignore,
|
||||||
|
bool if_exists);
|
||||||
bool mysql_compare_tables(TABLE *table,
|
bool mysql_compare_tables(TABLE *table,
|
||||||
Alter_info *alter_info,
|
Alter_info *alter_info,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
@ -244,7 +246,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists,
|
|||||||
int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||||
bool drop_temporary, bool drop_view,
|
bool drop_temporary, bool drop_view,
|
||||||
bool drop_sequence,
|
bool drop_sequence,
|
||||||
bool log_query, bool dont_free_locks);
|
bool dont_log_query, bool dont_free_locks);
|
||||||
bool log_drop_table(THD *thd, const LEX_CSTRING *db_name,
|
bool log_drop_table(THD *thd, const LEX_CSTRING *db_name,
|
||||||
const LEX_CSTRING *table_name, bool temporary_table);
|
const LEX_CSTRING *table_name, bool temporary_table);
|
||||||
bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db,
|
bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db,
|
||||||
|
@ -7098,10 +7098,11 @@ alter:
|
|||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
DBUG_ASSERT(!Lex->m_sql_cmd);
|
DBUG_ASSERT(!Lex->m_sql_cmd);
|
||||||
}
|
}
|
||||||
alter_options TABLE_SYM table_ident opt_lock_wait_timeout
|
alter_options TABLE_SYM opt_if_exists table_ident opt_lock_wait_timeout
|
||||||
{
|
{
|
||||||
|
Lex->create_info.set($5);
|
||||||
if (!Lex->first_select_lex()->
|
if (!Lex->first_select_lex()->
|
||||||
add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING,
|
add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING,
|
||||||
TL_READ_NO_INSERT, MDL_SHARED_UPGRADABLE))
|
TL_READ_NO_INSERT, MDL_SHARED_UPGRADABLE))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->first_select_lex()->db=
|
Lex->first_select_lex()->db=
|
||||||
@ -8298,9 +8299,10 @@ opt_no_write_to_binlog:
|
|||||||
;
|
;
|
||||||
|
|
||||||
rename:
|
rename:
|
||||||
RENAME table_or_tables
|
RENAME table_or_tables opt_if_exists
|
||||||
{
|
{
|
||||||
Lex->sql_command= SQLCOM_RENAME_TABLE;
|
Lex->sql_command= SQLCOM_RENAME_TABLE;
|
||||||
|
Lex->create_info.set($3);
|
||||||
if (Lex->main_select_push())
|
if (Lex->main_select_push())
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user