summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc178
1 files changed, 116 insertions, 62 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 34aef26ebc2..d9e68d919ef 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -414,9 +414,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.str,
- table_list->table_name.str, TRUE);
+ table_list->table_name.str, &err);
/* May return NULL if this table has already been closed via an alias. */
if (! table)
@@ -648,6 +649,7 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
size_t key_length= share->table_cache_key.length;
const char *db= key;
const char *table_name= db + share->db.length + 1;
+ bool remove_from_locked_tables= extra != HA_EXTRA_NOT_USED;
memcpy(key, share->table_cache_key.str, key_length);
@@ -661,7 +663,7 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
{
thd->locked_tables_list.unlink_from_list(thd,
table->pos_in_locked_tables,
- extra != HA_EXTRA_NOT_USED);
+ remove_from_locked_tables);
/* Inform handler that there is a drop table or a rename going on */
if (extra != HA_EXTRA_NOT_USED && table->db_stat)
{
@@ -1499,6 +1501,65 @@ static int set_partitions_as_used(TABLE_LIST *tl, TABLE *t)
/**
+ 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.str,
+ t->table_name.str, MDL_SHARED))
+ {
+ char path[FN_REFLEN + 1];
+ build_table_filename(path, sizeof(path) - 1,
+ t->db.str, t->table_name.str, 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.
@param thd Thread context.
@@ -1652,49 +1713,10 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
#endif
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.str,
- table_list->table_name.str,
- MDL_SHARED))
- {
- char path[FN_REFLEN + 1];
- build_table_filename(path, sizeof(path) - 1,
- table_list->db.str, table_list->table_name.str, 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.
@@ -2064,8 +2086,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
@@ -2078,15 +2101,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 (unlikely(!tab))
{
- if (!no_error)
- my_error(ER_TABLE_NOT_LOCKED, MYF(0), table_name);
- return NULL;
+ error= ER_TABLE_NOT_LOCKED;
+ goto err_exit;
}
/*
@@ -2098,9 +2121,8 @@ TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
if (unlikely(!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 &&
@@ -2108,10 +2130,21 @@ TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
(tab= find_locked_table(tab->next, db, table_name)))
continue;
- if (unlikely(!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;
}
@@ -3399,6 +3432,15 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
*/
if (tables->with)
{
+ if (tables->is_recursive_with_table() &&
+ !tables->is_with_table_recursive_reference())
+ {
+ tables->with->rec_outer_references++;
+ With_element *with_elem= tables->with;
+ while ((with_elem= with_elem->get_next_mutually_recursive()) !=
+ tables->with)
+ with_elem->rec_outer_references++;
+ }
if (tables->set_as_with_table(thd, tables->with))
DBUG_RETURN(1);
else
@@ -3813,10 +3855,10 @@ lock_table_names(THD *thd, const DDL_options_st &options,
mdl_requests.push_front(&global_request);
if (create_table)
- #ifdef WITH_WSREP
- if (thd->lex->sql_command != SQLCOM_CREATE_TABLE &&
+#ifdef WITH_WSREP
+ if (thd->lex->sql_command != SQLCOM_CREATE_TABLE &&
thd->wsrep_exec_mode != REPL_RECV)
- #endif
+#endif
lock_wait_timeout= 0; // Don't wait for timeout
}
@@ -3921,7 +3963,8 @@ 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.str, table->table_name.str, false))
+ if (!find_table_for_mdl_upgrade(thd, table->db.str, table->table_name.str,
+ NULL))
return TRUE;
}
@@ -4318,9 +4361,8 @@ 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_CSTRING *db,
- LEX_CSTRING *table,
- thr_lock_type lock_type)
+bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_CSTRING *db,
+ LEX_CSTRING *table, thr_lock_type lock_type)
{
for (; tl; tl= tl->next_global )
{
@@ -6932,10 +6974,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);
}