From 2f9555c40f96a956184a97e99d1b8f4cafbab024 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 10 Aug 2016 15:51:40 -0700 Subject: Removed the parameter from st_select_lex_unit::exec_recursive. Moved checking whether the limit set for the number of iterations when executing a recursive query has been reached from st_select_lex_unit::exec_recursive to TABLE_LIST::fill_recursive. Changed the name of the system variable max_recursion_level for max_recursive_iterations. Adjusted test cases. --- mysql-test/r/cte_recursive.result | 8 ++++---- mysql-test/r/mysqld--help.result | 4 ++-- .../suite/sys_vars/r/sysvars_server_notembedded.result | 2 +- mysql-test/t/cte_recursive.test | 6 +++--- sql/sql_class.h | 2 +- sql/sql_cte.h | 16 ++++++++++++++++ sql/sql_derived.cc | 11 ++++++++--- sql/sql_lex.h | 2 +- sql/sql_union.cc | 17 +---------------- sql/sys_vars.cc | 6 +++--- 10 files changed, 40 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/cte_recursive.result b/mysql-test/r/cte_recursive.result index a21416b5f43..f6ab5ee5dd7 100644 --- a/mysql-test/r/cte_recursive.result +++ b/mysql-test/r/cte_recursive.result @@ -1086,7 +1086,7 @@ generation name 1 Mom 2 Grandpa Bill 2 Grandma Ann -set statement max_recursion_level=2 for +set statement max_recursive_iterations=1 for with recursive ancestor_ids (id, generation) as @@ -1463,8 +1463,8 @@ drop table folks; create table t1(a int); insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); explain format=json -with recursive T as (select a from t1 union select a+10 from T where a < 1000) -select * from T; +with recursive t as (select a from t1 union select a+10 from t where a < 1000) +select * from t; EXPLAIN { "query_block": { @@ -1499,7 +1499,7 @@ EXPLAIN "access_type": "ALL", "rows": 10, "filtered": 100, - "attached_condition": "(T.a < 1000)" + "attached_condition": "(t.a < 1000)" } } } diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 9717b358f13..38075ef8520 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -450,7 +450,7 @@ The following options may be given as the first argument: max_allowed_packet instead. --max-prepared-stmt-count=# Maximum number of prepared statements in the server - --max-recursion-level[=#] + --max-recursive-iterations[=#] Maximum number of iterations when executing recursive queries --max-relay-log-size=# @@ -1273,7 +1273,7 @@ max-join-size 18446744073709551615 max-length-for-sort-data 1024 max-long-data-size 4194304 max-prepared-stmt-count 16382 -max-recursion-level 18446744073709551615 +max-recursive-iterations 18446744073709551615 max-relay-log-size 1073741824 max-seeks-for-key 18446744073709551615 max-sort-length 1024 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index d534669ac58..04709f014f7 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -2165,7 +2165,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME MAX_RECURSION_LEVEL +VARIABLE_NAME MAX_RECURSIVE_ITERATIONS SESSION_VALUE 4294967295 GLOBAL_VALUE 4294967295 GLOBAL_VALUE_ORIGIN COMPILE-TIME diff --git a/mysql-test/t/cte_recursive.test b/mysql-test/t/cte_recursive.test index 60f058b15f7..98fe159e174 100644 --- a/mysql-test/t/cte_recursive.test +++ b/mysql-test/t/cte_recursive.test @@ -914,7 +914,7 @@ as ) select * from ancestors; -set statement max_recursion_level=2 for +set statement max_recursive_iterations=1 for with recursive ancestor_ids (id, generation) as @@ -1074,8 +1074,8 @@ create table t1(a int); insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); explain format=json -with recursive T as (select a from t1 union select a+10 from T where a < 1000) -select * from T; +with recursive t as (select a from t1 union select a+10 from t where a < 1000) +select * from t; drop table t1; diff --git a/sql/sql_class.h b/sql/sql_class.h index 04ca37295bb..04a80166ad1 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -558,7 +558,7 @@ typedef struct system_variables ulong max_allowed_packet; ulong max_error_count; ulong max_length_for_sort_data; - ulong max_recursion_level; + ulong max_recursive_iterations; ulong max_sort_length; ulong max_tmp_tables; ulong max_insert_delayed_threads; diff --git a/sql/sql_cte.h b/sql/sql_cte.h index 52b2b8f4f77..dfe673dcce9 100644 --- a/sql/sql_cte.h +++ b/sql/sql_cte.h @@ -2,6 +2,7 @@ #define SQL_CTE_INCLUDED #include "sql_list.h" #include "sql_lex.h" +#include "sql_select.h" class select_union; struct st_unit_ctxt_elem; @@ -186,6 +187,8 @@ public: bool instantiate_tmp_tables(); + void prepare_for_next_iteration(); + friend class With_clause; }; @@ -356,6 +359,19 @@ bool With_element::all_are_stabilized() } +inline +void With_element::prepare_for_next_iteration() +{ + With_element *with_elem= this; + while ((with_elem= with_elem->get_next_mutually_recursive()) != this) + { + TABLE *rec_table= with_elem->first_rec_table_to_update; + if (rec_table) + rec_table->reginfo.join_tab->preread_init_done= false; + } +} + + inline void st_select_lex_unit::set_with_clause(With_clause *with_cl) { diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index e17896f9f24..33befdd4639 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -927,13 +927,18 @@ bool TABLE_LIST::fill_recursive(THD *thd) bool rc= false; st_select_lex_unit *unit= get_unit(); if (is_with_table_recursive_reference()) - rc= unit->exec_recursive(false); + { + rc= unit->exec_recursive(); + } else { rc= with->instantiate_tmp_tables(); - while(!rc && !with->all_are_stabilized()) + while (!rc && !with->all_are_stabilized()) { - rc= unit->exec_recursive(true); + if (with->level > thd->variables.max_recursive_iterations) + break; + with->prepare_for_next_iteration(); + rc= unit->exec_recursive(); } if (!rc) { diff --git a/sql/sql_lex.h b/sql/sql_lex.h index de3ccfc08a9..91741961db5 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -706,7 +706,7 @@ public: bool prepare(THD *thd, select_result *result, ulong additional_options); bool optimize(); bool exec(); - bool exec_recursive(bool is_driving_recursive); + bool exec_recursive(); bool cleanup(); inline void unclean() { cleaned= 0; } void reinit_exec_mechanism(); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 4a73a503ebe..382fabd39d7 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1167,7 +1167,7 @@ err: // One step of recursive execution -bool st_select_lex_unit::exec_recursive(bool is_driving_recursive) +bool st_select_lex_unit::exec_recursive() { st_select_lex *lex_select_save= thd->lex->current_select; st_select_lex *start= with_element->first_recursive; @@ -1189,18 +1189,6 @@ bool st_select_lex_unit::exec_recursive(bool is_driving_recursive) if ((saved_error= incr_table->file->ha_delete_all_rows())) goto err; - if (is_driving_recursive) - { - With_element *with_elem= with_element; - while ((with_elem= with_elem->get_next_mutually_recursive()) != - with_element) - { - rec_table= with_elem->first_rec_table_to_update; - if (rec_table) - rec_table->reginfo.join_tab->preread_init_done= false; - } - } - if (with_element->level == 0) { start= first_select(); @@ -1248,9 +1236,6 @@ bool st_select_lex_unit::exec_recursive(bool is_driving_recursive) if (with_element->level == 1) rec_table->reginfo.join_tab->preread_init_done= true; } - - if (with_element->level == thd->variables.max_recursion_level) - with_element->set_as_stabilized(); thd->lex->current_select= lex_select_save; err: diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index f63549ba3d7..29bb49a0083 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2145,10 +2145,10 @@ static Sys_var_ulong Sys_max_prepared_stmt_count( VALID_RANGE(0, 1024*1024), DEFAULT(16382), BLOCK_SIZE(1), &PLock_prepared_stmt_count); -static Sys_var_ulong Sys_max_recursion_level( - "max_recursion_level", +static Sys_var_ulong Sys_max_recursive_iterations( + "max_recursive_iterations", "Maximum number of iterations when executing recursive queries", - SESSION_VAR(max_recursion_level), CMD_LINE(OPT_ARG), + SESSION_VAR(max_recursive_iterations), CMD_LINE(OPT_ARG), VALID_RANGE(0, UINT_MAX), DEFAULT(UINT_MAX), BLOCK_SIZE(1)); static Sys_var_ulong Sys_max_sort_length( -- cgit v1.2.1