Index: Doc/Extra/version.html
==================================================================
--- Doc/Extra/version.html
+++ Doc/Extra/version.html
@@ -52,10 +52,11 @@
Add experimental support for the native regexp extension.
Never create a new connection wrapper in the SQLiteConnection.Shutdown method. ** Potentially Incompatible Change **
Add experimental GetMemoryStatistics, ReleaseMemory, and Shutdown methods to the SQLiteConnection class.
Add memory leak detection to the test project for the .NET Compact Framework.
Add SQLITE_ENABLE_MEMORY_MANAGEMENT compile-time option to the interop assembly.
+ Use current isolation level when enlisting into an existing transaction. Fix for [56b42d99c1].
Better handling of non-error log messages from the SQLite core library. Pursuant to [44df10ea90].
Add TraceWarning connection flag to enable tracing of type mapping failures and disable tracing of them by default. Pursuant to [6d45c782e4].
Use 32-bit values to keep track of numeric precision and scale when building the schema table for a query. Fix for [ef2216192d].
1.0.89.0 - October 28, 2013
Index: System.Data.SQLite/SQLiteConnection.cs
==================================================================
--- System.Data.SQLite/SQLiteConnection.cs
+++ System.Data.SQLite/SQLiteConnection.cs
@@ -1106,10 +1106,37 @@
StateChange(this, localEventArgs);
eventArgs = localEventArgs;
}
}
+
+#if !PLATFORM_COMPACTFRAMEWORK
+ ///
+ /// Determines and returns the fallback default isolation level when one cannot be
+ /// obtained from an existing connection instance.
+ ///
+ ///
+ /// The fallback default isolation level for this connection instance -OR-
+ /// if it cannot be determined.
+ ///
+ internal static IsolationLevel GetFallbackDefaultIsolationLevel()
+ {
+ return DefaultIsolationLevel;
+ }
+
+ ///
+ /// Determines and returns the default isolation level for this connection instance.
+ ///
+ ///
+ /// The default isolation level for this connection instance -OR-
+ /// if it cannot be determined.
+ ///
+ internal IsolationLevel GetDefaultIsolationLevel()
+ {
+ return _defaultIsolation;
+ }
+#endif
///
/// OBSOLETE. Creates a new SQLiteTransaction if one isn't already active on the connection.
///
/// This parameter is ignored.
Index: System.Data.SQLite/SQLiteEnlistment.cs
==================================================================
--- System.Data.SQLite/SQLiteEnlistment.cs
+++ System.Data.SQLite/SQLiteEnlistment.cs
@@ -8,35 +8,98 @@
#if !PLATFORM_COMPACTFRAMEWORK
namespace System.Data.SQLite
{
using System.Transactions;
- internal sealed class SQLiteEnlistment : IEnlistmentNotification, IDisposable
+ internal sealed class SQLiteEnlistment : IDisposable, IEnlistmentNotification
{
internal SQLiteTransaction _transaction;
internal Transaction _scope;
internal bool _disposeConnection;
internal SQLiteEnlistment(SQLiteConnection cnn, Transaction scope)
{
- _transaction = cnn.BeginTransaction();
+ _transaction = cnn.BeginTransaction(GetSystemDataIsolationLevel(
+ cnn, scope));
+
_scope = scope;
_scope.EnlistVolatile(this, System.Transactions.EnlistmentOptions.None);
}
- ///////////////////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
+
+ #region Private Methods
+ private System.Data.IsolationLevel GetSystemDataIsolationLevel(
+ SQLiteConnection connection,
+ Transaction transaction
+ )
+ {
+ if (transaction == null)
+ {
+ //
+ // TODO: Perhaps throw an exception here if the connection
+ // is null?
+ //
+ return (connection != null) ?
+ connection.GetDefaultIsolationLevel() :
+ SQLiteConnection.GetFallbackDefaultIsolationLevel();
+ }
+
+ System.Transactions.IsolationLevel isolationLevel =
+ transaction.IsolationLevel;
+
+ //
+ // TODO: Are these isolation level mappings actually correct?
+ //
+ switch (isolationLevel)
+ {
+ case IsolationLevel.Chaos:
+ return System.Data.IsolationLevel.Chaos;
+ case IsolationLevel.ReadCommitted:
+ return System.Data.IsolationLevel.ReadCommitted;
+ case IsolationLevel.ReadUncommitted:
+ return System.Data.IsolationLevel.ReadUncommitted;
+ case IsolationLevel.RepeatableRead:
+ return System.Data.IsolationLevel.RepeatableRead;
+ case IsolationLevel.Serializable:
+ return System.Data.IsolationLevel.Serializable;
+ case IsolationLevel.Snapshot:
+ return System.Data.IsolationLevel.Snapshot;
+ case IsolationLevel.Unspecified:
+ return System.Data.IsolationLevel.Unspecified;
+ }
+
+ //
+ // TODO: Perhaps throw an exception here?
+ //
+ return SQLiteConnection.GetFallbackDefaultIsolationLevel();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ private void Cleanup(SQLiteConnection cnn)
+ {
+ if (_disposeConnection)
+ cnn.Dispose();
+
+ _transaction = null;
+ _scope = null;
+ }
+ #endregion
+
+ ///////////////////////////////////////////////////////////////////////////
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
- ///////////////////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
#region IDisposable "Pattern" Members
private bool disposed;
private void CheckDisposed() /* throw */
{
@@ -44,11 +107,11 @@
if (disposed)
throw new ObjectDisposedException(typeof(SQLiteEnlistment).Name);
#endif
}
- ///////////////////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
private /* protected virtual */ void Dispose(bool disposing)
{
if (!disposed)
{
@@ -78,32 +141,22 @@
disposed = true;
}
}
#endregion
- ///////////////////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
#region Destructor
~SQLiteEnlistment()
{
Dispose(false);
}
#endregion
- ///////////////////////////////////////////////////////////////////////////////////////////////
-
- private void Cleanup(SQLiteConnection cnn)
- {
- if (_disposeConnection)
- cnn.Dispose();
-
- _transaction = null;
- _scope = null;
- }
+ ///////////////////////////////////////////////////////////////////////////
#region IEnlistmentNotification Members
-
public void Commit(Enlistment enlistment)
{
CheckDisposed();
SQLiteConnection cnn = _transaction.Connection;
@@ -121,15 +174,19 @@
{
Cleanup(cnn);
}
}
+ ///////////////////////////////////////////////////////////////////////////
+
public void InDoubt(Enlistment enlistment)
{
CheckDisposed();
enlistment.Done();
}
+
+ ///////////////////////////////////////////////////////////////////////////
public void Prepare(PreparingEnlistment preparingEnlistment)
{
CheckDisposed();
@@ -136,10 +193,12 @@
if (_transaction.IsValid(false) == false)
preparingEnlistment.ForceRollback();
else
preparingEnlistment.Prepared();
}
+
+ ///////////////////////////////////////////////////////////////////////////
public void Rollback(Enlistment enlistment)
{
CheckDisposed();
@@ -154,10 +213,9 @@
finally
{
Cleanup(cnn);
}
}
-
#endregion
}
}
-#endif // !PLATFORM_COMPACT_FRAMEWORK
+#endif // !PLATFORM_COMPACT_FRAMEWORK
Index: Tests/common.eagle
==================================================================
--- Tests/common.eagle
+++ Tests/common.eagle
@@ -1265,12 +1265,14 @@
#
# NOTE: Create the base command to evaluate and add the property settings
# that are almost always needed by our unit tests (i.e. the System
# and System.Data assembly references).
#
- set command [list compileCSharp $text $memory $symbols $strict results \
- errors $add System.dll $add System.Data.dll $add System.Xml.dll]
+ set command [list \
+ compileCSharp $text $memory $symbols $strict results errors \
+ $add System.dll $add System.Data.dll $add System.Transactions.dll \
+ $add System.Xml.dll]
#
# NOTE: Add all the provided file names as assembly references.
#
foreach fileName $fileNames {
ADDED Tests/tkt-56b42d99c1.eagle
Index: Tests/tkt-56b42d99c1.eagle
==================================================================
--- /dev/null
+++ Tests/tkt-56b42d99c1.eagle
@@ -0,0 +1,109 @@
+###############################################################################
+#
+# tkt-56b42d99c1.eagle --
+#
+# Written by Joe Mistachkin.
+# Released to the public domain, use at your own risk!
+#
+###############################################################################
+
+package require Eagle
+package require Eagle.Library
+package require Eagle.Test
+
+runTestPrologue
+
+###############################################################################
+
+package require System.Data.SQLite.Test
+runSQLiteTestPrologue
+
+###############################################################################
+
+runTest {test tkt-56b42d99c1-1.1 {enlisted transaction isolation} -setup {
+ setupDb [set fileName tkt-56b42d99c1-1.1.db]
+} -body {
+ set id [object invoke Interpreter.GetActive NextId]
+ set dataSource [file join [getDatabaseDirectory] $fileName]
+
+ unset -nocomplain results errors
+
+ set code [compileCSharpWith [subst {
+ using System.Data.SQLite;
+ using System.Reflection;
+ using System.Transactions;
+
+ namespace _Dynamic${id}
+ {
+ public static class Test${id}
+ {
+ public static bool TryEnlistInTransaction()
+ {
+ TransactionOptions transactionOptions = new TransactionOptions();
+ transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
+
+ using (TransactionScope transactionScope = new TransactionScope(
+ TransactionScopeOption.Required, transactionOptions))
+ {
+ using (SQLiteConnection connection1 = new SQLiteConnection(
+ "Data Source=${dataSource};"))
+ {
+ connection1.Open();
+
+ using (SQLiteConnection connection2 = new SQLiteConnection(
+ "Data Source=${dataSource};"))
+ {
+ connection2.Open();
+
+ BindingFlags bindingFlags = BindingFlags.Instance |
+ BindingFlags.NonPublic | BindingFlags.GetField;
+
+ FieldInfo fieldInfo1 = connection1.GetType().GetField(
+ "_enlistment", bindingFlags);
+
+ object enlistment1 = fieldInfo1.GetValue(connection1);
+ object enlistment2 = fieldInfo1.GetValue(connection2);
+
+ FieldInfo fieldInfo2 = enlistment1.GetType().GetField(
+ "_transaction", bindingFlags);
+
+ SQLiteTransaction transaction1 =
+ (SQLiteTransaction)fieldInfo2.GetValue(enlistment1);
+
+ SQLiteTransaction transaction2 =
+ (SQLiteTransaction)fieldInfo2.GetValue(enlistment2);
+
+ return (transaction1.IsolationLevel ==
+ transaction2.IsolationLevel);
+ }
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+
+ public static void Main()
+ {
+ // do nothing.
+ }
+ }
+ }
+ }] true true true 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} TryEnlistInTransaction
+ } result] : [set result ""]}] $result
+} -cleanup {
+ cleanupDb $fileName
+
+ unset -nocomplain result results errors code dataSource id db fileName
+} -constraints {eagle monoBug28 command.sql compile.DATA SQLite\
+System.Data.SQLite compileCSharp} -match regexp -result {^Ok\
+System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 True$}}
+
+###############################################################################
+
+runSQLiteTestEpilogue
+runTestEpilogue
Index: readme.htm
==================================================================
--- readme.htm
+++ readme.htm
@@ -197,10 +197,11 @@
Add experimental support for the native regexp extension.
Never create a new connection wrapper in the SQLiteConnection.Shutdown method. ** Potentially Incompatible Change **
Add experimental GetMemoryStatistics, ReleaseMemory, and Shutdown methods to the SQLiteConnection class.
Add memory leak detection to the test project for the .NET Compact Framework.
Add SQLITE_ENABLE_MEMORY_MANAGEMENT compile-time option to the interop assembly.
+ Use current isolation level when enlisting into an existing transaction. Fix for [56b42d99c1].
Better handling of non-error log messages from the SQLite core library. Pursuant to [44df10ea90].
Add TraceWarning connection flag to enable tracing of type mapping failures and disable tracing of them by default. Pursuant to [6d45c782e4].
Use 32-bit values to keep track of numeric precision and scale when building the schema table for a query. Fix for [ef2216192d].
Index: www/news.wiki
==================================================================
--- www/news.wiki
+++ www/news.wiki
@@ -13,10 +13,11 @@
Add experimental support for the native regexp extension.
Never create a new connection wrapper in the SQLiteConnection.Shutdown method. ** Potentially Incompatible Change **
Add experimental GetMemoryStatistics, ReleaseMemory, and Shutdown methods to the SQLiteConnection class.
Add memory leak detection to the test project for the .NET Compact Framework.
Add SQLITE_ENABLE_MEMORY_MANAGEMENT compile-time option to the interop assembly.
+ Use current isolation level when enlisting into an existing transaction. Fix for [56b42d99c1].
Better handling of non-error log messages from the SQLite core library. Pursuant to [44df10ea90].
Add TraceWarning connection flag to enable tracing of type mapping failures and disable tracing of them by default. Pursuant to [6d45c782e4].
Use 32-bit values to keep track of numeric precision and scale when building the schema table for a query. Fix for [ef2216192d].