]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix the IN-early-out optimization so that it works even for the corner case
authordrh <>
Thu, 29 Apr 2021 15:49:34 +0000 (15:49 +0000)
committerdrh <>
Thu, 29 Apr 2021 15:49:34 +0000 (15:49 +0000)
where the NULL bypass fires before the affinity of the LHS operator has been
set.  Fix for the problem described in
[forum:/forumpost/6a3ec138e9|forum post 6a3ec138e9].

FossilOrigin-Name: eb40248ce606b792a02e4e0b7dd826a82891c5f4c9793f3ca5d332e593109525

manifest
manifest.uuid
src/where.c
test/in6.test

index ea5d882265354f313be1b6134b13093c754556ab..6b37cd82f0a22078f558b891a3ab4bdf5fb9c4bf 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhanced\s"PRAGMA\svdbe_trace=on"\soutput\sassociated\swith\sthe\sseekHit\sflag.
-D 2021-04-29T13:58:28.373
+C Fix\sthe\sIN-early-out\soptimization\sso\sthat\sit\sworks\seven\sfor\sthe\scorner\scase\nwhere\sthe\sNULL\sbypass\sfires\sbefore\sthe\saffinity\sof\sthe\sLHS\soperator\shas\sbeen\nset.\s\sFix\sfor\sthe\sproblem\sdescribed\sin\n[forum:/forumpost/6a3ec138e9|forum\spost\s6a3ec138e9].
+D 2021-04-29T15:49:34.719
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -630,7 +630,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c 69e770e96fd56cc21608992bf2c6f1f3dc5cf2572d0495c6a643b06c3a679f14
 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
 F src/walker.c 6e540867a30d81e00205995fa2dc0e3d25365a7402251c9fd5d19aa4ff5e60b6
-F src/where.c c6e020d87235c7da91414a0075342339d9560c981b15ad4ed099e6c3fa1bdd20
+F src/where.c 33bae7248e206b874456982a07b859acd880fb7b137678b2dc1e277c234b8b6f
 F src/whereInt.h 446e5e8018f83358ef917cf32d8e6a86dc8430113d0b17e720f1839d3faa44c4
 F src/wherecode.c 992bf0d7520bffd345472fb9bc83a1ca0134e46d9e904879bb21e1e77957fcc3
 F src/whereexpr.c d8cafcf6781cf871082f04d7540862cf0fe30cb381dd1b2145a380376364fe8e
@@ -1077,7 +1077,7 @@ F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
 F test/in4.test cd08375ba470b248c3dc4ab30fd5dbcb682deafe3862d8249ba0ad6a11dd25ea
 F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
-F test/in6.test 8562d0945195cab3cc4ab3794e9118e72cb44c43f785c2b04d48a9d06ca6b4ec
+F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
 F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
 F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
 F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
@@ -1914,7 +1914,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 1b8da7924cc78710ae4bbe12b57140fdaeae5efb0e6ac10073ae9c98b7f8d7a4
-R c9961ebb679b5956c54d8a22972f2273
+P 683950009300657b0321d7d3f77f2585a28696ff93cedef399d1cd4aa484b2d4
+R 2fa8e2441473674deda1256a612f82a3
 U drh
-Z 5db4b3f7b88ff23bda45bc815f5f8c05
+Z cf36b9a5e331b2b6911dc39680ad6acd
index 0ac59627bb76a7b11ee9f466724772498b797ffd..868533c5555d28b7eac35e5d06e2b899365220b9 100644 (file)
@@ -1 +1 @@
-683950009300657b0321d7d3f77f2585a28696ff93cedef399d1cd4aa484b2d4
\ No newline at end of file
+eb40248ce606b792a02e4e0b7dd826a82891c5f4c9793f3ca5d332e593109525
\ No newline at end of file
index 7fee58d11e55c79737257ca7626abab2ee825657..606e326b184f741c008b2acea41fa92ead44f589 100644 (file)
@@ -5435,6 +5435,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
       int j;
       sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
       for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
+        assert( sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull
+                 || pParse->db->mallocFailed );
         sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
         if( pIn->eEndLoopOp!=OP_Noop ){
           if( pIn->nPrefix ){
@@ -5459,6 +5461,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
                   sqlite3VdbeCurrentAddr(v)+2,
                   pIn->iBase, pIn->nPrefix);
               VdbeCoverage(v);
+              /* Retarget the OP_IsNull against the left operand of IN so 
+              ** it jumps past the OP_IfNoHope.  This is because the
+              ** OP_IsNull also bypasses the OP_Affinity opcode that is
+              ** required by OP_IfNoHope. */
+              sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
             }
           }
           sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
index 3719a6cbf35a11187f3953c2b22759e65115af83..f477f60ef2832a324e8fc5b16f738972cc2cab91 100644 (file)
@@ -97,4 +97,23 @@ do_execsql_test in6-3.110 {
   SELECT quote(v5) FROM v0 LEFT JOIN v3 ON v4 = NULL AND v5 IN(0);
 } {NULL}
 
+# 2021-04-29 forum https://sqlite.org/forum/forumpost/6a3ec138e9
+# An early OP_IsNull bypass might skip over the OP_Affinity and
+# cause the OP_IfNoHope to jump on a false-positive, resulting in
+# incomplete output.
+#
+reset_db
+do_execsql_test in6-3.120 {
+  CREATE TABLE t1(a TEXT, b TEXT);
+  INSERT INTO t1 VALUES(null,10),(0,10),(10,10);
+  CREATE INDEX t1ab ON t1(a,b);
+  SELECT quote(a), quote(b), '|' FROM t1 WHERE b in (SELECT a FROM t1) AND a=0;
+} {'0' '10' |}
+do_execsql_test in6-3.130 {
+  CREATE TABLE t2(x TEXT);
+  INSERT INTO t2(x) VALUES(NULL),(0),(10);
+  SELECT quote(x), quote(a), quote(b), 'x'
+    FROM t2 LEFT JOIN t1 ON a=x AND b in (null,0,10);
+} {NULL NULL NULL x '0' '0' '10' x '10' '10' '10' x}
+
 finish_test