diff options
author | Galina Shalygina <galashalygina@gmail.com> | 2016-05-12 23:23:12 +0300 |
---|---|---|
committer | Galina Shalygina <galashalygina@gmail.com> | 2016-05-12 23:23:12 +0300 |
commit | d9b332bd2009cc520534bb9413e2f50c717237aa (patch) | |
tree | 483913747409a69096cc30705bc056dc53bf9976 /sql | |
parent | d0e973a3b0fc4384b8aeebfa6509a653b07b7eac (diff) | |
download | mariadb-git-d9b332bd2009cc520534bb9413e2f50c717237aa.tar.gz |
Made prepared statement, explain and views working with recursuve CTE.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_cte.cc | 20 | ||||
-rw-r--r-- | sql/sql_cte.h | 23 | ||||
-rw-r--r-- | sql/sql_select.cc | 4 | ||||
-rw-r--r-- | sql/sql_union.cc | 10 | ||||
-rw-r--r-- | sql/sql_view.cc | 10 |
5 files changed, 50 insertions, 17 deletions
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 04d53495400..7e60a8d1892 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -731,7 +731,7 @@ bool TABLE_LIST::is_with_table_recursive_reference() bool st_select_lex::check_unrestricted_recursive() { With_element *with_elem= get_with_element(); - if (!with_elem) + if (!with_elem ||!with_elem->is_recursive) return false; table_map unrestricted= 0; table_map encountered= 0; @@ -806,6 +806,18 @@ bool With_element::check_unrestricted_recursive(st_select_lex *sel, } } } + ti.rewind(); + while ((tbl= ti++)) + { + for (TABLE_LIST *tab= tbl; tab; tab= tab->embedding) + { + if (tab->outer_join & (JOIN_TYPE_LEFT | JOIN_TYPE_RIGHT)) + { + unrestricted|= get_elem_map(); + break; + } + } + } return false; } @@ -824,9 +836,9 @@ bool With_element::check_unrestricted_recursive(st_select_lex *sel, void With_clause::print(String *str, enum_query_type query_type) { - str->append(STRING_WITH_LEN("WITH ")); + str->append(STRING_WITH_LEN("with ")); if (with_recursive) - str->append(STRING_WITH_LEN("RECURSIVE ")); + str->append(STRING_WITH_LEN("recursive ")); for (With_element *with_elem= first_elem; with_elem != NULL; with_elem= with_elem->next_elem) @@ -853,7 +865,7 @@ void With_clause::print(String *str, enum_query_type query_type) void With_element::print(String *str, enum_query_type query_type) { str->append(query_name); - str->append(STRING_WITH_LEN(" AS ")); + str->append(STRING_WITH_LEN(" as ")); str->append('('); spec->print(str, query_type); str->append(')'); diff --git a/sql/sql_cte.h b/sql/sql_cte.h index b559be93de5..0312fcd0643 100644 --- a/sql/sql_cte.h +++ b/sql/sql_cte.h @@ -82,9 +82,8 @@ public: uint level; - select_union *partial_result; - select_union *final_result; select_union_recursive *rec_result; + TABLE *result_table; With_element(LEX_STRING *name, @@ -95,9 +94,8 @@ public: references(0), table(NULL), query_name(name), column_list(list), spec(unit), is_recursive(false), with_anchor(false), - partial_result(NULL), final_result(NULL), - rec_result(NULL), result_table(NULL) - { reset();} + level(0), rec_result(NULL), result_table(NULL) + {} bool check_dependencies_in_spec(THD *thd); @@ -147,10 +145,7 @@ public: void mark_as_cleaned(); - void reset() - { - level= 0; - } + void reset_for_exec(); void set_result_table(TABLE *tab) { result_table= tab; } @@ -284,4 +279,14 @@ void With_element::mark_as_cleaned() owner->cleaned|= get_elem_map(); } + +inline +void With_element::reset_for_exec() +{ + level= 0; + owner->with_prepared_anchor&= ~mutually_recursive; + owner->cleaned&= ~get_elem_map(); +} + + #endif /* SQL_CTE_INCLUDED */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0a961b4a53a..71b672b6131 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -816,6 +816,8 @@ JOIN::prepare(TABLE_LIST *tables_init, &hidden_group_fields, &select_lex->select_n_reserved)) DBUG_RETURN(-1); + if (select_lex->check_unrestricted_recursive()) + DBUG_RETURN(-1); /* Resolve the ORDER BY that was skipped, then remove it. */ if (skip_order_by && select_lex != select_lex->master_unit()->global_parameters()) @@ -24491,7 +24493,7 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) if (unit->is_union()) { - if (unit->union_needs_tmp_table()) + if (unit->union_needs_tmp_table() && unit->fake_select_lex) { unit->fake_select_lex->select_number= FAKE_SELECT_LEX_ID; // just for initialization unit->fake_select_lex->type= "UNION RESULT"; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 7345c6f224e..902620aaac1 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -514,6 +514,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, with_element->rec_result= new (thd_arg->mem_root) select_union_recursive(thd_arg); union_result= with_element->rec_result; + fake_select_lex= NULL; } if (!(tmp_result= union_result)) goto err; /* purecov: inspected */ @@ -615,7 +616,8 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, TMP_TABLE_ALL_COLUMNS); if (union_result->create_result_table(thd, &types, MY_TEST(union_distinct), - create_options, "", false, + create_options, derived->alias, + false, instantiate_tmp_table, false)) goto err; if (!derived->table) @@ -932,7 +934,7 @@ bool st_select_lex_unit::exec() if (uncacheable || !item || !item->assigned() || describe) { - if (!fake_select_lex) + if (!fake_select_lex && !(with_element && with_element->is_recursive)) union_result->cleanup(); for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select()) { @@ -973,7 +975,7 @@ bool st_select_lex_unit::exec() { records_at_start= table->file->stats.records; sl->join->exec(); - if (sl == union_distinct) + if (sl == union_distinct && !(with_element && with_element->is_recursive)) { // This is UNION DISTINCT, so there should be a fake_select_lex DBUG_ASSERT(fake_select_lex != NULL); @@ -1315,6 +1317,8 @@ void st_select_lex_unit::reinit_exec_mechanism() */ field->fixed= 0; } + if (with_element && with_element->is_recursive) + with_element->reset_for_exec(); } #endif } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index b66f678adfc..4fd4fb8dd01 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -35,6 +35,7 @@ #include "sp_cache.h" #include "datadict.h" // dd_frm_is_view() #include "sql_derived.h" +#include "sql_cte.h" // check_dependencies_in_with_clauses() #define MD5_BUFF_LENGTH 33 @@ -429,6 +430,12 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, lex->link_first_table_back(view, link_to_local); view->open_type= OT_BASE_ONLY; + if (check_dependencies_in_with_clauses(thd, lex->with_clauses_list)) + { + res= TRUE; + goto err; + } + if (open_temporary_tables(thd, lex->query_tables) || open_and_lock_tables(thd, lex->query_tables, TRUE, 0)) { @@ -1383,6 +1390,9 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, TABLE_LIST *tbl; Security_context *security_ctx= 0; + if (check_dependencies_in_with_clauses(thd, thd->lex->with_clauses_list)) + goto err; + /* Check rights to run commands (ANALYZE SELECT, EXPLAIN SELECT & SHOW CREATE) which show underlying tables. |