Changeset: c21397c0acde for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/c21397c0acde
Modified Files:
sql/backends/monet5/rel_bin.c
sql/common/sql_types.c
sql/server/CMakeLists.txt
sql/server/rel_select.c
sql/server/rel_unnest.c
sql/server/rel_updates.c
sql/server/sql_parser.y
sql/storage/bat/bat_storage.c
sql/storage/store.c
Branch: nested
Log Message:
some initial array/setof unnest handling
diffs (truncated from 406 to 300 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
@@ -695,6 +695,8 @@ tuple_create_result(backend *be, sql_exp
(void)sql_error(be->mvc, 02, SQLSTATE(42000) "Cannot handle
empty composite type");
return -1;
}
+ if (multiset) /* rowid */
+ append(cols, sa_list(be->mvc->sa));
for(node *n = attr->h; n; n = n->next) {
sql_exp *e = n->data;
@@ -705,9 +707,9 @@ tuple_create_result(backend *be, sql_exp
}
append(cols, sa_list(be->mvc->sa));
}
- if (multiset)
+ if (multiset) /* multisetid */
append(cols, sa_list(be->mvc->sa));
- if (multiset == MS_ARRAY)
+ if (multiset == MS_ARRAY) /* multisetnr */
append(cols, sa_list(be->mvc->sa));
return 0;
}
@@ -726,8 +728,15 @@ append_tuple(backend *be, sql_exp *tuple
}
assert(tuple->row);
list *attr = exp_get_values(tuple);
- node *n, *m;
- for(n = attr->h, m = cols->h; n; n = n->next, m = m->next) {
+ node *n, *m = cols->h;
+ if (multiset) {
+ if (lcnt == 1) {
+ list *vals = m->data;
+ append(vals, stmt_atom_int(be, rowcnt));
+ }
+ m = m->next;
+ }
+ for(n = attr->h; n; n = n->next, m = m->next) {
sql_exp *e = n->data;
list *vals = m->data;
@@ -781,9 +790,9 @@ value_list(backend *be, sql_exp *vals_ex
list *attr = sa_list(be->mvc->sa);
if (tuple_create_result(be, vals->h->data, attr, multiset) < 0)
return NULL;
- int rowcnt = 1;
- for (node *n = vals->h; n; n = n->next, rowcnt++) {
- if (append_tuple(be, n->data, left, sel, attr, rowcnt,
1, multiset) < 0)
+ int rowcnt = 1, lcnt = 1;
+ for (node *n = vals->h; n; n = n->next, lcnt++) {
+ if (append_tuple(be, n->data, left, sel, attr, rowcnt,
lcnt++, multiset) < 0)
return NULL;
}
return tuple_result(be, attr);
@@ -1584,6 +1593,20 @@ is_const_func(sql_subfunc *f, list *attr
}
static stmt*
+exp2bin_multiset(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *sel)
+{
+ (void)be;
+ (void)fe;
+ (void)right;
+ (void)sel;
+ assert(list_length(left->op4.lval) == 1);
+ stmt *s = left->op4.lval->h->data;
+ while(s->type == st_alias)
+ s = s->op1;
+ return s;
+}
+
+static stmt*
exp2bin_file_loader(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt
*sel)
{
assert(left == NULL); (void)left;
@@ -1812,6 +1835,8 @@ exp_bin(backend *be, sql_exp *e, stmt *l
return exp2bin_copyfrombinary(be, e, left,
right, sel);
if (strcmp(fname, "file_loader") == 0)
return exp2bin_file_loader(be, e, left, right,
sel);
+ if (strcmp(fname, "multiset") == 0)
+ return exp2bin_multiset(be, e, left, right,
sel);
if (strcmp(fname, "-1") == 0) /* map arguments to A0 ..
An */
return exp2bin_named_placeholders(be, e);
}
@@ -2804,7 +2829,7 @@ rel2bin_table(backend *be, sql_rel *rel,
}
}
}
- assert(rel->flag != TABLE_PROD_FUNC || !sub || !(sub->nrcols));
+ //assert(rel->flag != TABLE_PROD_FUNC || !sub ||
!(sub->nrcols));
sub = stmt_list(be, l);
return sub;
} else if (rel->l) { /* handle sub query via function */
@@ -5784,7 +5809,7 @@ rel2bin_insert(backend *be, sql_rel *rel
for (n = ol_first_node(t->columns), m = inserts->op4.lval->h; n && m; m
= m->next) {
sql_column *c = n->data;
- if (c->type.type->composite) {
+ if (c->type.type->composite && !c->type.multiset) {
n = insert_composite(updates, c, n, m->data);
} else {
updates[c->colnr] = m->data;
diff --git a/sql/common/sql_types.c b/sql/common/sql_types.c
--- a/sql/common/sql_types.c
+++ b/sql/common/sql_types.c
@@ -1738,6 +1738,18 @@ sqltypeinit( allocator *sa)
/* sys_update_schemas, sys_update_tables */
sql_create_procedure(sa, "sys_update_schemas", "sql", "update_schemas",
FALSE, 0);
sql_create_procedure(sa, "sys_update_tables", "sql", "update_tables",
FALSE, 0);
+
+ /* virtual multiset mapping functions */
+ sql_create_func(sa, "rowid", "", "", TRUE, TRUE, SCALE_NONE, 0, OID, 0);
+ sql_create_func(sa, "multisetid", "", "", TRUE, TRUE, SCALE_NONE, 0,
OID, 1, ANY);
+ sql_create_func(sa, "multisetnr", "", "", TRUE, TRUE, SCALE_NONE, 0,
INT, 1, ANY);
+ sql_create_func(sa, "multisetfield", "", "", TRUE, TRUE, SCALE_NONE, 0,
ANY, 1, ANY);
+ f = sql_create_union(sa, "multiset", "", "", TRUE, SCALE_NONE, 0,
TABLE, 1, ANY);
+ f->vararg = 1;
+ f->varres = 1;
+ f = sql_create_union(sa, "unnest", "", "", TRUE, SCALE_NONE, 0, TABLE,
1, ANY); /* unnest multiset */
+ f->vararg = 1;
+ f->varres = 1;
}
void
diff --git a/sql/server/CMakeLists.txt b/sql/server/CMakeLists.txt
--- a/sql/server/CMakeLists.txt
+++ b/sql/server/CMakeLists.txt
@@ -65,6 +65,7 @@ target_sources(sqlserver
rel_xml.c
rel_dump.c
rel_file_loader.c
+ rel_multiset.c
rel_dump.h rel_exp.h rel_rel.h
rel_basetable.h
rel_rewriter.h
@@ -95,6 +96,7 @@ target_sources(sqlserver
sql_tokens.h
sql_partition.h
rel_file_loader.h
+ rel_multiset.h
${BISON_sqlparser_OUTPUT_HEADER}
${BISON_sqlparser_OUTPUT_SOURCE}
PUBLIC
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
@@ -716,6 +716,30 @@ file_loader_add_table_column_types(mvc *
}
static sql_rel *
+rel_unnest_func(sql_query *query, list *exps, char *tname)
+{
+ if (list_empty(exps))
+ return sql_error(query->sql, ERR_NOTFOUND, SQLSTATE(42000)
"SELECT: unnest multiset missing");
+ for( node *n = exps->h; n; n = n->next) {
+ sql_exp *e = n->data;
+ 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))
+ return sql_error(query->sql, ERR_NOTFOUND,
SQLSTATE(42000) "SELECT: unnest multiset table missing");
+ sql_table *t = r->l;
+ sql_column *c = t?mvc_bind_column(query->sql, t,
exp_name(e)):NULL;
+ if (!c)
+ return sql_error(query->sql, ERR_NOTFOUND,
SQLSTATE(42000) "SELECT: unnest multiset column '%s' missing", exp_name(e));
+ 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?st->base.name:tname));
+ }
+ return NULL;
+}
+
+static sql_rel *
rel_file_loader(mvc *sql, list *exps, list *tl, char *tname)
{
sql_subfunc *f = NULL;
@@ -773,7 +797,10 @@ rel_named_table_function(sql_query *quer
dnode *l = sym->data.lval->h, *n;
char *fname = qname_schema_object(l->data.lval);
char *sname = qname_schema(l->data.lval);
-
+ bool unnest = (!sname && strcmp(fname, "unnest") == 0);
+
+ if (unnest)
+ lateral = 1;
tl = sa_list(sql->sa);
exps = sa_list(sql->sa);
if (l->next)
@@ -811,12 +838,16 @@ rel_named_table_function(sql_query *quer
append(exps, e);
is_value &= exp_is_atom(e);
}
- if (!is_value || (lateral && outer))
- sq = rel_project(sql->sa, NULL, exps);
- if (lateral && outer) {
- sq = rel_crossproduct(sql->sa, sq,
outer, op_join);
- set_dependent(sq);
- set_processed(sq);
+ if (unnest) {
+ is_value = 1;
+ } else {
+ if (!is_value || (lateral && outer))
+ sq = rel_project(sql->sa, NULL,
exps);
+ if (lateral && outer) {
+ sq = rel_crossproduct(sql->sa,
sq, outer, op_join);
+ set_dependent(sq);
+ set_processed(sq);
+ }
}
}
}
@@ -838,8 +869,7 @@ rel_named_table_function(sql_query *quer
append(tl, exp_subtype(e));
}
} else {
- for (node *en = exps->h; en; en = en->next)
- append(tl, exp_subtype(en->data));
+ tl = exp_types(sql->sa, exps);
}
}
@@ -855,6 +885,10 @@ rel_named_table_function(sql_query *quer
rel = rel_file_loader(sql, exps, tl, tname);
if (!rel)
return NULL;
+ } else if (!sname && strcmp(fname, "unnest") == 0) {
+ rel = rel_unnest_func(query, exps, tname);
+ if (!rel)
+ return NULL;
} else if (!(e = find_table_function(sql, sname, fname,
list_empty(exps) ? NULL : exps, tl, F_UNION)))
return NULL;
@@ -1221,8 +1255,17 @@ check_is_lateral(symbol *tableref)
{
if (tableref->token == SQL_NAME || tableref->token == SQL_TABLE ||
tableref->token == SQL_VALUES) {
- if (dlist_length(tableref->data.lval) == 3)
- return tableref->data.lval->h->next->data.i_val;
+ if (dlist_length(tableref->data.lval) == 3) {
+ if (tableref->data.lval->h->next->data.i_val)
+ return 1;
+ }
+ if (tableref->data.lval->h->type == type_symbol &&
tableref->data.lval->h->data.sym->token == SQL_NOP) {
+ symbol *sym = tableref->data.lval->h->data.sym;
+ dlist *qname = sym->data.lval->h->data.lval;
+ /* first is the qname */
+ if (dlist_length(qname) == 1 &&
strcmp(qname->h->data.sval, "unnest")==0)
+ return 1;
+ }
return 0;
} else if (tableref->token == SQL_WITH) {
if (dlist_length(tableref->data.lval) == 5)
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
@@ -18,6 +18,7 @@
#include "rel_exp.h"
#include "rel_select.h"
#include "rel_rewriter.h"
+#include "rel_multiset.h"
static void
exp_set_freevar(mvc *sql, sql_exp *e, sql_rel *r)
@@ -4594,6 +4595,7 @@ rel_unnest(mvc *sql, sql_rel *rel)
{
visitor v = { .sql = sql };
+ rel = rel_multiset(sql, rel);
rel = run_exp_rewriter(&v, rel, &rel_simplify_exp_and_rank, false,
"simplify_exp_and_rank");
rel = run_rel_rewriter(&v, rel, &rel_unnest_simplify,
"unnest_simplify");
rel = run_exp_rewriter(&v, rel, &rewrite_complex, true,
"rewrite_complex");
diff --git a/sql/server/rel_updates.c b/sql/server/rel_updates.c
--- a/sql/server/rel_updates.c
+++ b/sql/server/rel_updates.c
@@ -307,6 +307,8 @@ rel_insert_table(sql_query *query, sql_t
static node *
skip_nested_columns(mvc *sql, sql_column *ct, node *n)
{
+ if (ct->type.multiset)
+ return n;
if (ct->type.multiset) { /* skip id and optional number columns */
n = n->next;
if (ct->type.multiset == MS_ARRAY)
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -3952,13 +3952,6 @@ table_ref:
append_symbol($$->data.lval, $3);
}
}
-/*
- | select_with_parens
- { $$ = NULL;
- yyerror(m, "subquery table reference needs
alias, use AS xxx");
- YYABORT;
- }
-*/
| joined_table { $$ = $1;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]