Index: SQLite.Interop/src/core/sqlite3.c ================================================================== --- SQLite.Interop/src/core/sqlite3.c +++ SQLite.Interop/src/core/sqlite3.c @@ -1,8 +1,8 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.7.7. By combining all the individual C code files into this +** version 3.7.8. 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 ** of 5% or more are commonly seen when SQLite is compiled as a single ** translation unit. @@ -648,13 +648,13 @@ ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.7.7" -#define SQLITE_VERSION_NUMBER 3007007 -#define SQLITE_SOURCE_ID "2011-07-13 16:03:46 7aaf0a6ae1238129e07eb191ca3f043df445e27a" +#define SQLITE_VERSION "3.7.8" +#define SQLITE_VERSION_NUMBER 3007008 +#define SQLITE_SOURCE_ID "2011-07-22 21:25:57 a6b85c73406caa3bf0585341c8ebc9897a1884f4" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** @@ -14403,11 +14403,11 @@ DO_OS_MALLOC_TEST(0); /* 0x87f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before ** reaching the VFS. */ - rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f3f, pFlagsOut); + rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut); assert( rc==SQLITE_OK || pFile->pMethods==0 ); return rc; } SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ return pVfs->xDelete(pVfs, zPath, dirSync); @@ -21693,26 +21693,32 @@ return -x; } #ifdef SQLITE_ENABLE_8_3_NAMES /* -** If SQLITE_ENABLE_8_3_NAME is set at compile-time and if the database +** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database ** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and ** if filename in z[] has a suffix (a.k.a. "extension") that is longer than ** three characters, then shorten the suffix on z[] to be the last three ** characters of the original suffix. +** +** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always +** do the suffix shortening regardless of URI parameter. ** ** Examples: ** ** test.db-journal => test.nal ** test.db-wal => test.wal ** test.db-shm => test.shm */ SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){ +#if SQLITE_ENABLE_8_3_NAMES<2 const char *zOk; zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names"); - if( zOk && sqlite3GetBoolean(zOk) ){ + if( zOk && sqlite3GetBoolean(zOk) ) +#endif + { int i, sz; sz = sqlite3Strlen30(z); for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} if( z[i]=='.' && ALWAYS(sz>i+4) ) memcpy(&z[i+1], &z[sz-3], 4); } @@ -22242,14 +22248,17 @@ #ifdef MEMORY_DEBUG # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif #ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3OSTrace = 0; -#define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X +# ifndef SQLITE_DEBUG_OS_TRACE +# define SQLITE_DEBUG_OS_TRACE 0 +# endif + int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; +# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X #else -#define OSTRACE(X) +# define OSTRACE(X) #endif /* ** Macros for performance tracing. Normally turned off. Only works ** on i486 hardware. @@ -24574,14 +24583,17 @@ #ifdef MEMORY_DEBUG # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif #ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3OSTrace = 0; -#define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X +# ifndef SQLITE_DEBUG_OS_TRACE +# define SQLITE_DEBUG_OS_TRACE 0 +# endif + int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; +# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X #else -#define OSTRACE(X) +# define OSTRACE(X) #endif /* ** Macros for performance tracing. Normally turned off. Only works ** on i486 hardware. @@ -25166,11 +25178,13 @@ case EINVAL: case ENOTCONN: case ENODEV: case ENXIO: case ENOENT: +#ifdef ESTALE /* ESTALE is not defined on Interix systems */ case ESTALE: +#endif case ENOSYS: /* these should force the client to close the file and reconnect */ default: return sqliteIOErr; @@ -31329,14 +31343,17 @@ #ifdef MEMORY_DEBUG # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif #ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3OSTrace = 0; -#define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X +# ifndef SQLITE_DEBUG_OS_TRACE +# define SQLITE_DEBUG_OS_TRACE 0 +# endif + int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; +# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X #else -#define OSTRACE(X) +# define OSTRACE(X) #endif /* ** Macros for performance tracing. Normally turned off. Only works ** on i486 hardware. @@ -33893,15 +33910,17 @@ zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } if( isNT() ){ + int cnt = 0; WIN32_FILE_ATTRIBUTE_DATA sAttrData; memset(&sAttrData, 0, sizeof(sAttrData)); - if( GetFileAttributesExW((WCHAR*)zConverted, + while( (rc = GetFileAttributesExW((WCHAR*)zConverted, GetFileExInfoStandard, - &sAttrData) ){ + &sAttrData)) && rc==0 && retryIoerr(&cnt) ){} + if( rc ){ /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file ** as if it does not exist. */ if( flags==SQLITE_ACCESS_EXISTS && sAttrData.nFileSizeHigh==0 @@ -101629,16 +101648,17 @@ nRow = aiRowEst[0]/2; nInMul = (int)(nRow / aiRowEst[nEq]); } #ifdef SQLITE_ENABLE_STAT2 - /* If the constraint is of the form x=VALUE and histogram + /* If the constraint is of the form x=VALUE or x IN (E1,E2,...) + ** and we do not think that values of x are unique and if histogram ** data is available for column x, then it might be possible ** to get a better estimate on the number of rows based on ** VALUE and how common that value is according to the histogram. */ - if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){ + if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){ if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){ testcase( pFirstTerm->eOperator==WO_EQ ); testcase( pFirstTerm->eOperator==WO_ISNULL ); whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow); }else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){ Index: SQLite.Interop/src/core/sqlite3.h ================================================================== --- SQLite.Interop/src/core/sqlite3.h +++ SQLite.Interop/src/core/sqlite3.h @@ -105,13 +105,13 @@ ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.7.7" -#define SQLITE_VERSION_NUMBER 3007007 -#define SQLITE_SOURCE_ID "2011-07-13 16:03:46 7aaf0a6ae1238129e07eb191ca3f043df445e27a" +#define SQLITE_VERSION "3.7.8" +#define SQLITE_VERSION_NUMBER 3007008 +#define SQLITE_SOURCE_ID "2011-07-22 21:25:57 a6b85c73406caa3bf0585341c8ebc9897a1884f4" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** Index: SQLite.Interop/src/win/crypt.c ================================================================== --- SQLite.Interop/src/win/crypt.c +++ SQLite.Interop/src/win/crypt.c @@ -337,10 +337,12 @@ else // Change the writekey for an already-encrypted database { pBlock->hWriteKey = hKey; } + sqlite3_mutex_enter(db->mutex); + // Start a transaction rc = sqlite3BtreeBeginTrans(pbt, 1); if (!rc) { @@ -403,12 +405,14 @@ // pager anymore. Destroy the crypt block and remove the codec from the pager. if (!pBlock->hReadKey && !pBlock->hWriteKey) { sqlite3PagerSetCodec(p, NULL, NULL, NULL, NULL); } + + sqlite3_mutex_leave(db->mutex); return rc; } #endif // SQLITE_HAS_CODEC #endif // SQLITE_OMIT_DISKIO Index: SQLite.Interop/src/win/interop.c ================================================================== --- SQLite.Interop/src/win/interop.c +++ SQLite.Interop/src/win/interop.c @@ -10,10 +10,37 @@ // Additional open flags, we use this one privately //#define SQLITE_OPEN_SHAREDCACHE 0x01000000 typedef void (*SQLITEUSERFUNC)(sqlite3_context *, int, sqlite3_value **); typedef void (*SQLITEFUNCFINAL)(sqlite3_context *); + +__declspec(dllexport) void * WINAPI sqlite3DbMallocZero_interop(sqlite3 *db, int n) +{ + void *p; + if (db) { + sqlite3_mutex_enter(db->mutex); + } + p = sqlite3DbMallocZero(db,n); + if (db) { + sqlite3_mutex_leave(db->mutex); + } + return p; +} + +__declspec(dllexport) void sqlite3DbFree_interop(sqlite3 *db, void *p) +{ + if (db) { + sqlite3_mutex_enter(db->mutex); + } + if (p) { + sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP); + } + sqlite3DbFree(db,p); + if (db) { + sqlite3_mutex_leave(db->mutex); + } +} /* The goal of this version of close is different than that of sqlite3_close(), and is designed to lend itself better to .NET's non-deterministic finalizers and the GC thread. SQLite will not close a database if statements are open on it -- but for our purposes, we'd rather finalize all active statements and forcibly close the database. The reason is simple -- a lot of people don't Dispose() of their objects correctly and let the garbage collector @@ -35,11 +62,11 @@ if (ret == SQLITE_BUSY && db->pVdbe) { while (db->pVdbe) { // Make a copy of the first prepared statement - Vdbe *p = (Vdbe *)sqlite3_malloc(sizeof(Vdbe)); + Vdbe *p = (Vdbe *)sqlite3DbMallocZero_interop(db, sizeof(Vdbe)); Vdbe *po = db->pVdbe; if (!p) { ret = SQLITE_NOMEM; @@ -203,11 +230,11 @@ if (p && p->magic == VDBE_MAGIC_DEAD) { db = p->db; if (db == NULL) { - sqlite3_free(p); + sqlite3DbFree_interop(db, p); ret = SQLITE_OK; } } else ret = sqlite3_finalize(stmt); @@ -363,11 +390,19 @@ __declspec(dllexport) int WINAPI sqlite3_index_column_info_interop(sqlite3 *db, const char *zDb, const char *zIndexName, const char *zColumnName, int *sortOrder, int *onError, char **pzColl, int *plen) { Index *pIdx; Table *pTab; int n; + + sqlite3_mutex_enter(db->mutex); + sqlite3BtreeEnterAll(db); + pIdx = sqlite3FindIndex(db, zIndexName, zDb); + + sqlite3BtreeLeaveAll(db); + sqlite3_mutex_leave(db->mutex); + if (!pIdx) return SQLITE_ERROR; pTab = pIdx->pTable; for (n = 0; n < pIdx->nColumn; n++) {