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

Reply via email to