From: <fab...@us...> - 2009-10-31 17:33:49
|
Revision: 4811 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4811&view=rev Author: fabiomaulo Date: 2009-10-31 17:33:40 +0000 (Sat, 31 Oct 2009) Log Message: ----------- Fix NH-1998 Modified Paths: -------------- branches/2.1.x/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/FilterDefinition.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/JoinSequence.cs branches/2.1.x/nhibernate/src/NHibernate/Loader/JoinWalker.cs branches/2.1.x/nhibernate/src/NHibernate/Util/FilterHelper.cs branches/2.1.x/nhibernate/src/NHibernate/nhibernate-mapping.xsd branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs Modified: branches/2.1.x/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -4918,6 +4918,15 @@ /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string condition; + + /// <remarks/> + [System.Xml.Serialization.XmlAttributeAttribute("use-many-to-one")] + [System.ComponentModel.DefaultValueAttribute(true)] + public bool usemanytoone; + + public HbmFilterDef() { + this.usemanytoone = true; + } } /// <remarks/> Modified: branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -19,7 +19,7 @@ log.DebugFormat("Parsed filter-def [{0}]", filterDefSchema.name); - return new FilterDefinition(filterDefSchema.name, defaultCondition, parameterTypes); + return new FilterDefinition(filterDefSchema.name, defaultCondition, parameterTypes, filterDefSchema.usemanytoone); } private static IDictionary<string, IType> GetFilterParameterTypes(HbmFilterDef filterDefSchema) Modified: branches/2.1.x/nhibernate/src/NHibernate/Engine/FilterDefinition.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/FilterDefinition.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/FilterDefinition.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -14,22 +14,35 @@ private readonly string filterName; private readonly string defaultFilterCondition; private readonly IDictionary<string, IType> parameterTypes= new Dictionary<string, IType>(); + private readonly bool useInManyToOne; /// <summary> - /// Set the named parameter's value list for this filter. + /// Set the named parameter's value list for this filter. /// </summary> /// <param name="name">The name of the filter for which this configuration is in effect.</param> /// <param name="defaultCondition">The default filter condition.</param> - /// <param name="parameterTypes">A dictionary storing the NHibernate <see cref="IType" /> type + /// <param name="parameterTypes">A dictionary storing the NHibernate <see cref="IType"/> type /// of each parameter under its name.</param> - public FilterDefinition(string name, string defaultCondition, IDictionary<string, IType> parameterTypes) + /// <param name="useManyToOne">if set to <c>true</c> used in many to one rel</param> + public FilterDefinition(string name, string defaultCondition, IDictionary<string, IType> parameterTypes, + bool useManyToOne) { filterName = name; defaultFilterCondition = defaultCondition; this.parameterTypes = parameterTypes; + useInManyToOne = useManyToOne; } /// <summary> + /// Gets a value indicating whether to use this filter-def in manytoone refs. + /// </summary> + /// <value><c>true</c> if [use in many to one]; otherwise, <c>false</c>.</value> + public bool UseInManyToOne + { + get { return useInManyToOne; } + } + + /// <summary> /// Get the name of the filter this configuration defines. /// </summary> /// <returns>The filter name for this configuration.</returns> Modified: branches/2.1.x/nhibernate/src/NHibernate/Engine/JoinSequence.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -184,14 +184,10 @@ { // NH Different behavior : NH1179 and NH1293 // Apply filters in Many-To-One association - if (string.IsNullOrEmpty(on) && enabledFilters.Count > 0) - { - condition = join.Joinable.FilterFragment(join.Alias, enabledFilters); - } - else - { - condition = on; - } + var enabledForManyToOne = FilterHelper.GetEnabledForManyToOne(enabledFilters); + condition = string.IsNullOrEmpty(on) && enabledForManyToOne.Count > 0 + ? join.Joinable.FilterFragment(join.Alias, enabledForManyToOne) + : on; } if (withClauseFragment != null) Modified: branches/2.1.x/nhibernate/src/NHibernate/Loader/JoinWalker.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -17,6 +17,7 @@ protected readonly IList<OuterJoinableAssociation> associations = new List<OuterJoinableAssociation>(); private readonly ISet<AssociationKey> visitedAssociationKeys = new HashedSet<AssociationKey>(); private readonly IDictionary<string, IFilter> enabledFilters; + private readonly IDictionary<string, IFilter> enabledFiltersForManyToOne; private string[] suffixes; private string[] collectionSuffixes; @@ -113,6 +114,7 @@ { this.factory = factory; this.enabledFilters = enabledFilters; + enabledFiltersForManyToOne = FilterHelper.GetEnabledForManyToOne(enabledFilters); } /// <summary> @@ -566,12 +568,15 @@ oj.AddJoins(outerjoin); // NH Different behavior : NH1179 and NH1293 // Apply filters in Many-To-One association - if (enabledFilters.Count > 0) + if (enabledFiltersForManyToOne.Count > 0) { - var manyToOneFilterFragment = oj.Joinable.FilterFragment(oj.RHSAlias, enabledFilters); - var joinClauseDoesNotContainsFilterAlready = outerjoin.ToFromFragmentString.IndexOfCaseInsensitive(manyToOneFilterFragment) == -1; - if(joinClauseDoesNotContainsFilterAlready) + string manyToOneFilterFragment = oj.Joinable.FilterFragment(oj.RHSAlias, enabledFiltersForManyToOne); + bool joinClauseDoesNotContainsFilterAlready = + outerjoin.ToFromFragmentString.IndexOfCaseInsensitive(manyToOneFilterFragment) == -1; + if (joinClauseDoesNotContainsFilterAlready) + { outerjoin.AddCondition(manyToOneFilterFragment); + } } } last = oj; Modified: branches/2.1.x/nhibernate/src/NHibernate/Util/FilterHelper.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Util/FilterHelper.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Util/FilterHelper.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -67,5 +67,21 @@ } } } + + /// <summary> + /// Get only filters enabled for many-to-one association. + /// </summary> + /// <param name="enabledFilters">All enabled filters</param> + /// <returns>A new <see cref="IDictionary{TKey,TValue}"/> for filters enabled for many to one.</returns> + public static IDictionary<string, IFilter> GetEnabledForManyToOne(IDictionary<string, IFilter> enabledFilters) + { + var enabledFiltersForManyToOne = new Dictionary<string, IFilter>(); + foreach (var enabledFilter in enabledFilters) + { + if (enabledFilter.Value.FilterDefinition.UseInManyToOne) + enabledFiltersForManyToOne.Add(enabledFilter.Key, enabledFilter.Value); + } + return enabledFiltersForManyToOne; + } } } \ No newline at end of file Modified: branches/2.1.x/nhibernate/src/NHibernate/nhibernate-mapping.xsd =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2009-10-31 17:33:40 UTC (rev 4811) @@ -468,6 +468,7 @@ </xs:choice> <xs:attribute name="name" use="required" type="xs:string" /> <xs:attribute name="condition" type="xs:string" /> + <xs:attribute name="use-many-to-one" default="true" type="xs:boolean"/> </xs:complexType> </xs:element> <xs:element name="filter-param"> Added: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.ManyToOneFilters20Behaviour +{ + [TestFixture] + public class Fixture : BugTestCase + { + private static IList<Parent> joinGraphUsingHql(ISession s) + { + const string hql = @"select p from Parent p + join p.Child c"; + return s.CreateQuery(hql).List<Parent>(); + } + + private static IList<Parent> joinGraphUsingCriteria(ISession s) + { + return s.CreateCriteria(typeof (Parent)).SetFetchMode("Child", FetchMode.Join).List<Parent>(); + } + + private static Parent createParent() + { + return new Parent {Child = new Child()}; + } + + private static void enableFilters(ISession s) + { + IFilter f = s.EnableFilter("activeChild"); + f.SetParameter("active", 1); + IFilter f2 = s.EnableFilter("alwaysValid"); + f2.SetParameter("always", 1); + } + + protected override void OnTearDown() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + s.Delete("from Parent"); + tx.Commit(); + } + } + } + + [Test] + public void VerifyAlwaysFilter() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + Parent p = createParent(); + p.Child.Always = false; + s.Save(p); + tx.Commit(); + } + } + + using (ISession s = OpenSession()) + { + enableFilters(s); + IList<Parent> resCriteria = joinGraphUsingCriteria(s); + IList<Parent> resHql = joinGraphUsingHql(s); + + Assert.AreEqual(0, resCriteria.Count); + Assert.AreEqual(0, resHql.Count); + } + } + + [Test] + public void VerifyFilterActiveButNotUsedInManyToOne() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + s.Save(createParent()); + tx.Commit(); + } + } + + using (ISession s = OpenSession()) + { + enableFilters(s); + IList<Parent> resCriteria = joinGraphUsingCriteria(s); + IList<Parent> resHql = joinGraphUsingHql(s); + + Assert.AreEqual(1, resCriteria.Count); + Assert.IsNotNull(resCriteria[0].Child); + + Assert.AreEqual(1, resHql.Count); + Assert.IsNotNull(resHql[0].Child); + } + } + } +} \ No newline at end of file Added: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml 2009-10-31 17:33:40 UTC (rev 4811) @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.ManyToOneFilters20Behaviour" + assembly="NHibernate.Test"> + + <class name="Parent"> + <id name="Id"> + <generator class="guid.comb" /> + </id> + + <many-to-one name="Child" class="Child" cascade="all" not-null="true"/> + </class> + + <class name="Child"> + <id name="Id"> + <generator class="guid.comb" /> + </id> + <property name="IsActive"/> + <property name="Always"/> + <filter name="activeChild" condition=":active = IsActive" /> + <filter name="alwaysValid" condition=":always = Always" /> + </class> + + <filter-def name="activeChild" use-many-to-one="false"> + <filter-param name="active" type="int"/> + </filter-def> + + <filter-def name="alwaysValid"> + <filter-param name="always" type="int"/> + </filter-def> +</hibernate-mapping> + Added: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -0,0 +1,22 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.ManyToOneFilters20Behaviour +{ + public class Parent + { + public virtual Guid Id { get; set; } + public virtual Child Child { get; set; } + } + + public class Child + { + public Child() + { + Always = true; + } + + public virtual Guid Id { get; set; } + public virtual bool IsActive { get; set; } + public virtual bool Always { get; set; } + } +} \ No newline at end of file Modified: branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-31 17:33:40 UTC (rev 4811) @@ -368,6 +368,8 @@ <Compile Include="NHSpecificTest\ElementsEnums\IntEnumsBagPartialNameFixture.cs" /> <Compile Include="NHSpecificTest\ElementsEnums\IntEnumsBagFixture.cs" /> <Compile Include="NHSpecificTest\ElementsEnums\Something.cs" /> + <Compile Include="NHSpecificTest\ManyToOneFilters20Behaviour\Fixture.cs" /> + <Compile Include="NHSpecificTest\ManyToOneFilters20Behaviour\Model.cs" /> <Compile Include="NHSpecificTest\NH1025\Fixture.cs" /> <Compile Include="NHSpecificTest\NH1025\Model.cs" /> <Compile Include="NHSpecificTest\NH1255\Domain.cs" /> @@ -2017,6 +2019,7 @@ <EmbeddedResource Include="DriverTest\MultiTypeEntity.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\ManyToOneFilters20Behaviour\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2000\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2003\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1356\MappingsBag.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |