Skip to content

Commit 03bca68

Browse files
Merge 5.3.17 in 5.4.x
2 parents 85600e2 + 0e08e91 commit 03bca68

File tree

10 files changed

+246
-12
lines changed

10 files changed

+246
-12
lines changed

releasenotes.txt

+19
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,25 @@ Release notes - NHibernate - Version 5.4.0
234234
* #2242 Test case for NH-3972 - SQL error when selecting a column of a subclass when sibling classes have a column of the same name
235235

236236

237+
Build 5.3.17
238+
=============================
239+
240+
Release notes - NHibernate - Version 5.3.17
241+
242+
5 issues were resolved in this release.
243+
244+
** Bug
245+
246+
* #3306 Invalid SQL when referencing nullable entity in correlated subquery
247+
* #3304 Fix SetSnapShot CopyTo variance failure
248+
* #3294 Undefined join type failure with cross joins and Informix
249+
250+
** Task
251+
252+
* #3315 Release 5.3.17
253+
* #3300 Backport handling of null DateTime parameters in Npgsql 6+
254+
255+
237256
Build 5.3.16
238257
=============================
239258

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using System.Linq;
12+
using NUnit.Framework;
13+
using NHibernate.Linq;
14+
15+
namespace NHibernate.Test.NHSpecificTest.GH3306NullableEntityCorrelatedSubquery
16+
{
17+
using System.Threading.Tasks;
18+
[TestFixture]
19+
public class FixtureAsync : BugTestCase
20+
{
21+
private const string NAME_JOE = "Joe";
22+
private const string NAME_ALLEN = "Allen";
23+
24+
protected override void OnSetUp()
25+
{
26+
using (var session = OpenSession())
27+
using (var tx = session.BeginTransaction())
28+
{
29+
var joe = new Customer { Name = NAME_JOE };
30+
session.Save(joe);
31+
32+
var allen = new Customer { Name = NAME_ALLEN };
33+
session.Save(allen);
34+
35+
var joeInvoice0 = new Invoice { Customer = joe, Number = 0 };
36+
session.Save(joeInvoice0);
37+
38+
var allenInvoice1 = new Invoice { Customer = allen, Number = 1 };
39+
session.Save(allenInvoice1);
40+
41+
tx.Commit();
42+
}
43+
}
44+
45+
protected override void OnTearDown()
46+
{
47+
using (var session = OpenSession())
48+
using (var tx = session.BeginTransaction())
49+
{
50+
session.Delete("from Invoice");
51+
session.Delete("from Customer");
52+
tx.Commit();
53+
}
54+
}
55+
56+
[Test]
57+
public async Task NullableEntityInCorrelatedSubqueryAsync()
58+
{
59+
using (var s = OpenSession())
60+
{
61+
var customers = s.Query<Customer>().Where(c => c.Name == NAME_JOE);
62+
var results = await (s.Query<Invoice>()
63+
.Where(i => customers.Any(c => c.Invoices.Any(ci => ci.Customer == i.Customer))).ToListAsync());
64+
65+
Assert.That(results.Count, Is.EqualTo(1));
66+
}
67+
}
68+
}
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System.Linq;
2+
using NUnit.Framework;
3+
4+
namespace NHibernate.Test.NHSpecificTest.GH3306NullableEntityCorrelatedSubquery
5+
{
6+
[TestFixture]
7+
public class Fixture : BugTestCase
8+
{
9+
private const string NAME_JOE = "Joe";
10+
private const string NAME_ALLEN = "Allen";
11+
12+
protected override void OnSetUp()
13+
{
14+
using (var session = OpenSession())
15+
using (var tx = session.BeginTransaction())
16+
{
17+
var joe = new Customer { Name = NAME_JOE };
18+
session.Save(joe);
19+
20+
var allen = new Customer { Name = NAME_ALLEN };
21+
session.Save(allen);
22+
23+
var joeInvoice0 = new Invoice { Customer = joe, Number = 0 };
24+
session.Save(joeInvoice0);
25+
26+
var allenInvoice1 = new Invoice { Customer = allen, Number = 1 };
27+
session.Save(allenInvoice1);
28+
29+
tx.Commit();
30+
}
31+
}
32+
33+
protected override void OnTearDown()
34+
{
35+
using (var session = OpenSession())
36+
using (var tx = session.BeginTransaction())
37+
{
38+
session.Delete("from Invoice");
39+
session.Delete("from Customer");
40+
tx.Commit();
41+
}
42+
}
43+
44+
[Test]
45+
public void NullableEntityInCorrelatedSubquery()
46+
{
47+
using (var s = OpenSession())
48+
{
49+
var customers = s.Query<Customer>().Where(c => c.Name == NAME_JOE);
50+
var results = s.Query<Invoice>()
51+
.Where(i => customers.Any(c => c.Invoices.Any(ci => ci.Customer == i.Customer))).ToList();
52+
53+
Assert.That(results.Count, Is.EqualTo(1));
54+
}
55+
}
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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.GH3306NullableEntityCorrelatedSubquery">
5+
6+
<class name="Customer" >
7+
<id name="ID" type="Int32">
8+
<generator class="native" />
9+
</id>
10+
<property name="Name" type="String" />
11+
12+
<set name="Invoices" inverse="true" >
13+
<key column="CustomerID"/>
14+
<one-to-many class="Invoice"/>
15+
</set>
16+
</class>
17+
18+
<class name="Invoice">
19+
<id name="ID" type="Int32">
20+
<generator class="native" />
21+
</id>
22+
23+
<property name="Number" type="Int32" column="`Number`" />
24+
<many-to-one name="Customer" not-found="ignore" column="CustomerID" class="Customer" />
25+
</class>
26+
27+
</hibernate-mapping>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System.Collections.Generic;
2+
3+
namespace NHibernate.Test.NHSpecificTest.GH3306NullableEntityCorrelatedSubquery
4+
{
5+
public class Customer
6+
{
7+
public virtual int ID { get; protected set; }
8+
public virtual ISet<Invoice> Invoices { get; set; }
9+
public virtual string Name { get; set; }
10+
}
11+
12+
public class Invoice
13+
{
14+
public virtual int ID { get; protected set; }
15+
public virtual Customer Customer { get; set; }
16+
public virtual int Number { get; set; }
17+
}
18+
}

src/NHibernate.Test/UtilityTest/SetSnapShotFixture.cs

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
24
using System.IO;
35
using System.Runtime.Serialization.Formatters.Binary;
46
using NHibernate.Collection.Generic.SetHelpers;
7+
using NSubstitute.ExceptionExtensions;
58
using NUnit.Framework;
69

710
namespace NHibernate.Test.UtilityTest
@@ -70,6 +73,29 @@ public void TestCopyTo()
7073
Assert.That(list, Is.EquivalentTo(array));
7174
}
7275

76+
[Test]
77+
public void TestCopyToObjectArray()
78+
{
79+
var list = new List<string> { "test1", null, "test2" };
80+
ICollection sn = new SetSnapShot<string>(list);
81+
82+
var array = new object[3];
83+
sn.CopyTo(array, 0);
84+
Assert.That(list, Is.EquivalentTo(array));
85+
}
86+
87+
[Test]
88+
public void WhenCopyToIsCalledWithIncompatibleArrayTypeThenThrowArgumentOrInvalidCastException()
89+
{
90+
var list = new List<string> { "test1", null, "test2" };
91+
ICollection sn = new SetSnapShot<string>(list);
92+
93+
var array = new int[3];
94+
Assert.That(
95+
() => sn.CopyTo(array, 0),
96+
Throws.ArgumentException.Or.TypeOf<InvalidCastException>());
97+
}
98+
7399
[Test]
74100
public void TestSerialization()
75101
{

src/NHibernate/Collection/Generic/SetHelpers/SetSnapShot.cs

+24-6
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,16 @@ IEnumerator IEnumerable.GetEnumerator()
114114

115115
void ICollection.CopyTo(Array array, int index)
116116
{
117-
if (!(array is T[] typedArray))
117+
if (array is T[] typedArray)
118118
{
119-
throw new ArgumentException($"Array must be of type {typeof(T[])}.", nameof(array));
119+
CopyTo(typedArray, index);
120+
return;
120121
}
121122

122-
CopyTo(typedArray, index);
123+
if (_hasNull)
124+
array.SetValue(default(T), index);
125+
ICollection keysCollection = _values.Keys;
126+
keysCollection.CopyTo(array, index + (_hasNull ? 1 : 0));
123127
}
124128

125129
public int Count => _values.Count + (_hasNull ? 1 : 0);
@@ -153,12 +157,26 @@ protected SetSnapShot(SerializationInfo info, StreamingContext context) : base(i
153157

154158
void ICollection.CopyTo(Array array, int index)
155159
{
156-
if (!(array is T[] typedArray))
160+
if (array is T[] typedArray)
157161
{
158-
throw new ArgumentException($"Array must be of type {typeof(T[])}.", nameof(array));
162+
CopyTo(typedArray, index);
163+
return;
159164
}
160165

161-
CopyTo(typedArray, index);
166+
if (array == null)
167+
throw new ArgumentNullException(nameof(array));
168+
169+
if (index < 0)
170+
throw new ArgumentOutOfRangeException(nameof(index), index, "Array index cannot be negative");
171+
172+
if (index > array.Length || Count > array.Length - index)
173+
throw new ArgumentException("Provided array is too small", nameof(array));
174+
175+
foreach (var value in this)
176+
{
177+
array.SetValue(value, index);
178+
index++;
179+
}
162180
}
163181

164182
bool ICollection.IsSynchronized => false;

src/NHibernate/Dialect/InformixDialect.cs

+3
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ public override JoinFragment CreateOuterJoinFragment()
333333
return new InformixJoinFragment();
334334
}
335335

336+
/// <inheritdoc />
337+
public override bool SupportsCrossJoin => false;
338+
336339
/// <summary> The SQL literal value to which this database maps boolean values. </summary>
337340
/// <param name="value">The boolean value </param>
338341
/// <returns> The appropriate SQL literal. </returns>

src/NHibernate/Dialect/InformixDialect0940.cs

+1-4
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,7 @@ public override JoinFragment CreateOuterJoinFragment()
126126
return new ANSIJoinFragment();
127127
}
128128

129-
/// <inheritdoc />
130-
public override bool SupportsCrossJoin => false;
131-
132-
/// <summary>
129+
/// <summary>
133130
/// Does this Dialect have some kind of <c>LIMIT</c> syntax?
134131
/// </summary>
135132
/// <value>False, unless overridden.</value>

src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ private void DereferenceEntity(EntityType entityType, bool implicitJoin, string
398398
bool joinIsNeeded;
399399

400400
//For nullable entity comparisons we always need to add join (like not constrained one-to-one or not-found ignore associations)
401-
bool comparisonWithNullableEntity = entityType.IsNullable && Walker.IsComparativeExpressionClause;
401+
bool comparisonWithNullableEntity = entityType.IsNullable && Walker.IsComparativeExpressionClause && !IsCorrelatedSubselect;
402402

403403
if ( IsDotNode( parent ) )
404404
{

0 commit comments

Comments
 (0)