Clarify the relationship between a Window object and its associated Expr.

FossilOrigin-Name: 0cd55e98a478740032f5569ddc00fa5b0e063e90db6e00ac7598c9b7c2fffeee
diff --git a/src/expr.c b/src/expr.c
index 819a14b..9431c4c 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1271,7 +1271,7 @@
       if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){
         pNew->pWin = 0;
       }else{
-        pNew->pWin = sqlite3WindowDup(db, p->pWin);
+        pNew->pWin = sqlite3WindowDup(db, pNew, p->pWin);
       }
       if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
         if( pNew->op==TK_SELECT_COLUMN ){
diff --git a/src/resolve.c b/src/resolve.c
index 0d94668..221564f 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -800,8 +800,6 @@
             pExpr->pWin->pNextWin = pSel->pWin;
             pSel->pWin = pExpr->pWin;
           }
-          pExpr->pWin->pFunc = pDef;
-          pExpr->pWin->nArg = (pExpr->x.pList ? pExpr->x.pList->nExpr : 0);
         }else{
           NameContext *pNC2 = pNC;
           pExpr->op = TK_AGG_FUNCTION;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 7d4c3ea..cd702ce 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3488,7 +3488,6 @@
 
   Expr *pFilter;
   FuncDef *pFunc;
-  int nArg;
 
   int iEphCsr;            /* Temp table used by this window */
   int regAccum;
@@ -3513,7 +3512,7 @@
 int sqlite3WindowRewrite(Parse*, Select*);
 int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
 void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
-Window *sqlite3WindowDup(sqlite3 *db, Window *p);
+Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
 
 /*
 ** Assuming zIn points to the first byte of a UTF-8 character,
diff --git a/src/window.c b/src/window.c
index 9c63362..a627be1 100644
--- a/src/window.c
+++ b/src/window.c
@@ -26,7 +26,7 @@
   i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p));
   if( p ) (*p)++;
 }
-static void row_numberInverseFunc(
+static void row_numberInvFunc(
   sqlite3_context *pCtx, 
   int nArg,
   sqlite3_value **apArg
@@ -38,7 +38,8 @@
 }
 
 /*
-** Context object type used by rank() and dense_rank().
+** Context object type used by rank(), dense_rank(), percent_rank() and
+** cume_dist().
 */
 struct CallCount {
   i64 nValue;
@@ -58,7 +59,7 @@
   p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
   if( p ) p->nStep = 1;
 }
-static void dense_rankInverseFunc(
+static void dense_rankInvFunc(
   sqlite3_context *pCtx, 
   int nArg,
   sqlite3_value **apArg
@@ -93,7 +94,7 @@
     }
   }
 }
-static void rankInverseFunc(
+static void rankInvFunc(
   sqlite3_context *pCtx, 
   int nArg,
   sqlite3_value **apArg
@@ -130,7 +131,7 @@
     }
   }
 }
-static void percent_rankInverseFunc(
+static void percent_rankInvFunc(
   sqlite3_context *pCtx, 
   int nArg,
   sqlite3_value **apArg
@@ -166,7 +167,7 @@
     p->nStep++;
   }
 }
-static void cume_distInverseFunc(
+static void cume_distInvFunc(
   sqlite3_context *pCtx, 
   int nArg,
   sqlite3_value **apArg
@@ -181,6 +182,9 @@
   }
 }
 
+/*
+** Context object for ntile() window function.
+*/
 struct NtileCtx {
   i64 nTotal;                     /* Total rows in partition */
   i64 nParam;                     /* Parameter passed to ntile(N) */
@@ -214,7 +218,7 @@
     p->iRow++;
   }
 }
-static void ntileInverseFunc(
+static void ntileInvFunc(
   sqlite3_context *pCtx, 
   int nArg,
   sqlite3_value **apArg
@@ -243,6 +247,9 @@
   }
 }
 
+/*
+** Context object for last_value() window function.
+*/
 struct LastValueCtx {
   sqlite3_value *pVal;
   int nVal;
@@ -264,7 +271,7 @@
     p->nVal++;
   }
 }
-static void last_valueInverseFunc(
+static void last_valueInvFunc(
   sqlite3_context *pCtx, 
   int nArg,
   sqlite3_value **apArg
@@ -296,76 +303,33 @@
   }
 }
 
-static void nth_valueStepFunc(
-  sqlite3_context *pCtx, 
-  int nArg,
-  sqlite3_value **apArg
-){
-}
-static void nth_valueInverseFunc(
-  sqlite3_context *pCtx, 
-  int nArg,
-  sqlite3_value **apArg
-){
-}
-static void nth_valueValueFunc(sqlite3_context *pCtx){
-}
-
-static void first_valueStepFunc(
-  sqlite3_context *pCtx, 
-  int nArg,
-  sqlite3_value **apArg
-){
-}
-static void first_valueInverseFunc(
-  sqlite3_context *pCtx, 
-  int nArg,
-  sqlite3_value **apArg
-){
-}
-static void first_valueValueFunc(sqlite3_context *pCtx){
-}
-
-static void leadStepFunc(
-  sqlite3_context *pCtx, 
-  int nArg,
-  sqlite3_value **apArg
-){
-}
-static void leadInverseFunc(
-  sqlite3_context *pCtx, 
-  int nArg,
-  sqlite3_value **apArg
-){
-}
-static void leadValueFunc(sqlite3_context *pCtx){
-}
-
-static void lagStepFunc(
-  sqlite3_context *pCtx, 
-  int nArg,
-  sqlite3_value **apArg
-){
-}
-static void lagInverseFunc(
-  sqlite3_context *pCtx, 
-  int nArg,
-  sqlite3_value **apArg
-){
-}
-static void lagValueFunc(sqlite3_context *pCtx){
-}
+/*
+** No-op implementations of nth_value(), first_value(), lead() and lag().
+** These are all implemented inline using VDBE instructions. 
+*/
+static void nth_valueStepFunc(sqlite3_context *pCtx, int n, sqlite3_value **a){}
+static void nth_valueInvFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){}
+static void nth_valueValueFunc(sqlite3_context *pCtx){}
+static void first_valueStepFunc(sqlite3_context *p, int n, sqlite3_value **ap){}
+static void first_valueInvFunc(sqlite3_context *p, int n, sqlite3_value **ap){}
+static void first_valueValueFunc(sqlite3_context *pCtx){}
+static void leadStepFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){}
+static void leadInvFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){}
+static void leadValueFunc(sqlite3_context *pCtx){}
+static void lagStepFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){}
+static void lagInvFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){}
+static void lagValueFunc(sqlite3_context *pCtx){}
 
 #define WINDOWFUNC(name,nArg,extra) {                                      \
   nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,                      \
   name ## StepFunc, name ## ValueFunc, name ## ValueFunc,                  \
-  name ## InverseFunc, #name                                               \
+  name ## InvFunc, #name                                               \
 }
 
 #define WINDOWFUNCF(name,nArg,extra) {                                     \
   nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,                      \
   name ## StepFunc, name ## FinalizeFunc, name ## ValueFunc,               \
-  name ## InverseFunc, #name                                               \
+  name ## InvFunc, #name                                               \
 }
 
 /*
@@ -437,6 +401,7 @@
       pWin->eEnd = TK_CURRENT;
     }
   }
+  pWin->pFunc = pFunc;
 }
 
 typedef struct WindowRewrite WindowRewrite;
@@ -462,7 +427,7 @@
         Window *pWin;
         for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){
           if( pExpr->pWin==pWin ){
-            pExpr->pWin->pOwner = pExpr;
+            assert( pWin->pOwner==pExpr );
             return WRC_Prune;
           }
         }
@@ -684,6 +649,7 @@
 void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
   if( p ){
     p->pWin = pWin;
+    if( pWin ) pWin->pOwner = p;
   }else{
     sqlite3WindowDelete(pParse->db, pWin);
   }
@@ -766,6 +732,11 @@
   sqlite3VdbeAppendP4(v, (void*)azErr[bEnd], P4_STATIC);
 }
 
+static int windowArgCount(Window *pWin){
+  ExprList *pList = pWin->pOwner->x.pList;
+  return (pList ? pList->nExpr : 0);
+}
+
 /*
 ** Generate VM code to invoke either xStep() (if bInverse is 0) or 
 ** xInverse (if bInverse is non-zero) for each window function in the 
@@ -784,11 +755,11 @@
   for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
     int flags = pWin->pFunc->funcFlags;
     int regArg;
-    int nArg = pWin->nArg;
+    int nArg = windowArgCount(pWin);
 
     if( csr>=0 ){
       int i;
-      for(i=0; i<pWin->nArg; i++){
+      for(i=0; i<nArg; i++){
         sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i);
       }
       regArg = reg;
@@ -832,11 +803,12 @@
       int addrIf = 0;
       if( pWin->pFilter ){
         int regTmp;
+        assert( nArg==pWin->pOwner->x.pList->nExpr );
         if( csr>0 ){
           regTmp = sqlite3GetTempReg(pParse);
-          sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+pWin->nArg,regTmp);
+          sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
         }else{
-          regTmp = regArg + pWin->nArg;
+          regTmp = regArg + nArg;
         }
         addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
         if( csr>0 ){
@@ -876,7 +848,7 @@
       if( bFinal==0 ){
         sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
       }
-      sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, pWin->nArg);
+      sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, windowArgCount(pWin));
       sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
       if( bFinal ){
         sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult);
@@ -975,18 +947,19 @@
       sqlite3ReleaseTempReg(pParse, tmpReg);
     }
     else if( pFunc->xSFunc==leadStepFunc || pFunc->xSFunc==lagStepFunc ){
+      int nArg = pWin->pOwner->x.pList->nExpr;
       int iEph = pWin->iEphCsr;
       int csr = pWin->csrApp;
       int lbl = sqlite3VdbeMakeLabel(v);
       int tmpReg = sqlite3GetTempReg(pParse);
 
-      if( pWin->nArg<3 ){
+      if( nArg<3 ){
         sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
       }else{
         sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+2, pWin->regResult);
       }
       sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg);
-      if( pWin->nArg<2 ){
+      if( nArg<2 ){
         int val = (pFunc->xSFunc==leadStepFunc ? 1 : -1);
         sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val);
       }else{
@@ -1036,7 +1009,7 @@
   Window *pWin;
   for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
     sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
-    nArg = MAX(nArg, pWin->nArg);
+    nArg = MAX(nArg, windowArgCount(pWin));
     if( pWin->pFunc->xSFunc==nth_valueStepFunc
      || pWin->pFunc->xSFunc==first_valueStepFunc 
     ){
@@ -1663,7 +1636,7 @@
   sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1);
 }
 
-Window *sqlite3WindowDup(sqlite3 *db, Window *p){
+Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
   Window *pNew = 0;
   if( p ){
     pNew = sqlite3DbMallocZero(db, sizeof(Window));
@@ -1676,77 +1649,30 @@
       pNew->eStart = p->eStart;
       pNew->pStart = sqlite3ExprDup(db, pNew->pStart, 0);
       pNew->pEnd = sqlite3ExprDup(db, pNew->pEnd, 0);
+      pNew->pOwner = pOwner;
     }
   }
   return pNew;
 }
 
 /*
-** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
-**
-**   As above, except take no action for a "new peer". Invoke
-**   the sub-routine once only for each partition.
-**
-** RANGE BETWEEN CURRENT ROW AND CURRENT ROW
-**
-**   As above, except that the "new peer" condition is handled in the
-**   same way as "new partition" (so there is no "else if" block).
-**
-** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
-**
-**   One way is to just reverse the sort order and do as for BETWEEN 
-**   UNBOUNDED PRECEDING AND CURRENT ROW. But that is not quite the same for
-**   things like group_concat(). And perhaps other user defined aggregates 
-**   as well.
-**
-**   ...
-**     if( new partition ){
-**       Gosub flush_partition;
-**       ResetSorter eph-table
-**     }
-**     AggStep
-**     Insert (record into eph-table)
-**   sqlite3WhereEnd()
-**   Gosub flush_partition
-**
-**  flush_partition:
-**   OpenDup (csr -> csr2)
-**   foreach (record in eph-table) {
-**     if( new peer ){
-**       while( csr2!=csr ){
-**         AggStep (xInverse)
-**         Next (csr2)
-**       }
-**     }
-**     AggFinal (xValue)
-**     Gosub addrGosub
-**   }
-**
-**========================================================================
-**
-** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
-**   ...
-**     if( new partition ){
-**       AggFinal (xFinalize)
-**     }
-**     AggStep
-**     AggFinal (xValue)
-**     Gosub addrGosub
-**   sqlite3WhereEnd()
-**
+** sqlite3WhereBegin() has already been called for the SELECT statement 
+** passed as the second argument when this function is invoked. It generates
+** code to populate the Window.regResult register for each window function and
+** invoke the sub-routine at instruction addrGosub once for each row.
+** This function calls sqlite3WhereEnd() before returning. 
 */
 void sqlite3WindowCodeStep(
-  Parse *pParse, 
-  Select *p,
-  WhereInfo *pWInfo,
-  int regGosub, 
-  int addrGosub
+  Parse *pParse,                  /* Parse context */
+  Select *p,                      /* Rewritten SELECT statement */
+  WhereInfo *pWInfo,              /* Context returned by sqlite3WhereBegin() */
+  int regGosub,                   /* Register for OP_Gosub */
+  int addrGosub                   /* OP_Gosub here to return each row */
 ){
   Window *pMWin = p->pWin;
   Window *pWin;
 
-  /*
-  ** Call windowCodeRowExprStep() for all window modes *except*:
+  /* Call windowCodeRowExprStep() for all window modes *except*:
   **
   **   RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
   **   RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
@@ -1761,11 +1687,9 @@
     return;
   }
 
-  /*
-  ** Call windowCodeCacheStep() if there is a window function that requires
+  /* 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.
-  */
+  ** are returned.  */
   for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
     FuncDef *pFunc = pWin->pFunc;
     if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE)
@@ -1779,6 +1703,7 @@
     }
   }
 
+  /* Otherwise, call windowCodeDefaultStep().  */
   windowCodeDefaultStep(pParse, p, pWInfo, regGosub, addrGosub);
 }