Skip to content

Commit fe35045

Browse files
NH-4083 - Cease specifying parameter length for ODBC
1 parent 9e9d28d commit fe35045

File tree

3 files changed

+260
-157
lines changed

3 files changed

+260
-157
lines changed

src/NHibernate.Test/Async/TypesTest/StringTypeWithLengthFixture.cs

Lines changed: 135 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
using NHibernate.Dialect;
1616
using NHibernate.Driver;
1717
using NHibernate.Exceptions;
18-
using NHibernate.Linq;
1918
using NHibernate.Mapping.ByCode;
2019
using NUnit.Framework;
20+
using NHibernate.Linq;
2121

2222
namespace NHibernate.Test.TypesTest
2323
{
@@ -62,6 +62,16 @@ protected override HbmMapping GetMappings()
6262
return mapper.CompileMappingForAllExplicitlyAddedEntities();
6363
}
6464

65+
protected override void OnTearDown()
66+
{
67+
base.OnTearDown();
68+
using (var s = OpenSession())
69+
using (var t = s.BeginTransaction())
70+
{
71+
s.CreateQuery("delete from System.Object").ExecuteUpdate();
72+
t.Commit();
73+
}
74+
}
6575

6676
[Test]
6777
[Description("Values longer than the maximum possible string length " +
@@ -100,6 +110,57 @@ public Task ShouldPreventInsertionOfVeryLongStringThatWouldBeTruncatedAsync()
100110
}
101111
}
102112

113+
// NH-4083
114+
[Test]
115+
public async Task CanCompareShortValueWithLongStringAsync()
116+
{
117+
var maxStringLength = GetLongStringMappedLength();
118+
var longString = new string('x', maxStringLength);
119+
using (var s = OpenSession())
120+
{
121+
var b = new StringClass { LongStringValue = longString };
122+
await (s.SaveAsync(b));
123+
await (s.FlushAsync());
124+
}
125+
126+
using (var s = OpenSession())
127+
{
128+
var q = s.CreateQuery("from StringClass s where s.LongStringValue != :shortString")
129+
// Do not replace with SetString, otherwise length will be unspecified.
130+
.SetParameter("shortString", "aaa");
131+
var sc = await (q.UniqueResultAsync<StringClass>());
132+
Assert.That(sc, Is.Not.Null);
133+
Assert.That(sc.LongStringValue, Is.EqualTo(longString));
134+
}
135+
}
136+
137+
[Test]
138+
public async Task CanCompareLongValueWithLongStringAsync()
139+
{
140+
var maxStringLength = GetLongStringMappedLength();
141+
142+
if (Sfi.ConnectionProvider.Driver is OdbcDriver && maxStringLength >= 2000)
143+
Assert.Ignore("Odbc wrecks nvarchar parameter types when they are longer than 2000, it switch them to ntext");
144+
145+
var longString = new string('x', maxStringLength);
146+
using (var s = OpenSession())
147+
{
148+
var b = new StringClass { LongStringValue = longString };
149+
await (s.SaveAsync(b));
150+
await (s.FlushAsync());
151+
}
152+
153+
using (var s = OpenSession())
154+
{
155+
var q = s.CreateQuery("from StringClass s where s.LongStringValue = :longString")
156+
// Do not replace with SetString, otherwise length will be unspecified.
157+
.SetParameter("longString", longString);
158+
var sc = await (q.UniqueResultAsync<StringClass>());
159+
Assert.That(sc, Is.Not.Null);
160+
Assert.That(sc.LongStringValue, Is.EqualTo(longString));
161+
}
162+
}
163+
103164
[Test]
104165
[Description("Values longer than the mapped string length " +
105166
"should raise an exception if they would otherwise be truncated.")]
@@ -133,7 +194,6 @@ public Task ShouldPreventInsertionOfTooLongStringThatWouldBeTruncatedAsync()
133194
}
134195
}
135196

136-
137197
private async Task AssertFailedInsertExceptionDetailsAndEmptyTableAsync(Exception ex, CancellationToken cancellationToken = default(CancellationToken))
138198
{
139199
// We can get different sort of exceptions.
@@ -171,43 +231,92 @@ public Task ShouldPreventInsertionOfTooLongStringThatWouldBeTruncatedAsync()
171231
}
172232
}
173233

174-
175-
/// <summary>
176-
/// Some test cases doesn't work during some scenarios for well-known reasons. If the test
177-
/// fails under these circumstances, mark it as IGNORED. If it _stops_ failing, mark it
178-
/// as a FAILURE so that it can be investigated.
179-
/// </summary>
180-
private void AssertExpectedFailureOrNoException(Exception exception, bool requireExceptionAndIgnoreTest)
234+
[Test]
235+
public async Task CriteriaLikeParameterCanExceedColumnSizeAsync()
181236
{
182-
if (requireExceptionAndIgnoreTest)
237+
using (ISession s = OpenSession())
238+
using (s.BeginTransaction())
183239
{
184-
Assert.NotNull(
185-
exception,
186-
"Test was expected to have a well-known, but ignored, failure for the current configuration. If " +
187-
"that expected failure no longer occurs, it may now be possible to remove this exception.");
240+
await (s.SaveAsync(new StringClass {Id = 1, StringValue = "AAAAAAAAAB"}));
241+
await (s.SaveAsync(new StringClass {Id = 2, StringValue = "BAAAAAAAAA"}));
188242

189-
Assert.Ignore("This test is known to fail for the current configuration.");
190-
}
243+
var aaItems =
244+
await (s.CreateCriteria<StringClass>()
245+
.Add(Restrictions.Like("StringValue", "%AAAAAAAAA%"))
246+
.ListAsync());
191247

192-
// If the above didn't ignore the exception, it's for real - rethrow to trigger test failure.
193-
if (exception != null)
194-
throw new Exception("Wrapped exception.", exception);
248+
Assert.That(aaItems.Count, Is.EqualTo(2));
249+
}
195250
}
196251

252+
[Test]
253+
public async Task HqlLikeParameterCanExceedColumnSizeAsync()
254+
{
255+
using (ISession s = OpenSession())
256+
using (s.BeginTransaction())
257+
{
258+
await (s.SaveAsync(new StringClass {Id = 1, StringValue = "AAAAAAAAAB"}));
259+
await (s.SaveAsync(new StringClass {Id = 2, StringValue = "BAAAAAAAAA"}));
260+
261+
var aaItems =
262+
await (s.CreateQuery("from StringClass s where s.StringValue like :likeValue")
263+
.SetParameter("likeValue", "%AAAAAAAAA%")
264+
.ListAsync());
265+
266+
Assert.That(aaItems.Count, Is.EqualTo(2));
267+
}
268+
}
197269

198-
private TException CatchException<TException>(System.Action action)
199-
where TException : Exception
270+
[Test]
271+
public async Task CriteriaEqualityParameterCanExceedColumnSizeAsync()
200272
{
201-
try
273+
if (!TestDialect.SupportsNonDataBoundCondition)
274+
{
275+
// Doesn't work on Firebird due to Firebird not figuring out parameter types on its own.
276+
Assert.Ignore("Dialect does not support this test");
277+
}
278+
279+
// We should be able to query a column with a value longer than
280+
// the specified column size, to avoid tedious exceptions.
281+
using (ISession s = OpenSession())
282+
using (s.BeginTransaction())
202283
{
203-
action();
284+
await (s.SaveAsync(new StringClass {Id = 1, StringValue = "AAAAAAAAAB"}));
285+
await (s.SaveAsync(new StringClass {Id = 2, StringValue = "BAAAAAAAAA"}));
286+
287+
var aaItems =
288+
await (s.CreateCriteria<StringClass>()
289+
.Add(Restrictions.Eq("StringValue", "AAAAAAAAABx"))
290+
.ListAsync());
291+
292+
Assert.That(aaItems.Count, Is.EqualTo(0));
204293
}
205-
catch (TException exception)
294+
}
295+
296+
[Test]
297+
public async Task HqlEqualityParameterCanExceedColumnSizeAsync()
298+
{
299+
if (!TestDialect.SupportsNonDataBoundCondition)
206300
{
207-
return exception;
301+
// Doesn't work on Firebird due to Firebird not figuring out parameter types on its own.
302+
Assert.Ignore("Dialect does not support this test");
208303
}
209304

210-
return null;
305+
// We should be able to query a column with a value longer than
306+
// the specified column size, to avoid tedious exceptions.
307+
using (ISession s = OpenSession())
308+
using (s.BeginTransaction())
309+
{
310+
await (s.SaveAsync(new StringClass {Id = 1, StringValue = "AAAAAAAAAB"}));
311+
await (s.SaveAsync(new StringClass {Id = 2, StringValue = "BAAAAAAAAA"}));
312+
313+
var aaItems =
314+
await (s.CreateQuery("from StringClass s where s.StringValue = :likeValue")
315+
.SetParameter("likeValue", "AAAAAAAAABx")
316+
.ListAsync());
317+
318+
Assert.That(aaItems.Count, Is.EqualTo(0));
319+
}
211320
}
212321
}
213322
}

0 commit comments

Comments
 (0)