Changeset: cf2de4ff9917 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/cf2de4ff9917
Modified Files:
        clients/Tests/exports.stable.out
        sql/backends/monet5/rel_physical.c
        sql/common/sql_list.c
        sql/include/sql_list.h
        sql/server/rel_dump.c
        sql/server/rel_exp.c
        sql/server/rel_optimizer_private.h
        sql/server/rel_prop.c
        sql/server/rel_prop.h
        sql/server/rel_rel.c
        sql/server/rel_rel.h
        sql/server/rel_select.c
        sql/server/rel_unnest.c
        sql/test/BugTracker-2021/Tests/batappend-undefined.Bug-7130.test
Branch: unnest2
Log Message:

initial implementation of 'Improving Unnesting of Complex Queries, by Neumann'


diffs (truncated from 2887 to 300 lines):

diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -1607,6 +1607,7 @@ cq *qc_find(qc *cache, int id);
 cq *qc_insert(qc *cache, allocator *sa, sql_rel *r, symbol *s, list *params, 
mapi_query_t type, char *codedstr, int no_mitosis);
 void rel_base_use_all(mvc *sql, sql_rel *rel);
 sql_rel *rel_basetable(mvc *sql, sql_table *t, const char *tname);
+list *rel_boundvar(mvc *sql, sql_rel *rel);
 sql_rel *rel_project(allocator *sa, sql_rel *l, list *e);
 list *rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, 
int intern);
 void res_tables_destroy(res_table *results);
diff --git a/sql/backends/monet5/rel_physical.c 
b/sql/backends/monet5/rel_physical.c
--- a/sql/backends/monet5/rel_physical.c
+++ b/sql/backends/monet5/rel_physical.c
@@ -183,7 +183,9 @@ has_groupby(sql_rel *rel)
                case op_select:
                case op_topn:
                case op_sample:
-                       return has_groupby(rel->l);
+                       if (rel->l)
+                               return has_groupby(rel->l);
+                       return 0;
                case op_insert:
                case op_update:
                case op_delete:
@@ -206,11 +208,14 @@ has_groupby(sql_rel *rel)
 }
 
 static sql_rel *
-rel_partition(mvc *sql, sql_rel *rel)
+rel_partition(visitor *v, mvc *sql, sql_rel *rel)
 {
        if (mvc_highwater(sql))
                return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: 
running out of stack space");
 
+       if (v->opt >= 0 && rel->opt >= v->opt) /* only once */
+        return 0;
+
        switch (rel->op) {
        case op_basetable:
        case op_sample:
@@ -221,7 +226,7 @@ rel_partition(mvc *sql, sql_rel *rel)
        case op_groupby:
        case op_topn:
                if (rel->l)
-                       rel_partition(sql, rel->l);
+                       rel_partition(v, sql, rel->l);
                break;
        case op_semi:
        case op_anti:
@@ -229,20 +234,20 @@ rel_partition(mvc *sql, sql_rel *rel)
        case op_inter:
        case op_except:
                if (rel->l)
-                       rel_partition(sql, rel->l);
+                       rel_partition(v, sql, rel->l);
                if (rel->r)
-                       rel_partition(sql, rel->r);
+                       rel_partition(v, sql, rel->r);
                break;
        case op_munion:
                for (node *n = ((list*)rel->l)->h; n; n = n->next)
-                       rel_partition(sql, n->data);
+                       rel_partition(v, sql, n->data);
                break;
        case op_insert:
        case op_update:
        case op_delete:
        case op_truncate:
                if (rel->r && rel->card <= CARD_AGGR)
-                       rel_partition(sql, rel->r);
+                       rel_partition(v, sql, rel->r);
                break;
        case op_join:
        case op_left:
@@ -250,9 +255,9 @@ rel_partition(mvc *sql, sql_rel *rel)
        case op_full:
                if (has_groupby(rel->l) || has_groupby(rel->r)) {
                        if (rel->l)
-                               rel_partition(sql, rel->l);
+                               rel_partition(v, sql, rel->l);
                        if (rel->r)
-                               rel_partition(sql, rel->r);
+                               rel_partition(v, sql, rel->r);
                } else {
                        _rel_partition(sql, rel);
                }
@@ -260,22 +265,24 @@ rel_partition(mvc *sql, sql_rel *rel)
        case op_ddl:
                if (rel->flag == ddl_output || rel->flag == ddl_create_seq || 
rel->flag == ddl_alter_seq || rel->flag == ddl_alter_table || rel->flag == 
ddl_create_table || rel->flag == ddl_create_view) {
                        if (rel->l)
-                               rel_partition(sql, rel->l);
+                               rel_partition(v, sql, rel->l);
                } else if (rel->flag == ddl_list || rel->flag == ddl_exception) 
{
                        if (rel->l)
-                               rel_partition(sql, rel->l);
+                               rel_partition(v, sql, rel->l);
                        if (rel->r)
-                               rel_partition(sql, rel->r);
+                               rel_partition(v, sql, rel->r);
                }
                break;
        case op_table:
                if ((IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == 
TABLE_FROM_RELATION) && rel->l)
-                       rel_partition(sql, rel->l);
+                       rel_partition(v, sql, rel->l);
                break;
        default:
                assert(0);
                break;
        }
+       if (rel && v->opt >= 0)
+        rel->opt = v->opt;
        return rel;
 }
 
@@ -378,7 +385,9 @@ rel_physical(mvc *sql, sql_rel *rel)
 
        v.changes = 0;
        if (!sql->recursive) {
-                       (void)rel_partition(sql, rel);
+                       if (v.opt >= 0)
+                               v.opt = rel->opt+1;
+                       (void)rel_partition(&v, sql, rel);
        }
 
        rel = rel_exp_visitor_topdown(&v, rel, &exp_timezone, true);
diff --git a/sql/common/sql_list.c b/sql/common/sql_list.c
--- a/sql/common/sql_list.c
+++ b/sql/common/sql_list.c
@@ -59,6 +59,14 @@ sa_list_append(allocator *sa, list *l, v
 }
 
 list *
+sa_list_prepend(allocator *sa, list *l, void *data)
+{
+       if (!l)
+               l = SA_LIST(sa, NULL);
+       return list_prepend(l, data);
+}
+
+list *
 list_add(list *l, void *data)
 {
        if (!l)
diff --git a/sql/include/sql_list.h b/sql/include/sql_list.h
--- a/sql/include/sql_list.h
+++ b/sql/include/sql_list.h
@@ -41,6 +41,7 @@ sql_export list *sa_list(allocator *sa);
 extern list *list_new(allocator *sa, fdestroy destroy);
 
 extern list *sa_list_append( allocator *sa, list *l, void *data);
+extern list *sa_list_prepend( allocator *sa, list *l, void *data);
 extern list *list_add( list *l, void *data);
 
 extern void list_destroy(list *l);
diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c
--- a/sql/server/rel_dump.c
+++ b/sql/server/rel_dump.c
@@ -750,7 +750,7 @@ rel_print_rel(mvc *sql, stream  *fout, s
        }
        if (sql->show_details && decorate && rel->p) {
                for (prop *p = rel->p; p; p = p->p) {
-                       if ((p->kind != PROP_COUNT && p->kind != PROP_UKEY) || 
(ATOMIC_GET(&GDKdebug) & TESTINGMASK) == 0) {
+                       if ((p->kind != PROP_COUNT && p->kind != PROP_UKEY && 
p->kind != PROP_UNNESTING) || (ATOMIC_GET(&GDKdebug) & TESTINGMASK) == 0) {
                                char *pv = propvalue2string(ta, p);
                                mnstr_printf(fout, " %s %s", 
propkind2string(p), pv);
                        }
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -813,6 +813,8 @@ exp_ref_by_label(allocator *sa, sql_exp 
                */
        if (is_intern(o))
                set_intern(e);
+       if (is_freevar(o) && o->alias.label == o->nid /* only original IU */)
+               set_freevar(e, is_freevar(o)-1);
        return exp_propagate(sa, e, o);
 }
 
@@ -1912,8 +1914,9 @@ rel_find_exp_and_corresponding_rel(sql_r
                case op_basetable:
                        break;
                case op_munion:
-                       for (node* n = ((list*)rel->l)->h; n && !ne; n = 
n->next)
-                               ne = 
rel_find_exp_and_corresponding_rel(n->data, e, subexp, res, under_join);
+                       if (!is_project(rel->op) && rel->l)
+                               for (node* n = ((list*)rel->l)->h; n && !ne; n 
= n->next)
+                                       ne = 
rel_find_exp_and_corresponding_rel(n->data, e, subexp, res, under_join);
                        break;
                default:
                        if (!is_project(rel->op) && rel->l)
diff --git a/sql/server/rel_optimizer_private.h 
b/sql/server/rel_optimizer_private.h
--- a/sql/server/rel_optimizer_private.h
+++ b/sql/server/rel_optimizer_private.h
@@ -44,6 +44,7 @@ typedef struct sql_optimizer {
 #define statistics_gathered       (1 << 3)
 #define rel_remote_func_used      (1 << 4)
 #define rewrite_gt_zero_used      (1 << 5)
+#define unnest_used                              (1 << 6)
 
 #define is_rewrite_fix_count_used(X)    ((X & rewrite_fix_count_used) == 
rewrite_fix_count_used)
 #define is_rewrite_values_used(X)       ((X & rewrite_values_used) == 
rewrite_values_used)
@@ -51,6 +52,7 @@ typedef struct sql_optimizer {
 #define are_statistics_gathered(X)      ((X & statistics_gathered) == 
statistics_gathered)
 #define is_rel_remote_func_used(X)      ((X & rel_remote_func_used) == 
rel_remote_func_used)
 #define is_rewrite_gt_zero_used(X)      ((X & rewrite_gt_zero_used) == 
rewrite_gt_zero_used)
+#define is_unnest_used(X)                          ((X & unnest_used) == 
unnest_used)
 
 /* At the moment the following optimizers 'packs' can be disabled,
    later we could disable individual optimizers from the 'pack' */
diff --git a/sql/server/rel_prop.c b/sql/server/rel_prop.c
--- a/sql/server/rel_prop.c
+++ b/sql/server/rel_prop.c
@@ -114,6 +114,7 @@ propkind2string( prop *p)
                PT(GROUPINGS);
                PT(MIN);
                PT(MAX);
+               PT(UNNESTING);
        }
        return "UNKNOWN";
 }
diff --git a/sql/server/rel_prop.h b/sql/server/rel_prop.h
--- a/sql/server/rel_prop.h
+++ b/sql/server/rel_prop.h
@@ -22,7 +22,8 @@ typedef enum rel_prop {
        PROP_UKEY,              /* p = list of exps */
        PROP_REMOTE,    /* uri for remote execution */
        PROP_USED,      /* number of times exp is used */
-       PROP_GROUPINGS  /* used by ROLLUP/CUBE/GROUPING SETS, value contains 
the list of sets */
+       PROP_GROUPINGS,  /* used by ROLLUP/CUBE/GROUPING SETS, value contains 
the list of sets */
+       PROP_UNNESTING  /* used by unnesting rewriter */
 } rel_prop;
 
 typedef struct prop {
diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -1142,6 +1142,8 @@ rel_groupby(mvc *sql, sql_rel *l, list *
                                exp_label(sql->sa, e, ++sql->label);
                        ne = exp_ref(sql, e);
                        ne = exp_propagate(sql->sa, ne, e);
+                       if (is_freevar(e))
+                               set_freevar(ne, is_freevar(e)-1);
                        append(aggrs, ne);
                }
        }
@@ -1272,7 +1274,8 @@ exps_reset_props(list *exps, bool setnil
  * refer to the tname relation, anywhere in the relational tree
  */
 list *
-_rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int 
intern, int basecol /* basecol only */ )
+_rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int 
intern, int basecol /* basecol only */,
+               bool bound )
 {
        list *lexps, *rexps = NULL, *exps = NULL, *rels;
 
@@ -1290,10 +1293,10 @@ _rel_projections(mvc *sql, sql_rel *rel,
        case op_left:
        case op_right:
        case op_full:
-               lexps = _rel_projections(sql, rel->l, tname, settname, intern, 
basecol);
+               lexps = _rel_projections(sql, rel->l, tname, settname, intern, 
basecol, bound);
                exps_reset_props(lexps, is_right(rel->op) || is_full(rel->op));
                if (!rel->attr)
-                       rexps = _rel_projections(sql, rel->r, tname, settname, 
intern, basecol);
+                       rexps = _rel_projections(sql, rel->r, tname, settname, 
intern, basecol, bound);
                exps_reset_props(rexps, is_left(rel->op) || is_full(rel->op));
                if (rexps)
                        lexps = list_join(lexps, rexps);
@@ -1308,6 +1311,8 @@ _rel_projections(mvc *sql, sql_rel *rel,
                        for (node *en = r->h; en; en = en->next) {
                                sql_exp *e = en->data;
 
+                               if (is_freevar(e) && e->alias.label == e->nid 
&& bound)
+                                       continue;
                                if (basecol && !is_basecol(e))
                                        continue;
                                if (intern || !is_intern(e)) {
@@ -1336,6 +1341,8 @@ _rel_projections(mvc *sql, sql_rel *rel,
                        for (node *en = rel->exps->h; en; en = en->next) {
                                sql_exp *e = en->data;
 
+                               if (is_freevar(e) && e->alias.label == e->nid 
&& bound)
+                                       continue;
                                if (basecol && !is_basecol(e))
                                        continue;
                                if (intern || !is_intern(e)) {
@@ -1360,7 +1367,7 @@ _rel_projections(mvc *sql, sql_rel *rel,
                        if (rels->h)
                                r = rels->h->data;
                        if (r)
-                               exps = _rel_projections(sql, r, tname, 
settname, intern, basecol);
+                               exps = _rel_projections(sql, r, tname, 
settname, intern, basecol, bound);
                        /* it's a multi-union (expressions have to be the same 
in all the operands)
                         * so we are ok only with the expressions of the first 
operand
                         */
@@ -1368,6 +1375,8 @@ _rel_projections(mvc *sql, sql_rel *rel,
                                for (node *en = exps->h; en; en = en->next) {
                                        sql_exp *e = en->data;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to