Index: Externals/Eagle/lib/Eagle1.0/init.eagle ================================================================== --- Externals/Eagle/lib/Eagle1.0/init.eagle +++ Externals/Eagle/lib/Eagle1.0/init.eagle @@ -766,10 +766,40 @@ # # NOTE: By default, we do not want to persist the generated assembly # to disk. # $parameters GenerateInMemory true + + # + # NOTE: Make sure that the "standard" preprocessor defines match those + # for the platform (i.e. the ones used to compile the Eagle core + # library assembly). + # + set platformOptions [expr { \ + [info exists ::eagle_platform(compileOptions)] ? \ + $::eagle_platform(compileOptions) : [list]}] + + if {[llength $platformOptions] > 0} then { + # + # NOTE: Grab the existing compiler options, if any. + # + set compilerOptions [$parameters CompilerOptions] + + if {"DEBUG" in $platformOptions} then { + append compilerOptions " /define:DEBUG" + } + + if {"TRACE" in $platformOptions} then { + append compilerOptions " /define:TRACE" + } + + # + # NOTE: Reset the compiler options to the pre-existing ones plus the + # extra defines we may have added (above). + # + $parameters CompilerOptions $compilerOptions + } # # NOTE: Process any extra compiler settings the caller may have # provided. # Index: Externals/Eagle/lib/Eagle1.0/vendor.eagle ================================================================== --- Externals/Eagle/lib/Eagle1.0/vendor.eagle +++ Externals/Eagle/lib/Eagle1.0/vendor.eagle @@ -31,15 +31,28 @@ # support namespaces ourselves, we do not want to pollute the global # namespace if this script actually ends up being evaluated in Tcl. # namespace eval ::Eagle { if {[isEagle]} then { - # - # NOTE: This script library helper procedure helps to establish the link - # between the System.Data.SQLite test package and Eagle. - # - proc addTestSuiteToAutoPath { channel quiet } { + proc checkForTestOverrides { channel varNames quiet } { + set result 0 + + foreach varName $varNames { + if {[uplevel 1 [list info exists $varName]]} then { + incr result + + if {!$quiet} then { + puts -nonewline $channel [appendArgs \ + "Found vendor-specific test override \"" $varName "\".\n"] + } + } + } + + return $result + } + + proc addTestSuiteToAutoPath { channel varName quiet } { # # NOTE: Start with the directory containing this file. # set dir [file normalize [file dirname [info script]]] @@ -55,14 +68,22 @@ # if {[file exists [file join $dir Tests]] && \ [file isdirectory [file join $dir Tests]] && \ [file exists [file join $dir Tests pkgIndex.eagle]] && \ [file isfile [file join $dir Tests pkgIndex.eagle]]} then { + # + # NOTE: If requested, give the caller access to the name of the + # directory we just found. + # + if {[string length $varName] > 0} then { + upvar 1 $varName dir2 + } + # # NOTE: Ok, show the directory we found. # - set dir [file join $dir Tests] + set dir2 [file join $dir Tests] # # NOTE: We found the necessary directory to add to the auto-path; # However, we cannot simply add it to the auto-path directly # because the auto-path is dynamically constructed after this @@ -69,26 +90,26 @@ # script is evaluated; therefore, set the Eagle library path # environment variable and force the appropriate internal path # list to be refreshed. # if {![info exists ::env(EAGLELIBPATH)] || \ - [lsearch -exact $::env(EAGLELIBPATH) $dir] == -1} then { + [lsearch -exact $::env(EAGLELIBPATH) $dir2] == -1} then { # # NOTE: If we have NOT been instructed to be quiet, report now. # if {!$quiet} then { puts -nonewline $channel [appendArgs \ - "Found vendor-specific test package directory \"" $dir \ + "Found vendor-specific test package directory \"" $dir2 \ "\", adding...\n"] } # # NOTE: Append the directory to the necessary environment variable # so that it will get picked up when Eagle actually rebuilds # the auto-path list (below). # - lappend ::env(EAGLELIBPATH) $dir + lappend ::env(EAGLELIBPATH) $dir2 # # NOTE: Force Eagle to rebuild the auto-path list for the current # interpreter right now. # @@ -119,34 +140,46 @@ # NOTE: Directory not found, return failure. # return false } - proc checkForTestOverrides { channel varNames quiet } { - set result 0 - - foreach varName $varNames { - if {[uplevel 1 [list info exists $varName]]} then { - incr result - - if {!$quiet} then { - puts -nonewline $channel [appendArgs \ - "Found vendor-specific test override \"" $varName "\".\n"] - } - } - } - - return $result + proc setupInterpreterTestPath { channel dir quiet } { + object invoke -flags +NonPublic Interpreter.GetActive TestPath $dir + + if {!$quiet} then { + puts -nonewline $channel [appendArgs \ + "Set interpreter test path to \"" $dir \".\n] + } } checkForTestOverrides stdout \ [list binary_directory build_base_directory build_directory \ common_directory datetime_format test_configuration \ test_year] false - addTestSuiteToAutoPath stdout false + # + # NOTE: This variable will contain the name of the directory containing the + # vendor-specific testing infrastructure. + # + set ::vendor_directory "" + + # + # NOTE: This procedure will attempt to find the vendor-specific testing + # infrastructure directory and add it to the auto-path for the + # current interpreter. + # + addTestSuiteToAutoPath stdout ::vendor_directory false + + # + # NOTE: If we actually found a vendor-specific testing infrastructure + # directory then modify the TestPath property of the current + # interpreter to point directly to it. + # + if {[string length $::vendor_directory] > 0} then { + setupInterpreterTestPath stdout $::vendor_directory false + } } } ############################################################################### ############################### END VENDOR CODE ############################### ############################################################################### Index: SQLite.Interop/src/win/interop.c ================================================================== --- SQLite.Interop/src/win/interop.c +++ SQLite.Interop/src/win/interop.c @@ -81,10 +81,16 @@ if (ret) { // finalize failed -- so we must put back anything we munged CopyMemory(po, p, sizeof(Vdbe)); db->pVdbe = po; + + // + // NOTE: Ok, we must free this block that *we* allocated (above) since + // finalize did not do so. + // + sqlite3DbFree_interop(db, p); break; } else { ZeroMemory(po, sizeof(Vdbe)); Index: System.Data.SQLite/SQLite3.cs ================================================================== --- System.Data.SQLite/SQLite3.cs +++ System.Data.SQLite/SQLite3.cs @@ -6,10 +6,13 @@ ********************************************************/ namespace System.Data.SQLite { using System; +#if DEBUG + using System.Diagnostics; +#endif using System.Runtime.InteropServices; #if !PLATFORM_COMPACTFRAMEWORK [UnmanagedFunctionPointer(CallingConvention.Cdecl)] #endif @@ -45,12 +48,11 @@ { } protected override void Dispose(bool bDisposing) { - if (bDisposing) - Close(); + Close(); } // It isn't necessary to cleanup any functions we've registered. If the connection // goes to the pool and is resurrected later, re-registered functions will overwrite the // previous functions. The SQLiteFunctionCookieHandle will take care of freeing unmanaged @@ -89,10 +91,18 @@ get { return UTF8ToString(UnsafeNativeMethods.sqlite3_libversion(), -1); } } + + internal static string SQLiteSourceId + { + get + { + return UTF8ToString(UnsafeNativeMethods.sqlite3_sourceid(), -1); + } + } internal override bool AutoCommit { get { @@ -166,10 +176,15 @@ #if !SQLITE_STANDARD int n = UnsafeNativeMethods.sqlite3_open_interop(ToUTF8(strFilename), (int)flags, out db); #else int n = UnsafeNativeMethods.sqlite3_open_v2(ToUTF8(strFilename), out db, (int)flags, IntPtr.Zero); #endif + +#if DEBUG + Trace.WriteLine(String.Format("Open: {0}", db)); +#endif + if (n > 0) throw new SQLiteException(n, null); _sql = db; } // Bind functions to this connection. If any previous functions of the same name @@ -321,10 +336,14 @@ n = UnsafeNativeMethods.sqlite3_prepare_interop(_sql, psql, b.Length - 1, out stmt, out ptr, out len); #else n = UnsafeNativeMethods.sqlite3_prepare(_sql, psql, b.Length - 1, out stmt, out ptr); len = -1; #endif + +#if DEBUG + Trace.WriteLine(String.Format("Prepare: {0}", stmt)); +#endif if (n == 17) retries++; else if (n == 1) { Index: System.Data.SQLite/SQLite3_UTF16.cs ================================================================== --- System.Data.SQLite/SQLite3_UTF16.cs +++ System.Data.SQLite/SQLite3_UTF16.cs @@ -6,10 +6,13 @@ ********************************************************/ namespace System.Data.SQLite { using System; +#if DEBUG + using System.Diagnostics; +#endif using System.Runtime.InteropServices; /// /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode) /// @@ -61,11 +64,16 @@ #else if ((flags & SQLiteOpenFlagsEnum.Create) == 0 && System.IO.File.Exists(strFilename) == false) throw new SQLiteException((int)SQLiteErrorCode.CantOpen, strFilename); int n = UnsafeNativeMethods.sqlite3_open16(strFilename, out db); +#endif + +#if DEBUG + Trace.WriteLine(String.Format("Open: {0}", db)); #endif + if (n > 0) throw new SQLiteException(n, null); _sql = db; } _functionsArray = SQLiteFunction.BindFunctions(this); Index: System.Data.SQLite/SQLiteCommand.cs ================================================================== --- System.Data.SQLite/SQLiteCommand.cs +++ System.Data.SQLite/SQLiteCommand.cs @@ -219,32 +219,37 @@ { SQLiteStatement stmt = null; try { - if (_statementList == null) - _remainingText = _commandText; - - stmt = _cnn._sql.Prepare(_cnn, _remainingText, (_statementList == null) ? null : _statementList[_statementList.Count - 1], (uint)(_commandTimeout * 1000), out _remainingText); - if (stmt != null) - { - stmt._command = this; - if (_statementList == null) - _statementList = new List(); - - _statementList.Add(stmt); - - _parameterCollection.MapParameters(stmt); - stmt.BindParameters(); - } + if ((_cnn != null) && (_cnn._sql != null)) + { + if (_statementList == null) + _remainingText = _commandText; + + stmt = _cnn._sql.Prepare(_cnn, _remainingText, (_statementList == null) ? null : _statementList[_statementList.Count - 1], (uint)(_commandTimeout * 1000), out _remainingText); + + if (stmt != null) + { + stmt._command = this; + + if (_statementList == null) + _statementList = new List(); + + _statementList.Add(stmt); + + _parameterCollection.MapParameters(stmt); + stmt.BindParameters(); + } + } return stmt; } catch (Exception) { if (stmt != null) { - if (_statementList.Contains(stmt)) + if ((_statementList != null) && _statementList.Contains(stmt)) _statementList.Remove(stmt); stmt.Dispose(); } Index: System.Data.SQLite/SQLiteConnection.cs ================================================================== --- System.Data.SQLite/SQLiteConnection.cs +++ System.Data.SQLite/SQLiteConnection.cs @@ -485,12 +485,12 @@ } #endif if (_sql != null) { _sql.Close(); + _sql = null; } - _sql = null; _transactionLevel = 0; } OnStateChange(ConnectionState.Closed); } @@ -1077,10 +1077,20 @@ /// public static string SQLiteVersion { get { return SQLite3.SQLiteVersion; } } + + /// + /// This method returns the string whose value is the same as the + /// SQLITE_SOURCE_ID C preprocessor macro used when compiling the + /// SQLite core library. + /// + public static string SQLiteSourceId + { + get { return SQLite3.SQLiteSourceId; } + } /// /// Returns the state of the connection. /// #if !PLATFORM_COMPACTFRAMEWORK Index: System.Data.SQLite/SQLiteLog.cs ================================================================== --- System.Data.SQLite/SQLiteLog.cs +++ System.Data.SQLite/SQLiteLog.cs @@ -283,10 +283,35 @@ public static bool Enabled { get { lock (syncRoot) { return _enabled; } } set { lock (syncRoot) { _enabled = value; } } } + + /// + /// Log a message to all the registered log event handlers without going + /// through the SQLite library. + /// + /// The error code or zero for success. + /// The message to be logged. + public static void LogMessage( + int errorCode, + string message + ) + { + bool enabled; + SQLiteLogEventHandler handlers; + + lock (syncRoot) + { + enabled = _enabled; + handlers = _handlers; + } + + if (enabled && (handlers != null)) + handlers(null, new LogEventArgs( + IntPtr.Zero, errorCode, message, null)); + } /// /// Creates and initializes the default log event handler. /// private static void InitializeDefaultHandler() @@ -355,15 +380,25 @@ return; string message = e.Message; if (message == null) + { message = ""; - else if (message.Length == 0) - message = ""; + } + else + { + message = message.Trim(); + + if (message.Length == 0) + message = ""; + } + + int errorCode = e.ErrorCode; - Trace.WriteLine(String.Format("SQLite error ({0}): {1}", - e.ErrorCode, message)); + Trace.WriteLine(String.Format( + "SQLite {0} ({1}): {2}", errorCode == 0 ? + "message" : "error", errorCode, message)); } } #endif } Index: System.Data.SQLite/UnsafeNativeMethods.cs ================================================================== --- System.Data.SQLite/UnsafeNativeMethods.cs +++ System.Data.SQLite/UnsafeNativeMethods.cs @@ -6,10 +6,13 @@ ********************************************************/ namespace System.Data.SQLite { using System; +#if DEBUG + using System.Diagnostics; +#endif #if !PLATFORM_COMPACTFRAMEWORK && !DEBUG using System.Security; #endif @@ -349,10 +352,17 @@ #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_libversion(); +#if !PLATFORM_COMPACTFRAMEWORK + [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] +#else + [DllImport(SQLITE_DLL)] +#endif + internal static extern IntPtr sqlite3_sourceid(); + #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif @@ -872,15 +882,49 @@ protected override bool ReleaseHandle() { try { SQLiteBase.CloseConnection(this); + +#if DEBUG + try + { + Trace.WriteLine(String.Format( + "CloseConnection: {0}", handle)); + } + catch + { + } +#endif + +#if DEBUG + return true; +#endif } +#if DEBUG + catch (SQLiteException e) +#else catch (SQLiteException) +#endif { +#if DEBUG + try + { + Trace.WriteLine(String.Format( + "CloseConnection: {0}, exception: {1}", + handle, e)); + } + catch + { + } +#endif } +#if DEBUG + return false; +#else return true; +#endif } public override bool IsInvalid { get { return (handle == IntPtr.Zero); } @@ -914,18 +958,52 @@ protected override bool ReleaseHandle() { try { SQLiteBase.FinalizeStatement(this); + +#if DEBUG + try + { + Trace.WriteLine(String.Format( + "FinalizeStatement: {0}", handle)); + } + catch + { + } +#endif + +#if DEBUG + return true; +#endif } +#if DEBUG + catch (SQLiteException e) +#else catch (SQLiteException) +#endif { +#if DEBUG + try + { + Trace.WriteLine(String.Format( + "FinalizeStatement: {0}, exception: {1}", + handle, e)); + } + catch + { + } +#endif } +#if DEBUG + return false; +#else return true; +#endif } public override bool IsInvalid { get { return (handle == IntPtr.Zero); } } } } Index: Tests/common.eagle ================================================================== --- Tests/common.eagle +++ Tests/common.eagle @@ -302,16 +302,28 @@ proc checkForSQLite { channel } { tputs $channel "---- checking for core SQLite library... " if {[catch {object invoke -flags +NonPublic System.Data.SQLite.SQLite3 \ SQLiteVersion} version] == 0} then { + # + # NOTE: Attempt to query the Fossil source identifier for the SQLite + # core library. + # + if {[catch {object invoke -flags +NonPublic System.Data.SQLite.SQLite3 \ + SQLiteSourceId} sourceId]} then { + # + # NOTE: We failed to query the Fossil source identifier. + # + set sourceId unknown + } + # # NOTE: Yes, the SQLite core library appears to be available. # addConstraint SQLite - tputs $channel [appendArgs "yes (" $version ")\n"] + tputs $channel [appendArgs "yes (" $version " " $sourceId ")\n"] } else { tputs $channel no\n } } @@ -400,14 +412,21 @@ # set fileName [file join [getTemporaryPath] [file tail $fileName]] # # NOTE: By default, delete any pre-existing database with the same file - # name. + # name if it currently exists. # - if {$delete} then { - catch {file delete $fileName} + if {$delete && [file exists $fileName]} then { + if {[catch {file delete $fileName} error]} then { + # + # NOTE: We somehow failed to delete the file, report why. + # + tputs $::test_channel [appendArgs \ + "==== WARNING: failed to delete database file \"" $fileName \ + "\" during setup, error: " \n\t $error \n] + } } # # NOTE: Refer to the specified variable (e.g. "db") in the context of the # caller. The handle to the opened database will be stored there. @@ -468,45 +487,84 @@ # # NOTE: Close the connection to the database now. This should allow us to # delete the underlying database file. # - catch {sql close $db} + if {[info exists db] && [catch {sql close $db} error]} then { + # + # NOTE: We somehow failed to close the database, report why. + # + tputs $::test_channel [appendArgs \ + "==== WARNING: failed to close database \"" $db "\", error: " \ + \n\t $error \n] + } # - # NOTE: Delete the test database file now. For now, all test database - # files are stored in the temporary directory. + # NOTE: Attempt to delete the test database file now. For now, all test + # database files are stored in the temporary directory. # - catch {file delete [file join [getTemporaryPath] [file tail $fileName]]} + set fileName [file join [getTemporaryPath] [file tail $fileName]] + + if {[catch {file delete $fileName} error]} then { + # + # NOTE: We somehow failed to delete the file, report why. + # + tputs $::test_channel [appendArgs \ + "==== WARNING: failed to delete database file \"" $fileName \ + "\" during cleanup, error: " \n\t $error \n] + } } - proc reportSQLiteResources { channel } { - tputs $channel "---- current memory in use by SQLite... " + proc reportSQLiteResources { channel {quiet false} } { + # + # NOTE: Skip all output if we are running in "quiet" mode. + # + if {!$quiet} then { + tputs $channel "---- current memory in use by SQLite... " + } if {[catch {object invoke -flags +NonPublic \ System.Data.SQLite.UnsafeNativeMethods \ sqlite3_memory_used} memory] == 0} then { - tputs $channel [appendArgs $memory " bytes\n"] + if {!$quiet} then { + tputs $channel [appendArgs $memory " bytes\n"] + } } else { # # NOTE: Maybe the SQLite native library is unavailable? # - tputs $channel unknown\n + set memory unknown + + if {!$quiet} then { + tputs $channel [appendArgs $memory \n] + } } - tputs $channel "---- maximum memory in use by SQLite... " + set result $memory; # NOTE: Return memory in-use to caller. + + if {!$quiet} then { + tputs $channel "---- maximum memory in use by SQLite... " + } if {[catch {object invoke -flags +NonPublic \ System.Data.SQLite.UnsafeNativeMethods \ sqlite3_memory_highwater 0} memory] == 0} then { - tputs $channel [appendArgs $memory " bytes\n"] + if {!$quiet} then { + tputs $channel [appendArgs $memory " bytes\n"] + } } else { # # NOTE: Maybe the SQLite native library is unavailable? # - tputs $channel unknown\n + set memory unknown + + if {!$quiet} then { + tputs $channel [appendArgs $memory \n] + } } + + return $result } proc runSQLiteTestPrologue {} { # # NOTE: Skip running our custom prologue if the main one has been skipped. @@ -519,19 +577,21 @@ if {![info exists ::no(sqliteFiles)]} then { # # NOTE: Skip trying to delete any files if we are so instructed. # if {![info exists ::no(deleteSqliteFiles)]} then { + tryDeleteAssembly sqlite3.dll tryDeleteAssembly SQLite.Interop.dll tryDeleteAssembly System.Data.SQLite.dll tryDeleteAssembly System.Data.SQLite.Linq.dll } # # NOTE: Skip trying to copy any files if we are so instructed. # if {![info exists ::no(copySqliteFiles)]} then { + tryCopyAssembly sqlite3.dll tryCopyAssembly SQLite.Interop.dll tryCopyAssembly System.Data.SQLite.dll tryCopyAssembly System.Data.SQLite.Linq.dll } ADDED Tests/tkt-e30b820248.eagle Index: Tests/tkt-e30b820248.eagle ================================================================== --- /dev/null +++ Tests/tkt-e30b820248.eagle @@ -0,0 +1,274 @@ +############################################################################### +# +# tkt-e30b820248.eagle -- +# +# Written by Joe Mistachkin. +# Released to the public domain, use at your own risk! +# +############################################################################### + +package require Eagle +package require EagleLibrary +package require EagleTest + +runTestPrologue + +############################################################################### + +package require System.Data.SQLite.Test +runSQLiteTestPrologue + +############################################################################### + +set memory_used [reportSQLiteResources $test_channel true] + +############################################################################### + +runTest {test tkt-e30b820248-1.1 {disposal ordering} -setup { + set fileName tkt-e30b820248-1.1.db +} -body { + set id [object invoke Interpreter.GetActive NextId] + set dataSource [file join [getTemporaryPath] $fileName] + set name [file rootname [file tail $fileName]] + + set sql { \ + CREATE TABLE t1 (id1 INTEGER); \ + INSERT INTO t1 (id1) VALUES (1); \ + INSERT INTO t1 (id1) VALUES (2); \ + INSERT INTO t1 (id1) VALUES (?); \ + INSERT INTO t1 (id1) VALUES (?); \ + INSERT INTO t1 (id1) VALUES (?); \ + SELECT * FROM t1 ORDER BY id1; \ + } + + unset -nocomplain results errors + + set code [compileCSharpWith [subst { + using System.Data.SQLite; + using System.Diagnostics; + using System.IO; + + namespace _Dynamic${id} + { + public class Test${id} + { + public static void Main() + { + using (TraceListener listener = new TextWriterTraceListener( + new FileStream("${test_log}", FileMode.Append, + FileAccess.Write, FileShare.ReadWrite), "${name}")) + { + Trace.Listeners.Add(listener); + Trace.WriteLine("---- START TRACE \\"${name}\\""); + + using (SQLiteConnection connection = new SQLiteConnection( + "Data Source=${dataSource};")) + { + connection.Open(); + connection.LogMessage(0, "Connection opened."); + + using (SQLiteTransaction transaction = + connection.BeginTransaction()) + { + connection.LogMessage(0, "Transaction started."); + + using (SQLiteCommand command = connection.CreateCommand()) + { + command.Transaction = transaction; + command.CommandText = "${sql}"; + + command.Parameters.AddWithValue("x", 3); + command.Parameters.AddWithValue("y", 4); + command.Parameters.AddWithValue("z", 5); + + command.ExecuteNonQuery(); + connection.LogMessage(0, "Command executed."); + } + + transaction.Commit(); + connection.LogMessage(0, "Transaction committed."); + } + } + + Trace.WriteLine("---- END TRACE \\"${name}\\""); + Trace.Listeners.Remove(listener); + } + } + } + } + }] results errors System.Data.SQLite.dll] + + list $code $results \ + [expr {[info exists errors] ? $errors : ""}] \ + [expr {$code eq "Ok" ? [catch { + object invoke _Dynamic${id}.Test${id} Main + } result] : [set result ""]}] $result \ + [reportSQLiteResources $test_channel true] +} -cleanup { + cleanupDb $fileName + + unset -nocomplain result code results errors sql dataSource id db fileName +} -constraints \ +{eagle logFile monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \ +-match regexp -result [appendArgs "^Ok\ +System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{\\} " $memory_used \$]} + +############################################################################### + +for {set i 2} {$i < 5} {incr i} { + set memory_used [reportSQLiteResources $test_channel true] + + ############################################################################# + + runTest {test [appendArgs tkt-e30b820248-1. $i] {disposal ordering} -setup { + set fileName [appendArgs tkt-e30b820248-1. $i .db] + } -body { + set id [object invoke Interpreter.GetActive NextId] + set dataSource [file join [getTemporaryPath] $fileName] + set name [file rootname [file tail $fileName]] + + set sql { \ + CREATE TABLE t1 (id1 INTEGER); \ + INSERT INTO t1 (id1) VALUES (1); \ + INSERT INTO t1 (id1) VALUES (2); \ + INSERT INTO t1 (id1) VALUES (3); \ + INSERT INTO t1 (id1) VALUES (4); \ + INSERT INTO t1 (id1) VALUES (5); \ + SELECT * FROM t1 ORDER BY id1; \ + } + + unset -nocomplain results errors + + set code [compileCSharpWith [subst { + using System; + using System.Data.SQLite; + using System.Diagnostics; + using System.IO; + + namespace _Dynamic${id} + { + public class Test${id} + { + #region Private Static Data + private static SQLiteConnection connection; + #endregion + + ///////////////////////////////////////////////////////////////////// + + #region Public Static Methods + public static void OpenConnection() + { + connection = new SQLiteConnection("Data Source=${dataSource};"); + connection.Open(); + connection.LogMessage(0, "Connection opened."); + } + + ///////////////////////////////////////////////////////////////////// + + public static SQLiteCommand CreateCommand(string sql) + { + SQLiteCommand command = connection.CreateCommand(); + command.CommandText = sql; + connection.LogMessage(0, "Command created."); + return command; + } + + ///////////////////////////////////////////////////////////////////// + + public static SQLiteDataReader ExecuteReader(SQLiteCommand command) + { + SQLiteDataReader dataReader = command.ExecuteReader(); + connection.LogMessage(0, "Command executed."); + return dataReader; + } + + ///////////////////////////////////////////////////////////////////// + + public static SQLiteDataReader ExecuteReader(string sql) + { + SQLiteCommand command = CreateCommand(sql); + SQLiteDataReader dataReader = command.ExecuteReader(); + connection.LogMessage(0, "Command executed."); + return dataReader; + } + + ///////////////////////////////////////////////////////////////////// + + public static void CloseConnection() + { + connection.LogMessage(0, "Closing connection..."); + connection.Close(); + } + #endregion + + ///////////////////////////////////////////////////////////////////// + + public static void Main() + { + using (TraceListener listener = new TextWriterTraceListener( + new FileStream("${test_log}", FileMode.Append, + FileAccess.Write, FileShare.ReadWrite), "${name}")) + { + Trace.Listeners.Add(listener); + Trace.WriteLine("---- START TRACE \\"${name}\\""); + + OpenConnection(); + SQLiteDataReader dataReader = ExecuteReader("${sql}"); + + [expr {$i <= 2 ? { + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + } : ""}] + + dataReader.Close(); + + [expr {$i <= 3 ? { + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + } : ""}] + + CloseConnection(); + + [expr {$i <= 4 ? { + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + } : ""}] + + Trace.WriteLine("---- END TRACE \\"${name}\\""); + Trace.Listeners.Remove(listener); + } + } + } + } + }] results errors System.Data.SQLite.dll] + + list $code $results \ + [expr {[info exists errors] ? $errors : ""}] \ + [expr {$code eq "Ok" ? [catch { + object invoke _Dynamic${id}.Test${id} Main + } result] : [set result ""]}] $result \ + [reportSQLiteResources $test_channel true] + } -cleanup { + cleanupDb $fileName + + unset -nocomplain result code results errors sql dataSource id db fileName + } -constraints {eagle logFile monoBug28 command.sql compile.DATA SQLite\ +System.Data.SQLite} -match regexp -result [appendArgs "^Ok\ +System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{\\} " $memory_used \$]} +} + +############################################################################### + +unset -nocomplain i + +############################################################################### + +unset -nocomplain memory_used + +############################################################################### + +runSQLiteTestEpilogue +runTestEpilogue