/ Check-in [5f04b016]
Login

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

Overview
Comment:Omit all window-function related code when building with SQLITE_OMIT_WINDOWFUNC.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | exp-window-functions
Files: files | file ages | folders
SHA3-256: 5f04b016467342b5a796bf702ed25b621eb86f2961c1e703d276c93f2cb6aa89
User & Date: dan 2018-06-22 20:51:35
Context
2018-06-23
07:59
Fix a problem with using a window-function SELECT as a FROM clause sub-query in some circumstances. check-in: 11d73339 user: dan tags: exp-window-functions
2018-06-22
20:51
Omit all window-function related code when building with SQLITE_OMIT_WINDOWFUNC. check-in: 5f04b016 user: dan tags: exp-window-functions
17:57
Merge latest trunk changes. check-in: ebe65b23 user: dan tags: exp-window-functions
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  5186   5186   }
  5187   5187   
  5188   5188   /*
  5189   5189   ** This function is a no-op if cursor pCur does not point to a valid row.
  5190   5190   ** Otherwise, if pCur is valid, configure it so that the next call to
  5191   5191   ** sqlite3BtreeNext() is a no-op.
  5192   5192   */
         5193  +#ifndef SQLITE_OMIT_WINDOWFUNC
  5193   5194   void sqlite3BtreeSkipNext(BtCursor *pCur){
  5194   5195     if( pCur->eState==CURSOR_VALID ){
  5195   5196       pCur->eState = CURSOR_SKIPNEXT;
  5196   5197       pCur->skipNext = 1;
  5197   5198     }
  5198   5199   }
         5200  +#endif /* SQLITE_OMIT_WINDOWFUNC */
  5199   5201   
  5200   5202   /* Move the cursor to the last entry in the table.  Return SQLITE_OK
  5201   5203   ** on success.  Set *pRes to 0 if the cursor actually points to something
  5202   5204   ** or set *pRes to 1 if the table is empty.
  5203   5205   */
  5204   5206   int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
  5205   5207     int rc;

Changes to src/btree.h.

   297    297     int nData;              /* Size of pData.  0 if none. */
   298    298     int nZero;              /* Extra zero data appended after pData,nData */
   299    299   };
   300    300   
   301    301   int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
   302    302                          int flags, int seekResult);
   303    303   int sqlite3BtreeFirst(BtCursor*, int *pRes);
          304  +#ifndef SQLITE_OMIT_WINDOWFUNC
   304    305   void sqlite3BtreeSkipNext(BtCursor*);
          306  +#endif
   305    307   int sqlite3BtreeLast(BtCursor*, int *pRes);
   306    308   int sqlite3BtreeNext(BtCursor*, int flags);
   307    309   int sqlite3BtreeEof(BtCursor*);
   308    310   int sqlite3BtreePrevious(BtCursor*, int flags);
   309    311   i64 sqlite3BtreeIntegerKey(BtCursor*);
   310    312   #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
   311    313   i64 sqlite3BtreeOffset(BtCursor*);

Changes to src/expr.c.

   768    768       }
   769    769     }
   770    770     pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra);
   771    771     if( pNew ){
   772    772       memset(pNew, 0, sizeof(Expr));
   773    773       pNew->op = (u8)op;
   774    774       pNew->iAgg = -1;
   775         -    pNew->pWin = 0;
   776    775       if( pToken ){
   777    776         if( nExtra==0 ){
   778    777           pNew->flags |= EP_IntValue|EP_Leaf;
   779    778           pNew->u.iValue = iValue;
   780    779         }else{
   781    780           pNew->u.zToken = (char*)&pNew[1];
   782    781           assert( pToken->z!=0 || pToken->n==0 );
................................................................................
   858    857       p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
   859    858     }else{
   860    859       p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr));
   861    860       if( p ){
   862    861         memset(p, 0, sizeof(Expr));
   863    862         p->op = op & TKFLG_MASK;
   864    863         p->iAgg = -1;
   865         -      p->pWin = 0;
   866    864       }
   867    865       sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
   868    866     }
   869    867     if( p ) {
   870    868       sqlite3ExprCheckHeight(pParse, p->nHeight);
   871    869     }
   872    870     return p;
................................................................................
  1124   1122   ** to enforce this constraint.
  1125   1123   */
  1126   1124   static int dupedExprStructSize(Expr *p, int flags){
  1127   1125     int nSize;
  1128   1126     assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
  1129   1127     assert( EXPR_FULLSIZE<=0xfff );
  1130   1128     assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
  1131         -  if( 0==flags || p->op==TK_SELECT_COLUMN || p->pWin ){
         1129  +  if( 0==flags || p->op==TK_SELECT_COLUMN 
         1130  +#ifndef SQLITE_OMIT_WINDOWFUNC
         1131  +   || p->pWin 
         1132  +#endif
         1133  +  ){
  1132   1134       nSize = EXPR_FULLSIZE;
  1133   1135     }else{
  1134   1136       assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
  1135   1137       assert( !ExprHasProperty(p, EP_FromJoin) ); 
  1136   1138       assert( !ExprHasProperty(p, EP_MemToken) );
  1137   1139       assert( !ExprHasProperty(p, EP_NoReduce) );
  1138   1140       if( p->pLeft || p->x.pList ){
................................................................................
  1264   1266           pNew->pRight = p->pRight ?
  1265   1267                          exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
  1266   1268         }
  1267   1269         if( pzBuffer ){
  1268   1270           *pzBuffer = zAlloc;
  1269   1271         }
  1270   1272       }else{
         1273  +#ifndef SQLITE_OMIT_WINDOWFUNC
  1271   1274         if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){
  1272   1275           pNew->pWin = 0;
  1273   1276         }else{
  1274   1277           pNew->pWin = sqlite3WindowDup(db, pNew, p->pWin);
  1275   1278         }
         1279  +#endif /* SQLITE_OMIT_WINDOWFUNC */
  1276   1280         if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
  1277   1281           if( pNew->op==TK_SELECT_COLUMN ){
  1278   1282             pNew->pLeft = p->pLeft;
  1279   1283             assert( p->iColumn==0 || p->pRight==0 );
  1280   1284             assert( p->pRight==0  || p->pRight==p->pLeft );
  1281   1285           }else{
  1282   1286             pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
................................................................................
  1475   1479       pNew->iLimit = 0;
  1476   1480       pNew->iOffset = 0;
  1477   1481       pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
  1478   1482       pNew->addrOpenEphm[0] = -1;
  1479   1483       pNew->addrOpenEphm[1] = -1;
  1480   1484       pNew->nSelectRow = p->nSelectRow;
  1481   1485       pNew->pWith = withDup(db, p->pWith);
         1486  +#ifndef SQLITE_OMIT_WINDOWFUNC
  1482   1487       pNew->pWin = 0;
  1483   1488       pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
         1489  +#endif
  1484   1490       sqlite3SelectSetName(pNew, p->zSelName);
  1485   1491       *pp = pNew;
  1486   1492       pp = &pNew->pPrior;
  1487   1493       pNext = pNew;
  1488   1494     }
  1489   1495   
  1490   1496     return pRet;
................................................................................
  3796   3802         const char *zId;       /* The function name */
  3797   3803         u32 constMask = 0;     /* Mask of function arguments that are constant */
  3798   3804         int i;                 /* Loop counter */
  3799   3805         sqlite3 *db = pParse->db;  /* The database connection */
  3800   3806         u8 enc = ENC(db);      /* The text encoding used by this database */
  3801   3807         CollSeq *pColl = 0;    /* A collating sequence */
  3802   3808   
         3809  +#ifndef SQLITE_OMIT_WINDOWFUNC
  3803   3810         if( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) && pExpr->pWin ){
  3804   3811           return pExpr->pWin->regResult;
  3805   3812         }
         3813  +#endif
  3806   3814   
  3807   3815         if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
  3808   3816           /* SQL functions can be expensive. So try to move constant functions
  3809   3817           ** out of the inner loop, even if that means an extra OP_Copy. */
  3810   3818           return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
  3811   3819         }
  3812   3820         assert( !ExprHasProperty(pExpr, EP_xIsSelect) );

Changes to src/func.c.

  1509   1509         }
  1510   1510       }else{
  1511   1511         p->rSum += sqlite3_value_double(argv[0]);
  1512   1512         p->approx = 1;
  1513   1513       }
  1514   1514     }
  1515   1515   }
         1516  +#ifndef SQLITE_OMIT_WINDOWFUNC
  1516   1517   static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
  1517   1518     SumCtx *p;
  1518   1519     int type;
  1519   1520     assert( argc==1 );
  1520   1521     UNUSED_PARAMETER(argc);
  1521   1522     p = sqlite3_aggregate_context(context, sizeof(*p));
  1522   1523     type = sqlite3_value_numeric_type(argv[0]);
................................................................................
  1530   1531         }
  1531   1532       }else{
  1532   1533         p->rSum += sqlite3_value_double(argv[0]);
  1533   1534         p->approx = 1;
  1534   1535       }
  1535   1536     }
  1536   1537   }
         1538  +#else
         1539  +# define sumInverse 0
         1540  +#endif /* SQLITE_OMIT_WINDOWFUNC */
  1537   1541   static void sumFinalize(sqlite3_context *context){
  1538   1542     SumCtx *p;
  1539   1543     p = sqlite3_aggregate_context(context, 0);
  1540   1544     if( p && p->cnt>0 ){
  1541   1545       if( p->overflow ){
  1542   1546         sqlite3_result_error(context,"integer overflow",-1);
  1543   1547       }else if( p->approx ){
................................................................................
  1642   1646     if( pRes ){
  1643   1647       if( pRes->flags ){
  1644   1648         sqlite3_result_value(context, pRes);
  1645   1649       }
  1646   1650       if( bValue==0 ) sqlite3VdbeMemRelease(pRes);
  1647   1651     }
  1648   1652   }
         1653  +#ifndef SQLITE_OMIT_WINDOWFUNC
  1649   1654   static void minMaxValue(sqlite3_context *context){
  1650   1655     return minMaxValueFinalize(context, 1);
  1651   1656   }
         1657  +#else
         1658  +# define minMaxValue 0
         1659  +#endif /* SQLITE_OMIT_WINDOWFUNC */
  1652   1660   static void minMaxFinalize(sqlite3_context *context){
  1653   1661     return minMaxValueFinalize(context, 0);
  1654   1662   }
  1655   1663   
  1656   1664   /*
  1657   1665   ** group_concat(EXPR, ?SEPARATOR?)
  1658   1666   */
................................................................................
  1684   1692         if( zSep ) sqlite3_str_append(pAccum, zSep, nSep);
  1685   1693       }
  1686   1694       zVal = (char*)sqlite3_value_text(argv[0]);
  1687   1695       nVal = sqlite3_value_bytes(argv[0]);
  1688   1696       if( zVal ) sqlite3_str_append(pAccum, zVal, nVal);
  1689   1697     }
  1690   1698   }
         1699  +#ifndef SQLITE_OMIT_WINDOWFUNC
  1691   1700   static void groupConcatInverse(
  1692   1701     sqlite3_context *context,
  1693   1702     int argc,
  1694   1703     sqlite3_value **argv
  1695   1704   ){
  1696   1705     int n;
  1697   1706     assert( argc==1 || argc==2 );
................................................................................
  1708   1717       }else{
  1709   1718         pAccum->nChar -= n;
  1710   1719         memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar);
  1711   1720       }
  1712   1721       if( pAccum->nChar==0 ) pAccum->mxAlloc = 0;
  1713   1722     }
  1714   1723   }
         1724  +#else
         1725  +# define groupConcatInverse 0
         1726  +#endif /* SQLITE_OMIT_WINDOWFUNC */
  1715   1727   static void groupConcatFinalize(sqlite3_context *context){
  1716   1728     StrAccum *pAccum;
  1717   1729     pAccum = sqlite3_aggregate_context(context, 0);
  1718   1730     if( pAccum ){
  1719   1731       if( pAccum->accError==SQLITE_TOOBIG ){
  1720   1732         sqlite3_result_error_toobig(context);
  1721   1733       }else if( pAccum->accError==SQLITE_NOMEM ){
................................................................................
  1722   1734         sqlite3_result_error_nomem(context);
  1723   1735       }else{    
  1724   1736         sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, 
  1725   1737                             sqlite3_free);
  1726   1738       }
  1727   1739     }
  1728   1740   }
         1741  +#ifndef SQLITE_OMIT_WINDOWFUNC
  1729   1742   static void groupConcatValue(sqlite3_context *context){
  1730   1743     sqlite3_str *pAccum;
  1731   1744     pAccum = (sqlite3_str*)sqlite3_aggregate_context(context, 0);
  1732   1745     if( pAccum ){
  1733   1746       if( pAccum->accError==SQLITE_TOOBIG ){
  1734   1747         sqlite3_result_error_toobig(context);
  1735   1748       }else if( pAccum->accError==SQLITE_NOMEM ){
................................................................................
  1736   1749         sqlite3_result_error_nomem(context);
  1737   1750       }else{    
  1738   1751         const char *zText = sqlite3_str_value(pAccum);
  1739   1752         sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
  1740   1753       }
  1741   1754     }
  1742   1755   }
         1756  +#else
         1757  +# define groupConcatValue 0
         1758  +#endif /* SQLITE_OMIT_WINDOWFUNC */
  1743   1759   
  1744   1760   /*
  1745   1761   ** This routine does per-connection function registration.  Most
  1746   1762   ** of the built-in functions above are part of the global function set.
  1747   1763   ** This routine only deals with those that are not global.
  1748   1764   */
  1749   1765   void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){

Changes to src/parse.y.

   525    525   }
   526    526   %type multiselect_op {int}
   527    527   multiselect_op(A) ::= UNION(OP).             {A = @OP; /*A-overwrites-OP*/}
   528    528   multiselect_op(A) ::= UNION ALL.             {A = TK_ALL;}
   529    529   multiselect_op(A) ::= EXCEPT|INTERSECT(OP).  {A = @OP; /*A-overwrites-OP*/}
   530    530   %endif SQLITE_OMIT_COMPOUND_SELECT
   531    531   oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y)
   532         -                 groupby_opt(P) having_opt(Q) windowdefn_opt(R)
          532  +                 groupby_opt(P) having_opt(Q) 
          533  +%ifndef SQLITE_OMIT_WINDOWFUNC
          534  +                 windowdefn_opt(R)
          535  +%endif
   533    536                    orderby_opt(Z) limit_opt(L). {
   534    537   #if SELECTTRACE_ENABLED
   535    538     Token s = S; /*A-overwrites-S*/
   536    539   #endif
   537    540     A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L);
          541  +#ifndef SQLITE_OMIT_WINDOWFUNC
   538    542     if( A ){
   539    543       A->pWinDefn = R;
   540    544     }else{
   541    545       sqlite3WindowListDelete(pParse->db, R);
   542    546     }
          547  +#endif // SQLITE_OMIT_WINDOWFUNC
   543    548   #if SELECTTRACE_ENABLED
   544    549     /* Populate the Select.zSelName[] string that is used to help with
   545    550     ** query planner debugging, to differentiate between multiple Select
   546    551     ** objects in a complex query.
   547    552     **
   548    553     ** If the SELECT keyword is immediately followed by a C-style comment
   549    554     ** then extract the first few alphanumeric characters from within that
................................................................................
  1007   1012   }
  1008   1013   %ifndef SQLITE_OMIT_CAST
  1009   1014   expr(A) ::= CAST LP expr(E) AS typetoken(T) RP. {
  1010   1015     A = sqlite3ExprAlloc(pParse->db, TK_CAST, &T, 1);
  1011   1016     sqlite3ExprAttachSubtrees(pParse->db, A, E, 0);
  1012   1017   }
  1013   1018   %endif  SQLITE_OMIT_CAST
  1014         -expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP over_opt(Z). {
         1019  +expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP 
         1020  +%ifndef SQLITE_OMIT_WINDOWFUNC
         1021  +  over_opt(Z)
         1022  +%endif
         1023  +. {
  1015   1024     if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
  1016   1025       sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X);
  1017   1026     }
  1018   1027     A = sqlite3ExprFunction(pParse, Y, &X);
  1019   1028     sqlite3WindowAttach(pParse, A, Z);
  1020   1029     if( D==SF_Distinct && A ){
  1021   1030       A->flags |= EP_Distinct;
  1022   1031     }
  1023   1032   }
  1024         -expr(A) ::= id(X) LP STAR RP over_opt(Z). {
         1033  +expr(A) ::= id(X) LP STAR RP
         1034  +%ifndef SQLITE_OMIT_WINDOWFUNC
         1035  +  over_opt(Z)
         1036  +%endif
         1037  +. {
  1025   1038     A = sqlite3ExprFunction(pParse, 0, &X);
  1026   1039     sqlite3WindowAttach(pParse, A, Z);
  1027   1040   }
  1028   1041   term(A) ::= CTIME_KW(OP). {
  1029   1042     A = sqlite3ExprFunction(pParse, 0, &OP);
  1030   1043   }
         1044  +
         1045  +%ifndef SQLITE_OMIT_WINDOWFUNC
  1031   1046   
  1032   1047   %type windowdefn_opt {Window*}
  1033   1048   %destructor windowdefn_opt {sqlite3WindowDelete(pParse->db, $$);}
  1034   1049   windowdefn_opt(A) ::= . { A = 0; }
  1035   1050   windowdefn_opt(A) ::= WINDOW windowdefn_list(B). { A = B; }
  1036   1051   
  1037   1052   %type windowdefn_list {Window*}
................................................................................
  1117   1132   
  1118   1133   frame_bound(A) ::= UNBOUNDED PRECEDING. { A.eType = TK_UNBOUNDED; A.pExpr = 0; }
  1119   1134   frame_bound(A) ::= expr(X) PRECEDING.   { A.eType = TK_PRECEDING; A.pExpr = X; }
  1120   1135   frame_bound(A) ::= CURRENT ROW.         { A.eType = TK_CURRENT  ; A.pExpr = 0; }
  1121   1136   frame_bound(A) ::= expr(X) FOLLOWING.   { A.eType = TK_FOLLOWING; A.pExpr = X; }
  1122   1137   frame_bound(A) ::= UNBOUNDED FOLLOWING. { A.eType = TK_UNBOUNDED; A.pExpr = 0; }
  1123   1138   
         1139  +%endif // SQLITE_OMIT_WINDOWFUNC
  1124   1140   
  1125   1141   expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. {
  1126   1142     ExprList *pList = sqlite3ExprListAppend(pParse, X, Y);
  1127   1143     A = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
  1128   1144     if( A ){
  1129   1145       A->x.pList = pList;
  1130   1146     }else{

Changes to src/resolve.c.

   753    753             ** sqlite_version() that might change over time cannot be used
   754    754             ** in an index. */
   755    755             notValid(pParse, pNC, "non-deterministic functions",
   756    756                      NC_IdxExpr|NC_PartIdx);
   757    757           }
   758    758         }
   759    759   
          760  +#ifndef SQLITE_OMIT_WINDOWFUNC
   760    761         if( is_agg==0 && pExpr->pWin ){
   761    762           sqlite3ErrorMsg(pParse, 
   762    763               "%.*s() may not be used as a window function", nId, zId
   763    764           );
   764    765           pNC->nErr++;
   765    766         }else if( 
   766    767               (is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
................................................................................
   769    770         ){
   770    771           const char *zType;
   771    772           if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){
   772    773             zType = "window";
   773    774           }else{
   774    775             zType = "aggregate";
   775    776           }
          777  +#else
          778  +      if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
          779  +        const char *zType = "aggregate";
          780  +#endif
   776    781           sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()", zType, nId,zId);
   777    782           pNC->nErr++;
   778    783           is_agg = 0;
   779    784         }else if( no_such_func && pParse->db->init.busy==0
   780    785   #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
   781    786                   && pParse->explain==0
   782    787   #endif
................................................................................
   787    792           sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
   788    793                nId, zId);
   789    794           pNC->nErr++;
   790    795         }
   791    796         if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
   792    797         sqlite3WalkExprList(pWalker, pList);
   793    798         if( is_agg ){
          799  +#ifndef SQLITE_OMIT_WINDOWFUNC
   794    800           if( pExpr->pWin ){
   795    801             Select *pSel = pNC->pWinSelect;
   796    802             sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->pWin, pDef);
   797    803             if( 0==pSel->pWin 
   798    804              || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->pWin) 
   799    805             ){
   800    806               pExpr->pWin->pNextWin = pSel->pWin;
   801    807               pSel->pWin = pExpr->pWin;
   802    808             }
   803         -        }else{
          809  +        }else
          810  +#endif /* SQLITE_OMIT_WINDOWFUNC */
          811  +        {
   804    812             NameContext *pNC2 = pNC;
   805    813             pExpr->op = TK_AGG_FUNCTION;
   806    814             pExpr->op2 = 0;
   807    815             while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
   808    816               pExpr->op2++;
   809    817               pNC2 = pNC2->pNext;
   810    818             }
................................................................................
  1260   1268       return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
  1261   1269     }
  1262   1270   
  1263   1271     isCompound = p->pPrior!=0;
  1264   1272     nCompound = 0;
  1265   1273     pLeftmost = p;
  1266   1274     while( p ){
  1267         -    assert( p->pWin==0 );
  1268   1275       assert( (p->selFlags & SF_Expanded)!=0 );
  1269   1276       assert( (p->selFlags & SF_Resolved)==0 );
  1270   1277       p->selFlags |= SF_Resolved;
  1271   1278   
  1272   1279       /* Resolve the expressions in the LIMIT and OFFSET clauses. These
  1273   1280       ** are not allowed to refer to any names, so pass an empty NameContext.
  1274   1281       */

Changes to src/select.c.

    92     92       sqlite3ExprListDelete(db, p->pEList);
    93     93       sqlite3SrcListDelete(db, p->pSrc);
    94     94       sqlite3ExprDelete(db, p->pWhere);
    95     95       sqlite3ExprListDelete(db, p->pGroupBy);
    96     96       sqlite3ExprDelete(db, p->pHaving);
    97     97       sqlite3ExprListDelete(db, p->pOrderBy);
    98     98       sqlite3ExprDelete(db, p->pLimit);
           99  +#ifndef SQLITE_OMIT_WINDOWFUNC
    99    100       if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){
   100    101         sqlite3WindowListDelete(db, p->pWinDefn);
   101    102       }
          103  +#endif
   102    104       if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
   103    105       if( bFree ) sqlite3DbFreeNN(db, p);
   104    106       p = pPrior;
   105    107       bFree = 1;
   106    108     }
   107    109   }
   108    110   
................................................................................
   161    163     pNew->pGroupBy = pGroupBy;
   162    164     pNew->pHaving = pHaving;
   163    165     pNew->pOrderBy = pOrderBy;
   164    166     pNew->pPrior = 0;
   165    167     pNew->pNext = 0;
   166    168     pNew->pLimit = pLimit;
   167    169     pNew->pWith = 0;
          170  +#ifndef SQLITE_OMIT_WINDOWFUNC
   168    171     pNew->pWin = 0;
   169    172     pNew->pWinDefn = 0;
          173  +#endif
   170    174     if( pParse->db->mallocFailed ) {
   171    175       clearSelect(pParse->db, pNew, pNew!=&standin);
   172    176       pNew = 0;
   173    177     }else{
   174    178       assert( pNew->pSrc!=0 || pParse->nErr>0 );
   175    179     }
   176    180     assert( pNew!=&standin );
................................................................................
  3716   3720     pSrc = p->pSrc;
  3717   3721     assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
  3718   3722     pSubitem = &pSrc->a[iFrom];
  3719   3723     iParent = pSubitem->iCursor;
  3720   3724     pSub = pSubitem->pSelect;
  3721   3725     assert( pSub!=0 );
  3722   3726   
         3727  +#ifndef SQLITE_OMIT_WINDOWFUNC
  3723   3728     if( p->pWin || pSub->pWin ) return 0;                  /* Restriction (25) */
         3729  +#endif
  3724   3730   
  3725   3731     pSubSrc = pSub->pSrc;
  3726   3732     assert( pSubSrc );
  3727   3733     /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
  3728   3734     ** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET
  3729   3735     ** because they could be computed at compile-time.  But when LIMIT and OFFSET
  3730   3736     ** became arbitrary expressions, we were forced to add restrictions (13)
................................................................................
  5483   5489     }
  5484   5490   #endif
  5485   5491   
  5486   5492     if( pDest->eDest==SRT_Output ){
  5487   5493       generateColumnNames(pParse, p);
  5488   5494     }
  5489   5495   
  5490         -  if( (rc = sqlite3WindowRewrite(pParse, p)) ){
         5496  +#ifndef SQLITE_OMIT_WINDOWFUNC
         5497  +  if( sqlite3WindowRewrite(pParse, p) ){
  5491   5498       goto select_end;
  5492   5499     }
  5493   5500   #if SELECTTRACE_ENABLED
  5494   5501     if( sqlite3SelectTrace & 0x108 ){
  5495   5502       SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
  5496   5503       sqlite3TreeViewSelect(0, p, 0);
  5497   5504     }
  5498   5505   #endif
         5506  +#endif /* SQLITE_OMIT_WINDOWFUNC */
  5499   5507     pTabList = p->pSrc;
  5500   5508     isAgg = (p->selFlags & SF_Aggregate)!=0;
  5501   5509   
  5502   5510     /* Try to various optimizations (flattening subqueries, and strength
  5503   5511     ** reduction of join operators) in the FROM clause up into the main query
  5504   5512     */
  5505   5513   #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
................................................................................
  5869   5877       sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
  5870   5878       sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
  5871   5879     }else{
  5872   5880       sDistinct.eTnctType = WHERE_DISTINCT_NOOP;
  5873   5881     }
  5874   5882   
  5875   5883     if( !isAgg && pGroupBy==0 ){
  5876         -    Window *pWin = p->pWin;      /* Master window object (or NULL) */
  5877         -
  5878   5884       /* No aggregate functions and no GROUP BY clause */
  5879         -    u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
  5880         -    assert( WHERE_USE_LIMIT==SF_FixedLimit );
  5881         -    wctrlFlags |= p->selFlags & SF_FixedLimit;
  5882         -
         5885  +    u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0)
         5886  +                   | (p->selFlags & SF_FixedLimit);
         5887  +#ifndef SQLITE_OMIT_WINDOWFUNC
         5888  +    Window *pWin = p->pWin;      /* Master window object (or NULL) */
  5883   5889       if( pWin ){
  5884   5890         sqlite3WindowCodeInit(pParse, pWin);
  5885   5891       }
         5892  +#endif
         5893  +    assert( WHERE_USE_LIMIT==SF_FixedLimit );
         5894  +
  5886   5895   
  5887   5896       /* Begin the database scan. */
  5888   5897       SELECTTRACE(1,pParse,p,("WhereBegin\n"));
  5889   5898       pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
  5890   5899                                  p->pEList, wctrlFlags, p->nSelectRow);
  5891   5900       if( pWInfo==0 ) goto select_end;
  5892   5901       if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
................................................................................
  5908   5917       ** into an OP_Noop.
  5909   5918       */
  5910   5919       if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){
  5911   5920         sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);
  5912   5921       }
  5913   5922   
  5914   5923       assert( p->pEList==pEList );
         5924  +#ifndef SQLITE_OMIT_WINDOWFUNC
  5915   5925       if( pWin ){
  5916   5926         int addrGosub = sqlite3VdbeMakeLabel(v);
  5917   5927         int iCont = sqlite3VdbeMakeLabel(v);
  5918   5928         int regGosub = ++pParse->nMem;
  5919   5929         int addr = 0;
  5920   5930   
  5921   5931         sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub);
................................................................................
  5923   5933         addr = sqlite3VdbeAddOp0(v, OP_Goto);
  5924   5934         sqlite3VdbeResolveLabel(v, addrGosub);
  5925   5935         selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, 0);
  5926   5936         sqlite3VdbeResolveLabel(v, iCont);
  5927   5937         sqlite3VdbeAddOp1(v, OP_Return, regGosub);
  5928   5938         sqlite3VdbeJumpHere(v, addr);
  5929   5939   
  5930         -    }else{
         5940  +    }else
         5941  +#endif /* SQLITE_OMIT_WINDOWFUNC */
         5942  +    {
  5931   5943         /* Use the standard inner loop. */
  5932   5944         selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest,
  5933   5945             sqlite3WhereContinueLabel(pWInfo),
  5934   5946             sqlite3WhereBreakLabel(pWInfo));
  5935   5947   
  5936   5948         /* End the database scan loop.
  5937   5949         */

Changes to src/sqliteInt.h.

  2462   2462     i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
  2463   2463     u8 op2;                /* TK_REGISTER: original value of Expr.op
  2464   2464                            ** TK_COLUMN: the value of p5 for OP_Column
  2465   2465                            ** TK_AGG_FUNCTION: nesting depth */
  2466   2466     AggInfo *pAggInfo;     /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
  2467   2467     Table *pTab;           /* Table for TK_COLUMN expressions.  Can be NULL
  2468   2468                            ** for a column of an index on an expression */
         2469  +#ifndef SQLITE_OMIT_WINDOWFUNC
  2469   2470     Window *pWin;          /* Window definition for window functions */
         2471  +#endif
  2470   2472   };
  2471   2473   
  2472   2474   /*
  2473   2475   ** The following are the meanings of bits in the Expr.flags field.
  2474   2476   */
  2475   2477   #define EP_FromJoin  0x000001 /* Originates in ON/USING clause of outer join */
  2476   2478   #define EP_Agg       0x000002 /* Contains one or more aggregate functions */
................................................................................
  2815   2817     ExprList *pGroupBy;    /* The GROUP BY clause */
  2816   2818     Expr *pHaving;         /* The HAVING clause */
  2817   2819     ExprList *pOrderBy;    /* The ORDER BY clause */
  2818   2820     Select *pPrior;        /* Prior select in a compound select statement */
  2819   2821     Select *pNext;         /* Next select to the left in a compound */
  2820   2822     Expr *pLimit;          /* LIMIT expression. NULL means not used. */
  2821   2823     With *pWith;           /* WITH clause attached to this select. Or NULL. */
         2824  +#ifndef SQLITE_OMIT_WINDOWFUNC
  2822   2825     Window *pWin;          /* List of window functions */
  2823   2826     Window *pWinDefn;      /* List of named window definitions */
         2827  +#endif
  2824   2828   };
  2825   2829   
  2826   2830   /*
  2827   2831   ** Allowed values for Select.selFlags.  The "SF" prefix stands for
  2828   2832   ** "Select Flag".
  2829   2833   **
  2830   2834   ** Value constraints (all checked via assert())
................................................................................
  3513   3517   
  3514   3518     int regPart;
  3515   3519     Expr *pOwner;           /* Expression object this window is attached to */
  3516   3520     int nBufferCol;         /* Number of columns in buffer table */
  3517   3521     int iArgCol;            /* Offset of first argument for this function */
  3518   3522   };
  3519   3523   
         3524  +#ifndef SQLITE_OMIT_WINDOWFUNC
  3520   3525   void sqlite3WindowDelete(sqlite3*, Window*);
  3521   3526   void sqlite3WindowListDelete(sqlite3 *db, Window *p);
  3522   3527   Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*);
  3523   3528   void sqlite3WindowAttach(Parse*, Expr*, Window*);
  3524   3529   int sqlite3WindowCompare(Parse*, Window*, Window*);
  3525   3530   void sqlite3WindowCodeInit(Parse*, Window*);
  3526   3531   void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
  3527   3532   int sqlite3WindowRewrite(Parse*, Select*);
  3528   3533   int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
  3529   3534   void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
  3530   3535   Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
  3531   3536   Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
  3532   3537   void sqlite3WindowFunctions(void);
         3538  +#else
         3539  +# define sqlite3WindowDelete(a,b)
         3540  +# define sqlite3WindowFunctions()
         3541  +# define sqlite3WindowAttach(a,b,c)
         3542  +#endif
  3533   3543   
  3534   3544   /*
  3535   3545   ** Assuming zIn points to the first byte of a UTF-8 character,
  3536   3546   ** advance zIn to point to the first byte of the next UTF-8 character.
  3537   3547   */
  3538   3548   #define SQLITE_SKIP_UTF8(zIn) {                        \
  3539   3549     if( (*(zIn++))>=0xc0 ){                              \

Changes to src/test_config.c.

   757    757   #endif
   758    758   
   759    759   #ifdef SQLITE_ENABLE_URI_00_ERROR
   760    760     Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "1", TCL_GLOBAL_ONLY);
   761    761   #else
   762    762     Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "0", TCL_GLOBAL_ONLY);
   763    763   #endif
          764  +
          765  +#ifdef SQLITE_OMIT_WINDOWFUNC
          766  +  Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "0", TCL_GLOBAL_ONLY);
          767  +#else
          768  +  Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "1", TCL_GLOBAL_ONLY);
          769  +#endif
   764    770   
   765    771   #define LINKVAR(x) { \
   766    772       static const int cv_ ## x = SQLITE_ ## x; \
   767    773       Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
   768    774                   TCL_LINK_INT | TCL_LINK_READ_ONLY); }
   769    775   
   770    776     LINKVAR( MAX_LENGTH );

Changes to src/vdbe.c.

  5114   5114     if( isSorter(pC) ){
  5115   5115       rc = sqlite3VdbeSorterRewind(pC, &res);
  5116   5116     }else{
  5117   5117       assert( pC->eCurType==CURTYPE_BTREE );
  5118   5118       pCrsr = pC->uc.pCursor;
  5119   5119       assert( pCrsr );
  5120   5120       rc = sqlite3BtreeFirst(pCrsr, &res);
         5121  +#ifndef SQLITE_OMIT_WINDOWFUNC
  5121   5122       if( pOp->p5 ) sqlite3BtreeSkipNext(pCrsr);
         5123  +#endif
  5122   5124       pC->deferredMoveto = 0;
  5123   5125       pC->cacheStatus = CACHE_STALE;
  5124   5126     }
  5125   5127     if( rc ) goto abort_due_to_error;
  5126   5128     pC->nullRow = (u8)res;
  5127   5129     assert( pOp->p2>0 && pOp->p2<p->nOp );
  5128   5130     VdbeBranchTaken(res!=0,2);
................................................................................
  6365   6367     }
  6366   6368   #endif
  6367   6369   
  6368   6370     pMem->n++;
  6369   6371     assert( pCtx->pOut->flags==MEM_Null );
  6370   6372     assert( pCtx->isError==0 );
  6371   6373     assert( pCtx->skipFlag==0 );
  6372         -  (pOp->p1 ? (pCtx->pFunc->xInverse) : (pCtx->pFunc->xSFunc))
  6373         -    (pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
         6374  +#ifndef SQLITE_OMIT_WINDOWFUNC
         6375  +  if( pOp->p1 ){
         6376  +    (pCtx->pFunc->xInverse)(pCtx,pCtx->argc,pCtx->argv);
         6377  +  }else
         6378  +#endif
         6379  +  (pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
         6380  +
  6374   6381     if( pCtx->isError ){
  6375   6382       if( pCtx->isError>0 ){
  6376   6383         sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut));
  6377   6384         rc = pCtx->isError;
  6378   6385       }
  6379   6386       if( pCtx->skipFlag ){
  6380   6387         assert( pOp[-1].opcode==OP_CollSeq );
................................................................................
  6408   6415   ** the step function was not previously called.
  6409   6416   */
  6410   6417   case OP_AggFinal: {
  6411   6418     Mem *pMem;
  6412   6419     assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
  6413   6420     pMem = &aMem[pOp->p1];
  6414   6421     assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
         6422  +#ifndef SQLITE_OMIT_WINDOWFUNC
  6415   6423     if( pOp->p3 ){
  6416   6424       rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc);
  6417   6425       pMem = &aMem[pOp->p3];
  6418         -  }else{
  6419         -    rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
  6420         -  }
         6426  +  }else
         6427  +#endif
         6428  +  rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
         6429  +  
  6421   6430     if( rc ){
  6422   6431       sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem));
  6423   6432       goto abort_due_to_error;
  6424   6433     }
  6425   6434     sqlite3VdbeChangeEncoding(pMem, encoding);
  6426   6435     UPDATE_MAX_BLOBSIZE(pMem);
  6427   6436     if( sqlite3VdbeMemTooBig(pMem) ){

Changes to src/vdbeInt.h.

   493    493   void sqlite3VdbeIntegerAffinity(Mem*);
   494    494   int sqlite3VdbeMemRealify(Mem*);
   495    495   int sqlite3VdbeMemNumerify(Mem*);
   496    496   void sqlite3VdbeMemCast(Mem*,u8,u8);
   497    497   int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
   498    498   void sqlite3VdbeMemRelease(Mem *p);
   499    499   int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
          500  +#ifndef SQLITE_OMIT_WINDOWFUNC
   500    501   int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
          502  +#endif
   501    503   const char *sqlite3OpcodeName(int);
   502    504   int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
   503    505   int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
   504    506   int sqlite3VdbeCloseStatement(Vdbe *, int);
   505    507   void sqlite3VdbeFrameDelete(VdbeFrame*);
   506    508   int sqlite3VdbeFrameRestore(VdbeFrame *);
   507    509   #ifdef SQLITE_ENABLE_PREUPDATE_HOOK

Changes to src/vdbemem.c.

   419    419   ** Memory cell pAccum contains the context of an aggregate function.
   420    420   ** This routine calls the xValue method for that function and stores
   421    421   ** the results in memory cell pMem.
   422    422   **
   423    423   ** SQLITE_ERROR is returned if xValue() reports an error. SQLITE_OK 
   424    424   ** otherwise.
   425    425   */
          426  +#ifndef SQLITE_OMIT_WINDOWFUNC
   426    427   int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){
   427    428     sqlite3_context ctx;
   428    429     Mem t;
   429    430     assert( pFunc!=0 );
   430    431     assert( pFunc->xValue!=0 );
   431    432     assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef );
   432    433     assert( pAccum->db==0 || sqlite3_mutex_held(pAccum->db->mutex) );
................................................................................
   436    437     t.db = pAccum->db;
   437    438     ctx.pOut = pOut;
   438    439     ctx.pMem = pAccum;
   439    440     ctx.pFunc = pFunc;
   440    441     pFunc->xValue(&ctx);
   441    442     return ctx.isError;
   442    443   }
          444  +#endif /* SQLITE_OMIT_WINDOWFUNC */
   443    445   
   444    446   /*
   445    447   ** If the memory cell contains a value that must be freed by
   446    448   ** invoking the external callback in Mem.xDel, then this routine
   447    449   ** will free that value.  It also sets Mem.flags to MEM_Null.
   448    450   **
   449    451   ** This is a helper routine for sqlite3VdbeMemSetNull() and

Changes to src/window.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   */
    13     13   #include "sqliteInt.h"
    14     14   
           15  +#ifndef SQLITE_OMIT_WINDOWFUNC
           16  +
    15     17   /*
    16     18   ** SELECT REWRITING
    17     19   **
    18     20   **   Any SELECT statement that contains one or more window functions in
    19     21   **   either the select list or ORDER BY clause (the only two places window
    20     22   **   functions may be used) is transformed by function sqlite3WindowRewrite()
    21     23   **   in order to support window function processing. For example, with the
................................................................................
  2062   2064         windowCodeCacheStep(pParse, p, pWInfo, regGosub, addrGosub);
  2063   2065       }else{
  2064   2066         windowCodeDefaultStep(pParse, p, pWInfo, regGosub, addrGosub);
  2065   2067       }
  2066   2068     }
  2067   2069   }
  2068   2070   
         2071  +#endif /* SQLITE_OMIT_WINDOWFUNC */

Changes to test/pg_common.tcl.

   126    126     puts $::fd ""
   127    127   }
   128    128   
   129    129   proc finish_test {} {
   130    130     puts $::fd finish_test
   131    131     close $::fd
   132    132   }
          133  +
          134  +proc ifcapable {arg} {
          135  +   puts $::fd "ifcapable $arg { finish_test ; return }"
          136  +}
   133    137   

Changes to test/window1.test.

    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   
    14     14   set testdir [file dirname $argv0]
    15     15   source $testdir/tester.tcl
    16     16   set testprefix window1
    17     17   
           18  +ifcapable !windowfunc {
           19  +  finish_test
           20  +  return
           21  +}
    18     22   
    19     23   do_execsql_test 1.0 {
    20     24     CREATE TABLE t1(a, b, c, d);
    21     25     INSERT INTO t1 VALUES(1, 2, 3, 4);
    22     26     INSERT INTO t1 VALUES(5, 6, 7, 8);
    23     27     INSERT INTO t1 VALUES(9, 10, 11, 12);
    24     28   }

Changes to test/window2.tcl.

    12     12   
    13     13   source [file join [file dirname $argv0] pg_common.tcl]
    14     14   
    15     15   #=========================================================================
    16     16   
    17     17   
    18     18   start_test window2 "2018 May 19"
           19  +
           20  +ifcapable !windowfunc
    19     21   
    20     22   execsql_test 1.0 {
    21     23     DROP TABLE IF EXISTS t1;
    22     24     CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER);
    23     25     INSERT INTO t1 VALUES(1, 'odd',  'one',   1);
    24     26     INSERT INTO t1 VALUES(2, 'even', 'two',   2);
    25     27     INSERT INTO t1 VALUES(3, 'odd',  'three', 3);

Changes to test/window2.test.

    15     15   # DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED!
    16     16   ####################################################
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   set testprefix window2
    21     21   
           22  +ifcapable !windowfunc { finish_test ; return }
    22     23   do_execsql_test 1.0 {
    23     24     DROP TABLE IF EXISTS t1;
    24     25     CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER);
    25     26     INSERT INTO t1 VALUES(1, 'odd',  'one',   1);
    26     27     INSERT INTO t1 VALUES(2, 'even', 'two',   2);
    27     28     INSERT INTO t1 VALUES(3, 'odd',  'three', 3);
    28     29     INSERT INTO t1 VALUES(4, 'even', 'four',  4);

Changes to test/window3.tcl.

    11     11   #
    12     12   
    13     13   source [file join [file dirname $argv0] pg_common.tcl]
    14     14   
    15     15   #=========================================================================
    16     16   
    17     17   start_test window3 "2018 May 31"
           18  +ifcapable !windowfunc
    18     19   
    19     20   execsql_test 1.0 {
    20     21     DROP TABLE IF EXISTS t2;
    21     22     CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER);
    22     23     INSERT INTO t2(a, b) VALUES
    23     24     (1,0), (2,74), (3,41), (4,74), (5,23), (6,99), (7,26), (8,33), (9,2),
    24     25     (10,89), (11,81), (12,96), (13,59), (14,38), (15,68), (16,39), (17,62),

Changes to test/window3.test.

cannot compute difference between binary files

Changes to test/window4.tcl.

    11     11   #
    12     12   
    13     13   source [file join [file dirname $argv0] pg_common.tcl]
    14     14   
    15     15   #=========================================================================
    16     16   
    17     17   start_test window4 "2018 June 04"
           18  +ifcapable !windowfunc
    18     19   
    19     20   execsql_test 1.0 {
    20     21     DROP TABLE IF EXISTS t3;
    21     22     CREATE TABLE t3(a TEXT PRIMARY KEY);
    22     23     INSERT INTO t3 VALUES('a'), ('b'), ('c'), ('d'), ('e');
    23     24     INSERT INTO t3 VALUES('f'), ('g'), ('h'), ('i'), ('j');
    24     25   }

Changes to test/window4.test.

    15     15   # DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED!
    16     16   ####################################################
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   set testprefix window4
    21     21   
           22  +ifcapable !windowfunc { finish_test ; return }
    22     23   do_execsql_test 1.0 {
    23     24     DROP TABLE IF EXISTS t3;
    24     25     CREATE TABLE t3(a TEXT PRIMARY KEY);
    25     26     INSERT INTO t3 VALUES('a'), ('b'), ('c'), ('d'), ('e');
    26     27     INSERT INTO t3 VALUES('f'), ('g'), ('h'), ('i'), ('j');
    27     28   } {}
    28     29   

Changes to test/window5.test.

    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library. Specifically,
    12     12   # it tests the sqlite3_create_window_function() API.
    13     13   #
    14     14   
    15     15   set testdir [file dirname $argv0]
    16     16   source $testdir/tester.tcl
    17         -set testprefix window1
           17  +set testprefix window5
           18  +
           19  +ifcapable !windowfunc {
           20  +  finish_test
           21  +  return
           22  +}
    18     23   
    19     24   proc m_step {ctx val} {
    20     25     lappend ctx $val
    21     26     return $ctx
    22     27   }
    23     28   proc m_value {ctx} {
    24     29     set lSort [lsort $ctx]

Changes to test/windowfault.test.

    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   
    14     14   set testdir [file dirname $argv0]
    15     15   source $testdir/tester.tcl
    16     16   set testprefix windowfault
    17     17   
           18  +ifcapable !windowfunc {
           19  +  finish_test
           20  +  return
           21  +}
    18     22   
    19     23   do_execsql_test 1.0 {
    20     24     CREATE TABLE t1(a, b, c, d);
    21     25     INSERT INTO t1 VALUES(1, 2, 3, 4);
    22     26     INSERT INTO t1 VALUES(5, 6, 7, 8);
    23     27     INSERT INTO t1 VALUES(9, 10, 11, 12);
    24     28   }

Changes to tool/mkkeywordhash.c.

   144    144   #  define CTE        0x00040000
   145    145   #endif
   146    146   #ifdef SQLITE_OMIT_UPSERT
   147    147   #  define UPSERT     0
   148    148   #else
   149    149   #  define UPSERT     0x00080000
   150    150   #endif
          151  +#ifdef SQLITE_OMIT_WINDOWFUNC
          152  +#  define WINDOWFUNC 0
          153  +#else
          154  +#  define WINDOWFUNC 0x00100000
          155  +#endif
   151    156   
   152    157   /*
   153    158   ** These are the keywords
   154    159   */
   155    160   static Keyword aKeywordTable[] = {
   156    161     { "ABORT",            "TK_ABORT",        CONFLICT|TRIGGER       },
   157    162     { "ACTION",           "TK_ACTION",       FKEY                   },
................................................................................
   176    181     { "COLLATE",          "TK_COLLATE",      ALWAYS                 },
   177    182     { "COLUMN",           "TK_COLUMNKW",     ALTER                  },
   178    183     { "COMMIT",           "TK_COMMIT",       ALWAYS                 },
   179    184     { "CONFLICT",         "TK_CONFLICT",     CONFLICT               },
   180    185     { "CONSTRAINT",       "TK_CONSTRAINT",   ALWAYS                 },
   181    186     { "CREATE",           "TK_CREATE",       ALWAYS                 },
   182    187     { "CROSS",            "TK_JOIN_KW",      ALWAYS                 },
   183         -  { "CURRENT",          "TK_CURRENT",      ALWAYS                 },
          188  +  { "CURRENT",          "TK_CURRENT",      WINDOWFUNC             },
   184    189     { "CURRENT_DATE",     "TK_CTIME_KW",     ALWAYS                 },
   185    190     { "CURRENT_TIME",     "TK_CTIME_KW",     ALWAYS                 },
   186    191     { "CURRENT_TIMESTAMP","TK_CTIME_KW",     ALWAYS                 },
   187    192     { "DATABASE",         "TK_DATABASE",     ATTACH                 },
   188    193     { "DEFAULT",          "TK_DEFAULT",      ALWAYS                 },
   189    194     { "DEFERRED",         "TK_DEFERRED",     ALWAYS                 },
   190    195     { "DEFERRABLE",       "TK_DEFERRABLE",   FKEY                   },
................................................................................
   199    204     { "ELSE",             "TK_ELSE",         ALWAYS                 },
   200    205     { "ESCAPE",           "TK_ESCAPE",       ALWAYS                 },
   201    206     { "EXCEPT",           "TK_EXCEPT",       COMPOUND               },
   202    207     { "EXCLUSIVE",        "TK_EXCLUSIVE",    ALWAYS                 },
   203    208     { "EXISTS",           "TK_EXISTS",       ALWAYS                 },
   204    209     { "EXPLAIN",          "TK_EXPLAIN",      EXPLAIN                },
   205    210     { "FAIL",             "TK_FAIL",         CONFLICT|TRIGGER       },
   206         -  { "FILTER",           "TK_FILTER",       ALWAYS                 },
   207         -  { "FOLLOWING",        "TK_FOLLOWING",    ALWAYS                 },
          211  +  { "FILTER",           "TK_FILTER",       WINDOWFUNC             },
          212  +  { "FOLLOWING",        "TK_FOLLOWING",    WINDOWFUNC             },
   208    213     { "FOR",              "TK_FOR",          TRIGGER                },
   209    214     { "FOREIGN",          "TK_FOREIGN",      FKEY                   },
   210    215     { "FROM",             "TK_FROM",         ALWAYS                 },
   211    216     { "FULL",             "TK_JOIN_KW",      ALWAYS                 },
   212    217     { "GLOB",             "TK_LIKE_KW",      ALWAYS                 },
   213    218     { "GROUP",            "TK_GROUP",        ALWAYS                 },
   214    219     { "HAVING",           "TK_HAVING",       ALWAYS                 },
................................................................................
   240    245     { "NULL",             "TK_NULL",         ALWAYS                 },
   241    246     { "OF",               "TK_OF",           ALWAYS                 },
   242    247     { "OFFSET",           "TK_OFFSET",       ALWAYS                 },
   243    248     { "ON",               "TK_ON",           ALWAYS                 },
   244    249     { "OR",               "TK_OR",           ALWAYS                 },
   245    250     { "ORDER",            "TK_ORDER",        ALWAYS                 },
   246    251     { "OUTER",            "TK_JOIN_KW",      ALWAYS                 },
   247         -  { "OVER",             "TK_OVER",         ALWAYS                 },
   248         -  { "PARTITION",        "TK_PARTITION",    ALWAYS                 },
          252  +  { "OVER",             "TK_OVER",         WINDOWFUNC             },
          253  +  { "PARTITION",        "TK_PARTITION",    WINDOWFUNC             },
   249    254     { "PLAN",             "TK_PLAN",         EXPLAIN                },
   250    255     { "PRAGMA",           "TK_PRAGMA",       PRAGMA                 },
   251         -  { "PRECEDING",        "TK_PRECEDING",    ALWAYS                 },
          256  +  { "PRECEDING",        "TK_PRECEDING",    WINDOWFUNC             },
   252    257     { "PRIMARY",          "TK_PRIMARY",      ALWAYS                 },
   253    258     { "QUERY",            "TK_QUERY",        EXPLAIN                },
   254    259     { "RAISE",            "TK_RAISE",        TRIGGER                },
   255         -  { "RANGE",            "TK_RANGE",        ALWAYS                 },
          260  +  { "RANGE",            "TK_RANGE",        WINDOWFUNC             },
   256    261     { "RECURSIVE",        "TK_RECURSIVE",    CTE                    },
   257    262     { "REFERENCES",       "TK_REFERENCES",   FKEY                   },
   258    263     { "REGEXP",           "TK_LIKE_KW",      ALWAYS                 },
   259    264     { "REINDEX",          "TK_REINDEX",      REINDEX                },
   260    265     { "RELEASE",          "TK_RELEASE",      ALWAYS                 },
   261    266     { "RENAME",           "TK_RENAME",       ALTER                  },
   262    267     { "REPLACE",          "TK_REPLACE",      CONFLICT               },
................................................................................
   271    276     { "TABLE",            "TK_TABLE",        ALWAYS                 },
   272    277     { "TEMP",             "TK_TEMP",         ALWAYS                 },
   273    278     { "TEMPORARY",        "TK_TEMP",         ALWAYS                 },
   274    279     { "THEN",             "TK_THEN",         ALWAYS                 },
   275    280     { "TO",               "TK_TO",           ALWAYS                 },
   276    281     { "TRANSACTION",      "TK_TRANSACTION",  ALWAYS                 },
   277    282     { "TRIGGER",          "TK_TRIGGER",      TRIGGER                },
   278         -  { "UNBOUNDED",        "TK_UNBOUNDED",    ALWAYS                 },
          283  +  { "UNBOUNDED",        "TK_UNBOUNDED",    WINDOWFUNC             },
   279    284     { "UNION",            "TK_UNION",        COMPOUND               },
   280    285     { "UNIQUE",           "TK_UNIQUE",       ALWAYS                 },
   281    286     { "UPDATE",           "TK_UPDATE",       ALWAYS                 },
   282    287     { "USING",            "TK_USING",        ALWAYS                 },
   283    288     { "VACUUM",           "TK_VACUUM",       VACUUM                 },
   284    289     { "VALUES",           "TK_VALUES",       ALWAYS                 },
   285    290     { "VIEW",             "TK_VIEW",         VIEW                   },
   286    291     { "VIRTUAL",          "TK_VIRTUAL",      VTAB                   },
   287         -  { "WINDOW",           "TK_WINDOW",       ALWAYS                 },
          292  +  { "WINDOW",           "TK_WINDOW",       WINDOWFUNC             },
   288    293     { "WITH",             "TK_WITH",         CTE                    },
   289    294     { "WITHOUT",          "TK_WITHOUT",      ALWAYS                 },
   290    295     { "WHEN",             "TK_WHEN",         ALWAYS                 },
   291    296     { "WHERE",            "TK_WHERE",        ALWAYS                 },
   292    297   };
   293    298   
   294    299   /* Number of keywords */