Changeset: bff4d8dd5d4d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=bff4d8dd5d4d
Modified Files:
        monetdb5/optimizer/opt_pushselect.c
        sql/test/SQLancer/Tests/sqlancer10.test
Branch: default
Log Message:

SQLancer bug, when rewriting batalgebra.like + [theta]select -> likeselect, 
look for a possible negative case (= false), then swap 'anti' flag on those 
cases


diffs (135 lines):

diff --git a/monetdb5/optimizer/opt_pushselect.c 
b/monetdb5/optimizer/opt_pushselect.c
--- a/monetdb5/optimizer/opt_pushselect.c
+++ b/monetdb5/optimizer/opt_pushselect.c
@@ -328,23 +328,45 @@ OPTpushselectImplementation(Client cntxt
                                                !isaBatType(getArgType(mb, q, 
2)) && /* pattern is a value */
                                                (q->argc != 4 || 
!isaBatType(getArgType(mb, q, 3))) /* escape is a value */
                                                ) {
-                                       bool has_null_semantics = false;
+                                       bool selectok = true;
                                        int has_cand = (getArgType(mb, p, 2) == 
newBatType(TYPE_oid)), offset = 0;
                                        int a, anti = (getFunctionId(q)[0] == 
'n'), ignore_case = (getFunctionId(q)[anti?4:0] == 'i');
 
                                        /* TODO at the moment we cannot convert 
if the select statement has NULL semantics
-                                               we can convert it into VAL is 
NULL or PATERN is NULL or ESCAPE is NULL
+                                               we can convert it into VAL is 
NULL or PATTERN is NULL or ESCAPE is NULL
                                        */
-                                       if (getFunctionId(p) == selectRef && 
isVarConstant(mb,getArg(p, 2 + has_cand)) && isVarConstant(mb,getArg(p, 3 + 
has_cand))
-                                               && isVarConstant(mb,getArg(p, 4 
+ has_cand)) && isVarConstant(mb,getArg(p, 5 + has_cand))) {
-                                               ValRecord low = 
getVarConstant(mb, getArg(p, 2 + has_cand)), high = getVarConstant(mb, 
getArg(p, 3 + has_cand));
+                                       if (getFunctionId(p) == selectRef) {
+                                               bit low = 
*(bit*)getVarValue(mb, getArg(p, 2 + has_cand)), high = *(bit*)getVarValue(mb, 
getArg(p, 3 + has_cand));
                                                bit li = *(bit*)getVarValue(mb, 
getArg(p, 4 + has_cand)), hi = *(bit*)getVarValue(mb, getArg(p, 5 + has_cand));
+                                               bit santi = 
*(bit*)getVarValue(mb, getArg(p, 6 + has_cand)), sunknown = (p->argc == 
(has_cand ? 9 : 8)) ? 0 : *(bit*)getVarValue(mb, getArg(p, 7 + has_cand));
 
-                                               if (li && hi && VALisnil(&low) 
&& VALisnil(&high))
-                                                       has_null_semantics = 
true;
+                                               /* semantic or not symmetric 
cases, it cannot be converted */
+                                               if (is_bit_nil(low) || 
is_bit_nil(li) || is_bit_nil(santi) || low != high || li != hi || sunknown)
+                                                       selectok = false;
+
+                                               /* there are no negative 
candidate lists so on = false situations swap anti flag */
+                                               if (low == 0)
+                                                       anti = !anti;
+                                               if (li == 0)
+                                                       anti = !anti;
+                                               if (santi)
+                                                       anti = !anti;
+                                       } else if (getFunctionId(p) == 
thetaselectRef) {
+                                               bit truth_value = 
*(bit*)getVarValue(mb, getArg(p, 3));
+                                               str comparison = 
(str)getVarValue(mb, getArg(p, 4));
+
+                                               /* there are no negative 
candidate lists so on = false situations swap anti flag */
+                                               if (truth_value == 0)
+                                                       anti = !anti;
+                                               else if 
(is_bit_nil(truth_value))
+                                                       selectok = false;
+                                               if (strcmp(comparison, "<>") == 
0)
+                                                       anti = !anti;
+                                               else if (strcmp(comparison, 
"==") != 0)
+                                                       selectok = false;
                                        }
 
-                                       if (!has_null_semantics) {
+                                       if (selectok) {
                                                InstrPtr r = newInstruction(mb, 
algebraRef, likeselectRef);
                                                getArg(r,0) = getArg(p,0);
                                                r = addArgument(mb, r, 
getArg(q, 1));
diff --git a/sql/test/SQLancer/Tests/sqlancer10.test 
b/sql/test/SQLancer/Tests/sqlancer10.test
--- a/sql/test/SQLancer/Tests/sqlancer10.test
+++ b/sql/test/SQLancer/Tests/sqlancer10.test
@@ -35,6 +35,74 @@ statement ok
 START TRANSACTION
 
 statement ok
+CREATE TABLE "sys"."t1" ("c0" INTERVAL DAY,"c1" TIME,"c3" INTERVAL DAY,"c5" 
TIME)
+
+statement ok
+COPY 6 RECORDS INTO "sys"."t1" FROM stdin USING DELIMITERS E'\t',E'\n','"'
+<COPY_INTO_DATA>
+NULL   01:00:00        345600.000      01:00:08
+NULL   02:50:32        NULL    01:00:00
+NULL   02:50:32        NULL    01:00:00
+432000.000     01:00:00        259200.000      NULL
+179900573616000.000    01:00:00        12666182976000.000      NULL
+86400.000      02:04:32        2.000   01:00:00
+
+query T rowsort
+SELECT ALL t1.c3 FROM t1 WHERE (((COALESCE(r'', r'㉁*3', 
r'w1ZR'))ILIKE(r'-6739257'))) = FALSE
+----
+0
+146599340
+3
+4
+NULL
+NULL
+
+statement ok
+set optimizer = 'sequential_pipe'
+
+query T python .explain.function_histogram
+EXPLAIN SELECT 1 FROM t1 WHERE (((COALESCE('b', 'a'))ILIKE('c'))) = FALSE
+----
+user.main
+1
+querylog.define
+1
+sql.mvc
+1
+sql.tid
+1
+sql.bind
+1
+algebra.project
+5
+algebra.thetaselect
+2
+bat.replace
+2
+algebra.likeselect
+1
+algebra.projection
+1
+bat.pack
+5
+sql.resultSet
+1
+
+statement ok
+set optimizer = 'default_pipe'
+
+query I rowsort
+SELECT CAST(SUM(count) AS BIGINT) FROM (SELECT CAST((((COALESCE(r'', r'㉁*3', 
r'w1ZR'))ILIKE(r'-6739257'))) = FALSE AS INT) as count FROM t1) as res
+----
+6
+
+statement ok
+ROLLBACK
+
+statement ok
+START TRANSACTION
+
+statement ok
 CREATE TABLE "sys"."t2" ("c0" BOOLEAN,"c2" INTEGER)
 
 statement ok
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to