You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
(248) |
May
(82) |
Jun
(90) |
Jul
(177) |
Aug
(253) |
Sep
(157) |
Oct
(151) |
Nov
(143) |
Dec
(278) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(152) |
Feb
(107) |
Mar
(177) |
Apr
(133) |
May
(259) |
Jun
(81) |
Jul
(119) |
Aug
(306) |
Sep
(416) |
Oct
(240) |
Nov
(329) |
Dec
(206) |
2006 |
Jan
(466) |
Feb
(382) |
Mar
(153) |
Apr
(162) |
May
(133) |
Jun
(21) |
Jul
(18) |
Aug
(37) |
Sep
(97) |
Oct
(114) |
Nov
(110) |
Dec
(28) |
2007 |
Jan
(74) |
Feb
(65) |
Mar
(49) |
Apr
(76) |
May
(43) |
Jun
(15) |
Jul
(68) |
Aug
(55) |
Sep
(63) |
Oct
(59) |
Nov
(70) |
Dec
(66) |
2008 |
Jan
(71) |
Feb
(60) |
Mar
(120) |
Apr
(31) |
May
(48) |
Jun
(81) |
Jul
(107) |
Aug
(51) |
Sep
(80) |
Oct
(83) |
Nov
(83) |
Dec
(79) |
2009 |
Jan
(83) |
Feb
(110) |
Mar
(97) |
Apr
(91) |
May
(291) |
Jun
(250) |
Jul
(197) |
Aug
(58) |
Sep
(54) |
Oct
(122) |
Nov
(68) |
Dec
(34) |
2010 |
Jan
(50) |
Feb
(17) |
Mar
(63) |
Apr
(61) |
May
(84) |
Jun
(81) |
Jul
(138) |
Aug
(144) |
Sep
(78) |
Oct
(26) |
Nov
(30) |
Dec
(61) |
2011 |
Jan
(33) |
Feb
(35) |
Mar
(166) |
Apr
(221) |
May
(109) |
Jun
(76) |
Jul
(27) |
Aug
(37) |
Sep
(1) |
Oct
(4) |
Nov
(2) |
Dec
(1) |
2012 |
Jan
|
Feb
|
Mar
(2) |
Apr
(2) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2013 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(1) |
Sep
(3) |
Oct
(2) |
Nov
|
Dec
(1) |
2014 |
Jan
(1) |
Feb
(1) |
Mar
(3) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <fab...@us...> - 2011-07-10 15:26:35
|
Revision: 5979 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5979&view=rev Author: fabiomaulo Date: 2011-07-10 15:26:29 +0000 (Sun, 10 Jul 2011) Log Message: ----------- Set the current version of the trunk Modified Paths: -------------- trunk/nhibernate/build-common/common.xml Modified: trunk/nhibernate/build-common/common.xml =================================================================== --- trunk/nhibernate/build-common/common.xml 2011-07-10 15:16:45 UTC (rev 5978) +++ trunk/nhibernate/build-common/common.xml 2011-07-10 15:26:29 UTC (rev 5979) @@ -84,7 +84,7 @@ effectively SP0). --> - <property name="project.version" value="3.2.0.CR1" overwrite="false" /> + <property name="project.version" value="3.2.0.GA" overwrite="false" /> <!-- Compute short project version (major.minor) using a regex --> <regex input="${project.version}" pattern="^(?'shortversion'\d+\.\d+)" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-07-10 15:16:51
|
Revision: 5978 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5978&view=rev Author: fabiomaulo Date: 2011-07-10 15:16:45 +0000 (Sun, 10 Jul 2011) Log Message: ----------- Fix NH-2743 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/ISession.cs trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs Modified: trunk/nhibernate/src/NHibernate/ISession.cs =================================================================== --- trunk/nhibernate/src/NHibernate/ISession.cs 2011-07-09 20:30:42 UTC (rev 5977) +++ trunk/nhibernate/src/NHibernate/ISession.cs 2011-07-10 15:16:45 UTC (rev 5978) @@ -491,6 +491,36 @@ object Merge(string entityName, object obj); /// <summary> + /// Copy the state of the given object onto the persistent object with the same + /// identifier. If there is no persistent instance currently associated with + /// the session, it will be loaded. Return the persistent instance. If the + /// given instance is unsaved, save a copy of and return it as a newly persistent + /// instance. The given instance does not become associated with the session. + /// This operation cascades to associated instances if the association is mapped + /// with <tt>cascade="merge"</tt>.<br/> + /// The semantics of this method are defined by JSR-220. + /// </summary> + /// <param name="entity">a detached instance with state to be copied </param> + /// <returns> an updated persistent instance </returns> + T Merge<T>(T entity) where T : class; + + /// <summary> + /// Copy the state of the given object onto the persistent object with the same + /// identifier. If there is no persistent instance currently associated with + /// the session, it will be loaded. Return the persistent instance. If the + /// given instance is unsaved, save a copy of and return it as a newly persistent + /// instance. The given instance does not become associated with the session. + /// This operation cascades to associated instances if the association is mapped + /// with <tt>cascade="merge"</tt>.<br/> + /// The semantics of this method are defined by JSR-220. + /// <param name="entityName">Name of the entity.</param> + /// <param name="entity">a detached instance with state to be copied </param> + /// <returns> an updated persistent instance </returns> + /// </summary> + /// <returns></returns> + T Merge<T>(string entityName, T entity) where T : class; + + /// <summary> /// Make a transient instance persistent. This operation cascades to associated /// instances if the association is mapped with <tt>cascade="persist"</tt>.<br/> /// The semantics of this method are defined by JSR-220. Modified: trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2011-07-09 20:30:42 UTC (rev 5977) +++ trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2011-07-10 15:16:45 UTC (rev 5978) @@ -986,6 +986,16 @@ } } + public T Merge<T>(T entity) where T : class + { + return (T) Merge((object) entity); + } + + public T Merge<T>(string entityName, T entity) where T : class + { + return (T) Merge(entityName, (object) entity); + } + public object Merge(object obj) { using (new SessionIdLoggingContext(SessionId)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-07-09 20:30:48
|
Revision: 5977 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5977&view=rev Author: fabiomaulo Date: 2011-07-09 20:30:42 +0000 (Sat, 09 Jul 2011) Log Message: ----------- Not a real issue was just the mapping; the test is just to have another tests checking FK names generation. Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/A.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/A.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/B.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/B.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/C.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/C.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/Fixture.cs Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/A.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/A.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/A.cs 2011-07-09 20:30:42 UTC (rev 5977) @@ -0,0 +1,73 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.NH2761 +{ + public class A + { + public Int32 Id + { + get; + set; + } + + public B B + { + get; + set; + } + + public C C + { + get; + set; + } + + public String AProperty + { + get; + set; + } + + public override Int32 GetHashCode() + { + return (this.Id.GetHashCode()); + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return (false); + } + + if (this.GetType() != obj.GetType()) + { + return (false); + } + + A other = obj as A; + + if (Object.Equals(other.Id, this.Id) == false) + { + return (false); + } + + if (Object.Equals(other.AProperty, this.AProperty) == false) + { + return (false); + } + + if (Object.Equals(other.B, this.B) == false) + { + return (false); + } + + if (Object.Equals(other.C, this.C) == false) + { + return (false); + } + + return (true); + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/A.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/A.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/A.hbm.xml 2011-07-09 20:30:42 UTC (rev 5977) @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<hibernate-mapping default-lazy="false" + namespace="NHibernate.Test.NHSpecificTest.NH2761" + assembly="NHibernate.Test" + xmlns="urn:nhibernate-mapping-2.2"> + <class name="A" lazy="false" table="`A`"> + <id name="Id" access="property" column="`A_ID`"> + <generator class="hilo" /> + </id> + <property name="AProperty" column="`A_PROPERTY`" length="50"/> + <many-to-one name="B" class="B" column="`B_ID`" not-null="false" /> + <many-to-one name="C" class="C" column="`C_ID`" not-null="false" /> + </class> +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/B.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/B.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/B.cs 2011-07-09 20:30:42 UTC (rev 5977) @@ -0,0 +1,68 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.NH2761 +{ + public class B + { + public B() + { + this.As = new Iesi.Collections.Generic.HashedSet<A>(); + } + + public Int32 Id + { + get; + set; + } + + public String BProperty + { + get; + set; + } + + public C C + { + get; + set; + } + + public Iesi.Collections.Generic.ISet<A> As + { + get; + set; + } + + public override Int32 GetHashCode() + { + return (this.Id.GetHashCode()); + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return (false); + } + + if (this.GetType() != obj.GetType()) + { + return (false); + } + + B other = obj as B; + + if (Object.Equals(other.Id, this.Id) == false) + { + return (false); + } + + if (Object.Equals(other.BProperty, this.BProperty) == false) + { + return (false); + } + + return (true); + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/B.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/B.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/B.hbm.xml 2011-07-09 20:30:42 UTC (rev 5977) @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<hibernate-mapping default-lazy="false" + namespace="NHibernate.Test.NHSpecificTest.NH2761" + assembly="NHibernate.Test" + xmlns="urn:nhibernate-mapping-2.2"> + <class name="B" lazy="false" table="`B`"> + <id name="Id" access="property" column="`B_ID`"> + <generator class="hilo" /> + </id> + <property name="BProperty" column="`B_PROPERTY`" length="50"/> + <set name="As" inverse="true"> + <key column="`B_ID`"/> + <one-to-many class="A"/> + </set> + <many-to-one name="C" class="C" column="`C_ID`" not-null="false" fetch="select"/> + </class> +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/C.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/C.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/C.cs 2011-07-09 20:30:42 UTC (rev 5977) @@ -0,0 +1,69 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.NH2761 +{ + public class C + { + public C() + { + this.As = new Iesi.Collections.Generic.HashedSet<A>(); + this.Bs = new Iesi.Collections.Generic.HashedSet<B>(); + } + + public Int32 Id + { + get; + set; + } + + public String CProperty + { + get; + set; + } + + public Iesi.Collections.Generic.ISet<B> Bs + { + get; + set; + } + + public Iesi.Collections.Generic.ISet<A> As + { + get; + set; + } + + public override Int32 GetHashCode() + { + return (this.Id.GetHashCode()); + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return (false); + } + + if (this.GetType() != obj.GetType()) + { + return (false); + } + + C other = obj as C; + + if (Object.Equals(other.Id, this.Id) == false) + { + return (false); + } + + if (Object.Equals(other.CProperty, this.CProperty) == false) + { + return (false); + } + + return (true); + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/C.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/C.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/C.hbm.xml 2011-07-09 20:30:42 UTC (rev 5977) @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<hibernate-mapping default-lazy="false" + namespace="NHibernate.Test.NHSpecificTest.NH2761" + assembly="NHibernate.Test" + xmlns="urn:nhibernate-mapping-2.2"> + <class name="C" lazy="false" table="`C`"> + <id name="Id" access="property" column="`C_ID`"> + <generator class="hilo" /> + </id> + <property name="CProperty" column="`C_PROPERTY`" length="50"/> + <set name="As" inverse="true" lazy="true"> + <key column="`A_ID`"/> + <one-to-many class="A"/> + </set> + <set name="Bs" inverse="true"> + <key column="`B_ID`"/> + <one-to-many class="B"/> + </set> + </class> +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2761/Fixture.cs 2011-07-09 20:30:42 UTC (rev 5977) @@ -0,0 +1,40 @@ +using System.Linq; +using System.Reflection; +using NHibernate.Cfg; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.Test.NHSpecificTest.NH2761 +{ + public class Fixture + { + [Test] + public void WhenMultipleConfigurationUseSameMappingsThenConstraintsHasSameNames() + { + var mappings1 = GetMappings(); + var mappings2 = GetMappings(); + + var fkNamesForMappings1 = mappings1.IterateTables.SelectMany(t => t.ForeignKeyIterator).Select(fk => fk.Name).ToArray(); + var fkNamesForMappings2 = mappings2.IterateTables.SelectMany(t => t.ForeignKeyIterator).Select(fk => fk.Name).ToArray(); + + fkNamesForMappings1.Should().Have.SameValuesAs(fkNamesForMappings2); + } + + private Mappings GetMappings() + { + var configuration = GetConfiguration(); + return configuration.CreateMappings(Dialect.Dialect.GetDialect(configuration.Properties)); + } + + private Configuration GetConfiguration() + { + // for each call will use a differente instance of configuration + var configuration = TestConfigurationHelper.GetDefaultConfiguration(); + Assembly thisAssembly = GetType().Assembly; + configuration.AddResource("NHibernate.Test.NHSpecificTest.NH2761.A.hbm.xml", thisAssembly); + configuration.AddResource("NHibernate.Test.NHSpecificTest.NH2761.B.hbm.xml", thisAssembly); + configuration.AddResource("NHibernate.Test.NHSpecificTest.NH2761.C.hbm.xml", thisAssembly); + return configuration; + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-07-04 11:57:22 UTC (rev 5976) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-07-09 20:30:42 UTC (rev 5977) @@ -882,6 +882,10 @@ <Compile Include="NHSpecificTest\NH2746\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2760\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2760\Model.cs" /> + <Compile Include="NHSpecificTest\NH2761\A.cs" /> + <Compile Include="NHSpecificTest\NH2761\B.cs" /> + <Compile Include="NHSpecificTest\NH2761\C.cs" /> + <Compile Include="NHSpecificTest\NH2761\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2773\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2773\Model.cs" /> <Compile Include="NHSpecificTest\NH941\Domain.cs" /> @@ -2730,6 +2734,9 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH2761\A.hbm.xml" /> + <EmbeddedResource Include="NHSpecificTest\NH2761\B.hbm.xml" /> + <EmbeddedResource Include="NHSpecificTest\NH2761\C.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2773\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2693\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2746\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-07-04 11:57:28
|
Revision: 5976 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5976&view=rev Author: fabiomaulo Date: 2011-07-04 11:57:22 +0000 (Mon, 04 Jul 2011) Log Message: ----------- Preparing release Modified Paths: -------------- trunk/nhibernate/releasenotes.txt Modified: trunk/nhibernate/releasenotes.txt =================================================================== --- trunk/nhibernate/releasenotes.txt 2011-06-29 21:23:27 UTC (rev 5975) +++ trunk/nhibernate/releasenotes.txt 2011-07-04 11:57:22 UTC (rev 5976) @@ -14,6 +14,21 @@ * For those implementing IDrive without inherit from DriveBase: IDrive.AdjustCommand * Dialect base: removed some no more needed properties +Build 3.2.0.CR1 (rev5976) +============================= +** Bug + * [NH-2118] - GroupBy without Select doesnt work + * [NH-2387] - Postgres - Unable to run LINQ query using boolean predicate - ERROR: 42883: operator does not exist: boolean = integer + * [NH-2435] - No order by clause generated with self referencing orderby clause. + * [NH-2583] - Query with || operator and navigations (many-to-one) creates wrong joins + * [NH-2773] - ProxyObjectReference creates a new ProxyFactory for each deserialization which disables proxy caching + +** Improvement + * [NH-2748] - Support % operator + +** Patch + * [NH-2774] - Perf - reusing same regex object in joinwalker objects + Build 3.2.0.Beta2 (rev5964) ============================= ** Bug This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-06-29 21:23:33
|
Revision: 5975 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5975&view=rev Author: ricbrown Date: 2011-06-29 21:23:27 +0000 (Wed, 29 Jun 2011) Log Message: ----------- NH-2683: doc update for QueryOver extensions Modified Paths: -------------- trunk/nhibernate/doc/reference/modules/query_queryover.xml Modified: trunk/nhibernate/doc/reference/modules/query_queryover.xml =================================================================== --- trunk/nhibernate/doc/reference/modules/query_queryover.xml 2011-06-28 05:58:43 UTC (rev 5974) +++ trunk/nhibernate/doc/reference/modules/query_queryover.xml 2011-06-29 21:23:27 UTC (rev 5975) @@ -156,6 +156,16 @@ Restrictions.Where<Cat>(c => c.Age > 5) Restrictions.On<Cat>(c => c.Name).IsIn(new string[] { "Max", "Paddy" })))]]></programlisting> + <para> + However, in addition to the additional restrictions factory methods, there are extension methods to allow + a more concise inline syntax for some of the operators. So this: + </para> + <programlisting><![CDATA[ .WhereRestrictionOn(c => c.Name).IsLike("%anna%")]]></programlisting> + <para> + May also be written as: + </para> + <programlisting><![CDATA[ .Where(c => c..Name.IsLike("%anna%"))]]></programlisting> + </sect1> <sect1 id="queryqueryover-associations"> @@ -322,6 +332,24 @@ </sect1> + <sect1 id="queryqueryover-projectionfunctions"> + <title>Projection Functions</title> + + <para> + In addition to projecting properties, there are extension methods to allow certain common dialect-registered + functions to be applied. For example you can write the following to extract just the year part of a date: + </para> + <programlisting><![CDATA[ .Where(p => p.BirthDate.YearPart() == 1971)]]></programlisting> + + <para> + The functions can also be used inside projections: + </para> + <programlisting><![CDATA[ .Select( + p => Projections.Concat(p.LastName, ", ", p.FirstName), + p => p.Height.Abs())]]></programlisting> + + </sect1> + <sect1 id="queryqueryover-subqueries"> <title>Subqueries</title> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-06-28 05:58:49
|
Revision: 5974 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5974&view=rev Author: patearl Date: 2011-06-28 05:58:43 +0000 (Tue, 28 Jun 2011) Log Message: ----------- Tests: Enabled now passing NH-2118 test. Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2118/Fixture.cs Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2118/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2118/Fixture.cs 2011-06-28 05:47:09 UTC (rev 5973) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2118/Fixture.cs 2011-06-28 05:58:43 UTC (rev 5974) @@ -12,7 +12,6 @@ } [TestFixture] - [Ignore("Not fixed yet.")] public class Fixture : BugTestCase { protected override void OnSetUp() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-06-28 05:47:15
|
Revision: 5973 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5973&view=rev Author: patearl Date: 2011-06-28 05:47:09 +0000 (Tue, 28 Jun 2011) Log Message: ----------- Linq: Support basic non-aggregating group-by. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Linq/GroupBy/NonAggregatingGroupByRewriter.cs trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs Modified: trunk/nhibernate/src/NHibernate/Linq/GroupBy/NonAggregatingGroupByRewriter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/GroupBy/NonAggregatingGroupByRewriter.cs 2011-06-27 04:19:03 UTC (rev 5972) +++ trunk/nhibernate/src/NHibernate/Linq/GroupBy/NonAggregatingGroupByRewriter.cs 2011-06-28 05:47:09 UTC (rev 5973) @@ -18,6 +18,17 @@ public static void ReWrite(QueryModel queryModel) { + if (queryModel.ResultOperators.Count == 1 && + queryModel.ResultOperators[0] is GroupResultOperator && + IsNonAggregatingGroupBy(queryModel)) + { + GroupResultOperator resultOperator = (GroupResultOperator)queryModel.ResultOperators[0]; + queryModel.ResultOperators.Clear(); + queryModel.ResultOperators.Add(new NonAggregatingGroupBy(resultOperator)); + + return; + } + var subQueryExpression = queryModel.MainFromClause.FromExpression as SubQueryExpression; if ((subQueryExpression != null) && Modified: trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs 2011-06-27 04:19:03 UTC (rev 5972) +++ trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs 2011-06-28 05:47:09 UTC (rev 5973) @@ -28,20 +28,20 @@ } [Test] - [Ignore("Not working yet.")] public void SingleKeyGrouping() { var orders = db.Orders.GroupBy(o => o.Customer).ToList(); - Assert.That(orders.Count, Is.EqualTo(830)); + Assert.That(orders.Count(), Is.EqualTo(89)); + Assert.That(orders.Sum(o => o.Count()), Is.EqualTo(830)); CheckGrouping(orders, o => o.Customer); } [Test] - [Ignore("Not working yet.")] public void MultipleKeyGrouping() { var orders = db.Orders.GroupBy(o => new { o.Customer, o.Employee }).ToList(); - Assert.That(orders.Count, Is.EqualTo(830)); + Assert.That(orders.Count(), Is.EqualTo(464)); + Assert.That(orders.Sum(o => o.Count()), Is.EqualTo(830)); CheckGrouping( orders.Select(g => new TupGrouping<Customer, Employee, Order>(g.Key.Customer, g.Key.Employee, g)), @@ -69,10 +69,8 @@ HashSet<object> used = new HashSet<object>(); foreach (IGrouping<Tup<TKey1, TKey2>, TElement> group in groupedItems) { - Assert.IsFalse(used.Contains(group.Key.Item1)); - used.Add(group.Key.Item1); - Assert.IsFalse(used.Contains(group.Key.Item2)); - used.Add(group.Key.Item2); + Assert.IsFalse(used.Contains(group.Key)); + used.Add(group.Key); foreach (var item in group) { @@ -115,6 +113,24 @@ Item1 = item1; Item2 = item2; } + + public override bool Equals(object obj) + { + if (obj == null) + return false; + + if (obj.GetType() != GetType()) + return false; + + Tup<T1, T2> other = (Tup<T1, T2>) obj; + + return Equals(Item1, other.Item1) && Equals(Item2, other.Item2); + } + + public override int GetHashCode() + { + return Item1.GetHashCode() ^ Item2.GetHashCode(); + } } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-06-27 04:19:09
|
Revision: 5972 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5972&view=rev Author: patearl Date: 2011-06-27 04:19:03 +0000 (Mon, 27 Jun 2011) Log Message: ----------- Linq: Added a couple tests for boolean comparison to ensure that an issue had been fixed. Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/Linq/BinaryBooleanExpressionTests.cs Modified: trunk/nhibernate/src/NHibernate.Test/Linq/BinaryBooleanExpressionTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/BinaryBooleanExpressionTests.cs 2011-06-27 03:44:53 UTC (rev 5971) +++ trunk/nhibernate/src/NHibernate.Test/Linq/BinaryBooleanExpressionTests.cs 2011-06-27 04:19:03 UTC (rev 5972) @@ -90,6 +90,20 @@ } [Test] + public void BooleanPropertyComparison() + { + var query = db.Timesheets.Where(t => t.Submitted == true); + Assert.AreEqual(2, query.ToList().Count); + } + + [Test] + public void BooleanPropertyAlone() + { + var query = db.Timesheets.Where(t => t.Submitted); + Assert.AreEqual(2, query.ToList().Count); + } + + [Test] public void MammalsViaDynamicInvokedExpression() { //simulate dynamically created where clause This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-06-27 03:45:00
|
Revision: 5971 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5971&view=rev Author: patearl Date: 2011-06-27 03:44:53 +0000 (Mon, 27 Jun 2011) Log Message: ----------- Linq: Support for % operator. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/Linq/OperatorTests.cs Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2011-06-27 01:40:52 UTC (rev 5970) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2011-06-27 03:44:53 UTC (rev 5971) @@ -291,6 +291,9 @@ case ExpressionType.Divide: return _hqlTreeBuilder.Divide(lhs, rhs); + case ExpressionType.Modulo: + return _hqlTreeBuilder.MethodCall("mod", lhs, rhs); + case ExpressionType.LessThan: return _hqlTreeBuilder.LessThan(lhs, rhs); Added: trunk/nhibernate/src/NHibernate.Test/Linq/OperatorTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/OperatorTests.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/Linq/OperatorTests.cs 2011-06-27 03:44:53 UTC (rev 5971) @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NHibernate.DomainModel.Northwind.Entities; +using NHibernate.Linq; +using NUnit.Framework; + +namespace NHibernate.Test.Linq +{ + [TestFixture] + public class OperatorTests : LinqTestCase + { + [Test] + public void Mod() + { + Assert.AreEqual(2, session.Query<TimesheetEntry>().Where(a => a.NumberOfHours % 7 == 0).Count()); + } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-27 01:40:52 UTC (rev 5970) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-27 03:44:53 UTC (rev 5971) @@ -502,6 +502,7 @@ <Compile Include="Linq\NullComparisonTests.cs" /> <Compile Include="Linq\ObjectDumper.cs" /> <Compile Include="Linq\ByMethod\OrderByTests.cs" /> + <Compile Include="Linq\OperatorTests.cs" /> <Compile Include="Linq\PagingTests.cs" /> <Compile Include="Linq\ParameterisedQueries.cs" /> <Compile Include="Linq\PatientTests.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-06-27 01:40:58
|
Revision: 5970 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5970&view=rev Author: patearl Date: 2011-06-27 01:40:52 +0000 (Mon, 27 Jun 2011) Log Message: ----------- Linq: Minor improvement to a unit test. Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/OrderByTests.cs Modified: trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/OrderByTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/OrderByTests.cs 2011-06-27 00:59:46 UTC (rev 5969) +++ trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/OrderByTests.cs 2011-06-27 01:40:52 UTC (rev 5970) @@ -125,7 +125,8 @@ // Check join result. var allAnimals = db.Animals; var orderedAnimals = from a in db.Animals orderby a.Father.SerialNumber select a; - Assert.AreEqual(allAnimals.Count(), orderedAnimals.Count()); + // We to ToList() first or it skips the generation of the joins. + Assert.AreEqual(allAnimals.ToList().Count(), orderedAnimals.ToList().Count()); } } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-06-27 00:59:54
|
Revision: 5969 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5969&view=rev Author: patearl Date: 2011-06-27 00:59:46 +0000 (Mon, 27 Jun 2011) Log Message: ----------- Linq: Improved join detection in linq where clauses. Uses an easier to understand algorithm that corrects many cases. Also added some related tests. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Linq/Visitors/WhereJoinDetector.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Linq/Visitors/PossibleValueSet.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2583/InnerJoinFixture.cs Removed Paths: ------------- trunk/nhibernate/src/NHibernate/Linq/Visitors/WhereJoinDetectorDesignNotes.txt Added: trunk/nhibernate/src/NHibernate/Linq/Visitors/PossibleValueSet.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/PossibleValueSet.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/PossibleValueSet.cs 2011-06-27 00:59:46 UTC (rev 5969) @@ -0,0 +1,370 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NHibernate.Linq.Visitors +{ + /// <summary> + /// Represents a possible set of values for a computation. For example, an expression may + /// be null, it may be a non-null value, or we may even have a constant value that is known + /// precisely. This class contains operators that know how to combine these values with + /// each other. This class is intended to be used to provide static analysis of expressions + /// before we hit the database. As an example for future improvement, we could handle + /// ranges of numeric values. We can also improve this by handling operators such as the + /// comparison operators and arithmetic operators. They are currently handled by naive + /// null checks. + /// </summary> + public class PossibleValueSet + { + private System.Type ExpressionType { get; set; } + private bool ContainsNull { get; set; } + private bool ContainsAllNonNullValues { get; set; } + private List<object> DistinctValues + { + get + { + if (_DistinctValues == null) + _DistinctValues = new List<object>(); + return _DistinctValues; + } + } + private List<object> _DistinctValues; + + private bool ContainsAnyNonNullValues + { + get { return ContainsAllNonNullValues || DistinctValues.Any(); } + } + + private PossibleValueSet(System.Type expressionType) + { + ExpressionType = expressionType; + } + + public bool Contains(object obj) + { + if (obj == null) + return ContainsNull; + + if (obj.GetType() != ExpressionType) + return false; + + if (ContainsAllNonNullValues) + return true; + + return DistinctValues.Contains(obj); + } + + #region Operations + + public PossibleValueSet Add(PossibleValueSet pvs, System.Type resultType) + { + return MathOperation(pvs, resultType); + } + + public PossibleValueSet Divide(PossibleValueSet pvs, System.Type resultType) + { + return MathOperation(pvs, resultType); + } + + public PossibleValueSet Modulo(PossibleValueSet pvs, System.Type resultType) + { + return MathOperation(pvs, resultType); + } + + public PossibleValueSet Multiply(PossibleValueSet pvs, System.Type resultType) + { + return MathOperation(pvs, resultType); + } + + public PossibleValueSet Power(PossibleValueSet pvs, System.Type resultType) + { + return MathOperation(pvs, resultType); + } + + public PossibleValueSet Subtract(PossibleValueSet pvs, System.Type resultType) + { + return MathOperation(pvs, resultType); + } + + public PossibleValueSet And(PossibleValueSet pvs, System.Type resultType) + { + return MathOperation(pvs, resultType); + } + + public PossibleValueSet Or(PossibleValueSet pvs, System.Type resultType) + { + return MathOperation(pvs, resultType); + } + + public PossibleValueSet ExclusiveOr(PossibleValueSet pvs, System.Type resultType) + { + return MathOperation(pvs, resultType); + } + + public PossibleValueSet LeftShift(PossibleValueSet pvs, System.Type resultType) + { + return MathOperation(pvs, resultType); + } + + public PossibleValueSet RightShift(PossibleValueSet pvs, System.Type resultType) + { + return MathOperation(pvs, resultType); + } + + private PossibleValueSet MathOperation(PossibleValueSet pvs, System.Type resultType) + { + // If either side is only null, the result will be null. + if (!ContainsAnyNonNullValues || !pvs.ContainsAnyNonNullValues) + return CreateNull(resultType); + + // If neither side is null, the result cannot be null. + if (!ContainsNull && !pvs.ContainsNull) + return CreateAllNonNullValues(resultType); + + // Otherwise, the result can be anything. + return CreateAllValues(resultType); + } + + public PossibleValueSet AndAlso(PossibleValueSet pvs) + { + /* + * T && T == T + * T && F == F + * T && N == N + * F && T == F + * F && F == F + * F && N == F + * N && T == N + * N && F == F + * N && N == N + */ + + CheckType<bool>(); + pvs.CheckType<bool>(); + PossibleValueSet result = new PossibleValueSet(typeof(bool)); + + if (Contains(true) && pvs.Contains(true) && !result.Contains(true)) result.DistinctValues.Add(true); + if (Contains(true) && pvs.Contains(false) && !result.Contains(false)) result.DistinctValues.Add(false); + if (Contains(true) && pvs.Contains(null)) result.ContainsNull = true; + if (Contains(false) && pvs.Contains(true) && !result.Contains(false)) result.DistinctValues.Add(false); + if (Contains(false) && pvs.Contains(false) && !result.Contains(false)) result.DistinctValues.Add(false); + if (Contains(false) && pvs.Contains(null) && !result.Contains(false)) result.DistinctValues.Add(false); + if (Contains(null) && pvs.Contains(true)) result.ContainsNull = true; + if (Contains(null) && pvs.Contains(false) && !result.Contains(false)) result.DistinctValues.Add(false); + if (Contains(null) && pvs.Contains(null)) result.ContainsNull = true; + + return result; + } + + public PossibleValueSet OrElse(PossibleValueSet pvs) + { + /* + * T || T == T + * T || F == T + * T || N == T + * F || T == T + * F || F == F + * F || N == N + * N || T == T + * N || F == N + * N || N == N + */ + + CheckType<bool>(); + pvs.CheckType<bool>(); + + PossibleValueSet result = new PossibleValueSet(typeof(bool)); + + if (Contains(true) && pvs.Contains(true) && !result.Contains(true)) result.DistinctValues.Add(true); + if (Contains(true) && pvs.Contains(false) && !result.Contains(true)) result.DistinctValues.Add(true); + if (Contains(true) && pvs.Contains(null) && !result.Contains(true)) result.DistinctValues.Add(true); + if (Contains(false) && pvs.Contains(true) && !result.Contains(true)) result.DistinctValues.Add(true); + if (Contains(false) && pvs.Contains(false) && !result.Contains(false)) result.DistinctValues.Add(false); + if (Contains(false) && pvs.Contains(null)) result.ContainsNull = true; + if (Contains(null) && pvs.Contains(true) && !result.Contains(true)) result.DistinctValues.Add(true); + if (Contains(null) && pvs.Contains(false)) result.ContainsNull = true; + if (Contains(null) && pvs.Contains(null)) result.ContainsNull = true; + + return result; + } + + public PossibleValueSet Equal(PossibleValueSet pvs) + { + return ComparisonOperation(pvs); + } + + public PossibleValueSet NotEqual(PossibleValueSet pvs) + { + return ComparisonOperation(pvs); + } + + public PossibleValueSet GreaterThanOrEqual(PossibleValueSet pvs) + { + return ComparisonOperation(pvs); + } + + public PossibleValueSet GreaterThan(PossibleValueSet pvs) + { + return ComparisonOperation(pvs); + } + + public PossibleValueSet LessThan(PossibleValueSet pvs) + { + return ComparisonOperation(pvs); + } + + public PossibleValueSet LessThanOrEqual(PossibleValueSet pvs) + { + return ComparisonOperation(pvs); + } + + private PossibleValueSet ComparisonOperation(PossibleValueSet pvs) + { + return MathOperation(pvs, typeof (bool)); + } + + public PossibleValueSet Coalesce(PossibleValueSet pvs) + { + if (!ContainsNull) + return this; + + PossibleValueSet result = new PossibleValueSet(ExpressionType); + result.DistinctValues.AddRange(DistinctValues); + result.ContainsAllNonNullValues = ContainsAllNonNullValues; + + result.ContainsNull = pvs.ContainsNull; + result.ContainsAllNonNullValues |= pvs.ContainsAllNonNullValues; + result.DistinctValues.AddRange(pvs.DistinctValues.Except(result.DistinctValues)); + + return result; + } + + // Unary Operators + + public PossibleValueSet Not() + { + CheckType<bool>(); + + PossibleValueSet result = new PossibleValueSet(typeof(bool)); + result.ContainsNull = ContainsNull; + result.DistinctValues.AddRange(DistinctValues.Cast<bool>().Select(v => !v).Cast<object>()); + return result; + } + + public PossibleValueSet BitwiseNot(System.Type resultType) + { + return UnaryMathOperation(resultType); + } + + public PossibleValueSet ArrayLength(System.Type resultType) + { + return CreateAllNonNullValues(typeof (int)); + } + + public PossibleValueSet Convert(System.Type resultType) + { + return UnaryMathOperation(resultType); + } + + public PossibleValueSet Negate(System.Type resultType) + { + return UnaryMathOperation(resultType); + } + + public PossibleValueSet UnaryPlus(System.Type resultType) + { + return this; + } + + private PossibleValueSet UnaryMathOperation(System.Type resultType) + { + return + !ContainsAnyNonNullValues ? CreateNull(resultType) : + !ContainsNull ? CreateAllNonNullValues(resultType) : + CreateAllValues(resultType); + } + + // Special Operators + + public PossibleValueSet IsNull() + { + PossibleValueSet result = new PossibleValueSet(typeof(bool)); + if (ContainsNull) + result.DistinctValues.Add(true); + if (ContainsAllNonNullValues || DistinctValues.Any()) + result.DistinctValues.Add(false); + return result; + } + + public PossibleValueSet IsNotNull() + { + PossibleValueSet result = new PossibleValueSet(typeof(bool)); + if (ContainsNull) + result.DistinctValues.Add(false); + if (ContainsAllNonNullValues || DistinctValues.Any()) + result.DistinctValues.Add(true); + return result; + } + + public PossibleValueSet MemberAccess(System.Type resultType) + { + // If instance is null, member will be null too. + if (!ContainsAnyNonNullValues) + return CreateNull(resultType); + + // Otherwise, value could be anything due to value of member. + return CreateAllValues(resultType); + } + + #endregion + + private void CheckType<T>() + { + if (ExpressionType != typeof(T)) + throw new AssertionFailure("Cannot perform desired possible value set operation on expression of type: " + ExpressionType); + } + + public static PossibleValueSet CreateNull(System.Type expressionType) + { + return new PossibleValueSet(expressionType) {ContainsNull = true}; + } + + public static PossibleValueSet CreateAllNonNullValues(System.Type expressionType) + { + PossibleValueSet result = new PossibleValueSet(expressionType); + if (expressionType == typeof(bool)) + { + result.DistinctValues.Add(true); + result.DistinctValues.Add(false); + } + else + { + result.ContainsAllNonNullValues = true; + } + return result; + } + + public static PossibleValueSet CreateAllValues(System.Type expressionType) + { + PossibleValueSet result = CreateAllNonNullValues(expressionType); + result.ContainsNull = true; + return result; + } + + public static PossibleValueSet Create(System.Type expressionType, params object[] values) + { + PossibleValueSet result = new PossibleValueSet(expressionType); + foreach (var v in values) + { + if (v == null) + result.ContainsNull = true; + else if (v.GetType() == expressionType && !result.DistinctValues.Contains(v)) + result.DistinctValues.Add(v); + else + throw new AssertionFailure("Don't know how to add value to possible value set of type " + expressionType + ": " + v); + } + return result; + } + } +} Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/WhereJoinDetector.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/WhereJoinDetector.cs 2011-06-21 16:31:37 UTC (rev 5968) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/WhereJoinDetector.cs 2011-06-27 00:59:46 UTC (rev 5969) @@ -1,126 +1,69 @@ -// FIXME - Are there other things that can convert N into T? What about the ?: operator? using System; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using NHibernate.Linq.ReWriters; using Remotion.Linq.Clauses.Expressions; -using Remotion.Linq.Utilities; namespace NHibernate.Linq.Visitors { /// <summary> /// The WhereJoinDetector creates the joins for the where clause, including - /// optimizations for inner joins. The algorithms are explained in - /// the accompanying text file. + /// optimizations for inner joins. + /// + /// The detector asks the following question: + /// Can an empty outer join ever return a record (ie. produce true in the where clause)? + /// If not, it's equivalent to an inner join since empty joins that can't produce true + /// never appear in the result set. + /// + /// A record (object) will be in the result if the evaluation of the condition in 3-value SQL + /// logic will return true; it will not be in the result if the result is either logical-null + /// or false. The difference between outer joining and inner joining is that with the latter, + /// objects are missing from the set on which the condition is checked. Thus, inner joins + /// "emulates" a result that is logical-null or false. And therefore, we can replace an outer + /// join with an inner join only if the resulting condition was not true on the outer join in + /// the first place when there was an "empty outer join" - i.e., the outer join had to add + /// nulls because there was no joinable record. These nulls can appear even for a column + /// that is not nullable. + /// + /// For example: + /// a.B.C == 1 could never produce true if B didn't match any rows, so it's safe to inner join. + /// a.B.C == null could produce true even if B didn't match any rows, so we can't inner join. + /// a.B.C == 1 && a.D.E == 1 can be inner joined. + /// a.B.C == 1 || a.D.E == 1 must be outer joined. + /// + /// By default we outer join via the code in VisitExpression. The use of inner joins is only + /// an optimization hint to the database. + /// + /// More examples: + /// a.B.C == 1 || a.B.C == null + /// We don't need multiple joins for this. When we reach the ||, we ask the value sets + /// on either side if they have a value for when a.B.C is emptily outer joined. Both of + /// them do, so those values are combined. + /// a.B.C == 1 || a.D.E == 1 + /// In this case, there is no value for a.B.C on the right side, so we use the possible + /// values for the entire expression, ignoring specific members. We only test for the + /// empty outer joining of one member expression at a time, since we can't guarantee that + /// they will all be emptily outer joined at the same time. + /// a.B.C ?? a.D.E + /// Even though each side is null when emptily outer joined, we can't promise that a.D.E + /// will be emptily outer joined when a.B.C is. Therefore, despite both sides being + /// null, the result may not be. + /// + /// There was significant discussion on the developers mailing list regarding this topic. See also NH-2583. + /// + /// The code here is based on the excellent work started by Harald Mueller. /// </summary> internal class WhereJoinDetector : AbstractJoinDetector { - // Possible results of a condition when emptily outer joined. - private const int T = 1; - private const int N = 2; - private const int TN = T | N; - private const int F = 4; - private const int TF = T | F; - private const int NF = N | F; - private const int TNF = T | N | F; + // TODO: There are a number of types of expressions that we didn't handle here due to time constraints. For example, the ?: operator could be checked easily. - // Composition rules for possible results when emptily outer joined - // for &&, ||, !. - private static readonly int[,] AND = new int[8, 8]; - private static readonly int[,] OR = new int[8, 8]; - private static readonly int[] NOT = new int[8]; - private static readonly int[] ISNULL = new int[8]; - private static readonly int[] ISNOTNULL = new int[8]; + private Stack<bool> _handled = new Stack<bool>(); + + // Stack of result values of each expression. After an expression has processed itself, it adds itself to the stack. + private Stack<ExpressionValues> _values = new Stack<ExpressionValues>(); - /// <summary> - /// Setup of <see cref="AND"/>, <see cref="OR"/>, <see cref="NOT"/>. - /// </summary> - static WhereJoinDetector() - { - // Setup of simple values according to SQL 3-valued logic. - NOT[T] = F; - NOT[N] = N; - NOT[F] = T; - ISNULL[T] = F; - ISNULL[N] = T; - ISNULL[F] = F; - ISNOTNULL[T] = T; - ISNOTNULL[N] = F; - ISNOTNULL[F] = T; - - foreach (var p in new[] { T, N, F }) - { - OR[p, p] = AND[p, p] = p; - AND[p, F] = AND[F, p] = F; - OR[p, T] = OR[T, p] = T; - } - AND[T, N] = AND[N, T] = N; - OR[F, N] = OR[N, F] = N; - - // Setup of compound values. Idea: Split each - // compound value to simple values, compute results - // for simple values and or them together. - var allValues = new[] { T, N, TN, F, TF, NF, TNF }; - - // How compound values are split up into simple values. - var split = new int[8][]; - split[T] = new[] { T }; - split[N] = new[] { N }; - split[TN] = new[] { T, N }; - split[F] = new[] { F }; - split[TF] = new[] { T, F }; - split[NF] = new[] { N, F }; - split[TNF] = new[] { T, N, F }; - - foreach (var p in allValues) - { - int[] splitP = split[p]; - // We only need to compute unary operations for compound values. - if (splitP.Length > 1) - { - int notResult = 0; - int isNullResult = 0; - int isNotNullResult = 0; - foreach (var p0 in splitP) - { - notResult |= NOT[p0]; - isNullResult |= ISNULL[p0]; - isNotNullResult |= ISNOTNULL[p0]; - } - NOT[p] = notResult; - ISNULL[p] = isNullResult; - ISNOTNULL[p] = isNotNullResult; - } - foreach (var q in allValues) - { - int[] splitQ = split[q]; - // We must compute AND and OR if both values are compound, - // *but also* if one is compound and the other is simple - // (e.g. T and TNF). - if (splitP.Length > 1 || splitQ.Length > 1) - { - int andResult = 0; - int orResult = 0; - foreach (var p0 in splitP) - { - foreach (var q0 in splitQ) - { - andResult |= AND[p0, q0]; - orResult |= OR[p0, q0]; - } - } - AND[p, q] = andResult; - OR[p, q] = orResult; - } - } - } - } - - // The following is used for all *condition* traversal (but not *expressions* that are not conditions). - // This is the "mapping" described in the text at NH-2583. - private Stack<Dictionary<string, int>> _memberExpressionMappings = new Stack<Dictionary<string, int>>(); - - // The following two are used for member expressions traversal. + // The following is used for member expressions traversal. private int _memberExpressionDepth = 0; internal @@ -133,221 +76,327 @@ { WhereJoinDetector f = new WhereJoinDetector(nameGenerator, isEntityDecider, joins, expressionMap); - f._memberExpressionMappings.Push(new Dictionary<string, int>()); - f.VisitExpression(expression); - foreach (var mapping in f._memberExpressionMappings.Pop()) + ExpressionValues values = f._values.Pop(); + + foreach (var memberExpression in values.MemberExpressions) { // If outer join can never produce true, we can safely inner join. - if ((mapping.Value & T) == 0) + if (!values.GetValues(memberExpression).Contains(true)) { - f.MakeInnerIfJoined(mapping.Key); + f.MakeInnerIfJoined(memberExpression); } } } - protected override Expression VisitBinaryExpression(BinaryExpression expression) + public override Expression VisitExpression(Expression expression) { - ArgumentUtility.CheckNotNull("expression", expression); + if (expression == null) + return null; - Expression baseResult = expression; - if (expression.NodeType == ExpressionType.AndAlso && expression.Type == typeof(bool)) + // To ensure safety in situations we don't understand, we default to "all possible values" + // if we can't process any expression in a known way. The SetResultValues() method is used + // to indicate that the expression has been processed, and what the results are. + + _handled.Push(false); + int originalCount = _values.Count; + + Expression result = base.VisitExpression(expression); + + if (!_handled.Pop()) { - // Case (a) from the text at NH-2583. - _memberExpressionMappings.Push(new Dictionary<string, int>()); - var newLeft = VisitExpression(expression.Left); - var leftMapping = _memberExpressionMappings.Pop(); + // If this expression was not handled in a known way, we throw away any values that might + // have been returned and we return "all values" for this expression, since we don't know + // what the expresson might result in. + while (_values.Count > originalCount) + _values.Pop(); + _values.Push(new ExpressionValues(PossibleValueSet.CreateAllValues(expression.Type))); + } - _memberExpressionMappings.Push(new Dictionary<string, int>()); - var newRight = VisitExpression(expression.Right); - var rightMapping = _memberExpressionMappings.Pop(); + return result; + } - BinaryMapping(leftMapping, rightMapping, AND); + protected override Expression VisitBinaryExpression(BinaryExpression expression) + { + var result = base.VisitBinaryExpression(expression); - // The following is copy-pasted from Relinq's visitor, as I had to split the code above. - var newConversion = (LambdaExpression)VisitExpression(expression.Conversion); - if (newLeft != expression.Left || newRight != expression.Right || newConversion != expression.Conversion) - baseResult = Expression.MakeBinary(expression.NodeType, newLeft, newRight, expression.IsLiftedToNull, expression.Method, newConversion); + if (expression.NodeType == ExpressionType.AndAlso) + { + HandleBinaryOperation((a, b) => a.AndAlso(b)); } - else if (expression.NodeType == ExpressionType.OrElse && expression.Type == typeof(bool)) + else if (expression.NodeType == ExpressionType.OrElse) { - // Case (b) - _memberExpressionMappings.Push(new Dictionary<string, int>()); - var newLeft = VisitExpression(expression.Left); - var leftMapping = _memberExpressionMappings.Pop(); + HandleBinaryOperation((a, b) => a.OrElse(b)); + } + else if (expression.NodeType == ExpressionType.NotEqual && IsNullConstantExpression(expression.Right)) + { + // Discard result from right null. Left is visited first, so it's below right on the stack. + _values.Pop(); - _memberExpressionMappings.Push(new Dictionary<string, int>()); - var newRight = VisitExpression(expression.Right); - var rightMapping = _memberExpressionMappings.Pop(); + HandleUnaryOperation(pvs => pvs.IsNotNull()); + } + else if (expression.NodeType == ExpressionType.NotEqual && IsNullConstantExpression(expression.Left)) + { + // Discard result from left null. + var right = _values.Pop(); + _values.Pop(); // Discard left. + _values.Push(right); - BinaryMapping(leftMapping, rightMapping, OR); + HandleUnaryOperation(pvs => pvs.IsNotNull()); + } + else if (expression.NodeType == ExpressionType.Equal && IsNullConstantExpression(expression.Right)) + { + // Discard result from right null. Left is visited first, so it's below right on the stack. + _values.Pop(); - // Again, the following is copy-pasted from Relinq's visitor, as I had to split the code above. - var newConversion = (LambdaExpression)VisitExpression(expression.Conversion); - if (newLeft != expression.Left || newRight != expression.Right || newConversion != expression.Conversion) - baseResult = Expression.MakeBinary(expression.NodeType, newLeft, newRight, expression.IsLiftedToNull, expression.Method, newConversion); + HandleUnaryOperation(pvs => pvs.IsNull()); } - else if (expression.Type == typeof(bool) - && expression.NodeType == ExpressionType.NotEqual - && (IsNullConstantExpression(expression.Right) || IsNullConstantExpression(expression.Left))) + else if (expression.NodeType == ExpressionType.Equal && IsNullConstantExpression(expression.Left)) { - // Case (h) - _memberExpressionMappings.Push(new Dictionary<string, int>()); - baseResult = base.VisitBinaryExpression(expression); - UnaryMapping(_memberExpressionMappings.Pop(), ISNOTNULL); + // Discard result from left null. + var right = _values.Pop(); + _values.Pop(); // Discard left. + _values.Push(right); + + HandleUnaryOperation(pvs => pvs.IsNull()); } - else if (expression.Type == typeof(bool) - && expression.NodeType == ExpressionType.Equal - && (IsNullConstantExpression(expression.Right) || IsNullConstantExpression(expression.Left))) + else if (expression.NodeType == ExpressionType.Coalesce) { - // Case (i) - _memberExpressionMappings.Push(new Dictionary<string, int>()); - baseResult = base.VisitBinaryExpression(expression); - UnaryMapping(_memberExpressionMappings.Pop(), ISNULL); + HandleBinaryOperation((a, b) => a.Coalesce(b)); } - else // +, * etc. + else if (expression.NodeType == ExpressionType.Add || expression.NodeType == ExpressionType.AddChecked) { - // Case (j) - baseResult = base.VisitBinaryExpression(expression); + HandleBinaryOperation((a, b) => a.Add(b, expression.Type)); } - return baseResult; + else if (expression.NodeType == ExpressionType.Divide) + { + HandleBinaryOperation((a, b) => a.Divide(b, expression.Type)); + } + else if (expression.NodeType == ExpressionType.Modulo) + { + HandleBinaryOperation((a, b) => a.Modulo(b, expression.Type)); + } + else if (expression.NodeType == ExpressionType.Multiply || expression.NodeType == ExpressionType.MultiplyChecked) + { + HandleBinaryOperation((a, b) => a.Multiply(b, expression.Type)); + } + else if (expression.NodeType == ExpressionType.Power) + { + HandleBinaryOperation((a, b) => a.Power(b, expression.Type)); + } + else if (expression.NodeType == ExpressionType.Subtract || expression.NodeType == ExpressionType.SubtractChecked) + { + HandleBinaryOperation((a, b) => a.Subtract(b, expression.Type)); + } + else if (expression.NodeType == ExpressionType.And) + { + HandleBinaryOperation((a, b) => a.And(b, expression.Type)); + } + else if (expression.NodeType == ExpressionType.Or) + { + HandleBinaryOperation((a, b) => a.Or(b, expression.Type)); + } + else if (expression.NodeType == ExpressionType.ExclusiveOr) + { + HandleBinaryOperation((a, b) => a.ExclusiveOr(b, expression.Type)); + } + else if (expression.NodeType == ExpressionType.LeftShift) + { + HandleBinaryOperation((a, b) => a.LeftShift(b, expression.Type)); + } + else if (expression.NodeType == ExpressionType.RightShift) + { + HandleBinaryOperation((a, b) => a.RightShift(b, expression.Type)); + } + else if (expression.NodeType == ExpressionType.Equal) + { + HandleBinaryOperation((a, b) => a.Equal(b)); + } + else if (expression.NodeType == ExpressionType.NotEqual) + { + HandleBinaryOperation((a, b) => a.NotEqual(b)); + } + else if (expression.NodeType == ExpressionType.GreaterThanOrEqual) + { + HandleBinaryOperation((a, b) => a.GreaterThanOrEqual(b)); + } + else if (expression.NodeType == ExpressionType.GreaterThan) + { + HandleBinaryOperation((a, b) => a.GreaterThan(b)); + } + else if (expression.NodeType == ExpressionType.LessThan) + { + HandleBinaryOperation((a, b) => a.LessThan(b)); + } + else if (expression.NodeType == ExpressionType.LessThanOrEqual) + { + HandleBinaryOperation((a, b) => a.LessThanOrEqual(b)); + } + + return result; } protected override Expression VisitUnaryExpression(UnaryExpression expression) { - ArgumentUtility.CheckNotNull("expression", expression); + Expression result = base.VisitUnaryExpression(expression); - Expression baseResult; if (expression.NodeType == ExpressionType.Not && expression.Type == typeof(bool)) { - // Case (c) from text at NH-2583. - _memberExpressionMappings.Push(new Dictionary<string, int>()); - baseResult = VisitExpression(expression.Operand); - UnaryMapping(_memberExpressionMappings.Pop(), NOT); + HandleUnaryOperation(pvs => pvs.Not()); } - else + else if (expression.NodeType == ExpressionType.Not) { - baseResult = base.VisitUnaryExpression(expression); + HandleUnaryOperation(pvs => pvs.BitwiseNot(expression.Type)); } - return baseResult; + else if (expression.NodeType == ExpressionType.ArrayLength) + { + HandleUnaryOperation(pvs => pvs.ArrayLength(expression.Type)); + } + else if (expression.NodeType == ExpressionType.Convert || expression.NodeType == ExpressionType.ConvertChecked) + { + HandleUnaryOperation(pvs => pvs.Convert(expression.Type)); + } + else if (expression.NodeType == ExpressionType.Negate || expression.NodeType == ExpressionType.NegateChecked) + { + HandleUnaryOperation(pvs => pvs.Negate(expression.Type)); + } + else if (expression.NodeType == ExpressionType.UnaryPlus) + { + HandleUnaryOperation(pvs => pvs.UnaryPlus(expression.Type)); + } + + return result; } - //protected override Expression VisitConditionalExpression(ConditionalExpression expression) + // We would usually get NULL if one of our inner member expresions was null. + // However, it's possible a method call will convert the null value from the failed join into a non-null value. + // This could be optimized by actually checking what the method does. For example StartsWith("s") would leave null as null and would still allow us to inner join. + //protected override Expression VisitMethodCallExpression(MethodCallExpression expression) //{ - // ArgumentUtility.CheckNotNull("expression", expression); - - // VisitExpression(expression.Test); - // // If the ?: returns bool, it is (most probably ...) a condition which may require outer joins. - // // TODO: Check check whether HQL accepts ?: conditions; if not, should be rewritten it as (a && b || !a && c). - // if (expression.Type == typeof(bool)) - // { - // ... - // } - // return expression; + // Expression result = base.VisitMethodCallExpression(expression); + // return result; //} - protected override Expression VisitMethodCallExpression(MethodCallExpression expression) - { - _memberExpressionMappings.Push(new Dictionary<string, int>()); - Expression result = base.VisitMethodCallExpression(expression); - // We would usually get NULL if one of our inner member expresions was null. (Mapped to N) - // However, it's possible a method call will convert the null value from the failed join into any one of True, False, or Null. (Mapped to TNF) - // This could be optimized by actually checking what the method does. For example StartsWith("s") would leave null as null and would still allow us to inner join. - FixedMapping(_memberExpressionMappings.Pop(), TNF); - return result; - } - protected override Expression VisitMemberExpression(MemberExpression expression) { - ArgumentUtility.CheckNotNull("expression", expression); + // The member expression we're visiting might be on the end of a variety of things, such as: + // a.B + // a.B.C + // (a.B ?? a.C).D + // I'm not sure what processing re-linq does to strange member expressions. + // TODO: I suspect this code doesn't add the right joins for the last case. - Expression newExpression; - try - { - _memberExpressionDepth++; - newExpression = base.VisitExpression(expression.Expression); - } - finally - { - _memberExpressionDepth--; - } - bool isEntity = _isEntityDecider.IsEntity(expression.Type); + _memberExpressionDepth++; + var result = base.VisitMemberExpression(expression); + _memberExpressionDepth--; - if (isEntity) + ExpressionValues values = _values.Pop().Operation(pvs => pvs.MemberAccess(expression.Type)); + if (_isEntityDecider.IsEntity(expression.Type)) { - // See (h) why we do not check for _memberExpressionDepth here! - AddPossibility(ExpressionKeyVisitor.Visit(expression, null), N); + // Don't add joins for things like a.B == a.C where B and C are entities. + // We only need to join B when there's something like a.B.D. + // TODO: Add an exception for the Id property. + if (_memberExpressionDepth > 0) + AddJoin(expression); + + string key = ExpressionKeyVisitor.Visit(expression, null); + values.MemberExpressionValuesIfEmptyOuterJoined[key] = PossibleValueSet.CreateNull(expression.Type); } + SetResultValues(values); - if (_memberExpressionDepth > 0 && isEntity) + return result; + } + + private static bool IsNullConstantExpression(Expression expression) + { + if (expression is ConstantExpression) { - return AddJoin(expression); + var constant = (ConstantExpression)expression; + return constant.Value == null; } else { - if (newExpression != expression.Expression) - return Expression.MakeMemberAccess(newExpression, expression.Member); - return expression; + return false; } } - private void FixedMapping(Dictionary<string, int> sourceMapping, int value) + private void SetResultValues(ExpressionValues values) { - foreach (var me in sourceMapping.Keys) - { - AddPossibility(me, value); - } + _handled.Pop(); + _handled.Push(true); + _values.Push(values); } - private void BinaryMapping(Dictionary<string, int> leftMapping, Dictionary<string, int> rightMapping, int[,] op) + private void HandleBinaryOperation(Func<PossibleValueSet, PossibleValueSet, PossibleValueSet> operation) { - // Compute mapping for all member expressions in leftMapping. If the member expression is missing - // in rightMapping, use TNF as a "pessimistic approximation" instead (inside the ?: operator). See - // the text for an explanation of this. - foreach (var lhs in leftMapping) + var right = _values.Pop(); + var left = _values.Pop(); + SetResultValues(left.Operation(right, operation)); + } + + private void HandleUnaryOperation(Func<PossibleValueSet, PossibleValueSet> operation) + { + SetResultValues(_values.Pop().Operation(operation)); + } + + private class ExpressionValues + { + public ExpressionValues(PossibleValueSet valuesIfUnknownMemberExpression) { - AddPossibility(lhs.Key, op[lhs.Value, rightMapping.ContainsKey(lhs.Key) ? rightMapping[lhs.Key] : TNF]); + Values = valuesIfUnknownMemberExpression; + MemberExpressionValuesIfEmptyOuterJoined = new Dictionary<string, PossibleValueSet>(); } - // Compute mapping for all member expressions *only* in rightMapping (we did the common ones above). - // Again, use TNF as pessimistic approximation to result of left subcondition. - foreach (var rhs in rightMapping) + + /// <summary> + /// Possible values of expression if there's set of values for the requested member expression. + /// For example, if we have an expression "3" and we request the state for "a.B.C", we'll + /// use "3" from Values since it won't exist in MemberExpressionValuesIfEmptyOuterJoined. + /// </summary> + private PossibleValueSet Values { get; set; } + + /// <summary> + /// Stores the possible values of an expression that would result if the given member expression + /// string was emptily outer joined. For example a.B.C would result in "null" if we try to + /// outer join to B and there are no rows. Even if an expression tree does contain a particular + /// member experssion, it may not appear in this list. In that case, the emptily outer joined + /// value set for that member expression will be whatever's in Values instead. + /// </summary> + public Dictionary<string, PossibleValueSet> MemberExpressionValuesIfEmptyOuterJoined { get; private set; } + + public PossibleValueSet GetValues(string memberExpression) { - if (!leftMapping.ContainsKey(rhs.Key)) - { - AddPossibility(rhs.Key, op[rhs.Value, TNF]); - } + if (MemberExpressionValuesIfEmptyOuterJoined.ContainsKey(memberExpression)) + return MemberExpressionValuesIfEmptyOuterJoined[memberExpression]; + return Values; } - } - private void UnaryMapping(Dictionary<string, int> sourceMapping, int[] op) - { - foreach (var item in sourceMapping) + public IEnumerable<string> MemberExpressions { - AddPossibility(item.Key, op[item.Value]); + get { return MemberExpressionValuesIfEmptyOuterJoined.Keys; } } - } - private static bool IsNullConstantExpression(Expression expression) - { - if (expression is ConstantExpression) + public ExpressionValues Operation(ExpressionValues mergeWith, Func<PossibleValueSet, PossibleValueSet, PossibleValueSet> operation) { - var constant = (ConstantExpression)expression; - return constant.Value == null; + ExpressionValues result = new ExpressionValues(operation(Values, mergeWith.Values)); + foreach (string memberExpression in MemberExpressions.Union(mergeWith.MemberExpressions)) + { + var left = GetValues(memberExpression); + var right = mergeWith.GetValues(memberExpression); + result.MemberExpressionValuesIfEmptyOuterJoined.Add(memberExpression, operation(left, right)); + } + return result; } - else + + public ExpressionValues Operation(Func<PossibleValueSet, PossibleValueSet> operation) { - return false; + ExpressionValues result = new ExpressionValues(operation(Values)); + foreach (string memberExpression in MemberExpressions) + { + result.MemberExpressionValuesIfEmptyOuterJoined.Add(memberExpression, operation(GetValues(memberExpression))); + } + return result; } } - - private void AddPossibility(string memberPath, int value) - { - Dictionary<string, int> mapping = _memberExpressionMappings.Peek(); - if (mapping.ContainsKey(memberPath)) - mapping[memberPath] |= value; - else - mapping[memberPath] = value; - } } } Deleted: trunk/nhibernate/src/NHibernate/Linq/Visitors/WhereJoinDetectorDesignNotes.txt =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/WhereJoinDetectorDesignNotes.txt 2011-06-21 16:31:37 UTC (rev 5968) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/WhereJoinDetectorDesignNotes.txt 2011-06-27 00:59:46 UTC (rev 5969) @@ -1,309 +0,0 @@ -[Commiter's Notes: As with the code, this design document was contributed by Harald Mueller. - By default in Linq, a member expression such as a.B.C is converted into left outer joins so if we have something like a => (a.B.C == 1 || a.D.E == 2) we don't lose records due to the join where B or D is null. - This document describes how we optimize to inner joins when outer joins are not required, such as in the simple case of a => a.B.C == 1. - There was significant discussion on the developers mailing list regarding this topic. See also NH-2583.] - -Optimization of outer joins to inner joins for (||-4) semantics -=============================================================== - -It is interesting - and for some databases an advantage - to replace outer joins with inner joins if the outer joins are not necessary. "Not necessary" here means that the result must not be different whether using outer joins or inner joins. The question, obviously, is: For which joinable member expressions can we replace an outer join with an inner join without creating wrong results? - -It took me a few hours to find this out. Here is the result. - -A record (object) will be in the result if the evaluation of the condition in 3-value SQL logic will return true; it will not be in the result if the result is either logical-null or false. The difference between outer joining and inner joining is that with the latter, objects are missing from the set on which the condition is checked. Thus, inner joins "emulates" a result that is logical-null or false. And therefore, we can replace an outer join with an inner join only if the resulting condition was not true on the outer join in the first place when there was an "empty outer join" - i.e., the outer join had to add nulls because there was no joinable record. - -By the way, I will in the following call the nulls added by "dangling outer joins" "oj-nulls". They have to be distinguished from the two other sorts of nulls in SQL: -* "value-null" - a NULL in a column of a table -* "logical-null" - a NULL resulting from the evaluation of certain conditions on certain values (in SQL, at least one of these values must be a value-null or oj-null). -In contrast to value-nulls, oj-nulls have the peculiar property that they can exist even for non-nullable columns. - -If we look at the evaluation tree of a condition, we can assign to each node and for each joinable member expression one of the following small sets: - - t definitely makes the node true when the member expression is emptily outer-joined (i.e., joining it creates oj-nulls for all the simple properties) - n definitely makes the node logical-null when emptily outer-joined - f definitely makes the node false when emptily outer-joined - tn maybe makes it true, maybe logical-null when emptily outer-joined - tf maybe makes it true, maybe false when emptily outer-joined - nf maybe makes it logical-null, maybe false when emptily outer-joined - tnf maybe makes it true, maybe logical-null, maybe false when emptily outer-joined - -(An eighth set, the empty one, could only be assigned to a contradiction. We ignore such conditions in most of the following discussion). - -When we know these values at the top condition, we can then safely use inner joins for all member expressions for which the value does not contain t. -The reasoning is as follows: If for some result record, the empty outer join of a joinable member expression has made the top where condition logical-null or false, this record will be dropped from the result set - this is just the definition of how a query handles logical-null and false results. But an inner join cannot "do more harm" - it will also just drop the record from the result. Therefore, we can safely replace outer joins to such joinable member expressions with inner joins. - -In the following, we assemble the rules for computing the member expressions mappings introduced above. After a few examples, we look at the rules, and then more examples. - -(Remark: I use C# notation in the following, with the following semantics: -* Generally, the semantics for condition evaluation is 3-valued SQL semantics with condition results of true, logical-null, or false -* == null has the semantics of "is null" -* != null the semantics of "is not null" -* the final result contains objects where the condition evaluation yields true, but not logical-null or false - this is the standard mapping of 3-valued-semantics to 2-valued-semantics). - -As a first example, the condition - - x.A.B == 4 - -is logical-null when emptily outer-joining x.A, but never true or false. Thus, we have { x.A -> n }. Inner joining x.A (which drops records that are emptily joined) therefore yields the same 2-valued-logic result. - -On the other hand, the condition - - x.A.B == null && x.E == null - -can be made true or false by emptily outer-joining x.A, but never logical-null (resaon: The right side can only be true or false; and the left side also; so the complete condition is either true or false - depending on x.E's value). So, { x.A -> tf }, and therefore we cannot inner join x.A (there is a t in the mapping!). By direct reasoning, we see that inner joining x.A will drop all the non-joinable records, hence inner and outer joining are different for records where x.E is null, and will yield a different 2-valued-logic result. - -Finally, the condition - - x.A.B == null || x.E == null - -is always true when emptily outer-joining x.A, so { x.A -> t }. Hence, the result is always different from inner joining, where the empty join drops such records from the result. - -How can we compute the mapping from member expressions to possible values? First, we note that we can compute this mapping with different "preciseness". For example, one correct way would be to just collect all joinable member expressions into a set M, and then set { mE -> tnf } for all member expressions mE in M. Obviously, this prevents any inner joins. On the other hand, we can in principle quite precisely check condition like the following - the question is whether this is worth the effort: - - x.A.B == null x.A -> ... - !(x.A.B != null) x.A -> ... - (x.A.B ?? 4) == 4 x.A -> ... - !((x.A.B ?? 4) != 4) x.A -> ... - (x.A.B ?? x.E) == 4 x.A -> ... - (x.A.B ?? x.C.D) == 4 x.A -> ..., x.C -> ... - -In the following, I'll first give the rules for the 4 logical operators &&, ||, !, and ?!; then I'll give practical rules (I think) for common simple conditions; finally, I'll look at some more complex simple conditions. - -(a) && operator: - - && t n f tn tf nf tnf - - t t n f tn tf nf tnf tnf - n n f n nf nf nf nf - f f f f f f f - tn tn tnf nf tnf tnf - tf tf nf tnf tnf - nf nf nf nf - tnf tnf tnf - - - - -The single letters are easy: They follow the 3-valued SQL logic. E.g., if emptily joining a member expression will definitely return true for condition A and logical-null for condition B, it will definitely return (true && logical-null) = logical-null for A && B. -For the multiple values, we have to compute the union of the values in the small sets. For example, tn && tf is { t && t, t && f, n && t, n && f } = { t,f,n,f } = tnf. -If the member expression is missing on one side, we must assume any value for that side. After all, the condition on the other side could e.g. be 0 == 0, 0 == null, or 0 == 1. Therefore, the result is the same as if we would get tnf from the other side. See examples (ex.4) and (ex.5) below for some more thoughts on this. -The values below the diagonal are symmetric to the upper ones. - -(b) || operator: - - || t n f tn tf nf tnf - - t t t t t t t t t - n n n tn tn n tn tn - f f tn tf nf tnf tnf - tn tn tn tn tn tn - tf tf tnf tnf tnf - nf nf tnf tnf - tnf tnf tnf - - - - -The resoning is similar to &&. -Again, the values below the diagonal are symmetric to the upper ones. - -(c) ! operator: - - ! t n f tn tf nf tnf - f n t nf tf tn tnf - -The resoning is similar to &&. - -(d) Logical ?: operator: - -A ? B : C is equivalent to A && B || !A && C. From this, one can compute the mappings (I would need a three-dimensional "cube matrix" for their presentation, which is hard in text ... ok, a tree also would work ...). - -Now let us look at simple conditions. The following are *possible* member expression mappings. As said above, one can also assign the values more crudely - e.g., always assign tnf to all member expressions. However, the assignments below are reasonable precise - i.e., they assign the minimal sets for practical values (if I did not make a mistake). - -(e) mE*.P <op> <constant(s)> (where <constant(s)> are not value-nulls) - -mE* here is a symbol for a "nested sequence of member expressions" mE1, mE2, ..., .P is the final property. E.g. in - - a.B.C.D.E == 4 - -the member expressions are mE1=a.B, mE2=a.B.C, and mE3=a.B.C.D; the final property is E. In this case, we get { mE -> n } for all member expressions mE. Reason: Emptily outer joining any member expression will yield oj-null for P; but oj-null <op> <constant> is always logical-null. - -(f) mE*.P [<op>s <constant>s] == me'*.Q [<op>s <constant>s] - -The result depends on the definition of ==: We can either use the Linq definition where null == null is true (which requires an SQL translation of ... = ... OR ... IS NULL AND ... IS NULL); or the SQL definition where null == null is logical-null. - -In the first case, we reason as follows: - - - When one side (e.g. the left one) does empty outer-joining and yields oj-null for P, but the right side has non-oj-null values, the SQL - oj-null = value OR oj-null IS NULL AND value IS NULL - evaluates as logical-null OR true AND false, which is logical-null OR true, which is true. - - When both sides do empty outer-joining, we get - oj-null = oj-null OR oj-null IS NULL AND oj-null IS NULL - which is logical-null OR true AND true, which is true. - -So, empty outer joining will always yield true, and hence we get { mE -> t } for all member expressions mE. - -For the SQL definition of equality, we get the following: - - - When one side (e.g. the left one) does empty outer-joining and yields oj-null for P, but the right side has non-oj-null values, the SQL - oj-null = value - evaluates as logical-null. - - When both sides do empty outer-joining, we get - oj-null = oj-null - which is logical-null. - -So, empty outer joining will always yield logical-null, and hence we get { mE -> n } for all member expressions mE. - -(g) mE*.P [<op>s <constant>s] != me'*.Q [<op>s <constant>s] - -Again, the result depends on the definition of ==: We can either use the Linq definition where null != null is false (which requires an SQL translation of ... <> ... OR ... IS NULL AND ... IS NOT NULL OR ... IS NOT NULL AND ... IS NULL); or the SQL definition where null != null is logical-null. - -In the first case, we reason as follows: - - - When one side (e.g. the left one) does empty outer-joining and yields oj-null for P, but the right side has non-oj-null values, the SQL - oj-null <> value OR oj-null IS NULL AND value IS NOT NULL OR oj-null IS NOT NULL AND value IS NULL - evaluates as logical-null OR true AND true OR false AND false, which is true. - - When both sides do empty outer-joining, we get - oj-null <> oj-null OR oj-null IS NULL AND oj-null IS NOT NULL OR oj-null IS NOT NULL AND oj-null IS NULL - which is logical-null OR false OR false, which is logical-null. - -So, empty outer joining will yield true or logical-null, and hence we get { mE -> tn } for all member expressions mE. - -For the SQL definition of equality, we get the following: - - - When one side (e.g. the left one) does empty outer-joining and yields oj-null for P, but the right side has non-oj-null values, the SQL - oj-null <> value - evaluates as logical-null. - - When both sides do empty outer-joining, we get - oj-null <> oj-null - which is also logical-null. - -So, empty outer joining will always yield logical-null, and hence we get { mE -> n } for all member expressions mE. - -(h) mE*.P != null - -Here is a first attempt: Empty outer joining can only yield false, hence we get { mE -> f } for all member expressions mE. - -There is a small problem with this definition: If P itself is a pointer to a mapped entity, we would *not* record that P is guaranteed to point to a valid object. This hurts in the following query: - - x.A != null && x.A.B != 4 - -According to (e), the right side will create the mapping { x.A -> n }. The left side does not have a joinable member expression (x.A is not joined! it is just evaluated on x's table), so the mapping is { }. According to (a), we get for the whole condition { x.A -> nf }. Actually, we know that the result should be { x.A -> f }: An empty outer join of x.A will yield "false" fo... [truncated message content] |
From: <jul...@us...> - 2011-06-21 16:31:44
|
Revision: 5968 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5968&view=rev Author: julian-maughan Date: 2011-06-21 16:31:37 +0000 (Tue, 21 Jun 2011) Log Message: ----------- Fixed grammatical error in ModelMapper method names Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Mapping/ByCode/ModelMapper.cs trunk/nhibernate/src/NHibernate.Test/MappingByCode/ConventionModelMapperTests/ComponetsAccessorTests.cs trunk/nhibernate/src/NHibernate.Test/MappingByCode/ConventionModelMapperTests/ComponetsParentAccessorTests.cs trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/AllPropertiesRegistrationTests.cs trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/BasicMappingOfSimpleClass.cs trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/ClassWithComponentsTest.cs trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/ConformistMappingRegistrationTests/ClassMappingRegistrationTest.cs trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/NestedComponetsTests.cs trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1270/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1845/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1965/ReattachWithCollectionTest.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2510/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2568/UsageOfCustomCollectionPersisterTests.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2569/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2587/CachingWithLinq.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2632/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs trunk/nhibernate/src/NHibernate.Test/Stateless/FetchingLazyCollections/LazyCollectionFetchTests.cs Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/ModelMapper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ByCode/ModelMapper.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/ModelMapper.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -1766,12 +1766,12 @@ } } - public HbmMapping CompileMappingForAllExplicitAddedEntities() + public HbmMapping CompileMappingForAllExplicitlyAddedEntities() { return CompileMappingFor(customizerHolder.GetAllCustomizedEntities()); } - public IEnumerable<HbmMapping> CompileMappingForEachExplicitAddedEntity() + public IEnumerable<HbmMapping> CompileMappingForEachExplicitlyAddedEntity() { return CompileMappingForEach(customizerHolder.GetAllCustomizedEntities()); } Modified: trunk/nhibernate/src/NHibernate.Test/MappingByCode/ConventionModelMapperTests/ComponetsAccessorTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/MappingByCode/ConventionModelMapperTests/ComponetsAccessorTests.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/MappingByCode/ConventionModelMapperTests/ComponetsAccessorTests.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -34,7 +34,7 @@ { x.Property(c => c.Something); }); - return mapper.CompileMappingForAllExplicitAddedEntities(); + return mapper.CompileMappingForAllExplicitlyAddedEntities(); } [Test] Modified: trunk/nhibernate/src/NHibernate.Test/MappingByCode/ConventionModelMapperTests/ComponetsParentAccessorTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/MappingByCode/ConventionModelMapperTests/ComponetsParentAccessorTests.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/MappingByCode/ConventionModelMapperTests/ComponetsParentAccessorTests.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -57,7 +57,7 @@ x.Component(c => c.Owner); x.Property(c => c.Something); }); - return mapper.CompileMappingForAllExplicitAddedEntities(); + return mapper.CompileMappingForAllExplicitlyAddedEntities(); } [Test] Modified: trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/AllPropertiesRegistrationTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/AllPropertiesRegistrationTests.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/AllPropertiesRegistrationTests.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -140,7 +140,7 @@ y.Property(c => c.Something); }); }); - var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); var hbmClass = mappings.RootClasses[0]; var hbmJoinedSubclass = mappings.JoinedSubclasses[0]; hbmClass.Properties.Select(p => p.Name).Should().Have.SameValuesAs("Simple", "ComplexType", "Bag", "IdBag", "List", "Set", "Map", "Compo", "OneToOne", "ManyToOne", "Any", "DynamicCompo"); @@ -179,7 +179,7 @@ }); mapper.Class<Inherited>(mc =>{}); - var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); var hbmClass = mappings.RootClasses[0]; mappings.JoinedSubclasses.Should().Be.Empty(); hbmClass.Properties.Select(p => p.Name).Should().Have.SameValuesAs("Simple", "ComplexType", "Bag", "IdBag", "List", "Set", "Map", "Compo", "OneToOne", "ManyToOne", "Any", "DynamicCompo"); @@ -212,7 +212,7 @@ y.Property(c => c.Something); }); }); - var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); var hbmClass = mappings.RootClasses[0]; var hbmJoinedSubclass = mappings.JoinedSubclasses[0]; hbmClass.Properties.Select(p => p.Name).Should().Have.SameValuesAs("Simple", "ComplexType", "Bag", "IdBag", "List", "Set", "Map", "Compo", "OneToOne", "ManyToOne", "Any", "DynamicCompo"); @@ -251,7 +251,7 @@ }); mapper.Class<Inherited>(mc => { }); - HbmMapping mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + HbmMapping mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); HbmClass hbmClass = mappings.RootClasses[0]; mappings.JoinedSubclasses.Should().Be.Empty(); hbmClass.Properties.Select(p => p.Name).Should().Have.SameValuesAs("Simple", "ComplexType", "Bag", "IdBag", "List", "Set", "Map", "Compo", "OneToOne", "ManyToOne", "Any", Modified: trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/BasicMappingOfSimpleClass.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/BasicMappingOfSimpleClass.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/BasicMappingOfSimpleClass.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -109,7 +109,7 @@ }); ca.Property(x => x.Something, map => map.Length(150)); }); - var hbmMapping = mapper.CompileMappingForAllExplicitAddedEntities(); + var hbmMapping = mapper.CompileMappingForAllExplicitlyAddedEntities(); ModelIsWellFormed(hbmMapping); } Modified: trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/ClassWithComponentsTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/ClassWithComponentsTest.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/ClassWithComponentsTest.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -49,7 +49,7 @@ cm.Component(person => person.Address, comp => { }); }); - var hbmMapping = mapper.CompileMappingForAllExplicitAddedEntities(); + var hbmMapping = mapper.CompileMappingForAllExplicitlyAddedEntities(); var hbmClass = hbmMapping.RootClasses[0]; Modified: trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/ConformistMappingRegistrationTests/ClassMappingRegistrationTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/ConformistMappingRegistrationTests/ClassMappingRegistrationTest.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/ConformistMappingRegistrationTests/ClassMappingRegistrationTest.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -81,7 +81,7 @@ { var mapper = new ModelMapper(); mapper.AddMapping(typeof(MyClassMap)); - var hbmMapping = mapper.CompileMappingForAllExplicitAddedEntities(); + var hbmMapping = mapper.CompileMappingForAllExplicitlyAddedEntities(); ModelIsWellFormed(hbmMapping); } Modified: trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/NestedComponetsTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/NestedComponetsTests.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/MappingByCode/ExpliticMappingTests/NestedComponetsTests.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -47,7 +47,7 @@ x.Component(c => c.Owner); x.Property(c => c.Something); }); - return mapper.CompileMappingForAllExplicitAddedEntities(); + return mapper.CompileMappingForAllExplicitlyAddedEntities(); } private HbmMapping GetMappingWithParentInCompo() @@ -69,7 +69,7 @@ x.Component(c => c.Owner); x.Property(c => c.Something); }); - return mapper.CompileMappingForAllExplicitAddedEntities(); + return mapper.CompileMappingForAllExplicitlyAddedEntities(); } [Test] Modified: trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -25,7 +25,7 @@ rc.Id(x => x.Id); rc.Property(x => x.MyEmptyEnum); }); - var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); var conf = TestConfigurationHelper.GetDefaultConfiguration(); conf.AddMapping(mappings); Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1270/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1270/Fixture.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1270/Fixture.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -42,7 +42,7 @@ mm.ForeignKey("FK_UserInRole"); })); }); - var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); return mappings; } Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1845/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1845/Fixture.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1845/Fixture.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -21,7 +21,7 @@ map.Cascade(Mapping.ByCode.Cascade.All.Include(Mapping.ByCode.Cascade.DeleteOrphans)); }, rel => rel.OneToMany()); }); - var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); return mappings; } Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1965/ReattachWithCollectionTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1965/ReattachWithCollectionTest.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1965/ReattachWithCollectionTest.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -28,7 +28,7 @@ cm.Id(x => x.Id, map => map.Generator(Generators.Identity)); cm.Bag(x => x.Children, map => map.Cascade(Mapping.ByCode.Cascade.All.Include(Mapping.ByCode.Cascade.DeleteOrphans)), rel => rel.OneToMany()); }); - var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); return mappings; } Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2510/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2510/Fixture.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2510/Fixture.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -23,7 +23,7 @@ rc.Id(x=> x.Id); rc.Property(x => x.Data, map=> map.Lazy(true)); }); - var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); return mappings; } Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2568/UsageOfCustomCollectionPersisterTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2568/UsageOfCustomCollectionPersisterTests.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2568/UsageOfCustomCollectionPersisterTests.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -32,7 +32,7 @@ rm.Id(x => x.Id); rm.Bag(x => x.Relateds, am => am.Persister<MyCollectionPersister>(), rel=> rel.OneToMany()); }); - var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); return mappings; } Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2569/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2569/Fixture.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2569/Fixture.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -28,7 +28,7 @@ }); var conf = new Configuration(); conf.DataBaseIntegration(x=> x.Dialect<MsSql2008Dialect>()); - conf.AddDeserializedMapping(mapper.CompileMappingForAllExplicitAddedEntities(), "wholeDomain"); + conf.AddDeserializedMapping(mapper.CompileMappingForAllExplicitlyAddedEntities(), "wholeDomain"); var mappings = conf.CreateMappings(Dialect.Dialect.GetDialect()); var pc = mappings.GetClass(typeof(MyClass).FullName); Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2587/CachingWithLinq.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2587/CachingWithLinq.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2587/CachingWithLinq.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -51,7 +51,7 @@ mc.Id(x => x.Id); mc.ManyToOne(x=> x.Foo, map=> map.Column("FooId")); }); - var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); return mappings; } Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2632/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2632/Fixture.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2632/Fixture.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -38,7 +38,7 @@ cm.Property(x => x.Date); cm.ManyToOne(x => x.Customer, map => map.Column("CUSTOMERID")); }); - return mapper.CompileMappingForAllExplicitAddedEntities(); + return mapper.CompileMappingForAllExplicitlyAddedEntities(); } protected override void Configure(Cfg.Configuration configuration) Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -20,7 +20,7 @@ }, rel => rel.OneToMany()); }); mapper.Class<Related>(rc => rc.Id(x => x.Id, map => map.Generator(Generators.HighLow))); - HbmMapping mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + HbmMapping mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); return mappings; } Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -21,7 +21,7 @@ }, rel => rel.OneToMany()); }); mapper.Class<Related>(rc => rc.Id(x => x.Id, map => map.Generator(Generators.HighLow))); - HbmMapping mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + HbmMapping mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); return mappings; } Modified: trunk/nhibernate/src/NHibernate.Test/Stateless/FetchingLazyCollections/LazyCollectionFetchTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Stateless/FetchingLazyCollections/LazyCollectionFetchTests.cs 2011-06-21 14:22:28 UTC (rev 5967) +++ trunk/nhibernate/src/NHibernate.Test/Stateless/FetchingLazyCollections/LazyCollectionFetchTests.cs 2011-06-21 16:31:37 UTC (rev 5968) @@ -30,7 +30,7 @@ }); mapper.AddMapping<FamilyMap<Reptile>>(); mapper.AddMapping<FamilyMap<Human>>(); - var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities(); return mappings; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-21 14:22:34
|
Revision: 5967 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5967&view=rev Author: fabiomaulo Date: 2011-06-21 14:22:28 +0000 (Tue, 21 Jun 2011) Log Message: ----------- Fix NH-2773 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Model.cs Modified: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs 2011-06-21 12:35:12 UTC (rev 5966) +++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs 2011-06-21 14:22:28 UTC (rev 5967) @@ -6,7 +6,6 @@ #endregion -using System; using System.Collections.Generic; using NHibernate.Util; @@ -14,8 +13,7 @@ { public class ProxyCache : IProxyCache { - private readonly IDictionary<ProxyCacheEntry, System.Type> cache = new ThreadSafeDictionary<ProxyCacheEntry, System.Type>(new Dictionary<ProxyCacheEntry, System.Type>()); - private readonly object syncObject = new object(); + private static readonly IDictionary<ProxyCacheEntry, System.Type> cache = new ThreadSafeDictionary<ProxyCacheEntry, System.Type>(new Dictionary<ProxyCacheEntry, System.Type>()); #region IProxyCache Members @@ -32,20 +30,14 @@ public System.Type GetProxyType(System.Type baseType, params System.Type[] baseInterfaces) { - lock (syncObject) - { - var entry = new ProxyCacheEntry(baseType, baseInterfaces); - return cache[entry]; - } + var entry = new ProxyCacheEntry(baseType, baseInterfaces); + return cache[entry]; } public void StoreProxyType(System.Type result, System.Type baseType, params System.Type[] baseInterfaces) { - lock (syncObject) - { - var entry = new ProxyCacheEntry(baseType, baseInterfaces); - cache[entry] = result; - } + var entry = new ProxyCacheEntry(baseType, baseInterfaces); + cache[entry] = result; } #endregion Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Fixture.cs 2011-06-21 14:22:28 UTC (rev 5967) @@ -0,0 +1,72 @@ +using System; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH2773 { + public class Fixture : BugTestCase { + private Guid _entityGuid; + + protected override void OnSetUp() { + using (ISession session = OpenSession()) { + using (ITransaction tx = session.BeginTransaction()) { + var entity = new MyEntity(); + var entity2 = new MyEntity(); + entity.OtherEntity = entity2; + + session.Save(entity); + session.Save(entity2); + + _entityGuid = entity.Id; + + tx.Commit(); + } + } + } + + protected override void OnTearDown() { + base.OnTearDown(); + + using (ISession session = OpenSession()) { + using (ITransaction tx = session.BeginTransaction()) { + session.Delete("from MyEntity"); + tx.Commit(); + } + } + } + + [Test] + public void DeserializedSession_ProxyType_ShouldBeEqualToOriginalProxyType() { + System.Type originalProxyType = null; + System.Type deserializedProxyType = null; + ISession deserializedSession = null; + + using (ISession session = OpenSession()) { + using (ITransaction tx = session.BeginTransaction()) { + var entity = session.Get<MyEntity>(_entityGuid); + originalProxyType = entity.OtherEntity.GetType(); + tx.Commit(); + } + + + using (MemoryStream sessionMemoryStream = new MemoryStream()) { + BinaryFormatter formatter = new BinaryFormatter(); + formatter.Serialize(sessionMemoryStream, session); + + sessionMemoryStream.Seek(0, SeekOrigin.Begin); + deserializedSession = (ISession)formatter.Deserialize(sessionMemoryStream); + } + } + + using (ITransaction tx = deserializedSession.BeginTransaction()) { + var entity = deserializedSession.Get<MyEntity>(_entityGuid); + deserializedProxyType = entity.OtherEntity.GetType(); + tx.Commit(); + } + + deserializedSession.Dispose(); + + Assert.AreEqual(originalProxyType, deserializedProxyType); + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Mappings.hbm.xml 2011-06-21 14:22:28 UTC (rev 5967) @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH2773"> + <class name="MyEntity"> + <id name="Id" column="id"> + <generator class="guid" /> + </id> + <many-to-one name="OtherEntity" /> + </class> +</hibernate-mapping> \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2773/Model.cs 2011-06-21 14:22:28 UTC (rev 5967) @@ -0,0 +1,9 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.NH2773 { + [Serializable] + public class MyEntity { + public virtual Guid Id { get; set; } + public virtual MyEntity OtherEntity { get; set; } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-21 12:35:12 UTC (rev 5966) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-21 14:22:28 UTC (rev 5967) @@ -880,6 +880,8 @@ <Compile Include="NHSpecificTest\NH2746\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2760\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2760\Model.cs" /> + <Compile Include="NHSpecificTest\NH2773\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2773\Model.cs" /> <Compile Include="NHSpecificTest\NH941\Domain.cs" /> <Compile Include="NHSpecificTest\NH941\Fixture.cs" /> <Compile Include="NHSpecificTest\NH941\FixtureUsingList.cs" /> @@ -2726,6 +2728,7 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH2773\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2693\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2746\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2700\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-21 12:35:18
|
Revision: 5966 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5966&view=rev Author: fabiomaulo Date: 2011-06-21 12:35:12 +0000 (Tue, 21 Jun 2011) Log Message: ----------- Apply NH-2774 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs Modified: trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2011-06-20 12:11:12 UTC (rev 5965) +++ trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2011-06-21 12:35:12 UTC (rev 5966) @@ -19,7 +19,7 @@ private readonly ISet<AssociationKey> visitedAssociationKeys = new HashedSet<AssociationKey>(); private readonly IDictionary<string, IFilter> enabledFilters; private readonly IDictionary<string, IFilter> enabledFiltersForManyToOne; - private readonly Regex aliasRegex = new Regex(@"([\w]+)\.", RegexOptions.IgnoreCase | RegexOptions.Compiled); + private static readonly Regex aliasRegex = new Regex(@"([\w]+)\.", RegexOptions.IgnoreCase | RegexOptions.Compiled); private string[] suffixes; private string[] collectionSuffixes; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-20 12:11:18
|
Revision: 5965 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5965&view=rev Author: fabiomaulo Date: 2011-06-20 12:11:12 +0000 (Mon, 20 Jun 2011) Log Message: ----------- Actual trunk version Modified Paths: -------------- trunk/nhibernate/build-common/common.xml Modified: trunk/nhibernate/build-common/common.xml =================================================================== --- trunk/nhibernate/build-common/common.xml 2011-06-20 11:39:10 UTC (rev 5964) +++ trunk/nhibernate/build-common/common.xml 2011-06-20 12:11:12 UTC (rev 5965) @@ -84,7 +84,7 @@ effectively SP0). --> - <property name="project.version" value="3.2.0.Beta2" overwrite="false" /> + <property name="project.version" value="3.2.0.CR1" overwrite="false" /> <!-- Compute short project version (major.minor) using a regex --> <regex input="${project.version}" pattern="^(?'shortversion'\d+\.\d+)" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-20 11:39:17
|
Revision: 5964 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5964&view=rev Author: fabiomaulo Date: 2011-06-20 11:39:10 +0000 (Mon, 20 Jun 2011) Log Message: ----------- Preparing release Modified Paths: -------------- trunk/nhibernate/releasenotes.txt Modified: trunk/nhibernate/releasenotes.txt =================================================================== --- trunk/nhibernate/releasenotes.txt 2011-06-19 21:50:00 UTC (rev 5963) +++ trunk/nhibernate/releasenotes.txt 2011-06-20 11:39:10 UTC (rev 5964) @@ -14,6 +14,53 @@ * For those implementing IDrive without inherit from DriveBase: IDrive.AdjustCommand * Dialect base: removed some no more needed properties +Build 3.2.0.Beta2 (rev5964) +============================= +** Bug + * [NH-2206] - Cast is not supported by the new Linq provider + * [NH-2213] - CLONE -Wrong parameters order in IQuery with SetParameterList and Filter. SQL Server 2005 + * [NH-2296] - Subselect fetching strategy with a "SetMaxResults" query generates *extremely* inefficient sql + * [NH-2317] - Select after Take does not work properly + * [NH-2318] - Template functions fail with certain combinations of arguments. + * [NH-2328] - Linq query on <Any/> fails + * [NH-2415] - HQL parameters not converted correctly to SQL + * [NH-2657] - OrderBy After Cast Not Working + * [NH-2662] - Casting a joined alias in QueryOver loses alias context and looks for property on QueryOver root + * [NH-2700] - SqlFunctionProjection does not honor parameter order + * [NH-2701] - Cannot use Linq Skip() in conjunction with FetchMany and ToFuture + * [NH-2703] - Using a "with" restriction in outer joins result in wrong SQL + * [NH-2708] - Cast<>() with a where clause fails with a NotSupportedException + * [NH-2712] - Linq query doesn't support enums in VB.NET + * [NH-2717] - Count() after Cast<>() causes InvalidOperationException + * [NH-2729] - Parameter values are not set using OffsetStartsAtOne + * [NH-2733] - Using an expression in QueryOver gives: Lambda Parameter not in scope + * [NH-2736] - Inverted parameters in HQL statement using take + * [NH-2739] - Can't get ByCode mapping to produce not nullable varbinary(max) + * [NH-2741] - CLONE -HQL .class query on <any> mapping does not work + * [NH-2746] - Invalid SQL generated for MSSQL when using Filter and paging subquery together [regression from 2.1] + +** Improvement + * [NH-941] - One-Many Requiring Nullable Foreign Keys + * [NH-1050] - Unidirectional One To Many Without Nullable Foreign Key + * [NH-2070] - Better error message for "object references an unsaved transient instance" + * [NH-2427] - Support querying HasValue on Nullable types + * [NH-2683] - Add common dialect functions as extension methods for QueryOver + * [NH-2702] - Support HQL pagination with parameters + * [NH-2728] - ManyToAny missing from ICollectionElementRelation<TElement> + * [NH-2732] - Dialect.GetLimitString simplifications and improvements + * [NH-2738] - Exception thrown when mapping contains empty enum + * [NH-2749] - Externalize Remotion.Linq namespace + * [NH-2753] - one-shot-insert for <list> and <map> for unidirectional one-to-many + * [NH-2760] - Unable to order by sub-collection's count + * [NH-2770] - Property spelling of IDbIntegrationConfigurationProperties.LogFormatedSql + +** New Feature + * [NH-2616] - Support Trim() function in Linq + +** Patch + * [NH-2125] - Solution for NH2123 - Subselect in combination with a disjuction query causes an enormous memory cons + * [NH-2363] - Patch for ComponentCollectionCriteriaInfoProvider, fixed persister.ElementType cast in constructor. + Build 3.2.0.Beta1 (rev5839) ============================= ** Bug This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-19 21:50:07
|
Revision: 5963 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5963&view=rev Author: fabiomaulo Date: 2011-06-19 21:50:00 +0000 (Sun, 19 Jun 2011) Log Message: ----------- Tests for NH-2693 Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Model.cs Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Fixture.cs 2011-06-19 21:50:00 UTC (rev 5963) @@ -0,0 +1,292 @@ +using System.Collections.Generic; +using System.Linq; +using NHibernate.Linq; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH2693 { + public class Fixture : BugTestCase { + private List<FirstLevel> _firstLevels; + + protected override void OnSetUp() { + base.OnSetUp(); + + using (ISession session = OpenSession()) { + using (ITransaction tx = session.BeginTransaction()) { + var firstLevel1 = new FirstLevel(); + + var secondLevel1 = new SecondLevelComponent { FirstLevel = firstLevel1 }; + firstLevel1.SecondLevels.Add(secondLevel1); + + var thirdLevel1 = new SpecificThirdLevel(); + secondLevel1.ThirdLevel = thirdLevel1; + secondLevel1.SpecificThirdLevel = thirdLevel1; + + var fourthLevel1 = new FourthLevel { SomeString = "first", SpecificThirdLevel = thirdLevel1 }; + thirdLevel1.FourthLevels.Add(fourthLevel1); + var fourthLevel2 = new FourthLevel { SomeString = "second", SpecificThirdLevel = thirdLevel1 }; + thirdLevel1.FourthLevels.Add(fourthLevel2); + + + var firstLevel2 = new FirstLevel(); + + var secondLevel2 = new SecondLevelComponent { FirstLevel = firstLevel2 }; + firstLevel2.SecondLevels.Add(secondLevel2); + + var thirdLevel2 = new SpecificThirdLevel(); + secondLevel2.ThirdLevel = thirdLevel2; + secondLevel2.SpecificThirdLevel = thirdLevel2; + + var fourthLevel3 = new FourthLevel { SomeString = "third", SpecificThirdLevel = thirdLevel2 }; + thirdLevel2.FourthLevels.Add(fourthLevel3); + var fourthLevel4 = new FourthLevel { SomeString = "fourth", SpecificThirdLevel = thirdLevel2 }; + thirdLevel2.FourthLevels.Add(fourthLevel4); + + + var firstLevel3 = new FirstLevel(); + + var secondLevel3 = new SecondLevelComponent { FirstLevel = firstLevel3 }; + firstLevel3.SecondLevels.Add(secondLevel3); + + var thirdLevel3 = new SpecificThirdLevel(); + secondLevel3.ThirdLevel = thirdLevel3; + secondLevel3.SpecificThirdLevel = thirdLevel3; + + + session.Save(thirdLevel1); + session.Save(thirdLevel2); + session.Save(thirdLevel3); + session.Save(firstLevel1); + session.Save(firstLevel2); + session.Save(firstLevel3); + + _firstLevels = new List<FirstLevel>(); + _firstLevels.Add(firstLevel1); + _firstLevels.Add(firstLevel2); + _firstLevels.Add(firstLevel3); + + tx.Commit(); + } + } + } + + protected override void OnTearDown() { + base.OnTearDown(); + + using (ISession session = OpenSession()) { + using (ITransaction tx = session.BeginTransaction()) { + session.Delete("from FourthLevel"); + session.Delete("from ThirdLevel"); + session.Delete("from FirstLevel"); + tx.Commit(); + } + } + } + + [Test, Ignore("Not fixed yet")] + public void _1_Querying_BasedOnFourthLevelExistence_WithIsAndCasting_ShouldReturnSameEntitiesAsLinqToObjects() { + var expected = _firstLevels + .Where(first => first.SecondLevels + .Any(second => second.ThirdLevel is SpecificThirdLevel && + ((SpecificThirdLevel)second.ThirdLevel).FourthLevels + .Any() + ) + ) + .ToList(); + + using (ISession session = OpenSession()) { + using (ITransaction tx = session.BeginTransaction()) { + var result = session.Query<FirstLevel>() + .Where(first => first.SecondLevels + .Any(second => second.ThirdLevel is SpecificThirdLevel && + ((SpecificThirdLevel)second.ThirdLevel).FourthLevels + .Any() + ) + ) + .ToList(); + + Assert.AreEqual(expected.Count, result.Count); + Assert.IsTrue(result + .All(f => f.SecondLevels + .Any(s => ((SpecificThirdLevel)s.ThirdLevel).FourthLevels + .Any() + ) + ) + ); + } + } + } + + [Test, Ignore("Not fixed yet")] + public void _2_Querying_BasedOnFourthLevelExistence_WithSelectAndOfType_ShouldReturnSameEntitiesAsLinqToObjects() + { + var expected = _firstLevels + .Where(first => first.SecondLevels + .Select(second => second.ThirdLevel) + .OfType<SpecificThirdLevel>() + .Any(specificThird => specificThird.FourthLevels + .Any() + ) + ) + .ToList(); + + using (ISession session = OpenSession()) { + using (ITransaction tx = session.BeginTransaction()) { + var result = session.Query<FirstLevel>() + .Where(first => first.SecondLevels + .Select(second => second.ThirdLevel) + .OfType<SpecificThirdLevel>() + .Any(specificThird => specificThird.FourthLevels + .Any() + ) + ) + .ToList(); + + Assert.AreEqual(expected.Count, result.Count); + Assert.IsTrue(result + .All(f => f.SecondLevels + .Any(s => ((SpecificThirdLevel)s.ThirdLevel).FourthLevels + .Any() + ) + ) + ); + } + } + } + + [Test, Ignore("Not fixed yet")] + public void _3_Querying_BasedOnFourthLevelProperty_WithIsAndCasting_ShouldReturnSameEntitiesAsLinqToObjects() + { + var expected = _firstLevels + .Where(first => first.SecondLevels + .Any(second => second.ThirdLevel is SpecificThirdLevel && + ((SpecificThirdLevel)second.ThirdLevel).FourthLevels + .Any(fourth => fourth.SomeString == "first") + ) + ) + .ToList(); + + using (ISession session = OpenSession()) { + using (ITransaction tx = session.BeginTransaction()) { + var result = session.Query<FirstLevel>() + .Where(first => first.SecondLevels + .Any(second => second.ThirdLevel is SpecificThirdLevel && + ((SpecificThirdLevel)second.ThirdLevel).FourthLevels + .Any(fourth => fourth.SomeString == "first") + ) + ) + .ToList(); + + Assert.AreEqual(expected.Count, result.Count); + Assert.IsTrue(result + .All(f => f.SecondLevels + .Any(s => ((SpecificThirdLevel)s.ThirdLevel).FourthLevels + .Any(fo => fo.SomeString == "first") + ) + ) + ); + } + } + } + + [Test, Ignore("Not fixed yet")] + public void _4_Querying_BasedOnFourthLevelProperty_WithSelectAndOfType_ShouldReturnSameEntitiesAsLinqToObjects() + { + var expected = _firstLevels + .Where(first => first.SecondLevels + .Select(second => second.ThirdLevel) + .OfType<SpecificThirdLevel>() + .Any(specificThird => specificThird.FourthLevels + .Any(fourth => fourth.SomeString == "first") + ) + ) + .ToList(); + + using (ISession session = OpenSession()) { + using (ITransaction tx = session.BeginTransaction()) { + var result = session.Query<FirstLevel>() + .Where(first => first.SecondLevels + .Select(second => second.ThirdLevel) + .OfType<SpecificThirdLevel>() + .Any(specificThird => specificThird.FourthLevels + .Any(fourth => fourth.SomeString == "first") + ) + ) + .ToList(); + + Assert.AreEqual(expected.Count, result.Count); + Assert.IsTrue(result + .All(f => f.SecondLevels + .Any(s => ((SpecificThirdLevel)s.ThirdLevel).FourthLevels + .Any(fo => fo.SomeString == "first") + ) + ) + ); + } + } + } + + [Test] + public void _5_Querying_BasedOnFourthLevelExistence_ByUsingSpecificThirdLevelProperty_ShouldReturnSameEntitiesAsLinqToObjects() { + var expected = _firstLevels + .Where(first => first.SecondLevels + .Any(second => second.SpecificThirdLevel.FourthLevels + .Any() + ) + ) + .ToList(); + + using (ISession session = OpenSession()) { + using (ITransaction tx = session.BeginTransaction()) { + var result = session.Query<FirstLevel>() + .Where(first => first.SecondLevels + .Any(second => second.SpecificThirdLevel.FourthLevels + .Any() + ) + ) + .ToList(); + + Assert.AreEqual(expected.Count, result.Count); + Assert.IsTrue(result + .All(f => f.SecondLevels + .Any(second => second.SpecificThirdLevel.FourthLevels + .Any() + ) + ) + ); + } + } + } + + [Test] + public void _6_Querying_BasedOnFourthLevelProperty_ByUsingSpecificThirdLevelProperty_ShouldReturnSameEntitiesAsLinqToObjects() { + var expected = _firstLevels + .Where(first => first.SecondLevels + .Any(second => second.SpecificThirdLevel.FourthLevels + .Any(fourth => fourth.SomeString == "first") + ) + ) + .ToList(); + + using (ISession session = OpenSession()) { + using (ITransaction tx = session.BeginTransaction()) { + var result = session.Query<FirstLevel>() + .Where(first => first.SecondLevels + .Any(second => second.SpecificThirdLevel.FourthLevels + .Any(fourth => fourth.SomeString == "first") + ) + ) + .ToList(); + + Assert.AreEqual(expected.Count, result.Count); + Assert.IsTrue(result + .All(f => f.SecondLevels + .Any(second => second.SpecificThirdLevel.FourthLevels + .Any(fourth => fourth.SomeString == "first") + ) + ) + ); + } + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Mappings.hbm.xml 2011-06-19 21:50:00 UTC (rev 5963) @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH2693"> + <class name="FirstLevel"> + <!-- Id column must be same as key column of SecondLevels because of NH-2692 --> + <id name="Id" column="first_level_id"> + <generator class="guid" /> + </id> + <set name="SecondLevels"> + <key column="first_level_id" /> + <composite-element class="SecondLevelComponent"> + <parent name="FirstLevel" /> + <many-to-one name="ThirdLevel" /> + <many-to-one name="SpecificThirdLevel" /> + <property name="SomeBool" /> + </composite-element> + </set> + </class> + + <class name="ThirdLevel"> + <id name="Id"> + <generator class="guid" /> + </id> + <joined-subclass name="SpecificThirdLevel"> + <key column="third_level_id" /> + <set name="FourthLevels" cascade="all-delete-orphan" inverse="true"> + <key column="third_level_id" /> + <one-to-many class="FourthLevel"/> + </set> + </joined-subclass> + </class> + + <class name="FourthLevel"> + <id name="Id"> + <generator class="guid" /> + </id> + <many-to-one name="SpecificThirdLevel" column="third_level_id"/> + <property name="SomeString" /> + </class> +</hibernate-mapping> \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2693/Model.cs 2011-06-19 21:50:00 UTC (rev 5963) @@ -0,0 +1,40 @@ +using Iesi.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH2693 { + using System; + using System.Collections.Generic; + + public class FirstLevel { + public FirstLevel() { + SecondLevels = new HashedSet<SecondLevelComponent>(); + } + + public virtual Guid Id { get; set; } + public virtual ICollection<SecondLevelComponent> SecondLevels { get; set; } + } + + public class SecondLevelComponent { + public virtual FirstLevel FirstLevel { get; set; } + public virtual ThirdLevel ThirdLevel { get; set; } + public virtual SpecificThirdLevel SpecificThirdLevel { get; set; } + public virtual bool SomeBool { get; set; } + } + + public abstract class ThirdLevel { + public virtual Guid Id { get; set; } + } + + public class SpecificThirdLevel : ThirdLevel { + public SpecificThirdLevel() { + FourthLevels = new HashedSet<FourthLevel>(); + } + + public virtual ICollection<FourthLevel> FourthLevels { get; set; } + } + + public class FourthLevel { + public virtual Guid Id { get; set; } + public virtual SpecificThirdLevel SpecificThirdLevel { get; set; } + public virtual string SomeString { get; set; } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-19 21:20:05 UTC (rev 5962) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-19 21:50:00 UTC (rev 5963) @@ -855,6 +855,8 @@ <Compile Include="NHSpecificTest\NH2673\CachingWithTrasformerTests.cs" /> <Compile Include="NHSpecificTest\NH2691\Domain.cs" /> <Compile Include="NHSpecificTest\NH2691\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2693\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2693\Model.cs" /> <Compile Include="NHSpecificTest\NH2697\ArticleGroupItem.cs" /> <Compile Include="NHSpecificTest\NH2697\ArticleItem.cs" /> <Compile Include="NHSpecificTest\NH2697\SampleTest.cs" /> @@ -2724,6 +2726,7 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH2693\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2746\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2700\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2296\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-19 21:20:12
|
Revision: 5962 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5962&view=rev Author: fabiomaulo Date: 2011-06-19 21:20:05 +0000 (Sun, 19 Jun 2011) Log Message: ----------- Passing test for NH-2746 (the refactoring of param. management was for something) Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/DomainClasses.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/Mappings.hbm.xml Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/DomainClasses.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/DomainClasses.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/DomainClasses.cs 2011-06-19 21:20:05 UTC (rev 5962) @@ -0,0 +1,27 @@ +using Iesi.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH2746 +{ + public class T1 + { + public virtual int Id { get; set; } + public virtual string Name { get; set; } + public virtual Iesi.Collections.Generic.ISet<T2> Children { get; protected set; } + + public T1() + { + this.Children = new HashedSet<T2>(); + } + } + + public class T2 + { + public virtual int Id { get; set; } + public virtual string Name { get; set; } + public virtual T1 Parent { get; set; } + + public T2() + { + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/Fixture.cs 2011-06-19 21:20:05 UTC (rev 5962) @@ -0,0 +1,32 @@ +using NHibernate.Criterion; +using NHibernate.Transform; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.Test.NHSpecificTest.NH2746 +{ + public class Fixture: BugTestCase + { + [Test] + public void TestQuery() + { + using (ISession session = OpenSession()) + { + DetachedCriteria page = DetachedCriteria.For<T1>() + .SetFirstResult(3) + .SetMaxResults(7) + .AddOrder(NHibernate.Criterion.Order.Asc(Projections.Id())) + .SetProjection(Projections.Id()); + + ICriteria crit = session.CreateCriteria<T1>() + .Add(Subqueries.PropertyIn("id", page)) + .SetResultTransformer(new DistinctRootEntityResultTransformer()) + .SetFetchMode("Children", NHibernate.FetchMode.Join); + + session.EnableFilter("nameFilter").SetParameter("name", "Another child"); + + crit.Executing(c=> c.List<T1>()).NotThrows(); + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2746/Mappings.hbm.xml 2011-06-19 21:20:05 UTC (rev 5962) @@ -0,0 +1,29 @@ +<?xml version="1.0" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.NH2746" assembly="NHibernate.Test"> + <class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="T1" table="T1"> + <id column="Id" name="Id" > + <generator class="native" /> + </id> + + <property name="Name" column="Name" type="System.String" length="50" not-null="false" /> + <set name="Children" inverse="true" > + <key column="T1Id" /> + <one-to-many class="T2" /> + <filter name="nameFilter" condition=":name=Name" /> + </set> + </class> + + <class name="T2" table="T2"> + <id column="Id" name="Id" > + <generator class="native" /> + </id> + + <property name="Name" column="Name" type="System.String" length="50" not-null="false" /> + <many-to-one name="Parent" column="T1Id" not-null="true" /> + </class> + + <filter-def name="nameFilter" > + <filter-param name="name" type="System.String" /> + </filter-def> +</hibernate-mapping> \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-19 21:07:39 UTC (rev 5961) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-19 21:20:05 UTC (rev 5962) @@ -874,6 +874,8 @@ <Compile Include="NHSpecificTest\NH2733\Model.cs" /> <Compile Include="NHSpecificTest\NH2736\Domain.cs" /> <Compile Include="NHSpecificTest\NH2736\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2746\DomainClasses.cs" /> + <Compile Include="NHSpecificTest\NH2746\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2760\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2760\Model.cs" /> <Compile Include="NHSpecificTest\NH941\Domain.cs" /> @@ -2722,6 +2724,7 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH2746\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2700\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2296\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2760\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-19 21:07:45
|
Revision: 5961 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5961&view=rev Author: fabiomaulo Date: 2011-06-19 21:07:39 +0000 (Sun, 19 Jun 2011) Log Message: ----------- Passing test for NH-2700 (the refactoring of param. management was for something) Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/CustomDialect.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/ModelClass.cs Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/CustomDialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/CustomDialect.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/CustomDialect.cs 2011-06-19 21:07:39 UTC (rev 5961) @@ -0,0 +1,20 @@ +using NHibernate.Dialect; +using NHibernate.Dialect.Function; + +namespace NHibernate.Test.NHSpecificTest.NH2700 +{ + public class CustomDialect : MsSql2005Dialect + { + public CustomDialect() + { + RegisterFunction( + "AddDays", + new SQLFunctionTemplate( + NHibernateUtil.DateTime, + "dateadd(day,?2,?1)" + + ) + ); + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/Fixture.cs 2011-06-19 21:07:39 UTC (rev 5961) @@ -0,0 +1,66 @@ +using System; +using NHibernate.Criterion; +using NHibernate.Impl; +using NHibernate.Loader.Criteria; +using NUnit.Framework; +using Environment = NHibernate.Cfg.Environment; + +namespace NHibernate.Test.NHSpecificTest.NH2700 +{ + [TestFixture] + public class Fixture : BugTestCase + { + protected override void Configure(Cfg.Configuration configuration) + { + cfg.SetProperty(Environment.Dialect, typeof(CustomDialect).AssemblyQualifiedName); + } + + public static string GetSql(ICriteria criteria) + { + var criteriaImpl = (CriteriaImpl)criteria; + var session = criteriaImpl.Session; + var factory = session.Factory; + + var translator = + new CriteriaQueryTranslator( + factory, + criteriaImpl, + criteriaImpl.EntityOrClassName, + CriteriaQueryTranslator.RootSqlAlias); + + var implementors = factory.GetImplementors(criteriaImpl.EntityOrClassName); + + var walker = new CriteriaJoinWalker( + (Persister.Entity.IOuterJoinLoadable)factory.GetEntityPersister(implementors[0]), + translator, + factory, + criteriaImpl, + criteriaImpl.EntityOrClassName, + session.EnabledFilters); + + return walker.SqlString.ToString(); + } + + [Test] + public void TestProjection() + { + + using (var s = OpenSession()) + { + var proj = new SqlFunctionProjection("AddDays", NHibernateUtil.DateTime, + new IProjection[] + { + Projections.Property<ModelClass>(p=>p.Date1), + Projections.Property<ModelClass>(p=>p.Value1) + }); + var criteria = s.CreateCriteria<ModelClass>(); + criteria.SetProjection(proj); + + var sql = GetSql(criteria); + + Assert.That(sql, Is.StringMatching("dateadd\\(day,(.*?)Value1,(.*?)Date1\\)")); + Console.WriteLine(sql.ToString()); + } + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/Mappings.hbm.xml 2011-06-19 21:07:39 UTC (rev 5961) @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.NH2700" + assembly="NHibernate.Test"> + + <class name="ModelClass"> + <id name="Id"> + <generator class="native"/> + </id> + <property name="Date1"/> + <property name="Value1"/> + </class> +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/ModelClass.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/ModelClass.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2700/ModelClass.cs 2011-06-19 21:07:39 UTC (rev 5961) @@ -0,0 +1,12 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.NH2700 +{ + public class ModelClass + { + public virtual int Id { get; set; } + public virtual DateTime Date1 { get; set; } + public virtual DateTime Value1 { get; set; } + } + +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-19 20:57:39 UTC (rev 5960) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-19 21:07:39 UTC (rev 5961) @@ -858,6 +858,9 @@ <Compile Include="NHSpecificTest\NH2697\ArticleGroupItem.cs" /> <Compile Include="NHSpecificTest\NH2697\ArticleItem.cs" /> <Compile Include="NHSpecificTest\NH2697\SampleTest.cs" /> + <Compile Include="NHSpecificTest\NH2700\CustomDialect.cs" /> + <Compile Include="NHSpecificTest\NH2700\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2700\ModelClass.cs" /> <Compile Include="NHSpecificTest\NH2703\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2703\Model.cs" /> <Compile Include="NHSpecificTest\NH2705\ItemBase.cs" /> @@ -2719,6 +2722,7 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH2700\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2296\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2760\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2662\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-19 20:57:45
|
Revision: 5960 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5960&view=rev Author: fabiomaulo Date: 2011-06-19 20:57:39 +0000 (Sun, 19 Jun 2011) Log Message: ----------- Fix NH-2125 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Loader/Loader.cs Modified: trunk/nhibernate/src/NHibernate/Loader/Loader.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-06-18 23:03:18 UTC (rev 5959) +++ trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-06-19 20:57:39 UTC (rev 5960) @@ -518,28 +518,41 @@ if (keys.Count > 1) { //if we only returned one entity, query by key is more efficient + var subSelects = CreateSubselects(keys, queryParameters).ToArray(); - ISet<EntityKey>[] keySets = Transpose(keys); - - ILoadable[] loadables = EntityPersisters; - string[] aliases = Aliases; - foreach (EntityKey[] rowKeys in keys) { for (int i = 0; i < rowKeys.Length; i++) { - if (rowKeys[i] != null && loadables[i].HasSubselectLoadableCollections) + if (rowKeys[i] != null && subSelects[i] != null) { - SubselectFetch subselectFetch = - new SubselectFetch(aliases[i], loadables[i], queryParameters, keySets[i]); - - session.PersistenceContext.BatchFetchQueue.AddSubselect(rowKeys[i], subselectFetch); + session.PersistenceContext.BatchFetchQueue.AddSubselect(rowKeys[i], subSelects[i]); } } } } } + private IEnumerable<SubselectFetch> CreateSubselects(IList<EntityKey[]> keys, QueryParameters queryParameters) + { + // see NH-2123 NH-2125 + ISet<EntityKey>[] keySets = Transpose(keys); + ILoadable[] loadables = EntityPersisters; + string[] aliases = Aliases; + + for (int i = 0; i < loadables.Length; i++) + { + if (loadables[i].HasSubselectLoadableCollections) + { + yield return new SubselectFetch(aliases[i], loadables[i], queryParameters, keySets[i]); + } + else + { + yield return null; + } + } + } + internal void InitializeEntitiesAndCollections(IList hydratedObjects, object resultSetId, ISessionImplementor session, bool readOnly) { ICollectionPersister[] collectionPersisters = CollectionPersisters; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-18 23:03:25
|
Revision: 5959 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5959&view=rev Author: fabiomaulo Date: 2011-06-18 23:03:18 +0000 (Sat, 18 Jun 2011) Log Message: ----------- Removed no more needed code Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs trunk/nhibernate/src/NHibernate/Loader/Custom/ICustomQuery.cs trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLCustomQuery.cs trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj Removed Paths: ------------- trunk/nhibernate/src/NHibernate/Hql/IParameterTranslations.cs trunk/nhibernate/src/NHibernate/Param/ParameterTranslationsImpl.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs 2011-06-18 20:05:26 UTC (rev 5958) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs 2011-06-18 23:03:18 UTC (rev 5959) @@ -37,7 +37,6 @@ private QueryLoader _queryLoader; private IStatementExecutor _statementExecutor; private IStatement _sqlAst; - private ParameterTranslationsImpl _paramTranslations; private IDictionary<string, string> _tokenReplacements; private HqlSqlGenerator _generator; Deleted: trunk/nhibernate/src/NHibernate/Hql/IParameterTranslations.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/IParameterTranslations.cs 2011-06-18 20:05:26 UTC (rev 5958) +++ trunk/nhibernate/src/NHibernate/Hql/IParameterTranslations.cs 2011-06-18 23:03:18 UTC (rev 5959) @@ -1,20 +0,0 @@ -using System.Collections.Generic; -using NHibernate.Type; - -namespace NHibernate.Hql -{ - public interface IParameterTranslations - { - bool SupportsOrdinalParameterMetadata { get; } - - int OrdinalParameterCount { get; } - - int GetOrdinalParameterSqlLocation(int ordinalPosition); - - IType GetOrdinalParameterExpectedType(int ordinalPosition); - - IEnumerable<string> GetNamedParameterNames(); - - IType GetNamedParameterExpectedType(string name); - } -} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-06-18 20:05:26 UTC (rev 5958) +++ trunk/nhibernate/src/NHibernate/Loader/Custom/CustomLoader.cs 2011-06-18 23:03:18 UTC (rev 5959) @@ -26,7 +26,6 @@ private readonly SqlString sql; private readonly ISet<string> querySpaces = new HashedSet<string>(); - private readonly IDictionary<string, object> namedParameterBindPoints; private List<IParameterSpecification> parametersSpecifications; private readonly IQueryable[] entityPersisters; @@ -47,8 +46,7 @@ { sql = customQuery.SQL; querySpaces.AddAll(customQuery.QuerySpaces); - namedParameterBindPoints = customQuery.NamedParameterBindPoints; - this.parametersSpecifications = customQuery.CollectedParametersSpecifications.ToList(); + parametersSpecifications = customQuery.CollectedParametersSpecifications.ToList(); List<IQueryable> entitypersisters = new List<IQueryable>(); List<int> entityowners = new List<int>(); @@ -347,7 +345,7 @@ public IEnumerable<string> NamedParameters { - get { return namedParameterBindPoints.Keys; } + get { return parametersSpecifications.OfType<NamedParameterSpecification>().Select(np=> np.Name ); } } public class ResultRowProcessor Modified: trunk/nhibernate/src/NHibernate/Loader/Custom/ICustomQuery.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Custom/ICustomQuery.cs 2011-06-18 20:05:26 UTC (rev 5958) +++ trunk/nhibernate/src/NHibernate/Loader/Custom/ICustomQuery.cs 2011-06-18 23:03:18 UTC (rev 5959) @@ -22,22 +22,6 @@ /// </summary> ISet<string> QuerySpaces { get; } - /// <summary> - /// A map representing positions within the supplied <see cref="SQL"/> query to - /// which we need to bind named parameters. - /// </summary> - /// <remarks> - /// Optional, may return null if no named parameters. - /// The structure of the returned map (if one) as follows: - /// <ol> - /// <li>The keys into the map are the named parameter names</li> - /// <li>The corresponding value is either an if the - /// parameter occurs only once in the query; or a List of int if the - /// parameter occurs more than once</li> - /// </ol> - /// </remarks> - IDictionary<string, object> NamedParameterBindPoints { get; } - /// <summary> /// A collection of <see cref="IReturn"/> descriptors describing the /// ADO result set to be expected and how to map this result set. Modified: trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLCustomQuery.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLCustomQuery.cs 2011-06-18 20:05:26 UTC (rev 5958) +++ trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLCustomQuery.cs 2011-06-18 23:03:18 UTC (rev 5959) @@ -19,7 +19,6 @@ private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof (SQLCustomQuery)); private readonly List<IReturn> customQueryReturns = new List<IReturn>(); - private readonly Dictionary<string, object> namedParameterBindPoints = new Dictionary<string, object>(); private readonly ISet<string> querySpaces = new HashedSet<string>(); private readonly SqlString sql; private List<IParameterSpecification> parametersSpecifications; @@ -33,7 +32,6 @@ SQLQueryParser parser = new SQLQueryParser(factory, sqlQuery, new ParserContext(aliasContext)); sql = parser.Process(); - ArrayHelper.AddAll(namedParameterBindPoints, parser.NamedParameters); ArrayHelper.AddAll(customQueryReturns, processor.GenerateCustomReturns(parser.QueryHasAliases)); parametersSpecifications = parser.CollectedParametersSpecifications.ToList(); @@ -55,11 +53,6 @@ get { return sql; } } - public IDictionary<string, object> NamedParameterBindPoints - { - get { return namedParameterBindPoints; } - } - public ISet<string> QuerySpaces { get { return querySpaces; } Modified: trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs 2011-06-18 20:05:26 UTC (rev 5958) +++ trunk/nhibernate/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs 2011-06-18 23:03:18 UTC (rev 5959) @@ -28,8 +28,6 @@ private readonly string originalQueryString; private readonly IParserContext context; - private readonly Dictionary<string, object> namedParameters = new Dictionary<string, object>(); - private long aliasesFound; private IEnumerable<IParameterSpecification> parametersSpecifications; @@ -40,11 +38,6 @@ this.context = context; } - public IDictionary<string, object> NamedParameters - { - get { return namedParameters; } - } - public bool QueryHasAliases { get { return aliasesFound > 0; } @@ -253,11 +246,6 @@ var recognizer = new ParameterSubstitutionRecognizer(factory); ParameterParser.Parse(sqlString, recognizer); parametersSpecifications = recognizer.ParametersSpecifications.ToList(); - namedParameters.Clear(); - foreach (KeyValuePair<string, object> de in recognizer.namedParameterBindPoints) - { - namedParameters.Add(de.Key, de.Value); - } return recognizer.result.ToSqlString(); } @@ -266,7 +254,6 @@ { private readonly ISessionFactoryImplementor factory; internal SqlStringBuilder result = new SqlStringBuilder(); - internal Dictionary<string, object> namedParameterBindPoints = new Dictionary<string, object>(); internal int parameterCount = 0; private readonly List<IParameterSpecification> parametersSpecifications = new List<IParameterSpecification>(); private int positionalParameterCount; @@ -301,7 +288,6 @@ public void NamedParameter(string name, int position) { - AddNamedParameter(name); var paramSpec = new NamedParameterSpecification(1, position, name); var parameter = Parameter.Placeholder; parameter.BackTrack = paramSpec.GetIdsForBackTrack(factory).First(); @@ -323,27 +309,6 @@ { result.Add(sqlPart); } - - private void AddNamedParameter(string name) - { - int loc = parameterCount++; - object o; - if (!namedParameterBindPoints.TryGetValue(name, out o)) - { - namedParameterBindPoints[name] = loc; - } - else if (o is int) - { - List<int> list = new List<int>(4); - list.Add((int) o); - list.Add(loc); - namedParameterBindPoints[name] = list; - } - else - { - ((IList) o).Add(loc); - } - } } } } Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-06-18 20:05:26 UTC (rev 5958) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-06-18 23:03:18 UTC (rev 5959) @@ -1007,7 +1007,6 @@ <Compile Include="Param\IExplicitParameterSpecification.cs" /> <Compile Include="Param\IParameterSpecification.cs" /> <Compile Include="Param\NamedParameterSpecification.cs" /> - <Compile Include="Param\ParameterTranslationsImpl.cs" /> <Compile Include="Param\PositionalParameterSpecification.cs" /> <Compile Include="Hql\Ast\ANTLR\QuerySyntaxException.cs" /> <Compile Include="Hql\Ast\ANTLR\QueryTranslatorImpl.cs" /> @@ -1520,7 +1519,6 @@ <Compile Include="Criterion\IsNotEmptyExpression.cs" /> <Compile Include="Hql\HolderInstantiator.cs" /> <Compile Include="Hql\IFilterTranslator.cs" /> - <Compile Include="Hql\IParameterTranslations.cs" /> <Compile Include="Hql\IQueryTranslator.cs" /> <Compile Include="Hql\IQueryTranslatorFactory.cs" /> <Compile Include="Hql\NameGenerator.cs" /> Deleted: trunk/nhibernate/src/NHibernate/Param/ParameterTranslationsImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Param/ParameterTranslationsImpl.cs 2011-06-18 20:05:26 UTC (rev 5958) +++ trunk/nhibernate/src/NHibernate/Param/ParameterTranslationsImpl.cs 2011-06-18 23:03:18 UTC (rev 5959) @@ -1,143 +0,0 @@ -using System; -using System.Collections.Generic; -using NHibernate.Engine; -using NHibernate.Hql; -using NHibernate.Type; -using NHibernate.Util; - -namespace NHibernate.Param -{ - /// <summary> - /// Defines the information available for parameters encountered during - /// query translation through the antlr-based parser. - /// Author: Steve Ebersole - /// Ported by: Steve Strong - /// </summary> - public class ParameterTranslationsImpl : IParameterTranslations - { - private readonly Dictionary<string, ParameterInfo> _namedParameters; - private readonly ParameterInfo[] _ordinalParameters; - - public ParameterTranslationsImpl(IEnumerable<IParameterSpecification> parameterSpecifications) - { - List<ParameterInfo> ordinalParameterList = new List<ParameterInfo>(); - NullableDictionary<string, NamedParamTempHolder> namedParameterMap = new NullableDictionary<string, NamedParamTempHolder>(); - - int i = 0; - foreach (IParameterSpecification spec in parameterSpecifications) - { - if ( spec is PositionalParameterSpecification) - { - PositionalParameterSpecification ordinalSpec = ( PositionalParameterSpecification ) spec; - ordinalParameterList.Add( new ParameterInfo( i, ordinalSpec.ExpectedType) ); - } - else if ( spec is NamedParameterSpecification ) - { - NamedParameterSpecification namedSpec = ( NamedParameterSpecification ) spec; - NamedParamTempHolder paramHolder = namedParameterMap[namedSpec.Name]; - if ( paramHolder == null ) { - paramHolder = new NamedParamTempHolder(); - paramHolder.name = namedSpec.Name; - paramHolder.type = namedSpec.ExpectedType; - namedParameterMap.Add( namedSpec.Name, paramHolder ); - } - paramHolder.positions.Add( i ); - } - else { - // don't care about other param types here, just those explicitly user-defined... - - // Steve Strong Note: The original Java does not do this decrement; it increments i for - // every parameter type. However, within the Loader.GetParameterTypes() method, this introduces - // nulls into the paramTypeList array, which in turn causes Loader.ConvertITypesToSqlTypes() to crash - // with a null dereference. An alternative fix is to change the Loader to handle the null. I'm - // not sure which fix is the most appropriate. - // Legacy.FumTest.CompositeIDQuery() shows the bug if you remove the decrement below... - i--; - } - - i++; - } - - _ordinalParameters = ordinalParameterList.ToArray(); - _namedParameters = new Dictionary<string, ParameterInfo>(); - - foreach (NamedParamTempHolder holder in namedParameterMap.Values) - { - _namedParameters.Add(holder.name, new ParameterInfo( ArrayHelper.ToIntArray( holder.positions ), holder.type )); - } - } - - public int GetOrdinalParameterSqlLocation(int ordinalPosition) - { - return GetOrdinalParameterInfo(ordinalPosition).SqlLocations[0]; - } - - public IType GetOrdinalParameterExpectedType(int ordinalPosition) - { - return GetOrdinalParameterInfo(ordinalPosition).ExpectedType; - } - - public IEnumerable<string> GetNamedParameterNames() - { - return _namedParameters.Keys; - } - - public IType GetNamedParameterExpectedType(string name) - { - return GetNamedParameterInfo(name).ExpectedType; - } - - public bool SupportsOrdinalParameterMetadata - { - get { return true; } - } - - public int OrdinalParameterCount - { - get { return _ordinalParameters.Length; } - } - - private ParameterInfo GetOrdinalParameterInfo(int ordinalPosition) - { - // remember that ordinal parameters numbers are 1-based!!! - return _ordinalParameters[ordinalPosition - 1]; - } - - private ParameterInfo GetNamedParameterInfo(String name) - { - return _namedParameters[name]; - } - - class NamedParamTempHolder - { - internal String name; - internal IType type; - internal readonly List<int> positions = new List<int>(); - } - } - - [Serializable] - public class ParameterInfo - { - private readonly int[] sqlLocations; - - public ParameterInfo(int[] sqlPositions, IType expectedType) - { - sqlLocations = sqlPositions; - ExpectedType = expectedType; - } - - public ParameterInfo(int sqlPosition, IType expectedType) - { - sqlLocations = new[] { sqlPosition }; - ExpectedType = expectedType; - } - - public int[] SqlLocations - { - get { return sqlLocations; } - } - - public IType ExpectedType { get; private set; } - } -} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-18 20:05:32
|
Revision: 5958 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5958&view=rev Author: fabiomaulo Date: 2011-06-18 20:05:26 +0000 (Sat, 18 Jun 2011) Log Message: ----------- Removed no more needed code Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs trunk/nhibernate/src/NHibernate/Hql/IQueryTranslator.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs 2011-06-18 19:58:00 UTC (rev 5957) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs 2011-06-18 20:05:26 UTC (rev 5958) @@ -201,16 +201,6 @@ return _sqlAst.Walker.SelectClause.ColumnNames; } - public IParameterTranslations GetParameterTranslations() - { - if (_paramTranslations == null) - { - _paramTranslations = new ParameterTranslationsImpl(_sqlAst.Walker.Parameters); - } - - return _paramTranslations; - } - public ISet<string> QuerySpaces { get { return _sqlAst.Walker.QuerySpaces; } Modified: trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs 2011-06-18 19:58:00 UTC (rev 5957) +++ trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs 2011-06-18 20:05:26 UTC (rev 5958) @@ -1730,11 +1730,6 @@ return scalarColumnNames; } - public IParameterTranslations GetParameterTranslations() - { - return new ParameterTranslationsImpl(CollectedParameterSpecifications); - } - public bool ContainsCollectionFetches { get { return false; } Modified: trunk/nhibernate/src/NHibernate/Hql/IQueryTranslator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/IQueryTranslator.cs 2011-06-18 19:58:00 UTC (rev 5957) +++ trunk/nhibernate/src/NHibernate/Hql/IQueryTranslator.cs 2011-06-18 20:05:26 UTC (rev 5958) @@ -99,11 +99,6 @@ /// <returns>the column names in the generated SQL.</returns> string[][] GetColumnNames(); - /// <summary> - /// Information about any parameters encountered during translation. - /// </summary> - IParameterTranslations GetParameterTranslations(); - // <summary> // Validate the scrollability of the translated query. // </summary> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-18 19:58:07
|
Revision: 5957 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5957&view=rev Author: fabiomaulo Date: 2011-06-18 19:58:00 +0000 (Sat, 18 Jun 2011) Log Message: ----------- BuildParameterMetadata refactoring with parameter specifications fix Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs trunk/nhibernate/src/NHibernate/Param/DynamicFilterParameterSpecification.cs trunk/nhibernate/src/NHibernate/Param/NamedParameterSpecification.cs trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/Parameters/ trunk/nhibernate/src/NHibernate.Test/Parameters/NamedParameterSpecificationTest.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs 2011-06-18 18:52:29 UTC (rev 5956) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs 2011-06-18 19:58:00 UTC (rev 5957) @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using Antlr.Runtime; using Antlr.Runtime.Tree; using Iesi.Collections.Generic; @@ -17,6 +18,7 @@ using NHibernate.SqlCommand; using NHibernate.Type; using NHibernate.Util; +using IQueryable = NHibernate.Persister.Entity.IQueryable; namespace NHibernate.Hql.Ast.ANTLR { @@ -183,28 +185,14 @@ public ParameterMetadata BuildParameterMetadata() { - var parameterTranslations = GetParameterTranslations(); - - var ordinalDescriptors = new OrdinalParameterDescriptor[parameterTranslations.OrdinalParameterCount]; - - for (var i = 1; i <= ordinalDescriptors.Length; i++) - { - ordinalDescriptors[i - 1] = - new OrdinalParameterDescriptor(i, - parameterTranslations.SupportsOrdinalParameterMetadata - ? parameterTranslations.GetOrdinalParameterExpectedType(i) - : null); - } - - var namedDescriptorMap = new Dictionary<string, NamedParameterDescriptor>(); - foreach (var name in parameterTranslations.GetNamedParameterNames()) - { - namedDescriptorMap[name] = - new NamedParameterDescriptor(name, parameterTranslations.GetNamedParameterExpectedType(name), false);// description.JpaStyle); - - } - - return new ParameterMetadata(ordinalDescriptors, namedDescriptorMap); + IList<IParameterSpecification> specifications = _sqlAst.Walker.Parameters; + IEnumerable<OrdinalParameterDescriptor> ordinals = + specifications.OfType<PositionalParameterSpecification>().Select(op => new OrdinalParameterDescriptor(op.HqlPosition, op.ExpectedType)); + Dictionary<string, NamedParameterDescriptor> nameds = specifications.OfType<NamedParameterSpecification>() + .Distinct() + .Select(np => new {np.Name, Descriptor = new NamedParameterDescriptor(np.Name, np.ExpectedType, false)}) + .ToDictionary(ep => ep.Name, ep => ep.Descriptor); + return new ParameterMetadata(ordinals, nameds); } public string[][] GetColumnNames() Modified: trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs 2011-06-18 18:52:29 UTC (rev 5956) +++ trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs 2011-06-18 19:58:00 UTC (rev 5957) @@ -410,51 +410,19 @@ get { return actualReturnTypes; } } - public ParameterMetadata BuildParameterMetadata() - { - return BuildParameterMetadata(GetParameterTranslations(), queryString); - } + public ParameterMetadata BuildParameterMetadata() + { + IEnumerable<IParameterSpecification> specifications = CollectedParameterSpecifications; + IEnumerable<OrdinalParameterDescriptor> ordinals = + specifications.OfType<PositionalParameterSpecification>().Select(op => new OrdinalParameterDescriptor(op.HqlPosition, op.ExpectedType)); + Dictionary<string, NamedParameterDescriptor> nameds = specifications.OfType<NamedParameterSpecification>() + .Distinct() + .Select(np => new { np.Name, Descriptor = new NamedParameterDescriptor(np.Name, np.ExpectedType, false) }) + .ToDictionary(ep => ep.Name, ep => ep.Descriptor); + return new ParameterMetadata(ordinals, nameds); + } - private static ParameterMetadata BuildParameterMetadata(IParameterTranslations parameterTranslations, string hql) - { - long start = DateTime.Now.Ticks; - ParamLocationRecognizer recognizer = ParamLocationRecognizer.ParseLocations(hql); - long end = DateTime.Now.Ticks; - if (log.IsDebugEnabled) - { - log.Debug("HQL param location recognition took " + (end - start) + " mills (" + hql + ")"); - } - - int ordinalParamCount = parameterTranslations.OrdinalParameterCount; - int[] locations = recognizer.OrdinalParameterLocationList.ToArray(); - if (parameterTranslations.SupportsOrdinalParameterMetadata && locations.Length != ordinalParamCount) - { - throw new HibernateException("ordinal parameter mismatch"); - } - ordinalParamCount = locations.Length; - OrdinalParameterDescriptor[] ordinalParamDescriptors = new OrdinalParameterDescriptor[ordinalParamCount]; - for (int i = 1; i <= ordinalParamCount; i++) - { - ordinalParamDescriptors[i - 1] = - new OrdinalParameterDescriptor(i, - parameterTranslations.SupportsOrdinalParameterMetadata - ? parameterTranslations.GetOrdinalParameterExpectedType(i) - : null); - } - - Dictionary<string, NamedParameterDescriptor> namedParamDescriptorMap = new Dictionary<string, NamedParameterDescriptor>(); - foreach (KeyValuePair<string, ParamLocationRecognizer.NamedParameterDescription> entry in recognizer.NamedParameterDescriptionMap) - { - string name = entry.Key; - ParamLocationRecognizer.NamedParameterDescription description = entry.Value; - namedParamDescriptorMap[name] = - new NamedParameterDescriptor(name, parameterTranslations.GetNamedParameterExpectedType(name), description.JpaStyle); - - } - return new ParameterMetadata(ordinalParamDescriptors, namedParamDescriptorMap); - } - - public virtual string[][] ScalarColumnNames + public virtual string[][] ScalarColumnNames { get { return scalarColumnNames; } } Modified: trunk/nhibernate/src/NHibernate/Param/DynamicFilterParameterSpecification.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Param/DynamicFilterParameterSpecification.cs 2011-06-18 18:52:29 UTC (rev 5956) +++ trunk/nhibernate/src/NHibernate/Param/DynamicFilterParameterSpecification.cs 2011-06-18 19:58:00 UTC (rev 5957) @@ -90,7 +90,7 @@ public override bool Equals(object obj) { - return base.Equals(obj); + return Equals(obj as DynamicFilterParameterSpecification); } [Serializable] Modified: trunk/nhibernate/src/NHibernate/Param/NamedParameterSpecification.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Param/NamedParameterSpecification.cs 2011-06-18 18:52:29 UTC (rev 5956) +++ trunk/nhibernate/src/NHibernate/Param/NamedParameterSpecification.cs 2011-06-18 19:58:00 UTC (rev 5957) @@ -72,7 +72,7 @@ public override bool Equals(object obj) { - return base.Equals(obj as NamedParameterSpecification); + return Equals(obj as NamedParameterSpecification); } public bool Equals(NamedParameterSpecification other) Modified: trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs 2011-06-18 18:52:29 UTC (rev 5956) +++ trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs 2011-06-18 19:58:00 UTC (rev 5957) @@ -75,7 +75,7 @@ public override bool Equals(object obj) { - return base.Equals(obj as PositionalParameterSpecification); + return Equals(obj as PositionalParameterSpecification); } public bool Equals(PositionalParameterSpecification other) Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-18 18:52:29 UTC (rev 5956) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-06-18 19:58:00 UTC (rev 5957) @@ -883,6 +883,7 @@ <Compile Include="NHSpecificTest\SqlConverterAndMultiQuery\Fixture.cs" /> <Compile Include="NHSpecificTest\SqlConverterAndMultiQuery\Model.cs" /> <Compile Include="NHSpecificTest\SqlConverterAndMultiQuery\SqlConverter.cs" /> + <Compile Include="Parameters\NamedParameterSpecificationTest.cs" /> <Compile Include="PolymorphicGetAndLoad\Domain.cs" /> <Compile Include="PolymorphicGetAndLoad\PolymorphicGetAndLoadTest.cs" /> <Compile Include="PropertyTest\FieldCamelCaseMUnderscoreFixture.cs" /> Added: trunk/nhibernate/src/NHibernate.Test/Parameters/NamedParameterSpecificationTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Parameters/NamedParameterSpecificationTest.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/Parameters/NamedParameterSpecificationTest.cs 2011-06-18 19:58:00 UTC (rev 5957) @@ -0,0 +1,37 @@ +using NHibernate.Param; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.Test.Parameters +{ + public class NamedParameterSpecificationTest + { + [Test] + public void WhenHasSameNameThenSameHashCode() + { + var expected = (new NamedParameterSpecification(1, 0, "nhlist")).GetHashCode(); + (new NamedParameterSpecification(1, 0, "nhlist")).GetHashCode().Should().Be.EqualTo(expected); + } + + [Test] + public void WhenHasNoSameNameThenNoSameHashCode() + { + var expected = (new NamedParameterSpecification(1, 0, "nHlist")).GetHashCode(); + (new NamedParameterSpecification(1, 0, "nhlist")).GetHashCode().Should().Not.Be.EqualTo(expected); + } + + [Test] + public void WhenHasSameNameThenAreEquals() + { + var expected = (new NamedParameterSpecification(1, 0, "nhlist")); + (new NamedParameterSpecification(1, 0, "nhlist")).Should().Be.EqualTo(expected); + } + + [Test] + public void WhenHasNoSameNameThenAreNotEquals() + { + var expected = (new NamedParameterSpecification(1, 0, "nHlist")); + (new NamedParameterSpecification(1, 0, "nhlist")).Should().Not.Be.EqualTo(expected); + } + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-18 18:52:35
|
Revision: 5956 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5956&view=rev Author: fabiomaulo Date: 2011-06-18 18:52:29 +0000 (Sat, 18 Jun 2011) Log Message: ----------- Removed dead code Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/Query/OrdinalParameterDescriptor.cs trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs Modified: trunk/nhibernate/src/NHibernate/Engine/Query/OrdinalParameterDescriptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/OrdinalParameterDescriptor.cs 2011-06-18 18:44:52 UTC (rev 5955) +++ trunk/nhibernate/src/NHibernate/Engine/Query/OrdinalParameterDescriptor.cs 2011-06-18 18:52:29 UTC (rev 5956) @@ -8,13 +8,11 @@ { private readonly int ordinalPosition; private readonly IType expectedType; - private readonly int sourceLocation; - public OrdinalParameterDescriptor(int ordinalPosition, IType expectedType, int sourceLocation) + public OrdinalParameterDescriptor(int ordinalPosition, IType expectedType) { this.ordinalPosition = ordinalPosition; this.expectedType = expectedType; - this.sourceLocation = sourceLocation; } public int OrdinalPosition @@ -26,10 +24,5 @@ { get { return expectedType; } } - - public int SourceLocation - { - get { return sourceLocation; } - } } } Modified: trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2011-06-18 18:44:52 UTC (rev 5955) +++ trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2011-06-18 18:52:29 UTC (rev 5956) @@ -158,7 +158,7 @@ for (int i = 0; i < recognizer.OrdinalParameterLocationList.Count; i++) { int position = recognizer.OrdinalParameterLocationList[i]; - ordinalDescriptors[i] = new OrdinalParameterDescriptor(i, null, position); + ordinalDescriptors[i] = new OrdinalParameterDescriptor(i, null); } IDictionary<string, NamedParameterDescriptor> namedParamDescriptorMap = new Dictionary<string, NamedParameterDescriptor>(); Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs 2011-06-18 18:44:52 UTC (rev 5955) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs 2011-06-18 18:52:29 UTC (rev 5956) @@ -193,7 +193,7 @@ new OrdinalParameterDescriptor(i, parameterTranslations.SupportsOrdinalParameterMetadata ? parameterTranslations.GetOrdinalParameterExpectedType(i) - : null, parameterTranslations.GetOrdinalParameterSqlLocation(i)); + : null); } var namedDescriptorMap = new Dictionary<string, NamedParameterDescriptor>(); Modified: trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs 2011-06-18 18:44:52 UTC (rev 5955) +++ trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs 2011-06-18 18:52:29 UTC (rev 5956) @@ -439,7 +439,7 @@ new OrdinalParameterDescriptor(i, parameterTranslations.SupportsOrdinalParameterMetadata ? parameterTranslations.GetOrdinalParameterExpectedType(i) - : null, locations[i - 1]); + : null); } Dictionary<string, NamedParameterDescriptor> namedParamDescriptorMap = new Dictionary<string, NamedParameterDescriptor>(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-06-18 18:44:58
|
Revision: 5955 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5955&view=rev Author: fabiomaulo Date: 2011-06-18 18:44:52 +0000 (Sat, 18 Jun 2011) Log Message: ----------- Removed dead code Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs Modified: trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs 2011-06-18 17:42:18 UTC (rev 5954) +++ trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs 2011-06-18 18:44:52 UTC (rev 5955) @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Iesi.Collections.Generic; +using System.Linq; using NHibernate.Type; namespace NHibernate.Engine.Query @@ -9,28 +9,15 @@ [Serializable] public class ParameterMetadata { - private static readonly OrdinalParameterDescriptor[] EmptyOrdinals = new OrdinalParameterDescriptor[0]; - private readonly OrdinalParameterDescriptor[] ordinalDescriptors; private readonly Dictionary<string, NamedParameterDescriptor> namedDescriptorMap; + private readonly OrdinalParameterDescriptor[] ordinalDescriptors; - public ParameterMetadata(OrdinalParameterDescriptor[] ordinalDescriptors, - IDictionary<string, NamedParameterDescriptor> namedDescriptorMap) + public ParameterMetadata(IEnumerable<OrdinalParameterDescriptor> ordinalDescriptors, + IDictionary<string, NamedParameterDescriptor> namedDescriptorMap) { - if (ordinalDescriptors == null) - { - this.ordinalDescriptors = EmptyOrdinals; - } - else - { - OrdinalParameterDescriptor[] copy = new OrdinalParameterDescriptor[ordinalDescriptors.Length]; - Array.Copy(ordinalDescriptors, 0, copy, 0, ordinalDescriptors.Length); - this.ordinalDescriptors = copy; - } + this.ordinalDescriptors = ordinalDescriptors == null ? Enumerable.Empty<OrdinalParameterDescriptor>().ToArray() : ordinalDescriptors.ToArray(); - if (namedDescriptorMap == null) - this.namedDescriptorMap = new Dictionary<string, NamedParameterDescriptor>(); - else - this.namedDescriptorMap = new Dictionary<string, NamedParameterDescriptor>(namedDescriptorMap); + this.namedDescriptorMap = namedDescriptorMap == null ? new Dictionary<string, NamedParameterDescriptor>(1) : new Dictionary<string, NamedParameterDescriptor>(namedDescriptorMap); } public int OrdinalParameterCount @@ -57,17 +44,14 @@ return GetOrdinalParameterDescriptor(position).ExpectedType; } - public int GetOrdinalParameterSourceLocation(int position) - { - return GetOrdinalParameterDescriptor(position).SourceLocation; - } - public NamedParameterDescriptor GetNamedParameterDescriptor(string name) { NamedParameterDescriptor meta; namedDescriptorMap.TryGetValue(name, out meta); if (meta == null) + { throw new QueryParameterException("could not locate named parameter [" + name + "]"); + } return meta; } @@ -77,4 +61,4 @@ return GetNamedParameterDescriptor(name).ExpectedType; } } -} +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |