diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/legacy.c | 3 | ||||
-rw-r--r-- | src/loadext.c | 3 | ||||
-rw-r--r-- | src/main.c | 16 | ||||
-rw-r--r-- | src/os_unix.c | 32 | ||||
-rw-r--r-- | src/pager.c | 13 | ||||
-rw-r--r-- | src/prepare.c | 3 | ||||
-rw-r--r-- | src/sqlite.h.in | 40 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/table.c | 8 | ||||
-rw-r--r-- | src/test1.c | 38 | ||||
-rw-r--r-- | src/util.c | 4 | ||||
-rw-r--r-- | src/vdbeapi.c | 2 | ||||
-rw-r--r-- | src/vdbeaux.c | 18 | ||||
-rw-r--r-- | src/vtab.c | 3 |
14 files changed, 136 insertions, 50 deletions
diff --git a/src/legacy.c b/src/legacy.c index 39e1361fa..a74ad4f15 100644 --- a/src/legacy.c +++ b/src/legacy.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: legacy.c,v 1.15 2006/06/26 21:35:45 drh Exp $ +** $Id: legacy.c,v 1.16 2006/09/15 07:28:50 drh Exp $ */ #include "sqliteInt.h" @@ -131,5 +131,6 @@ exec_out: *pzErrMsg = 0; } + assert( (rc&db->errMask)==rc ); return rc; } diff --git a/src/loadext.c b/src/loadext.c index 81f6856d5..80cfc4ccc 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -385,7 +385,8 @@ int sqlite3_auto_extension(void *xInit){ aAutoExtension[nAutoExtension-1] = xInit; } } - sqlite3OsLeaveMutex(); + sqlite3OsLeaveMutex(); + assert( (rc&0xff)==rc ); return rc; } diff --git a/src/main.c b/src/main.c index b7e2cf16d..476577f11 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.356 2006/09/02 13:58:07 drh Exp $ +** $Id: main.c,v 1.357 2006/09/15 07:28:50 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -223,7 +223,7 @@ void sqlite3RollbackAll(sqlite3 *db){ */ const char *sqlite3ErrStr(int rc){ const char *z; - switch( rc ){ + switch( rc & 0xff ){ case SQLITE_ROW: case SQLITE_DONE: case SQLITE_OK: z = "not an error"; break; @@ -763,7 +763,7 @@ int sqlite3_errcode(sqlite3 *db){ if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } - return db->errCode; + return db->errCode & db->errMask; } /* @@ -841,6 +841,7 @@ static int openDatabase( /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; + db->errMask = 0xff; db->priorNewRowid = 0; db->magic = SQLITE_MAGIC_BUSY; db->nDb = 2; @@ -1011,6 +1012,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt){ }else{ rc = sqlite3VdbeReset((Vdbe*)pStmt); sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0); + assert( (rc & (sqlite3_db_handle(pStmt)->errMask))==rc ); } return rc; } @@ -1297,3 +1299,11 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int sqlite3_sleep(int ms){ return sqlite3OsSleep(ms); } + +/* +** Enable or disable the extended result codes. +*/ +int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ + db->errMask = onoff ? 0xffffffff : 0xff; + return SQLITE_OK; +} diff --git a/src/os_unix.c b/src/os_unix.c index ed810d6df..ada697463 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -937,8 +937,10 @@ static int unixRead(OsFile *id, void *pBuf, int amt){ SimulateIOError( got=0 ); if( got==amt ){ return SQLITE_OK; + }else if( got<0 ){ + return SQLITE_IOERR_READ; }else{ - return SQLITE_IOERR; + return SQLITE_IOERR_SHORT_READ; } } @@ -982,7 +984,7 @@ static int unixWrite(OsFile *id, const void *pBuf, int amt){ SimulateDiskfullError(( wrote=0, amt=1 )); if( amt>0 ){ if( wrote<0 ){ - return SQLITE_IOERR; + return SQLITE_IOERR_WRITE; }else{ return SQLITE_FULL; } @@ -1065,19 +1067,13 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ #if HAVE_FULLFSYNC if( fullSync ){ rc = fcntl(fd, F_FULLFSYNC, 0); - }else{ - rc = 1; - } - /* If the FULLSYNC failed, try to do a normal fsync() */ - if( rc ) rc = fsync(fd); - -#else /* if !defined(F_FULLSYNC) */ + }else +#endif /* HAVE_FULLFSYNC */ if( dataOnly ){ rc = fdatasync(fd); }else{ rc = fsync(fd); } -#endif /* defined(F_FULLFSYNC) */ #endif /* defined(SQLITE_NO_SYNC) */ return rc; @@ -1106,7 +1102,7 @@ static int unixSync(OsFile *id, int dataOnly){ rc = full_fsync(pFile->h, pFile->fullSync, dataOnly); SimulateIOError( rc=1 ); if( rc ){ - return SQLITE_IOERR; + return SQLITE_IOERR_FSYNC; } if( pFile->dirfd>=0 ){ TRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, @@ -1155,7 +1151,7 @@ int sqlite3UnixSyncDirectory(const char *zDirname){ close(fd); SimulateIOError( r=1 ); if( r ){ - return SQLITE_IOERR; + return SQLITE_IOERR_DIR_FSYNC; }else{ return SQLITE_OK; } @@ -1171,7 +1167,7 @@ static int unixTruncate(OsFile *id, i64 nByte){ rc = ftruncate(((unixFile*)id)->h, nByte); SimulateIOError( rc=1 ); if( rc ){ - return SQLITE_IOERR; + return SQLITE_IOERR_TRUNCATE; }else{ return SQLITE_OK; } @@ -1187,7 +1183,7 @@ static int unixFileSize(OsFile *id, i64 *pSize){ rc = fstat(((unixFile*)id)->h, &buf); SimulateIOError( rc=1 ); if( rc!=0 ){ - return SQLITE_IOERR; + return SQLITE_IOERR_FSTAT; } *pSize = buf.st_size; return SQLITE_OK; @@ -1397,7 +1393,7 @@ static int unixLock(OsFile *id, int locktype){ lock.l_len = 1L; lock.l_type = F_UNLCK; if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ - rc = SQLITE_IOERR; /* This should never happen */ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ goto end_lock; } if( s ){ @@ -1486,7 +1482,7 @@ static int unixUnlock(OsFile *id, int locktype){ lock.l_len = SHARED_SIZE; if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ /* This should never happen */ - rc = SQLITE_IOERR; + rc = SQLITE_IOERR_RDLOCK; } } lock.l_type = F_UNLCK; @@ -1496,7 +1492,7 @@ static int unixUnlock(OsFile *id, int locktype){ if( fcntl(pFile->h, F_SETLK, &lock)==0 ){ pLock->locktype = SHARED_LOCK; }else{ - rc = SQLITE_IOERR; /* This should never happen */ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ } } if( locktype==NO_LOCK ){ @@ -1514,7 +1510,7 @@ static int unixUnlock(OsFile *id, int locktype){ if( fcntl(pFile->h, F_SETLK, &lock)==0 ){ pLock->locktype = NO_LOCK; }else{ - rc = SQLITE_IOERR; /* This should never happen */ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ } } diff --git a/src/pager.c b/src/pager.c index 1013c1c2c..e8923e06f 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.271 2006/08/08 13:51:43 drh Exp $ +** @(#) $Id: pager.c,v 1.272 2006/09/15 07:28:50 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -476,12 +476,13 @@ static u32 retrieve32bits(PgHdr *p, int offset){ ** will immediately return the same error code. */ static int pager_error(Pager *pPager, int rc){ + int rc2 = rc & 0xff; assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK ); if( - rc==SQLITE_FULL || - rc==SQLITE_IOERR || - rc==SQLITE_CORRUPT || - rc==SQLITE_PROTOCOL + rc2==SQLITE_FULL || + rc2==SQLITE_IOERR || + rc2==SQLITE_CORRUPT || + rc2==SQLITE_PROTOCOL ){ pPager->errCode = rc; } @@ -2578,7 +2579,7 @@ int sqlite3pager_release_memory(int nReq){ ** The error will be returned to the user (or users, in the case ** of a shared pager cache) of the pager for which the error occured. */ - assert( rc==SQLITE_IOERR || rc==SQLITE_FULL ); + assert( (rc&0xff)==SQLITE_IOERR || rc==SQLITE_FULL ); assert( p->state>=PAGER_RESERVED ); pager_error(p, rc); } diff --git a/src/prepare.c b/src/prepare.c index b89059b85..7e52c8787 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.38 2006/08/12 13:28:23 drh Exp $ +** $Id: prepare.c,v 1.39 2006/09/15 07:28:50 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -546,6 +546,7 @@ int sqlite3_prepare( rc = sqlite3ApiExit(db, rc); sqlite3ReleaseThreadData(); + assert( (rc&db->errMask)==rc ); return rc; } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 2cd534b6d..302814884 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.192 2006/09/11 00:34:22 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.193 2006/09/15 07:28:50 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -199,6 +199,44 @@ int sqlite3_exec( /* end-of-error-codes */ /* +** Using the sqlite3_extended_result_codes() API, you can cause +** SQLite to return result codes with additional information in +** their upper bits. The lower 8 bits will be the same as the +** primary result codes above. But the upper bits might contain +** more specific error information. +** +** To extract the primary result code from an extended result code, +** simply mask off the lower 8 bits. +** +** primary = extended & 0xff; +** +** New result error codes may be added from time to time. Software +** that uses the extended result codes should plan accordingly and be +** sure to always handle new unknown codes gracefully. +** +** The SQLITE_OK result code will never be extended. It will always +** be exactly zero. +** +** The extended result codes always have the primary result code +** as a prefix. Primary result codes only contain a single "_" +** character. Extended result codes contain two or more "_" characters. +*/ +#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) +#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) +#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) +#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) +#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) +#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) +#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) +#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) + +/* +** Enable or disable the extended result codes. +*/ +int sqlite3_extended_result_codes(sqlite3*, int onoff); + +/* ** Each entry in an SQLite table has a unique integer key. (The key is ** the value of the INTEGER PRIMARY KEY column if there is such a column, ** otherwise the key is generated at random. The unique key is always diff --git a/src/sqliteInt.h b/src/sqliteInt.h index fae55f2ec..3aa94ff34 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.526 2006/09/11 23:45:50 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.527 2006/09/15 07:28:50 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -447,6 +447,7 @@ struct sqlite3 { Db *aDb; /* All backends */ int flags; /* Miscellanous flags. See below */ int errCode; /* Most recent error code (SQLITE_*) */ + int errMask; /* & result codes with this before returning */ u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ int nTable; /* Number of tables in the database */ diff --git a/src/table.c b/src/table.c index c4e228361..30c148489 100644 --- a/src/table.c +++ b/src/table.c @@ -146,7 +146,7 @@ int sqlite3_get_table( assert( sizeof(res.azResult[0])>= sizeof(res.nData) ); res.azResult[0] = (char*)res.nData; } - if( rc==SQLITE_ABORT ){ + if( (rc&0xff)==SQLITE_ABORT ){ sqlite3_free_table(&res.azResult[1]); if( res.zErrMsg ){ if( pzErrMsg ){ @@ -156,12 +156,12 @@ int sqlite3_get_table( sqliteFree(res.zErrMsg); } db->errCode = res.rc; - return res.rc; + return res.rc & db->errMask; } sqliteFree(res.zErrMsg); if( rc!=SQLITE_OK ){ sqlite3_free_table(&res.azResult[1]); - return rc; + return rc & db->errMask; } if( res.nAlloc>res.nData ){ char **azNew; @@ -176,7 +176,7 @@ int sqlite3_get_table( *pazResult = &res.azResult[1]; if( pnColumn ) *pnColumn = res.nColumn; if( pnRow ) *pnRow = res.nRow; - return rc; + return rc & db->errMask; } /* diff --git a/src/test1.c b/src/test1.c index e4e1359d1..b9dce6b99 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.221 2006/09/13 19:21:28 drh Exp $ +** $Id: test1.c,v 1.222 2006/09/15 07:28:51 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -65,7 +65,7 @@ static int get_sqlite_pointer( const char *sqlite3TestErrorName(int rc){ const char *zName = 0; - switch( rc ){ + switch( rc & 0xff ){ case SQLITE_OK: zName = "SQLITE_OK"; break; case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; case SQLITE_PERM: zName = "SQLITE_PERM"; break; @@ -1062,6 +1062,29 @@ static int test_enable_shared( #endif /* +** Usage: sqlite3_extended_result_codes DB BOOLEAN +** +*/ +static int test_extended_result_codes( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + int enable; + sqlite3 *db; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR; + sqlite3_extended_result_codes(db, enable); + return TCL_OK; +} + +/* ** Usage: sqlite3_libversion_number ** */ @@ -2331,6 +2354,8 @@ static int test_errcode( Tcl_Obj *CONST objv[] ){ sqlite3 *db; + int rc; + char zBuf[30]; if( objc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", @@ -2338,7 +2363,13 @@ static int test_errcode( return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0); + rc = sqlite3_errcode(db); + if( (rc&0xff)==rc ){ + zBuf[0] = 0; + }else{ + sprintf(zBuf,"+%d", rc>>8); + } + Tcl_AppendResult(interp, (char *)errorName(rc), zBuf, 0); return TCL_OK; } @@ -3861,6 +3892,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_load_extension", test_load_extension, 0}, { "sqlite3_enable_load_extension", test_enable_load, 0}, + { "sqlite3_extended_result_codes", test_extended_result_codes, 0}, /* sqlite3_column_*() API */ { "sqlite3_column_count", test_column_count ,0 }, diff --git a/src/util.c b/src/util.c index 905477d1f..457227da0 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.192 2006/07/26 01:39:30 drh Exp $ +** $Id: util.c,v 1.193 2006/09/15 07:28:51 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -1446,7 +1446,7 @@ int sqlite3ApiExit(sqlite3* db, int rc){ sqlite3Error(db, SQLITE_NOMEM, 0); rc = SQLITE_NOMEM; } - return rc; + return rc & (db ? db->errMask : 0xff); } /* diff --git a/src/vdbeapi.c b/src/vdbeapi.c index a0ced3d79..983f164cb 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -254,6 +254,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){ sqlite3Error(p->db, rc, 0); p->rc = sqlite3ApiExit(p->db, p->rc); + assert( (rc&0xff)==rc ); return rc; } @@ -815,6 +816,7 @@ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ rc = sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]); sqlite3MallocAllow(); } + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); return rc; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index a6ca9c3c7..5c534d122 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1435,18 +1435,20 @@ int sqlite3VdbeHalt(Vdbe *p){ ** VDBE_MAGIC_INIT. */ int sqlite3VdbeReset(Vdbe *p){ + sqlite3 *db; if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){ sqlite3Error(p->db, SQLITE_MISUSE, 0); return SQLITE_MISUSE; } + db = p->db; /* If the VM did not run to completion or if it encountered an ** error, then it might not have been halted properly. So halt ** it now. */ - sqlite3SafetyOn(p->db); + sqlite3SafetyOn(db); sqlite3VdbeHalt(p); - sqlite3SafetyOff(p->db); + sqlite3SafetyOff(db); /* If the VDBE has be run even partially, then transfer the error code ** and error message from the VDBE into the main database structure. But @@ -1455,21 +1457,20 @@ int sqlite3VdbeReset(Vdbe *p){ */ if( p->pc>=0 ){ if( p->zErrMsg ){ - sqlite3* db = p->db; sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, sqlite3FreeX); db->errCode = p->rc; p->zErrMsg = 0; }else if( p->rc ){ - sqlite3Error(p->db, p->rc, 0); + sqlite3Error(db, p->rc, 0); }else{ - sqlite3Error(p->db, SQLITE_OK, 0); + sqlite3Error(db, SQLITE_OK, 0); } }else if( p->rc && p->expired ){ /* The expired flag was set on the VDBE before the first call ** to sqlite3_step(). For consistency (since sqlite3_step() was ** called), set the database error in this case as well. */ - sqlite3Error(p->db, p->rc, 0); + sqlite3Error(db, p->rc, 0); } /* Reclaim all memory used by the VDBE @@ -1504,9 +1505,9 @@ int sqlite3VdbeReset(Vdbe *p){ p->magic = VDBE_MAGIC_INIT; p->aborted = 0; if( p->rc==SQLITE_SCHEMA ){ - sqlite3ResetInternalSchema(p->db, 0); + sqlite3ResetInternalSchema(db, 0); } - return p->rc; + return p->rc & db->errMask; } /* @@ -1517,6 +1518,7 @@ int sqlite3VdbeFinalize(Vdbe *p){ int rc = SQLITE_OK; if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){ rc = sqlite3VdbeReset(p); + assert( (rc & p->db->errMask)==rc ); }else if( p->magic!=VDBE_MAGIC_INIT ){ return SQLITE_MISUSE; } diff --git a/src/vtab.c b/src/vtab.c index 2fa389b43..c3e2481a6 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to help implement virtual tables. ** -** $Id: vtab.c,v 1.35 2006/09/13 19:21:28 drh Exp $ +** $Id: vtab.c,v 1.36 2006/09/15 07:28:51 drh Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" @@ -471,6 +471,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ sParse.pNewTable = 0; db->pVTab = 0; + assert( (rc&0xff)==rc ); return rc; } |