summaryrefslogtreecommitdiff
path: root/ext/sqlite/libsqlite/src/vdbe.c
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2004-07-10 12:27:51 +0000
committerWez Furlong <wez@php.net>2004-07-10 12:27:51 +0000
commite563b4eafa63ba8beb88defa1e36f037a7a97a60 (patch)
tree2e72dfa1c4b7fe62fde9ab326a67047ba2f4cc9e /ext/sqlite/libsqlite/src/vdbe.c
parentcd732f1a3f5df97407797fe7ebb97830552479ad (diff)
downloadphp-git-e563b4eafa63ba8beb88defa1e36f037a7a97a60.tar.gz
Upgrade bundled library to 2.8.14 + misc fixes
(http://www.sqlite.org/cvstrac/chngview?cn=1742)
Diffstat (limited to 'ext/sqlite/libsqlite/src/vdbe.c')
-rw-r--r--ext/sqlite/libsqlite/src/vdbe.c1961
1 files changed, 1008 insertions, 953 deletions
diff --git a/ext/sqlite/libsqlite/src/vdbe.c b/ext/sqlite/libsqlite/src/vdbe.c
index b0dd210049..09332560df 100644
--- a/ext/sqlite/libsqlite/src/vdbe.c
+++ b/ext/sqlite/libsqlite/src/vdbe.c
@@ -59,6 +59,15 @@
*/
int sqlite_search_count = 0;
+/*
+** 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 an interrupt.
+**
+** This facility is used for testing purposes only. It does not function
+** in an ordinary build.
+*/
+int sqlite_interrupt_count = 0;
/*
** Advance the virtual machine to the next output row.
@@ -110,6 +119,7 @@ int sqlite_step(
}
db = p->db;
if( sqliteSafetyOn(db) ){
+ p->rc = SQLITE_MISUSE;
return SQLITE_MISUSE;
}
if( p->explain ){
@@ -146,6 +156,7 @@ int sqlite_step(
static int AggInsert(Agg *p, char *zKey, int nKey){
AggElem *pElem, *pOld;
int i;
+ Mem *pMem;
pElem = sqliteMalloc( sizeof(AggElem) + nKey +
(p->nMem-1)*sizeof(pElem->aMem[0]) );
if( pElem==0 ) return 1;
@@ -158,8 +169,8 @@ static int AggInsert(Agg *p, char *zKey, int nKey){
sqliteFree(pOld);
return 0;
}
- for(i=0; i<p->nMem; i++){
- pElem->aMem[i].s.flags = STK_Null;
+ for(i=0, pMem=pElem->aMem; i<p->nMem; i++, pMem++){
+ pMem->flags = MEM_Null;
}
p->pCurrent = pElem;
return 0;
@@ -182,20 +193,19 @@ static AggElem *_AggInFocus(Agg *p){
** Convert the given stack entity into a string if it isn't one
** already.
*/
-#define Stringify(P,I) if((aStack[I].flags & STK_Str)==0){hardStringify(P,I);}
-static int hardStringify(Vdbe *p, int i){
- Stack *pStack = &p->aStack[i];
+#define Stringify(P) if(((P)->flags & MEM_Str)==0){hardStringify(P);}
+static int hardStringify(Mem *pStack){
int fg = pStack->flags;
- if( fg & STK_Real ){
- sqlite_snprintf(sizeof(pStack->z),pStack->z,"%.15g",pStack->r);
- }else if( fg & STK_Int ){
- sqlite_snprintf(sizeof(pStack->z),pStack->z,"%d",pStack->i);
+ if( fg & MEM_Real ){
+ sqlite_snprintf(sizeof(pStack->zShort),pStack->zShort,"%.15g",pStack->r);
+ }else if( fg & MEM_Int ){
+ sqlite_snprintf(sizeof(pStack->zShort),pStack->zShort,"%d",pStack->i);
}else{
- pStack->z[0] = 0;
+ pStack->zShort[0] = 0;
}
- p->zStack[i] = pStack->z;
- pStack->n = strlen(pStack->z)+1;
- pStack->flags = STK_Str;
+ pStack->z = pStack->zShort;
+ pStack->n = strlen(pStack->zShort)+1;
+ pStack->flags = MEM_Str | MEM_Short;
return 0;
}
@@ -206,25 +216,24 @@ static int hardStringify(Vdbe *p, int i){
** will fit but this routine always mallocs for space.
** Return non-zero if we run out of memory.
*/
-#define Dynamicify(P,I) ((aStack[I].flags & STK_Dyn)==0 ? hardDynamicify(P,I):0)
-static int hardDynamicify(Vdbe *p, int i){
- Stack *pStack = &p->aStack[i];
+#define Dynamicify(P) (((P)->flags & MEM_Dyn)==0 ? hardDynamicify(P):0)
+static int hardDynamicify(Mem *pStack){
int fg = pStack->flags;
char *z;
- if( (fg & STK_Str)==0 ){
- hardStringify(p, i);
+ if( (fg & MEM_Str)==0 ){
+ hardStringify(pStack);
}
- assert( (fg & STK_Dyn)==0 );
+ assert( (fg & MEM_Dyn)==0 );
z = sqliteMallocRaw( pStack->n );
if( z==0 ) return 1;
- memcpy(z, p->zStack[i], pStack->n);
- p->zStack[i] = z;
- pStack->flags |= STK_Dyn;
+ memcpy(z, pStack->z, pStack->n);
+ pStack->z = z;
+ pStack->flags |= MEM_Dyn;
return 0;
}
/*
-** An ephemeral string value (signified by the STK_Ephem flag) contains
+** An ephemeral string value (signified by the MEM_Ephem flag) contains
** a pointer to a dynamically allocated string where some other entity
** is responsible for deallocating that string. Because the stack entry
** does not control the string, it might be deleted without the stack
@@ -232,32 +241,39 @@ static int hardDynamicify(Vdbe *p, int i){
**
** This routine converts an ephemeral string into a dynamically allocated
** string that the stack entry itself controls. In other words, it
-** converts an STK_Ephem string into an STK_Dyn string.
+** converts an MEM_Ephem string into an MEM_Dyn string.
*/
-#define Deephemeralize(P,I) \
- if( ((P)->aStack[I].flags&STK_Ephem)!=0 && hardDeephem(P,I) ){ goto no_mem;}
-static int hardDeephem(Vdbe *p, int i){
- Stack *pStack = &p->aStack[i];
- char **pzStack = &p->zStack[i];
+#define Deephemeralize(P) \
+ if( ((P)->flags&MEM_Ephem)!=0 && hardDeephem(P) ){ goto no_mem;}
+static int hardDeephem(Mem *pStack){
char *z;
- assert( (pStack->flags & STK_Ephem)!=0 );
+ assert( (pStack->flags & MEM_Ephem)!=0 );
z = sqliteMallocRaw( pStack->n );
if( z==0 ) return 1;
- memcpy(z, *pzStack, pStack->n);
- *pzStack = z;
- pStack->flags &= ~STK_Ephem;
- pStack->flags |= STK_Dyn;
+ memcpy(z, pStack->z, pStack->n);
+ pStack->z = z;
+ pStack->flags &= ~MEM_Ephem;
+ pStack->flags |= MEM_Dyn;
return 0;
}
/*
-** Release the memory associated with the given stack level
+** Release the memory associated with the given stack level. This
+** leaves the Mem.flags field in an inconsistent state.
*/
-#define Release(P,I) if((P)->aStack[I].flags&STK_Dyn){ hardRelease(P,I); }
-static void hardRelease(Vdbe *p, int i){
- sqliteFree(p->zStack[i]);
- p->zStack[i] = 0;
- p->aStack[i].flags &= ~(STK_Str|STK_Dyn|STK_Static|STK_Ephem);
+#define Release(P) if((P)->flags&MEM_Dyn){ sqliteFree((P)->z); }
+
+/*
+** Pop the stack N times.
+*/
+static void popStack(Mem **ppTos, int N){
+ Mem *pTos = *ppTos;
+ while( N>0 ){
+ N--;
+ Release(pTos);
+ pTos--;
+ }
+ *ppTos = pTos;
}
/*
@@ -296,19 +312,18 @@ static int toInt(const char *zNum, int *pNum){
** Any prior string or real representation is invalidated.
** NULLs are converted into 0.
*/
-#define Integerify(P,I) \
- if(((P)->aStack[(I)].flags&STK_Int)==0){ hardIntegerify(P,I); }
-static void hardIntegerify(Vdbe *p, int i){
- if( p->aStack[i].flags & STK_Real ){
- p->aStack[i].i = (int)p->aStack[i].r;
- Release(p, i);
- }else if( p->aStack[i].flags & STK_Str ){
- toInt(p->zStack[i], &p->aStack[i].i);
- Release(p, i);
+#define Integerify(P) if(((P)->flags&MEM_Int)==0){ hardIntegerify(P); }
+static void hardIntegerify(Mem *pStack){
+ if( pStack->flags & MEM_Real ){
+ pStack->i = (int)pStack->r;
+ Release(pStack);
+ }else if( pStack->flags & MEM_Str ){
+ toInt(pStack->z, &pStack->i);
+ Release(pStack);
}else{
- p->aStack[i].i = 0;
+ pStack->i = 0;
}
- p->aStack[i].flags = STK_Int;
+ pStack->flags = MEM_Int;
}
/*
@@ -317,17 +332,16 @@ static void hardIntegerify(Vdbe *p, int i){
** Any prior string or integer representation is retained.
** NULLs are converted into 0.0.
*/
-#define Realify(P,I) \
- if(((P)->aStack[(I)].flags&STK_Real)==0){ hardRealify(P,I); }
-static void hardRealify(Vdbe *p, int i){
- if( p->aStack[i].flags & STK_Str ){
- p->aStack[i].r = sqliteAtoF(p->zStack[i]);
- }else if( p->aStack[i].flags & STK_Int ){
- p->aStack[i].r = p->aStack[i].i;
+#define Realify(P) if(((P)->flags&MEM_Real)==0){ hardRealify(P); }
+static void hardRealify(Mem *pStack){
+ if( pStack->flags & MEM_Str ){
+ pStack->r = sqliteAtoF(pStack->z, 0);
+ }else if( pStack->flags & MEM_Int ){
+ pStack->r = pStack->i;
}else{
- p->aStack[i].r = 0.0;
+ pStack->r = 0.0;
}
- p->aStack[i].flags |= STK_Real;
+ pStack->flags |= MEM_Real;
}
/*
@@ -363,17 +377,6 @@ static Sorter *Merge(Sorter *pLeft, Sorter *pRight){
}
/*
-** Code contained within the VERIFY() macro is not needed for correct
-** execution. It is there only to catch errors. So when we compile
-** with NDEBUG=1, the VERIFY() code is omitted.
-*/
-#ifdef NDEBUG
-# define VERIFY(X)
-#else
-# define VERIFY(X) X
-#endif
-
-/*
** The following routine works like a replacement for the standard
** library routine fgets(). The difference is in how end-of-line (EOL)
** is handled. Standard fgets() uses LF for EOL under unix, CRLF
@@ -486,8 +489,7 @@ int sqliteVdbeExec(
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
sqlite *db = p->db; /* The database */
- char **zStack = p->zStack; /* Text stack */
- Stack *aStack = p->aStack; /* Additional stack information */
+ Mem *pTos; /* Top entry in the operand stack */
char zBuf[100]; /* Space to sprintf() an integer */
#ifdef VDBE_PROFILE
unsigned long long start; /* CPU clock count at start of opcode */
@@ -503,13 +505,15 @@ int sqliteVdbeExec(
p->rc = SQLITE_OK;
assert( p->explain==0 );
if( sqlite_malloc_failed ) goto no_mem;
+ pTos = p->pTos;
if( p->popStack ){
- sqliteVdbePopStack(p, p->popStack);
+ popStack(&pTos, p->popStack);
p->popStack = 0;
}
+ CHECK_FOR_INTERRUPT;
for(pc=p->pc; rc==SQLITE_OK; pc++){
assert( pc>=0 && pc<p->nOp );
- assert( p->tos<=pc );
+ assert( pTos<=&p->aStack[pc] );
#ifdef VDBE_PROFILE
origPc = pc;
start = hwtime();
@@ -524,6 +528,18 @@ int sqliteVdbeExec(
}
#endif
+ /* Check to see if we need to simulate an interrupt. This only happens
+ ** if we have a special test build.
+ */
+#ifdef SQLITE_TEST
+ if( sqlite_interrupt_count>0 ){
+ sqlite_interrupt_count--;
+ if( sqlite_interrupt_count==0 ){
+ sqlite_interrupt(db);
+ }
+ }
+#endif
+
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Call the progress callback if it is configured and the required number
** of VDBE ops have been executed (either since this invocation of
@@ -531,14 +547,16 @@ int sqliteVdbeExec(
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
- if( db->xProgress && (db->nProgressOps==nProgressOps) ){
- if( db->xProgress(db->pProgressArg)!=0 ){
- rc = SQLITE_ABORT;
- continue; /* skip to the next iteration of the for loop */
+ if( db->xProgress ){
+ if( db->nProgressOps==nProgressOps ){
+ if( db->xProgress(db->pProgressArg)!=0 ){
+ rc = SQLITE_ABORT;
+ continue; /* skip to the next iteration of the for loop */
+ }
+ nProgressOps = 0;
}
- nProgressOps = 0;
+ nProgressOps++;
}
- nProgressOps++;
#endif
switch( pOp->opcode ){
@@ -641,6 +659,7 @@ case OP_Return: {
*/
case OP_Halt: {
p->magic = VDBE_MAGIC_HALT;
+ p->pTos = pTos;
if( pOp->p1!=SQLITE_OK ){
p->rc = pOp->p1;
p->errorAction = pOp->p2;
@@ -660,13 +679,13 @@ case OP_Halt: {
** then it is assumed to be a string representation of the same integer.
*/
case OP_Integer: {
- int i = ++p->tos;
- aStack[i].i = pOp->p1;
- aStack[i].flags = STK_Int;
+ pTos++;
+ pTos->i = pOp->p1;
+ pTos->flags = MEM_Int;
if( pOp->p3 ){
- zStack[i] = pOp->p3;
- aStack[i].flags |= STK_Str | STK_Static;
- aStack[i].n = strlen(pOp->p3)+1;
+ pTos->z = pOp->p3;
+ pTos->flags |= MEM_Str | MEM_Static;
+ pTos->n = strlen(pOp->p3)+1;
}
break;
}
@@ -677,17 +696,14 @@ case OP_Integer: {
** NULL is pushed onto the stack.
*/
case OP_String: {
- int i = ++p->tos;
- char *z;
- z = pOp->p3;
+ char *z = pOp->p3;
+ pTos++;
if( z==0 ){
- zStack[i] = 0;
- aStack[i].n = 0;
- aStack[i].flags = STK_Null;
+ pTos->flags = MEM_Null;
}else{
- zStack[i] = z;
- aStack[i].n = strlen(z) + 1;
- aStack[i].flags = STK_Str | STK_Static;
+ pTos->z = z;
+ pTos->n = strlen(z) + 1;
+ pTos->flags = MEM_Str | MEM_Static;
}
break;
}
@@ -702,16 +718,14 @@ case OP_String: {
** sqlite_bind() API.
*/
case OP_Variable: {
- int i = ++p->tos;
int j = pOp->p1 - 1;
+ pTos++;
if( j>=0 && j<p->nVar && p->azVar[j]!=0 ){
- zStack[i] = p->azVar[j];
- aStack[i].n = p->anVar[j];
- aStack[i].flags = STK_Str | STK_Static;
+ pTos->z = p->azVar[j];
+ pTos->n = p->anVar[j];
+ pTos->flags = MEM_Str | MEM_Static;
}else{
- zStack[i] = 0;
- aStack[i].n = 0;
- aStack[i].flags = STK_Null;
+ pTos->flags = MEM_Null;
}
break;
}
@@ -721,8 +735,9 @@ case OP_Variable: {
** P1 elements are popped off of the top of stack and discarded.
*/
case OP_Pop: {
- assert( p->tos+1>=pOp->p1 );
- sqliteVdbePopStack(p, pOp->p1);
+ assert( pOp->p1>=0 );
+ popStack(&pTos, pOp->p1);
+ assert( pTos>=&p->aStack[-1] );
break;
}
@@ -742,26 +757,23 @@ case OP_Pop: {
** Also see the Pull instruction.
*/
case OP_Dup: {
- int i = p->tos - pOp->p1;
- int j = ++p->tos;
- VERIFY( if( i<0 ) goto not_enough_stack; )
- memcpy(&aStack[j], &aStack[i], sizeof(aStack[i])-NBFS);
- if( aStack[j].flags & STK_Str ){
- int isStatic = (aStack[j].flags & STK_Static)!=0;
- if( pOp->p2 || isStatic ){
- zStack[j] = zStack[i];
- aStack[j].flags &= ~STK_Dyn;
- if( !isStatic ) aStack[j].flags |= STK_Ephem;
- }else if( aStack[i].n<=NBFS ){
- memcpy(aStack[j].z, zStack[i], aStack[j].n);
- zStack[j] = aStack[j].z;
- aStack[j].flags &= ~(STK_Static|STK_Dyn|STK_Ephem);
- }else{
- zStack[j] = sqliteMallocRaw( aStack[j].n );
- if( zStack[j]==0 ) goto no_mem;
- memcpy(zStack[j], zStack[i], aStack[j].n);
- aStack[j].flags &= ~(STK_Static|STK_Ephem);
- aStack[j].flags |= STK_Dyn;
+ Mem *pFrom = &pTos[-pOp->p1];
+ assert( pFrom<=pTos && pFrom>=p->aStack );
+ pTos++;
+ memcpy(pTos, pFrom, sizeof(*pFrom)-NBFS);
+ if( pTos->flags & MEM_Str ){
+ if( pOp->p2 && (pTos->flags & (MEM_Dyn|MEM_Ephem)) ){
+ pTos->flags &= ~MEM_Dyn;
+ pTos->flags |= MEM_Ephem;
+ }else if( pTos->flags & MEM_Short ){
+ memcpy(pTos->zShort, pFrom->zShort, pTos->n);
+ pTos->z = pTos->zShort;
+ }else if( (pTos->flags & MEM_Static)==0 ){
+ pTos->z = sqliteMallocRaw(pFrom->n);
+ if( sqlite_malloc_failed ) goto no_mem;
+ memcpy(pTos->z, pFrom->z, pFrom->n);
+ pTos->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short);
+ pTos->flags |= MEM_Dyn;
}
}
break;
@@ -778,32 +790,27 @@ case OP_Dup: {
** See also the Dup instruction.
*/
case OP_Pull: {
- int from = p->tos - pOp->p1;
- int to = p->tos;
+ Mem *pFrom = &pTos[-pOp->p1];
int i;
- Stack ts;
- char *tz;
- VERIFY( if( from<0 ) goto not_enough_stack; )
- Deephemeralize(p, from);
- ts = aStack[from];
- tz = zStack[from];
- Deephemeralize(p, to);
- for(i=from; i<to; i++){
- Deephemeralize(p, i+1);
- aStack[i] = aStack[i+1];
- assert( (aStack[i].flags & STK_Ephem)==0 );
- if( aStack[i].flags & (STK_Dyn|STK_Static) ){
- zStack[i] = zStack[i+1];
- }else{
- zStack[i] = aStack[i].z;
+ Mem ts;
+
+ ts = *pFrom;
+ Deephemeralize(pTos);
+ for(i=0; i<pOp->p1; i++, pFrom++){
+ Deephemeralize(&pFrom[1]);
+ *pFrom = pFrom[1];
+ assert( (pFrom->flags & MEM_Ephem)==0 );
+ if( pFrom->flags & MEM_Short ){
+ assert( pFrom->flags & MEM_Str );
+ assert( pFrom->z==pFrom[1].zShort );
+ pFrom->z = pFrom->zShort;
}
}
- aStack[to] = ts;
- assert( (aStack[to].flags & STK_Ephem)==0 );
- if( aStack[to].flags & (STK_Dyn|STK_Static) ){
- zStack[to] = tz;
- }else{
- zStack[to] = aStack[to].z;
+ *pTos = ts;
+ if( pTos->flags & MEM_Short ){
+ assert( pTos->flags & MEM_Str );
+ assert( pTos->z==pTos[-pOp->p1].zShort );
+ pTos->z = pTos->zShort;
}
break;
}
@@ -815,34 +822,36 @@ case OP_Pull: {
** of the top of the stack. Then pop the top of the stack.
*/
case OP_Push: {
- int from = p->tos;
- int to = p->tos - pOp->p1;
+ Mem *pTo = &pTos[-pOp->p1];
- VERIFY( if( to<0 ) goto not_enough_stack; )
- if( aStack[to].flags & STK_Dyn ){
- sqliteFree(zStack[to]);
+ assert( pTo>=p->aStack );
+ Deephemeralize(pTos);
+ Release(pTo);
+ *pTo = *pTos;
+ if( pTo->flags & MEM_Short ){
+ assert( pTo->z==pTos->zShort );
+ pTo->z = pTo->zShort;
}
- Deephemeralize(p, from);
- aStack[to] = aStack[from];
- if( aStack[to].flags & (STK_Dyn|STK_Static|STK_Ephem) ){
- zStack[to] = zStack[from];
- }else{
- zStack[to] = aStack[to].z;
- }
- aStack[from].flags = 0;
- p->tos--;
+ pTos--;
break;
}
-/* Opcode: ColumnName P1 * P3
+
+/* Opcode: ColumnName P1 P2 P3
**
** P3 becomes the P1-th column name (first is 0). An array of pointers
** to all column names is passed as the 4th parameter to the callback.
+** If P2==1 then this is the last column in the result set and thus the
+** number of columns in the result set will be P1. There must be at least
+** one OP_ColumnName with a P2==1 before invoking OP_Callback and the
+** number of columns specified in OP_Callback must one more than the P1
+** value of the OP_ColumnName that has P2==1.
*/
case OP_ColumnName: {
assert( pOp->p1>=0 && pOp->p1<p->nOp );
p->azColName[pOp->p1] = pOp->p3;
p->nCallback = 0;
+ if( pOp->p2 ) p->nResColumn = pOp->p1+1;
break;
}
@@ -853,63 +862,28 @@ case OP_ColumnName: {
** 3rd parameter.
*/
case OP_Callback: {
- int i = p->tos - pOp->p1 + 1;
- int j;
- VERIFY( if( i<0 ) goto not_enough_stack; )
- for(j=i; j<=p->tos; j++){
- if( aStack[j].flags & STK_Null ){
- zStack[j] = 0;
+ int i;
+ char **azArgv = p->zArgv;
+ Mem *pCol;
+
+ pCol = &pTos[1-pOp->p1];
+ assert( pCol>=p->aStack );
+ for(i=0; i<pOp->p1; i++, pCol++){
+ if( pCol->flags & MEM_Null ){
+ azArgv[i] = 0;
}else{
- Stringify(p, j);
+ Stringify(pCol);
+ azArgv[i] = pCol->z;
}
}
- zStack[p->tos+1] = 0;
- if( p->xCallback==0 ){
- p->azResColumn = &zStack[i];
- p->nResColumn = pOp->p1;
- p->popStack = pOp->p1;
- p->pc = pc + 1;
- return SQLITE_ROW;
- }
- if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
- if( p->xCallback(p->pCbArg, pOp->p1, &zStack[i], p->azColName)!=0 ){
- rc = SQLITE_ABORT;
- }
- if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
+ azArgv[i] = 0;
p->nCallback++;
- sqliteVdbePopStack(p, pOp->p1);
- if( sqlite_malloc_failed ) goto no_mem;
- break;
-}
-
-/* Opcode: NullCallback P1 * *
-**
-** Invoke the callback function once with the 2nd argument (the
-** number of columns) equal to P1 and with the 4th argument (the
-** names of the columns) set according to prior OP_ColumnName
-** instructions. This is all like the regular
-** OP_Callback or OP_SortCallback opcodes. But the 3rd argument
-** which normally contains a pointer to an array of pointers to
-** data is NULL.
-**
-** The callback is only invoked if there have been no prior calls
-** to OP_Callback or OP_SortCallback.
-**
-** This opcode is used to report the number and names of columns
-** in cases where the result set is empty.
-*/
-case OP_NullCallback: {
- if( p->nCallback==0 && p->xCallback!=0 ){
- if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
- if( p->xCallback(p->pCbArg, pOp->p1, 0, p->azColName)!=0 ){
- rc = SQLITE_ABORT;
- }
- if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
- p->nCallback++;
- if( sqlite_malloc_failed ) goto no_mem;
- }
- p->nResColumn = pOp->p1;
- break;
+ p->azResColumn = azArgv;
+ assert( p->nResColumn==pOp->p1 );
+ p->popStack = pOp->p1;
+ p->pc = pc + 1;
+ p->pTos = pTos;
+ return SQLITE_ROW;
}
/* Opcode: Concat P1 P2 P3
@@ -931,48 +905,53 @@ case OP_Concat: {
int i, j;
char *zSep;
int nSep;
+ Mem *pTerm;
nField = pOp->p1;
zSep = pOp->p3;
if( zSep==0 ) zSep = "";
nSep = strlen(zSep);
- VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
+ assert( &pTos[1-nField] >= p->aStack );
nByte = 1 - nSep;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( aStack[i].flags & STK_Null ){
+ pTerm = &pTos[1-nField];
+ for(i=0; i<nField; i++, pTerm++){
+ if( pTerm->flags & MEM_Null ){
nByte = -1;
break;
}else{
- Stringify(p, i);
- nByte += aStack[i].n - 1 + nSep;
+ Stringify(pTerm);
+ nByte += pTerm->n - 1 + nSep;
}
}
if( nByte<0 ){
- if( pOp->p2==0 ) sqliteVdbePopStack(p, nField);
- p->tos++;
- aStack[p->tos].flags = STK_Null;
- zStack[p->tos] = 0;
+ if( pOp->p2==0 ){
+ popStack(&pTos, nField);
+ }
+ pTos++;
+ pTos->flags = MEM_Null;
break;
}
zNew = sqliteMallocRaw( nByte );
if( zNew==0 ) goto no_mem;
j = 0;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & STK_Null)==0 ){
- memcpy(&zNew[j], zStack[i], aStack[i].n-1);
- j += aStack[i].n-1;
- }
- if( nSep>0 && i<p->tos ){
+ pTerm = &pTos[1-nField];
+ for(i=j=0; i<nField; i++, pTerm++){
+ assert( pTerm->flags & MEM_Str );
+ memcpy(&zNew[j], pTerm->z, pTerm->n-1);
+ j += pTerm->n-1;
+ if( nSep>0 && i<nField-1 ){
memcpy(&zNew[j], zSep, nSep);
j += nSep;
}
}
zNew[j] = 0;
- if( pOp->p2==0 ) sqliteVdbePopStack(p, nField);
- p->tos++;
- aStack[p->tos].n = nByte;
- aStack[p->tos].flags = STK_Str|STK_Dyn;
- zStack[p->tos] = zNew;
+ if( pOp->p2==0 ){
+ popStack(&pTos, nField);
+ }
+ pTos++;
+ pTos->n = nByte;
+ pTos->flags = MEM_Str|MEM_Dyn;
+ pTos->z = zNew;
break;
}
@@ -1027,17 +1006,17 @@ case OP_Subtract:
case OP_Multiply:
case OP_Divide:
case OP_Remainder: {
- int tos = p->tos;
- int nos = tos - 1;
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- if( ((aStack[tos].flags | aStack[nos].flags) & STK_Null)!=0 ){
- POPSTACK;
- Release(p, nos);
- aStack[nos].flags = STK_Null;
- }else if( (aStack[tos].flags & aStack[nos].flags & STK_Int)==STK_Int ){
+ Mem *pNos = &pTos[-1];
+ assert( pNos>=p->aStack );
+ if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){
+ Release(pTos);
+ pTos--;
+ Release(pTos);
+ pTos->flags = MEM_Null;
+ }else if( (pTos->flags & pNos->flags & MEM_Int)==MEM_Int ){
int a, b;
- a = aStack[tos].i;
- b = aStack[nos].i;
+ a = pTos->i;
+ b = pNos->i;
switch( pOp->opcode ){
case OP_Add: b += a; break;
case OP_Subtract: b -= a; break;
@@ -1053,16 +1032,17 @@ case OP_Remainder: {
break;
}
}
- POPSTACK;
- Release(p, nos);
- aStack[nos].i = b;
- aStack[nos].flags = STK_Int;
+ Release(pTos);
+ pTos--;
+ Release(pTos);
+ pTos->i = b;
+ pTos->flags = MEM_Int;
}else{
double a, b;
- Realify(p, tos);
- Realify(p, nos);
- a = aStack[tos].r;
- b = aStack[nos].r;
+ Realify(pTos);
+ Realify(pNos);
+ a = pTos->r;
+ b = pNos->r;
switch( pOp->opcode ){
case OP_Add: b += a; break;
case OP_Subtract: b -= a; break;
@@ -1080,17 +1060,19 @@ case OP_Remainder: {
break;
}
}
- POPSTACK;
- Release(p, nos);
- aStack[nos].r = b;
- aStack[nos].flags = STK_Real;
+ Release(pTos);
+ pTos--;
+ Release(pTos);
+ pTos->r = b;
+ pTos->flags = MEM_Real;
}
break;
divide_by_zero:
- sqliteVdbePopStack(p, 2);
- p->tos = nos;
- aStack[nos].flags = STK_Null;
+ Release(pTos);
+ pTos--;
+ Release(pTos);
+ pTos->flags = MEM_Null;
break;
}
@@ -1104,39 +1086,38 @@ divide_by_zero:
*/
case OP_Function: {
int n, i;
+ Mem *pArg;
+ char **azArgv;
sqlite_func ctx;
n = pOp->p1;
- VERIFY( if( n<0 ) goto bad_instruction; )
- VERIFY( if( p->tos+1<n ) goto not_enough_stack; )
- for(i=p->tos-n+1; i<=p->tos; i++){
- if( aStack[i].flags & STK_Null ){
- zStack[i] = 0;
+ pArg = &pTos[1-n];
+ azArgv = p->zArgv;
+ for(i=0; i<n; i++, pArg++){
+ if( pArg->flags & MEM_Null ){
+ azArgv[i] = 0;
}else{
- Stringify(p, i);
+ Stringify(pArg);
+ azArgv[i] = pArg->z;
}
}
ctx.pFunc = (FuncDef*)pOp->p3;
- ctx.s.flags = STK_Null;
- ctx.z = 0;
+ ctx.s.flags = MEM_Null;
+ ctx.s.z = 0;
ctx.isError = 0;
ctx.isStep = 0;
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
- (*ctx.pFunc->xFunc)(&ctx, n, (const char**)&zStack[p->tos-n+1]);
+ (*ctx.pFunc->xFunc)(&ctx, n, (const char**)azArgv);
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
- sqliteVdbePopStack(p, n);
- p->tos++;
- aStack[p->tos] = ctx.s;
- if( ctx.s.flags & STK_Dyn ){
- zStack[p->tos] = ctx.z;
- }else if( ctx.s.flags & STK_Str ){
- zStack[p->tos] = aStack[p->tos].z;
- }else{
- zStack[p->tos] = 0;
+ popStack(&pTos, n);
+ pTos++;
+ *pTos = ctx.s;
+ if( pTos->flags & MEM_Short ){
+ pTos->z = pTos->zShort;
}
if( ctx.isError ){
sqliteSetString(&p->zErrMsg,
- zStack[p->tos] ? zStack[p->tos] : "user function error", (char*)0);
+ (pTos->flags & MEM_Str)!=0 ? pTos->z : "user function error", (char*)0);
rc = SQLITE_ERROR;
}
break;
@@ -1174,20 +1155,20 @@ case OP_BitAnd:
case OP_BitOr:
case OP_ShiftLeft:
case OP_ShiftRight: {
- int tos = p->tos;
- int nos = tos - 1;
+ Mem *pNos = &pTos[-1];
int a, b;
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- if( (aStack[tos].flags | aStack[nos].flags) & STK_Null ){
- POPSTACK;
- Release(p,nos);
- aStack[nos].flags = STK_Null;
+
+ assert( pNos>=p->aStack );
+ if( (pTos->flags | pNos->flags) & MEM_Null ){
+ popStack(&pTos, 2);
+ pTos++;
+ pTos->flags = MEM_Null;
break;
}
- Integerify(p, tos);
- Integerify(p, nos);
- a = aStack[tos].i;
- b = aStack[nos].i;
+ Integerify(pTos);
+ Integerify(pNos);
+ a = pTos->i;
+ b = pNos->i;
switch( pOp->opcode ){
case OP_BitAnd: a &= b; break;
case OP_BitOr: a |= b; break;
@@ -1195,10 +1176,12 @@ case OP_ShiftRight: {
case OP_ShiftRight: a >>= b; break;
default: /* CANT HAPPEN */ break;
}
- POPSTACK;
- Release(p, nos);
- aStack[nos].i = a;
- aStack[nos].flags = STK_Int;
+ assert( (pTos->flags & MEM_Dyn)==0 );
+ assert( (pNos->flags & MEM_Dyn)==0 );
+ pTos--;
+ Release(pTos);
+ pTos->i = a;
+ pTos->flags = MEM_Int;
break;
}
@@ -1210,34 +1193,43 @@ case OP_ShiftRight: {
** To force the top of the stack to be an integer, just add 0.
*/
case OP_AddImm: {
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- Integerify(p, tos);
- aStack[tos].i += pOp->p1;
+ assert( pTos>=p->aStack );
+ Integerify(pTos);
+ pTos->i += pOp->p1;
break;
}
-/* Opcode: IsNumeric P1 P2 *
-**
-** Check the top of the stack to see if it is a numeric value. A numeric
-** value is an integer, a real number, or a string that looks like an
-** integer or a real number. When P1==0, pop the stack and jump to P2
-** if the value is numeric. Otherwise fall through and leave the stack
-** unchanged. The sense of the test is inverted when P1==1.
-*/
-case OP_IsNumeric: {
- int tos = p->tos;
- int r;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- r = (aStack[tos].flags & (STK_Int|STK_Real))!=0
- || (zStack[tos] && sqliteIsNumber(zStack[tos]));
- if( pOp->p1 ){
- r = !r;
- }
- if( r ){
- POPSTACK;
+/* Opcode: ForceInt P1 P2 *
+**
+** Convert the top of the stack into an integer. If the current top of
+** the stack is not numeric (meaning that is is a NULL or a string that
+** does not look like an integer or floating point number) then pop the
+** stack and jump to P2. If the top of the stack is numeric then
+** convert it into the least integer that is greater than or equal to its
+** current value if P1==0, or to the least integer that is strictly
+** greater than its current value if P1==1.
+*/
+case OP_ForceInt: {
+ int v;
+ assert( pTos>=p->aStack );
+ if( (pTos->flags & (MEM_Int|MEM_Real))==0
+ && ((pTos->flags & MEM_Str)==0 || sqliteIsNumber(pTos->z)==0) ){
+ Release(pTos);
+ pTos--;
pc = pOp->p2 - 1;
+ break;
}
+ if( pTos->flags & MEM_Int ){
+ v = pTos->i + (pOp->p1!=0);
+ }else{
+ Realify(pTos);
+ v = (int)pTos->r;
+ if( pTos->r>(double)v ) v++;
+ if( pOp->p1 && pTos->r==(double)v ) v++;
+ }
+ Release(pTos);
+ pTos->i = v;
+ pTos->flags = MEM_Int;
break;
}
@@ -1253,38 +1245,36 @@ case OP_IsNumeric: {
** of the stack is unchanged.
*/
case OP_MustBeInt: {
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( aStack[tos].flags & STK_Int ){
+ assert( pTos>=p->aStack );
+ if( pTos->flags & MEM_Int ){
/* Do nothing */
- }else if( aStack[tos].flags & STK_Real ){
- int i = aStack[tos].r;
+ }else if( pTos->flags & MEM_Real ){
+ int i = (int)pTos->r;
double r = (double)i;
- if( r!=aStack[tos].r ){
+ if( r!=pTos->r ){
goto mismatch;
}
- aStack[tos].i = i;
- }else if( aStack[tos].flags & STK_Str ){
+ pTos->i = i;
+ }else if( pTos->flags & MEM_Str ){
int v;
- if( !toInt(zStack[tos], &v) ){
+ if( !toInt(pTos->z, &v) ){
double r;
- if( !sqliteIsNumber(zStack[tos]) ){
+ if( !sqliteIsNumber(pTos->z) ){
goto mismatch;
}
- Realify(p, tos);
- assert( (aStack[tos].flags & STK_Real)!=0 );
- v = aStack[tos].r;
+ Realify(pTos);
+ v = (int)pTos->r;
r = (double)v;
- if( r!=aStack[tos].r ){
+ if( r!=pTos->r ){
goto mismatch;
}
}
- aStack[tos].i = v;
+ pTos->i = v;
}else{
goto mismatch;
}
- Release(p, tos);
- aStack[tos].flags = STK_Int;
+ Release(pTos);
+ pTos->flags = MEM_Int;
break;
mismatch:
@@ -1292,7 +1282,7 @@ mismatch:
rc = SQLITE_MISMATCH;
goto abort_due_to_error;
}else{
- if( pOp->p1 ) POPSTACK;
+ if( pOp->p1 ) popStack(&pTos, 1);
pc = pOp->p2 - 1;
}
break;
@@ -1415,39 +1405,31 @@ case OP_Lt:
case OP_Le:
case OP_Gt:
case OP_Ge: {
- int tos = p->tos;
- int nos = tos - 1;
+ Mem *pNos = &pTos[-1];
int c, v;
int ft, fn;
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- ft = aStack[tos].flags;
- fn = aStack[nos].flags;
- if( (ft | fn) & STK_Null ){
- POPSTACK;
- POPSTACK;
+ assert( pNos>=p->aStack );
+ ft = pTos->flags;
+ fn = pNos->flags;
+ if( (ft | fn) & MEM_Null ){
+ popStack(&pTos, 2);
if( pOp->p2 ){
if( pOp->p1 ) pc = pOp->p2-1;
}else{
- p->tos++;
- aStack[nos].flags = STK_Null;
+ pTos++;
+ pTos->flags = MEM_Null;
}
break;
- }else if( (ft & fn & STK_Int)==STK_Int ){
- c = aStack[nos].i - aStack[tos].i;
- }else if( (ft & STK_Int)!=0 && (fn & STK_Str)!=0 && toInt(zStack[nos],&v) ){
- Release(p, nos);
- aStack[nos].i = v;
- aStack[nos].flags = STK_Int;
- c = aStack[nos].i - aStack[tos].i;
- }else if( (fn & STK_Int)!=0 && (ft & STK_Str)!=0 && toInt(zStack[tos],&v) ){
- Release(p, tos);
- aStack[tos].i = v;
- aStack[tos].flags = STK_Int;
- c = aStack[nos].i - aStack[tos].i;
+ }else if( (ft & fn & MEM_Int)==MEM_Int ){
+ c = pNos->i - pTos->i;
+ }else if( (ft & MEM_Int)!=0 && (fn & MEM_Str)!=0 && toInt(pNos->z,&v) ){
+ c = v - pTos->i;
+ }else if( (fn & MEM_Int)!=0 && (ft & MEM_Str)!=0 && toInt(pTos->z,&v) ){
+ c = pNos->i - v;
}else{
- Stringify(p, tos);
- Stringify(p, nos);
- c = sqliteCompare(zStack[nos], zStack[tos]);
+ Stringify(pTos);
+ Stringify(pNos);
+ c = sqliteCompare(pNos->z, pTos->z);
}
switch( pOp->opcode ){
case OP_Eq: c = c==0; break;
@@ -1457,14 +1439,13 @@ case OP_Ge: {
case OP_Gt: c = c>0; break;
default: c = c>=0; break;
}
- POPSTACK;
- POPSTACK;
+ popStack(&pTos, 2);
if( pOp->p2 ){
if( c ) pc = pOp->p2-1;
}else{
- p->tos++;
- aStack[nos].flags = STK_Int;
- aStack[nos].i = c;
+ pTos++;
+ pTos->i = c;
+ pTos->flags = MEM_Int;
}
break;
}
@@ -1581,24 +1562,22 @@ case OP_StrLt:
case OP_StrLe:
case OP_StrGt:
case OP_StrGe: {
- int tos = p->tos;
- int nos = tos - 1;
+ Mem *pNos = &pTos[-1];
int c;
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- if( (aStack[nos].flags | aStack[tos].flags) & STK_Null ){
- POPSTACK;
- POPSTACK;
+ assert( pNos>=p->aStack );
+ if( (pNos->flags | pTos->flags) & MEM_Null ){
+ popStack(&pTos, 2);
if( pOp->p2 ){
if( pOp->p1 ) pc = pOp->p2-1;
}else{
- p->tos++;
- aStack[nos].flags = STK_Null;
+ pTos++;
+ pTos->flags = MEM_Null;
}
break;
}else{
- Stringify(p, tos);
- Stringify(p, nos);
- c = strcmp(zStack[nos], zStack[tos]);
+ Stringify(pTos);
+ Stringify(pNos);
+ c = strcmp(pNos->z, pTos->z);
}
/* The asserts on each case of the following switch are there to verify
** that string comparison opcodes are always exactly 6 greater than the
@@ -1613,14 +1592,13 @@ case OP_StrGe: {
case OP_StrGt: c = c>0; assert( pOp->opcode-6==OP_Gt ); break;
default: c = c>=0; assert( pOp->opcode-6==OP_Ge ); break;
}
- POPSTACK;
- POPSTACK;
+ popStack(&pTos, 2);
if( pOp->p2 ){
if( c ) pc = pOp->p2-1;
}else{
- p->tos++;
- aStack[nos].flags = STK_Int;
- aStack[nos].i = c;
+ pTos++;
+ pTos->flags = MEM_Int;
+ pTos->i = c;
}
break;
}
@@ -1639,22 +1617,21 @@ case OP_StrGe: {
*/
case OP_And:
case OP_Or: {
- int tos = p->tos;
- int nos = tos - 1;
+ Mem *pNos = &pTos[-1];
int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- if( aStack[tos].flags & STK_Null ){
+ assert( pNos>=p->aStack );
+ if( pTos->flags & MEM_Null ){
v1 = 2;
}else{
- Integerify(p, tos);
- v1 = aStack[tos].i==0;
+ Integerify(pTos);
+ v1 = pTos->i==0;
}
- if( aStack[nos].flags & STK_Null ){
+ if( pNos->flags & MEM_Null ){
v2 = 2;
}else{
- Integerify(p, nos);
- v2 = aStack[nos].i==0;
+ Integerify(pNos);
+ v2 = pNos->i==0;
}
if( pOp->opcode==OP_And ){
static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
@@ -1663,13 +1640,13 @@ case OP_Or: {
static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
v1 = or_logic[v1*3+v2];
}
- POPSTACK;
- Release(p, nos);
+ popStack(&pTos, 2);
+ pTos++;
if( v1==2 ){
- aStack[nos].flags = STK_Null;
+ pTos->flags = MEM_Null;
}else{
- aStack[nos].i = v1==0;
- aStack[nos].flags = STK_Int;
+ pTos->i = v1==0;
+ pTos->flags = MEM_Int;
}
break;
}
@@ -1688,29 +1665,28 @@ case OP_Or: {
*/
case OP_Negative:
case OP_AbsValue: {
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( aStack[tos].flags & STK_Real ){
- Release(p, tos);
- if( pOp->opcode==OP_Negative || aStack[tos].r<0.0 ){
- aStack[tos].r = -aStack[tos].r;
+ assert( pTos>=p->aStack );
+ if( pTos->flags & MEM_Real ){
+ Release(pTos);
+ if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
+ pTos->r = -pTos->r;
}
- aStack[tos].flags = STK_Real;
- }else if( aStack[tos].flags & STK_Int ){
- Release(p, tos);
- if( pOp->opcode==OP_Negative || aStack[tos].i<0 ){
- aStack[tos].i = -aStack[tos].i;
+ pTos->flags = MEM_Real;
+ }else if( pTos->flags & MEM_Int ){
+ Release(pTos);
+ if( pOp->opcode==OP_Negative || pTos->i<0 ){
+ pTos->i = -pTos->i;
}
- aStack[tos].flags = STK_Int;
- }else if( aStack[tos].flags & STK_Null ){
+ pTos->flags = MEM_Int;
+ }else if( pTos->flags & MEM_Null ){
/* Do nothing */
}else{
- Realify(p, tos);
- Release(p, tos);
- if( pOp->opcode==OP_Negative || aStack[tos].r<0.0 ){
- aStack[tos].r = -aStack[tos].r;
+ Realify(pTos);
+ Release(pTos);
+ if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
+ pTos->r = -pTos->r;
}
- aStack[tos].flags = STK_Real;
+ pTos->flags = MEM_Real;
}
break;
}
@@ -1722,13 +1698,12 @@ case OP_AbsValue: {
** is unchanged.
*/
case OP_Not: {
- int tos = p->tos;
- VERIFY( if( p->tos<0 ) goto not_enough_stack; )
- if( aStack[tos].flags & STK_Null ) break; /* Do nothing to NULLs */
- Integerify(p, tos);
- Release(p, tos);
- aStack[tos].i = !aStack[tos].i;
- aStack[tos].flags = STK_Int;
+ assert( pTos>=p->aStack );
+ if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
+ Integerify(pTos);
+ Release(pTos);
+ pTos->i = !pTos->i;
+ pTos->flags = MEM_Int;
break;
}
@@ -1739,13 +1714,12 @@ case OP_Not: {
** value is unchanged.
*/
case OP_BitNot: {
- int tos = p->tos;
- VERIFY( if( p->tos<0 ) goto not_enough_stack; )
- if( aStack[tos].flags & STK_Null ) break; /* Do nothing to NULLs */
- Integerify(p, tos);
- Release(p, tos);
- aStack[tos].i = ~aStack[tos].i;
- aStack[tos].flags = STK_Int;
+ assert( pTos>=p->aStack );
+ if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
+ Integerify(pTos);
+ Release(pTos);
+ pTos->i = ~pTos->i;
+ pTos->flags = MEM_Int;
break;
}
@@ -1781,15 +1755,16 @@ case OP_Noop: {
case OP_If:
case OP_IfNot: {
int c;
- VERIFY( if( p->tos<0 ) goto not_enough_stack; )
- if( aStack[p->tos].flags & STK_Null ){
+ assert( pTos>=p->aStack );
+ if( pTos->flags & MEM_Null ){
c = pOp->p1;
}else{
- Integerify(p, p->tos);
- c = aStack[p->tos].i;
+ Integerify(pTos);
+ c = pTos->i;
if( pOp->opcode==OP_IfNot ) c = !c;
}
- POPSTACK;
+ assert( (pTos->flags & MEM_Dyn)==0 );
+ pTos--;
if( c ) pc = pOp->p2-1;
break;
}
@@ -1802,16 +1777,18 @@ case OP_IfNot: {
*/
case OP_IsNull: {
int i, cnt;
+ Mem *pTerm;
cnt = pOp->p1;
if( cnt<0 ) cnt = -cnt;
- VERIFY( if( p->tos+1-cnt<0 ) goto not_enough_stack; )
- for(i=0; i<cnt; i++){
- if( aStack[p->tos-i].flags & STK_Null ){
+ pTerm = &pTos[1-cnt];
+ assert( pTerm>=p->aStack );
+ for(i=0; i<cnt; i++, pTerm++){
+ if( pTerm->flags & MEM_Null ){
pc = pOp->p2-1;
break;
}
}
- if( pOp->p1>0 ) sqliteVdbePopStack(p, cnt);
+ if( pOp->p1>0 ) popStack(&pTos, cnt);
break;
}
@@ -1825,10 +1802,10 @@ case OP_NotNull: {
int i, cnt;
cnt = pOp->p1;
if( cnt<0 ) cnt = -cnt;
- VERIFY( if( p->tos+1-cnt<0 ) goto not_enough_stack; )
- for(i=0; i<cnt && (aStack[p->tos-i].flags & STK_Null)==0; i++){}
+ assert( &pTos[1-cnt] >= p->aStack );
+ for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){}
if( i>=cnt ) pc = pOp->p2-1;
- if( pOp->p1>0 ) sqliteVdbePopStack(p, cnt);
+ if( pOp->p1>0 ) popStack(&pTos, cnt);
break;
}
@@ -1860,6 +1837,7 @@ case OP_MakeRecord: {
int i, j;
int idxWidth;
u32 addr;
+ Mem *pRec;
int addUnique = 0; /* True to cause bytes to be added to make the
** generated record distinct */
char zTemp[NBFS]; /* Temp space for small records */
@@ -1883,14 +1861,15 @@ case OP_MakeRecord: {
** Idx(N) contains the total number of bytes in the record.
*/
nField = pOp->p1;
- VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
+ pRec = &pTos[1-nField];
+ assert( pRec>=p->aStack );
nByte = 0;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & STK_Null) ){
+ for(i=0; i<nField; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
addUnique = pOp->p2;
}else{
- Stringify(p, i);
- nByte += aStack[i].n;
+ Stringify(pRec);
+ nByte += pRec->n;
}
}
if( addUnique ) nByte += sizeof(p->uniqueCnt);
@@ -1914,7 +1893,7 @@ case OP_MakeRecord: {
}
j = 0;
addr = idxWidth*(nField+1) + addUnique*sizeof(p->uniqueCnt);
- for(i=p->tos-nField+1; i<=p->tos; i++){
+ for(i=0, pRec=&pTos[1-nField]; i<nField; i++, pRec++){
zNewRecord[j++] = addr & 0xff;
if( idxWidth>1 ){
zNewRecord[j++] = (addr>>8)&0xff;
@@ -1922,8 +1901,8 @@ case OP_MakeRecord: {
zNewRecord[j++] = (addr>>16)&0xff;
}
}
- if( (aStack[i].flags & STK_Null)==0 ){
- addr += aStack[i].n;
+ if( (pRec->flags & MEM_Null)==0 ){
+ addr += pRec->n;
}
}
zNewRecord[j++] = addr & 0xff;
@@ -1938,24 +1917,24 @@ case OP_MakeRecord: {
p->uniqueCnt++;
j += sizeof(p->uniqueCnt);
}
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & STK_Null)==0 ){
- memcpy(&zNewRecord[j], zStack[i], aStack[i].n);
- j += aStack[i].n;
+ for(i=0, pRec=&pTos[1-nField]; i<nField; i++, pRec++){
+ if( (pRec->flags & MEM_Null)==0 ){
+ memcpy(&zNewRecord[j], pRec->z, pRec->n);
+ j += pRec->n;
}
}
- sqliteVdbePopStack(p, nField);
- p->tos++;
- aStack[p->tos].n = nByte;
+ popStack(&pTos, nField);
+ pTos++;
+ pTos->n = nByte;
if( nByte<=NBFS ){
assert( zNewRecord==zTemp );
- memcpy(aStack[p->tos].z, zTemp, nByte);
- zStack[p->tos] = aStack[p->tos].z;
- aStack[p->tos].flags = STK_Str;
+ memcpy(pTos->zShort, zTemp, nByte);
+ pTos->z = pTos->zShort;
+ pTos->flags = MEM_Str | MEM_Short;
}else{
assert( zNewRecord!=zTemp );
- aStack[p->tos].flags = STK_Str | STK_Dyn;
- zStack[p->tos] = zNewRecord;
+ pTos->z = zNewRecord;
+ pTos->flags = MEM_Str | MEM_Dyn;
}
break;
}
@@ -2040,39 +2019,41 @@ case OP_MakeKey: {
int addRowid;
int i, j;
int containsNull = 0;
+ Mem *pRec;
char zTemp[NBFS];
addRowid = pOp->opcode==OP_MakeIdxKey;
nField = pOp->p1;
- VERIFY( if( p->tos+1+addRowid<nField ) goto not_enough_stack; )
+ pRec = &pTos[1-nField];
+ assert( pRec>=p->aStack );
nByte = 0;
- for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){
- int flags = aStack[i].flags;
+ for(j=0, i=0; i<nField; i++, j++, pRec++){
+ int flags = pRec->flags;
int len;
char *z;
- if( flags & STK_Null ){
+ if( flags & MEM_Null ){
nByte += 2;
containsNull = 1;
}else if( pOp->p3 && pOp->p3[j]=='t' ){
- Stringify(p, i);
- aStack[i].flags &= ~(STK_Int|STK_Real);
- nByte += aStack[i].n+1;
- }else if( (flags & (STK_Real|STK_Int))!=0 || sqliteIsNumber(zStack[i]) ){
- if( (flags & (STK_Real|STK_Int))==STK_Int ){
- aStack[i].r = aStack[i].i;
- }else if( (flags & (STK_Real|STK_Int))==0 ){
- aStack[i].r = sqliteAtoF(zStack[i]);
+ Stringify(pRec);
+ pRec->flags &= ~(MEM_Int|MEM_Real);
+ nByte += pRec->n+1;
+ }else if( (flags & (MEM_Real|MEM_Int))!=0 || sqliteIsNumber(pRec->z) ){
+ if( (flags & (MEM_Real|MEM_Int))==MEM_Int ){
+ pRec->r = pRec->i;
+ }else if( (flags & (MEM_Real|MEM_Int))==0 ){
+ pRec->r = sqliteAtoF(pRec->z, 0);
}
- Release(p, i);
- z = aStack[i].z;
- sqliteRealToSortable(aStack[i].r, z);
+ Release(pRec);
+ z = pRec->zShort;
+ sqliteRealToSortable(pRec->r, z);
len = strlen(z);
- zStack[i] = 0;
- aStack[i].flags = STK_Real;
- aStack[i].n = len+1;
- nByte += aStack[i].n+1;
+ pRec->z = 0;
+ pRec->flags = MEM_Real;
+ pRec->n = len+1;
+ nByte += pRec->n+1;
}else{
- nByte += aStack[i].n+1;
+ nByte += pRec->n+1;
}
}
if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){
@@ -2087,40 +2068,44 @@ case OP_MakeKey: {
if( zNewKey==0 ) goto no_mem;
}
j = 0;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( aStack[i].flags & STK_Null ){
+ pRec = &pTos[1-nField];
+ for(i=0; i<nField; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
zNewKey[j++] = 'a';
zNewKey[j++] = 0;
+ }else if( pRec->flags==MEM_Real ){
+ zNewKey[j++] = 'b';
+ memcpy(&zNewKey[j], pRec->zShort, pRec->n);
+ j += pRec->n;
}else{
- if( aStack[i].flags & (STK_Int|STK_Real) ){
- zNewKey[j++] = 'b';
- }else{
- zNewKey[j++] = 'c';
- }
- memcpy(&zNewKey[j], zStack[i] ? zStack[i] : aStack[i].z, aStack[i].n);
- j += aStack[i].n;
+ assert( pRec->flags & MEM_Str );
+ zNewKey[j++] = 'c';
+ memcpy(&zNewKey[j], pRec->z, pRec->n);
+ j += pRec->n;
}
}
if( addRowid ){
u32 iKey;
- Integerify(p, p->tos-nField);
- iKey = intToKey(aStack[p->tos-nField].i);
+ pRec = &pTos[-nField];
+ assert( pRec>=p->aStack );
+ Integerify(pRec);
+ iKey = intToKey(pRec->i);
memcpy(&zNewKey[j], &iKey, sizeof(u32));
- sqliteVdbePopStack(p, nField+1);
+ popStack(&pTos, nField+1);
if( pOp->p2 && containsNull ) pc = pOp->p2 - 1;
}else{
- if( pOp->p2==0 ) sqliteVdbePopStack(p, nField+addRowid);
+ if( pOp->p2==0 ) popStack(&pTos, nField);
}
- p->tos++;
- aStack[p->tos].n = nByte;
+ pTos++;
+ pTos->n = nByte;
if( nByte<=NBFS ){
assert( zNewKey==zTemp );
- zStack[p->tos] = aStack[p->tos].z;
- memcpy(zStack[p->tos], zTemp, nByte);
- aStack[p->tos].flags = STK_Str;
+ pTos->z = pTos->zShort;
+ memcpy(pTos->zShort, zTemp, nByte);
+ pTos->flags = MEM_Str | MEM_Short;
}else{
- aStack[p->tos].flags = STK_Str|STK_Dyn;
- zStack[p->tos] = zNewKey;
+ pTos->z = zNewKey;
+ pTos->flags = MEM_Str | MEM_Dyn;
}
break;
}
@@ -2134,18 +2119,14 @@ case OP_MakeKey: {
** the key itself.
*/
case OP_IncrKey: {
- int tos = p->tos;
-
- VERIFY( if( tos<0 ) goto bad_instruction );
- Stringify(p, tos);
- if( aStack[tos].flags & (STK_Static|STK_Ephem) ){
- /* CANT HAPPEN. The IncrKey opcode is only applied to keys
- ** generated by MakeKey or MakeIdxKey and the results of those
- ** operands are always dynamic strings.
- */
- goto abort_due_to_error;
- }
- zStack[tos][aStack[tos].n-1]++;
+ assert( pTos>=p->aStack );
+ /* The IncrKey opcode is only applied to keys generated by
+ ** MakeKey or MakeIdxKey and the results of those operands
+ ** are always dynamic strings or zShort[] strings. So we
+ ** are always free to modify the string in place.
+ */
+ assert( pTos->flags & (MEM_Dyn|MEM_Short) );
+ pTos->z[pTos->n-1]++;
break;
}
@@ -2198,6 +2179,7 @@ case OP_Transaction: {
p->pc = pc;
p->undoTransOnError = 1;
p->rc = SQLITE_BUSY;
+ p->pTos = pTos;
return SQLITE_BUSY;
}else if( (*db->xBusyCallback)(db->pBusyArg, "", busy++)==0 ){
sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
@@ -2234,6 +2216,13 @@ case OP_Transaction: {
*/
case OP_Commit: {
int i;
+ if( db->xCommitCallback!=0 ){
+ if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
+ if( db->xCommitCallback(db->pCommitArg)!=0 ){
+ rc = SQLITE_CONSTRAINT;
+ }
+ if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
+ }
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
if( db->aDb[i].inTrans ){
rc = sqliteBtreeCommit(db->aDb[i].pBt);
@@ -2280,14 +2269,14 @@ case OP_Rollback: {
** executing this instruction.
*/
case OP_ReadCookie: {
- int i = ++p->tos;
int aMeta[SQLITE_N_BTREE_META];
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( db->aDb[pOp->p1].pBt!=0 );
rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
- aStack[i].i = aMeta[1+pOp->p2];
- aStack[i].flags = STK_Int;
+ pTos++;
+ pTos->i = aMeta[1+pOp->p2];
+ pTos->flags = MEM_Int;
break;
}
@@ -2306,14 +2295,15 @@ case OP_SetCookie: {
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( db->aDb[pOp->p1].pBt!=0 );
- VERIFY( if( p->tos<0 ) goto not_enough_stack; )
- Integerify(p, p->tos)
+ assert( pTos>=p->aStack );
+ Integerify(pTos)
rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
if( rc==SQLITE_OK ){
- aMeta[1+pOp->p2] = aStack[p->tos].i;
+ aMeta[1+pOp->p2] = pTos->i;
rc = sqliteBtreeUpdateMeta(db->aDb[pOp->p1].pBt, aMeta);
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
@@ -2392,32 +2382,31 @@ case OP_OpenRead:
case OP_OpenWrite: {
int busy = 0;
int i = pOp->p1;
- int tos = p->tos;
int p2 = pOp->p2;
int wrFlag;
Btree *pX;
int iDb;
- VERIFY( if( tos<0 ) goto not_enough_stack; );
- Integerify(p, tos);
- iDb = p->aStack[tos].i;
- tos--;
- VERIFY( if( iDb<0 || iDb>=db->nDb ) goto bad_instruction; );
- VERIFY( if( db->aDb[iDb].pBt==0 ) goto bad_instruction; );
+ assert( pTos>=p->aStack );
+ Integerify(pTos);
+ iDb = pTos->i;
+ pTos--;
+ assert( iDb>=0 && iDb<db->nDb );
pX = db->aDb[iDb].pBt;
+ assert( pX!=0 );
wrFlag = pOp->opcode==OP_OpenWrite;
if( p2<=0 ){
- VERIFY( if( tos<0 ) goto not_enough_stack; );
- Integerify(p, tos);
- p2 = p->aStack[tos].i;
- POPSTACK;
+ assert( pTos>=p->aStack );
+ Integerify(pTos);
+ p2 = pTos->i;
+ pTos--;
if( p2<2 ){
sqliteSetString(&p->zErrMsg, "root page number less than 2", (char*)0);
rc = SQLITE_INTERNAL;
break;
}
}
- VERIFY( if( i<0 ) goto bad_instruction; )
+ assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
sqliteVdbeCleanupCursor(&p->aCsr[i]);
memset(&p->aCsr[i], 0, sizeof(Cursor));
@@ -2430,6 +2419,7 @@ case OP_OpenWrite: {
if( db->xBusyCallback==0 ){
p->pc = pc;
p->rc = SQLITE_BUSY;
+ p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */
return SQLITE_BUSY;
}else if( (*db->xBusyCallback)(db->pBusyArg, pOp->p3, ++busy)==0 ){
sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
@@ -2446,10 +2436,6 @@ case OP_OpenWrite: {
}
}
}while( busy );
- if( p2<=0 ){
- POPSTACK;
- }
- POPSTACK;
break;
}
@@ -2474,7 +2460,7 @@ case OP_OpenWrite: {
case OP_OpenTemp: {
int i = pOp->p1;
Cursor *pCx;
- VERIFY( if( i<0 ) goto bad_instruction; )
+ assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
pCx = &p->aCsr[i];
sqliteVdbeCleanupCursor(pCx);
@@ -2512,7 +2498,7 @@ case OP_OpenTemp: {
case OP_OpenPseudo: {
int i = pOp->p1;
Cursor *pCx;
- VERIFY( if( i<0 ) goto bad_instruction; )
+ assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
pCx = &p->aCsr[i];
sqliteVdbeCleanupCursor(pCx);
@@ -2559,29 +2545,29 @@ case OP_Close: {
case OP_MoveLt:
case OP_MoveTo: {
int i = pOp->p1;
- int tos = p->tos;
Cursor *pC;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
+ assert( pTos>=p->aStack );
assert( i>=0 && i<p->nCursor );
pC = &p->aCsr[i];
if( pC->pCursor!=0 ){
int res, oc;
pC->nullRow = 0;
- if( aStack[tos].flags & STK_Int ){
- int iKey = intToKey(aStack[tos].i);
+ if( pTos->flags & MEM_Int ){
+ int iKey = intToKey(pTos->i);
if( pOp->p2==0 && pOp->opcode==OP_MoveTo ){
pC->movetoTarget = iKey;
pC->deferredMoveto = 1;
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res);
- pC->lastRecno = aStack[tos].i;
+ pC->lastRecno = pTos->i;
pC->recnoIsValid = res==0;
}else{
- Stringify(p, tos);
- sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
+ Stringify(pTos);
+ sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
pC->recnoIsValid = 0;
}
pC->deferredMoveto = 0;
@@ -2609,7 +2595,8 @@ case OP_MoveTo: {
}
}
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
@@ -2650,14 +2637,14 @@ case OP_Distinct:
case OP_NotFound:
case OP_Found: {
int i = pOp->p1;
- int tos = p->tos;
int alreadyExists = 0;
Cursor *pC;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){
+ assert( pTos>=p->aStack );
+ assert( i>=0 && i<p->nCursor );
+ if( (pC = &p->aCsr[i])->pCursor!=0 ){
int res, rx;
- Stringify(p, tos);
- rx = sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
+ Stringify(pTos);
+ rx = sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
alreadyExists = rx==SQLITE_OK && res==0;
pC->deferredMoveto = 0;
}
@@ -2667,7 +2654,8 @@ case OP_Found: {
if( !alreadyExists ) pc = pOp->p2 - 1;
}
if( pOp->opcode!=OP_Distinct ){
- POPSTACK;
+ Release(pTos);
+ pTos--;
}
break;
}
@@ -2694,18 +2682,18 @@ case OP_Found: {
*/
case OP_IsUnique: {
int i = pOp->p1;
- int tos = p->tos;
- int nos = tos-1;
+ Mem *pNos = &pTos[-1];
BtCursor *pCrsr;
int R;
/* Pop the value R off the top of the stack
*/
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- Integerify(p, tos);
- R = aStack[tos].i;
- POPSTACK;
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( pNos>=p->aStack );
+ Integerify(pTos);
+ R = pTos->i;
+ pTos--;
+ assert( i>=0 && i<=p->nCursor );
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res, rc;
int v; /* The record number on the P1 entry that matches K */
char *zKey; /* The value of K */
@@ -2713,9 +2701,9 @@ case OP_IsUnique: {
/* Make sure K is a string and make zKey point to K
*/
- Stringify(p, nos);
- zKey = zStack[nos];
- nKey = aStack[nos].n;
+ Stringify(pNos);
+ zKey = pNos->z;
+ nKey = pNos->n;
assert( nKey >= 4 );
/* Search for an entry in P1 where all but the last four bytes match K.
@@ -2755,9 +2743,9 @@ case OP_IsUnique: {
** stack. (These bytes are the record number of an entry that
** violates a UNIQUE constraint.)
*/
- p->tos++;
- aStack[tos].i = v;
- aStack[tos].flags = STK_Int;
+ pTos++;
+ pTos->i = v;
+ pTos->flags = MEM_Int;
}
break;
}
@@ -2777,15 +2765,15 @@ case OP_IsUnique: {
*/
case OP_NotExists: {
int i = pOp->p1;
- int tos = p->tos;
BtCursor *pCrsr;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( pTos>=p->aStack );
+ assert( i>=0 && i<p->nCursor );
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res, rx, iKey;
- assert( aStack[tos].flags & STK_Int );
- iKey = intToKey(aStack[tos].i);
+ assert( pTos->flags & MEM_Int );
+ iKey = intToKey(pTos->i);
rx = sqliteBtreeMoveto(pCrsr, (char*)&iKey, sizeof(int), &res);
- p->aCsr[i].lastRecno = aStack[tos].i;
+ p->aCsr[i].lastRecno = pTos->i;
p->aCsr[i].recnoIsValid = res==0;
p->aCsr[i].nullRow = 0;
if( rx!=SQLITE_OK || res!=0 ){
@@ -2793,7 +2781,8 @@ case OP_NotExists: {
p->aCsr[i].recnoIsValid = 0;
}
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
@@ -2808,7 +2797,8 @@ case OP_NewRecno: {
int i = pOp->p1;
int v = 0;
Cursor *pC;
- if( VERIFY( i<0 || i>=p->nCursor || ) (pC = &p->aCsr[i])->pCursor==0 ){
+ assert( i>=0 && i<p->nCursor );
+ if( (pC = &p->aCsr[i])->pCursor==0 ){
v = 0;
}else{
/* The next rowid or record number (different terms for the same
@@ -2873,10 +2863,12 @@ case OP_NewRecno: {
cnt = 0;
do{
if( v==0 || cnt>2 ){
- v = sqliteRandomInteger();
+ sqliteRandomness(sizeof(v), &v);
if( cnt<5 ) v &= 0xffffff;
}else{
- v += sqliteRandomByte() + 1;
+ unsigned char r;
+ sqliteRandomness(1, &r);
+ v += r + 1;
}
if( v==0 ) continue;
x = intToKey(v);
@@ -2892,9 +2884,9 @@ case OP_NewRecno: {
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
}
- p->tos++;
- aStack[p->tos].i = v;
- aStack[p->tos].flags = STK_Int;
+ pTos++;
+ pTos->i = v;
+ pTos->flags = MEM_Int;
break;
}
@@ -2906,9 +2898,12 @@ case OP_NewRecno: {
** stack. The key is the next value down on the stack. The key must
** be an integer. The stack is popped twice by this instruction.
**
-** If P2==1 then the row change count is incremented. If P2==0 the
-** row change count is unmodified. The rowid is stored for subsequent
-** return by the sqlite_last_insert_rowid() function if P2 is 1.
+** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
+** incremented (otherwise not). If the OPFLAG_CSCHANGE flag is set,
+** then the current statement change count is incremented (otherwise not).
+** If the OPFLAG_LASTROWID flag of P2 is set, then rowid is
+** stored for subsequent return by the sqlite_last_insert_rowid() function
+** (otherwise it's unmodified).
*/
/* Opcode: PutStrKey P1 * *
**
@@ -2922,32 +2917,36 @@ case OP_NewRecno: {
*/
case OP_PutIntKey:
case OP_PutStrKey: {
- int tos = p->tos;
- int nos = p->tos-1;
+ Mem *pNos = &pTos[-1];
int i = pOp->p1;
Cursor *pC;
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- if( VERIFY( i>=0 && i<p->nCursor && )
- ((pC = &p->aCsr[i])->pCursor!=0 || pC->pseudoTable) ){
+ assert( pNos>=p->aStack );
+ assert( i>=0 && i<p->nCursor );
+ if( ((pC = &p->aCsr[i])->pCursor!=0 || pC->pseudoTable) ){
char *zKey;
int nKey, iKey;
if( pOp->opcode==OP_PutStrKey ){
- Stringify(p, nos);
- nKey = aStack[nos].n;
- zKey = zStack[nos];
+ Stringify(pNos);
+ nKey = pNos->n;
+ zKey = pNos->z;
}else{
- assert( aStack[nos].flags & STK_Int );
+ assert( pNos->flags & MEM_Int );
nKey = sizeof(int);
- iKey = intToKey(aStack[nos].i);
+ iKey = intToKey(pNos->i);
zKey = (char*)&iKey;
- if( pOp->p2 ){
- db->nChange++;
- db->lastRowid = aStack[nos].i;
- }
- if( pC->nextRowidValid && aStack[nos].i>=pC->nextRowid ){
+ if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
+ if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
+ if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
+ if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
pC->nextRowidValid = 0;
}
}
+ if( pTos->flags & MEM_Null ){
+ pTos->z = 0;
+ pTos->n = 0;
+ }else{
+ assert( pTos->flags & MEM_Str );
+ }
if( pC->pseudoTable ){
/* PutStrKey does not work for pseudo-tables.
** The following assert makes sure we are not trying to use
@@ -2956,27 +2955,24 @@ case OP_PutStrKey: {
assert( pOp->opcode==OP_PutIntKey );
sqliteFree(pC->pData);
pC->iKey = iKey;
- pC->nData = aStack[tos].n;
- if( aStack[tos].flags & STK_Dyn ){
- pC->pData = zStack[tos];
- zStack[tos] = 0;
- aStack[tos].flags = STK_Null;
+ pC->nData = pTos->n;
+ if( pTos->flags & MEM_Dyn ){
+ pC->pData = pTos->z;
+ pTos->flags = MEM_Null;
}else{
pC->pData = sqliteMallocRaw( pC->nData );
if( pC->pData ){
- memcpy(pC->pData, zStack[tos], pC->nData);
+ memcpy(pC->pData, pTos->z, pC->nData);
}
}
pC->nullRow = 0;
}else{
- rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey,
- zStack[tos], aStack[tos].n);
+ rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n);
}
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
}
- POPSTACK;
- POPSTACK;
+ popStack(&pTos, 2);
break;
}
@@ -2989,8 +2985,9 @@ case OP_PutStrKey: {
** the next Next instruction will be a no-op. Hence it is OK to delete
** a record from within an Next loop.
**
-** The row change counter is incremented if P2==1 and is unmodified
-** if P2==0.
+** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
+** incremented (otherwise not). If OPFLAG_CSCHANGE flag is set,
+** then the current statement change count is incremented (otherwise not).
**
** If P1 is a pseudo-table, then this instruction is a no-op.
*/
@@ -3004,7 +3001,19 @@ case OP_Delete: {
rc = sqliteBtreeDelete(pC->pCursor);
pC->nextRowidValid = 0;
}
- if( pOp->p2 ) db->nChange++;
+ if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
+ if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
+ break;
+}
+
+/* Opcode: SetCounts * * *
+**
+** Called at end of statement. Updates lsChange (last statement change count)
+** and resets csChange (current statement change count) to 0.
+*/
+case OP_SetCounts: {
+ db->lsChange=db->csChange;
+ db->csChange=0;
break;
}
@@ -3043,46 +3052,46 @@ case OP_KeyAsData: {
case OP_RowKey:
case OP_RowData: {
int i = pOp->p1;
- int tos = ++p->tos;
Cursor *pC;
int n;
+ pTos++;
assert( i>=0 && i<p->nCursor );
pC = &p->aCsr[i];
if( pC->nullRow ){
- aStack[tos].flags = STK_Null;
+ pTos->flags = MEM_Null;
}else if( pC->pCursor!=0 ){
BtCursor *pCrsr = pC->pCursor;
sqliteVdbeCursorMoveto(pC);
if( pC->nullRow ){
- aStack[tos].flags = STK_Null;
+ pTos->flags = MEM_Null;
break;
}else if( pC->keyAsData || pOp->opcode==OP_RowKey ){
sqliteBtreeKeySize(pCrsr, &n);
}else{
sqliteBtreeDataSize(pCrsr, &n);
}
- aStack[tos].n = n;
+ pTos->n = n;
if( n<=NBFS ){
- aStack[tos].flags = STK_Str;
- zStack[tos] = aStack[tos].z;
+ pTos->flags = MEM_Str | MEM_Short;
+ pTos->z = pTos->zShort;
}else{
char *z = sqliteMallocRaw( n );
if( z==0 ) goto no_mem;
- aStack[tos].flags = STK_Str | STK_Dyn;
- zStack[tos] = z;
+ pTos->flags = MEM_Str | MEM_Dyn;
+ pTos->z = z;
}
if( pC->keyAsData || pOp->opcode==OP_RowKey ){
- sqliteBtreeKey(pCrsr, 0, n, zStack[tos]);
+ sqliteBtreeKey(pCrsr, 0, n, pTos->z);
}else{
- sqliteBtreeData(pCrsr, 0, n, zStack[tos]);
+ sqliteBtreeData(pCrsr, 0, n, pTos->z);
}
}else if( pC->pseudoTable ){
- aStack[tos].n = pC->nData;
- zStack[tos] = pC->pData;
- aStack[tos].flags = STK_Str|STK_Ephem;
+ pTos->n = pC->nData;
+ pTos->z = pC->pData;
+ pTos->flags = MEM_Str|MEM_Ephem;
}else{
- aStack[tos].flags = STK_Null;
+ pTos->flags = MEM_Null;
}
break;
}
@@ -3110,7 +3119,6 @@ case OP_Column: {
int amt, offset, end, payloadSize;
int i = pOp->p1;
int p2 = pOp->p2;
- int tos = p->tos+1;
Cursor *pC;
char *zRec;
BtCursor *pCrsr;
@@ -3118,11 +3126,12 @@ case OP_Column: {
unsigned char aHdr[10];
assert( i<p->nCursor );
+ pTos++;
if( i<0 ){
- VERIFY( if( tos+i<0 ) goto bad_instruction; )
- VERIFY( if( (aStack[tos+i].flags & STK_Str)==0 ) goto bad_instruction; )
- zRec = zStack[tos+i];
- payloadSize = aStack[tos+i].n;
+ assert( &pTos[i]>=p->aStack );
+ assert( pTos[i].flags & MEM_Str );
+ zRec = pTos[i].z;
+ payloadSize = pTos[i].n;
}else if( (pC = &p->aCsr[i])->pCursor!=0 ){
sqliteVdbeCursorMoveto(pC);
zRec = 0;
@@ -3146,8 +3155,7 @@ case OP_Column: {
** data begins.
*/
if( payloadSize==0 ){
- aStack[tos].flags = STK_Null;
- p->tos = tos;
+ pTos->flags = MEM_Null;
break;
}else if( payloadSize<256 ){
idxWidth = 1;
@@ -3189,31 +3197,28 @@ case OP_Column: {
/* amt and offset now hold the offset to the start of data and the
** amount of data. Go get the data and put it on the stack.
*/
+ pTos->n = amt;
if( amt==0 ){
- aStack[tos].flags = STK_Null;
+ pTos->flags = MEM_Null;
}else if( zRec ){
- aStack[tos].flags = STK_Str | STK_Ephem;
- aStack[tos].n = amt;
- zStack[tos] = &zRec[offset];
+ pTos->flags = MEM_Str | MEM_Ephem;
+ pTos->z = &zRec[offset];
}else{
if( amt<=NBFS ){
- aStack[tos].flags = STK_Str;
- zStack[tos] = aStack[tos].z;
- aStack[tos].n = amt;
+ pTos->flags = MEM_Str | MEM_Short;
+ pTos->z = pTos->zShort;
}else{
char *z = sqliteMallocRaw( amt );
if( z==0 ) goto no_mem;
- aStack[tos].flags = STK_Str | STK_Dyn;
- zStack[tos] = z;
- aStack[tos].n = amt;
+ pTos->flags = MEM_Str | MEM_Dyn;
+ pTos->z = z;
}
if( pC->keyAsData ){
- sqliteBtreeKey(pCrsr, offset, amt, zStack[tos]);
+ sqliteBtreeKey(pCrsr, offset, amt, pTos->z);
}else{
- sqliteBtreeData(pCrsr, offset, amt, zStack[tos]);
+ sqliteBtreeData(pCrsr, offset, amt, pTos->z);
}
}
- p->tos = tos;
break;
}
@@ -3226,27 +3231,27 @@ case OP_Column: {
*/
case OP_Recno: {
int i = pOp->p1;
- int tos = ++p->tos;
Cursor *pC;
int v;
assert( i>=0 && i<p->nCursor );
pC = &p->aCsr[i];
sqliteVdbeCursorMoveto(pC);
+ pTos++;
if( pC->recnoIsValid ){
v = pC->lastRecno;
}else if( pC->pseudoTable ){
v = keyToInt(pC->iKey);
}else if( pC->nullRow || pC->pCursor==0 ){
- aStack[tos].flags = STK_Null;
+ pTos->flags = MEM_Null;
break;
}else{
assert( pC->pCursor!=0 );
sqliteBtreeKey(pC->pCursor, 0, sizeof(u32), (char*)&v);
v = keyToInt(v);
}
- aStack[tos].i = v;
- aStack[tos].flags = STK_Int;
+ pTos->i = v;
+ pTos->flags = MEM_Int;
break;
}
@@ -3263,12 +3268,13 @@ case OP_Recno: {
*/
case OP_FullKey: {
int i = pOp->p1;
- int tos = ++p->tos;
BtCursor *pCrsr;
- VERIFY( if( !p->aCsr[i].keyAsData ) goto bad_instruction; )
- VERIFY( if( p->aCsr[i].pseudoTable ) goto bad_instruction; )
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( p->aCsr[i].keyAsData );
+ assert( !p->aCsr[i].pseudoTable );
+ assert( i>=0 && i<p->nCursor );
+ pTos++;
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int amt;
char *z;
@@ -3281,14 +3287,14 @@ case OP_FullKey: {
if( amt>NBFS ){
z = sqliteMallocRaw( amt );
if( z==0 ) goto no_mem;
- aStack[tos].flags = STK_Str | STK_Dyn;
+ pTos->flags = MEM_Str | MEM_Dyn;
}else{
- z = aStack[tos].z;
- aStack[tos].flags = STK_Str;
+ z = pTos->zShort;
+ pTos->flags = MEM_Str | MEM_Short;
}
sqliteBtreeKey(pCrsr, 0, amt, z);
- zStack[tos] = z;
- aStack[tos].n = amt;
+ pTos->z = z;
+ pTos->n = amt;
}
break;
}
@@ -3425,15 +3431,16 @@ case OP_Next: {
*/
case OP_IdxPut: {
int i = pOp->p1;
- int tos = p->tos;
BtCursor *pCrsr;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
- int nKey = aStack[tos].n;
- const char *zKey = zStack[tos];
+ assert( pTos>=p->aStack );
+ assert( i>=0 && i<p->nCursor );
+ assert( pTos->flags & MEM_Str );
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ int nKey = pTos->n;
+ const char *zKey = pTos->z;
if( pOp->p2 ){
int res, n;
- assert( aStack[tos].n >= 4 );
+ assert( nKey >= 4 );
rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
while( res!=0 ){
@@ -3460,7 +3467,8 @@ case OP_IdxPut: {
rc = sqliteBtreeInsert(pCrsr, zKey, nKey, "", 0);
assert( p->aCsr[i].deferredMoveto==0 );
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
@@ -3471,18 +3479,20 @@ case OP_IdxPut: {
*/
case OP_IdxDelete: {
int i = pOp->p1;
- int tos = p->tos;
BtCursor *pCrsr;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( pTos>=p->aStack );
+ assert( pTos->flags & MEM_Str );
+ assert( i>=0 && i<p->nCursor );
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int rx, res;
- rx = sqliteBtreeMoveto(pCrsr, zStack[tos], aStack[tos].n, &res);
+ rx = sqliteBtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
if( rx==SQLITE_OK && res==0 ){
rc = sqliteBtreeDelete(pCrsr);
}
assert( p->aCsr[i].deferredMoveto==0 );
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
@@ -3497,22 +3507,25 @@ case OP_IdxDelete: {
*/
case OP_IdxRecno: {
int i = pOp->p1;
- int tos = ++p->tos;
BtCursor *pCrsr;
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( i>=0 && i<p->nCursor );
+ pTos++;
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int v;
int sz;
assert( p->aCsr[i].deferredMoveto==0 );
sqliteBtreeKeySize(pCrsr, &sz);
if( sz<sizeof(u32) ){
- aStack[tos].flags = STK_Null;
+ pTos->flags = MEM_Null;
}else{
sqliteBtreeKey(pCrsr, sz - sizeof(u32), sizeof(u32), (char*)&v);
v = keyToInt(v);
- aStack[tos].i = v;
- aStack[tos].flags = STK_Int;
+ pTos->i = v;
+ pTos->flags = MEM_Int;
}
+ }else{
+ pTos->flags = MEM_Null;
}
break;
}
@@ -3546,15 +3559,16 @@ case OP_IdxLT:
case OP_IdxGT:
case OP_IdxGE: {
int i= pOp->p1;
- int tos = p->tos;
BtCursor *pCrsr;
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( i>=0 && i<p->nCursor );
+ assert( pTos>=p->aStack );
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res, rc;
- Stringify(p, tos);
+ Stringify(pTos);
assert( p->aCsr[i].deferredMoveto==0 );
- rc = sqliteBtreeKeyCompare(pCrsr, zStack[tos], aStack[tos].n, 4, &res);
+ rc = sqliteBtreeKeyCompare(pCrsr, pTos->z, pTos->n, 4, &res);
if( rc!=SQLITE_OK ){
break;
}
@@ -3567,7 +3581,8 @@ case OP_IdxGE: {
pc = pOp->p2 - 1 ;
}
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
@@ -3582,14 +3597,13 @@ case OP_IdxGE: {
*/
case OP_IdxIsNull: {
int i = pOp->p1;
- int tos = p->tos;
int k, n;
const char *z;
- assert( tos>=0 );
- assert( aStack[tos].flags & STK_Str );
- z = zStack[tos];
- n = aStack[tos].n;
+ assert( pTos>=p->aStack );
+ assert( pTos->flags & MEM_Str );
+ z = pTos->z;
+ n = pTos->n;
for(k=0; k<n && i>0; i--){
if( z[k]=='a' ){
pc = pOp->p2-1;
@@ -3598,7 +3612,8 @@ case OP_IdxIsNull: {
while( k<n && z[k] ){ k++; }
k++;
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
@@ -3662,7 +3677,6 @@ case OP_Clear: {
*/
case OP_CreateIndex:
case OP_CreateTable: {
- int i = ++p->tos;
int pgno;
assert( pOp->p3!=0 && pOp->p3type==P3_POINTER );
assert( pOp->p2>=0 && pOp->p2<db->nDb );
@@ -3672,11 +3686,14 @@ case OP_CreateTable: {
}else{
rc = sqliteBtreeCreateIndex(db->aDb[pOp->p2].pBt, &pgno);
}
+ pTos++;
if( rc==SQLITE_OK ){
- aStack[i].i = pgno;
- aStack[i].flags = STK_Int;
+ pTos->i = pgno;
+ pTos->flags = MEM_Int;
*(u32*)pOp->p3 = pgno;
pOp->p3 = 0;
+ }else{
+ pTos->flags = MEM_Null;
}
break;
}
@@ -3700,14 +3717,14 @@ case OP_CreateTable: {
case OP_IntegrityCk: {
int nRoot;
int *aRoot;
- int tos = ++p->tos;
int iSet = pOp->p1;
Set *pSet;
int j;
HashElem *i;
char *z;
- VERIFY( if( iSet<0 || iSet>=p->nSet ) goto bad_instruction; )
+ assert( iSet>=0 && iSet<p->nSet );
+ pTos++;
pSet = &p->aSet[iSet];
nRoot = sqliteHashCount(&pSet->hash);
aRoot = sqliteMallocRaw( sizeof(int)*(nRoot+1) );
@@ -3721,13 +3738,13 @@ case OP_IntegrityCk: {
z = sqliteBtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot);
if( z==0 || z[0]==0 ){
if( z ) sqliteFree(z);
- zStack[tos] = "ok";
- aStack[tos].n = 3;
- aStack[tos].flags = STK_Str | STK_Static;
+ pTos->z = "ok";
+ pTos->n = 3;
+ pTos->flags = MEM_Str | MEM_Static;
}else{
- zStack[tos] = z;
- aStack[tos].n = strlen(z) + 1;
- aStack[tos].flags = STK_Str | STK_Dyn;
+ pTos->z = z;
+ pTos->n = strlen(z) + 1;
+ pTos->flags = MEM_Str | MEM_Dyn;
}
sqliteFree(aRoot);
break;
@@ -3740,7 +3757,7 @@ case OP_IntegrityCk: {
*/
case OP_ListWrite: {
Keylist *pKeylist;
- VERIFY( if( p->tos<0 ) goto not_enough_stack; )
+ assert( pTos>=p->aStack );
pKeylist = p->pList;
if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){
pKeylist = sqliteMallocRaw( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) );
@@ -3751,19 +3768,30 @@ case OP_ListWrite: {
pKeylist->pNext = p->pList;
p->pList = pKeylist;
}
- Integerify(p, p->tos);
- pKeylist->aKey[pKeylist->nUsed++] = aStack[p->tos].i;
- POPSTACK;
+ Integerify(pTos);
+ pKeylist->aKey[pKeylist->nUsed++] = pTos->i;
+ Release(pTos);
+ pTos--;
break;
}
/* Opcode: ListRewind * * *
**
-** Rewind the temporary buffer back to the beginning. This is
-** now a no-op.
+** Rewind the temporary buffer back to the beginning.
*/
case OP_ListRewind: {
- /* This is now a no-op */
+ /* What this opcode codes, really, is reverse the order of the
+ ** linked list of Keylist structures so that they are read out
+ ** in the same order that they were read in. */
+ Keylist *pRev, *pTop;
+ pRev = 0;
+ while( p->pList ){
+ pTop = p->pList;
+ p->pList = pTop->pNext;
+ pTop->pNext = pRev;
+ pRev = pTop;
+ }
+ p->pList = pRev;
break;
}
@@ -3778,15 +3806,12 @@ case OP_ListRead: {
CHECK_FOR_INTERRUPT;
pKeylist = p->pList;
if( pKeylist!=0 ){
- VERIFY(
- if( pKeylist->nRead<0
- || pKeylist->nRead>=pKeylist->nUsed
- || pKeylist->nRead>=pKeylist->nKey ) goto bad_instruction;
- )
- p->tos++;
- aStack[p->tos].i = pKeylist->aKey[pKeylist->nRead++];
- aStack[p->tos].flags = STK_Int;
- zStack[p->tos] = 0;
+ assert( pKeylist->nRead>=0 );
+ assert( pKeylist->nRead<pKeylist->nUsed );
+ assert( pKeylist->nRead<pKeylist->nKey );
+ pTos++;
+ pTos->i = pKeylist->aKey[pKeylist->nRead++];
+ pTos->flags = MEM_Int;
if( pKeylist->nRead>=pKeylist->nUsed ){
p->pList = pKeylist->pNext;
sqliteFree(pKeylist);
@@ -3843,6 +3868,43 @@ case OP_ListPop: {
break;
}
+/* Opcode: ContextPush * * *
+**
+** Save the current Vdbe context such that it can be restored by a ContextPop
+** opcode. The context stores the last insert row id, the last statement change
+** count, and the current statement change count.
+*/
+case OP_ContextPush: {
+ p->contextStackDepth++;
+ assert(p->contextStackDepth > 0);
+ p->contextStack = sqliteRealloc(p->contextStack,
+ sizeof(Context) * p->contextStackDepth);
+ if( p->contextStack==0 ) goto no_mem;
+ p->contextStack[p->contextStackDepth - 1].lastRowid = p->db->lastRowid;
+ p->contextStack[p->contextStackDepth - 1].lsChange = p->db->lsChange;
+ p->contextStack[p->contextStackDepth - 1].csChange = p->db->csChange;
+ break;
+}
+
+/* Opcode: ContextPop * * *
+**
+** Restore the Vdbe context to the state it was in when contextPush was last
+** executed. The context stores the last insert row id, the last statement
+** change count, and the current statement change count.
+*/
+case OP_ContextPop: {
+ assert(p->contextStackDepth > 0);
+ p->contextStackDepth--;
+ p->db->lastRowid = p->contextStack[p->contextStackDepth].lastRowid;
+ p->db->lsChange = p->contextStack[p->contextStackDepth].lsChange;
+ p->db->csChange = p->contextStack[p->contextStackDepth].csChange;
+ if( p->contextStackDepth == 0 ){
+ sqliteFree(p->contextStack);
+ p->contextStack = 0;
+ }
+ break;
+}
+
/* Opcode: SortPut * * *
**
** The TOS is the key and the NOS is the data. Pop both from the stack
@@ -3850,29 +3912,21 @@ case OP_ListPop: {
** made using SortMakeKey and SortMakeRec, respectively.
*/
case OP_SortPut: {
- int tos = p->tos;
- int nos = tos - 1;
+ Mem *pNos = &pTos[-1];
Sorter *pSorter;
- VERIFY( if( tos<1 ) goto not_enough_stack; )
- if( Dynamicify(p, tos) || Dynamicify(p, nos) ) goto no_mem;
+ assert( pNos>=p->aStack );
+ if( Dynamicify(pTos) || Dynamicify(pNos) ) goto no_mem;
pSorter = sqliteMallocRaw( sizeof(Sorter) );
if( pSorter==0 ) goto no_mem;
pSorter->pNext = p->pSort;
p->pSort = pSorter;
- assert( aStack[tos].flags & STK_Dyn );
- pSorter->nKey = aStack[tos].n;
- pSorter->zKey = zStack[tos];
- pSorter->nData = aStack[nos].n;
- if( aStack[nos].flags & STK_Dyn ){
- pSorter->pData = zStack[nos];
- }else{
- pSorter->pData = sqliteStrDup(zStack[nos]);
- }
- aStack[tos].flags = 0;
- aStack[nos].flags = 0;
- zStack[tos] = 0;
- zStack[nos] = 0;
- p->tos -= 2;
+ assert( pTos->flags & MEM_Dyn );
+ pSorter->nKey = pTos->n;
+ pSorter->zKey = pTos->z;
+ assert( pNos->flags & MEM_Dyn );
+ pSorter->nData = pNos->n;
+ pSorter->pData = pNos->z;
+ pTos -= 2;
break;
}
@@ -3887,35 +3941,37 @@ case OP_SortMakeRec: {
char **azArg;
int nByte;
int nField;
- int i, j;
+ int i;
+ Mem *pRec;
nField = pOp->p1;
- VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
+ pRec = &pTos[1-nField];
+ assert( pRec>=p->aStack );
nByte = 0;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & STK_Null)==0 ){
- Stringify(p, i);
- nByte += aStack[i].n;
+ for(i=0; i<nField; i++, pRec++){
+ if( (pRec->flags & MEM_Null)==0 ){
+ Stringify(pRec);
+ nByte += pRec->n;
}
}
nByte += sizeof(char*)*(nField+1);
azArg = sqliteMallocRaw( nByte );
if( azArg==0 ) goto no_mem;
z = (char*)&azArg[nField+1];
- for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){
- if( aStack[i].flags & STK_Null ){
- azArg[j] = 0;
+ for(pRec=&pTos[1-nField], i=0; i<nField; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
+ azArg[i] = 0;
}else{
- azArg[j] = z;
- strcpy(z, zStack[i]);
- z += aStack[i].n;
+ azArg[i] = z;
+ memcpy(z, pRec->z, pRec->n);
+ z += pRec->n;
}
}
- sqliteVdbePopStack(p, nField);
- p->tos++;
- aStack[p->tos].n = nByte;
- zStack[p->tos] = (char*)azArg;
- aStack[p->tos].flags = STK_Str|STK_Dyn;
+ popStack(&pTos, nField);
+ pTos++;
+ pTos->n = nByte;
+ pTos->z = (char*)azArg;
+ pTos->flags = MEM_Str | MEM_Dyn;
break;
}
@@ -3939,41 +3995,42 @@ case OP_SortMakeKey: {
int nByte;
int nField;
int i, j, k;
+ Mem *pRec;
nField = strlen(pOp->p3);
- VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
+ pRec = &pTos[1-nField];
nByte = 1;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & STK_Null)!=0 ){
+ for(i=0; i<nField; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
nByte += 2;
}else{
- Stringify(p, i);
- nByte += aStack[i].n+2;
+ Stringify(pRec);
+ nByte += pRec->n+2;
}
}
zNewKey = sqliteMallocRaw( nByte );
if( zNewKey==0 ) goto no_mem;
j = 0;
k = 0;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & STK_Null)!=0 ){
+ for(pRec=&pTos[1-nField], i=0; i<nField; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
zNewKey[j++] = 'N';
zNewKey[j++] = 0;
k++;
}else{
zNewKey[j++] = pOp->p3[k++];
- memcpy(&zNewKey[j], zStack[i], aStack[i].n-1);
- j += aStack[i].n-1;
+ memcpy(&zNewKey[j], pRec->z, pRec->n-1);
+ j += pRec->n-1;
zNewKey[j++] = 0;
}
}
zNewKey[j] = 0;
assert( j<nByte );
- sqliteVdbePopStack(p, nField);
- p->tos++;
- aStack[p->tos].n = nByte;
- aStack[p->tos].flags = STK_Str|STK_Dyn;
- zStack[p->tos] = zNewKey;
+ popStack(&pTos, nField);
+ pTos++;
+ pTos->n = nByte;
+ pTos->flags = MEM_Str|MEM_Dyn;
+ pTos->z = zNewKey;
break;
}
@@ -4026,10 +4083,10 @@ case OP_SortNext: {
CHECK_FOR_INTERRUPT;
if( pSorter!=0 ){
p->pSort = pSorter->pNext;
- p->tos++;
- zStack[p->tos] = pSorter->pData;
- aStack[p->tos].n = pSorter->nData;
- aStack[p->tos].flags = STK_Str|STK_Dyn;
+ pTos++;
+ pTos->z = pSorter->pData;
+ pTos->n = pSorter->nData;
+ pTos->flags = MEM_Str|MEM_Dyn;
sqliteFree(pSorter->zKey);
sqliteFree(pSorter);
}else{
@@ -4046,25 +4103,15 @@ case OP_SortNext: {
** callback on it.
*/
case OP_SortCallback: {
- int i = p->tos;
- VERIFY( if( i<0 ) goto not_enough_stack; )
- if( p->xCallback==0 ){
- p->pc = pc+1;
- p->azResColumn = (char**)zStack[i];
- p->nResColumn = pOp->p1;
- p->popStack = 1;
- return SQLITE_ROW;
- }else{
- if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
- if( p->xCallback(p->pCbArg, pOp->p1, (char**)zStack[i], p->azColName)!=0 ){
- rc = SQLITE_ABORT;
- }
- if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
- p->nCallback++;
- }
- POPSTACK;
- if( sqlite_malloc_failed ) goto no_mem;
- break;
+ assert( pTos>=p->aStack );
+ assert( pTos->flags & MEM_Str );
+ p->nCallback++;
+ p->pc = pc+1;
+ p->azResColumn = (char**)pTos->z;
+ assert( p->nResColumn==pOp->p1 );
+ p->popStack = 1;
+ p->pTos = pTos;
+ return SQLITE_ROW;
}
/* Opcode: SortReset * * *
@@ -4082,7 +4129,7 @@ case OP_SortReset: {
** If P3 is "stdin" then open standard input for reading.
*/
case OP_FileOpen: {
- VERIFY( if( pOp->p3==0 ) goto bad_instruction; )
+ assert( pOp->p3!=0 );
if( p->pFile ){
if( p->pFile!=stdin ) fclose(p->pFile);
p->pFile = 0;
@@ -4227,20 +4274,19 @@ fileread_jump:
case OP_FileColumn: {
int i = pOp->p1;
char *z;
- if( VERIFY( i>=0 && i<p->nField && ) p->azField ){
+ assert( i>=0 && i<p->nField );
+ if( p->azField ){
z = p->azField[i];
}else{
z = 0;
}
- p->tos++;
+ pTos++;
if( z ){
- aStack[p->tos].n = strlen(z) + 1;
- zStack[p->tos] = z;
- aStack[p->tos].flags = STK_Str;
+ pTos->n = strlen(z) + 1;
+ pTos->z = z;
+ pTos->flags = MEM_Str | MEM_Ephem;
}else{
- aStack[p->tos].n = 0;
- zStack[p->tos] = 0;
- aStack[p->tos].flags = STK_Null;
+ pTos->flags = MEM_Null;
}
break;
}
@@ -4257,11 +4303,8 @@ case OP_FileColumn: {
*/
case OP_MemStore: {
int i = pOp->p1;
- int tos = p->tos;
- char *zOld;
Mem *pMem;
- int flags;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
+ assert( pTos>=p->aStack );
if( i>=p->nMem ){
int nOld = p->nMem;
Mem *aMem;
@@ -4271,8 +4314,8 @@ case OP_MemStore: {
if( aMem!=p->aMem ){
int j;
for(j=0; j<nOld; j++){
- if( aMem[j].z==p->aMem[j].s.z ){
- aMem[j].z = aMem[j].s.z;
+ if( aMem[j].flags & MEM_Short ){
+ aMem[j].z = aMem[j].zShort;
}
}
}
@@ -4281,33 +4324,24 @@ case OP_MemStore: {
memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld));
}
}
+ Deephemeralize(pTos);
pMem = &p->aMem[i];
- flags = pMem->s.flags;
- if( flags & STK_Dyn ){
- zOld = pMem->z;
- }else{
- zOld = 0;
- }
- pMem->s = aStack[tos];
- flags = pMem->s.flags;
- if( flags & (STK_Static|STK_Dyn|STK_Ephem) ){
- if( (flags & STK_Static)!=0 || (pOp->p2 && (flags & STK_Dyn)!=0) ){
- pMem->z = zStack[tos];
- }else if( flags & STK_Str ){
- pMem->z = sqliteMallocRaw( pMem->s.n );
+ Release(pMem);
+ *pMem = *pTos;
+ if( pMem->flags & MEM_Dyn ){
+ if( pOp->p2 ){
+ pTos->flags = MEM_Null;
+ }else{
+ pMem->z = sqliteMallocRaw( pMem->n );
if( pMem->z==0 ) goto no_mem;
- memcpy(pMem->z, zStack[tos], pMem->s.n);
- pMem->s.flags |= STK_Dyn;
- pMem->s.flags &= ~(STK_Static|STK_Ephem);
+ memcpy(pMem->z, pTos->z, pMem->n);
}
- }else{
- pMem->z = pMem->s.z;
+ }else if( pMem->flags & MEM_Short ){
+ pMem->z = pMem->zShort;
}
- if( zOld ) sqliteFree(zOld);
if( pOp->p2 ){
- zStack[tos] = 0;
- aStack[tos].flags = 0;
- POPSTACK;
+ Release(pTos);
+ pTos--;
}
break;
}
@@ -4322,14 +4356,13 @@ case OP_MemStore: {
** value pushed onto the stack will change too.
*/
case OP_MemLoad: {
- int tos = ++p->tos;
int i = pOp->p1;
- VERIFY( if( i<0 || i>=p->nMem ) goto bad_instruction; )
- memcpy(&aStack[tos], &p->aMem[i].s, sizeof(aStack[tos])-NBFS);;
- if( aStack[tos].flags & STK_Str ){
- zStack[tos] = p->aMem[i].z;
- aStack[tos].flags |= STK_Ephem;
- aStack[tos].flags &= ~(STK_Dyn|STK_Static);
+ assert( i>=0 && i<p->nMem );
+ pTos++;
+ memcpy(pTos, &p->aMem[i], sizeof(pTos[0])-NBFS);;
+ if( pTos->flags & MEM_Str ){
+ pTos->flags |= MEM_Ephem;
+ pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
}
break;
}
@@ -4346,11 +4379,11 @@ case OP_MemLoad: {
case OP_MemIncr: {
int i = pOp->p1;
Mem *pMem;
- VERIFY( if( i<0 || i>=p->nMem ) goto bad_instruction; )
+ assert( i>=0 && i<p->nMem );
pMem = &p->aMem[i];
- VERIFY( if( pMem->s.flags != STK_Int ) goto bad_instruction; )
- pMem->s.i++;
- if( pOp->p2>0 && pMem->s.i>0 ){
+ assert( pMem->flags==MEM_Int );
+ pMem->i++;
+ if( pOp->p2>0 && pMem->i>0 ){
pc = pOp->p2 - 1;
}
break;
@@ -4377,7 +4410,7 @@ case OP_AggReset: {
*/
case OP_AggInit: {
int i = pOp->p2;
- VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; )
+ assert( i>=0 && i<p->agg.nMem );
p->agg.apFunc[i] = (FuncDef*)pOp->p3;
break;
}
@@ -4396,32 +4429,35 @@ case OP_AggInit: {
case OP_AggFunc: {
int n = pOp->p2;
int i;
- Mem *pMem;
+ Mem *pMem, *pRec;
+ char **azArgv = p->zArgv;
sqlite_func ctx;
- VERIFY( if( n<0 ) goto bad_instruction; )
- VERIFY( if( p->tos+1<n ) goto not_enough_stack; )
- VERIFY( if( aStack[p->tos].flags!=STK_Int ) goto bad_instruction; )
- for(i=p->tos-n; i<p->tos; i++){
- if( aStack[i].flags & STK_Null ){
- zStack[i] = 0;
+ assert( n>=0 );
+ assert( pTos->flags==MEM_Int );
+ pRec = &pTos[-n];
+ assert( pRec>=p->aStack );
+ for(i=0; i<n; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
+ azArgv[i] = 0;
}else{
- Stringify(p, i);
+ Stringify(pRec);
+ azArgv[i] = pRec->z;
}
}
- i = aStack[p->tos].i;
- VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; )
+ i = pTos->i;
+ assert( i>=0 && i<p->agg.nMem );
ctx.pFunc = (FuncDef*)pOp->p3;
pMem = &p->agg.pCurrent->aMem[i];
- ctx.z = pMem->s.z;
+ ctx.s.z = pMem->zShort; /* Space used for small aggregate contexts */
ctx.pAgg = pMem->z;
- ctx.cnt = ++pMem->s.i;
+ ctx.cnt = ++pMem->i;
ctx.isError = 0;
ctx.isStep = 1;
- (ctx.pFunc->xStep)(&ctx, n, (const char**)&zStack[p->tos-n]);
+ (ctx.pFunc->xStep)(&ctx, n, (const char**)azArgv);
pMem->z = ctx.pAgg;
- pMem->s.flags = STK_AggCtx;
- sqliteVdbePopStack(p, n+1);
+ pMem->flags = MEM_AggCtx;
+ popStack(&pTos, n+1);
if( ctx.isError ){
rc = SQLITE_ERROR;
}
@@ -4443,15 +4479,14 @@ case OP_AggFunc: {
** in between an AggNext and an AggReset.
*/
case OP_AggFocus: {
- int tos = p->tos;
AggElem *pElem;
char *zKey;
int nKey;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- Stringify(p, tos);
- zKey = zStack[tos];
- nKey = aStack[tos].n;
+ assert( pTos>=p->aStack );
+ Stringify(pTos);
+ zKey = pTos->z;
+ nKey = pTos->n;
pElem = sqliteHashFind(&p->agg.hash, zKey, nKey);
if( pElem ){
p->agg.pCurrent = pElem;
@@ -4460,7 +4495,8 @@ case OP_AggFocus: {
AggInsert(&p->agg, zKey, nKey);
if( sqlite_malloc_failed ) goto no_mem;
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
@@ -4471,32 +4507,22 @@ case OP_AggFocus: {
*/
case OP_AggSet: {
AggElem *pFocus = AggInFocus(p->agg);
+ Mem *pMem;
int i = pOp->p2;
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
+ assert( pTos>=p->aStack );
if( pFocus==0 ) goto no_mem;
- if( VERIFY( i>=0 && ) i<p->agg.nMem ){
- Mem *pMem = &pFocus->aMem[i];
- char *zOld;
- if( pMem->s.flags & STK_Dyn ){
- zOld = pMem->z;
- }else{
- zOld = 0;
- }
- Deephemeralize(p, tos);
- pMem->s = aStack[tos];
- if( pMem->s.flags & STK_Dyn ){
- pMem->z = zStack[tos];
- zStack[tos] = 0;
- aStack[tos].flags = 0;
- }else if( pMem->s.flags & (STK_Static|STK_AggCtx) ){
- pMem->z = zStack[tos];
- }else if( pMem->s.flags & STK_Str ){
- pMem->z = pMem->s.z;
- }
- if( zOld ) sqliteFree(zOld);
- }
- POPSTACK;
+ assert( i>=0 && i<p->agg.nMem );
+ Deephemeralize(pTos);
+ pMem = &pFocus->aMem[i];
+ Release(pMem);
+ *pMem = *pTos;
+ if( pMem->flags & MEM_Dyn ){
+ pTos->flags = MEM_Null;
+ }else if( pMem->flags & MEM_Short ){
+ pMem->z = pMem->zShort;
+ }
+ Release(pTos);
+ pTos--;
break;
}
@@ -4508,15 +4534,16 @@ case OP_AggSet: {
*/
case OP_AggGet: {
AggElem *pFocus = AggInFocus(p->agg);
+ Mem *pMem;
int i = pOp->p2;
- int tos = ++p->tos;
if( pFocus==0 ) goto no_mem;
- if( VERIFY( i>=0 && ) i<p->agg.nMem ){
- Mem *pMem = &pFocus->aMem[i];
- aStack[tos] = pMem->s;
- zStack[tos] = pMem->z;
- aStack[tos].flags &= ~STK_Dyn;
- aStack[tos].flags |= STK_Ephem;
+ assert( i>=0 && i<p->agg.nMem );
+ pTos++;
+ pMem = &pFocus->aMem[i];
+ *pTos = *pMem;
+ if( pTos->flags & MEM_Str ){
+ pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
+ pTos->flags |= MEM_Ephem;
}
break;
}
@@ -4552,22 +4579,20 @@ case OP_AggNext: {
int freeCtx;
if( p->agg.apFunc[i]==0 ) continue;
if( p->agg.apFunc[i]->xFinalize==0 ) continue;
- ctx.s.flags = STK_Null;
- ctx.z = 0;
+ ctx.s.flags = MEM_Null;
+ ctx.s.z = aMem[i].zShort;
ctx.pAgg = (void*)aMem[i].z;
- freeCtx = aMem[i].z && aMem[i].z!=aMem[i].s.z;
- ctx.cnt = aMem[i].s.i;
+ freeCtx = aMem[i].z && aMem[i].z!=aMem[i].zShort;
+ ctx.cnt = aMem[i].i;
ctx.isStep = 0;
ctx.pFunc = p->agg.apFunc[i];
(*p->agg.apFunc[i]->xFinalize)(&ctx);
if( freeCtx ){
sqliteFree( aMem[i].z );
}
- aMem[i].s = ctx.s;
- aMem[i].z = ctx.z;
- if( (aMem[i].s.flags & STK_Str) &&
- (aMem[i].s.flags & (STK_Dyn|STK_Static|STK_Ephem))==0 ){
- aMem[i].z = aMem[i].s.z;
+ aMem[i] = ctx.s;
+ if( aMem[i].flags & MEM_Short ){
+ aMem[i].z = aMem[i].zShort;
}
}
}
@@ -4595,11 +4620,11 @@ case OP_SetInsert: {
if( pOp->p3 ){
sqliteHashInsert(&p->aSet[i].hash, pOp->p3, strlen(pOp->p3)+1, p);
}else{
- int tos = p->tos;
- if( tos<0 ) goto not_enough_stack;
- Stringify(p, tos);
- sqliteHashInsert(&p->aSet[i].hash, zStack[tos], aStack[tos].n, p);
- POPSTACK;
+ assert( pTos>=p->aStack );
+ Stringify(pTos);
+ sqliteHashInsert(&p->aSet[i].hash, pTos->z, pTos->n, p);
+ Release(pTos);
+ pTos--;
}
if( sqlite_malloc_failed ) goto no_mem;
break;
@@ -4613,14 +4638,13 @@ case OP_SetInsert: {
*/
case OP_SetFound: {
int i = pOp->p1;
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- Stringify(p, tos);
- if( i>=0 && i<p->nSet &&
- sqliteHashFind(&p->aSet[i].hash, zStack[tos], aStack[tos].n)){
+ assert( pTos>=p->aStack );
+ Stringify(pTos);
+ if( i>=0 && i<p->nSet && sqliteHashFind(&p->aSet[i].hash, pTos->z, pTos->n)){
pc = pOp->p2 - 1;
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
@@ -4632,14 +4656,14 @@ case OP_SetFound: {
*/
case OP_SetNotFound: {
int i = pOp->p1;
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- Stringify(p, tos);
+ assert( pTos>=p->aStack );
+ Stringify(pTos);
if( i<0 || i>=p->nSet ||
- sqliteHashFind(&p->aSet[i].hash, zStack[tos], aStack[tos].n)==0 ){
+ sqliteHashFind(&p->aSet[i].hash, pTos->z, pTos->n)==0 ){
pc = pOp->p2 - 1;
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
@@ -4658,7 +4682,6 @@ case OP_SetNotFound: {
case OP_SetFirst:
case OP_SetNext: {
Set *pSet;
- int tos;
CHECK_FOR_INTERRUPT;
if( pOp->p1<0 || pOp->p1>=p->nSet ){
if( pOp->opcode==OP_SetFirst ) pc = pOp->p2 - 1;
@@ -4672,7 +4695,7 @@ case OP_SetNext: {
break;
}
}else{
- VERIFY( if( pSet->prev==0 ) goto bad_instruction; )
+ assert( pSet->prev );
pSet->prev = sqliteHashNext(pSet->prev);
if( pSet->prev==0 ){
break;
@@ -4680,10 +4703,10 @@ case OP_SetNext: {
pc = pOp->p2 - 1;
}
}
- tos = ++p->tos;
- zStack[tos] = sqliteHashKey(pSet->prev);
- aStack[tos].n = sqliteHashKeysize(pSet->prev);
- aStack[tos].flags = STK_Str | STK_Ephem;
+ pTos++;
+ pTos->z = sqliteHashKey(pSet->prev);
+ pTos->n = sqliteHashKeysize(pSet->prev);
+ pTos->flags = MEM_Str | MEM_Ephem;
break;
}
@@ -4700,6 +4723,36 @@ case OP_Vacuum: {
break;
}
+/* Opcode: StackDepth * * *
+**
+** Push an integer onto the stack which is the depth of the stack prior
+** to that integer being pushed.
+*/
+case OP_StackDepth: {
+ int depth = (&pTos[1]) - p->aStack;
+ pTos++;
+ pTos->i = depth;
+ pTos->flags = MEM_Int;
+ break;
+}
+
+/* Opcode: StackReset * * *
+**
+** Pop a single integer off of the stack. Then pop the stack
+** as many times as necessary to get the depth of the stack down
+** to the value of the integer that was popped.
+*/
+case OP_StackReset: {
+ int depth, goal;
+ assert( pTos>=p->aStack );
+ Integerify(pTos);
+ goal = pTos->i;
+ depth = (&pTos[1]) - p->aStack;
+ assert( goal<depth );
+ popStack(&pTos, depth-goal);
+ break;
+}
+
/* An other opcode is illegal...
*/
default: {
@@ -4735,43 +4788,61 @@ 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 ){
+ assert( pTos->flags!=0 ); /* Must define some type */
+ if( pTos->flags & MEM_Str ){
+ int x = pTos->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short);
+ assert( x!=0 ); /* Strings must define a string subtype */
+ assert( (x & (x-1))==0 ); /* Only one string subtype can be defined */
+ assert( pTos->z!=0 ); /* Strings must have a value */
+ /* Mem.z points to Mem.zShort iff the subtype is MEM_Short */
+ assert( (pTos->flags & MEM_Short)==0 || pTos->z==pTos->zShort );
+ assert( (pTos->flags & MEM_Short)!=0 || pTos->z!=pTos->zShort );
+ }else{
+ /* Cannot define a string subtype for non-string objects */
+ assert( (pTos->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short))==0 );
+ }
+ /* MEM_Null excludes all other types */
+ assert( pTos->flags==MEM_Null || (pTos->flags&MEM_Null)==0 );
+ }
if( pc<-1 || pc>=p->nOp ){
sqliteSetString(&p->zErrMsg, "jump destination out of range", (char*)0);
rc = SQLITE_INTERNAL;
}
- if( p->trace && p->tos>=0 ){
+ if( p->trace && pTos>=p->aStack ){
int i;
fprintf(p->trace, "Stack:");
- for(i=p->tos; i>=0 && i>p->tos-5; i--){
- if( aStack[i].flags & STK_Null ){
+ for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){
+ if( pTos[i].flags & MEM_Null ){
fprintf(p->trace, " NULL");
- }else if( (aStack[i].flags & (STK_Int|STK_Str))==(STK_Int|STK_Str) ){
- fprintf(p->trace, " si:%d", aStack[i].i);
- }else if( aStack[i].flags & STK_Int ){
- fprintf(p->trace, " i:%d", aStack[i].i);
- }else if( aStack[i].flags & STK_Real ){
- fprintf(p->trace, " r:%g", aStack[i].r);
- }else if( aStack[i].flags & STK_Str ){
+ }else if( (pTos[i].flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
+ fprintf(p->trace, " si:%d", pTos[i].i);
+ }else if( pTos[i].flags & MEM_Int ){
+ fprintf(p->trace, " i:%d", pTos[i].i);
+ }else if( pTos[i].flags & MEM_Real ){
+ fprintf(p->trace, " r:%g", pTos[i].r);
+ }else if( pTos[i].flags & MEM_Str ){
int j, k;
char zBuf[100];
zBuf[0] = ' ';
- if( aStack[i].flags & STK_Dyn ){
+ if( pTos[i].flags & MEM_Dyn ){
zBuf[1] = 'z';
- assert( (aStack[i].flags & (STK_Static|STK_Ephem))==0 );
- }else if( aStack[i].flags & STK_Static ){
+ assert( (pTos[i].flags & (MEM_Static|MEM_Ephem))==0 );
+ }else if( pTos[i].flags & MEM_Static ){
zBuf[1] = 't';
- assert( (aStack[i].flags & (STK_Dyn|STK_Ephem))==0 );
- }else if( aStack[i].flags & STK_Ephem ){
+ assert( (pTos[i].flags & (MEM_Dyn|MEM_Ephem))==0 );
+ }else if( pTos[i].flags & MEM_Ephem ){
zBuf[1] = 'e';
- assert( (aStack[i].flags & (STK_Static|STK_Dyn))==0 );
+ assert( (pTos[i].flags & (MEM_Static|MEM_Dyn))==0 );
}else{
zBuf[1] = 's';
}
zBuf[2] = '[';
k = 3;
- for(j=0; j<20 && j<aStack[i].n; j++){
- int c = zStack[i][j];
- if( c==0 && j==aStack[i].n-1 ) break;
+ for(j=0; j<20 && j<pTos[i].n; j++){
+ int c = pTos[i].z[j];
+ if( c==0 && j==pTos[i].n-1 ) break;
if( isprint(c) && !isspace(c) ){
zBuf[k++] = c;
}else{
@@ -4794,6 +4865,7 @@ default: {
/* If we reach this point, it means that execution is finished.
*/
vdbe_halt:
+ CHECK_FOR_INTERRUPT
if( rc ){
p->rc = rc;
rc = SQLITE_ERROR;
@@ -4801,6 +4873,7 @@ vdbe_halt:
rc = SQLITE_DONE;
}
p->magic = VDBE_MAGIC_HALT;
+ p->pTos = pTos;
return rc;
/* Jump to here if a malloc() fails. It's hard to get a malloc()
@@ -4822,6 +4895,7 @@ abort_due_to_misuse:
*/
abort_due_to_error:
if( p->zErrMsg==0 ){
+ if( sqlite_malloc_failed ) rc = SQLITE_NOMEM;
sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
}
goto vdbe_halt;
@@ -4839,23 +4913,4 @@ abort_due_to_interrupt:
}
sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
goto vdbe_halt;
-
- /* Jump to here if a operator is encountered that requires more stack
- ** operands than are currently available on the stack.
- */
-not_enough_stack:
- sqlite_snprintf(sizeof(zBuf),zBuf,"%d",pc);
- sqliteSetString(&p->zErrMsg, "too few operands on stack at ", zBuf, (char*)0);
- rc = SQLITE_INTERNAL;
- goto vdbe_halt;
-
- /* Jump here if an illegal or illformed instruction is executed.
- */
-VERIFY(
-bad_instruction:
- sqlite_snprintf(sizeof(zBuf),zBuf,"%d",pc);
- sqliteSetString(&p->zErrMsg, "illegal operation at ", zBuf, (char*)0);
- rc = SQLITE_INTERNAL;
- goto vdbe_halt;
-)
}