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_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_LEX_CREATE_REPLACE 16
#define HA_MAX_REC_LENGTH 65535
/* 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_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_STRING connect_string;
const char *password, *tablespace;
@ -1602,7 +1632,6 @@ struct HA_CREATE_INFO
uint stats_sample_pages;
uint null_bits; /* NULL bits at start of record */
uint options; /* OR of HA_CREATE_ options */
uint org_options; /* original options from query */
uint merge_insert_method;
uint extra_size; /* length of extra data segment */
SQL_I_List<TABLE_LIST> merge_list;
@ -1635,7 +1664,11 @@ struct HA_CREATE_INFO
MDL_ticket *mdl_ticket;
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)
{
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.

View File

@ -3188,13 +3188,13 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
switch (lex->sql_command)
{
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;
case SQLCOM_CREATE_TABLE:
trx_cache= (lex->select_lex.item_list.elements &&
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;
break;
case SQLCOM_SET_OPTION:
@ -4335,7 +4335,8 @@ compare_errors:
has already been dropped. To ignore such irrelevant "table does
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 &&
!expected_error)
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;
break;
case SQLCOM_CREATE_TABLE:
if (lex->create_info.tmp_table())
if (lex->tmp_table())
flags= 0;
else
flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
break;
case SQLCOM_DROP_TABLE:
if (lex->drop_temporary)
if (lex->tmp_table())
flags= 0;
else
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;
if (lex_for_tmp_check->sql_command == SQLCOM_DROP_TABLE &&
lex_for_tmp_check->drop_temporary)
lex_for_tmp_check->tmp_table())
return TRUE;
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;
if (lex_for_tmp_check->sql_command == SQLCOM_CREATE_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->qname.length= temp_table_key_length;

View File

@ -3453,7 +3453,8 @@ Open_table_context::recover_from_failed_open()
break;
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)))
break;
@ -3484,7 +3485,8 @@ Open_table_context::recover_from_failed_open()
}
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)))
break;
@ -4132,7 +4134,7 @@ extern "C" uchar *schema_set_get_key(const TABLE_LIST *table, size_t *length,
*/
bool
lock_table_names(THD *thd,
lock_table_names(THD *thd, const DDL_options_st &options,
TABLE_LIST *tables_start, TABLE_LIST *tables_end,
ulong lock_wait_timeout, uint flags)
{
@ -4176,8 +4178,8 @@ lock_table_names(THD *thd,
DBUG_RETURN(FALSE);
/* Check if CREATE TABLE without REPLACE was used */
create_table= (thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
!(thd->lex->create_info.options & HA_LEX_CREATE_REPLACE));
create_table= thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
!options.or_replace();
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 (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,
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
@ -4344,8 +4346,9 @@ open_tables_check_upgradable_mdl(THD *thd, TABLE_LIST *tables_start,
@retval TRUE Error, reported.
*/
bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
Prelocking_strategy *prelocking_strategy)
bool open_tables(THD *thd, const DDL_options_st &options,
TABLE_LIST **start, uint *counter, uint flags,
Prelocking_strategy *prelocking_strategy)
{
/*
We use pointers to "next_global" member in the last processed
@ -4434,7 +4437,8 @@ restart:
else
{
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))
{
error= TRUE;
@ -5117,7 +5121,8 @@ end:
@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,
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_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;
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);
int setup_ftfuncs(SELECT_LEX* select);
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,
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);
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 */
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,
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 */
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
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
open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags)
{
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,
@ -478,12 +514,23 @@ inline TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
/* open_and_lock_tables with derived handling */
inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
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, tables, derived, flags,
return open_and_lock_tables(thd, options, tables, derived, flags,
&prelocking_strategy);
}
inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
bool derived, uint flags)
{
DML_prelocking_strategy prelocking_strategy;
return open_and_lock_tables(thd, thd->lex->create_info,
tables, derived, flags,
&prelocking_strategy);
}

View File

@ -5464,8 +5464,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
flags_access_some_set |= flags;
if (lex->sql_command != SQLCOM_CREATE_TABLE ||
(lex->sql_command == SQLCOM_CREATE_TABLE &&
lex->create_info.tmp_table()))
(lex->sql_command == SQLCOM_CREATE_TABLE && lex->tmp_table()))
{
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 {
ORDER *group;
TABLE_LIST *create_table;
HA_CREATE_INFO *create_info;
Table_specification_st *create_info;
TABLE_LIST *select_tables;
Alter_info *alter_info;
Field **field;
@ -4230,7 +4230,7 @@ class select_create: public select_insert {
public:
select_create (TABLE_LIST *table_arg,
HA_CREATE_INFO *create_info_par,
Table_specification_st *create_info_par,
Alter_info *alter_info_arg,
List<Item> &select_fields,enum_duplicates duplic, bool ignore,
TABLE_LIST *select_tables_arg)

View File

@ -233,7 +233,7 @@ void my_dbopt_cleanup(void)
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;
uint length;
@ -264,7 +264,7 @@ static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
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;
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()
*/
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;
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;
char buf[256];
@ -491,7 +492,7 @@ err1:
*/
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];
@ -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)
{
HA_CREATE_INFO db_info;
Schema_specification_st db_info;
if (thd->db != NULL && strcmp(db_name, thd->db) == 0)
return thd->db_charset;
@ -545,6 +546,7 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
thd Thread handler
db Name of database to create
Function assumes that this is already validated.
options DDL options, e.g. IF NOT EXISTS
create_info Database create options (like character set)
silent Used by replication when internally creating a database.
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,
bool silent)
int mysql_create_db(THD *thd, char *db,
const DDL_options_st &options,
Schema_specification_st *create_info,
bool silent)
{
char path[FN_REFLEN+16];
long result= 1;
int error= 0;
MY_STAT stat_info;
uint create_options= create_info ? create_info->options : 0;
uint path_len;
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 (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
if (!options.if_not_exists())
{
my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
error= -1;
@ -702,7 +705,8 @@ exit:
/* 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];
long result=1;
@ -773,7 +777,7 @@ exit:
@retval true Error
*/
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)
{
ulong deleted_tables= 0;
bool error= true;
@ -1602,7 +1606,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
int error= 0, change_to_newdb= 0;
char path[FN_REFLEN+16];
uint length;
HA_CREATE_INFO create_info;
Schema_specification_st create_info;
MY_DIR *dirp;
TABLE_LIST *table_list;
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 */
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;
/* Step2: Move tables to the new database */

View File

@ -20,9 +20,12 @@
class THD;
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
int mysql_create_db(THD *thd, char *db,
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_upgrade_db(THD *thd, LEX_STRING *old_db);
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
bool force_switch);
@ -35,9 +38,9 @@ bool mysql_opt_change_db(THD *thd,
bool my_dboptions_cache_init(void);
void my_dboptions_cache_free(void);
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,
HA_CREATE_INFO *db_create_info);
Schema_specification_st *db_create_info);
CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name);
bool my_dbopt_init(void);
void my_dbopt_cleanup(void);

View File

@ -3856,7 +3856,8 @@ void select_insert::abort_result_set() {
@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,
Alter_info *alter_info,
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
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() &&
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");
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,
&extra_lock, hook_ptr)))
/* abort() deletes table */
@ -4193,8 +4195,8 @@ select_create::binlog_show_create_table(TABLE **tables, uint count)
tmp_table_list.table = *tables;
query.length(0); // Have to zero it since constructor doesn't
result= show_create_table(thd, &tmp_table_list, &query, create_info,
WITH_DB_NAME);
result= show_create_table(thd, &tmp_table_list, &query,
create_info, WITH_DB_NAME);
DBUG_ASSERT(result == 0); /* show_create_table() always return 0 */
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->parse_vcol_expr= FALSE;
lex->check_exists= FALSE;
lex->create_info.lex_start();
lex->verbose= 0;
lex->name= null_lex_str;

View File

@ -2456,7 +2456,7 @@ struct LEX: public Query_tables_list
Item_sum *in_sum_func;
udf_func udf;
HA_CHECK_OPT check_opt; // check/repair options
HA_CREATE_INFO create_info;
Table_specification_st create_info;
KEY_CREATE_INFO key_create_info;
LEX_MASTER_INFO mi; // used by CHANGE MASTER
LEX_SERVER_OPTIONS server_options;
@ -2536,7 +2536,7 @@ struct LEX: public Query_tables_list
uint16 create_view_algorithm;
uint8 create_view_check;
uint8 context_analysis_only;
bool drop_temporary, local_file;
bool local_file;
bool check_exists;
bool autocommit;
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 set_last_field_type(enum enum_field_types type);
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) {
case SQLCOM_DROP_TABLE:
skip= (lex->drop_temporary ||
skip= (lex->tmp_table() ||
(thd->variables.option_bits & OPTION_GTID_BEGIN));
break;
case SQLCOM_ALTER_TABLE:
/* If ALTER TABLE of non-temporary table, do implicit commit */
skip= (lex->create_info.tmp_table());
skip= (lex->tmp_table());
break;
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
master and slave.
*/
skip= (lex->create_info.tmp_table() ||
skip= (lex->tmp_table() ||
(thd->variables.option_bits & OPTION_GTID_BEGIN));
break;
case SQLCOM_SET_OPTION:
@ -1165,12 +1165,10 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
DBUG_RETURN(FALSE);
const my_bool create_temp_tables=
(lex->sql_command == SQLCOM_CREATE_TABLE) &&
lex->create_info.tmp_table();
(lex->sql_command == SQLCOM_CREATE_TABLE) && lex->tmp_table();
const my_bool drop_temp_tables=
(lex->sql_command == SQLCOM_DROP_TABLE) &&
lex->drop_temporary;
(lex->sql_command == SQLCOM_DROP_TABLE) && lex->tmp_table();
const my_bool update_real_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) &&
!(lex->sql_command == SQLCOM_SET_OPTION) &&
!(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))
{
/* 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
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
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
retrying the create.
*/
create_info.org_options= create_info.options;
if (thd->slave_thread &&
slave_ddl_exec_mode_options == SLAVE_EXEC_MODE_IDEMPOTENT &&
!(lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS))
create_info.options|= HA_LEX_CREATE_REPLACE;
!lex->create_info.if_not_exists())
{
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
{
@ -3289,7 +3289,7 @@ mysql_execute_command(THD *thd)
/* Copy temporarily the statement flags to thd for lock_table_names() */
uint save_thd_create_info_options= thd->lex->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;
if (res)
{
@ -3300,8 +3300,7 @@ mysql_execute_command(THD *thd)
}
/* Ensure we don't try to create something from which we select from */
if ((create_info.options & HA_LEX_CREATE_REPLACE) &&
!create_info.tmp_table())
if (create_info.or_replace() && !create_info.tmp_table())
{
TABLE_LIST *duplicate;
if ((duplicate= unique_table(thd, lex->query_tables,
@ -3354,7 +3353,7 @@ mysql_execute_command(THD *thd)
else
{
/* regular create */
if (create_info.options & HA_LEX_CREATE_TABLE_LIKE)
if (create_info.like())
{
/* CREATE TABLE ... LIKE ... */
res= mysql_create_like_table(thd, create_table, select_tables,
@ -3366,13 +3365,12 @@ mysql_execute_command(THD *thd)
tables, like mysql replication does
*/
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)
}
/* Regular CREATE TABLE */
res= mysql_create_table(thd, create_table,
&create_info, &alter_info);
res= mysql_create_table(thd, create_table, &create_info, &alter_info);
}
if (!res)
{
@ -4076,7 +4074,7 @@ end_with_restore_list:
case SQLCOM_DROP_TABLE:
{
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))
goto error; /* purecov: inspected */
@ -4090,7 +4088,7 @@ end_with_restore_list:
{
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() ||
!find_temporary_table(thd, table)))
{
@ -4107,11 +4105,10 @@ end_with_restore_list:
*/
if (thd->slave_thread && !thd->slave_expected_error &&
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. */
res= mysql_rm_table(thd, first_table, lex->check_exists,
lex->drop_temporary);
res= mysql_rm_table(thd, first_table, lex->if_exists(), lex->tmp_table());
break;
}
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
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))
{
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))
break;
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;
}
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))
break;
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;
}
case SQLCOM_ALTER_DB_UPGRADE:
@ -4422,7 +4419,7 @@ end_with_restore_list:
my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
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;
}
case SQLCOM_CREATE_EVENT:
@ -4445,8 +4442,7 @@ end_with_restore_list:
switch (lex->sql_command) {
case SQLCOM_CREATE_EVENT:
{
bool if_not_exists= (lex->create_info.options &
HA_LEX_CREATE_IF_NOT_EXISTS);
bool if_not_exists= lex->create_info.if_not_exists();
res= Events::create_event(thd, lex->event_parse_data, if_not_exists);
break;
}
@ -4479,7 +4475,7 @@ end_with_restore_list:
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
if (!(res= Events::drop_event(thd,
lex->spname->m_db, lex->spname->m_name,
lex->check_exists)))
lex->if_exists())))
my_ok(thd);
break;
#else
@ -5192,7 +5188,7 @@ create_sp_error:
if (lex->spname->m_db.str == NULL)
{
if (lex->check_exists)
if (lex->if_exists())
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
@ -5262,7 +5258,7 @@ create_sp_error:
my_ok(thd);
break;
case SP_KEY_NOT_FOUND:
if (lex->check_exists)
if (lex->if_exists())
{
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
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 (! 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",
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;
if (lex->create_info.tmp_table())
if (lex->tmp_table())
create_table->open_type= OT_TEMPORARY_ONLY;
else
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.
*/
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 OR REPLACE on not temporary tables require DROP_ACL */
if ((lex->create_info.options & HA_LEX_CREATE_REPLACE) &&
!lex->create_info.tmp_table())
if (lex->create_info.or_replace() && !lex->tmp_table())
want_priv|= DROP_ACL;
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))
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))
goto err;

View File

@ -1187,7 +1187,7 @@ exit:
bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname,
LEX_STRING *orig_dbname,
HA_CREATE_INFO *create_info)
const DDL_options_st &options)
{
char buff[2048];
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;
#endif
HA_CREATE_INFO create;
uint create_options = create_info ? create_info->options : 0;
Protocol *protocol=thd->protocol;
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);
buffer.length(0);
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*/ "));
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,
HA_CREATE_INFO *create_info_arg,
Table_specification_st *create_info_arg,
enum_with_db_name with_db_name)
{
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 "));
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))
packet->append(STRING_WITH_LEN("OR REPLACE "));
if (share->tmp_table)
packet->append(STRING_WITH_LEN("TEMPORARY "));
packet->append(STRING_WITH_LEN("TABLE "));
if (create_info_arg &&
(create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
if (create_info_arg && create_info_arg->if_not_exists())
packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
if (table_list->schema_table)
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;
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);
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_db(THD *thd, LEX_STRING *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);
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 *db, const char *table_name,
const char *path,
const DDL_options_st options,
HA_CREATE_INFO *create_info,
Alter_info *alter_info,
int create_table_mode,
@ -4661,7 +4662,7 @@ int create_table_impl(THD *thd,
if ((tmp_table= find_temporary_table(thd, db, table_name)))
{
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;
/*
@ -4671,7 +4672,7 @@ int create_table_impl(THD *thd,
if (drop_temporary_table(thd, tmp_table, &is_trans))
goto err;
}
else if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
else if (options.if_not_exists())
goto warn;
else
{
@ -4697,7 +4698,7 @@ int create_table_impl(THD *thd,
{
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.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))
goto err;
}
else if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
else if (options.if_not_exists())
goto warn;
else
{
@ -4889,7 +4890,7 @@ warn:
int mysql_create_table_no_lock(THD *thd,
const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
Table_specification_st *create_info,
Alter_info *alter_info, bool *is_trans,
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,
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);
my_free(const_cast<uchar*>(frm.str));
return res;
@ -4933,7 +4935,7 @@ int mysql_create_table_no_lock(THD *thd,
*/
bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
HA_CREATE_INFO *create_info,
Table_specification_st *create_info,
Alter_info *alter_info)
{
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;
/* 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;
@ -4989,7 +4991,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
on a non temporary table
*/
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
@ -5230,9 +5232,9 @@ mysql_rename_table(handlerton *base, const char *old_db,
bool mysql_create_like_table(THD* thd, TABLE_LIST* 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;
Alter_info local_alter_info;
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() */
// QQ: is this really needed???
uint save_thd_create_info_options= thd->lex->create_info.options;
thd->lex->create_info.options|= create_info->options;
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;
}
/* Ensure we don't try to create something from which we select from */
if ((create_info->options & HA_LEX_CREATE_REPLACE) &&
!create_info->tmp_table())
if (create_info->or_replace() && !create_info->tmp_table())
{
TABLE_LIST *duplicate;
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");
/* 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.row_type= src_table->table->s->row_type;
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)
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. */
local_create_info.options&= ~HA_LEX_CREATE_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
*/
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
@ -5454,7 +5456,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
if (!table->view)
{
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
do_logging= FALSE;
@ -5907,10 +5910,11 @@ remove_key:
#ifdef WITH_PARTITION_STORAGE_ENGINE
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 */
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;
if (alt_part_info)
@ -5932,7 +5936,8 @@ remove_key:
}
}
/* 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);
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.new_db, alter_ctx.tmp_name,
alter_ctx.get_tmp_path(),
create_info, alter_info,
thd->lex->create_info, create_info, alter_info,
C_ALTER_TABLE_FRM_ONLY, NULL,
&key_info, &key_count, &frm);
reenable_binlog(thd);

View File

@ -31,6 +31,7 @@ struct handlerton;
class handler;
typedef struct st_ha_check_opt HA_CHECK_OPT;
struct HA_CREATE_INFO;
struct Table_specification_st;
typedef struct st_key KEY;
typedef struct st_key_cache KEY_CACHE;
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);
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen);
bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
HA_CREATE_INFO *create_info,
Table_specification_st *create_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,
const char *table_name,
HA_CREATE_INFO *create_info,
Table_specification_st *create_info,
Alter_info *alter_info, bool *is_trans,
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_create_like_table(THD *thd, TABLE_LIST *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,
const char * old_name, const char *new_db,
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)
{
bool if_exists= thd->lex->check_exists;
bool if_exists= thd->lex->if_exists();
/*
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];
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,
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,
const LEX_STRING &name,
bool check_exists,
KEY_CREATE_INFO *info= NULL, bool generated= 0)
{
Key *key;
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)
return TRUE;
@ -1010,6 +1011,7 @@ bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin)
enum sp_variable::enum_mode spvar_mode;
enum thr_lock_type lock_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
NCHAR_STRING opt_component key_cache_name
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>
opt_table_alias
@ -1736,8 +1739,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <num>
order_dir lock_option
udf_type opt_if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists create_or_replace opt_no_write_to_binlog
udf_type opt_local opt_table_options table_options
table_option opt_no_write_to_binlog
opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options union_option
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_default_time_precision
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.
@ -2459,25 +2468,20 @@ create:
create_or_replace opt_table_options TABLE_SYM opt_if_not_exists table_ident
{
LEX *lex= thd->lex;
lex->sql_command= SQLCOM_CREATE_TABLE;
if ($1 && $4)
{
my_error(ER_WRONG_USAGE, MYF(0), "OR REPLACE", "IF NOT EXISTS");
lex->create_info.init();
if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4))
MYSQL_YYABORT;
}
if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
TL_OPTION_UPDATING,
TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
lex->alter_info.reset();
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.
If the table exists, we should either not create it or replace it
*/
lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
lex->create_info.options= ($1 | $2 | $4);
lex->create_info.default_table_charset= NULL;
lex->name= null_lex_str;
lex->create_last_non_select_table= lex->last_table();
@ -2505,7 +2509,7 @@ create:
}
'(' 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;
}
opt_index_lock_algorithm { }
@ -2517,11 +2521,12 @@ create:
}
'(' 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;
}
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
{
if (add_create_index_prepare(Lex, $8))
@ -2529,7 +2534,7 @@ create:
}
'(' 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;
}
opt_index_lock_algorithm { }
@ -2541,20 +2546,19 @@ create:
opt_create_database_options
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_CREATE_DB;
lex->set_command(SQLCOM_CREATE_DB, $3);
lex->name= $4;
lex->create_info.options=$3;
}
| create_or_replace
{
Lex->create_view_mode= ($1 == 0 ? VIEW_CREATE_NEW :
VIEW_CREATE_OR_REPLACE);
Lex->create_view_mode= ($1.or_replace() ? VIEW_CREATE_OR_REPLACE :
VIEW_CREATE_NEW);
Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED;
Lex->create_view_suid= TRUE;
}
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",
"TRIGGERS / SP / EVENT");
@ -2639,7 +2643,7 @@ event_tail:
LEX *lex=Lex;
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)))
MYSQL_YYABORT;
lex->event_parse_data->identifier= $4;
@ -4821,7 +4825,7 @@ create_body:
| 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,
$1, NULL, 0, TL_READ, MDL_SHARED_READ);
if (! src_table)
@ -5614,27 +5618,36 @@ table_option:
TEMPORARY { $$=HA_LEX_CREATE_TMP_TABLE; }
;
opt_if_not_exists:
opt_if_not_exists_table_element:
/* empty */
{
Lex->check_exists= FALSE;
$$= 0;
}
| IF_SYM not EXISTS
{
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 /* empty */
{
$$= 0;
$$.init();
}
| CREATE OR_SYM REPLACE
{
$$= HA_LEX_CREATE_REPLACE;
$$.set(DDL_options_st::OPT_OR_REPLACE);
}
;
@ -6019,38 +6032,40 @@ column_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; }
normal_key_options
{
if (add_create_index (Lex, $1, $2))
if (add_create_index (Lex, $1, $2, Lex->check_exists))
MYSQL_YYABORT;
}
| fulltext opt_key_or_index opt_if_not_exists_ident init_key_options
'(' key_list ')'
| fulltext opt_key_or_index opt_if_not_exists_opt_table_element_name
init_key_options '(' key_list ')'
{ Lex->option_list= NULL; }
fulltext_key_options
{
if (add_create_index (Lex, $1, $3))
if (add_create_index (Lex, $1, $3, Lex->check_exists))
MYSQL_YYABORT;
}
| spatial opt_key_or_index opt_if_not_exists_ident init_key_options
'(' key_list ')'
| spatial opt_key_or_index opt_if_not_exists_opt_table_element_name
init_key_options '(' key_list ')'
{ Lex->option_list= NULL; }
spatial_key_options
{
if (add_create_index (Lex, $1, $3))
if (add_create_index (Lex, $1, $3, Lex->check_exists))
MYSQL_YYABORT;
}
| opt_constraint constraint_key_type opt_if_not_exists_ident key_alg
'(' key_list ')'
| opt_constraint constraint_key_type
opt_if_not_exists_opt_table_element_name key_alg '(' key_list ')'
{ Lex->option_list= NULL; }
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;
}
| 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;
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->option_list= NULL;
if (add_create_index (lex, Key::MULTIPLE, $1.str ? $1 : $4,
Lex->check_exists,
&default_key_create_info, 1))
MYSQL_YYABORT;
/* Only used for ALTER TABLE. Ignored otherwise. */
@ -7084,8 +7100,8 @@ opt_ident:
| field_ident { $$= $1; }
;
opt_if_not_exists_ident:
opt_if_not_exists opt_ident
opt_if_not_exists_opt_table_element_name:
opt_if_not_exists_table_element opt_ident
{
LEX *lex= Lex;
if (lex->check_exists && lex->sql_command != SQLCOM_ALTER_TABLE)
@ -7117,9 +7133,7 @@ alter:
Lex->duplicates= DUP_ERROR;
Lex->col_list.empty();
Lex->select_lex.init_order();
bzero(&Lex->create_info, sizeof(Lex->create_info));
Lex->create_info.db_type= 0;
Lex->create_info.default_table_charset= NULL;
Lex->create_info.init();
Lex->create_info.row_type= ROW_TYPE_NOT_USED;
Lex->alter_info.reset();
Lex->no_write_to_binlog= 0;
@ -7367,6 +7381,8 @@ alter_commands:
| DROP PARTITION_SYM opt_if_exists alt_part_name_list
{
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
all_or_alt_part_name_list
@ -7484,7 +7500,8 @@ all_or_alt_part_name_list:
;
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->part_info= new partition_info();
@ -7494,6 +7511,8 @@ add_partition_rule:
MYSQL_YYABORT;
}
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;
}
add_part_extra
@ -7570,7 +7589,7 @@ alter_list:
;
add_column:
ADD opt_column opt_if_not_exists
ADD opt_column opt_if_not_exists_table_element
{
LEX *lex=Lex;
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 |
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->create_last_non_select_table= Lex->last_table();
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->create_last_non_select_table= Lex->last_table();
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;
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.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;
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.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;
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
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_DROP_TABLE;
lex->drop_temporary= $2;
lex->check_exists= $4;
lex->set_command(SQLCOM_DROP_TABLE, $2, $4);
YYPS->m_lock_type= TL_UNLOCK;
YYPS->m_mdl_type= MDL_EXCLUSIVE;
}
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;
Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $4.str, $3);
@ -11782,8 +11801,7 @@ drop:
| DROP DATABASE opt_if_exists ident
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_DROP_DB;
lex->check_exists=$3;
lex->set_command(SQLCOM_DROP_DB, $3);
lex->name= $4;
}
| DROP FUNCTION_SYM opt_if_exists ident '.' ident
@ -11800,8 +11818,7 @@ drop:
my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
MYSQL_YYABORT;
}
lex->sql_command = SQLCOM_DROP_FUNCTION;
lex->check_exists= $3;
lex->set_command(SQLCOM_DROP_FUNCTION, $3);
spname= new sp_name($4, $6, true);
if (spname == NULL)
MYSQL_YYABORT;
@ -11820,8 +11837,7 @@ drop:
}
if (thd->db && lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
lex->sql_command = SQLCOM_DROP_FUNCTION;
lex->check_exists= $3;
lex->set_command(SQLCOM_DROP_FUNCTION, $3);
spname= new sp_name(db, $4, false);
if (spname == NULL)
MYSQL_YYABORT;
@ -11836,8 +11852,7 @@ drop:
my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
MYSQL_YYABORT;
}
lex->sql_command = SQLCOM_DROP_PROCEDURE;
lex->check_exists= $3;
lex->set_command(SQLCOM_DROP_PROCEDURE, $3);
lex->spname= $4;
}
| DROP USER clear_privileges user_list
@ -11851,8 +11866,7 @@ drop:
| DROP VIEW_SYM opt_if_exists
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_DROP_VIEW;
lex->check_exists= $3;
lex->set_command(SQLCOM_DROP_VIEW, $3);
YYPS->m_lock_type= TL_UNLOCK;
YYPS->m_mdl_type= MDL_EXCLUSIVE;
}
@ -11860,15 +11874,13 @@ drop:
{}
| DROP EVENT_SYM opt_if_exists sp_name
{
Lex->check_exists= $3;
Lex->spname= $4;
Lex->sql_command = SQLCOM_DROP_EVENT;
Lex->set_command(SQLCOM_DROP_EVENT, $3);
}
| DROP TRIGGER_SYM opt_if_exists sp_name
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_DROP_TRIGGER;
lex->check_exists= $3;
lex->set_command(SQLCOM_DROP_TRIGGER, $3);
lex->spname= $4;
}
| DROP TABLESPACE tablespace_name opt_ts_engine opt_ts_wait
@ -11883,8 +11895,7 @@ drop:
}
| DROP SERVER_SYM opt_if_exists ident_or_text
{
Lex->sql_command = SQLCOM_DROP_SERVER;
Lex->check_exists= $3;
Lex->set_command(SQLCOM_DROP_SERVER, $3);
Lex->server_options.reset($4);
}
;
@ -11934,7 +11945,7 @@ table_alias_ref:
}
;
opt_if_exists:
opt_if_exists_table_element:
/* empty */
{
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:
/* empty */ { $$= 0; }
| TEMPORARY { $$= 1; }
| TEMPORARY { $$= HA_LEX_CREATE_TMP_TABLE;; }
;
/*
** Insert : add new data to table
@ -12418,7 +12440,7 @@ show:
lex->ident=null_lex_str;
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.init();
}
show_param
{
@ -12620,8 +12642,7 @@ show_param:
}
| CREATE DATABASE opt_if_not_exists ident
{
Lex->sql_command=SQLCOM_SHOW_CREATE_DB;
Lex->create_info.options=$3;
Lex->set_command(SQLCOM_SHOW_CREATE_DB, $3);
Lex->name= $4;
}
| CREATE TABLE_SYM table_ident

View File

@ -471,4 +471,79 @@ public:
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 */

View File

@ -2080,7 +2080,7 @@ static bool sql_unusable_for_discovery(THD *thd, handlerton *engine,
if (lex->sql_command != SQLCOM_CREATE_TABLE)
return 1;
// ... create like
if (create_info->options & HA_LEX_CREATE_TABLE_LIKE)
if (lex->create_info.like())
return 1;
// ... create select
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())
return 1;
// ... if exists
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
if (lex->create_info.if_not_exists())
return 1;
// 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;
}
}
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
if (create_info->tmp_table())
{
/* CREATE TEMPORARY TABLE LIKE must be skipped from replication */