]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix problems with WHERE clauses that follow multiple FULL JOINs. This
authordrh <>
Mon, 18 Apr 2022 16:10:07 +0000 (16:10 +0000)
committerdrh <>
Mon, 18 Apr 2022 16:10:07 +0000 (16:10 +0000)
introduces some new faults in the tests, probably due to something
unrelated.

FossilOrigin-Name: 95b242d4c2fed7c713299565ac1010f8a7534a5695589e87d5a0204c7bf5f3dc

manifest
manifest.uuid
src/wherecode.c
test/join7.test

index c0b527257735fccf6a30ef95c36149e09b3af45c..ee28bfc67b35ff4c6659a2266f8078d2b9cfb9a1 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Merge\sthe\slatest\sfixes\sfrom\strunk.
-D 2022-04-18T14:41:24.045
+C Fix\sproblems\swith\sWHERE\sclauses\sthat\sfollow\smultiple\sFULL\sJOINs.\s\sThis\nintroduces\ssome\snew\sfaults\sin\sthe\stests,\sprobably\sdue\sto\ssomething\nunrelated.
+D 2022-04-18T16:10:07.804
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -641,7 +641,7 @@ F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
 F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
 F src/where.c 45102d682f6efd450d89c0c5f09b838be6d69c84c6105336730ee38d3b452fad
 F src/whereInt.h eecce79edc6f7005f91f35be6b18b7053f794e1b50e95bcd06a2d537fc176734
-F src/wherecode.c 4e03f17f8e7b89b9f85d14d705944acf0b0adff3de47753bdd99cf98b0142997
+F src/wherecode.c 1770ab730f14949fe55104b7970e4646087b1ff7f78a906b275cb08ae256f027
 F src/whereexpr.c 174d4ad5be165c610c907abb779ef4a97974d22b84e1ce7898d2d9f6947249e5
 F src/window.c 42a71595263dbd8ef8248218e4fc7d4b5ddccece52146ad48e079342d93f6f8f
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -1146,7 +1146,7 @@ F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
 F test/join5.test c4df54e2e204d7f1417bfbdd21ca324b4b07415c647595cc47798eacfddc96d3
 F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
-F test/join7.test e5c9b1b729d7e1d0b4195e99833e0ff0cf2d88e7fdd32b49af1044f4c76f72d9
+F test/join7.test 8e72de4b45e5e930d18c305c7efe86015fb2552731e4e03ea226353036b0dab0
 F test/join8.test 6ed7eed8993e060e5e9d07f6bcadf1bb634742a03b9824afbcfa193adf7f9965
 F test/join9.test f5db0954fe5aee36fbecb75a80c764d5f0a4b35335016c5829b0d2616039df6e
 F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
@@ -1948,8 +1948,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 009bbf8026106c5a74cced06cced48badb870a4b6e6a2f8104a544d2a8d79e45 1b2c5cef9560123344db391cd065090d1914724715ec6643d2d9b5fac2051a21
-R 7231a9090bdeb7be15e705cd24ff1359
+P 1ba3b3ccf145d84fa75afabe2fa925f65e43f815b25b15bd60073a41aa97bf57
+R 7c5e9401c90d81242051e832c8ba8500
 U drh
-Z 90235891d6fa6cd74fed426055fa90a6
+Z 6ccb42e7d5486d8748e5216dc5361d97
 # Remove this line to create a well-formed Fossil manifest.
index db6197b4412c19742afb013cc2c1804a485d7f05..3d64846252b7f22c83b8c5d616ea69e497b129b4 100644 (file)
@@ -1 +1 @@
-1ba3b3ccf145d84fa75afabe2fa925f65e43f815b25b15bd60073a41aa97bf57
\ No newline at end of file
+95b242d4c2fed7c713299565ac1010f8a7534a5695589e87d5a0204c7bf5f3dc
\ No newline at end of file
index e4a7b449f146a755e9c99bcf7dbf6e80e654d95a..ca02acf45ac3503ba06b429983cf264c269438b0 100644 (file)
@@ -2706,27 +2706,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
     pAlt->wtFlags |= TERM_CODED;
   }
 
-  /* For a LEFT OUTER JOIN, generate code that will record the fact that
-  ** at least one row of the right table has matched the left table.  
-  */
-  if( pLevel->iLeftJoin ){
-    pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
-    sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
-    VdbeComment((v, "record LEFT JOIN hit"));
-    for(pTerm=pWC->a, j=0; j<pWC->nBase; j++, pTerm++){
-      testcase( pTerm->wtFlags & TERM_VIRTUAL );
-      testcase( pTerm->wtFlags & TERM_CODED );
-      if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
-      if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
-        assert( pWInfo->untestedTerms );
-        continue;
-      }
-      assert( pTerm->pExpr );
-      sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
-      pTerm->wtFlags |= TERM_CODED;
-    }
-  }
-
   /* For a RIGHT OUTER JOIN, record the fact that the current row has
   ** been matched at least once.
   */
@@ -2759,19 +2738,45 @@ Bitmask sqlite3WhereCodeOneLoopStart(
     }
     jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, 0, r+1, nPk);
     VdbeCoverage(v);
+    VdbeComment((v, "match against %s", pTab->zName));
     sqlite3VdbeAddOp3(v, OP_MakeRecord, r+1, nPk, r);
     sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r, r+1, nPk);
     sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk);
     sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
     sqlite3VdbeJumpHere(v, jmp1);
     sqlite3ReleaseTempRange(pParse, r, nPk+1);
+  }
 
+  /* For a LEFT OUTER JOIN, generate code that will record the fact that
+  ** at least one row of the right table has matched the left table.  
+  */
+  if( pLevel->iLeftJoin ){
+    pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
+    sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
+    VdbeComment((v, "record LEFT JOIN hit"));
+    for(pTerm=pWC->a, j=0; j<pWC->nBase; j++, pTerm++){
+      testcase( pTerm->wtFlags & TERM_VIRTUAL );
+      testcase( pTerm->wtFlags & TERM_CODED );
+      if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+      if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
+        assert( pWInfo->untestedTerms );
+        continue;
+      }
+      if( pTabItem->fg.jointype & JT_LTORJ ) continue;
+      assert( pTerm->pExpr );
+      sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
+      pTerm->wtFlags |= TERM_CODED;
+    }
+  }
+
+  if( pLevel->pRJ ){
     /* Create a subroutine used to process all interior loops and code
     ** of the RIGHT JOIN.  During normal operation, the subroutine will
     ** be in-line with the rest of the code.  But at the end, a separate
     ** loop will run that invokes this subroutine for unmatched rows
     ** of pTab, with all tables to left begin set to NULL.
     */
+    WhereRightJoin *pRJ = pLevel->pRJ;
     sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pRJ->regReturn);
     pRJ->addrSubrtn = sqlite3VdbeCurrentAddr(v);
     assert( pParse->withinRJSubrtn < 255 );
@@ -2814,23 +2819,25 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
   int k;
 
   ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName));
-  for(k=0; k<iLevel; k++){
-    int iIdxCur;
-    mAll |= pWInfo->a[k].pWLoop->maskSelf;
-    sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
-    iIdxCur = pWInfo->a[k].iIdxCur;
-    if( iIdxCur ){
-      sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
+  if( (pTabItem->fg.jointype & JT_LTORJ)==0 ){
+    for(k=0; k<iLevel; k++){
+      int iIdxCur;
+      mAll |= pWInfo->a[k].pWLoop->maskSelf;
+      sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
+      iIdxCur = pWInfo->a[k].iIdxCur;
+      if( iIdxCur ){
+        sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
+      }
+    }
+    mAll |= pLoop->maskSelf;
+    for(k=0; k<pWC->nTerm; k++){
+      WhereTerm *pTerm = &pWC->a[k];
+      if( pTerm->wtFlags & TERM_VIRTUAL ) break;
+      if( pTerm->prereqAll & ~mAll ) continue;
+      if( ExprHasProperty(pTerm->pExpr, EP_FromJoin|EP_InnerJoin) ) continue;
+      pSubWhere = sqlite3ExprAnd(pParse, pSubWhere,
+                                 sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
     }
-  }
-  mAll |= pLoop->maskSelf;
-  for(k=0; k<pWC->nTerm; k++){
-    WhereTerm *pTerm = &pWC->a[k];
-    if( pTerm->wtFlags & TERM_VIRTUAL ) break;
-    if( pTerm->prereqAll & ~mAll ) continue;
-    if( ExprHasProperty(pTerm->pExpr, EP_FromJoin|EP_InnerJoin) ) continue;
-    pSubWhere = sqlite3ExprAnd(pParse, pSubWhere,
-                               sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
   }
   sFrom.nSrc = 1;
   sFrom.nAlloc = 1;
index a0507be1d93f2b9440db66f589be1fe079913505..a665ba1a9364166b05e4e3718e7fab79ce915997 100644 (file)
@@ -102,6 +102,8 @@ foreach {id schema} {
   reset_db
   db nullvalue NULL
   do_execsql_test join7-$id.setup $schema {}
+
+  # Verified against PG-14 for case 1
   do_execsql_test join7-$id.10 {
     SELECT b, d FROM t1 FULL OUTER JOIN t2 ON b=c ORDER BY +b;
   } {
@@ -110,6 +112,8 @@ foreach {id schema} {
     3    33
     4    44
   }
+
+  # Verified against PG-14 for case 1
   do_execsql_test join7-$id.20 {
     SELECT a, c FROM t1 FULL OUTER JOIN t2 ON b=c ORDER BY +b;
   } {
@@ -118,6 +122,7 @@ foreach {id schema} {
     1     3
     1     4
   }
+
   do_execsql_test join7-$id.30 {
     SELECT * FROM t1 FULL OUTER JOIN t2 ON b=c ORDER BY +b;
   } {
@@ -201,6 +206,8 @@ foreach {id schema} {
     1    3    3    33
     1    4    4    44
   }
+
+  # Verified against PG-14 for case 1
   do_execsql_test join7-$id.110 {
     SELECT * FROM t1 FULL OUTER JOIN t2 ON b=c WHERE a=1 ORDER BY +b;
   } {
@@ -208,6 +215,7 @@ foreach {id schema} {
     1    3    3    33
     1    4    4    44
   }
+
   do_execsql_test join7-$id.111 {
     SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c WHERE a=1 ORDER BY +b;
   } {
@@ -215,6 +223,8 @@ foreach {id schema} {
     1    3    3    33
     1    4    4    44
   }
+
+  # Verified against PG-14 for case 1
   do_execsql_test join7-$id.115 {
     SELECT * FROM t1 FULL OUTER JOIN t2 ON b=c
      WHERE a=1 OR a IS NULL ORDER BY +b;
@@ -224,6 +234,7 @@ foreach {id schema} {
     1    3    3    33
     1    4    4    44
   }
+
   do_execsql_test join7-$id.116 {
     SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c
      WHERE a=1 OR a IS NULL ORDER BY +b;
@@ -233,13 +244,15 @@ foreach {id schema} {
     1    3    3    33
     1    4    4    44
   }
+
+  # Verified against PG-14 for case 1:
   do_execsql_test join7-$id.120 {
     SELECT * FROM t1 FULL OUTER JOIN t2 ON b=c WHERE a IS NULL ORDER BY +d;
   } {
-    NULL NULL 3    33
-    NULL NULL 4    44
     NULL NULL 5    55
   }
+
+  # Verified against PG-14 for case 1:
   do_execsql_test join7-$id.130 {
     SELECT * FROM t1 FULL OUTER JOIN t2 ON b=c AND d<=0 ORDER BY +b, +d;
   } {
@@ -250,6 +263,8 @@ foreach {id schema} {
     1    3    NULL NULL
     1    4    NULL NULL
   }
+
+  # Verified against PG-14 for case 1:
   do_execsql_test join7-$id.140 {
     SELECT a, b, c, d
       FROM t2 FULL OUTER JOIN t1 ON b=c AND d<=0 ORDER BY +b, +d;
@@ -261,6 +276,7 @@ foreach {id schema} {
     1    3    NULL NULL
     1    4    NULL NULL
   }
+
   do_execsql_test join7-$id.141 {
     SELECT a, b, c, d
       FROM t2 FULL OUTER JOIN t1 ON b=c AND d<=0