summaryrefslogtreecommitdiff
path: root/sql/sql_show.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_show.cc')
-rw-r--r--sql/sql_show.cc32
1 files changed, 31 insertions, 1 deletions
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 85169783393..b8e2aeac88d 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -5120,6 +5120,7 @@ public:
int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
+ DBUG_ENTER("get_all_tables");
LEX *lex= thd->lex;
TABLE *table= tables->table;
TABLE_LIST table_acl_check;
@@ -5137,7 +5138,29 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
uint table_open_method= tables->table_open_method;
bool can_deadlock;
MEM_ROOT tmp_mem_root;
- DBUG_ENTER("get_all_tables");
+ /*
+ We're going to open FRM files for tables.
+ In case of VIEWs that contain stored function calls,
+ these stored functions will be parsed and put to the SP cache.
+
+ Suppose we have a view containing a stored function call:
+ CREATE VIEW v1 AS SELECT f1() AS c1;
+ and now we're running:
+ SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=f1();
+ If a parallel thread invalidates the cache,
+ e.g. by creating or dropping some stored routine,
+ the SELECT query will re-parse f1() when processing "v1"
+ and replace the outdated cached version of f1() to a new one.
+ But the old version of f1() is referenced from the m_sp member
+ of the Item_func_sp instances used in the WHERE condition.
+ We cannot destroy it. To avoid such clashes, let's remember
+ all old routines into a temporary SP cache collection
+ and process tables with a new empty temporary SP cache collection.
+ Then restore to the old SP cache collection at the end.
+ */
+ Sp_caches old_sp_caches;
+
+ old_sp_caches.sp_caches_swap(*thd);
bzero(&tmp_mem_root, sizeof(tmp_mem_root));
@@ -5313,6 +5336,13 @@ err:
thd->restore_backup_open_tables_state(&open_tables_state_backup);
free_root(&tmp_mem_root, 0);
+ /*
+ Now restore to the saved SP cache collection
+ and clear the temporary SP cache collection.
+ */
+ old_sp_caches.sp_caches_swap(*thd);
+ old_sp_caches.sp_caches_clear();
+
DBUG_RETURN(error);
}