Changeset: 9854f9997858 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/9854f9997858
Modified Files:
sql/backends/monet5/rel_bin.c
sql/backends/monet5/rel_tvtree.c
sql/backends/monet5/rel_tvtree.h
Branch: tvtree
Log Message:
Fixes support for mset/setof literal syntax
diffs (237 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
@@ -886,8 +886,7 @@ value_tvtree(backend *be, sql_exp *vals_
sql_subtype *st = exp_subtype(vals_exp);
tv_tree *t = tv_create(be, st);
- list *vals = exp_get_values(vals_exp);
- if (false == tv_parse_values(be, t, vals, left, sel))
+ if (false == tv_parse_values(be, t, vals_exp, left, sel))
return NULL;
stmt *ret = tv_generate_stmts(be, t);
diff --git a/sql/backends/monet5/rel_tvtree.c b/sql/backends/monet5/rel_tvtree.c
--- a/sql/backends/monet5/rel_tvtree.c
+++ b/sql/backends/monet5/rel_tvtree.c
@@ -103,6 +103,87 @@ tv_create(backend *be, sql_subtype *st)
}
static bool
+tv_parse_values_(backend *be, tv_tree *t, sql_exp *value, stmt *left, stmt
*sel);
+
+static bool
+mset_values_from_array_constructor(backend *be, tv_tree *t, sql_exp *values,
stmt *left, stmt *sel)
+{
+ /* add the rowid to the mset "origin" table */
+ 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 MS 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++) {
+
+ if (t->tvt == TV_MS_COMP) {
+ assert(t->cf);
+ int cfi = 0;
+ list *cf_vals = ((sql_exp*)n->data)->f;
+ for (node *m = cf_vals->h; m; m = m->next, cfi++)
+ if (false == tv_parse_values_(be, list_fetch(t->cf, cfi),
m->data, left, sel))
+ return false;
+ } else {
+ assert(t->vals && !t->cf);
+ stmt *i = exp_bin(be, n->data, left, NULL, NULL, NULL, NULL, sel,
0, 0, 0);
+ if (!i)
+ return false;
+ list_append(t->vals, i);
+ }
+
+ stmt *msid = stmt_atom_int(be, t->rid_idx);
+ if (!msid)
+ return false;
+ list_append(t->msid, msid);
+
+ if (t->tvt == TV_MS_COMP || t->tvt == TV_MS_BSC) {
+ stmt *msnr = stmt_atom_int(be, msnr_idx);
+ if (!msnr)
+ return false;
+ list_append(t->msnr, msnr);
+ }
+ }
+
+ /* we inserted all the mset-value subvalues so now
+ * increment this tv_tree node's (mset) rowid index */
+ t->rid_idx++;
+
+ return true;
+}
+
+static bool
+mset_values_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_SO_BSC || t->tvt == TV_MS_BSC);
+ assert(t->vals && !t->cf);
+
+ stmt *i = exp_bin(be, values, left, NULL, NULL, NULL, NULL, sel, 0, 0,
0);
+ if (!i)
+ return NULL;
+
+ assert(i->type == st_list);
+ assert(list_length(i->op4.lval) == 3 || list_length(i->op4.lval) == 4);
+
+ list_append(t->rid, list_fetch(i->op4.lval, 0));
+ list_append(t->vals, list_fetch(i->op4.lval, 1));
+ list_append(t->msid, list_fetch(i->op4.lval, 2));
+ if (t->tvt == TV_MS_BSC)
+ list_append(t->msnr, list_fetch(i->op4.lval, 3));
+
+ return true;
+}
+
+static bool
tv_parse_values_(backend *be, tv_tree *t, sql_exp *value, stmt *left, stmt
*sel)
{
switch (t->tvt) {
@@ -118,53 +199,13 @@ tv_parse_values_(backend *be, tv_tree *t
case TV_SO_COMP:
case TV_MS_BSC:
case TV_SO_BSC:
- assert(value->f);
-
- /* add the rowid to the mset "origin" table */
- 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
MS only) */
- int msnr_idx = 1; /* NOTE: in mset-value values are
1-offset indexed */
- list *ms_vals = value->f;
- for (node *n = ms_vals->h; n; n = n->next, msnr_idx++) {
-
- if (t->tvt == TV_MS_COMP) {
- assert(t->cf);
- int cfi = 0;
- list *cf_vals = ((sql_exp*)n->data)->f;
- for (node *m = cf_vals->h; m; m =
m->next, cfi++)
- if (false ==
tv_parse_values_(be, list_fetch(t->cf, cfi), m->data, left, sel))
- return false;
- } else {
- assert(t->vals && !t->cf);
- stmt *i = exp_bin(be, n->data, left,
NULL, NULL, NULL, NULL, sel, 0, 0, 0);
- if (!i)
- return false;
- list_append(t->vals, i);
- }
-
- stmt *msid = stmt_atom_int(be, t->rid_idx);
- if (!msid)
- return false;
- list_append(t->msid, msid);
-
- if (t->tvt == TV_MS_COMP || t->tvt ==
TV_MS_BSC) {
- stmt *msnr = stmt_atom_int(be,
msnr_idx);
- if (!msnr)
- return false;
- list_append(t->msnr, msnr);
- }
- }
-
- /* we inserted all the mset-value subvalues so now
- * increment this tv_tree node's (mset) rowid index */
- t->rid_idx++;
-
- break;
+ if (is_convert(value->type))
+ /* VALUES ('{1, 2, 3}') */
+ return mset_values_from_literal(be, t, value, left, sel);
+ else
+ /* VALUES (array[1, 2, 3]) */
+ return mset_values_from_array_constructor(be, t, value, left,
sel);
+ break;
case TV_COMP:
assert(value->f);
int cnt = 0;
@@ -181,7 +222,7 @@ tv_parse_values_(backend *be, tv_tree *t
return true;
}
-static sql_exp *
+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);
@@ -191,29 +232,36 @@ tv_exp_wrap_list(backend *be, tv_tree *t
}
bool
-tv_parse_values(backend *be, tv_tree *t, list *col_vals, stmt *left, stmt *sel)
+tv_parse_values(backend *be, tv_tree *t, sql_exp *col_vals, stmt *left, stmt
*sel)
{
- /* col_vals is a list with values that correspond to a column whose
+ list *vals = exp_get_values(col_vals);
+ /* vals is a list with values that correspond to a column whose
* (possibly "complex") type is represented by the tv_tree. NOTE:
- * in this case col_vals might be either
+ * in this case vals might be either
* 1. a list of many values or
- * 2. a single value of composite or mset/setof with composite type.
- * TODO: mset/setof with basic type?
- * that's why we need to check the _row_ flag in the first entry of
- * the col_vals list. If it is set it means we are dealing with a
- * single row insert and we need a dummy expression de (to put
- * col_vals at its e->f) so the handling it's similar to those two cases
+ * 2. a single value of composite or mset/setof with composite/basic
type.
+ * that's why we need to check for
+ * a. ->row in the first entry of col_vals exp
+ * b. for mset/setof the first ->row in the first entry of vals
+ * If it is set it means we are dealing with a single row insert and we
need
+ * a dummy expression de (to put vals at its e->f) so parsing the
values stays
+ * similar with the general case
*/
- bool single_row_val =((sql_exp*)col_vals->h->data)->row;
+ bool single_row_val = false;
+ single_row_val |= col_vals->row;
+ if ((t->tvt == TV_MS_BSC) || (t->tvt == TV_MS_COMP) ||
+ (t->tvt == TV_SO_BSC) || (t->tvt == TV_SO_COMP))
+ single_row_val |= ((sql_exp*)vals->h->data)->row;
- if (single_row_val) {
- /* we need to create a dummy expression to single row col_vals
+
+ if (single_row_val) {
+ /* we need to create a dummy expression to single row vals
* to adhere to the rest of the api */
- sql_exp *de = tv_exp_wrap_list(be, t, col_vals);
+ sql_exp *de = tv_exp_wrap_list(be, t, vals);
if (false == tv_parse_values_(be, t, de, left, sel))
return false;
} else {
- for (node *n = col_vals->h; n; n = n->next) {
+ for (node *n = vals->h; n; n = n->next) {
sql_exp *e = n->data;
if (false == tv_parse_values_(be, t, e, left, sel))
return false;
diff --git a/sql/backends/monet5/rel_tvtree.h b/sql/backends/monet5/rel_tvtree.h
--- a/sql/backends/monet5/rel_tvtree.h
+++ b/sql/backends/monet5/rel_tvtree.h
@@ -54,7 +54,7 @@ typedef struct type_values_tree {
} tv_tree;
tv_tree * tv_create(backend *be, sql_subtype *st);
-bool tv_parse_values(backend *be, tv_tree *t, list *cvals, stmt *left, stmt
*sel);
+bool tv_parse_values(backend *be, tv_tree *t, sql_exp *col_vals, stmt *left,
stmt *sel);
stmt * tv_generate_stmts(backend *be, tv_tree *t);
#endif /*_REL_TVTREE_H_*/
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]