Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix for the sqlite3AbortOtherActiveVdbes() problem. (CVS 4328) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
e40d40a5d41c491bef852a92e5846b27 |
User & Date: | drh 2007-08-30 01:19:59.000 |
Context
2007-08-30
| ||
02:26 | Test case fixes for fulltest. (CVS 4329) (check-in: cddce49505 user: drh tags: trunk) | |
01:19 | Fix for the sqlite3AbortOtherActiveVdbes() problem. (CVS 4328) (check-in: e40d40a5d4 user: drh tags: trunk) | |
2007-08-29
| ||
19:15 | Fix minor problems on various tests. This is a snapshot prior to possible major changes in order to fix the sqlite3AbortOtherActiveVdbes problem. (CVS 4327) (check-in: 35cb63ecfd user: drh tags: trunk) | |
Changes
Changes to src/btmutex.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* ** 2007 August 27 ** ** 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. ** ************************************************************************* ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* ** 2007 August 27 ** ** 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. ** ************************************************************************* ** ** $Id: btmutex.c,v 1.7 2007/08/30 01:19:59 drh Exp $ ** ** This file contains code used to implement mutexes on Btree objects. ** This code really belongs in btree.c. But btree.c is getting too ** big and we want to break it down some. This packaged seemed like ** a good breakout. */ #include "btreeInt.h" |
︙ | ︙ | |||
235 236 237 238 239 240 241 | ** ** The number of shared btrees will always be small (usually 0 or 1) ** so an insertion sort is an adequate algorithm here. */ void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){ int i, j; BtShared *pBt; | | | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | ** ** The number of shared btrees will always be small (usually 0 or 1) ** so an insertion sort is an adequate algorithm here. */ void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){ int i, j; BtShared *pBt; if( pBtree==0 || pBtree->sharable==0 ) return; #ifndef NDEBUG { for(i=0; i<pArray->nMutex; i++){ assert( pArray->aBtree[i]!=pBtree ); } } #endif |
︙ | ︙ |
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* ** $Id: btree.c,v 1.420 2007/08/30 01:19:59 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ #include "btreeInt.h" |
︙ | ︙ | |||
352 353 354 355 356 357 358 | ** If the second argument argument - doSeek - is false, then instead of ** returning the cursor to it's saved position, any saved position is deleted ** and the cursor state set to CURSOR_INVALID. */ int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){ int rc; assert( cursorHoldsMutex(pCur) ); | > | > > | | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 | ** If the second argument argument - doSeek - is false, then instead of ** returning the cursor to it's saved position, any saved position is deleted ** and the cursor state set to CURSOR_INVALID. */ int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){ int rc; assert( cursorHoldsMutex(pCur) ); assert( pCur->eState>=CURSOR_REQUIRESEEK ); if( pCur->eState==CURSOR_FAULT ){ return pCur->skip; } #ifndef SQLITE_OMIT_INCRBLOB if( pCur->isIncrblobHandle ){ return SQLITE_ABORT; } #endif pCur->eState = CURSOR_INVALID; rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip); if( rc==SQLITE_OK ){ sqlite3_free(pCur->pKey); pCur->pKey = 0; assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); } return rc; } #define restoreOrClearCursorPosition(p) \ (p->eState>=CURSOR_REQUIRESEEK ? \ sqlite3BtreeRestoreOrClearCursorPosition(p) : \ SQLITE_OK) #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Given a page number of a regular database page, return the page ** number for the pointer-map page that contains the entry for the |
︙ | ︙ | |||
2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 | } #ifndef NDEBUG /* ** Return the number of write-cursors open on this handle. This is for use ** in assert() expressions, so it is only compiled if NDEBUG is not ** defined. */ static int countWriteCursors(BtShared *pBt){ BtCursor *pCur; int r = 0; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 | } #ifndef NDEBUG /* ** Return the number of write-cursors open on this handle. This is for use ** in assert() expressions, so it is only compiled if NDEBUG is not ** defined. ** ** For the purposes of this routine, a write-cursor is any cursor that ** is capable of writing to the databse. That means the cursor was ** originally opened for writing and the cursor has not be disabled ** by having its state changed to CURSOR_FAULT. */ static int countWriteCursors(BtShared *pBt){ BtCursor *pCur; int r = 0; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++; } return r; } #endif /* ** This routine sets the state to CURSOR_FAULT and the error ** code to errCode for every cursor on BtShared that pBtree ** references. ** ** Every cursor is tripped, including cursors that belong ** to other database connections that happen to be sharing ** the cache with pBtree. ** ** This routine gets called when a rollback occurs. ** All cursors using the same cache must be tripped ** to prevent them from trying to use the btree after ** the rollback. The rollback may have deleted tables ** or moved root pages, so it is not sufficient to ** save the state of the cursor. The cursor must be ** invalidated. */ void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ BtCursor *p; sqlite3BtreeEnter(pBtree); for(p=pBtree->pBt->pCursor; p; p=p->pNext){ clearCursorPosition(p); p->eState = CURSOR_FAULT; p->skip = errCode; } sqlite3BtreeLeave(pBtree); } /* ** Rollback the transaction in progress. All cursors will be ** invalided by this operation. Any attempt to use a cursor ** that was open at the beginning of this operation will result ** in an error. ** |
︙ | ︙ | |||
2426 2427 2428 2429 2430 2431 2432 | /* This is a horrible situation. An IO or malloc() error occured whilst ** trying to save cursor positions. If this is an automatic rollback (as ** the result of a constraint, malloc() failure or IO error) then ** the cache may be internally inconsistent (not contain valid trees) so ** we cannot simply return the error to the caller. Instead, abort ** all queries that may be using any of the cursors that failed to save. */ | | < < < < < < < < | 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 | /* This is a horrible situation. An IO or malloc() error occured whilst ** trying to save cursor positions. If this is an automatic rollback (as ** the result of a constraint, malloc() failure or IO error) then ** the cache may be internally inconsistent (not contain valid trees) so ** we cannot simply return the error to the caller. Instead, abort ** all queries that may be using any of the cursors that failed to save. */ sqlite3BtreeTripAllCursors(p, rc); } #endif btreeIntegrity(p); unlockAllTables(p); if( p->inTrans==TRANS_WRITE ){ int rc2; |
︙ | ︙ | |||
3339 3340 3341 3342 3343 3344 3345 | static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; int rc = SQLITE_OK; Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; assert( cursorHoldsMutex(pCur) ); | > > > > | > > | 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 | static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; int rc = SQLITE_OK; Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; assert( cursorHoldsMutex(pCur) ); assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); if( pCur->eState>=CURSOR_REQUIRESEEK ){ if( pCur->eState==CURSOR_FAULT ){ return pCur->skip; } clearCursorPosition(pCur); } pRoot = pCur->pPage; if( pRoot && pRoot->pgno==pCur->pgnoRoot ){ assert( pRoot->isInit ); }else{ if( |
︙ | ︙ | |||
5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 | assert( !pBt->readOnly ); if( !pCur->wrFlag ){ return SQLITE_PERM; /* Cursor not open for writing */ } if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } /* Save the positions of any other cursors open on this table */ clearCursorPosition(pCur); if( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) ){ | > > > | 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 | assert( !pBt->readOnly ); if( !pCur->wrFlag ){ return SQLITE_PERM; /* Cursor not open for writing */ } if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } if( pCur->eState==CURSOR_FAULT ){ return pCur->skip; } /* Save the positions of any other cursors open on this table */ clearCursorPosition(pCur); if( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) ){ |
︙ | ︙ | |||
5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 | assert( pPage->isInit ); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing a delete */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; return rc; } assert( !pBt->readOnly ); if( pCur->idx >= pPage->nCell ){ return SQLITE_ERROR; /* The cursor is not pointing to anything */ } if( !pCur->wrFlag ){ return SQLITE_PERM; /* Did not open this cursor for writing */ } if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ | > > > | 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 | assert( pPage->isInit ); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing a delete */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; return rc; } assert( !pBt->readOnly ); if( pCur->eState==CURSOR_FAULT ){ return pCur->skip; } if( pCur->idx >= pPage->nCell ){ return SQLITE_ERROR; /* The cursor is not pointing to anything */ } if( !pCur->wrFlag ){ return SQLITE_PERM; /* Did not open this cursor for writing */ } if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ |
︙ | ︙ | |||
6785 6786 6787 6788 6789 6790 6791 | ** Only the data content may only be modified, it is not possible ** to change the length of the data stored. */ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ assert( cursorHoldsMutex(pCsr) ); assert( sqlite3_mutex_held(pCsr->pBtree->pSqlite->mutex) ); assert(pCsr->isIncrblobHandle); | > | > > | > | 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 | ** Only the data content may only be modified, it is not possible ** to change the length of the data stored. */ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ assert( cursorHoldsMutex(pCsr) ); assert( sqlite3_mutex_held(pCsr->pBtree->pSqlite->mutex) ); assert(pCsr->isIncrblobHandle); if( pCsr->eState>=CURSOR_REQUIRESEEK ){ if( pCsr->eState==CURSOR_FAULT ){ return pCsr->skip; }else{ return SQLITE_ABORT; } } /* Check some preconditions: ** (a) the cursor is open for writing, ** (b) there is no read-lock on the table being modified and ** (c) the cursor points at a valid row of an intKey table. */ |
︙ | ︙ |
Changes to src/btree.h.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** ** @(#) $Id: btree.h,v 1.92 2007/08/30 01:19:59 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ |
︙ | ︙ | |||
121 122 123 124 125 126 127 128 129 130 131 132 133 134 | #define BTREE_ZERODATA 2 /* Table has keys only - no data */ #define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */ int sqlite3BtreeDropTable(Btree*, int, int*); int sqlite3BtreeClearTable(Btree*, int); int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue); int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ int iTable, /* Index of root page */ int wrFlag, /* 1 for writing. 0 for read-only */ int(*)(void*,int,const void*,int,const void*), /* Key comparison function */ void*, /* First argument to compare function */ | > | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | #define BTREE_ZERODATA 2 /* Table has keys only - no data */ #define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */ int sqlite3BtreeDropTable(Btree*, int, int*); int sqlite3BtreeClearTable(Btree*, int); int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue); int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); void sqlite3BtreeTripAllCursors(Btree*, int); int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ int iTable, /* Index of root page */ int wrFlag, /* 1 for writing. 0 for read-only */ int(*)(void*,int,const void*,int,const void*), /* Key comparison function */ void*, /* First argument to compare function */ |
︙ | ︙ |
Changes to src/btreeInt.h.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* ** $Id: btreeInt.h,v 1.13 2007/08/30 01:19:59 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | ** ** CURSOR_REQUIRESEEK: ** The table that this cursor was opened on still exists, but has been ** modified since the cursor was last used. The cursor position is saved ** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in ** this state, restoreOrClearCursorPosition() can be called to attempt to ** seek the cursor to the saved position. */ #define CURSOR_INVALID 0 #define CURSOR_VALID 1 #define CURSOR_REQUIRESEEK 2 /* ** The TRACE macro will print high-level status information about the ** btree operation when the global variable sqlite3_btree_trace is ** enabled. */ #if SQLITE_TEST | > > > > > > > > | 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 | ** ** CURSOR_REQUIRESEEK: ** The table that this cursor was opened on still exists, but has been ** modified since the cursor was last used. The cursor position is saved ** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in ** this state, restoreOrClearCursorPosition() can be called to attempt to ** seek the cursor to the saved position. ** ** CURSOR_FAULT: ** A unrecoverable error (an I/O error or a malloc failure) has occurred ** on a different connection that shares the BtShared cache with this ** cursor. The error has left the cache in an inconsistent state. ** Do nothing else with this cursor. Any attempt to use the cursor ** should return the error code stored in BtCursor.skip */ #define CURSOR_INVALID 0 #define CURSOR_VALID 1 #define CURSOR_REQUIRESEEK 2 #define CURSOR_FAULT 3 /* ** The TRACE macro will print high-level status information about the ** btree operation when the global variable sqlite3_btree_trace is ** enabled. */ #if SQLITE_TEST |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.443 2007/08/30 01:19:59 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. |
︙ | ︙ | |||
160 161 162 163 164 165 166 | */ if( pParse->cookieGoto>0 ){ u32 mask; int iDb; sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; | | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | */ if( pParse->cookieGoto>0 ){ u32 mask; int iDb; sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0); sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); } #ifndef SQLITE_OMIT_VIRTUALTABLE if( pParse->pVirtualLock ){ char *vtab = (char *)pParse->pVirtualLock->pVtab; sqlite3VdbeOp3(v, OP_VBegin, 0, 0, vtab, P3_VTAB); |
︙ | ︙ | |||
843 844 845 846 847 848 849 850 851 852 853 854 855 856 | } #endif /* If the file format and encoding in the database have not been set, ** set them now. */ sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); /* file_format */ lbl = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_If, 0, lbl); fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? 1 : SQLITE_MAX_FILE_FORMAT; sqlite3VdbeAddOp(v, OP_Integer, fileFormat, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); sqlite3VdbeAddOp(v, OP_Integer, ENC(db), 0); | > | 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 | } #endif /* If the file format and encoding in the database have not been set, ** set them now. */ sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); /* file_format */ sqlite3VdbeUsesBtree(v, iDb); lbl = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_If, 0, lbl); fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? 1 : SQLITE_MAX_FILE_FORMAT; sqlite3VdbeAddOp(v, OP_Integer, fileFormat, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); sqlite3VdbeAddOp(v, OP_Integer, ENC(db), 0); |
︙ | ︙ | |||
2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 | ** The generated code will increase the file format number if necessary. */ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ Vdbe *v; v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); } } | > | 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 | ** The generated code will increase the file format number if necessary. */ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ Vdbe *v; v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); } } |
︙ | ︙ | |||
3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 | if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; v = sqlite3GetVdbe(pParse); if( !v ) return; if( type!=TK_DEFERRED ){ for(i=0; i<db->nDb; i++){ sqlite3VdbeAddOp(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); } } sqlite3VdbeAddOp(v, OP_AutoCommit, 0, 0); } /* ** Commit a transaction | > | 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 | if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; v = sqlite3GetVdbe(pParse); if( !v ) return; if( type!=TK_DEFERRED ){ for(i=0; i<db->nDb; i++){ sqlite3VdbeAddOp(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); sqlite3VdbeUsesBtree(v, i); } } sqlite3VdbeAddOp(v, OP_AutoCommit, 0, 0); } /* ** Commit a transaction |
︙ | ︙ |
Changes to src/pragma.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2003 April 6 ** ** 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. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2003 April 6 ** ** 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. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** ** $Id: pragma.c,v 1.147 2007/08/30 01:19:59 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* Ignore this whole file if pragmas are disabled */ #if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER) |
︙ | ︙ | |||
296 297 298 299 300 301 302 303 304 305 306 307 308 309 | { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 6, 0}, { OP_Integer, 0, 0, 0}, /* 5 */ { OP_Callback, 1, 0, 0}, }; int addr; if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( !zRight ){ sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P3_STATIC); addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+5, SQLITE_DEFAULT_CACHE_SIZE); }else{ | > | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 6, 0}, { OP_Integer, 0, 0, 0}, /* 5 */ { OP_Callback, 1, 0, 0}, }; int addr; if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeUsesBtree(v, iDb); if( !zRight ){ sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P3_STATIC); addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+5, SQLITE_DEFAULT_CACHE_SIZE); }else{ |
︙ | ︙ | |||
451 452 453 454 455 456 457 458 459 460 461 462 463 464 | int iAddr; iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); sqlite3VdbeChangeP1(v, iAddr, iDb); sqlite3VdbeChangeP1(v, iAddr+1, iDb); sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1); sqlite3VdbeChangeP1(v, iAddr+5, iDb); } } } }else #endif /* | > | 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | int iAddr; iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); sqlite3VdbeChangeP1(v, iAddr, iDb); sqlite3VdbeChangeP1(v, iAddr+1, iDb); sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1); sqlite3VdbeChangeP1(v, iAddr+5, iDb); sqlite3VdbeUsesBtree(v, iDb); } } } }else #endif /* |
︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 | */ if( sqlite3StrICmp(zLeft, "schema_version")==0 || sqlite3StrICmp(zLeft, "user_version")==0 || sqlite3StrICmp(zLeft, "freelist_count")==0 ){ int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */ switch( zLeft[0] ){ case 's': case 'S': iCookie = 0; break; case 'f': case 'F': iCookie = 1; iDb = (-1*(iDb+1)); | > | 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 | */ if( sqlite3StrICmp(zLeft, "schema_version")==0 || sqlite3StrICmp(zLeft, "user_version")==0 || sqlite3StrICmp(zLeft, "freelist_count")==0 ){ int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */ sqlite3VdbeUsesBtree(v, iDb); switch( zLeft[0] ){ case 's': case 'S': iCookie = 0; break; case 'f': case 'F': iCookie = 1; iDb = (-1*(iDb+1)); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** 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. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** 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.648 2007/08/30 01:19:59 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include <math.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 | ** has an index of 1. */ case OP_Statement: { /* no-push */ int i = pOp->p1; Btree *pBt; if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt)!=0 && !(db->autoCommit) ){ assert( sqlite3BtreeIsInTrans(pBt) ); if( !sqlite3BtreeIsInStmt(pBt) ){ rc = sqlite3BtreeBeginStmt(pBt); p->openedStatement = 1; } } break; } | > | 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 | ** has an index of 1. */ case OP_Statement: { /* no-push */ int i = pOp->p1; Btree *pBt; if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt)!=0 && !(db->autoCommit) ){ assert( sqlite3BtreeIsInTrans(pBt) ); assert( (p->btreeMask & (1<<i))!=0 ); if( !sqlite3BtreeIsInStmt(pBt) ){ rc = sqlite3BtreeBeginStmt(pBt); p->openedStatement = 1; } } break; } |
︙ | ︙ | |||
2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 | ** If P2 is zero, then a read-lock is obtained on the database file. */ case OP_Transaction: { /* no-push */ int i = pOp->p1; Btree *pBt; assert( i>=0 && i<db->nDb ); pBt = db->aDb[i].pBt; if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ p->pc = pc; p->rc = rc = SQLITE_BUSY; | > | 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 | ** If P2 is zero, then a read-lock is obtained on the database file. */ case OP_Transaction: { /* no-push */ int i = pOp->p1; Btree *pBt; assert( i>=0 && i<db->nDb ); assert( (p->btreeMask & (1<<i))!=0 ); pBt = db->aDb[i].pBt; if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ p->pc = pc; p->rc = rc = SQLITE_BUSY; |
︙ | ︙ | |||
2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 | assert( pOp->p2<SQLITE_N_BTREE_META ); if( iDb<0 ){ iDb = (-1*(iDb+1)); iCookie *= -1; } assert( iDb>=0 && iDb<db->nDb ); assert( db->aDb[iDb].pBt!=0 ); /* The indexing of meta values at the schema layer is off by one from ** the indexing in the btree layer. The btree considers meta[0] to ** be the number of free pages in the database (a read-only value) ** and meta[1] to be the schema cookie. The schema layer considers ** meta[1] to be the schema cookie. So we have to shift the index ** by one in the following statement. */ | > | 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 | assert( pOp->p2<SQLITE_N_BTREE_META ); if( iDb<0 ){ iDb = (-1*(iDb+1)); iCookie *= -1; } assert( iDb>=0 && iDb<db->nDb ); assert( db->aDb[iDb].pBt!=0 ); assert( (p->btreeMask & (1<<iDb))!=0 ); /* The indexing of meta values at the schema layer is off by one from ** the indexing in the btree layer. The btree considers meta[0] to ** be the number of free pages in the database (a read-only value) ** and meta[1] to be the schema cookie. The schema layer considers ** meta[1] to be the schema cookie. So we have to shift the index ** by one in the following statement. */ |
︙ | ︙ | |||
2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 | ** ** A transaction must be started before executing this opcode. */ case OP_SetCookie: { /* no-push */ Db *pDb; assert( pOp->p2<SQLITE_N_BTREE_META ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); assert( pTos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); /* See note about index shifting on OP_ReadCookie */ rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pTos->u.i); if( pOp->p2==0 ){ | > | 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 | ** ** A transaction must be started before executing this opcode. */ case OP_SetCookie: { /* no-push */ Db *pDb; assert( pOp->p2<SQLITE_N_BTREE_META ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (1<<pOp->p1))!=0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); assert( pTos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); /* See note about index shifting on OP_ReadCookie */ rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pTos->u.i); if( pOp->p2==0 ){ |
︙ | ︙ | |||
2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 | ** to be executed (to establish a read lock) before this opcode is ** invoked. */ case OP_VerifyCookie: { /* no-push */ int iMeta; Btree *pBt; assert( pOp->p1>=0 && pOp->p1<db->nDb ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&iMeta); }else{ rc = SQLITE_OK; iMeta = 0; } | > | 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 | ** to be executed (to establish a read lock) before this opcode is ** invoked. */ case OP_VerifyCookie: { /* no-push */ int iMeta; Btree *pBt; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (1<<pOp->p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&iMeta); }else{ rc = SQLITE_OK; iMeta = 0; } |
︙ | ︙ | |||
2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 | assert( pTos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); iDb = pTos->u.i; assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; assert( iDb>=0 && iDb<db->nDb ); pDb = &db->aDb[iDb]; pX = pDb->pBt; assert( pX!=0 ); if( pOp->opcode==OP_OpenWrite ){ wrFlag = 1; if( pDb->pSchema->file_format < p->minWriteFileFormat ){ p->minWriteFileFormat = pDb->pSchema->file_format; | > | 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 | assert( pTos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); iDb = pTos->u.i; assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; assert( iDb>=0 && iDb<db->nDb ); assert( (p->btreeMask & (1<<iDb))!=0 ); pDb = &db->aDb[iDb]; pX = pDb->pBt; assert( pX!=0 ); if( pOp->opcode==OP_OpenWrite ){ wrFlag = 1; if( pDb->pSchema->file_format < p->minWriteFileFormat ){ p->minWriteFileFormat = pDb->pSchema->file_format; |
︙ | ︙ | |||
4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 | #else iCnt = db->activeVdbeCnt; #endif if( iCnt>1 ){ rc = SQLITE_LOCKED; }else{ assert( iCnt==1 ); rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved); pTos++; pTos->flags = MEM_Int; pTos->u.i = iMoved; #ifndef SQLITE_OMIT_AUTOVACUUM if( rc==SQLITE_OK && iMoved!=0 ){ sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1); | > | 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 | #else iCnt = db->activeVdbeCnt; #endif if( iCnt>1 ){ rc = SQLITE_LOCKED; }else{ assert( iCnt==1 ); assert( (p->btreeMask & (1<<pOp->p2))!=0 ); rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved); pTos++; pTos->flags = MEM_Int; pTos->u.i = iMoved; #ifndef SQLITE_OMIT_AUTOVACUUM if( rc==SQLITE_OK && iMoved!=0 ){ sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1); |
︙ | ︙ | |||
4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 | } sqlite3BtreeCloseCursor(pCur); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } } #endif rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1); break; } /* Opcode: CreateTable P1 * * ** ** Allocate a new table in the main database file if P2==0 or in the | > | 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 | } sqlite3BtreeCloseCursor(pCur); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } } #endif assert( (p->btreeMask & (1<<pOp->p2))!=0 ); rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1); break; } /* Opcode: CreateTable P1 * * ** ** Allocate a new table in the main database file if P2==0 or in the |
︙ | ︙ | |||
4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 | */ case OP_CreateIndex: case OP_CreateTable: { int pgno; int flags; Db *pDb; assert( pOp->p1>=0 && pOp->p1<db->nDb ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ /* flags = BTREE_INTKEY; */ flags = BTREE_LEAFDATA|BTREE_INTKEY; }else{ flags = BTREE_ZERODATA; | > | 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 | */ case OP_CreateIndex: case OP_CreateTable: { int pgno; int flags; Db *pDb; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (1<<pOp->p1))!=0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ /* flags = BTREE_INTKEY; */ flags = BTREE_LEAFDATA|BTREE_INTKEY; }else{ flags = BTREE_ZERODATA; |
︙ | ︙ | |||
4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 | assert( (pnErr->flags & MEM_Int)!=0 ); for(j=0; j<nRoot; j++){ aRoot[j] = (pTos-j)->u.i; } aRoot[j] = 0; popStack(&pTos, nRoot); pTos++; z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot, pnErr->u.i, &nErr); pnErr->u.i -= nErr; if( nErr==0 ){ assert( z==0 ); pTos->flags = MEM_Null; }else{ | > > | 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 | assert( (pnErr->flags & MEM_Int)!=0 ); for(j=0; j<nRoot; j++){ aRoot[j] = (pTos-j)->u.i; } aRoot[j] = 0; popStack(&pTos, nRoot); pTos++; assert( pOp->p2>=0 && pOp->p2<db->nDb ); assert( (p->btreeMask & (1<<pOp->p2))!=0 ); z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot, pnErr->u.i, &nErr); pnErr->u.i -= nErr; if( nErr==0 ){ assert( z==0 ); pTos->flags = MEM_Null; }else{ |
︙ | ︙ | |||
4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 | ** the P1 database. If the vacuum has finished, jump to instruction ** P2. Otherwise, fall through to the next instruction. */ case OP_IncrVacuum: { /* no-push */ Btree *pBt; assert( pOp->p1>=0 && pOp->p1<db->nDb ); pBt = db->aDb[pOp->p1].pBt; rc = sqlite3BtreeIncrVacuum(pBt); if( rc==SQLITE_DONE ){ pc = pOp->p2 - 1; rc = SQLITE_OK; } break; | > | 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 | ** the P1 database. If the vacuum has finished, jump to instruction ** P2. Otherwise, fall through to the next instruction. */ case OP_IncrVacuum: { /* no-push */ Btree *pBt; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (1<<pOp->p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; rc = sqlite3BtreeIncrVacuum(pBt); if( rc==SQLITE_DONE ){ pc = pOp->p2 - 1; rc = SQLITE_OK; } break; |
︙ | ︙ | |||
4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 | */ case OP_TableLock: { /* no-push */ int p1 = pOp->p1; u8 isWriteLock = (p1<0); if( isWriteLock ){ p1 = (-1*p1)-1; } rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock); if( rc==SQLITE_LOCKED ){ const char *z = (const char *)pOp->p3; sqlite3SetString(&p->zErrMsg, "database table is locked: ", z, (char*)0); } break; } | > > | 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 | */ case OP_TableLock: { /* no-push */ int p1 = pOp->p1; u8 isWriteLock = (p1<0); if( isWriteLock ){ p1 = (-1*p1)-1; } assert( p1>=0 && p1<db->nDb ); assert( (p->btreeMask & (1<<p1))!=0 ); rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock); if( rc==SQLITE_LOCKED ){ const char *z = (const char *)pOp->p3; sqlite3SetString(&p->zErrMsg, "database table is locked: ", z, (char*)0); } break; } |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** ** $Id: vdbe.h,v 1.113 2007/08/30 01:19:59 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
116 117 118 119 120 121 122 | int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int); int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int); int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); void sqlite3VdbeUsesBtree(Vdbe*, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); int sqlite3VdbeCurrentAddr(Vdbe*); |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
656 657 658 659 660 661 662 | } #endif /* ** Declare to the Vdbe that the BTree object at db->aDb[i] is used. ** */ | | > > | | | > | 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 | } #endif /* ** Declare to the Vdbe that the BTree object at db->aDb[i] is used. ** */ void sqlite3VdbeUsesBtree(Vdbe *p, int i){ int mask; assert( i>=0 && i<p->db->nDb ); assert( i<sizeof(p->btreeMask)*8 ); mask = 1<<i; if( (p->btreeMask & mask)==0 ){ p->btreeMask |= mask; sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt); } } #if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* ** Print a single opcode. This routine is used for debugging only. */ |
︙ | ︙ | |||
1297 1298 1299 1300 1301 1302 1303 | assert( cnt==db->activeVdbeCnt ); } #else #define checkActiveVdbeCnt(x) #endif /* | | > > | > | | > | > > > > > | | | > | < < | < < > | 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 | assert( cnt==db->activeVdbeCnt ); } #else #define checkActiveVdbeCnt(x) #endif /* ** For every Btree that in database connection db which ** has been modified, "trip" or invalidate each cursor in ** that Btree might have been modified so that the cursor ** can never be used again. This happens when a rollback *** occurs. We have to trip all the other cursors, even ** cursor from other VMs in different database connections, ** so that none of them try to use the data at which they ** were pointing and which now may have been changed due ** to the rollback. ** ** Remember that a rollback can delete tables complete and ** reorder rootpages. So it is not sufficient just to save ** the state of the cursor. We have to invalidate the cursor ** so that it is never used again. */ void invalidateCursorsOnModifiedBtrees(sqlite3 *db){ int i; for(i=0; i<db->nDb; i++){ Btree *p = db->aDb[i].pBt; if( p && sqlite3BtreeIsInTrans(p) ){ sqlite3BtreeTripAllCursors(p, SQLITE_ABORT); } } } /* ** This routine is called the when a VDBE tries to halt. If the VDBE ** has made changes and is in autocommit mode, then commit those ** changes. If a rollback is needed, then do the rollback. |
︙ | ︙ | |||
1436 1437 1438 1439 1440 1441 1442 | p->rc = SQLITE_BUSY; } else if( p->rc==SQLITE_NOMEM && isStatement ){ xFunc = sqlite3BtreeRollbackStmt; }else{ /* We are forced to roll back the active transaction. Before doing ** so, abort any other statements this handle currently has active. */ | | | 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 | p->rc = SQLITE_BUSY; } else if( p->rc==SQLITE_NOMEM && isStatement ){ xFunc = sqlite3BtreeRollbackStmt; }else{ /* We are forced to roll back the active transaction. Before doing ** so, abort any other statements this handle currently has active. */ invalidateCursorsOnModifiedBtrees(db); sqlite3RollbackAll(db); db->autoCommit = 1; } } } /* If the auto-commit flag is set and this is the only active vdbe, then |
︙ | ︙ | |||
1476 1477 1478 1479 1480 1481 1482 | if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ if( p->openedStatement ){ xFunc = sqlite3BtreeCommitStmt; } }else if( p->errorAction==OE_Abort ){ xFunc = sqlite3BtreeRollbackStmt; }else{ | | | 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 | if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ if( p->openedStatement ){ xFunc = sqlite3BtreeCommitStmt; } }else if( p->errorAction==OE_Abort ){ xFunc = sqlite3BtreeRollbackStmt; }else{ invalidateCursorsOnModifiedBtrees(db); sqlite3RollbackAll(db); db->autoCommit = 1; } } /* If xFunc is not NULL, then it is one of sqlite3BtreeRollbackStmt or ** sqlite3BtreeCommitStmt. Call it once on each backend. If an error occurs |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement incremental BLOB I/O. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement incremental BLOB I/O. ** ** $Id: vdbeblob.c,v 1.16 2007/08/30 01:19:59 drh Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" #ifndef SQLITE_OMIT_INCRBLOB |
︙ | ︙ | |||
160 161 162 163 164 165 166 | sqlite3VdbeChangeP2(v, 0, (flags ? 1 : 0)); /* Configure the OP_VerifyCookie */ sqlite3VdbeChangeP1(v, 1, iDb); sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie); /* Make sure a mutex is held on the table to be accessed */ | | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | sqlite3VdbeChangeP2(v, 0, (flags ? 1 : 0)); /* Configure the OP_VerifyCookie */ sqlite3VdbeChangeP1(v, 1, iDb); sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie); /* Make sure a mutex is held on the table to be accessed */ sqlite3VdbeUsesBtree(v, iDb); /* Configure the db number pushed onto the stack */ sqlite3VdbeChangeP1(v, 2, iDb); /* Remove either the OP_OpenWrite or OpenRead. Set the P2 ** parameter of the other to pTab->tnum. */ |
︙ | ︙ |