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 -- [email protected]
To unsubscribe send an email to [email protected]