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: |
5fe15c1d8383989257e11d1806e6b035 |
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
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