aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/expr.c14
-rw-r--r--src/prepare.c8
-rw-r--r--src/shell.c.in29
-rw-r--r--src/sqliteInt.h2
4 files changed, 38 insertions, 15 deletions
diff --git a/src/expr.c b/src/expr.c
index a5272df7c..27f89d659 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1443,11 +1443,11 @@ void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){
**
** The pExpr might be deleted immediately on an OOM error.
**
-** The deferred delete is (currently) implemented by adding the
-** pExpr to the pParse->pConstExpr list with a register number of 0.
+** Return 0 if the delete was successfully deferred. Return non-zero
+** if the delete happened immediately because of an OOM.
*/
-void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
- sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr);
+int sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
+ return 0==sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr);
}
/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
@@ -6681,9 +6681,8 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
&& pAggInfo->aCol[iAgg].pCExpr==pExpr
){
pExpr = sqlite3ExprDup(db, pExpr, 0);
- if( pExpr ){
+ if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){
pAggInfo->aCol[iAgg].pCExpr = pExpr;
- sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}else{
@@ -6692,9 +6691,8 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
&& pAggInfo->aFunc[iAgg].pFExpr==pExpr
){
pExpr = sqlite3ExprDup(db, pExpr, 0);
- if( pExpr ){
+ if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){
pAggInfo->aFunc[iAgg].pFExpr = pExpr;
- sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}
diff --git a/src/prepare.c b/src/prepare.c
index 87569ee91..df9c98f74 100644
--- a/src/prepare.c
+++ b/src/prepare.c
@@ -633,7 +633,13 @@ void *sqlite3ParserAddCleanup(
void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */
void *pPtr /* Pointer to object to be cleaned up */
){
- ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
+ ParseCleanup *pCleanup;
+ if( sqlite3FaultSim(300) ){
+ pCleanup = 0;
+ sqlite3OomFault(pParse->db);
+ }else{
+ pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
+ }
if( pCleanup ){
pCleanup->pNext = pParse->pCleanup;
pParse->pCleanup = pCleanup;
diff --git a/src/shell.c.in b/src/shell.c.in
index 2f91ac8ba..298485344 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -7940,7 +7940,10 @@ static struct {
int iCnt; /* Trigger the fault only if iCnt is already zero */
int iInterval; /* Reset iCnt to this value after each fault */
int eVerbose; /* When to print output */
-} faultsim_state = {-1, 0, 0, 0, 0};
+ int nHit; /* Number of hits seen so far */
+ int nRepeat; /* Turn off after this many hits. 0 for never */
+ int nSkip; /* Skip this many before first fault */
+} faultsim_state = {-1, 0, 0, 0, 0, 0, 0};
/*
** This is the fault-sim callback
@@ -7949,8 +7952,8 @@ static int faultsim_callback(int iArg){
if( faultsim_state.iId>0 && faultsim_state.iId!=iArg ){
return SQLITE_OK;
}
- if( faultsim_state.iCnt>0 ){
- faultsim_state.iCnt--;
+ if( faultsim_state.iCnt ){
+ if( faultsim_state.iCnt>0 ) faultsim_state.iCnt--;
if( faultsim_state.eVerbose>=2 ){
oputf("FAULT-SIM id=%d no-fault (cnt=%d)\n", iArg, faultsim_state.iCnt);
}
@@ -7960,6 +7963,10 @@ static int faultsim_callback(int iArg){
oputf("FAULT-SIM id=%d returns %d\n", iArg, faultsim_state.iErr);
}
faultsim_state.iCnt = faultsim_state.iInterval;
+ faultsim_state.nHit++;
+ if( faultsim_state.nRepeat>0 && faultsim_state.nRepeat<=faultsim_state.nHit ){
+ faultsim_state.iCnt = -1;
+ }
return faultsim_state.iErr;
}
@@ -11121,17 +11128,23 @@ static int do_meta_command(char *zLine, ShellState *p){
if( cli_strcmp(z,"off")==0 ){
sqlite3_test_control(testctrl, 0);
}else if( cli_strcmp(z,"on")==0 ){
- faultsim_state.iCnt = faultsim_state.iInterval;
+ faultsim_state.iCnt = faultsim_state.nSkip;
if( faultsim_state.iErr==0 ) faultsim_state.iErr = 1;
+ faultsim_state.nHit = 0;
sqlite3_test_control(testctrl, faultsim_callback);
}else if( cli_strcmp(z,"reset")==0 ){
- faultsim_state.iCnt = faultsim_state.iInterval;
+ faultsim_state.iCnt = faultsim_state.nSkip;
+ faultsim_state.nHit = 0;
+ sqlite3_test_control(testctrl, faultsim_callback);
}else if( cli_strcmp(z,"status")==0 ){
oputf("faultsim.iId: %d\n", faultsim_state.iId);
oputf("faultsim.iErr: %d\n", faultsim_state.iErr);
oputf("faultsim.iCnt: %d\n", faultsim_state.iCnt);
+ oputf("faultsim.nHit: %d\n", faultsim_state.nHit);
oputf("faultsim.iInterval: %d\n", faultsim_state.iInterval);
oputf("faultsim.eVerbose: %d\n", faultsim_state.eVerbose);
+ oputf("faultsim.nRepeat: %d\n", faultsim_state.nRepeat);
+ oputf("faultsim.nSkip: %d\n", faultsim_state.nSkip);
}else if( cli_strcmp(z,"-v")==0 ){
if( faultsim_state.eVerbose<2 ) faultsim_state.eVerbose++;
}else if( cli_strcmp(z,"-q")==0 ){
@@ -11142,6 +11155,10 @@ static int do_meta_command(char *zLine, ShellState *p){
faultsim_state.iErr = atoi(azArg[++kk]);
}else if( cli_strcmp(z,"-interval")==0 && kk+1<nArg ){
faultsim_state.iInterval = atoi(azArg[++kk]);
+ }else if( cli_strcmp(z,"-repeat")==0 && kk+1<nArg ){
+ faultsim_state.nRepeat = atoi(azArg[++kk]);
+ }else if( cli_strcmp(z,"-skip")==0 && kk+1<nArg ){
+ faultsim_state.nSkip = atoi(azArg[++kk]);
}else if( cli_strcmp(z,"-?")==0 || sqlite3_strglob("*help*",z)==0){
bShowHelp = 1;
}else{
@@ -11165,6 +11182,8 @@ static int do_meta_command(char *zLine, ShellState *p){
" --errcode N When triggered, return N as error code\n"
" --id ID Trigger only for the ID specified\n"
" --interval N Trigger only after every N-th call\n"
+ " --repeat N Turn off after N hits. 0 means never\n"
+ " --skip N Skip the first N encounters\n"
);
}
break;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 0da289d52..aa8bfc4b7 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -4856,7 +4856,7 @@ void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
void sqlite3ExprDelete(sqlite3*, Expr*);
void sqlite3ExprDeleteGeneric(sqlite3*,void*);
-void sqlite3ExprDeferredDelete(Parse*, Expr*);
+int sqlite3ExprDeferredDelete(Parse*, Expr*);
void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);