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