Skip to content

Commit 56d3f3d

Browse files
authored
Merge pull request #1611 from fredericDelaporte/ParameterListHashset
Fix IFilter.SetParameterList not supporting HashSet<T> arguments
2 parents 1bfb987 + a6c4a5a commit 56d3f3d

File tree

8 files changed

+1140
-1070
lines changed

8 files changed

+1140
-1070
lines changed

src/NHibernate.Test/Async/FilterTest/DynamicFilterTest.cs

Lines changed: 608 additions & 529 deletions
Large diffs are not rendered by default.

src/NHibernate.Test/FilterTest/DynamicFilterTest.cs

Lines changed: 494 additions & 520 deletions
Large diffs are not rendered by default.

src/NHibernate.Test/FilterTest/Product.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ public virtual ISet<Category> Categories
7575
set { categories = value; }
7676
}
7777

78+
public virtual Guid ProductGuid { get; set; }
79+
7880
public override int GetHashCode()
7981
{
8082
return stockNumber;

src/NHibernate.Test/FilterTest/classes.hbm.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@
7979
<property name="EffectiveStartDate" column="eff_start_dt" type="Date"/>
8080
<property name="EffectiveEndDate" column="eff_end_dt" type="Date"/>
8181

82+
<property name="ProductGuid"/>
83+
8284
<set cascade="none" inverse="true" name="OrderLineItems">
8385
<key column="PROD_ID"/>
8486
<one-to-many class="LineItem"/>
@@ -93,6 +95,7 @@
9395
</set>
9496

9597
<filter name="effectiveDate" condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>
98+
<filter name="guidlist" condition="ProductGuid IN (:guids)"/>
9699
</class>
97100

98101
<class name="Salesperson" table="SALES_PERSON">
@@ -118,4 +121,4 @@
118121
<filter name="regionlist" condition="REG IN (:regions)"/>
119122
</class>
120123

121-
</hibernate-mapping>
124+
</hibernate-mapping>

src/NHibernate.Test/FilterTest/defs.hbm.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,8 @@
2424
<filter-def name="cat">
2525
<filter-param name="catId" type="long"/>
2626
</filter-def>
27-
</hibernate-mapping>
27+
28+
<filter-def name="guidlist">
29+
<filter-param name="guids" type="guid"/>
30+
</filter-def>
31+
</hibernate-mapping>

src/NHibernate/Engine/Query/NativeSQLQueryPlan.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,19 +151,16 @@ private SqlString ExpandDynamicFilterParameters(SqlString sqlString, ICollection
151151
string parameterName = parts[1];
152152
var filter = (FilterImpl)enabledFilters[filterName];
153153

154-
object value = filter.GetParameter(parameterName);
154+
var collectionSpan = filter.GetParameterSpan(parameterName);
155155
IType type = filter.FilterDefinition.GetParameterType(parameterName);
156156
int parameterColumnSpan = type.GetColumnSpan(session.Factory);
157-
var collectionValue = value as ICollection;
158-
int? collectionSpan = null;
159157

160158
// Add query chunk
161-
string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan).ToArray());
159+
string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan));
162160
string bindFragment;
163-
if (collectionValue != null && !type.ReturnedClass.IsArray)
161+
if (collectionSpan.HasValue && !type.ReturnedClass.IsArray)
164162
{
165-
collectionSpan = collectionValue.Count;
166-
bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionValue.Count).ToArray());
163+
bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionSpan.Value));
167164
}
168165
else
169166
{

src/NHibernate/Impl/FilterImpl.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class FilterImpl : IFilter
1616
private FilterDefinition definition;
1717

1818
private readonly IDictionary<string, object> parameters = new Dictionary<string, object>();
19+
private readonly Dictionary<string, int> _parameterSpans = new Dictionary<string, int>();
1920

2021
public void AfterDeserialize(FilterDefinition factoryDefinition)
2122
{
@@ -75,20 +76,21 @@ public IFilter SetParameter(string name, object value)
7576
/// <param name="name">The parameter's name.</param>
7677
/// <param name="values">The values to be expanded into an SQL IN list.</param>
7778
/// <returns>This FilterImpl instance (for method chaining).</returns>
79+
/// <exception cref="ArgumentNullException">Thrown when <paramref name="name"/> or <paramref name="values"/> are <see langword="null" />.</exception>
7880
public IFilter SetParameterList<T>(string name, ICollection<T> values)
7981
{
82+
if (values == null)
83+
throw new ArgumentNullException(nameof(values), "Collection must be not null!");
84+
8085
var type = definition.GetParameterType(name);
8186
if (type == null)
82-
{
8387
throw new HibernateException("Undefined filter parameter [" + name + "]");
84-
}
8588

8689
if (!type.ReturnedClass.IsAssignableFrom(typeof(T)))
87-
{
8890
throw new HibernateException("Incorrect type for parameter [" + name + "]");
89-
}
9091

91-
parameters[name] = values ?? throw new ArgumentException("Collection must be not null!", nameof(values));
92+
_parameterSpans[name] = values.Count;
93+
parameters[name] = values;
9294
return this;
9395
}
9496

@@ -99,6 +101,18 @@ public object GetParameter(string name)
99101
return result;
100102
}
101103

104+
/// <summary>
105+
/// Get the span of a value list parameter by name. <see langword="null" /> if the parameter is not a value list
106+
/// or if there is no such parameter.
107+
/// </summary>
108+
/// <param name="name">The parameter name.</param>
109+
/// <returns>The parameter span, or <see langword="null" /> if the parameter is not a value list or
110+
/// if there is no such parameter.</returns>
111+
public int? GetParameterSpan(string name)
112+
{
113+
return _parameterSpans.TryGetValue(name, out var result) ? result : default(int?);
114+
}
115+
102116
/// <summary>
103117
/// Perform validation of the filter state. This is used to verify the
104118
/// state of the filter after its enablement and before its use.

src/NHibernate/Loader/Loader.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,19 +1859,16 @@ protected SqlString ExpandDynamicFilterParameters(SqlString sqlString, ICollecti
18591859
string parameterName = parts[1];
18601860
var filter = (FilterImpl)enabledFilters[filterName];
18611861

1862-
object value = filter.GetParameter(parameterName);
1862+
int? collectionSpan = filter.GetParameterSpan(parameterName);
18631863
IType type = filter.FilterDefinition.GetParameterType(parameterName);
18641864
int parameterColumnSpan = type.GetColumnSpan(session.Factory);
1865-
var collectionValue = value as ICollection;
1866-
int? collectionSpan = null;
18671865

18681866
// Add query chunk
1869-
string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan).ToArray());
1867+
string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan));
18701868
string bindFragment;
1871-
if (collectionValue != null && !type.ReturnedClass.IsArray)
1869+
if (collectionSpan.HasValue && !type.ReturnedClass.IsArray)
18721870
{
1873-
collectionSpan = collectionValue.Count;
1874-
bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionValue.Count).ToArray());
1871+
bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionSpan.Value));
18751872
}
18761873
else
18771874
{

0 commit comments

Comments
 (0)