/ Check-in [5fe15c1d]
Login

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

Overview
Comment:Further simplifications to window-function code.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 5fe15c1d8383989257e11d1806e6b035acacd1b504ae385ba58d20db10f26eee
User & Date: dan 2019-09-25 16:41:44
Context
2019-09-25
17:47
Remove an unused variable. check-in: a1988445 user: drh tags: trunk
16:41
Further simplifications to window-function code. check-in: 5fe15c1d user: dan tags: trunk
11:49
In the previous check-in, the variable should be openMode, not openFlags. check-in: 77b0db22 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/window.c.

  1478   1478     Parse *pParse;             /* Parse context */
  1479   1479     Window *pMWin;             /* First in list of functions being processed */
  1480   1480     Vdbe *pVdbe;               /* VDBE object */
  1481   1481     int addrGosub;             /* OP_Gosub to this address to return one row */
  1482   1482     int regGosub;              /* Register used with OP_Gosub(addrGosub) */
  1483   1483     int regArg;                /* First in array of accumulator registers */
  1484   1484     int eDelete;               /* See above */
  1485         -  int regStart;              /* Value of <expr> PRECEDING */
  1486         -  int regEnd;                /* Value of <expr> FOLLOWING */
  1487   1485   
  1488   1486     WindowCsrAndReg start;
  1489   1487     WindowCsrAndReg current;
  1490   1488     WindowCsrAndReg end;
  1491   1489   };
  1492   1490   
  1493   1491   /*
................................................................................
  1595   1593           assert( pWin->bExprArgs || nArg  ||pWin->pOwner->x.pList==0 );
  1596   1594           regTmp = sqlite3GetTempReg(pParse);
  1597   1595           sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
  1598   1596           addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
  1599   1597           VdbeCoverage(v);
  1600   1598           sqlite3ReleaseTempReg(pParse, regTmp);
  1601   1599         }
  1602         -
  1603   1600         
  1604         -      /* If this is a (RANGE BETWEEN a PRECEDING AND b PRECEDING) or a
  1605         -      ** (RANGE BETWEEN b FOLLOWING AND a FOLLOWING) frame and (b > a), 
  1606         -      ** omit the OP_AggStep or OP_AggInverse if the peer value is numeric.
  1607         -      ** A numeric peer value is one for which the following is true: 
  1608         -      **
  1609         -      **    (peer IS NOT NULL AND peer < '')
  1610         -      */
  1611         -      if( pWin->eFrmType==TK_RANGE 
  1612         -       && pWin->eStart==pWin->eEnd 
  1613         -       && pWin->eStart==TK_PRECEDING
  1614         -      ){
  1615         -        int regPeer = sqlite3GetTempReg(pParse);
  1616         -        int regString = sqlite3GetTempReg(pParse);
  1617         -        int lbl = sqlite3VdbeMakeLabel(pParse);
  1618         -        VdbeModuleComment((v, "windowAggStep \"peer is numeric?\" test"));
  1619         -        assert( pMWin->eStart==TK_PRECEDING ); /* because pWin same as pMWin */
  1620         -        sqlite3VdbeAddOp3(v, OP_Le, p->regStart, lbl, p->regEnd);
  1621         -        VdbeCoverageNeverNull(v); /* because <expr> values previously checked */
  1622         -        windowReadPeerValues(p, csr, regPeer);
  1623         -        sqlite3VdbeAddOp2(v, OP_IsNull, regPeer, lbl);
  1624         -        sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
  1625         -        addrIf2 = sqlite3VdbeAddOp3(v, OP_Lt, regString, 0, regPeer);
  1626         -        sqlite3ReleaseTempReg(pParse, regPeer);
  1627         -        sqlite3ReleaseTempReg(pParse, regString);
  1628         -        sqlite3VdbeResolveLabel(v, lbl);
  1629         -        VdbeModuleComment((v, "windowAggStep end \"peer is numeric?\""));
  1630         -        assert( pWin->eStart==TK_PRECEDING || pWin->eStart==TK_FOLLOWING );
  1631         -        assert( pMWin->pOrderBy && pMWin->pOrderBy->nExpr==1 );
  1632         -      }
  1633         -
  1634   1601         if( pWin->bExprArgs ){
  1635   1602           int iStart = sqlite3VdbeCurrentAddr(v);
  1636   1603           VdbeOp *pOp, *pEnd;
  1637   1604   
  1638   1605           nArg = pWin->pOwner->x.pList->nExpr;
  1639   1606           regArg = sqlite3GetTempRange(pParse, nArg);
  1640   1607           sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);
................................................................................
  2176   2143       }
  2177   2144     }
  2178   2145   
  2179   2146     if( op==WINDOW_RETURN_ROW && pMWin->regStartRowid==0 ){
  2180   2147       windowAggFinal(p, 0);
  2181   2148     }
  2182   2149     addrContinue = sqlite3VdbeCurrentAddr(v);
         2150  +
         2151  +  /* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
         2152  +  ** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the 
         2153  +  ** start cursor does not advance past the end cursor within the 
         2154  +  ** temporary table. It otherwise might, if (a>b).  */
         2155  +  if( pMWin->eStart==pMWin->eEnd && regCountdown
         2156  +   && pMWin->eFrmType==TK_RANGE && op==WINDOW_AGGINVERSE
         2157  +  ){
         2158  +    int regRowid1 = sqlite3GetTempReg(pParse);
         2159  +    int regRowid2 = sqlite3GetTempReg(pParse);
         2160  +    sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
         2161  +    sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
         2162  +    sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
         2163  +    sqlite3ReleaseTempReg(pParse, regRowid1);
         2164  +    sqlite3ReleaseTempReg(pParse, regRowid2);
         2165  +    assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING );
         2166  +  }
         2167  +
  2183   2168     switch( op ){
  2184   2169       case WINDOW_RETURN_ROW:
  2185   2170         csr = p->current.csr;
  2186   2171         reg = p->current.reg;
  2187   2172         windowReturnOneRow(p);
  2188   2173         break;
  2189   2174   
................................................................................
  2226   2211       if( bPeer ){
  2227   2212         sqlite3VdbeAddOp2(v, OP_Goto, 0, lblDone);
  2228   2213       }
  2229   2214     }
  2230   2215   
  2231   2216     if( bPeer ){
  2232   2217       int nReg = (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0);
  2233         -    int regTmp;
  2234         -
  2235         -    /* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING), ensure
  2236         -    ** the start cursor does not advance past the end cursor within the
  2237         -    ** temporary table. It otherwise might, if (a>b).  */
  2238         -    if( pMWin->eStart==TK_FOLLOWING && pMWin->eEnd==TK_FOLLOWING
  2239         -     && pMWin->eFrmType==TK_RANGE && op==WINDOW_AGGINVERSE
  2240         -    ){
  2241         -      int regRowid1 = sqlite3GetTempReg(pParse);
  2242         -      int regRowid2 = sqlite3GetTempReg(pParse);
  2243         -      sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
  2244         -      sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
  2245         -      sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
  2246         -      sqlite3ReleaseTempReg(pParse, regRowid1);
  2247         -      sqlite3ReleaseTempReg(pParse, regRowid2);
  2248         -    }
  2249         -    regTmp = (nReg ? sqlite3GetTempRange(pParse, nReg) : 0);
         2218  +    int regTmp = (nReg ? sqlite3GetTempRange(pParse, nReg) : 0);
  2250   2219       windowReadPeerValues(p, csr, regTmp);
  2251   2220       windowIfNewPeer(pParse, pMWin->pOrderBy, regTmp, reg, addrContinue);
  2252   2221       sqlite3ReleaseTempRange(pParse, regTmp, nReg);
  2253   2222     }
  2254   2223   
  2255   2224     if( addrNextRange ){
  2256   2225       sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNextRange);
................................................................................
  2607   2576   **         Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
  2608   2577   **         regEnd = <expr2>
  2609   2578   **         regStart = <expr1>
  2610   2579   **       }else{
  2611   2580   **         while( (csrEnd.key + regEnd) <= csrCurrent.key ){
  2612   2581   **           AGGSTEP
  2613   2582   **         }
  2614         -**         RETURN_ROW
  2615   2583   **         while( (csrStart.key + regStart) < csrCurrent.key ){
  2616   2584   **           AGGINVERSE
  2617   2585   **         }
         2586  +**         RETURN_ROW
  2618   2587   **       }
  2619   2588   **     }
  2620   2589   **     flush:
  2621   2590   **       while( (csrEnd.key + regEnd) <= csrCurrent.key ){
  2622   2591   **         AGGSTEP
  2623   2592   **       }
  2624         -**       RETURN_ROW
  2625   2593   **       while( (csrStart.key + regStart) < csrCurrent.key ){
  2626   2594   **         AGGINVERSE
  2627   2595   **       }
         2596  +**       RETURN_ROW
  2628   2597   **
  2629   2598   **   RANGE BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING
  2630   2599   **
  2631   2600   **     ... loop started by sqlite3WhereBegin() ...
  2632   2601   **       if( new partition ){
  2633   2602   **         Gosub flush
  2634   2603   **       }
................................................................................
  2685   2654     int regRecord;                  /* regNew array in record form */
  2686   2655     int regRowid;                   /* Rowid for regRecord in eph table */
  2687   2656     int regNewPeer = 0;             /* Peer values for new row (part of regNew) */
  2688   2657     int regPeer = 0;                /* Peer values for current row */
  2689   2658     int regFlushPart = 0;           /* Register for "Gosub flush_partition" */
  2690   2659     WindowCodeArg s;                /* Context object for sub-routines */
  2691   2660     int lblWhereEnd;                /* Label just before sqlite3WhereEnd() code */
         2661  +  int regStart = 0;               /* Value of <expr> PRECEDING */
         2662  +  int regEnd = 0;                 /* Value of <expr> FOLLOWING */
  2692   2663   
  2693   2664     assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_CURRENT 
  2694   2665          || pMWin->eStart==TK_FOLLOWING || pMWin->eStart==TK_UNBOUNDED 
  2695   2666     );
  2696   2667     assert( pMWin->eEnd==TK_FOLLOWING || pMWin->eEnd==TK_CURRENT 
  2697   2668          || pMWin->eEnd==TK_UNBOUNDED || pMWin->eEnd==TK_PRECEDING 
  2698   2669     );
................................................................................
  2755   2726     regRecord = ++pParse->nMem;
  2756   2727     regRowid = ++pParse->nMem;
  2757   2728   
  2758   2729     /* If the window frame contains an "<expr> PRECEDING" or "<expr> FOLLOWING"
  2759   2730     ** clause, allocate registers to store the results of evaluating each
  2760   2731     ** <expr>.  */
  2761   2732     if( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING ){
  2762         -    s.regStart = ++pParse->nMem;
         2733  +    regStart = ++pParse->nMem;
  2763   2734     }
  2764   2735     if( pMWin->eEnd==TK_PRECEDING || pMWin->eEnd==TK_FOLLOWING ){
  2765         -    s.regEnd = ++pParse->nMem;
         2736  +    regEnd = ++pParse->nMem;
  2766   2737     }
  2767   2738   
  2768   2739     /* If this is not a "ROWS BETWEEN ..." frame, then allocate arrays of
  2769   2740     ** registers to store copies of the ORDER BY expressions (peer values) 
  2770   2741     ** for the main loop, and for each cursor (start, current and end). */
  2771   2742     if( pMWin->eFrmType!=TK_ROWS ){
  2772   2743       int nPeer = (pOrderBy ? pOrderBy->nExpr : 0);
................................................................................
  2813   2784     sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, regRowid);
  2814   2785     addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, regRowid);
  2815   2786     VdbeCoverageNeverNull(v);
  2816   2787   
  2817   2788     /* This block is run for the first row of each partition */
  2818   2789     s.regArg = windowInitAccum(pParse, pMWin);
  2819   2790   
  2820         -  if( s.regStart ){
  2821         -    sqlite3ExprCode(pParse, pMWin->pStart, s.regStart);
  2822         -    windowCheckValue(pParse, s.regStart, 0 + (pMWin->eFrmType==TK_RANGE?3:0));
         2791  +  if( regStart ){
         2792  +    sqlite3ExprCode(pParse, pMWin->pStart, regStart);
         2793  +    windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE?3:0));
  2823   2794     }
  2824         -  if( s.regEnd ){
  2825         -    sqlite3ExprCode(pParse, pMWin->pEnd, s.regEnd);
  2826         -    windowCheckValue(pParse, s.regEnd, 1 + (pMWin->eFrmType==TK_RANGE?3:0));
         2795  +  if( regEnd ){
         2796  +    sqlite3ExprCode(pParse, pMWin->pEnd, regEnd);
         2797  +    windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE?3:0));
  2827   2798     }
  2828   2799   
  2829         -  if( pMWin->eFrmType!=TK_RANGE && pMWin->eStart==pMWin->eEnd && s.regStart ){
         2800  +  if( pMWin->eFrmType!=TK_RANGE && pMWin->eStart==pMWin->eEnd && regStart ){
  2830   2801       int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le);
  2831         -    int addrGe = sqlite3VdbeAddOp3(v, op, s.regStart, 0, s.regEnd);
         2802  +    int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd);
  2832   2803       VdbeCoverageNeverNullIf(v, op==OP_Ge); /* NeverNull because bound <expr> */
  2833   2804       VdbeCoverageNeverNullIf(v, op==OP_Le); /*   values previously checked */
  2834   2805       windowAggFinal(&s, 0);
  2835   2806       sqlite3VdbeAddOp2(v, OP_Rewind, s.current.csr, 1);
  2836   2807       VdbeCoverageNeverTaken(v);
  2837   2808       windowReturnOneRow(&s);
  2838   2809       sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr);
  2839   2810       sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd);
  2840   2811       sqlite3VdbeJumpHere(v, addrGe);
  2841   2812     }
  2842         -  if( pMWin->eStart==TK_FOLLOWING && pMWin->eFrmType!=TK_RANGE && s.regEnd ){
         2813  +  if( pMWin->eStart==TK_FOLLOWING && pMWin->eFrmType!=TK_RANGE && regEnd ){
  2843   2814       assert( pMWin->eEnd==TK_FOLLOWING );
  2844         -    sqlite3VdbeAddOp3(v, OP_Subtract, s.regStart, s.regEnd, s.regStart);
         2815  +    sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regStart);
  2845   2816     }
  2846   2817   
  2847   2818     if( pMWin->eStart!=TK_UNBOUNDED ){
  2848   2819       sqlite3VdbeAddOp2(v, OP_Rewind, s.start.csr, 1);
  2849   2820       VdbeCoverageNeverTaken(v);
  2850   2821     }
  2851   2822     sqlite3VdbeAddOp2(v, OP_Rewind, s.current.csr, 1);
................................................................................
  2869   2840     }
  2870   2841     if( pMWin->eStart==TK_FOLLOWING ){
  2871   2842       windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0);
  2872   2843       if( pMWin->eEnd!=TK_UNBOUNDED ){
  2873   2844         if( pMWin->eFrmType==TK_RANGE ){
  2874   2845           int lbl = sqlite3VdbeMakeLabel(pParse);
  2875   2846           int addrNext = sqlite3VdbeCurrentAddr(v);
  2876         -        windowCodeRangeTest(&s, OP_Ge, s.current.csr, s.regEnd, s.end.csr, lbl);
  2877         -        windowCodeOp(&s, WINDOW_AGGINVERSE, s.regStart, 0);
         2847  +        windowCodeRangeTest(&s, OP_Ge, s.current.csr, regEnd, s.end.csr, lbl);
         2848  +        windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
  2878   2849           windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
  2879   2850           sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext);
  2880   2851           sqlite3VdbeResolveLabel(v, lbl);
  2881   2852         }else{
  2882         -        windowCodeOp(&s, WINDOW_RETURN_ROW, s.regEnd, 0);
  2883         -        windowCodeOp(&s, WINDOW_AGGINVERSE, s.regStart, 0);
         2853  +        windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 0);
         2854  +        windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
  2884   2855         }
  2885   2856       }
  2886   2857     }else
  2887   2858     if( pMWin->eEnd==TK_PRECEDING ){
  2888   2859       int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE);
  2889         -    windowCodeOp(&s, WINDOW_AGGSTEP, s.regEnd, 0);
  2890         -    if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, s.regStart, 0);
         2860  +    windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0);
         2861  +    if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
  2891   2862       windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
  2892         -    if( !bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, s.regStart, 0);
         2863  +    if( !bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
  2893   2864     }else{
  2894   2865       int addr = 0;
  2895   2866       windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0);
  2896   2867       if( pMWin->eEnd!=TK_UNBOUNDED ){
  2897   2868         if( pMWin->eFrmType==TK_RANGE ){
  2898   2869           int lbl = 0;
  2899   2870           addr = sqlite3VdbeCurrentAddr(v);
  2900         -        if( s.regEnd ){
         2871  +        if( regEnd ){
  2901   2872             lbl = sqlite3VdbeMakeLabel(pParse);
  2902         -          windowCodeRangeTest(&s, OP_Ge, s.current.csr,s.regEnd,s.end.csr,lbl);
         2873  +          windowCodeRangeTest(&s, OP_Ge, s.current.csr, regEnd, s.end.csr, lbl);
  2903   2874           }
  2904   2875           windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
  2905         -        windowCodeOp(&s, WINDOW_AGGINVERSE, s.regStart, 0);
  2906         -        if( s.regEnd ){
         2876  +        windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
         2877  +        if( regEnd ){
  2907   2878             sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
  2908   2879             sqlite3VdbeResolveLabel(v, lbl);
  2909   2880           }
  2910   2881         }else{
  2911         -        if( s.regEnd ){
  2912         -          addr = sqlite3VdbeAddOp3(v, OP_IfPos, s.regEnd, 0, 1);
         2882  +        if( regEnd ){
         2883  +          addr = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1);
  2913   2884             VdbeCoverage(v);
  2914   2885           }
  2915   2886           windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
  2916         -        windowCodeOp(&s, WINDOW_AGGINVERSE, s.regStart, 0);
  2917         -        if( s.regEnd ) sqlite3VdbeJumpHere(v, addr);
         2887  +        windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
         2888  +        if( regEnd ) sqlite3VdbeJumpHere(v, addr);
  2918   2889         }
  2919   2890       }
  2920   2891     }
  2921   2892   
  2922   2893     /* End of the main input loop */
  2923   2894     sqlite3VdbeResolveLabel(v, lblWhereEnd);
  2924   2895     sqlite3WhereEnd(pWInfo);
................................................................................
  2929   2900       sqlite3VdbeJumpHere(v, addrGosubFlush);
  2930   2901     }
  2931   2902   
  2932   2903     addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite);
  2933   2904     VdbeCoverage(v);
  2934   2905     if( pMWin->eEnd==TK_PRECEDING ){
  2935   2906       int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE);
  2936         -    windowCodeOp(&s, WINDOW_AGGSTEP, s.regEnd, 0);
  2937         -    if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, s.regStart, 0);
         2907  +    windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0);
         2908  +    if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
  2938   2909       windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
  2939   2910     }else if( pMWin->eStart==TK_FOLLOWING ){
  2940   2911       int addrStart;
  2941   2912       int addrBreak1;
  2942   2913       int addrBreak2;
  2943   2914       int addrBreak3;
  2944   2915       windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0);
  2945   2916       if( pMWin->eFrmType==TK_RANGE ){
  2946   2917         addrStart = sqlite3VdbeCurrentAddr(v);
  2947         -      addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, s.regStart, 1);
         2918  +      addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1);
  2948   2919         addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1);
  2949   2920       }else
  2950   2921       if( pMWin->eEnd==TK_UNBOUNDED ){
  2951   2922         addrStart = sqlite3VdbeCurrentAddr(v);
  2952         -      addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, s.regStart, 1);
         2923  +      addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regStart, 1);
  2953   2924         addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, 0, 1);
  2954   2925       }else{
  2955   2926         assert( pMWin->eEnd==TK_FOLLOWING );
  2956   2927         addrStart = sqlite3VdbeCurrentAddr(v);
  2957         -      addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, s.regEnd, 1);
  2958         -      addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, s.regStart, 1);
         2928  +      addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 1);
         2929  +      addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1);
  2959   2930       }
  2960   2931       sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
  2961   2932       sqlite3VdbeJumpHere(v, addrBreak2);
  2962   2933       addrStart = sqlite3VdbeCurrentAddr(v);
  2963   2934       addrBreak3 = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1);
  2964   2935       sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
  2965   2936       sqlite3VdbeJumpHere(v, addrBreak1);
................................................................................
  2966   2937       sqlite3VdbeJumpHere(v, addrBreak3);
  2967   2938     }else{
  2968   2939       int addrBreak;
  2969   2940       int addrStart;
  2970   2941       windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0);
  2971   2942       addrStart = sqlite3VdbeCurrentAddr(v);
  2972   2943       addrBreak = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1);
  2973         -    windowCodeOp(&s, WINDOW_AGGINVERSE, s.regStart, 0);
         2944  +    windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
  2974   2945       sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
  2975   2946       sqlite3VdbeJumpHere(v, addrBreak);
  2976   2947     }
  2977   2948     sqlite3VdbeJumpHere(v, addrEmpty);
  2978   2949   
  2979   2950     sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr);
  2980   2951     if( pMWin->pPartition ){

Changes to test/windowB.test.

   292    292     ) FROM t1;
   293    293   } {7 {} 8 {} abc 1001} 
   294    294   do_execsql_test 6.2 {
   295    295     SELECT a, sum(c) OVER (
   296    296       ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING EXCLUDE NO OTHERS
   297    297     ) FROM t1;
   298    298   } {7 {} 8 {} abc 1001} 
          299  +
          300  +#-------------------------------------------------------------------------
          301  +reset_db
          302  +do_execsql_test 7.0 {
          303  +  CREATE TABLE t1(a, c);
          304  +  CREATE INDEX i1 ON t1(a);
          305  +
          306  +  INSERT INTO t1 VALUES(NULL, 46);
          307  +  INSERT INTO t1 VALUES(NULL, 45);
          308  +  INSERT INTO t1 VALUES(7,  997);
          309  +  INSERT INTO t1 VALUES(7,  1000);
          310  +  INSERT INTO t1 VALUES(8,  997);
          311  +  INSERT INTO t1 VALUES(8,  1000);
          312  +  INSERT INTO t1 VALUES('abc', 1001);
          313  +  INSERT INTO t1 VALUES('abc', 1004);
          314  +  INSERT INTO t1 VALUES('xyz', 3333);
          315  +}
          316  +
          317  +do_execsql_test 7.1 {
          318  +  SELECT a, max(c) OVER (
          319  +    ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING
          320  +  ) FROM t1;
          321  +} {{} 46 {} 46  7 {} 7 {} 8 {} 8 {}  abc 1004 abc 1004 xyz 3333}
          322  +do_execsql_test 7.2 {
          323  +  SELECT a, min(c) OVER (
          324  +    ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING
          325  +  ) FROM t1;
          326  +} {{} 45 {} 45  7 {} 7 {} 8 {} 8 {}  abc 1001 abc 1001 xyz 3333}
          327  +
          328  +do_execsql_test 7.3 {
          329  +  SELECT a, max(c) OVER (
          330  +    ORDER BY a RANGE BETWEEN 0 PRECEDING AND 2 PRECEDING
          331  +  ) FROM t1;
          332  +} {{} 46 {} 46  7 {} 7 {} 8 {} 8 {}  abc 1004 abc 1004 xyz 3333}
          333  +do_execsql_test 7.4 {
          334  +  SELECT a, min(c) OVER (
          335  +    ORDER BY a RANGE BETWEEN 0 PRECEDING AND 2 PRECEDING
          336  +  ) FROM t1;
          337  +} {{} 45 {} 45  7 {} 7 {} 8 {} 8 {}  abc 1001 abc 1001 xyz 3333}
   299    338   
   300    339   finish_test