Skip to content

Commit ce272a6

Browse files
committed
NH-3588
Fixed Creating/Dropping of temporary table if the dialect doesn't support mixing of DDL and DML statements in the same tranaction
1 parent 251ed3b commit ce272a6

File tree

4 files changed

+89
-24
lines changed

4 files changed

+89
-24
lines changed

src/NHibernate/Dialect/FirebirdDialect.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,29 @@ public override SqlString GetLimitString(SqlString queryString, SqlString offset
126126
return queryString.Insert(insertIndex, limitFragment.ToSqlString());
127127
}
128128

129-
private static int GetAfterSelectInsertPoint(SqlString text)
129+
#region Temporaray Table Support
130+
public override bool SupportsTemporaryTables
131+
{
132+
get { return true; }
133+
}
134+
135+
public override string CreateTemporaryTableString
136+
{
137+
get { return "create global temporary table"; }
138+
}
139+
140+
public override bool? PerformTemporaryTableDDLInIsolation()
141+
{
142+
return true;
143+
}
144+
145+
public override bool DropTemporaryTableAfterUse()
146+
{
147+
return true;
148+
}
149+
#endregion
150+
151+
private static int GetAfterSelectInsertPoint(SqlString text)
130152
{
131153
if (text.StartsWithCaseInsensitive("select"))
132154
{

src/NHibernate/Hql/Ast/ANTLR/Exec/AbstractStatementExecutor.cs

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
using System;
22
using System.Data;
3+
using Antlr.Runtime;
34
using Antlr.Runtime.Tree;
45
using NHibernate.Action;
6+
using NHibernate.AdoNet.Util;
57
using NHibernate.Engine;
68
using NHibernate.Engine.Transaction;
79
using NHibernate.Event;
810
using NHibernate.Hql.Ast.ANTLR.Tree;
911
using NHibernate.Persister.Entity;
1012
using NHibernate.SqlCommand;
11-
12-
using Antlr.Runtime;
1313
using NHibernate.SqlTypes;
14+
using NHibernate.Transaction;
1415
using NHibernate.Util;
15-
using NHibernate.AdoNet.Util;
1616

1717
namespace NHibernate.Hql.Ast.ANTLR.Exec
1818
{
@@ -142,9 +142,12 @@ protected virtual void CreateTemporaryTableIfNecessary(IQueryable persister, ISe
142142
}
143143
else
144144
{
145-
work.DoWork(session.ConnectionManager.GetConnection(), null);
146-
session.ConnectionManager.AfterStatement();
147-
}
145+
using (var dummyCommand = session.ConnectionManager.CreateCommand())
146+
{
147+
work.DoWork(dummyCommand.Connection, dummyCommand.Transaction);
148+
session.ConnectionManager.AfterStatement();
149+
}
150+
}
148151
}
149152

150153
protected virtual bool ShouldIsolateTemporaryTableDDL()
@@ -165,21 +168,27 @@ protected virtual void DropTemporaryTableIfNecessary(IQueryable persister, ISess
165168

166169
if (ShouldIsolateTemporaryTableDDL())
167170
{
168-
if (Factory.Settings.IsDataDefinitionInTransactionSupported)
169-
{
170-
Isolater.DoIsolatedWork(work, session);
171-
}
172-
else
173-
{
174-
Isolater.DoNonTransactedWork(work, session);
175-
}
176-
}
177-
else
178-
{
179-
work.DoWork(session.ConnectionManager.GetConnection(), null);
180-
session.ConnectionManager.AfterStatement();
181-
}
182-
}
171+
session.ConnectionManager.Transaction.RegisterSynchronization(new AfterTransactionCompletes((success) =>
172+
{
173+
if (Factory.Settings.IsDataDefinitionInTransactionSupported)
174+
{
175+
Isolater.DoIsolatedWork(work, session);
176+
}
177+
else
178+
{
179+
Isolater.DoNonTransactedWork(work, session);
180+
}
181+
}));
182+
}
183+
else
184+
{
185+
using (var sillyCommand = session.ConnectionManager.CreateCommand())
186+
{
187+
work.DoWork(sillyCommand.Connection, sillyCommand.Transaction);
188+
session.ConnectionManager.AfterStatement();
189+
}
190+
}
191+
}
183192
else
184193
{
185194
// at the very least cleanup the data :)
@@ -229,7 +238,8 @@ public void DoWork(IDbConnection connection, IDbTransaction transaction)
229238
IDbCommand stmnt = null;
230239
try
231240
{
232-
stmnt = session.ConnectionManager.CreateCommand();
241+
stmnt = connection.CreateCommand();
242+
stmnt.Transaction = transaction;
233243
stmnt.CommandText = persister.TemporaryIdTableDDL;
234244
stmnt.ExecuteNonQuery();
235245
session.Factory.Settings.SqlStatementLogger.LogCommand(stmnt, FormatStyle.Ddl);
@@ -273,7 +283,8 @@ public void DoWork(IDbConnection connection, IDbTransaction transaction)
273283
IDbCommand stmnt = null;
274284
try
275285
{
276-
stmnt = session.ConnectionManager.CreateCommand();
286+
stmnt = connection.CreateCommand();
287+
stmnt.Transaction = transaction;
277288
stmnt.CommandText = "drop table " + persister.TemporaryIdTableName;
278289
stmnt.ExecuteNonQuery();
279290
session.Factory.Settings.SqlStatementLogger.LogCommand(stmnt, FormatStyle.Ddl);

src/NHibernate/NHibernate.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@
642642
<Compile Include="TransactionException.cs" />
643643
<Compile Include="Transaction\AdoNetWithDistributedTransactionFactory.cs" />
644644
<Compile Include="Transaction\AdoTransaction.cs" />
645+
<Compile Include="Transaction\AfterTransactionCompletes.cs" />
645646
<Compile Include="Transaction\ITransactionFactory.cs" />
646647
<Compile Include="Transform\AliasToEntityMapResultTransformer.cs" />
647648
<Compile Include="Transform\DistinctRootEntityResultTransformer.cs" />
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
3+
namespace NHibernate.Transaction
4+
{
5+
public class AfterTransactionCompletes : ISynchronization
6+
{
7+
#region Fields
8+
private readonly Action<bool> _whenCompleted;
9+
#endregion
10+
11+
#region Constructors/Destructors
12+
public AfterTransactionCompletes(Action<bool> whenCompleted)
13+
{
14+
_whenCompleted = whenCompleted;
15+
}
16+
#endregion
17+
18+
#region ISynchronization Members
19+
20+
public void BeforeCompletion()
21+
{
22+
}
23+
24+
public void AfterCompletion(bool success)
25+
{
26+
_whenCompleted(success);
27+
}
28+
29+
#endregion
30+
}
31+
}

0 commit comments

Comments
 (0)