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 -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to