* 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:
parent
87a9d60ec6
commit
b0a5dd73fa
@ -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;
|
||||||
|
@ -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,
|
||||||
|
285
sql/sql_base.cc
285
sql/sql_base.cc
@ -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, ¬_used,
|
FRM_READ_TABLE_ONLY, ¬_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 */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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, ¬_used, hash_value);
|
FRM_READ_TABLE_OR_VIEW, ¬_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),
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
20
sql/table.cc
20
sql/table.cc
@ -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:
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user