diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 14 | ||||
-rw-r--r-- | src/prepare.c | 8 | ||||
-rw-r--r-- | src/resolve.c | 4 | ||||
-rw-r--r-- | src/select.c | 12 | ||||
-rw-r--r-- | src/shell.c.in | 29 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 | ||||
-rw-r--r-- | src/test_bestindex.c | 3 | ||||
-rw-r--r-- | src/vdbe.c | 30 | ||||
-rw-r--r-- | src/vdbeaux.c | 4 | ||||
-rw-r--r-- | src/vtab.c | 5 | ||||
-rw-r--r-- | src/where.c | 2 |
11 files changed, 71 insertions, 44 deletions
diff --git a/src/expr.c b/src/expr.c index 2157cf4ed..7cd50e660 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 @@ -6680,9 +6680,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{ @@ -6691,9 +6690,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/resolve.c b/src/resolve.c index 898c78654..546731afe 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -1281,11 +1281,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ #endif } } -#ifndef SQLITE_OMIT_WINDOWFUNC - else if( ExprHasProperty(pExpr, EP_WinFunc) ){ + else if( ExprHasProperty(pExpr, EP_WinFunc) || pExpr->pLeft ){ is_agg = 1; } -#endif sqlite3WalkExprList(pWalker, pList); if( is_agg ){ if( pExpr->pLeft ){ diff --git a/src/select.c b/src/select.c index 8ee59cf68..9278ea18b 100644 --- a/src/select.c +++ b/src/select.c @@ -2324,8 +2324,7 @@ void sqlite3SubqueryColumnTypes( NameContext sNC; assert( pSelect!=0 ); - testcase( (pSelect->selFlags & SF_Resolved)==0 ); - assert( (pSelect->selFlags & SF_Resolved)!=0 || IN_RENAME_OBJECT ); + assert( (pSelect->selFlags & SF_Resolved)!=0 ); assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 ); assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB ); if( db->mallocFailed || IN_RENAME_OBJECT ) return; @@ -2381,12 +2380,12 @@ void sqlite3SubqueryColumnTypes( } } if( zType ){ - i64 m = sqlite3Strlen30(zType); + const i64 k = sqlite3Strlen30(zType); n = sqlite3Strlen30(pCol->zCnName); - pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2); + pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+k+2); pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); if( pCol->zCnName ){ - memcpy(&pCol->zCnName[n+1], zType, m+1); + memcpy(&pCol->zCnName[n+1], zType, k+1); pCol->colFlags |= COLFLAG_HASTYPE; } } @@ -6412,8 +6411,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ if( p->selFlags & SF_HasTypeInfo ) return; p->selFlags |= SF_HasTypeInfo; pParse = pWalker->pParse; - testcase( (p->selFlags & SF_Resolved)==0 ); - assert( (p->selFlags & SF_Resolved) || IN_RENAME_OBJECT ); + assert( (p->selFlags & SF_Resolved) ); pTabList = p->pSrc; for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; 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 0d33f9ee2..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*); @@ -5267,7 +5267,9 @@ void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); void sqlite3Error(sqlite3*,int); void sqlite3ErrorClear(sqlite3*); void sqlite3SystemError(sqlite3*,int); +#if !defined(SQLITE_OMIT_BLOB_LITERAL) void *sqlite3HexToBlob(sqlite3*, const char *z, int n); +#endif u8 sqlite3HexToInt(int h); int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); diff --git a/src/test_bestindex.c b/src/test_bestindex.c index 6b6b41395..0e1e86a81 100644 --- a/src/test_bestindex.c +++ b/src/test_bestindex.c @@ -215,6 +215,9 @@ static int tclConnect( rc = SQLITE_ERROR; }else{ rc = sqlite3_declare_vtab(db, Tcl_GetStringResult(interp)); + if( rc!=SQLITE_OK ){ + *pzErr = sqlite3_mprintf("declare_vtab: %s", sqlite3_errmsg(db)); + } } if( rc!=SQLITE_OK ){ diff --git a/src/vdbe.c b/src/vdbe.c index f06a71da4..6bfcb0ee1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4336,23 +4336,23 @@ case OP_OpenWrite: if( pDb->pSchema->file_format < p->minWriteFileFormat ){ p->minWriteFileFormat = pDb->pSchema->file_format; } + if( pOp->p5 & OPFLAG_P2ISREG ){ + assert( p2>0 ); + assert( p2<=(u32)(p->nMem+1 - p->nCursor) ); + pIn2 = &aMem[p2]; + assert( memIsValid(pIn2) ); + assert( (pIn2->flags & MEM_Int)!=0 ); + sqlite3VdbeMemIntegerify(pIn2); + p2 = (int)pIn2->u.i; + /* The p2 value always comes from a prior OP_CreateBtree opcode and + ** that opcode will always set the p2 value to 2 or more or else fail. + ** If there were a failure, the prepared statement would have halted + ** before reaching this instruction. */ + assert( p2>=2 ); + } }else{ wrFlag = 0; - } - if( pOp->p5 & OPFLAG_P2ISREG ){ - assert( p2>0 ); - assert( p2<=(u32)(p->nMem+1 - p->nCursor) ); - assert( pOp->opcode==OP_OpenWrite ); - pIn2 = &aMem[p2]; - assert( memIsValid(pIn2) ); - assert( (pIn2->flags & MEM_Int)!=0 ); - sqlite3VdbeMemIntegerify(pIn2); - p2 = (int)pIn2->u.i; - /* The p2 value always comes from a prior OP_CreateBtree opcode and - ** that opcode will always set the p2 value to 2 or more or else fail. - ** If there were a failure, the prepared statement would have halted - ** before reaching this instruction. */ - assert( p2>=2 ); + assert( (pOp->p5 & OPFLAG_P2ISREG)==0 ); } if( pOp->p4type==P4_KEYINFO ){ pKeyInfo = pOp->p4.pKeyInfo; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index e5c830343..e4c174e3f 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3355,9 +3355,9 @@ int sqlite3VdbeHalt(Vdbe *p){ /* Check for immediate foreign key violations. */ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ - sqlite3VdbeCheckFk(p, 0); + (void)sqlite3VdbeCheckFk(p, 0); } - + /* If the auto-commit flag is set and this is the only active writer ** VM, then we do either a commit or rollback of the current transaction. ** diff --git a/src/vtab.c b/src/vtab.c index 61dafab71..1036eed44 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -831,7 +831,10 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ for(i=0; aKeyword[i]; i++){ int tokenType = 0; do{ z += sqlite3GetToken(z, &tokenType); }while( tokenType==TK_SPACE ); - if( tokenType!=aKeyword[i] ) return SQLITE_MISUSE_BKPT; + if( tokenType!=aKeyword[i] ){ + sqlite3ErrorWithMsg(db, SQLITE_ERROR, "syntax error"); + return SQLITE_ERROR; + } } sqlite3_mutex_enter(db->mutex); diff --git a/src/where.c b/src/where.c index 13a362dcc..07c5b9cf9 100644 --- a/src/where.c +++ b/src/where.c @@ -3170,7 +3170,7 @@ static int whereLoopAddBtreeIndex( || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ){ if( iCol==XN_ROWID || pProbe->uniqNotNull - || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ) + || (pProbe->nKeyCol==1 && pProbe->onError && (eOp & WO_EQ)) ){ pNew->wsFlags |= WHERE_ONEROW; }else{ |