00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #include "sqliteInt.h"
00053 #include "pager.h"
00054 #include "btree.h"
00055 #include <assert.h>
00056
00057
00058 static BtOps sqliteBtreeOps;
00059 static BtCursorOps sqliteBtreeCursorOps;
00060
00061
00062
00063
00064
00065
00066
00067
00068 #define SWAB16(B,X) ((B)->needSwab? swab16((u16)X) : ((u16)X))
00069 #define SWAB32(B,X) ((B)->needSwab? swab32(X) : (X))
00070 #define SWAB_ADD(B,X,A) \
00071 if((B)->needSwab){ X=swab32(swab32(X)+A); }else{ X += (A); }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 #ifdef SQLITE_TEST
00082 int btree_native_byte_order = 1;
00083 #else
00084 # define btree_native_byte_order 1
00085 #endif
00086
00087
00088
00089
00090 typedef struct PageOne PageOne;
00091 typedef struct MemPage MemPage;
00092 typedef struct PageHdr PageHdr;
00093 typedef struct Cell Cell;
00094 typedef struct CellHdr CellHdr;
00095 typedef struct FreeBlk FreeBlk;
00096 typedef struct OverflowPage OverflowPage;
00097 typedef struct FreelistInfo FreelistInfo;
00098
00099
00100
00101
00102
00103
00104
00105
00106 #define ROUNDUP(X) ((X+3) & ~3)
00107
00108
00109
00110
00111
00112 static const char zMagicHeader[] =
00113 "** This file contains an SQLite 2.1 database **";
00114 #define MAGIC_SIZE (sizeof(zMagicHeader))
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 #define MAGIC 0xdae37528
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 struct PageOne {
00144 char zMagic[MAGIC_SIZE];
00145 int iMagic;
00146 Pgno freeList;
00147 int nFree;
00148 int aMeta[SQLITE_N_BTREE_META-1];
00149 };
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 struct PageHdr {
00170 Pgno rightChild;
00171 u16 firstCell;
00172 u16 firstFree;
00173 };
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 struct CellHdr {
00186 Pgno leftChild;
00187 u16 nKey;
00188 u16 iNext;
00189 u8 nKeyHi;
00190 u8 nDataHi;
00191 u16 nData;
00192 };
00193
00194
00195
00196
00197
00198
00199
00200 #define NKEY(b,h) (SWAB16(b,h.nKey) + h.nKeyHi*65536)
00201 #define NDATA(b,h) (SWAB16(b,h.nData) + h.nDataHi*65536)
00202
00203
00204
00205
00206
00207 #define MIN_CELL_SIZE (sizeof(CellHdr)+4)
00208
00209
00210
00211
00212
00213 #define MX_CELL ((SQLITE_USABLE_SIZE-sizeof(PageHdr))/MIN_CELL_SIZE)
00214
00215
00216
00217
00218
00219 #define USABLE_SPACE (SQLITE_USABLE_SIZE - sizeof(PageHdr))
00220
00221
00222
00223
00224
00225
00226
00227
00228 #define MX_LOCAL_PAYLOAD ((USABLE_SPACE/4-(sizeof(CellHdr)+sizeof(Pgno)))&~3)
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 struct Cell {
00245 CellHdr h;
00246 char aPayload[MX_LOCAL_PAYLOAD];
00247 Pgno ovfl;
00248 };
00249
00250
00251
00252
00253
00254
00255
00256 struct FreeBlk {
00257 u16 iSize;
00258 u16 iNext;
00259 };
00260
00261
00262
00263
00264 #define OVERFLOW_SIZE (SQLITE_USABLE_SIZE-sizeof(Pgno))
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 struct OverflowPage {
00278 Pgno iNext;
00279 char aPayload[OVERFLOW_SIZE];
00280 };
00281
00282
00283
00284
00285
00286
00287
00288
00289 struct FreelistInfo {
00290 int nFree;
00291 Pgno aFree[(OVERFLOW_SIZE-sizeof(int))/sizeof(Pgno)];
00292 };
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 struct MemPage {
00322 union u_page_data {
00323 char aDisk[SQLITE_PAGE_SIZE];
00324 PageHdr hdr;
00325 } u;
00326 u8 isInit;
00327 u8 idxShift;
00328 u8 isOverfull;
00329 MemPage *pParent;
00330 int idxParent;
00331 int nFree;
00332 int nCell;
00333 Cell *apCell[MX_CELL+2];
00334 };
00335
00336
00337
00338
00339
00340
00341 #define EXTRA_SIZE (sizeof(MemPage)-sizeof(union u_page_data))
00342
00343
00344
00345
00346 struct Btree {
00347 BtOps *pOps;
00348 Pager *pPager;
00349 BtCursor *pCursor;
00350 PageOne *page1;
00351 u8 inTrans;
00352 u8 inCkpt;
00353 u8 readOnly;
00354 u8 needSwab;
00355 };
00356 typedef Btree Bt;
00357
00358
00359
00360
00361
00362
00363 struct BtCursor {
00364 BtCursorOps *pOps;
00365 Btree *pBt;
00366 BtCursor *pNext, *pPrev;
00367 BtCursor *pShared;
00368 Pgno pgnoRoot;
00369 MemPage *pPage;
00370 int idx;
00371 u8 wrFlag;
00372 u8 eSkip;
00373 u8 iMatch;
00374 };
00375
00376
00377
00378
00379 #define SKIP_NONE 0
00380 #define SKIP_NEXT 1
00381 #define SKIP_PREV 2
00382 #define SKIP_INVALID 3
00383
00384
00385 static int fileBtreeCloseCursor(BtCursor *pCur);
00386
00387
00388
00389
00390 u16 swab16(u16 x){
00391 return ((x & 0xff)<<8) | ((x>>8)&0xff);
00392 }
00393 u32 swab32(u32 x){
00394 return ((x & 0xff)<<24) | ((x & 0xff00)<<8) |
00395 ((x>>8) & 0xff00) | ((x>>24)&0xff);
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405 static int cellSize(Btree *pBt, Cell *pCell){
00406 int n = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h);
00407 if( n>MX_LOCAL_PAYLOAD ){
00408 n = MX_LOCAL_PAYLOAD + sizeof(Pgno);
00409 }else{
00410 n = ROUNDUP(n);
00411 }
00412 n += sizeof(CellHdr);
00413 return n;
00414 }
00415
00416
00417
00418
00419
00420
00421 static void defragmentPage(Btree *pBt, MemPage *pPage){
00422 int pc, i, n;
00423 FreeBlk *pFBlk;
00424 char newPage[SQLITE_USABLE_SIZE];
00425
00426 assert( sqlitepager_iswriteable(pPage) );
00427 assert( pPage->isInit );
00428 pc = sizeof(PageHdr);
00429 pPage->u.hdr.firstCell = SWAB16(pBt, pc);
00430 memcpy(newPage, pPage->u.aDisk, pc);
00431 for(i=0; i<pPage->nCell; i++){
00432 Cell *pCell = pPage->apCell[i];
00433
00434
00435
00436 assert( Addr(pCell) > Addr(pPage) );
00437 assert( Addr(pCell) < Addr(pPage) + SQLITE_USABLE_SIZE );
00438
00439 n = cellSize(pBt, pCell);
00440 pCell->h.iNext = SWAB16(pBt, pc + n);
00441 memcpy(&newPage[pc], pCell, n);
00442 pPage->apCell[i] = (Cell*)&pPage->u.aDisk[pc];
00443 pc += n;
00444 }
00445 assert( pPage->nFree==SQLITE_USABLE_SIZE-pc );
00446 memcpy(pPage->u.aDisk, newPage, pc);
00447 if( pPage->nCell>0 ){
00448 pPage->apCell[pPage->nCell-1]->h.iNext = 0;
00449 }
00450 pFBlk = (FreeBlk*)&pPage->u.aDisk[pc];
00451 pFBlk->iSize = SWAB16(pBt, SQLITE_USABLE_SIZE - pc);
00452 pFBlk->iNext = 0;
00453 pPage->u.hdr.firstFree = SWAB16(pBt, pc);
00454 memset(&pFBlk[1], 0, SQLITE_USABLE_SIZE - pc - sizeof(FreeBlk));
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 static int allocateSpace(Btree *pBt, MemPage *pPage, int nByte){
00471 FreeBlk *p;
00472 u16 *pIdx;
00473 int start;
00474 int iSize;
00475 #ifndef NDEBUG
00476 int cnt = 0;
00477 #endif
00478
00479 assert( sqlitepager_iswriteable(pPage) );
00480 assert( nByte==ROUNDUP(nByte) );
00481 assert( pPage->isInit );
00482 if( pPage->nFree<nByte || pPage->isOverfull ) return 0;
00483 pIdx = &pPage->u.hdr.firstFree;
00484 p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)];
00485 while( (iSize = SWAB16(pBt, p->iSize))<nByte ){
00486 assert( cnt++ < SQLITE_USABLE_SIZE/4 );
00487 if( p->iNext==0 ){
00488 defragmentPage(pBt, pPage);
00489 pIdx = &pPage->u.hdr.firstFree;
00490 }else{
00491 pIdx = &p->iNext;
00492 }
00493 p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)];
00494 }
00495 if( iSize==nByte ){
00496 start = SWAB16(pBt, *pIdx);
00497 *pIdx = p->iNext;
00498 }else{
00499 FreeBlk *pNew;
00500 start = SWAB16(pBt, *pIdx);
00501 pNew = (FreeBlk*)&pPage->u.aDisk[start + nByte];
00502 pNew->iNext = p->iNext;
00503 pNew->iSize = SWAB16(pBt, iSize - nByte);
00504 *pIdx = SWAB16(pBt, start + nByte);
00505 }
00506 pPage->nFree -= nByte;
00507 return start;
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519 static void freeSpace(Btree *pBt, MemPage *pPage, int start, int size){
00520 int end = start + size;
00521 u16 *pIdx, idx;
00522 FreeBlk *pFBlk;
00523 FreeBlk *pNew;
00524 FreeBlk *pNext;
00525 int iSize;
00526
00527 assert( sqlitepager_iswriteable(pPage) );
00528 assert( size == ROUNDUP(size) );
00529 assert( start == ROUNDUP(start) );
00530 assert( pPage->isInit );
00531 pIdx = &pPage->u.hdr.firstFree;
00532 idx = SWAB16(pBt, *pIdx);
00533 while( idx!=0 && idx<start ){
00534 pFBlk = (FreeBlk*)&pPage->u.aDisk[idx];
00535 iSize = SWAB16(pBt, pFBlk->iSize);
00536 if( idx + iSize == start ){
00537 pFBlk->iSize = SWAB16(pBt, iSize + size);
00538 if( idx + iSize + size == SWAB16(pBt, pFBlk->iNext) ){
00539 pNext = (FreeBlk*)&pPage->u.aDisk[idx + iSize + size];
00540 if( pBt->needSwab ){
00541 pFBlk->iSize = swab16((u16)swab16(pNext->iSize)+iSize+size);
00542 }else{
00543 pFBlk->iSize += pNext->iSize;
00544 }
00545 pFBlk->iNext = pNext->iNext;
00546 }
00547 pPage->nFree += size;
00548 return;
00549 }
00550 pIdx = &pFBlk->iNext;
00551 idx = SWAB16(pBt, *pIdx);
00552 }
00553 pNew = (FreeBlk*)&pPage->u.aDisk[start];
00554 if( idx != end ){
00555 pNew->iSize = SWAB16(pBt, size);
00556 pNew->iNext = SWAB16(pBt, idx);
00557 }else{
00558 pNext = (FreeBlk*)&pPage->u.aDisk[idx];
00559 pNew->iSize = SWAB16(pBt, size + SWAB16(pBt, pNext->iSize));
00560 pNew->iNext = pNext->iNext;
00561 }
00562 *pIdx = SWAB16(pBt, start);
00563 pPage->nFree += size;
00564 }
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 static int initPage(Bt *pBt, MemPage *pPage, Pgno pgnoThis, MemPage *pParent){
00581 int idx;
00582 Cell *pCell;
00583 FreeBlk *pFBlk;
00584 int sz;
00585 int freeSpace;
00586
00587 if( pPage->pParent ){
00588 assert( pPage->pParent==pParent );
00589 return SQLITE_OK;
00590 }
00591 if( pParent ){
00592 pPage->pParent = pParent;
00593 sqlitepager_ref(pParent);
00594 }
00595 if( pPage->isInit ) return SQLITE_OK;
00596 pPage->isInit = 1;
00597 pPage->nCell = 0;
00598 freeSpace = USABLE_SPACE;
00599 idx = SWAB16(pBt, pPage->u.hdr.firstCell);
00600 while( idx!=0 ){
00601 if( idx>SQLITE_USABLE_SIZE-MIN_CELL_SIZE ) goto page_format_error;
00602 if( idx<sizeof(PageHdr) ) goto page_format_error;
00603 if( idx!=ROUNDUP(idx) ) goto page_format_error;
00604 pCell = (Cell*)&pPage->u.aDisk[idx];
00605 sz = cellSize(pBt, pCell);
00606 if( idx+sz > SQLITE_USABLE_SIZE ) goto page_format_error;
00607 freeSpace -= sz;
00608 pPage->apCell[pPage->nCell++] = pCell;
00609 idx = SWAB16(pBt, pCell->h.iNext);
00610 }
00611 pPage->nFree = 0;
00612 idx = SWAB16(pBt, pPage->u.hdr.firstFree);
00613 while( idx!=0 ){
00614 int iNext;
00615 if( idx>SQLITE_USABLE_SIZE-sizeof(FreeBlk) ) goto page_format_error;
00616 if( idx<sizeof(PageHdr) ) goto page_format_error;
00617 pFBlk = (FreeBlk*)&pPage->u.aDisk[idx];
00618 pPage->nFree += SWAB16(pBt, pFBlk->iSize);
00619 iNext = SWAB16(pBt, pFBlk->iNext);
00620 if( iNext>0 && iNext <= idx ) goto page_format_error;
00621 idx = iNext;
00622 }
00623 if( pPage->nCell==0 && pPage->nFree==0 ){
00624
00625
00626 return SQLITE_OK;
00627 }
00628 if( pPage->nFree!=freeSpace ) goto page_format_error;
00629 return SQLITE_OK;
00630
00631 page_format_error:
00632 return SQLITE_CORRUPT;
00633 }
00634
00635
00636
00637
00638
00639 static void zeroPage(Btree *pBt, MemPage *pPage){
00640 PageHdr *pHdr;
00641 FreeBlk *pFBlk;
00642 assert( sqlitepager_iswriteable(pPage) );
00643 memset(pPage, 0, SQLITE_USABLE_SIZE);
00644 pHdr = &pPage->u.hdr;
00645 pHdr->firstCell = 0;
00646 pHdr->firstFree = SWAB16(pBt, sizeof(*pHdr));
00647 pFBlk = (FreeBlk*)&pHdr[1];
00648 pFBlk->iNext = 0;
00649 pPage->nFree = SQLITE_USABLE_SIZE - sizeof(*pHdr);
00650 pFBlk->iSize = SWAB16(pBt, pPage->nFree);
00651 pPage->nCell = 0;
00652 pPage->isOverfull = 0;
00653 }
00654
00655
00656
00657
00658
00659
00660 static void pageDestructor(void *pData){
00661 MemPage *pPage = (MemPage*)pData;
00662 if( pPage->pParent ){
00663 MemPage *pParent = pPage->pParent;
00664 pPage->pParent = 0;
00665 sqlitepager_unref(pParent);
00666 }
00667 }
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 int sqliteBtreeOpen(
00681 const char *zFilename,
00682 int omitJournal,
00683 int nCache,
00684 Btree **ppBtree
00685 ){
00686 Btree *pBt;
00687 int rc;
00688
00689
00690
00691
00692
00693
00694 assert( sizeof(u32)==4 );
00695 assert( sizeof(u16)==2 );
00696 assert( sizeof(Pgno)==4 );
00697 assert( sizeof(PageHdr)==8 );
00698 assert( sizeof(CellHdr)==12 );
00699 assert( sizeof(FreeBlk)==4 );
00700 assert( sizeof(OverflowPage)==SQLITE_USABLE_SIZE );
00701 assert( sizeof(FreelistInfo)==OVERFLOW_SIZE );
00702 assert( sizeof(ptr)==sizeof(char*) );
00703 assert( sizeof(uptr)==sizeof(ptr) );
00704
00705 pBt = sqliteMalloc( sizeof(*pBt) );
00706 if( pBt==0 ){
00707 *ppBtree = 0;
00708 return SQLITE_NOMEM;
00709 }
00710 if( nCache<10 ) nCache = 10;
00711 rc = sqlitepager_open(&pBt->pPager, zFilename, nCache, EXTRA_SIZE,
00712 !omitJournal);
00713 if( rc!=SQLITE_OK ){
00714 if( pBt->pPager ) sqlitepager_close(pBt->pPager);
00715 sqliteFree(pBt);
00716 *ppBtree = 0;
00717 return rc;
00718 }
00719 sqlitepager_set_destructor(pBt->pPager, pageDestructor);
00720 pBt->pCursor = 0;
00721 pBt->page1 = 0;
00722 pBt->readOnly = sqlitepager_isreadonly(pBt->pPager);
00723 pBt->pOps = &sqliteBtreeOps;
00724 *ppBtree = pBt;
00725 return SQLITE_OK;
00726 }
00727
00728
00729
00730
00731 static int fileBtreeClose(Btree *pBt){
00732 while( pBt->pCursor ){
00733 fileBtreeCloseCursor(pBt->pCursor);
00734 }
00735 sqlitepager_close(pBt->pPager);
00736 sqliteFree(pBt);
00737 return SQLITE_OK;
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 static int fileBtreeSetCacheSize(Btree *pBt, int mxPage){
00756 sqlitepager_set_cachesize(pBt->pPager, mxPage);
00757 return SQLITE_OK;
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768 static int fileBtreeSetSafetyLevel(Btree *pBt, int level){
00769 sqlitepager_set_safety_level(pBt->pPager, level);
00770 return SQLITE_OK;
00771 }
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783 static int lockBtree(Btree *pBt){
00784 int rc;
00785 if( pBt->page1 ) return SQLITE_OK;
00786 rc = sqlitepager_get(pBt->pPager, 1, (void**)&pBt->page1);
00787 if( rc!=SQLITE_OK ) return rc;
00788
00789
00790
00791
00792 if( sqlitepager_pagecount(pBt->pPager)>0 ){
00793 PageOne *pP1 = pBt->page1;
00794 if( strcmp(pP1->zMagic,zMagicHeader)!=0 ||
00795 (pP1->iMagic!=MAGIC && swab32(pP1->iMagic)!=MAGIC) ){
00796 rc = SQLITE_NOTADB;
00797 goto page1_init_failed;
00798 }
00799 pBt->needSwab = pP1->iMagic!=MAGIC;
00800 }
00801 return rc;
00802
00803 page1_init_failed:
00804 sqlitepager_unref(pBt->page1);
00805 pBt->page1 = 0;
00806 return rc;
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 static void unlockBtreeIfUnused(Btree *pBt){
00820 if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
00821 sqlitepager_unref(pBt->page1);
00822 pBt->page1 = 0;
00823 pBt->inTrans = 0;
00824 pBt->inCkpt = 0;
00825 }
00826 }
00827
00828
00829
00830
00831
00832 static int newDatabase(Btree *pBt){
00833 MemPage *pRoot;
00834 PageOne *pP1;
00835 int rc;
00836 if( sqlitepager_pagecount(pBt->pPager)>1 ) return SQLITE_OK;
00837 pP1 = pBt->page1;
00838 rc = sqlitepager_write(pBt->page1);
00839 if( rc ) return rc;
00840 rc = sqlitepager_get(pBt->pPager, 2, (void**)&pRoot);
00841 if( rc ) return rc;
00842 rc = sqlitepager_write(pRoot);
00843 if( rc ){
00844 sqlitepager_unref(pRoot);
00845 return rc;
00846 }
00847 strcpy(pP1->zMagic, zMagicHeader);
00848 if( btree_native_byte_order ){
00849 pP1->iMagic = MAGIC;
00850 pBt->needSwab = 0;
00851 }else{
00852 pP1->iMagic = swab32(MAGIC);
00853 pBt->needSwab = 1;
00854 }
00855 zeroPage(pBt, pRoot);
00856 sqlitepager_unref(pRoot);
00857 return SQLITE_OK;
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 static int fileBtreeBeginTrans(Btree *pBt){
00876 int rc;
00877 if( pBt->inTrans ) return SQLITE_ERROR;
00878 if( pBt->readOnly ) return SQLITE_READONLY;
00879 if( pBt->page1==0 ){
00880 rc = lockBtree(pBt);
00881 if( rc!=SQLITE_OK ){
00882 return rc;
00883 }
00884 }
00885 rc = sqlitepager_begin(pBt->page1);
00886 if( rc==SQLITE_OK ){
00887 rc = newDatabase(pBt);
00888 }
00889 if( rc==SQLITE_OK ){
00890 pBt->inTrans = 1;
00891 pBt->inCkpt = 0;
00892 }else{
00893 unlockBtreeIfUnused(pBt);
00894 }
00895 return rc;
00896 }
00897
00898
00899
00900
00901
00902
00903
00904 static int fileBtreeCommit(Btree *pBt){
00905 int rc;
00906 rc = pBt->readOnly ? SQLITE_OK : sqlitepager_commit(pBt->pPager);
00907 pBt->inTrans = 0;
00908 pBt->inCkpt = 0;
00909 unlockBtreeIfUnused(pBt);
00910 return rc;
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922 static int fileBtreeRollback(Btree *pBt){
00923 int rc;
00924 BtCursor *pCur;
00925 if( pBt->inTrans==0 ) return SQLITE_OK;
00926 pBt->inTrans = 0;
00927 pBt->inCkpt = 0;
00928 rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager);
00929 for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
00930 if( pCur->pPage && pCur->pPage->isInit==0 ){
00931 sqlitepager_unref(pCur->pPage);
00932 pCur->pPage = 0;
00933 }
00934 }
00935 unlockBtreeIfUnused(pBt);
00936 return rc;
00937 }
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949 static int fileBtreeBeginCkpt(Btree *pBt){
00950 int rc;
00951 if( !pBt->inTrans || pBt->inCkpt ){
00952 return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
00953 }
00954 rc = pBt->readOnly ? SQLITE_OK : sqlitepager_ckpt_begin(pBt->pPager);
00955 pBt->inCkpt = 1;
00956 return rc;
00957 }
00958
00959
00960
00961
00962
00963
00964 static int fileBtreeCommitCkpt(Btree *pBt){
00965 int rc;
00966 if( pBt->inCkpt && !pBt->readOnly ){
00967 rc = sqlitepager_ckpt_commit(pBt->pPager);
00968 }else{
00969 rc = SQLITE_OK;
00970 }
00971 pBt->inCkpt = 0;
00972 return rc;
00973 }
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 static int fileBtreeRollbackCkpt(Btree *pBt){
00984 int rc;
00985 BtCursor *pCur;
00986 if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK;
00987 rc = sqlitepager_ckpt_rollback(pBt->pPager);
00988 for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
00989 if( pCur->pPage && pCur->pPage->isInit==0 ){
00990 sqlitepager_unref(pCur->pPage);
00991 pCur->pPage = 0;
00992 }
00993 }
00994 pBt->inCkpt = 0;
00995 return rc;
00996 }
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034 static
01035 int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){
01036 int rc;
01037 BtCursor *pCur, *pRing;
01038
01039 if( pBt->readOnly && wrFlag ){
01040 *ppCur = 0;
01041 return SQLITE_READONLY;
01042 }
01043 if( pBt->page1==0 ){
01044 rc = lockBtree(pBt);
01045 if( rc!=SQLITE_OK ){
01046 *ppCur = 0;
01047 return rc;
01048 }
01049 }
01050 pCur = sqliteMalloc( sizeof(*pCur) );
01051 if( pCur==0 ){
01052 rc = SQLITE_NOMEM;
01053 goto create_cursor_exception;
01054 }
01055 pCur->pgnoRoot = (Pgno)iTable;
01056 rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pCur->pPage);
01057 if( rc!=SQLITE_OK ){
01058 goto create_cursor_exception;
01059 }
01060 rc = initPage(pBt, pCur->pPage, pCur->pgnoRoot, 0);
01061 if( rc!=SQLITE_OK ){
01062 goto create_cursor_exception;
01063 }
01064 pCur->pOps = &sqliteBtreeCursorOps;
01065 pCur->pBt = pBt;
01066 pCur->wrFlag = wrFlag;
01067 pCur->idx = 0;
01068 pCur->eSkip = SKIP_INVALID;
01069 pCur->pNext = pBt->pCursor;
01070 if( pCur->pNext ){
01071 pCur->pNext->pPrev = pCur;
01072 }
01073 pCur->pPrev = 0;
01074 pRing = pBt->pCursor;
01075 while( pRing && pRing->pgnoRoot!=pCur->pgnoRoot ){ pRing = pRing->pNext; }
01076 if( pRing ){
01077 pCur->pShared = pRing->pShared;
01078 pRing->pShared = pCur;
01079 }else{
01080 pCur->pShared = pCur;
01081 }
01082 pBt->pCursor = pCur;
01083 *ppCur = pCur;
01084 return SQLITE_OK;
01085
01086 create_cursor_exception:
01087 *ppCur = 0;
01088 if( pCur ){
01089 if( pCur->pPage ) sqlitepager_unref(pCur->pPage);
01090 sqliteFree(pCur);
01091 }
01092 unlockBtreeIfUnused(pBt);
01093 return rc;
01094 }
01095
01096
01097
01098
01099
01100 static int fileBtreeCloseCursor(BtCursor *pCur){
01101 Btree *pBt = pCur->pBt;
01102 if( pCur->pPrev ){
01103 pCur->pPrev->pNext = pCur->pNext;
01104 }else{
01105 pBt->pCursor = pCur->pNext;
01106 }
01107 if( pCur->pNext ){
01108 pCur->pNext->pPrev = pCur->pPrev;
01109 }
01110 if( pCur->pPage ){
01111 sqlitepager_unref(pCur->pPage);
01112 }
01113 if( pCur->pShared!=pCur ){
01114 BtCursor *pRing = pCur->pShared;
01115 while( pRing->pShared!=pCur ){ pRing = pRing->pShared; }
01116 pRing->pShared = pCur->pShared;
01117 }
01118 unlockBtreeIfUnused(pBt);
01119 sqliteFree(pCur);
01120 return SQLITE_OK;
01121 }
01122
01123
01124
01125
01126
01127 static void getTempCursor(BtCursor *pCur, BtCursor *pTempCur){
01128 memcpy(pTempCur, pCur, sizeof(*pCur));
01129 pTempCur->pNext = 0;
01130 pTempCur->pPrev = 0;
01131 if( pTempCur->pPage ){
01132 sqlitepager_ref(pTempCur->pPage);
01133 }
01134 }
01135
01136
01137
01138
01139
01140 static void releaseTempCursor(BtCursor *pCur){
01141 if( pCur->pPage ){
01142 sqlitepager_unref(pCur->pPage);
01143 }
01144 }
01145
01146
01147
01148
01149
01150
01151
01152
01153 static int fileBtreeKeySize(BtCursor *pCur, int *pSize){
01154 Cell *pCell;
01155 MemPage *pPage;
01156
01157 pPage = pCur->pPage;
01158 assert( pPage!=0 );
01159 if( pCur->idx >= pPage->nCell ){
01160 *pSize = 0;
01161 }else{
01162 pCell = pPage->apCell[pCur->idx];
01163 *pSize = NKEY(pCur->pBt, pCell->h);
01164 }
01165 return SQLITE_OK;
01166 }
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
01177 char *aPayload;
01178 Pgno nextPage;
01179 int rc;
01180 Btree *pBt = pCur->pBt;
01181 assert( pCur!=0 && pCur->pPage!=0 );
01182 assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
01183 aPayload = pCur->pPage->apCell[pCur->idx]->aPayload;
01184 if( offset<MX_LOCAL_PAYLOAD ){
01185 int a = amt;
01186 if( a+offset>MX_LOCAL_PAYLOAD ){
01187 a = MX_LOCAL_PAYLOAD - offset;
01188 }
01189 memcpy(zBuf, &aPayload[offset], a);
01190 if( a==amt ){
01191 return SQLITE_OK;
01192 }
01193 offset = 0;
01194 zBuf += a;
01195 amt -= a;
01196 }else{
01197 offset -= MX_LOCAL_PAYLOAD;
01198 }
01199 if( amt>0 ){
01200 nextPage = SWAB32(pBt, pCur->pPage->apCell[pCur->idx]->ovfl);
01201 }
01202 while( amt>0 && nextPage ){
01203 OverflowPage *pOvfl;
01204 rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
01205 if( rc!=0 ){
01206 return rc;
01207 }
01208 nextPage = SWAB32(pBt, pOvfl->iNext);
01209 if( offset<OVERFLOW_SIZE ){
01210 int a = amt;
01211 if( a + offset > OVERFLOW_SIZE ){
01212 a = OVERFLOW_SIZE - offset;
01213 }
01214 memcpy(zBuf, &pOvfl->aPayload[offset], a);
01215 offset = 0;
01216 amt -= a;
01217 zBuf += a;
01218 }else{
01219 offset -= OVERFLOW_SIZE;
01220 }
01221 sqlitepager_unref(pOvfl);
01222 }
01223 if( amt>0 ){
01224 return SQLITE_CORRUPT;
01225 }
01226 return SQLITE_OK;
01227 }
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242 static int fileBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){
01243 MemPage *pPage;
01244
01245 assert( amt>=0 );
01246 assert( offset>=0 );
01247 assert( pCur->pPage!=0 );
01248 pPage = pCur->pPage;
01249 if( pCur->idx >= pPage->nCell ){
01250 return 0;
01251 }
01252 assert( amt+offset <= NKEY(pCur->pBt, pPage->apCell[pCur->idx]->h) );
01253 getPayload(pCur, offset, amt, zBuf);
01254 return amt;
01255 }
01256
01257
01258
01259
01260
01261
01262
01263
01264 static int fileBtreeDataSize(BtCursor *pCur, int *pSize){
01265 Cell *pCell;
01266 MemPage *pPage;
01267
01268 pPage = pCur->pPage;
01269 assert( pPage!=0 );
01270 if( pCur->idx >= pPage->nCell ){
01271 *pSize = 0;
01272 }else{
01273 pCell = pPage->apCell[pCur->idx];
01274 *pSize = NDATA(pCur->pBt, pCell->h);
01275 }
01276 return SQLITE_OK;
01277 }
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287 static int fileBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
01288 Cell *pCell;
01289 MemPage *pPage;
01290
01291 assert( amt>=0 );
01292 assert( offset>=0 );
01293 assert( pCur->pPage!=0 );
01294 pPage = pCur->pPage;
01295 if( pCur->idx >= pPage->nCell ){
01296 return 0;
01297 }
01298 pCell = pPage->apCell[pCur->idx];
01299 assert( amt+offset <= NDATA(pCur->pBt, pCell->h) );
01300 getPayload(pCur, offset + NKEY(pCur->pBt, pCell->h), amt, zBuf);
01301 return amt;
01302 }
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325 static int fileBtreeKeyCompare(
01326 BtCursor *pCur,
01327 const void *pKey,
01328 int nKey,
01329 int nIgnore,
01330 int *pResult
01331 ){
01332 Pgno nextPage;
01333 int n, c, rc, nLocal;
01334 Cell *pCell;
01335 Btree *pBt = pCur->pBt;
01336 const char *zKey = (const char*)pKey;
01337
01338 assert( pCur->pPage );
01339 assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
01340 pCell = pCur->pPage->apCell[pCur->idx];
01341 nLocal = NKEY(pBt, pCell->h) - nIgnore;
01342 if( nLocal<0 ) nLocal = 0;
01343 n = nKey<nLocal ? nKey : nLocal;
01344 if( n>MX_LOCAL_PAYLOAD ){
01345 n = MX_LOCAL_PAYLOAD;
01346 }
01347 c = memcmp(pCell->aPayload, zKey, n);
01348 if( c!=0 ){
01349 *pResult = c;
01350 return SQLITE_OK;
01351 }
01352 zKey += n;
01353 nKey -= n;
01354 nLocal -= n;
01355 nextPage = SWAB32(pBt, pCell->ovfl);
01356 while( nKey>0 && nLocal>0 ){
01357 OverflowPage *pOvfl;
01358 if( nextPage==0 ){
01359 return SQLITE_CORRUPT;
01360 }
01361 rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
01362 if( rc ){
01363 return rc;
01364 }
01365 nextPage = SWAB32(pBt, pOvfl->iNext);
01366 n = nKey<nLocal ? nKey : nLocal;
01367 if( n>OVERFLOW_SIZE ){
01368 n = OVERFLOW_SIZE;
01369 }
01370 c = memcmp(pOvfl->aPayload, zKey, n);
01371 sqlitepager_unref(pOvfl);
01372 if( c!=0 ){
01373 *pResult = c;
01374 return SQLITE_OK;
01375 }
01376 nKey -= n;
01377 nLocal -= n;
01378 zKey += n;
01379 }
01380 if( c==0 ){
01381 c = nLocal - nKey;
01382 }
01383 *pResult = c;
01384 return SQLITE_OK;
01385 }
01386
01387
01388
01389
01390
01391 static int moveToChild(BtCursor *pCur, int newPgno){
01392 int rc;
01393 MemPage *pNewPage;
01394 Btree *pBt = pCur->pBt;
01395
01396 newPgno = SWAB32(pBt, newPgno);
01397 rc = sqlitepager_get(pBt->pPager, newPgno, (void**)&pNewPage);
01398 if( rc ) return rc;
01399 rc = initPage(pBt, pNewPage, newPgno, pCur->pPage);
01400 if( rc ) return rc;
01401 assert( pCur->idx>=pCur->pPage->nCell
01402 || pCur->pPage->apCell[pCur->idx]->h.leftChild==SWAB32(pBt,newPgno) );
01403 assert( pCur->idx<pCur->pPage->nCell
01404 || pCur->pPage->u.hdr.rightChild==SWAB32(pBt,newPgno) );
01405 pNewPage->idxParent = pCur->idx;
01406 pCur->pPage->idxShift = 0;
01407 sqlitepager_unref(pCur->pPage);
01408 pCur->pPage = pNewPage;
01409 pCur->idx = 0;
01410 if( pNewPage->nCell<1 ){
01411 return SQLITE_CORRUPT;
01412 }
01413 return SQLITE_OK;
01414 }
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424 static void moveToParent(BtCursor *pCur){
01425 Pgno oldPgno;
01426 MemPage *pParent;
01427 MemPage *pPage;
01428 int idxParent;
01429 pPage = pCur->pPage;
01430 assert( pPage!=0 );
01431 pParent = pPage->pParent;
01432 assert( pParent!=0 );
01433 idxParent = pPage->idxParent;
01434 sqlitepager_ref(pParent);
01435 sqlitepager_unref(pPage);
01436 pCur->pPage = pParent;
01437 assert( pParent->idxShift==0 );
01438 if( pParent->idxShift==0 ){
01439 pCur->idx = idxParent;
01440 #ifndef NDEBUG
01441
01442
01443
01444 oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
01445 if( pCur->idx<pParent->nCell ){
01446 assert( pParent->apCell[idxParent]->h.leftChild==oldPgno );
01447 }else{
01448 assert( pParent->u.hdr.rightChild==oldPgno );
01449 }
01450 #endif
01451 }else{
01452
01453
01454
01455
01456
01457 int i;
01458 pCur->idx = pParent->nCell;
01459 oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
01460 for(i=0; i<pParent->nCell; i++){
01461 if( pParent->apCell[i]->h.leftChild==oldPgno ){
01462 pCur->idx = i;
01463 break;
01464 }
01465 }
01466 }
01467 }
01468
01469
01470
01471
01472 static int moveToRoot(BtCursor *pCur){
01473 MemPage *pNew;
01474 int rc;
01475 Btree *pBt = pCur->pBt;
01476
01477 rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pNew);
01478 if( rc ) return rc;
01479 rc = initPage(pBt, pNew, pCur->pgnoRoot, 0);
01480 if( rc ) return rc;
01481 sqlitepager_unref(pCur->pPage);
01482 pCur->pPage = pNew;
01483 pCur->idx = 0;
01484 return SQLITE_OK;
01485 }
01486
01487
01488
01489
01490
01491 static int moveToLeftmost(BtCursor *pCur){
01492 Pgno pgno;
01493 int rc;
01494
01495 while( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
01496 rc = moveToChild(pCur, pgno);
01497 if( rc ) return rc;
01498 }
01499 return SQLITE_OK;
01500 }
01501
01502
01503
01504
01505
01506
01507
01508
01509 static int moveToRightmost(BtCursor *pCur){
01510 Pgno pgno;
01511 int rc;
01512
01513 while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){
01514 pCur->idx = pCur->pPage->nCell;
01515 rc = moveToChild(pCur, pgno);
01516 if( rc ) return rc;
01517 }
01518 pCur->idx = pCur->pPage->nCell - 1;
01519 return SQLITE_OK;
01520 }
01521
01522
01523
01524
01525
01526 static int fileBtreeFirst(BtCursor *pCur, int *pRes){
01527 int rc;
01528 if( pCur->pPage==0 ) return SQLITE_ABORT;
01529 rc = moveToRoot(pCur);
01530 if( rc ) return rc;
01531 if( pCur->pPage->nCell==0 ){
01532 *pRes = 1;
01533 return SQLITE_OK;
01534 }
01535 *pRes = 0;
01536 rc = moveToLeftmost(pCur);
01537 pCur->eSkip = SKIP_NONE;
01538 return rc;
01539 }
01540
01541
01542
01543
01544
01545 static int fileBtreeLast(BtCursor *pCur, int *pRes){
01546 int rc;
01547 if( pCur->pPage==0 ) return SQLITE_ABORT;
01548 rc = moveToRoot(pCur);
01549 if( rc ) return rc;
01550 assert( pCur->pPage->isInit );
01551 if( pCur->pPage->nCell==0 ){
01552 *pRes = 1;
01553 return SQLITE_OK;
01554 }
01555 *pRes = 0;
01556 rc = moveToRightmost(pCur);
01557 pCur->eSkip = SKIP_NONE;
01558 return rc;
01559 }
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584 static
01585 int fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
01586 int rc;
01587 if( pCur->pPage==0 ) return SQLITE_ABORT;
01588 pCur->eSkip = SKIP_NONE;
01589 rc = moveToRoot(pCur);
01590 if( rc ) return rc;
01591 for(;;){
01592 int lwr, upr;
01593 Pgno chldPg;
01594 MemPage *pPage = pCur->pPage;
01595 int c = -1;
01596 lwr = 0;
01597 upr = pPage->nCell-1;
01598 while( lwr<=upr ){
01599 pCur->idx = (lwr+upr)/2;
01600 rc = fileBtreeKeyCompare(pCur, pKey, nKey, 0, &c);
01601 if( rc ) return rc;
01602 if( c==0 ){
01603 pCur->iMatch = c;
01604 if( pRes ) *pRes = 0;
01605 return SQLITE_OK;
01606 }
01607 if( c<0 ){
01608 lwr = pCur->idx+1;
01609 }else{
01610 upr = pCur->idx-1;
01611 }
01612 }
01613 assert( lwr==upr+1 );
01614 assert( pPage->isInit );
01615 if( lwr>=pPage->nCell ){
01616 chldPg = pPage->u.hdr.rightChild;
01617 }else{
01618 chldPg = pPage->apCell[lwr]->h.leftChild;
01619 }
01620 if( chldPg==0 ){
01621 pCur->iMatch = c;
01622 if( pRes ) *pRes = c;
01623 return SQLITE_OK;
01624 }
01625 pCur->idx = lwr;
01626 rc = moveToChild(pCur, chldPg);
01627 if( rc ) return rc;
01628 }
01629
01630 }
01631
01632
01633
01634
01635
01636
01637
01638 static int fileBtreeNext(BtCursor *pCur, int *pRes){
01639 int rc;
01640 MemPage *pPage = pCur->pPage;
01641 assert( pRes!=0 );
01642 if( pPage==0 ){
01643 *pRes = 1;
01644 return SQLITE_ABORT;
01645 }
01646 assert( pPage->isInit );
01647 assert( pCur->eSkip!=SKIP_INVALID );
01648 if( pPage->nCell==0 ){
01649 *pRes = 1;
01650 return SQLITE_OK;
01651 }
01652 assert( pCur->idx<pPage->nCell );
01653 if( pCur->eSkip==SKIP_NEXT ){
01654 pCur->eSkip = SKIP_NONE;
01655 *pRes = 0;
01656 return SQLITE_OK;
01657 }
01658 pCur->eSkip = SKIP_NONE;
01659 pCur->idx++;
01660 if( pCur->idx>=pPage->nCell ){
01661 if( pPage->u.hdr.rightChild ){
01662 rc = moveToChild(pCur, pPage->u.hdr.rightChild);
01663 if( rc ) return rc;
01664 rc = moveToLeftmost(pCur);
01665 *pRes = 0;
01666 return rc;
01667 }
01668 do{
01669 if( pPage->pParent==0 ){
01670 *pRes = 1;
01671 return SQLITE_OK;
01672 }
01673 moveToParent(pCur);
01674 pPage = pCur->pPage;
01675 }while( pCur->idx>=pPage->nCell );
01676 *pRes = 0;
01677 return SQLITE_OK;
01678 }
01679 *pRes = 0;
01680 if( pPage->u.hdr.rightChild==0 ){
01681 return SQLITE_OK;
01682 }
01683 rc = moveToLeftmost(pCur);
01684 return rc;
01685 }
01686
01687
01688
01689
01690
01691
01692
01693 static int fileBtreePrevious(BtCursor *pCur, int *pRes){
01694 int rc;
01695 Pgno pgno;
01696 MemPage *pPage;
01697 pPage = pCur->pPage;
01698 if( pPage==0 ){
01699 *pRes = 1;
01700 return SQLITE_ABORT;
01701 }
01702 assert( pPage->isInit );
01703 assert( pCur->eSkip!=SKIP_INVALID );
01704 if( pPage->nCell==0 ){
01705 *pRes = 1;
01706 return SQLITE_OK;
01707 }
01708 if( pCur->eSkip==SKIP_PREV ){
01709 pCur->eSkip = SKIP_NONE;
01710 *pRes = 0;
01711 return SQLITE_OK;
01712 }
01713 pCur->eSkip = SKIP_NONE;
01714 assert( pCur->idx>=0 );
01715 if( (pgno = pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
01716 rc = moveToChild(pCur, pgno);
01717 if( rc ) return rc;
01718 rc = moveToRightmost(pCur);
01719 }else{
01720 while( pCur->idx==0 ){
01721 if( pPage->pParent==0 ){
01722 if( pRes ) *pRes = 1;
01723 return SQLITE_OK;
01724 }
01725 moveToParent(pCur);
01726 pPage = pCur->pPage;
01727 }
01728 pCur->idx--;
01729 rc = SQLITE_OK;
01730 }
01731 *pRes = 0;
01732 return rc;
01733 }
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752 static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){
01753 PageOne *pPage1 = pBt->page1;
01754 int rc;
01755 if( pPage1->freeList ){
01756 OverflowPage *pOvfl;
01757 FreelistInfo *pInfo;
01758
01759 rc = sqlitepager_write(pPage1);
01760 if( rc ) return rc;
01761 SWAB_ADD(pBt, pPage1->nFree, -1);
01762 rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
01763 (void**)&pOvfl);
01764 if( rc ) return rc;
01765 rc = sqlitepager_write(pOvfl);
01766 if( rc ){
01767 sqlitepager_unref(pOvfl);
01768 return rc;
01769 }
01770 pInfo = (FreelistInfo*)pOvfl->aPayload;
01771 if( pInfo->nFree==0 ){
01772 *pPgno = SWAB32(pBt, pPage1->freeList);
01773 pPage1->freeList = pOvfl->iNext;
01774 *ppPage = (MemPage*)pOvfl;
01775 }else{
01776 int closest, n;
01777 n = SWAB32(pBt, pInfo->nFree);
01778 if( n>1 && nearby>0 ){
01779 int i, dist;
01780 closest = 0;
01781 dist = SWAB32(pBt, pInfo->aFree[0]) - nearby;
01782 if( dist<0 ) dist = -dist;
01783 for(i=1; i<n; i++){
01784 int d2 = SWAB32(pBt, pInfo->aFree[i]) - nearby;
01785 if( d2<0 ) d2 = -d2;
01786 if( d2<dist ) closest = i;
01787 }
01788 }else{
01789 closest = 0;
01790 }
01791 SWAB_ADD(pBt, pInfo->nFree, -1);
01792 *pPgno = SWAB32(pBt, pInfo->aFree[closest]);
01793 pInfo->aFree[closest] = pInfo->aFree[n-1];
01794 rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
01795 sqlitepager_unref(pOvfl);
01796 if( rc==SQLITE_OK ){
01797 sqlitepager_dont_rollback(*ppPage);
01798 rc = sqlitepager_write(*ppPage);
01799 }
01800 }
01801 }else{
01802 *pPgno = sqlitepager_pagecount(pBt->pPager) + 1;
01803 rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
01804 if( rc ) return rc;
01805 rc = sqlitepager_write(*ppPage);
01806 }
01807 return rc;
01808 }
01809
01810
01811
01812
01813
01814
01815
01816 static int freePage(Btree *pBt, void *pPage, Pgno pgno){
01817 PageOne *pPage1 = pBt->page1;
01818 OverflowPage *pOvfl = (OverflowPage*)pPage;
01819 int rc;
01820 int needUnref = 0;
01821 MemPage *pMemPage;
01822
01823 if( pgno==0 ){
01824 assert( pOvfl!=0 );
01825 pgno = sqlitepager_pagenumber(pOvfl);
01826 }
01827 assert( pgno>2 );
01828 assert( sqlitepager_pagenumber(pOvfl)==pgno );
01829 pMemPage = (MemPage*)pPage;
01830 pMemPage->isInit = 0;
01831 if( pMemPage->pParent ){
01832 sqlitepager_unref(pMemPage->pParent);
01833 pMemPage->pParent = 0;
01834 }
01835 rc = sqlitepager_write(pPage1);
01836 if( rc ){
01837 return rc;
01838 }
01839 SWAB_ADD(pBt, pPage1->nFree, 1);
01840 if( pPage1->nFree!=0 && pPage1->freeList!=0 ){
01841 OverflowPage *pFreeIdx;
01842 rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
01843 (void**)&pFreeIdx);
01844 if( rc==SQLITE_OK ){
01845 FreelistInfo *pInfo = (FreelistInfo*)pFreeIdx->aPayload;
01846 int n = SWAB32(pBt, pInfo->nFree);
01847 if( n<(sizeof(pInfo->aFree)/sizeof(pInfo->aFree[0])) ){
01848 rc = sqlitepager_write(pFreeIdx);
01849 if( rc==SQLITE_OK ){
01850 pInfo->aFree[n] = SWAB32(pBt, pgno);
01851 SWAB_ADD(pBt, pInfo->nFree, 1);
01852 sqlitepager_unref(pFreeIdx);
01853 sqlitepager_dont_write(pBt->pPager, pgno);
01854 return rc;
01855 }
01856 }
01857 sqlitepager_unref(pFreeIdx);
01858 }
01859 }
01860 if( pOvfl==0 ){
01861 assert( pgno>0 );
01862 rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pOvfl);
01863 if( rc ) return rc;
01864 needUnref = 1;
01865 }
01866 rc = sqlitepager_write(pOvfl);
01867 if( rc ){
01868 if( needUnref ) sqlitepager_unref(pOvfl);
01869 return rc;
01870 }
01871 pOvfl->iNext = pPage1->freeList;
01872 pPage1->freeList = SWAB32(pBt, pgno);
01873 memset(pOvfl->aPayload, 0, OVERFLOW_SIZE);
01874 if( needUnref ) rc = sqlitepager_unref(pOvfl);
01875 return rc;
01876 }
01877
01878
01879
01880
01881
01882 static int clearCell(Btree *pBt, Cell *pCell){
01883 Pager *pPager = pBt->pPager;
01884 OverflowPage *pOvfl;
01885 Pgno ovfl, nextOvfl;
01886 int rc;
01887
01888 if( NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h) <= MX_LOCAL_PAYLOAD ){
01889 return SQLITE_OK;
01890 }
01891 ovfl = SWAB32(pBt, pCell->ovfl);
01892 pCell->ovfl = 0;
01893 while( ovfl ){
01894 rc = sqlitepager_get(pPager, ovfl, (void**)&pOvfl);
01895 if( rc ) return rc;
01896 nextOvfl = SWAB32(pBt, pOvfl->iNext);
01897 rc = freePage(pBt, pOvfl, ovfl);
01898 if( rc ) return rc;
01899 sqlitepager_unref(pOvfl);
01900 ovfl = nextOvfl;
01901 }
01902 return SQLITE_OK;
01903 }
01904
01905
01906
01907
01908
01909 static int fillInCell(
01910 Btree *pBt,
01911 Cell *pCell,
01912 const void *pKey, int nKey,
01913 const void *pData,int nData
01914 ){
01915 OverflowPage *pOvfl, *pPrior;
01916 Pgno *pNext;
01917 int spaceLeft;
01918 int n, rc;
01919 int nPayload;
01920 const char *pPayload;
01921 char *pSpace;
01922 Pgno nearby = 0;
01923
01924 pCell->h.leftChild = 0;
01925 pCell->h.nKey = SWAB16(pBt, nKey & 0xffff);
01926 pCell->h.nKeyHi = nKey >> 16;
01927 pCell->h.nData = SWAB16(pBt, nData & 0xffff);
01928 pCell->h.nDataHi = nData >> 16;
01929 pCell->h.iNext = 0;
01930
01931 pNext = &pCell->ovfl;
01932 pSpace = pCell->aPayload;
01933 spaceLeft = MX_LOCAL_PAYLOAD;
01934 pPayload = pKey;
01935 pKey = 0;
01936 nPayload = nKey;
01937 pPrior = 0;
01938 while( nPayload>0 ){
01939 if( spaceLeft==0 ){
01940 rc = allocatePage(pBt, (MemPage**)&pOvfl, pNext, nearby);
01941 if( rc ){
01942 *pNext = 0;
01943 }else{
01944 nearby = *pNext;
01945 }
01946 if( pPrior ) sqlitepager_unref(pPrior);
01947 if( rc ){
01948 clearCell(pBt, pCell);
01949 return rc;
01950 }
01951 if( pBt->needSwab ) *pNext = swab32(*pNext);
01952 pPrior = pOvfl;
01953 spaceLeft = OVERFLOW_SIZE;
01954 pSpace = pOvfl->aPayload;
01955 pNext = &pOvfl->iNext;
01956 }
01957 n = nPayload;
01958 if( n>spaceLeft ) n = spaceLeft;
01959 memcpy(pSpace, pPayload, n);
01960 nPayload -= n;
01961 if( nPayload==0 && pData ){
01962 pPayload = pData;
01963 nPayload = nData;
01964 pData = 0;
01965 }else{
01966 pPayload += n;
01967 }
01968 spaceLeft -= n;
01969 pSpace += n;
01970 }
01971 *pNext = 0;
01972 if( pPrior ){
01973 sqlitepager_unref(pPrior);
01974 }
01975 return SQLITE_OK;
01976 }
01977
01978
01979
01980
01981
01982
01983 static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent,int idx){
01984 MemPage *pThis;
01985
01986 if( pgno==0 ) return;
01987 assert( pPager!=0 );
01988 pThis = sqlitepager_lookup(pPager, pgno);
01989 if( pThis && pThis->isInit ){
01990 if( pThis->pParent!=pNewParent ){
01991 if( pThis->pParent ) sqlitepager_unref(pThis->pParent);
01992 pThis->pParent = pNewParent;
01993 if( pNewParent ) sqlitepager_ref(pNewParent);
01994 }
01995 pThis->idxParent = idx;
01996 sqlitepager_unref(pThis);
01997 }
01998 }
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008 static void reparentChildPages(Btree *pBt, MemPage *pPage){
02009 int i;
02010 Pager *pPager = pBt->pPager;
02011 for(i=0; i<pPage->nCell; i++){
02012 reparentPage(pPager, SWAB32(pBt, pPage->apCell[i]->h.leftChild), pPage, i);
02013 }
02014 reparentPage(pPager, SWAB32(pBt, pPage->u.hdr.rightChild), pPage, i);
02015 pPage->idxShift = 0;
02016 }
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031 static void dropCell(Btree *pBt, MemPage *pPage, int idx, int sz){
02032 int j;
02033 assert( idx>=0 && idx<pPage->nCell );
02034 assert( sz==cellSize(pBt, pPage->apCell[idx]) );
02035 assert( sqlitepager_iswriteable(pPage) );
02036 freeSpace(pBt, pPage, Addr(pPage->apCell[idx]) - Addr(pPage), sz);
02037 for(j=idx; j<pPage->nCell-1; j++){
02038 pPage->apCell[j] = pPage->apCell[j+1];
02039 }
02040 pPage->nCell--;
02041 pPage->idxShift = 1;
02042 }
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057 static void insertCell(Btree *pBt, MemPage *pPage, int i, Cell *pCell, int sz){
02058 int idx, j;
02059 assert( i>=0 && i<=pPage->nCell );
02060 assert( sz==cellSize(pBt, pCell) );
02061 assert( sqlitepager_iswriteable(pPage) );
02062 idx = allocateSpace(pBt, pPage, sz);
02063 for(j=pPage->nCell; j>i; j--){
02064 pPage->apCell[j] = pPage->apCell[j-1];
02065 }
02066 pPage->nCell++;
02067 if( idx<=0 ){
02068 pPage->isOverfull = 1;
02069 pPage->apCell[i] = pCell;
02070 }else{
02071 memcpy(&pPage->u.aDisk[idx], pCell, sz);
02072 pPage->apCell[i] = (Cell*)&pPage->u.aDisk[idx];
02073 }
02074 pPage->idxShift = 1;
02075 }
02076
02077
02078
02079
02080
02081
02082
02083 static void relinkCellList(Btree *pBt, MemPage *pPage){
02084 int i;
02085 u16 *pIdx;
02086 assert( sqlitepager_iswriteable(pPage) );
02087 pIdx = &pPage->u.hdr.firstCell;
02088 for(i=0; i<pPage->nCell; i++){
02089 int idx = Addr(pPage->apCell[i]) - Addr(pPage);
02090 assert( idx>0 && idx<SQLITE_USABLE_SIZE );
02091 *pIdx = SWAB16(pBt, idx);
02092 pIdx = &pPage->apCell[i]->h.iNext;
02093 }
02094 *pIdx = 0;
02095 }
02096
02097
02098
02099
02100
02101
02102
02103 static void copyPage(MemPage *pTo, MemPage *pFrom){
02104 uptr from, to;
02105 int i;
02106 memcpy(pTo->u.aDisk, pFrom->u.aDisk, SQLITE_USABLE_SIZE);
02107 pTo->pParent = 0;
02108 pTo->isInit = 1;
02109 pTo->nCell = pFrom->nCell;
02110 pTo->nFree = pFrom->nFree;
02111 pTo->isOverfull = pFrom->isOverfull;
02112 to = Addr(pTo);
02113 from = Addr(pFrom);
02114 for(i=0; i<pTo->nCell; i++){
02115 uptr x = Addr(pFrom->apCell[i]);
02116 if( x>from && x<from+SQLITE_USABLE_SIZE ){
02117 *((uptr*)&pTo->apCell[i]) = x + to - from;
02118 }else{
02119 pTo->apCell[i] = pFrom->apCell[i];
02120 }
02121 }
02122 }
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136 #define NN 1
02137 #define NB (NN*2+1)
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179 static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
02180 MemPage *pParent;
02181 int nCell;
02182 int nOld;
02183 int nNew;
02184 int nDiv;
02185 int i, j, k;
02186 int idx;
02187 int nxDiv;
02188 int rc;
02189 int iCur;
02190 MemPage *pOldCurPage;
02191 int subtotal;
02192 MemPage *extraUnref = 0;
02193 MemPage *apOld[NB];
02194 Pgno pgnoOld[NB];
02195 MemPage *apNew[NB+1];
02196 Pgno pgnoNew[NB+1];
02197 int idxDiv[NB];
02198 Cell *apDiv[NB];
02199 Cell aTemp[NB];
02200 int cntNew[NB+1];
02201 int szNew[NB+1];
02202 MemPage aOld[NB];
02203 Cell *apCell[(MX_CELL+2)*NB];
02204 int szCell[(MX_CELL+2)*NB];
02205
02206
02207
02208
02209
02210 assert( sqlitepager_iswriteable(pPage) );
02211 if( !pPage->isOverfull && pPage->nFree<SQLITE_USABLE_SIZE/2
02212 && pPage->nCell>=2){
02213 relinkCellList(pBt, pPage);
02214 return SQLITE_OK;
02215 }
02216
02217
02218
02219
02220
02221
02222 pParent = pPage->pParent;
02223 if( pParent==0 ){
02224 Pgno pgnoChild;
02225 MemPage *pChild;
02226 assert( pPage->isInit );
02227 if( pPage->nCell==0 ){
02228 if( pPage->u.hdr.rightChild ){
02229
02230
02231
02232
02233
02234 pgnoChild = SWAB32(pBt, pPage->u.hdr.rightChild);
02235 rc = sqlitepager_get(pBt->pPager, pgnoChild, (void**)&pChild);
02236 if( rc ) return rc;
02237 memcpy(pPage, pChild, SQLITE_USABLE_SIZE);
02238 pPage->isInit = 0;
02239 rc = initPage(pBt, pPage, sqlitepager_pagenumber(pPage), 0);
02240 assert( rc==SQLITE_OK );
02241 reparentChildPages(pBt, pPage);
02242 if( pCur && pCur->pPage==pChild ){
02243 sqlitepager_unref(pChild);
02244 pCur->pPage = pPage;
02245 sqlitepager_ref(pPage);
02246 }
02247 freePage(pBt, pChild, pgnoChild);
02248 sqlitepager_unref(pChild);
02249 }else{
02250 relinkCellList(pBt, pPage);
02251 }
02252 return SQLITE_OK;
02253 }
02254 if( !pPage->isOverfull ){
02255
02256
02257 relinkCellList(pBt, pPage);
02258 return SQLITE_OK;
02259 }
02260
02261
02262
02263
02264
02265
02266
02267
02268 rc = sqlitepager_write(pPage);
02269 if( rc ) return rc;
02270 rc = allocatePage(pBt, &pChild, &pgnoChild, sqlitepager_pagenumber(pPage));
02271 if( rc ) return rc;
02272 assert( sqlitepager_iswriteable(pChild) );
02273 copyPage(pChild, pPage);
02274 pChild->pParent = pPage;
02275 pChild->idxParent = 0;
02276 sqlitepager_ref(pPage);
02277 pChild->isOverfull = 1;
02278 if( pCur && pCur->pPage==pPage ){
02279 sqlitepager_unref(pPage);
02280 pCur->pPage = pChild;
02281 }else{
02282 extraUnref = pChild;
02283 }
02284 zeroPage(pBt, pPage);
02285 pPage->u.hdr.rightChild = SWAB32(pBt, pgnoChild);
02286 pParent = pPage;
02287 pPage = pChild;
02288 }
02289 rc = sqlitepager_write(pParent);
02290 if( rc ) return rc;
02291 assert( pParent->isInit );
02292
02293
02294
02295
02296
02297
02298 if( pParent->idxShift ){
02299 Pgno pgno, swabPgno;
02300 pgno = sqlitepager_pagenumber(pPage);
02301 swabPgno = SWAB32(pBt, pgno);
02302 for(idx=0; idx<pParent->nCell; idx++){
02303 if( pParent->apCell[idx]->h.leftChild==swabPgno ){
02304 break;
02305 }
02306 }
02307 assert( idx<pParent->nCell || pParent->u.hdr.rightChild==swabPgno );
02308 }else{
02309 idx = pPage->idxParent;
02310 }
02311
02312
02313
02314
02315
02316 nOld = nNew = 0;
02317 sqlitepager_ref(pParent);
02318
02319
02320
02321
02322
02323
02324
02325
02326 nxDiv = idx - NN;
02327 if( nxDiv + NB > pParent->nCell ){
02328 nxDiv = pParent->nCell - NB + 1;
02329 }
02330 if( nxDiv<0 ){
02331 nxDiv = 0;
02332 }
02333 nDiv = 0;
02334 for(i=0, k=nxDiv; i<NB; i++, k++){
02335 if( k<pParent->nCell ){
02336 idxDiv[i] = k;
02337 apDiv[i] = pParent->apCell[k];
02338 nDiv++;
02339 pgnoOld[i] = SWAB32(pBt, apDiv[i]->h.leftChild);
02340 }else if( k==pParent->nCell ){
02341 pgnoOld[i] = SWAB32(pBt, pParent->u.hdr.rightChild);
02342 }else{
02343 break;
02344 }
02345 rc = sqlitepager_get(pBt->pPager, pgnoOld[i], (void**)&apOld[i]);
02346 if( rc ) goto balance_cleanup;
02347 rc = initPage(pBt, apOld[i], pgnoOld[i], pParent);
02348 if( rc ) goto balance_cleanup;
02349 apOld[i]->idxParent = k;
02350 nOld++;
02351 }
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361 if( pCur ){
02362 iCur = 0;
02363 for(i=0; i<nOld; i++){
02364 if( pCur->pPage==apOld[i] ){
02365 iCur += pCur->idx;
02366 break;
02367 }
02368 iCur += apOld[i]->nCell;
02369 if( i<nOld-1 && pCur->pPage==pParent && pCur->idx==idxDiv[i] ){
02370 break;
02371 }
02372 iCur++;
02373 }
02374 pOldCurPage = pCur->pPage;
02375 }
02376
02377
02378
02379
02380
02381
02382
02383 for(i=0; i<nOld; i++){
02384 copyPage(&aOld[i], apOld[i]);
02385 }
02386
02387
02388
02389
02390
02391
02392 nCell = 0;
02393 for(i=0; i<nOld; i++){
02394 MemPage *pOld = &aOld[i];
02395 for(j=0; j<pOld->nCell; j++){
02396 apCell[nCell] = pOld->apCell[j];
02397 szCell[nCell] = cellSize(pBt, apCell[nCell]);
02398 nCell++;
02399 }
02400 if( i<nOld-1 ){
02401 szCell[nCell] = cellSize(pBt, apDiv[i]);
02402 memcpy(&aTemp[i], apDiv[i], szCell[nCell]);
02403 apCell[nCell] = &aTemp[i];
02404 dropCell(pBt, pParent, nxDiv, szCell[nCell]);
02405 assert( SWAB32(pBt, apCell[nCell]->h.leftChild)==pgnoOld[i] );
02406 apCell[nCell]->h.leftChild = pOld->u.hdr.rightChild;
02407 nCell++;
02408 }
02409 }
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421 for(subtotal=k=i=0; i<nCell; i++){
02422 subtotal += szCell[i];
02423 if( subtotal > USABLE_SPACE ){
02424 szNew[k] = subtotal - szCell[i];
02425 cntNew[k] = i;
02426 subtotal = 0;
02427 k++;
02428 }
02429 }
02430 szNew[k] = subtotal;
02431 cntNew[k] = nCell;
02432 k++;
02433 for(i=k-1; i>0; i--){
02434 while( szNew[i]<USABLE_SPACE/2 ){
02435 cntNew[i-1]--;
02436 assert( cntNew[i-1]>0 );
02437 szNew[i] += szCell[cntNew[i-1]];
02438 szNew[i-1] -= szCell[cntNew[i-1]-1];
02439 }
02440 }
02441 assert( cntNew[0]>0 );
02442
02443
02444
02445
02446 for(i=0; i<k; i++){
02447 if( i<nOld ){
02448 apNew[i] = apOld[i];
02449 pgnoNew[i] = pgnoOld[i];
02450 apOld[i] = 0;
02451 sqlitepager_write(apNew[i]);
02452 }else{
02453 rc = allocatePage(pBt, &apNew[i], &pgnoNew[i], pgnoNew[i-1]);
02454 if( rc ) goto balance_cleanup;
02455 }
02456 nNew++;
02457 zeroPage(pBt, apNew[i]);
02458 apNew[i]->isInit = 1;
02459 }
02460
02461
02462
02463 while( i<nOld ){
02464 rc = freePage(pBt, apOld[i], pgnoOld[i]);
02465 if( rc ) goto balance_cleanup;
02466 sqlitepager_unref(apOld[i]);
02467 apOld[i] = 0;
02468 i++;
02469 }
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485 for(i=0; i<k-1; i++){
02486 int minV = pgnoNew[i];
02487 int minI = i;
02488 for(j=i+1; j<k; j++){
02489 if( pgnoNew[j]<(unsigned)minV ){
02490 minI = j;
02491 minV = pgnoNew[j];
02492 }
02493 }
02494 if( minI>i ){
02495 int t;
02496 MemPage *pT;
02497 t = pgnoNew[i];
02498 pT = apNew[i];
02499 pgnoNew[i] = pgnoNew[minI];
02500 apNew[i] = apNew[minI];
02501 pgnoNew[minI] = t;
02502 apNew[minI] = pT;
02503 }
02504 }
02505
02506
02507
02508
02509
02510 j = 0;
02511 for(i=0; i<nNew; i++){
02512 MemPage *pNew = apNew[i];
02513 while( j<cntNew[i] ){
02514 assert( pNew->nFree>=szCell[j] );
02515 if( pCur && iCur==j ){ pCur->pPage = pNew; pCur->idx = pNew->nCell; }
02516 insertCell(pBt, pNew, pNew->nCell, apCell[j], szCell[j]);
02517 j++;
02518 }
02519 assert( pNew->nCell>0 );
02520 assert( !pNew->isOverfull );
02521 relinkCellList(pBt, pNew);
02522 if( i<nNew-1 && j<nCell ){
02523 pNew->u.hdr.rightChild = apCell[j]->h.leftChild;
02524 apCell[j]->h.leftChild = SWAB32(pBt, pgnoNew[i]);
02525 if( pCur && iCur==j ){ pCur->pPage = pParent; pCur->idx = nxDiv; }
02526 insertCell(pBt, pParent, nxDiv, apCell[j], szCell[j]);
02527 j++;
02528 nxDiv++;
02529 }
02530 }
02531 assert( j==nCell );
02532 apNew[nNew-1]->u.hdr.rightChild = aOld[nOld-1].u.hdr.rightChild;
02533 if( nxDiv==pParent->nCell ){
02534 pParent->u.hdr.rightChild = SWAB32(pBt, pgnoNew[nNew-1]);
02535 }else{
02536 pParent->apCell[nxDiv]->h.leftChild = SWAB32(pBt, pgnoNew[nNew-1]);
02537 }
02538 if( pCur ){
02539 if( j<=iCur && pCur->pPage==pParent && pCur->idx>idxDiv[nOld-1] ){
02540 assert( pCur->pPage==pOldCurPage );
02541 pCur->idx += nNew - nOld;
02542 }else{
02543 assert( pOldCurPage!=0 );
02544 sqlitepager_ref(pCur->pPage);
02545 sqlitepager_unref(pOldCurPage);
02546 }
02547 }
02548
02549
02550
02551
02552 for(i=0; i<nNew; i++){
02553 reparentChildPages(pBt, apNew[i]);
02554 }
02555 reparentChildPages(pBt, pParent);
02556
02557
02558
02559
02560 rc = balance(pBt, pParent, pCur);
02561
02562
02563
02564
02565 balance_cleanup:
02566 if( extraUnref ){
02567 sqlitepager_unref(extraUnref);
02568 }
02569 for(i=0; i<nOld; i++){
02570 if( apOld[i]!=0 && apOld[i]!=&aOld[i] ) sqlitepager_unref(apOld[i]);
02571 }
02572 for(i=0; i<nNew; i++){
02573 sqlitepager_unref(apNew[i]);
02574 }
02575 if( pCur && pCur->pPage==0 ){
02576 pCur->pPage = pParent;
02577 pCur->idx = 0;
02578 }else{
02579 sqlitepager_unref(pParent);
02580 }
02581 return rc;
02582 }
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599 static int checkReadLocks(BtCursor *pCur){
02600 BtCursor *p;
02601 assert( pCur->wrFlag );
02602 for(p=pCur->pShared; p!=pCur; p=p->pShared){
02603 assert( p );
02604 assert( p->pgnoRoot==pCur->pgnoRoot );
02605 if( p->wrFlag==0 ) return SQLITE_LOCKED;
02606 if( sqlitepager_pagenumber(p->pPage)!=p->pgnoRoot ){
02607 moveToRoot(p);
02608 }
02609 }
02610 return SQLITE_OK;
02611 }
02612
02613
02614
02615
02616
02617
02618
02619 static int fileBtreeInsert(
02620 BtCursor *pCur,
02621 const void *pKey, int nKey,
02622 const void *pData, int nData
02623 ){
02624 Cell newCell;
02625 int rc;
02626 int loc;
02627 int szNew;
02628 MemPage *pPage;
02629 Btree *pBt = pCur->pBt;
02630
02631 if( pCur->pPage==0 ){
02632 return SQLITE_ABORT;
02633 }
02634 if( !pBt->inTrans || nKey+nData==0 ){
02635
02636 return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
02637 }
02638 assert( !pBt->readOnly );
02639 if( !pCur->wrFlag ){
02640 return SQLITE_PERM;
02641 }
02642 if( checkReadLocks(pCur) ){
02643 return SQLITE_LOCKED;
02644 }
02645 rc = fileBtreeMoveto(pCur, pKey, nKey, &loc);
02646 if( rc ) return rc;
02647 pPage = pCur->pPage;
02648 assert( pPage->isInit );
02649 rc = sqlitepager_write(pPage);
02650 if( rc ) return rc;
02651 rc = fillInCell(pBt, &newCell, pKey, nKey, pData, nData);
02652 if( rc ) return rc;
02653 szNew = cellSize(pBt, &newCell);
02654 if( loc==0 ){
02655 newCell.h.leftChild = pPage->apCell[pCur->idx]->h.leftChild;
02656 rc = clearCell(pBt, pPage->apCell[pCur->idx]);
02657 if( rc ) return rc;
02658 dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pPage->apCell[pCur->idx]));
02659 }else if( loc<0 && pPage->nCell>0 ){
02660 assert( pPage->u.hdr.rightChild==0 );
02661 pCur->idx++;
02662 }else{
02663 assert( pPage->u.hdr.rightChild==0 );
02664 }
02665 insertCell(pBt, pPage, pCur->idx, &newCell, szNew);
02666 rc = balance(pCur->pBt, pPage, pCur);
02667
02668
02669 pCur->eSkip = SKIP_INVALID;
02670 return rc;
02671 }
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687 static int fileBtreeDelete(BtCursor *pCur){
02688 MemPage *pPage = pCur->pPage;
02689 Cell *pCell;
02690 int rc;
02691 Pgno pgnoChild;
02692 Btree *pBt = pCur->pBt;
02693
02694 assert( pPage->isInit );
02695 if( pCur->pPage==0 ){
02696 return SQLITE_ABORT;
02697 }
02698 if( !pBt->inTrans ){
02699
02700 return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
02701 }
02702 assert( !pBt->readOnly );
02703 if( pCur->idx >= pPage->nCell ){
02704 return SQLITE_ERROR;
02705 }
02706 if( !pCur->wrFlag ){
02707 return SQLITE_PERM;
02708 }
02709 if( checkReadLocks(pCur) ){
02710 return SQLITE_LOCKED;
02711 }
02712 rc = sqlitepager_write(pPage);
02713 if( rc ) return rc;
02714 pCell = pPage->apCell[pCur->idx];
02715 pgnoChild = SWAB32(pBt, pCell->h.leftChild);
02716 clearCell(pBt, pCell);
02717 if( pgnoChild ){
02718
02719
02720
02721
02722
02723
02724
02725 BtCursor leafCur;
02726 Cell *pNext;
02727 int szNext;
02728 int notUsed;
02729 getTempCursor(pCur, &leafCur);
02730 rc = fileBtreeNext(&leafCur, ¬Used);
02731 if( rc!=SQLITE_OK ){
02732 if( rc!=SQLITE_NOMEM ) rc = SQLITE_CORRUPT;
02733 return rc;
02734 }
02735 rc = sqlitepager_write(leafCur.pPage);
02736 if( rc ) return rc;
02737 dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell));
02738 pNext = leafCur.pPage->apCell[leafCur.idx];
02739 szNext = cellSize(pBt, pNext);
02740 pNext->h.leftChild = SWAB32(pBt, pgnoChild);
02741 insertCell(pBt, pPage, pCur->idx, pNext, szNext);
02742 rc = balance(pBt, pPage, pCur);
02743 if( rc ) return rc;
02744 pCur->eSkip = SKIP_NEXT;
02745 dropCell(pBt, leafCur.pPage, leafCur.idx, szNext);
02746 rc = balance(pBt, leafCur.pPage, pCur);
02747 releaseTempCursor(&leafCur);
02748 }else{
02749 dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell));
02750 if( pCur->idx>=pPage->nCell ){
02751 pCur->idx = pPage->nCell-1;
02752 if( pCur->idx<0 ){
02753 pCur->idx = 0;
02754 pCur->eSkip = SKIP_NEXT;
02755 }else{
02756 pCur->eSkip = SKIP_PREV;
02757 }
02758 }else{
02759 pCur->eSkip = SKIP_NEXT;
02760 }
02761 rc = balance(pBt, pPage, pCur);
02762 }
02763 return rc;
02764 }
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776 static int fileBtreeCreateTable(Btree *pBt, int *piTable){
02777 MemPage *pRoot;
02778 Pgno pgnoRoot;
02779 int rc;
02780 if( !pBt->inTrans ){
02781
02782 return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
02783 }
02784 if( pBt->readOnly ){
02785 return SQLITE_READONLY;
02786 }
02787 rc = allocatePage(pBt, &pRoot, &pgnoRoot, 0);
02788 if( rc ) return rc;
02789 assert( sqlitepager_iswriteable(pRoot) );
02790 zeroPage(pBt, pRoot);
02791 sqlitepager_unref(pRoot);
02792 *piTable = (int)pgnoRoot;
02793 return SQLITE_OK;
02794 }
02795
02796
02797
02798
02799
02800 static int clearDatabasePage(Btree *pBt, Pgno pgno, int freePageFlag){
02801 MemPage *pPage;
02802 int rc;
02803 Cell *pCell;
02804 int idx;
02805
02806 rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pPage);
02807 if( rc ) return rc;
02808 rc = sqlitepager_write(pPage);
02809 if( rc ) return rc;
02810 rc = initPage(pBt, pPage, pgno, 0);
02811 if( rc ) return rc;
02812 idx = SWAB16(pBt, pPage->u.hdr.firstCell);
02813 while( idx>0 ){
02814 pCell = (Cell*)&pPage->u.aDisk[idx];
02815 idx = SWAB16(pBt, pCell->h.iNext);
02816 if( pCell->h.leftChild ){
02817 rc = clearDatabasePage(pBt, SWAB32(pBt, pCell->h.leftChild), 1);
02818 if( rc ) return rc;
02819 }
02820 rc = clearCell(pBt, pCell);
02821 if( rc ) return rc;
02822 }
02823 if( pPage->u.hdr.rightChild ){
02824 rc = clearDatabasePage(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1);
02825 if( rc ) return rc;
02826 }
02827 if( freePageFlag ){
02828 rc = freePage(pBt, pPage, pgno);
02829 }else{
02830 zeroPage(pBt, pPage);
02831 }
02832 sqlitepager_unref(pPage);
02833 return rc;
02834 }
02835
02836
02837
02838
02839 static int fileBtreeClearTable(Btree *pBt, int iTable){
02840 int rc;
02841 BtCursor *pCur;
02842 if( !pBt->inTrans ){
02843 return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
02844 }
02845 for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
02846 if( pCur->pgnoRoot==(Pgno)iTable ){
02847 if( pCur->wrFlag==0 ) return SQLITE_LOCKED;
02848 moveToRoot(pCur);
02849 }
02850 }
02851 rc = clearDatabasePage(pBt, (Pgno)iTable, 0);
02852 if( rc ){
02853 fileBtreeRollback(pBt);
02854 }
02855 return rc;
02856 }
02857
02858
02859
02860
02861
02862
02863 static int fileBtreeDropTable(Btree *pBt, int iTable){
02864 int rc;
02865 MemPage *pPage;
02866 BtCursor *pCur;
02867 if( !pBt->inTrans ){
02868 return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
02869 }
02870 for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
02871 if( pCur->pgnoRoot==(Pgno)iTable ){
02872 return SQLITE_LOCKED;
02873 }
02874 }
02875 rc = sqlitepager_get(pBt->pPager, (Pgno)iTable, (void**)&pPage);
02876 if( rc ) return rc;
02877 rc = fileBtreeClearTable(pBt, iTable);
02878 if( rc ) return rc;
02879 if( iTable>2 ){
02880 rc = freePage(pBt, pPage, iTable);
02881 }else{
02882 zeroPage(pBt, pPage);
02883 }
02884 sqlitepager_unref(pPage);
02885 return rc;
02886 }
02887
02888 #if 0
02889
02890
02891
02892
02893 static int copyCell(Btree *pBtFrom, BTree *pBtTo, Cell *pCell){
02894 Pager *pFromPager = pBtFrom->pPager;
02895 OverflowPage *pOvfl;
02896 Pgno ovfl, nextOvfl;
02897 Pgno *pPrev;
02898 int rc = SQLITE_OK;
02899 MemPage *pNew, *pPrevPg;
02900 Pgno new;
02901
02902 if( NKEY(pBtTo, pCell->h) + NDATA(pBtTo, pCell->h) <= MX_LOCAL_PAYLOAD ){
02903 return SQLITE_OK;
02904 }
02905 pPrev = &pCell->ovfl;
02906 pPrevPg = 0;
02907 ovfl = SWAB32(pBtTo, pCell->ovfl);
02908 while( ovfl && rc==SQLITE_OK ){
02909 rc = sqlitepager_get(pFromPager, ovfl, (void**)&pOvfl);
02910 if( rc ) return rc;
02911 nextOvfl = SWAB32(pBtFrom, pOvfl->iNext);
02912 rc = allocatePage(pBtTo, &pNew, &new, 0);
02913 if( rc==SQLITE_OK ){
02914 rc = sqlitepager_write(pNew);
02915 if( rc==SQLITE_OK ){
02916 memcpy(pNew, pOvfl, SQLITE_USABLE_SIZE);
02917 *pPrev = SWAB32(pBtTo, new);
02918 if( pPrevPg ){
02919 sqlitepager_unref(pPrevPg);
02920 }
02921 pPrev = &pOvfl->iNext;
02922 pPrevPg = pNew;
02923 }
02924 }
02925 sqlitepager_unref(pOvfl);
02926 ovfl = nextOvfl;
02927 }
02928 if( pPrevPg ){
02929 sqlitepager_unref(pPrevPg);
02930 }
02931 return rc;
02932 }
02933 #endif
02934
02935
02936 #if 0
02937
02938
02939
02940 static int copyDatabasePage(
02941 Btree *pBtFrom,
02942 Pgno pgnoFrom,
02943 Btree *pBtTo,
02944 Pgno *pTo
02945 ){
02946 MemPage *pPageFrom, *pPage;
02947 Pgno to;
02948 int rc;
02949 Cell *pCell;
02950 int idx;
02951
02952 rc = sqlitepager_get(pBtFrom->pPager, pgno, (void**)&pPageFrom);
02953 if( rc ) return rc;
02954 rc = allocatePage(pBt, &pPage, pTo, 0);
02955 if( rc==SQLITE_OK ){
02956 rc = sqlitepager_write(pPage);
02957 }
02958 if( rc==SQLITE_OK ){
02959 memcpy(pPage, pPageFrom, SQLITE_USABLE_SIZE);
02960 idx = SWAB16(pBt, pPage->u.hdr.firstCell);
02961 while( idx>0 ){
02962 pCell = (Cell*)&pPage->u.aDisk[idx];
02963 idx = SWAB16(pBt, pCell->h.iNext);
02964 if( pCell->h.leftChild ){
02965 Pgno newChld;
02966 rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pCell->h.leftChild),
02967 pBtTo, &newChld);
02968 if( rc ) return rc;
02969 pCell->h.leftChild = SWAB32(pBtFrom, newChld);
02970 }
02971 rc = copyCell(pBtFrom, pBtTo, pCell);
02972 if( rc ) return rc;
02973 }
02974 if( pPage->u.hdr.rightChild ){
02975 Pgno newChld;
02976 rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pPage->u.hdr.rightChild),
02977 pBtTo, &newChld);
02978 if( rc ) return rc;
02979 pPage->u.hdr.rightChild = SWAB32(pBtTo, newChild);
02980 }
02981 }
02982 sqlitepager_unref(pPage);
02983 return rc;
02984 }
02985 #endif
02986
02987
02988
02989
02990 static int fileBtreeGetMeta(Btree *pBt, int *aMeta){
02991 PageOne *pP1;
02992 int rc;
02993 int i;
02994
02995 rc = sqlitepager_get(pBt->pPager, 1, (void**)&pP1);
02996 if( rc ) return rc;
02997 aMeta[0] = SWAB32(pBt, pP1->nFree);
02998 for(i=0; i<sizeof(pP1->aMeta)/sizeof(pP1->aMeta[0]); i++){
02999 aMeta[i+1] = SWAB32(pBt, pP1->aMeta[i]);
03000 }
03001 sqlitepager_unref(pP1);
03002 return SQLITE_OK;
03003 }
03004
03005
03006
03007
03008 static int fileBtreeUpdateMeta(Btree *pBt, int *aMeta){
03009 PageOne *pP1;
03010 int rc, i;
03011 if( !pBt->inTrans ){
03012 return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
03013 }
03014 pP1 = pBt->page1;
03015 rc = sqlitepager_write(pP1);
03016 if( rc ) return rc;
03017 for(i=0; i<sizeof(pP1->aMeta)/sizeof(pP1->aMeta[0]); i++){
03018 pP1->aMeta[i] = SWAB32(pBt, aMeta[i+1]);
03019 }
03020 return SQLITE_OK;
03021 }
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033 #ifdef SQLITE_TEST
03034 static int fileBtreePageDump(Btree *pBt, int pgno, int recursive){
03035 int rc;
03036 MemPage *pPage;
03037 int i, j;
03038 int nFree;
03039 u16 idx;
03040 char range[20];
03041 unsigned char payload[20];
03042 rc = sqlitepager_get(pBt->pPager, (Pgno)pgno, (void**)&pPage);
03043 if( rc ){
03044 return rc;
03045 }
03046 if( recursive ) printf("PAGE %d:\n", pgno);
03047 i = 0;
03048 idx = SWAB16(pBt, pPage->u.hdr.firstCell);
03049 while( idx>0 && idx<=SQLITE_USABLE_SIZE-MIN_CELL_SIZE ){
03050 Cell *pCell = (Cell*)&pPage->u.aDisk[idx];
03051 int sz = cellSize(pBt, pCell);
03052 sprintf(range,"%d..%d", idx, idx+sz-1);
03053 sz = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h);
03054 if( sz>sizeof(payload)-1 ) sz = sizeof(payload)-1;
03055 memcpy(payload, pCell->aPayload, sz);
03056 for(j=0; j<sz; j++){
03057 if( payload[j]<0x20 || payload[j]>0x7f ) payload[j] = '.';
03058 }
03059 payload[sz] = 0;
03060 printf(
03061 "cell %2d: i=%-10s chld=%-4d nk=%-4d nd=%-4d payload=%s\n",
03062 i, range, (int)pCell->h.leftChild,
03063 NKEY(pBt, pCell->h), NDATA(pBt, pCell->h),
03064 payload
03065 );
03066 if( pPage->isInit && pPage->apCell[i]!=pCell ){
03067 printf("**** apCell[%d] does not match on prior entry ****\n", i);
03068 }
03069 i++;
03070 idx = SWAB16(pBt, pCell->h.iNext);
03071 }
03072 if( idx!=0 ){
03073 printf("ERROR: next cell index out of range: %d\n", idx);
03074 }
03075 printf("right_child: %d\n", SWAB32(pBt, pPage->u.hdr.rightChild));
03076 nFree = 0;
03077 i = 0;
03078 idx = SWAB16(pBt, pPage->u.hdr.firstFree);
03079 while( idx>0 && idx<SQLITE_USABLE_SIZE ){
03080 FreeBlk *p = (FreeBlk*)&pPage->u.aDisk[idx];
03081 sprintf(range,"%d..%d", idx, idx+p->iSize-1);
03082 nFree += SWAB16(pBt, p->iSize);
03083 printf("freeblock %2d: i=%-10s size=%-4d total=%d\n",
03084 i, range, SWAB16(pBt, p->iSize), nFree);
03085 idx = SWAB16(pBt, p->iNext);
03086 i++;
03087 }
03088 if( idx!=0 ){
03089 printf("ERROR: next freeblock index out of range: %d\n", idx);
03090 }
03091 if( recursive && pPage->u.hdr.rightChild!=0 ){
03092 idx = SWAB16(pBt, pPage->u.hdr.firstCell);
03093 while( idx>0 && idx<SQLITE_USABLE_SIZE-MIN_CELL_SIZE ){
03094 Cell *pCell = (Cell*)&pPage->u.aDisk[idx];
03095 fileBtreePageDump(pBt, SWAB32(pBt, pCell->h.leftChild), 1);
03096 idx = SWAB16(pBt, pCell->h.iNext);
03097 }
03098 fileBtreePageDump(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1);
03099 }
03100 sqlitepager_unref(pPage);
03101 return SQLITE_OK;
03102 }
03103 #endif
03104
03105 #ifdef SQLITE_TEST
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121 static int fileBtreeCursorDump(BtCursor *pCur, int *aResult){
03122 int cnt, idx;
03123 MemPage *pPage = pCur->pPage;
03124 Btree *pBt = pCur->pBt;
03125 aResult[0] = sqlitepager_pagenumber(pPage);
03126 aResult[1] = pCur->idx;
03127 aResult[2] = pPage->nCell;
03128 if( pCur->idx>=0 && pCur->idx<pPage->nCell ){
03129 aResult[3] = cellSize(pBt, pPage->apCell[pCur->idx]);
03130 aResult[6] = SWAB32(pBt, pPage->apCell[pCur->idx]->h.leftChild);
03131 }else{
03132 aResult[3] = 0;
03133 aResult[6] = 0;
03134 }
03135 aResult[4] = pPage->nFree;
03136 cnt = 0;
03137 idx = SWAB16(pBt, pPage->u.hdr.firstFree);
03138 while( idx>0 && idx<SQLITE_USABLE_SIZE ){
03139 cnt++;
03140 idx = SWAB16(pBt, ((FreeBlk*)&pPage->u.aDisk[idx])->iNext);
03141 }
03142 aResult[5] = cnt;
03143 aResult[7] = SWAB32(pBt, pPage->u.hdr.rightChild);
03144 return SQLITE_OK;
03145 }
03146 #endif
03147
03148
03149
03150
03151
03152 static Pager *fileBtreePager(Btree *pBt){
03153 return pBt->pPager;
03154 }
03155
03156
03157
03158
03159
03160 typedef struct IntegrityCk IntegrityCk;
03161 struct IntegrityCk {
03162 Btree *pBt;
03163 Pager *pPager;
03164 int nPage;
03165 int *anRef;
03166 char *zErrMsg;
03167 };
03168
03169
03170
03171
03172 static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){
03173 if( pCheck->zErrMsg ){
03174 char *zOld = pCheck->zErrMsg;
03175 pCheck->zErrMsg = 0;
03176 sqliteSetString(&pCheck->zErrMsg, zOld, "\n", zMsg1, zMsg2, (char*)0);
03177 sqliteFree(zOld);
03178 }else{
03179 sqliteSetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0);
03180 }
03181 }
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191 static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){
03192 if( iPage==0 ) return 1;
03193 if( iPage>pCheck->nPage || iPage<0 ){
03194 char zBuf[100];
03195 sprintf(zBuf, "invalid page number %d", iPage);
03196 checkAppendMsg(pCheck, zContext, zBuf);
03197 return 1;
03198 }
03199 if( pCheck->anRef[iPage]==1 ){
03200 char zBuf[100];
03201 sprintf(zBuf, "2nd reference to page %d", iPage);
03202 checkAppendMsg(pCheck, zContext, zBuf);
03203 return 1;
03204 }
03205 return (pCheck->anRef[iPage]++)>1;
03206 }
03207
03208
03209
03210
03211
03212 static void checkList(
03213 IntegrityCk *pCheck,
03214 int isFreeList,
03215 int iPage,
03216 int N,
03217 char *zContext
03218 ){
03219 int i;
03220 char zMsg[100];
03221 while( N-- > 0 ){
03222 OverflowPage *pOvfl;
03223 if( iPage<1 ){
03224 sprintf(zMsg, "%d pages missing from overflow list", N+1);
03225 checkAppendMsg(pCheck, zContext, zMsg);
03226 break;
03227 }
03228 if( checkRef(pCheck, iPage, zContext) ) break;
03229 if( sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pOvfl) ){
03230 sprintf(zMsg, "failed to get page %d", iPage);
03231 checkAppendMsg(pCheck, zContext, zMsg);
03232 break;
03233 }
03234 if( isFreeList ){
03235 FreelistInfo *pInfo = (FreelistInfo*)pOvfl->aPayload;
03236 int n = SWAB32(pCheck->pBt, pInfo->nFree);
03237 for(i=0; i<n; i++){
03238 checkRef(pCheck, SWAB32(pCheck->pBt, pInfo->aFree[i]), zContext);
03239 }
03240 N -= n;
03241 }
03242 iPage = SWAB32(pCheck->pBt, pOvfl->iNext);
03243 sqlitepager_unref(pOvfl);
03244 }
03245 }
03246
03247
03248
03249
03250
03251
03252 static int keyCompare(
03253 const char *zKey1, int nKey1,
03254 const char *zKey2, int nKey2
03255 ){
03256 int min = nKey1>nKey2 ? nKey2 : nKey1;
03257 int c = memcmp(zKey1, zKey2, min);
03258 if( c==0 ){
03259 c = nKey1 - nKey2;
03260 }
03261 return c;
03262 }
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282 static int checkTreePage(
03283 IntegrityCk *pCheck,
03284 int iPage,
03285 MemPage *pParent,
03286 char *zParentContext,
03287 char *zLowerBound,
03288 int nLower,
03289 char *zUpperBound,
03290 int nUpper
03291 ){
03292 MemPage *pPage;
03293 int i, rc, depth, d2, pgno;
03294 char *zKey1, *zKey2;
03295 int nKey1, nKey2;
03296 BtCursor cur;
03297 Btree *pBt;
03298 char zMsg[100];
03299 char zContext[100];
03300 char hit[SQLITE_USABLE_SIZE];
03301
03302
03303
03304 cur.pBt = pBt = pCheck->pBt;
03305 if( iPage==0 ) return 0;
03306 if( checkRef(pCheck, iPage, zParentContext) ) return 0;
03307 sprintf(zContext, "On tree page %d: ", iPage);
03308 if( (rc = sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pPage))!=0 ){
03309 sprintf(zMsg, "unable to get the page. error code=%d", rc);
03310 checkAppendMsg(pCheck, zContext, zMsg);
03311 return 0;
03312 }
03313 if( (rc = initPage(pBt, pPage, (Pgno)iPage, pParent))!=0 ){
03314 sprintf(zMsg, "initPage() returns error code %d", rc);
03315 checkAppendMsg(pCheck, zContext, zMsg);
03316 sqlitepager_unref(pPage);
03317 return 0;
03318 }
03319
03320
03321
03322 depth = 0;
03323 if( zLowerBound ){
03324 zKey1 = sqliteMalloc( nLower+1 );
03325 memcpy(zKey1, zLowerBound, nLower);
03326 zKey1[nLower] = 0;
03327 }else{
03328 zKey1 = 0;
03329 }
03330 nKey1 = nLower;
03331 cur.pPage = pPage;
03332 for(i=0; i<pPage->nCell; i++){
03333 Cell *pCell = pPage->apCell[i];
03334 int sz;
03335
03336
03337
03338 nKey2 = NKEY(pBt, pCell->h);
03339 sz = nKey2 + NDATA(pBt, pCell->h);
03340 sprintf(zContext, "On page %d cell %d: ", iPage, i);
03341 if( sz>MX_LOCAL_PAYLOAD ){
03342 int nPage = (sz - MX_LOCAL_PAYLOAD + OVERFLOW_SIZE - 1)/OVERFLOW_SIZE;
03343 checkList(pCheck, 0, SWAB32(pBt, pCell->ovfl), nPage, zContext);
03344 }
03345
03346
03347
03348 cur.idx = i;
03349 zKey2 = sqliteMallocRaw( nKey2+1 );
03350 getPayload(&cur, 0, nKey2, zKey2);
03351 if( zKey1 && keyCompare(zKey1, nKey1, zKey2, nKey2)>=0 ){
03352 checkAppendMsg(pCheck, zContext, "Key is out of order");
03353 }
03354
03355
03356
03357 pgno = SWAB32(pBt, pCell->h.leftChild);
03358 d2 = checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zKey2,nKey2);
03359 if( i>0 && d2!=depth ){
03360 checkAppendMsg(pCheck, zContext, "Child page depth differs");
03361 }
03362 depth = d2;
03363 sqliteFree(zKey1);
03364 zKey1 = zKey2;
03365 nKey1 = nKey2;
03366 }
03367 pgno = SWAB32(pBt, pPage->u.hdr.rightChild);
03368 sprintf(zContext, "On page %d at right child: ", iPage);
03369 checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zUpperBound,nUpper);
03370 sqliteFree(zKey1);
03371
03372
03373
03374 memset(hit, 0, sizeof(hit));
03375 memset(hit, 1, sizeof(PageHdr));
03376 for(i=SWAB16(pBt, pPage->u.hdr.firstCell); i>0 && i<SQLITE_USABLE_SIZE; ){
03377 Cell *pCell = (Cell*)&pPage->u.aDisk[i];
03378 int j;
03379 for(j=i+cellSize(pBt, pCell)-1; j>=i; j--) hit[j]++;
03380 i = SWAB16(pBt, pCell->h.iNext);
03381 }
03382 for(i=SWAB16(pBt,pPage->u.hdr.firstFree); i>0 && i<SQLITE_USABLE_SIZE; ){
03383 FreeBlk *pFBlk = (FreeBlk*)&pPage->u.aDisk[i];
03384 int j;
03385 for(j=i+SWAB16(pBt,pFBlk->iSize)-1; j>=i; j--) hit[j]++;
03386 i = SWAB16(pBt,pFBlk->iNext);
03387 }
03388 for(i=0; i<SQLITE_USABLE_SIZE; i++){
03389 if( hit[i]==0 ){
03390 sprintf(zMsg, "Unused space at byte %d of page %d", i, iPage);
03391 checkAppendMsg(pCheck, zMsg, 0);
03392 break;
03393 }else if( hit[i]>1 ){
03394 sprintf(zMsg, "Multiple uses for byte %d of page %d", i, iPage);
03395 checkAppendMsg(pCheck, zMsg, 0);
03396 break;
03397 }
03398 }
03399
03400
03401
03402 #if 0
03403 if( pParent && pParent->nCell>2 && pPage->nFree>3*SQLITE_USABLE_SIZE/4 ){
03404 sprintf(zMsg, "free space (%d) greater than max (%d)", pPage->nFree,
03405 SQLITE_USABLE_SIZE/3);
03406 checkAppendMsg(pCheck, zContext, zMsg);
03407 }
03408 #endif
03409
03410 sqlitepager_unref(pPage);
03411 return depth;
03412 }
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424 char *fileBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
03425 int i;
03426 int nRef;
03427 IntegrityCk sCheck;
03428
03429 nRef = *sqlitepager_stats(pBt->pPager);
03430 if( lockBtree(pBt)!=SQLITE_OK ){
03431 return sqliteStrDup("Unable to acquire a read lock on the database");
03432 }
03433 sCheck.pBt = pBt;
03434 sCheck.pPager = pBt->pPager;
03435 sCheck.nPage = sqlitepager_pagecount(sCheck.pPager);
03436 if( sCheck.nPage==0 ){
03437 unlockBtreeIfUnused(pBt);
03438 return 0;
03439 }
03440 sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) );
03441 sCheck.anRef[1] = 1;
03442 for(i=2; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; }
03443 sCheck.zErrMsg = 0;
03444
03445
03446
03447 checkList(&sCheck, 1, SWAB32(pBt, pBt->page1->freeList),
03448 SWAB32(pBt, pBt->page1->nFree), "Main freelist: ");
03449
03450
03451
03452 for(i=0; i<nRoot; i++){
03453 if( aRoot[i]==0 ) continue;
03454 checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: ", 0,0,0,0);
03455 }
03456
03457
03458
03459 for(i=1; i<=sCheck.nPage; i++){
03460 if( sCheck.anRef[i]==0 ){
03461 char zBuf[100];
03462 sprintf(zBuf, "Page %d is never used", i);
03463 checkAppendMsg(&sCheck, zBuf, 0);
03464 }
03465 }
03466
03467
03468
03469 unlockBtreeIfUnused(pBt);
03470 if( nRef != *sqlitepager_stats(pBt->pPager) ){
03471 char zBuf[100];
03472 sprintf(zBuf,
03473 "Outstanding page count goes from %d to %d during this analysis",
03474 nRef, *sqlitepager_stats(pBt->pPager)
03475 );
03476 checkAppendMsg(&sCheck, zBuf, 0);
03477 }
03478
03479
03480
03481 sqliteFree(sCheck.anRef);
03482 return sCheck.zErrMsg;
03483 }
03484
03485
03486
03487
03488 static const char *fileBtreeGetFilename(Btree *pBt){
03489 assert( pBt->pPager!=0 );
03490 return sqlitepager_filename(pBt->pPager);
03491 }
03492
03493
03494
03495
03496
03497
03498
03499
03500 static int fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
03501 int rc = SQLITE_OK;
03502 Pgno i, nPage, nToPage;
03503
03504 if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR;
03505 if( pBtTo->needSwab!=pBtFrom->needSwab ) return SQLITE_ERROR;
03506 if( pBtTo->pCursor ) return SQLITE_BUSY;
03507 memcpy(pBtTo->page1, pBtFrom->page1, SQLITE_USABLE_SIZE);
03508 rc = sqlitepager_overwrite(pBtTo->pPager, 1, pBtFrom->page1);
03509 nToPage = sqlitepager_pagecount(pBtTo->pPager);
03510 nPage = sqlitepager_pagecount(pBtFrom->pPager);
03511 for(i=2; rc==SQLITE_OK && i<=nPage; i++){
03512 void *pPage;
03513 rc = sqlitepager_get(pBtFrom->pPager, i, &pPage);
03514 if( rc ) break;
03515 rc = sqlitepager_overwrite(pBtTo->pPager, i, pPage);
03516 if( rc ) break;
03517 sqlitepager_unref(pPage);
03518 }
03519 for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){
03520 void *pPage;
03521 rc = sqlitepager_get(pBtTo->pPager, i, &pPage);
03522 if( rc ) break;
03523 rc = sqlitepager_write(pPage);
03524 sqlitepager_unref(pPage);
03525 sqlitepager_dont_write(pBtTo->pPager, i);
03526 }
03527 if( !rc && nPage<nToPage ){
03528 rc = sqlitepager_truncate(pBtTo->pPager, nPage);
03529 }
03530 if( rc ){
03531 fileBtreeRollback(pBtTo);
03532 }
03533 return rc;
03534 }
03535
03536
03537
03538
03539
03540
03541
03542 static BtOps sqliteBtreeOps = {
03543 fileBtreeClose,
03544 fileBtreeSetCacheSize,
03545 fileBtreeSetSafetyLevel,
03546 fileBtreeBeginTrans,
03547 fileBtreeCommit,
03548 fileBtreeRollback,
03549 fileBtreeBeginCkpt,
03550 fileBtreeCommitCkpt,
03551 fileBtreeRollbackCkpt,
03552 fileBtreeCreateTable,
03553 fileBtreeCreateTable,
03554 fileBtreeDropTable,
03555 fileBtreeClearTable,
03556 fileBtreeCursor,
03557 fileBtreeGetMeta,
03558 fileBtreeUpdateMeta,
03559 fileBtreeIntegrityCheck,
03560 fileBtreeGetFilename,
03561 fileBtreeCopyFile,
03562 fileBtreePager,
03563 #ifdef SQLITE_TEST
03564 fileBtreePageDump,
03565 #endif
03566 };
03567 static BtCursorOps sqliteBtreeCursorOps = {
03568 fileBtreeMoveto,
03569 fileBtreeDelete,
03570 fileBtreeInsert,
03571 fileBtreeFirst,
03572 fileBtreeLast,
03573 fileBtreeNext,
03574 fileBtreePrevious,
03575 fileBtreeKeySize,
03576 fileBtreeKey,
03577 fileBtreeKeyCompare,
03578 fileBtreeDataSize,
03579 fileBtreeData,
03580 fileBtreeCloseCursor,
03581 #ifdef SQLITE_TEST
03582 fileBtreeCursorDump,
03583 #endif
03584 };