summaryrefslogtreecommitdiff
path: root/sql/sql_cte.cc
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2016-06-30 15:13:12 -0700
committerIgor Babaev <igor@askmonty.org>2016-06-30 15:13:12 -0700
commit8c6a9aa30f9e74388aaf923ac8e3b19ca0f86188 (patch)
treec01c2583837dcdd98f76e425f718e0255816e3cc /sql/sql_cte.cc
parent22c37c1fcf39cae7387248616d072f272e851cd3 (diff)
downloadmariadb-git-8c6a9aa30f9e74388aaf923ac8e3b19ca0f86188.tar.gz
Added a proper check for acceptable mutually recursive CTE.
Diffstat (limited to 'sql/sql_cte.cc')
-rw-r--r--sql/sql_cte.cc73
1 files changed, 40 insertions, 33 deletions
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index 2b3a72c1b3a..3c663d7d260 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -292,43 +292,50 @@ bool With_clause::check_anchors()
with_elem != NULL;
with_elem= with_elem->next_elem)
{
- if (!with_elem->is_recursive || with_elem->with_anchor)
+ if (!with_elem->is_recursive)
continue;
-
- table_map anchored= 0;
- for (With_element *elem= with_elem;
- elem != NULL;
- elem= elem->next_elem)
- {
- if (elem->mutually_recursive && elem->with_anchor)
- anchored |= elem->get_elem_map();
- }
- table_map non_anchored= with_elem->mutually_recursive & ~anchored;
- with_elem->work_dep_map= non_anchored & with_elem->base_dep_map;
- }
-
- /*Building transitive clousure on work_dep_map*/
- for (With_element *with_elem= first_elem;
- with_elem != NULL;
- with_elem= with_elem->next_elem)
- {
- table_map with_elem_map= with_elem->get_elem_map();
- for (With_element *elem= first_elem; elem != NULL; elem= elem->next_elem)
+
+ if (!with_elem->with_anchor)
{
- if (elem->work_dep_map & with_elem_map)
- elem->work_dep_map|= with_elem->work_dep_map;
+ With_element *elem= with_elem;
+ while ((elem= elem->get_next_mutually_recursive()) != with_elem)
+ {
+ if (elem->with_anchor)
+ break;
+ }
+ if (elem == with_elem)
+ {
+ my_error(ER_RECURSIVE_WITHOUT_ANCHORS, MYF(0),
+ with_elem->query_name->str);
+ return true;
+ }
}
- }
-
- for (With_element *with_elem= first_elem;
- with_elem != NULL;
- with_elem= with_elem->next_elem)
- {
- if (with_elem->work_dep_map & with_elem->get_elem_map())
+ else
{
- my_error(ER_RECURSIVE_WITHOUT_ANCHORS, MYF(0),
- with_elem->query_name->str);
- return true;
+ With_element *elem= with_elem;
+ while ((elem= elem->get_next_mutually_recursive()) != with_elem)
+ elem->work_dep_map= elem->base_dep_map & elem->mutually_recursive;
+ elem= with_elem;
+ while ((elem= elem->get_next_mutually_recursive()) != with_elem)
+ {
+ table_map elem_map= elem->get_elem_map();
+ With_element *el= with_elem;
+ while ((el= el->get_next_mutually_recursive()) != with_elem)
+ {
+ if (el->work_dep_map & elem_map)
+ el->work_dep_map|= elem->work_dep_map;
+ }
+ }
+ elem= with_elem;
+ while ((elem= elem->get_next_mutually_recursive()) != with_elem)
+ {
+ if (elem->work_dep_map & elem->get_elem_map())
+ {
+ my_error(ER_UNACCEPTABLE_MUTUAL_RECURSION, MYF(0),
+ with_elem->query_name->str);
+ return true;
+ }
+ }
}
}