Additional test coverage for the btree module. Remove the failsafe() macro
and replace it with ALWAYS() and NEVER(). (CVS 5395)
FossilOrigin-Name: d7e2f0d2d45574d6191c1b191c0daf5260696f27
diff --git a/src/btree.c b/src/btree.c
index dab5c64..cdff148 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.478 2008/07/11 03:38:41 drh Exp $
+** $Id: btree.c,v 1.479 2008/07/11 16:15:18 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
@@ -793,7 +793,7 @@
assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) );
assert( (start + size)<=pPage->pBt->usableSize );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- if( size<4 ) size = 4;
+ assert( size>=0 ); /* Minimum cell size is 4 */
#ifdef SQLITE_SECURE_DELETE
/* Overwrite deleted information with zeros when the SECURE_DELETE
@@ -1177,8 +1177,7 @@
** If this Btree is a candidate for shared cache, try to find an
** existing BtShared object that we can share with
*/
- if( (flags & BTREE_PRIVATE)==0
- && isMemdb==0
+ if( isMemdb==0
&& (db->flags & SQLITE_Vtab)==0
&& zFilename && zFilename[0]
){
@@ -1187,9 +1186,7 @@
char *zFullPathname = sqlite3Malloc(nFullPathname);
sqlite3_mutex *mutexShared;
p->sharable = 1;
- if( db ){
- db->flags |= SQLITE_SharedCache;
- }
+ db->flags |= SQLITE_SharedCache;
if( !zFullPathname ){
sqlite3_free(p);
return SQLITE_NOMEM;
@@ -1375,10 +1372,10 @@
sqlite3SharedCacheList = pBt->pNext;
}else{
pList = sqlite3SharedCacheList;
- while( pList && pList->pNext!=pBt ){
+ while( ALWAYS(pList) && pList->pNext!=pBt ){
pList=pList->pNext;
}
- if( pList ){
+ if( ALWAYS(pList) ){
pList->pNext = pBt->pNext;
}
}
diff --git a/src/btree.h b/src/btree.h
index 43e7853..780f1d3 100644
--- a/src/btree.h
+++ b/src/btree.h
@@ -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.100 2008/07/10 00:32:42 drh Exp $
+** @(#) $Id: btree.h,v 1.101 2008/07/11 16:15:18 drh Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
@@ -76,11 +76,6 @@
#define BTREE_READWRITE 16 /* Open for both reading and writing */
#define BTREE_CREATE 32 /* Create the database if it does not exist */
-/* Additional values for the 4th argument of sqlite3BtreeOpen that
-** are not associated with PAGER_ values.
-*/
-#define BTREE_PRIVATE 64 /* Never share with other connections */
-
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetSafetyLevel(Btree*,int,int);
diff --git a/src/main.c b/src/main.c
index 479ed61..9da03f2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.475 2008/07/10 18:13:42 drh Exp $
+** $Id: main.c,v 1.476 2008/07/11 16:15:18 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -584,8 +584,7 @@
*/
int sqlite3InvokeBusyHandler(BusyHandler *p){
int rc;
- failsafe( p==0, 0x912aaf8d, {return 0;})
- if( p->xFunc==0 || p->nBusy<0 ) return 0;
+ if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0;
rc = p->xFunc(p->pArg, p->nBusy);
if( rc==0 ){
p->nBusy = -1;
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 7bfcd7d..b1a77a0 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -30,7 +30,7 @@
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
-** @(#) $Id: sqlite.h.in,v 1.367 2008/07/10 18:13:42 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.368 2008/07/11 16:15:18 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
@@ -6112,7 +6112,6 @@
#define SQLITE_STATUS_SCRATCH_USED 3
#define SQLITE_STATUS_SCRATCH_OVERFLOW 4
#define SQLITE_STATUS_MALLOC_SIZE 5
-#define SQLITE_STATUS_FAILSAFE 6
/*
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index b019dff..acb6ffa 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.740 2008/07/10 00:32:42 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.741 2008/07/11 16:15:18 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -63,24 +63,24 @@
#endif
/*
-** The failsafe() macro is used to test for error conditions that
-** should never occur. This is similar to assert() except that with
-** failsafe() the application attempts to recover gracefully rather
-** than abort. If a error condition is detected, a global flag is
-** set to the "Id" prior to recovery in order to alert the application
-** to the error condition.
+** The ALWAYS and NEVER macros surround boolean expressions which
+** are intended to always be true or false, respectively. Such
+** expressions could be omitted from the code completely. But they
+** are included in a few cases in order to enhance the resilience
+** of SQLite to unexpected behavior - to make the code "self-healing"
+** or "ductile" rather than being "brittle" and crashing at the first
+** hint of unplanned behavior.
**
-** The Id should be a random integer. The idea behind the Id is that
-** failsafe() faults in the field can be mapped back to specific failsafe()
-** macros, even if line numbers and filenames have changed.
-**
-** The test condition is argument Cond. The recovery action is
-** argument Action.
+** When doing coverage testing ALWAYS and NEVER are hard-coded to
+** be true and false so that the unreachable code then specify will
+** not be counted as untested code.
*/
#ifdef SQLITE_COVERAGE_TEST
-# define failsafe(Cond,Id,Action)
+# define ALWAYS(X) (1)
+# define NEVER(X) (0)
#else
-# define failsafe(Cond,Id,Action) if( Cond ){ sqlite3Failsafe(Id); Action; }
+# define ALWAYS(X) (X)
+# define NEVER(X) (X)
#endif
/*
@@ -1775,7 +1775,6 @@
int bCoreMutex; /* True to enable core mutexing */
int bFullMutex; /* True to enable full mutexing */
int mxStrlen; /* Maximum string length */
- int iFailsafe; /* Id of failed failsafe() */
sqlite3_mem_methods m; /* Low-level memory allocation interface */
sqlite3_mutex_methods mutex; /* Low-level mutex interface */
void *pHeap; /* Heap storage space */
@@ -2019,7 +2018,6 @@
#endif
int sqlite3SafetyCheckOk(sqlite3*);
int sqlite3SafetyCheckSickOrOk(sqlite3*);
-void sqlite3Failsafe(int);
void sqlite3ChangeCookie(Parse*, int);
void sqlite3MaterializeView(Parse*, Select*, Expr*, int);
diff --git a/src/status.c b/src/status.c
index e5d54f0..5d7d6fa 100644
--- a/src/status.c
+++ b/src/status.c
@@ -13,7 +13,7 @@
** This module implements the sqlite3_status() interface and related
** functionality.
**
-** $Id: status.c,v 1.2 2008/07/09 13:28:54 drh Exp $
+** $Id: status.c,v 1.3 2008/07/11 16:15:18 drh Exp $
*/
#include "sqliteInt.h"
@@ -73,11 +73,6 @@
** then this routine is not threadsafe.
*/
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
- if( op==SQLITE_STATUS_FAILSAFE ){
- *pCurrent = *pHighwater = sqlite3Config.iFailsafe;
- if( resetFlag ) sqlite3Config.iFailsafe = 0;
- return SQLITE_OK;
- }
if( op<0 || op>=ArraySize(sqlite3Stat.nowValue) ){
return SQLITE_MISUSE;
}
diff --git a/src/test_malloc.c b/src/test_malloc.c
index ee233e8..b67bccc 100644
--- a/src/test_malloc.c
+++ b/src/test_malloc.c
@@ -13,7 +13,7 @@
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
-** $Id: test_malloc.c,v 1.36 2008/07/10 18:13:42 drh Exp $
+** $Id: test_malloc.c,v 1.37 2008/07/11 16:15:18 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -1058,7 +1058,6 @@
{ "SQLITE_STATUS_SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED },
{ "SQLITE_STATUS_SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW },
{ "SQLITE_STATUS_MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE },
- { "SQLITE_STATUS_FAILSAFE", SQLITE_STATUS_FAILSAFE },
};
Tcl_Obj *pResult;
if( objc!=3 ){
diff --git a/src/util.c b/src/util.c
index ad1865c..f7a8193 100644
--- a/src/util.c
+++ b/src/util.c
@@ -14,7 +14,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.236 2008/07/10 00:32:42 drh Exp $
+** $Id: util.c,v 1.237 2008/07/11 16:15:18 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@@ -936,19 +936,3 @@
magic!=SQLITE_MAGIC_BUSY ) return 0;
return 1;
}
-
-#ifndef SQLITE_COVERAGE_TEST
-/*
-** Report a failsafe() macro failure
-*/
-void sqlite3Failsafe(int iCode){
- sqlite3Config.iFailsafe = iCode;
-
- /* The following assert is always false. When assert() is enabled,
- ** the following causes a failsafe() failure to work like an assert()
- ** failure. Normal operating mode for SQLite is for assert() to be
- ** disabled, however, so the following is normally a no-op.
- */
- assert( iCode==0 ); /* Always fails if assert() is enabled */
-}
-#endif
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index b774d99..6e61ce4 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -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.395 2008/07/08 22:28:49 shane Exp $
+** $Id: vdbeaux.c,v 1.396 2008/07/11 16:15:18 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -1083,11 +1083,12 @@
if( pCx==0 ){
return;
}
- if( pCx->pCursor ){
- sqlite3BtreeCloseCursor(pCx->pCursor);
- }
if( pCx->pBt ){
sqlite3BtreeClose(pCx->pBt);
+ /* The pCx->pCursor will be close automatically, if it exists, by
+ ** the call above. */
+ }else if( pCx->pCursor ){
+ sqlite3BtreeCloseCursor(pCx->pCursor);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pCx->pVtabCursor ){
diff --git a/src/where.c b/src/where.c
index 0f5ba2a..1b5a5f7 100644
--- a/src/where.c
+++ b/src/where.c
@@ -16,7 +16,7 @@
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
-** $Id: where.c,v 1.315 2008/07/09 13:28:54 drh Exp $
+** $Id: where.c,v 1.316 2008/07/11 16:15:18 drh Exp $
*/
#include "sqliteInt.h"
@@ -478,7 +478,7 @@
}
for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
- failsafe( j>=pIdx->nColumn, 0x0128fc98, {return 0;});
+ if( NEVER(j>=pIdx->nColumn) ) return 0;
}
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
}
@@ -1608,8 +1608,7 @@
flags |= WHERE_COLUMN_IN;
if( pExpr->pSelect!=0 ){
inMultiplier *= 25;
- }else{
- failsafe( pExpr->pList==0, 0x16b91d0f, continue);
+ }else if( ALWAYS(pExpr->pList) ){
inMultiplier *= pExpr->pList->nExpr + 1;
}
}
@@ -1725,9 +1724,9 @@
*/
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
if( pTerm
+ && ALWAYS((pTerm->flags & TERM_CODED)==0)
&& (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
){
- failsafe( (pTerm->flags & TERM_CODED)!=0, 0x641154a4, /* no-op */ );
pTerm->flags |= TERM_CODED;
if( pTerm->iParent>=0 ){
WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
@@ -1873,7 +1872,7 @@
int r1;
int k = pIdx->aiColumn[j];
pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx);
- failsafe( pTerm==0, 0x7592494c, break );
+ if( NEVER(pTerm==0) ) break;
assert( (pTerm->flags & TERM_CODED)==0 );
r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
if( r1!=regBase+j ){