diff --git a/src/NHibernate.Test/NHSpecificTest/NH2053/Animal.cs b/src/NHibernate.Test/NHSpecificTest/NH2053/Animal.cs new file mode 100644 index 00000000000..89eef38f3a0 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH2053/Animal.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NHibernate.Test.NHSpecificTest.NH2053 +{ + public class Animal + { + public virtual int AnimalId { get; set; } + public virtual string Name { get; set; } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH2053/Cat.cs b/src/NHibernate.Test/NHSpecificTest/NH2053/Cat.cs new file mode 100644 index 00000000000..1a25897644a --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH2053/Cat.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NHibernate.Test.NHSpecificTest.NH2053 +{ + public class Cat: Animal + { + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH2053/Dog.cs b/src/NHibernate.Test/NHSpecificTest/NH2053/Dog.cs new file mode 100644 index 00000000000..162c635ebbd --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH2053/Dog.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NHibernate.Test.NHSpecificTest.NH2053 +{ + public class Dog: Animal + { + public virtual Boolean Talkable { get; set; } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/NH2053/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH2053/Fixture.cs new file mode 100644 index 00000000000..76beb7b6f87 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH2053/Fixture.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using NHibernate.Dialect; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH2053 +{ + [TestFixture] + public class Fixture : BugTestCase + { + protected override bool AppliesTo(NHibernate.Dialect.Dialect dialect) + { + return dialect is MsSql2005Dialect; + } + protected override void OnSetUp() + { + using (var session = this.OpenSession()) + { + using (var tran = session.BeginTransaction()) + { + Dog snoopy = new Dog() + { + Name = "Snoopy", + Talkable = false + }; + snoopy.Name = "Snoopy"; + Dog Jake = new Dog() + { + Name = "Jake the dog", + Talkable = true + }; + session.Save(snoopy); + session.Save(Jake); + Cat kitty = new Cat() + { + Name = "Kitty" + }; + session.Save(kitty); + tran.Commit(); + } + } + } + protected override void OnTearDown() + { + using (var session = this.OpenSession()) + { + using (var tran = session.BeginTransaction()) + { + session.Delete("from Dog"); + session.Delete("from Animal"); + tran.Commit(); + } + } + } + + [Test] + public void JoinedSubClass_Filter() + { + using (var session = this.OpenSession()) + { + using (var tran = session.BeginTransaction()) + { + session.EnableFilter("talkableFilter").SetParameter("talkable", true); + var snoopy = session.QueryOver().Where(x => x.Name == "Snoopy").SingleOrDefault(); + Assert.AreEqual(null, snoopy); // there are no talking dog named Snoopy. + + var jake = session.QueryOver().Where(x => x.Name == "Jake the dog").SingleOrDefault(); + Assert.AreNotEqual(null, jake); + Assert.AreEqual("Jake the dog", jake.Name); + + var kitty = session.QueryOver().Where(x => x.Name == "Kitty").SingleOrDefault(); + Assert.AreNotEqual(null, kitty); + Assert.AreEqual("Kitty", kitty.Name); + } + } + } + + } +} \ No newline at end of file diff --git a/src/NHibernate.Test/NHSpecificTest/NH2053/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/NH2053/Mappings.hbm.xml new file mode 100644 index 00000000000..60aacf5f57b --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH2053/Mappings.hbm.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/NHibernate.Test/NHibernate.Test.csproj b/src/NHibernate.Test/NHibernate.Test.csproj index c60b89ab659..a9ac653ddde 100644 --- a/src/NHibernate.Test/NHibernate.Test.csproj +++ b/src/NHibernate.Test/NHibernate.Test.csproj @@ -696,6 +696,10 @@ + + + + @@ -3069,6 +3073,7 @@ + diff --git a/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs b/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs index a4d3f89bdd3..eb1849ccb58 100644 --- a/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs +++ b/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs @@ -4033,7 +4033,11 @@ public partial class HbmJoinedSubclass { /// [System.Xml.Serialization.XmlAttributeAttribute()] public string node; - + + /// + [System.Xml.Serialization.XmlElementAttribute("filter")] + public HbmFilter[] filter; + public HbmJoinedSubclass() { this.dynamicupdate = false; this.dynamicinsert = false; @@ -4619,6 +4623,10 @@ public partial class HbmSubclass { /// [System.Xml.Serialization.XmlAttributeAttribute()] public string node; + + /// + [System.Xml.Serialization.XmlElementAttribute("filter")] + public HbmFilter[] filter; public HbmSubclass() { this.dynamicupdate = false; diff --git a/src/NHibernate/Cfg/XmlHbmBinding/JoinedSubclassBinder.cs b/src/NHibernate/Cfg/XmlHbmBinding/JoinedSubclassBinder.cs index 48f6609c0e0..b4b8a4c3428 100644 --- a/src/NHibernate/Cfg/XmlHbmBinding/JoinedSubclassBinder.cs +++ b/src/NHibernate/Cfg/XmlHbmBinding/JoinedSubclassBinder.cs @@ -62,6 +62,8 @@ public void HandleJoinedSubclass(PersistentClass model, HbmJoinedSubclass joined BindJoinedSubclasses(joinedSubclassMapping.JoinedSubclasses, subclass, inheritedMetas); + new FiltersBinder(subclass, Mappings).Bind(joinedSubclassMapping.filter); + model.AddSubclass(subclass); mappings.AddClass(subclass); } diff --git a/src/NHibernate/Cfg/XmlHbmBinding/SubclassBinder.cs b/src/NHibernate/Cfg/XmlHbmBinding/SubclassBinder.cs index 6b93230ec0f..933ea74c6af 100644 --- a/src/NHibernate/Cfg/XmlHbmBinding/SubclassBinder.cs +++ b/src/NHibernate/Cfg/XmlHbmBinding/SubclassBinder.cs @@ -42,7 +42,9 @@ public void HandleSubclass(PersistentClass model, HbmSubclass subClassMapping, I model.AddSubclass(subclass); mappings.AddClass(subclass); - } + + new FiltersBinder(model, Mappings).Bind(subClassMapping.filter); + } } } \ No newline at end of file diff --git a/src/NHibernate/Mapping/ByCode/IJoinedSubclassMapper.cs b/src/NHibernate/Mapping/ByCode/IJoinedSubclassMapper.cs index fe88cb97829..a68b38ec51c 100644 --- a/src/NHibernate/Mapping/ByCode/IJoinedSubclassMapper.cs +++ b/src/NHibernate/Mapping/ByCode/IJoinedSubclassMapper.cs @@ -10,6 +10,7 @@ public interface IJoinedSubclassAttributesMapper : IEntityAttributesMapper, IEnt void Key(Action keyMapping); void Extends(System.Type baseType); void SchemaAction(SchemaAction action); + void Filter(string filterName, Action filterMapping); } public interface IJoinedSubclassMapper : IJoinedSubclassAttributesMapper, IPropertyContainerMapper {} @@ -21,6 +22,7 @@ public interface IJoinedSubclassAttributesMapper : IEntityAttributesMap void Schema(string schemaName); void Key(Action> keyMapping); void SchemaAction(SchemaAction action); + void Filter(string filterName, Action filterMapping); } public interface IJoinedSubclassMapper : IJoinedSubclassAttributesMapper, IPropertyContainerMapper where TEntity : class {} diff --git a/src/NHibernate/Mapping/ByCode/ISubclassMapper.cs b/src/NHibernate/Mapping/ByCode/ISubclassMapper.cs index 668f63941c3..5c6b04dc578 100644 --- a/src/NHibernate/Mapping/ByCode/ISubclassMapper.cs +++ b/src/NHibernate/Mapping/ByCode/ISubclassMapper.cs @@ -6,6 +6,7 @@ public interface ISubclassAttributesMapper : IEntityAttributesMapper, IEntitySql { void DiscriminatorValue(object value); void Extends(System.Type baseType); + void Filter(string filterName, Action filterMapping); } public interface ISubclassMapper : ISubclassAttributesMapper, IPropertyContainerMapper @@ -16,6 +17,7 @@ public interface ISubclassMapper : ISubclassAttributesMapper, IPropertyContainer public interface ISubclassAttributesMapper : IEntityAttributesMapper, IEntitySqlsMapper where TEntity : class { void DiscriminatorValue(object value); + void Filter(string filterName, Action filterMapping); } public interface ISubclassMapper : ISubclassAttributesMapper, IPropertyContainerMapper where TEntity : class diff --git a/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassCustomizer.cs b/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassCustomizer.cs index c59ca645c1d..6d49e6557c4 100644 --- a/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassCustomizer.cs +++ b/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassCustomizer.cs @@ -127,6 +127,11 @@ public void Schema(string schemaName) CustomizersHolder.AddCustomizer(typeof (TEntity), (IJoinedSubclassAttributesMapper m) => m.Schema(schemaName)); } + public void Filter(string filterName, Action filterMapping) + { + CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinedSubclassAttributesMapper m) => m.Filter(filterName, filterMapping)); + } + #endregion #region IConformistHoldersProvider Members diff --git a/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/SubclassCustomizer.cs b/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/SubclassCustomizer.cs index 0d59228a341..1b94efd7793 100644 --- a/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/SubclassCustomizer.cs +++ b/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/SubclassCustomizer.cs @@ -28,6 +28,11 @@ public void DiscriminatorValue(object value) CustomizersHolder.AddCustomizer(typeof (TEntity), (ISubclassMapper m) => m.DiscriminatorValue(value)); } + public void Filter(string filterName, Action filterMapping) + { + CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinedSubclassAttributesMapper m) => m.Filter(filterName, filterMapping)); + } + #endregion private Dictionary> JoinCustomizers diff --git a/src/NHibernate/Mapping/ByCode/Impl/JoinedSubclassMapper.cs b/src/NHibernate/Mapping/ByCode/Impl/JoinedSubclassMapper.cs index 4f8b6fc494f..f6871711496 100644 --- a/src/NHibernate/Mapping/ByCode/Impl/JoinedSubclassMapper.cs +++ b/src/NHibernate/Mapping/ByCode/Impl/JoinedSubclassMapper.cs @@ -189,6 +189,19 @@ public void SchemaAction(SchemaAction action) classMapping.schemaaction = action.ToSchemaActionString(); } + public void Filter(string filterName, Action filterMapping) + { + if (filterMapping == null) + { + filterMapping = x => { }; + } + var hbmFilter = new HbmFilter(); + var filterMapper = new FilterMapper(filterName, hbmFilter); + filterMapping(filterMapper); + Dictionary filters = classMapping.filter != null ? classMapping.filter.ToDictionary(f => f.name, f => f) : new Dictionary(1); + filters[filterName] = hbmFilter; + classMapping.filter = filters.Values.ToArray(); + } #endregion } } \ No newline at end of file diff --git a/src/NHibernate/Mapping/ByCode/Impl/SubclassMapper.cs b/src/NHibernate/Mapping/ByCode/Impl/SubclassMapper.cs index 5c04b1e1b85..c2c33c62e60 100644 --- a/src/NHibernate/Mapping/ByCode/Impl/SubclassMapper.cs +++ b/src/NHibernate/Mapping/ByCode/Impl/SubclassMapper.cs @@ -177,6 +177,19 @@ public void SqlDelete(string sql) public void Subselect(string sql) {} + public void Filter(string filterName, Action filterMapping) + { + if (filterMapping == null) + { + filterMapping = x => { }; + } + var hbmFilter = new HbmFilter(); + var filterMapper = new FilterMapper(filterName, hbmFilter); + filterMapping(filterMapper); + Dictionary filters = classMapping.filter != null ? classMapping.filter.ToDictionary(f => f.name, f => f) : new Dictionary(1); + filters[filterName] = hbmFilter; + classMapping.filter = filters.Values.ToArray(); + } #endregion } } \ No newline at end of file diff --git a/src/NHibernate/Mapping/Subclass.cs b/src/NHibernate/Mapping/Subclass.cs index dbee75a4810..5ae390f8eb3 100644 --- a/src/NHibernate/Mapping/Subclass.cs +++ b/src/NHibernate/Mapping/Subclass.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using NHibernate.Engine; using NHibernate.Util; @@ -157,7 +158,14 @@ public override ISet SynchronizedTables public override IDictionary FilterMap { - get { return Superclass.FilterMap; } + get { + var superclassFilters = Superclass.FilterMap; + var subclassFilters = base.FilterMap; + + return superclassFilters.Union( + subclassFilters + ).ToDictionary(k => k.Key, v => v.Value); + } } public override IDictionary TuplizerMap diff --git a/src/NHibernate/nhibernate-mapping.xsd b/src/NHibernate/nhibernate-mapping.xsd index 396c1905309..5f3bfea6211 100644 --- a/src/NHibernate/nhibernate-mapping.xsd +++ b/src/NHibernate/nhibernate-mapping.xsd @@ -676,6 +676,7 @@ + @@ -1353,6 +1354,7 @@ +