Updated SQLite to 3.3.13 - why? I have no idea
This commit is contained in:
@ -57,17 +57,21 @@
|
||||
** working correctly. This variable has no function other than to
|
||||
** help verify the correct operation of the library.
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_search_count = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** When this global variable is positive, it gets decremented once before
|
||||
** each instruction in the VDBE. When reaches zero, the SQLITE_Interrupt
|
||||
** of the db.flags field is set in order to simulate and interrupt.
|
||||
** each instruction in the VDBE. When reaches zero, the u1.isInterrupted
|
||||
** field of the sqlite3 structure is set in order to simulate and interrupt.
|
||||
**
|
||||
** This facility is used for testing purposes only. It does not function
|
||||
** in an ordinary build.
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_interrupt_count = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The next global variable is incremented each type the OP_Sort opcode
|
||||
@ -76,7 +80,9 @@ int sqlite3_interrupt_count = 0;
|
||||
** has no function other than to help verify the correct operation of the
|
||||
** library.
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_sort_count = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Release the memory associated with the given stack level. This
|
||||
@ -180,7 +186,7 @@ static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){
|
||||
Cursor *pCx;
|
||||
assert( iCur<p->nCursor );
|
||||
if( p->apCsr[iCur] ){
|
||||
sqlite3VdbeFreeCursor(p->apCsr[iCur]);
|
||||
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
|
||||
}
|
||||
p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) );
|
||||
if( pCx ){
|
||||
@ -376,7 +382,7 @@ __inline__ unsigned long long int hwtime(void){
|
||||
** flag on jump instructions, we get a (small) speed improvement.
|
||||
*/
|
||||
#define CHECK_FOR_INTERRUPT \
|
||||
if( db->flags & SQLITE_Interrupt ) goto abort_due_to_interrupt;
|
||||
if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
|
||||
|
||||
|
||||
/*
|
||||
@ -448,6 +454,21 @@ int sqlite3VdbeExec(
|
||||
p->resOnStack = 0;
|
||||
db->busyHandler.nBusy = 0;
|
||||
CHECK_FOR_INTERRUPT;
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( (p->db->flags & SQLITE_VdbeListing)!=0
|
||||
|| sqlite3OsFileExists("vdbe_explain")
|
||||
){
|
||||
int i;
|
||||
printf("VDBE Program Listing:\n");
|
||||
sqlite3VdbePrintSql(p);
|
||||
for(i=0; i<p->nOp; i++){
|
||||
sqlite3VdbePrintOp(stdout, i, &p->aOp[i]);
|
||||
}
|
||||
}
|
||||
if( sqlite3OsFileExists("vdbe_trace") ){
|
||||
p->trace = stdout;
|
||||
}
|
||||
#endif
|
||||
for(pc=p->pc; rc==SQLITE_OK; pc++){
|
||||
assert( pc>=0 && pc<p->nOp );
|
||||
assert( pTos<=&p->aStack[pc] );
|
||||
@ -495,11 +516,14 @@ int sqlite3VdbeExec(
|
||||
*/
|
||||
if( db->xProgress ){
|
||||
if( db->nProgressOps==nProgressOps ){
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
if( db->xProgress(db->pProgressArg)!=0 ){
|
||||
sqlite3SafetyOn(db);
|
||||
rc = SQLITE_ABORT;
|
||||
continue; /* skip to the next iteration of the for loop */
|
||||
}
|
||||
nProgressOps = 0;
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
}
|
||||
nProgressOps++;
|
||||
}
|
||||
@ -1803,32 +1827,31 @@ case OP_IfNot: { /* no-push */
|
||||
|
||||
/* Opcode: IsNull P1 P2 *
|
||||
**
|
||||
** If any of the top abs(P1) values on the stack are NULL, then jump
|
||||
** to P2. Pop the stack P1 times if P1>0. If P1<0 leave the stack
|
||||
** unchanged.
|
||||
** Check the top of the stack and jump to P2 if the top of the stack
|
||||
** is NULL. If P1 is positive, then pop P1 elements from the stack
|
||||
** regardless of whether or not the jump is taken. If P1 is negative,
|
||||
** pop -P1 elements from the stack only if the jump is taken and leave
|
||||
** the stack unchanged if the jump is not taken.
|
||||
*/
|
||||
case OP_IsNull: { /* same as TK_ISNULL, no-push */
|
||||
int i, cnt;
|
||||
Mem *pTerm;
|
||||
cnt = pOp->p1;
|
||||
if( cnt<0 ) cnt = -cnt;
|
||||
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( pTos->flags & MEM_Null ){
|
||||
pc = pOp->p2-1;
|
||||
if( pOp->p1<0 ){
|
||||
popStack(&pTos, -pOp->p1);
|
||||
}
|
||||
}
|
||||
if( pOp->p1>0 ) popStack(&pTos, cnt);
|
||||
if( pOp->p1>0 ){
|
||||
popStack(&pTos, pOp->p1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: NotNull P1 P2 *
|
||||
**
|
||||
** 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.
|
||||
** Jump to P2 if the top abs(P1) values on the stack are all not NULL.
|
||||
** Regardless of whether or not the jump is taken, pop the stack
|
||||
** P1 times if P1 is greater than zero. But if P1 is negative,
|
||||
** leave the stack unchanged.
|
||||
*/
|
||||
case OP_NotNull: { /* same as TK_NOTNULL, no-push */
|
||||
int i, cnt;
|
||||
@ -2001,7 +2024,9 @@ case OP_Column: {
|
||||
pC->aRow = 0;
|
||||
}
|
||||
}
|
||||
assert( zRec!=0 || avail>=payloadSize || avail>=9 );
|
||||
/* The following assert is true in all cases accept when
|
||||
** the database file has been corrupted externally.
|
||||
** assert( zRec!=0 || avail>=payloadSize || avail>=9 ); */
|
||||
szHdrSz = GetVarint((u8*)zData, offset);
|
||||
|
||||
/* The KeyFetch() or DataFetch() above are fast and will get the entire
|
||||
@ -2492,6 +2517,8 @@ case OP_VerifyCookie: { /* no-push */
|
||||
}
|
||||
if( rc==SQLITE_OK && iMeta!=pOp->p2 ){
|
||||
sqlite3SetString(&p->zErrMsg, "database schema has changed", (char*)0);
|
||||
sqlite3ResetInternalSchema(db, pOp->p1);
|
||||
sqlite3ExpirePreparedStatements(db);
|
||||
rc = SQLITE_SCHEMA;
|
||||
}
|
||||
break;
|
||||
@ -2637,9 +2664,9 @@ case OP_OpenWrite: { /* no-push */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: OpenVirtual P1 P2 P3
|
||||
/* Opcode: OpenEphemeral P1 P2 P3
|
||||
**
|
||||
** Open a new cursor P1 to a transient or virtual table.
|
||||
** Open a new cursor P1 to a transient table.
|
||||
** The cursor is always opened read/write even if
|
||||
** the main database is read-only. The transient or virtual
|
||||
** table is deleted automatically when the cursor is closed.
|
||||
@ -2648,8 +2675,14 @@ case OP_OpenWrite: { /* no-push */
|
||||
** The cursor points to a BTree table if P3==0 and to a BTree index
|
||||
** if P3 is not 0. If P3 is not NULL, it points to a KeyInfo structure
|
||||
** that defines the format of keys in the index.
|
||||
**
|
||||
** This opcode was once called OpenTemp. But that created
|
||||
** confusion because the term "temp table", might refer either
|
||||
** to a TEMP table at the SQL level, or to a table opened by
|
||||
** this opcode. Then this opcode was call OpenVirtual. But
|
||||
** that created confusion with the whole virtual-table idea.
|
||||
*/
|
||||
case OP_OpenVirtual: { /* no-push */
|
||||
case OP_OpenEphemeral: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pCx;
|
||||
assert( i>=0 );
|
||||
@ -2724,7 +2757,7 @@ case OP_OpenPseudo: { /* no-push */
|
||||
case OP_Close: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
if( i>=0 && i<p->nCursor ){
|
||||
sqlite3VdbeFreeCursor(p->apCsr[i]);
|
||||
sqlite3VdbeFreeCursor(p, p->apCsr[i]);
|
||||
p->apCsr[i] = 0;
|
||||
}
|
||||
break;
|
||||
@ -2815,7 +2848,9 @@ case OP_MoveGt: { /* no-push */
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
*pC->pIncrKey = 0;
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_search_count++;
|
||||
#endif
|
||||
if( oc==OP_MoveGe || oc==OP_MoveGt ){
|
||||
if( res<0 ){
|
||||
rc = sqlite3BtreeNext(pC->pCursor, &res);
|
||||
@ -2890,7 +2925,7 @@ case OP_MoveGt: { /* no-push */
|
||||
**
|
||||
** The top of the stack holds a blob constructed by MakeRecord. P1 is
|
||||
** an index. If no entry exists in P1 that matches the blob then jump
|
||||
** to P1. If an entry does existing, fall through. The cursor is left
|
||||
** to P2. If an entry does existing, fall through. The cursor is left
|
||||
** pointing to the entry that matches. The blob is popped from the stack.
|
||||
**
|
||||
** The difference between this operation and Distinct is that
|
||||
@ -2963,7 +2998,7 @@ case OP_IsUnique: { /* no-push */
|
||||
R = pTos->i;
|
||||
assert( (pTos->flags & MEM_Dyn)==0 );
|
||||
pTos--;
|
||||
assert( i>=0 && i<=p->nCursor );
|
||||
assert( i>=0 && i<p->nCursor );
|
||||
pCx = p->apCsr[i];
|
||||
assert( pCx!=0 );
|
||||
pCrsr = pCx->pCursor;
|
||||
@ -3064,6 +3099,9 @@ case OP_NotExists: { /* no-push */
|
||||
pC->rowidIsValid = res==0;
|
||||
pC->nullRow = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
/* res might be uninitialized if rc!=SQLITE_OK. But if rc!=SQLITE_OK
|
||||
** processing is about to abort so we really do not care whether or not
|
||||
** the following jump is taken. */
|
||||
if( res!=0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
pC->rowidIsValid = 0;
|
||||
@ -3260,6 +3298,10 @@ case OP_NewRowid: {
|
||||
** then rowid is stored for subsequent return by the
|
||||
** sqlite3_last_insert_rowid() function (otherwise it's unmodified).
|
||||
**
|
||||
** Parameter P3 may point to a string containing the table-name, or
|
||||
** may be NULL. If it is not NULL, then the update-hook
|
||||
** (sqlite3.xUpdateCallback) is invoked following a successful insert.
|
||||
**
|
||||
** This instruction only works on tables. The equivalent instruction
|
||||
** for indices is OP_IdxInsert.
|
||||
*/
|
||||
@ -3569,8 +3611,10 @@ case OP_Last: { /* no-push */
|
||||
** correctly optimizing out sorts.
|
||||
*/
|
||||
case OP_Sort: { /* no-push */
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_sort_count++;
|
||||
sqlite3_search_count--;
|
||||
#endif
|
||||
/* Fall through into OP_Rewind */
|
||||
}
|
||||
/* Opcode: Rewind P1 P2 *
|
||||
@ -3643,7 +3687,9 @@ case OP_Next: { /* no-push */
|
||||
}
|
||||
if( res==0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_search_count++;
|
||||
#endif
|
||||
}
|
||||
}else{
|
||||
pC->nullRow = 1;
|
||||
@ -3827,38 +3873,6 @@ case OP_IdxGE: { /* no-push */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IdxIsNull P1 P2 *
|
||||
**
|
||||
** The top of the stack contains an index entry such as might be generated
|
||||
** by the MakeIdxRec opcode. This routine looks at the first P1 fields of
|
||||
** that key. If any of the first P1 fields are NULL, then a jump is made
|
||||
** to address P2. Otherwise we fall straight through.
|
||||
**
|
||||
** The index entry is always popped from the stack.
|
||||
*/
|
||||
case OP_IdxIsNull: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
int k, n;
|
||||
const char *z;
|
||||
u32 serial_type;
|
||||
|
||||
assert( pTos>=p->aStack );
|
||||
assert( pTos->flags & MEM_Blob );
|
||||
z = pTos->z;
|
||||
n = pTos->n;
|
||||
k = sqlite3GetVarint32((u8*)z, &serial_type);
|
||||
for(; k<n && i>0; i--){
|
||||
k += sqlite3GetVarint32((u8*)&z[k], &serial_type);
|
||||
if( serial_type==0 ){ /* Serial type 0 is a NULL */
|
||||
pc = pOp->p2-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Release(pTos);
|
||||
pTos--;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Destroy P1 P2 *
|
||||
**
|
||||
** Delete an entire database table or index whose root page in the database
|
||||
@ -3881,19 +3895,31 @@ case OP_IdxIsNull: { /* no-push */
|
||||
*/
|
||||
case OP_Destroy: {
|
||||
int iMoved;
|
||||
if( db->activeVdbeCnt>1 ){
|
||||
int iCnt;
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
Vdbe *pVdbe;
|
||||
iCnt = 0;
|
||||
for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
|
||||
if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 ){
|
||||
iCnt++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
iCnt = db->activeVdbeCnt;
|
||||
#endif
|
||||
if( iCnt>1 ){
|
||||
rc = SQLITE_LOCKED;
|
||||
}else{
|
||||
assert( db->activeVdbeCnt==1 );
|
||||
assert( iCnt==1 );
|
||||
rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved);
|
||||
pTos++;
|
||||
pTos->flags = MEM_Int;
|
||||
pTos->i = iMoved;
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( rc==SQLITE_OK && iMoved!=0 ){
|
||||
sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3995,10 +4021,14 @@ case OP_CreateTable: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: ParseSchema P1 * P3
|
||||
/* Opcode: ParseSchema P1 P2 P3
|
||||
**
|
||||
** Read and parse all entries from the SQLITE_MASTER table of database P1
|
||||
** that match the WHERE clause P3.
|
||||
** that match the WHERE clause P3. P2 is the "force" flag. Always do
|
||||
** the parsing if P2 is true. If P2 is false, then this routine is a
|
||||
** no-op if the schema is not currently loaded. In other words, if P2
|
||||
** is false, the SQLITE_MASTER table is only parsed if the rest of the
|
||||
** schema is already loaded into the symbol table.
|
||||
**
|
||||
** This opcode invokes the parser to create a new virtual machine,
|
||||
** then runs the new virtual machine. It is thus a reentrant opcode.
|
||||
@ -4010,19 +4040,23 @@ case OP_ParseSchema: { /* no-push */
|
||||
InitData initData;
|
||||
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
if( !DbHasProperty(db, iDb, DB_SchemaLoaded) ) break;
|
||||
if( !pOp->p2 && !DbHasProperty(db, iDb, DB_SchemaLoaded) ){
|
||||
break;
|
||||
}
|
||||
zMaster = SCHEMA_TABLE(iDb);
|
||||
initData.db = db;
|
||||
initData.iDb = pOp->p1;
|
||||
initData.pzErrMsg = &p->zErrMsg;
|
||||
zSql = sqlite3MPrintf(
|
||||
"SELECT name, rootpage, sql, %d FROM '%q'.%s WHERE %s",
|
||||
pOp->p1, db->aDb[iDb].zName, zMaster, pOp->p3);
|
||||
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s",
|
||||
db->aDb[iDb].zName, zMaster, pOp->p3);
|
||||
if( zSql==0 ) goto no_mem;
|
||||
sqlite3SafetyOff(db);
|
||||
assert( db->init.busy==0 );
|
||||
db->init.busy = 1;
|
||||
assert( !sqlite3MallocFailed() );
|
||||
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
|
||||
if( rc==SQLITE_ABORT ) rc = initData.rc;
|
||||
sqliteFree(zSql);
|
||||
db->init.busy = 0;
|
||||
sqlite3SafetyOn(db);
|
||||
@ -4086,11 +4120,16 @@ case OP_DropTrigger: { /* no-push */
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
/* Opcode: IntegrityCk * P2 *
|
||||
/* Opcode: IntegrityCk P1 P2 *
|
||||
**
|
||||
** Do an analysis of the currently open database. Push onto the
|
||||
** stack the text of an error message describing any problems.
|
||||
** If there are no errors, push a "ok" onto the stack.
|
||||
** If no problems are found, push a NULL onto the stack.
|
||||
**
|
||||
** P1 is the address of a memory cell that contains the maximum
|
||||
** number of allowed errors. At most mem[P1] errors will be reported.
|
||||
** In other words, the analysis stops as soon as mem[P1] errors are
|
||||
** seen. Mem[P1] is updated with the number of errors remaining.
|
||||
**
|
||||
** The root page numbers of all tables in the database are integer
|
||||
** values on the stack. This opcode pulls as many integers as it
|
||||
@ -4099,13 +4138,15 @@ case OP_DropTrigger: { /* no-push */
|
||||
** If P2 is not zero, the check is done on the auxiliary database
|
||||
** file, not the main database file.
|
||||
**
|
||||
** This opcode is used for testing purposes only.
|
||||
** This opcode is used to implement the integrity_check pragma.
|
||||
*/
|
||||
case OP_IntegrityCk: {
|
||||
int nRoot;
|
||||
int *aRoot;
|
||||
int j;
|
||||
int nErr;
|
||||
char *z;
|
||||
Mem *pnErr;
|
||||
|
||||
for(nRoot=0; &pTos[-nRoot]>=p->aStack; nRoot++){
|
||||
if( (pTos[-nRoot].flags & MEM_Int)==0 ) break;
|
||||
@ -4113,6 +4154,10 @@ case OP_IntegrityCk: {
|
||||
assert( nRoot>0 );
|
||||
aRoot = sqliteMallocRaw( sizeof(int*)*(nRoot+1) );
|
||||
if( aRoot==0 ) goto no_mem;
|
||||
j = pOp->p1;
|
||||
assert( j>=0 && j<p->nMem );
|
||||
pnErr = &p->aMem[j];
|
||||
assert( (pnErr->flags & MEM_Int)!=0 );
|
||||
for(j=0; j<nRoot; j++){
|
||||
Mem *pMem = &pTos[-j];
|
||||
aRoot[j] = (int)pMem->i;
|
||||
@ -4120,12 +4165,12 @@ case OP_IntegrityCk: {
|
||||
aRoot[j] = 0;
|
||||
popStack(&pTos, nRoot);
|
||||
pTos++;
|
||||
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot);
|
||||
if( z==0 || z[0]==0 ){
|
||||
if( z ) sqliteFree(z);
|
||||
pTos->z = "ok";
|
||||
pTos->n = 2;
|
||||
pTos->flags = MEM_Str | MEM_Static | MEM_Term;
|
||||
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot,
|
||||
(int)pnErr->i, &nErr);
|
||||
pnErr->i -= nErr;
|
||||
if( nErr==0 ){
|
||||
assert( z==0 );
|
||||
pTos->flags = MEM_Null;
|
||||
}else{
|
||||
pTos->z = z;
|
||||
pTos->n = strlen(z);
|
||||
@ -4461,6 +4506,7 @@ case OP_AggFinal: { /* no-push */
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_VACUUM
|
||||
/* Opcode: Vacuum * * *
|
||||
**
|
||||
** Vacuum the entire database. This opcode will cause other virtual
|
||||
@ -4473,6 +4519,7 @@ case OP_Vacuum: { /* no-push */
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Opcode: Expire P1 * *
|
||||
**
|
||||
@ -4522,7 +4569,316 @@ case OP_TableLock: { /* no-push */
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* SHARED_OMIT_SHARED_CACHE */
|
||||
#endif /* SQLITE_OMIT_SHARED_CACHE */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VBegin * * P3
|
||||
**
|
||||
** P3 a pointer to an sqlite3_vtab structure. Call the xBegin method
|
||||
** for that table.
|
||||
*/
|
||||
case OP_VBegin: { /* no-push */
|
||||
rc = sqlite3VtabBegin(db, (sqlite3_vtab *)pOp->p3);
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VCreate P1 * P3
|
||||
**
|
||||
** P3 is the name of a virtual table in database P1. Call the xCreate method
|
||||
** for that table.
|
||||
*/
|
||||
case OP_VCreate: { /* no-push */
|
||||
rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p3, &p->zErrMsg);
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VDestroy P1 * P3
|
||||
**
|
||||
** P3 is the name of a virtual table in database P1. Call the xDestroy method
|
||||
** of that table.
|
||||
*/
|
||||
case OP_VDestroy: { /* no-push */
|
||||
p->inVtabMethod = 2;
|
||||
rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p3);
|
||||
p->inVtabMethod = 0;
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VOpen P1 * P3
|
||||
**
|
||||
** P3 is a pointer to a virtual table object, an sqlite3_vtab structure.
|
||||
** P1 is a cursor number. This opcode opens a cursor to the virtual
|
||||
** table and stores that cursor in P1.
|
||||
*/
|
||||
case OP_VOpen: { /* no-push */
|
||||
Cursor *pCur = 0;
|
||||
sqlite3_vtab_cursor *pVtabCursor = 0;
|
||||
|
||||
sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3);
|
||||
sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule;
|
||||
|
||||
assert(pVtab && pModule);
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
rc = pModule->xOpen(pVtab, &pVtabCursor);
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
if( SQLITE_OK==rc ){
|
||||
/* Initialise sqlite3_vtab_cursor base class */
|
||||
pVtabCursor->pVtab = pVtab;
|
||||
|
||||
/* Initialise vdbe cursor object */
|
||||
pCur = allocateCursor(p, pOp->p1, -1);
|
||||
if( pCur ){
|
||||
pCur->pVtabCursor = pVtabCursor;
|
||||
pCur->pModule = pVtabCursor->pVtab->pModule;
|
||||
}else{
|
||||
pModule->xClose(pVtabCursor);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VFilter P1 P2 P3
|
||||
**
|
||||
** P1 is a cursor opened using VOpen. P2 is an address to jump to if
|
||||
** the filtered result set is empty.
|
||||
**
|
||||
** P3 is either NULL or a string that was generated by the xBestIndex
|
||||
** method of the module. The interpretation of the P3 string is left
|
||||
** to the module implementation.
|
||||
**
|
||||
** This opcode invokes the xFilter method on the virtual table specified
|
||||
** by P1. The integer query plan parameter to xFilter is the top of the
|
||||
** stack. Next down on the stack is the argc parameter. Beneath the
|
||||
** next of stack are argc additional parameters which are passed to
|
||||
** xFilter as argv. The topmost parameter (i.e. 3rd element popped from
|
||||
** the stack) becomes argv[argc-1] when passed to xFilter.
|
||||
**
|
||||
** The integer query plan parameter, argc, and all argv stack values
|
||||
** are popped from the stack before this instruction completes.
|
||||
**
|
||||
** A jump is made to P2 if the result set after filtering would be
|
||||
** empty.
|
||||
*/
|
||||
case OP_VFilter: { /* no-push */
|
||||
int nArg;
|
||||
|
||||
const sqlite3_module *pModule;
|
||||
|
||||
Cursor *pCur = p->apCsr[pOp->p1];
|
||||
assert( pCur->pVtabCursor );
|
||||
pModule = pCur->pVtabCursor->pVtab->pModule;
|
||||
|
||||
/* Grab the index number and argc parameters off the top of the stack. */
|
||||
assert( (&pTos[-1])>=p->aStack );
|
||||
assert( (pTos[0].flags&MEM_Int)!=0 && pTos[-1].flags==MEM_Int );
|
||||
nArg = (int)pTos[-1].i;
|
||||
|
||||
/* Invoke the xFilter method */
|
||||
{
|
||||
int res = 0;
|
||||
int i;
|
||||
Mem **apArg = p->apArg;
|
||||
for(i = 0; i<nArg; i++){
|
||||
apArg[i] = &pTos[i+1-2-nArg];
|
||||
storeTypeInfo(apArg[i], 0);
|
||||
}
|
||||
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
p->inVtabMethod = 1;
|
||||
rc = pModule->xFilter(pCur->pVtabCursor, (int)pTos->i, pOp->p3, nArg, apArg);
|
||||
p->inVtabMethod = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
res = pModule->xEof(pCur->pVtabCursor);
|
||||
}
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
|
||||
if( res ){
|
||||
pc = pOp->p2 - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pop the index number, argc value and parameters off the stack */
|
||||
popStack(&pTos, 2+nArg);
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VRowid P1 * *
|
||||
**
|
||||
** Push an integer onto the stack which is the rowid of
|
||||
** the virtual-table that the P1 cursor is pointing to.
|
||||
*/
|
||||
case OP_VRowid: {
|
||||
const sqlite3_module *pModule;
|
||||
|
||||
Cursor *pCur = p->apCsr[pOp->p1];
|
||||
assert( pCur->pVtabCursor );
|
||||
pModule = pCur->pVtabCursor->pVtab->pModule;
|
||||
if( pModule->xRowid==0 ){
|
||||
sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xRowid", 0);
|
||||
rc = SQLITE_ERROR;
|
||||
} else {
|
||||
sqlite_int64 iRow;
|
||||
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
|
||||
pTos++;
|
||||
pTos->flags = MEM_Int;
|
||||
pTos->i = iRow;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VColumn P1 P2 *
|
||||
**
|
||||
** Push onto the stack the value of the P2-th column of
|
||||
** the row of the virtual-table that the P1 cursor is pointing to.
|
||||
*/
|
||||
case OP_VColumn: {
|
||||
const sqlite3_module *pModule;
|
||||
|
||||
Cursor *pCur = p->apCsr[pOp->p1];
|
||||
assert( pCur->pVtabCursor );
|
||||
pModule = pCur->pVtabCursor->pVtab->pModule;
|
||||
if( pModule->xColumn==0 ){
|
||||
sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xColumn", 0);
|
||||
rc = SQLITE_ERROR;
|
||||
} else {
|
||||
sqlite3_context sContext;
|
||||
memset(&sContext, 0, sizeof(sContext));
|
||||
sContext.s.flags = MEM_Null;
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
|
||||
|
||||
/* Copy the result of the function to the top of the stack. We
|
||||
** do this regardless of whether or not an error occured to ensure any
|
||||
** dynamic allocation in sContext.s (a Mem struct) is released.
|
||||
*/
|
||||
sqlite3VdbeChangeEncoding(&sContext.s, encoding);
|
||||
pTos++;
|
||||
pTos->flags = 0;
|
||||
sqlite3VdbeMemMove(pTos, &sContext.s);
|
||||
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VNext P1 P2 *
|
||||
**
|
||||
** Advance virtual table P1 to the next row in its result set and
|
||||
** jump to instruction P2. Or, if the virtual table has reached
|
||||
** the end of its result set, then fall through to the next instruction.
|
||||
*/
|
||||
case OP_VNext: { /* no-push */
|
||||
const sqlite3_module *pModule;
|
||||
int res = 0;
|
||||
|
||||
Cursor *pCur = p->apCsr[pOp->p1];
|
||||
assert( pCur->pVtabCursor );
|
||||
pModule = pCur->pVtabCursor->pVtab->pModule;
|
||||
if( pModule->xNext==0 ){
|
||||
sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xNext", 0);
|
||||
rc = SQLITE_ERROR;
|
||||
} else {
|
||||
/* Invoke the xNext() method of the module. There is no way for the
|
||||
** underlying implementation to return an error if one occurs during
|
||||
** xNext(). Instead, if an error occurs, true is returned (indicating that
|
||||
** data is available) and the error code returned when xColumn or
|
||||
** some other method is next invoked on the save virtual table cursor.
|
||||
*/
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
p->inVtabMethod = 1;
|
||||
rc = pModule->xNext(pCur->pVtabCursor);
|
||||
p->inVtabMethod = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
res = pModule->xEof(pCur->pVtabCursor);
|
||||
}
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
|
||||
if( !res ){
|
||||
/* If there is data, jump to P2 */
|
||||
pc = pOp->p2 - 1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VUpdate P1 P2 P3
|
||||
**
|
||||
** P3 is a pointer to a virtual table object, an sqlite3_vtab structure.
|
||||
** This opcode invokes the corresponding xUpdate method. P2 values
|
||||
** are taken from the stack to pass to the xUpdate invocation. The
|
||||
** value on the top of the stack corresponds to the p2th element
|
||||
** of the argv array passed to xUpdate.
|
||||
**
|
||||
** The xUpdate method will do a DELETE or an INSERT or both.
|
||||
** The argv[0] element (which corresponds to the P2-th element down
|
||||
** on the stack) is the rowid of a row to delete. If argv[0] is
|
||||
** NULL then no deletion occurs. The argv[1] element is the rowid
|
||||
** of the new row. This can be NULL to have the virtual table
|
||||
** select the new rowid for itself. The higher elements in the
|
||||
** stack are the values of columns in the new row.
|
||||
**
|
||||
** If P2==1 then no insert is performed. argv[0] is the rowid of
|
||||
** a row to delete.
|
||||
**
|
||||
** P1 is a boolean flag. If it is set to true and the xUpdate call
|
||||
** is successful, then the value returned by sqlite3_last_insert_rowid()
|
||||
** is set to the value of the rowid for the row just inserted.
|
||||
*/
|
||||
case OP_VUpdate: { /* no-push */
|
||||
sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3);
|
||||
sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule;
|
||||
int nArg = pOp->p2;
|
||||
assert( pOp->p3type==P3_VTAB );
|
||||
if( pModule->xUpdate==0 ){
|
||||
sqlite3SetString(&p->zErrMsg, "read-only table", 0);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
int i;
|
||||
sqlite_int64 rowid;
|
||||
Mem **apArg = p->apArg;
|
||||
Mem *pX = &pTos[1-nArg];
|
||||
for(i = 0; i<nArg; i++, pX++){
|
||||
storeTypeInfo(pX, 0);
|
||||
apArg[i] = pX;
|
||||
}
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
sqlite3VtabLock(pVtab);
|
||||
rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
|
||||
sqlite3VtabUnlock(pVtab);
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
if( pOp->p1 && rc==SQLITE_OK ){
|
||||
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
|
||||
db->lastRowid = rowid;
|
||||
}
|
||||
}
|
||||
popStack(&pTos, nArg);
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
/* An other opcode is illegal...
|
||||
*/
|
||||
@ -4560,8 +4916,12 @@ 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 ){
|
||||
/* Sanity checking on the top element of the stack. If the previous
|
||||
** instruction was VNoChange, then the flags field of the top
|
||||
** of the stack is set to 0. This is technically invalid for a memory
|
||||
** cell, so avoid calling MemSanity() in this case.
|
||||
*/
|
||||
if( pTos>=p->aStack && pTos->flags ){
|
||||
sqlite3VdbeMemSanity(pTos);
|
||||
}
|
||||
assert( pc>=-1 && pc<p->nOp );
|
||||
@ -4634,8 +4994,7 @@ abort_due_to_error:
|
||||
** flag.
|
||||
*/
|
||||
abort_due_to_interrupt:
|
||||
assert( db->flags & SQLITE_Interrupt );
|
||||
db->flags &= ~SQLITE_Interrupt;
|
||||
assert( db->u1.isInterrupted );
|
||||
if( db->magic!=SQLITE_MAGIC_BUSY ){
|
||||
rc = SQLITE_MISUSE;
|
||||
}else{
|
||||
|
Reference in New Issue
Block a user