Changeset: 6a7174945181 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=6a7174945181 Modified Files: sql/server/rel_exp.c sql/server/rel_select.c sql/test/miscellaneous/Tests/simple_selects.sql Branch: Oct2020 Log Message:
For every comparison the inputs must be from the same type. When determining the cardinality of a comparison with a quantifier, ignore conversions above it. This fixes one of the bugs I found today diffs (152 lines): 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 @@ -228,6 +228,26 @@ exp_or(sql_allocator *sa, list *l, list return e; } +static int /* if the quantifier has to be upcasted, ignore the upper conversion for the cardinalilty */ +quantifier_has_rel(sql_exp *e) +{ + if (!e) + return 0; + switch(e->type){ + case e_convert: + return quantifier_has_rel(e->l); + case e_psm: + return exp_is_rel(e); + case e_atom: + case e_column: + case e_func: + case e_aggr: + case e_cmp: + return 0; + } + return 0; +} + sql_exp * exp_in(sql_allocator *sa, sql_exp *l, list *r, int cmptype) { @@ -241,7 +261,7 @@ exp_in(sql_allocator *sa, sql_exp *l, li for (node *n = r->h; n ; n = n->next) { sql_exp *next = n->data; - if (!exp_is_rel(next) && exps_card < next->card) + if (!quantifier_has_rel(next) && exps_card < next->card) exps_card = next->card; } e->card = MAX(l->card, exps_card); @@ -276,10 +296,10 @@ exp_in_func(mvc *sql, sql_exp *le, sql_e for (node *n = ((list*)vals->f)->h ; n ; n = n->next) { sql_exp *next = n->data; - if (!exp_is_rel(next) && exps_card < next->card) + if (!quantifier_has_rel(next) && exps_card < next->card) exps_card = next->card; } - } else if (!exp_is_rel(vals)) + } else if (!quantifier_has_rel(vals)) exps_card = vals->card; e->card = MAX(le->card, exps_card); @@ -300,7 +320,7 @@ exp_compare_func(mvc *sql, sql_exp *le, if (e) { e->flag = quantifier; /* At ANY and ALL operators, the cardinality on the right side is ignored if it is a sub-relation */ - e->card = quantifier && exp_is_rel(re) ? le->card : MAX(le->card, re->card); + e->card = quantifier && quantifier_has_rel(re) ? le->card : MAX(le->card, re->card); if (!has_nil(le) && !has_nil(re)) set_has_no_nil(e); } 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 @@ -1550,7 +1550,7 @@ static sql_rel * rel_compare_exp_(sql_query *query, sql_rel *rel, sql_exp *ls, sql_exp *rs, sql_exp *rs2, int type, int anti, int quantifier, int f) { mvc *sql = query->sql; - sql_exp *L = ls, *R = rs, *e = NULL; + sql_exp *e = NULL; if (quantifier || exp_is_rel(ls) || exp_is_rel(rs)) { if (rs2) { @@ -1558,7 +1558,7 @@ rel_compare_exp_(sql_query *query, sql_r if (anti) set_anti(e); } else { - if (rel_binop_check_types(sql, rel, ls, rs, 0) < 0) + if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0) return NULL; e = exp_compare_func(sql, ls, rs, compare_func((comp_type)type, quantifier?0:anti), quantifier); if (anti && quantifier) @@ -1569,22 +1569,18 @@ rel_compare_exp_(sql_query *query, sql_r } else if (!rs2) { if (ls->card < rs->card) { sql_exp *swap = ls; - ls = rs; rs = swap; - - swap = L; - L = R; - R = swap; - type = (int)swap_compare((comp_type)type); } if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0) return NULL; e = exp_compare(sql->sa, ls, rs, type); } else { - if ((rs = exp_check_type(sql, exp_subtype(ls), rel, rs, type_equal)) == NULL || - (rs2 && (rs2 = exp_check_type(sql, exp_subtype(ls), rel, rs2, type_equal)) == NULL)) + assert(rs2); + if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0) + return NULL; + if (!(rs2 = exp_check_type(sql, exp_subtype(ls), rel, rs2, type_equal))) return NULL; e = exp_compare2(sql->sa, ls, rs, rs2, type); } @@ -1607,7 +1603,7 @@ rel_compare_exp_(sql_query *query, sql_r else return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function"); } - return rel_select_push_exp_down(sql, rel, e, ls, L, rs, R, rs2, f); + return rel_select_push_exp_down(sql, rel, e, ls, ls, rs, rs, rs2, f); } static sql_rel * @@ -1624,7 +1620,7 @@ rel_compare_exp(sql_query *query, sql_re /* TODO to handle filters here */ sql_exp *e; - if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal) < 0) + if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0) return NULL; e = rel_binop_(sql, rel, ls, rs, NULL, compare_op, card_value); @@ -2219,7 +2215,7 @@ rel_logical_value_exp(sql_query *query, cmp_type = swap_compare(cmp_type); } - if (rel_binop_check_types(sql, rel ? *rel : NULL, ls, rs, 0) < 0) + if (rel_convert_types(sql, rel ? *rel : NULL, rel ? *rel : NULL, &ls, &rs, 1, type_equal_no_any) < 0) return NULL; if (exp_is_null(ls) && exp_is_null(rs)) return exp_atom(sql->sa, atom_general(sql->sa, sql_bind_localtype("bit"), NULL)); diff --git a/sql/test/miscellaneous/Tests/simple_selects.sql b/sql/test/miscellaneous/Tests/simple_selects.sql --- a/sql/test/miscellaneous/Tests/simple_selects.sql +++ b/sql/test/miscellaneous/Tests/simple_selects.sql @@ -229,6 +229,12 @@ select 1, null intersect select 1, null; -- 1 NULL start transaction; +create or replace function ups() returns int begin if null > 1 then return 1; else return 2; end if; end; +select ups(); +create or replace function ups() returns int begin if 1 > 1 then return 1; end if; end; --error, return missing +rollback; + +start transaction; create function "😀"() returns int return 1; select "😀"(); -- 1 _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list