Changeset: d7fec2bf7345 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d7fec2bf7345
Modified Files:
sql/backends/monet5/rel_bin.c
sql/server/rel_exp.c
sql/server/rel_select.c
sql/server/rel_unnest.c
sql/server/sql_parser.y
sql/test/SQLancer/Tests/sqlancer22.test
sql/test/subquery/Tests/subquery3.test
sql/test/subquery/Tests/subquery4.test
Branch: default
Log Message:
add support for multi col in statements, fixes #7497
diffs (truncated from 513 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
@@ -446,8 +446,65 @@ subrel_project(backend *be, stmt *s, lis
}
static stmt *
+handle_in_tuple_exps(backend *be, sql_exp *ce, list *nl, stmt *left, stmt
*right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, bool in, int depth, int
reduce, int push)
+{
+ mvc *sql = be->mvc;
+ stmt *s = NULL;
+
+ list *lvals = ce->f, *lstmts = sa_list(sql->sa);
+ for(node *n = lvals->h; n; n = n->next) {
+ sql_exp *ce = n->data;
+ stmt *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL,
depth+1, 0, push);
+
+ if (c && reduce && c->nrcols == 0)
+ c = stmt_const(be, bin_find_smallest_column(be, left),
c);
+ if(!c)
+ return NULL;
+ lstmts = append(lstmts, c);
+ }
+
+ sql_subtype *bt = sql_bind_localtype("bit");
+ sql_subfunc *and = sql_bind_func(sql, "sys", "and", bt, bt, F_FUNC,
true, true);
+ sql_subfunc *or = sql_bind_func(sql, "sys", "or", bt, bt, F_FUNC, true,
true);
+ for (node *n = nl->h; n; n = n->next) {
+ sql_exp *e = n->data;
+ list *vals = e->f;
+ stmt *cursel = NULL;
+
+ for (node *m = vals->h, *o = lstmts->h; m && o; m = m->next, o
= o->next) {
+ stmt *c = o->data;
+ sql_subfunc *cmp = (in)
+ ?sql_bind_func(sql, "sys", "=", tail_type(c),
tail_type(c), F_FUNC, true, true)
+ :sql_bind_func(sql, "sys", "<>", tail_type(c),
tail_type(c), F_FUNC, true, true);
+ sql_exp *e = m->data;
+
+ stmt *i = exp_bin(be, e, left, right, grp, ext, cnt,
NULL, depth+1, 0, push);
+ if(!i)
+ return NULL;
+
+ i = stmt_binop(be, c, i, NULL, cmp);
+ if (cursel)
+ cursel = stmt_binop(be, cursel, i, NULL,
in?and:or);
+ else
+ cursel = i;
+ }
+ if (s)
+ s = stmt_binop(be, s, cursel, NULL, in?or:and);
+ else
+ s = cursel;
+ }
+ if (sel && !(depth || !reduce))
+ s = stmt_uselect(be,
+ s->nrcols == 0?stmt_const(be,
bin_find_smallest_column(be, left), s): s,
+ stmt_bool(be, 1), cmp_equal, sel, 0, 0);
+ return s;
+}
+
+static stmt *
handle_in_exps(backend *be, sql_exp *ce, list *nl, stmt *left, stmt *right,
stmt *grp, stmt *ext, stmt *cnt, stmt *sel, bool in, int depth, int reduce, int
push)
{
+ if (ce && is_values(ce))
+ return handle_in_tuple_exps(be, ce, nl, left, right, grp, ext,
cnt, sel, in, depth, reduce, push);
mvc *sql = be->mvc;
node *n;
stmt *s = NULL, *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL,
depth+1, 0, push);
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -2036,7 +2036,7 @@ exp_is_atom( sql_exp *e )
switch (e->type) {
case e_atom:
if (e->f) /* values list */
- return 0;
+ return exps_are_atoms(e->f);
return 1;
case e_convert:
return exp_is_atom(e->l);
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
@@ -823,45 +823,84 @@ exp_tuples_set_supertype(mvc *sql, list
for (node *m = vals->h; m; m = m->next) {
sql_exp *tuple = m->data;
- sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, tuple);
-
- for(n = tuple_relation->exps->h, i = 0; n; n = n->next, i++) {
- sql_subtype *tpe;
- sql_exp *e = n->data;
-
- if (has_type[i] && e->type == e_atom && !e->l && !e->r
&& !e->f && !e->tpe.type) {
- if (set_type_param(sql, types+i, e->flag) == 0)
- e->tpe = types[i];
- else
+ if (is_values(tuple)) {
+ list *exps = tuple->f;
+ for(n = exps->h, i = 0; n; n = n->next, i++) {
+ sql_subtype *tpe;
+ sql_exp *e = n->data;
+
+ if (has_type[i] && e->type == e_atom && !e->l
&& !e->r && !e->f && !e->tpe.type) {
+ if (set_type_param(sql, types+i,
e->flag) == 0)
+ e->tpe = types[i];
+ else
+ return NULL;
+ }
+ tpe = exp_subtype(e);
+ if (!tpe)
return NULL;
+ if (has_type[i] && tpe) {
+ supertype(types+i, types+i, tpe);
+ } else {
+ has_type[i] = 1;
+ types[i] = *tpe;
+ }
}
- tpe = exp_subtype(e);
- if (!tpe)
- return NULL;
- if (has_type[i] && tpe) {
- cmp_supertype(types+i, types+i, tpe);
- } else {
- has_type[i] = 1;
- types[i] = *tpe;
+ } else {
+ sql_rel *tuple_relation = exp_rel_get_rel(sql->sa,
tuple);
+
+ for(n = tuple_relation->exps->h, i = 0; n; n = n->next,
i++) {
+ sql_subtype *tpe;
+ sql_exp *e = n->data;
+
+ if (has_type[i] && e->type == e_atom && !e->l
&& !e->r && !e->f && !e->tpe.type) {
+ if (set_type_param(sql, types+i,
e->flag) == 0)
+ e->tpe = types[i];
+ else
+ return NULL;
+ }
+ tpe = exp_subtype(e);
+ if (!tpe)
+ return NULL;
+ if (has_type[i] && tpe) {
+ cmp_supertype(types+i, types+i, tpe);
+ } else {
+ has_type[i] = 1;
+ types[i] = *tpe;
+ }
}
}
}
for (node *m = vals->h; m; m = m->next) {
sql_exp *tuple = m->data;
- sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, tuple);
-
- list *nexps = sa_list(sql->sa);
- for(n = tuple_relation->exps->h, i = 0; n; n = n->next, i++) {
- sql_exp *e = n->data;
-
- e = exp_check_type(sql, types+i, NULL, e, type_equal);
- if (!e)
- return NULL;
- exp_label(sql->sa, e, ++sql->label);
- append(nexps, e);
- }
- tuple_relation->exps = nexps;
+ if (is_values(tuple)) {
+ list *exps = tuple->f;
+ list *nexps = sa_list(sql->sa);
+ for(n = exps->h, i = 0; n; n = n->next, i++) {
+ sql_exp *e = n->data;
+
+ e = exp_check_type(sql, types+i, NULL, e,
type_equal);
+ if (!e)
+ return NULL;
+ exp_label(sql->sa, e, ++sql->label);
+ append(nexps, e);
+ }
+ tuple->f = nexps;
+ } else {
+ sql_rel *tuple_relation = exp_rel_get_rel(sql->sa,
tuple);
+
+ list *nexps = sa_list(sql->sa);
+ for(n = tuple_relation->exps->h, i = 0; n; n = n->next,
i++) {
+ sql_exp *e = n->data;
+
+ e = exp_check_type(sql, types+i, NULL, e,
type_equal);
+ if (!e)
+ return NULL;
+ exp_label(sql->sa, e, ++sql->label);
+ append(nexps, e);
+ }
+ tuple_relation->exps = nexps;
+ }
}
return tuples;
}
@@ -889,20 +928,36 @@ tuples_check_types(mvc *sql, list *tuple
{
list *tuples_list = exp_get_values(tuples);
sql_exp *first_tuple = tuples_list->h->data;
- sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, first_tuple);
-
- assert(list_length(tuple_values) == list_length(tuple_relation->exps));
list *nvalues = sa_list(sql->sa);
- for (node *n = tuple_values->h, *m = tuple_relation->exps->h; n && m; n
= n->next, m = m->next) {
- sql_exp *le = n->data, *re = m->data;
-
- if (rel_binop_check_types(sql, NULL, le, re, 0) < 0)
- return NULL;
- if ((le = exp_check_type(sql, exp_subtype(re), NULL, le,
type_equal)) == NULL)
- return NULL;
- append(nvalues, le);
- }
- return nvalues;
+ if (is_values(first_tuple)) {
+ list *vals = first_tuple->f;
+
+ for (node *n = tuple_values->h, *m = vals->h; n && m; n =
n->next, m = m->next) {
+ sql_exp *le = n->data, *re = m->data;
+
+ if (rel_binop_check_types(sql, NULL, le, re, 0) < 0)
+ return NULL;
+ if ((le = exp_check_type(sql, exp_subtype(re), NULL,
le, type_equal)) == NULL)
+ return NULL;
+ append(nvalues, le);
+ }
+ return nvalues;
+ } else {
+ sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, first_tuple);
+
+ assert(list_length(tuple_values) ==
list_length(tuple_relation->exps));
+ for (node *n = tuple_values->h, *m = tuple_relation->exps->h; n
&& m; n = n->next, m = m->next) {
+ sql_exp *le = n->data, *re = m->data;
+
+ if (rel_binop_check_types(sql, NULL, le, re, 0) < 0)
+ return NULL;
+ if ((le = exp_check_type(sql, exp_subtype(re), NULL,
le, type_equal)) == NULL)
+ return NULL;
+ append(nvalues, le);
+ }
+ return nvalues;
+ }
+ return tuple_values;
}
static sql_rel *
@@ -2025,9 +2080,14 @@ rel_in_value_exp(sql_query *query, sql_r
le = exp_values(sql->sa, ll);
exp_label(sql->sa, le, ++sql->label);
ek.type = list_length(ll);
- is_tuple = 1;
+ is_tuple = list_length(ll);
}
/* list of values or subqueries */
+ /* 3 right hand side cases,
+ * 1 - value/tuple list of atoms
+ * 2 - list of scalar sub queries (needs check on 1 row/column per
query)
+ * 3 - single tabular ie. multi column, multi row query
+ */
if (n->type == type_list) {
sql_exp *values;
list *vals = sa_list(sql->sa);
@@ -2036,12 +2096,26 @@ rel_in_value_exp(sql_query *query, sql_r
n = n->data.lval->h;
for (; n; n = n->next) {
- re = rel_value_exp(query, rel, n->data.sym, f|sql_farg,
ek);
+ if (n->type == type_list) {
+ dnode *m = n->data.lval->h;
+ list *rl = sa_list(sql->sa);
+ for (; m; m = m->next) {
+ assert(m->type == type_symbol);
+ sql_exp *re = rel_value_exp(query, rel,
m->data.sym, f|sql_farg, ek);
+ if (!re)
+ return NULL;
+ append(rl, re);
+ }
+ re = exp_values(sql->sa, rl);
+ } else {
+ assert(n->type == type_symbol);
+ re = rel_value_exp(query, rel, n->data.sym,
f|sql_farg, ek);
+ }
if (!re)
return NULL;
- if (is_tuple && !exp_is_rel(re))
+ if (is_tuple && (!exp_is_rel(re) && !is_values(re)))
return sql_error(sql, 02, SQLSTATE(42000)
"Cannot match a tuple to a single value");
- if (is_tuple) {
+ if (is_tuple && exp_is_rel(re)) {
sql_rel *r = exp_rel_get_rel(sql->sa, re);
if (!r)
@@ -2056,6 +2130,8 @@ rel_in_value_exp(sql_query *query, sql_r
set_dependent((*rel));
if (is_project(r->op) && is_project_true(r->l)
&& list_length(r->exps) == 1)
re = r->exps->h->data;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]