| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 ** 2004 April 6 | 2 ** 2004 April 6 |
| 3 ** | 3 ** |
| 4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
| 5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
| 6 ** | 6 ** |
| 7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
| 8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
| 9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
| 10 ** | 10 ** |
| 11 ************************************************************************* | 11 ************************************************************************* |
| 12 ** $Id: btree.c,v 1.388 2007/05/24 09:20:16 danielk1977 Exp $ | 12 ** $Id: btree.c,v 1.388 2007/05/24 09:20:16 danielk1977 Exp $ |
| 13 ** | 13 ** |
| 14 ** This file implements a external (disk-based) database using BTrees. | 14 ** This file implements a external (disk-based) database using BTrees. |
| 15 ** See the header comment on "btreeInt.h" for additional information. | 15 ** See the header comment on "btreeInt.h" for additional information. |
| 16 ** Including a description of file format and an overview of operation. | 16 ** Including a description of file format and an overview of operation. |
| 17 */ | 17 */ |
| 18 #include "btreeInt.h" | 18 #include "btreeInt.h" |
| 19 | 19 |
| 20 /* | 20 /* |
| 21 ** The header string that appears at the beginning of every | 21 ** The header string that appears at the beginning of every |
| 22 ** SQLite database. | 22 ** SQLite database. |
| 23 */ | 23 */ |
| 24 static const char zMagicHeader[] = SQLITE_FILE_HEADER; | 24 static const char zMagicHeader[] = SQLITE_FILE_HEADER; |
| 25 | 25 |
| 26 /* | 26 /* |
| 27 ** The header string that appears at the beginning of a SQLite | 27 ** The header string that appears at the beginning of a SQLite |
| 28 ** database which has been poisoned. | 28 ** database which has been poisoned. |
| 29 */ | 29 */ |
| 30 static const char zPoisonHeader[] = "SQLite poison 3"; | 30 static const char zPoisonHeader[] = "SQLite poison 3"; |
| 31 | 31 |
| 32 /* | |
| 33 ** The user cookie position in the database meta information | |
| 34 ** (see prepare.c#215), incremented by one, because first position is actually | |
| 35 ** the number of free pages in Btree (see vdbe.c#2521) | |
| 36 */ | |
| 37 static const int kUserCookie = 6; | |
| 32 | 38 |
| 33 /* | 39 /* |
| 34 ** Set this global variable to 1 to enable tracing using the TRACE | 40 ** Set this global variable to 1 to enable tracing using the TRACE |
| 35 ** macro. | 41 ** macro. |
| 36 */ | 42 */ |
| 37 #if SQLITE_TEST | 43 #if SQLITE_TEST |
| 38 int sqlite3_btree_trace=0; /* True to enable tracing */ | 44 int sqlite3_btree_trace=0; /* True to enable tracing */ |
| 39 #endif | 45 #endif |
| 40 | 46 |
| 41 /* | 47 /* |
| 42 ** Forward declaration | 48 ** Forward declaration |
| 43 */ | 49 */ |
| 44 static int checkReadLocks(Btree*,Pgno,BtCursor*); | 50 static int checkReadLocks(Btree*,Pgno,BtCursor*); |
| 45 | 51 |
| 46 | 52 |
| 47 #ifdef SQLITE_OMIT_SHARED_CACHE | 53 #ifdef SQLITE_OMIT_SHARED_CACHE |
| 48 /* | 54 /* |
| 49 ** The functions queryTableLock(), lockTable() and unlockAllTables() | 55 ** The functions queryTableLock(), lockTable() and unlockAllTables() |
| 50 ** manipulate entries in the BtShared.pLock linked list used to store | 56 ** manipulate entries in the BtShared.pLock linked list used to store |
| 51 ** shared-cache table level locks. If the library is compiled with the | 57 ** shared-cache table level locks. If the library is compiled with the |
| 52 ** shared-cache feature disabled, then there is only ever one user | 58 ** shared-cache feature disabled, then there is only ever one user |
| 53 ** of each BtShared structure and so this locking is not necessary. | 59 ** of each BtShared structure and so this locking is not necessary. |
| 54 ** So define the lock related functions as no-ops. | 60 ** So define the lock related functions as no-ops. |
| 55 */ | 61 */ |
| 56 #define queryTableLock(a,b,c) SQLITE_OK | 62 #define queryTableLock(a,b,c) SQLITE_OK |
| 57 #define lockTable(a,b,c) SQLITE_OK | 63 #define lockTable(a,b,c) SQLITE_OK |
| 58 #define unlockAllTables(a) | 64 #define unlockAllTables(a) |
| 59 #else | 65 #else |
| 60 | 66 |
| 61 /* | 67 /* |
| 62 ** Query to see if btree handle p may obtain a lock of type eLock | 68 ** Query to see if btree handle p may obtain a lock of type eLock |
| 63 ** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return | 69 ** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return |
| 64 ** SQLITE_OK if the lock may be obtained (by calling lockTable()), or | 70 ** SQLITE_OK if the lock may be obtained (by calling lockTable()), or |
| 65 ** SQLITE_LOCKED if not. | 71 ** SQLITE_LOCKED if not. |
| 66 */ | 72 */ |
| 67 static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ | 73 static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ |
| 68 BtShared *pBt = p->pBt; | 74 BtShared *pBt = p->pBt; |
| 69 BtLock *pIter; | 75 BtLock *pIter; |
| 70 | 76 |
| 71 /* This is a no-op if the shared-cache is not enabled */ | 77 /* This is a no-op if the shared-cache is not enabled */ |
| 72 if( 0==sqlite3ThreadDataReadOnly()->useSharedData ){ | 78 if( 0==sqlite3ThreadDataReadOnly()->useSharedData ){ |
| 73 return SQLITE_OK; | 79 return SQLITE_OK; |
| 74 } | 80 } |
| 75 | 81 |
| 76 /* This (along with lockTable()) is where the ReadUncommitted flag is | 82 /* This (along with lockTable()) is where the ReadUncommitted flag is |
| 77 ** dealt with. If the caller is querying for a read-lock and the flag is | 83 ** dealt with. If the caller is querying for a read-lock and the flag is |
| 78 ** set, it is unconditionally granted - even if there are write-locks | 84 ** set, it is unconditionally granted - even if there are write-locks |
| 79 ** on the table. If a write-lock is requested, the ReadUncommitted flag | 85 ** on the table. If a write-lock is requested, the ReadUncommitted flag |
| 80 ** is not considered. | 86 ** is not considered. |
| 81 ** | 87 ** |
| (...skipping 6293 matching lines...) Show 10 above Show 10 below | |
| 6375 ** to allow poisoning to be rolled back, and the database is anyhow | 6381 ** to allow poisoning to be rolled back, and the database is anyhow |
| 6376 ** going bye-bye RSN. | 6382 ** going bye-bye RSN. |
| 6377 */ | 6383 */ |
| 6378 /* TODO(shess): Figure out if this might release the lock and let | 6384 /* TODO(shess): Figure out if this might release the lock and let |
| 6379 ** someone else get in there, which might deny us the lock a couple | 6385 ** someone else get in there, which might deny us the lock a couple |
| 6380 ** lines down. | 6386 ** lines down. |
| 6381 */ | 6387 */ |
| 6382 if( sqlite3BtreeIsInTrans(p) ) sqlite3BtreeRollback(p); | 6388 if( sqlite3BtreeIsInTrans(p) ) sqlite3BtreeRollback(p); |
| 6383 | 6389 |
| 6384 /* Start an exclusive transaction. This will check the headers, so | 6390 /* Start an exclusive transaction. This will check the headers, so |
| 6385 ** if someone else poisoned the database we should get an error. | 6391 ** if someone else poisoned the database we should get an error. |
| 6386 */ | 6392 */ |
| 6387 rc = sqlite3BtreeBeginTrans(p, 2); | 6393 rc = sqlite3BtreeBeginTrans(p, 2); |
| 6388 /* TODO(shess): Handle SQLITE_BUSY? */ | 6394 /* TODO(shess): Handle SQLITE_BUSY? */ |
| 6389 if( rc!=SQLITE_OK ) return rc; | 6395 if( rc!=SQLITE_OK ) return rc; |
| 6390 | 6396 |
| 6391 /* Copied from sqlite3BtreeUpdateMeta(). Writing the old version of | 6397 /* Copied from sqlite3BtreeUpdateMeta(). Writing the old version of |
| 6392 ** the page to the journal may be overkill, but it probably won't | 6398 ** the page to the journal may be overkill, but it probably won't |
| 6393 ** hurt. | 6399 ** hurt. |
| 6394 */ | 6400 */ |
| 6395 assert( pBt->inTrans==TRANS_WRITE ); | 6401 assert( pBt->inTrans==TRANS_WRITE ); |
| 6396 assert( pBt->pPage1!=0 ); | 6402 assert( pBt->pPage1!=0 ); |
| 6397 rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); | 6403 rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); |
| 6398 if( rc ) goto err; | 6404 if( rc ) goto err; |
| 6399 | 6405 |
| 6400 /* "SQLite format 3" changes to | 6406 /* "SQLite format 3" changes to |
| 6401 ** "SQLite poison 3". Be extra paranoid about making this change. | 6407 ** "SQLite poison 3". Be extra paranoid about making this change. |
| 6402 */ | 6408 */ |
| 6403 if( sizeof(zMagicHeader)!=16 || | 6409 if( sizeof(zMagicHeader)!=16 || |
| 6404 sizeof(zPoisonHeader)!=sizeof(zMagicHeader) ){ | 6410 sizeof(zPoisonHeader)!=sizeof(zMagicHeader) ){ |
| 6405 rc = SQLITE_ERROR; | 6411 rc = SQLITE_ERROR; |
| 6406 goto err; | 6412 goto err; |
| 6407 } | 6413 } |
| 6408 pP1 = pBt->pPage1->aData; | 6414 pP1 = pBt->pPage1->aData; |
| 6409 if( memcmp(pP1, zMagicHeader, 16)!=0 ){ | 6415 if( memcmp(pP1, zMagicHeader, 16)!=0 ){ |
| 6410 rc = SQLITE_CORRUPT; | 6416 rc = SQLITE_CORRUPT; |
| 6411 goto err; | 6417 goto err; |
| 6412 } | 6418 } |
| 6413 memcpy(pP1, zPoisonHeader, 16); | 6419 memcpy(pP1, zPoisonHeader, 16); |
| 6414 | 6420 |
| 6415 /* Push it to the database file. */ | 6421 /* Push it to the database file. */ |
| 6416 return sqlite3BtreeCommit(p); | 6422 return sqlite3BtreeCommit(p); |
| 6417 | 6423 |
| 6418 err: | 6424 err: |
| 6419 /* TODO(shess): What about errors, here? */ | 6425 /* TODO(shess): What about errors, here? */ |
| 6420 sqlite3BtreeRollback(p); | 6426 sqlite3BtreeRollback(p); |
| 6421 return rc; | 6427 return rc; |
| 6422 } | 6428 } |
| 6423 | 6429 |
| 6424 #endif | 6430 #endif |
| 6431 | |
| 6432 int sqlite3_get_user_version(sqlite3 *sqlite, int *user_version) { | |
| 6433 Btree *bt; | |
| 6434 | |
| 6435 if( sqlite == NULL ) return SQLITE_ERROR; | |
| 6436 if( sqlite->nDb<1 ) return SQLITE_ERROR; | |
| 6437 | |
| 6438 /* grab actual (not temporary tables) database */ | |
|
Scott.Hess
2008/05/22 23:44:28
Comments should mostly be composed of sentences.
Dimitri
2008/06/04 03:02:16
On 2008/05/22 23:44:28, Scott.Hess wrote:
> Commen
| |
| 6439 bt = sqlite->aDb[0].pBt; | |
| 6440 /* because sqlite3BtreeGetMeta sets a table read lock, it is safe to use | |
| 6441 ** without explicit read transaction. Besides, it is very unlikely we will | |
| 6442 ** ever call this outside of a transaction. | |
| 6443 */ | |
| 6444 return sqlite3BtreeGetMeta(bt, kUserCookie, (u32 *)user_version); | |
| 6445 } | |
| 6446 | |
| 6447 int sqlite3_set_user_version(sqlite3 *sqlite, int user_version) { | |
| 6448 Btree *bt; | |
| 6449 int rc; | |
| 6450 | |
| 6451 if( sqlite == NULL ) return SQLITE_ERROR; | |
| 6452 if( sqlite->nDb<1 ) return SQLITE_ERROR; | |
| 6453 | |
| 6454 bt = sqlite->aDb[0].pBt; | |
| 6455 if( bt->inTrans!= TRANS_WRITE ) { | |
|
Scott.Hess
2008/05/22 23:44:28
Shouldn't this be ==? No space after = sign in an
Dimitri
2008/06/04 03:02:16
On 2008/05/22 23:44:28, Scott.Hess wrote:
> Should
| |
| 6456 return sqlite3BtreeUpdateMeta(bt, kUserCookie, (u32)user_version); | |
| 6457 }else{ | |
| 6458 /* transacion isn't already in progress, have to enclose in | |
| 6459 ** a write-transaction | |
| 6460 */ | |
|
Scott.Hess
2008/05/22 23:44:28
sp on first occurrence of transaction. Revise com
| |
| 6461 rc = sqlite3BtreeBeginTrans(bt, 1); | |
| 6462 if( rc!=SQLITE_OK ) return rc; | |
| 6463 rc = sqlite3BtreeUpdateMeta(bt, kUserCookie, (u32)user_version); | |
| 6464 if( rc==SQLITE_OK ) return sqlite3BtreeCommit(bt); | |
| 6465 sqlite3BtreeRollback(bt); | |
| 6466 return rc; | |
|
Scott.Hess
2008/05/22 23:44:28
For Database2, is it even possible to get to this
Dimitri
2008/06/04 03:02:16
On 2008/05/22 23:44:28, Scott.Hess wrote:
> For Da
| |
| 6467 } | |
| 6468 } | |
|
Scott.Hess
2008/05/22 23:44:28
Sorry to be a pain, I'm trying to recall why we're
Dimitri
2008/06/04 03:02:16
On 2008/05/22 23:44:28, Scott.Hess wrote:
> Sorry
| |
| OLD | NEW |