Changeset: c78a7cef8bf1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/c78a7cef8bf1
Modified Files:
        monetdb5/modules/mal/tablet.c
        sql/server/rel_basetable.c
        sql/server/rel_basetable.h
        sql/server/rel_multiset.c
        sql/server/rel_prop.c
        sql/server/rel_prop.h
        sql/server/rel_select.c
Branch: nested
Log Message:

improved unnest handling, passing the unnest expression via an relational 
properly


diffs (truncated from 307 to 300 lines):

diff --git a/monetdb5/modules/mal/tablet.c b/monetdb5/modules/mal/tablet.c
--- a/monetdb5/modules/mal/tablet.c
+++ b/monetdb5/modules/mal/tablet.c
@@ -277,7 +277,8 @@ output_line(char **buf, size_t *len, cha
        return 0;
 }
 
-static ssize_t output_multiset(char **buf, size_t *len, ssize_t fill, char 
**localbuf, size_t *locallen, Column *fmt, BUN nr_attrs, int multiset, int 
composite, bool quoted, int id);
+static ssize_t output_multiset_dense(char **buf, size_t *len, ssize_t fill, 
char **localbuf, size_t *locallen, Column *fmt, BUN nr_attrs, int multiset, int 
composite, bool quoted, int id);
+static ssize_t output_multiset_sorted(char **buf, size_t *len, ssize_t fill, 
char **localbuf, size_t *locallen, Column *fmt, BUN nr_attrs, int multiset, int 
composite, bool quoted, int id);
 
 static inline ssize_t
 output_value(char **buf, size_t *len, ssize_t fill, char **localbuf, size_t 
*locallen, Column *f)
@@ -340,7 +341,15 @@ output_composite(char **buf, size_t *len
                        int nr_attrs = f->nrfields - 1;
                        const char *p = BUNtail(fmt[j+nr_attrs].ci, 
fmt[j+nr_attrs].p);
 
-                       fill = output_multiset(buf, len, fill, localbuf, 
locallen, fmt + j + 1, nr_attrs-1, f->multiset, f->composite, true, *(int*)p);
+                       /* various cases:
+                        *      rowid column dense (but for ints !!
+                        *      rowid column sorted
+                        *      else
+                        */
+                       if (f->c)
+                               fill = output_multiset_dense(buf, len, fill, 
localbuf, locallen, fmt + j + 1, nr_attrs-1, f->multiset, f->composite, true, 
*(int*)p);
+                       else
+                               fill = output_multiset_sorted(buf, len, fill, 
localbuf, locallen, fmt + j + 1, nr_attrs-1, f->multiset, f->composite, true, 
*(int*)p);
                        fmt[j+nr_attrs].p++;
                        f = fmt + j + nr_attrs; /* closing bracket */
                        j += nr_attrs + 1;
@@ -363,8 +372,9 @@ output_composite(char **buf, size_t *len
 }
 
 #define MS_ARRAY 2
+/* id is prev id + 1 */
 static ssize_t
-output_multiset(char **buf, size_t *len, ssize_t fill, char **localbuf, size_t 
*locallen,
+output_multiset_dense(char **buf, size_t *len, ssize_t fill, char **localbuf, 
size_t *locallen,
                                  Column *fmt, BUN nr_attrs, int multiset, int 
composite, bool quoted, int id)
 {
        nr_attrs -= (multiset == MS_ARRAY)?2:1;
@@ -395,6 +405,48 @@ output_multiset(char **buf, size_t *len,
        return fill;
 }
 
+/* id >= prev id */
+static ssize_t
+output_multiset_sorted(char **buf, size_t *len, ssize_t fill, char **localbuf, 
size_t *locallen,
+                                 Column *fmt, BUN nr_attrs, int multiset, int 
composite, bool quoted, int id)
+{
+       nr_attrs -= (multiset == MS_ARRAY)?2:1;
+       Column *msid = fmt + nr_attrs;
+       /* how to also keep prev id */
+       int *idp = (int*)Tloc(msid->c, msid->p);
+       int first = 1;
+
+       if (msid->p) {
+               int pos = msid->p;
+               while (idp[-1] >= id && (pos-1) >= 0) {
+                       idp--;
+                       pos--;
+               }
+       }
+
+       if (!quoted)
+               (*buf)[fill++] = '\'';
+       (*buf)[fill++] = '{';
+       (*buf)[fill] = 0;
+       for (; *idp == id && fill > 0; idp++, msid->p++) {
+               if (!first)
+                       (*buf)[fill++] = ',';
+               if (composite) {
+                       fill = output_composite(buf, len, fill, localbuf, 
locallen, fmt, nr_attrs, composite, true);
+               } else {
+                       fill = output_value(buf, len, fill, localbuf, locallen, 
fmt);
+               }
+               first = 0;
+       }
+       if (fill < 0)
+               return fill;
+       (*buf)[fill++] = '}';
+       if (!quoted)
+               (*buf)[fill++] = '\'';
+       (*buf)[fill] = 0;
+       return fill;
+}
+
 static ssize_t
 output_line_complex(char **buf, size_t *len, ssize_t fill, char **localbuf, 
size_t *locallen,
                                  Column *fmt, BUN nr_attrs)
@@ -409,7 +461,10 @@ output_line_complex(char **buf, size_t *
                        int nr_attrs = f->nrfields - 1;
                        p = BUNtail(fmt[j+nr_attrs].ci, fmt[j+nr_attrs].p);
 
-                       fill = output_multiset(buf, len, fill, localbuf, 
locallen, fmt + j + 1, nr_attrs-1, f->multiset, f->composite, false, *(int*)p);
+                       if (f->c)
+                           fill = output_multiset_dense(buf, len, fill, 
localbuf, locallen, fmt + j + 1, nr_attrs-1, f->multiset, f->composite, false, 
*(int*)p);
+                       else
+                           fill = output_multiset_sorted(buf, len, fill, 
localbuf, locallen, fmt + j + 1, nr_attrs-1, f->multiset, f->composite, false, 
*(int*)p);
                        fmt[j+nr_attrs].p++;
                        f = fmt + j + nr_attrs; /* closing bracket */
                        j += nr_attrs + 1;
diff --git a/sql/server/rel_basetable.c b/sql/server/rel_basetable.c
--- a/sql/server/rel_basetable.c
+++ b/sql/server/rel_basetable.c
@@ -28,19 +28,11 @@
 typedef struct rel_base_t {
        sql_table *mt;
        sql_alias *name;
-       list *subtables; /* list of sql_table pointers */
        int disallowed; /* ie check per column */
        int basenr;
        uint32_t used[];
 } rel_base_t;
 
-list *
-rel_base_subtables(sql_rel *r)
-{
-       rel_base_t *ba = r->r;
-       return ba->subtables;
-}
-
 void
 rel_base_disallow(sql_rel *r)
 {
@@ -225,7 +217,6 @@ rel_nested_basetable_add_cols(mvc *sql, 
 
        if (!ba)
                return NULL;
-       append(pba->subtables, t);
 
        sql_alias *atname = a_create(sa, colname);
        atname->parent = ba->name;
@@ -281,8 +272,6 @@ rel_nested_basetable(mvc *sql, sql_table
 {
        allocator *sa = sql->sa;
        sql_rel *rel = rel_create(sa);
-       /* keep each combination subtable / base number in a list */
-       /* each has a unique sub-range of numbers claimed */
        /* keep all column exp's as one large list in the result already */
 
        int nrcols = ol_length(t->columns), end = nrcols + 1 + 
ol_length(t->idxs);
@@ -292,7 +281,6 @@ rel_nested_basetable(mvc *sql, sql_table
        if(!rel || !ba)
                return NULL;
 
-       ba->subtables = sa_list(sa);
        ba->basenr = sql->nid;
        sql->nid += end;
        if (isTable(t) && t->s && !isDeclaredTable(t)) /* count active rows 
only */
diff --git a/sql/server/rel_basetable.h b/sql/server/rel_basetable.h
--- a/sql/server/rel_basetable.h
+++ b/sql/server/rel_basetable.h
@@ -59,6 +59,4 @@ extern int rel_base_has_column_privilege
 extern void rel_base_set_mergetable( sql_rel *rel, sql_table *mt); /* keep 
parent merge table */
 extern sql_table *rel_base_get_mergetable( sql_rel *rel);
 
-extern list *rel_base_subtables( sql_rel *rel);
-
 #endif /* _REL_BASETABLE_H_ */
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
@@ -30,10 +30,16 @@ ms_add_join_exps(visitor *v, sql_rel *re
 {
        if (list_empty(exps))
                return rel;
+       sql_rel *r = rel->r;
+       prop *p = r->p;
+       if (!p || p->kind != PROP_UNNEST)
+               return NULL;
+       sql_exp *re = p->value.pval;
+
        for(node *n = exps->h; n; n = n->next) {
                sql_exp *e = n->data;
                sql_subtype *t = exp_subtype(e);
-               if (t->multiset) {
+               if (exp_match(e, re) && t->multiset) {
                        v->changes++;
                        sql_exp *le = exp_ref(v->sql, e);
                        list *rexps = rel_projections(v->sql, rel->r, NULL, 0, 
1);
@@ -46,10 +52,12 @@ ms_add_join_exps(visitor *v, sql_rel *re
                        return rel;
                } else if (t->type->composite) {
                        /* sofar only handles one level */
-                       return ms_add_join_exps(v, rel, e->f);
+                       sql_rel *res = ms_add_join_exps(v, rel, e->f);
+                       if (res)
+                               return res;
                }
        }
-       return rel;
+       return NULL;
 }
 
 /* TODO handle composite/multset (ie deep nested cases) too */
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
@@ -12,6 +12,7 @@
 
 #include "monetdb_config.h"
 #include "sql_relation.h"
+#include "rel_exp.h"
 #include "rel_prop.h"
 #include "sql_string.h"
 #include "sql_atom.h"
@@ -112,6 +113,7 @@ propkind2string( prop *p)
                PT(GROUPINGS);
                PT(MIN);
                PT(MAX);
+               PT(UNNEST);
        }
        return "UNKNOWN";
 }
@@ -172,6 +174,9 @@ propvalue2string(allocator *sa, prop *p)
                }
                return res;
        }
+       case PROP_UNNEST: {
+               return sa_strdup(sa, exp_name((sql_exp*)p->value.pval));
+       }
        default:
                break;
        }
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
@@ -23,7 +23,8 @@ typedef enum rel_prop {
        PROP_HASHCOL,   /* could use hash idx */
        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_UNNEST     /* used by UNNEST function, value contains the unnest 
expression */
 } rel_prop;
 
 typedef struct prop {
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
@@ -726,6 +726,11 @@ rel_unnest_func(sql_query *query, list *
                if (!e->freevar || e->type != e_column)
                        return sql_error(query->sql, ERR_NOTFOUND, 
SQLSTATE(42000) "SELECT: unnest multiset not found");
                sql_rel *r = query_fetch_outer(query, e->freevar-1);
+               if (r && !is_basetable(r->op)) {
+                       sql_rel *rr = NULL;
+                       if (rel_find_exp_and_corresponding_rel(r, e, false, 
&rr, NULL))
+                               r = rr;
+               }
                if (r && is_basetable(r->op)) {
                        sql_table *t = r->l;
                        sql_column *c = t?mvc_bind_column(query->sql, t, 
exp_name(e)):NULL;
@@ -735,7 +740,13 @@ rel_unnest_func(sql_query *query, list *
                        sql_table *st = mvc_bind_table(query->sql, t->s, 
c->storage_type);
                        if (!st)
                                return sql_error(query->sql, ERR_NOTFOUND, 
SQLSTATE(42000) "SELECT: unnest multiset table '%s' missing", c->storage_type);
-                       return rel_basetable(query->sql, st, 
a_create(query->sql->sa, tname?tname:exp_name(e)));
+                       sql_rel *bt = rel_basetable(query->sql, st, 
a_create(query->sql->sa, tname?tname:exp_name(e)));
+                       if (!bt)
+                               return bt;
+                       prop *p = prop_create(query->sql->sa, PROP_UNNEST, 
bt->p);
+                       p->value.pval = e;
+                       bt->p = p;
+                       return bt;
                } else if (r) {
                        sql_subtype *t = exp_subtype(e);
                        reset_freevar(e);
@@ -755,31 +766,19 @@ rel_unnest_func(sql_query *query, list *
                                        append(nexps, ne);
                                        first = false;
                                }
-                               return rel_project(query->sql->sa, rel_dup(r), 
nexps);
+                               sql_rel *rp = rel_project(query->sql->sa, 
rel_dup(r), nexps);
+                               if (!rp)
+                                       return rp;
+                               prop *p = prop_create(query->sql->sa, 
PROP_UNNEST, rp->p);
+                               p->value.pval = e;
+                               rp->p = p;
+                               return rp;
                        } else {
                                return sql_error(query->sql, ERR_NOTFOUND, 
SQLSTATE(42000) "SELECT: unnest multiset table missing");
                        }
                } else {
                        return sql_error(query->sql, ERR_NOTFOUND, 
SQLSTATE(42000) "SELECT: unnest multiset table missing");
                }
-#if 0
-               assert(c->type.multiset && c->type.type->composite);
-               list *res_exps = sa_list(query->sql->sa);
-               sql_alias *ta = a_create(query->sql->sa, 
tname?tname:exp_name(e));
-               for (node *n = c->type.type->d.fields->h; n; n = n->next) {
-                       sql_arg *a = n->data;
-                       sql_exp *e = exp_column(query->sql->sa, ta, a->name, 
&a->type, CARD_MULTI, 1, 0, 0);
-                       e->alias.label = -(query->sql->nid++);
-
-                       set_basecol(e);
-                       append(res_exps, e);
-               }
-               list *args = sa_list(query->sql->sa);
-               append(args, e);
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to