]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix the cases in joinI.test on this branch.
authordan <Dan Kennedy>
Sat, 23 Aug 2025 16:26:36 +0000 (16:26 +0000)
committerdan <Dan Kennedy>
Sat, 23 Aug 2025 16:26:36 +0000 (16:26 +0000)
FossilOrigin-Name: 23ac2377315af02b73db6ae37bfeeda1453e41efb702a6b707346956c2d41a9d

manifest
manifest.uuid
src/select.c
src/sqliteInt.h
test/joinI.test

index 9565585a1456fa4dc8cf85c76b6e2ac442f5d38a..24ad7a244a0808bde189865aa8bef69c7d5e764a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Steal\sthe\stest/joinI.test\sfrom\sthe\son-clause-error-fix\sbranch\sthat\ndemonstrates\sthat\sthis\sbranch\sdoes\snot\swork.
-D 2025-08-22T19:30:26.745
+C Fix\sthe\scases\sin\sjoinI.test\son\sthis\sbranch.
+D 2025-08-23T16:26:36.004
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -741,12 +741,12 @@ F src/printf.c 5f0c957af9699e849d786e8fbaa3baab648ca5612230dc17916434c14bc8698f
 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c f8d1d011aba0964ff1bdccd049d4d2c2fec217efd90d202a4bb775e926b2c25d
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
-F src/select.c a8dadaafc129724107aee67153732e3cd3637207993e2f60073b76344edba239
+F src/select.c 32ccbdbc89ba40065891c891a6a9dcd50fb3171eaf041b8549929f479dd540cb
 F src/shell.c.in 0636915df0dbac6c780f04959f5d1055f206fb281b2c8fc8b113fe7bfc7d44ef
 F src/sqlite.h.in ebfc0358de0e18aabee7fa918f2f846894e23bebc74160fbe265c99046ee61b8
 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
 F src/sqlite3ext.h 0bfd049bb2088cc44c2ad54f2079d1c6e43091a4e1ce8868779b75f6c1484f1e
-F src/sqliteInt.h 7a313bfc16ea0a3b48f9b0fe69f887c971cc7884ce05969f9f02a229b8a31aae
+F src/sqliteInt.h 27c73e48878d31ef230ba867d1f8c3af6aed357fd93ccc605d3f1aae007ea62b
 F src/sqliteLimit.h fe70bd8983e5d317a264f2ea97473b359faf3ebb0827877a76813f5cf0cdc364
 F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -1335,7 +1335,7 @@ F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be
 F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
 F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
 F test/joinH.test fd76024ff104baec16417db5cafc0894ad4e0863e70803e63c1bba0322706339
-F test/joinI.test 78cae6f746a78f32d8aedb8cf7b93bcd802c245db0986330844dfb1a6700ebab
+F test/joinI.test c30a1096c80a1300f088feb64fd356309cd14059d78352426550d2676f015ab4
 F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa
 F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
 F test/journal3.test e5aeff93a7776cf644dbc48dec277655cff80a1cd24689036abc87869b120ea6
@@ -2170,8 +2170,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 0ec8a8f64434f8cc04f02a356ecaa409ebd886566ba09c32f0fff8ebd103a609
-R 1752fb5ac5dd2e1a0b7a8c6b08170380
-U drh
-Z 1500a43de7f87186b8488707b788a405
+P d163535ec8d463d74112d38a606fa4d900e66deb1a414c947973cd1880e41526
+R 690bd5803e72eefc9593af834d5d854a
+U dan
+Z fa70e0c9e7cfdd60641dd6afc4b1e883
 # Remove this line to create a well-formed Fossil manifest.
index bc0325b4e714116dfefc391b35c0261483a69dcd..83b0dedec45cc0d6fa411df3cd59bf90496a9342 100644 (file)
@@ -1 +1 @@
-d163535ec8d463d74112d38a606fa4d900e66deb1a414c947973cd1880e41526
+23ac2377315af02b73db6ae37bfeeda1453e41efb702a6b707346956c2d41a9d
index b9cc333acc8a59e25395ab41779f7c8023c23a68..d8873fb06507492e83cac807bc40b48c87562250 100644 (file)
@@ -7497,28 +7497,91 @@ static SQLITE_NOINLINE void existsToJoin(
 }
 
 /*
-** The xExpr and xSelect callbacks for the search of invalid ON clause terms.
+** Type used for Walker callbacks by selectCheckOnClauses().
+*/
+typedef struct CheckOnCtx CheckOnCtx;
+struct CheckOnCtx {
+  SrcList *pSrc;                  /* SrcList for this context */
+  int iJoin;                      /* Cursor numbers must be =< than this */
+  CheckOnCtx *pParent;            /* Parent context */
+};
+
+/*
+** True if the SrcList passed as the only argument contains at least
+** one RIGHT or FULL JOIN. False otherwise.  
+*/
+#define hasRightJoin(pSrc) (((pSrc)->a[0].fg.jointype & JT_LTORJ)!=0)
+
+/*
+** The xExpr callback for the search of invalid ON clause terms.
 */
 static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){
-  if( pExpr->op==TK_COLUMN 
-   && ExprHasProperty(pExpr, EP_OuterON|EP_InnerON)
+  CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx;
+
+  /* Check if pExpr is root or near-root of an ON clause constraint that needs
+  ** to be checked to ensure that it does not refer to tables in its FROM
+  ** clause to the right of itself. i.e. it is either:
+  **
+  **   + an ON clause on an OUTER join, or
+  **   + an ON clause on an INNER join within a FROM that features at
+  **     least one RIGHT or FULL join.
+  */
+  if( (ExprHasProperty(pExpr, EP_OuterON))
+   || (ExprHasProperty(pExpr, EP_InnerON) && hasRightJoin(pCtx->pSrc))
   ){
-    if( pExpr->w.iJoin<pExpr->iTable ){
-      if( ExprHasProperty(pExpr, EP_OuterON) || pWalker->eCode ){
-        sqlite3ErrorMsg(pWalker->pParse,
-            "ON clause references tables to its right");
-        return WRC_Abort;
+    /* If CheckOnCtx.iJoin is already set, then fall through and process
+    ** this expression node as normal. Or, if CheckOnCtx.iJoin is still 0,
+    ** set it to the cursor number of the RHS of the join to which this
+    ** ON expression was attached and then iterate through the entire 
+    ** expression.  */
+    assert( pCtx->iJoin==0 || pCtx->iJoin==pExpr->w.iJoin );
+    if( pCtx->iJoin==0 ){
+      pCtx->iJoin = pExpr->w.iJoin;
+      sqlite3WalkExprNN(pWalker, pExpr);
+      pCtx->iJoin = 0;
+      return WRC_Prune;
+    }
+  }
+
+  if( pExpr->op==TK_COLUMN ){
+    /* A column expression. Find the SrcList (if any) to which it refers.
+    ** Then, if CheckOnCtx.iJoin indicates that this expression is part of an
+    ** ON clause from that SrcList (i.e. if iJoin is non-zero), check that it
+    ** does not refer to a table to the right of CheckOnCtx.iJoin. */
+    do {
+      SrcList *pSrc = pCtx->pSrc;
+      int iTab = pExpr->iTable;
+      if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){
+        if( pCtx->iJoin && iTab>pCtx->iJoin ){
+          sqlite3ErrorMsg(pWalker->pParse, 
+              "ON clause references tables to its right");
+          return WRC_Abort;
+        }
+        break;
       }
-    }
+      pCtx = pCtx->pParent;
+    }while( pCtx );
   }
   return WRC_Continue;
 }
+
+/*
+** The xSelect callback for the search of invalid ON clause terms.
+*/
 static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){
-  UNUSED_PARAMETER(pWalker);
-  if( (pSelect->selFlags & SF_OnToWhere)==0 ){
-    return WRC_Prune;
-  }else{
+  CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx;
+  if( pSelect->pSrc==pCtx->pSrc || pSelect->pSrc->nSrc==0 ){
     return WRC_Continue;
+  }else{
+    CheckOnCtx sCtx;
+    memset(&sCtx, 0, sizeof(sCtx));
+    sCtx.pSrc = pSelect->pSrc;
+    sCtx.pParent = pCtx;
+    pWalker->u.pCheckOnCtx = &sCtx;
+    sqlite3WalkSelect(pWalker, pSelect);
+    pWalker->u.pCheckOnCtx = pCtx;
+    pSelect->selFlags &= ~SF_OnToWhere;
+    return WRC_Prune;
   }
 }
 
@@ -7528,15 +7591,17 @@ static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){
 */
 static void selectCheckOnClauses(Parse *pParse, Select *pSelect){
   Walker w;
-
+  CheckOnCtx sCtx;
   assert( pSelect->selFlags & SF_OnToWhere );
   assert( pSelect->pSrc!=0 && pSelect->pSrc->nSrc>=2 );
   memset(&w, 0, sizeof(w));
   w.pParse = pParse;
-  w.eCode = (pSelect->pSrc->a[0].fg.jointype & JT_LTORJ)!=0;
   w.xExprCallback = selectCheckOnClausesExpr;
   w.xSelectCallback = selectCheckOnClausesSelect;
-  sqlite3WalkSelect(&w, pSelect);
+  w.u.pCheckOnCtx = &sCtx;
+  memset(&sCtx, 0, sizeof(sCtx));
+  sCtx.pSrc = pSelect->pSrc;
+  sqlite3WalkExprNN(&w, pSelect->pWhere);
   pSelect->selFlags &= ~SF_OnToWhere;
 }
 
index d80ede7c759a5486c948c62ec3e384b7dde37a4f..f012650088d9e765c8bf2d77b0a51668a1a4337a 100644 (file)
@@ -4414,6 +4414,7 @@ struct Walker {
     SrcItem *pSrcItem;                        /* A single FROM clause item */
     DbFixer *pFix;                            /* See sqlite3FixSelect() */
     Mem *aMem;                                /* See sqlite3BtreeCursorHint() */
+    struct CheckOnCtx *pCheckOnCtx;           /* See selectCheckOnClauses() */
   } u;
 };
 
index a422f19470613559f5c13e0ef1916b9895dd4bd9..96dba7bb8d6dcc61ef000d44eb5b0c0d7acb8342 100644 (file)
@@ -93,4 +93,19 @@ do_catchsql_test 3.6 {
   ) CROSS JOIN t4;
 } {1 {ON clause references tables to its right}}
 
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 4.0 {
+  CREATE TABLE parent1(parent1key, child1key, Child2key, child3key);
+  CREATE TABLE child1 ( child1key NVARCHAR, value NVARCHAR );
+  CREATE TABLE child2 ( child2key NVARCHAR, value NVARCHAR );
+}
+
+do_execsql_test 4.1 {
+  SELECT parent1.parent1key, child1.value, child2.value
+    FROM parent1
+    LEFT OUTER JOIN child1 ON child1.child1key = parent1.child1key
+    INNER JOIN child2 ON child2.child2key = parent1.child2key;
+}
+
 finish_test