mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Make cellSizePtr() a method on the MemPage object, with alternative
implementations depending on the page type. This results is a small performance improvement and size reduction. FossilOrigin-Name: 02f7e9d7d7b93d0b6bbd6cc0d0359b3b741b9931
This commit is contained in:
73
src/btree.c
73
src/btree.c
@@ -1065,6 +1065,11 @@ static void btreeParseCell(
|
||||
** data area of the btree-page. The return number includes the cell
|
||||
** data header and the local payload, but not any overflow page or
|
||||
** the space used by the cell pointer.
|
||||
**
|
||||
** The first implementation, cellSizePtr(), handles pages that contain
|
||||
** payload, which is to say all index pages and left table pages. The
|
||||
** second cellSizePtrNoPayload() implemention is a high-speed version
|
||||
** for pages that contain no payload - internal table pages.
|
||||
*/
|
||||
static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
|
||||
u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of pCell */
|
||||
@@ -1080,12 +1085,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
|
||||
btreeParseCellPtr(pPage, pCell, &debuginfo);
|
||||
#endif
|
||||
|
||||
if( pPage->noPayload ){
|
||||
pEnd = &pIter[9];
|
||||
while( (*pIter++)&0x80 && pIter<pEnd );
|
||||
assert( pPage->childPtrSize==4 );
|
||||
return (u16)(pIter - pCell);
|
||||
}
|
||||
assert( pPage->noPayload==0 );
|
||||
nSize = *pIter;
|
||||
if( nSize>=0x80 ){
|
||||
pEnd = &pIter[9];
|
||||
@@ -1120,12 +1120,32 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
|
||||
assert( nSize==debuginfo.nSize || CORRUPT_DB );
|
||||
return (u16)nSize;
|
||||
}
|
||||
static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){
|
||||
u8 *pIter = pCell + 4; /* For looping over bytes of pCell */
|
||||
u8 *pEnd; /* End mark for a varint */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* The value returned by this function should always be the same as
|
||||
** the (CellInfo.nSize) value found by doing a full parse of the
|
||||
** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of
|
||||
** this function verifies that this invariant is not violated. */
|
||||
CellInfo debuginfo;
|
||||
btreeParseCellPtr(pPage, pCell, &debuginfo);
|
||||
#endif
|
||||
|
||||
assert( pPage->childPtrSize==4 );
|
||||
pEnd = pIter + 9;
|
||||
while( (*pIter++)&0x80 && pIter<pEnd );
|
||||
assert( debuginfo.nSize==(u16)(pIter - pCell) || CORRUPT_DB );
|
||||
return (u16)(pIter - pCell);
|
||||
}
|
||||
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* This variation on cellSizePtr() is used inside of assert() statements
|
||||
** only. */
|
||||
static u16 cellSize(MemPage *pPage, int iCell){
|
||||
return cellSizePtr(pPage, findCell(pPage, iCell));
|
||||
return pPage->xCellSize(pPage, findCell(pPage, iCell));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1203,7 +1223,7 @@ static int defragmentPage(MemPage *pPage){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
assert( pc>=iCellFirst && pc<=iCellLast );
|
||||
size = cellSizePtr(pPage, &src[pc]);
|
||||
size = pPage->xCellSize(pPage, &src[pc]);
|
||||
cbrk -= size;
|
||||
if( cbrk<iCellFirst || pc+size>usableSize ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
@@ -1507,6 +1527,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){
|
||||
pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 );
|
||||
flagByte &= ~PTF_LEAF;
|
||||
pPage->childPtrSize = 4-4*pPage->leaf;
|
||||
pPage->xCellSize = cellSizePtr;
|
||||
pBt = pPage->pBt;
|
||||
if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
|
||||
/* EVIDENCE-OF: R-03640-13415 A value of 5 means the page is an interior
|
||||
@@ -1516,8 +1537,14 @@ static int decodeFlags(MemPage *pPage, int flagByte){
|
||||
** table b-tree page. */
|
||||
assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 );
|
||||
pPage->intKey = 1;
|
||||
pPage->intKeyLeaf = pPage->leaf;
|
||||
pPage->noPayload = !pPage->leaf;
|
||||
if( pPage->leaf ){
|
||||
pPage->intKeyLeaf = 1;
|
||||
pPage->noPayload = 0;
|
||||
}else{
|
||||
pPage->intKeyLeaf = 0;
|
||||
pPage->noPayload = 1;
|
||||
pPage->xCellSize = cellSizePtrNoPayload;
|
||||
}
|
||||
pPage->maxLocal = pBt->maxLeaf;
|
||||
pPage->minLocal = pBt->minLeaf;
|
||||
}else if( flagByte==PTF_ZERODATA ){
|
||||
@@ -1624,7 +1651,7 @@ static int btreeInitPage(MemPage *pPage){
|
||||
if( pc<iCellFirst || pc>iCellLast ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
sz = cellSizePtr(pPage, &data[pc]);
|
||||
sz = pPage->xCellSize(pPage, &data[pc]);
|
||||
testcase( pc+sz==usableSize );
|
||||
if( pc+sz>usableSize ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
@@ -6096,7 +6123,7 @@ static void insertCell(
|
||||
** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
|
||||
** might be less than 8 (leaf-size + pointer) on the interior node. Hence
|
||||
** the term after the || in the following assert(). */
|
||||
assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) );
|
||||
assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );
|
||||
if( pPage->nOverflow || sz+2>pPage->nFree ){
|
||||
if( pTemp ){
|
||||
memcpy(pTemp, pCell, sz);
|
||||
@@ -6187,8 +6214,8 @@ static void rebuildPage(
|
||||
memcpy(pData, pCell, szCell[i]);
|
||||
put2byte(pCellptr, (pData - aData));
|
||||
pCellptr += 2;
|
||||
assert( szCell[i]==cellSizePtr(pPg, pCell) || CORRUPT_DB );
|
||||
testcase( szCell[i]==cellSizePtr(pPg,pCell) );
|
||||
assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
|
||||
testcase( szCell[i]==pPg->xCellSize(pPg,pCell) );
|
||||
}
|
||||
|
||||
/* The pPg->nFree field is now set incorrectly. The caller will fix it. */
|
||||
@@ -6478,7 +6505,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
|
||||
|
||||
u8 *pOut = &pSpace[4];
|
||||
u8 *pCell = pPage->apOvfl[0];
|
||||
u16 szCell = cellSizePtr(pPage, pCell);
|
||||
u16 szCell = pPage->xCellSize(pPage, pCell);
|
||||
u8 *pStop;
|
||||
|
||||
assert( sqlite3PagerIswriteable(pNew->pDbPage) );
|
||||
@@ -6784,12 +6811,12 @@ static int balance_nonroot(
|
||||
if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){
|
||||
apDiv[i] = pParent->apOvfl[0];
|
||||
pgno = get4byte(apDiv[i]);
|
||||
szNew[i] = cellSizePtr(pParent, apDiv[i]);
|
||||
szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
|
||||
pParent->nOverflow = 0;
|
||||
}else{
|
||||
apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow);
|
||||
pgno = get4byte(apDiv[i]);
|
||||
szNew[i] = cellSizePtr(pParent, apDiv[i]);
|
||||
szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
|
||||
|
||||
/* Drop the cell from the parent page. apDiv[i] still points to
|
||||
** the cell within the parent, even though it has been dropped.
|
||||
@@ -6879,7 +6906,7 @@ static int balance_nonroot(
|
||||
for(j=0; j<limit; j++){
|
||||
assert( nCell<nMaxCells );
|
||||
apCell[nCell] = findOverflowCell(pOld, j);
|
||||
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
|
||||
szCell[nCell] = pOld->xCellSize(pOld, apCell[nCell]);
|
||||
nCell++;
|
||||
}
|
||||
}else{
|
||||
@@ -6889,7 +6916,7 @@ static int balance_nonroot(
|
||||
for(j=0; j<limit; j++){
|
||||
assert( nCell<nMaxCells );
|
||||
apCell[nCell] = findCellv2(aData, maskPage, cellOffset, j);
|
||||
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
|
||||
szCell[nCell] = pOld->xCellSize(pOld, apCell[nCell]);
|
||||
nCell++;
|
||||
}
|
||||
}
|
||||
@@ -7207,7 +7234,7 @@ static int balance_nonroot(
|
||||
*/
|
||||
if( szCell[j]==4 ){
|
||||
assert(leafCorrection==4);
|
||||
sz = cellSizePtr(pParent, pCell);
|
||||
sz = pParent->xCellSize(pParent, pCell);
|
||||
}
|
||||
}
|
||||
iOvflSpace += sz;
|
||||
@@ -7652,7 +7679,7 @@ int sqlite3BtreeInsert(
|
||||
assert( newCell!=0 );
|
||||
rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew);
|
||||
if( rc ) goto end_insert;
|
||||
assert( szNew==cellSizePtr(pPage, newCell) );
|
||||
assert( szNew==pPage->xCellSize(pPage, newCell) );
|
||||
assert( szNew <= MX_CELL_SIZE(pBt) );
|
||||
idx = pCur->aiIdx[pCur->iPage];
|
||||
if( loc==0 ){
|
||||
@@ -7794,7 +7821,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
|
||||
|
||||
pCell = findCell(pLeaf, pLeaf->nCell-1);
|
||||
if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT;
|
||||
nCell = cellSizePtr(pLeaf, pCell);
|
||||
nCell = pLeaf->xCellSize(pLeaf, pCell);
|
||||
assert( MX_CELL_SIZE(pBt) >= nCell );
|
||||
pTmp = pBt->pTmpSpace;
|
||||
assert( pTmp!=0 );
|
||||
@@ -8806,7 +8833,7 @@ static int checkTreePage(
|
||||
int pc = get2byte(&data[cellStart+i*2]);
|
||||
u32 size = 65536;
|
||||
if( pc<=usableSize-4 ){
|
||||
size = cellSizePtr(pPage, &data[pc]);
|
||||
size = pPage->xCellSize(pPage, &data[pc]);
|
||||
}
|
||||
if( (int)(pc+size-1)>=usableSize ){
|
||||
pCheck->zPfx = 0;
|
||||
|
Reference in New Issue
Block a user