* remove ha_check_if_table_exists() and get_table_share_with_discover().

* rename check_if_table_exists() -> table_exists() and remove unneeded arguments
This commit is contained in:
Sergei Golubchik 2013-04-09 15:35:15 +02:00
parent 87a9d60ec6
commit b0a5dd73fa
9 changed files with 119 additions and 300 deletions

View File

@ -4203,33 +4203,6 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
} }
/**
Try to find a table in a storage engine.
@param db Normalized table schema name
@param name Normalized table name.
@param[out] exists Only valid if the function succeeded.
@retval TRUE An error is found
@retval FALSE Success, check *exists
*/
bool
ha_check_if_table_exists(THD* thd, const char *db, const char *name,
bool *exists)
{
uchar *frmblob= NULL;
size_t frmlen;
DBUG_ENTER("ha_check_if_table_exists");
*exists= ! ha_discover(thd, db, name, &frmblob, &frmlen);
if (*exists)
my_free(frmblob);
DBUG_RETURN(FALSE);
}
void st_ha_check_opt::init() void st_ha_check_opt::init()
{ {
flags= sql_flags= 0; flags= sql_flags= 0;

View File

@ -3068,8 +3068,6 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat);
/* discovery */ /* discovery */
int ha_create_table_from_engine(THD* thd, const char *db, const char *name); int ha_create_table_from_engine(THD* thd, const char *db, const char *name);
bool ha_check_if_table_exists(THD* thd, const char *db, const char *name,
bool *exists);
int ha_discover(THD* thd, const char* dbname, const char* name, int ha_discover(THD* thd, const char* dbname, const char* name,
uchar** frmblob, size_t* frmlen); uchar** frmblob, size_t* frmlen);
int ha_discover_table_names(THD *thd, LEX_STRING *db, MY_DIR *dirp, int ha_discover_table_names(THD *thd, LEX_STRING *db, MY_DIR *dirp,

View File

@ -575,18 +575,13 @@ static void table_def_unuse_table(TABLE *table)
table_list Table that should be opened table_list Table that should be opened
key Table cache key key Table cache key
key_length Length of key key_length Length of key
db_flags Flags to open_table_def(): op operation: what to open table or view
OPEN_VIEW
error out: Error code from open_table_def() error out: Error code from open_table_def()
IMPLEMENTATION IMPLEMENTATION
Get a table definition from the table definition cache. Get a table definition from the table definition cache.
If it doesn't exist, create a new from the table definition file. If it doesn't exist, create a new from the table definition file.
NOTES
We must have wrlock on LOCK_open when we come here
(To be changed later)
RETURN RETURN
0 Error 0 Error
# Share for table # Share for table
@ -673,6 +668,17 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
We found an existing table definition. Return it if we didn't get We found an existing table definition. Return it if we didn't get
an error when reading the table definition from file. an error when reading the table definition from file.
*/ */
if (share->is_view && op == FRM_READ_TABLE_ONLY)
{
open_table_error(share, OPEN_FRM_NOT_A_TABLE, ENOENT);
goto err;
}
if (!share->is_view && op == FRM_READ_VIEW_ONLY)
{
open_table_error(share, OPEN_FRM_NOT_A_VIEW, ENOENT);
goto err;
}
if (share->error) if (share->error)
{ {
/* Table definition contained an error */ /* Table definition contained an error */
@ -680,12 +686,6 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
goto err; goto err;
} }
if (share->is_view && op != FRM_READ_NO_ERROR_FOR_VIEW)
{
open_table_error(share, OPEN_FRM_NO_VIEWS, ENOENT);
goto err;
}
++share->ref_count; ++share->ref_count;
if (share->ref_count == 1 && share->prev) if (share->ref_count == 1 && share->prev)
@ -718,98 +718,6 @@ end:
} }
/**
Get a table share. If it didn't exist, try creating it from engine
For arguments and return values, see get_table_share()
*/
static TABLE_SHARE *
get_table_share_with_discover(THD *thd, TABLE_LIST *table_list,
char *key, uint key_length,
enum read_frm_op op, enum open_frm_error *error,
my_hash_value_type hash_value)
{
TABLE_SHARE *share;
bool exists;
DBUG_ENTER("get_table_share_with_discover");
share= get_table_share(thd, table_list, key, key_length, op, error,
hash_value);
/*
If share is not NULL, we found an existing share.
If share is NULL, and there is no error, we're inside
pre-locking, which silences 'ER_NO_SUCH_TABLE' errors
with the intention to silently drop non-existing tables
from the pre-locking list. In this case we still need to try
auto-discover before returning a NULL share.
Or, we're inside SHOW CREATE VIEW, which
also installs a silencer for ER_NO_SUCH_TABLE error.
If share is NULL and the error is ER_NO_SUCH_TABLE, this is
the same as above, only that the error was not silenced by
pre-locking or SHOW CREATE VIEW.
In both these cases it won't harm to try to discover the
table.
Finally, if share is still NULL, it's a real error and we need
to abort.
@todo Rework alternative ways to deal with ER_NO_SUCH TABLE.
*/
if (share ||
(thd->is_error() && thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE &&
thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE_IN_ENGINE))
DBUG_RETURN(share);
*error= OPEN_FRM_OK;
/* Table didn't exist. Check if some engine can provide it */
if (ha_check_if_table_exists(thd, table_list->db, table_list->table_name,
&exists))
{
thd->clear_error();
/* Conventionally, the storage engine API does not report errors. */
my_error(ER_OUT_OF_RESOURCES, MYF(0));
}
else if (! exists)
{
/*
No such table in any engine.
Hide "Table doesn't exist" errors if the table belongs to a view.
The check for thd->is_error() is necessary to not push an
unwanted error in case the error was already silenced.
@todo Rework the alternative ways to deal with ER_NO_SUCH TABLE.
*/
if (thd->is_error())
{
if (table_list->parent_l)
{
thd->clear_error();
my_error(ER_WRONG_MRG_TABLE, MYF(0));
}
else if (table_list->belong_to_view)
{
TABLE_LIST *view= table_list->belong_to_view;
thd->clear_error();
my_error(ER_VIEW_INVALID, MYF(0),
view->view_db.str, view->view_name.str);
}
}
}
else
{
thd->clear_error();
*error= OPEN_FRM_DISCOVER; /* Run auto-discover. */
}
DBUG_RETURN(NULL);
}
/** /**
Mark that we are not using table share anymore. Mark that we are not using table share anymore.
@ -871,7 +779,7 @@ void release_table_share(TABLE_SHARE *share)
# TABLE_SHARE for table # TABLE_SHARE for table
*/ */
TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name) static TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name)
{ {
char key[SAFE_NAME_LEN*2+2]; char key[SAFE_NAME_LEN*2+2];
uint key_length; uint key_length;
@ -2445,10 +2353,9 @@ void drop_open_table(THD *thd, TABLE *table, const char *db_name,
or in some storage engine. or in some storage engine.
@param thd Thread context @param thd Thread context
@param table Table list element @param db database name
@param fast_check Check only if share or .frm file exists @param table_name table name
@param[out] exists Out parameter which is set to TRUE if table @param path (optional) path to the frm file
exists and to FALSE otherwise.
@note This function acquires LOCK_open internally. @note This function acquires LOCK_open internally.
@ -2460,48 +2367,36 @@ void drop_open_table(THD *thd, TABLE *table, const char *db_name,
@retval FALSE No error. 'exists' out parameter set accordingly. @retval FALSE No error. 'exists' out parameter set accordingly.
*/ */
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool fast_check, bool table_exists(THD *thd, const char *db, const char *table_name,
bool *exists) const char *path)
{ {
char path[FN_REFLEN + 1]; char path_buf[FN_REFLEN + 1];
TABLE_SHARE *share; TABLE_SHARE *share;
DBUG_ENTER("check_if_table_exists"); DBUG_ENTER("table_exists");
*exists= TRUE;
DBUG_ASSERT(fast_check ||
thd->mdl_context.
is_lock_owner(MDL_key::TABLE, table->db,
table->table_name, MDL_SHARED));
mysql_mutex_lock(&LOCK_open); mysql_mutex_lock(&LOCK_open);
share= get_cached_table_share(table->db, table->table_name); share= get_cached_table_share(db, table_name);
mysql_mutex_unlock(&LOCK_open); mysql_mutex_unlock(&LOCK_open);
if (share) if (share)
goto end; DBUG_RETURN(TRUE);
build_table_filename(path, sizeof(path) - 1, table->db, table->table_name, if (!path)
reg_ext, 0); {
build_table_filename(path_buf, sizeof(path_buf) - 1,
db, table_name, reg_ext, 0);
path= path_buf;
}
if (!access(path, F_OK)) 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))
{
my_printf_error(ER_OUT_OF_RESOURCES, "Failed to open '%-.64s', error while "
"unpacking from engine", MYF(0), table->table_name);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
}
end: /* .FRM file doesn't exist. Try to discover it */
DBUG_RETURN(FALSE); uchar *frmblob= NULL;
size_t frmlen;
bool exists= ! ha_discover(thd, db, table_name, &frmblob, &frmlen);
my_free(frmblob);
DBUG_RETURN(exists);
} }
@ -2781,6 +2676,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
enum open_frm_error error; enum open_frm_error error;
TABLE_SHARE *share; TABLE_SHARE *share;
my_hash_value_type hash_value; my_hash_value_type hash_value;
enum read_frm_op read_op;
DBUG_ENTER("open_table"); DBUG_ENTER("open_table");
/* an open table operation needs a lot of the stack space */ /* an open table operation needs a lot of the stack space */
@ -3040,12 +2936,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
if (table_list->open_strategy == TABLE_LIST::OPEN_IF_EXISTS) if (table_list->open_strategy == TABLE_LIST::OPEN_IF_EXISTS)
{ {
bool exists; if (!table_exists(thd, table_list))
if (check_if_table_exists(thd, table_list, 0, &exists))
DBUG_RETURN(TRUE);
if (!exists)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
/* Table exists. Let us try to open it. */ /* Table exists. Let us try to open it. */
@ -3053,21 +2944,41 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
else if (table_list->open_strategy == TABLE_LIST::OPEN_STUB) else if (table_list->open_strategy == TABLE_LIST::OPEN_STUB)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
if (table_list->i_s_requested_object & OPEN_TABLE_ONLY)
read_op = FRM_READ_TABLE_ONLY;
else
if (table_list->i_s_requested_object & OPEN_VIEW_ONLY)
read_op = FRM_READ_VIEW_ONLY;
else
read_op = FRM_READ_TABLE_OR_VIEW;
retry_share: retry_share:
if (!(share= get_table_share_with_discover(thd, table_list, key, key_length, share= get_table_share(thd, table_list, key, key_length,
FRM_READ_NO_ERROR_FOR_VIEW, read_op, &error, hash_value);
&error, hash_value)))
if (!share)
{ {
/* /*
If thd->is_error() is not set, we either need discover or the error was Hide "Table doesn't exist" errors if the table belongs to a view.
silenced by the prelocking handler, in which case we should skip this The check for thd->is_error() is necessary to not push an
table. unwanted error in case the error was already silenced.
@todo Rework the alternative ways to deal with ER_NO_SUCH TABLE.
*/ */
if (error == OPEN_FRM_DISCOVER && !thd->is_error()) if (thd->is_error())
{ {
(void) ot_ctx->request_backoff_action(Open_table_context::OT_DISCOVER, if (table_list->parent_l)
table_list); {
thd->clear_error();
my_error(ER_WRONG_MRG_TABLE, MYF(0));
}
else if (table_list->belong_to_view)
{
TABLE_LIST *view= table_list->belong_to_view;
thd->clear_error();
my_error(ER_VIEW_INVALID, MYF(0),
view->view_db.str, view->view_name.str);
}
} }
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
@ -3090,12 +3001,6 @@ retry_share:
*/ */
if (check_and_update_table_version(thd, table_list, share)) if (check_and_update_table_version(thd, table_list, share))
goto err_lock; goto err_lock;
if (table_list->i_s_requested_object & OPEN_TABLE_ONLY)
{
my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db,
table_list->table_name);
goto err_lock;
}
/* Open view */ /* Open view */
if (open_new_frm(thd, share, alias, if (open_new_frm(thd, share, alias,
@ -3117,20 +3022,6 @@ retry_share:
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
/*
Note that situation when we are trying to open a table for what
was a view during previous execution of PS will be handled in by
the caller. Here we should simply open our table even if
TABLE_LIST::view is true.
*/
if (table_list->i_s_requested_object & OPEN_VIEW_ONLY)
{
my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db,
table_list->table_name);
goto err_lock;
}
mysql_mutex_lock(&LOCK_open); mysql_mutex_lock(&LOCK_open);
if (!(flags & MYSQL_OPEN_IGNORE_FLUSH) || if (!(flags & MYSQL_OPEN_IGNORE_FLUSH) ||
(share->protected_against_usage() && !(flags & MYSQL_OPEN_FOR_REPAIR))) (share->protected_against_usage() && !(flags & MYSQL_OPEN_FOR_REPAIR)))
@ -3894,11 +3785,12 @@ bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias,
hash_value= my_calc_hash(&table_def_cache, (uchar*) cache_key, hash_value= my_calc_hash(&table_def_cache, (uchar*) cache_key,
cache_key_length); cache_key_length);
if (!(share= get_table_share(thd, table_list, cache_key, cache_key_length, if (!(share= get_table_share(thd, table_list, cache_key, cache_key_length,
FRM_READ_NO_ERROR_FOR_VIEW, &error, hash_value))) FRM_READ_VIEW_ONLY, &error, hash_value)))
return TRUE; return TRUE;
bool err= !share->is_view || DBUG_ASSERT(share->is_view);
open_new_frm(thd, share, alias,
bool err= open_new_frm(thd, share, alias,
(HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
HA_GET_INDEX | HA_TRY_READ_ONLY), HA_GET_INDEX | HA_TRY_READ_ONLY),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD | flags, READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD | flags,
@ -3908,10 +3800,6 @@ bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias,
release_table_share(share); release_table_share(share);
mysql_mutex_unlock(&LOCK_open); mysql_mutex_unlock(&LOCK_open);
if (err)
my_error(ER_WRONG_OBJECT, MYF(0), table_list->db,
table_list->table_name, "VIEW");
return err; return err;
} }
@ -3985,12 +3873,11 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list)
cache_key_length); cache_key_length);
if (!(share= get_table_share(thd, table_list, cache_key, cache_key_length, if (!(share= get_table_share(thd, table_list, cache_key, cache_key_length,
FRM_READ_NO_ERROR_FOR_VIEW, &not_used, FRM_READ_TABLE_ONLY, &not_used,
hash_value))) hash_value)))
goto end_free; goto end_free;
if (share->is_view) DBUG_ASSERT(! share->is_view);
goto end_release;
if (open_table_from_share(thd, share, table_list->alias, if (open_table_from_share(thd, share, table_list->alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
@ -4016,7 +3903,6 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list)
result= FALSE; result= FALSE;
} }
end_release:
mysql_mutex_lock(&LOCK_open); mysql_mutex_lock(&LOCK_open);
release_table_share(share); release_table_share(share);
/* Remove the repaired share from the table cache. */ /* Remove the repaired share from the table cache. */
@ -4786,7 +4672,7 @@ lock_table_names(THD *thd,
if (mdl_requests.is_empty()) if (mdl_requests.is_empty())
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
/* Check if CREATE TABLE IF NOT EXISTS was used */ /* Check if CREATE TABLE was used */
create_table= (tables_start && tables_start->open_strategy == create_table= (tables_start && tables_start->open_strategy ==
TABLE_LIST::OPEN_IF_EXISTS); TABLE_LIST::OPEN_IF_EXISTS);
@ -4825,12 +4711,9 @@ lock_table_names(THD *thd,
for (;;) for (;;)
{ {
bool exists= TRUE;
bool res;
if (create_table) if (create_table)
thd->push_internal_handler(&error_handler); // Avoid warnings & errors thd->push_internal_handler(&error_handler); // Avoid warnings & errors
res= thd->mdl_context.acquire_locks(&mdl_requests, lock_wait_timeout); bool res= thd->mdl_context.acquire_locks(&mdl_requests, lock_wait_timeout);
if (create_table) if (create_table)
thd->pop_internal_handler(); thd->pop_internal_handler();
if (!res) if (!res)
@ -4840,13 +4723,10 @@ lock_table_names(THD *thd,
DBUG_RETURN(TRUE); // Return original error DBUG_RETURN(TRUE); // Return original error
/* /*
We come here in the case of lock timeout when executing We come here in the case of lock timeout when executing CREATE TABLE.
CREATE TABLE IF NOT EXISTS. Verify that table does exist (it usually does, as we got a lock conflict)
Verify that table really exists (it should as we got a lock conflict)
*/ */
if (check_if_table_exists(thd, tables_start, 1, &exists)) if (table_exists(thd, tables_start))
DBUG_RETURN(TRUE); // Should never happen
if (exists)
{ {
if (thd->lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS) if (thd->lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS)
{ {
@ -4858,17 +4738,16 @@ lock_table_names(THD *thd,
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), tables_start->table_name); my_error(ER_TABLE_EXISTS_ERROR, MYF(0), tables_start->table_name);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
/* purecov: begin inspected */
/* /*
We got error from acquire_locks but table didn't exists. We got error from acquire_locks, but the table didn't exists.
In theory this should never happen, except maybe in This could happen if another connection runs a statement
CREATE or DROP DATABASE scenario. involving this non-existent table, and this statement took the mdl,
but didn't error out with ER_NO_SUCH_TABLE yet (yes, a race condition).
We play safe and restart the original acquire_locks with the We play safe and restart the original acquire_locks with the
original timeout original timeout.
*/ */
create_table= 0; create_table= 0;
lock_wait_timeout= org_lock_wait_timeout; lock_wait_timeout= org_lock_wait_timeout;
/* purecov: end */
} }
} }

View File

@ -112,7 +112,6 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
enum open_frm_error *error, enum open_frm_error *error,
my_hash_value_type hash_value); my_hash_value_type hash_value);
void release_table_share(TABLE_SHARE *share); void release_table_share(TABLE_SHARE *share);
TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
uint lock_flags); uint lock_flags);
@ -333,8 +332,14 @@ TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
const char *table_name, const char *table_name,
bool no_error); bool no_error);
void mark_tmp_table_for_reuse(TABLE *table); void mark_tmp_table_for_reuse(TABLE *table);
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool fast_check,
bool *exists); bool table_exists(THD *thd, const char *db, const char *table_name,
const char *path);
static inline bool table_exists(THD *thd, TABLE_LIST *table)
{
return table_exists(thd, table->db, table->table_name, NULL);
}
int update_virtual_fields(THD *thd, TABLE *table, int update_virtual_fields(THD *thd, TABLE *table,
enum enum_vcol_update_mode vcol_update_mode= VCOL_UPDATE_FOR_READ); enum enum_vcol_update_mode vcol_update_mode= VCOL_UPDATE_FOR_READ);
int dynamic_column_error_message(enum_dyncol_func_result rc); int dynamic_column_error_message(enum_dyncol_func_result rc);

View File

@ -934,16 +934,10 @@ update_binlog:
for (tbl= tables; tbl; tbl= tbl->next_local) for (tbl= tables; tbl; tbl= tbl->next_local)
{ {
uint tbl_name_len; uint tbl_name_len;
bool exists;
char quoted_name[FN_REFLEN+3]; char quoted_name[FN_REFLEN+3];
// Only write drop table to the binlog for tables that no longer exist. // Only write drop table to the binlog for tables that no longer exist.
if (check_if_table_exists(thd, tbl, 0, &exists)) if (table_exists(thd, tbl))
{
error= true;
goto exit;
}
if (exists)
continue; continue;
my_snprintf(quoted_name, sizeof(quoted_name), "%`s", tbl->table_name); my_snprintf(quoted_name, sizeof(quoted_name), "%`s", tbl->table_name);

View File

@ -4057,12 +4057,14 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
of backward compatibility. of backward compatibility.
*/ */
if (!is_show_fields_or_keys && result && thd->is_error() && if (!is_show_fields_or_keys && result && thd->is_error() &&
thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE) (thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE ||
thd->stmt_da->sql_errno() == ER_WRONG_OBJECT))
{ {
/* /*
Hide error for a non-existing table. Hide error for a non-existing table.
For example, this error can occur when we use a where condition For example, this error can occur when we use a where condition
with a db name and table, but the table does not exist. with a db name and table, but the table does not exist or
there is a view with the same name.
*/ */
result= false; result= false;
thd->clear_error(); thd->clear_error();
@ -4383,7 +4385,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables,
key_length= create_table_def_key(thd, key, &table_list, 0); key_length= create_table_def_key(thd, key, &table_list, 0);
hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length);
share= get_table_share(thd, &table_list, key, key_length, share= get_table_share(thd, &table_list, key, key_length,
FRM_READ_NO_ERROR_FOR_VIEW, &not_used, hash_value); FRM_READ_TABLE_OR_VIEW, &not_used, hash_value);
if (!share) if (!share)
{ {
res= 0; res= 0;
@ -4407,10 +4409,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables,
res= 1; res= 1;
goto end_share; goto end_share;
} }
}
if (share->is_view)
{
if (open_new_frm(thd, share, table_name->str, if (open_new_frm(thd, share, table_name->str,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
HA_GET_INDEX | HA_TRY_READ_ONLY), HA_GET_INDEX | HA_TRY_READ_ONLY),

View File

@ -2279,11 +2279,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
} }
DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table"); DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table");
error= 0; error= 0;
if (drop_temporary || if (drop_temporary || !table_exists(thd, db, alias, path) ||
((access(path, F_OK) && (!drop_view && dd_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE))
ha_create_table_from_engine(thd, db, alias)) ||
(!drop_view &&
dd_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
{ {
/* /*
One of the following cases happened: One of the following cases happened:
@ -4320,50 +4317,10 @@ bool mysql_create_table_no_lock(THD *thd,
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)) if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
{ {
if (!access(path,F_OK)) if (table_exists(thd, db, table_name, path))
{ {
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
goto warn; goto warn;
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
goto err;
}
/*
We don't assert here, but check the result, because the table could be
in the table definition cache and in the same time the .frm could be
missing from the disk, in case of manual intervention which deletes
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
Then she could create the table. This case is pretty obscure and
therefore we don't introduce a new error message only for it.
*/
mysql_mutex_lock(&LOCK_open);
if (get_cached_table_share(db, table_name))
{
mysql_mutex_unlock(&LOCK_open);
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
goto err;
}
mysql_mutex_unlock(&LOCK_open);
}
/*
Check that table with given name does not already
exist in any storage engine. In such a case it should
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
unless user specified CREATE TABLE IF EXISTS
An exclusive metadata lock ensures that no
one else is attempting to discover the table. Since
it's not on disk as a frm file, no one could be using it!
*/
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
{
bool create_if_not_exists =
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
bool exists_in_engine;
ha_check_if_table_exists(thd, db, table_name, &exists_in_engine);
if (exists_in_engine)
{
if (create_if_not_exists)
goto warn;
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name); my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
goto err; goto err;
} }

View File

@ -685,8 +685,8 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share,
if (memcmp(head, STRING_WITH_LEN("TYPE=VIEW\n")) == 0) if (memcmp(head, STRING_WITH_LEN("TYPE=VIEW\n")) == 0)
{ {
share->is_view= 1; share->is_view= 1;
share->error= op == FRM_READ_NO_ERROR_FOR_VIEW share->error= op == FRM_READ_TABLE_ONLY
? OPEN_FRM_OK : OPEN_FRM_NO_VIEWS; ? OPEN_FRM_NOT_A_TABLE : OPEN_FRM_OK;
goto err; goto err;
} }
if (!is_binary_frm_header(head)) if (!is_binary_frm_header(head))
@ -695,6 +695,11 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share,
share->error = OPEN_FRM_CORRUPTED; share->error = OPEN_FRM_CORRUPTED;
goto err; goto err;
} }
if (op == FRM_READ_VIEW_ONLY)
{
share->error = OPEN_FRM_NOT_A_VIEW;
goto err;
}
if (my_fstat(file, &stats, MYF(0))) if (my_fstat(file, &stats, MYF(0)))
goto err; goto err;
@ -2802,7 +2807,7 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error,
int db_errno) int db_errno)
{ {
char buff[FN_REFLEN]; char buff[FN_REFLEN];
myf errortype= ME_ERROR+ME_WAITTANG; // Write fatals error to log const myf errortype= ME_ERROR+ME_WAITTANG; // Write fatals error to log
DBUG_ENTER("open_table_error"); DBUG_ENTER("open_table_error");
switch (error) { switch (error) {
@ -2825,8 +2830,15 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error,
break; break;
case OPEN_FRM_ERROR_ALREADY_ISSUED: case OPEN_FRM_ERROR_ALREADY_ISSUED:
break; break;
case OPEN_FRM_NOT_A_VIEW:
my_error(ER_WRONG_OBJECT, MYF(0), share->db.str,
share->table_name.str, "VIEW");
break;
case OPEN_FRM_NOT_A_TABLE:
my_error(ER_WRONG_OBJECT, MYF(0), share->db.str,
share->table_name.str, "TABLE");
break;
case OPEN_FRM_DISCOVER: case OPEN_FRM_DISCOVER:
case OPEN_FRM_NO_VIEWS:
DBUG_ASSERT(0); // open_table_error() is never called for this one DBUG_ASSERT(0); // open_table_error() is never called for this one
break; break;
case OPEN_FRM_CORRUPTED: case OPEN_FRM_CORRUPTED:

View File

@ -569,7 +569,8 @@ enum open_frm_error {
OPEN_FRM_CORRUPTED, OPEN_FRM_CORRUPTED,
OPEN_FRM_DISCOVER, OPEN_FRM_DISCOVER,
OPEN_FRM_ERROR_ALREADY_ISSUED, OPEN_FRM_ERROR_ALREADY_ISSUED,
OPEN_FRM_NO_VIEWS, OPEN_FRM_NOT_A_VIEW,
OPEN_FRM_NOT_A_TABLE
}; };
/** /**
@ -2448,7 +2449,8 @@ static inline void dbug_tmp_restore_column_maps(MY_BITMAP *read_set,
enum read_frm_op { enum read_frm_op {
FRM_READ_TABLE_ONLY, FRM_READ_TABLE_ONLY,
FRM_READ_NO_ERROR_FOR_VIEW FRM_READ_VIEW_ONLY,
FRM_READ_TABLE_OR_VIEW
}; };
size_t max_row_length(TABLE *table, const uchar *data); size_t max_row_length(TABLE *table, const uchar *data);