diff --git a/manifest b/manifest index 2f99c83238..45004bedab 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sfts4aux\svirtual\stable\sso\sthat\sit\sconsistently\sbehaves\sas\sif\sits\scolumns\shave\sblob\saffinity.\sReport\s[bugs:/info/2026-08-14T07:27:28Z\s|\s2026-08-14T07:27:28Z]. -D 2026-08-14T10:57:58.215 +C Adjust\sthe\sbytecode\sgenerated\sfor\sRIGHT\sJOIN\sso\sthat\sit\schecks\sfor\sduplicate\nRHS\srows\swhen\sthe\sLHS\sis\sNULL.\n[bugs:/info/2026-08-14T04:56:02Z|Bug\s2026-08-14T04:56:02Z] +D 2026-08-14T14:03:07.205 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -826,7 +826,7 @@ F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452 F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014 F src/where.c 2f5b4091f37bfac7658ea3d52b2c192d8fb2ec062f232815e0eb5152a46267db F src/whereInt.h f039ad303bc2913de673e431821ef8db3b619d249e6e5548d90072a684e72285 -F src/wherecode.c 32ca3ee7a56ee29c49ab31e4aa6152e9c01c2fcbf6a1ad2f612308780dd4583f +F src/wherecode.c f705ef20659991c9f570a6263c072eb0d04a8f6927242b433ab969900bbf9507 F src/whereexpr.c cd88bd3e1a421fb987eb5991ecf7a9a3d5dad1abb02a8baa070336b6dfa70b59 F src/window.c 0d7dacdf2e84c6ee8ff498d5cc881dd245fcb2f14f6c5976e97e112ce96e90dc F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1343,7 +1343,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c F test/ioerr5.test 5984da7bf74b6540aa356f2ab0c6ae68a6d12039a3d798a9ac6a100abc17d520 F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9 -F test/join.test c706b382ed09ddc89eee7ad0ffd08d862655b0abc292a690d41d995c18c17b3f +F test/join.test b41503f19c6d9b6a7cee7353c4ec98238131809275a96ee585041ab004e305e2 F test/join2.test f59d63264fb24784ae9c3bc9d867eb569cd6d442da5660f8852effe5c1938c27 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 @@ -2218,8 +2218,9 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P c406ce3f1e3b1a8edea2dbb03aff5649d5217019b23c88b0ae73e627a3a983ee -R 42cf4e4adf6431f8e4fb4ae87d7f63f6 -U dan -Z 6f550e71731fb8cfa22e6abbba032d6b +P d5b57f76b63552b23ba3e5e372a3773118b929a4116f60f374a91cba87c1152e 9d39b0973bff5af1787fafdd49e455c6c27d493c3bce997ae0fdf88eb9adb1d2 +R 87fd0f1fa4fa8993d3fd221438fd0c12 +T +closed 9d39b0973bff5af1787fafdd49e455c6c27d493c3bce997ae0fdf88eb9adb1d2 +U drh +Z 76a5d5a1a70df39c1a32e85a2320988d # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index a589f54974..4ed6da1de3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d5b57f76b63552b23ba3e5e372a3773118b929a4116f60f374a91cba87c1152e +f4f57ca539520b687cf00b0034cb20868cafa5f6c7602c1db71e1a7f885f3daf diff --git a/src/wherecode.c b/src/wherecode.c index ad8af68fb9..069a681e76 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -2940,12 +2940,12 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( pSubWInfo = sqlite3WhereBegin(pParse, pFrom, pSubWhere, 0, 0, 0, WHERE_RIGHT_JOIN, 0); if( pSubWInfo ){ - int iCur = pLevel->iTabCur; - int r = ++pParse->nMem; - int nPk; - int jmp = 0; + int iCur = pLevel->iTabCur; /* Table on RHS of RIGHT JOIN &*/ + int r = ++pParse->nMem; /* Register range to hold primary key */ + int nPk; /* Number of values in the primary key */ + int r2; /* Register holding record for primary key */ int addrCont = sqlite3WhereContinueLabel(pSubWInfo); - Table *pTab = pTabItem->pSTab; + Table *pTab = pTabItem->pSTab; /* Table on RHS of RIGHT JOIN */ if( HasRowid(pTab) ){ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r); nPk = 1; @@ -2959,13 +2959,31 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk); } } + + /* Generate code that checks to see if the current row of the RHS table + ** has appeared in any prior output row. */ if( pRJ->regBloom ){ - jmp = sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk); + sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, + sqlite3VdbeCurrentAddr(v)+2, r, nPk); VdbeCoverage(v); } sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, addrCont, r, nPk); VdbeCoverage(v); - if( jmp ) sqlite3VdbeJumpHere(v, jmp); + r2 = sqlite3GetTempReg(pParse); + + /* Generate code that inserts the PK of the RHS table into the + ** pRH->iMatch index to indicate that the current row has appeared + ** in the output set. */ + sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, r2); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r2, r, nPk); + sqlite3ReleaseTempReg(pParse, r2); + if( pRJ->regBloom ){ + sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r, nPk); + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); + } + + /* Invoke the subroutine that actually puts the current RHS table row + ** into the output set, with NULLs for the LHS. */ sqlite3VdbeAddOp2(v, OP_Gosub, pRJ->regReturn, pRJ->addrSubrtn); sqlite3WhereEnd(pSubWInfo); } diff --git a/test/join.test b/test/join.test index a1ce7da0c2..a3197c78dc 100644 --- a/test/join.test +++ b/test/join.test @@ -1410,4 +1410,29 @@ do_eqp_test join-33.3-eqp { `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN } +# Bug 2026-08-14T04:56:02Z +# +reset_db +db null NULL +do_execsql_test join-34.1 { + CREATE TABLE t0(a INT, b INT); + CREATE INDEX t0i ON t0(a); + INSERT INTO t0 VALUES (1,10), (1,20); + CREATE VIEW empty(c) AS SELECT 1 WHERE 0; +} +do_execsql_test join-34.2 { + SELECT * + FROM empty RIGHT JOIN t0 ON true + WHERE (a,b) IN (SELECT a,b FROM t0) + ORDER BY +b; +} {NULL 1 10 NULL 1 20} +do_execsql_test join-34.3 { + SELECT * + FROM empty FULL OUTER JOIN t0 ON true + WHERE (a,b) IN (SELECT a,b FROM t0) + ORDER BY +b; +} {NULL 1 10 NULL 1 20} + + + finish_test