1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Merge all recent trunk enhancements into the sessions branch.

FossilOrigin-Name: 54aaa6f29ad1bf84148c2403eed77e8311f68d66
This commit is contained in:
drh
2015-03-24 19:02:13 +00:00
42 changed files with 1110 additions and 400 deletions

View File

@@ -3245,20 +3245,6 @@ case OP_SetCookie: { /* in3 */
** See also OpenRead.
*/
case OP_ReopenIdx: {
VdbeCursor *pCur;
assert( pOp->p5==0 );
assert( pOp->p4type==P4_KEYINFO );
pCur = p->apCsr[pOp->p1];
if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
break;
}
/* If the cursor is not currently open or is open on a different
** index, then fall through into OP_OpenRead to force a reopen */
}
case OP_OpenRead:
case OP_OpenWrite: {
int nField;
KeyInfo *pKeyInfo;
int p2;
@@ -3268,8 +3254,20 @@ case OP_OpenWrite: {
VdbeCursor *pCur;
Db *pDb;
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
assert( pOp->p4type==P4_KEYINFO );
pCur = p->apCsr[pOp->p1];
if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
goto open_cursor_set_hints;
}
/* If the cursor is not currently open or is open on a different
** index, then fall through into OP_OpenRead to force a reopen */
case OP_OpenRead:
case OP_OpenWrite:
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR|OPFLAG_SEEKEQ))==pOp->p5 );
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
assert( p->bIsReader );
assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
|| p->readOnly==0 );
@@ -3332,14 +3330,17 @@ case OP_OpenWrite: {
pCur->pgnoRoot = p2;
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
pCur->pKeyInfo = pKeyInfo;
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
/* Set the VdbeCursor.isTable variable. Previous versions of
** SQLite used to check if the root-page flags were sane at this point
** and report database corruption if they were not, but this check has
** since moved into the btree layer. */
pCur->isTable = pOp->p4type!=P4_KEYINFO;
open_cursor_set_hints:
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
sqlite3BtreeCursorHints(pCur->pCursor,
(pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
break;
}
@@ -3600,6 +3601,22 @@ case OP_SeekGT: { /* jump, in3 */
#ifdef SQLITE_DEBUG
pC->seekOp = pOp->opcode;
#endif
/* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
** OP_SeekLE opcodes are allowed, and these must be immediately followed
** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
*/
#ifdef SQLITE_DEBUG
if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){
assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
assert( pOp[1].p1==pOp[0].p1 );
assert( pOp[1].p2==pOp[0].p2 );
assert( pOp[1].p3==pOp[0].p3 );
assert( pOp[1].p4.i==pOp[0].p4.i );
}
#endif
if( pC->isTable ){
/* The input value in P3 might be of any type: integer, real, string,
** blob, or NULL. But it needs to be an integer before we can do
@@ -4989,30 +5006,15 @@ case OP_IdxGE: { /* jump */
*/
case OP_Destroy: { /* out2-prerelease */
int iMoved;
int iCnt;
Vdbe *pVdbe;
int iDb;
assert( p->readOnly==0 );
#ifndef SQLITE_OMIT_VIRTUALTABLE
iCnt = 0;
for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){
if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->bIsReader
&& pVdbe->inVtabMethod<2 && pVdbe->pc>=0
){
iCnt++;
}
}
#else
iCnt = db->nVdbeRead;
#endif
pOut->flags = MEM_Null;
if( iCnt>1 ){
if( db->nVdbeRead > db->nVDestroy+1 ){
rc = SQLITE_LOCKED;
p->errorAction = OE_Abort;
}else{
iDb = pOp->p3;
assert( iCnt==1 );
assert( DbMaskTest(p->btreeMask, iDb) );
iMoved = 0; /* Not needed. Only to silence a warning. */
rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
@@ -6069,13 +6071,29 @@ case OP_VBegin: {
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VCreate P1 * * P4 *
/* Opcode: VCreate P1 P2 * * *
**
** P4 is the name of a virtual table in database P1. Call the xCreate method
** for that table.
** P2 is a register that holds the name of a virtual table in database
** P1. Call the xCreate method for that table.
*/
case OP_VCreate: {
rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg);
Mem sMem; /* For storing the record being decoded */
const char *zTab; /* Name of the virtual table */
memset(&sMem, 0, sizeof(sMem));
sMem.db = db;
/* Because P2 is always a static string, it is impossible for the
** sqlite3VdbeMemCopy() to fail */
assert( (aMem[pOp->p2].flags & MEM_Str)!=0 );
assert( (aMem[pOp->p2].flags & MEM_Static)!=0 );
rc = sqlite3VdbeMemCopy(&sMem, &aMem[pOp->p2]);
assert( rc==SQLITE_OK );
zTab = (const char*)sqlite3_value_text(&sMem);
assert( zTab || db->mallocFailed );
if( zTab ){
rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg);
}
sqlite3VdbeMemRelease(&sMem);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -6087,9 +6105,9 @@ case OP_VCreate: {
** of that table.
*/
case OP_VDestroy: {
p->inVtabMethod = 2;
db->nVDestroy++;
rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
p->inVtabMethod = 0;
db->nVDestroy--;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -6105,14 +6123,17 @@ case OP_VOpen: {
VdbeCursor *pCur;
sqlite3_vtab_cursor *pVtabCursor;
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
const sqlite3_module *pModule;
assert( p->bIsReader );
pCur = 0;
pVtabCursor = 0;
pVtab = pOp->p4.pVtab->pVtab;
pModule = (sqlite3_module *)pVtab->pModule;
assert(pVtab && pModule);
if( pVtab==0 || NEVER(pVtab->pModule==0) ){
rc = SQLITE_LOCKED;
break;
}
pModule = pVtab->pModule;
rc = pModule->xOpen(pVtab, &pVtabCursor);
sqlite3VtabImportErrmsg(p, pVtab);
if( SQLITE_OK==rc ){
@@ -6123,6 +6144,7 @@ case OP_VOpen: {
pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
if( pCur ){
pCur->pVtabCursor = pVtabCursor;
pVtab->nRef++;
}else{
db->mallocFailed = 1;
pModule->xClose(pVtabCursor);
@@ -6188,9 +6210,7 @@ case OP_VFilter: { /* jump */
apArg[i] = &pArgc[i+1];
}
p->inVtabMethod = 1;
rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
p->inVtabMethod = 0;
sqlite3VtabImportErrmsg(p, pVtab);
if( rc==SQLITE_OK ){
res = pModule->xEof(pVtabCursor);
@@ -6280,9 +6300,7 @@ case OP_VNext: { /* jump */
** data is available) and the error code returned when xColumn or
** some other method is next invoked on the save virtual table cursor.
*/
p->inVtabMethod = 1;
rc = pModule->xNext(pCur->pVtabCursor);
p->inVtabMethod = 0;
sqlite3VtabImportErrmsg(p, pVtab);
if( rc==SQLITE_OK ){
res = pModule->xEof(pCur->pVtabCursor);
@@ -6357,7 +6375,7 @@ case OP_VRename: {
*/
case OP_VUpdate: {
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
const sqlite3_module *pModule;
int nArg;
int i;
sqlite_int64 rowid;
@@ -6369,7 +6387,11 @@ case OP_VUpdate: {
);
assert( p->readOnly==0 );
pVtab = pOp->p4.pVtab->pVtab;
pModule = (sqlite3_module *)pVtab->pModule;
if( pVtab==0 || NEVER(pVtab->pModule==0) ){
rc = SQLITE_LOCKED;
break;
}
pModule = pVtab->pModule;
nArg = pOp->p2;
assert( pOp->p4type==P4_VTAB );
if( ALWAYS(pModule->xUpdate) ){