Changeset: c6801db26687 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/c6801db26687
Branch: nested
Log Message:

Merges tvtree branch


diffs (truncated from 546 to 300 lines):

diff --git a/sql/backends/monet5/CMakeLists.txt 
b/sql/backends/monet5/CMakeLists.txt
--- a/sql/backends/monet5/CMakeLists.txt
+++ b/sql/backends/monet5/CMakeLists.txt
@@ -146,6 +146,7 @@ target_sources(sql
   rel_bin.c rel_bin.h
   rel_physical.c rel_physical.h
   rel_predicates.c rel_predicates.h
+  rel_tvtree.c rel_tvtree.h
   sql_cat.c sql_cat.h
   sql_transaction.c sql_transaction.h
   sql_statement.c
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
@@ -24,6 +24,7 @@
 #include "rel_predicates.h"
 #include "rel_file_loader.h"
 #include "rel_proto_loader.h"
+#include "rel_tvtree.h"
 #include "sql_env.h"
 #include "sql_optimizer.h"
 #include "sql_gencode.h"
@@ -836,6 +837,8 @@ tuple_result(backend *be, list *cols)
 static stmt *
 value_list(backend *be, sql_exp *vals_exp, stmt *left, stmt *sel)
 {
+       if (!be) return NULL;
+
        assert(is_values(vals_exp));
        list *vals = exp_get_values(vals_exp);
        sql_subtype *type = exp_subtype(vals_exp);
@@ -883,6 +886,24 @@ value_list(backend *be, sql_exp *vals_ex
 }
 
 static stmt *
+value_tvtree(backend *be, sql_exp *vals_exp, stmt *left, stmt *sel)
+{
+       if (!be) return NULL;
+
+       assert(is_values(vals_exp));
+
+       sql_subtype *st = exp_subtype(vals_exp);
+       tv_tree *t = tv_create(be, st);
+
+       if (false == tv_parse_values(be, t, vals_exp, left, sel))
+               return NULL;
+
+       stmt *ret = tv_generate_stmts(be, t);
+
+       return ret;
+}
+
+static stmt *
 exp_list(backend *be, list *exps, stmt *l, stmt *r, stmt *grp, stmt *ext, stmt 
*cnt, stmt *sel)
 {
        mvc *sql = be->mvc;
@@ -1897,7 +1918,9 @@ exp_bin(backend *be, sql_exp *e, stmt *l
                        assert(vname->name);
                        s = stmt_var(be, vname->sname ? a_create(sql->sa, 
sa_strdup(sql->sa, vname->sname)) : NULL, sa_strdup(sql->sa, vname->name), 
e->tpe.type?&e->tpe:NULL, 0, e->flag);
                } else if (e->f) {              /* values */
-                       s = value_list(be, e, left, sel);
+                       // TODO: >>>>>>>>>>>>>>>>>>>> remove value_list and 
friends
+                       value_list(NULL, e, left, sel);
+                       s = value_tvtree(be, e, left, sel);
                } else {                        /* arguments */
                        sql_subtype *t = e->tpe.type?&e->tpe:NULL;
                        if (!t && 0) {
diff --git a/sql/backends/monet5/rel_tvtree.c b/sql/backends/monet5/rel_tvtree.c
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/rel_tvtree.c
@@ -0,0 +1,323 @@
+/*
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.  If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2024 - 2025 MonetDB Foundation;
+ * Copyright August 2008 - 2023 MonetDB B.V.;
+ * Copyright 1997 - July 2008 CWI.
+ */
+
+#include "monetdb_config.h"
+
+#include "rel_tvtree.h"
+#include "rel_exp.h"
+#include "rel_bin.h"
+#include "sql_statement.h"
+
+static tv_type
+tv_get_type(sql_subtype *st)
+{
+       if (st->multiset) {
+               if (st->multiset == MS_ARRAY)
+                       return TV_MSET;
+               if (st->multiset == MS_SETOF)
+                       return TV_SETOF;
+       } else if (st->type->composite)
+               return TV_COMP;
+
+       return TV_BASIC;
+}
+
+static tv_tree*
+tv_node(allocator *sa, sql_subtype *st, tv_type tvt)
+{
+       tv_tree *n = (sa)?SA_NEW(sa, tv_tree):MNEW(tv_tree);
+       if (n == NULL)
+               return NULL;
+       n->st = st;
+       n->tvt = tvt;
+       n->rid_idx = 0;
+       n->ctl = n->rid = n->msid = n->msnr = n->vals = NULL;
+
+       /* allocate only the lists that we need based on the tv-tree type */
+       switch (n->tvt) {
+               case TV_BASIC:
+                       n->vals = sa_list(sa);
+                       return n;
+        case TV_COMP:
+                       n->ctl = sa_list(sa);
+                       for (node *sf = st->type->d.fields->h; sf; sf = 
sf->next) {
+                               sql_arg *sfa = sf->data;
+                               append(n->ctl, tv_node(sa, &sfa->type, 
tv_get_type(&sfa->type)));
+                       }
+               return n;
+        case TV_MSET:
+                       n->msnr = sa_list(sa);
+                       /* fall through */
+        case TV_SETOF:
+               n->rid = sa_list(sa);
+               n->msid = sa_list(sa);
+                       n->ctl = sa_list(sa);
+
+                       /* For MSET/SETOF we make a new child node for the 
values
+                        * NOTE: the ->st of the child is the same as this node 
so
+                        * we need to **EXPLICITLY** specify the tv_type */
+                       tv_tree *sn;
+                       if (st->type->composite)
+                               sn = tv_node(sa, st, TV_COMP);
+                       else
+                               sn = tv_node(sa, st, TV_BASIC);
+                       sn->st = st;
+
+                       append(n->ctl, sn);
+
+                       return n;
+               default:
+                       assert(0);
+                       break;
+       }
+
+       return NULL;
+}
+
+tv_tree *
+tv_create(backend *be, sql_subtype *st)
+{
+       /* there is some ambiguity with the types-value tree construction:
+        * nodes which are mset/setof have their underlying type 
(composite/basic)
+        * in the same subtype->type struct. That's why we have to be careful
+        * with how we generate the nodes. Read carefully tv_node */
+       return tv_node(be->mvc->sa, st, tv_get_type(st));
+}
+
+static bool
+tv_parse_values_(backend *be, tv_tree *t, sql_exp *value, stmt *left, stmt 
*sel);
+
+static bool
+mset_value_from_array_constructor(backend *be, tv_tree *t, sql_exp *values, 
stmt *left, stmt *sel)
+{
+    /* rowid */
+    stmt *rid = stmt_atom_int(be, t->rid_idx);
+    if (!rid)
+        return false;
+    assert(t->rid);
+    list_append(t->rid, rid);
+
+    /* per value insert actual data, msid(=rowid), msnr(for MSET only) */
+    int msnr_idx = 1;  /* NOTE: in mset-value values are 1-offset indexed */
+    list *ms_vals = values->f;
+    for (node *n = ms_vals->h; n; n = n->next, msnr_idx++) {
+
+               /* vals (in the child tree) */
+               assert(list_length(t->ctl) == 1);
+               tv_tree *ct = t->ctl->h->data;
+               tv_parse_values_(be, ct, n->data, left, sel);
+
+               /* msid */
+        stmt *msid = stmt_atom_int(be, t->rid_idx);
+        if (!msid)
+            return false;
+        list_append(t->msid, msid);
+
+               /* msnr */
+        if (t->tvt == TV_MSET) {
+            stmt *msnr = stmt_atom_int(be, msnr_idx);
+            if (!msnr)
+                return false;
+            list_append(t->msnr, msnr);
+        }
+    }
+
+    /* we inserted all the mset-value's subvalues so now
+     * increment this tv_tree node's (mset) rowid index */
+    t->rid_idx++;
+
+    return true;
+}
+
+static bool
+mset_value_from_literal(backend *be, tv_tree *t, sql_exp *values, stmt *left, 
stmt *sel)
+{
+    /* per entry-value in the literal the call to exp_bin() will generate an
+     * `sql.from_varchar()` instruction. This instructions for a given returns
+     * either 3 or 4 bat results corresponding to rowid, value, msid and 
optionally
+     * msnr (multiset vs setof). Those return values will be in an st_list stmt
+     * so we have to retrieve them (from stmt_list's op4) and append them to 
the
+     * tv_tree list of stmts */
+    assert(t->tvt == TV_SETOF || t->tvt == TV_MSET);
+       assert(!t->vals && t->ctl);
+
+       stmt *i = exp_bin(be, values, left, NULL, NULL, NULL, NULL, sel, 0, 0, 
0);
+       if (!i)
+               return false;
+
+       assert(i->type == st_list);
+       assert(list_length(i->op4.lval) == 3 || list_length(i->op4.lval) == 4);
+
+       /* vals (in the child tree) */
+       assert(list_length(t->ctl) == 1);
+       tv_tree *ct = t->ctl->h->data;
+       list_append(ct->vals, list_fetch(i->op4.lval, 0));
+
+       /* msid */
+       list_append(t->msid, list_fetch(i->op4.lval, 1));
+
+       if (t->tvt == TV_MSET) {
+               /* msnr */
+               list_append(t->msnr, list_fetch(i->op4.lval, 2));
+               /* rowid */
+               list_append(t->rid, list_fetch(i->op4.lval, 3));
+       } else {
+               /* rowid */
+               list_append(t->rid, list_fetch(i->op4.lval, 2));
+       }
+
+    return true;
+}
+
+static bool
+tv_parse_values_(backend *be, tv_tree *t, sql_exp *value, stmt *left, stmt 
*sel)
+{
+       int cnt = 0;
+       stmt *i;
+       list *ct_vals;
+
+       switch (t->tvt) {
+               case TV_BASIC:
+                       assert(!value->f);
+                       i = exp_bin(be, value, left, NULL, NULL, NULL, NULL, 
sel, 0, 0, 0);
+                       if (!i)
+                               return false;
+                       assert(t->vals);
+                       list_append(t->vals, i);
+                       break;
+               case TV_MSET:
+               case TV_SETOF:
+            if (is_convert(value->type))
+                       /* VALUES ('{1, 2, 3}') */
+                return mset_value_from_literal(be, t, value, left, sel);
+            else
+                       /* VALUES (array[1, 2, 3]) */
+                return mset_value_from_array_constructor(be, t, value, left, 
sel);
+            break;
+               case TV_COMP:
+                       assert(value->f);
+                       ct_vals = value->f;
+                       for (node *n = ct_vals->h; n; cnt++, n = n->next)
+                               if (false == tv_parse_values_(be, 
list_fetch(t->ctl, cnt), n->data, left, sel))
+                                       return false;
+                       break;
+               default:
+                       assert(0);
+                       break;
+       }
+
+       return true;
+}
+
+static inline sql_exp *
+tv_exp_wrap_list(backend *be, tv_tree *t, list *l)
+{
+       sql_exp *e = exp_null(be->mvc->sa, t->st);
+       e->l = e->f = 0;
+       e->f = l;
+       return e;
+}
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to