Skip to content

Commit ab86ab8

Browse files
committed
Merge branch 'icambron-NH-2861'
2 parents a354e06 + 34db35a commit ab86ab8

File tree

6 files changed

+273
-8
lines changed

6 files changed

+273
-8
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using NUnit.Framework;
7+
8+
namespace NHibernate.Test.Join
9+
{
10+
[TestFixture]
11+
public class JoinedFilters : TestCase
12+
{
13+
protected override IList Mappings
14+
{
15+
get
16+
{
17+
return new []
18+
{
19+
"Join.TennisPlayer.hbm.xml",
20+
"Join.Person.hbm.xml"
21+
};
22+
}
23+
}
24+
25+
protected override void OnTearDown()
26+
{
27+
using (ISession s = OpenSession())
28+
using (ITransaction tx = s.BeginTransaction())
29+
{
30+
s.Delete("from TennisPlayer");
31+
tx.Commit();
32+
}
33+
}
34+
35+
protected override string MappingsAssembly
36+
{
37+
get { return "NHibernate.Test"; }
38+
}
39+
40+
[Test]
41+
public void FilterOnPrimaryTable()
42+
{
43+
using (ISession s = OpenSession())
44+
using (ITransaction tx = s.BeginTransaction())
45+
{
46+
s.EnableFilter("NameFilter").SetParameter("name", "Nadal");
47+
48+
CreatePlayers(s);
49+
50+
IList<TennisPlayer> people = s.CreateCriteria<TennisPlayer>().List<TennisPlayer>();
51+
Assert.AreEqual(1, people.Count);
52+
Assert.AreEqual("Nadal", people[0].Name);
53+
54+
tx.Commit();
55+
}
56+
}
57+
58+
[Test]
59+
public void FilterOnJoinedTable()
60+
{
61+
using (ISession s = OpenSession())
62+
using (ITransaction tx = s.BeginTransaction())
63+
{
64+
s.EnableFilter("MakeFilter").SetParameter("make", "Babolat");
65+
66+
CreatePlayers(s);
67+
68+
IList<TennisPlayer> people = s.CreateCriteria<TennisPlayer>().List<TennisPlayer>();
69+
Assert.AreEqual(1, people.Count);
70+
Assert.AreEqual("Babolat", people[0].RacquetMake);
71+
72+
tx.Commit();
73+
}
74+
}
75+
76+
[Test]
77+
public void FilterOnJoinedTableWithRepeatedColumn()
78+
{
79+
using (ISession s = OpenSession())
80+
using (ITransaction tx = s.BeginTransaction())
81+
{
82+
s.EnableFilter("ModelFilter").SetParameter("model", "AeroPro Drive");
83+
84+
CreatePlayers(s);
85+
86+
IList<TennisPlayer> people = s.CreateCriteria<TennisPlayer>().List<TennisPlayer>();
87+
Assert.AreEqual(1, people.Count);
88+
Assert.AreEqual("AeroPro Drive", people[0].RacquetModel);
89+
90+
tx.Commit();
91+
}
92+
}
93+
94+
private static void CreatePlayers(ISession s)
95+
{
96+
CreateAndSavePlayer(s, "Nadal", "Babolat", "AeroPro Drive");
97+
CreateAndSavePlayer(s, "Federer", "Wilson", "Six.One Tour BLX");
98+
s.Flush();
99+
}
100+
101+
private static void CreateAndSavePlayer(ISession session, string name, string make, string model)
102+
{
103+
var s = new TennisPlayer() {Name = name, RacquetMake = make, RacquetModel = model};
104+
session.Save(s);
105+
}
106+
}
107+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace NHibernate.Test.Join
7+
{
8+
public class TennisPlayer
9+
{
10+
public virtual long Id { get; set; }
11+
public virtual string Name { get; set; }
12+
public virtual string RacquetMake { get; set; }
13+
public virtual string RacquetModel { get; set; }
14+
15+
public virtual IList<Person> Coaches { get; set; }
16+
}
17+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
3+
namespace="NHibernate.Test.Join"
4+
assembly="NHibernate.Test"
5+
>
6+
7+
<class name="TennisPlayer" table="tennis_player" lazy="true">
8+
9+
<id name="Id" column="person_id" unsaved-value="0">
10+
<generator class="native"/>
11+
</id>
12+
13+
<bag name="Coaches" cascade="all" inverse="true" access="property">
14+
<key column="id"/>
15+
<one-to-many class="Person"/>
16+
</bag>
17+
18+
<property name="Name" not-null="true" length="80"/>
19+
20+
<join table="racquet">
21+
<key column="racquet_id"/>
22+
<property name="RacquetMake"/>
23+
<property name="RacquetModel" column="Name"/>
24+
</join>
25+
26+
<filter name="NameFilter"/>
27+
<filter name="MakeFilter"/>
28+
<filter name="ModelFilter"/>
29+
30+
</class>
31+
32+
<filter-def name="NameFilter" condition=":name = Name">
33+
<filter-param name="name" type="System.String"/>
34+
</filter-def>
35+
36+
<filter-def name="MakeFilter" condition=":make = RacquetMake">
37+
<filter-param name="make" type="System.String"/>
38+
</filter-def>
39+
40+
<filter-def name="ModelFilter" condition=":model = RacquetModel">
41+
<filter-param name="model" type="System.String"/>
42+
</filter-def>
43+
44+
</hibernate-mapping>

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@
494494
<Compile Include="Insertordering\Membership.cs" />
495495
<Compile Include="Insertordering\User.cs" />
496496
<Compile Include="KnownBugAttribute.cs" />
497+
<Compile Include="Join\JoinedFilters.cs" />
498+
<Compile Include="Join\TennisPlayer.cs" />
497499
<Compile Include="LazyOneToOne\Employee.cs" />
498500
<Compile Include="LazyOneToOne\Employment.cs" />
499501
<Compile Include="LazyOneToOne\LazyOneToOneTest.cs" />
@@ -3120,6 +3122,7 @@
31203122
<EmbeddedResource Include="NHSpecificTest\NH2907\Mappings.hbm.xml" />
31213123
<EmbeddedResource Include="NHSpecificTest\NH2869\Mappings.hbm.xml" />
31223124
<EmbeddedResource Include="NHSpecificTest\NH0000\Mappings.hbm.xml" />
3125+
<EmbeddedResource Include="Join\TennisPlayer.hbm.xml" />
31233126
<EmbeddedResource Include="NHSpecificTest\NH2828\Mappings.hbm.xml" />
31243127
<EmbeddedResource Include="NHSpecificTest\NH2761\A.hbm.xml" />
31253128
<EmbeddedResource Include="NHSpecificTest\NH2761\B.hbm.xml" />

src/NHibernate/Persister/Entity/AbstractEntityPersister.cs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3199,11 +3199,73 @@ protected void LogStaticSQL()
31993199
public virtual string FilterFragment(string alias, IDictionary<string, IFilter> enabledFilters)
32003200
{
32013201
StringBuilder sessionFilterFragment = new StringBuilder();
3202-
filterHelper.Render(sessionFilterFragment, GenerateFilterConditionAlias(alias), enabledFilters);
3202+
3203+
filterHelper.Render(sessionFilterFragment, GenerateFilterConditionAlias(alias), GetColumnsToTableAliasMap(alias), enabledFilters);
32033204

32043205
return sessionFilterFragment.Append(FilterFragment(alias)).ToString();
32053206
}
32063207

3208+
private IDictionary<string, string> GetColumnsToTableAliasMap(string rootAlias)
3209+
{
3210+
IDictionary<PropertyKey, string> propDictionary = new Dictionary<PropertyKey, string>();
3211+
for (int i =0; i < SubclassPropertyNameClosure.Length; i++)
3212+
{
3213+
string property = SubclassPropertyNameClosure[i];
3214+
string[] cols = GetSubclassPropertyColumnNames(property);
3215+
3216+
if (cols != null && cols.Length > 0)
3217+
{
3218+
PropertyKey key = new PropertyKey(cols[0], GetSubclassPropertyTableNumber(i));
3219+
propDictionary[key] = property;
3220+
}
3221+
}
3222+
3223+
IDictionary<string, string> dict = new Dictionary<string, string>();
3224+
for (int i = 0; i < SubclassColumnTableNumberClosure.Length; i++ )
3225+
{
3226+
string col = SubclassColumnClosure[i];
3227+
string alias = GenerateTableAlias(rootAlias, SubclassColumnTableNumberClosure[i]);
3228+
3229+
string fullColumn = string.Format("{0}.{1}", alias, col);
3230+
3231+
PropertyKey key = new PropertyKey(col, SubclassColumnTableNumberClosure[i]);
3232+
if (propDictionary.ContainsKey(key))
3233+
{
3234+
dict[propDictionary[key]] = fullColumn;
3235+
}
3236+
3237+
if (!dict.ContainsKey(col))
3238+
{
3239+
dict[col] = fullColumn;
3240+
}
3241+
}
3242+
3243+
return dict;
3244+
}
3245+
3246+
private class PropertyKey
3247+
{
3248+
public string Column { get; set; }
3249+
public int TableNumber { get; set; }
3250+
3251+
public PropertyKey(string column, int tableNumber)
3252+
{
3253+
Column = column;
3254+
TableNumber = tableNumber;
3255+
}
3256+
3257+
public override int GetHashCode()
3258+
{
3259+
return Column.GetHashCode() ^ TableNumber.GetHashCode();
3260+
}
3261+
3262+
public override bool Equals(object other)
3263+
{
3264+
PropertyKey otherTuple = other as PropertyKey;
3265+
return otherTuple == null ? false : Column.Equals(otherTuple.Column) && TableNumber.Equals(otherTuple.TableNumber);
3266+
}
3267+
}
3268+
32073269
public virtual string GenerateFilterConditionAlias(string rootAlias)
32083270
{
32093271
return rootAlias;

src/NHibernate/Util/FilterHelper.cs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Text;
4+
using System.Text.RegularExpressions;
45
using NHibernate.Dialect.Function;
56
using NHibernate.Impl;
67
using NHibernate.SqlCommand;
@@ -51,23 +52,54 @@ public string Render(String alias, IDictionary<string, IFilter> enabledFilters)
5152

5253
public void Render(StringBuilder buffer, string alias, IDictionary<string, IFilter> enabledFilters)
5354
{
54-
if (filterNames != null && filterNames.Length > 0)
55+
Render(buffer, alias, new Dictionary<string, string>(), enabledFilters);
56+
}
57+
58+
public void Render(StringBuilder buffer, string defaultAlias, IDictionary<string, string> propMap, IDictionary<string, IFilter> enabledFilters)
59+
{
60+
if (filterNames != null)
5561
{
56-
for (int i = 0, max = filterNames.Length; i < max; i++)
62+
int max = filterNames.Length;
63+
if (max > 0)
5764
{
58-
if (enabledFilters.ContainsKey(filterNames[i]))
65+
for (int i = 0; i < max; i++)
5966
{
60-
string condition = filterConditions[i];
61-
if (StringHelper.IsNotEmpty(condition))
67+
if (enabledFilters.ContainsKey(filterNames[i]))
6268
{
63-
buffer.Append(" and ");
64-
buffer.Append(StringHelper.Replace(condition, FilterImpl.MARKER, alias));
69+
string condition = filterConditions[i];
70+
if (StringHelper.IsNotEmpty(condition))
71+
{
72+
buffer.Append(" and ");
73+
AddFilterString(buffer, defaultAlias, propMap, condition);
74+
}
6575
}
6676
}
6777
}
6878
}
6979
}
7080

81+
private static void AddFilterString(StringBuilder buffer, string defaultAlias, IDictionary<string, string> propMap, string condition)
82+
{
83+
int i = condition.IndexOf(FilterImpl.MARKER);
84+
int upTo = 0;
85+
while (i > -1 && upTo < condition.Length)
86+
{
87+
buffer.Append(condition.Substring(upTo, i - upTo));
88+
int startOfProperty = i + FilterImpl.MARKER.Length + 1;
89+
90+
upTo = condition.IndexOf(" ", startOfProperty);
91+
upTo = upTo >= 0 ? upTo : condition.Length;
92+
string property = condition.Substring(startOfProperty, upTo - startOfProperty);
93+
94+
string fullColumn = propMap.ContainsKey(property) ? propMap[property] : string.Format(string.Format("{0}.{1}", defaultAlias, property));
95+
96+
buffer.Append(fullColumn);
97+
98+
i = condition.IndexOf(FilterImpl.MARKER, upTo);
99+
}
100+
buffer.Append(condition.Substring(upTo));
101+
}
102+
71103
/// <summary>
72104
/// Get only filters enabled for many-to-one association.
73105
/// </summary>

0 commit comments

Comments
 (0)