summaryrefslogtreecommitdiff
path: root/ext/pdo_sqlite/sqlite/src/vdbe.c
diff options
context:
space:
mode:
authorIlia Alshanetsky <iliaa@php.net>2006-08-14 16:15:29 +0000
committerIlia Alshanetsky <iliaa@php.net>2006-08-14 16:15:29 +0000
commite8f30d450255baa92c1f2abe5d4a2696b6e4ebf0 (patch)
tree1ededffa0df99ad1b61a3e476febad54b6a15991 /ext/pdo_sqlite/sqlite/src/vdbe.c
parent0091c7e1b337de1252824ec33c87b4bed9ca2a5c (diff)
downloadphp-git-e8f30d450255baa92c1f2abe5d4a2696b6e4ebf0.tar.gz
Upgraded bunbled SQLite lib to 3.3.7
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/vdbe.c')
-rw-r--r--ext/pdo_sqlite/sqlite/src/vdbe.c1311
1 files changed, 937 insertions, 374 deletions
diff --git a/ext/pdo_sqlite/sqlite/src/vdbe.c b/ext/pdo_sqlite/sqlite/src/vdbe.c
index a3c3cd11f0..98b9916abe 100644
--- a/ext/pdo_sqlite/sqlite/src/vdbe.c
+++ b/ext/pdo_sqlite/sqlite/src/vdbe.c
@@ -57,17 +57,21 @@
** working correctly. This variable has no function other than to
** help verify the correct operation of the library.
*/
+#ifdef SQLITE_TEST
int sqlite3_search_count = 0;
+#endif
/*
** When this global variable is positive, it gets decremented once before
-** each instruction in the VDBE. When reaches zero, the SQLITE_Interrupt
-** of the db.flags field is set in order to simulate and interrupt.
+** each instruction in the VDBE. When reaches zero, the u1.isInterrupted
+** field of the sqlite3 structure is set in order to simulate and interrupt.
**
** This facility is used for testing purposes only. It does not function
** in an ordinary build.
*/
+#ifdef SQLITE_TEST
int sqlite3_interrupt_count = 0;
+#endif
/*
** The next global variable is incremented each type the OP_Sort opcode
@@ -76,7 +80,9 @@ int sqlite3_interrupt_count = 0;
** has no function other than to help verify the correct operation of the
** library.
*/
+#ifdef SQLITE_TEST
int sqlite3_sort_count = 0;
+#endif
/*
** Release the memory associated with the given stack level. This
@@ -101,6 +107,22 @@ int sqlite3_sort_count = 0;
*/
#define Dynamicify(P,enc) sqlite3VdbeMemDynamicify(P)
+/*
+** The header of a record consists of a sequence variable-length integers.
+** These integers are almost always small and are encoded as a single byte.
+** The following macro takes advantage this fact to provide a fast decode
+** of the integers in a record header. It is faster for the common case
+** where the integer is a single byte. It is a little slower when the
+** integer is two or more bytes. But overall it is faster.
+**
+** The following expressions are equivalent:
+**
+** x = sqlite3GetVarint32( A, &B );
+**
+** x = GetVarint( A, B );
+**
+*/
+#define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B))
/*
** An ephemeral string value (signified by the MEM_Ephem flag) contains
@@ -118,23 +140,6 @@ int sqlite3_sort_count = 0;
&& sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
/*
-** Convert the given stack entity into a integer if it isn't one
-** already.
-**
-** Any prior string or real representation is invalidated.
-** NULLs are converted into 0.
-*/
-#define Integerify(P) sqlite3VdbeMemIntegerify(P)
-
-/*
-** Convert P so that it has type MEM_Real.
-**
-** Any prior string or integer representation is invalidated.
-** NULLs are converted into 0.0.
-*/
-#define Realify(P) sqlite3VdbeMemRealify(P)
-
-/*
** Argument pMem points at a memory cell 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
@@ -177,30 +182,64 @@ static void popStack(Mem **ppTos, int N){
** Allocate cursor number iCur. Return a pointer to it. Return NULL
** if we run out of memory.
*/
-static Cursor *allocateCursor(Vdbe *p, int iCur){
+static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){
Cursor *pCx;
assert( iCur<p->nCursor );
if( p->apCsr[iCur] ){
- sqlite3VdbeFreeCursor(p->apCsr[iCur]);
+ sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
}
p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) );
+ if( pCx ){
+ pCx->iDb = iDb;
+ }
return pCx;
}
/*
-** Apply any conversion required by the supplied column affinity to
-** memory cell pRec. affinity may be one of:
+** Try to convert a value into a numeric representation if we can
+** do so without loss of information. In other words, if the string
+** looks like a number, convert it into a number. If it does not
+** look like a number, leave it alone.
+*/
+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) ){
+ sqlite3VdbeMemRelease(pRec);
+ pRec->i = value;
+ pRec->flags = MEM_Int;
+ }else{
+ sqlite3VdbeMemRealify(pRec);
+ }
+ }
+ }
+}
+
+/*
+** Processing is determine by the affinity parameter:
+**
+** SQLITE_AFF_INTEGER:
+** SQLITE_AFF_REAL:
+** SQLITE_AFF_NUMERIC:
+** Try to convert pRec to an integer representation or a
+** floating-point representation if an integer representation
+** is not possible. Note that the integer representation is
+** always preferred, even if the affinity is REAL, because
+** an integer representation is more space efficient on disk.
**
-** SQLITE_AFF_NUMERIC
-** SQLITE_AFF_TEXT
-** SQLITE_AFF_NONE
-** SQLITE_AFF_INTEGER
+** SQLITE_AFF_TEXT:
+** Convert pRec to a text representation.
**
+** SQLITE_AFF_NONE:
+** No-op. pRec is unchanged.
*/
static void applyAffinity(Mem *pRec, char affinity, u8 enc){
- if( affinity==SQLITE_AFF_NONE ){
- /* do nothing */
- }else if( affinity==SQLITE_AFF_TEXT ){
+ if( affinity==SQLITE_AFF_TEXT ){
/* Only attempt the conversion to TEXT if there is an integer or real
** representation (blob and NULL do not get converted) but no string
** representation.
@@ -209,36 +248,32 @@ static void applyAffinity(Mem *pRec, char affinity, u8 enc){
sqlite3VdbeMemStringify(pRec, enc);
}
pRec->flags &= ~(MEM_Real|MEM_Int);
- }else{
- if( 0==(pRec->flags&(MEM_Real|MEM_Int)) ){
- /* pRec does not have a valid integer or real representation.
- ** Attempt a conversion if pRec has a string representation and
- ** it looks like a number.
- */
- int realnum;
- sqlite3VdbeMemNulTerminate(pRec);
- if( pRec->flags&MEM_Str && sqlite3IsNumber(pRec->z, &realnum, enc) ){
- if( realnum ){
- Realify(pRec);
- }else{
- Integerify(pRec);
- }
- }
- }
-
- if( affinity==SQLITE_AFF_INTEGER ){
- /* For INTEGER affinity, try to convert a real value to an int */
- if( (pRec->flags&MEM_Real) && !(pRec->flags&MEM_Int) ){
- pRec->i = pRec->r;
- if( ((double)pRec->i)==pRec->r ){
- pRec->flags |= MEM_Int;
- }
- }
+ }else if( affinity!=SQLITE_AFF_NONE ){
+ assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
+ || affinity==SQLITE_AFF_NUMERIC );
+ applyNumericAffinity(pRec);
+ if( pRec->flags & MEM_Real ){
+ sqlite3VdbeIntegerAffinity(pRec);
}
}
}
/*
+** Try to convert the type of a function argument or a result column
+** 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);
+ return pMem->type;
+}
+
+/*
** Exported version of applyAffinity(). This one works on sqlite3_value*,
** not the internal Mem* type.
*/
@@ -251,7 +286,7 @@ void sqlite3ValueApplyAffinity(sqlite3_value *pVal, u8 affinity, u8 enc){
** Write a nice string representation of the contents of cell pMem
** into buffer zBuf, length nBuf.
*/
-void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf){
+void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
char *zCsr = zBuf;
int f = pMem->flags;
@@ -347,7 +382,7 @@ __inline__ unsigned long long int hwtime(void){
** flag on jump instructions, we get a (small) speed improvement.
*/
#define CHECK_FOR_INTERRUPT \
- if( db->flags & SQLITE_Interrupt ) goto abort_due_to_interrupt;
+ if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
/*
@@ -388,6 +423,7 @@ int sqlite3VdbeExec(
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
sqlite3 *db = p->db; /* The database */
+ u8 encoding = ENC(db); /* The database encoding */
Mem *pTos; /* Top entry in the operand stack */
#ifdef VDBE_PROFILE
unsigned long long start; /* CPU clock count at start of opcode */
@@ -402,11 +438,15 @@ int sqlite3VdbeExec(
if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
assert( db->magic==SQLITE_MAGIC_BUSY );
+ pTos = p->pTos;
+ if( p->rc==SQLITE_NOMEM ){
+ /* This happens if a malloc() inside a call to sqlite3_column_text() or
+ ** sqlite3_column_text16() failed. */
+ goto no_mem;
+ }
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
p->rc = SQLITE_OK;
assert( p->explain==0 );
- pTos = p->pTos;
- if( sqlite3_malloc_failed ) goto no_mem;
if( p->popStack ){
popStack(&pTos, p->popStack);
p->popStack = 0;
@@ -417,7 +457,7 @@ int sqlite3VdbeExec(
for(pc=p->pc; rc==SQLITE_OK; pc++){
assert( pc>=0 && pc<p->nOp );
assert( pTos<=&p->aStack[pc] );
- if( sqlite3_malloc_failed ) goto no_mem;
+ if( sqlite3MallocFailed() ) goto no_mem;
#ifdef VDBE_PROFILE
origPc = pc;
start = hwtime();
@@ -461,11 +501,14 @@ int sqlite3VdbeExec(
*/
if( db->xProgress ){
if( db->nProgressOps==nProgressOps ){
+ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
if( db->xProgress(db->pProgressArg)!=0 ){
+ sqlite3SafetyOn(db);
rc = SQLITE_ABORT;
continue; /* skip to the next iteration of the for loop */
}
nProgressOps = 0;
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
}
nProgressOps++;
}
@@ -644,24 +687,25 @@ case OP_Real: { /* same as TK_FLOAT, */
pTos->enc = SQLITE_UTF8;
pTos->r = sqlite3VdbeRealValue(pTos);
pTos->flags |= MEM_Real;
- sqlite3VdbeChangeEncoding(pTos, db->enc);
+ sqlite3VdbeChangeEncoding(pTos, encoding);
break;
}
/* Opcode: String8 * * P3
**
-** P3 points to a nul terminated UTF-8 string. This opcode is transformed
+** P3 points to a nul terminated UTF-8 string. This opcode is transformed
** into an OP_String before it is executed for the first time.
*/
case OP_String8: { /* same as TK_STRING */
-#ifndef SQLITE_OMIT_UTF16
+ assert( pOp->p3!=0 );
pOp->opcode = OP_String;
+ pOp->p1 = strlen(pOp->p3);
- assert( pOp->p3!=0 );
- if( db->enc!=SQLITE_UTF8 ){
+#ifndef SQLITE_OMIT_UTF16
+ if( encoding!=SQLITE_UTF8 ){
pTos++;
sqlite3VdbeMemSetStr(pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC);
- if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, db->enc) ) goto no_mem;
+ if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, encoding) ) goto no_mem;
if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pTos) ) goto no_mem;
pTos->flags &= ~(MEM_Dyn);
pTos->flags |= MEM_Static;
@@ -670,34 +714,24 @@ case OP_String8: { /* same as TK_STRING */
}
pOp->p3type = P3_DYNAMIC;
pOp->p3 = pTos->z;
+ pOp->p1 = pTos->n;
break;
}
#endif
/* Otherwise fall through to the next case, OP_String */
}
-/* Opcode: String * * P3
+/* Opcode: String P1 * P3
**
-** The string value P3 is pushed onto the stack. If P3==0 then a
-** NULL is pushed onto the stack. P3 is assumed to be a nul terminated
-** string encoded with the database native encoding.
+** The string value P3 of length P1 (bytes) is pushed onto the stack.
*/
case OP_String: {
pTos++;
assert( pOp->p3!=0 );
pTos->flags = MEM_Str|MEM_Static|MEM_Term;
pTos->z = pOp->p3;
-#ifndef SQLITE_OMIT_UTF16
- if( db->enc==SQLITE_UTF8 ){
- pTos->n = strlen(pTos->z);
- }else{
- pTos->n = sqlite3utf16ByteLen(pTos->z, -1);
- }
-#else
- assert( db->enc==SQLITE_UTF8 );
- pTos->n = strlen(pTos->z);
-#endif
- pTos->enc = db->enc;
+ pTos->n = pOp->p1;
+ pTos->enc = encoding;
break;
}
@@ -868,20 +902,45 @@ case OP_Push: { /* no-push */
/* Opcode: Callback P1 * *
**
-** Pop P1 values off the stack and form them into an array. Then
-** invoke the callback function using the newly formed array as the
-** 3rd parameter.
+** The top P1 values on the stack represent a single result row from
+** a query. This opcode causes the sqlite3_step() call to terminate
+** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
+** structure to provide access to the top P1 values as the result
+** row. When the sqlite3_step() function is run again, the top P1
+** values will be automatically popped from the stack before the next
+** instruction executes.
*/
case OP_Callback: { /* no-push */
- int i;
+ Mem *pMem;
+ Mem *pFirstColumn;
assert( p->nResColumn==pOp->p1 );
- for(i=0; i<pOp->p1; i++){
- Mem *pVal = &pTos[0-i];
- sqlite3VdbeMemNulTerminate(pVal);
- storeTypeInfo(pVal, db->enc);
+ /* Data in the pager might be moved or changed out from under us
+ ** in between the return from this sqlite3_step() call and the
+ ** next call to sqlite3_step(). So deephermeralize everything on
+ ** the stack. Note that ephemeral data is never stored in memory
+ ** cells so we do not have to worry about them.
+ */
+ pFirstColumn = &pTos[0-pOp->p1];
+ for(pMem = p->aStack; pMem<pFirstColumn; pMem++){
+ Deephemeralize(pMem);
}
+ /* Invalidate all ephemeral cursor row caches */
+ p->cacheCtr = (p->cacheCtr + 2)|1;
+
+ /* Make sure the results of the current row are \000 terminated
+ ** and have an assigned type. The results are deephemeralized as
+ ** as side effect.
+ */
+ for(; pMem<=pTos; pMem++ ){
+ sqlite3VdbeMemNulTerminate(pMem);
+ storeTypeInfo(pMem, encoding);
+ }
+
+ /* Set up the statement structure so that it will pop the current
+ ** results from the stack when the statement returns.
+ */
p->resOnStack = 1;
p->nCallback++;
p->popStack = pOp->p1;
@@ -917,7 +976,7 @@ case OP_Concat: { /* same as TK_CONCAT */
nByte = -1;
break;
}
- Stringify(pTerm, db->enc);
+ Stringify(pTerm, encoding);
nByte += pTerm->n;
}
@@ -956,7 +1015,7 @@ case OP_Concat: { /* same as TK_CONCAT */
pTos->n = j;
pTos->flags = MEM_Str|MEM_Dyn|MEM_Term;
pTos->xDel = 0;
- pTos->enc = db->enc;
+ pTos->enc = encoding;
pTos->z = zNew;
}
break;
@@ -1014,8 +1073,10 @@ case OP_Multiply: /* same as TK_STAR, no-push */
case OP_Divide: /* same as TK_SLASH, no-push */
case OP_Remainder: { /* same as TK_REM, no-push */
Mem *pNos = &pTos[-1];
+ int flags;
assert( pNos>=p->aStack );
- if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){
+ flags = pTos->flags | pNos->flags;
+ if( (flags & MEM_Null)!=0 ){
Release(pTos);
pTos--;
Release(pTos);
@@ -1070,6 +1131,9 @@ case OP_Remainder: { /* same as TK_REM, no-push */
Release(pTos);
pTos->r = b;
pTos->flags = MEM_Real;
+ if( (flags & MEM_Real)==0 ){
+ sqlite3VdbeIntegerAffinity(pTos);
+ }
}
break;
@@ -1125,7 +1189,7 @@ case OP_Function: {
pArg = &pTos[1-n];
for(i=0; i<n; i++, pArg++){
apVal[i] = pArg;
- storeTypeInfo(pArg, db->enc);
+ storeTypeInfo(pArg, encoding);
}
assert( pOp->p3type==P3_FUNCDEF || pOp->p3type==P3_VDBEFUNC );
@@ -1150,7 +1214,7 @@ case OP_Function: {
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
(*ctx.pFunc->xFunc)(&ctx, n, apVal);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
- if( sqlite3_malloc_failed ) goto no_mem;
+ if( sqlite3MallocFailed() ) goto no_mem;
popStack(&pTos, n);
/* If any auxilary data functions have been called by this user function,
@@ -1162,22 +1226,17 @@ case OP_Function: {
pOp->p3type = P3_VDBEFUNC;
}
- /* Copy the result of the function to the top of the stack */
- sqlite3VdbeChangeEncoding(&ctx.s, db->enc);
- pTos++;
- pTos->flags = 0;
- sqlite3VdbeMemMove(pTos, &ctx.s);
-
/* If the function returned an error, throw an exception */
if( ctx.isError ){
- if( !(pTos->flags&MEM_Str) ){
- sqlite3SetString(&p->zErrMsg, "user function error", (char*)0);
- }else{
- sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pTos), (char*)0);
- sqlite3VdbeChangeEncoding(pTos, db->enc);
- }
+ sqlite3SetString(&p->zErrMsg, sqlite3_value_text(&ctx.s), (char*)0);
rc = SQLITE_ERROR;
}
+
+ /* Copy the result of the function to the top of the stack */
+ sqlite3VdbeChangeEncoding(&ctx.s, encoding);
+ pTos++;
+ pTos->flags = 0;
+ sqlite3VdbeMemMove(pTos, &ctx.s);
break;
}
@@ -1214,7 +1273,7 @@ case OP_BitOr: /* same as TK_BITOR, no-push */
case OP_ShiftLeft: /* same as TK_LSHIFT, no-push */
case OP_ShiftRight: { /* same as TK_RSHIFT, no-push */
Mem *pNos = &pTos[-1];
- int a, b;
+ i64 a, b;
assert( pNos>=p->aStack );
if( (pTos->flags | pNos->flags) & MEM_Null ){
@@ -1249,7 +1308,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, no-push */
*/
case OP_AddImm: { /* no-push */
assert( pTos>=p->aStack );
- Integerify(pTos);
+ sqlite3VdbeMemIntegerify(pTos);
pTos->i += pOp->p1;
break;
}
@@ -1267,7 +1326,7 @@ case OP_AddImm: { /* no-push */
case OP_ForceInt: { /* no-push */
i64 v;
assert( pTos>=p->aStack );
- applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc);
+ applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding);
if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){
Release(pTos);
pTos--;
@@ -1277,7 +1336,8 @@ case OP_ForceInt: { /* no-push */
if( pTos->flags & MEM_Int ){
v = pTos->i + (pOp->p1!=0);
}else{
- Realify(pTos);
+ /* FIX ME: should this not be assert( pTos->flags & MEM_Real ) ??? */
+ sqlite3VdbeMemRealify(pTos);
v = (int)pTos->r;
if( pTos->r>(double)v ) v++;
if( pOp->p1 && pTos->r==(double)v ) v++;
@@ -1301,7 +1361,7 @@ case OP_ForceInt: { /* no-push */
*/
case OP_MustBeInt: { /* no-push */
assert( pTos>=p->aStack );
- applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc);
+ applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding);
if( (pTos->flags & MEM_Int)==0 ){
if( pOp->p2==0 ){
rc = SQLITE_MISMATCH;
@@ -1317,67 +1377,39 @@ case OP_MustBeInt: { /* no-push */
break;
}
-#ifndef SQLITE_OMIT_CAST
-/* Opcode: ToInt * * *
+/* Opcode: RealAffinity * * *
**
-** Force the value on the top of the stack 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.
-**
-** A NULL value is not changed by this routine. It remains NULL.
-*/
-case OP_ToInt: { /* no-push */
- assert( pTos>=p->aStack );
- if( pTos->flags & MEM_Null ) break;
- assert( MEM_Str==(MEM_Blob>>3) );
- pTos->flags |= (pTos->flags&MEM_Blob)>>3;
- applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc);
- sqlite3VdbeMemIntegerify(pTos);
- break;
-}
-
-/* Opcode: ToNumeric * * *
-**
-** Force the value on the top of the stack to be numeric (either an
-** integer or a floating-point number.
-** If the value is text or blob, try to convert it to an using the
-** equivalent of atoi() or atof() and store 0 if no such conversion
-** is possible.
+** If the top of the stack is an integer, convert it to a real value.
**
-** A NULL value is not changed by this routine. It remains NULL.
+** This opcode is used when extracting information from a column that
+** has REAL affinity. Such column values may still be stored as
+** integers, for space efficiency, but after extraction we want them
+** to have only a real value.
*/
-case OP_ToNumeric: { /* no-push */
+case OP_RealAffinity: { /* no-push */
assert( pTos>=p->aStack );
- if( pTos->flags & MEM_Null ) break;
- assert( MEM_Str==(MEM_Blob>>3) );
- pTos->flags |= (pTos->flags&MEM_Blob)>>3;
- applyAffinity(pTos, SQLITE_AFF_NUMERIC, db->enc);
- if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){
+ if( pTos->flags & MEM_Int ){
sqlite3VdbeMemRealify(pTos);
- }else{
- sqlite3VdbeMemRelease(pTos);
}
- assert( (pTos->flags & MEM_Dyn)==0 );
- pTos->flags &= (MEM_Int|MEM_Real);
break;
}
+#ifndef SQLITE_OMIT_CAST
/* Opcode: ToText * * *
**
** Force the value on the top of the stack to be text.
-** If the value is numeric, convert it to an using the
+** If the value is numeric, convert it to a string using the
** equivalent of printf(). Blob values are unchanged and
** are afterwards simply interpreted as text.
**
** A NULL value is not changed by this routine. It remains NULL.
*/
-case OP_ToText: { /* no-push */
+case OP_ToText: { /* same as TK_TO_TEXT, no-push */
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Null ) break;
assert( MEM_Str==(MEM_Blob>>3) );
pTos->flags |= (pTos->flags&MEM_Blob)>>3;
- applyAffinity(pTos, SQLITE_AFF_TEXT, db->enc);
+ applyAffinity(pTos, SQLITE_AFF_TEXT, encoding);
assert( pTos->flags & MEM_Str );
pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Blob);
break;
@@ -1392,17 +1424,71 @@ case OP_ToText: { /* no-push */
**
** A NULL value is not changed by this routine. It remains NULL.
*/
-case OP_ToBlob: { /* no-push */
+case OP_ToBlob: { /* same as TK_TO_BLOB, no-push */
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Null ) break;
if( (pTos->flags & MEM_Blob)==0 ){
- applyAffinity(pTos, SQLITE_AFF_TEXT, db->enc);
+ applyAffinity(pTos, SQLITE_AFF_TEXT, encoding);
assert( pTos->flags & MEM_Str );
pTos->flags |= MEM_Blob;
}
pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Str);
break;
}
+
+/* Opcode: ToNumeric * * *
+**
+** Force the value on the top of the stack to be numeric (either an
+** integer or a floating-point number.)
+** If the value is text or blob, try to convert it to an using the
+** equivalent of atoi() or atof() and store 0 if no such conversion
+** is possible.
+**
+** A NULL value is not changed by this routine. It remains NULL.
+*/
+case OP_ToNumeric: { /* same as TK_TO_NUMERIC, no-push */
+ assert( pTos>=p->aStack );
+ if( (pTos->flags & MEM_Null)==0 ){
+ sqlite3VdbeMemNumerify(pTos);
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_CAST */
+
+/* Opcode: ToInt * * *
+**
+** Force the value on the top of the stack 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.
+**
+** A NULL value is not changed by this routine. It remains NULL.
+*/
+case OP_ToInt: { /* same as TK_TO_INT, no-push */
+ assert( pTos>=p->aStack );
+ if( (pTos->flags & MEM_Null)==0 ){
+ sqlite3VdbeMemIntegerify(pTos);
+ }
+ break;
+}
+
+#ifndef SQLITE_OMIT_CAST
+/* Opcode: ToReal * * *
+**
+** Force the value on the top of the stack to be a floating point number.
+** If The value is currently an integer, convert it.
+** 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.
+**
+** A NULL value is not changed by this routine. It remains NULL.
+*/
+case OP_ToReal: { /* same as TK_TO_REAL, no-push */
+ assert( pTos>=p->aStack );
+ if( (pTos->flags & MEM_Null)==0 ){
+ sqlite3VdbeMemRealify(pTos);
+ }
+ break;
+}
#endif /* SQLITE_OMIT_CAST */
/* Opcode: Eq P1 P2 P3
@@ -1422,7 +1508,8 @@ case OP_ToBlob: { /* no-push */
** 0x200 is set but is NULL when the 0x200 bit of P1 is clear.
**
** The least significant byte of P1 (mask 0xff) must be an affinity character -
-** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values
+** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
+** to coerce both values
** according to the affinity before the comparison is made. If the byte is
** 0x00, then numeric affinity is used.
**
@@ -1522,8 +1609,8 @@ case OP_Ge: { /* same as TK_GE, no-push */
affinity = pOp->p1 & 0xFF;
if( affinity ){
- applyAffinity(pNos, affinity, db->enc);
- applyAffinity(pTos, affinity, db->enc);
+ applyAffinity(pNos, affinity, encoding);
+ applyAffinity(pTos, affinity, encoding);
}
assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 );
@@ -1571,13 +1658,13 @@ case OP_Or: { /* same as TK_OR, no-push */
if( pTos->flags & MEM_Null ){
v1 = 2;
}else{
- Integerify(pTos);
+ sqlite3VdbeMemIntegerify(pTos);
v1 = pTos->i==0;
}
if( pNos->flags & MEM_Null ){
v2 = 2;
}else{
- Integerify(pNos);
+ sqlite3VdbeMemIntegerify(pNos);
v2 = pNos->i==0;
}
if( pOp->opcode==OP_And ){
@@ -1614,6 +1701,7 @@ case OP_Negative: /* same as TK_UMINUS, no-push */
case OP_AbsValue: {
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Real ){
+ neg_abs_real_case:
Release(pTos);
if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
pTos->r = -pTos->r;
@@ -1628,11 +1716,8 @@ case OP_AbsValue: {
}else if( pTos->flags & MEM_Null ){
/* Do nothing */
}else{
- Realify(pTos);
- if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
- pTos->r = -pTos->r;
- }
- pTos->flags = MEM_Real;
+ sqlite3VdbeMemNumerify(pTos);
+ goto neg_abs_real_case;
}
break;
}
@@ -1646,7 +1731,7 @@ case OP_AbsValue: {
case OP_Not: { /* same as TK_NOT, no-push */
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
- Integerify(pTos);
+ sqlite3VdbeMemIntegerify(pTos);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos->i = !pTos->i;
pTos->flags = MEM_Int;
@@ -1662,7 +1747,7 @@ case OP_Not: { /* same as TK_NOT, no-push */
case OP_BitNot: { /* same as TK_BITNOT, no-push */
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
- Integerify(pTos);
+ sqlite3VdbeMemIntegerify(pTos);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos->i = ~pTos->i;
pTos->flags = MEM_Int;
@@ -1795,13 +1880,6 @@ case OP_SetNumColumns: { /* no-push */
** If the KeyAsData opcode has previously executed on this cursor, then the
** field might be extracted from the key rather than the data.
**
-** If P1 is negative, then the record is stored on the stack rather than in
-** a table. For P1==-1, the top of the stack is used. For P1==-2, the
-** next on the stack is used. And so forth. The value pushed is always
-** just a pointer into the record which is stored further down on the
-** stack. The column value is not copied. The number of columns in the
-** record is stored on the stack just above the record itself.
-**
** If the column contains fewer than P2 fields, then push a NULL. Or
** if P3 is of type P3_MEM, then push the P3 value. The P3 value will
** be default value for a column that has been added using the ALTER TABLE
@@ -1819,10 +1897,7 @@ case OP_Column: {
u32 *aType; /* aType[i] holds the numeric type of the i-th column */
u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
u32 nField; /* number of fields in the record */
- u32 szHdr; /* Number of bytes in the record header */
int len; /* The length of the serialized data for the column */
- int offset = 0; /* Offset into the data */
- int idx; /* Index into the header */
int i; /* Loop counter */
char *zData; /* Part of the record being decoded */
Mem sMem; /* For storing the record being decoded */
@@ -1836,31 +1911,19 @@ case OP_Column: {
** bytes in the record.
**
** zRec is set to be the complete text of the record if it is available.
- ** The complete record text is always available for pseudo-tables and
- ** when we are decoded a record from the stack. If the record is stored
- ** in a cursor, the complete record text might be available in the
- ** pC->aRow cache. Or it might not be. If the data is unavailable,
- ** zRec is set to NULL.
+ ** The complete record text is always available for pseudo-tables
+ ** If the record is stored in a cursor, the complete record text
+ ** might be available in the pC->aRow cache. Or it might not be.
+ ** If the data is unavailable, zRec is set to NULL.
**
** We also compute the number of columns in the record. For cursors,
** the number of columns is stored in the Cursor.nField element. For
** records on the stack, the next entry down on the stack is an integer
** which is the number of records.
*/
- assert( p1<0 || p->apCsr[p1]!=0 );
- if( p1<0 ){
- /* Take the record off of the stack */
- Mem *pRec = &pTos[p1];
- Mem *pCnt = &pRec[-1];
- assert( pRec>=p->aStack );
- assert( pRec->flags & MEM_Blob );
- payloadSize = pRec->n;
- zRec = pRec->z;
- assert( pCnt>=p->aStack );
- assert( pCnt->flags & MEM_Int );
- nField = pCnt->i;
- pCrsr = 0;
- }else if( (pC = p->apCsr[p1])->pCursor!=0 ){
+ pC = p->apCsr[p1];
+ assert( pC!=0 );
+ if( pC->pCursor!=0 ){
/* The record is stored in a B-Tree */
rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
@@ -1868,9 +1931,9 @@ case OP_Column: {
pCrsr = pC->pCursor;
if( pC->nullRow ){
payloadSize = 0;
- }else if( pC->cacheValid ){
+ }else if( pC->cacheStatus==p->cacheCtr ){
payloadSize = pC->payloadSize;
- zRec = pC->aRow;
+ zRec = (char*)pC->aRow;
}else if( pC->isIndex ){
i64 payloadSize64;
sqlite3BtreeKeySize(pCrsr, &payloadSize64);
@@ -1879,16 +1942,14 @@ case OP_Column: {
sqlite3BtreeDataSize(pCrsr, &payloadSize);
}
nField = pC->nField;
-#ifndef SQLITE_OMIT_TRIGGER
}else if( pC->pseudoTable ){
/* The record is the sole entry of a pseudo-table */
payloadSize = pC->nData;
zRec = pC->pData;
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
assert( payloadSize==0 || zRec!=0 );
nField = pC->nField;
pCrsr = 0;
-#endif
}else{
zRec = 0;
payloadSize = 0;
@@ -1898,7 +1959,7 @@ case OP_Column: {
/* If payloadSize is 0, then just push a NULL onto the stack. */
if( payloadSize==0 ){
- pTos->flags = MEM_Null;
+ assert( pTos->flags==MEM_Null );
break;
}
@@ -1907,20 +1968,26 @@ case OP_Column: {
/* Read and parse the table header. Store the results of the parse
** into the record header cache fields of the cursor.
*/
- if( pC && pC->cacheValid ){
+ if( pC && pC->cacheStatus==p->cacheCtr ){
aType = pC->aType;
aOffset = pC->aOffset;
}else{
- int avail; /* Number of bytes of available data */
- if( pC && pC->aType ){
- aType = pC->aType;
- }else{
- aType = sqliteMallocRaw( 2*nField*sizeof(aType) );
+ u8 *zIdx; /* Index into header */
+ u8 *zEndHdr; /* Pointer to first byte after the header */
+ u32 offset; /* Offset into the data */
+ int szHdrSz; /* Size of the header size field at start of record */
+ int avail; /* Number of bytes of available data */
+
+ aType = pC->aType;
+ if( aType==0 ){
+ pC->aType = aType = sqliteMallocRaw( 2*nField*sizeof(aType) );
}
- aOffset = &aType[nField];
if( aType==0 ){
goto no_mem;
}
+ pC->aOffset = aOffset = &aType[nField];
+ pC->payloadSize = payloadSize;
+ pC->cacheStatus = p->cacheCtr;
/* Figure out how many bytes are in the header */
if( zRec ){
@@ -1937,13 +2004,14 @@ case OP_Column: {
** the record.
*/
if( avail>=payloadSize ){
- zRec = pC->aRow = zData;
+ zRec = zData;
+ pC->aRow = (u8*)zData;
}else{
pC->aRow = 0;
}
}
- idx = sqlite3GetVarint32(zData, &szHdr);
-
+ assert( zRec!=0 || avail>=payloadSize || avail>=9 );
+ szHdrSz = GetVarint((u8*)zData, offset);
/* The KeyFetch() or DataFetch() above are fast and will get the entire
** record header in most cases. But they will fail to get the complete
@@ -1951,58 +2019,47 @@ case OP_Column: {
** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to
** acquire the complete header text.
*/
- if( !zRec && avail<szHdr ){
- rc = sqlite3VdbeMemFromBtree(pCrsr, 0, szHdr, pC->isIndex, &sMem);
+ if( !zRec && avail<offset ){
+ rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
zData = sMem.z;
}
+ zEndHdr = (u8 *)&zData[offset];
+ zIdx = (u8 *)&zData[szHdrSz];
/* Scan the header and use it to fill in the aType[] and aOffset[]
** arrays. aType[i] will contain the type integer for the i-th
** column and aOffset[i] will contain the offset from the beginning
** of the record to the start of the data for the i-th column
*/
- offset = szHdr;
- assert( offset>0 );
- i = 0;
- while( idx<szHdr && i<nField && offset<=payloadSize ){
- aOffset[i] = offset;
- idx += sqlite3GetVarint32(&zData[idx], &aType[i]);
- offset += sqlite3VdbeSerialTypeLen(aType[i]);
- i++;
+ for(i=0; i<nField; i++){
+ if( zIdx<zEndHdr ){
+ aOffset[i] = offset;
+ zIdx += GetVarint(zIdx, aType[i]);
+ offset += sqlite3VdbeSerialTypeLen(aType[i]);
+ }else{
+ /* If i is less that nField, then there are less fields in this
+ ** record than SetNumColumns indicated there are columns in the
+ ** table. Set the offset for any extra columns not present in
+ ** the record to 0. This tells code below to push a NULL onto the
+ ** stack instead of deserializing a value from the record.
+ */
+ aOffset[i] = 0;
+ }
}
Release(&sMem);
sMem.flags = MEM_Null;
- /* If i is less that nField, then there are less fields in this
- ** record than SetNumColumns indicated there are columns in the
- ** table. Set the offset for any extra columns not present in
- ** the record to 0. This tells code below to push a NULL onto the
- ** stack instead of deserializing a value from the record.
- */
- while( i<nField ){
- aOffset[i++] = 0;
- }
-
- /* The header should end at the start of data and the data should
- ** end at last byte of the record. If this is not the case then
- ** we are dealing with a malformed record.
+ /* If we have read more header data than was contained in the header,
+ ** or if the end of the last field appears to be past the end of the
+ ** record, then we must be dealing with a corrupt database.
*/
- if( idx!=szHdr || offset!=payloadSize ){
+ if( zIdx>zEndHdr || offset>payloadSize ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
-
- /* Remember all aType and aColumn information if we have a cursor
- ** to remember it in. */
- if( pC ){
- pC->payloadSize = payloadSize;
- pC->aType = aType;
- pC->aOffset = aOffset;
- pC->cacheValid = 1;
- }
}
/* Get the column information. If aOffset[p2] is non-zero, then
@@ -2023,8 +2080,8 @@ case OP_Column: {
}
zData = sMem.z;
}
- sqlite3VdbeSerialGet(zData, aType[p2], pTos);
- pTos->enc = db->enc;
+ sqlite3VdbeSerialGet((u8*)zData, aType[p2], pTos);
+ pTos->enc = encoding;
}else{
if( pOp->p3type==P3_MEM ){
sqlite3VdbeMemShallowCopy(pTos, (Mem *)(pOp->p3), MEM_Static);
@@ -2035,7 +2092,7 @@ case OP_Column: {
/* If we dynamically allocated space to hold the data (in the
** sqlite3VdbeMemFromBtree() call above) then transfer control of that
- ** dynamically allocated space over to the pTos structure rather.
+ ** dynamically allocated space over to the pTos structure.
** This prevents a memory copy.
*/
if( (sMem.flags & MEM_Dyn)!=0 ){
@@ -2052,10 +2109,6 @@ case OP_Column: {
rc = sqlite3VdbeMemMakeWriteable(pTos);
op_column_out:
- /* Release the aType[] memory if we are not dealing with cursor */
- if( !pC || !pC->aType ){
- sqliteFree(aType);
- }
break;
}
@@ -2081,17 +2134,14 @@ op_column_out:
** field of the index key (i.e. the first character of P3 corresponds to the
** lowest element on the stack).
**
-** The mapping from character to affinity is as follows:
-** 'n' = NUMERIC.
-** 'i' = INTEGER.
-** 't' = TEXT.
-** 'o' = NONE.
+** The mapping from character to affinity is given by the SQLITE_AFF_
+** macros defined in sqliteInt.h.
**
** If P3 is NULL then all index fields have the affinity NONE.
**
** See also OP_MakeIdxRec
*/
-/* Opcode: MakeRecordI P1 P2 P3
+/* Opcode: MakeIdxRec P1 P2 P3
**
** This opcode works just OP_MakeRecord except that it reads an extra
** integer from the stack (thus reading a total of abs(P1+1) entries)
@@ -2133,6 +2183,7 @@ case OP_MakeRecord: {
int jumpIfNull; /* Jump here if non-zero and any entries are NULL. */
int addRowid; /* True to append a rowid column at the end */
char *zAffinity; /* The affinity string for the record */
+ int file_format; /* File format to use for encoding */
leaveOnStack = ((pOp->p1<0)?1:0);
nField = pOp->p1 * (leaveOnStack?-1:1);
@@ -2143,18 +2194,19 @@ case OP_MakeRecord: {
pData0 = &pTos[1-nField];
assert( pData0>=p->aStack );
containsNull = 0;
+ file_format = p->minWriteFileFormat;
/* 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<=pTos; pRec++){
if( zAffinity ){
- applyAffinity(pRec, zAffinity[pRec-pData0], db->enc);
+ applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
}
if( pRec->flags&MEM_Null ){
containsNull = 1;
}
- serial_type = sqlite3VdbeSerialType(pRec);
+ serial_type = sqlite3VdbeSerialType(pRec, file_format);
nData += sqlite3VdbeSerialTypeLen(serial_type);
nHdr += sqlite3VarintLen(serial_type);
}
@@ -2166,8 +2218,8 @@ case OP_MakeRecord: {
if( addRowid ){
pRowid = &pTos[0-nField];
assert( pRowid>=p->aStack );
- Integerify(pRowid);
- serial_type = sqlite3VdbeSerialType(pRowid);
+ sqlite3VdbeMemIntegerify(pRowid);
+ serial_type = sqlite3VdbeSerialType(pRowid, 0);
nData += sqlite3VdbeSerialTypeLen(serial_type);
nHdr += sqlite3VarintLen(serial_type);
}
@@ -2186,24 +2238,24 @@ case OP_MakeRecord: {
goto no_mem;
}
}else{
- zNewRecord = zTemp;
+ zNewRecord = (u8*)zTemp;
}
/* Write the record */
zCsr = zNewRecord;
zCsr += sqlite3PutVarint(zCsr, nHdr);
for(pRec=pData0; pRec<=pTos; pRec++){
- serial_type = sqlite3VdbeSerialType(pRec);
+ serial_type = sqlite3VdbeSerialType(pRec, file_format);
zCsr += sqlite3PutVarint(zCsr, serial_type); /* serial type */
}
if( addRowid ){
- zCsr += sqlite3PutVarint(zCsr, sqlite3VdbeSerialType(pRowid));
+ zCsr += sqlite3PutVarint(zCsr, sqlite3VdbeSerialType(pRowid, 0));
}
for(pRec=pData0; pRec<=pTos; pRec++){
- zCsr += sqlite3VdbeSerialPut(zCsr, pRec); /* serial data */
+ zCsr += sqlite3VdbeSerialPut(zCsr, pRec, file_format); /* serial data */
}
if( addRowid ){
- zCsr += sqlite3VdbeSerialPut(zCsr, pRowid);
+ zCsr += sqlite3VdbeSerialPut(zCsr, pRowid, 0);
}
assert( zCsr==(zNewRecord+nByte) );
@@ -2220,7 +2272,7 @@ case OP_MakeRecord: {
pTos->flags = MEM_Blob | MEM_Short;
}else{
assert( zNewRecord!=(unsigned char *)zTemp );
- pTos->z = zNewRecord;
+ pTos->z = (char*)zNewRecord;
pTos->flags = MEM_Blob | MEM_Dyn;
pTos->xDel = 0;
}
@@ -2248,7 +2300,7 @@ case OP_MakeRecord: {
case OP_Statement: { /* no-push */
int i = pOp->p1;
Btree *pBt;
- if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt) && !(db->autoCommit) ){
+ if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt)!=0 && !(db->autoCommit) ){
assert( sqlite3BtreeIsInTrans(pBt) );
if( !sqlite3BtreeIsInStmt(pBt) ){
rc = sqlite3BtreeBeginStmt(pBt);
@@ -2280,26 +2332,29 @@ case OP_AutoCommit: { /* no-push */
** that the other VMs must complete first.
*/
sqlite3SetString(&p->zErrMsg, "cannot ", rollback?"rollback":"commit",
- " transaction - SQL statements in progress", 0);
+ " transaction - SQL statements in progress", (char*)0);
rc = SQLITE_ERROR;
}else if( i!=db->autoCommit ){
- db->autoCommit = i;
if( pOp->p2 ){
assert( i==1 );
sqlite3RollbackAll(db);
- }else if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
- p->pTos = pTos;
- p->pc = pc;
- db->autoCommit = 1-i;
- p->rc = SQLITE_BUSY;
- return SQLITE_BUSY;
+ db->autoCommit = 1;
+ }else{
+ db->autoCommit = i;
+ if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
+ p->pTos = pTos;
+ p->pc = pc;
+ db->autoCommit = 1-i;
+ p->rc = SQLITE_BUSY;
+ return SQLITE_BUSY;
+ }
}
return SQLITE_DONE;
}else{
sqlite3SetString(&p->zErrMsg,
(!i)?"cannot start a transaction within a transaction":(
(rollback)?"cannot rollback - no transaction is active":
- "cannot commit - no transaction is active"), 0);
+ "cannot commit - no transaction is active"), (char*)0);
rc = SQLITE_ERROR;
}
@@ -2396,16 +2451,24 @@ case OP_SetCookie: { /* no-push */
pDb = &db->aDb[pOp->p1];
assert( pDb->pBt!=0 );
assert( pTos>=p->aStack );
- Integerify(pTos);
+ sqlite3VdbeMemIntegerify(pTos);
/* See note about index shifting on OP_ReadCookie */
rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pTos->i);
if( pOp->p2==0 ){
/* When the schema cookie changes, record the new cookie internally */
- pDb->schema_cookie = pTos->i;
+ pDb->pSchema->schema_cookie = pTos->i;
db->flags |= SQLITE_InternChanges;
+ }else if( pOp->p2==1 ){
+ /* Record changes in the file format */
+ pDb->pSchema->file_format = pTos->i;
}
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
+ if( pOp->p1==1 ){
+ /* Invalidate all prepared statements whenever the TEMP database
+ ** schema is changed. Ticket #1644 */
+ sqlite3ExpirePreparedStatements(db);
+ }
break;
}
@@ -2493,26 +2556,35 @@ case OP_OpenWrite: { /* no-push */
Btree *pX;
int iDb;
Cursor *pCur;
+ Db *pDb;
assert( pTos>=p->aStack );
- Integerify(pTos);
+ sqlite3VdbeMemIntegerify(pTos);
iDb = pTos->i;
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
assert( iDb>=0 && iDb<db->nDb );
- pX = db->aDb[iDb].pBt;
+ pDb = &db->aDb[iDb];
+ pX = pDb->pBt;
assert( pX!=0 );
- wrFlag = pOp->opcode==OP_OpenWrite;
+ if( pOp->opcode==OP_OpenWrite ){
+ wrFlag = 1;
+ if( pDb->pSchema->file_format < p->minWriteFileFormat ){
+ p->minWriteFileFormat = pDb->pSchema->file_format;
+ }
+ }else{
+ wrFlag = 0;
+ }
if( p2<=0 ){
assert( pTos>=p->aStack );
- Integerify(pTos);
+ sqlite3VdbeMemIntegerify(pTos);
p2 = pTos->i;
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
assert( p2>=2 );
}
assert( i>=0 );
- pCur = allocateCursor(p, i);
+ pCur = allocateCursor(p, i, iDb);
if( pCur==0 ) goto no_mem;
pCur->nullRow = 1;
if( pX==0 ) break;
@@ -2524,7 +2596,7 @@ case OP_OpenWrite: { /* no-push */
if( pOp->p3type==P3_KEYINFO ){
pCur->pKeyInfo = (KeyInfo*)pOp->p3;
pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
- pCur->pKeyInfo->enc = p->db->enc;
+ pCur->pKeyInfo->enc = ENC(p->db);
}else{
pCur->pKeyInfo = 0;
pCur->pIncrKey = &pCur->bogusIncrKey;
@@ -2574,9 +2646,9 @@ case OP_OpenWrite: { /* no-push */
break;
}
-/* Opcode: OpenVirtual P1 P2 P3
+/* Opcode: OpenEphemeral P1 P2 P3
**
-** Open a new cursor P1 to a transient or virtual table.
+** 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
** table is deleted automatically when the cursor is closed.
@@ -2585,12 +2657,18 @@ case OP_OpenWrite: { /* no-push */
** The cursor points to a BTree table if P3==0 and to a BTree index
** if P3 is not 0. If P3 is not NULL, it points to a KeyInfo structure
** that defines the format of keys in the index.
+**
+** This opcode was once called OpenTemp. But that created
+** confusion because the term "temp table", might refer either
+** to a TEMP table at the SQL level, or to a table opened by
+** this opcode. Then this opcode was call OpenVirtual. But
+** that created confusion with the whole virtual-table idea.
*/
-case OP_OpenVirtual: { /* no-push */
+case OP_OpenEphemeral: { /* no-push */
int i = pOp->p1;
Cursor *pCx;
assert( i>=0 );
- pCx = allocateCursor(p, i);
+ pCx = allocateCursor(p, i, -1);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
rc = sqlite3BtreeFactory(db, 0, 1, TEMP_PAGES, &pCx->pBt);
@@ -2612,7 +2690,7 @@ case OP_OpenVirtual: { /* no-push */
rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeRecordCompare,
pOp->p3, &pCx->pCursor);
pCx->pKeyInfo = (KeyInfo*)pOp->p3;
- pCx->pKeyInfo->enc = p->db->enc;
+ pCx->pKeyInfo->enc = ENC(p->db);
pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
}
pCx->isTable = 0;
@@ -2627,7 +2705,6 @@ case OP_OpenVirtual: { /* no-push */
break;
}
-#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: OpenPseudo P1 * *
**
** Open a new cursor that points to a fake table that contains a single
@@ -2636,13 +2713,15 @@ case OP_OpenVirtual: { /* no-push */
** closed.
**
** A pseudo-table created by this opcode is useful for holding the
-** NEW or OLD tables in a trigger.
+** NEW or OLD tables in a trigger. Also used to hold the a single
+** row output from the sorter so that the row can be decomposed into
+** individual columns using the OP_Column opcode.
*/
case OP_OpenPseudo: { /* no-push */
int i = pOp->p1;
Cursor *pCx;
assert( i>=0 );
- pCx = allocateCursor(p, i);
+ pCx = allocateCursor(p, i, -1);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->pseudoTable = 1;
@@ -2651,7 +2730,6 @@ case OP_OpenPseudo: { /* no-push */
pCx->isIndex = 0;
break;
}
-#endif
/* Opcode: Close P1 * *
**
@@ -2661,7 +2739,7 @@ case OP_OpenPseudo: { /* no-push */
case OP_Close: { /* no-push */
int i = pOp->p1;
if( i>=0 && i<p->nCursor ){
- sqlite3VdbeFreeCursor(p->apCsr[i]);
+ sqlite3VdbeFreeCursor(p, p->apCsr[i]);
p->apCsr[i] = 0;
}
break;
@@ -2725,7 +2803,7 @@ case OP_MoveGt: { /* no-push */
*pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
if( pC->isTable ){
i64 iKey;
- Integerify(pTos);
+ sqlite3VdbeMemIntegerify(pTos);
iKey = intToKey(pTos->i);
if( pOp->p2==0 && pOp->opcode==OP_MoveGe ){
pC->movetoTarget = iKey;
@@ -2741,7 +2819,8 @@ case OP_MoveGt: { /* no-push */
pC->lastRowid = pTos->i;
pC->rowidIsValid = res==0;
}else{
- Stringify(pTos, db->enc);
+ assert( pTos->flags & MEM_Blob );
+ /* Stringify(pTos, encoding); */
rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
@@ -2749,9 +2828,11 @@ case OP_MoveGt: { /* no-push */
pC->rowidIsValid = 0;
}
pC->deferredMoveto = 0;
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
*pC->pIncrKey = 0;
+#ifdef SQLITE_TEST
sqlite3_search_count++;
+#endif
if( oc==OP_MoveGe || oc==OP_MoveGt ){
if( res<0 ){
rc = sqlite3BtreeNext(pC->pCursor, &res);
@@ -2846,11 +2927,11 @@ case OP_Found: { /* no-push */
if( (pC = p->apCsr[i])->pCursor!=0 ){
int res, rx;
assert( pC->isTable==0 );
- Stringify(pTos, db->enc);
+ Stringify(pTos, encoding);
rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
alreadyExists = rx==SQLITE_OK && res==0;
pC->deferredMoveto = 0;
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
}
if( pOp->opcode==OP_Found ){
if( alreadyExists ) pc = pOp->p2 - 1;
@@ -2868,7 +2949,7 @@ case OP_Found: { /* no-push */
**
** The top of the stack is an integer record number. Call this
** record number R. The next on the stack is an index key created
-** using MakeIdxKey. Call it K. This instruction pops R from the
+** using MakeIdxRec. Call it K. This instruction pops R from the
** stack but it leaves K unchanged.
**
** P1 is an index. So it has no data and its key consists of a
@@ -2895,7 +2976,7 @@ case OP_IsUnique: { /* no-push */
/* Pop the value R off the top of the stack
*/
assert( pNos>=p->aStack );
- Integerify(pTos);
+ sqlite3VdbeMemIntegerify(pTos);
R = pTos->i;
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
@@ -2904,7 +2985,7 @@ case OP_IsUnique: { /* no-push */
assert( pCx!=0 );
pCrsr = pCx->pCursor;
if( pCrsr!=0 ){
- int res, rc;
+ int res;
i64 v; /* The record number on the P1 entry that matches K */
char *zKey; /* The value of K */
int nKey; /* Number of bytes in K */
@@ -2913,20 +2994,22 @@ case OP_IsUnique: { /* no-push */
/* Make sure K is a string and make zKey point to K
*/
- Stringify(pNos, db->enc);
+ Stringify(pNos, encoding);
zKey = pNos->z;
nKey = pNos->n;
- szRowid = sqlite3VdbeIdxRowidLen(nKey, zKey);
+ szRowid = sqlite3VdbeIdxRowidLen((u8*)zKey);
len = nKey-szRowid;
/* Search for an entry in P1 where all but the last four bytes match K.
** If there is no such entry, jump immediately to P2.
*/
assert( pCx->deferredMoveto==0 );
- pCx->cacheValid = 0;
+ pCx->cacheStatus = CACHE_STALE;
rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
if( res<0 ){
rc = sqlite3BtreeNext(pCrsr, &res);
if( res ){
@@ -2934,7 +3017,7 @@ case OP_IsUnique: { /* no-push */
break;
}
}
- rc = sqlite3VdbeIdxKeyCompare(pCx, len, zKey, &res);
+ rc = sqlite3VdbeIdxKeyCompare(pCx, len, (u8*)zKey, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res>0 ){
pc = pOp->p2 - 1;
@@ -2997,7 +3080,7 @@ case OP_NotExists: { /* no-push */
pC->lastRowid = pTos->i;
pC->rowidIsValid = res==0;
pC->nullRow = 0;
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
if( res!=0 ){
pc = pOp->p2 - 1;
pC->rowidIsValid = 0;
@@ -3105,7 +3188,10 @@ case OP_NewRowid: {
if( pC->nextRowidValid ){
v = pC->nextRowid;
}else{
- rx = sqlite3BtreeLast(pC->pCursor, &res);
+ rc = sqlite3BtreeLast(pC->pCursor, &res);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
if( res ){
v = 1;
}else{
@@ -3124,7 +3210,7 @@ case OP_NewRowid: {
Mem *pMem;
assert( pOp->p2>0 && pOp->p2<p->nMem ); /* P2 is a valid memory cell */
pMem = &p->aMem[pOp->p2];
- Integerify(pMem);
+ sqlite3VdbeMemIntegerify(pMem);
assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P2) holds an integer */
if( pMem->i==MAX_ROWID || pC->useRandomRowid ){
rc = SQLITE_FULL;
@@ -3170,7 +3256,7 @@ case OP_NewRowid: {
}
pC->rowidIsValid = 0;
pC->deferredMoveto = 0;
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
}
pTos++;
pTos->i = v;
@@ -3178,7 +3264,7 @@ case OP_NewRowid: {
break;
}
-/* Opcode: Insert P1 P2 *
+/* Opcode: Insert P1 P2 P3
**
** Write an entry into the table of cursor P1. A new entry is
** created if it doesn't already exist or the data for an existing
@@ -3191,6 +3277,10 @@ case OP_NewRowid: {
** then rowid is stored for subsequent return by the
** sqlite3_last_insert_rowid() function (otherwise it's unmodified).
**
+** Parameter P3 may point to a string containing the table-name, or
+** may be NULL. If it is not NULL, then the update-hook
+** (sqlite3.xUpdateCallback) is invoked following a successful insert.
+**
** This instruction only works on tables. The equivalent instruction
** for indices is OP_IdxInsert.
*/
@@ -3210,7 +3300,7 @@ case OP_Insert: { /* no-push */
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
- if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
+ if( pC->nextRowidValid && pNos->i>=pC->nextRowid ){
pC->nextRowidValid = 0;
}
if( pTos->flags & MEM_Null ){
@@ -3219,7 +3309,6 @@ case OP_Insert: { /* no-push */
}else{
assert( pTos->flags & (MEM_Blob|MEM_Str) );
}
-#ifndef SQLITE_OMIT_TRIGGER
if( pC->pseudoTable ){
sqliteFree(pC->pData);
pC->iKey = iKey;
@@ -3236,21 +3325,29 @@ case OP_Insert: { /* no-push */
}
pC->nullRow = 0;
}else{
-#endif
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pTos->z, pTos->n);
-#ifndef SQLITE_OMIT_TRIGGER
}
-#endif
pC->rowidIsValid = 0;
pC->deferredMoveto = 0;
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
+
+ /* Invoke the update-hook if required. */
+ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3 ){
+ const char *zDb = db->aDb[pC->iDb].zName;
+ const char *zTbl = pOp->p3;
+ int op = ((pOp->p2 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
+ assert( pC->isTable );
+ db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey);
+ assert( pC->iDb>=0 );
+ }
}
popStack(&pTos, 2);
+
break;
}
-/* Opcode: Delete P1 P2 *
+/* Opcode: Delete P1 P2 P3
**
** Delete the record at which the P1 cursor is currently pointing.
**
@@ -3271,11 +3368,37 @@ case OP_Delete: { /* no-push */
pC = p->apCsr[i];
assert( pC!=0 );
if( pC->pCursor!=0 ){
+ i64 iKey;
+
+ /* If the update-hook will be invoked, set iKey to the rowid of the
+ ** row being deleted.
+ */
+ if( db->xUpdateCallback && pOp->p3 ){
+ assert( pC->isTable );
+ if( pC->rowidIsValid ){
+ iKey = pC->lastRowid;
+ }else{
+ rc = sqlite3BtreeKeySize(pC->pCursor, &iKey);
+ if( rc ){
+ goto abort_due_to_error;
+ }
+ iKey = keyToInt(iKey);
+ }
+ }
+
rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
rc = sqlite3BtreeDelete(pC->pCursor);
pC->nextRowidValid = 0;
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
+
+ /* Invoke the update-hook if required. */
+ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3 ){
+ const char *zDb = db->aDb[pC->iDb].zName;
+ const char *zTbl = pOp->p3;
+ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey);
+ assert( pC->iDb>=0 );
+ }
}
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
break;
@@ -3360,12 +3483,10 @@ case OP_RowData: {
}else{
sqlite3BtreeData(pCrsr, 0, n, pTos->z);
}
-#ifndef SQLITE_OMIT_TRIGGER
}else if( pC->pseudoTable ){
pTos->n = pC->nData;
pTos->z = pC->pData;
pTos->flags = MEM_Blob|MEM_Ephem;
-#endif
}else{
pTos->flags = MEM_Null;
}
@@ -3445,7 +3566,7 @@ case OP_Last: { /* no-push */
rc = sqlite3BtreeLast(pCrsr, &res);
pC->nullRow = res;
pC->deferredMoveto = 0;
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
@@ -3469,8 +3590,10 @@ case OP_Last: { /* no-push */
** correctly optimizing out sorts.
*/
case OP_Sort: { /* no-push */
+#ifdef SQLITE_TEST
sqlite3_sort_count++;
sqlite3_search_count--;
+#endif
/* Fall through into OP_Rewind */
}
/* Opcode: Rewind P1 P2 *
@@ -3494,7 +3617,7 @@ case OP_Rewind: { /* no-push */
rc = sqlite3BtreeFirst(pCrsr, &res);
pC->atFirst = res==0;
pC->deferredMoveto = 0;
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
}else{
res = 1;
}
@@ -3539,11 +3662,13 @@ case OP_Next: { /* no-push */
rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
sqlite3BtreePrevious(pCrsr, &res);
pC->nullRow = res;
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
}
if( res==0 ){
pc = pOp->p2 - 1;
+#ifdef SQLITE_TEST
sqlite3_search_count++;
+#endif
}
}else{
pC->nullRow = 1;
@@ -3554,9 +3679,9 @@ case OP_Next: { /* no-push */
/* Opcode: IdxInsert P1 * *
**
-** The top of the stack holds a SQL index key made using the
-** MakeIdxKey instruction. This opcode writes that key into the
-** index P1. Data for the entry is nil.
+** The top of the stack holds a SQL index key made using either the
+** MakeIdxRec or MakeRecord instructions. This opcode writes that key
+** into the index P1. Data for the entry is nil.
**
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
@@ -3576,7 +3701,7 @@ case OP_IdxInsert: { /* no-push */
assert( pC->isTable==0 );
rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0);
assert( pC->deferredMoveto==0 );
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
}
Release(pTos);
pTos--;
@@ -3585,7 +3710,8 @@ case OP_IdxInsert: { /* no-push */
/* Opcode: IdxDelete P1 * *
**
-** The top of the stack is an index key built using the MakeIdxKey opcode.
+** The top of the stack is an index key built using the either the
+** MakeIdxRec or MakeRecord opcodes.
** This opcode removes that entry from the index.
*/
case OP_IdxDelete: { /* no-push */
@@ -3597,13 +3723,13 @@ case OP_IdxDelete: { /* no-push */
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
- int rx, res;
- rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
- if( rx==SQLITE_OK && res==0 ){
+ int res;
+ rc = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
+ if( rc==SQLITE_OK && res==0 ){
rc = sqlite3BtreeDelete(pCrsr);
}
assert( pC->deferredMoveto==0 );
- pC->cacheValid = 0;
+ pC->cacheStatus = CACHE_STALE;
}
Release(pTos);
pTos--;
@@ -3616,7 +3742,7 @@ case OP_IdxDelete: { /* no-push */
** the end of the index key pointed to by cursor P1. This integer should be
** the rowid of the table entry to which this index entry points.
**
-** See also: Rowid, MakeIdxKey.
+** See also: Rowid, MakeIdxRec.
*/
case OP_IdxRowid: {
int i = pOp->p1;
@@ -3700,14 +3826,14 @@ case OP_IdxGE: { /* no-push */
assert( p->apCsr[i]!=0 );
assert( pTos>=p->aStack );
if( (pC = p->apCsr[i])->pCursor!=0 ){
- int res, rc;
+ int res;
assert( pTos->flags & MEM_Blob ); /* Created using OP_Make*Key */
- Stringify(pTos, db->enc);
+ Stringify(pTos, encoding);
assert( pC->deferredMoveto==0 );
*pC->pIncrKey = pOp->p3!=0;
assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT );
- rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, pTos->z, &res);
+ rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, (u8*)pTos->z, &res);
*pC->pIncrKey = 0;
if( rc!=SQLITE_OK ){
break;
@@ -3729,7 +3855,7 @@ case OP_IdxGE: { /* no-push */
/* Opcode: IdxIsNull P1 P2 *
**
** The top of the stack contains an index entry such as might be generated
-** by the MakeIdxKey opcode. This routine looks at the first P1 fields of
+** by the MakeIdxRec opcode. This routine looks at the first P1 fields of
** that key. If any of the first P1 fields are NULL, then a jump is made
** to address P2. Otherwise we fall straight through.
**
@@ -3745,9 +3871,9 @@ case OP_IdxIsNull: { /* no-push */
assert( pTos->flags & MEM_Blob );
z = pTos->z;
n = pTos->n;
- k = sqlite3GetVarint32(z, &serial_type);
+ k = sqlite3GetVarint32((u8*)z, &serial_type);
for(; k<n && i>0; i--){
- k += sqlite3GetVarint32(&z[k], &serial_type);
+ k += sqlite3GetVarint32((u8*)&z[k], &serial_type);
if( serial_type==0 ){ /* Serial type 0 is a NULL */
pc = pOp->p2-1;
break;
@@ -3780,19 +3906,31 @@ case OP_IdxIsNull: { /* no-push */
*/
case OP_Destroy: {
int iMoved;
- if( db->activeVdbeCnt>1 ){
+ Vdbe *pVdbe;
+ int iCnt;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ iCnt = 0;
+ for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
+ if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 ){
+ iCnt++;
+ }
+ }
+#else
+ iCnt = db->activeVdbeCnt;
+#endif
+ if( iCnt>1 ){
rc = SQLITE_LOCKED;
}else{
- assert( db->activeVdbeCnt==1 );
+ assert( iCnt==1 );
rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved);
pTos++;
pTos->flags = MEM_Int;
pTos->i = iMoved;
- #ifndef SQLITE_OMIT_AUTOVACUUM
+#ifndef SQLITE_OMIT_AUTOVACUUM
if( rc==SQLITE_OK && iMoved!=0 ){
sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1);
}
- #endif
+#endif
}
break;
}
@@ -3810,6 +3948,41 @@ case OP_Destroy: {
** See also: Destroy
*/
case OP_Clear: { /* no-push */
+
+ /* For consistency with the way other features of SQLite operate
+ ** with a truncate, we will also skip the update callback.
+ */
+#if 0
+ Btree *pBt = db->aDb[pOp->p2].pBt;
+ if( db->xUpdateCallback && pOp->p3 ){
+ const char *zDb = db->aDb[pOp->p2].zName;
+ const char *zTbl = pOp->p3;
+ BtCursor *pCur = 0;
+ int fin = 0;
+
+ rc = sqlite3BtreeCursor(pBt, pOp->p1, 0, 0, 0, &pCur);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ for(
+ rc=sqlite3BtreeFirst(pCur, &fin);
+ rc==SQLITE_OK && !fin;
+ rc=sqlite3BtreeNext(pCur, &fin)
+ ){
+ i64 iKey;
+ rc = sqlite3BtreeKeySize(pCur, &iKey);
+ if( rc ){
+ break;
+ }
+ iKey = keyToInt(iKey);
+ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey);
+ }
+ sqlite3BtreeCloseCursor(pCur);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ }
+#endif
rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
break;
}
@@ -3885,14 +4058,20 @@ case OP_ParseSchema: { /* no-push */
sqlite3SafetyOff(db);
assert( db->init.busy==0 );
db->init.busy = 1;
+ assert( !sqlite3MallocFailed() );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
+ if( rc==SQLITE_ABORT ) rc = initData.rc;
+ sqliteFree(zSql);
db->init.busy = 0;
sqlite3SafetyOn(db);
- sqliteFree(zSql);
+ if( rc==SQLITE_NOMEM ){
+ sqlite3FailedMalloc();
+ goto no_mem;
+ }
break;
}
-#ifndef SQLITE_OMIT_ANALYZE
+#if !defined(SQLITE_OMIT_ANALYZE) && !defined(SQLITE_OMIT_PARSER)
/* Opcode: LoadAnalysis P1 * *
**
** Read the sqlite_stat1 table for database P1 and load the content
@@ -3905,7 +4084,7 @@ case OP_LoadAnalysis: { /* no-push */
sqlite3AnalysisLoad(db, iDb);
break;
}
-#endif /* SQLITE_OMIT_ANALYZE */
+#endif /* !defined(SQLITE_OMIT_ANALYZE) && !defined(SQLITE_OMIT_PARSER) */
/* Opcode: DropTable P1 * P3
**
@@ -3992,7 +4171,7 @@ case OP_IntegrityCk: {
pTos->xDel = 0;
}
pTos->enc = SQLITE_UTF8;
- sqlite3VdbeChangeEncoding(pTos, db->enc);
+ sqlite3VdbeChangeEncoding(pTos, encoding);
sqliteFree(aRoot);
break;
}
@@ -4005,7 +4184,7 @@ case OP_IntegrityCk: {
*/
case OP_FifoWrite: { /* no-push */
assert( pTos>=p->aStack );
- Integerify(pTos);
+ sqlite3VdbeMemIntegerify(pTos);
sqlite3VdbeFifoPush(&p->sFifo, pTos->i);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
@@ -4046,7 +4225,7 @@ case OP_ContextPush: { /* no-push */
/* FIX ME: This should be allocated as part of the vdbe at compile-time */
if( i>=p->contextStackDepth ){
p->contextStackDepth = i+1;
- sqlite3ReallocOrFree((void**)&p->contextStack, sizeof(Context)*(i+1));
+ sqliteReallocOrFree((void**)&p->contextStack, sizeof(Context)*(i+1));
if( p->contextStack==0 ) goto no_mem;
}
pContext = &p->contextStack[i];
@@ -4129,8 +4308,8 @@ case OP_MemMax: { /* no-push */
assert( pTos>=p->aStack );
assert( i>=0 && i<p->nMem );
pMem = &p->aMem[i];
- Integerify(pMem);
- Integerify(pTos);
+ sqlite3VdbeMemIntegerify(pMem);
+ sqlite3VdbeMemIntegerify(pTos);
if( pMem->i<pTos->i){
pMem->i = pTos->i;
}
@@ -4140,30 +4319,27 @@ case OP_MemMax: { /* no-push */
/* Opcode: MemIncr P1 P2 *
**
-** Increment the integer valued memory cell P1 by 1. If P2 is not zero
-** and the result after the increment is exactly 1, then jump
-** to P2.
+** Increment the integer valued memory cell P2 by the value in P1.
**
-** This instruction throws an error if the memory cell is not initially
-** an integer.
+** It is illegal to use this instruction on a memory cell that does
+** not contain an integer. An assertion fault will result if you try.
*/
case OP_MemIncr: { /* no-push */
- int i = pOp->p1;
+ int i = pOp->p2;
Mem *pMem;
assert( i>=0 && i<p->nMem );
pMem = &p->aMem[i];
assert( pMem->flags==MEM_Int );
- pMem->i++;
- if( pOp->p2>0 && pMem->i==1 ){
- pc = pOp->p2 - 1;
- }
+ pMem->i += pOp->p1;
break;
}
/* Opcode: IfMemPos P1 P2 *
**
-** If the value of memory cell P1 is 1 or greater, jump to P2. This
-** opcode assumes that memory cell P1 holds an integer value.
+** If the value of memory cell P1 is 1 or greater, jump to P2.
+**
+** It is illegal to use this instruction on a memory cell that does
+** not contain an integer. An assertion fault will result if you try.
*/
case OP_IfMemPos: { /* no-push */
int i = pOp->p1;
@@ -4177,6 +4353,44 @@ case OP_IfMemPos: { /* no-push */
break;
}
+/* Opcode: IfMemNeg P1 P2 *
+**
+** If the value of memory cell P1 is less than zero, jump to P2.
+**
+** It is illegal to use this instruction on a memory cell that does
+** not contain an integer. An assertion fault will result if you try.
+*/
+case OP_IfMemNeg: { /* no-push */
+ int i = pOp->p1;
+ Mem *pMem;
+ assert( i>=0 && i<p->nMem );
+ pMem = &p->aMem[i];
+ assert( pMem->flags==MEM_Int );
+ if( pMem->i<0 ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+/* Opcode: IfMemZero P1 P2 *
+**
+** If the value of memory cell P1 is exactly 0, jump to P2.
+**
+** It is illegal to use this instruction on a memory cell that does
+** not contain an integer. An assertion fault will result if you try.
+*/
+case OP_IfMemZero: { /* no-push */
+ int i = pOp->p1;
+ Mem *pMem;
+ assert( i>=0 && i<p->nMem );
+ pMem = &p->aMem[i];
+ assert( pMem->flags==MEM_Int );
+ if( pMem->i==0 ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
/* Opcode: MemNull P1 * *
**
** Store a NULL in memory cell P1
@@ -4233,12 +4447,15 @@ case OP_AggStep: { /* no-push */
assert( apVal || n==0 );
for(i=0; i<n; i++, pRec++){
apVal[i] = pRec;
- storeTypeInfo(pRec, db->enc);
+ storeTypeInfo(pRec, encoding);
}
ctx.pFunc = (FuncDef*)pOp->p3;
assert( pOp->p1>=0 && pOp->p1<p->nMem );
ctx.pMem = pMem = &p->aMem[pOp->p1];
pMem->n++;
+ ctx.s.flags = MEM_Null;
+ ctx.s.z = 0;
+ ctx.s.xDel = 0;
ctx.isError = 0;
ctx.pColl = 0;
if( ctx.pFunc->needCollSeq ){
@@ -4250,8 +4467,10 @@ case OP_AggStep: { /* no-push */
(ctx.pFunc->xStep)(&ctx, n, apVal);
popStack(&pTos, n);
if( ctx.isError ){
+ sqlite3SetString(&p->zErrMsg, sqlite3_value_text(&ctx.s), (char*)0);
rc = SQLITE_ERROR;
}
+ sqlite3VdbeMemRelease(&ctx.s);
break;
}
@@ -4272,7 +4491,10 @@ case OP_AggFinal: { /* no-push */
assert( pOp->p1>=0 && pOp->p1<p->nMem );
pMem = &p->aMem[pOp->p1];
assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
- sqlite3VdbeMemFinalize(pMem, (FuncDef*)pOp->p3);
+ rc = sqlite3VdbeMemFinalize(pMem, (FuncDef*)pOp->p3);
+ if( rc==SQLITE_ERROR ){
+ sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pMem), (char*)0);
+ }
break;
}
@@ -4308,6 +4530,344 @@ case OP_Expire: { /* no-push */
break;
}
+#ifndef SQLITE_OMIT_SHARED_CACHE
+/* Opcode: TableLock P1 P2 P3
+**
+** Obtain a lock on a particular table. This instruction is only used when
+** the shared-cache feature is enabled.
+**
+** If P1 is not negative, then it is the index of the database
+** in sqlite3.aDb[] and a read-lock is required. If P1 is negative, a
+** write-lock is required. In this case the index of the database is the
+** absolute value of P1 minus one (iDb = abs(P1) - 1;) and a write-lock is
+** required.
+**
+** P2 contains the root-page of the table to lock.
+**
+** P3 contains a pointer to the name of the table being locked. This is only
+** used to generate an error message if the lock cannot be obtained.
+*/
+case OP_TableLock: { /* no-push */
+ int p1 = pOp->p1;
+ u8 isWriteLock = (p1<0);
+ if( isWriteLock ){
+ p1 = (-1*p1)-1;
+ }
+ rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
+ if( rc==SQLITE_LOCKED ){
+ const char *z = (const char *)pOp->p3;
+ sqlite3SetString(&p->zErrMsg, "database table is locked: ", z, (char*)0);
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_SHARED_CACHE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VBegin * * P3
+**
+** P3 a pointer to an sqlite3_vtab structure. Call the xBegin method
+** for that table.
+*/
+case OP_VBegin: { /* no-push */
+ rc = sqlite3VtabBegin(db, (sqlite3_vtab *)pOp->p3);
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VCreate P1 * P3
+**
+** P3 is the name of a virtual table in database P1. Call the xCreate method
+** for that table.
+*/
+case OP_VCreate: { /* no-push */
+ rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p3, &p->zErrMsg);
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VDestroy P1 * P3
+**
+** P3 is the name of a virtual table in database P1. Call the xDestroy method
+** of that table.
+*/
+case OP_VDestroy: { /* no-push */
+ p->inVtabMethod = 2;
+ rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p3);
+ p->inVtabMethod = 0;
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VOpen P1 * P3
+**
+** P3 is a pointer to a virtual table object, an sqlite3_vtab structure.
+** P1 is a cursor number. This opcode opens a cursor to the virtual
+** table and stores that cursor in P1.
+*/
+case OP_VOpen: { /* no-push */
+ Cursor *pCur = 0;
+ sqlite3_vtab_cursor *pVtabCursor = 0;
+
+ sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3);
+ sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule;
+
+ assert(pVtab && pModule);
+ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ rc = pModule->xOpen(pVtab, &pVtabCursor);
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ if( SQLITE_OK==rc ){
+ /* Initialise sqlite3_vtab_cursor base class */
+ pVtabCursor->pVtab = pVtab;
+
+ /* Initialise vdbe cursor object */
+ pCur = allocateCursor(p, pOp->p1, -1);
+ if( pCur ){
+ pCur->pVtabCursor = pVtabCursor;
+ pCur->pModule = pVtabCursor->pVtab->pModule;
+ }else{
+ pModule->xClose(pVtabCursor);
+ }
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VFilter P1 P2 P3
+**
+** P1 is a cursor opened using VOpen. P2 is an address to jump to if
+** the filtered result set is empty.
+**
+** P3 is either NULL or a string that was generated by the xBestIndex
+** method of the module. The interpretation of the P3 string is left
+** to the module implementation.
+**
+** This opcode invokes the xFilter method on the virtual table specified
+** by P1. The integer query plan parameter to xFilter is the top of the
+** stack. Next down on the stack is the argc parameter. Beneath the
+** next of stack are argc additional parameters which are passed to
+** xFilter as argv. The topmost parameter (i.e. 3rd element popped from
+** the stack) becomes argv[argc-1] when passed to xFilter.
+**
+** The integer query plan parameter, argc, and all argv stack values
+** are popped from the stack before this instruction completes.
+**
+** A jump is made to P2 if the result set after filtering would be
+** empty.
+*/
+case OP_VFilter: { /* no-push */
+ int nArg;
+
+ const sqlite3_module *pModule;
+
+ Cursor *pCur = p->apCsr[pOp->p1];
+ assert( pCur->pVtabCursor );
+ pModule = pCur->pVtabCursor->pVtab->pModule;
+
+ /* Grab the index number and argc parameters off the top of the stack. */
+ assert( (&pTos[-1])>=p->aStack );
+ assert( (pTos[0].flags&MEM_Int)!=0 && pTos[-1].flags==MEM_Int );
+ nArg = pTos[-1].i;
+
+ /* Invoke the xFilter method if one is defined. */
+ if( pModule->xFilter ){
+ int res;
+ int i;
+ Mem **apArg = p->apArg;
+ for(i = 0; i<nArg; i++){
+ apArg[i] = &pTos[i+1-2-nArg];
+ storeTypeInfo(apArg[i], 0);
+ }
+
+ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ p->inVtabMethod = 1;
+ rc = pModule->xFilter(pCur->pVtabCursor, pTos->i, pOp->p3, nArg, apArg);
+ p->inVtabMethod = 0;
+ if( rc==SQLITE_OK ){
+ res = pModule->xEof(pCur->pVtabCursor);
+ }
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+
+ if( res ){
+ pc = pOp->p2 - 1;
+ }
+ }
+
+ /* Pop the index number, argc value and parameters off the stack */
+ popStack(&pTos, 2+nArg);
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VRowid P1 * *
+**
+** Push an integer onto the stack which is the rowid of
+** the virtual-table that the P1 cursor is pointing to.
+*/
+case OP_VRowid: {
+ const sqlite3_module *pModule;
+
+ Cursor *pCur = p->apCsr[pOp->p1];
+ assert( pCur->pVtabCursor );
+ pModule = pCur->pVtabCursor->pVtab->pModule;
+ if( pModule->xRowid==0 ){
+ sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xRowid", 0);
+ rc = SQLITE_ERROR;
+ } else {
+ sqlite_int64 iRow;
+
+ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+
+ pTos++;
+ pTos->flags = MEM_Int;
+ pTos->i = iRow;
+ }
+
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VColumn P1 P2 *
+**
+** Push onto the stack the value of the P2-th column of
+** the row of the virtual-table that the P1 cursor is pointing to.
+*/
+case OP_VColumn: {
+ const sqlite3_module *pModule;
+
+ Cursor *pCur = p->apCsr[pOp->p1];
+ assert( pCur->pVtabCursor );
+ pModule = pCur->pVtabCursor->pVtab->pModule;
+ if( pModule->xColumn==0 ){
+ sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xColumn", 0);
+ rc = SQLITE_ERROR;
+ } else {
+ sqlite3_context sContext;
+ memset(&sContext, 0, sizeof(sContext));
+ sContext.s.flags = MEM_Null;
+ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
+
+ /* Copy the result of the function to the top of the stack. We
+ ** do this regardless of whether or not an error occured to ensure any
+ ** dynamic allocation in sContext.s (a Mem struct) is released.
+ */
+ sqlite3VdbeChangeEncoding(&sContext.s, encoding);
+ pTos++;
+ pTos->flags = 0;
+ sqlite3VdbeMemMove(pTos, &sContext.s);
+
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ }
+
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VNext P1 P2 *
+**
+** Advance virtual table P1 to the next row in its result set and
+** jump to instruction P2. Or, if the virtual table has reached
+** the end of its result set, then fall through to the next instruction.
+*/
+case OP_VNext: { /* no-push */
+ const sqlite3_module *pModule;
+ int res = 0;
+
+ Cursor *pCur = p->apCsr[pOp->p1];
+ assert( pCur->pVtabCursor );
+ pModule = pCur->pVtabCursor->pVtab->pModule;
+ if( pModule->xNext==0 ){
+ sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xNext", 0);
+ rc = SQLITE_ERROR;
+ } else {
+ /* Invoke the xNext() method of the module. There is no way for the
+ ** underlying implementation to return an error if one occurs during
+ ** xNext(). Instead, if an error occurs, true is returned (indicating that
+ ** 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;
+ 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 */
+ pc = pOp->p2 - 1;
+ }
+ }
+
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VUpdate P1 P2 P3
+**
+** P3 is a pointer to a virtual table object, an sqlite3_vtab structure.
+** This opcode invokes the corresponding xUpdate method. P2 values
+** are taken from the stack to pass to the xUpdate invocation. The
+** value on the top of the stack corresponds to the p2th element
+** of the argv array passed to xUpdate.
+**
+** The xUpdate method will do a DELETE or an INSERT or both.
+** The argv[0] element (which corresponds to the P2-th element down
+** on the stack) is the rowid of a row to delete. If argv[0] is
+** NULL then no deletion occurs. The argv[1] element is the rowid
+** of the new row. This can be NULL to have the virtual table
+** select the new rowid for itself. The higher elements in the
+** stack are the values of columns in the new row.
+**
+** If P2==1 then no insert is performed. argv[0] is the rowid of
+** a row to delete.
+**
+** P1 is a boolean flag. If it is set to true and the xUpdate call
+** is successful, then the value returned by sqlite3_last_insert_rowid()
+** is set to the value of the rowid for the row just inserted.
+*/
+case OP_VUpdate: { /* no-push */
+ sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3);
+ sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule;
+ int nArg = pOp->p2;
+ assert( pOp->p3type==P3_VTAB );
+ if( pModule->xUpdate==0 ){
+ sqlite3SetString(&p->zErrMsg, "read-only table", 0);
+ rc = SQLITE_ERROR;
+ }else{
+ int i;
+ sqlite_int64 rowid;
+ Mem **apArg = p->apArg;
+ Mem *pX = &pTos[1-nArg];
+ for(i = 0; i<nArg; i++, pX++){
+ storeTypeInfo(pX, 0);
+ apArg[i] = pX;
+ }
+ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ if( pOp->p1 && rc==SQLITE_OK ){
+ assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
+ db->lastRowid = rowid;
+ }
+ }
+ popStack(&pTos, nArg);
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
/* An other opcode is illegal...
*/
@@ -4345,9 +4905,13 @@ default: {
** the evaluator loop. So we can leave it out when NDEBUG is defined.
*/
#ifndef NDEBUG
- /* Sanity checking on the top element of the stack */
- if( pTos>=p->aStack ){
- sqlite3VdbeMemSanity(pTos, db->enc);
+ /* Sanity checking on the top element of the stack. If the previous
+ ** instruction was VNoChange, then the flags field of the top
+ ** of the stack is set to 0. This is technically invalid for a memory
+ ** cell, so avoid calling MemSanity() in this case.
+ */
+ if( pTos>=p->aStack && pTos->flags ){
+ sqlite3VdbeMemSanity(pTos);
}
assert( pc>=-1 && pc<p->nOp );
#ifdef SQLITE_DEBUG
@@ -4366,7 +4930,7 @@ default: {
fprintf(p->trace, " r:%g", pTos[i].r);
}else{
char zBuf[100];
- sqlite3VdbeMemPrettyPrint(&pTos[i], zBuf, 100);
+ sqlite3VdbeMemPrettyPrint(&pTos[i], zBuf);
fprintf(p->trace, " ");
fprintf(p->trace, "%s", zBuf);
}
@@ -4410,7 +4974,7 @@ abort_due_to_misuse:
*/
abort_due_to_error:
if( p->zErrMsg==0 ){
- if( sqlite3_malloc_failed ) rc = SQLITE_NOMEM;
+ if( sqlite3MallocFailed() ) rc = SQLITE_NOMEM;
sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0);
}
goto vdbe_halt;
@@ -4419,8 +4983,7 @@ abort_due_to_error:
** flag.
*/
abort_due_to_interrupt:
- assert( db->flags & SQLITE_Interrupt );
- db->flags &= ~SQLITE_Interrupt;
+ assert( db->u1.isInterrupted );
if( db->magic!=SQLITE_MAGIC_BUSY ){
rc = SQLITE_MISUSE;
}else{