Skip to content

Commit 131b97e

Browse files
committed
Fix NH-2257 (Parameter ordering not working when driver does not support Named Parameters)
SVN: trunk@5073
1 parent 294de3e commit 131b97e

File tree

9 files changed

+116
-0
lines changed

9 files changed

+116
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace NHibernate.Test.NHSpecificTest.NH2257
4+
{
5+
public class Foo
6+
{
7+
public virtual int Id { get; set; }
8+
public virtual string Name { get; set; }
9+
public virtual int Ord { get; set; }
10+
}
11+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System.Linq;
2+
using NUnit.Framework;
3+
4+
namespace NHibernate.Test.NHSpecificTest.NH2257
5+
{
6+
public class Fixture : BugTestCase
7+
{
8+
protected override bool AppliesTo(NHibernate.Dialect.Dialect dialect)
9+
{
10+
return (dialect is NHibernate.Dialect.InformixDialect1000);
11+
}
12+
13+
[Test]
14+
public void InformixUsingDuplicateParameters()
15+
{
16+
using (var session = OpenSession())
17+
using (var transaction = session.BeginTransaction())
18+
{
19+
session.Save(new Foo() { Name = "aa" });
20+
21+
var list =
22+
session.CreateQuery("from Foo f where f.Name = :p1 and not f.Name <> :p1")
23+
.SetParameter("p1", "aa")
24+
.List<Foo>();
25+
26+
Assert.That(list.Count, Is.EqualTo(1));
27+
}
28+
}
29+
}
30+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
3+
assembly="NHibernate.Test"
4+
namespace="NHibernate.Test.NHSpecificTest.NH2257">
5+
6+
<class name="Foo">
7+
<id name="Id">
8+
<generator class="hilo" />
9+
</id>
10+
<property name="Name"/>
11+
<property name="Ord"/>
12+
</class>
13+
</hibernate-mapping>

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,8 @@
774774
<Compile Include="NHSpecificTest\NH2243\Person.cs" />
775775
<Compile Include="NHSpecificTest\NH2251\Domain.cs" />
776776
<Compile Include="NHSpecificTest\NH2251\Fixture.cs" />
777+
<Compile Include="NHSpecificTest\NH2257\Domain.cs" />
778+
<Compile Include="NHSpecificTest\NH2257\Fixture.cs" />
777779
<Compile Include="NHSpecificTest\NH473\Child.cs" />
778780
<Compile Include="NHSpecificTest\NH473\Fixture.cs" />
779781
<Compile Include="NHSpecificTest\NH473\Parent.cs" />
@@ -2215,6 +2217,7 @@
22152217
<EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" />
22162218
<EmbeddedResource Include="CollectionTest\NullableValueTypeElementMapFixture.hbm.xml" />
22172219
<Content Include="DynamicEntity\package.html" />
2220+
<EmbeddedResource Include="NHSpecificTest\NH2257\Mappings.hbm.xml" />
22182221
<EmbeddedResource Include="NHSpecificTest\NH2208\Mappings.hbm.xml" />
22192222
<EmbeddedResource Include="NHSpecificTest\NH2251\Mappings.hbm.xml" />
22202223
<EmbeddedResource Include="NHSpecificTest\NH2041\Mappings.hbm.xml" />

src/NHibernate/AdoNet/AbstractBatcher.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ public int ExecuteNonQuery(IDbCommand cmd)
222222
}
223223
}
224224

225+
public void ExpandQueryParameters(IDbCommand cmd, SqlString sqlString)
226+
{
227+
Driver.ExpandQueryParameters(cmd, sqlString);
228+
}
229+
225230
public IDataReader ExecuteReader(IDbCommand cmd)
226231
{
227232
CheckReaders();

src/NHibernate/Driver/DriverBase.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,36 @@ public IDbDataParameter GenerateParameter(IDbCommand command, string name, SqlTy
208208
return dbParam;
209209
}
210210

211+
public virtual void ExpandQueryParameters(IDbCommand cmd, SqlString sqlString)
212+
{
213+
if (UseNamedPrefixInSql)
214+
return; // named parameters are ok
215+
216+
var expandedParameters = new List<IDbDataParameter>();
217+
foreach (object part in sqlString.Parts)
218+
{
219+
if (part is Parameter)
220+
{
221+
var parameter = (Parameter)part;
222+
var originalParameter = (IDbDataParameter)cmd.Parameters[parameter.ParameterPosition.Value];
223+
expandedParameters.Add(CloneParameter(cmd, originalParameter));
224+
}
225+
}
226+
227+
cmd.Parameters.Clear();
228+
foreach (var parameter in expandedParameters)
229+
cmd.Parameters.Add(parameter);
230+
}
231+
232+
protected virtual IDbDataParameter CloneParameter(IDbCommand cmd, IDbDataParameter originalParameter)
233+
{
234+
var clone = cmd.CreateParameter();
235+
clone.DbType = originalParameter.DbType;
236+
clone.ParameterName = originalParameter.ParameterName;
237+
clone.Value = originalParameter.Value;
238+
return clone;
239+
}
240+
211241
public void PrepareCommand(IDbCommand command)
212242
{
213243
OnBeforePrepare(command);

src/NHibernate/Driver/IDriver.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,16 @@ public interface IDriver
9595
/// <param name="sqlType">The SqlType to set for IDbDataParameter.</param>
9696
/// <returns>An IDbDataParameter ready to be added to an IDbCommand.</returns>
9797
IDbDataParameter GenerateParameter(IDbCommand command, string name, SqlType sqlType);
98+
99+
/// <summary>
100+
/// Expand the parameters of the cmd to have a single parameter for each parameter in the
101+
/// sql string
102+
/// </summary>
103+
/// <remarks>
104+
/// This is for databases that do not support named parameters. So, instead of a single parameter
105+
/// for 'select ... from MyTable t where t.Col1 = @p0 and t.Col2 = @p0' we can issue
106+
/// 'select ... from MyTable t where t.Col1 = ? and t.Col2 = ?'
107+
/// </remarks>
108+
void ExpandQueryParameters(IDbCommand cmd, SqlString sqlString);
98109
}
99110
}

src/NHibernate/Engine/IBatcher.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@ public interface IBatcher : IDisposable
131131
/// </remarks>
132132
int ExecuteNonQuery(IDbCommand cmd);
133133

134+
/// <summary>
135+
/// Expand the parameters of the cmd to have a single parameter for each parameter in the
136+
/// sql string
137+
/// </summary>
138+
/// <remarks>
139+
/// This is for databases that do not support named parameters. So, instead of a single parameter
140+
/// for 'select ... from MyTable t where t.Col1 = @p0 and t.Col2 = @p0' we can issue
141+
/// 'select ... from MyTable t where t.Col1 = ? and t.Col2 = ?'
142+
/// </remarks>
143+
void ExpandQueryParameters(IDbCommand cmd, SqlString sqlString);
144+
134145
/// <summary>
135146
/// Must be called when an exception occurs.
136147
/// </summary>

src/NHibernate/Loader/Loader.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,8 @@ protected internal virtual IDbCommand PrepareQueryCommand(QueryParameters queryP
11481148
BindLimitParameters(command, colIndex, selection, session);
11491149
}
11501150

1151+
session.Batcher.ExpandQueryParameters(command, sqlString);
1152+
11511153
if (!useLimit)
11521154
{
11531155
SetMaxRows(command, selection);

0 commit comments

Comments
 (0)