Changeset: 6fce72691f82 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/6fce72691f82 Modified Files: sql/server/rel_optimize_proj.c sql/server/rel_select.c sql/server/rel_unnest.c sql/test/cte/Tests/All sql/test/cte/Tests/recursive_cte_correlated_subquery.test sql/test/cte/Tests/test_correlated_recursive_cte.test Branch: recursive_cte Log Message:
handle some recursive ctes with correlation diffs (truncated from 578 to 300 lines): diff --git a/sql/server/rel_optimize_proj.c b/sql/server/rel_optimize_proj.c --- a/sql/server/rel_optimize_proj.c +++ b/sql/server/rel_optimize_proj.c @@ -1752,6 +1752,9 @@ rel_push_aggr_down_n_arry(visitor *v, sq list *rgbe = NULL, *gbe = NULL, *exps = NULL; node *n, *m; + if (is_recursive(u)) + return rel; + // TODO why? if (u->op == op_project && !need_distinct(u)) u = u->l; @@ -1910,7 +1913,7 @@ rel_push_aggr_down(visitor *v, sql_rel * if (!u || !(is_union(u->op) || is_munion(u->op)) || need_distinct(u) || is_single(u) || !u->exps || rel_is_ref(u)) return rel; - if (is_munion(u->op) && !is_recursive(u)) + if (is_munion(u->op)) return rel_push_aggr_down_n_arry(v, rel); ul = u->l; diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c --- a/sql/server/rel_select.c +++ b/sql/server/rel_select.c @@ -259,6 +259,45 @@ rel_subquery_optname(sql_query *query, s return rel_table_optname(sql, sq, sn->name, refs); } +static void +rel_rename(mvc *sql, sql_rel *nrel, char *rname, sql_rel *brel) +{ + assert(is_project(nrel->op)); + if (brel) { + if (is_project(nrel->op) && nrel->exps) { + for (node *ne = nrel->exps->h, *be = brel->exps->h; ne && be; ne = ne->next, be = be->next) { + sql_exp *e = ne->data; + sql_exp *b = be->data; + char *name = NULL; + + if (!is_intern(e)) { + if (!exp_name(e)) + name = make_label(sql->sa, ++sql->label); + noninternexp_setname(sql, e, rname, name); + set_basecol(e); + e->alias.label = b->alias.label; + } + } + } + list_hash_clear(nrel->exps); + } else if (is_project(nrel->op) && nrel->exps) { + node *ne = nrel->exps->h; + + for (; ne; ne = ne->next) { + sql_exp *e = ne->data; + char *name = NULL; + + if (!is_intern(e)) { + if (!exp_name(e)) + name = make_label(sql->sa, ++sql->label); + noninternexp_setname(sql, e, rname, name); + set_basecol(e); + } + } + list_hash_clear(nrel->exps); + } +} + sql_rel * rel_with_query(sql_query *query, symbol *q ) { @@ -275,7 +314,7 @@ rel_with_query(sql_query *query, symbol symbol *sym = d->data.sym; dnode *dn = sym->data.lval->h->next; char *rname = qname_schema_object(dn->data.lval); - sql_rel *nrel; + sql_rel *nrel, *base_rel = NULL; symbol *recursive_part = NULL; sql_rel_view *recursive_union = NULL; int recursive_distinct = 0; @@ -307,7 +346,8 @@ rel_with_query(sql_query *query, symbol return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL); } if (recursive && recursive_part) { - sql_rel *base_rel = nrel; + base_rel = nrel; + rel_rename(sql, base_rel, rname, base_rel); dn->next->next->data.sym = recursive_part; set_processed(nrel); nrel = rel_semantic(query, sym); @@ -352,23 +392,7 @@ rel_with_query(sql_query *query, symbol return NULL; } } - assert(is_project(nrel->op)); - if (is_project(nrel->op) && nrel->exps) { - node *ne = nrel->exps->h; - - for (; ne; ne = ne->next) { - sql_exp *e = ne->data; - char *name = NULL; - - if (!is_intern(e)) { - if (!exp_name(e)) - name = make_label(sql->sa, ++sql->label); - noninternexp_setname(sql, e, rname, name); - set_basecol(e); - } - } - list_hash_clear(nrel->exps); - } + rel_rename(sql, nrel, rname, base_rel); } rel = rel_semantic(query, next); stack_pop_frame(sql); diff --git a/sql/server/rel_unnest.c b/sql/server/rel_unnest.c --- a/sql/server/rel_unnest.c +++ b/sql/server/rel_unnest.c @@ -826,6 +826,19 @@ push_up_project(mvc *sql, sql_rel *rel, { sql_rel *r = rel->r; + if (rel_is_ref(r) && is_recursive(r)) { + + if (is_join(rel->op) && is_dependent(rel)) { + sql_rel *l = r->l; + r->l = rel; + rel->r = l; + /* add missing expressions */ + list *exps = rel_projections(sql, rel->l, NULL, 1, 1); + r->exps = list_distinct(list_merge(exps, r->exps, (fdup)NULL), (fcmp)exp_equal, (fdup)NULL); + return r; + } + assert(0); + } assert(is_simple_project(r->op)); if (rel_is_ref(r)) { sql_rel *nr = rel_project(sql->sa, r->l ? rel_dup(r->l) : NULL, exps_copy(sql, r->exps)); @@ -1579,12 +1592,18 @@ push_up_munion(mvc *sql, sql_rel *rel, l sql_rel *d = rel->l, *s = rel->r; int need_distinct = is_semi(rel->op) && need_distinct(d); int len = 0, need_length_reduction = 0; + int rec = is_recursive(s); /* left of rel should be a set */ list *rlist = sa_list(sql->sa); if (d && is_distinct_set(sql, d, ad) && s && is_munion(s->op)) { list *iu = s->l; - for(node *n = iu->h; n; n = n->next) { + if (rec) { + sql_rel *r = iu->h->data; + set_recursive(r); + append(rlist, rel_dup(r)); + } + for(node *n = rec?iu->h->next:iu->h; n; n = n->next) { sql_rel *sl = n->data; sl = rel_project(sql->sa, rel_dup(sl), rel_projections(sql, sl, NULL, 1, 1)); for (node *n = sl->exps->h, *m = s->exps->h; n && m; n = n->next, m = m->next) @@ -1611,7 +1630,7 @@ push_up_munion(mvc *sql, sql_rel *rel, l } } - for(node *n = rlist->h; n; n = n->next) { + for(node *n = rec?rlist->h->next:rlist->h; n; n = n->next) { /* D djoin (sl setop sr) -> (D djoin sl) setop (D djoin sr) */ sql_rel *sl = n->data; sl = rel_crossproduct(sql->sa, rel_dup(d), sl, rel->op); @@ -1641,7 +1660,16 @@ push_up_munion(mvc *sql, sql_rel *rel, l ns->exps = list_merge(sexps, ns->exps, (fdup)NULL); } /* add/remove projections to inner parts of the union (as we push a join or semijoin down) */ - for(node *n = rlist->h; n; n = n->next) { + if (rec) { + sql_rel *sl = rlist->h->data; + list *exps = exps_copy(sql, ad); + for(node *n = exps->h; n; n = n->next) { + sql_exp *e = n->data; + set_freevar(e, 0); + } + sl->exps = list_merge(exps, sl->exps, (fdup)NULL); + } + for(node *n = rec?rlist->h->next:rlist->h; n; n = n->next) { sql_rel *sl = n->data; n->data = rel_project(sql->sa, sl, rel_projections(sql, sl, NULL, 1, 1)); } diff --git a/sql/test/cte/Tests/All b/sql/test/cte/Tests/All --- a/sql/test/cte/Tests/All +++ b/sql/test/cte/Tests/All @@ -6,7 +6,7 @@ recursive_cte_complex_pipelines #recursive_cte_correlated_subquery recursive_cte_error recursive_hang_2745 -#test_correlated_recursive_cte +test_correlated_recursive_cte test_cte_in_cte test_cte_overflow test_cte diff --git a/sql/test/cte/Tests/recursive_cte_correlated_subquery.test b/sql/test/cte/Tests/recursive_cte_correlated_subquery.test --- a/sql/test/cte/Tests/recursive_cte_correlated_subquery.test +++ b/sql/test/cte/Tests/recursive_cte_correlated_subquery.test @@ -4,26 +4,26 @@ input(sud) AS ( VALUES('53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79') ), digits(z, lp) AS ( -SELECT CAST(lp+1 AS TEXT), lp::int+1 FROM generate_series(0,8,1) t(lp) +SELECT CAST(lp+1 AS TEXT), cast(lp as int)+1 FROM generate_series(0,8+1,1) t(lp) ), x(s, ind) AS ( -SELECT sud, instr(sud, '.') FROM input +SELECT sud, contains(sud, '.') FROM input UNION ALL SELECT -substr(s, 1, ind::int-1) || z || substr(s, ind::int+1), -instr(substr(s, 1, ind::int-1) || z || substr(s, ind::int+1), '.' ) +substr(s, 1, cast(ind as int)-1) || z || substr(s, cast(ind as int)+1), +contains(substr(s, 1, cast(ind as int)-1) || z || substr(s, cast(ind as int)+1), '.' ) FROM x, digits AS z -WHERE ind::int>0 +WHERE cast(ind as int) >0 AND NOT EXISTS ( SELECT 1 FROM digits AS lp -WHERE z.z = substr(s, ((ind::int-1)//9)*9 + lp, 1) -OR z.z = substr(s, ((ind::int-1)%9) + (lp-1)*9 + 1, 1) -OR z.z = substr(s, (((ind::int-1)//3) % 3) * 3 -+ ((ind::int-1)//27) * 27 + lp -+ ((lp-1) // 3) * 6, 1) +WHERE z.z = substr(s, ((cast(ind as int)-1)/9)*9 + lp, 1) +OR z.z = substr(s, ((cast(ind as int)-1)%9) + (lp-1)*9 + 1, 1) +OR z.z = substr(s, (((cast(ind as int)-1)/3) % 3) * 3 ++ ((cast(ind as int)-1)/27) * 27 + lp ++ ((lp-1) / 3) * 6, 1) ) ) -SELECT s FROM x WHERE ind::int=0; +SELECT s FROM x WHERE cast(ind as int)=0; ---- 534678912672195348198342567859761423426853791713924856961537284287419635345286179 diff --git a/sql/test/cte/Tests/test_correlated_recursive_cte.test b/sql/test/cte/Tests/test_correlated_recursive_cte.test --- a/sql/test/cte/Tests/test_correlated_recursive_cte.test +++ b/sql/test/cte/Tests/test_correlated_recursive_cte.test @@ -12,13 +12,20 @@ FROM generate_series(1,4+1) AS _(x), L SELECT * FROM t) AS t ORDER BY x, y; ---- -1 1 -1 2 -1 3 -2 2 -2 3 -3 3 -4 4 +1 +1 +1 +2 +1 +3 +2 +2 +2 +3 +3 +3 +4 +4 # Correlation in the recursive query query II @@ -34,15 +41,24 @@ FROM generate_series(1,4+1) AS _(x), L SELECT * FROM t) AS t ORDER BY x, y; ---- -1 1 -1 2 -1 3 -2 1 -2 3 -3 1 -3 4 -4 1 -4 5 +1 +1 +1 +2 +1 +3 +2 +1 +2 +3 +3 +1 +3 +4 +4 +1 +4 +5 _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org