Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions sql/handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6421,7 +6421,8 @@ static my_bool discover_existence(THD *thd, plugin_ref plugin,
bool ha_table_exists(THD *thd, const LEX_CSTRING *db,
const LEX_CSTRING *table_name, LEX_CUSTRING *table_id,
LEX_CSTRING *partition_engine_name,
handlerton **hton, bool *is_sequence)
handlerton **hton, bool *is_sequence,
HA_CREATE_INFO *ha_create_info)
{
handlerton *dummy;
bool dummy2;
Expand Down Expand Up @@ -6475,8 +6476,17 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db,
retry_from_frm:
#endif
char path[FN_REFLEN + 1];
size_t path_len = build_table_filename(path, sizeof(path) - 1,
db->str, table_name->str, "", 0);
size_t path_len= 0;
if (ha_create_info)
{
path_len= ha_create_info->table_path.length;
strncpy(path, ha_create_info->table_path.str, path_len);
}
else
/* this happens for views */
path_len = build_table_filename(path, sizeof(path) - 1,
db->str, table_name->str, "", 0);

st_discover_existence_args args= {path, path_len, db->str, table_name->str, 0, true};

if (file_ext_exists(path, path_len, reg_ext))
Expand Down
7 changes: 5 additions & 2 deletions sql/handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2325,12 +2325,14 @@ struct HA_CREATE_INFO: public Table_scope_and_contents_source_st,
{
/* TODO: remove after MDEV-20865 */
Alter_info *alter_info;

bool table_exists;
LEX_CSTRING table_path;
void init()
{
Table_scope_and_contents_source_st::init();
Schema_specification_st::init();
alter_info= NULL;
table_exists= false;
}
ulong table_options_with_row_type()
{
Expand Down Expand Up @@ -5592,7 +5594,8 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db,
const LEX_CSTRING *table_name,
LEX_CUSTRING *table_version= 0,
LEX_CSTRING *partition_engine_name= 0,
handlerton **hton= 0, bool *is_sequence= 0);
handlerton **hton= 0, bool *is_sequence= 0,
HA_CREATE_INFO *ha_create_info= 0);
bool ha_check_if_updates_are_ignored(THD *thd, handlerton *hton,
const char *op);
#endif /* MYSQL_SERVER */
Expand Down
39 changes: 26 additions & 13 deletions sql/sql_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3455,8 +3455,9 @@ Open_table_context::recover_from_failed_open()
case OT_ADD_HISTORY_PARTITION:
DEBUG_SYNC(m_thd, "add_history_partition");
if (!m_thd->locked_tables_mode)
result= lock_table_names(m_thd, m_thd->lex->create_info, m_failed_table,
NULL, get_timeout(), 0);
result= lock_table_names(m_thd, m_thd->lex->create_info,
m_thd->lex->create_info, m_failed_table,
NULL, get_timeout(), 0);
else
{
DBUG_ASSERT(!result);
Expand Down Expand Up @@ -4275,6 +4276,7 @@ open_and_process_table(THD *thd, TABLE_LIST *tables, uint *counter, uint flags,

static bool upgrade_lock_if_not_exists(THD *thd,
const DDL_options_st &create_info,
HA_CREATE_INFO &ha_create_info,
TABLE_LIST *create_table,
ulong lock_wait_timeout)
{
Expand All @@ -4284,9 +4286,14 @@ static bool upgrade_lock_if_not_exists(THD *thd,
thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE)
{
DEBUG_SYNC(thd,"create_table_before_check_if_exists");
if (!create_info.or_replace() &&
ha_table_exists(thd, &create_table->db, &create_table->table_name,
NULL, NULL, &create_table->db_type))
/* Mark table as existed for CREATE to optimize calls of ha_table_exists
and store table path. We should not change original default handlerton
ha_create_info.db_type from `ha_table_exists`.
*/
ha_create_info.table_exists= ha_table_exists(thd, &create_table->db, &create_table->table_name,
NULL, NULL, &create_table->db_type,
NULL, &ha_create_info);
if (!create_info.or_replace() && ha_create_info.table_exists)
{
if (create_info.if_not_exists())
{
Expand Down Expand Up @@ -4339,7 +4346,7 @@ static bool upgrade_lock_if_not_exists(THD *thd,
*/

bool
lock_table_names(THD *thd, const DDL_options_st &options,
lock_table_names(THD *thd, const DDL_options_st &options, HA_CREATE_INFO &ha_opt,
TABLE_LIST *tables_start, TABLE_LIST *tables_end,
ulong lock_wait_timeout, uint flags)
{
Expand Down Expand Up @@ -4385,12 +4392,17 @@ lock_table_names(THD *thd, const DDL_options_st &options,

if (mdl_requests.is_empty())
DBUG_RETURN(FALSE);

char path[FN_REFLEN + 1];
ha_opt.table_path.length= build_table_filename(path, FN_REFLEN - 1,
tables_start->db.str,
tables_start->table_name.str,
"", 0);
lex_string_set3(&ha_opt.table_path, path, ha_opt.table_path.length);
if (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK)
{
DBUG_RETURN(thd->mdl_context.acquire_locks(&mdl_requests,
lock_wait_timeout) ||
upgrade_lock_if_not_exists(thd, options, tables_start,
upgrade_lock_if_not_exists(thd, options, ha_opt, tables_start,
lock_wait_timeout));
}

Expand All @@ -4403,7 +4415,7 @@ lock_table_names(THD *thd, const DDL_options_st &options,
mdl_savepoint= thd->mdl_context.mdl_savepoint();

while (!thd->mdl_context.acquire_locks(&mdl_requests, lock_wait_timeout) &&
!upgrade_lock_if_not_exists(thd, options, tables_start,
!upgrade_lock_if_not_exists(thd, options, ha_opt, tables_start,
lock_wait_timeout) &&
!thd->mdl_context.try_acquire_lock(&global_request))
{
Expand Down Expand Up @@ -4528,7 +4540,7 @@ open_tables_check_upgradable_mdl(THD *thd, TABLE_LIST *tables_start,
@retval TRUE Error, reported.
*/

bool open_tables(THD *thd, const DDL_options_st &options,
bool open_tables(THD *thd, const DDL_options_st &options, HA_CREATE_INFO &ha_opt,
TABLE_LIST **start, uint *counter, uint flags,
Prelocking_strategy *prelocking_strategy)
{
Expand Down Expand Up @@ -4618,7 +4630,7 @@ bool open_tables(THD *thd, const DDL_options_st &options,
else
{
TABLE_LIST *table;
if (lock_table_names(thd, options, *start,
if (lock_table_names(thd, options, ha_opt, *start,
thd->lex->first_not_own_table(),
ot_ctx.get_timeout(), flags))
{
Expand Down Expand Up @@ -5186,7 +5198,7 @@ bool open_and_lock_internal_tables(TABLE *table, bool lock_table)
TABLE_LIST *tmp= table->internal_tables;
DML_prelocking_strategy prelocking_strategy;

if (open_tables(thd, thd->lex->create_info, &tmp, &counter, 0,
if (open_tables(thd, thd->lex->create_info, thd->lex->create_info, &tmp, &counter, 0,
&prelocking_strategy))
goto err;

Expand Down Expand Up @@ -5616,6 +5628,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
*/

bool open_and_lock_tables(THD *thd, const DDL_options_st &options,
HA_CREATE_INFO &ha_opt,
TABLE_LIST *tables,
bool derived, uint flags,
Prelocking_strategy *prelocking_strategy)
Expand All @@ -5625,7 +5638,7 @@ bool open_and_lock_tables(THD *thd, const DDL_options_st &options,
DBUG_ENTER("open_and_lock_tables");
DBUG_PRINT("enter", ("derived handling: %d", derived));

if (open_tables(thd, options, &tables, &counter, flags, prelocking_strategy))
if (open_tables(thd, options, ha_opt, &tables, &counter, flags, prelocking_strategy))
goto err;

DBUG_EXECUTE_IF("sleep_open_and_lock_after_open", {
Expand Down
29 changes: 15 additions & 14 deletions sql/sql_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,39 +248,39 @@ int setup_ftfuncs(SELECT_LEX* select);
void cleanup_ftfuncs(SELECT_LEX *select_lex);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
bool lock_table_names(THD *thd, const DDL_options_st &options,
TABLE_LIST *table_list,
HA_CREATE_INFO &ha_opt, TABLE_LIST *table_list,
TABLE_LIST *table_list_end, ulong lock_wait_timeout,
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);
return lock_table_names(thd, thd->lex->create_info, 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,
HA_CREATE_INFO &ha_opt, 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);
return open_tables(thd, thd->lex->create_info, thd->lex->create_info,
tables, counter, flags, prelocking_strategy);
}
/* open_and_lock_tables with optional derived handling */
bool open_and_lock_tables(THD *thd, const DDL_options_st &options,
TABLE_LIST *tables,
HA_CREATE_INFO &ha_opt, 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,
return open_and_lock_tables(thd, thd->lex->create_info, thd->lex->create_info,
tables, derived, flags, prelocking_strategy);
}
/* simple open_and_lock_tables without derived handling for single table */
Expand Down Expand Up @@ -482,21 +482,21 @@ class Alter_table_prelocking_strategy : public Prelocking_strategy


inline bool
open_tables(THD *thd, const DDL_options_st &options,
open_tables(THD *thd, const DDL_options_st &options, HA_CREATE_INFO &ha_opt,
TABLE_LIST **tables, uint *counter, uint flags)
{
DML_prelocking_strategy prelocking_strategy;

return open_tables(thd, options, tables, counter, flags,
return open_tables(thd, options, ha_opt, 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, thd->lex->create_info, tables, counter, flags,
&prelocking_strategy);
return open_tables(thd, thd->lex->create_info, thd->lex->create_info,
tables, counter, flags, &prelocking_strategy);
}

inline TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
Expand All @@ -512,20 +512,21 @@ 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,
const DDL_options_st &options,
HA_CREATE_INFO &ha_opt,
TABLE_LIST *tables,
bool derived, uint flags)
{
DML_prelocking_strategy prelocking_strategy;

return open_and_lock_tables(thd, options, tables, derived, flags,
return open_and_lock_tables(thd, options, ha_opt, 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,
return open_and_lock_tables(thd, thd->lex->create_info, thd->lex->create_info,
tables, derived, flags,
&prelocking_strategy);
}
Expand Down
56 changes: 46 additions & 10 deletions sql/sql_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4484,10 +4484,28 @@ int create_table_impl(THD *thd,
goto err;
}

handlerton *db_type;
if (!internal_tmp_table &&
ha_table_exists(thd, &db, &table_name,
&create_info->org_tabledef_version, NULL, &db_type))
handlerton *db_type= NULL;
bool tbl_exists= false;
/* This check is need in case OPT_REPLACE and OPT_IF_NOT_EXISTS ddl and LOCK,
for which there is no call of `lock_table_names` and `ha_table_exists`.
*/
if (options.or_replace() || options.if_not_exists())
{
char path[FN_REFLEN + 1];
create_info->table_path.length= build_table_filename(path, FN_REFLEN - 1,
db.str,
table_name.str,
"", 0);
lex_string_set3(&create_info->table_path, path,
create_info->table_path.length);
tbl_exists= ha_table_exists(thd, &db, &table_name,
&create_info->org_tabledef_version,
NULL, &db_type, NULL, create_info);
}
else
tbl_exists= create_info->table_exists;

if (!internal_tmp_table && tbl_exists)
{
if (ha_check_if_updates_are_ignored(thd, db_type, "CREATE"))
{
Expand Down Expand Up @@ -4747,13 +4765,12 @@ int mysql_create_table_no_lock(THD *thd,
{
const LEX_CSTRING *alias= table_case_name(create_info, table_name);
path_length= build_table_filename(path, sizeof(path) - 1, db->str,
alias->str,
"", 0);
alias->str,"", 0);
// Check if we hit FN_REFLEN bytes along with file extension.
if (path_length+reg_ext_length > FN_REFLEN)
{
my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), (int) sizeof(path)-1,
path);
path);
return true;
}
}
Expand Down Expand Up @@ -4893,7 +4910,10 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,

/* Open or obtain an exclusive metadata lock on table being created */
create_table->db_type= 0;
result= open_and_lock_tables(thd, *create_info, create_table, FALSE, 0);
create_info->table_exists= false;
lex_string_set3(&create_info->table_path, "\0", FN_REFLEN);
result= open_and_lock_tables(thd, *create_info, *create_info,
create_table, FALSE, 0);

thd->lex->create_info.options= save_thd_create_info_options;

Expand Down Expand Up @@ -5368,7 +5388,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
properly isolated from all concurrent operations which matter.
*/

res= open_tables(thd, *create_info, &thd->lex->query_tables, &not_used, 0);
res= open_tables(thd, *create_info, *create_info, &thd->lex->query_tables, &not_used, 0);

if (res)
{
Expand Down Expand Up @@ -12946,7 +12966,7 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
goto end_with_restore_list;
}

res= open_and_lock_tables(thd, create_info, lex->query_tables, TRUE, 0);
res= open_and_lock_tables(thd, create_info, create_info, lex->query_tables, TRUE, 0);
if (unlikely(res))
{
/* Got error or warning. Set res to 1 if error */
Expand Down Expand Up @@ -12999,6 +13019,22 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
CREATE from SELECT give its SELECT_LEX for SELECT,
and item_list belong to SELECT
*/
/*
Check here if the table is already being created,
since `create_table_impl()` will be called,
without inovking of `mysql_create_table()` that calls `ha_table_exists`.
*/
char path[FN_REFLEN + 1];
create_info.table_path.length= build_table_filename(path, FN_REFLEN - 1,
create_table->db.str,
create_table->table_name.str,
"", 0);
lex_string_set3(&create_info.table_path, path,
create_info.table_path.length);
create_info.table_exists= ha_table_exists(thd, &create_table->db,
&create_table->table_name,
NULL, NULL,
&create_table->db_type);
if (!(res= handle_select(thd, lex, result, 0)))
{
if (create_info.tmp_table())
Expand Down