Index: SQLite.Interop/props/SQLite.Interop.2005.vsprops ================================================================== --- SQLite.Interop/props/SQLite.Interop.2005.vsprops +++ SQLite.Interop/props/SQLite.Interop.2005.vsprops @@ -37,11 +37,11 @@ Value="1,0,83,0" PerformEnvironmentSet="true" /> 2010 083 1.0 1.0.83.0 1,0,83,0 - INTEROP_TEST_EXTENSION=1 + INTEROP_DEBUG=3;INTEROP_TEST_EXTENSION=1 INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1 /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteCommand.bmp,System.Data.SQLite.SQLiteCommand.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteConnection.bmp,System.Data.SQLite.SQLiteConnection.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteDataAdapter.bmp,System.Data.SQLite.SQLiteDataAdapter.bmp $(ProjectDir)..\System.Data.SQLite\System.Data.SQLite.snk SQLite.Interop System.Data.SQLite Index: SQLite.Interop/props/SQLite.Interop.2012.props ================================================================== --- SQLite.Interop/props/SQLite.Interop.2012.props +++ SQLite.Interop/props/SQLite.Interop.2012.props @@ -12,11 +12,11 @@ 2012 083 1.0 1.0.83.0 1,0,83,0 - INTEROP_TEST_EXTENSION=1 + INTEROP_DEBUG=3;INTEROP_TEST_EXTENSION=1 INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1 /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteCommand.bmp,System.Data.SQLite.SQLiteCommand.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteConnection.bmp,System.Data.SQLite.SQLiteConnection.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteDataAdapter.bmp,System.Data.SQLite.SQLiteDataAdapter.bmp $(ProjectDir)..\System.Data.SQLite\System.Data.SQLite.snk SQLite.Interop System.Data.SQLite Index: SQLite.Interop/src/win/interop.c ================================================================== --- SQLite.Interop/src/win/interop.c +++ SQLite.Interop/src/win/interop.c @@ -16,13 +16,50 @@ #ifdef SQLITE_OS_WIN #if defined(INTEROP_CODEC) #include "crypt.c" #endif + +#define INTEROP_DEBUG_NONE (0x00) +#define INTEROP_DEBUG_CLOSE (0x01) +#define INTEROP_DEBUG_FINALIZE (0x02) +#define INTEROP_DEBUG_OPEN (0x04) +#define INTEROP_DEBUG_OPEN16 (0x08) +#define INTEROP_DEBUG_PREPARE (0x10) +#define INTEROP_DEBUG_PREPARE16 (0x20) +#define INTEROP_DEBUG_RESET (0x40) typedef void (*SQLITEUSERFUNC)(sqlite3_context *, int, sqlite3_value **); typedef void (*SQLITEFUNCFINAL)(sqlite3_context *); + +#if defined(INTEROP_DEBUG) +SQLITE_PRIVATE void sqlite3InteropDebug(const char *zFormat, ...){ + va_list ap; /* Vararg list */ + StrAccum acc; /* String accumulator */ + char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ + va_start(ap, zFormat); + sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0); + acc.useMalloc = 0; + sqlite3VXPrintf(&acc, 0, zFormat, ap); + va_end(ap); +#if SQLITE_VERSION_NUMBER >= 3007013 + sqlite3_win32_write_debug(sqlite3StrAccumFinish(&acc), -1); +#elif defined(SQLITE_WIN32_HAS_ANSI) + OutputDebugStringA(sqlite3StrAccumFinish(&acc)); +#elif defined(SQLITE_WIN32_HAS_WIDE) + { + LPWSTR zWideMsg = utf8ToUnicode(sqlite3StrAccumFinish(&acc)); + if( zWideMsg ){ + OutputDebugStringW(zWideMsg); + sqlite3_free(zWideMsg); + } + } +#else + fprintf(stderr, "%s", sqlite3StrAccumFinish(&acc)); +#endif +} +#endif #if SQLITE_VERSION_NUMBER < 3007014 SQLITE_PRIVATE void * sqlite3DbMallocZero_interop(sqlite3 *db, int n) { void *p; @@ -64,14 +101,26 @@ statement's memory is preserved, and marked as BAD, but we can still manage to finalize everything and forcibly close the database. Later when the GC gets around to calling finalize_interop() on the "bad" statement, we detect that and finish deallocating the pointer. */ SQLITE_API int WINAPI sqlite3_close_interop(sqlite3 *db) { + int ret; #if SQLITE_VERSION_NUMBER >= 3007014 - return sqlite3_close_v2(db); + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CLOSE) + sqlite3InteropDebug("sqlite3_close_interop(): calling sqlite3_close_v2(%p)...\n", db); +#endif + + ret = sqlite3_close_v2(db); + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CLOSE) + sqlite3InteropDebug("sqlite3_close_interop(): sqlite3_close_v2(%p) returned %d.\n", db, ret); +#endif + + return ret; #else - int ret = sqlite3_close(db); + ret = sqlite3_close(db); if (ret == SQLITE_BUSY) { sqlite3_mutex_enter(db->mutex); @@ -125,29 +174,46 @@ } SQLITE_API int WINAPI sqlite3_open_interop(const char*filename, int flags, sqlite3 **ppdb) { int ret; + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_OPEN) + sqlite3InteropDebug("sqlite3_open_interop(): calling sqlite3_open_v2(\"%s\", %d, %p)...\n", filename, flags, ppdb); +#endif ret = sqlite3_open_v2(filename, ppdb, flags, NULL); + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_OPEN) + sqlite3InteropDebug("sqlite3_open_interop(): sqlite3_open_v2(\"%s\", %d, %p) returned %d.\n", filename, flags, ppdb, ret); +#endif #if defined(INTEROP_EXTENSION_FUNCTIONS) - if (ret == 0) + if (ret == SQLITE_OK) RegisterExtensionFunctions(*ppdb); #endif return ret; } SQLITE_API int WINAPI sqlite3_open16_interop(const char *filename, int flags, sqlite3 **ppdb) { - int ret = sqlite3_open_interop(filename, flags, ppdb); - if (!ret) - { - if(!DbHasProperty(*ppdb, 0, DB_SchemaLoaded)) - ENC(*ppdb) = SQLITE_UTF16NATIVE; - } + int ret; + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_OPEN16) + sqlite3InteropDebug("sqlite3_open16_interop(): calling sqlite3_open_interop(\"%s\", %d, %p)...\n", filename, flags, ppdb); +#endif + + ret = sqlite3_open_interop(filename, flags, ppdb); + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_OPEN16) + sqlite3InteropDebug("sqlite3_open16_interop(): sqlite3_open_interop(\"%s\", %d, %p) returned %d.\n", filename, flags, ppdb, ret); +#endif + + if ((ret == SQLITE_OK) && !DbHasProperty(*ppdb, 0, DB_SchemaLoaded)) + ENC(*ppdb) = SQLITE_UTF16NATIVE; + return ret; } SQLITE_API const char * WINAPI sqlite3_errmsg_interop(sqlite3 *db, int *plen) { @@ -157,22 +223,40 @@ } SQLITE_API int WINAPI sqlite3_prepare_interop(sqlite3 *db, const char *sql, int nbytes, sqlite3_stmt **ppstmt, const char **pztail, int *plen) { int n; + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_PREPARE) + sqlite3InteropDebug("sqlite3_prepare_interop(): calling sqlite3_prepare(%p, \"%s\", %d, %p)...\n", db, sql, nbytes, ppstmt); +#endif n = sqlite3_prepare(db, sql, nbytes, ppstmt, pztail); + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_PREPARE) + sqlite3InteropDebug("sqlite3_prepare_interop(): sqlite3_prepare(%p, \"%s\", %d, %p) returned %d.\n", db, sql, nbytes, ppstmt, n); +#endif + *plen = (*pztail != 0) ? strlen(*pztail) : 0; return n; } SQLITE_API int WINAPI sqlite3_prepare16_interop(sqlite3 *db, const void *sql, int nchars, sqlite3_stmt **ppstmt, const void **pztail, int *plen) { int n; + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_PREPARE16) + sqlite3InteropDebug("sqlite3_prepare_interop(): calling sqlite3_prepare16(%p, \"%s\", %d, %p)...\n", db, sql, nchars, ppstmt); +#endif n = sqlite3_prepare16(db, sql, nchars * sizeof(wchar_t), ppstmt, pztail); + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_PREPARE16) + sqlite3InteropDebug("sqlite3_prepare_interop(): sqlite3_prepare16(%p, \"%s\", %d, %p) returned %d.\n", db, sql, nchars, ppstmt, n); +#endif + *plen = (*pztail != 0) ? wcslen((wchar_t *)*pztail) * sizeof(wchar_t) : 0; return n; } @@ -245,12 +329,24 @@ return pval; } SQLITE_API int WINAPI sqlite3_finalize_interop(sqlite3_stmt *stmt) { + int ret; #if SQLITE_VERSION_NUMBER >= 3007014 - return sqlite3_finalize(stmt); + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_FINALIZE) + sqlite3InteropDebug("sqlite3_finalize_interop(): calling sqlite3_finalize(%p)...\n", stmt); +#endif + + ret = sqlite3_finalize(stmt); + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_FINALIZE) + sqlite3InteropDebug("sqlite3_finalize_interop(): sqlite3_finalize(%p) returned %d.\n", stmt, ret); +#endif + + return ret; #else Vdbe *p; int ret = SQLITE_OK; p = (Vdbe *)stmt; @@ -278,15 +374,25 @@ #endif } SQLITE_API int WINAPI sqlite3_reset_interop(sqlite3_stmt *stmt) { + int ret; #if SQLITE_VERSION_NUMBER >= 3007014 - return sqlite3_reset(stmt); -#else - int ret; + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_RESET) + sqlite3InteropDebug("sqlite3_reset_interop(): calling sqlite3_reset(%p)...\n", stmt); +#endif + + ret = sqlite3_reset(stmt); + +#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_RESET) + sqlite3InteropDebug("sqlite3_reset_interop(): sqlite3_reset(%p) returned %d.\n", stmt, ret); +#endif + return ret; +#else if (((Vdbe *)stmt)->magic == VDBE_MAGIC_DEAD) return SQLITE_SCHEMA; ret = sqlite3_reset(stmt); return ret; #endif } @@ -297,11 +403,11 @@ if (eTextRep == SQLITE_UTF16) eTextRep = SQLITE_UTF16NATIVE; n = sqlite3_create_function(psql, zFunctionName, nArg, eTextRep, 0, func, funcstep, funcfinal); - if (n == 0) + if (n == SQLITE_OK) { if (needCollSeq) { FuncDef *pFunc = sqlite3FindFunction(psql, zFunctionName, strlen(zFunctionName), nArg, eTextRep, 0); if( pFunc ) @@ -488,11 +594,11 @@ SQLITE_API int WINAPI sqlite3_cursor_rowid(sqlite3_stmt *pstmt, int cursor, sqlite_int64 *prowid) { Vdbe *p = (Vdbe *)pstmt; sqlite3 *db = (p == NULL) ? NULL : p->db; VdbeCursor *pC; - int ret = 0; + int ret = SQLITE_OK; sqlite3_mutex_enter(db->mutex); while (1) { if (cursor < 0 || cursor >= p->nCursor) @@ -587,10 +693,9 @@ sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi) - sqlite3_create_function(db, "interopTest", -1, SQLITE_ANY, 0, + return sqlite3_create_function(db, "interopTest", -1, SQLITE_ANY, 0, interopTestFunc, 0, 0); - return 0; } #endif Index: SQLite.NET.Settings.targets ================================================================== --- SQLite.NET.Settings.targets +++ SQLite.NET.Settings.targets @@ -168,11 +168,11 @@ functions will be unavailable. If this is enabled, it must also be enabled via the "INTEROP_EXTENSION_FUNCTIONS=1" preprocessor define being present in the "INTEROP_EXTRA_DEFINES" macro in the build properties file: - "SQLite.Interop\props\SQLite.Interop.20XX.[vs]props" + "SQLite.Interop\props\SQLite.Interop.20YY.[vs]props" for the corresponding version(s) of Visual Studio. --> true @@ -183,11 +183,11 @@ extension will be unavailable. If this is enabled, it must also be enabled via the "INTEROP_TEST_EXTENSION=1" preprocessor define being present in the "INTEROP_DEBUG_DEFINES" macro in the build properties file: - "SQLite.Interop\props\SQLite.Interop.20XX.[vs]props" + "SQLite.Interop\props\SQLite.Interop.20YY.[vs]props" for the corresponding version(s) of Visual Studio. --> true false @@ -203,16 +203,42 @@ "SQLite.Interop\props\sqlite3.[vs]props" AND via the "INTEROP_CODEC=1" preprocessor define being present in the "INTEROP_EXTRA_DEFINES" macro in the build properties file: - "SQLite.Interop\props\SQLite.Interop.20XX.[vs]props" + "SQLite.Interop\props\SQLite.Interop.20YY.[vs]props" both for the corresponding version(s) of Visual Studio. --> true + + true + false + Index: System.Data.SQLite/SQLiteDefineConstants.cs ================================================================== --- System.Data.SQLite/SQLiteDefineConstants.cs +++ System.Data.SQLite/SQLiteDefineConstants.cs @@ -21,10 +21,14 @@ #endif #if INTEROP_CODEC "INTEROP_CODEC", #endif + +#if INTEROP_DEBUG + "INTEROP_DEBUG", +#endif #if INTEROP_EXTENSION_FUNCTIONS "INTEROP_EXTENSION_FUNCTIONS", #endif Index: System.Data.SQLite/System.Data.SQLite.Properties.targets ================================================================== --- System.Data.SQLite/System.Data.SQLite.Properties.targets +++ System.Data.SQLite/System.Data.SQLite.Properties.targets @@ -136,14 +136,22 @@ --> $(DefineConstants);INTEROP_CODEC + + + $(DefineConstants);INTEROP_DEBUG + + $(DefineConstants);TRACE_CONNECTION Index: Tests/backup.eagle ================================================================== --- Tests/backup.eagle +++ Tests/backup.eagle @@ -80,11 +80,13 @@ for {set i 0} {$i < [llength $params(pages)]} {incr i} { set pages [lindex $params(pages) $i] set callback [lindex $params(callbacks) $i] runTest {test [appendArgs backup-1. $i] {BackupDatabase method} -setup { - setupDb [set fileName(1) :memory:] "" "" "" "" "" false false false memDb + setupDb [set fileName(1) :memory:] "" "" "" "" "" \ + false false false true memDb + setupDb [set fileName(2) [appendArgs backup-1. $i .db]] } -body { set id [object invoke Interpreter.GetActive NextId] set dataSource [file join [getDatabaseDirectory] $fileName(2)] Index: Tests/basic.eagle ================================================================== --- Tests/basic.eagle +++ Tests/basic.eagle @@ -1678,11 +1678,11 @@ lappend result [object invoke -flags +NonPublic \ System.Data.SQLite.UnsafeNativeMethods sqlite3_win32_set_directory 2 \ $directory(temp)] - setupDb [set fileName data-1.33.db] "" "" "" "" "" false false + setupDb [set fileName data-1.33.db] "" "" "" "" "" false false false false sql execute $db "CREATE TABLE t1(x NOT NULL);" for {set i 1} {$i < 100} {incr i} { sql execute $db "INSERT INTO t1 (x) VALUES(?);" [list param1 String $i] Index: Tests/common.eagle ================================================================== --- Tests/common.eagle +++ Tests/common.eagle @@ -355,10 +355,11 @@ return [uplevel 1 [list subst [appendArgs $prefix { if {[hasRuntimeOption native]} then { object invoke Interpreter.GetActive AddRuntimeOption native } + set ::test_channel {$::test_channel} set ::path {$::path} set ::test_year {[getBuildYear]} set ::test_configuration {[getBuildConfiguration]} } $suffix]]] } @@ -631,11 +632,12 @@ [string range $fileName 0 12] eq "file::memory:"}] } proc setupDb { fileName {mode ""} {dateTimeFormat ""} {dateTimeKind ""} {flags ""} - {extra ""} {qualify true} {delete true} {uri false} {varName db} } { + {extra ""} {qualify true} {delete true} {uri false} + {temporary true} {varName db} } { # # NOTE: First, see if our caller has requested an in-memory database. # set isMemory [isMemoryDb $fileName] @@ -762,14 +764,21 @@ # set db [sql open -type SQLite [subst $connection]] # # NOTE: Configure the temporary directory for the newly opened database - # connection now. + # connection now unless the caller forbids it. + # + if {$temporary} then { + sql execute $db [appendArgs \ + "PRAGMA temp_store_directory = \"" [getTemporaryDirectory] "\";"] + } + + # + # NOTE: Always return the connection handle upon success. # - sql execute $db [appendArgs \ - "PRAGMA temp_store_directory = \"" [getTemporaryDirectory] "\";"] + return $db } proc getDbConnection { {varName db} } { # # NOTE: Refer to the specified variable (e.g. "db") in the context of our Index: Tests/stress.eagle ================================================================== --- Tests/stress.eagle +++ Tests/stress.eagle @@ -113,11 +113,11 @@ # cleanupFile $fileName(2) ############################################################################# - setupDb $fileName(1) "" "" "" "" "" false false true srcDb + setupDb $fileName(1) "" "" "" "" "" false false true true srcDb setupDb $fileName(2) ############################################################################# set workload(1) [list [list srcFileName dstFileName table count] { Index: Tests/tkt-2ce0870fad.eagle ================================================================== --- Tests/tkt-2ce0870fad.eagle +++ Tests/tkt-2ce0870fad.eagle @@ -41,10 +41,11 @@ # # NOTE: Keep track of whether or not the global test year and configuration # variables already exist in the primary application domain before the # test. If not, we will need to unset them after the test. # + set hadTestChannel {[info exists ::test_channel]} set hadTestYear {[info exists ::test_year]} set hadTestYearClrV2 {[info exists ::test_year_clr_v2]} set hadTestYearClrV4 {[info exists ::test_year_clr_v4]} set hadTestConfiguration {[info exists ::test_configuration]} }] -body { @@ -79,10 +80,14 @@ if {!$hadTestYear} then { unset -nocomplain ::test_year } + if {!$hadTestChannel} then { + unset -nocomplain ::test_channel + } + # # NOTE: If this is the primary application domain, skip unsetting the # loop variable because the surrounding [for] command still needs # it. # @@ -89,11 +94,11 @@ if {$i <= 1} then { unset -nocomplain i } unset -nocomplain assembly appDomainId db fileName hadTestConfiguration \ - hadTestYearClrV4 hadTestYearClrV2 hadTestYear + hadTestYearClrV4 hadTestYearClrV2 hadTestYear hadTestChannel } -constraints {eagle monoBug28 command.sql compile.DATA\ compile.ISOLATED_INTERPRETERS SQLite System.Data.SQLite} -isolationLevel \ [expr {$i == 1 ? "AppDomain" : "Default"}] -match regexp -result \ {^\d+ \d+ True System#Data#SQLite#SQLiteConnection#\d+$}} } Index: Tests/tkt-ac47dd230a.eagle ================================================================== --- Tests/tkt-ac47dd230a.eagle +++ Tests/tkt-ac47dd230a.eagle @@ -21,11 +21,11 @@ ############################################################################### runTest {test tkt-ac47dd230a-1.1 {multiple AppDomains} -setup { for {set i 1} {$i < 3} {incr i} { set appDomain($i) [object invoke AppDomain CreateDomain \ - tkt-ac47dd230a-1.1.$i] + [appendArgs tkt-ac47dd230a-1.1. $i]] set result null set interpreterHelper($i) [object invoke -alias InterpreterHelper \ Create $appDomain($i) null Default Default null null null result]