]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
If a query has an ORDER BY clause that only refers to result columns of the order-by-push-down
authordrh <>
Wed, 2 Aug 2023 18:20:10 +0000 (18:20 +0000)
committerdrh <>
Wed, 2 Aug 2023 18:20:10 +0000 (18:20 +0000)
left-most table and the left most table is a MATERIALIZED common table
expresion, then attempt to push the ORDER BY clause down into the subquery.

FossilOrigin-Name: 8e7a70b2bbcf85e67936eea62018f5142e8e03a2326fbb610eaef3fc8af3be98

manifest
manifest.uuid
src/select.c

index bd8750b7dcfa1e5e01e45e8f788b30f70140acb2..5d1865d1c5433ede41a46b36bcaea8ebee9658b5 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Performance\soptimization\sfor\sJSON\srendering\slogic.
-D 2023-08-02T16:06:02.660
+C If\sa\squery\shas\san\sORDER\sBY\sclause\sthat\sonly\srefers\sto\sresult\scolumns\sof\sthe\nleft-most\stable\sand\sthe\sleft\smost\stable\sis\sa\sMATERIALIZED\scommon\stable\nexpresion,\sthen\sattempt\sto\spush\sthe\sORDER\sBY\sclause\sdown\sinto\sthe\ssubquery.
+D 2023-08-02T18:20:10.121
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -643,7 +643,7 @@ F src/printf.c e3ba080e2f409f9bfcc8d34724e6fc160e9c718dc92d0548f6b71b8b6f860ce2
 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c 37953a5f36c60bea413c3c04efcd433b6177009f508ef2ace0494728912fe2e9
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
-F src/select.c abf48be202d35c4f450325b61992e98ac4aa81ed1e29709069432877d3b555d3
+F src/select.c 5d94f21834e0b5960617f5bef266a01675428679422124a0015ff2ed18de0086
 F src/shell.c.in 694aaf751f00610381533d4a31c83d142cfc83ef91ef65e2aa6912ace7c39b40
 F src/sqlite.h.in 7b07a33d2af82ee974aa91e6294abce0282b2f4c5934b291d2fff961810dd867
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
@@ -2049,8 +2049,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 c4347e4400e96f932ac12f8f22484a2ebce2a578d1b2181977954c432f117bfd
-R a3168d15b44149a629121fdff1d59acd
+P ea0b9aecbaca9a8e784fd2bcb50f78cbdcf4c5cfb45a7700bb222e4cc104c644
+R ee3670aab2a8384c34615ac09a8a53a3
+T *branch * order-by-push-down
+T *sym-order-by-push-down *
+T -sym-trunk *
 U drh
-Z 37bd268b83df81194e3e4e7be36a0655
+Z 30f1c0db753d338fceeb02d267e9d680
 # Remove this line to create a well-formed Fossil manifest.
index ca5b942d1b9988ae4bde44965c100c365d85dfa0..59bc55d78d22b4c0cb110017e99bf165ec91f84e 100644 (file)
@@ -1 +1 @@
-ea0b9aecbaca9a8e784fd2bcb50f78cbdcf4c5cfb45a7700bb222e4cc104c644
\ No newline at end of file
+8e7a70b2bbcf85e67936eea62018f5142e8e03a2326fbb610eaef3fc8af3be98
\ No newline at end of file
index 41e42b68085f7def5a19477380bb4ddf03156719..e34750e15bd60195f6d888ed9685e0e036441a0c 100644 (file)
@@ -7007,6 +7007,54 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){
   return 0;
 }
 
+/*
+** If the ORDER BY clause on the outer query pOuter only refers directly
+** to columns of the subquery pSub, then drop the ORDER BY clause on the
+** outer query and create a new equivalent ORDER BY clause on the
+** subquery.
+**
+** Return non-zero on success.  Return zero if the ORDER BY transfer
+** could not occur, either because conditions were not met or because
+** of an OOM.
+*/
+static SQLITE_NOINLINE int transferOrderByIntoSubquery(
+  Parse *pParse,      /* Parsing context */
+  int iCursor,        /* Cursor number for the subquery */
+  Select *pSub,       /* The sub query */
+  Select *pOuter      /* The outer query */
+){
+  int i;
+  ExprList *pEL = pOuter->pOrderBy;
+  ExprList *pNew;
+
+  for(i=pEL->nExpr-1; i>=0; i--){
+    Expr *pExpr = pEL->a[i].pExpr;
+    if( pExpr->op!=TK_COLUMN ) return 0;
+    if( pExpr->iTable!=iCursor ) return 0;
+  }
+  /* If we get to this point, it means that the ORDER BY should be
+  ** transferred. */
+  pNew = 0;
+  for(i=0; i<pEL->nExpr; i++){
+    int iCol = pEL->a[0].pExpr->iColumn;
+    pNew = sqlite3ExprListAppend(pParse, pNew,
+               sqlite3ExprDup(pParse->db, pSub->pEList->a[iCol].pExpr, 0));
+    if( pParse->nErr ) break;
+    pNew->a[i].u.x.iOrderByCol = iCol+1;
+  }
+  if( pParse->nErr ){
+    sqlite3ExprListDelete(pParse->db, pNew);
+    return 0;
+  }
+  sqlite3ParserAddCleanup(pParse,
+      (void(*)(sqlite3*,void*))sqlite3ExprListDelete,
+       pOuter->pOrderBy);
+  pOuter->pOrderBy = 0;
+  pSub->pOrderBy = pNew;
+  return 1;
+}
+
+
 /*
 ** Return TRUE (non-zero) if the i-th entry in the pTabList SrcList can
 ** be implemented as a co-routine.  The i-th entry is guaranteed to be
@@ -7291,6 +7339,21 @@ int sqlite3Select(
     ** a MATERIALIZED common table expression is an optimization fence.
     */
     if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ){
+      /* If the MATERIALIZED common table expression is the left-most
+      ** term of the outer query, and if it has no ORDER BY clause, but
+      ** there is an ORDER BY clause on the outer query that only references
+      ** the common table expression, then transfer the ORDER BY clause over
+      ** to the common table expression.
+      */
+      if( i==0
+       && pSub->pOrderBy==0
+       && sSort.pOrderBy!=0
+       && transferOrderByIntoSubquery(pParse, pItem->iCursor, pSub, p)
+      ){
+        sSort.pOrderBy = 0;
+        TREETRACE(0x800,pParse,p,
+                ("transfer ORDER BY into left-most subquery"));
+      }
       continue;
     }