Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -560,10 +560,13 @@ int *aPermute = 0; /* Permutation of columns for OP_Compare */ i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ #ifdef VDBE_PROFILE u64 start; /* CPU clock count at start of opcode */ #endif + Op *pCtxOp = 0; /* Opcode for which ctx is initialized */ + sqlite3_context ctx; /* Function call context */ + /*** INSERT STACK UNION HERE ***/ assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ sqlite3VdbeEnter(p); if( p->rc==SQLITE_NOMEM ){ @@ -941,10 +944,11 @@ pcx = p->aOp[pcx].p2-1; } aOp = p->aOp; aMem = p->aMem; pOp = &aOp[pcx]; + pCtxOp = 0; break; } p->rc = pOp->p1; p->errorAction = (u8)pOp->p2; p->pc = pcx; @@ -1564,39 +1568,43 @@ ** See also: AggStep and AggFinal */ case OP_Function: { int i; Mem *pArg; - sqlite3_context ctx; sqlite3_value **apVal; int n; n = pOp->p5; - apVal = p->apArg; - assert( apVal || n==0 ); - assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - ctx.pOut = &aMem[pOp->p3]; + if( pOp!=pCtxOp ){ + apVal = p->apArg; + assert( apVal || n==0 ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + ctx.pOut = &aMem[pOp->p3]; + + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); + assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); + pArg = &aMem[pOp->p2]; + for(i=0; ip4type==P4_FUNCDEF ); + ctx.pFunc = pOp->p4.pFunc; + ctx.iOp = (int)(pOp - aOp); + ctx.pVdbe = p; + pCtxOp = pOp; + } +#ifdef SQLITE_DEBUG + for(i=0; iapArg[i]) ); + REGISTER_TRACE(pOp->p2+i, p->apArg[i]); + } +#endif memAboutToChange(p, ctx.pOut); - - assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); - assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); - pArg = &aMem[pOp->p2]; - for(i=0; ip2+i, pArg); - } - - assert( pOp->p4type==P4_FUNCDEF ); - ctx.pFunc = pOp->p4.pFunc; - ctx.iOp = (int)(pOp - aOp); - ctx.pVdbe = p; MemSetTypeFlag(ctx.pOut, MEM_Null); ctx.fErrorOrAux = 0; db->lastRowid = lastRowid; - (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */ + (*ctx.pFunc->xFunc)(&ctx, n, p->apArg); /* IMP: R-24505-23230 */ lastRowid = db->lastRowid; /* Remember rowid changes made by xFunc */ /* If the function returned an error, throw an exception */ if( ctx.fErrorOrAux ){ if( ctx.isError ){ @@ -5502,10 +5510,11 @@ p->aMem = aMem = &VdbeFrameMem(pFrame)[-1]; p->nMem = pFrame->nChildMem; p->nCursor = (u16)pFrame->nChildCsr; p->apCsr = (VdbeCursor **)&aMem[p->nMem+1]; p->aOp = aOp = pProgram->aOp; + pCtxOp = 0; p->nOp = pProgram->nOp; p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; p->nOnceFlag = pProgram->nOnce; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS p->anExec = 0; @@ -5712,39 +5721,40 @@ int n; int i; Mem *pMem; Mem *pRec; Mem t; - sqlite3_context ctx; + sqlite3_context actx; sqlite3_value **apVal; n = pOp->p5; assert( n>=0 ); pRec = &aMem[pOp->p2]; + pCtxOp = 0; apVal = p->apArg; assert( apVal || n==0 ); for(i=0; ip4.pFunc; + actx.pFunc = pOp->p4.pFunc; assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - ctx.pMem = pMem = &aMem[pOp->p3]; + actx.pMem = pMem = &aMem[pOp->p3]; pMem->n++; sqlite3VdbeMemInit(&t, db, MEM_Null); - ctx.pOut = &t; - ctx.isError = 0; - ctx.pVdbe = p; - ctx.iOp = (int)(pOp - aOp); - ctx.skipFlag = 0; - (ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */ - if( ctx.isError ){ + actx.pOut = &t; + actx.isError = 0; + actx.pVdbe = p; + actx.iOp = (int)(pOp - aOp); + actx.skipFlag = 0; + (actx.pFunc->xStep)(&actx, n, apVal); /* IMP: R-24505-23230 */ + if( actx.isError ){ sqlite3VdbeError(p, "%s", sqlite3_value_text(&t)); - rc = ctx.isError; + rc = actx.isError; } - if( ctx.skipFlag ){ + if( actx.skipFlag ){ assert( pOp[-1].opcode==OP_CollSeq ); i = pOp[-1].p1; if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); } sqlite3VdbeMemRelease(&t); @@ -6170,10 +6180,11 @@ res = 0; apArg = p->apArg; for(i = 0; ixFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); sqlite3VtabImportErrmsg(p, pVtab); if( rc==SQLITE_OK ){ res = pModule->xEof(pVtabCursor); } @@ -6353,10 +6364,11 @@ nArg = pOp->p2; assert( pOp->p4type==P4_VTAB ); if( ALWAYS(pModule->xUpdate) ){ u8 vtabOnConflict = db->vtabOnConflict; apArg = p->apArg; + pCtxOp = 0; pX = &aMem[pOp->p3]; for(i=0; i