Changeset: 4fd82b761be9 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/4fd82b761be9
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/sql_statement.c
        sql/backends/monet5/sql_statement.h
        sql/include/sql_relation.h
        sql/server/rel_exp.c
        sql/server/rel_multiset.c
        sql/test/nested/Tests/webclicks.test.in
Branch: nestedtypes
Log Message:

keep better track of nested structures


diffs (290 lines):

diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -1759,6 +1759,7 @@ nested_stmts(backend *be, list *exps, no
                        if (e->type == e_column && e->f) {
                                stmt *s = nested_stmts(be, e->f, &m);
                                s->label = e->alias.label;
+                               s->nested = true;
                                append(r, s);
                        } else {
                                stmt *s = m->data;
@@ -1927,8 +1928,10 @@ exp_bin(backend *be, sql_exp *e, stmt *l
                } else {
                        s = stmt_convert(be, l, (!push&&l->nrcols==0)?NULL:sel, 
from, to);
                }
-               if (s && s->type == st_list && e->f)
+               if (s && s->type == st_list && e->f) {
                        s = nested_stmts(be, e->f, &s->op4.lval->h);
+                       s->nested = true;
+               }
        }       break;
        case e_func: {
                node *en;
@@ -2586,6 +2589,9 @@ rel2bin_subtable(backend *be, sql_table 
                        assert(c);
                        if (exp->f && (c->type.multiset || 
c->type.type->composite)) {
                                s = rel2bin_subtable(be, t, dels, c, exp->f);
+                               if (!s)
+                                       return s;
+                               s->nested = true;
                                if (s && s->type == st_list && 
c->type.multiset) { /* keep rowid at the end */
                                        stmt *ns = stmt_col(be, c, dels, 
dels->partition);
                                        list_append(s->op4.lval, ns);
@@ -2669,6 +2675,7 @@ rel2bin_basetable(backend *be, sql_rel *
                                s = rel2bin_subtable(be, t, dels, c, exp->f);
                                if (!s)
                                        return s;
+                               s->nested = true;
                                if (s && s->type == st_list && 
c->type.multiset) { /* keep rowid at the end */
                                        stmt *ns = (c == fcol) ? col : 
stmt_col(be, c, complex?dels:NULL, dels->partition);
                                        list_append(s->op4.lval, ns);
diff --git a/sql/backends/monet5/sql_statement.c 
b/sql/backends/monet5/sql_statement.c
--- a/sql/backends/monet5/sql_statement.c
+++ b/sql/backends/monet5/sql_statement.c
@@ -2609,6 +2609,15 @@ stmt_project_join(backend *be, stmt *op1
        return q;
 }
 
+static list *
+unnest_stmt(stmt *o)
+{
+       while (o->type == st_alias)
+               o = o->op1;
+       assert(o && o->type == st_list);
+       return o->op4.lval;
+}
+
 stmt *
 stmt_project(backend *be, stmt *op1, stmt *op2)
 {
@@ -2616,6 +2625,21 @@ stmt_project(backend *be, stmt *op1, stm
                return NULL;
        if (!op2->nrcols)
                return stmt_const(be, op1, op2);
+       if (op2->nested) {
+               list *ops = unnest_stmt(op2);
+               list *nops = sa_list(be->mvc->sa);
+               for(node *n = ops->h; n; n = n->next) {
+                       stmt *i = n->data;
+                       if (!i->nested)
+                               i = stmt_project(be, op1, i);
+                       append(nops, i);
+               }
+               stmt *s = stmt_list(be, nops);
+               if (s == NULL)
+                       return NULL;
+               s->nested = true;
+               return s;
+       }
        InstrPtr q = stmt_project_join(be, op1, op2, false);
        if (q) {
                stmt *s = stmt_create(be->mvc->sa, st_join);
@@ -4744,6 +4768,7 @@ stmt_alias_(backend *be, stmt *op1, int 
        s->key = op1->key;
        s->aggr = op1->aggr;
        s->multiset = op1->multiset;
+       s->nested = op1->nested;
 
        s->tname = tname;
        s->cname = alias;
diff --git a/sql/backends/monet5/sql_statement.h 
b/sql/backends/monet5/sql_statement.h
--- a/sql/backends/monet5/sql_statement.h
+++ b/sql/backends/monet5/sql_statement.h
@@ -125,7 +125,8 @@ typedef struct stmt {
         partition:1,   /* selected as mitosis candidate */
         reduce:1,              /* used to reduce number of rows (also for 
joins) */
         loop:1,                /* cond statement is looping */
-        multiset:1;    /* id column of multiset */
+        multiset:1,    /* id column of multiset */
+        nested:1;              /* id column of nested */
 
        struct stmt *cand;      /* optional candidate list */
 
diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h
--- a/sql/include/sql_relation.h
+++ b/sql/include/sql_relation.h
@@ -193,6 +193,7 @@ typedef enum operator_type {
 #define is_column(et)          (et != e_cmp)
 #define is_alias(et)           (et == e_column)
 #define is_analytic(e)                 ((e)->type == e_func && 
((sql_subfunc*)(e)->f)->func->type == F_ANALYTIC)
+#define is_nested(e)           (e->f && ((e)->type == e_convert || (e)->type 
== e_column))
 
 #define is_base(op)            (op == op_basetable || op == op_table)
 #define is_basetable(op)       (op == op_basetable)
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
@@ -1047,7 +1047,7 @@ exp_setname(mvc *sql, sql_exp *e, sql_al
        if (name)
                e->alias.name = name;
        e->alias.parent = p;
-       if ((e->type == e_convert || e->type == e_column) && e->f)
+       if (is_nested(e))
                exps_setname(sql, e->f, p, name);
 }
 
@@ -2917,7 +2917,7 @@ exps_bind_nid(list *exps, int nid)
 
                        if (e->alias.label == nid)
                                return e;
-                       if (e->f && (e->type == e_column || e->type == 
e_convert)) {
+                       if (is_nested(e)) {
                                e = exps_bind_nid(e->f, nid);
                                if (e)
                                        return e;
diff --git a/sql/server/rel_multiset.c b/sql/server/rel_multiset.c
--- a/sql/server/rel_multiset.c
+++ b/sql/server/rel_multiset.c
@@ -7,44 +7,61 @@
 #include "rel_updates.h"
 #include "rel_rewriter.h"
 
-extern void _rel_print(mvc *sql, sql_rel *cur);
+/* TODO move into unnest code */
+static bool
+has_multiset(list *exps)
+{
+       bool needed = false;
+       if (list_empty(exps))
+               return needed;
+       for(node *n = exps->h; n && !needed; n = n->next) {
+               sql_exp *e = n->data;
+               sql_subtype *t = exp_subtype(e);
+
+               needed = (t && t->multiset);
+               if (!needed && t->type->composite && is_nested(e))
+                       needed = has_multiset(e->f);
+       }
+       return needed;
+}
+
+static sql_rel *
+ms_add_join_exps(visitor *v, sql_rel *rel, list *exps)
+{
+       if (list_empty(exps))
+               return rel;
+       for(node *n = exps->h; n; n = n->next) {
+               sql_exp *e = n->data;
+               sql_subtype *t = exp_subtype(e);
+               if (t->multiset) {
+                       v->changes++;
+                       sql_exp *le = exp_ref(v->sql, e);
+                       list *rexps = rel_projections(v->sql, rel->r, NULL, 0, 
1);
+                       sql_exp *re = exps_bind_column(rexps, "id", NULL, NULL, 
0);
+                       if (le && re) {
+                               re = exp_ref(v->sql, re);
+                               e = exp_compare(v->sql->sa, le, re, cmp_equal);
+                               rel->exps = sa_list_append(v->sql->sa, 
rel->exps, e);
+                       }
+                       return rel;
+               } else if (t->type->composite) {
+                       /* sofar only handles one level */
+                       return ms_add_join_exps(v, rel, e->f);
+               }
+       }
+       return rel;
+}
 
 /* TODO handle composite/multset (ie deep nested cases) too */
 static sql_rel *
 fm_join(visitor *v, sql_rel *rel)
 {
        if (list_empty(rel->exps) && is_dependent(rel)) {
-               bool needed = false;
-               sql_rel *l = rel->l;
-               sql_rel *r = rel->r;
-               if (0 && r && is_basetable(r->op)) {
-                       sql_table *t = r->l;
-                       if (t->base.name[0] == '%')
-                               return l;
-               }
-               list *exps = rel_projections(v->sql, l, NULL, 0, 1);
-               for(node *n = exps->h; n && !needed; n = n->next) {
-                       sql_subtype *t = exp_subtype(n->data);
-                       needed = (t && t->multiset);
-               }
-               if (needed) {
-                       for(node *n = exps->h; n; n = n->next) {
-                               sql_exp *e = n->data;
-                               sql_subtype *t = exp_subtype(e);
-                               if (t->multiset) {
-                                       v->changes++;
-                                       sql_exp *le = exp_ref(v->sql, e);
-                                       list *rexps = rel_projections(v->sql, 
r, NULL, 0, 1);
-                                       sql_exp *re = exps_bind_column(rexps, 
"id", NULL, NULL, 0);
-                                       if (le && re) {
-                                               re = exp_ref(v->sql, re);
-                                               e = exp_compare(v->sql->sa, le, 
re, cmp_equal);
-                                               rel->exps = 
sa_list_append(v->sql->sa, rel->exps, e);
-                                       }
-                                       return rel;
-                               }
-                       }
-               }
+               list *exps = rel_projections(v->sql, rel->l, NULL, 0, 1);
+               bool needed = has_multiset(exps);
+
+               if (needed)
+                       return ms_add_join_exps(v, rel, exps);
        }
        return rel;
 }
diff --git a/sql/test/nested/Tests/webclicks.test.in 
b/sql/test/nested/Tests/webclicks.test.in
--- a/sql/test/nested/Tests/webclicks.test.in
+++ b/sql/test/nested/Tests/webclicks.test.in
@@ -61,11 +61,49 @@ productDetail
 2024-11-30 22:13:37.823000
 Mozilla
 
-#query
-#select e.eventid, el.element.key from ( select cast(t.json as event) as e 
from (select json from 
r'/home/niels/data/rc/default/sql/test/nested/Tests/webclicks.json') t), 
unnest(e.location.list) el
-#----
-#996257967-103007874
-#996257967-103007874
+query TT
+select e.eventid, el.element.key from ( select cast(t.json as event) as e from 
(select json from 
r'/home/niels/data/rc/default/sql/test/nested/Tests/webclicks.json') t), 
unnest(e.location.list) el
+----
+996257967-103007874
+hash
+996257967-103007874
+hostname
+996257967-103007874
+pageSubType
+996257967-103007874
+pageType
+996257967-103007874
+pathname
+996257967-103007874
+protocol
+996257967-103007874
+referrer
+996257967-103007874
+search
+996257967-103007874
+state
+996257967-103007874
+title
+996257967-103007874
+hash
+996257967-103007874
+hostname
+996257967-103007874
+pageSubType
+996257967-103007874
+pageType
+996257967-103007874
+pathname
+996257967-103007874
+protocol
+996257967-103007874
+referrer
+996257967-103007874
+search
+996257967-103007874
+state
+996257967-103007874
+title
 
 #query TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
 #select cast(t.json as event) from (select json from 
r'$TSTSRCDIR/webclicks.json') t
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to