diff options
author | Igor Babaev <igor@askmonty.org> | 2016-06-30 15:13:12 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2016-06-30 15:13:12 -0700 |
commit | 8c6a9aa30f9e74388aaf923ac8e3b19ca0f86188 (patch) | |
tree | c01c2583837dcdd98f76e425f718e0255816e3cc /sql/sql_cte.cc | |
parent | 22c37c1fcf39cae7387248616d072f272e851cd3 (diff) | |
download | mariadb-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.cc | 73 |
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; + } + } } } |