Skip to content

Commit

Permalink
Implement dispose for Connection and Transaction. Add test cases as w…
Browse files Browse the repository at this point in the history
…ell.
  • Loading branch information
ChTimTsubasa committed Apr 4, 2019
1 parent b2becaf commit 4bb3eb4
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 0 deletions.
37 changes: 37 additions & 0 deletions Snowflake.Data.Tests/SFConnectionIT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,5 +217,42 @@ public void TestConnectWithDifferentRole()
conn.Close();
}
}

// Test that when a connection is disposed, a close would send out and unfinished transaction would be roll back.
[Test]
public void TestConnectionDispose()
{
using (IDbConnection conn = new SnowflakeDbConnection())
{
// Setup
conn.ConnectionString = connectionString;
conn.Open();
IDbCommand command = conn.CreateCommand();
command.CommandText = "create or replace table testConnDispose(c int)";
command.ExecuteNonQuery();

IDbTransaction t1 = conn.BeginTransaction();
IDbCommand t1c1 = conn.CreateCommand();
t1c1.Transaction = t1;
t1c1.CommandText = "insert into testConnDispose values (1)";
t1c1.ExecuteNonQuery();
}

using (IDbConnection conn = new SnowflakeDbConnection())
{
// Previous connection would be disposed and
// uncommitted txn would rollback at this point
conn.ConnectionString = connectionString;
conn.Open();
IDbCommand command = conn.CreateCommand();
command.CommandText = "SELECT * FROM testConnDispose";
IDataReader reader = command.ExecuteReader();
Assert.IsFalse(reader.Read());

// Cleanup
command.CommandText = "DROP TABLE IF EXISTS testConnDispose";
command.ExecuteNonQuery();
}
}
}
}
51 changes: 51 additions & 0 deletions Snowflake.Data.Tests/SFDbTransactionIT.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2012-2019 Snowflake Computing Inc. All rights reserved.
*/

namespace Snowflake.Data.Tests
{
using NUnit.Framework;
using Snowflake.Data.Client;
using System.Data;

[TestFixture]
class SFDbTransactionIT : SFBaseTest
{
[Test]
// Test that when a transaction is disposed, rollback would be sent out
public void TestTransactionDispose()
{
var conn = new SnowflakeDbConnection();
try
{
conn.ConnectionString = connectionString;
conn.Open();

IDbCommand command = conn.CreateCommand();
command.CommandText = "create or replace table testTransactionDispose(c int)";
command.ExecuteNonQuery();

using (IDbTransaction t1 = conn.BeginTransaction())
{
IDbCommand t1c1 = conn.CreateCommand();
t1c1.Transaction = t1;
t1c1.CommandText = "insert into testTransactionDispose values (1)";
t1c1.ExecuteNonQuery();
}

// Transaction t1 would be disposed and rollback at this point, tuple inserted is not visible
IDbCommand c2 = conn.CreateCommand();
c2.CommandText = "SELECT * FROM testTransactionDispose";
IDataReader reader2 = c2.ExecuteReader();
Assert.IsFalse(reader2.Read());
}
finally
{
IDbCommand command = conn.CreateCommand();
command.CommandText = "DROP TABLE IF EXISTS testTransactionDispose";
command.ExecuteNonQuery();
conn.Close();
}
}
}
}
18 changes: 18 additions & 0 deletions Snowflake.Data/Client/SnowflakeDbConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public class SnowflakeDbConnection : DbConnection

private int _connectionTimeout;

private bool disposed = false;

public SnowflakeDbConnection()
{
_connectionState = ConnectionState.Closed;
Expand Down Expand Up @@ -140,5 +142,21 @@ protected override DbCommand CreateDbCommand()
{
return new SnowflakeDbCommand(this);
}

protected override void Dispose(bool disposing)
{
if (disposed)
return;

this.Close();
disposed = true;

base.Dispose(disposing);
}

~SnowflakeDbConnection()
{
Dispose(false);
}
}
}
19 changes: 19 additions & 0 deletions Snowflake.Data/Client/SnowflakeDbTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class SnowflakeDbTransaction : DbTransaction

private SnowflakeDbConnection connection;

private bool disposed = false;

public SnowflakeDbTransaction(IsolationLevel isolationLevel, SnowflakeDbConnection connection)
{
logger.Debug("Begin transaction.");
Expand Down Expand Up @@ -71,5 +73,22 @@ public override void Rollback()
command.ExecuteNonQuery();
}
}

protected override void Dispose(bool disposing)
{
if (disposed)
return;

// Snowflake can handle a rollback for a rollback without any transaction
this.Rollback();
disposed = true;

base.Dispose(disposing);
}

~SnowflakeDbTransaction()
{
Dispose(false);
}
}
}

0 comments on commit 4bb3eb4

Please sign in to comment.