DBD-SQLite2
view release on metacpan or search on metacpan
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** The code in this file implements execution method of the
** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c")
** handles housekeeping details such as creating and deleting
** VDBE instances. This file is solely interested in executing
** the VDBE program.
**
** In the external interface, an "sqlite_vm*" is an opaque pointer
** to a VDBE.
**
** The SQL parser generates a program which is then executed by
** the VDBE to do the work of the SQL statement. VDBE programs are
** similar in form to assembly language. The program consists of
** a linear sequence of operations. Each operation has an opcode
** and 3 operands. Operands P1 and P2 are integers. Operand P3
** is a null-terminated string. The P2 operand must be non-negative.
** Opcodes will typically ignore one or more operands. Many opcodes
** ignore all three operands.
**
** Computation results are stored on a stack. Each entry on the
** stack is either an integer, a null-terminated string, a floating point
** number, or the SQL "NULL" value. An inplicit conversion from one
** type to the other occurs as necessary.
**
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files. The formatting
** of the code in this file is, therefore, important. See other comments
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"
/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode. The test
** procedures use this information to make sure that indices are
** working correctly. This variable has no function other than to
** help verify the correct operation of the library.
*/
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.
**
** The return vale will be either SQLITE_BUSY, SQLITE_DONE,
** SQLITE_ROW, SQLITE_ERROR, or SQLITE_MISUSE.
**
** SQLITE_BUSY means that the virtual machine attempted to open
** a locked database and there is no busy callback registered.
** Call sqlite_step() again to retry the open. *pN is set to 0
** and *pazColName and *pazValue are both set to NULL.
**
** SQLITE_DONE means that the virtual machine has finished
** executing. sqlite_step() should not be called again on this
** virtual machine. *pN and *pazColName are set appropriately
** but *pazValue is set to NULL.
**
** SQLITE_ROW means that the virtual machine has generated another
** row of the result set. *pN is set to the number of columns in
** the row. *pazColName is set to the names of the columns followed
** by the column datatypes. *pazValue is set to the values of each
** column in the row. The value of the i-th column is (*pazValue)[i].
** The name of the i-th column is (*pazColName)[i] and the datatype
** of the i-th column is (*pazColName)[i+*pN].
**
** SQLITE_ERROR means that a run-time error (such as a constraint
** violation) has occurred. The details of the error will be returned
** by the next call to sqlite_finalize(). sqlite_step() should not
** be called again on the VM.
**
** SQLITE_MISUSE means that the this routine was called inappropriately.
** Perhaps it was called on a virtual machine that had already been
** finalized or on one that had previously returned SQLITE_ERROR or
** SQLITE_DONE. Or it could be the case the the same database connection
** is being used simulataneously by two or more threads.
*/
int sqlite_step(
sqlite_vm *pVm, /* The virtual machine to execute */
int *pN, /* OUT: Number of columns in result */
const char ***pazValue, /* OUT: Column data */
const char ***pazColName /* OUT: Column names and datatypes */
){
Vdbe *p = (Vdbe*)pVm;
sqlite *db;
/*
** The parameters are pointers to the head of two sorted lists
** of Sorter structures. Merge these two lists together and return
** a single sorted list. This routine forms the core of the merge-sort
** algorithm.
**
** In the case of a tie, left sorts in front of right.
*/
static Sorter *Merge(Sorter *pLeft, Sorter *pRight){
Sorter sHead;
Sorter *pTail;
pTail = &sHead;
pTail->pNext = 0;
while( pLeft && pRight ){
int c = sqliteSortCompare(pLeft->zKey, pRight->zKey);
if( c<=0 ){
pTail->pNext = pLeft;
pLeft = pLeft->pNext;
}else{
pTail->pNext = pRight;
pRight = pRight->pNext;
}
pTail = pTail->pNext;
}
if( pLeft ){
pTail->pNext = pLeft;
}else if( pRight ){
pTail->pNext = pRight;
}
return sHead.pNext;
}
/*
** 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
** under windows, and CR under mac. This routine accepts any of these
** character sequences as an EOL mark. The EOL mark is replaced by
** a single LF character in zBuf.
*/
static char *vdbe_fgets(char *zBuf, int nBuf, FILE *in){
int i, c;
for(i=0; i<nBuf-1 && (c=getc(in))!=EOF; i++){
zBuf[i] = c;
if( c=='\r' || c=='\n' ){
if( c=='\r' ){
zBuf[i] = '\n';
c = getc(in);
if( c!=EOF && c!='\n' ) ungetc(c, in);
}
i++;
break;
}
}
zBuf[i] = 0;
return i>0 ? zBuf : 0;
}
/*
** Make sure there is space in the Vdbe structure to hold at least
** mxCursor cursors. If there is not currently enough space, then
** allocate more.
**
** If a memory allocation error occurs, return 1. Return 0 if
** everything works.
*/
static int expandCursorArraySize(Vdbe *p, int mxCursor){
if( mxCursor>=p->nCursor ){
Cursor *aCsr = sqliteRealloc( p->aCsr, (mxCursor+1)*sizeof(Cursor) );
if( aCsr==0 ) return 1;
p->aCsr = aCsr;
memset(&p->aCsr[p->nCursor], 0, sizeof(Cursor)*(mxCursor+1-p->nCursor));
p->nCursor = mxCursor+1;
}
return 0;
}
#ifdef VDBE_PROFILE
/*
** The following routine only works on pentium-class processors.
** It uses the RDTSC opcode to read cycle count value out of the
** processor and returns that value. This can be used for high-res
** profiling.
*/
__inline__ unsigned long long int hwtime(void){
unsigned long long int x;
__asm__("rdtsc\n\t"
"mov %%edx, %%ecx\n\t"
:"=A" (x));
return x;
}
#endif
/*
** The CHECK_FOR_INTERRUPT macro defined here looks to see if the
** sqlite_interrupt() routine has been called. If it has been, then
** processing of the VDBE program is interrupted.
**
** This macro added to every instruction that does a jump in order to
** implement a loop. This test used to be on every single instruction,
** but that meant we more testing that we needed. By only testing the
** flag on jump instructions, we get a (small) speed improvement.
*/
#define CHECK_FOR_INTERRUPT \
if( db->flags & SQLITE_Interrupt ) goto abort_due_to_interrupt;
/*
** Execute as much of a VDBE program as we can then return.
**
** sqliteVdbeMakeReady() must be called before this routine in order to
** close the program with a final OP_Halt and to set up the callbacks
** and the error message pointer.
**
** Whenever a row or result data is available, this routine will either
** invoke the result callback (if there is one) or return with
** SQLITE_ROW.
**
** If an attempt is made to open a locked database, then this routine
** will either invoke the busy callback (if there is one) or it will
** return SQLITE_BUSY.
** SUMMARY:
**
** Formatting is important to scripts that scan this file.
** Do not deviate from the formatting style currently in use.
**
*****************************************************************************/
/* Opcode: Goto * P2 *
**
** An unconditional jump to address P2.
** The next instruction executed will be
** the one at index P2 from the beginning of
** the program.
*/
case OP_Goto: {
CHECK_FOR_INTERRUPT;
pc = pOp->p2 - 1;
break;
}
/* Opcode: Gosub * P2 *
**
** Push the current address plus 1 onto the return address stack
** and then jump to address P2.
**
** The return address stack is of limited depth. If too many
** OP_Gosub operations occur without intervening OP_Returns, then
** the return address stack will fill up and processing will abort
** with a fatal error.
*/
case OP_Gosub: {
if( p->returnDepth>=sizeof(p->returnStack)/sizeof(p->returnStack[0]) ){
sqliteSetString(&p->zErrMsg, "return address stack overflow", (char*)0);
p->rc = SQLITE_INTERNAL;
return SQLITE_ERROR;
}
p->returnStack[p->returnDepth++] = pc+1;
pc = pOp->p2 - 1;
break;
}
/* Opcode: Return * * *
**
** Jump immediately to the next instruction after the last unreturned
** OP_Gosub. If an OP_Return has occurred for all OP_Gosubs, then
** processing aborts with a fatal error.
*/
case OP_Return: {
if( p->returnDepth<=0 ){
sqliteSetString(&p->zErrMsg, "return address stack underflow", (char*)0);
p->rc = SQLITE_INTERNAL;
return SQLITE_ERROR;
}
p->returnDepth--;
pc = p->returnStack[p->returnDepth] - 1;
break;
}
/* Opcode: Halt P1 P2 *
**
** Exit immediately. All open cursors, Lists, Sorts, etc are closed
** automatically.
**
** P1 is the result code returned by sqlite_exec(). For a normal
** halt, this should be SQLITE_OK (0). For errors, it can be some
** other value. If P1!=0 then P2 will determine whether or not to
** rollback the current transaction. Do not rollback if P2==OE_Fail.
** Do the rollback if P2==OE_Rollback. If P2==OE_Abort, then back
** out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction.
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program. So a jump past the last instruction of the program
** is the same as executing Halt.
*/
case OP_Halt: {
p->magic = VDBE_MAGIC_HALT;
p->pTos = pTos;
if( pOp->p1!=SQLITE_OK ){
p->rc = pOp->p1;
p->errorAction = pOp->p2;
if( pOp->p3 ){
sqliteSetString(&p->zErrMsg, pOp->p3, (char*)0);
}
return SQLITE_ERROR;
}else{
p->rc = SQLITE_OK;
return SQLITE_DONE;
}
}
/* Opcode: Integer P1 * P3
**
** The integer value P1 is pushed onto the stack. If P3 is not zero
** then it is assumed to be a string representation of the same integer.
*/
case OP_Integer: {
pTos++;
pTos->i = pOp->p1;
pTos->flags = MEM_Int;
if( pOp->p3 ){
pTos->z = pOp->p3;
pTos->flags |= MEM_Str | MEM_Static;
pTos->n = strlen(pOp->p3)+1;
}
break;
}
/* Opcode: String * * P3
**
** The string value P3 is pushed onto the stack. If P3==0 then a
** NULL is pushed onto the stack.
*/
case OP_String: {
char *z = pOp->p3;
pTos++;
if( z==0 ){
pTos->flags = MEM_Null;
}else{
pTos->z = z;
pTos->n = strlen(z) + 1;
** Begin a transaction. The transaction ends when a Commit or Rollback
** opcode is encountered. Depending on the ON CONFLICT setting, the
** transaction might also be rolled back if an error is encountered.
**
** P1 is the index of the database file on which the transaction is
** started. Index 0 is the main database file and index 1 is the
** file used for temporary tables.
**
** A write lock is obtained on the database file when a transaction is
** started. No other process can read or write the file while the
** transaction is underway. Starting a transaction also creates a
** rollback journal. A transaction must be started before any changes
** can be made to the database.
*/
case OP_Transaction: {
int busy = 1;
int i = pOp->p1;
assert( i>=0 && i<db->nDb );
if( db->aDb[i].inTrans ) break;
while( db->aDb[i].pBt!=0 && busy ){
rc = sqliteBtreeBeginTrans(db->aDb[i].pBt);
switch( rc ){
case SQLITE_BUSY: {
if( db->xBusyCallback==0 ){
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);
busy = 0;
}
break;
}
case SQLITE_READONLY: {
rc = SQLITE_OK;
/* Fall thru into the next case */
}
case SQLITE_OK: {
p->inTempTrans = 0;
busy = 0;
break;
}
default: {
goto abort_due_to_error;
}
}
}
db->aDb[i].inTrans = 1;
p->undoTransOnError = 1;
break;
}
/* Opcode: Commit * * *
**
** Cause all modifications to the database that have been made since the
** last Transaction to actually take effect. No additional modifications
** are allowed until another transaction is started. The Commit instruction
** deletes the journal file and releases the write lock on the database.
** A read lock continues to be held if there are still cursors open.
*/
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);
db->aDb[i].inTrans = 0;
}
}
if( rc==SQLITE_OK ){
sqliteCommitInternalChanges(db);
}else{
sqliteRollbackAll(db);
}
break;
}
/* Opcode: Rollback P1 * *
**
** Cause all modifications to the database that have been made since the
** last Transaction to be undone. The database is restored to its state
** before the Transaction opcode was executed. No additional modifications
** are allowed until another transaction is started.
**
** P1 is the index of the database file that is committed. An index of 0
** is used for the main database and an index of 1 is used for the file used
** to hold temporary tables.
**
** This instruction automatically closes all cursors and releases both
** the read and write locks on the indicated database.
*/
case OP_Rollback: {
sqliteRollbackAll(db);
break;
}
/* Opcode: ReadCookie P1 P2 *
**
** Read cookie number P2 from database P1 and push it onto the stack.
** P2==0 is the schema version. P2==1 is the database format.
** P2==2 is the recommended pager cache size, and so forth. P1==0 is
** the main database file and P1==1 is the database file used to store
** temporary tables.
**
** There must be a read-lock on the database (either a transaction
** must be started or there must be an open cursor) before
** executing this instruction.
*/
case OP_ReadCookie: {
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);
pTos++;
pTos->i = aMeta[1+pOp->p2];
pTos->flags = MEM_Int;
break;
}
/* Opcode: SetCookie P1 P2 *
**
** Write the top of the stack into cookie number P2 of database P1.
** P2==0 is the schema version. P2==1 is the database format.
** P2==2 is the recommended pager cache size, and so forth. P1==0 is
** the main database file and P1==1 is the database file used to store
** temporary tables.
**
** A transaction must be started before executing this opcode.
*/
case OP_SetCookie: {
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 );
assert( pTos>=p->aStack );
Integerify(pTos)
rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
if( rc==SQLITE_OK ){
aMeta[1+pOp->p2] = pTos->i;
rc = sqliteBtreeUpdateMeta(db->aDb[pOp->p1].pBt, aMeta);
}
Release(pTos);
pTos--;
break;
}
/* Opcode: VerifyCookie P1 P2 *
**
** Check the value of global database parameter number 0 (the
** schema version) and make sure it is equal to P2.
** P1 is the database number which is 0 for the main database file
** and 1 for the file holding temporary tables and some higher number
** for auxiliary databases.
**
** The cookie changes its value whenever the database schema changes.
** This operation is used to detect when that the cookie has changed
** and that the current process needs to reread the schema.
**
** Either a transaction needs to have been started or an OP_Open needs
** to be executed (to establish a read lock) before this opcode is
** invoked.
*/
case OP_VerifyCookie: {
int aMeta[SQLITE_N_BTREE_META];
assert( pOp->p1>=0 && pOp->p1<db->nDb );
rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
if( rc==SQLITE_OK && aMeta[1]!=pOp->p2 ){
sqliteSetString(&p->zErrMsg, "database schema has changed", (char*)0);
rc = SQLITE_SCHEMA;
}
break;
}
/* Opcode: OpenRead P1 P2 P3
**
** Open a read-only cursor for the database table whose root page is
** P2 in a database file. The database file is determined by an
** integer from the top of the stack. 0 means the main database and
** 1 means the database used for temporary tables. Give the new
** cursor an identifier of P1. The P1 values need not be contiguous
** but all P1 values should be small integers. It is an error for
** P1 to be negative.
**
** If P2==0 then take the root page number from the next of the stack.
**
** There will be a read lock on the database whenever there is an
** open cursor. If the database was unlocked prior to this instruction
** then a read lock is acquired as part of this instruction. A read
** lock allows other processes to read the database but prohibits
** any other process from modifying the database. The read lock is
** released when all cursors are closed. If this instruction attempts
** to get a read lock but fails, the script terminates with an
** SQLITE_BUSY error code.
**
** The P3 value is the name of the table or index being opened.
** The P3 value is not actually used by this opcode and may be
** omitted. But the code generator usually inserts the index or
** table name into P3 to make the code easier to read.
**
** See also OpenWrite.
*/
/* Opcode: OpenWrite P1 P2 P3
**
** Open a read/write cursor named P1 on the table or index whose root
** page is P2. If P2==0 then take the root page number from the stack.
**
** The P3 value is the name of the table or index being opened.
** The P3 value is not actually used by this opcode and may be
** omitted. But the code generator usually inserts the index or
** table name into P3 to make the code easier to read.
**
** This instruction works just like OpenRead except that it opens the cursor
** in read/write mode. For a given table, there can be one or more read-only
** cursors or a single read/write cursor but not both.
**
** See also OpenRead.
*/
case OP_OpenRead:
case OP_OpenWrite: {
int busy = 0;
int i = pOp->p1;
int p2 = pOp->p2;
int wrFlag;
Btree *pX;
int iDb;
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 ){
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;
}
}
assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
sqliteVdbeCleanupCursor(&p->aCsr[i]);
memset(&p->aCsr[i], 0, sizeof(Cursor));
p->aCsr[i].nullRow = 1;
if( pX==0 ) break;
do{
rc = sqliteBtreeCursor(pX, p2, wrFlag, &p->aCsr[i].pCursor);
switch( rc ){
case SQLITE_BUSY: {
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);
busy = 0;
}
break;
}
case SQLITE_OK: {
busy = 0;
break;
}
default: {
goto abort_due_to_error;
}
}
}while( busy );
break;
}
/* Opcode: OpenTemp P1 P2 *
**
** Open a new cursor to a transient table.
** The transient cursor is always opened read/write even if
** the main database is read-only. The transient table is deleted
** automatically when the cursor is closed.
**
** The cursor points to a BTree table if P2==0 and to a BTree index
** if P2==1. A BTree table must have an integer key and can have arbitrary
** data. A BTree index has no data but can have an arbitrary key.
**
** This opcode is used for tables that exist for the duration of a single
** SQL statement only. Tables created using CREATE TEMPORARY TABLE
** are opened using OP_OpenRead or OP_OpenWrite. "Temporary" in the
** context of this opcode means for the duration of a single SQL statement
** whereas "Temporary" in the context of CREATE TABLE means for the duration
** of the connection to the database. Same word; different meanings.
*/
case OP_OpenTemp: {
int i = pOp->p1;
Cursor *pCx;
assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
pCx = &p->aCsr[i];
sqliteVdbeCleanupCursor(pCx);
memset(pCx, 0, sizeof(*pCx));
pCx->nullRow = 1;
rc = sqliteBtreeFactory(db, 0, 1, TEMP_PAGES, &pCx->pBt);
if( rc==SQLITE_OK ){
rc = sqliteBtreeBeginTrans(pCx->pBt);
}
if( rc==SQLITE_OK ){
if( pOp->p2 ){
int pgno;
rc = sqliteBtreeCreateIndex(pCx->pBt, &pgno);
if( rc==SQLITE_OK ){
rc = sqliteBtreeCursor(pCx->pBt, pgno, 1, &pCx->pCursor);
}
}else{
rc = sqliteBtreeCursor(pCx->pBt, 2, 1, &pCx->pCursor);
}
}
break;
}
/* Opcode: OpenPseudo P1 * *
**
** Open a new cursor that points to a fake table that contains a single
** row of data. Any attempt to write a second row of data causes the
** first row to be deleted. All data is deleted when the cursor is
** closed.
**
** A pseudo-table created by this opcode is useful for holding the
** NEW or OLD tables in a trigger.
*/
case OP_OpenPseudo: {
int i = pOp->p1;
Cursor *pCx;
assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
pCx = &p->aCsr[i];
sqliteVdbeCleanupCursor(pCx);
memset(pCx, 0, sizeof(*pCx));
pCx->nullRow = 1;
pCx->pseudoTable = 1;
break;
}
/* Opcode: Close P1 * *
**
** Close a cursor previously opened as P1. If P1 is not
** currently open, this instruction is a no-op.
*/
case OP_Close: {
int i = pOp->p1;
if( i>=0 && i<p->nCursor ){
sqliteVdbeCleanupCursor(&p->aCsr[i]);
}
break;
}
/* Opcode: MoveTo P1 P2 *
**
** Pop the top of the stack and use its value as a key. Reposition
** cursor P1 so that it points to an entry with a matching key. If
** the table contains no record with a matching key, then the cursor
** is left pointing at the first record that is greater than the key.
** If there are no records greater than the key and P2 is not zero,
** then an immediate jump to P2 is made.
**
** See also: Found, NotFound, Distinct, MoveLt
*/
/* Opcode: MoveLt P1 P2 *
**
** Pop the top of the stack and use its value as a key. Reposition
** cursor P1 so that it points to the entry with the largest key that is
** less than the key popped from the stack.
** If there are no records less than than the key and P2
** is not zero then an immediate jump to P2 is made.
**
** See also: MoveTo
*/
case OP_MoveLt:
case OP_MoveTo: {
int i = pOp->p1;
Cursor *pC;
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( pTos->flags & MEM_Int ){
int iKey = intToKey(pTos->i);
if( pOp->p2==0 && pOp->opcode==OP_MoveTo ){
pC->movetoTarget = iKey;
pC->deferredMoveto = 1;
Release(pTos);
pTos--;
break;
}
sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res);
pC->lastRecno = pTos->i;
pC->recnoIsValid = res==0;
}else{
Stringify(pTos);
sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
pC->recnoIsValid = 0;
}
pC->deferredMoveto = 0;
sqlite_search_count++;
oc = pOp->opcode;
if( oc==OP_MoveTo && res<0 ){
sqliteBtreeNext(pC->pCursor, &res);
pC->recnoIsValid = 0;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
}else if( oc==OP_MoveLt ){
if( res>=0 ){
sqliteBtreePrevious(pC->pCursor, &res);
pC->recnoIsValid = 0;
}else{
/* res might be negative because the table is empty. Check to
** see if this is the case.
*/
int keysize;
res = sqliteBtreeKeySize(pC->pCursor,&keysize)!=0 || keysize==0;
}
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
}
}
Release(pTos);
pTos--;
break;
}
/* Opcode: Distinct P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key does
** not exist in the table of cursor P1, then jump to P2. If the record
** does already exist, then fall thru. The cursor is left pointing
** at the record if it exists. The key is not popped from the stack.
**
** This operation is similar to NotFound except that this operation
** does not pop the key from the stack.
**
** See also: Found, NotFound, MoveTo, IsUnique, NotExists
*/
/* Opcode: Found P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key
** does exist in table of P1, then jump to P2. If the record
** does not exist, then fall thru. The cursor is left pointing
** to the record if it exists. The key is popped from the stack.
**
** See also: Distinct, NotFound, MoveTo, IsUnique, NotExists
*/
/* Opcode: NotFound P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key
** does not exist in table of P1, then jump to P2. If the record
** does exist, then fall thru. The cursor is left pointing to the
** record if it exists. The key is popped from the stack.
**
** The difference between this operation and Distinct is that
** Distinct does not pop the key from the stack.
**
** See also: Distinct, Found, MoveTo, NotExists, IsUnique
*/
case OP_Distinct:
case OP_NotFound:
case OP_Found: {
int i = pOp->p1;
int alreadyExists = 0;
Cursor *pC;
assert( pTos>=p->aStack );
assert( i>=0 && i<p->nCursor );
if( (pC = &p->aCsr[i])->pCursor!=0 ){
int res, rx;
Stringify(pTos);
rx = sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
alreadyExists = rx==SQLITE_OK && res==0;
pC->deferredMoveto = 0;
}
if( pOp->opcode==OP_Found ){
if( alreadyExists ) pc = pOp->p2 - 1;
}else{
if( !alreadyExists ) pc = pOp->p2 - 1;
}
if( pOp->opcode!=OP_Distinct ){
Release(pTos);
pTos--;
}
break;
}
/* Opcode: IsUnique P1 P2 *
**
** The top of the stack is an integer record number. Call this
** record number R. The next on the stack is an index key created
** using MakeIdxKey. Call it K. This instruction pops R from the
** stack but it leaves K unchanged.
**
** P1 is an index. So all but the last four bytes of K are an
** index string. The last four bytes of K are a record number.
**
** This instruction asks if there is an entry in P1 where the
** index string matches K but the record number is different
** from R. If there is no such entry, then there is an immediate
** jump to P2. If any entry does exist where the index string
** matches K but the record number is not R, then the record
** number for that entry is pushed onto the stack and control
** falls through to the next instruction.
**
** See also: Distinct, NotFound, NotExists, Found
*/
case OP_IsUnique: {
int i = pOp->p1;
Mem *pNos = &pTos[-1];
BtCursor *pCrsr;
int R;
int res, rc;
int v; /* The record number on the P1 entry that matches K */
char *zKey; /* The value of K */
int nKey; /* Number of bytes in K */
/* Make sure K is a string and make zKey point to K
*/
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.
** 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 ){
rc = sqliteBtreeNext(pCrsr, &res);
if( res ){
pc = pOp->p2 - 1;
break;
}
}
rc = sqliteBtreeKeyCompare(pCrsr, zKey, nKey-4, 4, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res>0 ){
pc = pOp->p2 - 1;
break;
}
/* At this point, pCrsr is pointing to an entry in P1 where all but
** the last for bytes of the key match K. Check to see if the last
** four bytes of the key are different from R. If the last four
** bytes equal R then jump immediately to P2.
*/
sqliteBtreeKey(pCrsr, nKey - 4, 4, (char*)&v);
v = keyToInt(v);
if( v==R ){
pc = pOp->p2 - 1;
break;
}
/* The last four bytes of the key are different from R. Convert the
** last four bytes of the key into an integer and push it onto the
** stack. (These bytes are the record number of an entry that
** violates a UNIQUE constraint.)
*/
pTos++;
pTos->i = v;
pTos->flags = MEM_Int;
}
break;
}
/* Opcode: NotExists P1 P2 *
**
** Use the top of the stack as a integer key. If a record with that key
** does not exist in table of P1, then jump to P2. If the record
** does exist, then fall thru. The cursor is left pointing to the
** record if it exists. The integer key is popped from the stack.
**
** The difference between this operation and NotFound is that this
** operation assumes the key is an integer and NotFound assumes it
** is a string.
**
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
*/
case OP_NotExists: {
int i = pOp->p1;
BtCursor *pCrsr;
assert( pTos>=p->aStack );
assert( i>=0 && i<p->nCursor );
if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res, rx, iKey;
assert( pTos->flags & MEM_Int );
iKey = intToKey(pTos->i);
rx = sqliteBtreeMoveto(pCrsr, (char*)&iKey, sizeof(int), &res);
p->aCsr[i].lastRecno = pTos->i;
p->aCsr[i].recnoIsValid = res==0;
p->aCsr[i].nullRow = 0;
if( rx!=SQLITE_OK || res!=0 ){
pc = pOp->p2 - 1;
p->aCsr[i].recnoIsValid = 0;
}
}
Release(pTos);
pTos--;
break;
}
/* Opcode: NewRecno P1 * *
**
** Get a new integer record number used as the key to a table.
** The record number is not previously used as a key in the database
** table that cursor P1 points to. The new record number is pushed
** onto the stack.
*/
case OP_NewRecno: {
int i = pOp->p1;
int v = 0;
Cursor *pC;
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
** thing) is obtained in a two-step algorithm.
**
** First we attempt to find the largest existing rowid and add one
** to that. But if the largest existing rowid is already the maximum
** positive integer, we have to fall through to the second
** probabilistic algorithm
**
** The second algorithm is to select a rowid at random and see if
** it already exists in the table. If it does not exist, we have
** succeeded. If the random rowid does exist, we select a new one
** and try again, up to 1000 times.
**
** For a table with less than 2 billion entries, the probability
** of not finding a unused rowid is about 1.0e-300. This is a
** non-zero probability, but it is still vanishingly small and should
** never cause a problem. You are much, much more likely to have a
** hardware failure than for this algorithm to fail.
**
** The analysis in the previous paragraph assumes that you have a good
** source of random numbers. Is a library function like lrand48()
** good enough? Maybe. Maybe not. It's hard to know whether there
** might be subtle bugs is some implementations of lrand48() that
** could cause problems. To avoid uncertainty, SQLite uses its own
** random number generator based on the RC4 algorithm.
**
** To promote locality of reference for repetitive inserts, the
** first few attempts at chosing a random rowid pick values just a little
** larger than the previous rowid. This has been shown experimentally
** to double the speed of the COPY operation.
*/
int res, rx, cnt, x;
cnt = 0;
if( !pC->useRandomRowid ){
if( pC->nextRowidValid ){
v = pC->nextRowid;
}else{
rx = sqliteBtreeLast(pC->pCursor, &res);
if( res ){
v = 1;
}else{
sqliteBtreeKey(pC->pCursor, 0, sizeof(v), (void*)&v);
v = keyToInt(v);
if( v==0x7fffffff ){
pC->useRandomRowid = 1;
}else{
v++;
}
}
}
if( v<0x7fffffff ){
pC->nextRowidValid = 1;
pC->nextRowid = v+1;
}else{
pC->nextRowidValid = 0;
}
}
if( pC->useRandomRowid ){
v = db->priorNewRowid;
cnt = 0;
do{
if( v==0 || cnt>2 ){
sqliteRandomness(sizeof(v), &v);
if( cnt<5 ) v &= 0xffffff;
}else{
unsigned char r;
sqliteRandomness(1, &r);
v += r + 1;
}
if( v==0 ) continue;
x = intToKey(v);
rx = sqliteBtreeMoveto(pC->pCursor, &x, sizeof(int), &res);
cnt++;
}while( cnt<1000 && rx==SQLITE_OK && res==0 );
db->priorNewRowid = v;
if( rx==SQLITE_OK && res==0 ){
rc = SQLITE_FULL;
goto abort_due_to_error;
}
}
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
}
pTos++;
pTos->i = v;
pTos->flags = MEM_Int;
break;
}
/* Opcode: PutIntKey P1 P2 *
**
** Write an entry into the table of cursor P1. A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten. The data is the value on the top of the
** 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 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 * *
**
** Write an entry into the table of cursor P1. A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten. The data is the value on the top of the
** stack. The key is the next value down on the stack. The key must
** be a string. The stack is popped twice by this instruction.
**
** P1 may not be a pseudo-table opened using the OpenPseudo opcode.
*/
case OP_PutIntKey:
case OP_PutStrKey: {
Mem *pNos = &pTos[-1];
int i = pOp->p1;
Cursor *pC;
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(pNos);
nKey = pNos->n;
zKey = pNos->z;
}else{
assert( pNos->flags & MEM_Int );
nKey = sizeof(int);
iKey = intToKey(pNos->i);
zKey = (char*)&iKey;
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
** PutStrKey on a pseudo-table
*/
assert( pOp->opcode==OP_PutIntKey );
sqliteFree(pC->pData);
pC->iKey = iKey;
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, pTos->z, pC->nData);
}
}
pC->nullRow = 0;
}else{
rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n);
}
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
}
popStack(&pTos, 2);
break;
}
/* Opcode: Delete P1 P2 *
**
** Delete the record at which the P1 cursor is currently pointing.
**
** The cursor will be left pointing at either the next or the previous
** record in the table. If it is left pointing at the next record, then
** the next Next instruction will be a no-op. Hence it is OK to delete
** a record from within an Next loop.
**
** 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.
*/
case OP_Delete: {
int i = pOp->p1;
Cursor *pC;
assert( i>=0 && i<p->nCursor );
pC = &p->aCsr[i];
if( pC->pCursor!=0 ){
sqliteVdbeCursorMoveto(pC);
rc = sqliteBtreeDelete(pC->pCursor);
pC->nextRowidValid = 0;
}
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;
}
/* Opcode: KeyAsData P1 P2 *
**
** Turn the key-as-data mode for cursor P1 either on (if P2==1) or
** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls
** data off of the key rather than the data. This is used for
** processing compound selects.
*/
case OP_KeyAsData: {
int i = pOp->p1;
assert( i>=0 && i<p->nCursor );
p->aCsr[i].keyAsData = pOp->p2;
break;
}
/* Opcode: RowData P1 * *
**
** Push onto the stack the complete row data for cursor P1.
** There is no interpretation of the data. 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.
*/
/* 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;
Cursor *pC;
int n;
pTos++;
assert( i>=0 && i<p->nCursor );
pC = &p->aCsr[i];
if( pC->nullRow ){
pTos->flags = MEM_Null;
}else if( pC->pCursor!=0 ){
BtCursor *pCrsr = pC->pCursor;
sqliteVdbeCursorMoveto(pC);
if( pC->nullRow ){
pTos->flags = MEM_Null;
break;
}else if( pC->keyAsData || pOp->opcode==OP_RowKey ){
sqliteBtreeKeySize(pCrsr, &n);
}else{
sqliteBtreeDataSize(pCrsr, &n);
}
pTos->n = n;
if( n<=NBFS ){
pTos->flags = MEM_Str | MEM_Short;
pTos->z = pTos->zShort;
}else{
char *z = sqliteMallocRaw( n );
if( z==0 ) goto no_mem;
pTos->flags = MEM_Str | MEM_Dyn;
pTos->z = z;
}
if( pC->keyAsData || pOp->opcode==OP_RowKey ){
sqliteBtreeKey(pCrsr, 0, n, pTos->z);
}else{
sqliteBtreeData(pCrsr, 0, n, pTos->z);
}
}else if( pC->pseudoTable ){
pTos->n = pC->nData;
pTos->z = pC->pData;
pTos->flags = MEM_Str|MEM_Ephem;
}else{
pTos->flags = MEM_Null;
}
break;
}
/* Opcode: Column P1 P2 *
**
** Interpret the data that cursor P1 points to as
** a structure built using the MakeRecord instruction.
** (See the MakeRecord opcode for additional information about
** the format of the data.)
** Push onto the stack the value of the P2-th column contained
** in the data.
**
** If the KeyAsData opcode has previously executed on this cursor,
** then the field might be extracted from the key rather than the
** data.
**
** If P1 is negative, then the record is stored on the stack rather
** than in a table. For P1==-1, the top of the stack is used.
** For P1==-2, the next on the stack is used. And so forth. The
** value pushed is always just a pointer into the record which is
** stored further down on the stack. The column value is not copied.
*/
case OP_Column: {
int amt, offset, end, payloadSize;
int i = pOp->p1;
int p2 = pOp->p2;
Cursor *pC;
char *zRec;
BtCursor *pCrsr;
int idxWidth;
unsigned char aHdr[10];
assert( i<p->nCursor );
pTos++;
if( i<0 ){
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;
pCrsr = pC->pCursor;
if( pC->nullRow ){
payloadSize = 0;
}else if( pC->keyAsData ){
sqliteBtreeKeySize(pCrsr, &payloadSize);
}else{
sqliteBtreeDataSize(pCrsr, &payloadSize);
}
}else if( pC->pseudoTable ){
payloadSize = pC->nData;
zRec = pC->pData;
assert( payloadSize==0 || zRec!=0 );
}else{
payloadSize = 0;
}
/* Figure out how many bytes in the column data and where the column
** data begins.
*/
if( payloadSize==0 ){
pTos->flags = MEM_Null;
break;
}else if( payloadSize<256 ){
idxWidth = 1;
}else if( payloadSize<65536 ){
idxWidth = 2;
}else{
idxWidth = 3;
}
/* Figure out where the requested column is stored and how big it is.
pTos->n = amt;
if( amt==0 ){
pTos->flags = MEM_Null;
}else if( zRec ){
pTos->flags = MEM_Str | MEM_Ephem;
pTos->z = &zRec[offset];
}else{
if( amt<=NBFS ){
pTos->flags = MEM_Str | MEM_Short;
pTos->z = pTos->zShort;
}else{
char *z = sqliteMallocRaw( amt );
if( z==0 ) goto no_mem;
pTos->flags = MEM_Str | MEM_Dyn;
pTos->z = z;
}
if( pC->keyAsData ){
sqliteBtreeKey(pCrsr, offset, amt, pTos->z);
}else{
sqliteBtreeData(pCrsr, offset, amt, pTos->z);
}
}
break;
}
/* Opcode: Recno P1 * *
**
** Push onto the stack an integer which is the first 4 bytes of the
** the key to the current entry in a sequential scan of the database
** file P1. The sequential scan should have been started using the
** Next opcode.
*/
case OP_Recno: {
int i = pOp->p1;
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 ){
pTos->flags = MEM_Null;
break;
}else{
assert( pC->pCursor!=0 );
sqliteBtreeKey(pC->pCursor, 0, sizeof(u32), (char*)&v);
v = keyToInt(v);
}
pTos->i = v;
pTos->flags = MEM_Int;
break;
}
/* Opcode: FullKey P1 * *
**
** Extract the complete key from the record that cursor P1 is currently
** pointing to and push the key onto the stack as a string.
**
** Compare this opcode to Recno. The Recno opcode extracts the first
** 4 bytes of the key and pushes those bytes onto the stack as an
** integer. This instruction pushes the entire key as a string.
**
** This opcode may not be used on a pseudo-table.
*/
case OP_FullKey: {
int i = pOp->p1;
BtCursor *pCrsr;
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;
sqliteVdbeCursorMoveto(&p->aCsr[i]);
sqliteBtreeKeySize(pCrsr, &amt);
if( amt<=0 ){
rc = SQLITE_CORRUPT;
goto abort_due_to_error;
}
if( amt>NBFS ){
z = sqliteMallocRaw( amt );
if( z==0 ) goto no_mem;
pTos->flags = MEM_Str | MEM_Dyn;
}else{
z = pTos->zShort;
pTos->flags = MEM_Str | MEM_Short;
}
sqliteBtreeKey(pCrsr, 0, amt, z);
pTos->z = z;
pTos->n = amt;
}
break;
}
/* Opcode: NullRow P1 * *
**
** Move the cursor P1 to a null row. Any OP_Column operations
** that occur while the cursor is on the null row will always push
** a NULL onto the stack.
*/
case OP_NullRow: {
int i = pOp->p1;
assert( i>=0 && i<p->nCursor );
p->aCsr[i].nullRow = 1;
p->aCsr[i].recnoIsValid = 0;
break;
}
/* Opcode: Last P1 P2 *
**
** The next use of the Recno or Column or Next instruction for P1
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Last: {
int i = pOp->p1;
Cursor *pC;
BtCursor *pCrsr;
assert( i>=0 && i<p->nCursor );
pC = &p->aCsr[i];
if( (pCrsr = pC->pCursor)!=0 ){
int res;
rc = sqliteBtreeLast(pCrsr, &res);
pC->nullRow = res;
pC->deferredMoveto = 0;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
}else{
pC->nullRow = 0;
}
break;
}
/* Opcode: Rewind P1 P2 *
**
** The next use of the Recno or Column or Next instruction for P1
** will refer to the first entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Rewind: {
int i = pOp->p1;
Cursor *pC;
BtCursor *pCrsr;
assert( i>=0 && i<p->nCursor );
pC = &p->aCsr[i];
if( (pCrsr = pC->pCursor)!=0 ){
int res;
rc = sqliteBtreeFirst(pCrsr, &res);
pC->atFirst = res==0;
pC->nullRow = res;
pC->deferredMoveto = 0;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
}else{
pC->nullRow = 0;
}
break;
}
/* Opcode: Next P1 P2 *
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index. If there are no more key/value pairs then fall through
** to the following instruction. But if the cursor advance was successful,
** jump immediately to P2.
**
** See also: Prev
*/
/* Opcode: Prev P1 P2 *
**
** Back up cursor P1 so that it points to the previous key/data pair in its
** table or index. If there is no previous key/value pairs then fall through
** to the following instruction. But if the cursor backup was successful,
** jump immediately to P2.
*/
case OP_Prev:
case OP_Next: {
Cursor *pC;
BtCursor *pCrsr;
CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = &p->aCsr[pOp->p1];
if( (pCrsr = pC->pCursor)!=0 ){
int res;
if( pC->nullRow ){
res = 1;
}else{
assert( pC->deferredMoveto==0 );
rc = pOp->opcode==OP_Next ? sqliteBtreeNext(pCrsr, &res) :
sqliteBtreePrevious(pCrsr, &res);
pC->nullRow = res;
}
if( res==0 ){
pc = pOp->p2 - 1;
sqlite_search_count++;
}
}else{
pC->nullRow = 1;
}
pC->recnoIsValid = 0;
break;
}
/* Opcode: IdxPut P1 P2 P3
**
** The top of the stack holds a SQL index key made using the
** MakeIdxKey instruction. This opcode writes that key into the
** index P1. Data for the entry is nil.
**
** If P2==1, then the key must be unique. If the key is not unique,
** the program aborts with a SQLITE_CONSTRAINT error and the database
** is rolled back. If P3 is not null, then it becomes part of the
** error message returned with the SQLITE_CONSTRAINT.
*/
case OP_IdxPut: {
int i = pOp->p1;
BtCursor *pCrsr;
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( nKey >= 4 );
rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
while( res!=0 ){
int c;
sqliteBtreeKeySize(pCrsr, &n);
if( n==nKey
**
** The top of the stack is an index key built using the MakeIdxKey opcode.
** This opcode removes that entry from the index.
*/
case OP_IdxDelete: {
int i = pOp->p1;
BtCursor *pCrsr;
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, pTos->z, pTos->n, &res);
if( rx==SQLITE_OK && res==0 ){
rc = sqliteBtreeDelete(pCrsr);
}
assert( p->aCsr[i].deferredMoveto==0 );
}
Release(pTos);
pTos--;
break;
}
/* Opcode: IdxRecno P1 * *
**
** Push onto the stack an integer which is the last 4 bytes of the
** the key to the current entry in index P1. These 4 bytes should
** be the record number of the table entry to which this index entry
** points.
**
** See also: Recno, MakeIdxKey.
*/
case OP_IdxRecno: {
int i = pOp->p1;
BtCursor *pCrsr;
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) ){
pTos->flags = MEM_Null;
}else{
sqliteBtreeKey(pCrsr, sz - sizeof(u32), sizeof(u32), (char*)&v);
v = keyToInt(v);
pTos->i = v;
pTos->flags = MEM_Int;
}
}else{
pTos->flags = MEM_Null;
}
break;
}
/* Opcode: IdxGT P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
** index entry. If the index entry is greater than the top of the stack
** then jump to P2. Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
*/
/* Opcode: IdxGE P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
** index entry. If the index entry is greater than or equal to
** the top of the stack
** then jump to P2. Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
*/
/* Opcode: IdxLT P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
** index entry. If the index entry is less than the top of the stack
** then jump to P2. Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
*/
case OP_IdxLT:
case OP_IdxGT:
case OP_IdxGE: {
int i= pOp->p1;
BtCursor *pCrsr;
assert( i>=0 && i<p->nCursor );
assert( pTos>=p->aStack );
if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res, rc;
Stringify(pTos);
assert( p->aCsr[i].deferredMoveto==0 );
rc = sqliteBtreeKeyCompare(pCrsr, pTos->z, pTos->n, 4, &res);
if( rc!=SQLITE_OK ){
break;
}
if( pOp->opcode==OP_IdxLT ){
res = -res;
}else if( pOp->opcode==OP_IdxGE ){
res++;
}
if( res>0 ){
pc = pOp->p2 - 1 ;
}
}
Release(pTos);
pTos--;
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 k, n;
const char *z;
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;
break;
}
while( k<n && z[k] ){ k++; }
k++;
( run in 0.886 second using v1.01-cache-2.11-cpan-13bb782fe5a )