]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When flattening the right operand of a LEFT JOIN,
authordrh <>
Thu, 2 Mar 2023 14:09:11 +0000 (14:09 +0000)
committerdrh <>
Thu, 2 Mar 2023 14:09:11 +0000 (14:09 +0000)
ensure that the OP_IfNullRow opcode does not
NULL-out a subquery result that was computed within OP_Once.

FossilOrigin-Name: c80b262c9dbde80c51872f36f9c4d406eba1c3f34468d36d5cb7084b1720ee5c

manifest
manifest.uuid
src/expr.c
test/join2.test

index 1d89f9426485d7952cf45c671d8a9f9e1d51be8b..65b3d743573a0fdec4c80d938bf0c3f2d7ebe8fa 100644 (file)
--- 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.
index 73118326db30278560649e0255d454e360e5dd72..c9c86cfa9c126666908509c48576f9af7c5ac143 100644 (file)
@@ -1 +1 @@
-371838562a675c1bdd9c80250230eb87ac0e5e135cc39abbdbe1f8b1b8149445
\ No newline at end of file
+c80b262c9dbde80c51872f36f9c4d406eba1c3f34468d36d5cb7084b1720ee5c
\ No newline at end of file
index 763e961b6eb266feabd6d287e9953645b57df20c..b688e5b40138675be7c995412c49f8baaaba33aa 100644 (file)
@@ -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;
     }
 
index b3fd2653531794ac6daf26aa4a9d743803fc64d5..39cabf880953cf4c6e0262c764c394ab9de453b1 100644 (file)
@@ -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