1
0
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:
Oleksandr Byelkin
2018-09-14 08:47:22 +02:00
321 changed files with 6852 additions and 195819 deletions

View File

@ -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);
}