1
0
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:
Igor Babaev
2013-01-08 19:34:33 -08:00
54 changed files with 2575 additions and 1676 deletions

View File

@ -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.
*/