]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improve comments and code legibility in new file window.c.
authordan <dan@noemail.net>
Thu, 14 Jun 2018 14:27:05 +0000 (14:27 +0000)
committerdan <dan@noemail.net>
Thu, 14 Jun 2018 14:27:05 +0000 (14:27 +0000)
FossilOrigin-Name: bb915854d435bdd78f141d70e23527e97922ec176acd3ed8060c78dffc96bab8

manifest
manifest.uuid
src/window.c

index dadf035fa0937845d7e65300446e0b68018188d9..9c3a7a405a1b42b9fba99bae36e6573e2eb0ba23 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sproblems\swith\s"RANGE\sBETWEEN\sCURRENT\sROW\sAND\sUNBOUNDED\sFOLLOWING"\swindow\nframes.
-D 2018-06-13T20:29:38.362
+C Improve\scomments\sand\scode\slegibility\sin\snew\sfile\swindow.c.
+D 2018-06-14T14:27:05.155
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 498b77b89a8cb42f2ee20fcd6317f279a45c0d6ff40d27825f94b69884c09bbe
@@ -583,7 +583,7 @@ F src/where.c fe1a6f97c12cc9472ccce86166ba3f827cf61d6ae770c036a6396b63863baac4
 F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
 F src/wherecode.c 3317f2b083a66d3e65a03edf316ade4ccb0a99c9956273282ebb579b95d4ba96
 F src/whereexpr.c 6f022d6cc9daf56495f191b199352f783aff5cf268ba136b4d8cea3fb62d8c7d
-F src/window.c 4a26ff629a2207fbb766b64eec5de56a642db2ee1a58ca7f3d9bf7241ca2265d
+F src/window.c 0a6b366a3301c68172fcdbebd5b9ddf0466cdc6533ff92ad859b4acd06aaa29b
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
 F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -1740,7 +1740,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 6413e38a174044c28fa9b8b937e6c972d144547a246e6f2882e782538300d042
-R 30609a9614da284dabc36852804237fe
+P c34f31dbd79891249ee9485e91f6ea558ee1db62e04fb0fff2c051612b8fa5e7
+R 250d0aa9c508f0b3712323b0e393b7d6
 U dan
-Z 71b05cd13cd6b1243eec19b7dd0b41c2
+Z 8f2ba813d9d3711cc22cf41096ce6e24
index 8d9afc357c4868173f1f9c45689e11b453264e14..594644608c8eb004127fb339964a4add68f27d93 100644 (file)
@@ -1 +1 @@
-c34f31dbd79891249ee9485e91f6ea558ee1db62e04fb0fff2c051612b8fa5e7
\ No newline at end of file
+bb915854d435bdd78f141d70e23527e97922ec176acd3ed8060c78dffc96bab8
\ No newline at end of file
index 395d6733be33f80fe932d48343e83be6a75f8c6e..459d05e29e19cbb136cae08e22901c0493e45a45 100644 (file)
@@ -1236,6 +1236,12 @@ static void windowReturnRows(
   sqlite3VdbeJumpHere(v, addr+1);   /* The OP_Goto */
 }
 
+/*
+** Generate code to set the accumulator register for each window function
+** in the linked list passed as the second argument to NULL. And perform
+** any equivalent initialization required by any built-in window functions
+** in the list.
+*/
 static int windowInitAccum(Parse *pParse, Window *pMWin){
   Vdbe *v = sqlite3GetVdbe(pParse);
   int regArg;
@@ -1258,15 +1264,11 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){
 
 
 /*
-** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
-** ----------------------------------------------------
+** This function does the work of sqlite3WindowCodeStep() for all "ROWS"
+** window frame types except for "BETWEEN UNBOUNDED PRECEDING AND CURRENT
+** ROW". Pseudo-code for each follows.
 **
-** Pseudo-code for the implementation of this window frame type is as
-** follows. sqlite3WhereBegin() has already been called to generate the
-** top of the main loop when this function is called.
-**
-** Each time the sub-routine at addrGosub is invoked, a single output
-** row is generated based on the current row indicated by Window.iEphCsr.
+** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
 **
 **     ...
 **       if( new partition ){
@@ -1551,6 +1553,16 @@ static void windowCodeRowExprStep(
 }
 
 /*
+** This function does the work of sqlite3WindowCodeStep() for cases that
+** would normally be handled by windowCodeDefaultStep() when there are
+** one or more built-in window-functions that require the entire partition
+** to be cached in a temp table before any rows can be returned. Additionally.
+** "RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" is always handled by
+** this function.
+**
+** Pseudo-code corresponding to the VM code generated by this function
+** for each type of window follows.
+**
 ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
 **
 **   flush_partition:
@@ -1581,8 +1593,64 @@ static void windowCodeRowExprStep(
 **     Return
 **
 ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
-** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+**
+**   As above, except that the "if( new peer )" branch is always taken.
+**
 ** RANGE BETWEEN CURRENT ROW AND CURRENT ROW 
+**
+**   As above, except that each of the for() loops becomes:
+**
+**         for(i=0; i<ctr; i++){
+**           Gosub addrGosub
+**           AggStep (xInverse, iEphCsr)
+**           Next iEphCsr
+**         }
+**
+** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+**
+**   flush_partition:
+**     Once {
+**       OpenDup (iEphCsr -> csrLead)
+**     }
+**     foreach row (csrLead) {
+**       AggStep (csrLead)
+**     }
+**     foreach row (iEphCsr) {
+**       Gosub addrGosub
+**     }
+** 
+** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
+**
+**   flush_partition:
+**     Once {
+**       OpenDup (iEphCsr -> csrLead)
+**     }
+**     foreach row (csrLead){
+**       AggStep (csrLead)
+**     }
+**     Rewind (csrLead)
+**     Integer ctr 0
+**     foreach row (csrLead){
+**       if( new peer ){
+**         AggFinal (xValue)
+**         for(i=0; i<ctr; i++){
+**           Gosub addrGosub
+**           AggStep (xInverse, iEphCsr)
+**           Next iEphCsr
+**         }
+**         Integer ctr 0
+**       }
+**       Incr ctr
+**     }
+**
+**     AggFinal (xFinalize)
+**     for(i=0; i<ctr; i++){
+**       Gosub addrGosub
+**       Next iEphCsr
+**     }
+**
+**     ResetSorter (csr)
+**     Return
 */
 static void windowCodeCacheStep(
   Parse *pParse, 
@@ -1598,7 +1666,7 @@ static void windowCodeCacheStep(
   int addr;
   ExprList *pPart = pMWin->pPartition;
   ExprList *pOrderBy = pMWin->pOrderBy;
-  int nPeer = pOrderBy->nExpr;
+  int nPeer = pOrderBy ? pOrderBy->nExpr : 0;
   int regNewPeer;
 
   int addrGoto;                   /* Address of Goto used to jump flush_par.. */
@@ -1610,8 +1678,9 @@ static void windowCodeCacheStep(
   int regArg;                     /* Register array to martial function args */
   int regSize;
   int nArg;
-  int bReverse;
   int lblEmpty;
+  int bReverse = pMWin->pOrderBy && pMWin->eStart==TK_CURRENT 
+          && pMWin->eEnd==TK_UNBOUNDED;
 
   assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) 
        || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED) 
@@ -1620,7 +1689,6 @@ static void windowCodeCacheStep(
   );
 
   lblEmpty = sqlite3VdbeMakeLabel(v);
-  bReverse = (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED);
   regNewPeer = pParse->nMem+1;
   pParse->nMem += nPeer;
 
@@ -1878,34 +1946,60 @@ void sqlite3WindowCodeStep(
   int addrGosub                   /* OP_Gosub here to return each row */
 ){
   Window *pMWin = p->pWin;
-  ExprList *pOrderBy = pMWin->pOrderBy;
 
-  /* Call windowCodeRowExprStep() for all "ROWS" window modes except:
+  /* There are three different functions that may be used to do the work
+  ** of this one, depending on the window frame and the specific built-in
+  ** window functions used (if any).
+  **
+  ** windowCodeRowExprStep() handles all "ROWS" window frames, except for:
   **
   **   ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+  **
+  ** The exception is because windowCodeRowExprStep() implements all window
+  ** frame types by caching the entire partition in a temp table, and
+  ** "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" is easy enough to
+  ** implement without such a cache.
+  **
+  ** windowCodeCacheStep() is used for:
+  **
+  **   RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
+  **
+  ** It is also used for anything not handled by windowCodeRowExprStep() 
+  ** that invokes a built-in window function that requires the entire 
+  ** partition to be cached in a temp table before any rows are returned
+  ** (e.g. nth_value() or percent_rank()).
+  **
+  ** Finally, assuming there is no built-in window function that requires
+  ** the partition to be cached, windowCodeDefaultStep() is used for:
+  **
+  **   RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 
+  **   RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+  **   RANGE BETWEEN CURRENT ROW AND CURRENT ROW 
+  **   ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+  **
+  ** windowCodeDefaultStep() is the only one of the three functions that
+  ** does not cache each partition in a temp table before beginning to
+  ** return rows.
   */
-  if( (pMWin->eType==TK_ROWS 
-   && (pMWin->eStart!=TK_UNBOUNDED || pMWin->eEnd!=TK_CURRENT || !pOrderBy))
+  if( pMWin->eType==TK_ROWS 
+   && (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy)
   ){
     windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub);
   }else{
     Window *pWin;
-    int bCache = 0;
+    int bCache = 0;               /* True to use CacheStep() */
 
-    if( pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED && pOrderBy ){
+    if( pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED ){
       bCache = 1;
     }else{
-      /* Call windowCodeCacheStep() if there is a window function that requires
-      ** that the entire partition be cached in a temp table before any rows
-      ** are returned.  */
       for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
         FuncDef *pFunc = pWin->pFunc;
         if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE)
-            || (pFunc->xSFunc==nth_valueStepFunc)
-            || (pFunc->xSFunc==first_valueStepFunc)
-            || (pFunc->xSFunc==leadStepFunc)
-            || (pFunc->xSFunc==lagStepFunc)
-          ){
+         || (pFunc->xSFunc==nth_valueStepFunc)
+         || (pFunc->xSFunc==first_valueStepFunc)
+         || (pFunc->xSFunc==leadStepFunc)
+         || (pFunc->xSFunc==lagStepFunc)
+        ){
           bCache = 1;
           break;
         }