From: drh <> Date: Thu, 2 Mar 2023 14:09:11 +0000 (+0000) Subject: When flattening the right operand of a LEFT JOIN, X-Git-Tag: version-3.41.1~12 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7a83522677fdf26dc8706a21e0af7ee20a57c77c;p=thirdparty%2Fsqlite.git When flattening the right operand of a LEFT JOIN, ensure that the OP_IfNullRow opcode does not NULL-out a subquery result that was computed within OP_Once. FossilOrigin-Name: c80b262c9dbde80c51872f36f9c4d406eba1c3f34468d36d5cb7084b1720ee5c --- diff --git a/manifest b/manifest index 1d89f94264..65b3d74357 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sflattening\sa\sview\sthat\sis\sthe\sright\soperand\sof\sa\sLEFT\sJOIN\nalways\sinsert\sthe\sTK_IF_NULL_ROW\sexpression\snodes,\seven\sfor\sTK_COLUMN\nexpressions,\sas\sthe\sTK_COLUMN\smight\sbe\sa\scolumn\sfrom\san\souter\squery\nand\shence\sstill\sneed\sto\sbe\sNULLed\sout. -D 2023-03-01T20:44:34.141 +C When\sflattening\sthe\sright\soperand\sof\sa\sLEFT\sJOIN,\nensure\sthat\sthe\sOP_IfNullRow\sopcode\sdoes\snot\nNULL-out\sa\ssubquery\sresult\sthat\swas\scomputed\swithin\sOP_Once. +D 2023-03-02T14:09:11.338 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -571,7 +571,7 @@ F src/date.c f21815ca7172ce073db3163ac54c8d9f2841077165c1a6123b4d1c376a0c7ec7 F src/dbpage.c d47549716549311f79dc39fe5c8fb19390a6eb2c960f8e37c89a9c4de0c1052e F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e -F src/expr.c e3520c28b322d0e06e883c91de15322ddd06a98d5b4564c3273c99da9391d1b8 +F src/expr.c 8f9d5c20cf412d231b485bae592c78ff1906ce4b8e6b0f185f07441bd4070e72 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002 F src/func.c d187be57a886ddf4e6b7ef584a494361899be3df5eee6d4a747b68ff4aff4122 @@ -1215,7 +1215,7 @@ F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4 F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9 F test/join.test e32cb9b1491eed682489e2cde33a22a4eb7611fe5aa3b0aa4b275fe27ab3f3ac -F test/join2.test 88f4527101710806674d49257439f198fa147a7fcec11afedf51cf4894dc8877 +F test/join2.test c378a2c59db8da13a265481c9aeab08d854c524f56a0eda12fa7bc535bfbebb1 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 F test/join5.test 91f1f4c7d81fd87b58e9ba7cf4a2b5d39e3583b4f8e498a162722a60259c5208 @@ -2045,9 +2045,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9dc460318d98308f51e31df216872ff96ece67c86f50c3fd11bf2a3df112afdd -Q +198b3e33dcfd74c7ba6abcf789ee81dfed464a50ebf15c8edeff349d36789fca -R 72a34dd5ec4ce343ea308cb4fbef2927 +P 371838562a675c1bdd9c80250230eb87ac0e5e135cc39abbdbe1f8b1b8149445 +Q +8fe13f7a5e5eb798189acb25a608df7a94c2f5cc83463331a048b779c7890c82 +R 9795d2127c64d5e6196616fc73ed63ae U drh -Z dc1e8cfabf9c76a49d329efd6999fa4b +Z 4fdc16272f2027c0cdb33e22ff3d2802 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 73118326db..c9c86cfa9c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -371838562a675c1bdd9c80250230eb87ac0e5e135cc39abbdbe1f8b1b8149445 \ No newline at end of file +c80b262c9dbde80c51872f36f9c4d406eba1c3f34468d36d5cb7084b1720ee5c \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 763e961b6e..b688e5b401 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4833,16 +4833,22 @@ expr_code_doover: break; } } - addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable); - /* Temporarily disable factoring of constant expressions, since - ** even though expressions may appear to be constant, they are not - ** really constant because they originate from the right-hand side - ** of a LEFT JOIN. */ - pParse->okConstFactor = 0; + addrINR = sqlite3VdbeAddOp3(v, OP_IfNullRow, pExpr->iTable, 0, target); + /* The OP_IfNullRow opcode above can overwrite the result register with + ** NULL. So we have to ensure that the result register is not a value + ** that is suppose to be a constant. Two defenses are needed: + ** (1) Temporarily disable factoring of constant expressions + ** (2) Make sure the computed value really is stored in register + ** "target" and not someplace else. + */ + pParse->okConstFactor = 0; /* note (1) above */ inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); pParse->okConstFactor = okConstFactor; + if( inReg!=target ){ /* note (2) above */ + sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); + inReg = target; + } sqlite3VdbeJumpHere(v, addrINR); - sqlite3VdbeChangeP3(v, addrINR, inReg); break; } diff --git a/test/join2.test b/test/join2.test index b3fd265353..39cabf8809 100644 --- a/test/join2.test +++ b/test/join2.test @@ -386,4 +386,22 @@ do_execsql_test 10.4 { ) FROM t1; } NULL +# 2023-03-02 https://sqlite.org/forum/forumpost/402f05296d +# +# The TK_IF_NULL_ROW expression node must ensure that it does not overwrite +# the result register of an OP_Once subroutine. +# +optimization_control db all 1 +do_execsql_test 11.1 { + DROP TABLE t1; + DROP TABLE t2; + DROP TABLE t3; + CREATE TABLE t1(x TEXT, y INTEGER); + INSERT INTO t1(x,y) VALUES(NULL,-2),(NULL,1),('0',2); + CREATE TABLE t2(z INTEGER); + INSERT INTO t2(z) VALUES(2),(-2); + CREATE VIEW t3 AS SELECT z, (SELECT count(*) FROM t1) AS w FROM t2; + SELECT * FROM t1 LEFT JOIN t3 ON y=z; +} {NULL -2 -2 3 NULL 1 NULL NULL 0 2 2 3} + finish_test