Skip to content

Fix IFilter.SetParameterList not supporting HashSet<T> arguments #1611

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,137 changes: 608 additions & 529 deletions src/NHibernate.Test/Async/FilterTest/DynamicFilterTest.cs

Large diffs are not rendered by default.

1,014 changes: 494 additions & 520 deletions src/NHibernate.Test/FilterTest/DynamicFilterTest.cs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/NHibernate.Test/FilterTest/Product.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public virtual ISet<Category> Categories
set { categories = value; }
}

public virtual Guid ProductGuid { get; set; }

public override int GetHashCode()
{
return stockNumber;
Expand Down
5 changes: 4 additions & 1 deletion src/NHibernate.Test/FilterTest/classes.hbm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
<property name="EffectiveStartDate" column="eff_start_dt" type="Date"/>
<property name="EffectiveEndDate" column="eff_end_dt" type="Date"/>

<property name="ProductGuid"/>

<set cascade="none" inverse="true" name="OrderLineItems">
<key column="PROD_ID"/>
<one-to-many class="LineItem"/>
Expand All @@ -93,6 +95,7 @@
</set>

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

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

</hibernate-mapping>
</hibernate-mapping>
6 changes: 5 additions & 1 deletion src/NHibernate.Test/FilterTest/defs.hbm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@
<filter-def name="cat">
<filter-param name="catId" type="long"/>
</filter-def>
</hibernate-mapping>

<filter-def name="guidlist">
<filter-param name="guids" type="guid"/>
</filter-def>
</hibernate-mapping>
11 changes: 4 additions & 7 deletions src/NHibernate/Engine/Query/NativeSQLQueryPlan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,19 +151,16 @@ private SqlString ExpandDynamicFilterParameters(SqlString sqlString, ICollection
string parameterName = parts[1];
var filter = (FilterImpl)enabledFilters[filterName];

object value = filter.GetParameter(parameterName);
var collectionSpan = filter.GetParameterSpan(parameterName);
IType type = filter.FilterDefinition.GetParameterType(parameterName);
int parameterColumnSpan = type.GetColumnSpan(session.Factory);
var collectionValue = value as ICollection;
int? collectionSpan = null;

// Add query chunk
string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan).ToArray());
string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan));
string bindFragment;
if (collectionValue != null && !type.ReturnedClass.IsArray)
if (collectionSpan.HasValue && !type.ReturnedClass.IsArray)
{
collectionSpan = collectionValue.Count;
bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionValue.Count).ToArray());
bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionSpan.Value));
}
else
{
Expand Down
24 changes: 19 additions & 5 deletions src/NHibernate/Impl/FilterImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class FilterImpl : IFilter
private FilterDefinition definition;

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

public void AfterDeserialize(FilterDefinition factoryDefinition)
{
Expand Down Expand Up @@ -75,20 +76,21 @@ public IFilter SetParameter(string name, object value)
/// <param name="name">The parameter's name.</param>
/// <param name="values">The values to be expanded into an SQL IN list.</param>
/// <returns>This FilterImpl instance (for method chaining).</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="name"/> or <paramref name="values"/> are <see langword="null" />.</exception>
public IFilter SetParameterList<T>(string name, ICollection<T> values)
{
if (values == null)
throw new ArgumentNullException(nameof(values), "Collection must be not null!");

var type = definition.GetParameterType(name);
if (type == null)
{
throw new HibernateException("Undefined filter parameter [" + name + "]");
}

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

parameters[name] = values ?? throw new ArgumentException("Collection must be not null!", nameof(values));
_parameterSpans[name] = values.Count;
parameters[name] = values;
return this;
}

Expand All @@ -99,6 +101,18 @@ public object GetParameter(string name)
return result;
}

/// <summary>
/// Get the span of a value list parameter by name. <see langword="null" /> if the parameter is not a value list
/// or if there is no such parameter.
/// </summary>
/// <param name="name">The parameter name.</param>
/// <returns>The parameter span, or <see langword="null" /> if the parameter is not a value list or
/// if there is no such parameter.</returns>
public int? GetParameterSpan(string name)
{
return _parameterSpans.TryGetValue(name, out var result) ? result : default(int?);
}

/// <summary>
/// Perform validation of the filter state. This is used to verify the
/// state of the filter after its enablement and before its use.
Expand Down
11 changes: 4 additions & 7 deletions src/NHibernate/Loader/Loader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1859,19 +1859,16 @@ protected SqlString ExpandDynamicFilterParameters(SqlString sqlString, ICollecti
string parameterName = parts[1];
var filter = (FilterImpl)enabledFilters[filterName];

object value = filter.GetParameter(parameterName);
int? collectionSpan = filter.GetParameterSpan(parameterName);
IType type = filter.FilterDefinition.GetParameterType(parameterName);
int parameterColumnSpan = type.GetColumnSpan(session.Factory);
var collectionValue = value as ICollection;
int? collectionSpan = null;

// Add query chunk
string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan).ToArray());
string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan));
string bindFragment;
if (collectionValue != null && !type.ReturnedClass.IsArray)
if (collectionSpan.HasValue && !type.ReturnedClass.IsArray)
{
collectionSpan = collectionValue.Count;
bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionValue.Count).ToArray());
bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionSpan.Value));
}
else
{
Expand Down