/ Check-in [410e13b0]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Identify specific FuncDef objects for window functions using the pointer to the function name (FuncDef.zName) rather than the pointer to the xStep method. This allows xStep method pointer to be replaced with a single noopStepFunc() procedure, and thus save having lots of different no-op step functions.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 410e13b0e0fb6e040808f076014d55ecf2b541c5439b4fd53c5bdcb8d800098e
User & Date: drh 2018-07-08 01:02:26
Context
2018-07-09
02:02
During WITHOUT ROWID table creation, if the sqlite3CreateTable() call fails due to an authorizer denying the INSERT into the sqlite_master table, then detect this fact and abort the CREATE TABLE early, to avoid an assertion fault. check-in: 164b1641 user: drh tags: trunk
2018-07-08
01:02
Identify specific FuncDef objects for window functions using the pointer to the function name (FuncDef.zName) rather than the pointer to the xStep method. This allows xStep method pointer to be replaced with a single noopStepFunc() procedure, and thus save having lots of different no-op step functions. check-in: 410e13b0 user: drh tags: trunk
2018-07-07
20:55
Simplifications to the implementation of the sum() SQL function. check-in: a8b13002 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/window.c.

   148    148     sqlite3_context *pCtx, 
   149    149     int nArg,
   150    150     sqlite3_value **apArg
   151    151   ){
   152    152     i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p));
   153    153     if( p ) (*p)++;
   154    154   }
   155         -static void row_numberInvFunc(
   156         -  sqlite3_context *pCtx, 
   157         -  int nArg,
   158         -  sqlite3_value **apArg
   159         -){
   160         -}
   161    155   static void row_numberValueFunc(sqlite3_context *pCtx){
   162    156     i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p));
   163    157     sqlite3_result_int64(pCtx, (p ? *p : 0));
   164    158   }
   165    159   
   166    160   /*
   167    161   ** Context object type used by rank(), dense_rank(), percent_rank() and
................................................................................
   184    178     int nArg,
   185    179     sqlite3_value **apArg
   186    180   ){
   187    181     struct CallCount *p;
   188    182     p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
   189    183     if( p ) p->nStep = 1;
   190    184   }
   191         -static void dense_rankInvFunc(
   192         -  sqlite3_context *pCtx, 
   193         -  int nArg,
   194         -  sqlite3_value **apArg
   195         -){
   196         -}
   197    185   static void dense_rankValueFunc(sqlite3_context *pCtx){
   198    186     struct CallCount *p;
   199    187     p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
   200    188     if( p ){
   201    189       if( p->nStep ){
   202    190         p->nValue++;
   203    191         p->nStep = 0;
................................................................................
   222    210     if( p ){
   223    211       p->nStep++;
   224    212       if( p->nValue==0 ){
   225    213         p->nValue = p->nStep;
   226    214       }
   227    215     }
   228    216   }
   229         -static void rankInvFunc(
   230         -  sqlite3_context *pCtx, 
   231         -  int nArg,
   232         -  sqlite3_value **apArg
   233         -){
   234         -}
   235    217   static void rankValueFunc(sqlite3_context *pCtx){
   236    218     struct CallCount *p;
   237    219     p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
   238    220     if( p ){
   239    221       sqlite3_result_int64(pCtx, p->nValue);
   240    222       p->nValue = 0;
   241    223     }
................................................................................
   262    244       }
   263    245       p->nStep++;
   264    246       if( p->nValue==0 ){
   265    247         p->nValue = p->nStep;
   266    248       }
   267    249     }
   268    250   }
   269         -static void percent_rankInvFunc(
   270         -  sqlite3_context *pCtx, 
   271         -  int nArg,
   272         -  sqlite3_value **apArg
   273         -){
   274         -}
   275    251   static void percent_rankValueFunc(sqlite3_context *pCtx){
   276    252     struct CallCount *p;
   277    253     p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
   278    254     if( p ){
   279    255       if( p->nTotal>1 ){
   280    256         double r = (double)(p->nValue-1) / (double)(p->nTotal-1);
   281    257         sqlite3_result_double(pCtx, r);
................................................................................
   304    280     if( p ){
   305    281       if( p->nTotal==0 ){
   306    282         p->nTotal = sqlite3_value_int64(apArg[0]);
   307    283       }
   308    284       p->nStep++;
   309    285     }
   310    286   }
   311         -static void cume_distInvFunc(
   312         -  sqlite3_context *pCtx, 
   313         -  int nArg,
   314         -  sqlite3_value **apArg
   315         -){
   316         -}
   317    287   static void cume_distValueFunc(sqlite3_context *pCtx){
   318    288     struct CallCount *p;
   319    289     p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
   320    290     if( p && p->nTotal ){
   321    291       double r = (double)(p->nStep) / (double)(p->nTotal);
   322    292       sqlite3_result_double(pCtx, r);
   323    293     }
................................................................................
   355    325               pCtx, "argument of ntile must be a positive integer", -1
   356    326           );
   357    327         }
   358    328       }
   359    329       p->iRow++;
   360    330     }
   361    331   }
   362         -static void ntileInvFunc(
   363         -  sqlite3_context *pCtx, 
   364         -  int nArg,
   365         -  sqlite3_value **apArg
   366         -){
   367         -}
   368    332   static void ntileValueFunc(sqlite3_context *pCtx){
   369    333     struct NtileCtx *p;
   370    334     p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
   371    335     if( p && p->nParam>0 ){
   372    336       int nSize = (p->nTotal / p->nParam);
   373    337       if( nSize==0 ){
   374    338         sqlite3_result_int64(pCtx, p->iRow);
................................................................................
   445    409       sqlite3_result_value(pCtx, p->pVal);
   446    410       sqlite3_value_free(p->pVal);
   447    411       p->pVal = 0;
   448    412     }
   449    413   }
   450    414   
   451    415   /*
   452         -** No-op implementations of nth_value(), first_value(), lead() and lag().
   453         -** These are all implemented inline using VDBE instructions. 
   454         -*/
   455         -static void nth_valueStepFunc(sqlite3_context *pCtx, int n, sqlite3_value **a){}
   456         -static void nth_valueInvFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){}
   457         -static void nth_valueValueFunc(sqlite3_context *pCtx){}
   458         -static void first_valueStepFunc(sqlite3_context *p, int n, sqlite3_value **ap){}
   459         -static void first_valueInvFunc(sqlite3_context *p, int n, sqlite3_value **ap){}
   460         -static void first_valueValueFunc(sqlite3_context *pCtx){}
   461         -static void leadStepFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){}
   462         -static void leadInvFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){}
   463         -static void leadValueFunc(sqlite3_context *pCtx){}
   464         -static void lagStepFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){}
   465         -static void lagInvFunc(sqlite3_context *pCtx, int n, sqlite3_value **ap){}
   466         -static void lagValueFunc(sqlite3_context *pCtx){}
   467         -
   468         -#define WINDOWFUNC(name,nArg,extra) {                                      \
   469         -  nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,                      \
   470         -  name ## StepFunc, name ## ValueFunc, name ## ValueFunc,                  \
   471         -  name ## InvFunc, #name                                               \
   472         -}
   473         -
   474         -#define WINDOWFUNCF(name,nArg,extra) {                                     \
          416  +** Static names for the built-in window function names.  These static
          417  +** names are used, rather than string literals, so that FuncDef objects
          418  +** can be associated with a particular window function by direct
          419  +** comparison of the zName pointer.  Example:
          420  +**
          421  +**       if( pFuncDef->zName==row_valueName ){ ... }
          422  +*/
          423  +static const char row_numberName[] =   "row_number";
          424  +static const char dense_rankName[] =   "dense_rank";
          425  +static const char rankName[] =         "rank";
          426  +static const char percent_rankName[] = "percent_rank";
          427  +static const char cume_distName[] =    "cume_dist";
          428  +static const char ntileName[] =        "ntile";
          429  +static const char last_valueName[] =   "last_value";
          430  +static const char nth_valueName[] =    "nth_value";
          431  +static const char first_valueName[] =  "first_value";
          432  +static const char leadName[] =         "lead";
          433  +static const char lagName[] =          "lag";
          434  +
          435  +/*
          436  +** No-op implementations of xStep() and xFinalize().  Used as place-holders
          437  +** for built-in window functions that never call those interfaces.
          438  +**
          439  +** The noopValueFunc() is called but is expected to do nothing.  The
          440  +** noopStepFunc() is never called, and so it is marked with NO_TEST to
          441  +** let the test coverage routine know not to expect this function to be
          442  +** invoked.
          443  +*/
          444  +static void noopStepFunc(    /*NO_TEST*/
          445  +  sqlite3_context *p,        /*NO_TEST*/
          446  +  int n,                     /*NO_TEST*/
          447  +  sqlite3_value **a          /*NO_TEST*/
          448  +){                           /*NO_TEST*/
          449  +  assert(0);                 /*NO_TEST*/
          450  +}                            /*NO_TEST*/
          451  +static void noopValueFunc(sqlite3_context *p){ /*no-op*/; }
          452  +
          453  +/* Window functions that use all window interfaces: xStep, xFinal,
          454  +** xValue, and xInverse */
          455  +#define WINDOWFUNCALL(name,nArg,extra) {                                   \
   475    456     nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,                      \
   476    457     name ## StepFunc, name ## FinalizeFunc, name ## ValueFunc,               \
   477         -  name ## InvFunc, #name                                               \
          458  +  name ## InvFunc, name ## Name                                            \
   478    459   }
          460  +
          461  +/* Window functions that are implemented using bytecode and thus have
          462  +** no-op routines for their methods */
          463  +#define WINDOWFUNCNOOP(name,nArg,extra) {                                  \
          464  +  nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,                      \
          465  +  noopStepFunc, noopValueFunc, noopValueFunc,                              \
          466  +  noopStepFunc, name ## Name                                               \
          467  +}
          468  +
          469  +/* Window functions that use all window interfaces: xStep, the
          470  +** same routine for xFinalize and xValue and which never call
          471  +** xInverse. */
          472  +#define WINDOWFUNCX(name,nArg,extra) {                                     \
          473  +  nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,                      \
          474  +  name ## StepFunc, name ## ValueFunc, name ## ValueFunc,                  \
          475  +  noopStepFunc, name ## Name                                               \
          476  +}
          477  +
   479    478   
   480    479   /*
   481    480   ** Register those built-in window functions that are not also aggregates.
   482    481   */
   483    482   void sqlite3WindowFunctions(void){
   484    483     static FuncDef aWindowFuncs[] = {
   485         -    WINDOWFUNC(row_number, 0, 0),
   486         -    WINDOWFUNC(dense_rank, 0, 0),
   487         -    WINDOWFUNC(rank, 0, 0),
   488         -    WINDOWFUNC(percent_rank, 0, SQLITE_FUNC_WINDOW_SIZE),
   489         -    WINDOWFUNC(cume_dist, 0, SQLITE_FUNC_WINDOW_SIZE),
   490         -    WINDOWFUNC(ntile, 1, SQLITE_FUNC_WINDOW_SIZE),
   491         -    WINDOWFUNCF(last_value, 1, 0),
   492         -    WINDOWFUNC(nth_value, 2, 0),
   493         -    WINDOWFUNC(first_value, 1, 0),
   494         -    WINDOWFUNC(lead, 1, 0), WINDOWFUNC(lead, 2, 0), WINDOWFUNC(lead, 3, 0),
   495         -    WINDOWFUNC(lag, 1, 0),  WINDOWFUNC(lag, 2, 0),  WINDOWFUNC(lag, 3, 0),
          484  +    WINDOWFUNCX(row_number, 0, 0),
          485  +    WINDOWFUNCX(dense_rank, 0, 0),
          486  +    WINDOWFUNCX(rank, 0, 0),
          487  +    WINDOWFUNCX(percent_rank, 0, SQLITE_FUNC_WINDOW_SIZE),
          488  +    WINDOWFUNCX(cume_dist, 0, SQLITE_FUNC_WINDOW_SIZE),
          489  +    WINDOWFUNCX(ntile, 1, SQLITE_FUNC_WINDOW_SIZE),
          490  +    WINDOWFUNCALL(last_value, 1, 0),
          491  +    WINDOWFUNCNOOP(nth_value, 2, 0),
          492  +    WINDOWFUNCNOOP(first_value, 1, 0),
          493  +    WINDOWFUNCNOOP(lead, 1, 0),
          494  +    WINDOWFUNCNOOP(lead, 2, 0),
          495  +    WINDOWFUNCNOOP(lead, 3, 0),
          496  +    WINDOWFUNCNOOP(lag, 1, 0),
          497  +    WINDOWFUNCNOOP(lag, 2, 0),
          498  +    WINDOWFUNCNOOP(lag, 3, 0),
   496    499     };
   497    500     sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs));
   498    501   }
   499    502   
   500    503   /*
   501    504   ** This function is called immediately after resolving the function name
   502    505   ** for a window function within a SELECT statement. Argument pList is a
................................................................................
   540    543     if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){
   541    544       sqlite3 *db = pParse->db;
   542    545       if( pWin->pFilter ){
   543    546         sqlite3ErrorMsg(pParse, 
   544    547             "FILTER clause may only be used with aggregate window functions"
   545    548         );
   546    549       }else
   547         -    if( pFunc->xSFunc==row_numberStepFunc || pFunc->xSFunc==ntileStepFunc ){
          550  +    if( pFunc->zName==row_numberName || pFunc->zName==ntileName ){
   548    551         sqlite3ExprDelete(db, pWin->pStart);
   549    552         sqlite3ExprDelete(db, pWin->pEnd);
   550    553         pWin->pStart = pWin->pEnd = 0;
   551    554         pWin->eType = TK_ROWS;
   552    555         pWin->eStart = TK_UNBOUNDED;
   553    556         pWin->eEnd = TK_CURRENT;
   554    557       }else
   555    558   
   556         -    if( pFunc->xSFunc==dense_rankStepFunc || pFunc->xSFunc==rankStepFunc
   557         -     || pFunc->xSFunc==percent_rankStepFunc || pFunc->xSFunc==cume_distStepFunc
          559  +    if( pFunc->zName==dense_rankName || pFunc->zName==rankName
          560  +     || pFunc->zName==percent_rankName || pFunc->zName==cume_distName
   558    561       ){
   559    562         sqlite3ExprDelete(db, pWin->pStart);
   560    563         sqlite3ExprDelete(db, pWin->pEnd);
   561    564         pWin->pStart = pWin->pEnd = 0;
   562    565         pWin->eType = TK_RANGE;
   563    566         pWin->eStart = TK_UNBOUNDED;
   564    567         pWin->eEnd = TK_CURRENT;
................................................................................
   977    980           assert( pKeyInfo->aSortOrder[0]==0 );
   978    981           pKeyInfo->aSortOrder[0] = 1;
   979    982         }
   980    983         sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2);
   981    984         sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO);
   982    985         sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1);
   983    986       }
   984         -    else if( p->xSFunc==nth_valueStepFunc || p->xSFunc==first_valueStepFunc ){
          987  +    else if( p->zName==nth_valueName || p->zName==first_valueName ){
   985    988         /* Allocate two registers at pWin->regApp. These will be used to
   986    989         ** store the start and end index of the current frame.  */
   987    990         assert( pMWin->iEphCsr );
   988    991         pWin->regApp = pParse->nMem+1;
   989    992         pWin->csrApp = pParse->nTab++;
   990    993         pParse->nMem += 2;
   991    994         sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr);
   992    995       }
   993         -    else if( p->xSFunc==leadStepFunc || p->xSFunc==lagStepFunc ){
          996  +    else if( p->zName==leadName || p->zName==lagName ){
   994    997         assert( pMWin->iEphCsr );
   995    998         pWin->csrApp = pParse->nTab++;
   996    999         sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr);
   997   1000       }
   998   1001     }
   999   1002   }
  1000   1003   
................................................................................
  1097   1100           sqlite3VdbeAddOp4Int(v, OP_SeekGE, pWin->csrApp, 0, regArg, 1);
  1098   1101           VdbeCoverage(v);
  1099   1102           sqlite3VdbeAddOp1(v, OP_Delete, pWin->csrApp);
  1100   1103           sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
  1101   1104         }
  1102   1105         sqlite3VdbeJumpHere(v, addrIsNull);
  1103   1106       }else if( pWin->regApp ){
  1104         -      assert( pWin->pFunc->xSFunc==nth_valueStepFunc 
  1105         -           || pWin->pFunc->xSFunc==first_valueStepFunc 
         1107  +      assert( pWin->pFunc->zName==nth_valueName
         1108  +           || pWin->pFunc->zName==first_valueName
  1106   1109         );
  1107   1110         assert( bInverse==0 || bInverse==1 );
  1108   1111         sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1);
  1109         -    }else if( pWin->pFunc->xSFunc==leadStepFunc 
  1110         -           || pWin->pFunc->xSFunc==lagStepFunc 
         1112  +    }else if( pWin->pFunc->zName==leadName
         1113  +           || pWin->pFunc->zName==lagName
  1111   1114       ){
  1112   1115         /* no-op */
  1113   1116       }else{
  1114   1117         int addrIf = 0;
  1115   1118         if( pWin->pFilter ){
  1116   1119           int regTmp;
  1117   1120           assert( nArg==pWin->pOwner->x.pList->nExpr );
................................................................................
  1259   1262     int regGosub,
  1260   1263     int addrGosub
  1261   1264   ){
  1262   1265     Vdbe *v = sqlite3GetVdbe(pParse);
  1263   1266     Window *pWin;
  1264   1267     for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
  1265   1268       FuncDef *pFunc = pWin->pFunc;
  1266         -    if( pFunc->xSFunc==nth_valueStepFunc 
  1267         -     || pFunc->xSFunc==first_valueStepFunc 
         1269  +    if( pFunc->zName==nth_valueName
         1270  +     || pFunc->zName==first_valueName
  1268   1271       ){
  1269   1272         int csr = pWin->csrApp;
  1270   1273         int lbl = sqlite3VdbeMakeLabel(v);
  1271   1274         int tmpReg = sqlite3GetTempReg(pParse);
  1272   1275         sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
  1273   1276   
  1274         -      if( pFunc->xSFunc==nth_valueStepFunc ){
         1277  +      if( pFunc->zName==nth_valueName ){
  1275   1278           sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+1,tmpReg);
  1276   1279         }else{
  1277   1280           sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg);
  1278   1281         }
  1279   1282         sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg);
  1280   1283         sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg);
  1281   1284         VdbeCoverage(v);
  1282   1285         sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg);
  1283   1286         VdbeCoverage(v);
  1284   1287         sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult);
  1285   1288         sqlite3VdbeResolveLabel(v, lbl);
  1286   1289         sqlite3ReleaseTempReg(pParse, tmpReg);
  1287   1290       }
  1288         -    else if( pFunc->xSFunc==leadStepFunc || pFunc->xSFunc==lagStepFunc ){
         1291  +    else if( pFunc->zName==leadName || pFunc->zName==lagName ){
  1289   1292         int nArg = pWin->pOwner->x.pList->nExpr;
  1290   1293         int iEph = pMWin->iEphCsr;
  1291   1294         int csr = pWin->csrApp;
  1292   1295         int lbl = sqlite3VdbeMakeLabel(v);
  1293   1296         int tmpReg = sqlite3GetTempReg(pParse);
  1294   1297   
  1295   1298         if( nArg<3 ){
  1296   1299           sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
  1297   1300         }else{
  1298   1301           sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+2, pWin->regResult);
  1299   1302         }
  1300   1303         sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg);
  1301   1304         if( nArg<2 ){
  1302         -        int val = (pFunc->xSFunc==leadStepFunc ? 1 : -1);
         1305  +        int val = (pFunc->zName==leadName ? 1 : -1);
  1303   1306           sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val);
  1304   1307         }else{
  1305         -        int op = (pFunc->xSFunc==leadStepFunc ? OP_Add : OP_Subtract);
         1308  +        int op = (pFunc->zName==leadName ? OP_Add : OP_Subtract);
  1306   1309           int tmpReg2 = sqlite3GetTempReg(pParse);
  1307   1310           sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+1, tmpReg2);
  1308   1311           sqlite3VdbeAddOp3(v, op, tmpReg2, tmpReg, tmpReg);
  1309   1312           sqlite3ReleaseTempReg(pParse, tmpReg2);
  1310   1313         }
  1311   1314   
  1312   1315         sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg);
................................................................................
  1369   1372     int regArg;
  1370   1373     int nArg = 0;
  1371   1374     Window *pWin;
  1372   1375     for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
  1373   1376       FuncDef *pFunc = pWin->pFunc;
  1374   1377       sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
  1375   1378       nArg = MAX(nArg, windowArgCount(pWin));
  1376         -    if( pFunc->xSFunc==nth_valueStepFunc
  1377         -     || pFunc->xSFunc==first_valueStepFunc 
         1379  +    if( pFunc->zName==nth_valueName
         1380  +     || pFunc->zName==first_valueName
  1378   1381       ){
  1379   1382         sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp);
  1380   1383         sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1);
  1381   1384       }
  1382   1385   
  1383   1386       if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){
  1384   1387         assert( pWin->eStart!=TK_UNBOUNDED );
................................................................................
  2156   2159   
  2157   2160       if( pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED ){
  2158   2161         bCache = 1;
  2159   2162       }else{
  2160   2163         for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
  2161   2164           FuncDef *pFunc = pWin->pFunc;
  2162   2165           if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE)
  2163         -         || (pFunc->xSFunc==nth_valueStepFunc)
  2164         -         || (pFunc->xSFunc==first_valueStepFunc)
  2165         -         || (pFunc->xSFunc==leadStepFunc)
  2166         -         || (pFunc->xSFunc==lagStepFunc)
         2166  +         || (pFunc->zName==nth_valueName)
         2167  +         || (pFunc->zName==first_valueName)
         2168  +         || (pFunc->zName==leadName)
         2169  +         || (pFunc->zName==lagName)
  2167   2170           ){
  2168   2171             bCache = 1;
  2169   2172             break;
  2170   2173           }
  2171   2174         }
  2172   2175       }
  2173   2176