MDEV-7112 Split HA_CREATE_INFO

This commit is contained in:
Alexander Barkov 2014-12-08 10:56:08 +04:00
parent b372720177
commit c6d3f8058d
23 changed files with 491 additions and 219 deletions

View File

@ -376,10 +376,8 @@ enum enum_alter_inplace_result {
#define HA_KEY_BLOB_LENGTH 2 #define HA_KEY_BLOB_LENGTH 2
#define HA_LEX_CREATE_TMP_TABLE 1 #define HA_LEX_CREATE_TMP_TABLE 1
#define HA_LEX_CREATE_IF_NOT_EXISTS 2
#define HA_LEX_CREATE_TABLE_LIKE 4
#define HA_CREATE_TMP_ALTER 8 #define HA_CREATE_TMP_ALTER 8
#define HA_LEX_CREATE_REPLACE 16
#define HA_MAX_REC_LENGTH 65535 #define HA_MAX_REC_LENGTH 65535
/* Table caching type */ /* Table caching type */
@ -1580,9 +1578,41 @@ enum enum_stats_auto_recalc { HA_STATS_AUTO_RECALC_DEFAULT= 0,
HA_STATS_AUTO_RECALC_ON, HA_STATS_AUTO_RECALC_ON,
HA_STATS_AUTO_RECALC_OFF }; HA_STATS_AUTO_RECALC_OFF };
struct HA_CREATE_INFO /**
A helper struct for schema DDL statements:
CREATE SCHEMA [IF NOT EXISTS] name [ schema_specification... ]
ALTER SCHEMA name [ schema_specification... ]
It stores the "schema_specification" part of the CREATE/ALTER statements and
is passed to mysql_create_db() and mysql_alter_db().
Currently consists only of the schema default character set and collation.
*/
struct Schema_specification_st
{ {
CHARSET_INFO *table_charset, *default_table_charset; CHARSET_INFO *default_table_charset;
void init()
{
bzero(this, sizeof(*this));
}
};
/**
A helper struct for table DDL statements, e.g.:
CREATE [OR REPLACE] [TEMPORARY]
TABLE [IF NOT EXISTS] tbl_name table_contents_source;
Represents a combinations of:
1. The scope, i.e. TEMPORARY or not TEMPORARY
2. The "table_contents_source" part of the table DDL statements,
which can be initialized from either of these:
- table_element_list ... // Explicit definition (column and key list)
- LIKE another_table_name ... // Copy structure from another table
- [AS] SELECT ... // Copy structure from a subquery
*/
struct Table_scope_and_contents_source_st
{
CHARSET_INFO *table_charset;
LEX_CUSTRING tabledef_version; LEX_CUSTRING tabledef_version;
LEX_STRING connect_string; LEX_STRING connect_string;
const char *password, *tablespace; const char *password, *tablespace;
@ -1602,7 +1632,6 @@ struct HA_CREATE_INFO
uint stats_sample_pages; uint stats_sample_pages;
uint null_bits; /* NULL bits at start of record */ uint null_bits; /* NULL bits at start of record */
uint options; /* OR of HA_CREATE_ options */ uint options; /* OR of HA_CREATE_ options */
uint org_options; /* original options from query */
uint merge_insert_method; uint merge_insert_method;
uint extra_size; /* length of extra data segment */ uint extra_size; /* length of extra data segment */
SQL_I_List<TABLE_LIST> merge_list; SQL_I_List<TABLE_LIST> merge_list;
@ -1635,7 +1664,11 @@ struct HA_CREATE_INFO
MDL_ticket *mdl_ticket; MDL_ticket *mdl_ticket;
bool table_was_deleted; bool table_was_deleted;
bool tmp_table() { return options & HA_LEX_CREATE_TMP_TABLE; } void init()
{
bzero(this, sizeof(*this));
}
bool tmp_table() const { return options & HA_LEX_CREATE_TMP_TABLE; }
void use_default_db_type(THD *thd) void use_default_db_type(THD *thd)
{ {
db_type= tmp_table() ? ha_default_tmp_handlerton(thd) db_type= tmp_table() ? ha_default_tmp_handlerton(thd)
@ -1644,6 +1677,54 @@ struct HA_CREATE_INFO
}; };
/**
This struct is passed to handler table routines, e.g. ha_create().
It does not include the "OR REPLACE" and "IF NOT EXISTS" parts, as these
parts are handled on the SQL level and are not needed on the handler level.
*/
struct HA_CREATE_INFO: public Table_scope_and_contents_source_st,
public Schema_specification_st
{
void init()
{
Table_scope_and_contents_source_st::init();
Schema_specification_st::init();
}
};
/**
This struct is passed to mysql_create_table() and similar creation functions,
as well as to show_create_table().
*/
struct Table_specification_st: public HA_CREATE_INFO,
public DDL_options_st
{
// Deep initialization
void init()
{
HA_CREATE_INFO::init();
DDL_options_st::init();
}
void init(DDL_options_st::Options options)
{
HA_CREATE_INFO::init();
DDL_options_st::init(options);
}
/*
Quick initialization, for parser.
Most of the HA_CREATE_INFO is left uninitialized.
It gets fully initialized in sql_yacc.yy, only when the parser
scans a related keyword (e.g. CREATE, ALTER).
*/
void lex_start()
{
HA_CREATE_INFO::options= 0;
DDL_options_st::init();
}
};
/** /**
In-place alter handler context. In-place alter handler context.

View File

@ -3188,13 +3188,13 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
switch (lex->sql_command) switch (lex->sql_command)
{ {
case SQLCOM_DROP_TABLE: case SQLCOM_DROP_TABLE:
use_cache= (lex->drop_temporary && thd->in_multi_stmt_transaction_mode()); use_cache= (lex->tmp_table() && thd->in_multi_stmt_transaction_mode());
break; break;
case SQLCOM_CREATE_TABLE: case SQLCOM_CREATE_TABLE:
trx_cache= (lex->select_lex.item_list.elements && trx_cache= (lex->select_lex.item_list.elements &&
thd->is_current_stmt_binlog_format_row()); thd->is_current_stmt_binlog_format_row());
use_cache= (lex->create_info.tmp_table() && use_cache= (lex->tmp_table() &&
thd->in_multi_stmt_transaction_mode()) || trx_cache; thd->in_multi_stmt_transaction_mode()) || trx_cache;
break; break;
case SQLCOM_SET_OPTION: case SQLCOM_SET_OPTION:
@ -4335,7 +4335,8 @@ compare_errors:
has already been dropped. To ignore such irrelevant "table does has already been dropped. To ignore such irrelevant "table does
not exist errors", we silently clear the error if TEMPORARY was used. not exist errors", we silently clear the error if TEMPORARY was used.
*/ */
if (thd->lex->sql_command == SQLCOM_DROP_TABLE && thd->lex->drop_temporary && if (thd->lex->sql_command == SQLCOM_DROP_TABLE &&
thd->lex->tmp_table() &&
thd->is_error() && thd->get_stmt_da()->sql_errno() == ER_BAD_TABLE_ERROR && thd->is_error() && thd->get_stmt_da()->sql_errno() == ER_BAD_TABLE_ERROR &&
!expected_error) !expected_error)
thd->get_stmt_da()->reset_diagnostics_area(); thd->get_stmt_da()->reset_diagnostics_area();

View File

@ -281,13 +281,13 @@ sp_get_flags_for_command(LEX *lex)
flags= sp_head::CONTAINS_DYNAMIC_SQL; flags= sp_head::CONTAINS_DYNAMIC_SQL;
break; break;
case SQLCOM_CREATE_TABLE: case SQLCOM_CREATE_TABLE:
if (lex->create_info.tmp_table()) if (lex->tmp_table())
flags= 0; flags= 0;
else else
flags= sp_head::HAS_COMMIT_OR_ROLLBACK; flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
break; break;
case SQLCOM_DROP_TABLE: case SQLCOM_DROP_TABLE:
if (lex->drop_temporary) if (lex->tmp_table())
flags= 0; flags= 0;
else else
flags= sp_head::HAS_COMMIT_OR_ROLLBACK; flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
@ -4000,7 +4000,7 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
SP_TABLE *tab; SP_TABLE *tab;
if (lex_for_tmp_check->sql_command == SQLCOM_DROP_TABLE && if (lex_for_tmp_check->sql_command == SQLCOM_DROP_TABLE &&
lex_for_tmp_check->drop_temporary) lex_for_tmp_check->tmp_table())
return TRUE; return TRUE;
for (uint i= 0 ; i < m_sptabs.records ; i++) for (uint i= 0 ; i < m_sptabs.records ; i++)
@ -4065,7 +4065,7 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
return FALSE; return FALSE;
if (lex_for_tmp_check->sql_command == SQLCOM_CREATE_TABLE && if (lex_for_tmp_check->sql_command == SQLCOM_CREATE_TABLE &&
lex_for_tmp_check->query_tables == table && lex_for_tmp_check->query_tables == table &&
lex_for_tmp_check->create_info.tmp_table()) lex_for_tmp_check->tmp_table())
{ {
tab->temp= TRUE; tab->temp= TRUE;
tab->qname.length= temp_table_key_length; tab->qname.length= temp_table_key_length;

View File

@ -3453,7 +3453,8 @@ Open_table_context::recover_from_failed_open()
break; break;
case OT_DISCOVER: case OT_DISCOVER:
{ {
if ((result= lock_table_names(m_thd, m_failed_table, NULL, if ((result= lock_table_names(m_thd, m_thd->lex->create_info,
m_failed_table, NULL,
get_timeout(), 0))) get_timeout(), 0)))
break; break;
@ -3484,7 +3485,8 @@ Open_table_context::recover_from_failed_open()
} }
case OT_REPAIR: case OT_REPAIR:
{ {
if ((result= lock_table_names(m_thd, m_failed_table, NULL, if ((result= lock_table_names(m_thd, m_thd->lex->create_info,
m_failed_table, NULL,
get_timeout(), 0))) get_timeout(), 0)))
break; break;
@ -4132,7 +4134,7 @@ extern "C" uchar *schema_set_get_key(const TABLE_LIST *table, size_t *length,
*/ */
bool bool
lock_table_names(THD *thd, lock_table_names(THD *thd, const DDL_options_st &options,
TABLE_LIST *tables_start, TABLE_LIST *tables_end, TABLE_LIST *tables_start, TABLE_LIST *tables_end,
ulong lock_wait_timeout, uint flags) ulong lock_wait_timeout, uint flags)
{ {
@ -4176,8 +4178,8 @@ lock_table_names(THD *thd,
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
/* Check if CREATE TABLE without REPLACE was used */ /* Check if CREATE TABLE without REPLACE was used */
create_table= (thd->lex->sql_command == SQLCOM_CREATE_TABLE && create_table= thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
!(thd->lex->create_info.options & HA_LEX_CREATE_REPLACE)); !options.or_replace();
if (!(flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK)) if (!(flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK))
{ {
@ -4231,7 +4233,7 @@ lock_table_names(THD *thd,
*/ */
if (ha_table_exists(thd, tables_start->db, tables_start->table_name)) if (ha_table_exists(thd, tables_start->db, tables_start->table_name))
{ {
if (thd->lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS) if (options.if_not_exists())
{ {
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
@ -4344,7 +4346,8 @@ open_tables_check_upgradable_mdl(THD *thd, TABLE_LIST *tables_start,
@retval TRUE Error, reported. @retval TRUE Error, reported.
*/ */
bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags, bool open_tables(THD *thd, const DDL_options_st &options,
TABLE_LIST **start, uint *counter, uint flags,
Prelocking_strategy *prelocking_strategy) Prelocking_strategy *prelocking_strategy)
{ {
/* /*
@ -4434,7 +4437,8 @@ restart:
else else
{ {
TABLE_LIST *table; TABLE_LIST *table;
if (lock_table_names(thd, *start, thd->lex->first_not_own_table(), if (lock_table_names(thd, options, *start,
thd->lex->first_not_own_table(),
ot_ctx.get_timeout(), flags)) ot_ctx.get_timeout(), flags))
{ {
error= TRUE; error= TRUE;
@ -5117,7 +5121,8 @@ end:
@retval TRUE Error @retval TRUE Error
*/ */
bool open_and_lock_tables(THD *thd, TABLE_LIST *tables, bool open_and_lock_tables(THD *thd, const DDL_options_st &options,
TABLE_LIST *tables,
bool derived, uint flags, bool derived, uint flags,
Prelocking_strategy *prelocking_strategy) Prelocking_strategy *prelocking_strategy)
{ {
@ -5126,7 +5131,7 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
DBUG_ENTER("open_and_lock_tables"); DBUG_ENTER("open_and_lock_tables");
DBUG_PRINT("enter", ("derived handling: %d", derived)); DBUG_PRINT("enter", ("derived handling: %d", derived));
if (open_tables(thd, &tables, &counter, flags, prelocking_strategy)) if (open_tables(thd, options, &tables, &counter, flags, prelocking_strategy))
goto err; goto err;
DBUG_EXECUTE_IF("sleep_open_and_lock_after_open", { DBUG_EXECUTE_IF("sleep_open_and_lock_after_open", {

View File

@ -226,15 +226,41 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
void wrap_ident(THD *thd, Item **conds); void wrap_ident(THD *thd, Item **conds);
int setup_ftfuncs(SELECT_LEX* select); int setup_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
bool lock_table_names(THD *thd, TABLE_LIST *table_list, bool lock_table_names(THD *thd, const DDL_options_st &options,
TABLE_LIST *table_list,
TABLE_LIST *table_list_end, ulong lock_wait_timeout, TABLE_LIST *table_list_end, ulong lock_wait_timeout,
uint flags); uint flags);
bool open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags, static inline bool
lock_table_names(THD *thd, TABLE_LIST *table_list,
TABLE_LIST *table_list_end, ulong lock_wait_timeout,
uint flags)
{
return lock_table_names(thd, thd->lex->create_info, table_list,
table_list_end, lock_wait_timeout, flags);
}
bool open_tables(THD *thd, const DDL_options_st &options,
TABLE_LIST **tables, uint *counter, uint flags,
Prelocking_strategy *prelocking_strategy); Prelocking_strategy *prelocking_strategy);
static inline bool
open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags,
Prelocking_strategy *prelocking_strategy)
{
return open_tables(thd, thd->lex->create_info, tables, counter, flags,
prelocking_strategy);
}
/* open_and_lock_tables with optional derived handling */ /* open_and_lock_tables with optional derived handling */
bool open_and_lock_tables(THD *thd, TABLE_LIST *tables, bool open_and_lock_tables(THD *thd, const DDL_options_st &options,
TABLE_LIST *tables,
bool derived, uint flags, bool derived, uint flags,
Prelocking_strategy *prelocking_strategy); Prelocking_strategy *prelocking_strategy);
static inline bool
open_and_lock_tables(THD *thd, TABLE_LIST *tables,
bool derived, uint flags,
Prelocking_strategy *prelocking_strategy)
{
return open_and_lock_tables(thd, thd->lex->create_info,
tables, derived, flags, prelocking_strategy);
}
/* simple open_and_lock_tables without derived handling for single table */ /* simple open_and_lock_tables without derived handling for single table */
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l, TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
thr_lock_type lock_type, uint flags, thr_lock_type lock_type, uint flags,
@ -459,12 +485,22 @@ public:
}; };
inline bool
open_tables(THD *thd, const DDL_options_st &options,
TABLE_LIST **tables, uint *counter, uint flags)
{
DML_prelocking_strategy prelocking_strategy;
return open_tables(thd, options, tables, counter, flags,
&prelocking_strategy);
}
inline bool inline bool
open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags) open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags)
{ {
DML_prelocking_strategy prelocking_strategy; DML_prelocking_strategy prelocking_strategy;
return open_tables(thd, tables, counter, flags, &prelocking_strategy); return open_tables(thd, thd->lex->create_info, tables, counter, flags,
&prelocking_strategy);
} }
inline TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l, inline TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
@ -478,12 +514,23 @@ inline TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
/* open_and_lock_tables with derived handling */ /* open_and_lock_tables with derived handling */
inline bool open_and_lock_tables(THD *thd,
const DDL_options_st &options,
TABLE_LIST *tables,
bool derived, uint flags)
{
DML_prelocking_strategy prelocking_strategy;
return open_and_lock_tables(thd, options, tables, derived, flags,
&prelocking_strategy);
}
inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables, inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
bool derived, uint flags) bool derived, uint flags)
{ {
DML_prelocking_strategy prelocking_strategy; DML_prelocking_strategy prelocking_strategy;
return open_and_lock_tables(thd, tables, derived, flags, return open_and_lock_tables(thd, thd->lex->create_info,
tables, derived, flags,
&prelocking_strategy); &prelocking_strategy);
} }

View File

@ -5464,8 +5464,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
flags_access_some_set |= flags; flags_access_some_set |= flags;
if (lex->sql_command != SQLCOM_CREATE_TABLE || if (lex->sql_command != SQLCOM_CREATE_TABLE ||
(lex->sql_command == SQLCOM_CREATE_TABLE && (lex->sql_command == SQLCOM_CREATE_TABLE && lex->tmp_table()))
lex->create_info.tmp_table()))
{ {
my_bool trans= table->table->file->has_transactions(); my_bool trans= table->table->file->has_transactions();

View File

@ -4218,7 +4218,7 @@ class select_insert :public select_result_interceptor {
class select_create: public select_insert { class select_create: public select_insert {
ORDER *group; ORDER *group;
TABLE_LIST *create_table; TABLE_LIST *create_table;
HA_CREATE_INFO *create_info; Table_specification_st *create_info;
TABLE_LIST *select_tables; TABLE_LIST *select_tables;
Alter_info *alter_info; Alter_info *alter_info;
Field **field; Field **field;
@ -4230,7 +4230,7 @@ class select_create: public select_insert {
public: public:
select_create (TABLE_LIST *table_arg, select_create (TABLE_LIST *table_arg,
HA_CREATE_INFO *create_info_par, Table_specification_st *create_info_par,
Alter_info *alter_info_arg, Alter_info *alter_info_arg,
List<Item> &select_fields,enum_duplicates duplic, bool ignore, List<Item> &select_fields,enum_duplicates duplic, bool ignore,
TABLE_LIST *select_tables_arg) TABLE_LIST *select_tables_arg)

View File

@ -233,7 +233,7 @@ void my_dbopt_cleanup(void)
1 on error. 1 on error.
*/ */
static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create) static my_bool get_dbopt(const char *dbname, Schema_specification_st *create)
{ {
my_dbopt_t *opt; my_dbopt_t *opt;
uint length; uint length;
@ -264,7 +264,7 @@ static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
1 on error. 1 on error.
*/ */
static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create) static my_bool put_dbopt(const char *dbname, Schema_specification_st *create)
{ {
my_dbopt_t *opt; my_dbopt_t *opt;
uint length; uint length;
@ -333,7 +333,8 @@ static void del_dbopt(const char *path)
1 Could not create file or write to it. Error sent through my_error() 1 Could not create file or write to it. Error sent through my_error()
*/ */
static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) static bool write_db_opt(THD *thd, const char *path,
Schema_specification_st *create)
{ {
register File file; register File file;
char buf[256]; // Should be enough for one option char buf[256]; // Should be enough for one option
@ -379,7 +380,7 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
*/ */
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) bool load_db_opt(THD *thd, const char *path, Schema_specification_st *create)
{ {
File file; File file;
char buf[256]; char buf[256];
@ -491,7 +492,7 @@ err1:
*/ */
bool load_db_opt_by_name(THD *thd, const char *db_name, bool load_db_opt_by_name(THD *thd, const char *db_name,
HA_CREATE_INFO *db_create_info) Schema_specification_st *db_create_info)
{ {
char db_opt_path[FN_REFLEN + 1]; char db_opt_path[FN_REFLEN + 1];
@ -518,7 +519,7 @@ bool load_db_opt_by_name(THD *thd, const char *db_name,
CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name) CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
{ {
HA_CREATE_INFO db_info; Schema_specification_st db_info;
if (thd->db != NULL && strcmp(db_name, thd->db) == 0) if (thd->db != NULL && strcmp(db_name, thd->db) == 0)
return thd->db_charset; return thd->db_charset;
@ -545,6 +546,7 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
thd Thread handler thd Thread handler
db Name of database to create db Name of database to create
Function assumes that this is already validated. Function assumes that this is already validated.
options DDL options, e.g. IF NOT EXISTS
create_info Database create options (like character set) create_info Database create options (like character set)
silent Used by replication when internally creating a database. silent Used by replication when internally creating a database.
In this case the entry should not be logged. In this case the entry should not be logged.
@ -561,14 +563,15 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
*/ */
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, int mysql_create_db(THD *thd, char *db,
const DDL_options_st &options,
Schema_specification_st *create_info,
bool silent) bool silent)
{ {
char path[FN_REFLEN+16]; char path[FN_REFLEN+16];
long result= 1; long result= 1;
int error= 0; int error= 0;
MY_STAT stat_info; MY_STAT stat_info;
uint create_options= create_info ? create_info->options : 0;
uint path_len; uint path_len;
DBUG_ENTER("mysql_create_db"); DBUG_ENTER("mysql_create_db");
@ -598,7 +601,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
if (mysql_file_stat(key_file_misc, path, &stat_info, MYF(0))) if (mysql_file_stat(key_file_misc, path, &stat_info, MYF(0)))
{ {
if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS)) if (!options.if_not_exists())
{ {
my_error(ER_DB_CREATE_EXISTS, MYF(0), db); my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
error= -1; error= -1;
@ -702,7 +705,8 @@ exit:
/* db-name is already validated when we come here */ /* db-name is already validated when we come here */
bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) bool mysql_alter_db(THD *thd, const char *db,
Schema_specification_st *create_info)
{ {
char path[FN_REFLEN+16]; char path[FN_REFLEN+16];
long result=1; long result=1;
@ -1602,7 +1606,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
int error= 0, change_to_newdb= 0; int error= 0, change_to_newdb= 0;
char path[FN_REFLEN+16]; char path[FN_REFLEN+16];
uint length; uint length;
HA_CREATE_INFO create_info; Schema_specification_st create_info;
MY_DIR *dirp; MY_DIR *dirp;
TABLE_LIST *table_list; TABLE_LIST *table_list;
SELECT_LEX *sl= thd->lex->current_select; SELECT_LEX *sl= thd->lex->current_select;
@ -1650,7 +1654,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
} }
/* Step1: Create the new database */ /* Step1: Create the new database */
if ((error= mysql_create_db(thd, new_db.str, &create_info, 1))) if ((error= mysql_create_db(thd, new_db.str, DDL_options(), &create_info, 1)))
goto exit; goto exit;
/* Step2: Move tables to the new database */ /* Step2: Move tables to the new database */

View File

@ -20,8 +20,11 @@
class THD; class THD;
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); int mysql_create_db(THD *thd, char *db,
bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create); const DDL_options_st &options,
Schema_specification_st *create, bool silent);
bool mysql_alter_db(THD *thd, const char *db,
Schema_specification_st *create);
bool mysql_rm_db(THD *thd, char *db, bool if_exists, bool silent); bool mysql_rm_db(THD *thd, char *db, bool if_exists, bool silent);
bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db); bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db);
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
@ -35,9 +38,9 @@ bool mysql_opt_change_db(THD *thd,
bool my_dboptions_cache_init(void); bool my_dboptions_cache_init(void);
void my_dboptions_cache_free(void); void my_dboptions_cache_free(void);
bool check_db_dir_existence(const char *db_name); bool check_db_dir_existence(const char *db_name);
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create); bool load_db_opt(THD *thd, const char *path, Schema_specification_st *create);
bool load_db_opt_by_name(THD *thd, const char *db_name, bool load_db_opt_by_name(THD *thd, const char *db_name,
HA_CREATE_INFO *db_create_info); Schema_specification_st *db_create_info);
CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name); CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name);
bool my_dbopt_init(void); bool my_dbopt_init(void);
void my_dbopt_cleanup(void); void my_dbopt_cleanup(void);

View File

@ -3856,7 +3856,8 @@ void select_insert::abort_result_set() {
@retval 0 Error @retval 0 Error
*/ */
static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, static TABLE *create_table_from_items(THD *thd,
Table_specification_st *create_info,
TABLE_LIST *create_table, TABLE_LIST *create_table,
Alter_info *alter_info, Alter_info *alter_info,
List<Item> *items, List<Item> *items,
@ -4101,7 +4102,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
row-based replication for the statement. If we are creating a row-based replication for the statement. If we are creating a
temporary table, we need to start a statement transaction. temporary table, we need to start a statement transaction.
*/ */
if (!thd->lex->create_info.tmp_table() && if (!thd->lex->tmp_table() &&
thd->is_current_stmt_binlog_format_row() && thd->is_current_stmt_binlog_format_row() &&
mysql_bin_log.is_open()) mysql_bin_log.is_open())
{ {
@ -4110,7 +4111,8 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
DEBUG_SYNC(thd,"create_table_select_before_check_if_exists"); DEBUG_SYNC(thd,"create_table_select_before_check_if_exists");
if (!(table= create_table_from_items(thd, create_info, create_table, if (!(table= create_table_from_items(thd, create_info,
create_table,
alter_info, &values, alter_info, &values,
&extra_lock, hook_ptr))) &extra_lock, hook_ptr)))
/* abort() deletes table */ /* abort() deletes table */
@ -4193,8 +4195,8 @@ select_create::binlog_show_create_table(TABLE **tables, uint count)
tmp_table_list.table = *tables; tmp_table_list.table = *tables;
query.length(0); // Have to zero it since constructor doesn't query.length(0); // Have to zero it since constructor doesn't
result= show_create_table(thd, &tmp_table_list, &query, create_info, result= show_create_table(thd, &tmp_table_list, &query,
WITH_DB_NAME); create_info, WITH_DB_NAME);
DBUG_ASSERT(result == 0); /* show_create_table() always return 0 */ DBUG_ASSERT(result == 0); /* show_create_table() always return 0 */
if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())

View File

@ -514,6 +514,7 @@ void lex_start(THD *thd)
lex->use_only_table_context= FALSE; lex->use_only_table_context= FALSE;
lex->parse_vcol_expr= FALSE; lex->parse_vcol_expr= FALSE;
lex->check_exists= FALSE; lex->check_exists= FALSE;
lex->create_info.lex_start();
lex->verbose= 0; lex->verbose= 0;
lex->name= null_lex_str; lex->name= null_lex_str;

View File

@ -2456,7 +2456,7 @@ struct LEX: public Query_tables_list
Item_sum *in_sum_func; Item_sum *in_sum_func;
udf_func udf; udf_func udf;
HA_CHECK_OPT check_opt; // check/repair options HA_CHECK_OPT check_opt; // check/repair options
HA_CREATE_INFO create_info; Table_specification_st create_info;
KEY_CREATE_INFO key_create_info; KEY_CREATE_INFO key_create_info;
LEX_MASTER_INFO mi; // used by CHANGE MASTER LEX_MASTER_INFO mi; // used by CHANGE MASTER
LEX_SERVER_OPTIONS server_options; LEX_SERVER_OPTIONS server_options;
@ -2536,7 +2536,7 @@ struct LEX: public Query_tables_list
uint16 create_view_algorithm; uint16 create_view_algorithm;
uint8 create_view_check; uint8 create_view_check;
uint8 context_analysis_only; uint8 context_analysis_only;
bool drop_temporary, local_file; bool local_file;
bool check_exists; bool check_exists;
bool autocommit; bool autocommit;
bool verbose, no_write_to_binlog; bool verbose, no_write_to_binlog;
@ -2817,6 +2817,39 @@ struct LEX: public Query_tables_list
void init_last_field(Create_field *field, const char *name, CHARSET_INFO *cs); void init_last_field(Create_field *field, const char *name, CHARSET_INFO *cs);
void set_last_field_type(enum enum_field_types type); void set_last_field_type(enum enum_field_types type);
bool set_bincmp(CHARSET_INFO *cs, bool bin); bool set_bincmp(CHARSET_INFO *cs, bool bin);
void set_command(enum_sql_command command,
DDL_options_st options)
{
sql_command= command;
create_info.set(options);
}
void set_command(enum_sql_command command,
uint scope,
DDL_options_st options)
{
set_command(command, options);
create_info.options|= scope; // HA_LEX_CREATE_TMP_TABLE or 0
}
bool set_command_with_check(enum_sql_command command,
uint scope,
DDL_options_st options)
{
if (options.or_replace() && options.if_not_exists())
{
my_error(ER_WRONG_USAGE, MYF(0), "OR REPLACE", "IF NOT EXISTS");
return true;
}
set_command(command, scope, options);
return false;
}
/*
DROP shares lex->create_info to store TEMPORARY and IF EXISTS options
to save on extra initialization in lex_start().
Add some wrappers, to avoid direct use of lex->create_info in the
caller code processing DROP statements (which might look confusing).
*/
bool tmp_table() const { return create_info.tmp_table(); }
bool if_exists() const { return create_info.if_exists(); }
}; };

View File

@ -218,12 +218,12 @@ static bool stmt_causes_implicit_commit(THD *thd, uint mask)
switch (lex->sql_command) { switch (lex->sql_command) {
case SQLCOM_DROP_TABLE: case SQLCOM_DROP_TABLE:
skip= (lex->drop_temporary || skip= (lex->tmp_table() ||
(thd->variables.option_bits & OPTION_GTID_BEGIN)); (thd->variables.option_bits & OPTION_GTID_BEGIN));
break; break;
case SQLCOM_ALTER_TABLE: case SQLCOM_ALTER_TABLE:
/* If ALTER TABLE of non-temporary table, do implicit commit */ /* If ALTER TABLE of non-temporary table, do implicit commit */
skip= (lex->create_info.tmp_table()); skip= (lex->tmp_table());
break; break;
case SQLCOM_CREATE_TABLE: case SQLCOM_CREATE_TABLE:
/* /*
@ -232,7 +232,7 @@ static bool stmt_causes_implicit_commit(THD *thd, uint mask)
This ensures that CREATE ... SELECT will in the same GTID group on the This ensures that CREATE ... SELECT will in the same GTID group on the
master and slave. master and slave.
*/ */
skip= (lex->create_info.tmp_table() || skip= (lex->tmp_table() ||
(thd->variables.option_bits & OPTION_GTID_BEGIN)); (thd->variables.option_bits & OPTION_GTID_BEGIN));
break; break;
case SQLCOM_SET_OPTION: case SQLCOM_SET_OPTION:
@ -1165,12 +1165,10 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
const my_bool create_temp_tables= const my_bool create_temp_tables=
(lex->sql_command == SQLCOM_CREATE_TABLE) && (lex->sql_command == SQLCOM_CREATE_TABLE) && lex->tmp_table();
lex->create_info.tmp_table();
const my_bool drop_temp_tables= const my_bool drop_temp_tables=
(lex->sql_command == SQLCOM_DROP_TABLE) && (lex->sql_command == SQLCOM_DROP_TABLE) && lex->tmp_table();
lex->drop_temporary;
const my_bool update_real_tables= const my_bool update_real_tables=
some_non_temp_table_to_be_updated(thd, all_tables) && some_non_temp_table_to_be_updated(thd, all_tables) &&
@ -2554,7 +2552,7 @@ mysql_execute_command(THD *thd)
if (!(lex->sql_command == SQLCOM_UPDATE_MULTI) && if (!(lex->sql_command == SQLCOM_UPDATE_MULTI) &&
!(lex->sql_command == SQLCOM_SET_OPTION) && !(lex->sql_command == SQLCOM_SET_OPTION) &&
!(lex->sql_command == SQLCOM_DROP_TABLE && !(lex->sql_command == SQLCOM_DROP_TABLE &&
lex->drop_temporary && lex->check_exists) && lex->tmp_table() && lex->if_exists()) &&
all_tables_not_ok(thd, all_tables)) all_tables_not_ok(thd, all_tables))
{ {
/* we warn the slave SQL thread */ /* we warn the slave SQL thread */
@ -3138,7 +3136,7 @@ mysql_execute_command(THD *thd)
safe. A shallow copy is enough as this code won't modify any memory safe. A shallow copy is enough as this code won't modify any memory
referenced from this structure. referenced from this structure.
*/ */
HA_CREATE_INFO create_info(lex->create_info); Table_specification_st create_info(lex->create_info);
/* /*
We need to copy alter_info for the same reasons of re-execution We need to copy alter_info for the same reasons of re-execution
safety, only in case of Alter_info we have to do (almost) a deep safety, only in case of Alter_info we have to do (almost) a deep
@ -3199,11 +3197,13 @@ mysql_execute_command(THD *thd)
CREATE TABLE OR EXISTS failures by dropping the table and CREATE TABLE OR EXISTS failures by dropping the table and
retrying the create. retrying the create.
*/ */
create_info.org_options= create_info.options;
if (thd->slave_thread && if (thd->slave_thread &&
slave_ddl_exec_mode_options == SLAVE_EXEC_MODE_IDEMPOTENT && slave_ddl_exec_mode_options == SLAVE_EXEC_MODE_IDEMPOTENT &&
!(lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS)) !lex->create_info.if_not_exists())
create_info.options|= HA_LEX_CREATE_REPLACE; {
create_info.add(DDL_options_st::OPT_OR_REPLACE);
create_info.add(DDL_options_st::OPT_OR_REPLACE_SLAVE_GENERATED);
}
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
{ {
@ -3289,7 +3289,7 @@ mysql_execute_command(THD *thd)
/* Copy temporarily the statement flags to thd for lock_table_names() */ /* Copy temporarily the statement flags to thd for lock_table_names() */
uint save_thd_create_info_options= thd->lex->create_info.options; uint save_thd_create_info_options= thd->lex->create_info.options;
thd->lex->create_info.options|= create_info.options; thd->lex->create_info.options|= create_info.options;
res= open_and_lock_tables(thd, lex->query_tables, TRUE, 0); res= open_and_lock_tables(thd, create_info, lex->query_tables, TRUE, 0);
thd->lex->create_info.options= save_thd_create_info_options; thd->lex->create_info.options= save_thd_create_info_options;
if (res) if (res)
{ {
@ -3300,8 +3300,7 @@ mysql_execute_command(THD *thd)
} }
/* Ensure we don't try to create something from which we select from */ /* Ensure we don't try to create something from which we select from */
if ((create_info.options & HA_LEX_CREATE_REPLACE) && if (create_info.or_replace() && !create_info.tmp_table())
!create_info.tmp_table())
{ {
TABLE_LIST *duplicate; TABLE_LIST *duplicate;
if ((duplicate= unique_table(thd, lex->query_tables, if ((duplicate= unique_table(thd, lex->query_tables,
@ -3354,7 +3353,7 @@ mysql_execute_command(THD *thd)
else else
{ {
/* regular create */ /* regular create */
if (create_info.options & HA_LEX_CREATE_TABLE_LIKE) if (create_info.like())
{ {
/* CREATE TABLE ... LIKE ... */ /* CREATE TABLE ... LIKE ... */
res= mysql_create_like_table(thd, create_table, select_tables, res= mysql_create_like_table(thd, create_table, select_tables,
@ -3366,13 +3365,12 @@ mysql_execute_command(THD *thd)
tables, like mysql replication does tables, like mysql replication does
*/ */
if (WSREP(thd) && (!thd->is_current_stmt_binlog_format_row() || if (WSREP(thd) && (!thd->is_current_stmt_binlog_format_row() ||
!(create_info.options & HA_LEX_CREATE_TMP_TABLE))) !create_info.tmp_table()))
{ {
WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, NULL) WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, NULL)
} }
/* Regular CREATE TABLE */ /* Regular CREATE TABLE */
res= mysql_create_table(thd, create_table, res= mysql_create_table(thd, create_table, &create_info, &alter_info);
&create_info, &alter_info);
} }
if (!res) if (!res)
{ {
@ -4076,7 +4074,7 @@ end_with_restore_list:
case SQLCOM_DROP_TABLE: case SQLCOM_DROP_TABLE:
{ {
DBUG_ASSERT(first_table == all_tables && first_table != 0); DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (!lex->drop_temporary) if (!lex->tmp_table())
{ {
if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE)) if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */ goto error; /* purecov: inspected */
@ -4090,7 +4088,7 @@ end_with_restore_list:
{ {
for (TABLE_LIST *table= all_tables; table; table= table->next_global) for (TABLE_LIST *table= all_tables; table; table= table->next_global)
{ {
if (!lex->drop_temporary && if (!lex->tmp_table() &&
(!thd->is_current_stmt_binlog_format_row() || (!thd->is_current_stmt_binlog_format_row() ||
!find_temporary_table(thd, table))) !find_temporary_table(thd, table)))
{ {
@ -4107,11 +4105,10 @@ end_with_restore_list:
*/ */
if (thd->slave_thread && !thd->slave_expected_error && if (thd->slave_thread && !thd->slave_expected_error &&
slave_ddl_exec_mode_options == SLAVE_EXEC_MODE_IDEMPOTENT) slave_ddl_exec_mode_options == SLAVE_EXEC_MODE_IDEMPOTENT)
lex->check_exists= 1; lex->create_info.set(DDL_options_st::OPT_IF_EXISTS);
/* DDL and binlog write order are protected by metadata locks. */ /* DDL and binlog write order are protected by metadata locks. */
res= mysql_rm_table(thd, first_table, lex->check_exists, res= mysql_rm_table(thd, first_table, lex->if_exists(), lex->tmp_table());
lex->drop_temporary);
break; break;
} }
case SQLCOM_SHOW_PROCESSLIST: case SQLCOM_SHOW_PROCESSLIST:
@ -4276,7 +4273,7 @@ end_with_restore_list:
it, we need to use a copy of LEX::create_info to make execution it, we need to use a copy of LEX::create_info to make execution
prepared statement- safe. prepared statement- safe.
*/ */
HA_CREATE_INFO create_info(lex->create_info); Schema_specification_st create_info(lex->create_info);
if (check_db_name(&lex->name)) if (check_db_name(&lex->name))
{ {
my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str); my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
@ -4304,7 +4301,7 @@ end_with_restore_list:
if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0)) if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0))
break; break;
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL) WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL)
res= mysql_create_db(thd, lex->name.str, &create_info, 0); res= mysql_create_db(thd, lex->name.str, lex->create_info, &create_info, 0);
break; break;
} }
case SQLCOM_DROP_DB: case SQLCOM_DROP_DB:
@ -4336,7 +4333,7 @@ end_with_restore_list:
if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0)) if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0))
break; break;
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL) WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL)
res= mysql_rm_db(thd, lex->name.str, lex->check_exists, 0); res= mysql_rm_db(thd, lex->name.str, lex->if_exists(), 0);
break; break;
} }
case SQLCOM_ALTER_DB_UPGRADE: case SQLCOM_ALTER_DB_UPGRADE:
@ -4422,7 +4419,7 @@ end_with_restore_list:
my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str); my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
break; break;
} }
res= mysqld_show_create_db(thd, &db_name, &lex->name, &lex->create_info); res= mysqld_show_create_db(thd, &db_name, &lex->name, lex->create_info);
break; break;
} }
case SQLCOM_CREATE_EVENT: case SQLCOM_CREATE_EVENT:
@ -4445,8 +4442,7 @@ end_with_restore_list:
switch (lex->sql_command) { switch (lex->sql_command) {
case SQLCOM_CREATE_EVENT: case SQLCOM_CREATE_EVENT:
{ {
bool if_not_exists= (lex->create_info.options & bool if_not_exists= lex->create_info.if_not_exists();
HA_LEX_CREATE_IF_NOT_EXISTS);
res= Events::create_event(thd, lex->event_parse_data, if_not_exists); res= Events::create_event(thd, lex->event_parse_data, if_not_exists);
break; break;
} }
@ -4479,7 +4475,7 @@ end_with_restore_list:
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
if (!(res= Events::drop_event(thd, if (!(res= Events::drop_event(thd,
lex->spname->m_db, lex->spname->m_name, lex->spname->m_db, lex->spname->m_name,
lex->check_exists))) lex->if_exists())))
my_ok(thd); my_ok(thd);
break; break;
#else #else
@ -5192,7 +5188,7 @@ create_sp_error:
if (lex->spname->m_db.str == NULL) if (lex->spname->m_db.str == NULL)
{ {
if (lex->check_exists) if (lex->if_exists())
{ {
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
@ -5262,7 +5258,7 @@ create_sp_error:
my_ok(thd); my_ok(thd);
break; break;
case SP_KEY_NOT_FOUND: case SP_KEY_NOT_FOUND:
if (lex->check_exists) if (lex->if_exists())
{ {
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
@ -5495,7 +5491,7 @@ create_sp_error:
if ((err_code= drop_server(thd, &lex->server_options))) if ((err_code= drop_server(thd, &lex->server_options)))
{ {
if (! lex->check_exists && err_code == ER_FOREIGN_SERVER_DOESNT_EXIST) if (! lex->if_exists() && err_code == ER_FOREIGN_SERVER_DOESNT_EXIST)
{ {
DBUG_PRINT("info", ("problem dropping server %s", DBUG_PRINT("info", ("problem dropping server %s",
lex->server_options.server_name.str)); lex->server_options.server_name.str));
@ -8448,7 +8444,7 @@ void create_table_set_open_action_and_adjust_tables(LEX *lex)
{ {
TABLE_LIST *create_table= lex->query_tables; TABLE_LIST *create_table= lex->query_tables;
if (lex->create_info.tmp_table()) if (lex->tmp_table())
create_table->open_type= OT_TEMPORARY_ONLY; create_table->open_type= OT_TEMPORARY_ONLY;
else else
create_table->open_type= OT_BASE_ONLY; create_table->open_type= OT_BASE_ONLY;
@ -8494,12 +8490,11 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
CREATE TABLE ... SELECT, also require INSERT. CREATE TABLE ... SELECT, also require INSERT.
*/ */
want_priv= lex->create_info.tmp_table() ? CREATE_TMP_ACL : want_priv= lex->tmp_table() ? CREATE_TMP_ACL :
(CREATE_ACL | (select_lex->item_list.elements ? INSERT_ACL : 0)); (CREATE_ACL | (select_lex->item_list.elements ? INSERT_ACL : 0));
/* CREATE OR REPLACE on not temporary tables require DROP_ACL */ /* CREATE OR REPLACE on not temporary tables require DROP_ACL */
if ((lex->create_info.options & HA_LEX_CREATE_REPLACE) && if (lex->create_info.or_replace() && !lex->tmp_table())
!lex->create_info.tmp_table())
want_priv|= DROP_ACL; want_priv|= DROP_ACL;
if (check_access(thd, want_priv, create_table->db, if (check_access(thd, want_priv, create_table->db,
@ -8563,7 +8558,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
UINT_MAX, FALSE)) UINT_MAX, FALSE))
goto err; goto err;
} }
else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE) else if (lex->create_info.like())
{ {
if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE)) if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE))
goto err; goto err;

View File

@ -1187,7 +1187,7 @@ exit:
bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname, bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname,
LEX_STRING *orig_dbname, LEX_STRING *orig_dbname,
HA_CREATE_INFO *create_info) const DDL_options_st &options)
{ {
char buff[2048]; char buff[2048];
String buffer(buff, sizeof(buff), system_charset_info); String buffer(buff, sizeof(buff), system_charset_info);
@ -1196,7 +1196,6 @@ bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname,
uint db_access; uint db_access;
#endif #endif
HA_CREATE_INFO create; HA_CREATE_INFO create;
uint create_options = create_info ? create_info->options : 0;
Protocol *protocol=thd->protocol; Protocol *protocol=thd->protocol;
DBUG_ENTER("mysql_show_create_db"); DBUG_ENTER("mysql_show_create_db");
@ -1243,7 +1242,7 @@ bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname,
protocol->store(orig_dbname->str, orig_dbname->length, system_charset_info); protocol->store(orig_dbname->str, orig_dbname->length, system_charset_info);
buffer.length(0); buffer.length(0);
buffer.append(STRING_WITH_LEN("CREATE DATABASE ")); buffer.append(STRING_WITH_LEN("CREATE DATABASE "));
if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS) if (options.if_not_exists())
buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ ")); buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ "));
append_identifier(thd, &buffer, dbname->str, dbname->length); append_identifier(thd, &buffer, dbname->str, dbname->length);
@ -1654,7 +1653,7 @@ static void append_create_options(THD *thd, String *packet,
*/ */
int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
HA_CREATE_INFO *create_info_arg, Table_specification_st *create_info_arg,
enum_with_db_name with_db_name) enum_with_db_name with_db_name)
{ {
List<Item> field_list; List<Item> field_list;
@ -1696,14 +1695,14 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN("CREATE ")); packet->append(STRING_WITH_LEN("CREATE "));
if (create_info_arg && if (create_info_arg &&
(create_info_arg->org_options & HA_LEX_CREATE_REPLACE || ((create_info_arg->or_replace() &&
!create_info_arg->or_replace_slave_generated()) ||
create_info_arg->table_was_deleted)) create_info_arg->table_was_deleted))
packet->append(STRING_WITH_LEN("OR REPLACE ")); packet->append(STRING_WITH_LEN("OR REPLACE "));
if (share->tmp_table) if (share->tmp_table)
packet->append(STRING_WITH_LEN("TEMPORARY ")); packet->append(STRING_WITH_LEN("TEMPORARY "));
packet->append(STRING_WITH_LEN("TABLE ")); packet->append(STRING_WITH_LEN("TABLE "));
if (create_info_arg && if (create_info_arg && create_info_arg->if_not_exists())
(create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
packet->append(STRING_WITH_LEN("IF NOT EXISTS ")); packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
if (table_list->schema_table) if (table_list->schema_table)
alias= table_list->schema_table->table_name; alias= table_list->schema_table->table_name;

View File

@ -76,7 +76,7 @@ typedef struct system_status_var STATUS_VAR;
typedef enum { WITHOUT_DB_NAME, WITH_DB_NAME } enum_with_db_name; typedef enum { WITHOUT_DB_NAME, WITH_DB_NAME } enum_with_db_name;
int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
HA_CREATE_INFO *create_info_arg, Table_specification_st *create_info_arg,
enum_with_db_name with_db_name); enum_with_db_name with_db_name);
int copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table); int copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table);
@ -88,7 +88,7 @@ int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd);
bool mysqld_show_create(THD *thd, TABLE_LIST *table_list); bool mysqld_show_create(THD *thd, TABLE_LIST *table_list);
bool mysqld_show_create_db(THD *thd, LEX_STRING *db_name, bool mysqld_show_create_db(THD *thd, LEX_STRING *db_name,
LEX_STRING *orig_db_name, LEX_STRING *orig_db_name,
HA_CREATE_INFO *create); const DDL_options_st &options);
void mysqld_list_processes(THD *thd,const char *user,bool verbose); void mysqld_list_processes(THD *thd,const char *user,bool verbose);
int mysqld_show_status(THD *thd); int mysqld_show_status(THD *thd);

View File

@ -4617,6 +4617,7 @@ int create_table_impl(THD *thd,
const char *orig_db, const char *orig_table_name, const char *orig_db, const char *orig_table_name,
const char *db, const char *table_name, const char *db, const char *table_name,
const char *path, const char *path,
const DDL_options_st options,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
Alter_info *alter_info, Alter_info *alter_info,
int create_table_mode, int create_table_mode,
@ -4661,7 +4662,7 @@ int create_table_impl(THD *thd,
if ((tmp_table= find_temporary_table(thd, db, table_name))) if ((tmp_table= find_temporary_table(thd, db, table_name)))
{ {
bool table_creation_was_logged= tmp_table->s->table_creation_was_logged; bool table_creation_was_logged= tmp_table->s->table_creation_was_logged;
if (create_info->options & HA_LEX_CREATE_REPLACE) if (options.or_replace())
{ {
bool is_trans; bool is_trans;
/* /*
@ -4671,7 +4672,7 @@ int create_table_impl(THD *thd,
if (drop_temporary_table(thd, tmp_table, &is_trans)) if (drop_temporary_table(thd, tmp_table, &is_trans))
goto err; goto err;
} }
else if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) else if (options.if_not_exists())
goto warn; goto warn;
else else
{ {
@ -4697,7 +4698,7 @@ int create_table_impl(THD *thd,
{ {
if (!internal_tmp_table && ha_table_exists(thd, db, table_name)) if (!internal_tmp_table && ha_table_exists(thd, db, table_name))
{ {
if (create_info->options & HA_LEX_CREATE_REPLACE) if (options.or_replace())
{ {
TABLE_LIST table_list; TABLE_LIST table_list;
table_list.init_one_table(db, strlen(db), table_name, table_list.init_one_table(db, strlen(db), table_name,
@ -4733,7 +4734,7 @@ int create_table_impl(THD *thd,
restart_trans_for_tables(thd, thd->lex->query_tables)) restart_trans_for_tables(thd, thd->lex->query_tables))
goto err; goto err;
} }
else if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) else if (options.if_not_exists())
goto warn; goto warn;
else else
{ {
@ -4889,7 +4890,7 @@ warn:
int mysql_create_table_no_lock(THD *thd, int mysql_create_table_no_lock(THD *thd,
const char *db, const char *table_name, const char *db, const char *table_name,
HA_CREATE_INFO *create_info, Table_specification_st *create_info,
Alter_info *alter_info, bool *is_trans, Alter_info *alter_info, bool *is_trans,
int create_table_mode) int create_table_mode)
{ {
@ -4916,7 +4917,8 @@ int mysql_create_table_no_lock(THD *thd,
} }
res= create_table_impl(thd, db, table_name, db, table_name, path, res= create_table_impl(thd, db, table_name, db, table_name, path,
create_info, alter_info, create_table_mode, *create_info, create_info,
alter_info, create_table_mode,
is_trans, &not_used_1, &not_used_2, &frm); is_trans, &not_used_1, &not_used_2, &frm);
my_free(const_cast<uchar*>(frm.str)); my_free(const_cast<uchar*>(frm.str));
return res; return res;
@ -4933,7 +4935,7 @@ int mysql_create_table_no_lock(THD *thd,
*/ */
bool mysql_create_table(THD *thd, TABLE_LIST *create_table, bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
HA_CREATE_INFO *create_info, Table_specification_st *create_info,
Alter_info *alter_info) Alter_info *alter_info)
{ {
const char *db= create_table->db; const char *db= create_table->db;
@ -4952,7 +4954,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
thd->lex->create_info.options|= create_info->options; thd->lex->create_info.options|= create_info->options;
/* Open or obtain an exclusive metadata lock on table being created */ /* Open or obtain an exclusive metadata lock on table being created */
result= open_and_lock_tables(thd, create_table, FALSE, 0); result= open_and_lock_tables(thd, *create_info, create_table, FALSE, 0);
thd->lex->create_info.options= save_thd_create_info_options; thd->lex->create_info.options= save_thd_create_info_options;
@ -4989,7 +4991,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
on a non temporary table on a non temporary table
*/ */
if (thd->locked_tables_mode && pos_in_locked_tables && if (thd->locked_tables_mode && pos_in_locked_tables &&
(create_info->options & HA_LEX_CREATE_REPLACE)) create_info->or_replace())
{ {
/* /*
Add back the deleted table and re-created table as a locked table Add back the deleted table and re-created table as a locked table
@ -5230,9 +5232,9 @@ mysql_rename_table(handlerton *base, const char *old_db,
bool mysql_create_like_table(THD* thd, TABLE_LIST* table, bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
TABLE_LIST* src_table, TABLE_LIST* src_table,
HA_CREATE_INFO *create_info) Table_specification_st *create_info)
{ {
HA_CREATE_INFO local_create_info; Table_specification_st local_create_info;
TABLE_LIST *pos_in_locked_tables= 0; TABLE_LIST *pos_in_locked_tables= 0;
Alter_info local_alter_info; Alter_info local_alter_info;
Alter_table_ctx local_alter_ctx; // Not used Alter_table_ctx local_alter_ctx; // Not used
@ -5262,6 +5264,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
*/ */
/* Copy temporarily the statement flags to thd for lock_table_names() */ /* Copy temporarily the statement flags to thd for lock_table_names() */
// QQ: is this really needed???
uint save_thd_create_info_options= thd->lex->create_info.options; uint save_thd_create_info_options= thd->lex->create_info.options;
thd->lex->create_info.options|= create_info->options; thd->lex->create_info.options|= create_info->options;
res= open_tables(thd, &thd->lex->query_tables, &not_used, 0); res= open_tables(thd, &thd->lex->query_tables, &not_used, 0);
@ -5274,8 +5277,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
goto err; goto err;
} }
/* Ensure we don't try to create something from which we select from */ /* Ensure we don't try to create something from which we select from */
if ((create_info->options & HA_LEX_CREATE_REPLACE) && if (create_info->or_replace() && !create_info->tmp_table())
!create_info->tmp_table())
{ {
TABLE_LIST *duplicate; TABLE_LIST *duplicate;
if ((duplicate= unique_table(thd, table, src_table, 0))) if ((duplicate= unique_table(thd, table, src_table, 0)))
@ -5289,8 +5291,12 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
DEBUG_SYNC(thd, "create_table_like_after_open"); DEBUG_SYNC(thd, "create_table_like_after_open");
/* Fill HA_CREATE_INFO and Alter_info with description of source table. */ /*
bzero((char*) &local_create_info, sizeof(local_create_info)); Fill Table_specification_st and Alter_info with the source table description.
Set OR REPLACE and IF NOT EXISTS option as in the CREATE TABLE LIKE
statement.
*/
local_create_info.init(create_info->create_like_options());
local_create_info.db_type= src_table->table->s->db_type(); local_create_info.db_type= src_table->table->s->db_type();
local_create_info.row_type= src_table->table->s->row_type; local_create_info.row_type= src_table->table->s->row_type;
if (mysql_prepare_alter_table(thd, src_table->table, &local_create_info, if (mysql_prepare_alter_table(thd, src_table->table, &local_create_info,
@ -5311,10 +5317,6 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
*/ */
if (src_table->schema_table) if (src_table->schema_table)
local_create_info.max_rows= 0; local_create_info.max_rows= 0;
/* Set IF NOT EXISTS option as in the CREATE TABLE LIKE statement. */
local_create_info.options|= (create_info->options &
(HA_LEX_CREATE_IF_NOT_EXISTS |
HA_LEX_CREATE_REPLACE));
/* Replace type of source table with one specified in the statement. */ /* Replace type of source table with one specified in the statement. */
local_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE; local_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
local_create_info.options|= create_info->tmp_table(); local_create_info.options|= create_info->tmp_table();
@ -5344,7 +5346,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
on a non temporary table on a non temporary table
*/ */
if (thd->locked_tables_mode && pos_in_locked_tables && if (thd->locked_tables_mode && pos_in_locked_tables &&
(create_info->options & HA_LEX_CREATE_REPLACE)) create_info->or_replace())
{ {
/* /*
Add back the deleted table and re-created table as a locked table Add back the deleted table and re-created table as a locked table
@ -5454,7 +5456,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
if (!table->view) if (!table->view)
{ {
int result __attribute__((unused))= int result __attribute__((unused))=
show_create_table(thd, table, &query, create_info, WITHOUT_DB_NAME); show_create_table(thd, table, &query,
create_info, WITHOUT_DB_NAME);
DBUG_ASSERT(result == 0); // show_create_table() always return 0 DBUG_ASSERT(result == 0); // show_create_table() always return 0
do_logging= FALSE; do_logging= FALSE;
@ -5907,10 +5910,11 @@ remove_key:
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *tab_part_info= table->part_info; partition_info *tab_part_info= table->part_info;
if (tab_part_info && thd->lex->check_exists) if (tab_part_info)
{ {
/* ALTER TABLE ADD PARTITION IF NOT EXISTS */ /* ALTER TABLE ADD PARTITION IF NOT EXISTS */
if (alter_info->flags & Alter_info::ALTER_ADD_PARTITION) if ((alter_info->flags & Alter_info::ALTER_ADD_PARTITION) &&
thd->lex->create_info.if_not_exists())
{ {
partition_info *alt_part_info= thd->lex->part_info; partition_info *alt_part_info= thd->lex->part_info;
if (alt_part_info) if (alt_part_info)
@ -5932,7 +5936,8 @@ remove_key:
} }
} }
/* ALTER TABLE DROP PARTITION IF EXISTS */ /* ALTER TABLE DROP PARTITION IF EXISTS */
if (alter_info->flags & Alter_info::ALTER_DROP_PARTITION) if ((alter_info->flags & Alter_info::ALTER_DROP_PARTITION) &&
thd->lex->if_exists())
{ {
List_iterator<char> names_it(alter_info->partition_names); List_iterator<char> names_it(alter_info->partition_names);
char *name; char *name;
@ -8634,7 +8639,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
alter_ctx.db, alter_ctx.table_name, alter_ctx.db, alter_ctx.table_name,
alter_ctx.new_db, alter_ctx.tmp_name, alter_ctx.new_db, alter_ctx.tmp_name,
alter_ctx.get_tmp_path(), alter_ctx.get_tmp_path(),
create_info, alter_info, thd->lex->create_info, create_info, alter_info,
C_ALTER_TABLE_FRM_ONLY, NULL, C_ALTER_TABLE_FRM_ONLY, NULL,
&key_info, &key_count, &frm); &key_info, &key_count, &frm);
reenable_binlog(thd); reenable_binlog(thd);

View File

@ -31,6 +31,7 @@ struct handlerton;
class handler; class handler;
typedef struct st_ha_check_opt HA_CHECK_OPT; typedef struct st_ha_check_opt HA_CHECK_OPT;
struct HA_CREATE_INFO; struct HA_CREATE_INFO;
struct Table_specification_st;
typedef struct st_key KEY; typedef struct st_key KEY;
typedef struct st_key_cache KEY_CACHE; typedef struct st_key_cache KEY_CACHE;
typedef struct st_lock_param_type ALTER_PARTITION_PARAM_TYPE; typedef struct st_lock_param_type ALTER_PARTITION_PARAM_TYPE;
@ -151,7 +152,7 @@ uint build_table_shadow_filename(char *buff, size_t bufflen,
ALTER_PARTITION_PARAM_TYPE *lpt); ALTER_PARTITION_PARAM_TYPE *lpt);
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen); uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen);
bool mysql_create_table(THD *thd, TABLE_LIST *create_table, bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
HA_CREATE_INFO *create_info, Table_specification_st *create_info,
Alter_info *alter_info); Alter_info *alter_info);
/* /*
@ -192,7 +193,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
int mysql_create_table_no_lock(THD *thd, const char *db, int mysql_create_table_no_lock(THD *thd, const char *db,
const char *table_name, const char *table_name,
HA_CREATE_INFO *create_info, Table_specification_st *create_info,
Alter_info *alter_info, bool *is_trans, Alter_info *alter_info, bool *is_trans,
int create_table_mode); int create_table_mode);
@ -227,7 +228,7 @@ bool mysql_compare_tables(TABLE *table,
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy); bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy);
bool mysql_create_like_table(THD *thd, TABLE_LIST *table, bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
TABLE_LIST *src_table, TABLE_LIST *src_table,
HA_CREATE_INFO *create_info); Table_specification_st *create_info);
bool mysql_rename_table(handlerton *base, const char *old_db, bool mysql_rename_table(handlerton *base, const char *old_db,
const char * old_name, const char *new_db, const char * old_name, const char *new_db,
const char * new_name, uint flags); const char * new_name, uint flags);

View File

@ -444,7 +444,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
if (!create) if (!create)
{ {
bool if_exists= thd->lex->check_exists; bool if_exists= thd->lex->if_exists();
/* /*
Protect the query table list from the temporary and potentially Protect the query table list from the temporary and potentially

View File

@ -1640,7 +1640,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
{ {
char name[FN_REFLEN]; char name[FN_REFLEN];
my_snprintf(name, sizeof(name), "%s.%s", view->db, view->table_name); my_snprintf(name, sizeof(name), "%s.%s", view->db, view->table_name);
if (thd->lex->check_exists) if (thd->lex->if_exists())
{ {
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),

View File

@ -736,11 +736,12 @@ static bool add_create_index_prepare (LEX *lex, Table_ident *table)
static bool add_create_index (LEX *lex, Key::Keytype type, static bool add_create_index (LEX *lex, Key::Keytype type,
const LEX_STRING &name, const LEX_STRING &name,
bool check_exists,
KEY_CREATE_INFO *info= NULL, bool generated= 0) KEY_CREATE_INFO *info= NULL, bool generated= 0)
{ {
Key *key; Key *key;
key= new Key(type, name, info ? info : &lex->key_create_info, generated, key= new Key(type, name, info ? info : &lex->key_create_info, generated,
lex->col_list, lex->option_list, lex->check_exists); lex->col_list, lex->option_list, check_exists);
if (key == NULL) if (key == NULL)
return TRUE; return TRUE;
@ -1010,6 +1011,7 @@ bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin)
enum sp_variable::enum_mode spvar_mode; enum sp_variable::enum_mode spvar_mode;
enum thr_lock_type lock_type; enum thr_lock_type lock_type;
enum enum_mysql_timestamp_type date_time_type; enum enum_mysql_timestamp_type date_time_type;
DDL_options_st object_ddl_options;
} }
%{ %{
@ -1714,7 +1716,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
IDENT_sys TEXT_STRING_sys TEXT_STRING_literal IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component key_cache_name NCHAR_STRING opt_component key_cache_name
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
opt_constraint constraint opt_ident opt_if_not_exists_ident opt_constraint constraint opt_ident
opt_if_not_exists_opt_table_element_name
%type <lex_str_ptr> %type <lex_str_ptr>
opt_table_alias opt_table_alias
@ -1736,8 +1739,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <num> %type <num>
order_dir lock_option order_dir lock_option
udf_type opt_if_exists opt_local opt_table_options table_options udf_type opt_local opt_table_options table_options
table_option opt_if_not_exists create_or_replace opt_no_write_to_binlog table_option opt_no_write_to_binlog
opt_temporary all_or_any opt_distinct opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options union_option opt_ignore_leaves fulltext_options union_option
opt_not opt_union_order_or_limit opt_not opt_union_order_or_limit
@ -1749,6 +1752,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_time_precision kill_type kill_option int_num opt_time_precision kill_type kill_option int_num
opt_default_time_precision opt_default_time_precision
case_stmt_body opt_bin_mod case_stmt_body opt_bin_mod
opt_if_exists_table_element opt_if_not_exists_table_element
%type <object_ddl_options>
create_or_replace
opt_if_not_exists
opt_if_exists
/* /*
Bit field of MYSQL_START_TRANS_OPT_* flags. Bit field of MYSQL_START_TRANS_OPT_* flags.
@ -2459,25 +2468,20 @@ create:
create_or_replace opt_table_options TABLE_SYM opt_if_not_exists table_ident create_or_replace opt_table_options TABLE_SYM opt_if_not_exists table_ident
{ {
LEX *lex= thd->lex; LEX *lex= thd->lex;
lex->sql_command= SQLCOM_CREATE_TABLE; lex->create_info.init();
if ($1 && $4) if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4))
{
my_error(ER_WRONG_USAGE, MYF(0), "OR REPLACE", "IF NOT EXISTS");
MYSQL_YYABORT; MYSQL_YYABORT;
}
if (!lex->select_lex.add_table_to_list(thd, $5, NULL, if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
TL_OPTION_UPDATING, TL_OPTION_UPDATING,
TL_WRITE, MDL_EXCLUSIVE)) TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->alter_info.reset(); lex->alter_info.reset();
lex->col_list.empty(); lex->col_list.empty();
bzero((char*) &lex->create_info,sizeof(lex->create_info));
/* /*
For CREATE TABLE we should not open the table even if it exists. For CREATE TABLE we should not open the table even if it exists.
If the table exists, we should either not create it or replace it If the table exists, we should either not create it or replace it
*/ */
lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB; lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
lex->create_info.options= ($1 | $2 | $4);
lex->create_info.default_table_charset= NULL; lex->create_info.default_table_charset= NULL;
lex->name= null_lex_str; lex->name= null_lex_str;
lex->create_last_non_select_table= lex->last_table(); lex->create_last_non_select_table= lex->last_table();
@ -2505,7 +2509,7 @@ create:
} }
'(' key_list ')' normal_key_options '(' key_list ')' normal_key_options
{ {
if (add_create_index(Lex, $2, $5)) if (add_create_index(Lex, $2, $5, $4.if_not_exists()))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
opt_index_lock_algorithm { } opt_index_lock_algorithm { }
@ -2517,11 +2521,12 @@ create:
} }
'(' key_list ')' fulltext_key_options '(' key_list ')' fulltext_key_options
{ {
if (add_create_index(Lex, $2, $5)) if (add_create_index(Lex, $2, $5, $4.if_not_exists()))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
opt_index_lock_algorithm { } opt_index_lock_algorithm { }
| CREATE spatial INDEX_SYM opt_if_not_exists ident init_key_options ON | CREATE spatial INDEX_SYM opt_if_not_exists ident
init_key_options ON
table_ident table_ident
{ {
if (add_create_index_prepare(Lex, $8)) if (add_create_index_prepare(Lex, $8))
@ -2529,7 +2534,7 @@ create:
} }
'(' key_list ')' spatial_key_options '(' key_list ')' spatial_key_options
{ {
if (add_create_index(Lex, $2, $5)) if (add_create_index(Lex, $2, $5, $4.if_not_exists()))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
opt_index_lock_algorithm { } opt_index_lock_algorithm { }
@ -2541,20 +2546,19 @@ create:
opt_create_database_options opt_create_database_options
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command=SQLCOM_CREATE_DB; lex->set_command(SQLCOM_CREATE_DB, $3);
lex->name= $4; lex->name= $4;
lex->create_info.options=$3;
} }
| create_or_replace | create_or_replace
{ {
Lex->create_view_mode= ($1 == 0 ? VIEW_CREATE_NEW : Lex->create_view_mode= ($1.or_replace() ? VIEW_CREATE_OR_REPLACE :
VIEW_CREATE_OR_REPLACE); VIEW_CREATE_NEW);
Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED; Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED;
Lex->create_view_suid= TRUE; Lex->create_view_suid= TRUE;
} }
view_or_trigger_or_sp_or_event view_or_trigger_or_sp_or_event
{ {
if ($1 && Lex->sql_command != SQLCOM_CREATE_VIEW) if ($1.or_replace() && Lex->sql_command != SQLCOM_CREATE_VIEW)
{ {
my_error(ER_WRONG_USAGE, MYF(0), "OR REPLACE", my_error(ER_WRONG_USAGE, MYF(0), "OR REPLACE",
"TRIGGERS / SP / EVENT"); "TRIGGERS / SP / EVENT");
@ -2639,7 +2643,7 @@ event_tail:
LEX *lex=Lex; LEX *lex=Lex;
lex->stmt_definition_begin= $1; lex->stmt_definition_begin= $1;
lex->create_info.options= $3; lex->create_info.set($3);
if (!(lex->event_parse_data= Event_parse_data::new_instance(thd))) if (!(lex->event_parse_data= Event_parse_data::new_instance(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->event_parse_data->identifier= $4; lex->event_parse_data->identifier= $4;
@ -4821,7 +4825,7 @@ create_body:
| create_like | create_like
{ {
Lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE; Lex->create_info.add(DDL_options_st::OPT_LIKE);
TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd, TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd,
$1, NULL, 0, TL_READ, MDL_SHARED_READ); $1, NULL, 0, TL_READ, MDL_SHARED_READ);
if (! src_table) if (! src_table)
@ -5614,27 +5618,36 @@ table_option:
TEMPORARY { $$=HA_LEX_CREATE_TMP_TABLE; } TEMPORARY { $$=HA_LEX_CREATE_TMP_TABLE; }
; ;
opt_if_not_exists: opt_if_not_exists_table_element:
/* empty */ /* empty */
{ {
Lex->check_exists= FALSE; Lex->check_exists= FALSE;
$$= 0;
} }
| IF_SYM not EXISTS | IF_SYM not EXISTS
{ {
Lex->check_exists= TRUE; Lex->check_exists= TRUE;
$$=HA_LEX_CREATE_IF_NOT_EXISTS; }
;
opt_if_not_exists:
/* empty */
{
$$.init();
}
| IF_SYM not EXISTS
{
$$.set(DDL_options_st::OPT_IF_NOT_EXISTS);
} }
; ;
create_or_replace: create_or_replace:
CREATE /* empty */ CREATE /* empty */
{ {
$$= 0; $$.init();
} }
| CREATE OR_SYM REPLACE | CREATE OR_SYM REPLACE
{ {
$$= HA_LEX_CREATE_REPLACE; $$.set(DDL_options_st::OPT_OR_REPLACE);
} }
; ;
@ -6019,38 +6032,40 @@ column_def:
; ;
key_def: key_def:
normal_key_type opt_if_not_exists_ident key_alg '(' key_list ')' normal_key_type opt_if_not_exists_opt_table_element_name
key_alg '(' key_list ')'
{ Lex->option_list= NULL; } { Lex->option_list= NULL; }
normal_key_options normal_key_options
{ {
if (add_create_index (Lex, $1, $2)) if (add_create_index (Lex, $1, $2, Lex->check_exists))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| fulltext opt_key_or_index opt_if_not_exists_ident init_key_options | fulltext opt_key_or_index opt_if_not_exists_opt_table_element_name
'(' key_list ')' init_key_options '(' key_list ')'
{ Lex->option_list= NULL; } { Lex->option_list= NULL; }
fulltext_key_options fulltext_key_options
{ {
if (add_create_index (Lex, $1, $3)) if (add_create_index (Lex, $1, $3, Lex->check_exists))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| spatial opt_key_or_index opt_if_not_exists_ident init_key_options | spatial opt_key_or_index opt_if_not_exists_opt_table_element_name
'(' key_list ')' init_key_options '(' key_list ')'
{ Lex->option_list= NULL; } { Lex->option_list= NULL; }
spatial_key_options spatial_key_options
{ {
if (add_create_index (Lex, $1, $3)) if (add_create_index (Lex, $1, $3, Lex->check_exists))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| opt_constraint constraint_key_type opt_if_not_exists_ident key_alg | opt_constraint constraint_key_type
'(' key_list ')' opt_if_not_exists_opt_table_element_name key_alg '(' key_list ')'
{ Lex->option_list= NULL; } { Lex->option_list= NULL; }
normal_key_options normal_key_options
{ {
if (add_create_index (Lex, $2, $3.str ? $3 : $1)) if (add_create_index (Lex, $2, $3.str ? $3 : $1, Lex->check_exists))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| opt_constraint FOREIGN KEY_SYM opt_if_not_exists_ident '(' key_list ')' references | opt_constraint FOREIGN KEY_SYM opt_if_not_exists_opt_table_element_name
'(' key_list ')' references
{ {
LEX *lex=Lex; LEX *lex=Lex;
Key *key= new Foreign_key($4.str ? $4 : $1, lex->col_list, Key *key= new Foreign_key($4.str ? $4 : $1, lex->col_list,
@ -6066,6 +6081,7 @@ key_def:
lex->alter_info.key_list.push_back(key); lex->alter_info.key_list.push_back(key);
lex->option_list= NULL; lex->option_list= NULL;
if (add_create_index (lex, Key::MULTIPLE, $1.str ? $1 : $4, if (add_create_index (lex, Key::MULTIPLE, $1.str ? $1 : $4,
Lex->check_exists,
&default_key_create_info, 1)) &default_key_create_info, 1))
MYSQL_YYABORT; MYSQL_YYABORT;
/* Only used for ALTER TABLE. Ignored otherwise. */ /* Only used for ALTER TABLE. Ignored otherwise. */
@ -7084,8 +7100,8 @@ opt_ident:
| field_ident { $$= $1; } | field_ident { $$= $1; }
; ;
opt_if_not_exists_ident: opt_if_not_exists_opt_table_element_name:
opt_if_not_exists opt_ident opt_if_not_exists_table_element opt_ident
{ {
LEX *lex= Lex; LEX *lex= Lex;
if (lex->check_exists && lex->sql_command != SQLCOM_ALTER_TABLE) if (lex->check_exists && lex->sql_command != SQLCOM_ALTER_TABLE)
@ -7117,9 +7133,7 @@ alter:
Lex->duplicates= DUP_ERROR; Lex->duplicates= DUP_ERROR;
Lex->col_list.empty(); Lex->col_list.empty();
Lex->select_lex.init_order(); Lex->select_lex.init_order();
bzero(&Lex->create_info, sizeof(Lex->create_info)); Lex->create_info.init();
Lex->create_info.db_type= 0;
Lex->create_info.default_table_charset= NULL;
Lex->create_info.row_type= ROW_TYPE_NOT_USED; Lex->create_info.row_type= ROW_TYPE_NOT_USED;
Lex->alter_info.reset(); Lex->alter_info.reset();
Lex->no_write_to_binlog= 0; Lex->no_write_to_binlog= 0;
@ -7367,6 +7381,8 @@ alter_commands:
| DROP PARTITION_SYM opt_if_exists alt_part_name_list | DROP PARTITION_SYM opt_if_exists alt_part_name_list
{ {
Lex->alter_info.flags|= Alter_info::ALTER_DROP_PARTITION; Lex->alter_info.flags|= Alter_info::ALTER_DROP_PARTITION;
DBUG_ASSERT(!Lex->if_exists());
Lex->create_info.add($3);
} }
| REBUILD_SYM PARTITION_SYM opt_no_write_to_binlog | REBUILD_SYM PARTITION_SYM opt_no_write_to_binlog
all_or_alt_part_name_list all_or_alt_part_name_list
@ -7484,7 +7500,8 @@ all_or_alt_part_name_list:
; ;
add_partition_rule: add_partition_rule:
ADD PARTITION_SYM opt_if_not_exists opt_no_write_to_binlog ADD PARTITION_SYM opt_if_not_exists
opt_no_write_to_binlog
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->part_info= new partition_info(); lex->part_info= new partition_info();
@ -7494,6 +7511,8 @@ add_partition_rule:
MYSQL_YYABORT; MYSQL_YYABORT;
} }
lex->alter_info.flags|= Alter_info::ALTER_ADD_PARTITION; lex->alter_info.flags|= Alter_info::ALTER_ADD_PARTITION;
DBUG_ASSERT(!Lex->create_info.if_not_exists());
lex->create_info.set($3);
lex->no_write_to_binlog= $4; lex->no_write_to_binlog= $4;
} }
add_part_extra add_part_extra
@ -7570,7 +7589,7 @@ alter_list:
; ;
add_column: add_column:
ADD opt_column opt_if_not_exists ADD opt_column opt_if_not_exists_table_element
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN; lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN;
@ -7592,19 +7611,21 @@ alter_list_item:
Lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN | Lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN |
Alter_info::ALTER_ADD_INDEX; Alter_info::ALTER_ADD_INDEX;
} }
| CHANGE opt_column opt_if_exists field_ident field_spec opt_place | CHANGE opt_column opt_if_exists_table_element field_ident
field_spec opt_place
{ {
Lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN; Lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
Lex->create_last_non_select_table= Lex->last_table(); Lex->create_last_non_select_table= Lex->last_table();
Lex->last_field->change= $4.str; Lex->last_field->change= $4.str;
} }
| MODIFY_SYM opt_column opt_if_exists field_spec opt_place | MODIFY_SYM opt_column opt_if_exists_table_element
field_spec opt_place
{ {
Lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN; Lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
Lex->create_last_non_select_table= Lex->last_table(); Lex->create_last_non_select_table= Lex->last_table();
Lex->last_field->change= Lex->last_field->field_name; Lex->last_field->change= Lex->last_field->field_name;
} }
| DROP opt_column opt_if_exists field_ident opt_restrict | DROP opt_column opt_if_exists_table_element field_ident opt_restrict
{ {
LEX *lex=Lex; LEX *lex=Lex;
Alter_drop *ad= new Alter_drop(Alter_drop::COLUMN, $4.str, $3); Alter_drop *ad= new Alter_drop(Alter_drop::COLUMN, $4.str, $3);
@ -7613,7 +7634,7 @@ alter_list_item:
lex->alter_info.drop_list.push_back(ad); lex->alter_info.drop_list.push_back(ad);
lex->alter_info.flags|= Alter_info::ALTER_DROP_COLUMN; lex->alter_info.flags|= Alter_info::ALTER_DROP_COLUMN;
} }
| DROP FOREIGN KEY_SYM opt_if_exists field_ident | DROP FOREIGN KEY_SYM opt_if_exists_table_element field_ident
{ {
LEX *lex=Lex; LEX *lex=Lex;
Alter_drop *ad= new Alter_drop(Alter_drop::FOREIGN_KEY, $5.str, $4); Alter_drop *ad= new Alter_drop(Alter_drop::FOREIGN_KEY, $5.str, $4);
@ -7632,7 +7653,7 @@ alter_list_item:
lex->alter_info.drop_list.push_back(ad); lex->alter_info.drop_list.push_back(ad);
lex->alter_info.flags|= Alter_info::ALTER_DROP_INDEX; lex->alter_info.flags|= Alter_info::ALTER_DROP_INDEX;
} }
| DROP key_or_index opt_if_exists field_ident | DROP key_or_index opt_if_exists_table_element field_ident
{ {
LEX *lex=Lex; LEX *lex=Lex;
Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $4.str, $3); Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $4.str, $3);
@ -11755,15 +11776,13 @@ drop:
DROP opt_temporary table_or_tables opt_if_exists DROP opt_temporary table_or_tables opt_if_exists
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command = SQLCOM_DROP_TABLE; lex->set_command(SQLCOM_DROP_TABLE, $2, $4);
lex->drop_temporary= $2;
lex->check_exists= $4;
YYPS->m_lock_type= TL_UNLOCK; YYPS->m_lock_type= TL_UNLOCK;
YYPS->m_mdl_type= MDL_EXCLUSIVE; YYPS->m_mdl_type= MDL_EXCLUSIVE;
} }
table_list opt_restrict table_list opt_restrict
{} {}
| DROP INDEX_SYM opt_if_exists ident ON table_ident {} | DROP INDEX_SYM opt_if_exists_table_element ident ON table_ident {}
{ {
LEX *lex=Lex; LEX *lex=Lex;
Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $4.str, $3); Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $4.str, $3);
@ -11782,8 +11801,7 @@ drop:
| DROP DATABASE opt_if_exists ident | DROP DATABASE opt_if_exists ident
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command= SQLCOM_DROP_DB; lex->set_command(SQLCOM_DROP_DB, $3);
lex->check_exists=$3;
lex->name= $4; lex->name= $4;
} }
| DROP FUNCTION_SYM opt_if_exists ident '.' ident | DROP FUNCTION_SYM opt_if_exists ident '.' ident
@ -11800,8 +11818,7 @@ drop:
my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"); my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
MYSQL_YYABORT; MYSQL_YYABORT;
} }
lex->sql_command = SQLCOM_DROP_FUNCTION; lex->set_command(SQLCOM_DROP_FUNCTION, $3);
lex->check_exists= $3;
spname= new sp_name($4, $6, true); spname= new sp_name($4, $6, true);
if (spname == NULL) if (spname == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
@ -11820,8 +11837,7 @@ drop:
} }
if (thd->db && lex->copy_db_to(&db.str, &db.length)) if (thd->db && lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sql_command = SQLCOM_DROP_FUNCTION; lex->set_command(SQLCOM_DROP_FUNCTION, $3);
lex->check_exists= $3;
spname= new sp_name(db, $4, false); spname= new sp_name(db, $4, false);
if (spname == NULL) if (spname == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
@ -11836,8 +11852,7 @@ drop:
my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"); my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
MYSQL_YYABORT; MYSQL_YYABORT;
} }
lex->sql_command = SQLCOM_DROP_PROCEDURE; lex->set_command(SQLCOM_DROP_PROCEDURE, $3);
lex->check_exists= $3;
lex->spname= $4; lex->spname= $4;
} }
| DROP USER clear_privileges user_list | DROP USER clear_privileges user_list
@ -11851,8 +11866,7 @@ drop:
| DROP VIEW_SYM opt_if_exists | DROP VIEW_SYM opt_if_exists
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_DROP_VIEW; lex->set_command(SQLCOM_DROP_VIEW, $3);
lex->check_exists= $3;
YYPS->m_lock_type= TL_UNLOCK; YYPS->m_lock_type= TL_UNLOCK;
YYPS->m_mdl_type= MDL_EXCLUSIVE; YYPS->m_mdl_type= MDL_EXCLUSIVE;
} }
@ -11860,15 +11874,13 @@ drop:
{} {}
| DROP EVENT_SYM opt_if_exists sp_name | DROP EVENT_SYM opt_if_exists sp_name
{ {
Lex->check_exists= $3;
Lex->spname= $4; Lex->spname= $4;
Lex->sql_command = SQLCOM_DROP_EVENT; Lex->set_command(SQLCOM_DROP_EVENT, $3);
} }
| DROP TRIGGER_SYM opt_if_exists sp_name | DROP TRIGGER_SYM opt_if_exists sp_name
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_DROP_TRIGGER; lex->set_command(SQLCOM_DROP_TRIGGER, $3);
lex->check_exists= $3;
lex->spname= $4; lex->spname= $4;
} }
| DROP TABLESPACE tablespace_name opt_ts_engine opt_ts_wait | DROP TABLESPACE tablespace_name opt_ts_engine opt_ts_wait
@ -11883,8 +11895,7 @@ drop:
} }
| DROP SERVER_SYM opt_if_exists ident_or_text | DROP SERVER_SYM opt_if_exists ident_or_text
{ {
Lex->sql_command = SQLCOM_DROP_SERVER; Lex->set_command(SQLCOM_DROP_SERVER, $3);
Lex->check_exists= $3;
Lex->server_options.reset($4); Lex->server_options.reset($4);
} }
; ;
@ -11934,7 +11945,7 @@ table_alias_ref:
} }
; ;
opt_if_exists: opt_if_exists_table_element:
/* empty */ /* empty */
{ {
Lex->check_exists= FALSE; Lex->check_exists= FALSE;
@ -11947,9 +11958,20 @@ opt_if_exists:
} }
; ;
opt_if_exists:
/* empty */
{
$$.set(DDL_options_st::OPT_NONE);
}
| IF_SYM EXISTS
{
$$.set(DDL_options_st::OPT_IF_EXISTS);
}
;
opt_temporary: opt_temporary:
/* empty */ { $$= 0; } /* empty */ { $$= 0; }
| TEMPORARY { $$= 1; } | TEMPORARY { $$= HA_LEX_CREATE_TMP_TABLE;; }
; ;
/* /*
** Insert : add new data to table ** Insert : add new data to table
@ -12418,7 +12440,7 @@ show:
lex->ident=null_lex_str; lex->ident=null_lex_str;
mysql_init_select(lex); mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST; lex->current_select->parsing_place= SELECT_LIST;
bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.init();
} }
show_param show_param
{ {
@ -12620,8 +12642,7 @@ show_param:
} }
| CREATE DATABASE opt_if_not_exists ident | CREATE DATABASE opt_if_not_exists ident
{ {
Lex->sql_command=SQLCOM_SHOW_CREATE_DB; Lex->set_command(SQLCOM_SHOW_CREATE_DB, $3);
Lex->create_info.options=$3;
Lex->name= $4; Lex->name= $4;
} }
| CREATE TABLE_SYM table_ident | CREATE TABLE_SYM table_ident

View File

@ -471,4 +471,79 @@ public:
Discrete_interval* get_current() const { return current; }; Discrete_interval* get_current() const { return current; };
}; };
/*
DDL options:
- CREATE IF NOT EXISTS
- DROP IF EXISTS
- CRESTE LIKE
- REPLACE
*/
struct DDL_options_st
{
public:
enum Options
{
OPT_NONE= 0,
OPT_IF_NOT_EXISTS= 2, // CREATE TABLE IF NOT EXISTS
OPT_LIKE= 4, // CREATE TABLE LIKE
OPT_OR_REPLACE= 16, // CREATE OR REPLACE TABLE
OPT_OR_REPLACE_SLAVE_GENERATED= 32,// REPLACE was added on slave, it was
// not in the original query on master.
OPT_IF_EXISTS= 64
};
private:
Options m_options;
public:
Options create_like_options() const
{
return (DDL_options_st::Options)
(((uint) m_options) & (OPT_IF_NOT_EXISTS | OPT_OR_REPLACE));
}
void init() { m_options= OPT_NONE; }
void init(Options options) { m_options= options; }
void set(Options other)
{
m_options= other;
}
void set(const DDL_options_st other)
{
m_options= other.m_options;
}
bool if_not_exists() const { return m_options & OPT_IF_NOT_EXISTS; }
bool or_replace() const { return m_options & OPT_OR_REPLACE; }
bool or_replace_slave_generated() const
{ return m_options & OPT_OR_REPLACE_SLAVE_GENERATED; }
bool like() const { return m_options & OPT_LIKE; }
bool if_exists() const { return m_options & OPT_IF_EXISTS; }
void add(const DDL_options_st::Options other)
{
m_options= (Options) ((uint) m_options | (uint) other);
}
void add(const DDL_options_st &other)
{
add(other.m_options);
}
DDL_options_st operator|(const DDL_options_st &other)
{
add(other.m_options);
return *this;
}
DDL_options_st operator|=(DDL_options_st::Options other)
{
add(other);
return *this;
}
};
class DDL_options: public DDL_options_st
{
public:
DDL_options() { init(); }
};
#endif /* STRUCTS_INCLUDED */ #endif /* STRUCTS_INCLUDED */

View File

@ -2080,7 +2080,7 @@ static bool sql_unusable_for_discovery(THD *thd, handlerton *engine,
if (lex->sql_command != SQLCOM_CREATE_TABLE) if (lex->sql_command != SQLCOM_CREATE_TABLE)
return 1; return 1;
// ... create like // ... create like
if (create_info->options & HA_LEX_CREATE_TABLE_LIKE) if (lex->create_info.like())
return 1; return 1;
// ... create select // ... create select
if (lex->select_lex.item_list.elements) if (lex->select_lex.item_list.elements)
@ -2089,7 +2089,7 @@ static bool sql_unusable_for_discovery(THD *thd, handlerton *engine,
if (create_info->tmp_table()) if (create_info->tmp_table())
return 1; return 1;
// ... if exists // ... if exists
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) if (lex->create_info.if_not_exists())
return 1; return 1;
// XXX error out or rather ignore the following: // XXX error out or rather ignore the following:

View File

@ -2371,7 +2371,7 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
break; break;
} }
} }
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) if (create_info->tmp_table())
{ {
/* CREATE TEMPORARY TABLE LIKE must be skipped from replication */ /* CREATE TEMPORARY TABLE LIKE must be skipped from replication */