Use separate opcodes, OP_AggValue and OP_AggInverse, for the new callbacks
associated with Window Functions, for improved readability of EXPLAIN output. FossilOrigin-Name: fa6538050938ffeb042fbee31512514d6d3ace514b2a3dfd8365bbeb13f35a78
This commit is contained in:
+1
-1
@@ -5187,7 +5187,7 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
|
||||
if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem);
|
||||
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, pF->iMem);
|
||||
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
|
||||
sqlite3VdbeChangeP5(v, (u8)nArg);
|
||||
sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
|
||||
|
||||
+40
-12
@@ -6288,18 +6288,29 @@ case OP_DecrJumpZero: { /* jump, in1 */
|
||||
}
|
||||
|
||||
|
||||
/* Opcode: AggStep0 P1 P2 P3 P4 P5
|
||||
/* Opcode: AggStep * P2 P3 P4 P5
|
||||
** Synopsis: accum=r[P3] step(r[P2@P5])
|
||||
**
|
||||
** Execute the xStep (if P1==0) or xInverse (if P1!=0) function for an
|
||||
** aggregate. The function has P5 arguments. P4 is a pointer to the
|
||||
** Execute the xStep function for an aggregate.
|
||||
** The function has P5 arguments. P4 is a pointer to the
|
||||
** FuncDef structure that specifies the function. Register P3 is the
|
||||
** accumulator.
|
||||
**
|
||||
** The P5 arguments are taken from register P2 and its
|
||||
** successors.
|
||||
*/
|
||||
/* Opcode: AggStep P1 P2 P3 P4 P5
|
||||
/* Opcode: AggInverse * P2 P3 P4 P5
|
||||
** Synopsis: accum=r[P3] inverse(r[P2@P5])
|
||||
**
|
||||
** Execute the xInverse function for an aggregate.
|
||||
** The function has P5 arguments. P4 is a pointer to the
|
||||
** FuncDef structure that specifies the function. Register P3 is the
|
||||
** accumulator.
|
||||
**
|
||||
** The P5 arguments are taken from register P2 and its
|
||||
** successors.
|
||||
*/
|
||||
/* Opcode: AggStep1 P1 P2 P3 P4 P5
|
||||
** Synopsis: accum=r[P3] step(r[P2@P5])
|
||||
**
|
||||
** Execute the xStep (if P1==0) or xInverse (if P1!=0) function for an
|
||||
@@ -6316,7 +6327,8 @@ case OP_DecrJumpZero: { /* jump, in1 */
|
||||
** sqlite3_context only happens once, instead of on each call to the
|
||||
** step function.
|
||||
*/
|
||||
case OP_AggStep0: {
|
||||
case OP_AggInverse:
|
||||
case OP_AggStep: {
|
||||
int n;
|
||||
sqlite3_context *pCtx;
|
||||
|
||||
@@ -6339,10 +6351,11 @@ case OP_AggStep0: {
|
||||
pCtx->argc = n;
|
||||
pOp->p4type = P4_FUNCCTX;
|
||||
pOp->p4.pCtx = pCtx;
|
||||
pOp->opcode = OP_AggStep;
|
||||
assert( pOp->p1==(pOp->opcode==OP_AggInverse) );
|
||||
pOp->opcode = OP_AggStep1;
|
||||
/* Fall through into OP_AggStep */
|
||||
}
|
||||
case OP_AggStep: {
|
||||
case OP_AggStep1: {
|
||||
int i;
|
||||
sqlite3_context *pCtx;
|
||||
Mem *pMem;
|
||||
@@ -6399,13 +6412,12 @@ case OP_AggStep: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: AggFinal P1 P2 P3 P4 *
|
||||
/* Opcode: AggFinal P1 P2 * P4 *
|
||||
** Synopsis: accum=r[P1] N=P2
|
||||
**
|
||||
** P1 is the memory location that is the accumulator for an aggregate
|
||||
** or window function. If P3 is zero, then execute the finalizer function
|
||||
** for an aggregate and store the result in P1. Or, if P3 is non-zero,
|
||||
** invoke the xValue() function and store the result in register P3.
|
||||
** or window function. Execute the finalizer function
|
||||
** for an aggregate and store the result in P1.
|
||||
**
|
||||
** P2 is the number of arguments that the step function takes and
|
||||
** P4 is a pointer to the FuncDef for this function. The P2
|
||||
@@ -6414,9 +6426,23 @@ case OP_AggStep: {
|
||||
** P4 argument is only needed for the case where
|
||||
** the step function was not previously called.
|
||||
*/
|
||||
/* Opcode: AggValue * P2 P3 P4 *
|
||||
** Synopsis: r[P3]=value N=P2
|
||||
**
|
||||
** Invoke the xValue() function and store the result in register P3.
|
||||
**
|
||||
** P2 is the number of arguments that the step function takes and
|
||||
** P4 is a pointer to the FuncDef for this function. The P2
|
||||
** argument is not used by this opcode. It is only there to disambiguate
|
||||
** functions that can take varying numbers of arguments. The
|
||||
** P4 argument is only needed for the case where
|
||||
** the step function was not previously called.
|
||||
*/
|
||||
case OP_AggValue:
|
||||
case OP_AggFinal: {
|
||||
Mem *pMem;
|
||||
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
|
||||
assert( pOp->p3==0 || pOp->opcode==OP_AggValue );
|
||||
pMem = &aMem[pOp->p1];
|
||||
assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
@@ -6425,7 +6451,9 @@ case OP_AggFinal: {
|
||||
pMem = &aMem[pOp->p3];
|
||||
}else
|
||||
#endif
|
||||
rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
|
||||
{
|
||||
rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
|
||||
}
|
||||
|
||||
if( rc ){
|
||||
sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem));
|
||||
|
||||
@@ -435,6 +435,7 @@ int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.flags = MEM_Null;
|
||||
t.db = pAccum->db;
|
||||
sqlite3VdbeMemSetNull(pOut);
|
||||
ctx.pOut = pOut;
|
||||
ctx.pMem = pAccum;
|
||||
ctx.pFunc = pFunc;
|
||||
|
||||
+16
-16
@@ -988,7 +988,7 @@ static int windowArgCount(Window *pWin){
|
||||
** the first register in an array of registers guaranteed to be large
|
||||
** enough to hold the array of arguments for each function. In this case
|
||||
** the arguments are extracted from the current row of csr into the
|
||||
** array of registers before invoking OP_AggStep.
|
||||
** array of registers before invoking OP_AggStep or OP_AggInverse
|
||||
**
|
||||
** Or, if csr is less than zero, then the array of registers at reg is
|
||||
** already populated with all columns from the current row of the sub-query.
|
||||
@@ -1076,7 +1076,8 @@ static void windowAggStep(
|
||||
pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr);
|
||||
sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_AggStep0, bInverse, regArg, pWin->regAccum);
|
||||
sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep,
|
||||
bInverse, regArg, pWin->regAccum);
|
||||
sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
|
||||
sqlite3VdbeChangeP5(v, (u8)nArg);
|
||||
if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
|
||||
@@ -1108,16 +1109,15 @@ static void windowAggFinal(Parse *pParse, Window *pMWin, int bFinal){
|
||||
}
|
||||
}else if( pWin->regApp ){
|
||||
}else{
|
||||
if( bFinal==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, windowArgCount(pWin));
|
||||
sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
|
||||
if( bFinal ){
|
||||
sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, windowArgCount(pWin));
|
||||
sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult);
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
|
||||
}else{
|
||||
sqlite3VdbeChangeP3(v, -1, pWin->regResult);
|
||||
sqlite3VdbeAddOp3(v, OP_AggValue, pWin->regAccum, windowArgCount(pWin),
|
||||
pWin->regResult);
|
||||
sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1273,7 +1273,7 @@ static void windowReturnOneRow(
|
||||
** regCtr--;
|
||||
** windowReturnOneRow()
|
||||
** if( bInverse ){
|
||||
** AggStep (xInverse)
|
||||
** AggInverse
|
||||
** }
|
||||
** Next (Window.iEphCsr)
|
||||
** }
|
||||
@@ -1367,7 +1367,7 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){
|
||||
** Gosub addrGosub
|
||||
** Next(csr) // if EOF goto flush_partition_done
|
||||
** if( (regStart--)<=0 ){
|
||||
** AggStep (csrStart, xInverse)
|
||||
** AggInverse (csrStart)
|
||||
** Next(csrStart)
|
||||
** }
|
||||
** }
|
||||
@@ -1395,7 +1395,7 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){
|
||||
** Gosub addrGosub
|
||||
** Next(csr) // if EOF goto flush_partition_done
|
||||
** if( (regStart--)<=0 ){
|
||||
** AggStep (csrStart, xInverse)
|
||||
** AggInverse (csrStart)
|
||||
** Next(csrStart)
|
||||
** }
|
||||
** }
|
||||
@@ -1418,7 +1418,7 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){
|
||||
** if( new peer ) break;
|
||||
** }
|
||||
** while( (regPeer--)>0 ){
|
||||
** AggStep (csrStart, xInverse)
|
||||
** AggInverse (csrStart)
|
||||
** Next(csrStart)
|
||||
** }
|
||||
** }
|
||||
@@ -1435,7 +1435,7 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){
|
||||
** Gosub addrGosub
|
||||
** Next(csr) // if EOF goto flush_partition_done
|
||||
** }
|
||||
** AggStep (csrStart, xInverse)
|
||||
** AggInverse (csrStart)
|
||||
** Next (csrStart)
|
||||
** }
|
||||
**
|
||||
@@ -1451,7 +1451,7 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){
|
||||
** Gosub addrGosub
|
||||
** Next(csr) // if EOF goto flush_partition_done
|
||||
** if( (regStart--)<=0 ){
|
||||
** AggStep (csr2, xInverse)
|
||||
** AggInverse (csr2)
|
||||
** Next (csr2)
|
||||
** }
|
||||
**
|
||||
@@ -1682,7 +1682,7 @@ static void windowCodeRowExprStep(
|
||||
**
|
||||
** for(i=0; i<ctr; i++){
|
||||
** Gosub addrGosub
|
||||
** AggStep (xInverse, iEphCsr)
|
||||
** AggInverse (iEphCsr)
|
||||
** Next iEphCsr
|
||||
** }
|
||||
**
|
||||
@@ -1715,7 +1715,7 @@ static void windowCodeRowExprStep(
|
||||
** AggFinal (xValue)
|
||||
** for(i=0; i<ctr; i++){
|
||||
** Gosub addrGosub
|
||||
** AggStep (xInverse, iEphCsr)
|
||||
** AggInverse (iEphCsr)
|
||||
** Next iEphCsr
|
||||
** }
|
||||
** Integer ctr 0
|
||||
|
||||
Reference in New Issue
Block a user