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]