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