mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge 5.5-mwl248 -> 10.0-base
This commit is contained in:
146
sql/sql_base.cc
146
sql/sql_base.cc
@ -2406,10 +2406,11 @@ void drop_open_table(THD *thd, TABLE *table, const char *db_name,
|
||||
Check that table exists in table definition cache, on disk
|
||||
or in some storage engine.
|
||||
|
||||
@param thd Thread context
|
||||
@param table Table list element
|
||||
@param[out] exists Out parameter which is set to TRUE if table
|
||||
exists and to FALSE otherwise.
|
||||
@param thd Thread context
|
||||
@param table Table list element
|
||||
@param fast_check Check only if share or .frm file exists
|
||||
@param[out] exists Out parameter which is set to TRUE if table
|
||||
exists and to FALSE otherwise.
|
||||
|
||||
@note This function acquires LOCK_open internally.
|
||||
|
||||
@ -2421,7 +2422,8 @@ void drop_open_table(THD *thd, TABLE *table, const char *db_name,
|
||||
@retval FALSE No error. 'exists' out parameter set accordingly.
|
||||
*/
|
||||
|
||||
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists)
|
||||
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool fast_check,
|
||||
bool *exists)
|
||||
{
|
||||
char path[FN_REFLEN + 1];
|
||||
TABLE_SHARE *share;
|
||||
@ -2429,7 +2431,8 @@ bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists)
|
||||
|
||||
*exists= TRUE;
|
||||
|
||||
DBUG_ASSERT(thd->mdl_context.
|
||||
DBUG_ASSERT(fast_check ||
|
||||
thd->mdl_context.
|
||||
is_lock_owner(MDL_key::TABLE, table->db,
|
||||
table->table_name, MDL_SHARED));
|
||||
|
||||
@ -2446,6 +2449,12 @@ bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists)
|
||||
if (!access(path, F_OK))
|
||||
goto end;
|
||||
|
||||
if (fast_check)
|
||||
{
|
||||
*exists= FALSE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* .FRM file doesn't exist. Check if some engine can provide it. */
|
||||
if (ha_check_if_table_exists(thd, table->db, table->table_name, exists))
|
||||
{
|
||||
@ -2995,7 +3004,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
{
|
||||
bool exists;
|
||||
|
||||
if (check_if_table_exists(thd, table_list, &exists))
|
||||
if (check_if_table_exists(thd, table_list, 0, &exists))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (!exists)
|
||||
@ -3148,16 +3157,6 @@ retry_share:
|
||||
while (table_cache_count > table_cache_size && unused_tables)
|
||||
free_cache_entry(unused_tables);
|
||||
|
||||
if (get_use_stat_tables_mode(thd) > NEVER)
|
||||
{
|
||||
if (share->table_category != TABLE_CATEGORY_SYSTEM)
|
||||
{
|
||||
if (!share->stats_can_be_read &&
|
||||
!alloc_statistics_for_table_share(thd, share, TRUE))
|
||||
share->stats_can_be_read= TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
mysql_mutex_unlock(&LOCK_open);
|
||||
|
||||
/* make a new table */
|
||||
@ -4643,22 +4642,24 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
|
||||
if (get_use_stat_tables_mode(thd) > NEVER && tables->table)
|
||||
{
|
||||
TABLE_SHARE *table_share= tables->table->s;
|
||||
if (table_share && table_share->table_category != TABLE_CATEGORY_SYSTEM)
|
||||
if (table_share && table_share->table_category == TABLE_CATEGORY_USER &&
|
||||
table_share->tmp_table == NO_TMP_TABLE)
|
||||
{
|
||||
if (!table_share->stats_can_be_read &&
|
||||
!alloc_statistics_for_table_share(thd, table_share, FALSE))
|
||||
{
|
||||
KEY *key_info= table_share->key_info;
|
||||
KEY *key_info_end= key_info + table_share->keys;
|
||||
KEY *table_key_info= tables->table->key_info;
|
||||
for ( ; key_info < key_info_end; key_info++, table_key_info++)
|
||||
table_key_info->read_stats= key_info->read_stats;
|
||||
Field **field_ptr= table_share->field;
|
||||
Field **table_field_ptr= tables->table->field;
|
||||
for ( ; *field_ptr; field_ptr++, table_field_ptr++)
|
||||
(*table_field_ptr)->read_stats= (*field_ptr)->read_stats;
|
||||
|
||||
table_share->stats_can_be_read= TRUE;
|
||||
if (table_share->stats_cb.stats_can_be_read ||
|
||||
!alloc_statistics_for_table_share(thd, table_share, FALSE))
|
||||
{
|
||||
if (table_share->stats_cb.stats_can_be_read)
|
||||
{
|
||||
KEY *key_info= table_share->key_info;
|
||||
KEY *key_info_end= key_info + table_share->keys;
|
||||
KEY *table_key_info= tables->table->key_info;
|
||||
for ( ; key_info < key_info_end; key_info++, table_key_info++)
|
||||
table_key_info->read_stats= key_info->read_stats;
|
||||
Field **field_ptr= table_share->field;
|
||||
Field **table_field_ptr= tables->table->field;
|
||||
for ( ; *field_ptr; field_ptr++, table_field_ptr++)
|
||||
(*table_field_ptr)->read_stats= (*field_ptr)->read_stats;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4711,7 +4712,18 @@ extern "C" uchar *schema_set_get_key(const uchar *record, size_t *length,
|
||||
open, see open_table() description for details.
|
||||
|
||||
@retval FALSE Success.
|
||||
@retval TRUE Failure (e.g. connection was killed)
|
||||
@retval TRUE Failure (e.g. connection was killed) or table existed
|
||||
for a CREATE TABLE.
|
||||
|
||||
@notes
|
||||
In case of CREATE TABLE we avoid a wait for tables that are in use
|
||||
by first trying to do a meta data lock with timeout == 0. If we get a
|
||||
timeout we will check if table exists (it should) and retry with
|
||||
normal timeout if it didn't exists.
|
||||
Note that for CREATE TABLE IF EXISTS we only generate a warning
|
||||
but still return TRUE (to abort the calling open_table() function).
|
||||
On must check THD->is_error() if one wants to distinguish between warning
|
||||
and error.
|
||||
*/
|
||||
|
||||
bool
|
||||
@ -4723,6 +4735,10 @@ lock_table_names(THD *thd,
|
||||
TABLE_LIST *table;
|
||||
MDL_request global_request;
|
||||
Hash_set<TABLE_LIST, schema_set_get_key> schema_set;
|
||||
ulong org_lock_wait_timeout= lock_wait_timeout;
|
||||
/* Check if we are using CREATE TABLE ... IF NOT EXISTS */
|
||||
bool create_table;
|
||||
Dummy_error_handler error_handler;
|
||||
DBUG_ENTER("lock_table_names");
|
||||
|
||||
DBUG_ASSERT(!thd->locked_tables_mode);
|
||||
@ -4744,8 +4760,14 @@ lock_table_names(THD *thd,
|
||||
}
|
||||
}
|
||||
|
||||
if (! (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) &&
|
||||
! mdl_requests.is_empty())
|
||||
if (mdl_requests.is_empty())
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
/* Check if CREATE TABLE IF NOT EXISTS was used */
|
||||
create_table= (tables_start && tables_start->open_strategy ==
|
||||
TABLE_LIST::OPEN_IF_EXISTS);
|
||||
|
||||
if (!(flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK))
|
||||
{
|
||||
/*
|
||||
Scoped locks: Take intention exclusive locks on all involved
|
||||
@ -4773,12 +4795,58 @@ lock_table_names(THD *thd,
|
||||
global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
|
||||
MDL_STATEMENT);
|
||||
mdl_requests.push_front(&global_request);
|
||||
|
||||
if (create_table)
|
||||
lock_wait_timeout= 0; // Don't wait for timeout
|
||||
}
|
||||
|
||||
if (thd->mdl_context.acquire_locks(&mdl_requests, lock_wait_timeout))
|
||||
DBUG_RETURN(TRUE);
|
||||
for (;;)
|
||||
{
|
||||
bool exists= TRUE;
|
||||
bool res;
|
||||
|
||||
DBUG_RETURN(FALSE);
|
||||
if (create_table)
|
||||
thd->push_internal_handler(&error_handler); // Avoid warnings & errors
|
||||
res= thd->mdl_context.acquire_locks(&mdl_requests, lock_wait_timeout);
|
||||
if (create_table)
|
||||
thd->pop_internal_handler();
|
||||
if (!res)
|
||||
DBUG_RETURN(FALSE); // Got locks
|
||||
|
||||
if (!create_table)
|
||||
DBUG_RETURN(TRUE); // Return original error
|
||||
|
||||
/*
|
||||
We come here in the case of lock timeout when executing
|
||||
CREATE TABLE IF NOT EXISTS.
|
||||
Verify that table really exists (it should as we got a lock conflict)
|
||||
*/
|
||||
if (check_if_table_exists(thd, tables_start, 1, &exists))
|
||||
DBUG_RETURN(TRUE); // Should never happen
|
||||
if (exists)
|
||||
{
|
||||
if (thd->lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS)
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
|
||||
tables_start->table_name);
|
||||
}
|
||||
else
|
||||
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), tables_start->table_name);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
/* purecov: begin inspected */
|
||||
/*
|
||||
We got error from acquire_locks but table didn't exists.
|
||||
In theory this should never happen, except maybe in
|
||||
CREATE or DROP DATABASE scenario.
|
||||
We play safe and restart the original acquire_locks with the
|
||||
original timeout
|
||||
*/
|
||||
create_table= 0;
|
||||
lock_wait_timeout= org_lock_wait_timeout;
|
||||
/* purecov: end */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4900,7 +4968,7 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize temporary MEM_ROOT for new .FRM parsing. Do not allocate
|
||||
Initialize temporary MEM_ROOT for new .FRM parsing. Do not alloctaate
|
||||
anything yet, to avoid penalty for statements which don't use views
|
||||
and thus new .FRM format.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user