aboutsummaryrefslogtreecommitdiff
path: root/src/btree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/btree.c')
-rw-r--r--src/btree.c110
1 files changed, 59 insertions, 51 deletions
diff --git a/src/btree.c b/src/btree.c
index 4e6f6478a..036e63a01 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -350,7 +350,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
if( !pLock ){
pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock));
if( !pLock ){
- return SQLITE_NOMEM;
+ return SQLITE_NOMEM_BKPT;
}
pLock->iTable = iTable;
pLock->pBtree = p;
@@ -553,7 +553,7 @@ static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
assert( pgno<=pBt->nPage );
pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage);
if( !pBt->pHasContent ){
- rc = SQLITE_NOMEM;
+ rc = SQLITE_NOMEM_BKPT;
}
}
if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){
@@ -632,7 +632,7 @@ static int saveCursorKey(BtCursor *pCur){
sqlite3_free(pKey);
}
}else{
- rc = SQLITE_NOMEM;
+ rc = SQLITE_NOMEM_BKPT;
}
}
assert( !pCur->curIntKey || !pCur->pKey );
@@ -764,7 +764,7 @@ static int btreeMoveto(
pIdxKey = sqlite3VdbeAllocUnpackedRecord(
pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
);
- if( pIdxKey==0 ) return SQLITE_NOMEM;
+ if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 ){
sqlite3DbFree(pCur->pKeyInfo->db, pFree);
@@ -2176,7 +2176,7 @@ int sqlite3BtreeOpen(
}
p = sqlite3MallocZero(sizeof(Btree));
if( !p ){
- return SQLITE_NOMEM;
+ return SQLITE_NOMEM_BKPT;
}
p->inTrans = TRANS_NONE;
p->db = db;
@@ -2200,7 +2200,7 @@ int sqlite3BtreeOpen(
p->sharable = 1;
if( !zFullPathname ){
sqlite3_free(p);
- return SQLITE_NOMEM;
+ return SQLITE_NOMEM_BKPT;
}
if( isMemdb ){
memcpy(zFullPathname, zFilename, nFilename);
@@ -2268,7 +2268,7 @@ int sqlite3BtreeOpen(
pBt = sqlite3MallocZero( sizeof(*pBt) );
if( pBt==0 ){
- rc = SQLITE_NOMEM;
+ rc = SQLITE_NOMEM_BKPT;
goto btree_open_out;
}
rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
@@ -2337,8 +2337,7 @@ int sqlite3BtreeOpen(
if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
if( pBt->mutex==0 ){
- rc = SQLITE_NOMEM;
- db->mallocFailed = 0;
+ rc = SQLITE_NOMEM_BKPT;
goto btree_open_out;
}
}
@@ -2621,21 +2620,6 @@ int sqlite3BtreeSetPagerFlags(
#endif
/*
-** Return TRUE if the given btree is set to safety level 1. In other
-** words, return TRUE if no sync() occurs on the disk files.
-*/
-int sqlite3BtreeSyncDisabled(Btree *p){
- BtShared *pBt = p->pBt;
- int rc;
- assert( sqlite3_mutex_held(p->db->mutex) );
- sqlite3BtreeEnter(p);
- assert( pBt && pBt->pPager );
- rc = sqlite3PagerNosync(pBt->pPager);
- sqlite3BtreeLeave(p);
- return rc;
-}
-
-/*
** Change the default pages size and the number of reserved bytes per page.
** Or, if the page size has already been fixed, return SQLITE_READONLY
** without changing anything.
@@ -4049,13 +4033,13 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
** on the database already. If a write-cursor is requested, then
** the caller is assumed to have an open write transaction.
**
-** If wrFlag==0, then the cursor can only be used for reading.
-** If wrFlag==1, then the cursor can be used for reading or for
-** writing if other conditions for writing are also met. These
-** are the conditions that must be met in order for writing to
-** be allowed:
+** If the BTREE_WRCSR bit of wrFlag is clear, then the cursor can only
+** be used for reading. If the BTREE_WRCSR bit is set, then the cursor
+** can be used for reading or for writing if other conditions for writing
+** are also met. These are the conditions that must be met in order
+** for writing to be allowed:
**
-** 1: The cursor must have been opened with wrFlag==1
+** 1: The cursor must have been opened with wrFlag containing BTREE_WRCSR
**
** 2: Other database connections that share the same pager cache
** but which are not in the READ_UNCOMMITTED state may not have
@@ -4067,6 +4051,16 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
**
** 4: There must be an active transaction.
**
+** The BTREE_FORDELETE bit of wrFlag may optionally be set if BTREE_WRCSR
+** is set. If FORDELETE is set, that is a hint to the implementation that
+** this cursor will only be used to seek to and delete entries of an index
+** as part of a larger DELETE statement. The FORDELETE hint is not used by
+** this implementation. But in a hypothetical alternative storage engine
+** in which index entries are automatically deleted when corresponding table
+** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE
+** operations on this cursor can be no-ops and all READ operations can
+** return a null row (2-bytes: 0x01 0x00).
+**
** No checking is done to make sure that page iTable really is the
** root page of a b-tree. If it is not, then the cursor acquired
** will not work correctly.
@@ -4105,7 +4099,7 @@ static int btreeCursor(
if( wrFlag ){
allocateTempSpace(pBt);
- if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM;
+ if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT;
}
if( iTable==1 && btreePagecount(pBt)==0 ){
assert( wrFlag==0 );
@@ -4503,7 +4497,7 @@ static int accessPayload(
pCur->aOverflow, nOvfl*2*sizeof(Pgno)
);
if( aNew==0 ){
- rc = SQLITE_NOMEM;
+ rc = SQLITE_NOMEM_BKPT;
}else{
pCur->nOvflAlloc = nOvfl*2;
pCur->aOverflow = aNew;
@@ -5208,7 +5202,7 @@ int sqlite3BtreeMovetoUnpacked(
}
pCellKey = sqlite3Malloc( nCell+18 );
if( pCellKey==0 ){
- rc = SQLITE_NOMEM;
+ rc = SQLITE_NOMEM_BKPT;
goto moveto_finish;
}
pCur->aiIdx[pCur->iPage] = (u16)idx;
@@ -6139,7 +6133,7 @@ static int fillInCell(
{
CellInfo info;
pPage->xParseCell(pPage, pCell, &info);
- assert( nHeader=(int)(info.pPayload - pCell) );
+ assert( nHeader==(int)(info.pPayload - pCell) );
assert( info.nKey==nKey );
assert( *pnSize == info.nSize );
assert( spaceLeft == info.nLocal );
@@ -7027,7 +7021,7 @@ static int balance_nonroot(
assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx );
if( !aOvflSpace ){
- return SQLITE_NOMEM;
+ return SQLITE_NOMEM_BKPT;
}
/* Find the sibling pages to balance. Also locate the cells in pParent
@@ -7127,7 +7121,7 @@ static int balance_nonroot(
assert( szScratch<=6*(int)pBt->pageSize );
b.apCell = sqlite3ScratchMalloc( szScratch );
if( b.apCell==0 ){
- rc = SQLITE_NOMEM;
+ rc = SQLITE_NOMEM_BKPT;
goto balance_cleanup;
}
b.szCell = (u16*)&b.apCell[nMaxCells];
@@ -7798,8 +7792,8 @@ static int balance(BtCursor *pCur){
u8 aBalanceQuickSpace[13];
u8 *pFree = 0;
- TESTONLY( int balance_quick_called = 0 );
- TESTONLY( int balance_deeper_called = 0 );
+ VVA_ONLY( int balance_quick_called = 0 );
+ VVA_ONLY( int balance_deeper_called = 0 );
do {
int iPage = pCur->iPage;
@@ -7812,7 +7806,8 @@ static int balance(BtCursor *pCur){
** and copy the current contents of the root-page to it. The
** next iteration of the do-loop will balance the child page.
*/
- assert( (balance_deeper_called++)==0 );
+ assert( balance_deeper_called==0 );
+ VVA_ONLY( balance_deeper_called++ );
rc = balance_deeper(pPage, &pCur->apPage[1]);
if( rc==SQLITE_OK ){
pCur->iPage = 1;
@@ -7851,7 +7846,8 @@ static int balance(BtCursor *pCur){
** function. If this were not verified, a subtle bug involving reuse
** of the aBalanceQuickSpace[] might sneak in.
*/
- assert( (balance_quick_called++)==0 );
+ assert( balance_quick_called==0 );
+ VVA_ONLY( balance_quick_called++ );
rc = balance_quick(pParent, pPage, aBalanceQuickSpace);
}else
#endif
@@ -8082,13 +8078,21 @@ end_insert:
/*
** Delete the entry that the cursor is pointing to.
**
-** If the second parameter is zero, then the cursor is left pointing at an
-** arbitrary location after the delete. If it is non-zero, then the cursor
-** is left in a state such that the next call to BtreeNext() or BtreePrev()
-** moves it to the same row as it would if the call to BtreeDelete() had
-** been omitted.
-*/
-int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
+** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then
+** the cursor is left pointing at an arbitrary location after the delete.
+** But if that bit is set, then the cursor is left in a state such that
+** the next call to BtreeNext() or BtreePrev() moves it to the same row
+** as it would have been on if the call to BtreeDelete() had been omitted.
+**
+** The BTREE_AUXDELETE bit of flags indicates that is one of several deletes
+** associated with a single table entry and its indexes. Only one of those
+** deletes is considered the "primary" delete. The primary delete occurs
+** on a cursor that is not a BTREE_FORDELETE cursor. All but one delete
+** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag.
+** The BTREE_AUXDELETE bit is a hint that is not used by this implementation,
+** but which might be used by alternative storage engines.
+*/
+int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
Btree *p = pCur->pBtree;
BtShared *pBt = p->pBt;
int rc; /* Return code */
@@ -8098,6 +8102,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
int iCellDepth; /* Depth of node containing pCell */
u16 szCell; /* Size of the cell being deleted */
int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
+ u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */
assert( cursorOwnsBtShared(pCur) );
assert( pBt->inTransaction==TRANS_WRITE );
@@ -8107,6 +8112,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
assert( pCur->eState==CURSOR_VALID );
+ assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
iCellDepth = pCur->iPage;
iCellIdx = pCur->aiIdx[iCellDepth];
@@ -8219,7 +8225,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
if( rc==SQLITE_OK ){
if( bSkipnext ){
assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) );
- assert( pPage==pCur->apPage[pCur->iPage] );
+ assert( pPage==pCur->apPage[pCur->iPage] || CORRUPT_DB );
assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
pCur->eState = CURSOR_SKIPNEXT;
if( iCellIdx>=pPage->nCell ){
@@ -8805,9 +8811,9 @@ static void checkAppendMsg(
sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1);
}
if( pCheck->zPfx ){
- sqlite3XPrintf(&pCheck->errMsg, 0, pCheck->zPfx, pCheck->v1, pCheck->v2);
+ sqlite3XPrintf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2);
}
- sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
+ sqlite3VXPrintf(&pCheck->errMsg, zFormat, ap);
va_end(ap);
if( pCheck->errMsg.accError==STRACCUM_NOMEM ){
pCheck->mallocFailed = 1;
@@ -9308,7 +9314,8 @@ char *sqlite3BtreeIntegrityCheck(
sqlite3BtreeEnter(p);
assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
- assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 );
+ VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) );
+ assert( nRef>=0 );
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
sCheck.nPage = btreePagecount(sCheck.pBt);
@@ -9321,6 +9328,7 @@ char *sqlite3BtreeIntegrityCheck(
sCheck.aPgRef = 0;
sCheck.heap = 0;
sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
+ sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL;
if( sCheck.nPage==0 ){
goto integrity_ck_cleanup;
}