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. |
*/ |