From: <fab...@us...> - 2011-03-27 20:44:44
|
Revision: 5555 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5555&view=rev Author: fabiomaulo Date: 2011-03-27 20:44:38 +0000 (Sun, 27 Mar 2011) Log Message: ----------- Fix NH-2603 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Persister/Collection/AbstractCollectionPersister.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Model.cs Modified: trunk/nhibernate/src/NHibernate/Persister/Collection/AbstractCollectionPersister.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Persister/Collection/AbstractCollectionPersister.cs 2011-03-27 19:31:22 UTC (rev 5554) +++ trunk/nhibernate/src/NHibernate/Persister/Collection/AbstractCollectionPersister.cs 2011-03-27 20:44:38 UTC (rev 5555) @@ -844,11 +844,9 @@ private SqlString GenerateSelectSizeString(ISessionImplementor sessionImplementor) { - string selectValue = isCollectionIntegerIndex - ? "max(" + IndexColumnNames[0] + ") + 1" - : "count(" + ElementColumnNames[0] + ")"; //sets, maps, bags + string selectValue = GetCountSqlSelectClause(); - return new SqlSimpleSelectBuilder(dialect, factory) + return new SqlSimpleSelectBuilder(dialect, factory) .SetTableName(TableName) .AddWhereFragment(KeyColumnNames, KeyType, "=") .AddColumn(selectValue) @@ -856,6 +854,20 @@ .Append(FilterFragment(TableName, sessionImplementor.EnabledFilters)); } + protected virtual string GetCountSqlSelectClause() + { + // NH: too many "if" when each collection can have its persister + return isCollectionIntegerIndex + ? (string.Format("max({0}) + 1", IndexColumnNames[0])) + : (HasIndex ? string.Format("count({0})", GetIndexCountExpression()) : string.Format("count({0})", ElementColumnNames[0])); + } + + private string GetIndexCountExpression() + { + // when the index has at least one column then use that column to perform the count, otherwise it will use the formula. + return IndexColumnNames[0] ?? IndexFormulas[0]; + } + private SqlString GenerateDetectRowByIndexString() { if (!hasIndex) Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Fixture.cs 2011-03-27 20:44:38 UTC (rev 5555) @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.Test.NHSpecificTest.NH2603 +{ + public class Fixture : BugTestCase + { + #region Scenarios + + private class ListScenario : IDisposable + { + private readonly ISessionFactory factory; + + public ListScenario(ISessionFactory factory) + { + this.factory = factory; + using (ISession s = factory.OpenSession()) + { + using (ITransaction t = s.BeginTransaction()) + { + var entity = new Parent(); + var child = new Child(); + entity.ListChildren = new List<Child> {null, child, null}; + s.Save(entity); + t.Commit(); + } + } + } + + public void Dispose() + { + using (ISession s = factory.OpenSession()) + { + using (ITransaction t = s.BeginTransaction()) + { + s.Delete("from Parent"); + s.Delete("from Child"); + t.Commit(); + } + } + } + } + + private class MapScenario : IDisposable + { + private readonly ISessionFactory factory; + + public MapScenario(ISessionFactory factory) + { + this.factory = factory; + using (ISession s = factory.OpenSession()) + { + using (ITransaction t = s.BeginTransaction()) + { + var entity = new Parent(); + entity.MapChildren = new Dictionary<int, Child> + { + {0, null}, + {1, new Child()}, + {2, null}, + }; + s.Save(entity); + t.Commit(); + } + } + } + + public void Dispose() + { + using (ISession s = factory.OpenSession()) + { + using (ITransaction t = s.BeginTransaction()) + { + s.Delete("from Parent"); + s.Delete("from Child"); + t.Commit(); + } + } + } + } + + #endregion + + [Test] + public void List() + { + using (new ListScenario(Sfi)) + { + // by design NH will clean null elements at the end of the List since 'null' and 'no element' mean the same. + // the effective ammount store will be 1(one) because ther is only one valid element but whem we initialize the collection + // it will have 2 elements (the first with null) + using (ISession s = OpenSession()) + { + using (ITransaction t = s.BeginTransaction()) + { + var entity = s.CreateQuery("from Parent").UniqueResult<Parent>(); + IList<object[]> members = s.GetNamedQuery("ListMemberSpy") + .SetParameter("parentid", entity.Id) + .List<object[]>(); + int lazyCount = entity.ListChildren.Count; + NHibernateUtil.IsInitialized(entity.ListChildren).Should().Be.False(); + NHibernateUtil.Initialize(entity.ListChildren); + int initCount = entity.ListChildren.Count; + initCount.Should().Be.EqualTo(lazyCount); + members.Count.Should("because only the valid element should be persisted.").Be(1); + } + } + } + } + + [Test] + public void Map() + { + using (new MapScenario(Sfi)) + { + using (ISession s = OpenSession()) + { + // for the case of <map> what really matter is the key, then NH should count the KEY and not the elements. + using (ITransaction t = s.BeginTransaction()) + { + var entity = s.CreateQuery("from Parent").UniqueResult<Parent>(); + IList<object[]> members = s.GetNamedQuery("MapMemberSpy") + .SetParameter("parentid", entity.Id) + .List<object[]>(); + int lazyCount = entity.MapChildren.Count; + NHibernateUtil.IsInitialized(entity.MapChildren).Should().Be.False(); + NHibernateUtil.Initialize(entity.MapChildren); + int initCount = entity.MapChildren.Count; + initCount.Should().Be.EqualTo(lazyCount); + members.Count.Should("because all elements with a valid key should be persisted.").Be(3); + } + } + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Mappings.hbm.xml 2011-03-27 20:44:38 UTC (rev 5555) @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.NH2603" + assembly="NHibernate.Test" +> + <class name="Parent" > + <id name="Id"> + <generator class="increment"/> + </id> + <list name="ListChildren" lazy="extra" cascade="all" table="ListChildren"> + <key column="listparentid"/> + <!-- sqlite doesn't like a column named index --> + <index column="childindex"/> + <many-to-many class="Child" column="childid"/> + </list> + <map name="MapChildren" lazy="extra" cascade="all" table="MapChildren"> + <key column="mapparentid" /> + <map-key column="childindex" type="int" /> + <many-to-many class="Child"> + <column name="childid" not-null="false" /> + </many-to-many> + </map> + </class> + + <class name="Child"> + <id name="Id"> + <generator class="increment"/> + </id> + </class> + + <sql-query name="ListMemberSpy"> + select listparentid, childindex, childid + from ListChildren + where listparentid = :parentid + </sql-query> + + <sql-query name="MapMemberSpy"> + select mapparentid, childindex, childid + from MapChildren + where mapparentid = :parentid + </sql-query> + +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2603/Model.cs 2011-03-27 20:44:38 UTC (rev 5555) @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH2603 +{ + public class Parent + { + public virtual int Id + { + get; + set; + } + + public virtual IList<Child> ListChildren + { + get; + set; + } + + public virtual IDictionary<int, Child> MapChildren + { + get; + set; + } + } + + public class Child + { + public virtual int Id + { + get; + set; + } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-03-27 19:31:22 UTC (rev 5554) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-03-27 20:44:38 UTC (rev 5555) @@ -670,6 +670,8 @@ <Compile Include="NHSpecificTest\NH2565\Domain.cs" /> <Compile Include="NHSpecificTest\NH2565\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2580\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2603\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2603\Model.cs" /> <Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" /> <Compile Include="NHSpecificTest\Properties\DynamicEntityTest.cs" /> <Compile Include="NHSpecificTest\Properties\Model.cs" /> @@ -2496,6 +2498,7 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH2603\Mappings.hbm.xml" /> <EmbeddedResource Include="Subselect\Beings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2488\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2490\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |