]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Generalize pushdown to allow any uncorrelated subquery to be pushed down.
authordrh <>
Sat, 6 Apr 2024 12:19:50 +0000 (12:19 +0000)
committerdrh <>
Sat, 6 Apr 2024 12:19:50 +0000 (12:19 +0000)
FossilOrigin-Name: 87c45fb0d5f5ca5d6d1ad27bef83f294231d17d94299e1997364a7975b423e38

manifest
manifest.uuid
src/expr.c
src/parse.y
src/resolve.c
src/sqliteInt.h

index 8fd5496617f9c3ca478e37b62ce1ae01a9dc417e..581e5d22d19059376e425364e96e542fb05991d9 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Experimental\senhancement\sin\swhich\sexpressions\sof\sthe\sform\s"expr\sIN\stable"\ncan\sbe\spushed\sdown\sinto\ssubexpressions.
-D 2024-04-05T20:01:28.787
+C Generalize\spushdown\sto\sallow\sany\suncorrelated\ssubquery\sto\sbe\spushed\sdown.
+D 2024-04-06T12:19:50.927
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -700,7 +700,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875
 F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
 F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
-F src/expr.c 48e6732170b5f3c07f9ebbdbe12c478e2867ea4be4361946ed26e2c8d607f7e8
+F src/expr.c f2f4768a25d62f645d11233930c0514f5f05fdadd8150e17d64187dd5aa41e4a
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
 F src/func.c 283d4f3b2751a1d9339fd93a8a013d1948fd5f4474a3cab0955eb4fafd445d0f
@@ -739,7 +739,7 @@ F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
 F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd
 F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
-F src/parse.y 67b9965a501599d5a1a4333125fab0dd230e03e28045700c9b331f7c3269bda5
+F src/parse.y 5bcef16094213efcc365a9d4dc4e3131f09251dc8838dce4a9e5f9764bff5b82
 F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
 F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
@@ -748,14 +748,14 @@ F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
 F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c
 F src/printf.c 87b67bba3662a0523f39ae6b084a3907109702f717c654d6cecb838af5cd57f1
 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
-F src/resolve.c eb1860b134fb044fd819c4347105c148d5aac7c6498032be2829e5cc95619b28
+F src/resolve.c f242e509b2ff9e31799d26ddd87f20db1124426203aa16833a694d401b50d650
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
 F src/select.c 15a221347789e393b39e7d2d2bd102167979c95a1ce0675bb870b86a24ca6cf4
 F src/shell.c.in 0354ca51eee5fbf6af394a7ef9f5ef6823ef45b743db65431f6777e4d5be2199
 F src/sqlite.h.in 32389e0d584551b300d0157881336162c14315a424cbf385c0d65eb7c2e31f7b
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
-F src/sqliteInt.h a0d0f014baafcb61f5d0a6d206d4b190644d57bb762dff2073903595653d6319
+F src/sqliteInt.h e9ef8bb759f6ed7c41971bd8189dca3d38cc8bc69c463a6f49aaa9401857091a
 F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
 F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -2184,11 +2184,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 4484ec6d26b31305e31de89bdbae26344d8083a7e7de20861430d31737d9979c
-R 445c665a7eec3209ded422866778f161
-T *branch * pushdown-IN-table
-T *sym-pushdown-IN-table *
-T -sym-trunk *
+P 2cbd7838fd6ffdf210f34671cd2e3e749a076a3a6f155bbe5f910a67db31c5b1
+R 3f1ebbef3f30ee834eac030ff4cc2f9a
+T *branch * pushdown-subquery
+T *sym-pushdown-subquery *
+T -sym-pushdown-IN-table *
 U drh
-Z 5ecd3bbce21aa8f702309c384d09dab0
+Z 00cc18dd5b8247ec2ec6349e18d457dd
 # Remove this line to create a well-formed Fossil manifest.
index 7d0dacd7c00b3b9abbce6bbb10b8706ad9f713a5..b3cce22c826e1829696c730fefb581d671fabf67 100644 (file)
@@ -1 +1 @@
-2cbd7838fd6ffdf210f34671cd2e3e749a076a3a6f155bbe5f910a67db31c5b1
\ No newline at end of file
+87c45fb0d5f5ca5d6d1ad27bef83f294231d17d94299e1997364a7975b423e38
\ No newline at end of file
index f2b252792befea1bf12bed1d4c97b6192c9bad14..9513e5ffd500925a068a7d8a683f2a25548989a2 100644 (file)
@@ -2550,38 +2550,17 @@ static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
 
 /*
 ** This routine examines sub-SELECT statements as an expression is being
-** walked as part of sqlite3ExprIsTableConstant() (hereafter IsTabConst()).
-** Most SELECT statements will cause IsTabConst() to return false.  However,
-** if:
-**
-**    (1)  The SELECT is the right-hand side of an IN operator, and
-**    (2)  Nothing in the SELECT refers to anything other than itself
-**
-** Then this routine causes the sub-SELECT to be bypassed, so that if
-** nothing else is amiss the IsTabConst() routine can return true.
+** walked as part of sqlite3ExprIsTableConstant().  Sub-SELECTs are considered
+** constant as long as they are uncorrelated - meaning that they do not
+** contain any terms from outer contexts.
 */
 static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){
-  int savedCursor;
   assert( pSelect!=0 );
   assert( pWalker->eCode==3 || pWalker->eCode==0 );
-  if( (pSelect->selFlags & SF_RhsOfIN)==0 ){
+  if( (pSelect->selFlags & SF_Correlated)!=0 ){
     pWalker->eCode = 0;
     return WRC_Abort;
   }
-  assert( pSelect->pSrc!=0 );
-  assert( pSelect->pSrc->nSrc==1 );
-  assert( pSelect->pWhere==0 );
-  assert( pSelect->pGroupBy==0 );
-  assert( pSelect->pHaving==0 );
-  assert( pSelect->pOrderBy==0 );
-  assert( pSelect->pPrior==0 );
-  assert( pSelect->pNext==0 );
-  assert( pSelect->pLimit==0 );
-  assert( pSelect->pWith==0 );
-  savedCursor = pWalker->u.iCur;
-  pWalker->u.iCur = pSelect->pSrc->a[0].iCursor;
-  sqlite3WalkExprList(pWalker, pSelect->pEList);
-  pWalker->u.iCur = savedCursor;
   return WRC_Prune;
 }
 
@@ -2591,8 +2570,7 @@ static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){
 ** expression must not refer to any non-deterministic function nor any
 ** table other than iCur.
 **
-** 2024-04-05:  Operators of the form "expr IN table" are now allowed, where
-** "table" is the name of a table.
+** Enhanced on 2024-04-06:  Allow pExpr to contain uncorrelated subqueries.
 */
 static int sqlite3ExprIsTableConstant(Expr *p, int iCur){
   Walker w;
index 7a3d637663fb42565c4e477b359f2820716278bf..d22c8e6fc27eb50ef2f861590ff1cbde8767cf36 100644 (file)
@@ -1369,10 +1369,6 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
     if( E )  sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, E);
     A = sqlite3PExpr(pParse, TK_IN, A, 0);
     sqlite3PExprAddSelect(pParse, A, pSelect);
-    if( pParse->nErr==0 ){
-      assert( pSelect!=0 );
-      pSelect->selFlags |= SF_RhsOfIN;
-    }
     if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
   }
   expr(A) ::= EXISTS LP select(Y) RP. {
index 6e0c9906a6fc226ada886c4bdf2773882b8b0e33..7378addf5d201e1b04a838c69b783ec24bacebc8 100644 (file)
@@ -1349,6 +1349,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
         testcase( pNC->ncFlags & NC_PartIdx );
         testcase( pNC->ncFlags & NC_IdxExpr );
         testcase( pNC->ncFlags & NC_GenCol );
+        assert( pExpr->x.pSelect );
         if( pNC->ncFlags & NC_SelfRef ){
           notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
         }else{
@@ -1357,6 +1358,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
         assert( pNC->nRef>=nRef );
         if( nRef!=pNC->nRef ){
           ExprSetProperty(pExpr, EP_VarSelect);
+          pExpr->x.pSelect->selFlags |= SF_Correlated;
         }
         pNC->ncFlags |= NC_Subquery;
       }
index 29acb570dec480296b504882706353689ce0fa01..a735c445e7f30f32f21f3ec72dac1894188757d1 100644 (file)
@@ -3585,7 +3585,7 @@ struct Select {
 #define SF_CopyCte       0x4000000 /* SELECT statement is a copy of a CTE */
 #define SF_OrderByReqd   0x8000000 /* The ORDER BY clause may not be omitted */
 #define SF_UpdateFrom   0x10000000 /* Query originates with UPDATE FROM */
-#define SF_RhsOfIN      0x20000000 /* Right-hand-side of an IN operator */
+#define SF_Correlated   0x20000000 /* True if references the outer context */
 
 /* True if S exists and has SF_NestedFrom */
 #define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
@@ -5082,7 +5082,6 @@ int sqlite3ExprTruthValue(const Expr*);
 int sqlite3ExprIsConstant(Parse*,Expr*);
 int sqlite3ExprIsConstantOrFunction(Expr*, u8);
 int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
-// int sqlite3ExprIsTableConstant(Expr*,int);
 int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int);
 #ifdef SQLITE_ENABLE_CURSOR_HINTS
 int sqlite3ExprContainsSubquery(Expr*);