summaryrefslogtreecommitdiff
path: root/ext/sqlite/libsqlite/src/vdbe.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sqlite/libsqlite/src/vdbe.c')
-rw-r--r--ext/sqlite/libsqlite/src/vdbe.c133
1 files changed, 84 insertions, 49 deletions
diff --git a/ext/sqlite/libsqlite/src/vdbe.c b/ext/sqlite/libsqlite/src/vdbe.c
index bd080f37d3..b0dd210049 100644
--- a/ext/sqlite/libsqlite/src/vdbe.c
+++ b/ext/sqlite/libsqlite/src/vdbe.c
@@ -363,42 +363,6 @@ static Sorter *Merge(Sorter *pLeft, Sorter *pRight){
}
/*
-** Convert an integer in between the native integer format and
-** the bigEndian format used as the record number for tables.
-**
-** The bigEndian format (most significant byte first) is used for
-** record numbers so that records will sort into the correct order
-** even though memcmp() is used to compare the keys. On machines
-** whose native integer format is little endian (ex: i486) the
-** order of bytes is reversed. On native big-endian machines
-** (ex: Alpha, Sparc, Motorola) the byte order is the same.
-**
-** This function is its own inverse. In other words
-**
-** X == byteSwap(byteSwap(X))
-*/
-static int byteSwap(int x){
- union {
- char zBuf[sizeof(int)];
- int i;
- } ux;
- ux.zBuf[3] = x&0xff;
- ux.zBuf[2] = (x>>8)&0xff;
- ux.zBuf[1] = (x>>16)&0xff;
- ux.zBuf[0] = (x>>24)&0xff;
- return ux.i;
-}
-
-/*
-** When converting from the native format to the key format and back
-** again, in addition to changing the byte order we invert the high-order
-** bit of the most significant byte. This causes negative numbers to
-** sort before positive numbers in the memcmp() function.
-*/
-#define keyToInt(X) (byteSwap(X) ^ 0x80000000)
-#define intToKey(X) (byteSwap((X) ^ 0x80000000))
-
-/*
** 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.
@@ -1157,7 +1121,9 @@ case OP_Function: {
ctx.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]);
+ if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
sqliteVdbePopStack(p, n);
p->tos++;
aStack[p->tos] = ctx.s;
@@ -1831,8 +1797,8 @@ case OP_IfNot: {
/* Opcode: IsNull P1 P2 *
**
** If any of the top abs(P1) values on the stack are NULL, then jump
-** to P2. The stack is popped P1 times if P1>0. If P1<0 then all values
-** are left unchanged on the stack.
+** to P2. Pop the stack P1 times if P1>0. If P1<0 leave the stack
+** unchanged.
*/
case OP_IsNull: {
int i, cnt;
@@ -1851,14 +1817,18 @@ case OP_IsNull: {
/* Opcode: NotNull P1 P2 *
**
-** Jump to P2 if the top value on the stack is not NULL. Pop the
-** stack if P1 is greater than zero. If P1 is less than or equal to
-** zero then leave the value on the stack.
+** Jump to P2 if the top P1 values on the stack are all not NULL. Pop the
+** stack if P1 times if P1 is greater than zero. If P1 is less than
+** zero then leave the stack unchanged.
*/
case OP_NotNull: {
- VERIFY( if( p->tos<0 ) goto not_enough_stack; )
- if( (aStack[p->tos].flags & STK_Null)==0 ) pc = pOp->p2-1;
- if( pOp->p1>0 ){ POPSTACK; }
+ 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++){}
+ if( i>=cnt ) pc = pOp->p2-1;
+ if( pOp->p1>0 ) sqliteVdbePopStack(p, cnt);
break;
}
@@ -2597,8 +2567,15 @@ case OP_MoveTo: {
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( pOp->p2==0 && pOp->opcode==OP_MoveTo ){
+ pC->movetoTarget = iKey;
+ pC->deferredMoveto = 1;
+ POPSTACK;
+ break;
+ }
sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res);
pC->lastRecno = aStack[tos].i;
pC->recnoIsValid = res==0;
@@ -2607,7 +2584,7 @@ case OP_MoveTo: {
sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
pC->recnoIsValid = 0;
}
- pC->nullRow = 0;
+ pC->deferredMoveto = 0;
sqlite_search_count++;
oc = pOp->opcode;
if( oc==OP_MoveTo && res<0 ){
@@ -2682,6 +2659,7 @@ case OP_Found: {
Stringify(p, tos);
rx = sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
alreadyExists = rx==SQLITE_OK && res==0;
+ pC->deferredMoveto = 0;
}
if( pOp->opcode==OP_Found ){
if( alreadyExists ) pc = pOp->p2 - 1;
@@ -2743,6 +2721,7 @@ case OP_IsUnique: {
/* 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( p->aCsr[i].deferredMoveto==0 );
rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res<0 ){
@@ -2911,6 +2890,7 @@ case OP_NewRecno: {
}
}
pC->recnoIsValid = 0;
+ pC->deferredMoveto = 0;
}
p->tos++;
aStack[p->tos].i = v;
@@ -2993,6 +2973,7 @@ case OP_PutStrKey: {
zStack[tos], aStack[tos].n);
}
pC->recnoIsValid = 0;
+ pC->deferredMoveto = 0;
}
POPSTACK;
POPSTACK;
@@ -3019,6 +3000,7 @@ case OP_Delete: {
assert( i>=0 && i<p->nCursor );
pC = &p->aCsr[i];
if( pC->pCursor!=0 ){
+ sqliteVdbeCursorMoveto(pC);
rc = sqliteBtreeDelete(pC->pCursor);
pC->nextRowidValid = 0;
}
@@ -3049,6 +3031,16 @@ case OP_KeyAsData: {
** If the cursor is not pointing to a valid row, a NULL is pushed
** onto the stack.
*/
+/* Opcode: RowKey P1 * *
+**
+** Push onto the stack the complete row key for cursor P1.
+** There is no interpretation of the key. It is just copied
+** onto the stack exactly as it is found in the database file.
+**
+** If the cursor is not pointing to a valid row, a NULL is pushed
+** onto the stack.
+*/
+case OP_RowKey:
case OP_RowData: {
int i = pOp->p1;
int tos = ++p->tos;
@@ -3061,10 +3053,11 @@ case OP_RowData: {
aStack[tos].flags = STK_Null;
}else if( pC->pCursor!=0 ){
BtCursor *pCrsr = pC->pCursor;
+ sqliteVdbeCursorMoveto(pC);
if( pC->nullRow ){
aStack[tos].flags = STK_Null;
break;
- }else if( pC->keyAsData ){
+ }else if( pC->keyAsData || pOp->opcode==OP_RowKey ){
sqliteBtreeKeySize(pCrsr, &n);
}else{
sqliteBtreeDataSize(pCrsr, &n);
@@ -3079,7 +3072,7 @@ case OP_RowData: {
aStack[tos].flags = STK_Str | STK_Dyn;
zStack[tos] = z;
}
- if( pC->keyAsData ){
+ if( pC->keyAsData || pOp->opcode==OP_RowKey ){
sqliteBtreeKey(pCrsr, 0, n, zStack[tos]);
}else{
sqliteBtreeData(pCrsr, 0, n, zStack[tos]);
@@ -3131,6 +3124,7 @@ case OP_Column: {
zRec = zStack[tos+i];
payloadSize = aStack[tos+i].n;
}else if( (pC = &p->aCsr[i])->pCursor!=0 ){
+ sqliteVdbeCursorMoveto(pC);
zRec = 0;
pCrsr = pC->pCursor;
if( pC->nullRow ){
@@ -3237,7 +3231,9 @@ case OP_Recno: {
int v;
assert( i>=0 && i<p->nCursor );
- if( (pC = &p->aCsr[i])->recnoIsValid ){
+ pC = &p->aCsr[i];
+ sqliteVdbeCursorMoveto(pC);
+ if( pC->recnoIsValid ){
v = pC->lastRecno;
}else if( pC->pseudoTable ){
v = keyToInt(pC->iKey);
@@ -3276,6 +3272,7 @@ case OP_FullKey: {
int amt;
char *z;
+ sqliteVdbeCursorMoveto(&p->aCsr[i]);
sqliteBtreeKeySize(pCrsr, &amt);
if( amt<=0 ){
rc = SQLITE_CORRUPT;
@@ -3329,7 +3326,8 @@ case OP_Last: {
if( (pCrsr = pC->pCursor)!=0 ){
int res;
rc = sqliteBtreeLast(pCrsr, &res);
- p->aCsr[i].nullRow = res;
+ pC->nullRow = res;
+ pC->deferredMoveto = 0;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
@@ -3359,6 +3357,7 @@ case OP_Rewind: {
rc = sqliteBtreeFirst(pCrsr, &res);
pC->atFirst = res==0;
pC->nullRow = res;
+ pC->deferredMoveto = 0;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
@@ -3397,6 +3396,7 @@ case OP_Next: {
if( pC->nullRow ){
res = 1;
}else{
+ assert( pC->deferredMoveto==0 );
rc = pOp->opcode==OP_Next ? sqliteBtreeNext(pCrsr, &res) :
sqliteBtreePrevious(pCrsr, &res);
pC->nullRow = res;
@@ -3458,6 +3458,7 @@ case OP_IdxPut: {
}
}
rc = sqliteBtreeInsert(pCrsr, zKey, nKey, "", 0);
+ assert( p->aCsr[i].deferredMoveto==0 );
}
POPSTACK;
break;
@@ -3479,6 +3480,7 @@ case OP_IdxDelete: {
if( rx==SQLITE_OK && res==0 ){
rc = sqliteBtreeDelete(pCrsr);
}
+ assert( p->aCsr[i].deferredMoveto==0 );
}
POPSTACK;
break;
@@ -3501,6 +3503,7 @@ case OP_IdxRecno: {
if( VERIFY( i>=0 && i<p->nCursor && ) (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;
@@ -3550,6 +3553,7 @@ case OP_IdxGE: {
int res, rc;
Stringify(p, tos);
+ assert( p->aCsr[i].deferredMoveto==0 );
rc = sqliteBtreeKeyCompare(pCrsr, zStack[tos], aStack[tos].n, 4, &res);
if( rc!=SQLITE_OK ){
break;
@@ -3567,6 +3571,37 @@ case OP_IdxGE: {
break;
}
+/* 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
+** that key. If any of the first P1 fields are NULL, then a jump is made
+** to address P2. Otherwise we fall straight through.
+**
+** The index entry is always popped from the stack.
+*/
+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;
+ for(k=0; k<n && i>0; i--){
+ if( z[k]=='a' ){
+ pc = pOp->p2-1;
+ break;
+ }
+ while( k<n && z[k] ){ k++; }
+ k++;
+ }
+ POPSTACK;
+ break;
+}
+
/* Opcode: Destroy P1 P2 *
**
** Delete an entire database table or index whose root page in the database