mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Merge branch '10.1' into 10.2
This commit is contained in:
160
sql/sql_base.cc
160
sql/sql_base.cc
@ -411,9 +411,10 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables,
|
||||
for (TABLE_LIST *table_list= tables_to_reopen; table_list;
|
||||
table_list= table_list->next_global)
|
||||
{
|
||||
int err;
|
||||
/* A check that the table was locked for write is done by the caller. */
|
||||
TABLE *table= find_table_for_mdl_upgrade(thd, table_list->db,
|
||||
table_list->table_name, TRUE);
|
||||
table_list->table_name, &err);
|
||||
|
||||
/* May return NULL if this table has already been closed via an alias. */
|
||||
if (! table)
|
||||
@ -1460,6 +1461,66 @@ open_table_get_mdl_lock(THD *thd, Open_table_context *ot_ctx,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check if the given table is actually a VIEW that was LOCK-ed
|
||||
|
||||
@param thd Thread context.
|
||||
@param t Table to check.
|
||||
|
||||
@retval TRUE The 't'-table is a locked view
|
||||
needed to remedy problem before retrying again.
|
||||
@retval FALSE 't' was not locked, not a VIEW or an error happened.
|
||||
*/
|
||||
bool is_locked_view(THD *thd, TABLE_LIST *t)
|
||||
{
|
||||
DBUG_ENTER("check_locked_view");
|
||||
/*
|
||||
Is this table a view and not a base table?
|
||||
(it is work around to allow to open view with locked tables,
|
||||
real fix will be made after definition cache will be made)
|
||||
|
||||
Since opening of view which was not explicitly locked by LOCK
|
||||
TABLES breaks metadata locking protocol (potentially can lead
|
||||
to deadlocks) it should be disallowed.
|
||||
*/
|
||||
if (thd->mdl_context.is_lock_owner(MDL_key::TABLE,
|
||||
t->db, t->table_name,
|
||||
MDL_SHARED))
|
||||
{
|
||||
char path[FN_REFLEN + 1];
|
||||
build_table_filename(path, sizeof(path) - 1,
|
||||
t->db, t->table_name, reg_ext, 0);
|
||||
/*
|
||||
Note that we can't be 100% sure that it is a view since it's
|
||||
possible that we either simply have not found unused TABLE
|
||||
instance in THD::open_tables list or were unable to open table
|
||||
during prelocking process (in this case in theory we still
|
||||
should hold shared metadata lock on it).
|
||||
*/
|
||||
if (dd_frm_is_view(thd, path))
|
||||
{
|
||||
/*
|
||||
If parent_l of the table_list is non null then a merge table
|
||||
has this view as child table, which is not supported.
|
||||
*/
|
||||
if (t->parent_l)
|
||||
{
|
||||
my_error(ER_WRONG_MRG_TABLE, MYF(0));
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
if (!tdc_open_view(thd, t, CHECK_METADATA_VERSION))
|
||||
{
|
||||
DBUG_ASSERT(t->view != 0);
|
||||
DBUG_RETURN(TRUE); // VIEW
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Open a base table.
|
||||
|
||||
@ -1608,49 +1669,10 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
|
||||
DBUG_PRINT("info",("Using locked table"));
|
||||
goto reset;
|
||||
}
|
||||
/*
|
||||
Is this table a view and not a base table?
|
||||
(it is work around to allow to open view with locked tables,
|
||||
real fix will be made after definition cache will be made)
|
||||
|
||||
Since opening of view which was not explicitly locked by LOCK
|
||||
TABLES breaks metadata locking protocol (potentially can lead
|
||||
to deadlocks) it should be disallowed.
|
||||
*/
|
||||
if (thd->mdl_context.is_lock_owner(MDL_key::TABLE,
|
||||
table_list->db,
|
||||
table_list->table_name,
|
||||
MDL_SHARED))
|
||||
{
|
||||
char path[FN_REFLEN + 1];
|
||||
build_table_filename(path, sizeof(path) - 1,
|
||||
table_list->db, table_list->table_name, reg_ext, 0);
|
||||
/*
|
||||
Note that we can't be 100% sure that it is a view since it's
|
||||
possible that we either simply have not found unused TABLE
|
||||
instance in THD::open_tables list or were unable to open table
|
||||
during prelocking process (in this case in theory we still
|
||||
should hold shared metadata lock on it).
|
||||
*/
|
||||
if (dd_frm_is_view(thd, path))
|
||||
{
|
||||
/*
|
||||
If parent_l of the table_list is non null then a merge table
|
||||
has this view as child table, which is not supported.
|
||||
*/
|
||||
if (table_list->parent_l)
|
||||
{
|
||||
my_error(ER_WRONG_MRG_TABLE, MYF(0));
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
if (is_locked_view(thd, table_list))
|
||||
DBUG_RETURN(FALSE); // VIEW
|
||||
|
||||
if (!tdc_open_view(thd, table_list, CHECK_METADATA_VERSION))
|
||||
{
|
||||
DBUG_ASSERT(table_list->view != 0);
|
||||
DBUG_RETURN(FALSE); // VIEW
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
No table in the locked tables list. In case of explicit LOCK TABLES
|
||||
this can happen if a user did not include the table into the list.
|
||||
@ -2003,8 +2025,9 @@ TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name)
|
||||
@param thd Thread context
|
||||
@param db Database name.
|
||||
@param table_name Name of table.
|
||||
@param no_error Don't emit error if no suitable TABLE
|
||||
instance were found.
|
||||
@param p_error In the case of an error (when the function returns NULL)
|
||||
the error number is stored there.
|
||||
If the p_error is NULL, function launches the error itself.
|
||||
|
||||
@note This function checks if the connection holds a global IX
|
||||
metadata lock. If no such lock is found, it is not safe to
|
||||
@ -2017,15 +2040,15 @@ TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name)
|
||||
*/
|
||||
|
||||
TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
|
||||
const char *table_name, bool no_error)
|
||||
const char *table_name, int *p_error)
|
||||
{
|
||||
TABLE *tab= find_locked_table(thd->open_tables, db, table_name);
|
||||
int error;
|
||||
|
||||
if (!tab)
|
||||
{
|
||||
if (!no_error)
|
||||
my_error(ER_TABLE_NOT_LOCKED, MYF(0), table_name);
|
||||
return NULL;
|
||||
error= ER_TABLE_NOT_LOCKED;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2037,9 +2060,8 @@ TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
|
||||
if (!thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "",
|
||||
MDL_INTENTION_EXCLUSIVE))
|
||||
{
|
||||
if (!no_error)
|
||||
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_name);
|
||||
return NULL;
|
||||
error= ER_TABLE_NOT_LOCKED_FOR_WRITE;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
while (tab->mdl_ticket != NULL &&
|
||||
@ -2047,10 +2069,21 @@ TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
|
||||
(tab= find_locked_table(tab->next, db, table_name)))
|
||||
continue;
|
||||
|
||||
if (!tab && !no_error)
|
||||
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_name);
|
||||
if (unlikely(!tab))
|
||||
{
|
||||
error= ER_TABLE_NOT_LOCKED_FOR_WRITE;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
return tab;
|
||||
|
||||
err_exit:
|
||||
if (p_error)
|
||||
*p_error= error;
|
||||
else
|
||||
my_error(error, MYF(0), table_name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -3816,7 +3849,7 @@ open_tables_check_upgradable_mdl(THD *thd, TABLE_LIST *tables_start,
|
||||
Note that find_table_for_mdl_upgrade() will report an error if
|
||||
no suitable ticket is found.
|
||||
*/
|
||||
if (!find_table_for_mdl_upgrade(thd, table->db, table->table_name, false))
|
||||
if (!find_table_for_mdl_upgrade(thd, table->db, table->table_name, NULL))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -4213,8 +4246,9 @@ handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
|
||||
@note this can be changed to use a hash, instead of scanning the linked
|
||||
list, if the performance of this function will ever become an issue
|
||||
*/
|
||||
static bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_STRING *db,
|
||||
LEX_STRING *table, thr_lock_type lock_type)
|
||||
|
||||
bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_STRING *db,
|
||||
LEX_STRING *table, thr_lock_type lock_type)
|
||||
{
|
||||
for (; tl; tl= tl->next_global )
|
||||
{
|
||||
@ -6673,10 +6707,22 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
|
||||
|
||||
result= FALSE;
|
||||
|
||||
err:
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
DBUG_RETURN(result);
|
||||
|
||||
err:
|
||||
/*
|
||||
Actually we failed to build join columns list, so we have to
|
||||
clear it to avoid problems with half-build join on next run.
|
||||
The list was created in mark_common_columns().
|
||||
*/
|
||||
table_ref_1->remove_join_columns();
|
||||
table_ref_2->remove_join_columns();
|
||||
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user