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 -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to