/ Check-in [093d2b25]
Login

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

Overview
Comment:Modify new window functions function so that cursors are stepped immediately after each operation, instead of immediately before.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | window-functions
Files: files | file ages | folders
SHA3-256: 093d2b25f1b656bba57d665aac68109436861b157a5769432b612176dae3f6eb
User & Date: dan 2019-03-07 19:26:17
Wiki:window-functions
Context
2019-03-07
20:47
Fix other "ROWS BETWEEN" cases on this branch. check-in: a5f68f66 user: dan tags: window-functions
19:26
Modify new window functions function so that cursors are stepped immediately after each operation, instead of immediately before. check-in: 093d2b25 user: dan tags: window-functions
2019-03-06
21:04
Simplify the window function code generator some more. check-in: 45cbd3b4 user: dan tags: window-functions
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/window.c.

  1888   1888     Vdbe *v = p->pVdbe;
  1889   1889     int addrIf = 0; 
  1890   1890   
  1891   1891     if( regCountdown>0 ){
  1892   1892       addrIf = sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, 0, 1);
  1893   1893     }
  1894   1894   
  1895         -  if( jumpOnEof ){
  1896         -    sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+2);
  1897         -    ret = sqlite3VdbeAddOp0(v, OP_Goto);
  1898         -  }else{
  1899         -    sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+1);
  1900         -  }
  1901         -
  1902   1895     switch( op ){
  1903   1896       case WINDOW_RETURN_ROW:
  1904   1897         windowAggFinal(p->pParse, p->pMWin, 0);
  1905   1898         windowReturnOneRow(p->pParse, p->pMWin, p->regGosub, p->addrGosub);
  1906   1899         break;
  1907   1900   
  1908   1901       case WINDOW_AGGINVERSE:
................................................................................
  1910   1903         break;
  1911   1904   
  1912   1905       case WINDOW_AGGSTEP:
  1913   1906         windowAggStep(p->pParse, p->pMWin, csr, 0, p->regArg, p->pMWin->regSize);
  1914   1907         break;
  1915   1908     }
  1916   1909   
  1917         -  if( ret ){
  1918         -    sqlite3VdbeJumpHere(v, ret);
         1910  +  if( jumpOnEof ){
         1911  +    sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+2);
         1912  +    ret = sqlite3VdbeAddOp0(v, OP_Goto);
         1913  +  }else{
         1914  +    sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+1);
  1919   1915     }
         1916  +
  1920   1917     if( regCountdown>0 ){
  1921   1918       sqlite3VdbeJumpHere(v, addrIf);
  1922   1919     }
  1923   1920     return ret;
  1924   1921   }
  1925   1922   
  1926   1923   
................................................................................
  2020   2017     int addrIf;
  2021   2018     int addrGosubFlush;
  2022   2019     int addrInteger;
  2023   2020     int addrCacheRewind;
  2024   2021     int addrCacheNext;
  2025   2022   
  2026   2023     int addrShortcut = 0;
         2024  +  int addrEmpty = 0;
  2027   2025   
  2028   2026     int bCache = windowCachePartition(pMWin);
  2029   2027   
  2030   2028     int reg = pParse->nMem+1;
  2031   2029     int regRecord = reg+nSub;
  2032   2030     int regRowid = regRecord+1;
  2033   2031     WindowCodeArg s;
................................................................................
  2133   2131       addrShortcut = sqlite3VdbeAddOp0(v, OP_Goto);
  2134   2132       sqlite3VdbeJumpHere(v, addrGe);
  2135   2133     }
  2136   2134     if( pMWin->eStart==TK_FOLLOWING ){
  2137   2135       sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regStart);
  2138   2136     }
  2139   2137   
  2140         -  sqlite3VdbeAddOp2(v, OP_Rewind, csrStart, 1);   sqlite3VdbeChangeP5(v, 1);
  2141         -  sqlite3VdbeAddOp2(v, OP_Rewind, csrCurrent, 1); sqlite3VdbeChangeP5(v, 1);
  2142         -  sqlite3VdbeAddOp2(v, OP_Rewind, csrEnd, 1); sqlite3VdbeChangeP5(v, 1);
         2138  +  sqlite3VdbeAddOp2(v, OP_Rewind, csrStart, 1);
         2139  +  sqlite3VdbeAddOp2(v, OP_Rewind, csrCurrent, 1);
         2140  +  sqlite3VdbeAddOp2(v, OP_Rewind, csrEnd, 1);
  2143   2141   
  2144   2142     sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regFirst);
  2145   2143     addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
  2146   2144   
  2147   2145     /* Begin generating SECOND_ROW_CODE */
  2148   2146     VdbeModuleComment((pParse->pVdbe, "Begin windowCodeStep.SECOND_ROW_CODE"));
  2149   2147     if( bCache ){
  2150   2148       addrCacheNext = sqlite3VdbeCurrentAddr(v);
  2151   2149     }else{
  2152   2150       sqlite3VdbeJumpHere(v, addrIf);
  2153   2151     }
  2154   2152     if( pMWin->eStart==TK_FOLLOWING ){
         2153  +    windowCodeOp(&s, WINDOW_AGGSTEP, csrEnd, 0, 0);
  2155   2154       windowCodeOp(&s, WINDOW_RETURN_ROW, csrCurrent, regEnd, 0);
  2156   2155       windowCodeOp(&s, WINDOW_AGGINVERSE, csrStart, regStart, 0);
  2157   2156     }else
  2158   2157     if( pMWin->eEnd==TK_PRECEDING ){
  2159   2158       windowCodeOp(&s, WINDOW_AGGSTEP, csrEnd, regEnd, 0);
  2160   2159       windowCodeOp(&s, WINDOW_RETURN_ROW, csrCurrent, 0, 0);
  2161   2160       windowCodeOp(&s, WINDOW_AGGINVERSE, csrStart, regStart, 0);
  2162   2161     }else{
  2163         -    int addr = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1);
         2162  +    int addr;
         2163  +    windowCodeOp(&s, WINDOW_AGGSTEP, csrEnd, 0, 0);
         2164  +    addr = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1);
  2164   2165       windowCodeOp(&s, WINDOW_RETURN_ROW, csrCurrent, 0, 0);
  2165   2166       windowCodeOp(&s, WINDOW_AGGINVERSE, csrStart, regStart, 0);
  2166   2167       sqlite3VdbeJumpHere(v, addr);
  2167   2168     }
  2168   2169     VdbeModuleComment((pParse->pVdbe, "End windowCodeStep.SECOND_ROW_CODE"));
  2169   2170   
  2170         -  VdbeModuleComment((pParse->pVdbe, "Begin windowCodeStep.ALL_ROW_CODE"));
  2171         -  sqlite3VdbeJumpHere(v, addrGoto);
  2172         -  if( pMWin->eEnd!=TK_PRECEDING ){
  2173         -    windowCodeOp(&s, WINDOW_AGGSTEP, csrEnd, 0, 0);
  2174         -  }
  2175         -  VdbeModuleComment((pParse->pVdbe, "End windowCodeStep.ALL_ROW_CODE"));
  2176         -
  2177   2171     /* End of the main input loop */
         2172  +  sqlite3VdbeJumpHere(v, addrGoto);
  2178   2173     if( bCache ){
  2179   2174       sqlite3VdbeAddOp2(v, OP_Next, csrWrite, addrCacheNext);
  2180   2175       sqlite3VdbeJumpHere(v, addrCacheRewind); 
  2181   2176     }else{
  2182   2177       if( addrShortcut>0 ) sqlite3VdbeJumpHere(v, addrShortcut);
  2183   2178       sqlite3WhereEnd(pWInfo);
  2184   2179     }
  2185   2180   
  2186   2181     /* Fall through */
  2187         -
  2188         -  VdbeModuleComment((pParse->pVdbe, "Begin windowCodeStep.FLUSH_CODE"));
  2189   2182     if( pMWin->pPartition && bCache==0 ){
  2190   2183       addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart);
  2191   2184       sqlite3VdbeJumpHere(v, addrGosubFlush);
  2192   2185     }
  2193   2186   
         2187  +  VdbeModuleComment((pParse->pVdbe, "Begin windowCodeStep.FLUSH_CODE"));
         2188  +  addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite);
  2194   2189     if( pMWin->eEnd==TK_PRECEDING ){
  2195         -    windowCodeOp(&s, WINDOW_AGGSTEP, csrEnd, regEnd, 1);
  2196         -    windowCodeOp(&s, WINDOW_RETURN_ROW, csrCurrent, 0, 1);
         2190  +    windowCodeOp(&s, WINDOW_AGGSTEP, csrEnd, regEnd, 0);
         2191  +    windowCodeOp(&s, WINDOW_RETURN_ROW, csrCurrent, 0, 0);
         2192  +  }else if( pMWin->eStart==TK_FOLLOWING ){
         2193  +    int addrStart;
         2194  +    int addrBreak1;
         2195  +    int addrBreak2;
         2196  +    int addrBreak3;
         2197  +    windowCodeOp(&s, WINDOW_AGGSTEP, csrEnd, 0, 0);
         2198  +    addrStart = sqlite3VdbeCurrentAddr(v);
         2199  +    addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, csrCurrent, regEnd, 1);
         2200  +    addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, csrStart, regStart, 1);
         2201  +    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
         2202  +    sqlite3VdbeJumpHere(v, addrBreak2);
         2203  +    addrStart = sqlite3VdbeCurrentAddr(v);
         2204  +    addrBreak3 = windowCodeOp(&s, WINDOW_RETURN_ROW, csrCurrent, 0, 1);
         2205  +    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
         2206  +    sqlite3VdbeJumpHere(v, addrBreak1);
         2207  +    sqlite3VdbeJumpHere(v, addrBreak3);
  2197   2208     }else{
  2198   2209       int addrBreak;
  2199         -    int addrStart = sqlite3VdbeCurrentAddr(v);
  2200         -    if( pMWin->eStart==TK_FOLLOWING ){
  2201         -      addrBreak = windowCodeOp(&s, WINDOW_RETURN_ROW, csrCurrent, regEnd, 1);
  2202         -      windowCodeOp(&s, WINDOW_AGGINVERSE, csrStart, regStart, 1);
  2203         -    }else{
  2204         -      addrBreak = windowCodeOp(&s, WINDOW_RETURN_ROW, csrCurrent, 0, 1);
  2205         -      windowCodeOp(&s, WINDOW_AGGINVERSE, csrStart, regStart, 0);
  2206         -    }
         2210  +    int addrStart;
         2211  +    windowCodeOp(&s, WINDOW_AGGSTEP, csrEnd, 0, 0);
         2212  +    addrStart = sqlite3VdbeCurrentAddr(v);
         2213  +    addrBreak = windowCodeOp(&s, WINDOW_RETURN_ROW, csrCurrent, 0, 1);
         2214  +    windowCodeOp(&s, WINDOW_AGGINVERSE, csrStart, regStart, 0);
  2207   2215       sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
  2208   2216       sqlite3VdbeJumpHere(v, addrBreak);
  2209   2217     }
         2218  +
         2219  +  sqlite3VdbeJumpHere(v, addrEmpty);
  2210   2220   
  2211   2221     if( bCache && addrShortcut>0 ) sqlite3VdbeJumpHere(v, addrShortcut);
  2212   2222     sqlite3VdbeAddOp1(v, OP_ResetSorter, csrCurrent);
  2213   2223     sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regSize);
  2214   2224     if( bCache==0 ) sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regFirst);
  2215   2225     VdbeModuleComment((pParse->pVdbe, "End windowCodeStep.FLUSH_CODE"));
  2216   2226     if( pMWin->pPartition ){
................................................................................
  2677   2687     ** windowCodeDefaultStep() is the only one of the three functions that
  2678   2688     ** does not cache each partition in a temp table before beginning to
  2679   2689     ** return rows.
  2680   2690     */
  2681   2691     if( pMWin->eType==TK_ROWS 
  2682   2692      && (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy)
  2683   2693     ){
  2684         -    if( (pMWin->eStart!=TK_PRECEDING && pMWin->eStart!=TK_FOLLOWING)
  2685         -     || (pMWin->eEnd!=TK_FOLLOWING && pMWin->eEnd!=TK_PRECEDING) 
         2694  +    int bCache = windowCachePartition(pMWin);
         2695  +    if( (pMWin->eEnd!=TK_FOLLOWING   && pMWin->eEnd!=TK_PRECEDING) 
         2696  +     || (pMWin->eStart!=TK_FOLLOWING && pMWin->eStart!=TK_PRECEDING) 
  2686   2697       ){
  2687   2698         VdbeModuleComment((pParse->pVdbe, "Begin RowExprStep()"));
  2688   2699         windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub);
  2689   2700         VdbeModuleComment((pParse->pVdbe, "End RowExprStep()"));
  2690   2701       }else{
  2691   2702         VdbeModuleComment((pParse->pVdbe, "Begin windowCodeStep()"));
  2692   2703         windowCodeStep(pParse, p, pWInfo, regGosub, addrGosub);