upgraded bundled SQLite to 3.8.7.2, take care of SQLITE_BUSY_RECOVERY and SQLITE_BUSY_SNAPSHOT

This commit is contained in:
Guenter Obiltschnig 2014-11-19 18:46:17 +01:00
Родитель e657309a0b
Коммит b8503e82e0
3 изменённых файлов: 124 добавлений и 72 удалений

Просмотреть файл

@ -164,6 +164,8 @@ void Utility::throwException(int rc, const std::string& addErrMsg)
case SQLITE_ABORT:
throw ExecutionAbortedException(std::string("Callback routine requested an abort"), addErrMsg);
case SQLITE_BUSY:
case SQLITE_BUSY_RECOVERY:
case SQLITE_BUSY_SNAPSHOT:
throw DBLockedException(std::string("The database file is locked"), addErrMsg);
case SQLITE_LOCKED:
throw TableLockedException(std::string("A table in the database is locked"), addErrMsg);

Просмотреть файл

@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.8.7.1. By combining all the individual C code files into this
** version 3.8.7.2. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@ -231,9 +231,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.8.7.1"
#define SQLITE_VERSION "3.8.7.2"
#define SQLITE_VERSION_NUMBER 3008007
#define SQLITE_SOURCE_ID "2014-10-29 13:59:56 3b7b72c4685aa5cf5e675c2c47ebec10d9704221"
#define SQLITE_SOURCE_ID "2014-11-18 20:57:56 2ab564bf9655b7c7b97ab85cafc8a48329b27f93"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -9013,7 +9013,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int);
SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int,int);
SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags);
SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*);
@ -9046,7 +9046,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *);
SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*);
SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);
SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int);
SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
@ -13062,7 +13062,7 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *);
SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, char*, int, int);
SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int);
SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*);
SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum*,int);
SQLITE_PRIVATE void sqlite3AppendChar(StrAccum*,int,char);
SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*);
SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*);
SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int);
@ -20947,7 +20947,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
const et_info *infop; /* Pointer to the appropriate info structure */
char *zOut; /* Rendering buffer */
int nOut; /* Size of the rendering buffer */
char *zExtra; /* Malloced memory used by some conversion */
char *zExtra = 0; /* Malloced memory used by some conversion */
#ifndef SQLITE_OMIT_FLOATING_POINT
int exp, e2; /* exponent of real numbers */
int nsd; /* Number of significant digits returned */
@ -21064,7 +21064,6 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
break;
}
}
zExtra = 0;
/*
** At this point, variables are initialized as follows:
@ -21355,13 +21354,16 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
}else{
c = va_arg(ap,int);
}
buf[0] = (char)c;
if( precision>=0 ){
for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
length = precision;
}else{
length =1;
if( precision>1 ){
width -= precision-1;
if( width>1 && !flag_leftjustify ){
sqlite3AppendChar(pAccum, width-1, ' ');
width = 0;
}
sqlite3AppendChar(pAccum, precision-1, c);
}
length = 1;
buf[0] = c;
bufpt = buf;
break;
case etSTRING:
@ -21462,11 +21464,14 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
** the output.
*/
width -= length;
if( width>0 && !flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
sqlite3StrAccumAppend(pAccum, bufpt, length);
if( width>0 && flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
if( zExtra ) sqlite3_free(zExtra);
if( zExtra ){
sqlite3_free(zExtra);
zExtra = 0;
}
}/* End for loop over the format string */
} /* End of function */
@ -21519,11 +21524,11 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
}
/*
** Append N space characters to the given string buffer.
** Append N copies of character c to the given string buffer.
*/
SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *p, int N){
SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){
if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
while( (N--)>0 ) p->zText[p->nChar++] = ' ';
while( (N--)>0 ) p->zText[p->nChar++] = c;
}
/*
@ -50636,7 +50641,6 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p
}
if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
}
assert( rc==SQLITE_OK );
return rc;
}
@ -51715,6 +51719,11 @@ struct CellInfo {
**
** Fields in this structure are accessed under the BtShared.mutex
** found at self->pBt->mutex.
**
** skipNext meaning:
** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op.
** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op.
** eState==FAULT: Cursor fault with skipNext as error code.
*/
struct BtCursor {
Btree *pBtree; /* The Btree to which this cursor belongs */
@ -51727,7 +51736,8 @@ struct BtCursor {
void *pKey; /* Saved key that was cursor last known position */
Pgno pgnoRoot; /* The root page of this tree */
int nOvflAlloc; /* Allocated size of aOverflow[] array */
int skipNext; /* Prev() is noop if negative. Next() is noop if positive */
int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
** Error code if eState==CURSOR_FAULT */
u8 curFlags; /* zero or more BTCF_* flags defined below */
u8 eState; /* One of the CURSOR_XXX constants (see below) */
u8 hints; /* As configured by CursorSetHints() */
@ -51773,7 +51783,7 @@ struct BtCursor {
** on a different connection that shares the BtShared cache with this
** cursor. The error has left the cache in an inconsistent state.
** Do nothing else with this cursor. Any attempt to use the cursor
** should return the error code stored in BtCursor.skip
** should return the error code stored in BtCursor.skipNext
*/
#define CURSOR_INVALID 0
#define CURSOR_VALID 1
@ -54355,7 +54365,7 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){
** The call to sqlite3BtreeRollback() drops any table-locks held by
** this handle.
*/
sqlite3BtreeRollback(p, SQLITE_OK);
sqlite3BtreeRollback(p, SQLITE_OK, 0);
sqlite3BtreeLeave(p);
/* If there are still other outstanding references to the shared-btree
@ -55648,60 +55658,91 @@ SQLITE_PRIVATE int sqlite3BtreeCommit(Btree *p){
/*
** This routine sets the state to CURSOR_FAULT and the error
** code to errCode for every cursor on BtShared that pBtree
** references.
** code to errCode for every cursor on any BtShared that pBtree
** references. Or if the writeOnly flag is set to 1, then only
** trip write cursors and leave read cursors unchanged.
**
** Every cursor is tripped, including cursors that belong
** to other database connections that happen to be sharing
** the cache with pBtree.
** Every cursor is a candidate to be tripped, including cursors
** that belong to other database connections that happen to be
** sharing the cache with pBtree.
**
** This routine gets called when a rollback occurs.
** All cursors using the same cache must be tripped
** to prevent them from trying to use the btree after
** the rollback. The rollback may have deleted tables
** or moved root pages, so it is not sufficient to
** save the state of the cursor. The cursor must be
** invalidated.
** This routine gets called when a rollback occurs. If the writeOnly
** flag is true, then only write-cursors need be tripped - read-only
** cursors save their current positions so that they may continue
** following the rollback. Or, if writeOnly is false, all cursors are
** tripped. In general, writeOnly is false if the transaction being
** rolled back modified the database schema. In this case b-tree root
** pages may be moved or deleted from the database altogether, making
** it unsafe for read cursors to continue.
**
** If the writeOnly flag is true and an error is encountered while
** saving the current position of a read-only cursor, all cursors,
** including all read-cursors are tripped.
**
** SQLITE_OK is returned if successful, or if an error occurs while
** saving a cursor position, an SQLite error code.
*/
SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){
SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){
BtCursor *p;
if( pBtree==0 ) return;
int rc = SQLITE_OK;
assert( (writeOnly==0 || writeOnly==1) && BTCF_WriteFlag==1 );
if( pBtree ){
sqlite3BtreeEnter(pBtree);
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
int i;
if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){
if( p->eState==CURSOR_VALID ){
rc = saveCursorPosition(p);
if( rc!=SQLITE_OK ){
(void)sqlite3BtreeTripAllCursors(pBtree, rc, 0);
break;
}
}
}else{
sqlite3BtreeClearCursor(p);
p->eState = CURSOR_FAULT;
p->skipNext = errCode;
}
for(i=0; i<=p->iPage; i++){
releasePage(p->apPage[i]);
p->apPage[i] = 0;
}
}
sqlite3BtreeLeave(pBtree);
}
return rc;
}
/*
** Rollback the transaction in progress. All cursors will be
** invalided by this operation. Any attempt to use a cursor
** that was open at the beginning of this operation will result
** in an error.
** Rollback the transaction in progress.
**
** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped).
** Only write cursors are tripped if writeOnly is true but all cursors are
** tripped if writeOnly is false. Any attempt to use
** a tripped cursor will result in an error.
**
** This will release the write lock on the database file. If there
** are no active cursors, it also releases the read lock.
*/
SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){
SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
int rc;
BtShared *pBt = p->pBt;
MemPage *pPage1;
assert( writeOnly==1 || writeOnly==0 );
assert( tripCode==SQLITE_ABORT_ROLLBACK || tripCode==SQLITE_OK );
sqlite3BtreeEnter(p);
if( tripCode==SQLITE_OK ){
rc = tripCode = saveAllCursors(pBt, 0, 0);
if( rc ) writeOnly = 0;
}else{
rc = SQLITE_OK;
}
if( tripCode ){
sqlite3BtreeTripAllCursors(p, tripCode);
int rc2 = sqlite3BtreeTripAllCursors(p, tripCode, writeOnly);
assert( rc==SQLITE_OK || (writeOnly==0 && rc2==SQLITE_OK) );
if( rc2!=SQLITE_OK ) rc = rc2;
}
btreeIntegrity(p);
@ -56036,13 +56077,9 @@ SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){
*/
SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
if( pCur->eState!=CURSOR_VALID ){
*pSize = 0;
}else{
assert( pCur->eState==CURSOR_VALID );
getCellInfo(pCur);
*pSize = pCur->info.nKey;
}
return SQLITE_OK;
}
@ -61466,7 +61503,7 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
}
/* If a transaction is still open on the Btree, roll it back. */
sqlite3BtreeRollback(p->pDest, SQLITE_OK);
sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
/* Set the error code of the destination database handle. */
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
@ -71304,7 +71341,7 @@ case OP_Column: {
pC->payloadSize = pC->szRow = avail = pReg->n;
pC->aRow = (u8*)pReg->z;
}else{
MemSetTypeFlag(pDest, MEM_Null);
sqlite3VdbeMemSetNull(pDest);
goto op_column_out;
}
}else{
@ -71828,11 +71865,18 @@ case OP_Savepoint: {
db->isTransactionSavepoint = 0;
rc = p->rc;
}else{
int isSchemaChange;
iSavepoint = db->nSavepoint - iSavepoint - 1;
if( p1==SAVEPOINT_ROLLBACK ){
isSchemaChange = (db->flags & SQLITE_InternChanges)!=0;
for(ii=0; ii<db->nDb; ii++){
sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT);
rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt,
SQLITE_ABORT_ROLLBACK,
isSchemaChange==0);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}else{
isSchemaChange = 0;
}
for(ii=0; ii<db->nDb; ii++){
rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint);
@ -71840,7 +71884,7 @@ case OP_Savepoint: {
goto abort_due_to_error;
}
}
if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
if( isSchemaChange ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
db->flags = (db->flags | SQLITE_InternChanges);
@ -72237,7 +72281,7 @@ case OP_OpenWrite: {
|| p->readOnly==0 );
if( p->expired ){
rc = SQLITE_ABORT;
rc = SQLITE_ABORT_ROLLBACK;
break;
}
@ -73404,6 +73448,10 @@ case OP_Rowid: { /* out2-prerelease */
assert( pC->pCursor!=0 );
rc = sqlite3VdbeCursorRestore(pC);
if( rc ) goto abort_due_to_error;
if( pC->nullRow ){
pOut->flags = MEM_Null;
break;
}
rc = sqlite3BtreeKeySize(pC->pCursor, &v);
assert( rc==SQLITE_OK ); /* Always so because of CursorRestore() above */
}
@ -82435,7 +82483,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
pSelect->iLimit = 0;
testcase( pSelect->selFlags & SF_Distinct );
pSelect->selFlags &= ~SF_Distinct;
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
if( sqlite3Select(pParse, pSelect, &dest) ){
sqlite3KeyInfoUnref(pKeyInfo);
@ -125927,13 +125974,15 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
/*
** Rollback all database files. If tripCode is not SQLITE_OK, then
** any open cursors are invalidated ("tripped" - as in "tripping a circuit
** any write cursors are invalidated ("tripped" - as in "tripping a circuit
** breaker") and made to return tripCode if there are any further
** attempts to use that cursor.
** attempts to use that cursor. Read cursors remain open and valid
** but are "saved" in case the table pages are moved around.
*/
SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
int i;
int inTrans = 0;
int schemaChange;
assert( sqlite3_mutex_held(db->mutex) );
sqlite3BeginBenignMalloc();
@ -125944,6 +125993,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
** the database rollback and schema reset, which can cause false
** corruption reports in some cases. */
sqlite3BtreeEnterAll(db);
schemaChange = (db->flags & SQLITE_InternChanges)!=0 && db->init.busy==0;
for(i=0; i<db->nDb; i++){
Btree *p = db->aDb[i].pBt;
@ -125951,7 +126001,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
if( sqlite3BtreeIsInTrans(p) ){
inTrans = 1;
}
sqlite3BtreeRollback(p, tripCode);
sqlite3BtreeRollback(p, tripCode, !schemaChange);
}
}
sqlite3VtabRollback(db);

Просмотреть файл

@ -107,9 +107,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.8.7.1"
#define SQLITE_VERSION "3.8.7.2"
#define SQLITE_VERSION_NUMBER 3008007
#define SQLITE_SOURCE_ID "2014-10-29 13:59:56 3b7b72c4685aa5cf5e675c2c47ebec10d9704221"
#define SQLITE_SOURCE_ID "2014-11-18 20:57:56 2ab564bf9655b7c7b97ab85cafc8a48329b27f93"
/*
** CAPI3REF: Run-Time Library Version Numbers