Merge pull request #2057 from directhex/monolite-on-jenkins
[mono.git] / mcs / class / Mono.Data.Sqlite / Mono.Data.Sqlite_2.0 / SQLiteTransaction.cs
index dc79c8656b2132caa4e32f62a60d458d1e1d9cf3..4978ecb0fd38ffa6b4ad7af730436fdb8716b25e 100644 (file)
-//
-// Mono.Data.Sqlite.SQLiteTransaction.cs
-//
-// Author(s):
-//   Robert Simpson (robert@blackcastlesoft.com)
-//
-// Adapted and modified for the Mono Project by
-//   Marek Habersack (grendello@gmail.com)
-//
-//
-// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
-// Copyright (C) 2007 Marek Habersack
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-/********************************************************
- * ADO.NET 2.0 Data Provider for Sqlite Version 3.X
- * Written by Robert Simpson (robert@blackcastlesoft.com)
- * 
- * Released to the public domain, use at your own risk!
- ********************************************************/
-#if NET_2_0
-namespace Mono.Data.Sqlite
-{
-  using System;
-  using System.Data;
-  using System.Data.Common;
-
-  /// <summary>
-  /// Sqlite implementation of DbTransaction.
-  /// </summary>
-  public sealed class SqliteTransaction : DbTransaction
-  {
-    /// <summary>
-    /// The connection to which this transaction is bound
-    /// </summary>
-    internal SqliteConnection _cnn;
-    internal long _version; // Matches the version of the connection
-
-    /// <summary>
-    /// Constructs the transaction object, binding it to the supplied connection
-    /// </summary>
-    /// <param name="connection">The connection to open a transaction on</param>
-    /// <param name="deferredLock">TRUE to defer the writelock, or FALSE to lock immediately</param>
-    internal SqliteTransaction(SqliteConnection connection, bool deferredLock)
-    {
-      _cnn = connection;
-      _version = _cnn._version;
-
-      if (_cnn._transactionLevel++ == 0)
-      {
-        try
-        {
-          using (SqliteCommand cmd = _cnn.CreateCommand())
-          {
-            if (!deferredLock)
-              cmd.CommandText = "BEGIN IMMEDIATE";
-            else
-              cmd.CommandText = "BEGIN";
-
-            cmd.ExecuteNonQuery();
-          }
-        }
-        catch (SqliteException)
-        {
-          _cnn._transactionLevel--;
-          _cnn = null;
-          throw;
-        }
-      }
-    }
-
-    /// <summary>
-    /// Commits the current transaction.
-    /// </summary>
-    public override void Commit()
-    {
-      IsValid(true);
-
-      if (--_cnn._transactionLevel == 0)
-      {
-        try
-        {
-          using (SqliteCommand cmd = _cnn.CreateCommand())
-          {
-            cmd.CommandText = "COMMIT";
-            cmd.ExecuteNonQuery();
-          }
-        }
-        finally
-        {
-          _cnn = null;
-        }
-      }
-      else
-      {
-        _cnn = null;
-      }
-    }
-
-    /// <summary>
-    /// Returns the underlying connection to which this transaction applies.
-    /// </summary>
-    public new SqliteConnection Connection
-    {
-      get { return _cnn; }
-    }
-
-    /// <summary>
-    /// Forwards to the local Connection property
-    /// </summary>
-    protected override DbConnection DbConnection
-    {
-      get { return Connection; }
-    }
-
-    /// <summary>
-    /// Disposes the transaction.  If it is currently active, any changes are rolled back.
-    /// </summary>
-    protected override void Dispose(bool disposing)
-    {
-      if (IsValid(false))
-        Rollback();
-
-      _cnn = null;
-
-      base.Dispose(disposing);
-    }
-
-    /// <summary>
-    /// Gets the isolation level of the transaction.  Sqlite only supports Serializable transactions.
-    /// </summary>
-    public override IsolationLevel IsolationLevel
-    {
-      get { return IsolationLevel.Serializable; }
-    }
-
-    /// <summary>
-    /// Rolls back the active transaction.
-    /// </summary>
-    public override void Rollback()
-    {
-      IsValid(true);
-
-      try
-      {
-        using (SqliteCommand cmd = _cnn.CreateCommand())
-        {
-          cmd.CommandText = "ROLLBACK";
-          cmd.ExecuteNonQuery();
-        }
-        _cnn._transactionLevel = 0;
-      }
-      finally
-      {
-        _cnn = null;
-      }
-    }
-
-    internal bool IsValid(bool throwError)
-    {
-      if (_cnn == null)
-      {
-        if (throwError == true) throw new ArgumentNullException("No connection associated with this transaction");
-        else return false;
-      }
-
-      if (_cnn._transactionLevel == 0)
-      {
-        if (throwError == true) throw new SqliteException((int)SqliteErrorCode.Misuse, "No transaction is active on this connection");
-        else return false;
-      }
-      if (_cnn._version != _version)
-      {
-        if (throwError == true) throw new SqliteException((int)SqliteErrorCode.Misuse, "The connection was closed and re-opened, changes were rolled back");
-        else return false;
-      }
-      if (_cnn.State != ConnectionState.Open)
-      {
-        if (throwError == true) throw new SqliteException((int)SqliteErrorCode.Misuse, "Connection was closed");
-        else return false;
-      }
-
-      return true;
-    }
-  }
-}
-#endif
+/********************************************************\r
+ * ADO.NET 2.0 Data Provider for SQLite Version 3.X\r
+ * Written by Robert Simpson (robert@blackcastlesoft.com)\r
+ * \r
+ * Released to the public domain, use at your own risk!\r
+ ********************************************************/\r
+\r
+namespace Mono.Data.Sqlite\r
+{\r
+  using System;\r
+  using System.Data;\r
+  using System.Data.Common;\r
+\r
+  /// <summary>\r
+  /// SQLite implementation of DbTransaction.\r
+  /// </summary>\r
+  public sealed class SqliteTransaction : DbTransaction\r
+  {\r
+    /// <summary>\r
+    /// The connection to which this transaction is bound\r
+    /// </summary>\r
+    internal SqliteConnection _cnn;\r
+    internal long _version; // Matches the version of the connection\r
+    private IsolationLevel _level;\r
+\r
+    /// <summary>\r
+    /// Constructs the transaction object, binding it to the supplied connection\r
+    /// </summary>\r
+    /// <param name="connection">The connection to open a transaction on</param>\r
+    /// <param name="deferredLock">TRUE to defer the writelock, or FALSE to lock immediately</param>\r
+    internal SqliteTransaction(SqliteConnection connection, bool deferredLock)\r
+    {\r
+      _cnn = connection;\r
+      _version = _cnn._version;\r
+\r
+      _level = (deferredLock == true) ? IsolationLevel.ReadCommitted : IsolationLevel.Serializable;\r
+\r
+      if (_cnn._transactionLevel++ == 0)\r
+      {\r
+        try\r
+        {\r
+          using (SqliteCommand cmd = _cnn.CreateCommand())\r
+          {\r
+            if (!deferredLock)\r
+              cmd.CommandText = "BEGIN IMMEDIATE";\r
+            else\r
+              cmd.CommandText = "BEGIN";\r
+\r
+            cmd.ExecuteNonQuery();\r
+          }\r
+        }\r
+        catch (SqliteException)\r
+        {\r
+          _cnn._transactionLevel--;\r
+          _cnn = null;\r
+          throw;\r
+        }\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// Commits the current transaction.\r
+    /// </summary>\r
+    public override void Commit()\r
+    {\r
+      IsValid(true);\r
+\r
+      if (_cnn._transactionLevel - 1 == 0)\r
+      {\r
+        using (SqliteCommand cmd = _cnn.CreateCommand())\r
+        {\r
+          cmd.CommandText = "COMMIT";\r
+          cmd.ExecuteNonQuery();\r
+        }\r
+      }\r
+      _cnn._transactionLevel--;\r
+      _cnn = null;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Returns the underlying connection to which this transaction applies.\r
+    /// </summary>\r
+    public new SqliteConnection Connection\r
+    {\r
+      get { return _cnn; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// Forwards to the local Connection property\r
+    /// </summary>\r
+    protected override DbConnection DbConnection\r
+    {\r
+      get { return Connection; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// Disposes the transaction.  If it is currently active, any changes are rolled back.\r
+    /// </summary>\r
+    protected override void Dispose(bool disposing)\r
+    {\r
+      if (disposing)\r
+      {\r
+        lock (this)\r
+        {\r
+          if (IsValid(false))\r
+            Rollback();\r
+\r
+          _cnn = null;\r
+        }\r
+      }\r
+      base.Dispose(disposing);\r
+    }\r
+\r
+    /// <summary>\r
+    /// Gets the isolation level of the transaction.  SQLite only supports Serializable transactions.\r
+    /// </summary>\r
+    public override IsolationLevel IsolationLevel\r
+    {\r
+      get { return _level; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// Rolls back the active transaction.\r
+    /// </summary>\r
+    public override void Rollback()\r
+    {\r
+      IsValid(true);\r
+\r
+      IssueRollback(_cnn);\r
+\r
+      _cnn._transactionLevel = 0;\r
+      _cnn = null;\r
+    }\r
+\r
+    internal static void IssueRollback(SqliteConnection cnn)\r
+    {\r
+      using (SqliteCommand cmd = cnn.CreateCommand())\r
+      {\r
+        cmd.CommandText = "ROLLBACK";\r
+        cmd.ExecuteNonQuery();\r
+      }\r
+    }\r
+\r
+    internal bool IsValid(bool throwError)\r
+    {\r
+      if (_cnn == null)\r
+      {\r
+        if (throwError == true) throw new ArgumentNullException("No connection associated with this transaction");\r
+        else return false;\r
+      }\r
+\r
+      if (_cnn._transactionLevel == 0)\r
+      {\r
+        if (throwError == true) throw new SqliteException((int)SQLiteErrorCode.Misuse, "No transaction is active on this connection");\r
+        else return false;\r
+      }\r
+      if (_cnn._version != _version)\r
+      {\r
+        if (throwError == true) throw new SqliteException((int)SQLiteErrorCode.Misuse, "The connection was closed and re-opened, changes were rolled back");\r
+        else return false;\r
+      }\r
+      if (_cnn.State != ConnectionState.Open)\r
+      {\r
+        if (throwError == true) throw new SqliteException((int)SQLiteErrorCode.Misuse, "Connection was closed");\r
+        else return false;\r
+      }\r
+\r
+      return true;\r
+    }\r
+  }\r
+}\r