From 569c6676a6ddb0ff73821d7693b5e18ddef809b9 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 16 Oct 2014 22:51:35 -0400 Subject: Imported Upstream version 3.2.0 --- src/vdbe.c | 2779 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 1538 insertions(+), 1241 deletions(-) (limited to 'src/vdbe.c') diff --git a/src/vdbe.c b/src/vdbe.c index f343e13..61adb9c 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -9,33 +9,8 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** The code in this file implements execution method of the -** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c") -** handles housekeeping details such as creating and deleting -** VDBE instances. This file is solely interested in executing -** the VDBE program. -** -** In the external interface, an "sqlite3_stmt*" is an opaque pointer -** to a VDBE. -** -** The SQL parser generates a program which is then executed by -** the VDBE to do the work of the SQL statement. VDBE programs are -** similar in form to assembly language. The program consists of -** a linear sequence of operations. Each operation has an opcode -** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4 -** is a null-terminated string. Operand P5 is an unsigned character. -** Few opcodes use all 5 operands. -** -** Computation results are stored on a set of registers numbered beginning -** with 1 and going up to Vdbe.nMem. Each register can store -** either an integer, a null-terminated string, a floating point -** number, or the SQL "NULL" value. An implicit conversion from one -** type to the other occurs as necessary. -** -** Most of the code in this file is taken up by the sqlite3VdbeExec() -** function which does the work of interpreting a VDBE program. -** But other routines are also provided to help in building up -** a program instruction by instruction. +** The code in this file implements the function that runs the +** bytecode of a prepared statement. ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting @@ -49,7 +24,11 @@ /* ** Invoke this macro on memory cells just prior to changing the ** value of the cell. This macro verifies that shallow copies are -** not misused. +** not misused. A shallow copy of a string or blob just copies a +** pointer to the string or blob, not the content. If the original +** is changed while the copy is still in use, the string or blob might +** be changed out from under the copy. This macro verifies that nothing +** like that ever happens. */ #ifdef SQLITE_DEBUG # define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M) @@ -108,7 +87,7 @@ static void updateMaxBlobsize(Mem *p){ #endif /* -** The next global variable is incremented each type the OP_Found opcode +** The next global variable is incremented each time the OP_Found opcode ** is executed. This is used to test whether or not the foreign key ** operation implemented using OP_FkIsZero is working. This variable ** has no function other than to help verify the correct operation of the @@ -128,6 +107,40 @@ int sqlite3_found_count = 0; # define UPDATE_MAX_BLOBSIZE(P) #endif +/* +** Invoke the VDBE coverage callback, if that callback is defined. This +** feature is used for test suite validation only and does not appear an +** production builds. +** +** M is an integer, 2 or 3, that indices how many different ways the +** branch can go. It is usually 2. "I" is the direction the branch +** goes. 0 means falls through. 1 means branch is taken. 2 means the +** second alternative branch is taken. +** +** iSrcLine is the source code line (from the __LINE__ macro) that +** generated the VDBE instruction. This instrumentation assumes that all +** source code is in a single file (the amalgamation). Special values 1 +** and 2 for the iSrcLine parameter mean that this particular branch is +** always taken or never taken, respectively. +*/ +#if !defined(SQLITE_VDBE_COVERAGE) +# define VdbeBranchTaken(I,M) +#else +# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M) + static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){ + if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){ + M = iSrcLine; + /* Assert the truth of VdbeCoverageAlwaysTaken() and + ** VdbeCoverageNeverTaken() */ + assert( (M & I)==I ); + }else{ + if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ + sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, + iSrcLine,I,M); + } + } +#endif + /* ** Convert the given register into a string if it isn't one ** already. Return non-zero if a malloc() fails. @@ -145,38 +158,14 @@ int sqlite3_found_count = 0; ** ** This routine converts an ephemeral string into a dynamically allocated ** string that the register itself controls. In other words, it -** converts an MEM_Ephem string into an MEM_Dyn string. +** converts an MEM_Ephem string into a string with P.z==P.zMalloc. */ #define Deephemeralize(P) \ if( ((P)->flags&MEM_Ephem)!=0 \ && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} /* Return true if the cursor was opened using the OP_OpenSorter opcode. */ -# define isSorter(x) ((x)->pSorter!=0) - -/* -** Argument pMem points at a register that will be passed to a -** user-defined function or returned to the user as the result of a query. -** This routine sets the pMem->type variable used by the sqlite3_value_*() -** routines. -*/ -void sqlite3VdbeMemStoreType(Mem *pMem){ - int flags = pMem->flags; - if( flags & MEM_Null ){ - pMem->type = SQLITE_NULL; - } - else if( flags & MEM_Int ){ - pMem->type = SQLITE_INTEGER; - } - else if( flags & MEM_Real ){ - pMem->type = SQLITE_FLOAT; - } - else if( flags & MEM_Str ){ - pMem->type = SQLITE_TEXT; - }else{ - pMem->type = SQLITE_BLOB; - } -} +#define isSorter(x) ((x)->pSorter!=0) /* ** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL @@ -212,9 +201,8 @@ static VdbeCursor *allocateCursor( int nByte; VdbeCursor *pCx = 0; nByte = - ROUND8(sizeof(VdbeCursor)) + - (isBtreeCursor?sqlite3BtreeCursorSize():0) + - 2*nField*sizeof(u32); + ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField + + (isBtreeCursor?sqlite3BtreeCursorSize():0); assert( iCurnCursor ); if( p->apCsr[iCur] ){ @@ -226,12 +214,9 @@ static VdbeCursor *allocateCursor( memset(pCx, 0, sizeof(VdbeCursor)); pCx->iDb = iDb; pCx->nField = nField; - if( nField ){ - pCx->aType = (u32 *)&pMem->z[ROUND8(sizeof(VdbeCursor))]; - } if( isBtreeCursor ){ pCx->pCursor = (BtCursor*) - &pMem->z[ROUND8(sizeof(VdbeCursor))+2*nField*sizeof(u32)]; + &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField]; sqlite3BtreeCursorZero(pCx->pCursor); } } @@ -245,21 +230,21 @@ static VdbeCursor *allocateCursor( ** look like a number, leave it alone. */ static void applyNumericAffinity(Mem *pRec){ - if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){ - double rValue; - i64 iValue; - u8 enc = pRec->enc; - if( (pRec->flags&MEM_Str)==0 ) return; - if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return; - if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){ - pRec->u.i = iValue; - pRec->flags |= MEM_Int; - }else{ - pRec->r = rValue; - pRec->flags |= MEM_Real; - } + double rValue; + i64 iValue; + u8 enc = pRec->enc; + if( (pRec->flags&MEM_Str)==0 ) return; + if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return; + if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){ + pRec->u.i = iValue; + pRec->flags |= MEM_Int; + }else{ + pRec->r = rValue; + pRec->flags |= MEM_Real; } } +#define ApplyNumericAffinity(X) \ + if(((X)->flags&(MEM_Real|MEM_Int))==0){applyNumericAffinity(X);} /* ** Processing is determine by the affinity parameter: @@ -296,7 +281,7 @@ static void applyAffinity( }else if( affinity!=SQLITE_AFF_NONE ){ assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL || affinity==SQLITE_AFF_NUMERIC ); - applyNumericAffinity(pRec); + ApplyNumericAffinity(pRec); if( pRec->flags & MEM_Real ){ sqlite3VdbeIntegerAffinity(pRec); } @@ -310,12 +295,13 @@ static void applyAffinity( ** loss of information and return the revised type of the argument. */ int sqlite3_value_numeric_type(sqlite3_value *pVal){ - Mem *pMem = (Mem*)pVal; - if( pMem->type==SQLITE_TEXT ){ + int eType = sqlite3_value_type(pVal); + if( eType==SQLITE_TEXT ){ + Mem *pMem = (Mem*)pVal; applyNumericAffinity(pMem); - sqlite3VdbeMemStoreType(pMem); + eType = sqlite3_value_type(pVal); } - return pMem->type; + return eType; } /* @@ -330,6 +316,29 @@ void sqlite3ValueApplyAffinity( applyAffinity((Mem *)pVal, affinity, enc); } +/* +** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or +** none. +** +** Unlike applyNumericAffinity(), this routine does not modify pMem->flags. +** But it does set pMem->r and pMem->u.i appropriately. +*/ +static u16 numericType(Mem *pMem){ + if( pMem->flags & (MEM_Int|MEM_Real) ){ + return pMem->flags & (MEM_Int|MEM_Real); + } + if( pMem->flags & (MEM_Str|MEM_Blob) ){ + if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){ + return 0; + } + if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ + return MEM_Int; + } + return MEM_Real; + } + return 0; +} + #ifdef SQLITE_DEBUG /* ** Write a nice string representation of the contents of cell pMem @@ -417,37 +426,36 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ /* ** Print the value of a register for tracing purposes: */ -static void memTracePrint(FILE *out, Mem *p){ - if( p->flags & MEM_Invalid ){ - fprintf(out, " undefined"); +static void memTracePrint(Mem *p){ + if( p->flags & MEM_Undefined ){ + printf(" undefined"); }else if( p->flags & MEM_Null ){ - fprintf(out, " NULL"); + printf(" NULL"); }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ - fprintf(out, " si:%lld", p->u.i); + printf(" si:%lld", p->u.i); }else if( p->flags & MEM_Int ){ - fprintf(out, " i:%lld", p->u.i); + printf(" i:%lld", p->u.i); #ifndef SQLITE_OMIT_FLOATING_POINT }else if( p->flags & MEM_Real ){ - fprintf(out, " r:%g", p->r); + printf(" r:%g", p->r); #endif }else if( p->flags & MEM_RowSet ){ - fprintf(out, " (rowset)"); + printf(" (rowset)"); }else{ char zBuf[200]; sqlite3VdbeMemPrettyPrint(p, zBuf); - fprintf(out, " "); - fprintf(out, "%s", zBuf); + printf(" %s", zBuf); } } -static void registerTrace(FILE *out, int iReg, Mem *p){ - fprintf(out, "REG[%d] = ", iReg); - memTracePrint(out, p); - fprintf(out, "\n"); +static void registerTrace(int iReg, Mem *p){ + printf("REG[%d] = ", iReg); + memTracePrint(p); + printf("\n"); } #endif #ifdef SQLITE_DEBUG -# define REGISTER_TRACE(R,M) if(p->trace)registerTrace(p->trace,R,M) +# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M) #else # define REGISTER_TRACE(R,M) #endif @@ -463,20 +471,6 @@ static void registerTrace(FILE *out, int iReg, Mem *p){ #endif -/* -** The CHECK_FOR_INTERRUPT macro defined here looks to see if the -** sqlite3_interrupt() routine has been called. If it has been, then -** processing of the VDBE program is interrupted. -** -** This macro added to every instruction that does a jump in order to -** implement a loop. This test used to be on every single instruction, -** but that meant we more testing than we needed. By only testing the -** flag on jump instructions, we get a (small) speed improvement. -*/ -#define CHECK_FOR_INTERRUPT \ - if( db->u1.isInterrupted ) goto abort_due_to_interrupt; - - #ifndef NDEBUG /* ** This function is only called from within an assert() expression. It @@ -497,50 +491,10 @@ static int checkSavepointCount(sqlite3 *db){ } #endif -/* -** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored -** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored -** in memory obtained from sqlite3DbMalloc). -*/ -static void importVtabErrMsg(Vdbe *p, sqlite3_vtab *pVtab){ - sqlite3 *db = p->db; - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg); - sqlite3_free(pVtab->zErrMsg); - pVtab->zErrMsg = 0; -} - /* -** Execute as much of a VDBE program as we can then return. -** -** sqlite3VdbeMakeReady() must be called before this routine in order to -** close the program with a final OP_Halt and to set up the callbacks -** and the error message pointer. -** -** Whenever a row or result data is available, this routine will either -** invoke the result callback (if there is one) or return with -** SQLITE_ROW. -** -** If an attempt is made to open a locked database, then this routine -** will either invoke the busy callback (if there is one) or it will -** return SQLITE_BUSY. -** -** If an error occurs, an error message is written to memory obtained -** from sqlite3_malloc() and p->zErrMsg is made to point to that memory. -** The error code is stored in p->rc and this routine returns SQLITE_ERROR. -** -** If the callback ever returns non-zero, then the program exits -** immediately. There will be no error message but the p->rc field is -** set to SQLITE_ABORT and this routine will return SQLITE_ERROR. -** -** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this -** routine to return SQLITE_ERROR. -** -** Other fatal errors return SQLITE_ERROR. -** -** After this routine has finished, sqlite3VdbeFinalize() should be -** used to clean up the mess that was left behind. +** Execute as much of a VDBE program as we can. +** This is the core of sqlite3_step(). */ int sqlite3VdbeExec( Vdbe *p /* The VDBE */ @@ -552,21 +506,20 @@ int sqlite3VdbeExec( sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ + int iCompare = 0; /* Result of last OP_Compare operation */ + unsigned nVmStep = 0; /* Number of virtual machine steps */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK - int checkProgress; /* True if progress callbacks are enabled */ - int nProgressOps = 0; /* Opcodes executed since progress callback. */ + unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */ #endif Mem *aMem = p->aMem; /* Copy of p->aMem */ Mem *pIn1 = 0; /* 1st input operand */ Mem *pIn2 = 0; /* 2nd input operand */ Mem *pIn3 = 0; /* 3rd input operand */ Mem *pOut = 0; /* Output operand */ - int iCompare = 0; /* Result of last OP_Compare operation */ 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 */ - int origPc; /* Program counter at start of opcode */ #endif /*** INSERT STACK UNION HERE ***/ @@ -578,24 +531,49 @@ int sqlite3VdbeExec( goto no_mem; } assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); + assert( p->bIsReader || p->readOnly!=0 ); p->rc = SQLITE_OK; + p->iCurrentTime = 0; assert( p->explain==0 ); p->pResultSet = 0; db->busyHandler.nBusy = 0; - CHECK_FOR_INTERRUPT; + if( db->u1.isInterrupted ) goto abort_due_to_interrupt; sqlite3VdbeIOTraceSql(p); #ifndef SQLITE_OMIT_PROGRESS_CALLBACK - checkProgress = db->xProgress!=0; + if( db->xProgress ){ + assert( 0 < db->nProgressOps ); + nProgressLimit = (unsigned)p->aCounter[SQLITE_STMTSTATUS_VM_STEP]; + if( nProgressLimit==0 ){ + nProgressLimit = db->nProgressOps; + }else{ + nProgressLimit %= (unsigned)db->nProgressOps; + } + } #endif #ifdef SQLITE_DEBUG sqlite3BeginBenignMalloc(); - if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){ + if( p->pc==0 + && (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0 + ){ int i; - printf("VDBE Program Listing:\n"); + int once = 1; sqlite3VdbePrintSql(p); - for(i=0; inOp; i++){ - sqlite3VdbePrintOp(stdout, i, &aOp[i]); + if( p->db->flags & SQLITE_VdbeListing ){ + printf("VDBE Program Listing:\n"); + for(i=0; inOp; i++){ + sqlite3VdbePrintOp(stdout, i, &aOp[i]); + } + } + if( p->db->flags & SQLITE_VdbeEQP ){ + for(i=0; inOp; i++){ + if( aOp[i].opcode==OP_Explain ){ + if( once ) printf("VDBE Query Plan:\n"); + printf("%s\n", aOp[i].p4.z); + once = 0; + } + } } + if( p->db->flags & SQLITE_VdbeTrace ) printf("VDBE Trace:\n"); } sqlite3EndBenignMalloc(); #endif @@ -603,20 +581,16 @@ int sqlite3VdbeExec( assert( pc>=0 && pcnOp ); if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE - origPc = pc; start = sqlite3Hwtime(); #endif + nVmStep++; pOp = &aOp[pc]; /* Only allow tracing if SQLITE_DEBUG is defined. */ #ifdef SQLITE_DEBUG - if( p->trace ){ - if( pc==0 ){ - printf("VDBE Execution Trace:\n"); - sqlite3VdbePrintSql(p); - } - sqlite3VdbePrintOp(p->trace, pc, pOp); + if( db->flags & SQLITE_VdbeTrace ){ + sqlite3VdbePrintOp(stdout, pc, pOp); } #endif @@ -633,27 +607,6 @@ int sqlite3VdbeExec( } #endif -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - /* Call the progress callback if it is configured and the required number - ** of VDBE ops have been executed (either since this invocation of - ** sqlite3VdbeExec() or since last time the progress callback was called). - ** If the progress callback returns non-zero, exit the virtual machine with - ** a return code SQLITE_ABORT. - */ - if( checkProgress ){ - if( db->nProgressOps==nProgressOps ){ - int prc; - prc = db->xProgress(db->pProgressArg); - if( prc!=0 ){ - rc = SQLITE_INTERRUPT; - goto vdbe_error_halt; - } - nProgressOps = 0; - } - nProgressOps++; - } -#endif - /* On any opcode with the "out2-prerelease" tag, free any ** external allocations out of mem[p2] and set mem[p2] to be ** an undefined integer. Opcodes will either fill in the integer @@ -662,7 +615,7 @@ int sqlite3VdbeExec( assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){ assert( pOp->p2>0 ); - assert( pOp->p2<=p->nMem ); + assert( pOp->p2<=(p->nMem-p->nCursor) ); pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); VdbeMemRelease(pOut); @@ -673,30 +626,33 @@ int sqlite3VdbeExec( #ifdef SQLITE_DEBUG if( (pOp->opflags & OPFLG_IN1)!=0 ){ assert( pOp->p1>0 ); - assert( pOp->p1<=p->nMem ); + assert( pOp->p1<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p1]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) ); REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); } if( (pOp->opflags & OPFLG_IN2)!=0 ){ assert( pOp->p2>0 ); - assert( pOp->p2<=p->nMem ); + assert( pOp->p2<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p2]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) ); REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); } if( (pOp->opflags & OPFLG_IN3)!=0 ){ assert( pOp->p3>0 ); - assert( pOp->p3<=p->nMem ); + assert( pOp->p3<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p3]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) ); REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); } if( (pOp->opflags & OPFLG_OUT2)!=0 ){ assert( pOp->p2>0 ); - assert( pOp->p2<=p->nMem ); + assert( pOp->p2<=(p->nMem-p->nCursor) ); memAboutToChange(p, &aMem[pOp->p2]); } if( (pOp->opflags & OPFLG_OUT3)!=0 ){ assert( pOp->p3>0 ); - assert( pOp->p3<=p->nMem ); + assert( pOp->p3<=(p->nMem-p->nCursor) ); memAboutToChange(p, &aMem[pOp->p3]); } #endif @@ -744,10 +700,44 @@ int sqlite3VdbeExec( ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. +** +** The P1 parameter is not actually used by this opcode. However, it +** is sometimes set to 1 instead of 0 as a hint to the command-line shell +** that this Goto is the bottom of a loop and that the lines from P2 down +** to the current line should be indented for EXPLAIN output. */ case OP_Goto: { /* jump */ - CHECK_FOR_INTERRUPT; pc = pOp->p2 - 1; + + /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, + ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon + ** completion. Check to see if sqlite3_interrupt() has been called + ** or if the progress callback needs to be invoked. + ** + ** This code uses unstructured "goto" statements and does not look clean. + ** But that is not due to sloppy coding habits. The code is written this + ** way for performance, to avoid having to run the interrupt and progress + ** checks on every opcode. This helps sqlite3_step() to run about 1.5% + ** faster according to "valgrind --tool=cachegrind" */ +check_for_interrupt: + if( db->u1.isInterrupted ) goto abort_due_to_interrupt; +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + /* Call the progress callback if it is configured and the required number + ** of VDBE ops have been executed (either since this invocation of + ** sqlite3VdbeExec() or since last time the progress callback was called). + ** If the progress callback returns non-zero, exit the virtual machine with + ** a return code SQLITE_ABORT. + */ + if( db->xProgress!=0 && nVmStep>=nProgressLimit ){ + assert( db->nProgressOps!=0 ); + nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps); + if( db->xProgress(db->pProgressArg) ){ + rc = SQLITE_INTERRUPT; + goto vdbe_error_halt; + } + } +#endif + break; } @@ -757,9 +747,9 @@ case OP_Goto: { /* jump */ ** and then jump to address P2. */ case OP_Gosub: { /* jump */ - assert( pOp->p1>0 && pOp->p1<=p->nMem ); + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Dyn)==0 ); + assert( VdbeMemDynamic(pIn1)==0 ); memAboutToChange(p, pIn1); pIn1->flags = MEM_Int; pIn1->u.i = pc; @@ -770,23 +760,78 @@ case OP_Gosub: { /* jump */ /* Opcode: Return P1 * * * * ** -** Jump to the next instruction after the address in register P1. +** Jump to the next instruction after the address in register P1. After +** the jump, register P1 becomes undefined. */ case OP_Return: { /* in1 */ pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags & MEM_Int ); + assert( pIn1->flags==MEM_Int ); pc = (int)pIn1->u.i; + pIn1->flags = MEM_Undefined; + break; +} + +/* Opcode: InitCoroutine P1 P2 P3 * * +** +** Set up register P1 so that it will Yield to the coroutine +** located at address P3. +** +** If P2!=0 then the coroutine implementation immediately follows +** this opcode. So jump over the coroutine implementation to +** address P2. +** +** See also: EndCoroutine +*/ +case OP_InitCoroutine: { /* jump */ + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + assert( pOp->p2>=0 && pOp->p2nOp ); + assert( pOp->p3>=0 && pOp->p3nOp ); + pOut = &aMem[pOp->p1]; + assert( !VdbeMemDynamic(pOut) ); + pOut->u.i = pOp->p3 - 1; + pOut->flags = MEM_Int; + if( pOp->p2 ) pc = pOp->p2 - 1; + break; +} + +/* Opcode: EndCoroutine P1 * * * * +** +** The instruction at the address in register P1 is a Yield. +** Jump to the P2 parameter of that Yield. +** After the jump, register P1 becomes undefined. +** +** See also: InitCoroutine +*/ +case OP_EndCoroutine: { /* in1 */ + VdbeOp *pCaller; + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags==MEM_Int ); + assert( pIn1->u.i>=0 && pIn1->u.inOp ); + pCaller = &aOp[pIn1->u.i]; + assert( pCaller->opcode==OP_Yield ); + assert( pCaller->p2>=0 && pCaller->p2nOp ); + pc = pCaller->p2 - 1; + pIn1->flags = MEM_Undefined; break; } -/* Opcode: Yield P1 * * * * +/* Opcode: Yield P1 P2 * * * ** -** Swap the program counter with the value in register P1. +** Swap the program counter with the value in register P1. This +** has the effect of yielding to a coroutine. +** +** If the coroutine that is launched by this instruction ends with +** Yield or Return then continue to the next instruction. But if +** the coroutine launched by this instruction ends with +** EndCoroutine, then jump to P2 rather than continuing with the +** next instruction. +** +** See also: InitCoroutine */ -case OP_Yield: { /* in1 */ +case OP_Yield: { /* in1, jump */ int pcDest; pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Dyn)==0 ); + assert( VdbeMemDynamic(pIn1)==0 ); pIn1->flags = MEM_Int; pcDest = (int)pIn1->u.i; pIn1->u.i = pc; @@ -795,11 +840,13 @@ case OP_Yield: { /* in1 */ break; } -/* Opcode: HaltIfNull P1 P2 P3 P4 * +/* Opcode: HaltIfNull P1 P2 P3 P4 P5 +** Synopsis: if r[P3]=null halt ** ** Check the value in register P3. If it is NULL then Halt using ** parameter P1, P2, and P4 as if this were a Halt instruction. If the ** value in register P3 is not NULL, then this routine is a no-op. +** The P5 parameter should be 1. */ case OP_HaltIfNull: { /* in3 */ pIn3 = &aMem[pOp->p3]; @@ -807,7 +854,7 @@ case OP_HaltIfNull: { /* in3 */ /* Fall through into OP_Halt */ } -/* Opcode: Halt P1 P2 * P4 * +/* Opcode: Halt P1 P2 * P4 P5 ** ** Exit immediately. All open cursors, etc are closed ** automatically. @@ -822,11 +869,25 @@ case OP_HaltIfNull: { /* in3 */ ** ** If P4 is not null then it is an error message string. ** +** P5 is a value between 0 and 4, inclusive, that modifies the P4 string. +** +** 0: (no change) +** 1: NOT NULL contraint failed: P4 +** 2: UNIQUE constraint failed: P4 +** 3: CHECK constraint failed: P4 +** 4: FOREIGN KEY constraint failed: P4 +** +** If P5 is not zero and P4 is NULL, then everything after the ":" is +** omitted. +** ** There is an implied "Halt 0 0 0" instruction inserted at the very end of ** every program. So a jump past the last instruction of the program ** is the same as executing Halt. */ case OP_Halt: { + const char *zType; + const char *zLogFmt; + if( pOp->p1==SQLITE_OK && p->pFrame ){ /* Halt the sub-program. Return control to the parent frame. */ VdbeFrame *pFrame = p->pFrame; @@ -847,18 +908,33 @@ case OP_Halt: { aMem = p->aMem; break; } - p->rc = pOp->p1; p->errorAction = (u8)pOp->p2; p->pc = pc; - if( pOp->p4.z ){ - assert( p->rc!=SQLITE_OK ); - sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z); - }else if( p->rc ){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql); + if( p->rc ){ + if( pOp->p5 ){ + static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK", + "FOREIGN KEY" }; + assert( pOp->p5>=1 && pOp->p5<=4 ); + testcase( pOp->p5==1 ); + testcase( pOp->p5==2 ); + testcase( pOp->p5==3 ); + testcase( pOp->p5==4 ); + zType = azType[pOp->p5-1]; + }else{ + zType = 0; + } + assert( zType!=0 || pOp->p4.z!=0 ); + zLogFmt = "abort at %d in [%s]: %s"; + if( zType && pOp->p4.z ){ + sqlite3SetString(&p->zErrMsg, db, "%s constraint failed: %s", + zType, pOp->p4.z); + }else if( pOp->p4.z ){ + sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); + }else{ + sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", zType); + } + sqlite3_log(pOp->p1, zLogFmt, pc, p->zSql, p->zErrMsg); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); @@ -866,13 +942,14 @@ case OP_Halt: { p->rc = rc = SQLITE_BUSY; }else{ assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); - assert( rc==SQLITE_OK || db->nDeferredCons>0 ); + assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 ); rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; } goto vdbe_return; } /* Opcode: Integer P1 P2 * * * +** Synopsis: r[P2]=P1 ** ** The 32-bit integer value P1 is written into register P2. */ @@ -882,6 +959,7 @@ case OP_Integer: { /* out2-prerelease */ } /* Opcode: Int64 * P2 * P4 * +** Synopsis: r[P2]=P4 ** ** P4 is a pointer to a 64-bit integer value. ** Write that value into register P2. @@ -894,6 +972,7 @@ case OP_Int64: { /* out2-prerelease */ #ifndef SQLITE_OMIT_FLOATING_POINT /* Opcode: Real * P2 * P4 * +** Synopsis: r[P2]=P4 ** ** P4 is a pointer to a 64-bit floating point value. ** Write that value into register P2. @@ -907,9 +986,12 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ #endif /* Opcode: String8 * P2 * P4 * +** Synopsis: r[P2]='P4' ** ** P4 points to a nul terminated UTF-8 string. This opcode is transformed -** into an OP_String before it is executed for the first time. +** into a String before it is executed for the first time. During +** this transformation, the length of string P4 is computed and stored +** as the P1 parameter. */ case OP_String8: { /* same as TK_STRING, out2-prerelease */ assert( pOp->p4.z!=0 ); @@ -922,10 +1004,9 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */ if( rc==SQLITE_TOOBIG ) goto too_big; if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; assert( pOut->zMalloc==pOut->z ); - assert( pOut->flags & MEM_Dyn ); + assert( VdbeMemDynamic(pOut)==0 ); pOut->zMalloc = 0; pOut->flags |= MEM_Static; - pOut->flags &= ~MEM_Dyn; if( pOp->p4type==P4_DYNAMIC ){ sqlite3DbFree(db, pOp->p4.z); } @@ -941,6 +1022,7 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */ } /* Opcode: String P1 P2 * P4 * +** Synopsis: r[P2]='P4' (len=P1) ** ** The string value P4 of length P1 (bytes) is stored in register P2. */ @@ -955,6 +1037,7 @@ case OP_String: { /* out2-prerelease */ } /* Opcode: Null P1 P2 P3 * * +** Synopsis: r[P2..P3]=NULL ** ** Write a NULL into registers P2. If P3 greater than P2, then also write ** NULL into register P3 and every register in between P2 and P3. If P3 @@ -969,7 +1052,7 @@ case OP_Null: { /* out2-prerelease */ int cnt; u16 nullFlag; cnt = pOp->p3-pOp->p2; - assert( pOp->p3<=p->nMem ); + assert( pOp->p3<=(p->nMem-p->nCursor) ); pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; while( cnt>0 ){ pOut++; @@ -981,8 +1064,23 @@ case OP_Null: { /* out2-prerelease */ break; } +/* Opcode: SoftNull P1 * * * * +** Synopsis: r[P1]=NULL +** +** Set register P1 to have the value NULL as seen by the OP_MakeRecord +** instruction, but do not free any string or blob memory associated with +** the register, so that if the value was a string or blob that was +** previously copied using OP_SCopy, the copies will continue to be valid. +*/ +case OP_SoftNull: { + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + pOut = &aMem[pOp->p1]; + pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined; + break; +} -/* Opcode: Blob P1 P2 * P4 +/* Opcode: Blob P1 P2 * P4 * +** Synopsis: r[P2]=P4 (len=P1) ** ** P4 points to a blob of data P1 bytes long. Store this ** blob in register P2. @@ -996,10 +1094,11 @@ case OP_Blob: { /* out2-prerelease */ } /* Opcode: Variable P1 P2 * P4 * +** Synopsis: r[P2]=parameter(P1,P4) ** ** Transfer the values of bound parameter P1 into register P2 ** -** If the parameter is named, then its name appears in P4 and P3==1. +** If the parameter is named, then its name appears in P4. ** The P4 value is used by sqlite3_bind_parameter_name(). */ case OP_Variable: { /* out2-prerelease */ @@ -1017,11 +1116,13 @@ case OP_Variable: { /* out2-prerelease */ } /* Opcode: Move P1 P2 P3 * * +** Synopsis: r[P2@P3]=r[P1@P3] ** -** Move the values in register P1..P1+P3 over into -** registers P2..P2+P3. Registers P1..P1+P3 are +** Move the P3 values in register P1..P1+P3-1 over into +** registers P2..P2+P3-1. Registers P1..P1+P3-1 are ** left holding a NULL. It is an error for register ranges -** P1..P1+P3 and P2..P2+P3 to overlap. +** P1..P1+P3-1 and P2..P2+P3-1 to overlap. It is an error +** for P3 to be less than 1. */ case OP_Move: { char *zMalloc; /* Holding variable for allocated memory */ @@ -1029,7 +1130,7 @@ case OP_Move: { int p1; /* Register to copy from */ int p2; /* Register to copy to */ - n = pOp->p3 + 1; + n = pOp->p3; p1 = pOp->p1; p2 = pOp->p2; assert( n>0 && p1>0 && p2>0 ); @@ -1037,28 +1138,31 @@ case OP_Move: { pIn1 = &aMem[p1]; pOut = &aMem[p2]; - while( n-- ){ - assert( pOut<=&aMem[p->nMem] ); - assert( pIn1<=&aMem[p->nMem] ); + do{ + assert( pOut<=&aMem[(p->nMem-p->nCursor)] ); + assert( pIn1<=&aMem[(p->nMem-p->nCursor)] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); + VdbeMemRelease(pOut); zMalloc = pOut->zMalloc; - pOut->zMalloc = 0; - sqlite3VdbeMemMove(pOut, pIn1); + memcpy(pOut, pIn1, sizeof(Mem)); #ifdef SQLITE_DEBUG if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){ pOut->pScopyFrom += p1 - pOp->p2; } #endif + pIn1->flags = MEM_Undefined; + pIn1->xDel = 0; pIn1->zMalloc = zMalloc; REGISTER_TRACE(p2++, pOut); pIn1++; pOut++; - } + }while( --n ); break; } /* Opcode: Copy P1 P2 P3 * * +** Synopsis: r[P2@P3+1]=r[P1@P3+1] ** ** Make a copy of registers P1..P1+P3 into registers P2..P2+P3. ** @@ -1087,6 +1191,7 @@ case OP_Copy: { } /* Opcode: SCopy P1 P2 * * * +** Synopsis: r[P2]=r[P1] ** ** Make a shallow copy of register P1 into register P2. ** @@ -1098,7 +1203,7 @@ case OP_Copy: { ** during the lifetime of the copy. Use OP_Copy to make a complete ** copy. */ -case OP_SCopy: { /* in1, out2 */ +case OP_SCopy: { /* out2 */ pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; assert( pOut!=pIn1 ); @@ -1106,24 +1211,36 @@ case OP_SCopy: { /* in1, out2 */ #ifdef SQLITE_DEBUG if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1; #endif - REGISTER_TRACE(pOp->p2, pOut); break; } /* Opcode: ResultRow P1 P2 * * * +** Synopsis: output=r[P1@P2] ** ** The registers P1 through P1+P2-1 contain a single row of ** results. This opcode causes the sqlite3_step() call to terminate ** with an SQLITE_ROW return code and it sets up the sqlite3_stmt -** structure to provide access to the top P1 values as the result -** row. +** structure to provide access to the r(P1)..r(P1+P2-1) values as +** the result row. */ case OP_ResultRow: { Mem *pMem; int i; assert( p->nResColumn==pOp->p2 ); assert( pOp->p1>0 ); - assert( pOp->p1+pOp->p2<=p->nMem+1 ); + assert( pOp->p1+pOp->p2<=(p->nMem-p->nCursor)+1 ); + +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + /* Run the progress counter just before returning. + */ + if( db->xProgress!=0 + && nVmStep>=nProgressLimit + && db->xProgress(db->pProgressArg)!=0 + ){ + rc = SQLITE_INTERRUPT; + goto vdbe_error_halt; + } +#endif /* If this statement has violated immediate foreign key constraints, do ** not return the number of rows modified. And do not RELEASE the statement @@ -1169,7 +1286,6 @@ case OP_ResultRow: { assert( (pMem[i].flags & MEM_Ephem)==0 || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 ); sqlite3VdbeMemNulTerminate(&pMem[i]); - sqlite3VdbeMemStoreType(&pMem[i]); REGISTER_TRACE(pOp->p1+i, &pMem[i]); } if( db->mallocFailed ) goto no_mem; @@ -1182,6 +1298,7 @@ case OP_ResultRow: { } /* Opcode: Concat P1 P2 P3 * * +** Synopsis: r[P3]=r[P2]+r[P1] ** ** Add the text in register P1 onto the end of the text in ** register P2 and store the result in register P3. @@ -1211,15 +1328,15 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } - MemSetTypeFlag(pOut, MEM_Str); if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ goto no_mem; } + MemSetTypeFlag(pOut, MEM_Str); if( pOut!=pIn2 ){ memcpy(pOut->z, pIn2->z, pIn2->n); } memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n); - pOut->z[nByte] = 0; + pOut->z[nByte]=0; pOut->z[nByte+1] = 0; pOut->flags |= MEM_Term; pOut->n = (int)nByte; @@ -1229,12 +1346,14 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ } /* Opcode: Add P1 P2 P3 * * +** Synopsis: r[P3]=r[P1]+r[P2] ** ** Add the value in register P1 to the value in register P2 ** and store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: Multiply P1 P2 P3 * * +** Synopsis: r[P3]=r[P1]*r[P2] ** ** ** Multiply the value in register P1 by the value in register P2 @@ -1242,12 +1361,14 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ ** If either input is NULL, the result is NULL. */ /* Opcode: Subtract P1 P2 P3 * * +** Synopsis: r[P3]=r[P2]-r[P1] ** ** Subtract the value in register P1 from the value in register P2 ** and store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: Divide P1 P2 P3 * * +** Synopsis: r[P3]=r[P2]/r[P1] ** ** Divide the value in register P1 by the value in register P2 ** and store the result in register P3 (P3=P2/P1). If the value in @@ -1255,10 +1376,11 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ ** NULL, the result is NULL. */ /* Opcode: Remainder P1 P2 P3 * * +** Synopsis: r[P3]=r[P2]%r[P1] ** -** Compute the remainder after integer division of the value in -** register P1 by the value in register P2 and store the result in P3. -** If the value in register P2 is zero the result is NULL. +** Compute the remainder after integer register P2 is divided by +** register P1 and store the result in register P3. +** If the value in register P1 is zero the result is NULL. ** If either operand is NULL, the result is NULL. */ case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ @@ -1267,20 +1389,22 @@ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ char bIntint; /* Started out as two integer operands */ - int flags; /* Combined MEM_* flags from both inputs */ + u16 flags; /* Combined MEM_* flags from both inputs */ + u16 type1; /* Numeric type of left operand */ + u16 type2; /* Numeric type of right operand */ i64 iA; /* Integer value of left operand */ i64 iB; /* Integer value of right operand */ double rA; /* Real value of left operand */ double rB; /* Real value of right operand */ pIn1 = &aMem[pOp->p1]; - applyNumericAffinity(pIn1); + type1 = numericType(pIn1); pIn2 = &aMem[pOp->p2]; - applyNumericAffinity(pIn2); + type2 = numericType(pIn2); pOut = &aMem[pOp->p3]; flags = pIn1->flags | pIn2->flags; if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; - if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ + if( (type1 & type2 & MEM_Int)!=0 ){ iA = pIn1->u.i; iB = pIn2->u.i; bIntint = 1; @@ -1336,7 +1460,7 @@ fp_math: } pOut->r = rB; MemSetTypeFlag(pOut, MEM_Real); - if( (flags & MEM_Real)==0 && !bIntint ){ + if( ((type1|type2)&MEM_Real)==0 && !bIntint ){ sqlite3VdbeIntegerAffinity(pOut); } #endif @@ -1372,6 +1496,7 @@ case OP_CollSeq: { } /* Opcode: Function P1 P2 P3 P4 P5 +** Synopsis: r[P3]=func(r[P2@P5]) ** ** Invoke a user function (P4 is a pointer to a Function structure that ** defines the function) with P5 arguments taken from register P2 and @@ -1397,44 +1522,37 @@ case OP_Function: { n = pOp->p5; apVal = p->apArg; assert( apVal || n==0 ); - assert( pOp->p3>0 && pOp->p3<=p->nMem ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pOut = &aMem[pOp->p3]; memAboutToChange(p, pOut); - assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem+1) ); + 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 || pOp->p4type==P4_VDBEFUNC ); - if( pOp->p4type==P4_FUNCDEF ){ - ctx.pFunc = pOp->p4.pFunc; - ctx.pVdbeFunc = 0; - }else{ - ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc; - ctx.pFunc = ctx.pVdbeFunc->pFunc; - } - - ctx.s.flags = MEM_Null; - ctx.s.db = db; - ctx.s.xDel = 0; - ctx.s.zMalloc = 0; + assert( pOp->p4type==P4_FUNCDEF ); + 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. */ - sqlite3VdbeMemMove(&ctx.s, pOut); + memcpy(&ctx.s, pOut, sizeof(Mem)); + pOut->flags = MEM_Null; + pOut->xDel = 0; + pOut->zMalloc = 0; MemSetTypeFlag(&ctx.s, MEM_Null); - ctx.isError = 0; - if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ + ctx.fErrorOrAux = 0; + if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); @@ -1444,15 +1562,6 @@ case OP_Function: { (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */ lastRowid = db->lastRowid; - /* If any auxiliary data functions have been called by this user function, - ** immediately call the destructor for any non-static values. - */ - if( ctx.pVdbeFunc ){ - sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1); - pOp->p4.pVdbeFunc = ctx.pVdbeFunc; - pOp->p4type = P4_VDBEFUNC; - } - if( db->mallocFailed ){ /* Even though a malloc() has failed, the implementation of the ** user function may have called an sqlite3_result_XXX() function @@ -1464,14 +1573,18 @@ case OP_Function: { } /* If the function returned an error, throw an exception */ - if( ctx.isError ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); - rc = ctx.isError; + if( ctx.fErrorOrAux ){ + if( ctx.isError ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); + rc = ctx.isError; + } + sqlite3VdbeDeleteAuxData(p, pc, pOp->p1); } /* Copy the result of the function into register P3 */ sqlite3VdbeChangeEncoding(&ctx.s, encoding); - sqlite3VdbeMemMove(pOut, &ctx.s); + assert( pOut->flags==MEM_Null ); + memcpy(pOut, &ctx.s, sizeof(Mem)); if( sqlite3VdbeMemTooBig(pOut) ){ goto too_big; } @@ -1490,18 +1603,21 @@ case OP_Function: { } /* Opcode: BitAnd P1 P2 P3 * * +** Synopsis: r[P3]=r[P1]&r[P2] ** ** Take the bit-wise AND of the values in register P1 and P2 and ** store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: BitOr P1 P2 P3 * * +** Synopsis: r[P3]=r[P1]|r[P2] ** ** Take the bit-wise OR of the values in register P1 and P2 and ** store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: ShiftLeft P1 P2 P3 * * +** Synopsis: r[P3]=r[P2]<>r[P1] ** ** Shift the integer value in register P2 to the right by the ** number of bits specified by the integer in register P1. @@ -1568,6 +1685,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ } /* Opcode: AddImm P1 P2 * * * +** Synopsis: r[P1]=r[P1]+P2 ** ** Add the constant P2 to the value in register P1. ** The result is always an integer. @@ -1591,17 +1709,20 @@ case OP_AddImm: { /* in1 */ */ case OP_MustBeInt: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; - applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); if( (pIn1->flags & MEM_Int)==0 ){ - if( pOp->p2==0 ){ - rc = SQLITE_MISMATCH; - goto abort_due_to_error; - }else{ - pc = pOp->p2 - 1; + applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); + VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2); + if( (pIn1->flags & MEM_Int)==0 ){ + if( pOp->p2==0 ){ + rc = SQLITE_MISMATCH; + goto abort_due_to_error; + }else{ + pc = pOp->p2 - 1; + break; + } } - }else{ - MemSetTypeFlag(pIn1, MEM_Int); } + MemSetTypeFlag(pIn1, MEM_Int); break; } @@ -1629,7 +1750,7 @@ case OP_RealAffinity: { /* in1 */ ** ** Force the value in register P1 to be text. ** If the value is numeric, convert it to a string using the -** equivalent of printf(). Blob values are unchanged and +** equivalent of sprintf(). Blob values are unchanged and ** are afterwards simply interpreted as text. ** ** A NULL value is not changed by this routine. It remains NULL. @@ -1726,6 +1847,7 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */ #endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */ /* Opcode: Lt P1 P2 P3 P4 P5 +** Synopsis: if r[P1]r[P3] goto P2 ** ** This works just like the Lt opcode except that the jump is taken if ** the content of register P3 is greater than the content of ** register P1. See the Lt opcode for additional information. */ /* Opcode: Ge P1 P2 P3 P4 P5 +** Synopsis: if r[P1]>=r[P3] goto P2 ** ** This works just like the Lt opcode except that the jump is taken if ** the content of register P3 is greater than or equal to the content of @@ -1825,6 +1952,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ */ assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); assert( (flags1 & MEM_Cleared)==0 ); + assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); if( (flags1&MEM_Null)!=0 && (flags3&MEM_Null)!=0 && (flags3&MEM_Cleared)==0 @@ -1842,8 +1970,11 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ pOut = &aMem[pOp->p2]; MemSetTypeFlag(pOut, MEM_Null); REGISTER_TRACE(pOp->p2, pOut); - }else if( pOp->p5 & SQLITE_JUMPIFNULL ){ - pc = pOp->p2-1; + }else{ + VdbeBranchTaken(2,3); + if( pOp->p5 & SQLITE_JUMPIFNULL ){ + pc = pOp->p2-1; + } } break; } @@ -1876,10 +2007,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ MemSetTypeFlag(pOut, MEM_Int); pOut->u.i = res; REGISTER_TRACE(pOp->p2, pOut); - }else if( res ){ - pc = pOp->p2-1; + }else{ + VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); + if( res ){ + pc = pOp->p2-1; + } } - /* Undo any changes made by applyAffinity() to the input registers. */ pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask); pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask); @@ -1903,6 +2036,7 @@ case OP_Permutation: { } /* Opcode: Compare P1 P2 P3 P4 P5 +** Synopsis: r[P1@P3] <-> r[P2@P3] ** ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of @@ -1942,11 +2076,11 @@ case OP_Compare: { if( aPermute ){ int k, mx = 0; for(k=0; kmx ) mx = aPermute[k]; - assert( p1>0 && p1+mx<=p->nMem+1 ); - assert( p2>0 && p2+mx<=p->nMem+1 ); + assert( p1>0 && p1+mx<=(p->nMem-p->nCursor)+1 ); + assert( p2>0 && p2+mx<=(p->nMem-p->nCursor)+1 ); }else{ - assert( p1>0 && p1+n<=p->nMem+1 ); - assert( p2>0 && p2+n<=p->nMem+1 ); + assert( p1>0 && p1+n<=(p->nMem-p->nCursor)+1 ); + assert( p2>0 && p2+n<=(p->nMem-p->nCursor)+1 ); } #endif /* SQLITE_DEBUG */ for(i=0; ip1 - 1; + pc = pOp->p1 - 1; VdbeBranchTaken(0,3); }else if( iCompare==0 ){ - pc = pOp->p2 - 1; + pc = pOp->p2 - 1; VdbeBranchTaken(1,3); }else{ - pc = pOp->p3 - 1; + pc = pOp->p3 - 1; VdbeBranchTaken(2,3); } break; } /* Opcode: And P1 P2 P3 * * +** Synopsis: r[P3]=(r[P1] && r[P2]) ** ** Take the logical AND of the values in registers P1 and P2 and ** write the result into register P3. @@ -1995,6 +2130,7 @@ case OP_Jump: { /* jump */ ** a NULL output. */ /* Opcode: Or P1 P2 P3 * * +** Synopsis: r[P3]=(r[P1] || r[P2]) ** ** Take the logical OR of the values in register P1 and P2 and ** store the answer in register P3. @@ -2038,6 +2174,7 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ } /* Opcode: Not P1 P2 * * * +** Synopsis: r[P2]= !r[P1] ** ** Interpret the value in register P1 as a boolean value. Store the ** boolean complement in register P2. If the value in register P1 is @@ -2055,6 +2192,7 @@ case OP_Not: { /* same as TK_NOT, in1, out2 */ } /* Opcode: BitNot P1 P2 * * * +** Synopsis: r[P1]= ~r[P1] ** ** Interpret the content of register P1 as an integer. Store the ** ones-complement of the P1 value into register P2. If P1 holds @@ -2073,11 +2211,18 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ /* Opcode: Once P1 P2 * * * ** -** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, -** set the flag and fall through to the next instruction. +** Check the "once" flag number P1. If it is set, jump to instruction P2. +** Otherwise, set the flag and fall through to the next instruction. +** In other words, this opcode causes all following opcodes up through P2 +** (but not including P2) to run just once and to be skipped on subsequent +** times through the loop. +** +** All "once" flags are initially cleared whenever a prepared statement +** first begins to run. */ case OP_Once: { /* jump */ assert( pOp->p1nOnceFlag ); + VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); if( p->aOnceFlag[pOp->p1] ){ pc = pOp->p2-1; }else{ @@ -2090,13 +2235,13 @@ case OP_Once: { /* jump */ ** ** Jump to P2 if the value in register P1 is true. The value ** is considered true if it is numeric and non-zero. If the value -** in P1 is NULL then take the jump if P3 is non-zero. +** in P1 is NULL then take the jump if and only if P3 is non-zero. */ /* Opcode: IfNot P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is False. The value ** is considered false if it has a numeric value of zero. If the value -** in P1 is NULL then take the jump if P3 is zero. +** in P1 is NULL then take the jump if and only if P3 is non-zero. */ case OP_If: /* jump, in1 */ case OP_IfNot: { /* jump, in1 */ @@ -2112,6 +2257,7 @@ case OP_IfNot: { /* jump, in1 */ #endif if( pOp->opcode==OP_IfNot ) c = !c; } + VdbeBranchTaken(c!=0, 2); if( c ){ pc = pOp->p2-1; } @@ -2119,11 +2265,13 @@ case OP_IfNot: { /* jump, in1 */ } /* Opcode: IsNull P1 P2 * * * +** Synopsis: if r[P1]==NULL goto P2 ** ** Jump to P2 if the value in register P1 is NULL. */ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; + VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2); if( (pIn1->flags & MEM_Null)!=0 ){ pc = pOp->p2 - 1; } @@ -2131,11 +2279,13 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ } /* Opcode: NotNull P1 P2 * * * +** Synopsis: if r[P1]!=NULL goto P2 ** ** Jump to P2 if the value in register P1 is not NULL. */ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; + VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2); if( (pIn1->flags & MEM_Null)==0 ){ pc = pOp->p2 - 1; } @@ -2143,6 +2293,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ } /* Opcode: Column P1 P2 P3 P4 P5 +** Synopsis: r[P3]=PX ** ** Interpret the data that cursor P1 points to as a structure built using ** the MakeRecord instruction. (See the MakeRecord opcode for additional @@ -2167,153 +2318,98 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ ** skipped for length() and all content loading can be skipped for typeof(). */ case OP_Column: { - u32 payloadSize; /* Number of bytes in the record */ i64 payloadSize64; /* Number of bytes in the record */ - int p1; /* P1 value of the opcode */ int p2; /* column number to retrieve */ VdbeCursor *pC; /* The VDBE cursor */ - char *zRec; /* Pointer to complete record-data */ BtCursor *pCrsr; /* The BTree cursor */ u32 *aType; /* aType[i] holds the numeric type of the i-th column */ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ - int nField; /* number of fields in the record */ int len; /* The length of the serialized data for the column */ int i; /* Loop counter */ - char *zData; /* Part of the record being decoded */ Mem *pDest; /* Where to write the extracted value */ Mem sMem; /* For storing the record being decoded */ - u8 *zIdx; /* Index into header */ - u8 *zEndHdr; /* Pointer to first byte after the header */ + const u8 *zData; /* Part of the record being decoded */ + const u8 *zHdr; /* Next unparsed byte of the header */ + const u8 *zEndHdr; /* Pointer to first byte after the header */ u32 offset; /* Offset into the data */ u32 szField; /* Number of bytes in the content of a field */ - int szHdr; /* Size of the header size field at start of record */ - int avail; /* Number of bytes of available data */ + u32 avail; /* Number of bytes of available data */ u32 t; /* A type code from the record header */ Mem *pReg; /* PseudoTable input register */ - - p1 = pOp->p1; p2 = pOp->p2; - pC = 0; - memset(&sMem, 0, sizeof(sMem)); - assert( p1nCursor ); - assert( pOp->p3>0 && pOp->p3<=p->nMem ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); - zRec = 0; - - /* This block sets the variable payloadSize to be the total number of - ** bytes in the record. - ** - ** zRec is set to be the complete text of the record if it is available. - ** The complete record text is always available for pseudo-tables - ** If the record is stored in a cursor, the complete record text - ** might be available in the pC->aRow cache. Or it might not be. - ** If the data is unavailable, zRec is set to NULL. - ** - ** We also compute the number of columns in the record. For cursors, - ** the number of columns is stored in the VdbeCursor.nField element. - */ - pC = p->apCsr[p1]; + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; assert( pC!=0 ); + assert( p2nField ); + aType = pC->aType; + aOffset = aType + pC->nField; #ifndef SQLITE_OMIT_VIRTUALTABLE - assert( pC->pVtabCursor==0 ); + assert( pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */ #endif pCrsr = pC->pCursor; - if( pCrsr!=0 ){ - /* The record is stored in a B-Tree */ - rc = sqlite3VdbeCursorMoveto(pC); - if( rc ) goto abort_due_to_error; - if( pC->nullRow ){ - payloadSize = 0; - }else if( pC->cacheStatus==p->cacheCtr ){ - payloadSize = pC->payloadSize; - zRec = (char*)pC->aRow; - }else if( pC->isIndex ){ - assert( sqlite3BtreeCursorIsValid(pCrsr) ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64); - assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ - /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the - ** payload size, so it is impossible for payloadSize64 to be - ** larger than 32 bits. */ - assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 ); - payloadSize = (u32)payloadSize64; - }else{ - assert( sqlite3BtreeCursorIsValid(pCrsr) ); - VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &payloadSize); - assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ - } - }else if( ALWAYS(pC->pseudoTableReg>0) ){ - pReg = &aMem[pC->pseudoTableReg]; - if( pC->multiPseudo ){ - sqlite3VdbeMemShallowCopy(pDest, pReg+p2, MEM_Ephem); - Deephemeralize(pDest); - goto op_column_out; - } - assert( pReg->flags & MEM_Blob ); - assert( memIsValid(pReg) ); - payloadSize = pReg->n; - zRec = pReg->z; - pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr; - assert( payloadSize==0 || zRec!=0 ); - }else{ - /* Consider the row to be NULL */ - payloadSize = 0; - } - - /* If payloadSize is 0, then just store a NULL. This can happen because of - ** nullRow or because of a corrupt database. */ - if( payloadSize==0 ){ - MemSetTypeFlag(pDest, MEM_Null); - goto op_column_out; - } - assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 ); - if( payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - - nField = pC->nField; - assert( p2aType; - if( pC->cacheStatus==p->cacheCtr ){ - aOffset = pC->aOffset; - }else{ - assert(aType); - avail = 0; - pC->aOffset = aOffset = &aType[nField]; - pC->payloadSize = payloadSize; - pC->cacheStatus = p->cacheCtr; + assert( pCrsr!=0 || pC->pseudoTableReg>0 ); /* pCrsr NULL on PseudoTables */ + assert( pCrsr!=0 || pC->nullRow ); /* pC->nullRow on PseudoTables */ - /* Figure out how many bytes are in the header */ - if( zRec ){ - zData = zRec; + /* If the cursor cache is stale, bring it up-to-date */ + rc = sqlite3VdbeCursorMoveto(pC); + if( rc ) goto abort_due_to_error; + if( pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){ + if( pC->nullRow ){ + if( pCrsr==0 ){ + assert( pC->pseudoTableReg>0 ); + pReg = &aMem[pC->pseudoTableReg]; + assert( pReg->flags & MEM_Blob ); + assert( memIsValid(pReg) ); + pC->payloadSize = pC->szRow = avail = pReg->n; + pC->aRow = (u8*)pReg->z; + }else{ + MemSetTypeFlag(pDest, MEM_Null); + goto op_column_out; + } }else{ - if( pC->isIndex ){ - zData = (char*)sqlite3BtreeKeyFetch(pCrsr, &avail); + assert( pCrsr ); + if( pC->isTable==0 ){ + assert( sqlite3BtreeCursorIsValid(pCrsr) ); + VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64); + assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ + /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the + ** payload size, so it is impossible for payloadSize64 to be + ** larger than 32 bits. */ + assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 ); + pC->aRow = sqlite3BtreeKeyFetch(pCrsr, &avail); + pC->payloadSize = (u32)payloadSize64; }else{ - zData = (char*)sqlite3BtreeDataFetch(pCrsr, &avail); + assert( sqlite3BtreeCursorIsValid(pCrsr) ); + VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &pC->payloadSize); + assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ + pC->aRow = sqlite3BtreeDataFetch(pCrsr, &avail); } - /* If KeyFetch()/DataFetch() managed to get the entire payload, - ** save the payload in the pC->aRow cache. That will save us from - ** having to make additional calls to fetch the content portion of - ** the record. - */ - assert( avail>=0 ); - if( payloadSize <= (u32)avail ){ - zRec = zData; - pC->aRow = (u8*)zData; + assert( avail<=65536 ); /* Maximum page size is 64KiB */ + if( pC->payloadSize <= (u32)avail ){ + pC->szRow = pC->payloadSize; }else{ - pC->aRow = 0; + pC->szRow = avail; } + if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + } + pC->cacheStatus = p->cacheCtr; + pC->iHdrOffset = getVarint32(pC->aRow, offset); + pC->nHdrParsed = 0; + aOffset[0] = offset; + if( availaRow does not have to hold the entire row, but it does at least + ** need to cover the header of the record. If pC->aRow does not contain + ** the complete header, then set it to zero, forcing the header to be + ** dynamically allocated. */ + pC->aRow = 0; + pC->szRow = 0; } - /* The following assert is true in all cases except when - ** the database file has been corrupted externally. - ** assert( zRec!=0 || avail>=payloadSize || avail>=9 ); */ - szHdr = getVarint32((u8*)zData, offset); /* Make sure a corrupt database has not given us an oversize header. ** Do this now to avoid an oversize memory allocation. @@ -2324,161 +2420,156 @@ case OP_Column: { ** 3-byte type for each of the maximum of 32768 columns plus three ** extra bytes for the header length itself. 32768*3 + 3 = 98307. */ - if( offset > 98307 ){ + if( offset > 98307 || offset > pC->payloadSize ){ rc = SQLITE_CORRUPT_BKPT; - goto op_column_out; + goto op_column_error; } + } - /* Compute in len the number of bytes of data we need to read in order - ** to get nField type values. offset is an upper bound on this. But - ** nField might be significantly less than the true number of columns - ** in the table, and in that case, 5*nField+3 might be smaller than offset. - ** We want to minimize len in order to limit the size of the memory - ** allocation, especially if a corrupt database file has caused offset - ** to be oversized. Offset is limited to 98307 above. But 98307 might - ** still exceed Robson memory allocation limits on some configurations. - ** On systems that cannot tolerate large memory allocations, nField*5+3 - ** will likely be much smaller since nField will likely be less than - ** 20 or so. This insures that Robson memory allocation limits are - ** not exceeded even for corrupt database files. - */ - len = nField*5 + 3; - if( len > (int)offset ) len = (int)offset; - - /* The KeyFetch() or DataFetch() above are fast and will get the entire - ** record header in most cases. But they will fail to get the complete - ** record header if the record header does not fit on a single page - ** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to - ** acquire the complete header text. + /* Make sure at least the first p2+1 entries of the header have been + ** parsed and valid information is in aOffset[] and aType[]. + */ + if( pC->nHdrParsed<=p2 ){ + /* If there is more header available for parsing in the record, try + ** to extract additional fields up through the p2+1-th field */ - if( !zRec && availisIndex, &sMem); - if( rc!=SQLITE_OK ){ - goto op_column_out; + if( pC->iHdrOffsetaRow==0 ){ + memset(&sMem, 0, sizeof(sMem)); + rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], + !pC->isTable, &sMem); + if( rc!=SQLITE_OK ){ + goto op_column_error; + } + zData = (u8*)sMem.z; + }else{ + zData = pC->aRow; } - zData = sMem.z; - } - zEndHdr = (u8 *)&zData[len]; - zIdx = (u8 *)&zData[szHdr]; - - /* Scan the header and use it to fill in the aType[] and aOffset[] - ** arrays. aType[i] will contain the type integer for the i-th - ** column and aOffset[i] will contain the offset from the beginning - ** of the record to the start of the data for the i-th column - */ - for(i=0; inHdrParsed; + offset = aOffset[i]; + zHdr = zData + pC->iHdrOffset; + zEndHdr = zData + aOffset[0]; + assert( i<=p2 && zHdrnHdrParsed = i; + pC->iHdrOffset = (u32)(zHdr - zData); + if( pC->aRow==0 ){ + sqlite3VdbeMemRelease(&sMem); + sMem.flags = MEM_Null; + } + + /* If we have read more header data than was contained in the header, + ** or if the end of the last field appears to be past the end of the + ** record, or if the end of the last field appears to be before the end + ** of the record (when all fields present), then we must be dealing + ** with a corrupt database. + */ + if( (zHdr > zEndHdr) + || (offset > pC->payloadSize) + || (zHdr==zEndHdr && offset!=pC->payloadSize) + ){ + rc = SQLITE_CORRUPT_BKPT; + goto op_column_error; } } - sqlite3VdbeMemRelease(&sMem); - sMem.flags = MEM_Null; - - /* If we have read more header data than was contained in the header, - ** or if the end of the last field appears to be past the end of the - ** record, or if the end of the last field appears to be before the end - ** of the record (when all fields present), then we must be dealing - ** with a corrupt database. + + /* If after trying to extra new entries from the header, nHdrParsed is + ** still not up to p2, that means that the record has fewer than p2 + ** columns. So the result will be either the default value or a NULL. */ - if( (zIdx > zEndHdr) || (offset > payloadSize) - || (zIdx==zEndHdr && offset!=payloadSize) ){ - rc = SQLITE_CORRUPT_BKPT; + if( pC->nHdrParsed<=p2 ){ + if( pOp->p4type==P4_MEM ){ + sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); + }else{ + MemSetTypeFlag(pDest, MEM_Null); + } goto op_column_out; } } - /* Get the column information. If aOffset[p2] is non-zero, then - ** deserialize the value from the record. If aOffset[p2] is zero, - ** then there are not enough fields in the record to satisfy the - ** request. In this case, set the value NULL or to P4 if P4 is - ** a pointer to a Mem object. + /* Extract the content for the p2+1-th column. Control can only + ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are + ** all valid. */ - if( aOffset[p2] ){ - assert( rc==SQLITE_OK ); - if( zRec ){ - /* This is the common case where the whole row fits on a single page */ - VdbeMemRelease(pDest); - sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], pDest); + assert( p2nHdrParsed ); + assert( rc==SQLITE_OK ); + assert( sqlite3VdbeCheckMemInvariants(pDest) ); + if( pC->szRow>=aOffset[p2+1] ){ + /* This is the common case where the desired content fits on the original + ** page - where the content is not on an overflow page */ + VdbeMemRelease(pDest); + sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest); + }else{ + /* This branch happens only when content is on overflow pages */ + t = aType[p2]; + if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 + && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)) + || (len = sqlite3VdbeSerialTypeLen(t))==0 + ){ + /* Content is irrelevant for the typeof() function and for + ** the length(X) function if X is a blob. So we might as well use + ** bogus content rather than reading content from disk. NULL works + ** for text and blob and whatever is in the payloadSize64 variable + ** will work for everything else. Content is also irrelevant if + ** the content length is 0. */ + zData = t<=13 ? (u8*)&payloadSize64 : 0; + sMem.zMalloc = 0; }else{ - /* This branch happens only when the row overflows onto multiple pages */ - t = aType[p2]; - if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 - && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0) - ){ - /* Content is irrelevant for the typeof() function and for - ** the length(X) function if X is a blob. So we might as well use - ** bogus content rather than reading content from disk. NULL works - ** for text and blob and whatever is in the payloadSize64 variable - ** will work for everything else. */ - zData = t<12 ? (char*)&payloadSize64 : 0; - }else{ - len = sqlite3VdbeSerialTypeLen(t); - sqlite3VdbeMemMove(&sMem, pDest); - rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, - &sMem); - if( rc!=SQLITE_OK ){ - goto op_column_out; - } - zData = sMem.z; + memset(&sMem, 0, sizeof(sMem)); + sqlite3VdbeMemMove(&sMem, pDest); + rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable, + &sMem); + if( rc!=SQLITE_OK ){ + goto op_column_error; } - sqlite3VdbeSerialGet((u8*)zData, t, pDest); + zData = (u8*)sMem.z; } - pDest->enc = encoding; - }else{ - if( pOp->p4type==P4_MEM ){ - sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); - }else{ - MemSetTypeFlag(pDest, MEM_Null); + sqlite3VdbeSerialGet(zData, t, pDest); + /* If we dynamically allocated space to hold the data (in the + ** sqlite3VdbeMemFromBtree() call above) then transfer control of that + ** dynamically allocated space over to the pDest structure. + ** This prevents a memory copy. */ + if( sMem.zMalloc ){ + assert( sMem.z==sMem.zMalloc ); + assert( VdbeMemDynamic(pDest)==0 ); + assert( (pDest->flags & (MEM_Blob|MEM_Str))==0 || pDest->z==sMem.z ); + pDest->flags &= ~(MEM_Ephem|MEM_Static); + pDest->flags |= MEM_Term; + pDest->z = sMem.z; + pDest->zMalloc = sMem.zMalloc; } } - - /* If we dynamically allocated space to hold the data (in the - ** sqlite3VdbeMemFromBtree() call above) then transfer control of that - ** dynamically allocated space over to the pDest structure. - ** This prevents a memory copy. - */ - if( sMem.zMalloc ){ - assert( sMem.z==sMem.zMalloc ); - assert( !(pDest->flags & MEM_Dyn) ); - assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z ); - pDest->flags &= ~(MEM_Ephem|MEM_Static); - pDest->flags |= MEM_Term; - pDest->z = sMem.z; - pDest->zMalloc = sMem.zMalloc; - } - - rc = sqlite3VdbeMemMakeWriteable(pDest); + pDest->enc = encoding; op_column_out: + Deephemeralize(pDest); +op_column_error: UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); break; } /* Opcode: Affinity P1 P2 * P4 * +** Synopsis: affinity(r[P1@P2]) ** ** Apply affinities to a range of P2 registers starting with P1. ** @@ -2495,9 +2586,8 @@ case OP_Affinity: { assert( zAffinity[pOp->p2]==0 ); pIn1 = &aMem[pOp->p1]; while( (cAff = *(zAffinity++))!=0 ){ - assert( pIn1 <= &p->aMem[p->nMem] ); + assert( pIn1 <= &p->aMem[(p->nMem-p->nCursor)] ); assert( memIsValid(pIn1) ); - ExpandBlob(pIn1); applyAffinity(pIn1, cAff, encoding); pIn1++; } @@ -2505,6 +2595,7 @@ case OP_Affinity: { } /* Opcode: MakeRecord P1 P2 P3 P4 * +** Synopsis: r[P3]=mkrec(r[P1@P2]) ** ** Convert P2 registers beginning with P1 into the [record format] ** use as a data record in a database table or as a key @@ -2533,7 +2624,8 @@ case OP_MakeRecord: { int nField; /* Number of fields in the record */ char *zAffinity; /* The affinity string for the record */ int file_format; /* File format to use for encoding */ - int i; /* Space used in zNewRecord[] */ + int i; /* Space used in zNewRecord[] header */ + int j; /* Space used in zNewRecord[] content */ int len; /* Length of a field */ /* Assuming the record contains N fields, the record format looks @@ -2556,7 +2648,7 @@ case OP_MakeRecord: { nZero = 0; /* Number of zero bytes at the end of the record */ nField = pOp->p1; zAffinity = pOp->p4.z; - assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem+1 ); + assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem-p->nCursor)+1 ); pData0 = &aMem[nField]; nField = pOp->p2; pLast = &pData0[nField-1]; @@ -2567,36 +2659,52 @@ case OP_MakeRecord: { pOut = &aMem[pOp->p3]; memAboutToChange(p, pOut); + /* Apply the requested affinity to all inputs + */ + assert( pData0<=pLast ); + if( zAffinity ){ + pRec = pData0; + do{ + applyAffinity(pRec++, *(zAffinity++), encoding); + assert( zAffinity[0]==0 || pRec<=pLast ); + }while( zAffinity[0] ); + } + /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ - for(pRec=pData0; pRec<=pLast; pRec++){ + pRec = pLast; + do{ assert( memIsValid(pRec) ); - if( zAffinity ){ - applyAffinity(pRec, zAffinity[pRec-pData0], encoding); - } - if( pRec->flags&MEM_Zero && pRec->n>0 ){ - sqlite3VdbeMemExpandBlob(pRec); - } serial_type = sqlite3VdbeSerialType(pRec, file_format); len = sqlite3VdbeSerialTypeLen(serial_type); - nData += len; - nHdr += sqlite3VarintLen(serial_type); if( pRec->flags & MEM_Zero ){ - /* Only pure zero-filled BLOBs can be input to this Opcode. - ** We do not allow blobs with a prefix and a zero-filled tail. */ - nZero += pRec->u.nZero; - }else if( len ){ - nZero = 0; + if( nData ){ + sqlite3VdbeMemExpandBlob(pRec); + }else{ + nZero += pRec->u.nZero; + len -= pRec->u.nZero; + } } - } + nData += len; + testcase( serial_type==127 ); + testcase( serial_type==128 ); + nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); + }while( (--pRec)>=pData0 ); /* Add the initial header varint and total the size */ - nHdr += nVarint = sqlite3VarintLen(nHdr); - if( nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } @@ -2613,18 +2721,20 @@ case OP_MakeRecord: { /* Write the record */ i = putVarint32(zNewRecord, nHdr); - for(pRec=pData0; pRec<=pLast; pRec++){ + j = nHdr; + assert( pData0<=pLast ); + pRec = pData0; + do{ serial_type = sqlite3VdbeSerialType(pRec, file_format); - i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ - } - for(pRec=pData0; pRec<=pLast; pRec++){ /* serial data */ - i += sqlite3VdbeSerialPut(&zNewRecord[i], (int)(nByte-i), pRec,file_format); - } - assert( i==nByte ); + i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ + j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */ + }while( (++pRec)<=pLast ); + assert( i==nHdr ); + assert( j==nByte ); - assert( pOp->p3>0 && pOp->p3<=p->nMem ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pOut->n = (int)nByte; - pOut->flags = MEM_Blob | MEM_Dyn; + pOut->flags = MEM_Blob; pOut->xDel = 0; if( nZero ){ pOut->u.nZero = nZero; @@ -2637,6 +2747,7 @@ case OP_MakeRecord: { } /* Opcode: Count P1 P2 * * * +** Synopsis: r[P2]=count() ** ** Store the number of entries (an integer value) in the table or index ** opened by cursor P1 in register P2 @@ -2647,11 +2758,9 @@ case OP_Count: { /* out2-prerelease */ BtCursor *pCrsr; pCrsr = p->apCsr[pOp->p1]->pCursor; - if( ALWAYS(pCrsr) ){ - rc = sqlite3BtreeCount(pCrsr, &nEntry); - }else{ - nEntry = 0; - } + assert( pCrsr ); + nEntry = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3BtreeCount(pCrsr, &nEntry); pOut->u.i = nEntry; break; } @@ -2683,9 +2792,10 @@ case OP_Savepoint: { assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK ); assert( db->pSavepoint || db->isTransactionSavepoint==0 ); assert( checkSavepointCount(db) ); + assert( p->bIsReader ); if( p1==SAVEPOINT_BEGIN ){ - if( db->writeVdbeCnt>0 ){ + if( db->nVdbeWrite>0 ){ /* A new savepoint cannot be created if there are active write ** statements (i.e. open read/write incremental blob handles). */ @@ -2725,6 +2835,7 @@ case OP_Savepoint: { pNew->pNext = db->pSavepoint; db->pSavepoint = pNew; pNew->nDeferredCons = db->nDeferredCons; + pNew->nDeferredImmCons = db->nDeferredImmCons; } } }else{ @@ -2742,7 +2853,7 @@ case OP_Savepoint: { if( !pSavepoint ){ sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", zName); rc = SQLITE_ERROR; - }else if( db->writeVdbeCnt>0 && p1==SAVEPOINT_RELEASE ){ + }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){ /* It is not possible to release (commit) a savepoint if there are ** active write statements. */ @@ -2812,6 +2923,7 @@ case OP_Savepoint: { } }else{ db->nDeferredCons = pSavepoint->nDeferredCons; + db->nDeferredImmCons = pSavepoint->nDeferredImmCons; } if( !isTransaction ){ @@ -2843,10 +2955,11 @@ case OP_AutoCommit: { turnOnAC = desiredAutoCommit && !db->autoCommit; assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); assert( desiredAutoCommit==1 || iRollback==0 ); - assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ + assert( db->nVdbeActive>0 ); /* At least this one VM is active */ + assert( p->bIsReader ); #if 0 - if( turnOnAC && iRollback && db->activeVdbeCnt>1 ){ + if( turnOnAC && iRollback && db->nVdbeActive>1 ){ /* If this instruction implements a ROLLBACK and other VMs are ** still running, and a transaction is active, return an error indicating ** that the other VMs must complete first. @@ -2856,7 +2969,7 @@ case OP_AutoCommit: { rc = SQLITE_BUSY; }else #endif - if( turnOnAC && !iRollback && db->writeVdbeCnt>0 ){ + if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){ /* If this instruction implements a COMMIT and other VMs are writing ** return an error indicating that the other VMs must complete first. */ @@ -2898,25 +3011,19 @@ case OP_AutoCommit: { break; } -/* Opcode: Transaction P1 P2 * * * +/* Opcode: Transaction P1 P2 P3 P4 P5 ** -** Begin a transaction. The transaction ends when a Commit or Rollback -** opcode is encountered. Depending on the ON CONFLICT setting, the -** transaction might also be rolled back if an error is encountered. +** Begin a transaction on database P1 if a transaction is not already +** active. +** If P2 is non-zero, then a write-transaction is started, or if a +** read-transaction is already active, it is upgraded to a write-transaction. +** If P2 is zero, then a read-transaction is started. ** ** P1 is the index of the database file on which the transaction is ** started. Index 0 is the main database file and index 1 is the ** file used for temporary tables. Indices of 2 or more are used for ** attached databases. ** -** If P2 is non-zero, then a write-transaction is started. A RESERVED lock is -** obtained on the database file when a write-transaction is started. No -** other process can start another write transaction while this transaction is -** underway. Starting a write transaction also creates a rollback journal. A -** write transaction must be started before any changes can be made to the -** database. If P2 is 2 or greater then an EXCLUSIVE lock is also obtained -** on the file. -** ** If a write-transaction is started and the Vdbe.usesStmtJournal flag is ** true (this flag is set if the Vdbe may modify more than one row and may ** throw an ABORT exception), a statement transaction may also be opened. @@ -2927,13 +3034,30 @@ case OP_AutoCommit: { ** entire transaction. If no error is encountered, the statement transaction ** will automatically commit when the VDBE halts. ** -** If P2 is zero, then a read-lock is obtained on the database file. +** If P5!=0 then this opcode also checks the schema cookie against P3 +** and the schema generation counter against P4. +** The cookie changes its value whenever the database schema changes. +** This operation is used to detect when that the cookie has changed +** and that the current process needs to reread the schema. If the schema +** cookie in P3 differs from the schema cookie in the database header or +** if the schema generation counter in P4 differs from the current +** generation counter, then an SQLITE_SCHEMA error is raised and execution +** halts. The sqlite3_step() wrapper function might then reprepare the +** statement and rerun it from the beginning. */ case OP_Transaction: { Btree *pBt; + int iMeta; + int iGen; + assert( p->bIsReader ); + assert( p->readOnly==0 || pOp->p2==0 ); assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); + if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){ + rc = SQLITE_READONLY; + goto abort_due_to_error; + } pBt = db->aDb[pOp->p1].pBt; if( pBt ){ @@ -2948,7 +3072,7 @@ case OP_Transaction: { } if( pOp->p2 && p->usesStmtJournal - && (db->autoCommit==0 || db->activeVdbeCnt>1) + && (db->autoCommit==0 || db->nVdbeRead>1) ){ assert( sqlite3BtreeIsInTrans(pBt) ); if( p->iStatement==0 ){ @@ -2966,14 +3090,44 @@ case OP_Transaction: { ** counter. If the statement transaction needs to be rolled back, ** the value of this counter needs to be restored too. */ p->nStmtDefCons = db->nDeferredCons; + p->nStmtDefImmCons = db->nDeferredImmCons; } - } - break; -} -/* Opcode: ReadCookie P1 P2 P3 * * -** -** Read cookie number P3 from database P1 and write it into register P2. + /* Gather the schema version number for checking */ + sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); + iGen = db->aDb[pOp->p1].pSchema->iGeneration; + }else{ + iGen = iMeta = 0; + } + assert( pOp->p5==0 || pOp->p4type==P4_INT32 ); + if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){ + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); + /* If the schema-cookie from the database file matches the cookie + ** stored with the in-memory representation of the schema, do + ** not reload the schema from the database file. + ** + ** If virtual-tables are in use, this is not just an optimization. + ** Often, v-tables store their data in other SQLite tables, which + ** are queried from within xNext() and other v-table methods using + ** prepared queries. If such a query is out-of-date, we do not want to + ** discard the database schema, as the user code implementing the + ** v-table would have to be ready for the sqlite3_vtab structure itself + ** to be invalidated whenever sqlite3_step() is called from within + ** a v-table method. + */ + if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ + sqlite3ResetOneSchema(db, pOp->p1); + } + p->expired = 1; + rc = SQLITE_SCHEMA; + } + break; +} + +/* Opcode: ReadCookie P1 P2 P3 * * +** +** Read cookie number P3 from database P1 and write it into register P2. ** P3==1 is the schema version. P3==2 is the database format. ** P3==3 is the recommended pager cache size, and so forth. P1==0 is ** the main database file and P1==1 is the database file used to store @@ -2988,12 +3142,13 @@ case OP_ReadCookie: { /* out2-prerelease */ int iDb; int iCookie; + assert( p->bIsReader ); iDb = pOp->p1; iCookie = pOp->p3; assert( pOp->p3=0 && iDbnDb ); assert( db->aDb[iDb].pBt!=0 ); - assert( (p->btreeMask & (((yDbMask)1)<btreeMask, iDb) ); sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta); pOut->u.i = iMeta; @@ -3014,7 +3169,8 @@ case OP_SetCookie: { /* in3 */ Db *pDb; assert( pOp->p2p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( p->readOnly==0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); @@ -3039,66 +3195,8 @@ case OP_SetCookie: { /* in3 */ break; } -/* Opcode: VerifyCookie P1 P2 P3 * * -** -** Check the value of global database parameter number 0 (the -** schema version) and make sure it is equal to P2 and that the -** generation counter on the local schema parse equals P3. -** -** P1 is the database number which is 0 for the main database file -** and 1 for the file holding temporary tables and some higher number -** for auxiliary databases. -** -** The cookie changes its value whenever the database schema changes. -** This operation is used to detect when that the cookie has changed -** and that the current process needs to reread the schema. -** -** Either a transaction needs to have been started or an OP_Open needs -** to be executed (to establish a read lock) before this opcode is -** invoked. -*/ -case OP_VerifyCookie: { - int iMeta; - int iGen; - Btree *pBt; - - assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); - assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); - pBt = db->aDb[pOp->p1].pBt; - if( pBt ){ - sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); - iGen = db->aDb[pOp->p1].pSchema->iGeneration; - }else{ - iGen = iMeta = 0; - } - if( iMeta!=pOp->p2 || iGen!=pOp->p3 ){ - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); - /* If the schema-cookie from the database file matches the cookie - ** stored with the in-memory representation of the schema, do - ** not reload the schema from the database file. - ** - ** If virtual-tables are in use, this is not just an optimization. - ** Often, v-tables store their data in other SQLite tables, which - ** are queried from within xNext() and other v-table methods using - ** prepared queries. If such a query is out-of-date, we do not want to - ** discard the database schema, as the user code implementing the - ** v-table would have to be ready for the sqlite3_vtab structure itself - ** to be invalidated whenever sqlite3_step() is called from within - ** a v-table method. - */ - if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ - sqlite3ResetOneSchema(db, pOp->p1); - } - - p->expired = 1; - rc = SQLITE_SCHEMA; - } - break; -} - /* Opcode: OpenRead P1 P2 P3 P4 P5 +** Synopsis: root=P2 iDb=P3 ** ** Open a read-only cursor for the database table whose root page is ** P2 in a database file. The database file is determined by P3. @@ -3126,9 +3224,24 @@ case OP_VerifyCookie: { ** sequence of the index being opened. Otherwise, if P4 is an integer ** value, it is set to the number of columns in the table. ** -** See also OpenWrite. +** See also: OpenWrite, ReopenIdx +*/ +/* Opcode: ReopenIdx P1 P2 P3 P4 P5 +** Synopsis: root=P2 iDb=P3 +** +** The ReopenIdx opcode works exactly like ReadOpen except that it first +** checks to see if the cursor on P1 is already open with a root page +** number of P2 and if it is this opcode becomes a no-op. In other words, +** if the cursor is already open, do not reopen it. +** +** The ReopenIdx opcode may only be used with P5==0 and with P4 being +** a P4_KEYINFO object. Furthermore, the P3 value must be the same as +** every other ReopenIdx or OpenRead for the same cursor number. +** +** See the OpenRead opcode documentation for additional information. */ /* Opcode: OpenWrite P1 P2 P3 P4 P5 +** Synopsis: root=P2 iDb=P3 ** ** Open a read/write cursor named P1 on the table or index whose root ** page is P2. Or if P5!=0 use the content of register P2 to find the @@ -3147,6 +3260,19 @@ case OP_VerifyCookie: { ** ** See also OpenRead. */ +case OP_ReopenIdx: { + VdbeCursor *pCur; + + assert( pOp->p5==0 ); + assert( pOp->p4type==P4_KEYINFO ); + pCur = p->apCsr[pOp->p1]; + if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ + assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ + break; + } + /* If the cursor is not currently open or is open on a different + ** index, then fall through into OP_OpenRead to force a reopen */ +} case OP_OpenRead: case OP_OpenWrite: { int nField; @@ -3160,6 +3286,9 @@ case OP_OpenWrite: { assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); + assert( p->bIsReader ); + assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx + || p->readOnly==0 ); if( p->expired ){ rc = SQLITE_ABORT; @@ -3171,7 +3300,7 @@ case OP_OpenWrite: { p2 = pOp->p2; iDb = pOp->p3; assert( iDb>=0 && iDbnDb ); - assert( (p->btreeMask & (((yDbMask)1)<btreeMask, iDb) ); pDb = &db->aDb[iDb]; pX = pDb->pBt; assert( pX!=0 ); @@ -3186,7 +3315,7 @@ case OP_OpenWrite: { } if( pOp->p5 & OPFLAG_P2ISREG ){ assert( p2>0 ); - assert( p2<=p->nMem ); + assert( p2<=(p->nMem-p->nCursor) ); pIn2 = &aMem[p2]; assert( memIsValid(pIn2) ); assert( (pIn2->flags & MEM_Int)!=0 ); @@ -3203,16 +3332,20 @@ case OP_OpenWrite: { } if( pOp->p4type==P4_KEYINFO ){ pKeyInfo = pOp->p4.pKeyInfo; - pKeyInfo->enc = ENC(p->db); - nField = pKeyInfo->nField+1; + assert( pKeyInfo->enc==ENC(db) ); + assert( pKeyInfo->db==db ); + nField = pKeyInfo->nField+pKeyInfo->nXField; }else if( pOp->p4type==P4_INT32 ){ nField = pOp->p4.i; } assert( pOp->p1>=0 ); + assert( nField>=0 ); + testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */ pCur = allocateCursor(p, pOp->p1, nField, iDb, 1); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; pCur->isOrdered = 1; + pCur->pgnoRoot = p2; rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); pCur->pKeyInfo = pKeyInfo; assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); @@ -3222,16 +3355,16 @@ case OP_OpenWrite: { ** sqlite3BtreeCursor() may return is SQLITE_OK. */ assert( rc==SQLITE_OK ); - /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of + /* Set the VdbeCursor.isTable variable. Previous versions of ** SQLite used to check if the root-page flags were sane at this point ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; - pCur->isIndex = !pCur->isTable; break; } /* Opcode: OpenEphemeral P1 P2 * P4 P5 +** Synopsis: nColumn=P2 ** ** Open a new cursor P1 to a transient table. ** The cursor is always opened read/write even if @@ -3243,18 +3376,13 @@ case OP_OpenWrite: { ** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure ** that defines the format of keys in the index. ** -** This opcode was once called OpenTemp. But that created -** confusion because the term "temp table", might refer either -** to a TEMP table at the SQL level, or to a table opened by -** this opcode. Then this opcode was call OpenVirtual. But -** that created confusion with the whole virtual-table idea. -** ** The P5 parameter can be a mask of the BTREE_* flags defined ** in btree.h. These flags control aspects of the operation of ** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are ** added automatically. */ /* Opcode: OpenAutoindex P1 P2 * P4 * +** Synopsis: nColumn=P2 ** ** This opcode works the same as OP_OpenEphemeral. It has a ** different name to distinguish its use. Tables created using @@ -3264,17 +3392,20 @@ case OP_OpenWrite: { case OP_OpenAutoindex: case OP_OpenEphemeral: { VdbeCursor *pCx; + KeyInfo *pKeyInfo; + static const int vfsFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TRANSIENT_DB; - assert( pOp->p1>=0 ); + assert( pOp->p2>=0 ); pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; + pCx->isEphemeral = 1; rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); if( rc==SQLITE_OK ){ @@ -3286,16 +3417,16 @@ case OP_OpenEphemeral: { ** opening it. If a transient table is required, just use the ** automatically created table with root-page 1 (an BLOB_INTKEY table). */ - if( pOp->p4.pKeyInfo ){ + if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ int pgno; assert( pOp->p4type==P4_KEYINFO ); rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); - rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, - (KeyInfo*)pOp->p4.z, pCx->pCursor); - pCx->pKeyInfo = pOp->p4.pKeyInfo; - pCx->pKeyInfo->enc = ENC(p->db); + assert( pKeyInfo->db==db ); + assert( pKeyInfo->enc==ENC(db) ); + pCx->pKeyInfo = pKeyInfo; + rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, pKeyInfo, pCx->pCursor); } pCx->isTable = 0; }else{ @@ -3304,7 +3435,6 @@ case OP_OpenEphemeral: { } } pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); - pCx->isIndex = !pCx->isTable; break; } @@ -3317,22 +3447,24 @@ case OP_OpenEphemeral: { case OP_SorterOpen: { VdbeCursor *pCx; + assert( pOp->p1>=0 ); + assert( pOp->p2>=0 ); pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; pCx->pKeyInfo = pOp->p4.pKeyInfo; - pCx->pKeyInfo->enc = ENC(p->db); - pCx->isSorter = 1; + assert( pCx->pKeyInfo->db==db ); + assert( pCx->pKeyInfo->enc==ENC(db) ); rc = sqlite3VdbeSorterInit(db, pCx); break; } -/* Opcode: OpenPseudo P1 P2 P3 * P5 +/* Opcode: OpenPseudo P1 P2 P3 * * +** Synopsis: P3 columns in r[P2] ** ** Open a new cursor that points to a fake table that contains a single -** row of data. The content of that one row in the content of memory -** register P2 when P5==0. In other words, cursor P1 becomes an alias for the -** MEM_Blob content contained in register P2. When P5==1, then the -** row is represented by P3 consecutive registers beginning with P2. +** row of data. The content of that one row is the content of memory +** register P2. In other words, cursor P1 becomes an alias for the +** MEM_Blob content contained in register P2. ** ** A pseudo-table created by this opcode is used to hold a single ** row output from the sorter so that the row can be decomposed into @@ -3346,13 +3478,13 @@ case OP_OpenPseudo: { VdbeCursor *pCx; assert( pOp->p1>=0 ); + assert( pOp->p3>=0 ); pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->pseudoTableReg = pOp->p2; pCx->isTable = 1; - pCx->isIndex = 0; - pCx->multiPseudo = pOp->p5; + assert( pOp->p5==0 ); break; } @@ -3368,7 +3500,8 @@ case OP_Close: { break; } -/* Opcode: SeekGe P1 P2 P3 P4 * +/* Opcode: SeekGE P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), ** use the value in register P3 as the key. If cursor P1 refers @@ -3379,9 +3512,14 @@ case OP_Close: { ** is greater than or equal to the key value. If there are no records ** greater than or equal to the key and P2 is not zero, then jump to P2. ** -** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe +** This opcode leaves the cursor configured to move in forward order, +** from the beginning toward the end. In other words, the cursor is +** configured to use Next, not Prev. +** +** See also: Found, NotFound, SeekLt, SeekGt, SeekLe */ -/* Opcode: SeekGt P1 P2 P3 P4 * +/* Opcode: SeekGT P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), ** use the value in register P3 as a key. If cursor P1 refers @@ -3392,9 +3530,14 @@ case OP_Close: { ** is greater than the key value. If there are no records greater than ** the key and P2 is not zero, then jump to P2. ** -** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe +** This opcode leaves the cursor configured to move in forward order, +** from the beginning toward the end. In other words, the cursor is +** configured to use Next, not Prev. +** +** See also: Found, NotFound, SeekLt, SeekGe, SeekLe */ -/* Opcode: SeekLt P1 P2 P3 P4 * +/* Opcode: SeekLT P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), ** use the value in register P3 as a key. If cursor P1 refers @@ -3405,9 +3548,14 @@ case OP_Close: { ** is less than the key value. If there are no records less than ** the key and P2 is not zero, then jump to P2. ** -** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe +** This opcode leaves the cursor configured to move in reverse order, +** from the end toward the beginning. In other words, the cursor is +** configured to use Prev, not Next. +** +** See also: Found, NotFound, SeekGt, SeekGe, SeekLe */ -/* Opcode: SeekLe P1 P2 P3 P4 * +/* Opcode: SeekLE P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), ** use the value in register P3 as a key. If cursor P1 refers @@ -3418,12 +3566,16 @@ case OP_Close: { ** is less than or equal to the key value. If there are no records ** less than or equal to the key and P2 is not zero, then jump to P2. ** -** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt +** This opcode leaves the cursor configured to move in reverse order, +** from the end toward the beginning. In other words, the cursor is +** configured to use Prev, not Next. +** +** See also: Found, NotFound, SeekGt, SeekGe, SeekLt */ -case OP_SeekLt: /* jump, in3 */ -case OP_SeekLe: /* jump, in3 */ -case OP_SeekGe: /* jump, in3 */ -case OP_SeekGt: { /* jump, in3 */ +case OP_SeekLT: /* jump, in3 */ +case OP_SeekLE: /* jump, in3 */ +case OP_SeekGE: /* jump, in3 */ +case OP_SeekGT: { /* jump, in3 */ int res; int oc; VdbeCursor *pC; @@ -3436,143 +3588,135 @@ case OP_SeekGt: { /* jump, in3 */ pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->pseudoTableReg==0 ); - assert( OP_SeekLe == OP_SeekLt+1 ); - assert( OP_SeekGe == OP_SeekLt+2 ); - assert( OP_SeekGt == OP_SeekLt+3 ); + assert( OP_SeekLE == OP_SeekLT+1 ); + assert( OP_SeekGE == OP_SeekLT+2 ); + assert( OP_SeekGT == OP_SeekLT+3 ); assert( pC->isOrdered ); - if( ALWAYS(pC->pCursor!=0) ){ - oc = pOp->opcode; - pC->nullRow = 0; - if( pC->isTable ){ - /* The input value in P3 might be of any type: integer, real, string, - ** blob, or NULL. But it needs to be an integer before we can do - ** the seek, so covert it. */ - pIn3 = &aMem[pOp->p3]; - applyNumericAffinity(pIn3); - iKey = sqlite3VdbeIntValue(pIn3); - pC->rowidIsValid = 0; + assert( pC->pCursor!=0 ); + oc = pOp->opcode; + pC->nullRow = 0; +#ifdef SQLITE_DEBUG + pC->seekOp = pOp->opcode; +#endif + if( pC->isTable ){ + /* The input value in P3 might be of any type: integer, real, string, + ** blob, or NULL. But it needs to be an integer before we can do + ** the seek, so covert it. */ + pIn3 = &aMem[pOp->p3]; + ApplyNumericAffinity(pIn3); + iKey = sqlite3VdbeIntValue(pIn3); + pC->rowidIsValid = 0; - /* If the P3 value could not be converted into an integer without - ** loss of information, then special processing is required... */ - if( (pIn3->flags & MEM_Int)==0 ){ - if( (pIn3->flags & MEM_Real)==0 ){ - /* If the P3 value cannot be converted into any kind of a number, - ** then the seek is not possible, so jump to P2 */ - pc = pOp->p2 - 1; - break; - } - /* If we reach this point, then the P3 value must be a floating - ** point number. */ - assert( (pIn3->flags & MEM_Real)!=0 ); - - if( iKey==SMALLEST_INT64 && (pIn3->r<(double)iKey || pIn3->r>0) ){ - /* The P3 value is too large in magnitude to be expressed as an - ** integer. */ - res = 1; - if( pIn3->r<0 ){ - if( oc>=OP_SeekGe ){ assert( oc==OP_SeekGe || oc==OP_SeekGt ); - rc = sqlite3BtreeFirst(pC->pCursor, &res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - } - }else{ - if( oc<=OP_SeekLe ){ assert( oc==OP_SeekLt || oc==OP_SeekLe ); - rc = sqlite3BtreeLast(pC->pCursor, &res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - } - } - if( res ){ - pc = pOp->p2 - 1; - } - break; - }else if( oc==OP_SeekLt || oc==OP_SeekGe ){ - /* Use the ceiling() function to convert real->int */ - if( pIn3->r > (double)iKey ) iKey++; - }else{ - /* Use the floor() function to convert real->int */ - assert( oc==OP_SeekLe || oc==OP_SeekGt ); - if( pIn3->r < (double)iKey ) iKey--; - } - } - rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - if( res==0 ){ - pC->rowidIsValid = 1; - pC->lastRowid = iKey; + /* If the P3 value could not be converted into an integer without + ** loss of information, then special processing is required... */ + if( (pIn3->flags & MEM_Int)==0 ){ + if( (pIn3->flags & MEM_Real)==0 ){ + /* If the P3 value cannot be converted into any kind of a number, + ** then the seek is not possible, so jump to P2 */ + pc = pOp->p2 - 1; VdbeBranchTaken(1,2); + break; } - }else{ - nField = pOp->p4.i; - assert( pOp->p4type==P4_INT32 ); - assert( nField>0 ); - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)nField; - - /* The next line of code computes as follows, only faster: - ** if( oc==OP_SeekGt || oc==OP_SeekLe ){ - ** r.flags = UNPACKED_INCRKEY; - ** }else{ - ** r.flags = 0; - ** } + + /* If the approximation iKey is larger than the actual real search + ** term, substitute >= for > and < for <=. e.g. if the search term + ** is 4.9 and the integer approximation 5: + ** + ** (x > 4.9) -> (x >= 5) + ** (x <= 4.9) -> (x < 5) */ - r.flags = (u8)(UNPACKED_INCRKEY * (1 & (oc - OP_SeekLt))); - assert( oc!=OP_SeekGt || r.flags==UNPACKED_INCRKEY ); - assert( oc!=OP_SeekLe || r.flags==UNPACKED_INCRKEY ); - assert( oc!=OP_SeekGe || r.flags==0 ); - assert( oc!=OP_SeekLt || r.flags==0 ); + if( pIn3->r<(double)iKey ){ + assert( OP_SeekGE==(OP_SeekGT-1) ); + assert( OP_SeekLT==(OP_SeekLE-1) ); + assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) ); + if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--; + } + + /* If the approximation iKey is smaller than the actual real search + ** term, substitute <= for < and > for >=. */ + else if( pIn3->r>(double)iKey ){ + assert( OP_SeekLE==(OP_SeekLT+1) ); + assert( OP_SeekGT==(OP_SeekGE+1) ); + assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) ); + if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++; + } + } + rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + if( res==0 ){ + pC->rowidIsValid = 1; + pC->lastRowid = iKey; + } + }else{ + nField = pOp->p4.i; + assert( pOp->p4type==P4_INT32 ); + assert( nField>0 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)nField; + + /* The next line of code computes as follows, only faster: + ** if( oc==OP_SeekGT || oc==OP_SeekLE ){ + ** r.default_rc = -1; + ** }else{ + ** r.default_rc = +1; + ** } + */ + r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1); + assert( oc!=OP_SeekGT || r.default_rc==-1 ); + assert( oc!=OP_SeekLE || r.default_rc==-1 ); + assert( oc!=OP_SeekGE || r.default_rc==+1 ); + assert( oc!=OP_SeekLT || r.default_rc==+1 ); - r.aMem = &aMem[pOp->p3]; + r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG - { int i; for(i=0; ipCursor, &r, 0, 0, &res); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - pC->rowidIsValid = 0; + ExpandBlob(r.aMem); + rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; } - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; + pC->rowidIsValid = 0; + } + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; #ifdef SQLITE_TEST - sqlite3_search_count++; + sqlite3_search_count++; #endif - if( oc>=OP_SeekGe ){ assert( oc==OP_SeekGe || oc==OP_SeekGt ); - if( res<0 || (res==0 && oc==OP_SeekGt) ){ - rc = sqlite3BtreeNext(pC->pCursor, &res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - pC->rowidIsValid = 0; - }else{ - res = 0; - } + if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT ); + if( res<0 || (res==0 && oc==OP_SeekGT) ){ + res = 0; + rc = sqlite3BtreeNext(pC->pCursor, &res); + if( rc!=SQLITE_OK ) goto abort_due_to_error; + pC->rowidIsValid = 0; }else{ - assert( oc==OP_SeekLt || oc==OP_SeekLe ); - if( res>0 || (res==0 && oc==OP_SeekLt) ){ - rc = sqlite3BtreePrevious(pC->pCursor, &res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - pC->rowidIsValid = 0; - }else{ - /* res might be negative because the table is empty. Check to - ** see if this is the case. - */ - res = sqlite3BtreeEof(pC->pCursor); - } - } - assert( pOp->p2>0 ); - if( res ){ - pc = pOp->p2 - 1; + res = 0; } }else{ - /* This happens when attempting to open the sqlite3_master table - ** for read access returns SQLITE_EMPTY. In this case always - ** take the jump (since there are no records in the table). - */ + assert( oc==OP_SeekLT || oc==OP_SeekLE ); + if( res>0 || (res==0 && oc==OP_SeekLT) ){ + res = 0; + rc = sqlite3BtreePrevious(pC->pCursor, &res); + if( rc!=SQLITE_OK ) goto abort_due_to_error; + pC->rowidIsValid = 0; + }else{ + /* res might be negative because the table is empty. Check to + ** see if this is the case. + */ + res = sqlite3BtreeEof(pC->pCursor); + } + } + assert( pOp->p2>0 ); + VdbeBranchTaken(res!=0,2); + if( res ){ pc = pOp->p2 - 1; } break; } /* Opcode: Seek P1 P2 * * * +** Synopsis: intkey=r[P2] ** ** P1 is an open table cursor and P2 is a rowid integer. Arrange ** for P1 to move so that it points to the rowid given by P2. @@ -3587,19 +3731,19 @@ case OP_Seek: { /* in2 */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - if( ALWAYS(pC->pCursor!=0) ){ - assert( pC->isTable ); - pC->nullRow = 0; - pIn2 = &aMem[pOp->p2]; - pC->movetoTarget = sqlite3VdbeIntValue(pIn2); - pC->rowidIsValid = 0; - pC->deferredMoveto = 1; - } + assert( pC->pCursor!=0 ); + assert( pC->isTable ); + pC->nullRow = 0; + pIn2 = &aMem[pOp->p2]; + pC->movetoTarget = sqlite3VdbeIntValue(pIn2); + pC->rowidIsValid = 0; + pC->deferredMoveto = 1; break; } /* Opcode: Found P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] ** ** If P4==0 then register P3 holds a blob constructed by MakeRecord. If ** P4>0 then register P3 is the first of P4 registers that form an unpacked @@ -3608,8 +3752,15 @@ case OP_Seek: { /* in2 */ ** Cursor P1 is on an index btree. If the record identified by P3 and P4 ** is a prefix of any entry in P1 then a jump is made to P2 and ** P1 is left pointing at the matching entry. +** +** This operation leaves the cursor in a state where it can be +** advanced in the forward direction. The Next instruction will work, +** but not the Prev instruction. +** +** See also: NotFound, NoConflict, NotExists. SeekGe */ /* Opcode: NotFound P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] ** ** If P4==0 then register P3 holds a blob constructed by MakeRecord. If ** P4>0 then register P3 is the first of P4 registers that form an unpacked @@ -3621,169 +3772,134 @@ case OP_Seek: { /* in2 */ ** falls through to the next instruction and P1 is left pointing at the ** matching entry. ** -** See also: Found, NotExists, IsUnique +** This operation leaves the cursor in a state where it cannot be +** advanced in either direction. In other words, the Next and Prev +** opcodes do not work after this operation. +** +** See also: Found, NotExists, NoConflict +*/ +/* Opcode: NoConflict P1 P2 P3 P4 * +** Synopsis: key=r[P3@P4] +** +** If P4==0 then register P3 holds a blob constructed by MakeRecord. If +** P4>0 then register P3 is the first of P4 registers that form an unpacked +** record. +** +** Cursor P1 is on an index btree. If the record identified by P3 and P4 +** contains any NULL value, jump immediately to P2. If all terms of the +** record are not-NULL then a check is done to determine if any row in the +** P1 index btree has a matching key prefix. If there are no matches, jump +** immediately to P2. If there is a match, fall through and leave the P1 +** cursor pointing to the matching row. +** +** This opcode is similar to OP_NotFound with the exceptions that the +** branch is always taken if any part of the search key input is NULL. +** +** This operation leaves the cursor in a state where it cannot be +** advanced in either direction. In other words, the Next and Prev +** opcodes do not work after this operation. +** +** See also: NotFound, Found, NotExists */ +case OP_NoConflict: /* jump, in3 */ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ int alreadyExists; + int ii; VdbeCursor *pC; int res; char *pFree; UnpackedRecord *pIdxKey; UnpackedRecord r; - char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7]; + char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7]; #ifdef SQLITE_TEST - sqlite3_found_count++; + if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++; #endif - alreadyExists = 0; assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pOp->p4type==P4_INT32 ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); +#ifdef SQLITE_DEBUG + pC->seekOp = pOp->opcode; +#endif pIn3 = &aMem[pOp->p3]; - if( ALWAYS(pC->pCursor!=0) ){ - - assert( pC->isTable==0 ); - if( pOp->p4.i>0 ){ - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)pOp->p4.i; - r.aMem = pIn3; + assert( pC->pCursor!=0 ); + assert( pC->isTable==0 ); + pFree = 0; /* Not needed. Only used to suppress a compiler warning. */ + if( pOp->p4.i>0 ){ + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)pOp->p4.i; + r.aMem = pIn3; + for(ii=0; iip3+ii, &r.aMem[ii]); #endif - r.flags = UNPACKED_PREFIX_MATCH; - pIdxKey = &r; - }else{ - pIdxKey = sqlite3VdbeAllocUnpackedRecord( - pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree - ); - if( pIdxKey==0 ) goto no_mem; - assert( pIn3->flags & MEM_Blob ); - assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */ - sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); - pIdxKey->flags |= UNPACKED_PREFIX_MATCH; - } - rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res); - if( pOp->p4.i==0 ){ - sqlite3DbFree(db, pFree); } - if( rc!=SQLITE_OK ){ - break; + pIdxKey = &r; + }else{ + pIdxKey = sqlite3VdbeAllocUnpackedRecord( + pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree + ); + if( pIdxKey==0 ) goto no_mem; + assert( pIn3->flags & MEM_Blob ); + assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */ + sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); + } + pIdxKey->default_rc = 0; + if( pOp->opcode==OP_NoConflict ){ + /* For the OP_NoConflict opcode, take the jump if any of the + ** input fields are NULL, since any key with a NULL will not + ** conflict */ + for(ii=0; iip2 - 1; VdbeBranchTaken(1,2); + break; + } } - alreadyExists = (res==0); - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; } + rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res); + if( pOp->p4.i==0 ){ + sqlite3DbFree(db, pFree); + } + if( rc!=SQLITE_OK ){ + break; + } + pC->seekResult = res; + alreadyExists = (res==0); + pC->nullRow = 1-alreadyExists; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; if( pOp->opcode==OP_Found ){ + VdbeBranchTaken(alreadyExists!=0,2); if( alreadyExists ) pc = pOp->p2 - 1; }else{ + VdbeBranchTaken(alreadyExists==0,2); if( !alreadyExists ) pc = pOp->p2 - 1; } break; } -/* Opcode: IsUnique P1 P2 P3 P4 * -** -** Cursor P1 is open on an index b-tree - that is to say, a btree which -** no data and where the key are records generated by OP_MakeRecord with -** the list field being the integer ROWID of the entry that the index -** entry refers to. -** -** The P3 register contains an integer record number. Call this record -** number R. Register P4 is the first in a set of N contiguous registers -** that make up an unpacked index key that can be used with cursor P1. -** The value of N can be inferred from the cursor. N includes the rowid -** value appended to the end of the index record. This rowid value may -** or may not be the same as R. -** -** If any of the N registers beginning with register P4 contains a NULL -** value, jump immediately to P2. -** -** Otherwise, this instruction checks if cursor P1 contains an entry -** where the first (N-1) fields match but the rowid value at the end -** of the index entry is not R. If there is no such entry, control jumps -** to instruction P2. Otherwise, the rowid of the conflicting index -** entry is copied to register P3 and control falls through to the next -** instruction. -** -** See also: NotFound, NotExists, Found -*/ -case OP_IsUnique: { /* jump, in3 */ - u16 ii; - VdbeCursor *pCx; - BtCursor *pCrsr; - u16 nField; - Mem *aMx; - UnpackedRecord r; /* B-Tree index search key */ - i64 R; /* Rowid stored in register P3 */ - - pIn3 = &aMem[pOp->p3]; - aMx = &aMem[pOp->p4.i]; - /* Assert that the values of parameters P1 and P4 are in range. */ - assert( pOp->p4type==P4_INT32 ); - assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem ); - assert( pOp->p1>=0 && pOp->p1nCursor ); - - /* Find the index cursor. */ - pCx = p->apCsr[pOp->p1]; - assert( pCx->deferredMoveto==0 ); - pCx->seekResult = 0; - pCx->cacheStatus = CACHE_STALE; - pCrsr = pCx->pCursor; - - /* If any of the values are NULL, take the jump. */ - nField = pCx->pKeyInfo->nField; - for(ii=0; iip2 - 1; - pCrsr = 0; - break; - } - } - assert( (aMx[nField].flags & MEM_Null)==0 ); - - if( pCrsr!=0 ){ - /* Populate the index search key. */ - r.pKeyInfo = pCx->pKeyInfo; - r.nField = nField + 1; - r.flags = UNPACKED_PREFIX_SEARCH; - r.aMem = aMx; -#ifdef SQLITE_DEBUG - { int i; for(i=0; iu.i; - - /* Search the B-Tree index. If no conflicting record is found, jump - ** to P2. Otherwise, copy the rowid of the conflicting record to - ** register P3 and fall through to the next instruction. */ - rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &pCx->seekResult); - if( (r.flags & UNPACKED_PREFIX_SEARCH) || r.rowid==R ){ - pc = pOp->p2 - 1; - }else{ - pIn3->u.i = r.rowid; - } - } - break; -} - /* Opcode: NotExists P1 P2 P3 * * +** Synopsis: intkey=r[P3] ** -** Use the content of register P3 as an integer key. If a record -** with that key does not exist in table of P1, then jump to P2. -** If the record does exist, then fall through. The cursor is left -** pointing to the record if it exists. +** P1 is the index of a cursor open on an SQL table btree (with integer +** keys). P3 is an integer rowid. If P1 does not contain a record with +** rowid P3 then jump immediately to P2. If P1 does contain a record +** with rowid P3 then leave the cursor pointing at that record and fall +** through to the next instruction. ** -** The difference between this operation and NotFound is that this -** operation assumes the key is an integer and that P1 is a table whereas -** NotFound assumes key is a blob constructed from MakeRecord and -** P1 is an index. +** The OP_NotFound opcode performs the same operation on index btrees +** (with arbitrary multi-value keys). ** -** See also: Found, NotFound, IsUnique +** This opcode leaves the cursor in a state where it cannot be advanced +** in either direction. In other words, the Next and Prev opcodes will +** not work following this opcode. +** +** See also: Found, NotFound, NoConflict */ case OP_NotExists: { /* jump, in3 */ VdbeCursor *pC; @@ -3796,35 +3912,32 @@ case OP_NotExists: { /* jump, in3 */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); +#ifdef SQLITE_DEBUG + pC->seekOp = 0; +#endif assert( pC->isTable ); assert( pC->pseudoTableReg==0 ); pCrsr = pC->pCursor; - if( ALWAYS(pCrsr!=0) ){ - res = 0; - iKey = pIn3->u.i; - rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res); - pC->lastRowid = pIn3->u.i; - pC->rowidIsValid = res==0 ?1:0; - pC->nullRow = 0; - pC->cacheStatus = CACHE_STALE; - pC->deferredMoveto = 0; - if( res!=0 ){ - pc = pOp->p2 - 1; - assert( pC->rowidIsValid==0 ); - } - pC->seekResult = res; - }else{ - /* This happens when an attempt to open a read cursor on the - ** sqlite_master table returns SQLITE_EMPTY. - */ + assert( pCrsr!=0 ); + res = 0; + iKey = pIn3->u.i; + rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res); + pC->lastRowid = pIn3->u.i; + pC->rowidIsValid = res==0 ?1:0; + pC->nullRow = 0; + pC->cacheStatus = CACHE_STALE; + pC->deferredMoveto = 0; + VdbeBranchTaken(res!=0,2); + if( res!=0 ){ pc = pOp->p2 - 1; assert( pC->rowidIsValid==0 ); - pC->seekResult = 0; } + pC->seekResult = res; break; } /* Opcode: Sequence P1 P2 * * * +** Synopsis: r[P2]=cursor[P1].ctr++ ** ** Find the next available sequence number for cursor P1. ** Write the sequence number into register P2. @@ -3840,6 +3953,7 @@ case OP_Sequence: { /* out2-prerelease */ /* Opcode: NewRowid P1 P2 P3 * * +** Synopsis: r[P2]=rowid ** ** Get a new integer record number (a.k.a "rowid") used as the key to a table. ** The record number is not previously used as a key in the database @@ -3895,59 +4009,54 @@ case OP_NewRowid: { /* out2-prerelease */ #endif if( !pC->useRandomRowid ){ - v = sqlite3BtreeGetCachedRowid(pC->pCursor); - if( v==0 ){ - rc = sqlite3BtreeLast(pC->pCursor, &res); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - if( res ){ - v = 1; /* IMP: R-61914-48074 */ + rc = sqlite3BtreeLast(pC->pCursor, &res); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + if( res ){ + v = 1; /* IMP: R-61914-48074 */ + }else{ + assert( sqlite3BtreeCursorIsValid(pC->pCursor) ); + rc = sqlite3BtreeKeySize(pC->pCursor, &v); + assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ + if( v>=MAX_ROWID ){ + pC->useRandomRowid = 1; }else{ - assert( sqlite3BtreeCursorIsValid(pC->pCursor) ); - rc = sqlite3BtreeKeySize(pC->pCursor, &v); - assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ - if( v>=MAX_ROWID ){ - pC->useRandomRowid = 1; - }else{ - v++; /* IMP: R-29538-34987 */ - } + v++; /* IMP: R-29538-34987 */ } } + } #ifndef SQLITE_OMIT_AUTOINCREMENT - if( pOp->p3 ){ + if( pOp->p3 ){ + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3>0 ); + if( p->pFrame ){ + for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3>0 ); - if( p->pFrame ){ - for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3<=pFrame->nMem ); - pMem = &pFrame->aMem[pOp->p3]; - }else{ - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3<=p->nMem ); - pMem = &aMem[pOp->p3]; - memAboutToChange(p, pMem); - } - assert( memIsValid(pMem) ); - - REGISTER_TRACE(pOp->p3, pMem); - sqlite3VdbeMemIntegerify(pMem); - assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ - if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ - rc = SQLITE_FULL; /* IMP: R-12275-61338 */ - goto abort_due_to_error; - } - if( vu.i+1 ){ - v = pMem->u.i + 1; - } - pMem->u.i = v; + assert( pOp->p3<=pFrame->nMem ); + pMem = &pFrame->aMem[pOp->p3]; + }else{ + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3<=(p->nMem-p->nCursor) ); + pMem = &aMem[pOp->p3]; + memAboutToChange(p, pMem); } -#endif + assert( memIsValid(pMem) ); - sqlite3BtreeSetCachedRowid(pC->pCursor, vp3, pMem); + sqlite3VdbeMemIntegerify(pMem); + assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ + if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ + rc = SQLITE_FULL; /* IMP: R-12275-61338 */ + goto abort_due_to_error; + } + if( vu.i+1 ){ + v = pMem->u.i + 1; + } + pMem->u.i = v; } +#endif if( pC->useRandomRowid ){ /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the ** largest possible integer (9223372036854775807) then the database @@ -3989,6 +4098,7 @@ case OP_NewRowid: { /* out2-prerelease */ } /* Opcode: Insert P1 P2 P3 P4 P5 +** Synopsis: intkey=r[P3] data=r[P2] ** ** Write an entry into the table of cursor P1. A new entry is ** created if it doesn't already exist or the data for an existing @@ -4028,6 +4138,7 @@ case OP_NewRowid: { /* out2-prerelease */ ** for indices is OP_IdxInsert. */ /* Opcode: InsertInt P1 P2 P3 P4 P5 +** Synopsis: intkey=P3 data=r[P2] ** ** This works exactly like OP_Insert except that the key is the ** integer value P3, not the value of the integer stored in register P3. @@ -4079,10 +4190,9 @@ case OP_InsertInt: { }else{ nZero = 0; } - sqlite3BtreeSetCachedRowid(pC->pCursor, 0); rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pData->z, pData->n, nZero, - pOp->p5 & OPFLAG_APPEND, seekResult + (pOp->p5 & OPFLAG_APPEND)!=0, seekResult ); pC->rowidIsValid = 0; pC->deferredMoveto = 0; @@ -4107,7 +4217,7 @@ case OP_InsertInt: { ** The cursor will be left pointing at either the next or the previous ** record in the table. If it is left pointing at the next record, then ** the next Next instruction will be a no-op. Hence it is OK to delete -** a record from within an Next loop. +** a record from within a Next loop. ** ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is ** incremented (otherwise not). @@ -4124,20 +4234,11 @@ case OP_Delete: { i64 iKey; VdbeCursor *pC; - iKey = 0; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ - - /* If the update-hook will be invoked, set iKey to the rowid of the - ** row being deleted. - */ - if( db->xUpdateCallback && pOp->p4.z ){ - assert( pC->isTable ); - assert( pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */ - iKey = pC->lastRowid; - } + iKey = pC->lastRowid; /* Only used for the update hook */ /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or ** OP_Column on the same table without any intervening operations that @@ -4150,15 +4251,13 @@ case OP_Delete: { rc = sqlite3VdbeCursorMoveto(pC); if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; - sqlite3BtreeSetCachedRowid(pC->pCursor, 0); rc = sqlite3BtreeDelete(pC->pCursor); pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ - if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ - const char *zDb = db->aDb[pC->iDb].zName; - const char *zTbl = pOp->p4.z; - db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey); + if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && pC->isTable ){ + db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, + db->aDb[pC->iDb].zName, pOp->p4.z, iKey); assert( pC->iDb>=0 ); } if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; @@ -4177,21 +4276,33 @@ case OP_ResetCount: { break; } -/* Opcode: SorterCompare P1 P2 P3 +/* Opcode: SorterCompare P1 P2 P3 P4 +** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2 +** +** P1 is a sorter cursor. This instruction compares a prefix of the +** record blob in register P3 against a prefix of the entry that +** the sorter cursor currently points to. Only the first P4 fields +** of r[P3] and the sorter record are compared. ** -** P1 is a sorter cursor. This instruction compares the record blob in -** register P3 with the entry that the sorter cursor currently points to. -** If, excluding the rowid fields at the end, the two records are a match, -** fall through to the next instruction. Otherwise, jump to instruction P2. +** If either P3 or the sorter contains a NULL in one of their significant +** fields (not counting the P4 fields at the end which are ignored) then +** the comparison is assumed to be equal. +** +** Fall through to next instruction if the two records compare equal to +** each other. Jump to P2 if they are different. */ case OP_SorterCompare: { VdbeCursor *pC; int res; + int nKeyCol; pC = p->apCsr[pOp->p1]; assert( isSorter(pC) ); + assert( pOp->p4type==P4_INT32 ); pIn3 = &aMem[pOp->p3]; - rc = sqlite3VdbeSorterCompare(pC, pIn3, &res); + nKeyCol = pOp->p4.i; + rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res); + VdbeBranchTaken(res!=0,2); if( res ){ pc = pOp->p2-1; } @@ -4199,6 +4310,7 @@ case OP_SorterCompare: { }; /* Opcode: SorterData P1 P2 * * * +** Synopsis: r[P2]=data ** ** Write into register P2 the current sorter data for sorter cursor P1. */ @@ -4207,12 +4319,14 @@ case OP_SorterData: { pOut = &aMem[pOp->p2]; pC = p->apCsr[pOp->p1]; - assert( pC->isSorter ); + assert( isSorter(pC) ); rc = sqlite3VdbeSorterRowkey(pC, pOut); + assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) ); break; } /* Opcode: RowData P1 P2 * * * +** Synopsis: r[P2]=data ** ** Write into register P2 the complete row data for cursor P1. ** There is no interpretation of the data. @@ -4223,10 +4337,11 @@ case OP_SorterData: { ** of a real table, not a pseudo-table. */ /* Opcode: RowKey P1 P2 * * * +** Synopsis: r[P2]=key ** ** Write into register P2 the complete row key for cursor P1. ** There is no interpretation of the data. -** The key is copied onto the P3 register exactly as +** The key is copied onto the P2 register exactly as ** it is found in the database file. ** ** If the P1 cursor must be pointing to a valid row (not a NULL row) @@ -4245,9 +4360,9 @@ case OP_RowData: { /* Note that RowKey and RowData are really exactly the same instruction */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - assert( pC->isSorter==0 ); + assert( isSorter(pC)==0 ); assert( pC->isTable || pOp->opcode!=OP_RowData ); - assert( pC->isIndex || pOp->opcode==OP_RowData ); + assert( pC->isTable==0 || pOp->opcode==OP_RowData ); assert( pC!=0 ); assert( pC->nullRow==0 ); assert( pC->pseudoTableReg==0 ); @@ -4264,7 +4379,7 @@ case OP_RowData: { rc = sqlite3VdbeCursorMoveto(pC); if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; - if( pC->isIndex ){ + if( pC->isTable==0 ){ assert( !pC->isTable ); VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &n64); assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ @@ -4284,17 +4399,19 @@ case OP_RowData: { } pOut->n = n; MemSetTypeFlag(pOut, MEM_Blob); - if( pC->isIndex ){ + if( pC->isTable==0 ){ rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z); }else{ rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z); } pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ UPDATE_MAX_BLOBSIZE(pOut); + REGISTER_TRACE(pOp->p2, pOut); break; } /* Opcode: Rowid P1 P2 * * * +** Synopsis: r[P2]=rowid ** ** Store in register P2 an integer which is the key of the table entry that ** P1 is currently point to. @@ -4324,7 +4441,7 @@ case OP_Rowid: { /* out2-prerelease */ pModule = pVtab->pModule; assert( pModule->xRowid ); rc = pModule->xRowid(pC->pVtabCursor, &v); - importVtabErrMsg(p, pVtab); + sqlite3VtabImportErrmsg(p, pVtab); #endif /* SQLITE_OMIT_VIRTUALTABLE */ }else{ assert( pC->pCursor!=0 ); @@ -4355,7 +4472,7 @@ case OP_NullRow: { assert( pC!=0 ); pC->nullRow = 1; pC->rowidIsValid = 0; - assert( pC->pCursor || pC->pVtabCursor ); + pC->cacheStatus = CACHE_STALE; if( pC->pCursor ){ sqlite3BtreeClearCursor(pC->pCursor); } @@ -4364,11 +4481,15 @@ case OP_NullRow: { /* Opcode: Last P1 P2 * * * ** -** The next use of the Rowid or Column or Next instruction for P1 +** The next use of the Rowid or Column or Prev instruction for P1 ** will refer to the last entry in the database table or index. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. +** +** This opcode leaves the cursor configured to move in reverse order, +** from the end toward the beginning. In other words, the cursor is +** configured to use Prev, not Next. */ case OP_Last: { /* jump */ VdbeCursor *pC; @@ -4380,15 +4501,18 @@ case OP_Last: { /* jump */ assert( pC!=0 ); pCrsr = pC->pCursor; res = 0; - if( ALWAYS(pCrsr!=0) ){ - rc = sqlite3BtreeLast(pCrsr, &res); - } + assert( pCrsr!=0 ); + rc = sqlite3BtreeLast(pCrsr, &res); pC->nullRow = (u8)res; pC->deferredMoveto = 0; pC->rowidIsValid = 0; pC->cacheStatus = CACHE_STALE; - if( pOp->p2>0 && res ){ - pc = pOp->p2 - 1; +#ifdef SQLITE_DEBUG + pC->seekOp = OP_Last; +#endif + if( pOp->p2>0 ){ + VdbeBranchTaken(res!=0,2); + if( res ) pc = pOp->p2 - 1; } break; } @@ -4412,7 +4536,7 @@ case OP_Sort: { /* jump */ sqlite3_sort_count++; sqlite3_search_count--; #endif - p->aCounter[SQLITE_STMTSTATUS_SORT-1]++; + p->aCounter[SQLITE_STMTSTATUS_SORT]++; /* Fall through into OP_Rewind */ } /* Opcode: Rewind P1 P2 * * * @@ -4422,6 +4546,10 @@ case OP_Sort: { /* jump */ ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. +** +** This opcode leaves the cursor configured to move in forward order, +** from the beginning toward the end. In other words, the cursor is +** configured to use Next, not Prev. */ case OP_Rewind: { /* jump */ VdbeCursor *pC; @@ -4431,35 +4559,48 @@ case OP_Rewind: { /* jump */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->isSorter==(pOp->opcode==OP_SorterSort) ); + assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) ); res = 1; +#ifdef SQLITE_DEBUG + pC->seekOp = OP_Rewind; +#endif if( isSorter(pC) ){ rc = sqlite3VdbeSorterRewind(db, pC, &res); }else{ pCrsr = pC->pCursor; assert( pCrsr ); rc = sqlite3BtreeFirst(pCrsr, &res); - pC->atFirst = res==0 ?1:0; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; pC->rowidIsValid = 0; } pC->nullRow = (u8)res; assert( pOp->p2>0 && pOp->p2nOp ); + VdbeBranchTaken(res!=0,2); if( res ){ pc = pOp->p2 - 1; } break; } -/* Opcode: Next P1 P2 * P4 P5 +/* Opcode: Next P1 P2 P3 P4 P5 ** ** Advance cursor P1 so that it points to the next key/data pair in its ** table or index. If there are no more key/value pairs then fall through ** to the following instruction. But if the cursor advance was successful, ** jump immediately to P2. ** -** The P1 cursor must be for a real table, not a pseudo-table. +** The Next opcode is only valid following an SeekGT, SeekGE, or +** OP_Rewind opcode used to position the cursor. Next is not allowed +** to follow SeekLT, SeekLE, or OP_Last. +** +** The P1 cursor must be for a real table, not a pseudo-table. P1 must have +** been opened prior to this opcode or the program will segfault. +** +** The P3 value is a hint to the btree implementation. If P3==1, that +** means P1 is an SQL index and that this instruction could have been +** omitted if that index had been unique. P3 is usually 0. P3 is +** always either 0 or 1. ** ** P4 is always of type P4_ADVANCE. The function pointer points to ** sqlite3BtreeNext(). @@ -4467,16 +4608,32 @@ case OP_Rewind: { /* jump */ ** If P5 is positive and the jump is taken, then event counter ** number P5-1 in the prepared statement is incremented. ** -** See also: Prev +** See also: Prev, NextIfOpen */ -/* Opcode: Prev P1 P2 * * P5 +/* Opcode: NextIfOpen P1 P2 P3 P4 P5 +** +** This opcode works just like Next except that if cursor P1 is not +** open it behaves a no-op. +*/ +/* Opcode: Prev P1 P2 P3 P4 P5 ** ** Back up cursor P1 so that it points to the previous key/data pair in its ** table or index. If there is no previous key/value pairs then fall through ** to the following instruction. But if the cursor backup was successful, ** jump immediately to P2. ** -** The P1 cursor must be for a real table, not a pseudo-table. +** +** The Prev opcode is only valid following an SeekLT, SeekLE, or +** OP_Last opcode used to position the cursor. Prev is not allowed +** to follow SeekGT, SeekGE, or OP_Rewind. +** +** The P1 cursor must be for a real table, not a pseudo-table. If P1 is +** not open then the behavior is undefined. +** +** The P3 value is a hint to the btree implementation. If P3==1, that +** means P1 is an SQL index and that this instruction could have been +** omitted if that index had been unique. P3 is usually 0. P3 is +** always either 0 or 1. ** ** P4 is always of type P4_ADVANCE. The function pointer points to ** sqlite3BtreePrevious(). @@ -4484,45 +4641,69 @@ case OP_Rewind: { /* jump */ ** If P5 is positive and the jump is taken, then event counter ** number P5-1 in the prepared statement is incremented. */ -case OP_SorterNext: /* jump */ -case OP_Prev: /* jump */ -case OP_Next: { /* jump */ +/* Opcode: PrevIfOpen P1 P2 P3 P4 P5 +** +** This opcode works just like Prev except that if cursor P1 is not +** open it behaves a no-op. +*/ +case OP_SorterNext: { /* jump */ VdbeCursor *pC; int res; - CHECK_FOR_INTERRUPT; + pC = p->apCsr[pOp->p1]; + assert( isSorter(pC) ); + res = 0; + rc = sqlite3VdbeSorterNext(db, pC, &res); + goto next_tail; +case OP_PrevIfOpen: /* jump */ +case OP_NextIfOpen: /* jump */ + if( p->apCsr[pOp->p1]==0 ) break; + /* Fall through */ +case OP_Prev: /* jump */ +case OP_Next: /* jump */ assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p5<=ArraySize(p->aCounter) ); + assert( pOp->p5aCounter) ); pC = p->apCsr[pOp->p1]; - if( pC==0 ){ - break; /* See ticket #2273 */ - } - assert( pC->isSorter==(pOp->opcode==OP_SorterNext) ); - if( isSorter(pC) ){ - assert( pOp->opcode==OP_SorterNext ); - rc = sqlite3VdbeSorterNext(db, pC, &res); - }else{ - res = 1; - assert( pC->deferredMoveto==0 ); - assert( pC->pCursor ); - assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); - assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); - rc = pOp->p4.xAdvance(pC->pCursor, &res); - } - pC->nullRow = (u8)res; + res = pOp->p3; + assert( pC!=0 ); + assert( pC->deferredMoveto==0 ); + assert( pC->pCursor ); + assert( res==0 || (res==1 && pC->isTable==0) ); + testcase( res==1 ); + assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); + assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); + assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext ); + assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious); + + /* The Next opcode is only used after SeekGT, SeekGE, and Rewind. + ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */ + assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen + || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE + || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found); + assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen + || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE + || pC->seekOp==OP_Last ); + + rc = pOp->p4.xAdvance(pC->pCursor, &res); +next_tail: pC->cacheStatus = CACHE_STALE; + VdbeBranchTaken(res==0,2); if( res==0 ){ + pC->nullRow = 0; pc = pOp->p2 - 1; - if( pOp->p5 ) p->aCounter[pOp->p5-1]++; + p->aCounter[pOp->p5]++; #ifdef SQLITE_TEST sqlite3_search_count++; #endif + }else{ + pC->nullRow = 1; } pC->rowidIsValid = 0; - break; + goto check_for_interrupt; } /* Opcode: IdxInsert P1 P2 P3 * P5 +** Synopsis: key=r[P2] ** ** Register P2 holds an SQL index key made using the ** MakeRecord instructions. This opcode writes that key @@ -4531,6 +4712,14 @@ case OP_Next: { /* jump */ ** P3 is a flag that provides a hint to the b-tree layer that this ** insert is likely to be an append. ** +** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is +** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear, +** then the change counter is unchanged. +** +** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have +** just done a seek to the spot where the new entry is to be inserted. +** This flag avoids doing an extra seek. +** ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. */ @@ -4544,31 +4733,32 @@ case OP_IdxInsert: { /* in2 */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->isSorter==(pOp->opcode==OP_SorterInsert) ); + assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) ); pIn2 = &aMem[pOp->p2]; assert( pIn2->flags & MEM_Blob ); pCrsr = pC->pCursor; - if( ALWAYS(pCrsr!=0) ){ - assert( pC->isTable==0 ); - rc = ExpandBlob(pIn2); - if( rc==SQLITE_OK ){ - if( isSorter(pC) ){ - rc = sqlite3VdbeSorterWrite(db, pC, pIn2); - }else{ - nKey = pIn2->n; - zKey = pIn2->z; - rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3, - ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) - ); - assert( pC->deferredMoveto==0 ); - pC->cacheStatus = CACHE_STALE; - } + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; + assert( pCrsr!=0 ); + assert( pC->isTable==0 ); + rc = ExpandBlob(pIn2); + if( rc==SQLITE_OK ){ + if( isSorter(pC) ){ + rc = sqlite3VdbeSorterWrite(db, pC, pIn2); + }else{ + nKey = pIn2->n; + zKey = pIn2->z; + rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3, + ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) + ); + assert( pC->deferredMoveto==0 ); + pC->cacheStatus = CACHE_STALE; } } break; } /* Opcode: IdxDelete P1 P2 P3 * * +** Synopsis: key=r[P2@P3] ** ** The content of P3 registers starting at register P2 form ** an unpacked index key. This opcode removes that entry from the @@ -4581,30 +4771,31 @@ case OP_IdxDelete: { UnpackedRecord r; assert( pOp->p3>0 ); - assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 ); + assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem-p->nCursor)+1 ); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); pCrsr = pC->pCursor; - if( ALWAYS(pCrsr!=0) ){ - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)pOp->p3; - r.flags = 0; - r.aMem = &aMem[pOp->p2]; + assert( pCrsr!=0 ); + assert( pOp->p5==0 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)pOp->p3; + r.default_rc = 0; + r.aMem = &aMem[pOp->p2]; #ifdef SQLITE_DEBUG - { int i; for(i=0; ideferredMoveto==0 ); - pC->cacheStatus = CACHE_STALE; + rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); + if( rc==SQLITE_OK && res==0 ){ + rc = sqlite3BtreeDelete(pCrsr); } + assert( pC->deferredMoveto==0 ); + pC->cacheStatus = CACHE_STALE; break; } /* Opcode: IdxRowid P1 P2 * * * +** Synopsis: r[P2]=rowid ** ** Write into register P2 an integer which is the last entry in the record at ** the end of the index key pointed to by cursor P1. This integer should be @@ -4621,52 +4812,72 @@ case OP_IdxRowid: { /* out2-prerelease */ pC = p->apCsr[pOp->p1]; assert( pC!=0 ); pCrsr = pC->pCursor; + assert( pCrsr!=0 ); pOut->flags = MEM_Null; - if( ALWAYS(pCrsr!=0) ){ - rc = sqlite3VdbeCursorMoveto(pC); - if( NEVER(rc) ) goto abort_due_to_error; - assert( pC->deferredMoveto==0 ); - assert( pC->isTable==0 ); - if( !pC->nullRow ){ - rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - pOut->u.i = rowid; - pOut->flags = MEM_Int; + rc = sqlite3VdbeCursorMoveto(pC); + if( NEVER(rc) ) goto abort_due_to_error; + assert( pC->deferredMoveto==0 ); + assert( pC->isTable==0 ); + if( !pC->nullRow ){ + rowid = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; } + pOut->u.i = rowid; + pOut->flags = MEM_Int; } break; } /* Opcode: IdxGE P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] ** ** The P4 register values beginning with P3 form an unpacked index -** key that omits the ROWID. Compare this key value against the index -** that P1 is currently pointing to, ignoring the ROWID on the P1 index. +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** fields at the end. ** ** If the P1 index entry is greater than or equal to the key value ** then jump to P2. Otherwise fall through to the next instruction. +*/ +/* Opcode: IdxGT P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] +** +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** fields at the end. ** -** If P5 is non-zero then the key value is increased by an epsilon -** prior to the comparison. This make the opcode work like IdxGT except -** that if the key from register P3 is a prefix of the key in the cursor, -** the result is false whereas it would be true with IdxGT. +** If the P1 index entry is greater than the key value +** then jump to P2. Otherwise fall through to the next instruction. */ /* Opcode: IdxLT P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] ** ** The P4 register values beginning with P3 form an unpacked index -** key that omits the ROWID. Compare this key value against the index -** that P1 is currently pointing to, ignoring the ROWID on the P1 index. +** key that omits the PRIMARY KEY or ROWID. Compare this key value against +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or +** ROWID on the P1 index. ** ** If the P1 index entry is less than the key value then jump to P2. ** Otherwise fall through to the next instruction. +*/ +/* Opcode: IdxLE P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] ** -** If P5 is non-zero then the key value is increased by an epsilon prior -** to the comparison. This makes the opcode work like IdxLE. +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY or ROWID. Compare this key value against +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or +** ROWID on the P1 index. +** +** If the P1 index entry is less than or equal to the key value then jump +** to P2. Otherwise fall through to the next instruction. */ +case OP_IdxLE: /* jump */ +case OP_IdxGT: /* jump */ case OP_IdxLT: /* jump */ -case OP_IdxGE: { /* jump */ +case OP_IdxGE: { /* jump */ VdbeCursor *pC; int res; UnpackedRecord r; @@ -4675,31 +4886,36 @@ case OP_IdxGE: { /* jump */ pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->isOrdered ); - if( ALWAYS(pC->pCursor!=0) ){ - assert( pC->deferredMoveto==0 ); - assert( pOp->p5==0 || pOp->p5==1 ); - assert( pOp->p4type==P4_INT32 ); - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)pOp->p4.i; - if( pOp->p5 ){ - r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH; - }else{ - r.flags = UNPACKED_PREFIX_MATCH; - } - r.aMem = &aMem[pOp->p3]; + assert( pC->pCursor!=0); + assert( pC->deferredMoveto==0 ); + assert( pOp->p5==0 || pOp->p5==1 ); + assert( pOp->p4type==P4_INT32 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)pOp->p4.i; + if( pOp->opcodeopcode==OP_IdxLE || pOp->opcode==OP_IdxGT ); + r.default_rc = -1; + }else{ + assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT ); + r.default_rc = 0; + } + r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG - { int i; for(i=0; iopcode==OP_IdxLT ){ - res = -res; - }else{ - assert( pOp->opcode==OP_IdxGE ); - res++; - } - if( res>0 ){ - pc = pOp->p2 - 1 ; - } + res = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res); + assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) ); + if( (pOp->opcode&1)==(OP_IdxLT&1) ){ + assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT ); + res = -res; + }else{ + assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT ); + res++; + } + VdbeBranchTaken(res>0,2); + if( res>0 ){ + pc = pOp->p2 - 1 ; } break; } @@ -4730,15 +4946,18 @@ case OP_Destroy: { /* out2-prerelease */ Vdbe *pVdbe; int iDb; + assert( p->readOnly==0 ); #ifndef SQLITE_OMIT_VIRTUALTABLE iCnt = 0; for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){ - if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 ){ + if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->bIsReader + && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 + ){ iCnt++; } } #else - iCnt = db->activeVdbeCnt; + iCnt = db->nVdbeRead; #endif pOut->flags = MEM_Null; if( iCnt>1 ){ @@ -4747,7 +4966,8 @@ case OP_Destroy: { /* out2-prerelease */ }else{ iDb = pOp->p3; assert( iCnt==1 ); - assert( (p->btreeMask & (((yDbMask)1)<btreeMask, iDb) ); + iMoved = 0; /* Not needed. Only to silence a warning. */ rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved); pOut->flags = MEM_Int; pOut->u.i = iMoved; @@ -4785,7 +5005,8 @@ case OP_Clear: { int nChange; nChange = 0; - assert( (p->btreeMask & (((yDbMask)1)<p2))!=0 ); + assert( p->readOnly==0 ); + assert( DbMaskTest(p->btreeMask, pOp->p2) ); rc = sqlite3BtreeClearTable( db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) ); @@ -4800,7 +5021,31 @@ case OP_Clear: { break; } +/* Opcode: ResetSorter P1 * * * * +** +** Delete all contents from the ephemeral table or sorter +** that is open on cursor P1. +** +** This opcode only works for cursors used for sorting and +** opened with OP_OpenEphemeral or OP_SorterOpen. +*/ +case OP_ResetSorter: { + VdbeCursor *pC; + + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + if( pC->pSorter ){ + sqlite3VdbeSorterReset(db, pC->pSorter); + }else{ + assert( pC->isEphemeral ); + rc = sqlite3BtreeClearTableOfCursor(pC->pCursor); + } + break; +} + /* Opcode: CreateTable P1 P2 * * * +** Synopsis: r[P2]=root iDb=P1 ** ** Allocate a new table in the main database file if P1==0 or in the ** auxiliary database file if P1==1 or in an attached database if @@ -4814,6 +5059,7 @@ case OP_Clear: { ** See also: CreateIndex */ /* Opcode: CreateIndex P1 P2 * * * +** Synopsis: r[P2]=root iDb=P1 ** ** Allocate a new index in the main database file if P1==0 or in the ** auxiliary database file if P1==1 or in an attached database if @@ -4830,7 +5076,8 @@ case OP_CreateTable: { /* out2-prerelease */ pgno = 0; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( p->readOnly==0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ @@ -4917,7 +5164,8 @@ case OP_LoadAnalysis: { ** ** Remove the internal (in-memory) data structures that describe ** the table named P4 in database P1. This is called after a table -** is dropped in order to keep the internal representation of the +** is dropped from disk (using the Destroy opcode) in order to keep +** the internal representation of the ** schema consistent with what is on disk. */ case OP_DropTable: { @@ -4929,7 +5177,8 @@ case OP_DropTable: { ** ** Remove the internal (in-memory) data structures that describe ** the index named P4 in database P1. This is called after an index -** is dropped in order to keep the internal representation of the +** is dropped from disk (using the Destroy opcode) +** in order to keep the internal representation of the ** schema consistent with what is on disk. */ case OP_DropIndex: { @@ -4941,7 +5190,8 @@ case OP_DropIndex: { ** ** Remove the internal (in-memory) data structures that describe ** the trigger named P4 in database P1. This is called after a trigger -** is dropped in order to keep the internal representation of the +** is dropped from disk (using the Destroy opcode) in order to keep +** the internal representation of the ** schema consistent with what is on disk. */ case OP_DropTrigger: { @@ -4978,12 +5228,13 @@ case OP_IntegrityCk: { int nErr; /* Number of errors reported */ char *z; /* Text of the error report */ Mem *pnErr; /* Register keeping track of errors remaining */ - + + assert( p->bIsReader ); nRoot = pOp->p2; assert( nRoot>0 ); aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); if( aRoot==0 ) goto no_mem; - assert( pOp->p3>0 && pOp->p3<=p->nMem ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pnErr = &aMem[pOp->p3]; assert( (pnErr->flags & MEM_Int)!=0 ); assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); @@ -4993,7 +5244,7 @@ case OP_IntegrityCk: { } aRoot[j] = 0; assert( pOp->p5nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p5))!=0 ); + assert( DbMaskTest(p->btreeMask, pOp->p5) ); z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, (int)pnErr->u.i, &nErr); sqlite3DbFree(db, aRoot); @@ -5013,6 +5264,7 @@ case OP_IntegrityCk: { #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* Opcode: RowSetAdd P1 P2 * * * +** Synopsis: rowset(P1)=r[P2] ** ** Insert the integer value held by register P2 into a boolean index ** held in register P1. @@ -5032,6 +5284,7 @@ case OP_RowSetAdd: { /* in1, in2 */ } /* Opcode: RowSetRead P1 P2 P3 * * +** Synopsis: r[P3]=rowset(P1) ** ** Extract the smallest value from boolean index P1 and put that value into ** register P3. Or, if boolean index P1 is initially empty, leave P3 @@ -5039,7 +5292,7 @@ case OP_RowSetAdd: { /* in1, in2 */ */ case OP_RowSetRead: { /* jump, in1, out3 */ i64 val; - CHECK_FOR_INTERRUPT; + pIn1 = &aMem[pOp->p1]; if( (pIn1->flags & MEM_RowSet)==0 || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0 @@ -5047,14 +5300,17 @@ case OP_RowSetRead: { /* jump, in1, out3 */ /* The boolean index is empty */ sqlite3VdbeMemSetNull(pIn1); pc = pOp->p2 - 1; + VdbeBranchTaken(1,2); }else{ /* A value was pulled from the index */ sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); + VdbeBranchTaken(0,2); } - break; + goto check_for_interrupt; } /* Opcode: RowSetTest P1 P2 P3 P4 +** Synopsis: if r[P3] in rowset(P1) goto P2 ** ** Register P3 is assumed to hold a 64-bit integer value. If register P1 ** contains a RowSet object and that RowSet object contains @@ -5097,9 +5353,8 @@ case OP_RowSetTest: { /* jump, in1, in3 */ assert( pOp->p4type==P4_INT32 ); assert( iSet==-1 || iSet>=0 ); if( iSet ){ - exists = sqlite3RowSetTest(pIn1->u.pRowSet, - (u8)(iSet>=0 ? iSet & 0xf : 0xff), - pIn3->u.i); + exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i); + VdbeBranchTaken(exists!=0,2); if( exists ){ pc = pOp->p2 - 1; break; @@ -5114,7 +5369,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */ #ifndef SQLITE_OMIT_TRIGGER -/* Opcode: Program P1 P2 P3 P4 * +/* Opcode: Program P1 P2 P3 P4 P5 ** ** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). ** @@ -5126,6 +5381,8 @@ case OP_RowSetTest: { /* jump, in1, in3 */ ** memory required by the sub-vdbe at runtime. ** ** P4 is a pointer to the VM containing the trigger program. +** +** If P5 is non-zero, then recursive program invocation is enabled. */ case OP_Program: { /* jump */ int nMem; /* Number of memory registers for sub-program */ @@ -5203,7 +5460,7 @@ case OP_Program: { /* jump */ pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ - pMem->flags = MEM_Invalid; + pMem->flags = MEM_Undefined; pMem->db = db; } }else{ @@ -5258,6 +5515,7 @@ case OP_Param: { /* out2-prerelease */ #ifndef SQLITE_OMIT_FOREIGN_KEY /* Opcode: FkCounter P1 P2 * * * +** Synopsis: fkctr[P1]+=P2 ** ** Increment a "constraint counter" by P2 (P2 may be negative or positive). ** If P1 is non-zero, the database constraint counter is incremented @@ -5265,7 +5523,9 @@ case OP_Param: { /* out2-prerelease */ ** statement counter is incremented (immediate foreign key constraints). */ case OP_FkCounter: { - if( pOp->p1 ){ + if( db->flags & SQLITE_DeferFKs ){ + db->nDeferredImmCons += pOp->p2; + }else if( pOp->p1 ){ db->nDeferredCons += pOp->p2; }else{ p->nFkConstraint += pOp->p2; @@ -5274,6 +5534,7 @@ case OP_FkCounter: { } /* Opcode: FkIfZero P1 P2 * * * +** Synopsis: if fkctr[P1]==0 goto P2 ** ** This opcode tests if a foreign key constraint-counter is currently zero. ** If so, jump to instruction P2. Otherwise, fall through to the next @@ -5286,9 +5547,11 @@ case OP_FkCounter: { */ case OP_FkIfZero: { /* jump */ if( pOp->p1 ){ - if( db->nDeferredCons==0 ) pc = pOp->p2-1; + VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2); + if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; }else{ - if( p->nFkConstraint==0 ) pc = pOp->p2-1; + VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2); + if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; } break; } @@ -5296,6 +5559,7 @@ case OP_FkIfZero: { /* jump */ #ifndef SQLITE_OMIT_AUTOINCREMENT /* Opcode: MemMax P1 P2 * * * +** Synopsis: r[P1]=max(r[P1],r[P2]) ** ** P1 is a register in the root frame of this VM (the root frame is ** different from the current frame if this instruction is being executed @@ -5306,7 +5570,6 @@ case OP_FkIfZero: { /* jump */ ** an integer. */ case OP_MemMax: { /* in2 */ - Mem *pIn1; VdbeFrame *pFrame; if( p->pFrame ){ for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); @@ -5326,6 +5589,7 @@ case OP_MemMax: { /* in2 */ #endif /* SQLITE_OMIT_AUTOINCREMENT */ /* Opcode: IfPos P1 P2 * * * +** Synopsis: if r[P1]>0 goto P2 ** ** If the value of register P1 is 1 or greater, jump to P2. ** @@ -5335,22 +5599,24 @@ case OP_MemMax: { /* in2 */ case OP_IfPos: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken( pIn1->u.i>0, 2); if( pIn1->u.i>0 ){ pc = pOp->p2 - 1; } break; } -/* Opcode: IfNeg P1 P2 * * * +/* Opcode: IfNeg P1 P2 P3 * * +** Synopsis: r[P1]+=P3, if r[P1]<0 goto P2 ** -** If the value of register P1 is less than zero, jump to P2. -** -** It is illegal to use this instruction on a register that does -** not contain an integer. An assertion fault will result if you try. +** Register P1 must contain an integer. Add literal P3 to the value in +** register P1 then if the value of register P1 is less than zero, jump to P2. */ case OP_IfNeg: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); + pIn1->u.i += pOp->p3; + VdbeBranchTaken(pIn1->u.i<0, 2); if( pIn1->u.i<0 ){ pc = pOp->p2 - 1; } @@ -5358,17 +5624,16 @@ case OP_IfNeg: { /* jump, in1 */ } /* Opcode: IfZero P1 P2 P3 * * +** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2 ** ** The register P1 must contain an integer. Add literal P3 to the ** value in register P1. If the result is exactly 0, jump to P2. -** -** It is illegal to use this instruction on a register that does -** not contain an integer. An assertion fault will result if you try. */ case OP_IfZero: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); pIn1->u.i += pOp->p3; + VdbeBranchTaken(pIn1->u.i==0, 2); if( pIn1->u.i==0 ){ pc = pOp->p2 - 1; } @@ -5376,6 +5641,7 @@ case OP_IfZero: { /* jump, in1 */ } /* Opcode: AggStep * P2 P3 P4 P5 +** Synopsis: accum=r[P3] step(r[P2@P5]) ** ** Execute the step function for an aggregate. The ** function has P5 arguments. P4 is a pointer to the FuncDef @@ -5402,10 +5668,9 @@ case OP_AggStep: { assert( memIsValid(pRec) ); apVal[i] = pRec; memAboutToChange(p, pRec); - sqlite3VdbeMemStoreType(pRec); } ctx.pFunc = pOp->p4.pFunc; - assert( pOp->p3>0 && pOp->p3<=p->nMem ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); ctx.pMem = pMem = &aMem[pOp->p3]; pMem->n++; ctx.s.flags = MEM_Null; @@ -5416,7 +5681,7 @@ case OP_AggStep: { ctx.isError = 0; ctx.pColl = 0; ctx.skipFlag = 0; - if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ + if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>p->aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); @@ -5439,6 +5704,7 @@ case OP_AggStep: { } /* Opcode: AggFinal P1 P2 * P4 * +** Synopsis: accum=r[P1] N=P2 ** ** Execute the finalizer function for an aggregate. P1 is ** the memory location that is the accumulator for the aggregate. @@ -5452,7 +5718,7 @@ case OP_AggStep: { */ case OP_AggFinal: { Mem *pMem; - assert( pOp->p1>0 && pOp->p1<=p->nMem ); + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); pMem = &aMem[pOp->p1]; assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); @@ -5484,6 +5750,7 @@ case OP_Checkpoint: { int aRes[3]; /* Results */ Mem *pMem; /* Write results here */ + assert( p->readOnly==0 ); aRes[0] = 0; aRes[1] = aRes[2] = -1; assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE @@ -5503,7 +5770,7 @@ case OP_Checkpoint: { #endif #ifndef SQLITE_OMIT_PRAGMA -/* Opcode: JournalMode P1 P2 P3 * P5 +/* Opcode: JournalMode P1 P2 P3 * * ** ** Change the journal mode of database P1 to P3. P3 must be one of the ** PAGER_JOURNALMODE_XXX values. If changing between the various rollback @@ -5533,6 +5800,7 @@ case OP_JournalMode: { /* out2-prerelease */ || eNew==PAGER_JOURNALMODE_QUERY ); assert( pOp->p1>=0 && pOp->p1nDb ); + assert( p->readOnly==0 ); pBt = db->aDb[pOp->p1].pBt; pPager = sqlite3BtreePager(pBt); @@ -5556,7 +5824,7 @@ case OP_JournalMode: { /* out2-prerelease */ if( (eNew!=eOld) && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL) ){ - if( !db->autoCommit || db->activeVdbeCnt>1 ){ + if( !db->autoCommit || db->nVdbeRead>1 ){ rc = SQLITE_ERROR; sqlite3SetString(&p->zErrMsg, db, "cannot change %s wal mode from within a transaction", @@ -5615,6 +5883,7 @@ case OP_JournalMode: { /* out2-prerelease */ ** a transaction. */ case OP_Vacuum: { + assert( p->readOnly==0 ); rc = sqlite3RunVacuum(&p->zErrMsg, db); break; } @@ -5631,9 +5900,11 @@ case OP_IncrVacuum: { /* jump */ Btree *pBt; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( p->readOnly==0 ); pBt = db->aDb[pOp->p1].pBt; rc = sqlite3BtreeIncrVacuum(pBt); + VdbeBranchTaken(rc==SQLITE_DONE,2); if( rc==SQLITE_DONE ){ pc = pOp->p2 - 1; rc = SQLITE_OK; @@ -5644,12 +5915,13 @@ case OP_IncrVacuum: { /* jump */ /* Opcode: Expire P1 * * * * ** -** Cause precompiled statements to become expired. An expired statement -** fails with an error code of SQLITE_SCHEMA if it is ever executed -** (via sqlite3_step()). +** Cause precompiled statements to expire. When an expired statement +** is executed using sqlite3_step() it will either automatically +** reprepare itself (if it was originally created using sqlite3_prepare_v2()) +** or it will fail with SQLITE_SCHEMA. ** ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, -** then only the currently executing statement is affected. +** then only the currently executing statement is expired. */ case OP_Expire: { if( !pOp->p1 ){ @@ -5662,6 +5934,7 @@ case OP_Expire: { #ifndef SQLITE_OMIT_SHARED_CACHE /* Opcode: TableLock P1 P2 P3 P4 * +** Synopsis: iDb=P1 root=P2 write=P3 ** ** Obtain a lock on a particular table. This instruction is only used when ** the shared-cache feature is enabled. @@ -5680,7 +5953,7 @@ case OP_TableLock: { if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){ int p1 = pOp->p1; assert( p1>=0 && p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<btreeMask, p1) ); assert( isWriteLock==0 || isWriteLock==1 ); rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock); if( (rc&0xFF)==SQLITE_LOCKED ){ @@ -5706,7 +5979,7 @@ case OP_VBegin: { VTable *pVTab; pVTab = pOp->p4.pVtab; rc = sqlite3VtabBegin(db, pVTab); - if( pVTab ) importVtabErrMsg(p, pVTab->pVtab); + if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -5750,13 +6023,14 @@ case OP_VOpen: { sqlite3_vtab *pVtab; sqlite3_module *pModule; + assert( p->bIsReader ); pCur = 0; pVtabCursor = 0; pVtab = pOp->p4.pVtab->pVtab; pModule = (sqlite3_module *)pVtab->pModule; assert(pVtab && pModule); rc = pModule->xOpen(pVtab, &pVtabCursor); - importVtabErrMsg(p, pVtab); + sqlite3VtabImportErrmsg(p, pVtab); if( SQLITE_OK==rc ){ /* Initialize sqlite3_vtab_cursor base class */ pVtabCursor->pVtab = pVtab; @@ -5765,7 +6039,6 @@ case OP_VOpen: { pCur = allocateCursor(p, pOp->p1, 0, -1, 0); if( pCur ){ pCur->pVtabCursor = pVtabCursor; - pCur->pModule = pVtabCursor->pVtab->pModule; }else{ db->mallocFailed = 1; pModule->xClose(pVtabCursor); @@ -5777,6 +6050,7 @@ case OP_VOpen: { #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VFilter P1 P2 P3 P4 * +** Synopsis: iplan=r[P3] zplan='P4' ** ** P1 is a cursor opened using VOpen. P2 is an address to jump to if ** the filtered result set is empty. @@ -5828,17 +6102,16 @@ case OP_VFilter: { /* jump */ apArg = p->apArg; for(i = 0; iinVtabMethod = 1; rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); p->inVtabMethod = 0; - importVtabErrMsg(p, pVtab); + sqlite3VtabImportErrmsg(p, pVtab); if( rc==SQLITE_OK ){ res = pModule->xEof(pVtabCursor); } - + VdbeBranchTaken(res!=0,2); if( res ){ pc = pOp->p2 - 1; } @@ -5851,6 +6124,7 @@ case OP_VFilter: { /* jump */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VColumn P1 P2 P3 * * +** Synopsis: r[P3]=vcolumn(P2) ** ** Store the value of the P2-th column of ** the row of the virtual-table that the @@ -5864,7 +6138,7 @@ case OP_VColumn: { VdbeCursor *pCur = p->apCsr[pOp->p1]; assert( pCur->pVtabCursor ); - assert( pOp->p3>0 && pOp->p3<=p->nMem ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); if( pCur->nullRow ){ @@ -5885,7 +6159,7 @@ case OP_VColumn: { MemSetTypeFlag(&sContext.s, MEM_Null); rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2); - importVtabErrMsg(p, pVtab); + sqlite3VtabImportErrmsg(p, pVtab); if( sContext.isError ){ rc = sContext.isError; } @@ -5938,16 +6212,16 @@ case OP_VNext: { /* jump */ p->inVtabMethod = 1; rc = pModule->xNext(pCur->pVtabCursor); p->inVtabMethod = 0; - importVtabErrMsg(p, pVtab); + sqlite3VtabImportErrmsg(p, pVtab); if( rc==SQLITE_OK ){ res = pModule->xEof(pCur->pVtabCursor); } - + VdbeBranchTaken(!res,2); if( !res ){ /* If there is data, jump to P2 */ pc = pOp->p2 - 1; } - break; + goto check_for_interrupt; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -5966,6 +6240,7 @@ case OP_VRename: { pName = &aMem[pOp->p1]; assert( pVtab->pModule->xRename ); assert( memIsValid(pName) ); + assert( p->readOnly==0 ); REGISTER_TRACE(pOp->p1, pName); assert( pName->flags & MEM_Str ); testcase( pName->enc==SQLITE_UTF8 ); @@ -5974,7 +6249,7 @@ case OP_VRename: { rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8); if( rc==SQLITE_OK ){ rc = pVtab->pModule->xRename(pVtab, pName->z); - importVtabErrMsg(p, pVtab); + sqlite3VtabImportErrmsg(p, pVtab); p->expired = 0; } break; @@ -5982,7 +6257,8 @@ case OP_VRename: { #endif #ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VUpdate P1 P2 P3 P4 * +/* Opcode: VUpdate P1 P2 P3 P4 P5 +** Synopsis: data=r[P3@P2] ** ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. ** This opcode invokes the corresponding xUpdate method. P2 values @@ -6004,6 +6280,9 @@ case OP_VRename: { ** P1 is a boolean flag. If it is set to true and the xUpdate call ** is successful, then the value returned by sqlite3_last_insert_rowid() ** is set to the value of the rowid for the row just inserted. +** +** P5 is the error actions (OE_Replace, OE_Fail, OE_Ignore, etc) to +** apply in the case of a constraint failure on an insert or update. */ case OP_VUpdate: { sqlite3_vtab *pVtab; @@ -6017,6 +6296,7 @@ case OP_VUpdate: { assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace ); + assert( p->readOnly==0 ); pVtab = pOp->p4.pVtab->pVtab; pModule = (sqlite3_module *)pVtab->pModule; nArg = pOp->p2; @@ -6028,14 +6308,13 @@ case OP_VUpdate: { for(i=0; ivtabOnConflict = pOp->p5; rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid); db->vtabOnConflict = vtabOnConflict; - importVtabErrMsg(p, pVtab); + sqlite3VtabImportErrmsg(p, pVtab); if( rc==SQLITE_OK && pOp->p1 ){ assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) ); db->lastRowid = lastRowid = rowid; @@ -6091,16 +6370,26 @@ case OP_MaxPgcnt: { /* out2-prerelease */ #endif -#ifndef SQLITE_OMIT_TRACE -/* Opcode: Trace * * * P4 * +/* Opcode: Init * P2 * P4 * +** Synopsis: Start at P2 +** +** Programs contain a single instance of this opcode as the very first +** opcode. ** ** If tracing is enabled (by the sqlite3_trace()) interface, then ** the UTF-8 string contained in P4 is emitted on the trace callback. +** Or if P4 is blank, use the string returned by sqlite3_sql(). +** +** If P2 is not zero, jump to instruction P2. */ -case OP_Trace: { +case OP_Init: { /* jump */ char *zTrace; char *z; + if( pOp->p2 ){ + pc = pOp->p2 - 1; + } +#ifndef SQLITE_OMIT_TRACE if( db->xTrace && !p->doingRerun && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 @@ -6109,6 +6398,16 @@ case OP_Trace: { db->xTrace(db->pTraceArg, z); sqlite3DbFree(db, z); } +#ifdef SQLITE_USE_FCNTL_TRACE + zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); + if( zTrace ){ + int i; + for(i=0; inDb; i++){ + if( DbMaskTest(p->btreeMask, i)==0 ) continue; + sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace); + } + } +#endif /* SQLITE_USE_FCNTL_TRACE */ #ifdef SQLITE_DEBUG if( (db->flags & SQLITE_SqlTrace)!=0 && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 @@ -6116,9 +6415,9 @@ case OP_Trace: { sqlite3DebugPrintf("SQL-trace: %s\n", zTrace); } #endif /* SQLITE_DEBUG */ +#endif /* SQLITE_OMIT_TRACE */ break; } -#endif /* Opcode: Noop * * * * * @@ -6147,13 +6446,9 @@ default: { /* This is really OP_Noop and OP_Explain */ #ifdef VDBE_PROFILE { - u64 elapsed = sqlite3Hwtime() - start; - pOp->cycles += elapsed; + u64 endTime = sqlite3Hwtime(); + if( endTime>start ) pOp->cycles += endTime - start; pOp->cnt++; -#if 0 - fprintf(stdout, "%10llu ", elapsed); - sqlite3VdbePrintOp(stdout, origPc, &aOp[origPc]); -#endif } #endif @@ -6166,13 +6461,13 @@ default: { /* This is really OP_Noop and OP_Explain */ assert( pc>=-1 && pcnOp ); #ifdef SQLITE_DEBUG - if( p->trace ){ - if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc); + if( db->flags & SQLITE_VdbeTrace ){ + if( rc!=0 ) printf("rc=%d\n",rc); if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){ - registerTrace(p->trace, pOp->p2, &aMem[pOp->p2]); + registerTrace(pOp->p2, &aMem[pOp->p2]); } if( pOp->opflags & OPFLG_OUT3 ){ - registerTrace(p->trace, pOp->p3, &aMem[pOp->p3]); + registerTrace(pOp->p3, &aMem[pOp->p3]); } } #endif /* SQLITE_DEBUG */ @@ -6200,6 +6495,8 @@ vdbe_error_halt: ** top. */ vdbe_return: db->lastRowid = lastRowid; + testcase( nVmStep>0 ); + p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; sqlite3VdbeLeave(p); return rc; -- cgit v1.2.3