|
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.
|