diff options
author | drh <drh@noemail.net> | 2014-09-02 15:49:47 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2014-09-02 15:49:47 +0000 |
commit | bf9ed6f9af8db145efb7294b1bb05b35fc70e7fc (patch) | |
tree | 870d850426bb945aee018a2dc2612f52f3248619 /src/vdbe.c | |
parent | e1ed0b0e1787b0e5c6b2b59de4e2f161a82bec22 (diff) | |
parent | f8ede57a6165889316f8a9df8ac1166c7a568100 (diff) | |
download | sqlite-bf9ed6f9af8db145efb7294b1bb05b35fc70e7fc.tar.gz sqlite-bf9ed6f9af8db145efb7294b1bb05b35fc70e7fc.zip |
Merge the latest trunk changes, including the multi-threaded sorter, into
the sessions branch.
FossilOrigin-Name: d4cce2c71e64ab7b6a65a81b88b69445ed859351
Diffstat (limited to 'src/vdbe.c')
-rw-r--r-- | src/vdbe.c | 116 |
1 files changed, 49 insertions, 67 deletions
diff --git a/src/vdbe.c b/src/vdbe.c index 0f76cff82..36f05afbc 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1175,7 +1175,7 @@ case OP_Move: { assert( pIn1<=&aMem[(p->nMem-p->nCursor)] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); - VdbeMemReleaseExtern(pOut); + sqlite3VdbeMemRelease(pOut); zMalloc = pOut->zMalloc; memcpy(pOut, pIn1, sizeof(Mem)); #ifdef SQLITE_DEBUG @@ -1555,8 +1555,8 @@ case OP_Function: { apVal = p->apArg; assert( apVal || n==0 ); assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - pOut = &aMem[pOp->p3]; - memAboutToChange(p, pOut); + ctx.pOut = &aMem[pOp->p3]; + memAboutToChange(p, ctx.pOut); assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); @@ -1572,16 +1572,7 @@ case OP_Function: { ctx.pFunc = pOp->p4.pFunc; ctx.iOp = pc; ctx.pVdbe = p; - - /* The output cell may already have a buffer allocated. Move - ** the pointer to ctx.s so in case the user-function can use - ** the already allocated buffer instead of allocating a new one. - */ - memcpy(&ctx.s, pOut, sizeof(Mem)); - pOut->flags = MEM_Null; - pOut->xDel = 0; - pOut->zMalloc = 0; - MemSetTypeFlag(&ctx.s, MEM_Null); + MemSetTypeFlag(ctx.pOut, MEM_Null); ctx.fErrorOrAux = 0; if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ @@ -1594,43 +1585,23 @@ case OP_Function: { (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */ lastRowid = db->lastRowid; - if( db->mallocFailed ){ - /* Even though a malloc() has failed, the implementation of the - ** user function may have called an sqlite3_result_XXX() function - ** to return a value. The following call releases any resources - ** associated with such a value. - */ - sqlite3VdbeMemRelease(&ctx.s); - goto no_mem; - } - /* If the function returned an error, throw an exception */ if( ctx.fErrorOrAux ){ if( ctx.isError ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(ctx.pOut)); rc = ctx.isError; } sqlite3VdbeDeleteAuxData(p, pc, pOp->p1); } /* Copy the result of the function into register P3 */ - sqlite3VdbeChangeEncoding(&ctx.s, encoding); - assert( pOut->flags==MEM_Null ); - memcpy(pOut, &ctx.s, sizeof(Mem)); - if( sqlite3VdbeMemTooBig(pOut) ){ + sqlite3VdbeChangeEncoding(ctx.pOut, encoding); + if( sqlite3VdbeMemTooBig(ctx.pOut) ){ goto too_big; } -#if 0 - /* The app-defined function has done something that as caused this - ** statement to expire. (Perhaps the function called sqlite3_exec() - ** with a CREATE TABLE statement.) - */ - if( p->expired ) rc = SQLITE_ABORT; -#endif - - REGISTER_TRACE(pOp->p3, pOut); - UPDATE_MAX_BLOBSIZE(pOut); + REGISTER_TRACE(pOp->p3, ctx.pOut); + UPDATE_MAX_BLOBSIZE(ctx.pOut); break; } @@ -1779,6 +1750,7 @@ case OP_RealAffinity: { /* in1 */ #ifndef SQLITE_OMIT_CAST /* Opcode: Cast P1 P2 * * * +** Synopsis: affinity(r[P1]) ** ** Force the value in register P1 to be the type defined by P2. ** @@ -3400,11 +3372,15 @@ case OP_OpenEphemeral: { break; } -/* Opcode: SorterOpen P1 P2 * P4 * +/* Opcode: SorterOpen P1 P2 P3 P4 * ** ** This opcode works like OP_OpenEphemeral except that it opens ** a transient index that is specifically designed to sort large ** tables using an external merge-sort algorithm. +** +** If argument P3 is non-zero, then it indicates that the sorter may +** assume that a stable sort considering the first P3 fields of each +** key is sufficient to produce the required results. */ case OP_SorterOpen: { VdbeCursor *pCx; @@ -3416,7 +3392,25 @@ case OP_SorterOpen: { pCx->pKeyInfo = pOp->p4.pKeyInfo; assert( pCx->pKeyInfo->db==db ); assert( pCx->pKeyInfo->enc==ENC(db) ); - rc = sqlite3VdbeSorterInit(db, pCx); + rc = sqlite3VdbeSorterInit(db, pOp->p3, pCx); + break; +} + +/* Opcode: SequenceTest P1 P2 * * * +** Synopsis: if( cursor[P1].ctr++ ) pc = P2 +** +** P1 is a sorter cursor. If the sequence counter is currently zero, jump +** to P2. Regardless of whether or not the jump is taken, increment the +** the sequence value. +*/ +case OP_SequenceTest: { + VdbeCursor *pC; + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC->pSorter ); + if( (pC->seqCount++)==0 ){ + pc = pOp->p2 - 1; + } break; } @@ -4316,6 +4310,7 @@ case OP_SorterCompare: { assert( pOp->p4type==P4_INT32 ); pIn3 = &aMem[pOp->p3]; nKeyCol = pOp->p4.i; + res = 0; rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res); VdbeBranchTaken(res!=0,2); if( res ){ @@ -4580,7 +4575,7 @@ case OP_Rewind: { /* jump */ pC->seekOp = OP_Rewind; #endif if( isSorter(pC) ){ - rc = sqlite3VdbeSorterRewind(db, pC, &res); + rc = sqlite3VdbeSorterRewind(pC, &res); }else{ pCrsr = pC->pCursor; assert( pCrsr ); @@ -4758,7 +4753,7 @@ case OP_IdxInsert: { /* in2 */ rc = ExpandBlob(pIn2); if( rc==SQLITE_OK ){ if( isSorter(pC) ){ - rc = sqlite3VdbeSorterWrite(db, pC, pIn2); + rc = sqlite3VdbeSorterWrite(pC, pIn2); }else{ nKey = pIn2->n; zKey = pIn2->z; @@ -5671,6 +5666,7 @@ case OP_AggStep: { int i; Mem *pMem; Mem *pRec; + Mem t; sqlite3_context ctx; sqlite3_value **apVal; @@ -5688,11 +5684,12 @@ case OP_AggStep: { assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); ctx.pMem = pMem = &aMem[pOp->p3]; pMem->n++; - ctx.s.flags = MEM_Null; - ctx.s.z = 0; - ctx.s.zMalloc = 0; - ctx.s.xDel = 0; - ctx.s.db = db; + t.flags = MEM_Null; + t.z = 0; + t.zMalloc = 0; + t.xDel = 0; + t.db = db; + ctx.pOut = &t; ctx.isError = 0; ctx.pColl = 0; ctx.skipFlag = 0; @@ -5704,7 +5701,7 @@ case OP_AggStep: { } (ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */ if( ctx.isError ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&t)); rc = ctx.isError; } if( ctx.skipFlag ){ @@ -5712,9 +5709,7 @@ case OP_AggStep: { i = pOp[-1].p1; if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); } - - sqlite3VdbeMemRelease(&ctx.s); - + sqlite3VdbeMemRelease(&t); break; } @@ -6164,27 +6159,14 @@ case OP_VColumn: { pModule = pVtab->pModule; assert( pModule->xColumn ); memset(&sContext, 0, sizeof(sContext)); - - /* The output cell may already have a buffer allocated. Move - ** the current contents to sContext.s so in case the user-function - ** can use the already allocated buffer instead of allocating a - ** new one. - */ - sqlite3VdbeMemMove(&sContext.s, pDest); - MemSetTypeFlag(&sContext.s, MEM_Null); - + sContext.pOut = pDest; + MemSetTypeFlag(pDest, MEM_Null); rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2); sqlite3VtabImportErrmsg(p, pVtab); if( sContext.isError ){ rc = sContext.isError; } - - /* Copy the result of the function to the P3 register. We - ** do this regardless of whether or not an error occurred to ensure any - ** dynamic allocation in sContext.s (a Mem struct) is released. - */ - sqlite3VdbeChangeEncoding(&sContext.s, encoding); - sqlite3VdbeMemMove(pDest, &sContext.s); + sqlite3VdbeChangeEncoding(pDest, encoding); REGISTER_TRACE(pOp->p3, pDest); UPDATE_MAX_BLOBSIZE(pDest); |