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