]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Remember if a SELECT statement contains an ON clause. If it does, then after
authordrh <>
Fri, 22 Aug 2025 19:17:44 +0000 (19:17 +0000)
committerdrh <>
Fri, 22 Aug 2025 19:17:44 +0000 (19:17 +0000)
name resolution, scan the WHERE clause to verify that the ON clause does not
reference tables to its right.

FossilOrigin-Name: 0ec8a8f64434f8cc04f02a356ecaa409ebd886566ba09c32f0fff8ebd103a609

manifest
manifest.uuid
src/select.c
src/sqliteInt.h
src/whereexpr.c

index c098e4e21c58b1edbde69df95b03ca8c34598f3d..01c8ad28a1cc6dce217aa6cb2573390e2a2e240c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhance\streeview\sso\sthat\sit\sshows\sthe\scontents\sof\sON\sclauses\swhile\nthey\sare\sstill\sattached\sto\sthe\sSrcItem\sobject\sand\sbefore\sthey\sare\nmoved\sinto\sthe\sWHERE\sclause.
-D 2025-08-22T18:19:26.194
+C Remember\sif\sa\sSELECT\sstatement\scontains\san\sON\sclause.\s\sIf\sit\sdoes,\sthen\safter\nname\sresolution,\sscan\sthe\sWHERE\sclause\sto\sverify\sthat\sthe\sON\sclause\sdoes\snot\nreference\stables\sto\sits\sright.
+D 2025-08-22T19:17:44.984
 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 78ebf432355e820962a5001277cb43ffe3d82441c6dc9c8f0aeb0b15fbd5dd02
+F src/select.c a8dadaafc129724107aee67153732e3cd3637207993e2f60073b76344edba239
 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 a54f83985985655d1276e9e356dd6ae19b8d0b62c2abc75cc9e8f402ea141207
+F src/sqliteInt.h 7a313bfc16ea0a3b48f9b0fe69f887c971cc7884ce05969f9f02a229b8a31aae
 F src/sqliteLimit.h fe70bd8983e5d317a264f2ea97473b359faf3ebb0827877a76813f5cf0cdc364
 F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -826,7 +826,7 @@ F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
 F src/where.c f2f075bd17065922235632feb368efe92a7f03d42797eb575267574fbf6d4218
 F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
 F src/wherecode.c 71c5c6804b7f882dec8ec858758accae02fcfca13df3cc720f1f258e663ec7c5
-F src/whereexpr.c 78c28a8da187816d5d82049f2e343fb39f4a8e30b5bf1bda9b96cecde40ca8bd
+F src/whereexpr.c 403a44eeec1a0f0914fccc6a59376b6924bc00ef6728fe6ffce4cf3051b320fc
 F src/window.c d01227141f622f24fbe36ca105fbe6ef023f9fd98f1ccd65da95f88886565db5
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
@@ -2169,8 +2169,11 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 9ada44eb6d26532e45cdd2ed8d5707f1734d0177a13b493ff9cf070e0a992522
-R 6e697a296e1f3201fc9a77e474a82c56
+P 3e285bc117bcbfafe083709d27cca776d6ba418a9f0f58a6d4178035fba2d6ca
+R 96dd89e794ca1ca3ff39762daec8741d
+T *branch * on-clause-fix-3rd-try
+T *sym-on-clause-fix-3rd-try *
+T -sym-trunk *
 U drh
-Z ad617721d7c7f540adf02c29a96cfdc3
+Z 3d2156998fed14f6409bf44712a40780
 # Remove this line to create a well-formed Fossil manifest.
index bb4c1eff6c10a1e86142f949b2304989ce6ba527..eda1ade79b7091adb777694eef033685e14f0a1c 100644 (file)
@@ -1 +1 @@
-3e285bc117bcbfafe083709d27cca776d6ba418a9f0f58a6d4178035fba2d6ca
+0ec8a8f64434f8cc04f02a356ecaa409ebd886566ba09c32f0fff8ebd103a609
index 8bdd13e272e886f2dde8cd06ba316ef94bef3ba3..b9cc333acc8a59e25395ab41779f7c8023c23a68 100644 (file)
@@ -660,6 +660,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
       p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn);
       pRight->u3.pOn = 0;
       pRight->fg.isOn = 1;
+      p->selFlags |= SF_OnToWhere;
     }
   }
   return 0;
@@ -7495,6 +7496,50 @@ static SQLITE_NOINLINE void existsToJoin(
   }
 }
 
+/*
+** The xExpr and xSelect callbacks 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)
+  ){
+    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;
+      }
+    }
+  }
+  return WRC_Continue;
+}
+static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){
+  UNUSED_PARAMETER(pWalker);
+  if( (pSelect->selFlags & SF_OnToWhere)==0 ){
+    return WRC_Prune;
+  }else{
+    return WRC_Continue;
+  }
+}
+
+/*
+** Check all ON clauses in pSelect to verify that they do not reference
+** columns to the right.
+*/
+static void selectCheckOnClauses(Parse *pParse, Select *pSelect){
+  Walker w;
+
+  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);
+  pSelect->selFlags &= ~SF_OnToWhere;
+}
+
 /*
 ** Generate byte-code for the SELECT statement given in the p argument. 
 **
@@ -7622,6 +7667,18 @@ int sqlite3Select(
   }
 #endif
 
+  /* If the SELECT statement contains ON clauses that were moved into
+  ** into the WHERE clause, go through and verify that none of the terms
+  ** in the ON clauses reference tables to the right of the ON clause.
+  ** Do this now, after name resolution, but before query flattening
+  */
+  if( p->selFlags & SF_OnToWhere ){
+    selectCheckOnClauses(pParse, p);
+    if( pParse->nErr ){
+      goto select_end;
+    }
+  }
+
   /* If the SF_UFSrcCheck flag is set, then this function is being called
   ** as part of populating the temp table for an UPDATE...FROM statement.
   ** In this case, it is an error if the target object (pSrc->a[0]) name
index a09c94ae62e9d9ed92f05e3a720604aa210e8883..d80ede7c759a5486c948c62ec3e384b7dde37a4f 100644 (file)
@@ -3660,6 +3660,7 @@ struct Select {
 #define SF_OrderByReqd   0x8000000 /* The ORDER BY clause may not be omitted */
 #define SF_UpdateFrom   0x10000000 /* Query originates with UPDATE FROM */
 #define SF_Correlated   0x20000000 /* True if references the outer context */
+#define SF_OnToWhere    0x40000000 /* One or more ON clauses moved to WHERE */
 
 /* True if SrcItem X is a subquery that has SF_NestedFrom */
 #define IsNestedFrom(X) \
index 0d17b0d7529f110a0da1e3b4d5e9191655020ba2..0d99ca85e6f3248039e67c7cbe7abdb91a761e43 100644 (file)
@@ -1170,21 +1170,7 @@ static void exprAnalyze(
       prereqAll |= x;
       extraRight = x-1;  /* ON clause terms may not be used with an index
                          ** on left table of a LEFT JOIN.  Ticket #3015 */
-      if( (prereqAll>>1)>=x ){
-        sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
-        return;
-      }
     }else if( (prereqAll>>1)>=x ){
-      /* The ON clause of an INNER JOIN references a table to its right.
-      ** Most other SQL database engines raise an error.  But SQLite versions
-      ** 3.0 through 3.38 just put the ON clause constraint into the WHERE
-      ** clause and carried on.   Beginning with 3.39, raise an error only
-      ** if there is a RIGHT or FULL JOIN in the query.  This makes SQLite
-      ** more like other systems, and also preserves legacy. */
-      if( ALWAYS(pSrc->nSrc>0) && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
-        sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
-        return;
-      }
       ExprClearProperty(pExpr, EP_InnerON);
     }
   }