1
0
mirror of https://github.com/sqlite/sqlite.git synced 2026-10-23 21:49:02 +03:00

Adjust the bytecode generated for RIGHT JOIN so that it checks for duplicate

RHS rows when the LHS is NULL.
[bugs:/info/2026-08-14T04:56:02Z|Bug 2026-08-14T04:56:02Z]

FossilOrigin-Name: f4f57ca539520b687cf00b0034cb20868cafa5f6c7602c1db71e1a7f885f3daf
This commit is contained in:
drh
2026-08-14 14:03:07 +00:00
4 changed files with 60 additions and 16 deletions

View File

@@ -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.

View File

@@ -1 +1 @@
d5b57f76b63552b23ba3e5e372a3773118b929a4116f60f374a91cba87c1152e
f4f57ca539520b687cf00b0034cb20868cafa5f6c7602c1db71e1a7f885f3daf

View File

@@ -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);
}

View File

@@ -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