1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Add further tests for new window function functionality.

FossilOrigin-Name: 1fbddf01b1c3fff95b05e2f2f709754e2b514296060b4846518791e7161d9ddb
This commit is contained in:
dan
2019-03-18 21:19:40 +00:00
parent 108e6b2c87
commit 0525b6f47f
6 changed files with 30051 additions and 1287 deletions

View File

@@ -248,16 +248,9 @@ static void nth_valueStepFunc(
pCtx, "second argument to nth_value must be a positive integer", -1
);
}
static void nth_valueValueFunc(sqlite3_context *pCtx){
struct NthValueCtx *p;
p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
if( p && p->pValue ){
sqlite3_result_value(pCtx, p->pValue);
}
}
static void nth_valueFinalizeFunc(sqlite3_context *pCtx){
struct NthValueCtx *p;
p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, 0);
if( p && p->pValue ){
sqlite3_result_value(pCtx, p->pValue);
sqlite3_value_free(p->pValue);
@@ -265,6 +258,7 @@ static void nth_valueFinalizeFunc(sqlite3_context *pCtx){
}
}
#define nth_valueInvFunc noopStepFunc
#define nth_valueValueFunc noopValueFunc
static void first_valueStepFunc(
sqlite3_context *pCtx,
@@ -282,13 +276,6 @@ static void first_valueStepFunc(
UNUSED_PARAMETER(nArg);
UNUSED_PARAMETER(apArg);
}
static void first_valueValueFunc(sqlite3_context *pCtx){
struct NthValueCtx *p;
p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
if( p && p->pValue ){
sqlite3_result_value(pCtx, p->pValue);
}
}
static void first_valueFinalizeFunc(sqlite3_context *pCtx){
struct NthValueCtx *p;
p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
@@ -299,6 +286,7 @@ static void first_valueFinalizeFunc(sqlite3_context *pCtx){
}
}
#define first_valueInvFunc noopStepFunc
#define first_valueValueFunc noopValueFunc
/*
** Implementation of built-in window function rank(). Assumes that
@@ -404,8 +392,8 @@ static void cume_distInvFunc(
}
static void cume_distValueFunc(sqlite3_context *pCtx){
struct CallCount *p;
p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
if( p && p->nTotal ){
p = (struct CallCount*)sqlite3_aggregate_context(pCtx, 0);
if( p ){
double r = (double)(p->nStep) / (double)(p->nTotal);
sqlite3_result_double(pCtx, r);
}
@@ -529,7 +517,7 @@ static void last_valueInvFunc(
}
static void last_valueValueFunc(sqlite3_context *pCtx){
struct LastValueCtx *p;
p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, 0);
if( p && p->pVal ){
sqlite3_result_value(pCtx, p->pVal);
}
@@ -1405,8 +1393,6 @@ static void windowAggStep(
);
assert( bInverse==0 || bInverse==1 );
sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1);
}else if( pFunc->zName==leadName || pFunc->zName==lagName ){
/* no-op */
}else if( pFunc->xSFunc!=noopStepFunc ){
int addrIf = 0;
if( pWin->pFilter ){
@@ -1506,9 +1492,6 @@ static void windowAggFinal(WindowCodeArg *p, int bFin){
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_Column, pWin->csrApp, 0, pWin->regResult);
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
if( bFin ){
sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp);
}
}else if( pWin->regApp ){
assert( pMWin->regStartRowid==0 );
}else{
@@ -1526,6 +1509,12 @@ static void windowAggFinal(WindowCodeArg *p, int bFin){
}
}
/*
** Generate code to calculate the current values of all window functions in the
** p->pMWin list by doing a full scan of the current window frame. Store the
** results in the Window.regResult registers, ready to return the upper
** layer.
*/
static void windowFullScan(WindowCodeArg *p){
Window *pWin;
Parse *pParse = p->pParse;
@@ -1828,11 +1817,17 @@ static void windowCodeRangeTest(
sqlite3ReleaseTempReg(pParse, reg2);
}
/*
** Helper function for sqlite3WindowCodeStep(). Each call to this function
** generates VM code for a single RETURN_ROW, AGGSTEP or AGGINVERSE
** operation. Refer to the header comment for sqlite3WindowCodeStep() for
** details.
*/
static int windowCodeOp(
WindowCodeArg *p,
int op,
int regCountdown,
int jumpOnEof
WindowCodeArg *p, /* Context object */
int op, /* WINDOW_RETURN_ROW, AGGSTEP or AGGINVERSE */
int regCountdown, /* Register for OP_IfPos countdown */
int jumpOnEof /* Jump here if stepped cursor reaches EOF */
){
int csr, reg;
Parse *pParse = p->pParse;
@@ -1857,40 +1852,28 @@ static int windowCodeOp(
if( regCountdown>0 ){
if( pMWin->eType==TK_RANGE ){
addrNextRange = sqlite3VdbeCurrentAddr(v);
switch( op ){
case WINDOW_RETURN_ROW: {
assert( 0 );
break;
}
case WINDOW_AGGINVERSE: {
if( pMWin->eStart==TK_FOLLOWING ){
windowCodeRangeTest(
p, OP_Le, p->current.csr, regCountdown, p->start.csr, lblDone
);
}else{
windowCodeRangeTest(
p, OP_Ge, p->start.csr, regCountdown, p->current.csr, lblDone
);
}
break;
}
case WINDOW_AGGSTEP: {
assert( op==WINDOW_AGGINVERSE || op==WINDOW_AGGSTEP );
if( op==WINDOW_AGGINVERSE ){
if( pMWin->eStart==TK_FOLLOWING ){
windowCodeRangeTest(
p, OP_Gt, p->end.csr, regCountdown, p->current.csr, lblDone
p, OP_Le, p->current.csr, regCountdown, p->start.csr, lblDone
);
}else{
windowCodeRangeTest(
p, OP_Ge, p->start.csr, regCountdown, p->current.csr, lblDone
);
break;
}
}else{
windowCodeRangeTest(
p, OP_Gt, p->end.csr, regCountdown, p->current.csr, lblDone
);
}
}else{
addrIf = sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, 0, 1);
}
}
if( op==WINDOW_RETURN_ROW ){
if( op==WINDOW_RETURN_ROW && pMWin->regStartRowid==0 ){
windowAggFinal(p, 0);
}
addrContinue = sqlite3VdbeCurrentAddr(v);
@@ -1912,7 +1895,8 @@ static int windowCodeOp(
}
break;
case WINDOW_AGGSTEP:
default:
assert( op==WINDOW_AGGSTEP );
csr = p->end.csr;
reg = p->end.reg;
if( pMWin->regStartRowid ){
@@ -2421,8 +2405,6 @@ void sqlite3WindowCodeStep(
break;
}
s.eDelete = 0;
/* Allocate registers for the array of values from the sub-query, the
** samve values in record form, and the rowid used to insert said record
** into the ephemeral table. */
@@ -2501,7 +2483,7 @@ void sqlite3WindowCodeStep(
windowCheckValue(pParse, regEnd, 1 + (pMWin->eType==TK_RANGE ? 3 : 0));
}
if( pMWin->eStart==pMWin->eEnd && regStart && regEnd ){
if( pMWin->eStart==pMWin->eEnd && regStart ){
int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le);
int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd);
windowAggFinal(&s, 0);