summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorGalina Shalygina <galashalygina@gmail.com>2016-05-12 23:23:12 +0300
committerGalina Shalygina <galashalygina@gmail.com>2016-05-12 23:23:12 +0300
commitd9b332bd2009cc520534bb9413e2f50c717237aa (patch)
tree483913747409a69096cc30705bc056dc53bf9976 /sql
parentd0e973a3b0fc4384b8aeebfa6509a653b07b7eac (diff)
downloadmariadb-git-d9b332bd2009cc520534bb9413e2f50c717237aa.tar.gz
Made prepared statement, explain and views working with recursuve CTE.
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_cte.cc20
-rw-r--r--sql/sql_cte.h23
-rw-r--r--sql/sql_select.cc4
-rw-r--r--sql/sql_union.cc10
-rw-r--r--sql/sql_view.cc10
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.