diff options
Diffstat (limited to 'ext/sqlite/libsqlite/src/btree.c')
-rw-r--r-- | ext/sqlite/libsqlite/src/btree.c | 86 |
1 files changed, 45 insertions, 41 deletions
diff --git a/ext/sqlite/libsqlite/src/btree.c b/ext/sqlite/libsqlite/src/btree.c index 1133b1a353..a367092501 100644 --- a/ext/sqlite/libsqlite/src/btree.c +++ b/ext/sqlite/libsqlite/src/btree.c @@ -210,13 +210,13 @@ struct CellHdr { ** The maximum number of database entries that can be held in a single ** page of the database. */ -#define MX_CELL ((SQLITE_PAGE_SIZE-sizeof(PageHdr))/MIN_CELL_SIZE) +#define MX_CELL ((SQLITE_USABLE_SIZE-sizeof(PageHdr))/MIN_CELL_SIZE) /* ** The amount of usable space on a single page of the BTree. This is the ** page size minus the overhead of the page header. */ -#define USABLE_SPACE (SQLITE_PAGE_SIZE - sizeof(PageHdr)) +#define USABLE_SPACE (SQLITE_USABLE_SIZE - sizeof(PageHdr)) /* ** The maximum amount of payload (in bytes) that can be stored locally for @@ -261,7 +261,7 @@ struct FreeBlk { /* ** The number of bytes of payload that will fit on a single overflow page. */ -#define OVERFLOW_SIZE (SQLITE_PAGE_SIZE-sizeof(Pgno)) +#define OVERFLOW_SIZE (SQLITE_USABLE_SIZE-sizeof(Pgno)) /* ** When the key and data for a single entry in the BTree will not fit in @@ -319,7 +319,7 @@ struct FreelistInfo { ** The pageDestructor() routine handles that chore. */ struct MemPage { - union { + union u_page_data { char aDisk[SQLITE_PAGE_SIZE]; /* Page data stored on disk */ PageHdr hdr; /* Overlay page header */ } u; @@ -338,7 +338,7 @@ struct MemPage { ** to the end. EXTRA_SIZE is the number of bytes of space needed to hold ** that extra information. */ -#define EXTRA_SIZE (sizeof(MemPage)-SQLITE_PAGE_SIZE) +#define EXTRA_SIZE (sizeof(MemPage)-sizeof(union u_page_data)) /* ** Everything we need to know about an open database @@ -421,7 +421,7 @@ static int cellSize(Btree *pBt, Cell *pCell){ static void defragmentPage(Btree *pBt, MemPage *pPage){ int pc, i, n; FreeBlk *pFBlk; - char newPage[SQLITE_PAGE_SIZE]; + char newPage[SQLITE_USABLE_SIZE]; assert( sqlitepager_iswriteable(pPage) ); assert( pPage->isInit ); @@ -434,7 +434,7 @@ static void defragmentPage(Btree *pBt, MemPage *pPage){ /* This routine should never be called on an overfull page. The ** following asserts verify that constraint. */ assert( Addr(pCell) > Addr(pPage) ); - assert( Addr(pCell) < Addr(pPage) + SQLITE_PAGE_SIZE ); + assert( Addr(pCell) < Addr(pPage) + SQLITE_USABLE_SIZE ); n = cellSize(pBt, pCell); pCell->h.iNext = SWAB16(pBt, pc + n); @@ -442,16 +442,16 @@ static void defragmentPage(Btree *pBt, MemPage *pPage){ pPage->apCell[i] = (Cell*)&pPage->u.aDisk[pc]; pc += n; } - assert( pPage->nFree==SQLITE_PAGE_SIZE-pc ); + assert( pPage->nFree==SQLITE_USABLE_SIZE-pc ); memcpy(pPage->u.aDisk, newPage, pc); if( pPage->nCell>0 ){ pPage->apCell[pPage->nCell-1]->h.iNext = 0; } pFBlk = (FreeBlk*)&pPage->u.aDisk[pc]; - pFBlk->iSize = SWAB16(pBt, SQLITE_PAGE_SIZE - pc); + pFBlk->iSize = SWAB16(pBt, SQLITE_USABLE_SIZE - pc); pFBlk->iNext = 0; pPage->u.hdr.firstFree = SWAB16(pBt, pc); - memset(&pFBlk[1], 0, SQLITE_PAGE_SIZE - pc - sizeof(FreeBlk)); + memset(&pFBlk[1], 0, SQLITE_USABLE_SIZE - pc - sizeof(FreeBlk)); } /* @@ -483,7 +483,7 @@ static int allocateSpace(Btree *pBt, MemPage *pPage, int nByte){ pIdx = &pPage->u.hdr.firstFree; p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)]; while( (iSize = SWAB16(pBt, p->iSize))<nByte ){ - assert( cnt++ < SQLITE_PAGE_SIZE/4 ); + assert( cnt++ < SQLITE_USABLE_SIZE/4 ); if( p->iNext==0 ){ defragmentPage(pBt, pPage); pIdx = &pPage->u.hdr.firstFree; @@ -598,12 +598,12 @@ static int initPage(Bt *pBt, MemPage *pPage, Pgno pgnoThis, MemPage *pParent){ freeSpace = USABLE_SPACE; idx = SWAB16(pBt, pPage->u.hdr.firstCell); while( idx!=0 ){ - if( idx>SQLITE_PAGE_SIZE-MIN_CELL_SIZE ) goto page_format_error; + if( idx>SQLITE_USABLE_SIZE-MIN_CELL_SIZE ) goto page_format_error; if( idx<sizeof(PageHdr) ) goto page_format_error; if( idx!=ROUNDUP(idx) ) goto page_format_error; pCell = (Cell*)&pPage->u.aDisk[idx]; sz = cellSize(pBt, pCell); - if( idx+sz > SQLITE_PAGE_SIZE ) goto page_format_error; + if( idx+sz > SQLITE_USABLE_SIZE ) goto page_format_error; freeSpace -= sz; pPage->apCell[pPage->nCell++] = pCell; idx = SWAB16(pBt, pCell->h.iNext); @@ -612,7 +612,7 @@ static int initPage(Bt *pBt, MemPage *pPage, Pgno pgnoThis, MemPage *pParent){ idx = SWAB16(pBt, pPage->u.hdr.firstFree); while( idx!=0 ){ int iNext; - if( idx>SQLITE_PAGE_SIZE-sizeof(FreeBlk) ) goto page_format_error; + if( idx>SQLITE_USABLE_SIZE-sizeof(FreeBlk) ) goto page_format_error; if( idx<sizeof(PageHdr) ) goto page_format_error; pFBlk = (FreeBlk*)&pPage->u.aDisk[idx]; pPage->nFree += SWAB16(pBt, pFBlk->iSize); @@ -640,13 +640,13 @@ static void zeroPage(Btree *pBt, MemPage *pPage){ PageHdr *pHdr; FreeBlk *pFBlk; assert( sqlitepager_iswriteable(pPage) ); - memset(pPage, 0, SQLITE_PAGE_SIZE); + memset(pPage, 0, SQLITE_USABLE_SIZE); pHdr = &pPage->u.hdr; pHdr->firstCell = 0; pHdr->firstFree = SWAB16(pBt, sizeof(*pHdr)); pFBlk = (FreeBlk*)&pHdr[1]; pFBlk->iNext = 0; - pPage->nFree = SQLITE_PAGE_SIZE - sizeof(*pHdr); + pPage->nFree = SQLITE_USABLE_SIZE - sizeof(*pHdr); pFBlk->iSize = SWAB16(pBt, pPage->nFree); pPage->nCell = 0; pPage->isOverfull = 0; @@ -697,7 +697,7 @@ int sqliteBtreeOpen( assert( sizeof(PageHdr)==8 ); assert( sizeof(CellHdr)==12 ); assert( sizeof(FreeBlk)==4 ); - assert( sizeof(OverflowPage)==SQLITE_PAGE_SIZE ); + assert( sizeof(OverflowPage)==SQLITE_USABLE_SIZE ); assert( sizeof(FreelistInfo)==OVERFLOW_SIZE ); assert( sizeof(ptr)==sizeof(char*) ); assert( sizeof(uptr)==sizeof(ptr) ); @@ -793,7 +793,7 @@ static int lockBtree(Btree *pBt){ PageOne *pP1 = pBt->page1; if( strcmp(pP1->zMagic,zMagicHeader)!=0 || (pP1->iMagic!=MAGIC && swab32(pP1->iMagic)!=MAGIC) ){ - rc = SQLITE_CORRUPT; + rc = SQLITE_NOTADB; goto page1_init_failed; } pBt->needSwab = pP1->iMagic!=MAGIC; @@ -1031,10 +1031,15 @@ static int fileBtreeRollbackCkpt(Btree *pBt){ ** root page of a b-tree. If it is not, then the cursor acquired ** will not work correctly. */ -static int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){ +static +int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){ int rc; BtCursor *pCur, *pRing; + if( pBt->readOnly && wrFlag ){ + *ppCur = 0; + return SQLITE_READONLY; + } if( pBt->page1==0 ){ rc = lockBtree(pBt); if( rc!=SQLITE_OK ){ @@ -2082,7 +2087,7 @@ static void relinkCellList(Btree *pBt, MemPage *pPage){ pIdx = &pPage->u.hdr.firstCell; for(i=0; i<pPage->nCell; i++){ int idx = Addr(pPage->apCell[i]) - Addr(pPage); - assert( idx>0 && idx<SQLITE_PAGE_SIZE ); + assert( idx>0 && idx<SQLITE_USABLE_SIZE ); *pIdx = SWAB16(pBt, idx); pIdx = &pPage->apCell[i]->h.iNext; } @@ -2098,7 +2103,7 @@ static void relinkCellList(Btree *pBt, MemPage *pPage){ static void copyPage(MemPage *pTo, MemPage *pFrom){ uptr from, to; int i; - memcpy(pTo->u.aDisk, pFrom->u.aDisk, SQLITE_PAGE_SIZE); + memcpy(pTo->u.aDisk, pFrom->u.aDisk, SQLITE_USABLE_SIZE); pTo->pParent = 0; pTo->isInit = 1; pTo->nCell = pFrom->nCell; @@ -2108,7 +2113,7 @@ static void copyPage(MemPage *pTo, MemPage *pFrom){ from = Addr(pFrom); for(i=0; i<pTo->nCell; i++){ uptr x = Addr(pFrom->apCell[i]); - if( x>from && x<from+SQLITE_PAGE_SIZE ){ + if( x>from && x<from+SQLITE_USABLE_SIZE ){ *((uptr*)&pTo->apCell[i]) = x + to - from; }else{ pTo->apCell[i] = pFrom->apCell[i]; @@ -2203,7 +2208,7 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){ ** underfull. */ assert( sqlitepager_iswriteable(pPage) ); - if( !pPage->isOverfull && pPage->nFree<SQLITE_PAGE_SIZE/2 + if( !pPage->isOverfull && pPage->nFree<SQLITE_USABLE_SIZE/2 && pPage->nCell>=2){ relinkCellList(pBt, pPage); return SQLITE_OK; @@ -2229,7 +2234,7 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){ pgnoChild = SWAB32(pBt, pPage->u.hdr.rightChild); rc = sqlitepager_get(pBt->pPager, pgnoChild, (void**)&pChild); if( rc ) return rc; - memcpy(pPage, pChild, SQLITE_PAGE_SIZE); + memcpy(pPage, pChild, SQLITE_USABLE_SIZE); pPage->isInit = 0; rc = initPage(pBt, pPage, sqlitepager_pagenumber(pPage), 0); assert( rc==SQLITE_OK ); @@ -2724,7 +2729,8 @@ static int fileBtreeDelete(BtCursor *pCur){ getTempCursor(pCur, &leafCur); rc = fileBtreeNext(&leafCur, ¬Used); if( rc!=SQLITE_OK ){ - return SQLITE_CORRUPT; + if( rc!=SQLITE_NOMEM ) rc = SQLITE_CORRUPT; + return rc; } rc = sqlitepager_write(leafCur.pPage); if( rc ) return rc; @@ -2907,7 +2913,7 @@ static int copyCell(Btree *pBtFrom, BTree *pBtTo, Cell *pCell){ if( rc==SQLITE_OK ){ rc = sqlitepager_write(pNew); if( rc==SQLITE_OK ){ - memcpy(pNew, pOvfl, SQLITE_PAGE_SIZE); + memcpy(pNew, pOvfl, SQLITE_USABLE_SIZE); *pPrev = SWAB32(pBtTo, new); if( pPrevPg ){ sqlitepager_unref(pPrevPg); @@ -2950,7 +2956,7 @@ static int copyDatabasePage( rc = sqlitepager_write(pPage); } if( rc==SQLITE_OK ){ - memcpy(pPage, pPageFrom, SQLITE_PAGE_SIZE); + memcpy(pPage, pPageFrom, SQLITE_USABLE_SIZE); idx = SWAB16(pBt, pPage->u.hdr.firstCell); while( idx>0 ){ pCell = (Cell*)&pPage->u.aDisk[idx]; @@ -3040,7 +3046,7 @@ static int fileBtreePageDump(Btree *pBt, int pgno, int recursive){ if( recursive ) printf("PAGE %d:\n", pgno); i = 0; idx = SWAB16(pBt, pPage->u.hdr.firstCell); - while( idx>0 && idx<=SQLITE_PAGE_SIZE-MIN_CELL_SIZE ){ + while( idx>0 && idx<=SQLITE_USABLE_SIZE-MIN_CELL_SIZE ){ Cell *pCell = (Cell*)&pPage->u.aDisk[idx]; int sz = cellSize(pBt, pCell); sprintf(range,"%d..%d", idx, idx+sz-1); @@ -3070,7 +3076,7 @@ static int fileBtreePageDump(Btree *pBt, int pgno, int recursive){ nFree = 0; i = 0; idx = SWAB16(pBt, pPage->u.hdr.firstFree); - while( idx>0 && idx<SQLITE_PAGE_SIZE ){ + while( idx>0 && idx<SQLITE_USABLE_SIZE ){ FreeBlk *p = (FreeBlk*)&pPage->u.aDisk[idx]; sprintf(range,"%d..%d", idx, idx+p->iSize-1); nFree += SWAB16(pBt, p->iSize); @@ -3084,7 +3090,7 @@ static int fileBtreePageDump(Btree *pBt, int pgno, int recursive){ } if( recursive && pPage->u.hdr.rightChild!=0 ){ idx = SWAB16(pBt, pPage->u.hdr.firstCell); - while( idx>0 && idx<SQLITE_PAGE_SIZE-MIN_CELL_SIZE ){ + while( idx>0 && idx<SQLITE_USABLE_SIZE-MIN_CELL_SIZE ){ Cell *pCell = (Cell*)&pPage->u.aDisk[idx]; fileBtreePageDump(pBt, SWAB32(pBt, pCell->h.leftChild), 1); idx = SWAB16(pBt, pCell->h.iNext); @@ -3129,7 +3135,7 @@ static int fileBtreeCursorDump(BtCursor *pCur, int *aResult){ aResult[4] = pPage->nFree; cnt = 0; idx = SWAB16(pBt, pPage->u.hdr.firstFree); - while( idx>0 && idx<SQLITE_PAGE_SIZE ){ + while( idx>0 && idx<SQLITE_USABLE_SIZE ){ cnt++; idx = SWAB16(pBt, ((FreeBlk*)&pPage->u.aDisk[idx])->iNext); } @@ -3139,7 +3145,6 @@ static int fileBtreeCursorDump(BtCursor *pCur, int *aResult){ } #endif -#ifdef SQLITE_TEST /* ** Return the pager associated with a BTree. This routine is used for ** testing and debugging only. @@ -3147,7 +3152,6 @@ static int fileBtreeCursorDump(BtCursor *pCur, int *aResult){ static Pager *fileBtreePager(Btree *pBt){ return pBt->pPager; } -#endif /* ** This structure is passed around through all the sanity checking routines @@ -3293,7 +3297,7 @@ static int checkTreePage( Btree *pBt; char zMsg[100]; char zContext[100]; - char hit[SQLITE_PAGE_SIZE]; + char hit[SQLITE_USABLE_SIZE]; /* Check that the page exists */ @@ -3369,19 +3373,19 @@ static int checkTreePage( */ memset(hit, 0, sizeof(hit)); memset(hit, 1, sizeof(PageHdr)); - for(i=SWAB16(pBt, pPage->u.hdr.firstCell); i>0 && i<SQLITE_PAGE_SIZE; ){ + for(i=SWAB16(pBt, pPage->u.hdr.firstCell); i>0 && i<SQLITE_USABLE_SIZE; ){ Cell *pCell = (Cell*)&pPage->u.aDisk[i]; int j; for(j=i+cellSize(pBt, pCell)-1; j>=i; j--) hit[j]++; i = SWAB16(pBt, pCell->h.iNext); } - for(i=SWAB16(pBt,pPage->u.hdr.firstFree); i>0 && i<SQLITE_PAGE_SIZE; ){ + for(i=SWAB16(pBt,pPage->u.hdr.firstFree); i>0 && i<SQLITE_USABLE_SIZE; ){ FreeBlk *pFBlk = (FreeBlk*)&pPage->u.aDisk[i]; int j; for(j=i+SWAB16(pBt,pFBlk->iSize)-1; j>=i; j--) hit[j]++; i = SWAB16(pBt,pFBlk->iNext); } - for(i=0; i<SQLITE_PAGE_SIZE; i++){ + for(i=0; i<SQLITE_USABLE_SIZE; i++){ if( hit[i]==0 ){ sprintf(zMsg, "Unused space at byte %d of page %d", i, iPage); checkAppendMsg(pCheck, zMsg, 0); @@ -3396,9 +3400,9 @@ static int checkTreePage( /* Check that free space is kept to a minimum */ #if 0 - if( pParent && pParent->nCell>2 && pPage->nFree>3*SQLITE_PAGE_SIZE/4 ){ + if( pParent && pParent->nCell>2 && pPage->nFree>3*SQLITE_USABLE_SIZE/4 ){ sprintf(zMsg, "free space (%d) greater than max (%d)", pPage->nFree, - SQLITE_PAGE_SIZE/3); + SQLITE_USABLE_SIZE/3); checkAppendMsg(pCheck, zContext, zMsg); } #endif @@ -3500,7 +3504,7 @@ static int fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR; if( pBtTo->needSwab!=pBtFrom->needSwab ) return SQLITE_ERROR; if( pBtTo->pCursor ) return SQLITE_BUSY; - memcpy(pBtTo->page1, pBtFrom->page1, SQLITE_PAGE_SIZE); + memcpy(pBtTo->page1, pBtFrom->page1, SQLITE_USABLE_SIZE); rc = sqlitepager_overwrite(pBtTo->pPager, 1, pBtFrom->page1); nToPage = sqlitepager_pagecount(pBtTo->pPager); nPage = sqlitepager_pagecount(pBtFrom->pPager); @@ -3555,9 +3559,9 @@ static BtOps sqliteBtreeOps = { fileBtreeIntegrityCheck, fileBtreeGetFilename, fileBtreeCopyFile, + fileBtreePager, #ifdef SQLITE_TEST fileBtreePageDump, - fileBtreePager #endif }; static BtCursorOps sqliteBtreeCursorOps = { |