Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Unified Diff: third_party/sqlite/src/src/vdbe.c

Issue 6990047: Import SQLite 3.7.6.3. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/sqlite/src/src/vdbe.h ('k') | third_party/sqlite/src/src/vdbeInt.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/sqlite/src/src/vdbe.c
diff --git a/third_party/sqlite/src/src/vdbe.c b/third_party/sqlite/src/src/vdbe.c
index e25280a9e2cb6327683d0730ceb5001229565e86..5376b08a00ef9d9f2d27e0d54627fcbe64af20ff 100644
--- a/third_party/sqlite/src/src/vdbe.c
+++ b/third_party/sqlite/src/src/vdbe.c
@@ -42,13 +42,22 @@
** of the code in this file is, therefore, important. See other comments
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
-**
-** $Id: vdbe.c,v 1.874 2009/07/24 17:58:53 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
/*
+** Invoke this macro on memory cells just prior to changing the
+** value of the cell. This macro verifies that shallow copies are
+** not misused.
+*/
+#ifdef SQLITE_DEBUG
+# define memAboutToChange(P,M) sqlite3VdbeMemPrepareToChange(P,M)
+#else
+# define memAboutToChange(P,M)
+#endif
+
+/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test
** procedures use this information to make sure that indices are
@@ -99,6 +108,17 @@ static void updateMaxBlobsize(Mem *p){
#endif
/*
+** The next global variable is incremented each type 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
+** library.
+*/
+#ifdef SQLITE_TEST
+int sqlite3_found_count = 0;
+#endif
+
+/*
** Test a register to see if it exceeds the current maximum blob size.
** If it does, record the new maximum blob size.
*/
@@ -140,12 +160,10 @@ static void updateMaxBlobsize(Mem *p){
/*
** 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.
-** The second argument, 'db_enc' is the text encoding used by the vdbe for
-** register variables. This routine sets the pMem->enc and pMem->type
-** variables used by the sqlite3_value_*() routines.
+** This routine sets the pMem->type variable used by the sqlite3_value_*()
+** routines.
*/
-#define storeTypeInfo(A,B) _storeTypeInfo(A)
-static void _storeTypeInfo(Mem *pMem){
+void sqlite3VdbeMemStoreType(Mem *pMem){
int flags = pMem->flags;
if( flags & MEM_Null ){
pMem->type = SQLITE_NULL;
@@ -164,23 +182,6 @@ static void _storeTypeInfo(Mem *pMem){
}
/*
-** Properties of opcodes. The OPFLG_INITIALIZER macro is
-** created by mkopcodeh.awk during compilation. Data is obtained
-** from the comments following the "case OP_xxxx:" statements in
-** this file.
-*/
-static const unsigned char opcodeProperty[] = OPFLG_INITIALIZER;
-
-/*
-** Return true if an opcode has any of the OPFLG_xxx properties
-** specified by mask.
-*/
-int sqlite3VdbeOpcodeHasProperty(int opcode, int mask){
- assert( opcode>0 && opcode<(int)sizeof(opcodeProperty) );
- return (opcodeProperty[opcode]&mask)!=0;
-}
-
-/*
** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL
** if we run out of memory.
*/
@@ -214,7 +215,7 @@ static VdbeCursor *allocateCursor(
int nByte;
VdbeCursor *pCx = 0;
nByte =
- sizeof(VdbeCursor) +
+ ROUND8(sizeof(VdbeCursor)) +
(isBtreeCursor?sqlite3BtreeCursorSize():0) +
2*nField*sizeof(u32);
@@ -225,15 +226,16 @@ static VdbeCursor *allocateCursor(
}
if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
- memset(pMem->z, 0, nByte);
+ memset(pCx, 0, sizeof(VdbeCursor));
pCx->iDb = iDb;
pCx->nField = nField;
if( nField ){
- pCx->aType = (u32 *)&pMem->z[sizeof(VdbeCursor)];
+ pCx->aType = (u32 *)&pMem->z[ROUND8(sizeof(VdbeCursor))];
}
if( isBtreeCursor ){
pCx->pCursor = (BtCursor*)
- &pMem->z[sizeof(VdbeCursor)+2*nField*sizeof(u32)];
+ &pMem->z[ROUND8(sizeof(VdbeCursor))+2*nField*sizeof(u32)];
+ sqlite3BtreeCursorZero(pCx->pCursor);
}
}
return pCx;
@@ -247,18 +249,17 @@ static VdbeCursor *allocateCursor(
*/
static void applyNumericAffinity(Mem *pRec){
if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
- int realnum;
- sqlite3VdbeMemNulTerminate(pRec);
- if( (pRec->flags&MEM_Str)
- && sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){
- i64 value;
- sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8);
- if( !realnum && sqlite3Atoi64(pRec->z, &value) ){
- pRec->u.i = value;
- MemSetTypeFlag(pRec, MEM_Int);
- }else{
- sqlite3VdbeMemRealify(pRec);
- }
+ 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;
}
}
}
@@ -310,13 +311,13 @@ static void applyAffinity(
** into a numeric representation. Use either INTEGER or REAL whichever
** is appropriate. But only do the conversion if it is possible without
** loss of information and return the revised type of the argument.
-**
-** This is an EXPERIMENTAL api and is subject to change or removal.
*/
int sqlite3_value_numeric_type(sqlite3_value *pVal){
Mem *pMem = (Mem*)pVal;
- applyNumericAffinity(pMem);
- storeTypeInfo(pMem, 0);
+ if( pMem->type==SQLITE_TEXT ){
+ applyNumericAffinity(pMem);
+ sqlite3VdbeMemStoreType(pMem);
+ }
return pMem->type;
}
@@ -476,22 +477,6 @@ static void registerTrace(FILE *out, int iReg, Mem *p){
#define CHECK_FOR_INTERRUPT \
if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
-#ifdef SQLITE_DEBUG
-static int fileExists(sqlite3 *db, const char *zFile){
- int res = 0;
- int rc = SQLITE_OK;
-#ifdef SQLITE_TEST
- /* If we are currently testing IO errors, then do not call OsAccess() to
- ** test for the presence of zFile. This is because any IO error that
- ** occurs here will not be reported, causing the test to fail.
- */
- extern int sqlite3_io_error_pending;
- if( sqlite3_io_error_pending<=0 )
-#endif
- rc = sqlite3OsAccess(db->pVfs, zFile, SQLITE_ACCESS_EXISTS, &res);
- return (res && rc==SQLITE_OK);
-}
-#endif
#ifndef NDEBUG
/*
@@ -514,6 +499,20 @@ 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
@@ -547,30 +546,32 @@ static int checkSavepointCount(sqlite3 *db){
int sqlite3VdbeExec(
Vdbe *p /* The VDBE */
){
- int pc; /* The program counter */
+ int pc=0; /* The program counter */
+ Op *aOp = p->aOp; /* Copy of p->aOp */
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
sqlite3 *db = p->db; /* The database */
+ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
u8 encoding = ENC(db); /* The database encoding */
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ int checkProgress; /* True if progress callbacks are enabled */
+ int nProgressOps = 0; /* Opcodes executed since progress callback. */
+#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 */
- u8 opProperty;
int iCompare = 0; /* Result of last OP_Compare operation */
int *aPermute = 0; /* Permutation of columns for OP_Compare */
#ifdef VDBE_PROFILE
u64 start; /* CPU clock count at start of opcode */
int origPc; /* Program counter at start of opcode */
#endif
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- int nProgressOps = 0; /* Opcodes executed since progress callback. */
-#endif
/*** INSERT STACK UNION HERE ***/
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
- assert( db->magic==SQLITE_MAGIC_BUSY );
- sqlite3VdbeMutexArrayEnter(p);
+ sqlite3VdbeEnter(p);
if( p->rc==SQLITE_NOMEM ){
/* This happens if a malloc() inside a call to sqlite3_column_text() or
** sqlite3_column_text16() failed. */
@@ -583,21 +584,19 @@ int sqlite3VdbeExec(
db->busyHandler.nBusy = 0;
CHECK_FOR_INTERRUPT;
sqlite3VdbeIOTraceSql(p);
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ checkProgress = db->xProgress!=0;
+#endif
#ifdef SQLITE_DEBUG
sqlite3BeginBenignMalloc();
- if( p->pc==0
- && ((p->db->flags & SQLITE_VdbeListing) || fileExists(db, "vdbe_explain"))
- ){
+ if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){
int i;
printf("VDBE Program Listing:\n");
sqlite3VdbePrintSql(p);
for(i=0; i<p->nOp; i++){
- sqlite3VdbePrintOp(stdout, i, &p->aOp[i]);
+ sqlite3VdbePrintOp(stdout, i, &aOp[i]);
}
}
- if( fileExists(db, "vdbe_trace") ){
- p->trace = stdout;
- }
sqlite3EndBenignMalloc();
#endif
for(pc=p->pc; rc==SQLITE_OK; pc++){
@@ -607,7 +606,7 @@ int sqlite3VdbeExec(
origPc = pc;
start = sqlite3Hwtime();
#endif
- pOp = &p->aOp[pc];
+ pOp = &aOp[pc];
/* Only allow tracing if SQLITE_DEBUG is defined.
*/
@@ -619,13 +618,6 @@ int sqlite3VdbeExec(
}
sqlite3VdbePrintOp(p->trace, pc, pOp);
}
- if( p->trace==0 && pc==0 ){
- sqlite3BeginBenignMalloc();
- if( fileExists(db, "vdbe_sqltrace") ){
- sqlite3VdbePrintSql(p);
- }
- sqlite3EndBenignMalloc();
- }
#endif
@@ -648,12 +640,10 @@ int sqlite3VdbeExec(
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
- if( db->xProgress ){
+ if( checkProgress ){
if( db->nProgressOps==nProgressOps ){
int prc;
- if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
- prc =db->xProgress(db->pProgressArg);
- if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ prc = db->xProgress(db->pProgressArg);
if( prc!=0 ){
rc = SQLITE_INTERRUPT;
goto vdbe_error_halt;
@@ -664,66 +654,53 @@ int sqlite3VdbeExec(
}
#endif
- /* Do common setup processing for any opcode that is marked
- ** with the "out2-prerelease" tag. Such opcodes have a single
- ** output which is specified by the P2 parameter. The P2 register
- ** is initialized to a NULL.
+ /* On any opcode with the "out2-prerelase" 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
+ ** value or convert mem[p2] to a different type.
*/
- opProperty = opcodeProperty[pOp->opcode];
- if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){
+ assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
+ if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
assert( pOp->p2>0 );
assert( pOp->p2<=p->nMem );
- pOut = &p->aMem[pOp->p2];
+ pOut = &aMem[pOp->p2];
+ memAboutToChange(p, pOut);
sqlite3VdbeMemReleaseExternal(pOut);
- pOut->flags = MEM_Null;
- pOut->n = 0;
- }else
-
- /* Do common setup for opcodes marked with one of the following
- ** combinations of properties.
- **
- ** in1
- ** in1 in2
- ** in1 in2 out3
- ** in1 in3
- **
- ** Variables pIn1, pIn2, and pIn3 are made to point to appropriate
- ** registers for inputs. Variable pOut points to the output register.
- */
- if( (opProperty & OPFLG_IN1)!=0 ){
+ pOut->flags = MEM_Int;
+ }
+
+ /* Sanity checking on other operands */
+#ifdef SQLITE_DEBUG
+ if( (pOp->opflags & OPFLG_IN1)!=0 ){
assert( pOp->p1>0 );
assert( pOp->p1<=p->nMem );
- pIn1 = &p->aMem[pOp->p1];
- REGISTER_TRACE(pOp->p1, pIn1);
- if( (opProperty & OPFLG_IN2)!=0 ){
- assert( pOp->p2>0 );
- assert( pOp->p2<=p->nMem );
- pIn2 = &p->aMem[pOp->p2];
- REGISTER_TRACE(pOp->p2, pIn2);
- /* As currently implemented, in2 implies out3. There is no reason
- ** why this has to be, it just worked out that way. */
- assert( (opProperty & OPFLG_OUT3)!=0 );
- assert( pOp->p3>0 );
- assert( pOp->p3<=p->nMem );
- pOut = &p->aMem[pOp->p3];
- }else if( (opProperty & OPFLG_IN3)!=0 ){
- assert( pOp->p3>0 );
- assert( pOp->p3<=p->nMem );
- pIn3 = &p->aMem[pOp->p3];
- REGISTER_TRACE(pOp->p3, pIn3);
- }
- }else if( (opProperty & OPFLG_IN2)!=0 ){
+ assert( memIsValid(&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 );
- pIn2 = &p->aMem[pOp->p2];
- REGISTER_TRACE(pOp->p2, pIn2);
- }else if( (opProperty & OPFLG_IN3)!=0 ){
+ assert( memIsValid(&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 );
- pIn3 = &p->aMem[pOp->p3];
- REGISTER_TRACE(pOp->p3, pIn3);
+ assert( memIsValid(&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 );
+ memAboutToChange(p, &aMem[pOp->p2]);
+ }
+ if( (pOp->opflags & OPFLG_OUT3)!=0 ){
+ assert( pOp->p3>0 );
+ assert( pOp->p3<=p->nMem );
+ memAboutToChange(p, &aMem[pOp->p3]);
+ }
+#endif
+
switch( pOp->opcode ){
/*****************************************************************************
@@ -779,11 +756,10 @@ case OP_Goto: { /* jump */
** Write the current address onto register P1
** and then jump to address P2.
*/
-case OP_Gosub: { /* jump */
- assert( pOp->p1>0 );
- assert( pOp->p1<=p->nMem );
- pIn1 = &p->aMem[pOp->p1];
+case OP_Gosub: { /* jump, in1 */
+ pIn1 = &aMem[pOp->p1];
assert( (pIn1->flags & MEM_Dyn)==0 );
+ memAboutToChange(p, pIn1);
pIn1->flags = MEM_Int;
pIn1->u.i = pc;
REGISTER_TRACE(pOp->p1, pIn1);
@@ -796,6 +772,7 @@ case OP_Gosub: { /* jump */
** Jump to the next instruction after the address in register P1.
*/
case OP_Return: { /* in1 */
+ pIn1 = &aMem[pOp->p1];
assert( pIn1->flags & MEM_Int );
pc = (int)pIn1->u.i;
break;
@@ -807,6 +784,7 @@ case OP_Return: { /* in1 */
*/
case OP_Yield: { /* in1 */
int pcDest;
+ pIn1 = &aMem[pOp->p1];
assert( (pIn1->flags & MEM_Dyn)==0 );
pIn1->flags = MEM_Int;
pcDest = (int)pIn1->u.i;
@@ -823,6 +801,7 @@ case OP_Yield: { /* in1 */
** value in register P3 is not NULL, then this routine is a no-op.
*/
case OP_HaltIfNull: { /* in3 */
+ pIn3 = &aMem[pOp->p3];
if( (pIn3->flags & MEM_Null)==0 ) break;
/* Fall through into OP_Halt */
}
@@ -862,6 +841,8 @@ case OP_Halt: {
** as the p2 of the calling OP_Program. */
pc = p->aOp[pc].p2-1;
}
+ aOp = p->aOp;
+ aMem = p->aMem;
break;
}
@@ -869,13 +850,21 @@ case OP_Halt: {
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);
}
rc = sqlite3VdbeHalt(p);
- assert( rc==SQLITE_BUSY || rc==SQLITE_OK );
+ assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
if( rc==SQLITE_BUSY ){
p->rc = rc = SQLITE_BUSY;
}else{
+ assert( rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT );
+ assert( rc==SQLITE_OK || db->nDeferredCons>0 );
rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
}
goto vdbe_return;
@@ -886,7 +875,6 @@ case OP_Halt: {
** The 32-bit integer value P1 is written into register P2.
*/
case OP_Integer: { /* out2-prerelease */
- pOut->flags = MEM_Int;
pOut->u.i = pOp->p1;
break;
}
@@ -898,11 +886,11 @@ case OP_Integer: { /* out2-prerelease */
*/
case OP_Int64: { /* out2-prerelease */
assert( pOp->p4.pI64!=0 );
- pOut->flags = MEM_Int;
pOut->u.i = *pOp->p4.pI64;
break;
}
+#ifndef SQLITE_OMIT_FLOATING_POINT
/* Opcode: Real * P2 * P4 *
**
** P4 is a pointer to a 64-bit floating point value.
@@ -914,6 +902,7 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
pOut->r = *pOp->p4.pReal;
break;
}
+#endif
/* Opcode: String8 * P2 * P4 *
**
@@ -968,6 +957,7 @@ case OP_String: { /* out2-prerelease */
** Write a NULL into register P2.
*/
case OP_Null: { /* out2-prerelease */
+ pOut->flags = MEM_Null;
break;
}
@@ -975,11 +965,7 @@ case OP_Null: { /* out2-prerelease */
/* Opcode: Blob P1 P2 * P4
**
** P4 points to a blob of data P1 bytes long. Store this
-** blob in register P2. This instruction is not coded directly
-** by the compiler. Instead, the compiler layer specifies
-** an OP_HexBlob opcode, with the hex string representation of
-** the blob as P4. This opcode is transformed to an OP_Blob
-** the first time it is executed.
+** blob in register P2.
*/
case OP_Blob: { /* out2-prerelease */
assert( pOp->p1 <= SQLITE_MAX_LENGTH );
@@ -989,38 +975,23 @@ case OP_Blob: { /* out2-prerelease */
break;
}
-/* Opcode: Variable P1 P2 P3 P4 *
+/* Opcode: Variable P1 P2 * P4 *
**
-** Transfer the values of bound parameters P1..P1+P3-1 into registers
-** P2..P2+P3-1.
+** Transfer the values of bound parameter P1 into register P2
**
** If the parameter is named, then its name appears in P4 and P3==1.
** The P4 value is used by sqlite3_bind_parameter_name().
*/
-case OP_Variable: {
- int p1; /* Variable to copy from */
- int p2; /* Register to copy to */
- int n; /* Number of values left to copy */
+case OP_Variable: { /* out2-prerelease */
Mem *pVar; /* Value being transferred */
- p1 = pOp->p1 - 1;
- p2 = pOp->p2;
- n = pOp->p3;
- assert( p1>=0 && p1+n<=p->nVar );
- assert( p2>=1 && p2+n-1<=p->nMem );
- assert( pOp->p4.z==0 || pOp->p3==1 );
-
- while( n-- > 0 ){
- pVar = &p->aVar[p1++];
- if( sqlite3VdbeMemTooBig(pVar) ){
- goto too_big;
- }
- pOut = &p->aMem[p2++];
- sqlite3VdbeMemReleaseExternal(pOut);
- pOut->flags = MEM_Null;
- sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
- UPDATE_MAX_BLOBSIZE(pOut);
+ assert( pOp->p1>0 && pOp->p1<=p->nVar );
+ pVar = &p->aVar[pOp->p1 - 1];
+ if( sqlite3VdbeMemTooBig(pVar) ){
+ goto too_big;
}
+ sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
+ UPDATE_MAX_BLOBSIZE(pOut);
break;
}
@@ -1043,11 +1014,13 @@ case OP_Move: {
assert( n>0 && p1>0 && p2>0 );
assert( p1+n<=p2 || p2+n<=p1 );
- pIn1 = &p->aMem[p1];
- pOut = &p->aMem[p2];
+ pIn1 = &aMem[p1];
+ pOut = &aMem[p2];
while( n-- ){
- assert( pOut<=&p->aMem[p->nMem] );
- assert( pIn1<=&p->aMem[p->nMem] );
+ assert( pOut<=&aMem[p->nMem] );
+ assert( pIn1<=&aMem[p->nMem] );
+ assert( memIsValid(pIn1) );
+ memAboutToChange(p, pOut);
zMalloc = pOut->zMalloc;
pOut->zMalloc = 0;
sqlite3VdbeMemMove(pOut, pIn1);
@@ -1066,10 +1039,9 @@ case OP_Move: {
** This instruction makes a deep copy of the value. A duplicate
** is made of any string or blob constant. See also OP_SCopy.
*/
-case OP_Copy: { /* in1 */
- assert( pOp->p2>0 );
- assert( pOp->p2<=p->nMem );
- pOut = &p->aMem[pOp->p2];
+case OP_Copy: { /* in1, out2 */
+ pIn1 = &aMem[pOp->p1];
+ pOut = &aMem[pOp->p2];
assert( pOut!=pIn1 );
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
Deephemeralize(pOut);
@@ -1089,13 +1061,14 @@ case OP_Copy: { /* in1 */
** during the lifetime of the copy. Use OP_Copy to make a complete
** copy.
*/
-case OP_SCopy: { /* in1 */
- REGISTER_TRACE(pOp->p1, pIn1);
- assert( pOp->p2>0 );
- assert( pOp->p2<=p->nMem );
- pOut = &p->aMem[pOp->p2];
+case OP_SCopy: { /* in1, out2 */
+ pIn1 = &aMem[pOp->p1];
+ pOut = &aMem[pOp->p2];
assert( pOut!=pIn1 );
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
+#ifdef SQLITE_DEBUG
+ if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1;
+#endif
REGISTER_TRACE(pOp->p2, pOut);
break;
}
@@ -1115,6 +1088,15 @@ case OP_ResultRow: {
assert( pOp->p1>0 );
assert( pOp->p1+pOp->p2<=p->nMem+1 );
+ /* If this statement has violated immediate foreign key constraints, do
+ ** not return the number of rows modified. And do not RELEASE the statement
+ ** transaction. It needs to be rolled back. */
+ if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
+ assert( db->flags&SQLITE_CountRows );
+ assert( p->usesStmtJournal );
+ break;
+ }
+
/* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then
** DML statements invoke this opcode to return the number of rows
** modified to the user. This is the only way that a VM that
@@ -1143,10 +1125,14 @@ case OP_ResultRow: {
** and have an assigned type. The results are de-ephemeralized as
** as side effect.
*/
- pMem = p->pResultSet = &p->aMem[pOp->p1];
+ pMem = p->pResultSet = &aMem[pOp->p1];
for(i=0; i<pOp->p2; i++){
+ assert( memIsValid(&pMem[i]) );
+ Deephemeralize(&pMem[i]);
+ assert( (pMem[i].flags & MEM_Ephem)==0
+ || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
sqlite3VdbeMemNulTerminate(&pMem[i]);
- storeTypeInfo(&pMem[i], encoding);
+ sqlite3VdbeMemStoreType(&pMem[i]);
REGISTER_TRACE(pOp->p1+i, &pMem[i]);
}
if( db->mallocFailed ) goto no_mem;
@@ -1173,6 +1159,9 @@ case OP_ResultRow: {
case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
i64 nByte;
+ pIn1 = &aMem[pOp->p1];
+ pIn2 = &aMem[pOp->p2];
+ pOut = &aMem[pOp->p3];
assert( pIn1!=pOut );
if( (pIn1->flags | pIn2->flags) & MEM_Null ){
sqlite3VdbeMemSetNull(pOut);
@@ -1246,27 +1235,23 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
double rA; /* Real value of left operand */
double rB; /* Real value of right operand */
+ pIn1 = &aMem[pOp->p1];
applyNumericAffinity(pIn1);
+ pIn2 = &aMem[pOp->p2];
applyNumericAffinity(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 ){
iA = pIn1->u.i;
iB = pIn2->u.i;
switch( pOp->opcode ){
- case OP_Add: iB += iA; break;
- case OP_Subtract: iB -= iA; break;
- case OP_Multiply: iB *= iA; break;
+ case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break;
+ case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break;
+ case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break;
case OP_Divide: {
if( iA==0 ) goto arithmetic_result_is_null;
- /* Dividing the largest possible negative 64-bit integer (1<<63) by
- ** -1 returns an integer too large to store in a 64-bit data-type. On
- ** some architectures, the value overflows to (1<<63). On others,
- ** a SIGFPE is issued. The following statement normalizes this
- ** behavior so that all architectures behave as if integer
- ** overflow occurred.
- */
- if( iA==-1 && iB==SMALLEST_INT64 ) iA = 1;
+ if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math;
iB /= iA;
break;
}
@@ -1280,6 +1265,7 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
pOut->u.i = iB;
MemSetTypeFlag(pOut, MEM_Int);
}else{
+fp_math:
rA = sqlite3VdbeRealValue(pIn1);
rB = sqlite3VdbeRealValue(pIn2);
switch( pOp->opcode ){
@@ -1301,6 +1287,10 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
break;
}
}
+#ifdef SQLITE_OMIT_FLOATING_POINT
+ pOut->u.i = rB;
+ MemSetTypeFlag(pOut, MEM_Int);
+#else
if( sqlite3IsNaN(rB) ){
goto arithmetic_result_is_null;
}
@@ -1309,6 +1299,7 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
if( (flags & MEM_Real)==0 ){
sqlite3VdbeIntegerAffinity(pOut);
}
+#endif
}
break;
@@ -1359,14 +1350,19 @@ case OP_Function: {
n = pOp->p5;
apVal = p->apArg;
assert( apVal || n==0 );
+ assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ pOut = &aMem[pOp->p3];
+ memAboutToChange(p, pOut);
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem+1) );
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
- pArg = &p->aMem[pOp->p2];
+ pArg = &aMem[pOp->p2];
for(i=0; i<n; i++, pArg++){
+ assert( memIsValid(pArg) );
apVal[i] = pArg;
- storeTypeInfo(pArg, encoding);
- REGISTER_TRACE(pOp->p2, pArg);
+ Deephemeralize(pArg);
+ sqlite3VdbeMemStoreType(pArg);
+ REGISTER_TRACE(pOp->p2+i, pArg);
}
assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
@@ -1378,8 +1374,6 @@ case OP_Function: {
ctx.pFunc = ctx.pVdbeFunc->pFunc;
}
- assert( pOp->p3>0 && pOp->p3<=p->nMem );
- pOut = &p->aMem[pOp->p3];
ctx.s.flags = MEM_Null;
ctx.s.db = db;
ctx.s.xDel = 0;
@@ -1394,26 +1388,17 @@ case OP_Function: {
ctx.isError = 0;
if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
- assert( pOp>p->aOp );
+ assert( pOp>aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
assert( pOp[-1].opcode==OP_CollSeq );
ctx.pColl = pOp[-1].p4.pColl;
}
- if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
- (*ctx.pFunc->xFunc)(&ctx, n, apVal);
- if( sqlite3SafetyOn(db) ){
- sqlite3VdbeMemRelease(&ctx.s);
- goto abort_due_to_misuse;
- }
+ (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
if( db->mallocFailed ){
/* Even though a malloc() has failed, the implementation of the
** user function may have called an sqlite3_result_XXX() function
** to return a value. The following call releases any resources
** associated with such a value.
- **
- ** Note: Maybe MemRelease() should be called if sqlite3SafetyOn()
- ** fails also (the if(...) statement above). But if people are
- ** misusing sqlite, they have bigger problems than a leaked value.
*/
sqlite3VdbeMemRelease(&ctx.s);
goto no_mem;
@@ -1440,6 +1425,15 @@ case OP_Function: {
if( sqlite3VdbeMemTooBig(pOut) ){
goto too_big;
}
+
+#if 0
+ /* The app-defined function has done something that as caused this
+ ** statement to expire. (Perhaps the function called sqlite3_exec()
+ ** with a CREATE TABLE statement.)
+ */
+ if( p->expired ) rc = SQLITE_ABORT;
+#endif
+
REGISTER_TRACE(pOp->p3, pOut);
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -1460,7 +1454,7 @@ case OP_Function: {
/* Opcode: ShiftLeft P1 P2 P3 * *
**
** Shift the integer value in register P2 to the left by the
-** number of bits specified by the integer in regiser P1.
+** number of bits specified by the integer in register P1.
** Store the result in register P3.
** If either input is NULL, the result is NULL.
*/
@@ -1475,23 +1469,50 @@ case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */
case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */
case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */
case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
- i64 a;
- i64 b;
-
+ i64 iA;
+ u64 uA;
+ i64 iB;
+ u8 op;
+
+ pIn1 = &aMem[pOp->p1];
+ pIn2 = &aMem[pOp->p2];
+ pOut = &aMem[pOp->p3];
if( (pIn1->flags | pIn2->flags) & MEM_Null ){
sqlite3VdbeMemSetNull(pOut);
break;
}
- a = sqlite3VdbeIntValue(pIn2);
- b = sqlite3VdbeIntValue(pIn1);
- switch( pOp->opcode ){
- case OP_BitAnd: a &= b; break;
- case OP_BitOr: a |= b; break;
- case OP_ShiftLeft: a <<= b; break;
- default: assert( pOp->opcode==OP_ShiftRight );
- a >>= b; break;
+ iA = sqlite3VdbeIntValue(pIn2);
+ iB = sqlite3VdbeIntValue(pIn1);
+ op = pOp->opcode;
+ if( op==OP_BitAnd ){
+ iA &= iB;
+ }else if( op==OP_BitOr ){
+ iA |= iB;
+ }else if( iB!=0 ){
+ assert( op==OP_ShiftRight || op==OP_ShiftLeft );
+
+ /* If shifting by a negative amount, shift in the other direction */
+ if( iB<0 ){
+ assert( OP_ShiftRight==OP_ShiftLeft+1 );
+ op = 2*OP_ShiftLeft + 1 - op;
+ iB = iB>(-64) ? -iB : 64;
+ }
+
+ if( iB>=64 ){
+ iA = (iA>=0 || op==OP_ShiftLeft) ? 0 : -1;
+ }else{
+ memcpy(&uA, &iA, sizeof(uA));
+ if( op==OP_ShiftLeft ){
+ uA <<= iB;
+ }else{
+ uA >>= iB;
+ /* Sign-extend on a right shift of a negative number */
+ if( iA<0 ) uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-iB);
+ }
+ memcpy(&iA, &uA, sizeof(iA));
+ }
}
- pOut->u.i = a;
+ pOut->u.i = iA;
MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -1504,6 +1525,8 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
** To force any register to be an integer, just add 0.
*/
case OP_AddImm: { /* in1 */
+ pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
sqlite3VdbeMemIntegerify(pIn1);
pIn1->u.i += pOp->p2;
break;
@@ -1517,6 +1540,7 @@ case OP_AddImm: { /* in1 */
** raise an SQLITE_MISMATCH exception.
*/
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 ){
@@ -1531,6 +1555,7 @@ case OP_MustBeInt: { /* jump, in1 */
break;
}
+#ifndef SQLITE_OMIT_FLOATING_POINT
/* Opcode: RealAffinity P1 * * * *
**
** If register P1 holds an integer convert it to a real value.
@@ -1541,11 +1566,13 @@ case OP_MustBeInt: { /* jump, in1 */
** to have only a real value.
*/
case OP_RealAffinity: { /* in1 */
+ pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Int ){
sqlite3VdbeMemRealify(pIn1);
}
break;
}
+#endif
#ifndef SQLITE_OMIT_CAST
/* Opcode: ToText P1 * * * *
@@ -1558,6 +1585,8 @@ case OP_RealAffinity: { /* in1 */
** A NULL value is not changed by this routine. It remains NULL.
*/
case OP_ToText: { /* same as TK_TO_TEXT, in1 */
+ pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
if( pIn1->flags & MEM_Null ) break;
assert( MEM_Str==(MEM_Blob>>3) );
pIn1->flags |= (pIn1->flags&MEM_Blob)>>3;
@@ -1579,6 +1608,7 @@ case OP_ToText: { /* same as TK_TO_TEXT, in1 */
** A NULL value is not changed by this routine. It remains NULL.
*/
case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
+ pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Null ) break;
if( (pIn1->flags & MEM_Blob)==0 ){
applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
@@ -1602,16 +1632,15 @@ case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
** A NULL value is not changed by this routine. It remains NULL.
*/
case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */
- if( (pIn1->flags & (MEM_Null|MEM_Int|MEM_Real))==0 ){
- sqlite3VdbeMemNumerify(pIn1);
- }
+ pIn1 = &aMem[pOp->p1];
+ sqlite3VdbeMemNumerify(pIn1);
break;
}
#endif /* SQLITE_OMIT_CAST */
/* Opcode: ToInt P1 * * * *
**
-** Force the value in register P1 be an integer. If
+** Force the value in register P1 to be an integer. If
** The value is currently a real number, drop its fractional part.
** If the value is text or blob, try to convert it to an integer using the
** equivalent of atoi() and store 0 if no such conversion is possible.
@@ -1619,13 +1648,14 @@ case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */
** A NULL value is not changed by this routine. It remains NULL.
*/
case OP_ToInt: { /* same as TK_TO_INT, in1 */
+ pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_Null)==0 ){
sqlite3VdbeMemIntegerify(pIn1);
}
break;
}
-#ifndef SQLITE_OMIT_CAST
+#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT)
/* Opcode: ToReal P1 * * * *
**
** Force the value in register P1 to be a floating point number.
@@ -1636,12 +1666,14 @@ case OP_ToInt: { /* same as TK_TO_INT, in1 */
** A NULL value is not changed by this routine. It remains NULL.
*/
case OP_ToReal: { /* same as TK_TO_REAL, in1 */
+ pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
if( (pIn1->flags & MEM_Null)==0 ){
sqlite3VdbeMemRealify(pIn1);
}
break;
}
-#endif /* SQLITE_OMIT_CAST */
+#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */
/* Opcode: Lt P1 P2 P3 P4 P5
**
@@ -1650,7 +1682,7 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
**
** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
** reg(P3) is NULL then take the jump. If the SQLITE_JUMPIFNULL
-** bit is clear then fall thru if either operand is NULL.
+** bit is clear then fall through if either operand is NULL.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
@@ -1678,12 +1710,24 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
** This works just like the Lt opcode except that the jump is taken if
** the operands in registers P1 and P3 are not equal. See the Lt opcode for
** additional information.
+**
+** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
+** true or false and is never NULL. If both operands are NULL then the result
+** of comparison is false. If either operand is NULL then the result is true.
+** If neither operand is NULL the the result is the same as it would be if
+** the SQLITE_NULLEQ flag were omitted from P5.
*/
/* Opcode: Eq P1 P2 P3 P4 P5
**
** This works just like the Lt opcode except that the jump is taken if
** the operands in registers P1 and P3 are equal.
** See the Lt opcode for additional information.
+**
+** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
+** true or false and is never NULL. If both operands are NULL then the result
+** of comparison is true. If either operand is NULL then the result is false.
+** If neither operand is NULL the the result is the same as it would be if
+** the SQLITE_NULLEQ flag were omitted from P5.
*/
/* Opcode: Le P1 P2 P3 P4 P5
**
@@ -1709,37 +1753,52 @@ case OP_Lt: /* same as TK_LT, jump, in1, in3 */
case OP_Le: /* same as TK_LE, jump, in1, in3 */
case OP_Gt: /* same as TK_GT, jump, in1, in3 */
case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
- int flags;
- int res;
- char affinity;
-
- flags = pIn1->flags|pIn3->flags;
-
- if( flags&MEM_Null ){
- /* If either operand is NULL then the result is always NULL.
- ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
- */
- if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &p->aMem[pOp->p2];
- MemSetTypeFlag(pOut, MEM_Null);
- REGISTER_TRACE(pOp->p2, pOut);
- }else if( pOp->p5 & SQLITE_JUMPIFNULL ){
- pc = pOp->p2-1;
+ int res; /* Result of the comparison of pIn1 against pIn3 */
+ char affinity; /* Affinity to use for comparison */
+ u16 flags1; /* Copy of initial value of pIn1->flags */
+ u16 flags3; /* Copy of initial value of pIn3->flags */
+
+ pIn1 = &aMem[pOp->p1];
+ pIn3 = &aMem[pOp->p3];
+ flags1 = pIn1->flags;
+ flags3 = pIn3->flags;
+ if( (pIn1->flags | pIn3->flags)&MEM_Null ){
+ /* One or both operands are NULL */
+ if( pOp->p5 & SQLITE_NULLEQ ){
+ /* If SQLITE_NULLEQ is set (which will only happen if the operator is
+ ** OP_Eq or OP_Ne) then take the jump or not depending on whether
+ ** or not both operands are null.
+ */
+ assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
+ res = (pIn1->flags & pIn3->flags & MEM_Null)==0;
+ }else{
+ /* SQLITE_NULLEQ is clear and at least one operand is NULL,
+ ** then the result is always NULL.
+ ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
+ */
+ if( pOp->p5 & SQLITE_STOREP2 ){
+ pOut = &aMem[pOp->p2];
+ MemSetTypeFlag(pOut, MEM_Null);
+ REGISTER_TRACE(pOp->p2, pOut);
+ }else if( pOp->p5 & SQLITE_JUMPIFNULL ){
+ pc = pOp->p2-1;
+ }
+ break;
+ }
+ }else{
+ /* Neither operand is NULL. Do a comparison. */
+ affinity = pOp->p5 & SQLITE_AFF_MASK;
+ if( affinity ){
+ applyAffinity(pIn1, affinity, encoding);
+ applyAffinity(pIn3, affinity, encoding);
+ if( db->mallocFailed ) goto no_mem;
}
- break;
- }
- affinity = pOp->p5 & SQLITE_AFF_MASK;
- if( affinity ){
- applyAffinity(pIn1, affinity, encoding);
- applyAffinity(pIn3, affinity, encoding);
- if( db->mallocFailed ) goto no_mem;
+ assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
+ ExpandBlob(pIn1);
+ ExpandBlob(pIn3);
+ res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
-
- assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
- ExpandBlob(pIn1);
- ExpandBlob(pIn3);
- res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
switch( pOp->opcode ){
case OP_Eq: res = res==0; break;
case OP_Ne: res = res!=0; break;
@@ -1750,13 +1809,18 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
}
if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &p->aMem[pOp->p2];
+ pOut = &aMem[pOp->p2];
+ memAboutToChange(p, pOut);
MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = res;
REGISTER_TRACE(pOp->p2, pOut);
}else 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);
break;
}
@@ -1778,8 +1842,8 @@ case OP_Permutation: {
/* Opcode: Compare P1 P2 P3 P4 *
**
-** Compare to vectors of registers in reg(P1)..reg(P1+P3-1) (all this
-** one "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of
+** 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
** the comparison for use by the next OP_Jump instruct.
**
** P4 is a KeyInfo structure that defines collating sequences and sort
@@ -1805,17 +1869,28 @@ case OP_Compare: {
assert( n>0 );
assert( pKeyInfo!=0 );
p1 = pOp->p1;
- assert( p1>0 && p1+n<=p->nMem+1 );
p2 = pOp->p2;
- assert( p2>0 && p2+n<=p->nMem+1 );
+#if SQLITE_DEBUG
+ if( aPermute ){
+ int k, mx = 0;
+ for(k=0; k<n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
+ assert( p1>0 && p1+mx<=p->nMem+1 );
+ assert( p2>0 && p2+mx<=p->nMem+1 );
+ }else{
+ assert( p1>0 && p1+n<=p->nMem+1 );
+ assert( p2>0 && p2+n<=p->nMem+1 );
+ }
+#endif /* SQLITE_DEBUG */
for(i=0; i<n; i++){
idx = aPermute ? aPermute[i] : i;
- REGISTER_TRACE(p1+idx, &p->aMem[p1+idx]);
- REGISTER_TRACE(p2+idx, &p->aMem[p2+idx]);
+ assert( memIsValid(&aMem[p1+idx]) );
+ assert( memIsValid(&aMem[p2+idx]) );
+ REGISTER_TRACE(p1+idx, &aMem[p1+idx]);
+ REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
assert( i<pKeyInfo->nField );
pColl = pKeyInfo->aColl[i];
bRev = pKeyInfo->aSortOrder[i];
- iCompare = sqlite3MemCompare(&p->aMem[p1+idx], &p->aMem[p2+idx], pColl);
+ iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
if( iCompare ){
if( bRev ) iCompare = -iCompare;
break;
@@ -1865,11 +1940,13 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
+ pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Null ){
v1 = 2;
}else{
v1 = sqlite3VdbeIntValue(pIn1)!=0;
}
+ pIn2 = &aMem[pOp->p2];
if( pIn2->flags & MEM_Null ){
v2 = 2;
}else{
@@ -1882,6 +1959,7 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
v1 = or_logic[v1*3+v2];
}
+ pOut = &aMem[pOp->p3];
if( v1==2 ){
MemSetTypeFlag(pOut, MEM_Null);
}else{
@@ -1897,8 +1975,9 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
** boolean complement in register P2. If the value in register P1 is
** NULL, then a NULL is stored in P2.
*/
-case OP_Not: { /* same as TK_NOT, in1 */
- pOut = &p->aMem[pOp->p2];
+case OP_Not: { /* same as TK_NOT, in1, out2 */
+ pIn1 = &aMem[pOp->p1];
+ pOut = &aMem[pOp->p2];
if( pIn1->flags & MEM_Null ){
sqlite3VdbeMemSetNull(pOut);
}else{
@@ -1913,8 +1992,9 @@ case OP_Not: { /* same as TK_NOT, in1 */
** ones-complement of the P1 value into register P2. If P1 holds
** a NULL then store a NULL in P2.
*/
-case OP_BitNot: { /* same as TK_BITNOT, in1 */
- pOut = &p->aMem[pOp->p2];
+case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
+ pIn1 = &aMem[pOp->p1];
+ pOut = &aMem[pOp->p2];
if( pIn1->flags & MEM_Null ){
sqlite3VdbeMemSetNull(pOut);
}else{
@@ -1938,6 +2018,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1 */
case OP_If: /* jump, in1 */
case OP_IfNot: { /* jump, in1 */
int c;
+ pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Null ){
c = pOp->p3;
}else{
@@ -1959,6 +2040,7 @@ case OP_IfNot: { /* jump, in1 */
** Jump to P2 if the value in register P1 is NULL.
*/
case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
+ pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_Null)!=0 ){
pc = pOp->p2 - 1;
}
@@ -1970,6 +2052,7 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
** 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];
if( (pIn1->flags & MEM_Null)==0 ){
pc = pOp->p2 - 1;
}
@@ -2014,7 +2097,7 @@ case OP_Column: {
u8 *zIdx; /* Index into header */
u8 *zEndHdr; /* Pointer to first byte after the header */
u32 offset; /* Offset into the data */
- u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */
+ 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 */
Mem *pReg; /* PseudoTable input register */
@@ -2026,7 +2109,8 @@ case OP_Column: {
memset(&sMem, 0, sizeof(sMem));
assert( p1<p->nCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- pDest = &p->aMem[pOp->p3];
+ pDest = &aMem[pOp->p3];
+ memAboutToChange(p, pDest);
MemSetTypeFlag(pDest, MEM_Null);
zRec = 0;
@@ -2072,8 +2156,9 @@ case OP_Column: {
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
}
}else if( pC->pseudoTableReg>0 ){
- pReg = &p->aMem[pC->pseudoTableReg];
+ pReg = &aMem[pC->pseudoTableReg];
assert( pReg->flags & MEM_Blob );
+ assert( memIsValid(pReg) );
payloadSize = pReg->n;
zRec = pReg->z;
pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
@@ -2189,12 +2274,16 @@ case OP_Column: {
** 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
*/
- offset64 = offset;
for(i=0; i<nField; i++){
if( zIdx<zEndHdr ){
- aOffset[i] = (u32)offset64;
+ aOffset[i] = offset;
zIdx += getVarint32(zIdx, aType[i]);
- offset64 += sqlite3VdbeSerialTypeLen(aType[i]);
+ szField = sqlite3VdbeSerialTypeLen(aType[i]);
+ offset += szField;
+ if( offset<szField ){ /* True if offset overflows */
+ zIdx = &zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
+ break;
+ }
}else{
/* If i is less that nField, then there are less fields in this
** record than SetNumColumns indicated there are columns in the
@@ -2214,8 +2303,8 @@ case OP_Column: {
** of the record (when all fields present), then we must be dealing
** with a corrupt database.
*/
- if( (zIdx > zEndHdr)|| (offset64 > payloadSize)
- || (zIdx==zEndHdr && offset64!=(u64)payloadSize) ){
+ if( (zIdx > zEndHdr) || (offset > payloadSize)
+ || (zIdx==zEndHdr && offset!=payloadSize) ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
@@ -2283,29 +2372,28 @@ op_column_out:
** memory cell in the range.
*/
case OP_Affinity: {
- char *zAffinity; /* The affinity to be applied */
- Mem *pData0; /* First register to which to apply affinity */
- Mem *pLast; /* Last register to which to apply affinity */
- Mem *pRec; /* Current register */
+ const char *zAffinity; /* The affinity to be applied */
+ char cAff; /* A single character of affinity */
zAffinity = pOp->p4.z;
- pData0 = &p->aMem[pOp->p1];
- pLast = &pData0[pOp->p2-1];
- for(pRec=pData0; pRec<=pLast; pRec++){
- ExpandBlob(pRec);
- applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
+ assert( zAffinity!=0 );
+ assert( zAffinity[pOp->p2]==0 );
+ pIn1 = &aMem[pOp->p1];
+ while( (cAff = *(zAffinity++))!=0 ){
+ assert( pIn1 <= &p->aMem[p->nMem] );
+ assert( memIsValid(pIn1) );
+ ExpandBlob(pIn1);
+ applyAffinity(pIn1, cAff, encoding);
+ pIn1++;
}
break;
}
/* Opcode: MakeRecord P1 P2 P3 P4 *
**
-** Convert P2 registers beginning with P1 into a single entry
-** suitable for use as a data record in a database table or as a key
-** in an index. The details of the format are irrelevant as long as
-** the OP_Column opcode can decode the record later.
-** Refer to source code comments for the details of the record
-** format.
+** Convert P2 registers beginning with P1 into the [record format]
+** use as a data record in a database table or as a key
+** in an index. The OP_Column opcode can decode the record later.
**
** P4 may be a string that is P2 characters long. The nth character of the
** string indicates the column affinity that should be used for the nth
@@ -2350,20 +2438,25 @@ case OP_MakeRecord: {
*/
nData = 0; /* Number of bytes of data space */
nHdr = 0; /* Number of bytes of header space */
- nByte = 0; /* Data space required for this record */
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 );
- pData0 = &p->aMem[nField];
+ pData0 = &aMem[nField];
nField = pOp->p2;
pLast = &pData0[nField-1];
file_format = p->minWriteFileFormat;
+ /* Identify the output register */
+ assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
+ pOut = &aMem[pOp->p3];
+ memAboutToChange(p, pOut);
+
/* 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++){
+ assert( memIsValid(pRec) );
if( zAffinity ){
applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
}
@@ -2398,8 +2491,6 @@ case OP_MakeRecord: {
** be one of the input registers (because the following call to
** sqlite3VdbeMemGrow() could clobber the value before it is used).
*/
- assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
- pOut = &p->aMem[pOp->p3];
if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){
goto no_mem;
}
@@ -2446,7 +2537,6 @@ case OP_Count: { /* out2-prerelease */
}else{
nEntry = 0;
}
- pOut->flags = MEM_Int;
pOut->u.i = nEntry;
break;
}
@@ -2508,6 +2598,7 @@ case OP_Savepoint: {
/* Link the new savepoint into the database handle's list. */
pNew->pNext = db->pSavepoint;
db->pSavepoint = pNew;
+ pNew->nDeferredCons = db->nDeferredCons;
}
}
}else{
@@ -2545,6 +2636,9 @@ case OP_Savepoint: {
*/
int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint;
if( isTransaction && p1==SAVEPOINT_RELEASE ){
+ if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
+ goto vdbe_return;
+ }
db->autoCommit = 1;
if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
p->pc = pc;
@@ -2564,7 +2658,8 @@ case OP_Savepoint: {
}
if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
sqlite3ExpirePreparedStatements(db);
- sqlite3ResetInternalSchema(db, 0);
+ sqlite3ResetInternalSchema(db, -1);
+ db->flags = (db->flags | SQLITE_InternChanges);
}
}
@@ -2577,7 +2672,10 @@ case OP_Savepoint: {
db->nSavepoint--;
}
- /* If it is a RELEASE, then destroy the savepoint being operated on too */
+ /* If it is a RELEASE, then destroy the savepoint being operated on
+ ** too. If it is a ROLLBACK TO, then set the number of deferred
+ ** constraint violations present in the database to the value stored
+ ** when the savepoint was created. */
if( p1==SAVEPOINT_RELEASE ){
assert( pSavepoint==db->pSavepoint );
db->pSavepoint = pSavepoint->pNext;
@@ -2585,6 +2683,8 @@ case OP_Savepoint: {
if( !isTransaction ){
db->nSavepoint--;
}
+ }else{
+ db->nDeferredCons = pSavepoint->nDeferredCons;
}
}
}
@@ -2633,6 +2733,8 @@ case OP_AutoCommit: {
assert( desiredAutoCommit==1 );
sqlite3RollbackAll(db);
db->autoCommit = 1;
+ }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
+ goto vdbe_return;
}else{
db->autoCommit = (u8)desiredAutoCommit;
if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
@@ -2696,7 +2798,7 @@ case OP_Transaction: {
Btree *pBt;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( (p->btreeMask & (1<<pOp->p1))!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
pBt = db->aDb[pOp->p1].pBt;
if( pBt ){
@@ -2706,7 +2808,7 @@ case OP_Transaction: {
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
- if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){
+ if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
@@ -2720,6 +2822,11 @@ case OP_Transaction: {
p->iStatement = db->nSavepoint + db->nStatement;
}
rc = sqlite3BtreeBeginStmt(pBt, p->iStatement);
+
+ /* Store the current value of the database handles deferred constraint
+ ** counter. If the statement transaction needs to be rolled back,
+ ** the value of this counter needs to be restored too. */
+ p->nStmtDefCons = db->nDeferredCons;
}
}
break;
@@ -2747,11 +2854,10 @@ case OP_ReadCookie: { /* out2-prerelease */
assert( pOp->p3<SQLITE_N_BTREE_META );
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pBt!=0 );
- assert( (p->btreeMask & (1<<iDb))!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
pOut->u.i = iMeta;
- MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -2769,9 +2875,11 @@ case OP_SetCookie: { /* in3 */
Db *pDb;
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( (p->btreeMask & (1<<pOp->p1))!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
pDb = &db->aDb[pOp->p1];
assert( pDb->pBt!=0 );
+ assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
+ pIn3 = &aMem[pOp->p3];
sqlite3VdbeMemIntegerify(pIn3);
/* See note about index shifting on OP_ReadCookie */
rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i);
@@ -2787,14 +2895,17 @@ case OP_SetCookie: { /* in3 */
/* Invalidate all prepared statements whenever the TEMP database
** schema is changed. Ticket #1644 */
sqlite3ExpirePreparedStatements(db);
+ p->expired = 0;
}
break;
}
-/* Opcode: VerifyCookie P1 P2 *
+/* 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.
+** 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.
@@ -2809,16 +2920,20 @@ case OP_SetCookie: { /* in3 */
*/
case OP_VerifyCookie: {
int iMeta;
+ int iGen;
Btree *pBt;
+
assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( (p->btreeMask & (1<<pOp->p1))!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->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{
- iMeta = 0;
+ iGen = iMeta = 0;
}
- if( iMeta!=pOp->p2 ){
+ 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
@@ -2838,7 +2953,7 @@ case OP_VerifyCookie: {
sqlite3ResetInternalSchema(db, pOp->p1);
}
- sqlite3ExpirePreparedStatements(db);
+ p->expired = 1;
rc = SQLITE_SCHEMA;
}
break;
@@ -2904,17 +3019,23 @@ case OP_OpenWrite: {
VdbeCursor *pCur;
Db *pDb;
+ if( p->expired ){
+ rc = SQLITE_ABORT;
+ break;
+ }
+
nField = 0;
pKeyInfo = 0;
p2 = pOp->p2;
iDb = pOp->p3;
assert( iDb>=0 && iDb<db->nDb );
- assert( (p->btreeMask & (1<<iDb))!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
pDb = &db->aDb[iDb];
pX = pDb->pBt;
assert( pX!=0 );
if( pOp->opcode==OP_OpenWrite ){
wrFlag = 1;
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
p->minWriteFileFormat = pDb->pSchema->file_format;
}
@@ -2924,7 +3045,9 @@ case OP_OpenWrite: {
if( pOp->p5 ){
assert( p2>0 );
assert( p2<=p->nMem );
- pIn2 = &p->aMem[p2];
+ pIn2 = &aMem[p2];
+ assert( memIsValid(pIn2) );
+ assert( (pIn2->flags & MEM_Int)!=0 );
sqlite3VdbeMemIntegerify(pIn2);
p2 = (int)pIn2->u.i;
/* The p2 value always comes from a prior OP_CreateTable opcode and
@@ -2947,6 +3070,7 @@ case OP_OpenWrite: {
pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
if( pCur==0 ) goto no_mem;
pCur->nullRow = 1;
+ pCur->isOrdered = 1;
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
pCur->pKeyInfo = pKeyInfo;
@@ -2973,10 +3097,10 @@ case OP_OpenWrite: {
**
** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if
-** the main database is read-only. The transient or virtual
+** the main database is read-only. The ephemeral
** table is deleted automatically when the cursor is closed.
**
-** P2 is the number of columns in the virtual table.
+** P2 is the number of columns in the ephemeral table.
** The cursor points to a BTree table if P4==0 and to a BTree index
** 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.
@@ -2987,9 +3111,17 @@ case OP_OpenWrite: {
** this opcode. Then this opcode was call OpenVirtual. But
** that created confusion with the whole virtual-table idea.
*/
+/* Opcode: OpenAutoindex P1 P2 * P4 *
+**
+** This opcode works the same as OP_OpenEphemeral. It has a
+** different name to distinguish its use. Tables created using
+** by this opcode will be used for automatically created transient
+** indices in joins.
+*/
+case OP_OpenAutoindex:
case OP_OpenEphemeral: {
VdbeCursor *pCx;
- static const int openFlags =
+ static const int vfsFlags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
@@ -3000,21 +3132,21 @@ case OP_OpenEphemeral: {
pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
- rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, openFlags,
- &pCx->pBt);
+ rc = sqlite3BtreeOpen(0, db, &pCx->pBt,
+ BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
}
if( rc==SQLITE_OK ){
/* If a transient index is required, create it by calling
- ** sqlite3BtreeCreateTable() with the BTREE_ZERODATA flag before
+ ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
** opening it. If a transient table is required, just use the
- ** automatically created table with root-page 1 (an INTKEY table).
+ ** automatically created table with root-page 1 (an BLOB_INTKEY table).
*/
if( pOp->p4.pKeyInfo ){
int pgno;
assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA);
+ rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY);
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1,
@@ -3028,6 +3160,7 @@ case OP_OpenEphemeral: {
pCx->isTable = 1;
}
}
+ pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
pCx->isIndex = !pCx->isTable;
break;
}
@@ -3039,7 +3172,7 @@ case OP_OpenEphemeral: {
** 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 the a single
+** 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
** individual columns using the OP_Column opcode. The OP_Column opcode
** is the only cursor opcode that works with a pseudo-table.
@@ -3140,6 +3273,10 @@ 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( pC->isOrdered );
if( pC->pCursor!=0 ){
oc = pOp->opcode;
pC->nullRow = 0;
@@ -3147,6 +3284,7 @@ case OP_SeekGt: { /* jump, in3 */
/* 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;
@@ -3169,12 +3307,12 @@ case OP_SeekGt: { /* jump, in3 */
** integer. */
res = 1;
if( pIn3->r<0 ){
- if( oc==OP_SeekGt || oc==OP_SeekGe ){
+ 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_SeekLt || oc==OP_SeekLe ){
+ 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;
}
@@ -3206,12 +3344,25 @@ case OP_SeekGt: { /* jump, in3 */
assert( nField>0 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)nField;
- if( oc==OP_SeekGt || oc==OP_SeekLe ){
- r.flags = UNPACKED_INCRKEY;
- }else{
- r.flags = 0;
- }
- r.aMem = &p->aMem[pOp->p3];
+
+ /* 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;
+ ** }
+ */
+ r.flags = (u16)(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 );
+
+ r.aMem = &aMem[pOp->p3];
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+#endif
+ ExpandBlob(r.aMem);
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
@@ -3223,7 +3374,7 @@ case OP_SeekGt: { /* jump, in3 */
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
- if( oc==OP_SeekGe || oc==OP_SeekGt ){
+ 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;
@@ -3276,6 +3427,7 @@ case OP_Seek: { /* in2 */
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;
@@ -3284,33 +3436,27 @@ case OP_Seek: { /* in2 */
}
-/* Opcode: Found P1 P2 P3 * *
-**
-** Register P3 holds a blob constructed by MakeRecord. P1 is an index.
-** If an entry that matches the value in register p3 exists in P1 then
-** jump to P2. If the P3 value does not match any entry in P1
-** then fall thru. The P1 cursor is left pointing at the matching entry
-** if it exists.
-**
-** This instruction is used to implement the IN operator where the
-** left-hand side is a SELECT statement. P1 may be a true index, or it
-** may be a temporary index that holds the results of the SELECT
-** statement. This instruction is also used to implement the
-** DISTINCT keyword in SELECT statements.
+/* Opcode: Found P1 P2 P3 P4 *
**
-** This instruction checks if index P1 contains a record for which
-** the first N serialized values exactly match the N serialized values
-** in the record in register P3, where N is the total number of values in
-** the P3 record (the P3 record is a prefix of the P1 record).
+** 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.
**
-** See also: NotFound, IsUnique, NotExists
+** 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.
*/
-/* Opcode: NotFound P1 P2 P3 * *
+/* Opcode: NotFound P1 P2 P3 P4 *
**
-** Register P3 holds a blob constructed by MakeRecord. P1 is
-** an index. If no entry exists in P1 that matches the blob then jump
-** to P2. If an entry does existing, fall through. The cursor is left
-** pointing to the entry that matches.
+** 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
+** is not the prefix of any entry in P1 then a jump is made to P2. If P1
+** does contain an entry whose prefix matches the P3/P4 record then control
+** falls through to the next instruction and P1 is left pointing at the
+** matching entry.
**
** See also: Found, NotExists, IsUnique
*/
@@ -3320,27 +3466,45 @@ case OP_Found: { /* jump, in3 */
VdbeCursor *pC;
int res;
UnpackedRecord *pIdxKey;
+ UnpackedRecord r;
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
+#ifdef SQLITE_TEST
+ sqlite3_found_count++;
+#endif
+
alreadyExists = 0;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( pOp->p4type==P4_INT32 );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
+ pIn3 = &aMem[pOp->p3];
if( ALWAYS(pC->pCursor!=0) ){
assert( pC->isTable==0 );
- assert( pIn3->flags & MEM_Blob );
- ExpandBlob(pIn3);
- pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z,
- aTempRec, sizeof(aTempRec));
- if( pIdxKey==0 ){
- goto no_mem;
- }
- if( pOp->opcode==OP_Found ){
+ if( pOp->p4.i>0 ){
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = (u16)pOp->p4.i;
+ r.aMem = pIn3;
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+#endif
+ r.flags = UNPACKED_PREFIX_MATCH;
+ pIdxKey = &r;
+ }else{
+ assert( pIn3->flags & MEM_Blob );
+ assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
+ pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z,
+ aTempRec, sizeof(aTempRec));
+ if( pIdxKey==0 ){
+ goto no_mem;
+ }
pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
}
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
+ if( pOp->p4.i==0 ){
+ sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
+ }
if( rc!=SQLITE_OK ){
break;
}
@@ -3358,9 +3522,10 @@ case OP_Found: { /* jump, in3 */
/* Opcode: IsUnique P1 P2 P3 P4 *
**
-** Cursor P1 is open on an index. So it has no data and its key consists
-** of a record generated by OP_MakeRecord where the last field is the
-** rowid of the entry that the index refers to.
+** 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
@@ -3386,11 +3551,12 @@ case OP_IsUnique: { /* jump, in3 */
VdbeCursor *pCx;
BtCursor *pCrsr;
u16 nField;
- Mem *aMem;
+ Mem *aMx;
UnpackedRecord r; /* B-Tree index search key */
i64 R; /* Rowid stored in register P3 */
- aMem = &p->aMem[pOp->p4.i];
+ 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 );
@@ -3406,20 +3572,23 @@ case OP_IsUnique: { /* jump, in3 */
/* If any of the values are NULL, take the jump. */
nField = pCx->pKeyInfo->nField;
for(ii=0; ii<nField; ii++){
- if( aMem[ii].flags & MEM_Null ){
+ if( aMx[ii].flags & MEM_Null ){
pc = pOp->p2 - 1;
pCrsr = 0;
break;
}
}
- assert( (aMem[nField].flags & MEM_Null)==0 );
+ 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 = aMem;
+ r.aMem = aMx;
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+#endif
/* Extract the value of R from register P3. */
sqlite3VdbeMemIntegerify(pIn3);
@@ -3442,7 +3611,7 @@ case OP_IsUnique: { /* jump, in3 */
**
** Use the content of register P3 as a 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 thru. The cursor is left
+** If the record does exist, then fall through. The cursor is left
** pointing to the record if it exists.
**
** The difference between this operation and NotFound is that this
@@ -3458,6 +3627,7 @@ case OP_NotExists: { /* jump, in3 */
int res;
u64 iKey;
+ pIn3 = &aMem[pOp->p3];
assert( pIn3->flags & MEM_Int );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
@@ -3501,7 +3671,6 @@ case OP_Sequence: { /* out2-prerelease */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( p->apCsr[pOp->p1]!=0 );
pOut->u.i = p->apCsr[pOp->p1]->seqCount++;
- MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -3550,7 +3719,6 @@ case OP_NewRowid: { /* out2-prerelease */
** and try again, up to 100 times.
*/
assert( pC->isTable );
- cnt = 0;
#ifdef SQLITE_32BIT_ROWID
# define MAX_ROWID 0x7fffffff
@@ -3570,7 +3738,7 @@ case OP_NewRowid: { /* out2-prerelease */
goto abort_due_to_error;
}
if( res ){
- v = 1;
+ v = 1; /* IMP: R-61914-48074 */
}else{
assert( sqlite3BtreeCursorIsValid(pC->pCursor) );
rc = sqlite3BtreeKeySize(pC->pCursor, &v);
@@ -3578,7 +3746,7 @@ case OP_NewRowid: { /* out2-prerelease */
if( v==MAX_ROWID ){
pC->useRandomRowid = 1;
}else{
- v++;
+ v++; /* IMP: R-29538-34987 */
}
}
}
@@ -3595,14 +3763,16 @@ case OP_NewRowid: { /* out2-prerelease */
}else{
/* Assert that P3 is a valid memory cell. */
assert( pOp->p3<=p->nMem );
- pMem = &p->aMem[pOp->p3];
+ 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;
+ rc = SQLITE_FULL; /* IMP: R-12275-61338 */
goto abort_due_to_error;
}
if( v<pMem->u.i+1 ){
@@ -3615,30 +3785,41 @@ case OP_NewRowid: { /* out2-prerelease */
sqlite3BtreeSetCachedRowid(pC->pCursor, v<MAX_ROWID ? v+1 : 0);
}
if( pC->useRandomRowid ){
+ /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
+ ** largest possible integer (9223372036854775807) then the database
+ ** engine starts picking positive candidate ROWIDs at random until
+ ** it finds one that is not previously used. */
assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
** an AUTOINCREMENT table. */
+ /* on the first attempt, simply do one more than previous */
v = db->lastRowid;
+ v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+ v++; /* ensure non-zero */
cnt = 0;
- do{
- if( cnt==0 && (v&0xffffff)==v ){
- v++;
+ while( ((rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)v,
+ 0, &res))==SQLITE_OK)
+ && (res==0)
+ && (++cnt<100)){
+ /* collision - try another random rowid */
+ sqlite3_randomness(sizeof(v), &v);
+ if( cnt<5 ){
+ /* try "small" random rowids for the initial attempts */
+ v &= 0xffffff;
}else{
- sqlite3_randomness(sizeof(v), &v);
- if( cnt<5 ) v &= 0xffffff;
+ v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
}
- rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)v, 0, &res);
- cnt++;
- }while( cnt<100 && rc==SQLITE_OK && res==0 );
+ v++; /* ensure non-zero */
+ }
if( rc==SQLITE_OK && res==0 ){
- rc = SQLITE_FULL;
+ rc = SQLITE_FULL; /* IMP: R-38219-53002 */
goto abort_due_to_error;
}
+ assert( v>0 ); /* EV: R-40812-03570 */
}
pC->rowidIsValid = 0;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}
- MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = v;
break;
}
@@ -3682,7 +3863,13 @@ case OP_NewRowid: { /* out2-prerelease */
** This instruction only works on tables. The equivalent instruction
** for indices is OP_IdxInsert.
*/
-case OP_Insert: {
+/* Opcode: InsertInt P1 P2 P3 P4 P5
+**
+** 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.
+*/
+case OP_Insert:
+case OP_InsertInt: {
Mem *pData; /* MEM cell holding data for the record to be inserted */
Mem *pKey; /* MEM cell holding key for the record */
i64 iKey; /* The integer ROWID or key for the record to be inserted */
@@ -3693,21 +3880,29 @@ case OP_Insert: {
const char *zTbl; /* Table name - used by the opdate hook */
int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
- pData = &p->aMem[pOp->p2];
- pKey = &p->aMem[pOp->p3];
+ pData = &aMem[pOp->p2];
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( memIsValid(pData) );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->pCursor!=0 );
assert( pC->pseudoTableReg==0 );
- assert( pKey->flags & MEM_Int );
assert( pC->isTable );
REGISTER_TRACE(pOp->p2, pData);
- REGISTER_TRACE(pOp->p3, pKey);
- iKey = pKey->u.i;
+ if( pOp->opcode==OP_Insert ){
+ pKey = &aMem[pOp->p3];
+ assert( pKey->flags & MEM_Int );
+ assert( memIsValid(pKey) );
+ REGISTER_TRACE(pOp->p3, pKey);
+ iKey = pKey->u.i;
+ }else{
+ assert( pOp->opcode==OP_InsertInt );
+ iKey = pOp->p3;
+ }
+
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
- if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = pKey->u.i;
+ if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = iKey;
if( pData->flags & MEM_Null ){
pData->z = 0;
pData->n = 0;
@@ -3845,7 +4040,8 @@ case OP_RowData: {
u32 n;
i64 n64;
- pOut = &p->aMem[pOp->p2];
+ pOut = &aMem[pOp->p2];
+ memAboutToChange(p, pOut);
/* Note that RowKey and RowData are really exactly the same instruction */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
@@ -3918,7 +4114,7 @@ case OP_Rowid: { /* out2-prerelease */
assert( pC!=0 );
assert( pC->pseudoTableReg==0 );
if( pC->nullRow ){
- /* Do nothing so that reg[P2] remains NULL */
+ pOut->flags = MEM_Null;
break;
}else if( pC->deferredMoveto ){
v = pC->movetoTarget;
@@ -3927,12 +4123,8 @@ case OP_Rowid: { /* out2-prerelease */
pVtab = pC->pVtabCursor->pVtab;
pModule = pVtab->pModule;
assert( pModule->xRowid );
- if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xRowid(pC->pVtabCursor, &v);
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = pVtab->zErrMsg;
- pVtab->zErrMsg = 0;
- if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ importVtabErrMsg(p, pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
assert( pC->pCursor!=0 );
@@ -3946,7 +4138,6 @@ case OP_Rowid: { /* out2-prerelease */
}
}
pOut->u.i = v;
- MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -4039,14 +4230,13 @@ case OP_Rewind: { /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
+ res = 1;
if( (pCrsr = pC->pCursor)!=0 ){
rc = sqlite3BtreeFirst(pCrsr, &res);
pC->atFirst = res==0 ?1:0;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
pC->rowidIsValid = 0;
- }else{
- res = 1;
}
pC->nullRow = (u8)res;
assert( pOp->p2>0 && pOp->p2<p->nOp );
@@ -4056,7 +4246,7 @@ case OP_Rewind: { /* jump */
break;
}
-/* Opcode: Next P1 P2 * * *
+/* Opcode: Next P1 P2 * * 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
@@ -4065,9 +4255,12 @@ case OP_Rewind: { /* jump */
**
** The P1 cursor must be for a real table, not a pseudo-table.
**
+** If P5 is positive and the jump is taken, then event counter
+** number P5-1 in the prepared statement is incremented.
+**
** See also: Prev
*/
-/* Opcode: Prev P1 P2 * * *
+/* Opcode: Prev P1 P2 * * 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
@@ -4075,6 +4268,9 @@ case OP_Rewind: { /* jump */
** jump immediately to P2.
**
** The P1 cursor must be for a real table, not a pseudo-table.
+**
+** If P5 is positive and the jump is taken, then event counter
+** number P5-1 in the prepared statement is incremented.
*/
case OP_Prev: /* jump */
case OP_Next: { /* jump */
@@ -4084,6 +4280,7 @@ case OP_Next: { /* jump */
CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( pOp->p5<=ArraySize(p->aCounter) );
pC = p->apCsr[pOp->p1];
if( pC==0 ){
break; /* See ticket #2273 */
@@ -4131,6 +4328,7 @@ case OP_IdxInsert: { /* in2 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
+ pIn2 = &aMem[pOp->p2];
assert( pIn2->flags & MEM_Blob );
pCrsr = pC->pCursor;
if( ALWAYS(pCrsr!=0) ){
@@ -4171,7 +4369,10 @@ case OP_IdxDelete: {
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p3;
r.flags = 0;
- r.aMem = &p->aMem[pOp->p2];
+ r.aMem = &aMem[pOp->p2];
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+#endif
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
if( rc==SQLITE_OK && res==0 ){
rc = sqlite3BtreeDelete(pCrsr);
@@ -4199,6 +4400,7 @@ case OP_IdxRowid: { /* out2-prerelease */
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
pCrsr = pC->pCursor;
+ pOut->flags = MEM_Null;
if( ALWAYS(pCrsr!=0) ){
rc = sqlite3VdbeCursorMoveto(pC);
if( NEVER(rc) ) goto abort_due_to_error;
@@ -4209,8 +4411,8 @@ case OP_IdxRowid: { /* out2-prerelease */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = rowid;
+ pOut->flags = MEM_Int;
}
}
break;
@@ -4230,7 +4432,7 @@ case OP_IdxRowid: { /* out2-prerelease */
** 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.
*/
-/* Opcode: IdxLT P1 P2 P3 * P5
+/* Opcode: IdxLT P1 P2 P3 P4 P5
**
** The P4 register values beginning with P3 form an unpacked index
** key that omits the ROWID. Compare this key value against the index
@@ -4242,8 +4444,8 @@ case OP_IdxRowid: { /* out2-prerelease */
** 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.
*/
-case OP_IdxLT: /* jump, in3 */
-case OP_IdxGE: { /* jump, in3 */
+case OP_IdxLT: /* jump */
+case OP_IdxGE: { /* jump */
VdbeCursor *pC;
int res;
UnpackedRecord r;
@@ -4251,6 +4453,7 @@ case OP_IdxGE: { /* jump, in3 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
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 );
@@ -4262,7 +4465,10 @@ case OP_IdxGE: { /* jump, in3 */
}else{
r.flags = UNPACKED_IGNORE_ROWID;
}
- r.aMem = &p->aMem[pOp->p3];
+ r.aMem = &aMem[pOp->p3];
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+#endif
rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
if( pOp->opcode==OP_IdxLT ){
res = -res;
@@ -4312,19 +4518,23 @@ case OP_Destroy: { /* out2-prerelease */
#else
iCnt = db->activeVdbeCnt;
#endif
+ pOut->flags = MEM_Null;
if( iCnt>1 ){
rc = SQLITE_LOCKED;
p->errorAction = OE_Abort;
}else{
iDb = pOp->p3;
assert( iCnt==1 );
- assert( (p->btreeMask & (1<<iDb))!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
- MemSetTypeFlag(pOut, MEM_Int);
+ pOut->flags = MEM_Int;
pOut->u.i = iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( rc==SQLITE_OK && iMoved!=0 ){
- sqlite3RootPageMoved(&db->aDb[iDb], iMoved, pOp->p1);
+ sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1);
+ /* All OP_Destroy operations occur on the same btree */
+ assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 );
+ resetSchemaOnFault = iDb+1;
}
#endif
}
@@ -4353,14 +4563,16 @@ case OP_Clear: {
int nChange;
nChange = 0;
- assert( (p->btreeMask & (1<<pOp->p2))!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
rc = sqlite3BtreeClearTable(
db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
);
if( pOp->p3 ){
p->nChange += nChange;
if( pOp->p3>0 ){
- p->aMem[pOp->p3].u.i += nChange;
+ assert( memIsValid(&aMem[pOp->p3]) );
+ memAboutToChange(p, &aMem[pOp->p3]);
+ aMem[pOp->p3].u.i += nChange;
}
}
break;
@@ -4396,29 +4608,24 @@ case OP_CreateTable: { /* out2-prerelease */
pgno = 0;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( (p->btreeMask & (1<<pOp->p1))!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
pDb = &db->aDb[pOp->p1];
assert( pDb->pBt!=0 );
if( pOp->opcode==OP_CreateTable ){
/* flags = BTREE_INTKEY; */
- flags = BTREE_LEAFDATA|BTREE_INTKEY;
+ flags = BTREE_INTKEY;
}else{
- flags = BTREE_ZERODATA;
+ flags = BTREE_BLOBKEY;
}
rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
pOut->u.i = pgno;
- MemSetTypeFlag(pOut, MEM_Int);
break;
}
-/* Opcode: ParseSchema P1 P2 * P4 *
+/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
-** that match the WHERE clause P4. P2 is the "force" flag. Always do
-** the parsing if P2 is true. If P2 is false, then this routine is a
-** no-op if the schema is not currently loaded. In other words, if P2
-** is false, the SQLITE_MASTER table is only parsed if the rest of the
-** schema is already loaded into the symbol table.
+** that match the WHERE clause P4.
**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine. It is thus a re-entrant opcode.
@@ -4429,44 +4636,30 @@ case OP_ParseSchema: {
char *zSql;
InitData initData;
+ /* Any prepared statement that invokes this opcode will hold mutexes
+ ** on every btree. This is a prerequisite for invoking
+ ** sqlite3InitCallback().
+ */
+#ifdef SQLITE_DEBUG
+ for(iDb=0; iDb<db->nDb; iDb++){
+ assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
+ }
+#endif
+
iDb = pOp->p1;
assert( iDb>=0 && iDb<db->nDb );
-
- /* If pOp->p2 is 0, then this opcode is being executed to read a
- ** single row, for example the row corresponding to a new index
- ** created by this VDBE, from the sqlite_master table. It only
- ** does this if the corresponding in-memory schema is currently
- ** loaded. Otherwise, the new index definition can be loaded along
- ** with the rest of the schema when it is required.
- **
- ** Although the mutex on the BtShared object that corresponds to
- ** database iDb (the database containing the sqlite_master table
- ** read by this instruction) is currently held, it is necessary to
- ** obtain the mutexes on all attached databases before checking if
- ** the schema of iDb is loaded. This is because, at the start of
- ** the sqlite3_exec() call below, SQLite will invoke
- ** sqlite3BtreeEnterAll(). If all mutexes are not already held, the
- ** iDb mutex may be temporarily released to avoid deadlock. If
- ** this happens, then some other thread may delete the in-memory
- ** schema of database iDb before the SQL statement runs. The schema
- ** will not be reloaded becuase the db->init.busy flag is set. This
- ** can result in a "no such table: sqlite_master" or "malformed
- ** database schema" error being returned to the user.
- */
- assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
- sqlite3BtreeEnterAll(db);
- if( pOp->p2 || DbHasProperty(db, iDb, DB_SchemaLoaded) ){
+ assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
+ /* Used to be a conditional */ {
zMaster = SCHEMA_TABLE(iDb);
initData.db = db;
initData.iDb = pOp->p1;
initData.pzErrMsg = &p->zErrMsg;
zSql = sqlite3MPrintf(db,
- "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s",
+ "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
db->aDb[iDb].zName, zMaster, pOp->p4.z);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
- (void)sqlite3SafetyOff(db);
assert( db->init.busy==0 );
db->init.busy = 1;
initData.rc = SQLITE_OK;
@@ -4475,10 +4668,8 @@ case OP_ParseSchema: {
if( rc==SQLITE_OK ) rc = initData.rc;
sqlite3DbFree(db, zSql);
db->init.busy = 0;
- (void)sqlite3SafetyOn(db);
}
}
- sqlite3BtreeLeaveAll(db);
if( rc==SQLITE_NOMEM ){
goto no_mem;
}
@@ -4570,16 +4761,16 @@ case OP_IntegrityCk: {
aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) );
if( aRoot==0 ) goto no_mem;
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- pnErr = &p->aMem[pOp->p3];
+ pnErr = &aMem[pOp->p3];
assert( (pnErr->flags & MEM_Int)!=0 );
assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
- pIn1 = &p->aMem[pOp->p1];
+ pIn1 = &aMem[pOp->p1];
for(j=0; j<nRoot; j++){
aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]);
}
aRoot[j] = 0;
assert( pOp->p5<db->nDb );
- assert( (p->btreeMask & (1<<pOp->p5))!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
(int)pnErr->u.i, &nErr);
sqlite3DbFree(db, aRoot);
@@ -4605,19 +4796,15 @@ case OP_IntegrityCk: {
**
** An assertion fails if P2 is not an integer.
*/
-case OP_RowSetAdd: { /* in2 */
- Mem *pIdx;
- Mem *pVal;
- assert( pOp->p1>0 && pOp->p1<=p->nMem );
- pIdx = &p->aMem[pOp->p1];
- assert( pOp->p2>0 && pOp->p2<=p->nMem );
- pVal = &p->aMem[pOp->p2];
- assert( (pVal->flags & MEM_Int)!=0 );
- if( (pIdx->flags & MEM_RowSet)==0 ){
- sqlite3VdbeMemSetRowSet(pIdx);
- if( (pIdx->flags & MEM_RowSet)==0 ) goto no_mem;
- }
- sqlite3RowSetInsert(pIdx->u.pRowSet, pVal->u.i);
+case OP_RowSetAdd: { /* in1, in2 */
+ pIn1 = &aMem[pOp->p1];
+ pIn2 = &aMem[pOp->p2];
+ assert( (pIn2->flags & MEM_Int)!=0 );
+ if( (pIn1->flags & MEM_RowSet)==0 ){
+ sqlite3VdbeMemSetRowSet(pIn1);
+ if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
+ }
+ sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i);
break;
}
@@ -4627,23 +4814,19 @@ case OP_RowSetAdd: { /* in2 */
** register P3. Or, if boolean index P1 is initially empty, leave P3
** unchanged and jump to instruction P2.
*/
-case OP_RowSetRead: { /* jump, out3 */
- Mem *pIdx;
+case OP_RowSetRead: { /* jump, in1, out3 */
i64 val;
- assert( pOp->p1>0 && pOp->p1<=p->nMem );
CHECK_FOR_INTERRUPT;
- pIdx = &p->aMem[pOp->p1];
- pOut = &p->aMem[pOp->p3];
- if( (pIdx->flags & MEM_RowSet)==0
- || sqlite3RowSetNext(pIdx->u.pRowSet, &val)==0
+ pIn1 = &aMem[pOp->p1];
+ if( (pIn1->flags & MEM_RowSet)==0
+ || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0
){
/* The boolean index is empty */
- sqlite3VdbeMemSetNull(pIdx);
+ sqlite3VdbeMemSetNull(pIn1);
pc = pOp->p2 - 1;
}else{
/* A value was pulled from the index */
- assert( pOp->p3>0 && pOp->p3<=p->nMem );
- sqlite3VdbeMemSetInt64(pOut, val);
+ sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val);
}
break;
}
@@ -4675,6 +4858,8 @@ case OP_RowSetTest: { /* jump, in1, in3 */
int iSet;
int exists;
+ pIn1 = &aMem[pOp->p1];
+ pIn3 = &aMem[pOp->p3];
iSet = pOp->p4.i;
assert( pIn3->flags&MEM_Int );
@@ -4730,27 +4915,28 @@ case OP_Program: { /* jump */
void *t; /* Token identifying trigger */
pProgram = pOp->p4.pProgram;
- pRt = &p->aMem[pOp->p3];
+ pRt = &aMem[pOp->p3];
+ assert( memIsValid(pRt) );
assert( pProgram->nOp>0 );
- /* If the SQLITE_RecTriggers flag is clear, then recursive invocation of
- ** triggers is disabled for backwards compatibility (flag set/cleared by
- ** the "PRAGMA recursive_triggers" command).
+ /* If the p5 flag is clear, then recursive invocation of triggers is
+ ** disabled for backwards compatibility (p5 is set if this sub-program
+ ** is really a trigger, not a foreign key action, and the flag set
+ ** and cleared by the "PRAGMA recursive_triggers" command is clear).
**
** It is recursive invocation of triggers, at the SQL level, that is
** disabled. In some cases a single trigger may generate more than one
** SubProgram (if the trigger may be executed with more than one different
** ON CONFLICT algorithm). SubProgram structures associated with a
** single trigger all have the same value for the SubProgram.token
- ** variable.
- */
- if( 0==(db->flags&SQLITE_RecTriggers) ){
+ ** variable. */
+ if( pOp->p5 ){
t = pProgram->token;
for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent);
if( pFrame ) break;
}
- if( p->nFrame>db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
+ if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
rc = SQLITE_ERROR;
sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion");
break;
@@ -4808,11 +4994,11 @@ case OP_Program: { /* jump */
pFrame->nChange = p->nChange;
p->nChange = 0;
p->pFrame = pFrame;
- p->aMem = &VdbeFrameMem(pFrame)[-1];
+ p->aMem = aMem = &VdbeFrameMem(pFrame)[-1];
p->nMem = pFrame->nChildMem;
p->nCursor = (u16)pFrame->nChildCsr;
- p->apCsr = (VdbeCursor **)&p->aMem[p->nMem+1];
- p->aOp = pProgram->aOp;
+ p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
+ p->aOp = aOp = pProgram->aOp;
p->nOp = pProgram->nOp;
pc = -1;
@@ -4842,6 +5028,44 @@ case OP_Param: { /* out2-prerelease */
#endif /* #ifndef SQLITE_OMIT_TRIGGER */
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+/* Opcode: FkCounter 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
+** (deferred foreign key constraints). Otherwise, if P1 is zero, the
+** statement counter is incremented (immediate foreign key constraints).
+*/
+case OP_FkCounter: {
+ if( pOp->p1 ){
+ db->nDeferredCons += pOp->p2;
+ }else{
+ p->nFkConstraint += pOp->p2;
+ }
+ break;
+}
+
+/* Opcode: FkIfZero P1 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
+** instruction.
+**
+** If P1 is non-zero, then the jump is taken if the database constraint-counter
+** is zero (the one that counts deferred constraint violations). If P1 is
+** zero, the jump is taken if the statement constraint-counter is zero
+** (immediate foreign key constraint violations).
+*/
+case OP_FkIfZero: { /* jump */
+ if( pOp->p1 ){
+ if( db->nDeferredCons==0 ) pc = pOp->p2-1;
+ }else{
+ if( p->nFkConstraint==0 ) pc = pOp->p2-1;
+ }
+ break;
+}
+#endif /* #ifndef SQLITE_OMIT_FOREIGN_KEY */
+
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Opcode: MemMax P1 P2 * * *
**
@@ -4860,9 +5084,11 @@ case OP_MemMax: { /* in2 */
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
pIn1 = &pFrame->aMem[pOp->p1];
}else{
- pIn1 = &p->aMem[pOp->p1];
+ pIn1 = &aMem[pOp->p1];
}
+ assert( memIsValid(pIn1) );
sqlite3VdbeMemIntegerify(pIn1);
+ pIn2 = &aMem[pOp->p2];
sqlite3VdbeMemIntegerify(pIn2);
if( pIn1->u.i<pIn2->u.i){
pIn1->u.i = pIn2->u.i;
@@ -4879,6 +5105,7 @@ case OP_MemMax: { /* in2 */
** not contain an integer. An assertion fault will result if you try.
*/
case OP_IfPos: { /* jump, in1 */
+ pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int );
if( pIn1->u.i>0 ){
pc = pOp->p2 - 1;
@@ -4894,6 +5121,7 @@ case OP_IfPos: { /* jump, in1 */
** not contain an integer. An assertion fault will result if you try.
*/
case OP_IfNeg: { /* jump, in1 */
+ pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int );
if( pIn1->u.i<0 ){
pc = pOp->p2 - 1;
@@ -4901,15 +5129,18 @@ case OP_IfNeg: { /* jump, in1 */
break;
}
-/* Opcode: IfZero P1 P2 * * *
+/* Opcode: IfZero P1 P2 P3 * *
**
-** If the value of register P1 is exactly 0, jump to 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;
if( pIn1->u.i==0 ){
pc = pOp->p2 - 1;
}
@@ -4936,16 +5167,18 @@ case OP_AggStep: {
n = pOp->p5;
assert( n>=0 );
- pRec = &p->aMem[pOp->p2];
+ pRec = &aMem[pOp->p2];
apVal = p->apArg;
assert( apVal || n==0 );
for(i=0; i<n; i++, pRec++){
+ assert( memIsValid(pRec) );
apVal[i] = pRec;
- storeTypeInfo(pRec, encoding);
+ memAboutToChange(p, pRec);
+ sqlite3VdbeMemStoreType(pRec);
}
ctx.pFunc = pOp->p4.pFunc;
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- ctx.pMem = pMem = &p->aMem[pOp->p3];
+ ctx.pMem = pMem = &aMem[pOp->p3];
pMem->n++;
ctx.s.flags = MEM_Null;
ctx.s.z = 0;
@@ -4960,12 +5193,14 @@ case OP_AggStep: {
assert( pOp[-1].opcode==OP_CollSeq );
ctx.pColl = pOp[-1].p4.pColl;
}
- (ctx.pFunc->xStep)(&ctx, n, apVal);
+ (ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */
if( ctx.isError ){
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s));
rc = ctx.isError;
}
+
sqlite3VdbeMemRelease(&ctx.s);
+
break;
}
@@ -4984,7 +5219,7 @@ case OP_AggStep: {
case OP_AggFinal: {
Mem *pMem;
assert( pOp->p1>0 && pOp->p1<=p->nMem );
- pMem = &p->aMem[pOp->p1];
+ pMem = &aMem[pOp->p1];
assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
if( rc ){
@@ -4998,6 +5233,143 @@ case OP_AggFinal: {
break;
}
+#ifndef SQLITE_OMIT_WAL
+/* Opcode: Checkpoint P1 P2 P3 * *
+**
+** Checkpoint database P1. This is a no-op if P1 is not currently in
+** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL
+** or RESTART. Write 1 or 0 into mem[P3] if the checkpoint returns
+** SQLITE_BUSY or not, respectively. Write the number of pages in the
+** WAL after the checkpoint into mem[P3+1] and the number of pages
+** in the WAL that have been checkpointed after the checkpoint
+** completes into mem[P3+2]. However on an error, mem[P3+1] and
+** mem[P3+2] are initialized to -1.
+*/
+case OP_Checkpoint: {
+ int i; /* Loop counter */
+ int aRes[3]; /* Results */
+ Mem *pMem; /* Write results here */
+
+ aRes[0] = 0;
+ aRes[1] = aRes[2] = -1;
+ assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
+ || pOp->p2==SQLITE_CHECKPOINT_FULL
+ || pOp->p2==SQLITE_CHECKPOINT_RESTART
+ );
+ rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]);
+ if( rc==SQLITE_BUSY ){
+ rc = SQLITE_OK;
+ aRes[0] = 1;
+ }
+ for(i=0, pMem = &aMem[pOp->p3]; i<3; i++, pMem++){
+ sqlite3VdbeMemSetInt64(pMem, (i64)aRes[i]);
+ }
+ break;
+};
+#endif
+
+#ifndef SQLITE_OMIT_PRAGMA
+/* Opcode: JournalMode P1 P2 P3 * P5
+**
+** 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
+** modes (delete, truncate, persist, off and memory), this is a simple
+** operation. No IO is required.
+**
+** If changing into or out of WAL mode the procedure is more complicated.
+**
+** Write a string containing the final journal-mode to register P2.
+*/
+case OP_JournalMode: { /* out2-prerelease */
+ Btree *pBt; /* Btree to change journal mode of */
+ Pager *pPager; /* Pager associated with pBt */
+ int eNew; /* New journal mode */
+ int eOld; /* The old journal mode */
+ const char *zFilename; /* Name of database file for pPager */
+
+ eNew = pOp->p3;
+ assert( eNew==PAGER_JOURNALMODE_DELETE
+ || eNew==PAGER_JOURNALMODE_TRUNCATE
+ || eNew==PAGER_JOURNALMODE_PERSIST
+ || eNew==PAGER_JOURNALMODE_OFF
+ || eNew==PAGER_JOURNALMODE_MEMORY
+ || eNew==PAGER_JOURNALMODE_WAL
+ || eNew==PAGER_JOURNALMODE_QUERY
+ );
+ assert( pOp->p1>=0 && pOp->p1<db->nDb );
+
+ pBt = db->aDb[pOp->p1].pBt;
+ pPager = sqlite3BtreePager(pBt);
+ eOld = sqlite3PagerGetJournalMode(pPager);
+ if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld;
+ if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;
+
+#ifndef SQLITE_OMIT_WAL
+ zFilename = sqlite3PagerFilename(pPager);
+
+ /* Do not allow a transition to journal_mode=WAL for a database
+ ** in temporary storage or if the VFS does not support shared memory
+ */
+ if( eNew==PAGER_JOURNALMODE_WAL
+ && (zFilename[0]==0 /* Temp file */
+ || !sqlite3PagerWalSupported(pPager)) /* No shared-memory support */
+ ){
+ eNew = eOld;
+ }
+
+ if( (eNew!=eOld)
+ && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL)
+ ){
+ if( !db->autoCommit || db->activeVdbeCnt>1 ){
+ rc = SQLITE_ERROR;
+ sqlite3SetString(&p->zErrMsg, db,
+ "cannot change %s wal mode from within a transaction",
+ (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
+ );
+ break;
+ }else{
+
+ if( eOld==PAGER_JOURNALMODE_WAL ){
+ /* If leaving WAL mode, close the log file. If successful, the call
+ ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
+ ** file. An EXCLUSIVE lock may still be held on the database file
+ ** after a successful return.
+ */
+ rc = sqlite3PagerCloseWal(pPager);
+ if( rc==SQLITE_OK ){
+ sqlite3PagerSetJournalMode(pPager, eNew);
+ }
+ }else if( eOld==PAGER_JOURNALMODE_MEMORY ){
+ /* Cannot transition directly from MEMORY to WAL. Use mode OFF
+ ** as an intermediate */
+ sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF);
+ }
+
+ /* Open a transaction on the database file. Regardless of the journal
+ ** mode, this transaction always uses a rollback journal.
+ */
+ assert( sqlite3BtreeIsInTrans(pBt)==0 );
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
+ }
+ }
+ }
+#endif /* ifndef SQLITE_OMIT_WAL */
+
+ if( rc ){
+ eNew = eOld;
+ }
+ eNew = sqlite3PagerSetJournalMode(pPager, eNew);
+
+ pOut = &aMem[pOp->p2];
+ pOut->flags = MEM_Str|MEM_Static|MEM_Term;
+ pOut->z = (char *)sqlite3JournalModename(eNew);
+ pOut->n = sqlite3Strlen30(pOut->z);
+ pOut->enc = SQLITE_UTF8;
+ sqlite3VdbeChangeEncoding(pOut, encoding);
+ break;
+};
+#endif /* SQLITE_OMIT_PRAGMA */
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/* Opcode: Vacuum * * * * *
@@ -5007,9 +5379,7 @@ case OP_AggFinal: {
** a transaction.
*/
case OP_Vacuum: {
- if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = sqlite3RunVacuum(&p->zErrMsg, db);
- if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
break;
}
#endif
@@ -5025,7 +5395,7 @@ case OP_IncrVacuum: { /* jump */
Btree *pBt;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( (p->btreeMask & (1<<pOp->p1))!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
pBt = db->aDb[pOp->p1].pBt;
rc = sqlite3BtreeIncrVacuum(pBt);
if( rc==SQLITE_DONE ){
@@ -5074,7 +5444,7 @@ case OP_TableLock: {
if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
int p1 = pOp->p1;
assert( p1>=0 && p1<db->nDb );
- assert( (p->btreeMask & (1<<p1))!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<p1))!=0 );
assert( isWriteLock==0 || isWriteLock==1 );
rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
if( (rc&0xFF)==SQLITE_LOCKED ){
@@ -5100,11 +5470,7 @@ case OP_VBegin: {
VTable *pVTab;
pVTab = pOp->p4.pVtab;
rc = sqlite3VtabBegin(db, pVTab);
- if( pVTab ){
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = pVTab->pVtab->zErrMsg;
- pVTab->pVtab->zErrMsg = 0;
- }
+ if( pVTab ) importVtabErrMsg(p, pVTab->pVtab);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -5153,12 +5519,8 @@ case OP_VOpen: {
pVtab = pOp->p4.pVtab->pVtab;
pModule = (sqlite3_module *)pVtab->pModule;
assert(pVtab && pModule);
- if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xOpen(pVtab, &pVtabCursor);
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = pVtab->zErrMsg;
- pVtab->zErrMsg = 0;
- if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ importVtabErrMsg(p, pVtab);
if( SQLITE_OK==rc ){
/* Initialize sqlite3_vtab_cursor base class */
pVtabCursor->pVtab = pVtab;
@@ -5209,9 +5571,10 @@ case OP_VFilter: { /* jump */
int i;
Mem **apArg;
- pQuery = &p->aMem[pOp->p3];
+ pQuery = &aMem[pOp->p3];
pArgc = &pQuery[1];
pCur = p->apCsr[pOp->p1];
+ assert( memIsValid(pQuery) );
REGISTER_TRACE(pOp->p3, pQuery);
assert( pCur->pVtabCursor );
pVtabCursor = pCur->pVtabCursor;
@@ -5229,20 +5592,16 @@ case OP_VFilter: { /* jump */
apArg = p->apArg;
for(i = 0; i<nArg; i++){
apArg[i] = &pArgc[i+1];
- storeTypeInfo(apArg[i], 0);
+ sqlite3VdbeMemStoreType(apArg[i]);
}
- if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
p->inVtabMethod = 1;
rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
p->inVtabMethod = 0;
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = pVtab->zErrMsg;
- pVtab->zErrMsg = 0;
+ importVtabErrMsg(p, pVtab);
if( rc==SQLITE_OK ){
res = pModule->xEof(pVtabCursor);
}
- if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( res ){
pc = pOp->p2 - 1;
@@ -5270,7 +5629,8 @@ case OP_VColumn: {
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- pDest = &p->aMem[pOp->p3];
+ pDest = &aMem[pOp->p3];
+ memAboutToChange(p, pDest);
if( pCur->nullRow ){
sqlite3VdbeMemSetNull(pDest);
break;
@@ -5288,11 +5648,8 @@ case OP_VColumn: {
sqlite3VdbeMemMove(&sContext.s, pDest);
MemSetTypeFlag(&sContext.s, MEM_Null);
- if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = pVtab->zErrMsg;
- pVtab->zErrMsg = 0;
+ importVtabErrMsg(p, pVtab);
if( sContext.isError ){
rc = sContext.isError;
}
@@ -5302,13 +5659,10 @@ case OP_VColumn: {
** dynamic allocation in sContext.s (a Mem struct) is released.
*/
sqlite3VdbeChangeEncoding(&sContext.s, encoding);
- REGISTER_TRACE(pOp->p3, pDest);
sqlite3VdbeMemMove(pDest, &sContext.s);
+ REGISTER_TRACE(pOp->p3, pDest);
UPDATE_MAX_BLOBSIZE(pDest);
- if( sqlite3SafetyOn(db) ){
- goto abort_due_to_misuse;
- }
if( sqlite3VdbeMemTooBig(pDest) ){
goto too_big;
}
@@ -5345,17 +5699,13 @@ case OP_VNext: { /* jump */
** data is available) and the error code returned when xColumn or
** some other method is next invoked on the save virtual table cursor.
*/
- if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
p->inVtabMethod = 1;
rc = pModule->xNext(pCur->pVtabCursor);
p->inVtabMethod = 0;
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = pVtab->zErrMsg;
- pVtab->zErrMsg = 0;
+ importVtabErrMsg(p, pVtab);
if( rc==SQLITE_OK ){
res = pModule->xEof(pCur->pVtabCursor);
}
- if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( !res ){
/* If there is data, jump to P2 */
@@ -5377,16 +5727,14 @@ case OP_VRename: {
Mem *pName;
pVtab = pOp->p4.pVtab->pVtab;
- pName = &p->aMem[pOp->p1];
+ pName = &aMem[pOp->p1];
assert( pVtab->pModule->xRename );
+ assert( memIsValid(pName) );
REGISTER_TRACE(pOp->p1, pName);
assert( pName->flags & MEM_Str );
- if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pVtab->pModule->xRename(pVtab, pName->z);
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = pVtab->zErrMsg;
- pVtab->zErrMsg = 0;
- if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ importVtabErrMsg(p, pVtab);
+ p->expired = 0;
break;
}
@@ -5431,18 +5779,16 @@ case OP_VUpdate: {
assert( pOp->p4type==P4_VTAB );
if( ALWAYS(pModule->xUpdate) ){
apArg = p->apArg;
- pX = &p->aMem[pOp->p3];
+ pX = &aMem[pOp->p3];
for(i=0; i<nArg; i++){
- storeTypeInfo(pX, 0);
+ assert( memIsValid(pX) );
+ memAboutToChange(p, pX);
+ sqlite3VdbeMemStoreType(pX);
apArg[i] = pX;
pX++;
}
- if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = pVtab->zErrMsg;
- pVtab->zErrMsg = 0;
- if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ importVtabErrMsg(p, pVtab);
if( rc==SQLITE_OK && pOp->p1 ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
db->lastRowid = rowid;
@@ -5459,24 +5805,37 @@ case OP_VUpdate: {
** Write the current number of pages in database P1 to memory cell P2.
*/
case OP_Pagecount: { /* out2-prerelease */
- int p1;
- int nPage;
- Pager *pPager;
-
- p1 = pOp->p1;
- pPager = sqlite3BtreePager(db->aDb[p1].pBt);
- rc = sqlite3PagerPagecount(pPager, &nPage);
- /* OP_Pagecount is always called from within a read transaction. The
- ** page count has already been successfully read and cached. So the
- ** sqlite3PagerPagecount() call above cannot fail. */
- if( ALWAYS(rc==SQLITE_OK) ){
- pOut->flags = MEM_Int;
- pOut->u.i = nPage;
+ pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt);
+ break;
+}
+#endif
+
+
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+/* Opcode: MaxPgcnt P1 P2 P3 * *
+**
+** Try to set the maximum page count for database P1 to the value in P3.
+** Do not let the maximum page count fall below the current page count and
+** do not change the maximum page count value if P3==0.
+**
+** Store the maximum page count after the change in register P2.
+*/
+case OP_MaxPgcnt: { /* out2-prerelease */
+ unsigned int newMax;
+ Btree *pBt;
+
+ pBt = db->aDb[pOp->p1].pBt;
+ newMax = 0;
+ if( pOp->p3 ){
+ newMax = sqlite3BtreeLastPage(pBt);
+ if( newMax < (unsigned)pOp->p3 ) newMax = (unsigned)pOp->p3;
}
+ pOut->u.i = sqlite3BtreeMaxPageCount(pBt, newMax);
break;
}
#endif
+
#ifndef SQLITE_OMIT_TRACE
/* Opcode: Trace * * * P4 *
**
@@ -5489,7 +5848,9 @@ case OP_Trace: {
zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
if( zTrace ){
if( db->xTrace ){
- db->xTrace(db->pTraceArg, zTrace);
+ char *z = sqlite3VdbeExpandSql(p, zTrace);
+ db->xTrace(db->pTraceArg, z);
+ sqlite3DbFree(db, z);
}
#ifdef SQLITE_DEBUG
if( (db->flags & SQLITE_SqlTrace)!=0 ){
@@ -5514,6 +5875,7 @@ case OP_Trace: {
** the same as a no-op. This opcodesnever appears in a real VM program.
*/
default: { /* This is really OP_Noop and OP_Explain */
+ assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
break;
}
@@ -5532,7 +5894,7 @@ default: { /* This is really OP_Noop and OP_Explain */
pOp->cnt++;
#if 0
fprintf(stdout, "%10llu ", elapsed);
- sqlite3VdbePrintOp(stdout, origPc, &p->aOp[origPc]);
+ sqlite3VdbePrintOp(stdout, origPc, &aOp[origPc]);
#endif
}
#endif
@@ -5548,11 +5910,11 @@ default: { /* This is really OP_Noop and OP_Explain */
#ifdef SQLITE_DEBUG
if( p->trace ){
if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc);
- if( opProperty & OPFLG_OUT2_PRERELEASE ){
- registerTrace(p->trace, pOp->p2, pOut);
+ if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){
+ registerTrace(p->trace, pOp->p2, &aMem[pOp->p2]);
}
- if( opProperty & OPFLG_OUT3 ){
- registerTrace(p->trace, pOp->p3, pOut);
+ if( pOp->opflags & OPFLG_OUT3 ){
+ registerTrace(p->trace, pOp->p3, &aMem[pOp->p3]);
}
}
#endif /* SQLITE_DEBUG */
@@ -5565,15 +5927,21 @@ default: { /* This is really OP_Noop and OP_Explain */
vdbe_error_halt:
assert( rc );
p->rc = rc;
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(rc, "statement aborts at %d: [%s] %s",
+ pc, p->zSql, p->zErrMsg);
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
rc = SQLITE_ERROR;
+ if( resetSchemaOnFault>0 ){
+ sqlite3ResetInternalSchema(db, resetSchemaOnFault-1);
+ }
/* This is the only way out of this procedure. We have to
** release the mutexes on btrees that were acquired at the
** top. */
vdbe_return:
- sqlite3BtreeMutexArrayLeave(&p->aMutex);
+ sqlite3VdbeLeave(p);
return rc;
/* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
@@ -5592,12 +5960,6 @@ no_mem:
rc = SQLITE_NOMEM;
goto vdbe_error_halt;
- /* Jump to here for an SQLITE_MISUSE error.
- */
-abort_due_to_misuse:
- rc = SQLITE_MISUSE;
- /* Fall thru into abort_due_to_error */
-
/* Jump to here for any other kind of fatal error. The "rc" variable
** should hold the error number.
*/
« no previous file with comments | « third_party/sqlite/src/src/vdbe.h ('k') | third_party/sqlite/src/src/vdbeInt.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698