summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2017-01-28 14:52:19 -0800
committerIgor Babaev <igor@askmonty.org>2017-01-28 15:47:11 -0800
commitabfcdb8fbc4dec1ef9e6ea8fc9961344186b0209 (patch)
treead29f96d2bbff77ef346507d387f6b31b907a6f8
parent64b5e94236e7c4246863fc70b91c346ba7b66b8b (diff)
downloadmariadb-git-abfcdb8fbc4dec1ef9e6ea8fc9961344186b0209.tar.gz
Fixed bug mdev-10773.
The temporary tables created for recursive table references should be closed in close_thread_tables(), because they might be used in the statements like ANALYZE WITH r AS (...) SELECT * from r where r is defined through recursion.
-rw-r--r--mysql-test/r/cte_recursive.result65
-rw-r--r--mysql-test/t/cte_recursive.test12
-rw-r--r--sql/sql_base.cc17
-rw-r--r--sql/sql_class.h6
-rw-r--r--sql/sql_union.cc9
5 files changed, 108 insertions, 1 deletions
diff --git a/mysql-test/r/cte_recursive.result b/mysql-test/r/cte_recursive.result
index d5476aec1c4..20ca5c8f8cb 100644
--- a/mysql-test/r/cte_recursive.result
+++ b/mysql-test/r/cte_recursive.result
@@ -2343,3 +2343,68 @@ select id + 1, uuid() from data_generator where id < 150000
select * from data_generator
) as a;
drop table t1;
+#
+# MDEV-10773: ANALYZE for query with recursive CTE
+#
+analyze format=json
+with recursive src(counter) as
+(select 1
+union
+select counter+1 from src where counter<10
+) select * from src;
+ANALYZE
+{
+ "query_block": {
+ "select_id": 1,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 10,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100,
+ "materialized": {
+ "query_block": {
+ "recursive_union": {
+ "table_name": "<union2,3>",
+ "access_type": "ALL",
+ "r_loops": 0,
+ "r_rows": null,
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 2,
+ "table": {
+ "message": "No tables used"
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 3,
+ "r_loops": 10,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ALL",
+ "r_loops": 10,
+ "rows": 2,
+ "r_rows": 1,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 90,
+ "attached_condition": "src.counter < 10"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/mysql-test/t/cte_recursive.test b/mysql-test/t/cte_recursive.test
index ea0f73be259..332996d4921 100644
--- a/mysql-test/t/cte_recursive.test
+++ b/mysql-test/t/cte_recursive.test
@@ -1505,3 +1505,15 @@ select id, test_data
) as a;
drop table t1;
+
+--echo #
+--echo # MDEV-10773: ANALYZE for query with recursive CTE
+--echo #
+
+--replace_regex /"r_total_time_ms": [0-9]*[.]?[0-9]*/"r_total_time_ms": "REPLACED"/
+analyze format=json
+with recursive src(counter) as
+(select 1
+ union
+ select counter+1 from src where counter<10
+) select * from src;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index ac4b8a45107..3758b3ba710 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -769,6 +769,23 @@ void close_thread_tables(THD *thd)
thd->derived_tables= 0;
}
+ if (thd->rec_tables)
+ {
+ TABLE *next;
+ /*
+ Close all temporary tables created for recursive table references.
+ This action was postponed because the table could be used in the
+ statements like ANALYZE WITH r AS (...) SELECT * from r
+ where r is defined through recursion.
+ */
+ for (table= thd->rec_tables ; table ; table= next)
+ {
+ next= table->next;
+ free_tmp_table(thd, table);
+ }
+ thd->rec_tables= 0;
+ }
+
/*
Mark all temporary tables used by this statement as free for reuse.
*/
diff --git a/sql/sql_class.h b/sql/sql_class.h
index b6dafd939bc..295474d0d62 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1381,6 +1381,11 @@ public:
*/
TABLE *derived_tables;
+ /*
+ Temporary tables created for recursive table references.
+ */
+ TABLE *rec_tables;
+
/*
During a MySQL session, one can lock tables in two modes: automatic
or manual. In automatic mode all necessary tables are locked just before
@@ -1461,6 +1466,7 @@ public:
open_tables= 0;
temporary_tables= 0;
derived_tables= 0;
+ rec_tables= 0;
extra_lock= 0;
lock= 0;
locked_tables_mode= LTM_NONE;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index b30b5528741..71d0e331101 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -283,7 +283,14 @@ void select_union_recursive::cleanup()
tab->file->extra(HA_EXTRA_RESET_STATE);
tab->file->ha_delete_all_rows();
}
- free_tmp_table(thd, tab);
+ /*
+ The table will be closed later in close_thread_tables(),
+ because it might be used in the statements like
+ ANALYZE WITH r AS (...) SELECT * from r
+ where r is defined through recursion.
+ */
+ tab->next= thd->rec_tables;
+ thd->rec_tables= tab;
}
}