From: drh <> Date: Mon, 18 Apr 2022 16:10:07 +0000 (+0000) Subject: Fix problems with WHERE clauses that follow multiple FULL JOINs. This X-Git-Tag: version-3.39.0~206^2~28 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e1bcc9dd083888a7581d7db8c8fd7d0d9d98e17;p=thirdparty%2Fsqlite.git Fix problems with WHERE clauses that follow multiple FULL JOINs. This introduces some new faults in the tests, probably due to something unrelated. FossilOrigin-Name: 95b242d4c2fed7c713299565ac1010f8a7534a5695589e87d5a0204c7bf5f3dc --- diff --git a/manifest b/manifest index c0b5272577..ee28bfc67b 100644 --- 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. diff --git a/manifest.uuid b/manifest.uuid index db6197b441..3d64846252 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1ba3b3ccf145d84fa75afabe2fa925f65e43f815b25b15bd60073a41aa97bf57 \ No newline at end of file +95b242d4c2fed7c713299565ac1010f8a7534a5695589e87d5a0204c7bf5f3dc \ No newline at end of file diff --git a/src/wherecode.c b/src/wherecode.c index e4a7b449f1..ca02acf45a 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -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; jnBase; 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; jnBase; 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; ka[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; ka[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; knTerm; 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; knTerm; 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; diff --git a/test/join7.test b/test/join7.test index a0507be1d9..a665ba1a93 100644 --- a/test/join7.test +++ b/test/join7.test @@ -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