Changeset: 5ea5bee7dcd2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/5ea5bee7dcd2
Added Files:
        sql/test/BugTracker-2024/Tests/7554-incorrect-result-between.test
        sql/test/BugTracker-2024/Tests/7555-incorrect-semijoin-rewrite.test
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimize_exps.c
        sql/server/rel_rewriter.c
        sql/server/rel_statistics.c
        sql/test/BugTracker-2024/Tests/All
Branch: Aug2024
Log Message:

added tests for bugs #7554 and #7555
fixed #7554, properly handle exp_is_null vs exp_is_not_null
fixed #7555, exp_has_func should return true on exp_convert (on down casting)


diffs (168 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
@@ -1956,7 +1956,8 @@ exp_is_cmp_exp_is_false(sql_exp* e)
 }
 
 static inline bool
-exp_single_bound_cmp_exp_is_false(sql_exp* e) {
+exp_single_bound_cmp_exp_is_false(sql_exp* e)
+{
     assert(e->type == e_cmp);
     sql_exp* l = e->l;
     sql_exp* r = e->r;
@@ -1990,7 +1991,8 @@ exp_regular_cmp_exp_is_false(sql_exp* e)
 }
 
 static inline bool
-exp_or_exp_is_false(sql_exp* e) {
+exp_or_exp_is_false(sql_exp* e)
+{
     assert(e->type == e_cmp && e->flag == cmp_or);
 
        list* left = e->l;
@@ -2018,7 +2020,8 @@ exp_or_exp_is_false(sql_exp* e) {
 }
 
 static inline bool
-exp_cmp_exp_is_false(sql_exp* e) {
+exp_cmp_exp_is_false(sql_exp* e)
+{
     assert(e->type == e_cmp);
 
     switch (e->flag) {
@@ -2137,7 +2140,7 @@ exp_is_null(sql_exp *e )
                                return ((e->flag == cmp_in && 
exp_is_null(e->l)) ||
                                                (e->flag == cmp_notin && 
(exp_is_null(e->l) || exps_have_null(e->r))));
                        } else if (e->f) {
-                               return exp_is_null(e->l) || (!is_anti(e) && 
(exp_is_null(e->r) || exp_is_null(e->f)));
+                               return exp_is_null(e->l) && exp_is_null(e->r) 
&& exp_is_null(e->f);
                        } else {
                                return exp_is_null(e->l) || exp_is_null(e->r);
                        }
@@ -2666,6 +2669,14 @@ exp_has_func_or_cmp(sql_exp *e, bool cmp
                        return exps_have_func_or_cmp(e->f, true);
                return 0;
        case e_convert:
+               {
+                       sql_subtype *t = exp_totype(e);
+                       sql_subtype *f = exp_fromtype(e);
+                       if (t->type->eclass == EC_FLT && (f->type->eclass == 
EC_DEC || f->type->eclass == EC_NUM))
+                               return exp_has_func_or_cmp(e->l, cmp);
+                       if (f->type->localtype > t->type->localtype)
+                               return true;
+               }
                return exp_has_func_or_cmp(e->l, cmp);
        case e_func:
                return 1;
diff --git a/sql/server/rel_exp.h b/sql/server/rel_exp.h
--- a/sql/server/rel_exp.h
+++ b/sql/server/rel_exp.h
@@ -160,6 +160,7 @@ extern int exp_is_join(sql_exp *e, list 
 extern int exp_is_eqjoin(sql_exp *e);
 extern int exp_is_join_exp(sql_exp *e);
 extern int exp_is_atom(sql_exp *e);
+/* exp_is_true/false etc return true if the expression is true, on unknown etc 
false is returned */
 extern int exp_is_true(sql_exp *e);
 extern int exp_is_false(sql_exp *e);
 extern int exp_is_zero(sql_exp *e);
diff --git a/sql/server/rel_optimize_exps.c b/sql/server/rel_optimize_exps.c
--- a/sql/server/rel_optimize_exps.c
+++ b/sql/server/rel_optimize_exps.c
@@ -456,7 +456,7 @@ rel_simplify_predicates(visitor *v, sql_
                sql_exp *le = n->data;
                sql_exp *re = n->next->data;
 
-               if (exp_is_atom(le) && !exp_is_null(le) && exp_is_atom(re) && 
le->type == e_atom && le->l && re->type == e_atom && re->l) {
+               if (exp_is_atom(le) && exp_is_not_null(le) && exp_is_atom(re) 
&& le->type == e_atom && le->l && re->type == e_atom && re->l) {
                        n = n->next->next;
                        if (exp_match_exp(le, re)) { /* x==y -> a */
                                sql_exp *res = n->data;
diff --git a/sql/server/rel_rewriter.c b/sql/server/rel_rewriter.c
--- a/sql/server/rel_rewriter.c
+++ b/sql/server/rel_rewriter.c
@@ -187,7 +187,7 @@ rewrite_simplify_exp(visitor *v, sql_rel
                sql_exp *l = e->l, *r = e->r;
                if (is_func(l->type) && exp_is_true(r) && 
(is_anyequal_func(((sql_subfunc*)l->f)) || 
is_exists_func(((sql_subfunc*)l->f))))
                        return l;
-               if (is_func(l->type) && exp_is_false(r) && !exp_is_null(r) && 
(is_anyequal_func(((sql_subfunc*)l->f)) || 
is_exists_func(((sql_subfunc*)l->f)))) {
+               if (is_func(l->type) && exp_is_false(r) && exp_is_not_null(r) 
&& (is_anyequal_func(((sql_subfunc*)l->f)) || 
is_exists_func(((sql_subfunc*)l->f)))) {
                        sql_subfunc *sf = l->f;
                        if (is_anyequal_func(sf))
                                return exp_in_func(v->sql, 
((list*)l->l)->h->data, ((list*)l->l)->h->next->data, !is_anyequal(sf), 0);
diff --git a/sql/server/rel_statistics.c b/sql/server/rel_statistics.c
--- a/sql/server/rel_statistics.c
+++ b/sql/server/rel_statistics.c
@@ -1101,11 +1101,11 @@ rel_get_statistics_(visitor *v, sql_rel 
 
                if (lv != BUN_NONE) {
                        sql_exp *le = rel->exps->h->data, *oe = 
list_length(rel->exps) > 1 ? rel->exps->h->next->data : NULL;
-                       if (oe && oe->l && !exp_is_null(oe)) { /* no parameters 
*/
+                       if (oe && oe->l && exp_is_not_null(oe)) { /* no 
parameters */
                                BUN offset = (BUN) 
((atom*)oe->l)->data.val.lval;
                                lv = offset >= lv ? 0 : lv - offset;
                        }
-                       if (le->l && !exp_is_null(le)) {
+                       if (le->l && exp_is_not_null(le)) {
                                BUN limit = (BUN) ((atom*)le->l)->data.val.lval;
                                lv = MIN(lv, limit);
                        }
diff --git a/sql/test/BugTracker-2024/Tests/7554-incorrect-result-between.test 
b/sql/test/BugTracker-2024/Tests/7554-incorrect-result-between.test
new file mode 100644
--- /dev/null
+++ b/sql/test/BugTracker-2024/Tests/7554-incorrect-result-between.test
@@ -0,0 +1,8 @@
+query T
+SELECT (1 BETWEEN NULL AND -1) IS NULL
+----
+False
+
+query I
+SELECT 1 WHERE ((1 BETWEEN NULL AND -1) IS NULL)
+----
diff --git 
a/sql/test/BugTracker-2024/Tests/7555-incorrect-semijoin-rewrite.test 
b/sql/test/BugTracker-2024/Tests/7555-incorrect-semijoin-rewrite.test
new file mode 100644
--- /dev/null
+++ b/sql/test/BugTracker-2024/Tests/7555-incorrect-semijoin-rewrite.test
@@ -0,0 +1,32 @@
+statement ok
+CREATE TABLE t1 (c1 BOOLEAN)
+
+statement ok
+CREATE TABLE t0 (c0 INTEGER, PRIMARY KEY(c0) )
+
+statement ok
+INSERT INTO t1(c1) VALUES (true)
+
+statement ok
+INSERT INTO t0(c0) VALUES (2)
+
+statement ok
+INSERT INTO t0(c0) VALUES (1)
+
+query T
+SELECT t1.c1 FROM t0, t1 WHERE (NOT (t1.c1 != CAST(t0.c0 AS BOOLEAN)))
+----
+True
+True
+
+query T
+SELECT t1.c1 FROM t0, t1 WHERE (NOT (t1.c1 != CAST(t0.c0 AS BOOLEAN))) UNION 
ALL SELECT t1.c1 FROM t0, t1 WHERE (t1.c1 != CAST(t0.c0 AS BOOLEAN))
+----
+True
+True
+
+statement ok
+DROP table t0
+
+statement ok
+DROP table t1
diff --git a/sql/test/BugTracker-2024/Tests/All 
b/sql/test/BugTracker-2024/Tests/All
--- a/sql/test/BugTracker-2024/Tests/All
+++ b/sql/test/BugTracker-2024/Tests/All
@@ -78,3 +78,5 @@ 7550-select-statistics-auth
 7552-nested-expression-with-null
 7553-join-on-startswith-crash
 7045-do-not-push-down-converts
+7554-incorrect-result-between
+7555-incorrect-semijoin-rewrite
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to