Changeset: ed8b1fabc2fb for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=ed8b1fabc2fb Modified Files: sql/server/rel_select.c Branch: Jun2020 Log Message:
also check types of tuple in (tuple returning query, ...) diffs (176 lines): 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 @@ -700,7 +700,8 @@ rel_op_(mvc *sql, sql_schema *s, char *f static sql_exp* exp_values_set_supertype(mvc *sql, sql_exp *values) { - list *vals = values->f, *nexps; + assert(is_values(values)); + list *vals = exp_get_values(values), *nexps; sql_subtype *tpe = exp_subtype(vals->h->data); if (tpe) @@ -753,6 +754,116 @@ exp_values_set_supertype(mvc *sql, sql_e return values; } +static sql_exp* +exp_tuples_set_supertype(mvc *sql, list *tuple_values, sql_exp *tuples) +{ + assert(is_values(tuples)); + list *vals = exp_get_values(tuples); + if (!vals || !vals->h) + return NULL; + + int tuple_width = list_length(tuple_values), i; + sql_subtype **types = SA_NEW_ARRAY(sql->sa, sql_subtype*, tuple_width); + node *n; + + for(n = tuple_values->h, i = 0; n; n = n->next, i++) { + sql_exp *e = n->data; + types[i] = exp_subtype(e); + } + + 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 the expression is a parameter set its type */ + /* check for param + if (types[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 (types[i] && tpe) { + supertype(types[i], types[i], tpe); + } else { + 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; + + /* if the expression is a parameter set its type + sql_exp *e = m->data; + if (e->type == e_atom && !e->l && !e->r && !e->f && !e->tpe.type) { + if (set_type_param(sql, tpe, e->flag) == 0) + e->tpe = *tpe; + else + return NULL; + } + * */ + e = rel_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; +} + +static int +rel_binop_check_types(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, int upcast) +{ + sql_subtype *t1 = exp_subtype(ls), *t2 = exp_subtype(rs); + + if (!t1 || !t2) { + if (t2 && !t1 && rel_set_type_param(sql, t2, rel, ls, upcast) < 0) + return -1; + if (t1 && !t2 && rel_set_type_param(sql, t1, rel, rs, upcast) < 0) + return -1; + } + if (!exp_subtype(ls) && !exp_subtype(rs)) { + (void) sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression"); + return -1; + } + return 0; +} + +static list * +tuples_check_types(mvc *sql, list *tuple_values, sql_exp *tuples) +{ + 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 = rel_check_type(sql, exp_subtype(re), NULL, le, type_cast)) == NULL) + return NULL; + append(nvalues, le); + } + return nvalues; +} + static sql_rel * rel_values(sql_query *query, symbol *tableref) { @@ -1264,24 +1375,6 @@ exp_fix_scale(mvc *sql, sql_subtype *ct, return e; } -static int -rel_binop_check_types(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, int upcast) -{ - sql_subtype *t1 = exp_subtype(ls), *t2 = exp_subtype(rs); - - if (!t1 || !t2) { - if (t2 && !t1 && rel_set_type_param(sql, t2, rel, ls, upcast) < 0) - return -1; - if (t1 && !t2 && rel_set_type_param(sql, t1, rel, rs, upcast) < 0) - return -1; - } - if (!exp_subtype(ls) && !exp_subtype(rs)) { - (void) sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression"); - return -1; - } - return 0; -} - /* try to do an in-place conversion * * in-place conversion is only possible if the exp is a variable. @@ -2035,15 +2128,11 @@ rel_in_value_exp(sql_query *query, sql_r values = exp_values(sql->sa, vals); exp_label(sql->sa, values, ++sql->label); if (is_tuple) { - sql_exp *e_rel = (sql_exp *) vals->h->data; - list *le_vals = le->f, *rel_vals = ((sql_rel*)e_rel->l)->exps; - - for (node *m = le_vals->h, *o = rel_vals->h ; m && o ; m = m->next, o = o->next) { - sql_exp *e = m->data, *f = o->data; - - if (rel_binop_check_types(sql, rel ? *rel : NULL, e, f, 0) < 0) - return NULL; - } + values = exp_tuples_set_supertype(sql, exp_get_values(le), values); + list *nvalues = tuples_check_types(sql, exp_get_values(le), values); + if (!nvalues) + return NULL; + le->f = nvalues; } else { /* if it's not a tuple, enforce coersion on the type for every element on the list */ values = exp_values_set_supertype(sql, values); if (rel_binop_check_types(sql, rel ? *rel : NULL, le, values, 0) < 0) _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list