SQLite

Check-in [180be26623]
Login

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

Overview
Comment:Avoid allocating excessive registers for the PARTITION BY expressions when processing window functions.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | window-functions
Files: files | file ages | folders
SHA3-256: 180be266238e18c01f8bd52c75dd9aa3e26e553620258141cd95189a0ae59ddb
User & Date: dan 2019-03-13 17:20:27.939
Context
2019-03-13
17:31
Merge latest trunk changes into this branch. (check-in: 0b904517bd user: dan tags: window-functions)
17:20
Avoid allocating excessive registers for the PARTITION BY expressions when processing window functions. (check-in: 180be26623 user: dan tags: window-functions)
15:29
Remove rows from the ephemeral table used by window functions once they are no longer required. (check-in: 6ad5531920 user: dan tags: window-functions)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/sqliteInt.h.
3567
3568
3569
3570
3571
3572
3573
3574

3575
3576
3577
3578
3579
3580
3581
3582
3567
3568
3569
3570
3571
3572
3573

3574

3575
3576
3577
3578
3579
3580
3581







-
+
-







  Expr *pFilter;          /* The FILTER expression */
  FuncDef *pFunc;         /* The function */
  int iEphCsr;            /* Partition buffer or Peer buffer */
  int regAccum;
  int regResult;
  int csrApp;             /* Function cursor (used by min/max) */
  int regApp;             /* Function register (also used by min/max) */
  int regPart;            /* First in a set of registers holding PARTITION BY
  int regPart;            /* Array of registers for PARTITION BY values */
                          ** and ORDER BY values for the window */
  Expr *pOwner;           /* Expression object this window is attached to */
  int nBufferCol;         /* Number of columns in buffer table */
  int iArgCol;            /* Offset of first argument for this function */
  int regFirst;
};

#ifndef SQLITE_OMIT_WINDOWFUNC
Changes to src/window.c.
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123





1124
1125
1126


1127
1128
1129
1130
1131
1132
1133
1114
1115
1116
1117
1118
1119
1120



1121
1122
1123
1124
1125
1126


1127
1128
1129
1130
1131
1132
1133
1134
1135







-
-
-
+
+
+
+
+

-
-
+
+







** This is called by code in select.c before it calls sqlite3WhereBegin()
** to begin iterating through the sub-query results. It is used to allocate
** and initialize registers and cursors used by sqlite3WindowCodeStep().
*/
void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){
  Window *pWin;
  Vdbe *v = sqlite3GetVdbe(pParse);
  int nPart = (pMWin->pPartition ? pMWin->pPartition->nExpr : 0);
  nPart += (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0);
  if( nPart ){

  /* Allocate registers to use for PARTITION BY values, if any. Initialize
  ** said registers to NULL.  */
  if( pMWin->pPartition ){
    int nExpr = pMWin->pPartition->nExpr;
    pMWin->regPart = pParse->nMem+1;
    pParse->nMem += nPart;
    sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nPart-1);
    pParse->nMem += nExpr;
    sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nExpr-1);
  }

  pMWin->regFirst = ++pParse->nMem;
  sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regFirst);

  for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
    FuncDef *p = pWin->pFunc;
2107
2108
2109
2110
2111
2112
2113


2114
2115
2116
2117
2118
2119
2120
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124







+
+







**         }
**         RETURN_ROW
**       }
**       while( !eof csrCurrent ){
**         RETURN_ROW
**       }
**
** The text above leaves out many details. Refer to the code and comments
** below for a more complete picture.
*/
void sqlite3WindowCodeStep(
  Parse *pParse,                  /* Parse context */
  Select *p,                      /* Rewritten SELECT statement */
  WhereInfo *pWInfo,              /* Context returned by sqlite3WhereBegin() */
  int regGosub,                   /* Register for OP_Gosub */
  int addrGosub                   /* OP_Gosub here to return each row */
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2302
2303
2304
2305
2306
2307
2308


2309
2310
2311
2312
2313
2314
2315







-
-







    sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.current.reg, pOrderBy->nExpr-1);
    sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.end.reg, pOrderBy->nExpr-1);
  }

  sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regFirst);
  sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd);

  /* Begin generating SECOND_ROW_CODE */
  VdbeModuleComment((pParse->pVdbe, "Begin WindowCodeStep.SECOND_ROW"));
  sqlite3VdbeJumpHere(v, addrIfNot);
  if( regPeer ){
    windowIfNewPeer(pParse, pOrderBy, regNewPeer, regPeer, lblWhereEnd);
  }
  if( pMWin->eStart==TK_FOLLOWING ){
    windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0);
    if( pMWin->eEnd!=TK_UNBOUNDED ){
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2352
2353
2354
2355
2356
2357
2358

2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369

2370
2371
2372
2373
2374
2375
2376







-











-







        if( regEnd ) addr = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1);
        windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
        windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
        if( regEnd ) sqlite3VdbeJumpHere(v, addr);
      }
    }
  }
  VdbeModuleComment((pParse->pVdbe, "End WindowCodeStep.SECOND_ROW"));

  /* End of the main input loop */
  sqlite3VdbeResolveLabel(v, lblWhereEnd);
  sqlite3WhereEnd(pWInfo);

  /* Fall through */
  if( pMWin->pPartition ){
    addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart);
    sqlite3VdbeJumpHere(v, addrGosubFlush);
  }

  VdbeModuleComment((pParse->pVdbe, "Begin WindowCodeStep.FLUSH"));
  addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite);
  if( pMWin->eEnd==TK_PRECEDING ){
    windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0);
    windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
  }else if( pMWin->eStart==TK_FOLLOWING ){
    int addrStart;
    int addrBreak1;
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2409
2410
2411
2412
2413
2414
2415

2416
2417
2418
2419
2420
2421
2422







-







    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
    sqlite3VdbeJumpHere(v, addrBreak);
  }
  sqlite3VdbeJumpHere(v, addrEmpty);

  sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr);
  sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regFirst);
  VdbeModuleComment((pParse->pVdbe, "End WindowCodeStep.FLUSH"));
  if( pMWin->pPartition ){
    sqlite3VdbeChangeP1(v, addrInteger, sqlite3VdbeCurrentAddr(v));
    sqlite3VdbeAddOp1(v, OP_Return, regFlushPart);
  }
}

#endif /* SQLITE_OMIT_WINDOWFUNC */