Further simplifications to btree.c, especially the sqlite3BtreeKey() and
sqlite3BtreeData() functions. New assert() statements added to verify that these routines are called correctly. (CVS 6917) FossilOrigin-Name: 96cfd079528501f6f1e658ce8a5a4e3bdea729be
This commit is contained in:
+47
-36
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.697 2009/07/21 19:25:24 danielk1977 Exp $
|
||||
** $Id: btree.c,v 1.698 2009/07/22 00:35:24 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** See the header comment on "btreeInt.h" for additional information.
|
||||
@@ -539,6 +539,9 @@ static void btreeClearHasContent(BtShared *pBt){
|
||||
/*
|
||||
** Save the current cursor position in the variables BtCursor.nKey
|
||||
** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
|
||||
**
|
||||
** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID)
|
||||
** prior to calling this routine.
|
||||
*/
|
||||
static int saveCursorPosition(BtCursor *pCur){
|
||||
int rc;
|
||||
@@ -548,7 +551,7 @@ static int saveCursorPosition(BtCursor *pCur){
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
|
||||
rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
|
||||
assert( rc==SQLITE_OK ); /* Cannot fail since pCur->eState==VALID */
|
||||
assert( rc==SQLITE_OK ); /* KeySize() cannot fail */
|
||||
|
||||
/* If this is an intKey table, then the above call to BtreeKeySize()
|
||||
** stores the integer key in pCur->nKey. In this case this value is
|
||||
@@ -2707,11 +2710,14 @@ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
|
||||
** database so that the last page of the file currently in use
|
||||
** is no longer in use.
|
||||
**
|
||||
** If the nFin parameter is non-zero, the implementation assumes
|
||||
** If the nFin parameter is non-zero, this function assumes
|
||||
** that the caller will keep calling incrVacuumStep() until
|
||||
** it returns SQLITE_DONE or an error, and that nFin is the
|
||||
** number of pages the database file will contain after this
|
||||
** process is complete.
|
||||
** process is complete. If nFin is zero, it is assumed that
|
||||
** incrVacuumStep() will be called a finite amount of times
|
||||
** which may or may not empty the freelist. A full autovacuum
|
||||
** has nFin>0. A "PRAGMA incremental_vacuum" has nFin==0.
|
||||
*/
|
||||
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
|
||||
Pgno nFreeList; /* Number of pages still on the free-list */
|
||||
@@ -2855,8 +2861,8 @@ static int autoVacuumCommit(BtShared *pBt){
|
||||
invalidateAllOverflowCache(pBt);
|
||||
assert(pBt->autoVacuum);
|
||||
if( !pBt->incrVacuum ){
|
||||
Pgno nFin; /* Number of pages to be freed */
|
||||
Pgno nFree; /* Number of pages no the freelist */
|
||||
Pgno nFin; /* Number of pages in database after autovacuuming */
|
||||
Pgno nFree; /* Number of pages on the freelist initially */
|
||||
Pgno nPtrmap; /* Number of PtrMap pages to be freed */
|
||||
Pgno iFree; /* The next page to be freed */
|
||||
int nEntry; /* Number of entries on one ptrmap page */
|
||||
@@ -3441,6 +3447,17 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
||||
}
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#ifndef NDEBUG /* The next routine used only within assert() statements */
|
||||
/*
|
||||
** Return true if the given BtCursor is valid. A valid cursor is one
|
||||
** that is currently pointing to a row in a (non-empty) table.
|
||||
** This is a verification routine is used only within assert() statements.
|
||||
*/
|
||||
int sqlite3BtreeCursorIsValid(BtCursor *pCur){
|
||||
return pCur && pCur->eState==CURSOR_VALID;
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
|
||||
/*
|
||||
** Set *pSize to the size of the buffer needed to hold the value of
|
||||
** the key for the current entry. If the cursor is not pointing
|
||||
@@ -3448,47 +3465,41 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
||||
**
|
||||
** For a table with the INTKEY flag set, this routine returns the key
|
||||
** itself, not the number of bytes in the key.
|
||||
**
|
||||
** The caller must position the cursor prior to invoking this routine.
|
||||
**
|
||||
** This routine cannot fail. It always returns SQLITE_OK.
|
||||
*/
|
||||
int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
|
||||
int rc;
|
||||
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
rc = restoreCursorPosition(pCur);
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
|
||||
if( pCur->eState==CURSOR_INVALID ){
|
||||
*pSize = 0;
|
||||
}else{
|
||||
getCellInfo(pCur);
|
||||
*pSize = pCur->info.nKey;
|
||||
}
|
||||
assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
|
||||
if( pCur->eState!=CURSOR_VALID ){
|
||||
*pSize = 0;
|
||||
}else{
|
||||
getCellInfo(pCur);
|
||||
*pSize = pCur->info.nKey;
|
||||
}
|
||||
return rc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set *pSize to the number of bytes of data in the entry the
|
||||
** cursor currently points to. Always return SQLITE_OK.
|
||||
** Failure is not possible. If the cursor is not currently
|
||||
** pointing to an entry (which can happen, for example, if
|
||||
** the database is empty) then *pSize is set to 0.
|
||||
** cursor currently points to.
|
||||
**
|
||||
** The caller must guarantee that the cursor is pointing to a non-NULL
|
||||
** valid entry. In other words, the calling procedure must guarantee
|
||||
** that the cursor has Cursor.eState==CURSOR_VALID.
|
||||
**
|
||||
** Failure is not possible. This function always returns SQLITE_OK.
|
||||
** It might just as well be a procedure (returning void) but we continue
|
||||
** to return an integer result code for historical reasons.
|
||||
*/
|
||||
int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
|
||||
int rc;
|
||||
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
rc = restoreCursorPosition(pCur);
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
|
||||
if( pCur->eState==CURSOR_INVALID ){
|
||||
/* Not pointing at a valid entry - set *pSize to 0. */
|
||||
*pSize = 0;
|
||||
}else{
|
||||
getCellInfo(pCur);
|
||||
*pSize = pCur->info.nData;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
getCellInfo(pCur);
|
||||
*pSize = pCur->info.nData;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+5
-1
@@ -13,7 +13,7 @@
|
||||
** subsystem. See comments in the source code for a detailed description
|
||||
** of what each interface routine does.
|
||||
**
|
||||
** @(#) $Id: btree.h,v 1.119 2009/07/09 05:07:38 danielk1977 Exp $
|
||||
** @(#) $Id: btree.h,v 1.120 2009/07/22 00:35:24 drh Exp $
|
||||
*/
|
||||
#ifndef _BTREE_H_
|
||||
#define _BTREE_H_
|
||||
@@ -185,6 +185,10 @@ int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
|
||||
void sqlite3BtreeCacheOverflow(BtCursor *);
|
||||
void sqlite3BtreeClearCursor(BtCursor *);
|
||||
|
||||
#ifndef NDEBUG
|
||||
int sqlite3BtreeCursorIsValid(BtCursor*);
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_BTREECOUNT
|
||||
int sqlite3BtreeCount(BtCursor *, i64 *);
|
||||
#endif
|
||||
|
||||
+7
-3
@@ -43,7 +43,7 @@
|
||||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.872 2009/07/14 18:35:45 drh Exp $
|
||||
** $Id: vdbe.c,v 1.873 2009/07/22 00:35:24 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "vdbeInt.h"
|
||||
@@ -2055,6 +2055,7 @@ case OP_Column: {
|
||||
payloadSize = pC->payloadSize;
|
||||
zRec = (char*)pC->aRow;
|
||||
}else if( pC->isIndex ){
|
||||
assert( sqlite3BtreeCursorIsValid(pCrsr) );
|
||||
rc = sqlite3BtreeKeySize(pCrsr, &payloadSize64);
|
||||
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
|
||||
/* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
|
||||
@@ -2063,8 +2064,9 @@ case OP_Column: {
|
||||
assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 );
|
||||
payloadSize = (u32)payloadSize64;
|
||||
}else{
|
||||
assert( sqlite3BtreeCursorIsValid(pCrsr) );
|
||||
rc = sqlite3BtreeDataSize(pCrsr, &payloadSize);
|
||||
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
|
||||
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
|
||||
}
|
||||
}else if( pC->pseudoTable ){
|
||||
/* The record is the sole entry of a pseudo-table */
|
||||
@@ -3593,6 +3595,7 @@ case OP_NewRowid: { /* out2-prerelease */
|
||||
if( res ){
|
||||
v = 1;
|
||||
}else{
|
||||
assert( sqlite3BtreeCursorIsValid(pC->pCursor) );
|
||||
rc = sqlite3BtreeKeySize(pC->pCursor, &v);
|
||||
assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
|
||||
if( v==MAX_ROWID ){
|
||||
@@ -3879,6 +3882,7 @@ case OP_RowData: {
|
||||
assert( pC->pseudoTable==0 );
|
||||
assert( pC->pCursor!=0 );
|
||||
pCrsr = pC->pCursor;
|
||||
assert( sqlite3BtreeCursorIsValid(pCrsr) );
|
||||
|
||||
/* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
|
||||
** OP_Rewind/Op_Next with no intervening instructions that might invalidate
|
||||
@@ -3899,7 +3903,7 @@ case OP_RowData: {
|
||||
n = (u32)n64;
|
||||
}else{
|
||||
rc = sqlite3BtreeDataSize(pCrsr, &n);
|
||||
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
|
||||
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
|
||||
if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
goto too_big;
|
||||
}
|
||||
|
||||
+3
-1
@@ -14,7 +14,7 @@
|
||||
** to version 2.8.7, all this code was combined into the vdbe.c source file.
|
||||
** But that file was getting too big so this subroutines were split out.
|
||||
**
|
||||
** $Id: vdbeaux.c,v 1.476 2009/07/17 17:25:43 danielk1977 Exp $
|
||||
** $Id: vdbeaux.c,v 1.477 2009/07/22 00:35:24 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "vdbeInt.h"
|
||||
@@ -2599,6 +2599,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
|
||||
** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so
|
||||
** this code can safely assume that nCellKey is 32-bits
|
||||
*/
|
||||
assert( sqlite3BtreeCursorIsValid(pCur) );
|
||||
rc = sqlite3BtreeKeySize(pCur, &nCellKey);
|
||||
assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
|
||||
assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey );
|
||||
@@ -2675,6 +2676,7 @@ int sqlite3VdbeIdxKeyCompare(
|
||||
BtCursor *pCur = pC->pCursor;
|
||||
Mem m;
|
||||
|
||||
assert( sqlite3BtreeCursorIsValid(pCur) );
|
||||
rc = sqlite3BtreeKeySize(pCur, &nCellKey);
|
||||
assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
|
||||
/* nCellKey will always be between 0 and 0xffffffff because of the say
|
||||
|
||||
Reference in New Issue
Block a user