From: <fab...@us...> - 2009-10-14 20:27:15
|
Revision: 4748 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4748&view=rev Author: fabiomaulo Date: 2009-10-14 20:27:08 +0000 (Wed, 14 Oct 2009) Log Message: ----------- Merge r4747 (fix NH-1973) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Type/DateTime2Type.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Dates/DateTime2Fixture.cs Modified: trunk/nhibernate/src/NHibernate/Type/DateTime2Type.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Type/DateTime2Type.cs 2009-10-14 20:25:37 UTC (rev 4747) +++ trunk/nhibernate/src/NHibernate/Type/DateTime2Type.cs 2009-10-14 20:27:08 UTC (rev 4748) @@ -19,5 +19,37 @@ { get { return "DateTime2"; } } + + public override object Get(IDataReader rs, int index) + { + try + { + return Convert.ToDateTime(rs[index]); + } + catch (Exception ex) + { + throw new FormatException(string.Format("Input string '{0}' was not in the correct format.", rs[index]), ex); + } + } + + public override void Set(IDbCommand st, object value, int index) + { + ((IDataParameter) st.Parameters[index]).Value = (DateTime) value; + } + + public override bool IsEqual(object x, object y) + { + if (x == y) + { + return true; + } + + if (x == null || y == null) + { + return false; + } + + return x.Equals(y); + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Dates/DateTime2Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Dates/DateTime2Fixture.cs 2009-10-14 20:25:37 UTC (rev 4747) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/Dates/DateTime2Fixture.cs 2009-10-14 20:27:08 UTC (rev 4748) @@ -33,5 +33,14 @@ SavingAndRetrievingAction(new AllDates { Sql_datetime2 = DateTime.MaxValue }, entity => DateTimeAssert.AreEqual(entity.Sql_datetime2, DateTime.MaxValue)); } + + [Test] + public void SaveMillisecond() + { + DateTime datetime2 = DateTime.MinValue.AddMilliseconds(123); + + SavingAndRetrievingAction(new AllDates { Sql_datetime2 = datetime2 }, + entity => Assert.That(entity.Sql_datetime2, Is.EqualTo(datetime2))); + } } } \ 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...> - 2009-10-14 22:04:07
|
Revision: 4753 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4753&view=rev Author: fabiomaulo Date: 2009-10-14 22:03:56 +0000 (Wed, 14 Oct 2009) Log Message: ----------- Merge r4752 (fix NH-1931) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQueryNonScalarReturn.cs trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQueryScalarReturn.cs trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQuerySpecification.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQueryNonScalarReturnTest.cs trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQueryScalarReturnTest.cs trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQuerySpecificationTest.cs Modified: trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQueryNonScalarReturn.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQueryNonScalarReturn.cs 2009-10-14 22:02:56 UTC (rev 4752) +++ trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQueryNonScalarReturn.cs 2009-10-14 22:03:56 UTC (rev 4753) @@ -1,5 +1,4 @@ using System; -using System.Collections; using NHibernate.Util; using System.Collections.Generic; @@ -51,5 +50,28 @@ { get { return propertyResults; } } + + public override bool Equals(object obj) + { + return Equals(obj as NativeSQLQueryNonScalarReturn); + } + + public bool Equals(NativeSQLQueryNonScalarReturn other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return Equals(other.alias, alias); + } + + public override int GetHashCode() + { + return alias.GetHashCode(); + } } } Modified: trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQueryScalarReturn.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQueryScalarReturn.cs 2009-10-14 22:02:56 UTC (rev 4752) +++ trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQueryScalarReturn.cs 2009-10-14 22:03:56 UTC (rev 4753) @@ -28,5 +28,28 @@ { get { return type; } } + + public override bool Equals(object obj) + { + return Equals(obj as NativeSQLQueryScalarReturn); + } + + public bool Equals(NativeSQLQueryScalarReturn other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return Equals(other.columnAlias, columnAlias); + } + + public override int GetHashCode() + { + return columnAlias.GetHashCode(); + } } } Modified: trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQuerySpecification.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQuerySpecification.cs 2009-10-14 22:02:56 UTC (rev 4752) +++ trunk/nhibernate/src/NHibernate/Engine/Query/Sql/NativeSQLQuerySpecification.cs 2009-10-14 22:03:56 UTC (rev 4753) @@ -38,7 +38,7 @@ hCode = 29 * hCode + CollectionHelper.GetHashCode(this.querySpaces); if (this.sqlQueryReturns != null) { - hCode = 29 * hCode + sqlQueryReturns.Length; + hCode = 29 * hCode + CollectionHelper.GetHashCode(this.sqlQueryReturns); } } @@ -65,16 +65,13 @@ if (this == obj) return true; - NativeSQLQuerySpecification that = obj as NativeSQLQuerySpecification; + var that = obj as NativeSQLQuerySpecification; if (that == null) return false; - return hashCode == that.hashCode && - CollectionHelper.CollectionEquals(querySpaces, that.querySpaces) && - querySpaces.Equals(that.querySpaces) && - queryString.Equals(that.queryString) && - CollectionHelper.CollectionEquals<INativeSQLQueryReturn>(sqlQueryReturns, that.sqlQueryReturns); + // NHibernate different impl.: NativeSQLQuerySpecification is immutable and the hash is calculated at Ctor + return hashCode == that.hashCode; } public override int GetHashCode() Added: trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQueryNonScalarReturnTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQueryNonScalarReturnTest.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQueryNonScalarReturnTest.cs 2009-10-14 22:03:56 UTC (rev 4753) @@ -0,0 +1,57 @@ +using NHibernate.Engine.Query.Sql; +using NUnit.Framework; + +namespace NHibernate.Test.EngineTest +{ + [TestFixture] + public class NativeSQLQueryNonScalarReturnTest + { + [Test] + public void NativeSQLQueryCollectionReturnEqualsByAlias() + { + var sr1 = new NativeSQLQueryCollectionReturn("myAlias", "owner", "ownerProp", null,LockMode.None); + var sr2 = new NativeSQLQueryCollectionReturn("myAlias", "owner", "ownerProp", null, LockMode.None); + Assert.AreEqual(sr1, sr2); + } + + [Test] + public void NativeSQLQueryCollectionReturnHashCodeByAlias() + { + var sr1 = new NativeSQLQueryCollectionReturn("myAlias", "owner", "ownerProp", null,LockMode.None); + var sr2 = new NativeSQLQueryCollectionReturn("myAlias", "owner", "ownerProp", null, LockMode.None); + Assert.AreEqual(sr1.GetHashCode(), sr2.GetHashCode()); + } + + [Test] + public void NativeSQLQueryJoinReturnEqualsByAlias() + { + var sr1 = new NativeSQLQueryJoinReturn("myAlias", "owner", "ownerProp", null, LockMode.None); + var sr2 = new NativeSQLQueryJoinReturn("myAlias", "owner", "ownerProp", null, LockMode.None); + Assert.AreEqual(sr1, sr2); + } + + [Test] + public void NativeSQLQueryJoinReturnHashCodeByAlias() + { + var sr1 = new NativeSQLQueryJoinReturn("myAlias", "owner", "ownerProp", null, LockMode.None); + var sr2 = new NativeSQLQueryJoinReturn("myAlias", "owner", "ownerProp", null, LockMode.None); + Assert.AreEqual(sr1.GetHashCode(), sr2.GetHashCode()); + } + + [Test] + public void NativeSQLQueryRootReturnEqualsByAlias() + { + var sr1 = new NativeSQLQueryRootReturn("myAlias", "entity", null, LockMode.None); + var sr2 = new NativeSQLQueryRootReturn("myAlias", "entity", null, LockMode.None); + Assert.AreEqual(sr1, sr2); + } + + [Test] + public void NativeSQLQueryRootReturnHashCodeByAlias() + { + var sr1 = new NativeSQLQueryRootReturn("myAlias", "entity", null, LockMode.None); + var sr2 = new NativeSQLQueryRootReturn("myAlias", "entity", null, LockMode.None); + Assert.AreEqual(sr1.GetHashCode(), sr2.GetHashCode()); + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQueryScalarReturnTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQueryScalarReturnTest.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQueryScalarReturnTest.cs 2009-10-14 22:03:56 UTC (rev 4753) @@ -0,0 +1,25 @@ +using NHibernate.Engine.Query.Sql; +using NUnit.Framework; + +namespace NHibernate.Test.EngineTest +{ + [TestFixture] + public class NativeSQLQueryScalarReturnTest + { + [Test] + public void EqualsByAlias() + { + var sr1 = new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32); + var sr2 = new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32); + Assert.AreEqual(sr1, sr2); + } + + [Test] + public void HashCodeByAlias() + { + var sr1 = new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32); + var sr2 = new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32); + Assert.AreEqual(sr1.GetHashCode(), sr2.GetHashCode()); + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQuerySpecificationTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQuerySpecificationTest.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/EngineTest/NativeSQLQuerySpecificationTest.cs 2009-10-14 22:03:56 UTC (rev 4753) @@ -0,0 +1,59 @@ +using NHibernate.Engine.Query.Sql; +using NUnit.Framework; +using System.Collections.Generic; + +namespace NHibernate.Test.EngineTest +{ + [TestFixture] + public class NativeSQLQuerySpecificationTest + { + [Test] + public void Equality() + { + var sr1 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "SOMETHING" }); + var sr2 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "SOMETHING" }); + Assert.AreEqual(sr1, sr2); + } + + [Test] + public void HashCode() + { + var sr1 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "SOMETHING" }); + var sr2 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "SOMETHING" }); + Assert.AreEqual(sr1.GetHashCode(), sr2.GetHashCode()); + } + + [Test] + public void WhenChangeReturns_NotEqual() + { + var sr1 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "SOMETHING" }); + var sr2 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAliasChanged", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "SOMETHING" }); + Assert.AreNotEqual(sr1, sr2); + } + + [Test] + public void WhenChangeReturns_NotEqualHashCode() + { + var sr1 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "SOMETHING" }); + var sr2 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAliasChanged", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "SOMETHING" }); + Assert.AreNotEqual(sr1.GetHashCode(), sr2.GetHashCode()); + } + + [Test] + public void WhenChangeSpace_NotEqual() + { + var sr1 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "SOMETHING" }); + var sr2 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "ANOTHER" }); + Assert.AreNotEqual(sr1, sr2); + } + + [Test] + public void WhenChangeSpace_NotEqualHashCode() + { + var sr1 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "SOMETHING" }); + var sr2 = new NativeSQLQuerySpecification("SELECT * FROM SOMETHING", new INativeSQLQueryReturn[] { new NativeSQLQueryScalarReturn("myAlias", NHibernateUtil.Int32), new NativeSQLQueryScalarReturn("otherAlias", NHibernateUtil.Int32) }, new List<string> { "ANOTHER" }); + Assert.AreNotEqual(sr1.GetHashCode(), sr2.GetHashCode()); + } + + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-14 22:02:56 UTC (rev 4752) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-14 22:03:56 UTC (rev 4753) @@ -161,6 +161,9 @@ <Compile Include="Criteria\Reptile.cs" /> <Compile Include="DriverTest\SqlClientDriverFixture.cs" /> <Compile Include="DriverTest\SqlServerCeDriverFixture.cs" /> + <Compile Include="EngineTest\NativeSQLQueryNonScalarReturnTest.cs" /> + <Compile Include="EngineTest\NativeSQLQueryScalarReturnTest.cs" /> + <Compile Include="EngineTest\NativeSQLQuerySpecificationTest.cs" /> <Compile Include="ExpressionTest\RestrictionsFixture.cs" /> <Compile Include="Criteria\Student.cs" /> <Compile Include="Criteria\StudentDTO.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-15 12:53:52
|
Revision: 4755 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4755&view=rev Author: fabiomaulo Date: 2009-10-15 12:53:45 +0000 (Thu, 15 Oct 2009) Log Message: ----------- Merge r4754 (fix NH-1895) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Event/Default/DefaultDeleteEventListener.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/DomainClasses.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/SampleTest.cs Modified: trunk/nhibernate/src/NHibernate/Event/Default/DefaultDeleteEventListener.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/Default/DefaultDeleteEventListener.cs 2009-10-15 12:43:59 UTC (rev 4754) +++ trunk/nhibernate/src/NHibernate/Event/Default/DefaultDeleteEventListener.cs 2009-10-15 12:53:45 UTC (rev 4755) @@ -140,12 +140,16 @@ protected virtual void DeleteTransientEntity(IEventSource session, object entity, bool cascadeDeleteEnabled, IEntityPersister persister, ISet transientEntities) { log.Info("handling transient entity in delete processing"); - if (transientEntities.Contains(entity)) + // NH different impl : NH-1895 + if(transientEntities == null) { + transientEntities = new HashedSet(); + } + if (!transientEntities.Add(entity)) + { log.Debug("already handled transient entity; skipping"); return; } - transientEntities.Add(entity); CascadeBeforeDelete(session, persister, entity, null, transientEntities); CascadeAfterDelete(session, persister, entity, transientEntities); } Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/DomainClasses.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/DomainClasses.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/DomainClasses.cs 2009-10-15 12:53:45 UTC (rev 4755) @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH1895 +{ + public class Order + { + public Order() + { + Details = new List<Detail>(); + } + + public Guid Id { get; set; } + public string Name { get; set; } + public IList<Detail> Details { get; set; } + } + + public class Detail + { + public Guid Id { get; set; } + public string Name { get; set; } + public Order Parent { get; set; } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/Mappings.hbm.xml 2009-10-15 12:53:45 UTC (rev 4755) @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH1895" + default-lazy="false"> + <class name="Order" table="[Order]"> + <id name="Id" type="guid" column="O_Id"> + <generator class="assigned" /> + </id> + <property name="Name" type="string" column="O_Name" /> + <bag name="Details" inverse="true" cascade="delete-orphan" lazy="false" > + <key column="D_OrderId" /> + <one-to-many class="Detail" /> + </bag> + </class> + <class name="Detail" table="Detail"> + <id name="Id" type="guid" column="D_Id"> + <generator class="assigned" /> + </id> + <property name="Name" type="string" column="D_Name" /> + <many-to-one name="Parent" column="D_OrderId" not-null="true" class="Order" /> + </class> +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/SampleTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/SampleTest.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1895/SampleTest.cs 2009-10-15 12:53:45 UTC (rev 4755) @@ -0,0 +1,30 @@ +using System; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH1895 +{ + [TestFixture] + public class SampleTest : BugTestCase + { + [Test] + public void SaveTest() + { + var o = new Order {Id = Guid.NewGuid(), Name = "Test Order"}; + for (int i = 0; i < 5; i++) + { + var d = new Detail {Id = Guid.NewGuid(), Name = "Test Detail " + i, Parent = o}; + o.Details.Add(d); + } + using (ISession session = OpenSession()) + { + session.Save(o); + session.Flush(); + } + using (ISession session = OpenSession()) + { + session.Delete(o); + session.Flush(); + } + } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-15 12:43:59 UTC (rev 4754) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-15 12:53:45 UTC (rev 4755) @@ -395,6 +395,8 @@ <Compile Include="NHSpecificTest\ElementsEnums\IntEnumsBagFixture.cs" /> <Compile Include="NHSpecificTest\ElementsEnums\Something.cs" /> <Compile Include="NHSpecificTest\Futures\FutureQueryOverFixture.cs" /> + <Compile Include="NHSpecificTest\NH1895\DomainClasses.cs" /> + <Compile Include="NHSpecificTest\NH1895\SampleTest.cs" /> <Compile Include="NHSpecificTest\NH1922\Fixture.cs" /> <Compile Include="NHSpecificTest\NH1922\Model.cs" /> <Compile Include="NHSpecificTest\NH1927\Fixture.cs" /> @@ -2040,6 +2042,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\NH1895\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1985\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1990\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1959\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-15 15:55:38
|
Revision: 4756 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4756&view=rev Author: fabiomaulo Date: 2009-10-15 15:55:27 +0000 (Thu, 15 Oct 2009) Log Message: ----------- Fix NH-1963 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/TypedValue.cs trunk/nhibernate/src/NHibernate.Test/EngineTest/TypedValueFixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1963/CacheableQueryOnByteArray.cs Modified: trunk/nhibernate/src/NHibernate/Engine/TypedValue.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/TypedValue.cs 2009-10-15 12:53:45 UTC (rev 4755) +++ trunk/nhibernate/src/NHibernate/Engine/TypedValue.cs 2009-10-15 15:55:27 UTC (rev 4756) @@ -22,7 +22,7 @@ this.type = type; this.value = value; ICollection values = value as ICollection; - if (!type.IsCollectionType && values != null) + if (!type.IsCollectionType && values != null && !type.ReturnedClass.IsArray) comparer = new ParameterListComparer(entityMode); else comparer = new DefaultComparer(entityMode); @@ -38,6 +38,11 @@ get { return type; } } + public IEqualityComparer<TypedValue> Comparer + { + get { return comparer; } + } + public override int GetHashCode() { return comparer.GetHashCode(this); @@ -54,7 +59,7 @@ } [Serializable] - private class ParameterListComparer : IEqualityComparer<TypedValue> + public class ParameterListComparer : IEqualityComparer<TypedValue> { private readonly EntityMode entityMode; @@ -118,7 +123,7 @@ } [Serializable] - private class DefaultComparer : IEqualityComparer<TypedValue> + public class DefaultComparer : IEqualityComparer<TypedValue> { private readonly EntityMode entityMode; Modified: trunk/nhibernate/src/NHibernate.Test/EngineTest/TypedValueFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/EngineTest/TypedValueFixture.cs 2009-10-15 12:53:45 UTC (rev 4755) +++ trunk/nhibernate/src/NHibernate.Test/EngineTest/TypedValueFixture.cs 2009-10-15 15:55:27 UTC (rev 4756) @@ -27,5 +27,16 @@ { Assert.AreEqual("null", new TypedValue(NHibernateUtil.Int32, null, EntityMode.Poco).ToString()); } + + [Test] + public void WhenTheTypeIsAnArray_ChoseTheDefaultComparer() + { + byte[] value = new byte[]{1,2,3}; + + + var tv = new TypedValue(NHibernateUtil.BinaryBlob, value, EntityMode.Poco); + + Assert.That(tv.Comparer, Is.TypeOf<TypedValue.DefaultComparer>()); + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1963/CacheableQueryOnByteArray.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1963/CacheableQueryOnByteArray.cs 2009-10-15 12:53:45 UTC (rev 4755) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1963/CacheableQueryOnByteArray.cs 2009-10-15 15:55:27 UTC (rev 4756) @@ -39,7 +39,7 @@ return dialect as MsSql2000Dialect != null; } - [Test,Ignore] + [Test] public void Should_be_able_to_do_cacheable_query_on_byte_array_field() { using (ISession session = this.OpenSession()) @@ -47,7 +47,7 @@ var data = new byte[] { 1, 2, 3 }; var result = session.CreateQuery("from DomainClass d where d.ByteData = :data") - .SetParameter("data", data) + .SetBinary("data", data) .SetCacheable(true) .UniqueResult<DomainClass>(); @@ -59,7 +59,7 @@ var data = new byte[] { 1, 2, 3 }; var result = session.CreateQuery("from DomainClass d where d.ByteData = :data") - .SetParameter("data", data) + .SetBinary("data", data) .SetCacheable(true) .UniqueResult<DomainClass>(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-15 18:21:43
|
Revision: 4759 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4759&view=rev Author: fabiomaulo Date: 2009-10-15 18:21:31 +0000 (Thu, 15 Oct 2009) Log Message: ----------- Merge r4758 (fix NH-1979) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs 2009-10-15 18:19:47 UTC (rev 4758) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs 2009-10-15 18:21:31 UTC (rev 4759) @@ -397,7 +397,14 @@ public void Parameter() { - args.Add(new SqlString(SqlCommand.Parameter.Placeholder)); + if (argInd == args.Count) + { + args.Add(new SqlString(SqlCommand.Parameter.Placeholder)); + } + else + { + args[argInd] = args[argInd].Append(new SqlString(SqlCommand.Parameter.Placeholder)); + } } public void CommaBetweenParameters(string comma) Modified: trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs 2009-10-15 18:19:47 UTC (rev 4758) +++ trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs 2009-10-15 18:21:31 UTC (rev 4759) @@ -736,6 +736,23 @@ } } + [Test] + public void CastNH1979() + { + IgnoreIfNotSupported("cast"); + using (ISession s = OpenSession()) + { + Animal a1 = new Animal("abcdef", 1.3f); + s.Save(a1); + s.Flush(); + } + using (ISession s = OpenSession()) + { + string hql = "select cast(((a.BodyWeight + 50) / :divisor) as int) from Animal a"; + IList l = s.CreateQuery(hql).SetInt32("divisor", 2).List(); + Assert.AreEqual(1, l.Count); + } + } [Test] public void Current_TimeStamp() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-16 17:09:14
|
Revision: 4761 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4761&view=rev Author: fabiomaulo Date: 2009-10-16 17:09:03 +0000 (Fri, 16 Oct 2009) Log Message: ----------- Merge r4760 (fix NH-1987) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs trunk/nhibernate/src/NHibernate.Test/Stats/StatsFixture.cs Modified: trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2009-10-15 23:52:32 UTC (rev 4760) +++ trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2009-10-16 17:09:03 UTC (rev 4761) @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Data; +using System.Diagnostics; using Iesi.Collections; using Iesi.Collections.Generic; using log4net; @@ -189,6 +190,14 @@ private void GetResultsFromDatabase(IList results) { + bool statsEnabled = session.Factory.Statistics.IsStatisticsEnabled; + var stopWatch = new Stopwatch(); + if (statsEnabled) + { + stopWatch.Start(); + } + int rowCount = 0; + using ( IDbCommand command = session.Batcher.PrepareCommand(CommandType.Text, sqlString, types.ToArray())) @@ -228,6 +237,8 @@ int count; for (count = 0; count < maxRows && reader.Read(); count++) { + rowCount++; + object o = loader.GetRowFromResultSet(reader, session, queryParameters, loader.GetLockModes(queryParameters.LockModes), null, hydratedObjects[i], keys, false); @@ -262,6 +273,11 @@ } } } + if (statsEnabled) + { + stopWatch.Stop(); + session.Factory.StatisticsImplementor.QueryExecuted(string.Format("{0} queries (MultiCriteria)", loaders.Count), rowCount, stopWatch.Elapsed); + } } private void CreateCriteriaLoaders() Modified: trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2009-10-15 23:52:32 UTC (rev 4760) +++ trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2009-10-16 17:09:03 UTC (rev 4761) @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Data; +using System.Diagnostics; using System.Text.RegularExpressions; using Iesi.Collections; using log4net; @@ -474,6 +475,14 @@ protected ArrayList DoList() { + bool statsEnabled = session.Factory.Statistics.IsStatisticsEnabled; + var stopWatch = new Stopwatch(); + if (statsEnabled) + { + stopWatch.Start(); + } + int rowCount = 0; + IDbCommand command = PrepareQueriesCommand(); BindParameters(command); @@ -535,6 +544,8 @@ log.Debug("result set row: " + count); } + rowCount++; + object result = translator.Loader.GetRowFromResultSet(reader, session, @@ -590,6 +601,11 @@ translator.Loader.CreateSubselects(subselectResultKeys[i], parameter, session); } } + if (statsEnabled) + { + stopWatch.Stop(); + session.Factory.StatisticsImplementor.QueryExecuted(string.Format("{0} queries (MultiQuery)", translators.Count), rowCount, stopWatch.Elapsed); + } return results; } Modified: trunk/nhibernate/src/NHibernate.Test/Stats/StatsFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Stats/StatsFixture.cs 2009-10-15 23:52:32 UTC (rev 4760) +++ trunk/nhibernate/src/NHibernate.Test/Stats/StatsFixture.cs 2009-10-16 17:09:03 UTC (rev 4761) @@ -1,5 +1,6 @@ using System.Collections; using Iesi.Collections.Generic; +using NHibernate.Criterion; using NHibernate.Stat; using NUnit.Framework; @@ -209,5 +210,53 @@ tx.Commit(); s.Close(); } + + [Test] + public void IncrementQueryExecutionCount_WhenExplicitQueryIsExecuted() + { + using (ISession s = OpenSession()) + using (ITransaction tx = s.BeginTransaction()) + { + FillDb(s); + tx.Commit(); + } + + IStatistics stats = sessions.Statistics; + stats.Clear(); + using (ISession s = OpenSession()) + { + var r = s.CreateCriteria<Country>().List(); + } + Assert.AreEqual(1, stats.QueryExecutionCount); + + stats.Clear(); + using (ISession s = OpenSession()) + { + var r = s.CreateQuery("from Country").List(); + } + Assert.AreEqual(1, stats.QueryExecutionCount); + + stats.Clear(); + using (ISession s = OpenSession()) + { + var r = s.CreateMultiQuery().Add("from Country").Add("from Continent").List(); + } + Assert.AreEqual(1, stats.QueryExecutionCount); + + stats.Clear(); + using (ISession s = OpenSession()) + { + var r = s.CreateMultiCriteria().Add(DetachedCriteria.For<Country>()).Add(DetachedCriteria.For<Continent>()).List(); + } + Assert.AreEqual(1, stats.QueryExecutionCount); + + using (ISession s = OpenSession()) + using (ITransaction tx = s.BeginTransaction()) + { + CleanDb(s); + tx.Commit(); + } + } + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-16 20:22:09
|
Revision: 4767 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4767&view=rev Author: fabiomaulo Date: 2009-10-16 20:21:57 +0000 (Fri, 16 Oct 2009) Log Message: ----------- Merge r4766 (re-fix NH-1255) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Domain.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Mappings.hbm.xml Modified: trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd =================================================================== --- trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2009-10-16 20:18:56 UTC (rev 4766) +++ trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2009-10-16 20:21:57 UTC (rev 4767) @@ -743,6 +743,7 @@ <xs:attribute name="foreign-key" type="xs:string" /> <xs:attribute name="lazy" type="restrictedLaziness"> </xs:attribute> + <xs:attribute name="not-found" default="exception" type="notFoundMode"/> </xs:complexType> </xs:element> <xs:element name="key-property"> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Domain.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Domain.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Domain.cs 2009-10-16 20:21:57 UTC (rev 4767) @@ -0,0 +1,65 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.NH1255 +{ + public class Customer + { + public int Id { get; set; } + public string Name { get; set; } + } + + public class CustomerValue + { + public CustomerValueId Id { get; set; } + public decimal Value { get; set; } + } + + public class CustomerValueId : IEquatable<CustomerValueId> + { + private int? requestedHashCode; + public Customer Customer { get; set; } + public int CustomKey { get; set; } + + public bool Equals(CustomerValueId other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return Equals(other.Customer, Customer) && other.CustomKey == CustomKey; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + if (ReferenceEquals(this, obj)) + { + return true; + } + if (obj.GetType() != typeof (CustomerValueId)) + { + return false; + } + return Equals((CustomerValueId) obj); + } + + public override int GetHashCode() + { + if (!requestedHashCode.HasValue) + { + unchecked + { + requestedHashCode = ((Customer != null ? Customer.GetHashCode() : base.GetHashCode()) * 397) ^ CustomKey; + } + } + return requestedHashCode.Value; + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Fixture.cs 2009-10-16 20:21:57 UTC (rev 4767) @@ -0,0 +1,19 @@ +using NHibernate.Cfg; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH1255 +{ + [TestFixture] + public class Fixture + { + [Test] + public void CanLoadMappingWithNotNullIgnore() + { + var cfg = new Configuration(); + if (TestConfigurationHelper.hibernateConfigFile != null) + cfg.Configure(TestConfigurationHelper.hibernateConfigFile); + Assert.DoesNotThrow( + () => cfg.AddResource("NHibernate.Test.NHSpecificTest.NH1255.Mappings.hbm.xml", typeof (Customer).Assembly)); + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1255/Mappings.hbm.xml 2009-10-16 20:21:57 UTC (rev 4767) @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH1255" + default-lazy="false"> + + <class name="Customer"> + <id name="Id"> + <generator class="native" /> + </id> + <property name="Name" /> + </class> + + <class name="CustomerValue" > + <composite-id name="Id" class="CustomerValueId"> + <key-many-to-one class="Customer" name="Customer" not-found="ignore" /> + <key-property name="CustomKey" /> + </composite-id> + <property name="Value" /> + </class> + +</hibernate-mapping> Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-16 20:18:56 UTC (rev 4766) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-16 20:21:57 UTC (rev 4767) @@ -395,6 +395,8 @@ <Compile Include="NHSpecificTest\ElementsEnums\IntEnumsBagFixture.cs" /> <Compile Include="NHSpecificTest\ElementsEnums\Something.cs" /> <Compile Include="NHSpecificTest\Futures\FutureQueryOverFixture.cs" /> + <Compile Include="NHSpecificTest\NH1255\Domain.cs" /> + <Compile Include="NHSpecificTest\NH1255\Fixture.cs" /> <Compile Include="NHSpecificTest\NH1895\DomainClasses.cs" /> <Compile Include="NHSpecificTest\NH1895\SampleTest.cs" /> <Compile Include="NHSpecificTest\NH1922\Fixture.cs" /> @@ -2042,6 +2044,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\NH1255\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1895\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1985\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1990\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-18 13:40:02
|
Revision: 4774 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4774&view=rev Author: fabiomaulo Date: 2009-10-18 13:39:50 +0000 (Sun, 18 Oct 2009) Log Message: ----------- Merge r4773 (fix NH-1760) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/JoinHelper.cs trunk/nhibernate/src/NHibernate/Loader/AbstractEntityJoinWalker.cs trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs trunk/nhibernate/src/NHibernate/Persister/Entity/IOuterJoinLoadable.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/DomainClass.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/SampleTest.cs Modified: trunk/nhibernate/src/NHibernate/Engine/JoinHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/JoinHelper.cs 2009-10-18 13:19:08 UTC (rev 4773) +++ trunk/nhibernate/src/NHibernate/Engine/JoinHelper.cs 2009-10-18 13:39:50 UTC (rev 4774) @@ -1,4 +1,3 @@ -using System; using NHibernate.Persister.Entity; using NHibernate.Type; using NHibernate.Util; @@ -11,118 +10,150 @@ { } - /// <summary> - /// Get the aliased columns of the owning entity which are to - /// be used in the join - /// </summary> - public static string[] GetAliasedLHSColumnNames( - IAssociationType type, - string alias, - int property, - IOuterJoinLoadable lhsPersister, - IMapping mapping - ) + public static ILhsAssociationTypeSqlInfo GetLhsSqlInfo(string alias, int property, + IOuterJoinLoadable lhsPersister, IMapping mapping) { - return GetAliasedLHSColumnNames(type, alias, property, 0, lhsPersister, mapping); + return new PropertiesLhsAssociationTypeSqlInfo(alias, property, lhsPersister, mapping); } + public static ILhsAssociationTypeSqlInfo GetIdLhsSqlInfo(string alias, IOuterJoinLoadable lhsPersister, IMapping mapping) + { + return new IdPropertiesLhsAssociationTypeSqlInfo(alias, lhsPersister, mapping); + } + /// <summary> - /// Get the columns of the owning entity which are to + /// Get the columns of the associated table which are to /// be used in the join /// </summary> - public static string[] GetLHSColumnNames( - IAssociationType type, - int property, - IOuterJoinLoadable lhsPersister, - IMapping mapping - ) + public static string[] GetRHSColumnNames(IAssociationType type, ISessionFactoryImplementor factory) { - return GetLHSColumnNames(type, property, 0, lhsPersister, mapping); + string uniqueKeyPropertyName = type.RHSUniqueKeyPropertyName; + IJoinable joinable = type.GetAssociatedJoinable(factory); + if (uniqueKeyPropertyName == null) + { + return joinable.KeyColumnNames; + } + else + { + return ((IOuterJoinLoadable)joinable).GetPropertyColumnNames(uniqueKeyPropertyName); + } } + } + public interface ILhsAssociationTypeSqlInfo + { /// <summary> /// Get the aliased columns of the owning entity which are to /// be used in the join /// </summary> - public static string[] GetAliasedLHSColumnNames( - IAssociationType type, - string alias, - int property, - int begin, - IOuterJoinLoadable lhsPersister, - IMapping mapping - ) + string[] GetAliasedColumnNames(IAssociationType type, int begin); + + /// <summary> + /// Get the columns of the owning entity which are to + /// be used in the join + /// </summary> + string[] GetColumnNames(IAssociationType type, int begin); + + string GetTableName(IAssociationType type); + } + + public abstract class AbstractLhsAssociationTypeSqlInfo : ILhsAssociationTypeSqlInfo + { + protected AbstractLhsAssociationTypeSqlInfo(string @alias, IOuterJoinLoadable persister, IMapping mapping) { + Alias = alias; + Persister = persister; + Mapping = mapping; + } + + public string Alias { get; private set; } + + public IOuterJoinLoadable Persister { get; private set; } + + public IMapping Mapping { get; private set; } + + #region Implementation of ILhsAssociationTypeSqlInfo + + + public string[] GetAliasedColumnNames(IAssociationType type, int begin) + { if (type.UseLHSPrimaryKey) { - return StringHelper.Qualify(alias, lhsPersister.IdentifierColumnNames); + return StringHelper.Qualify(Alias, Persister.IdentifierColumnNames); } else { string propertyName = type.LHSPropertyName; if (propertyName == null) { - return ArrayHelper.Slice( - lhsPersister.ToColumns(alias, property), - begin, - type.GetColumnSpan(mapping) - ); + return ArrayHelper.Slice(GetAliasedColumns(), begin, type.GetColumnSpan(Mapping)); } else { - return ((IPropertyMapping) lhsPersister).ToColumns(alias, propertyName); //bad cast + return ((IPropertyMapping)Persister).ToColumns(Alias, propertyName); //bad cast } } } - /// <summary> - /// Get the columns of the owning entity which are to - /// be used in the join - /// </summary> - public static string[] GetLHSColumnNames( - IAssociationType type, - int property, - int begin, - IOuterJoinLoadable lhsPersister, - IMapping mapping - ) + public string[] GetColumnNames(IAssociationType type, int begin) { if (type.UseLHSPrimaryKey) { - //return lhsPersister.getSubclassPropertyColumnNames(property); - return lhsPersister.IdentifierColumnNames; + return Persister.IdentifierColumnNames; } else { string propertyName = type.LHSPropertyName; if (propertyName == null) { - //slice, to get the columns for this component - //property - return ArrayHelper.Slice( - lhsPersister.GetSubclassPropertyColumnNames(property), - begin, - type.GetColumnSpan(mapping) - ); + //slice, to get the columns for this component property + return ArrayHelper.Slice(GetColumns(), begin, type.GetColumnSpan(Mapping)); } else { //property-refs for associations defined on a //component are not supported, so no need to slice - return lhsPersister.GetPropertyColumnNames(propertyName); + return Persister.GetPropertyColumnNames(propertyName); } } } - public static string GetLHSTableName( - IAssociationType type, - int property, - IOuterJoinLoadable lhsPersister - ) + protected abstract string[] GetAliasedColumns(); + protected abstract string[] GetColumns(); + + public abstract string GetTableName(IAssociationType type); + + #endregion + } + + public class PropertiesLhsAssociationTypeSqlInfo : AbstractLhsAssociationTypeSqlInfo + { + private readonly int propertyIdx; + + public PropertiesLhsAssociationTypeSqlInfo(string alias, + int propertyIdx, IOuterJoinLoadable persister, IMapping mapping) + : base(alias, persister, mapping) { + this.propertyIdx = propertyIdx; + } + + #region Overrides of AbstractLhsAssociationTypeSqlInfo + + protected override string[] GetAliasedColumns() + { + return Persister.ToColumns(Alias, propertyIdx); + } + + protected override string[] GetColumns() + { + return Persister.GetSubclassPropertyColumnNames(propertyIdx); + } + + public override string GetTableName(IAssociationType type) + { if (type.UseLHSPrimaryKey) { - return lhsPersister.TableName; + return Persister.TableName; } else { @@ -132,12 +163,12 @@ //if there is no property-ref, assume the join //is to the subclass table (ie. the table of the //subclass that the association belongs to) - return lhsPersister.GetSubclassPropertyTableName(property); + return Persister.GetSubclassPropertyTableName(propertyIdx); } else { //handle a property-ref - string propertyRefTable = lhsPersister.GetPropertyTableName(propertyName); + string propertyRefTable = Persister.GetPropertyTableName(propertyName); if (propertyRefTable == null) { //it is possible that the tree-walking in OuterJoinLoader can get to @@ -147,29 +178,38 @@ //assumes that the property-ref refers to a property of the subclass //table that the association belongs to (a reasonable guess) //TODO: fix this, add: IOuterJoinLoadable.getSubclassPropertyTableName(string propertyName) - propertyRefTable = lhsPersister.GetSubclassPropertyTableName(property); + propertyRefTable = Persister.GetSubclassPropertyTableName(propertyIdx); } return propertyRefTable; } } } - /// <summary> - /// Get the columns of the associated table which are to - /// be used in the join - /// </summary> - public static string[] GetRHSColumnNames(IAssociationType type, ISessionFactoryImplementor factory) + #endregion + } + + public class IdPropertiesLhsAssociationTypeSqlInfo : AbstractLhsAssociationTypeSqlInfo + { + public IdPropertiesLhsAssociationTypeSqlInfo(string alias, IOuterJoinLoadable persister, IMapping mapping) : base(alias, persister, mapping) {} + + #region Overrides of AbstractLhsAssociationTypeSqlInfo + + protected override string[] GetAliasedColumns() { - string uniqueKeyPropertyName = type.RHSUniqueKeyPropertyName; - IJoinable joinable = type.GetAssociatedJoinable(factory); - if (uniqueKeyPropertyName == null) - { - return joinable.KeyColumnNames; - } - else - { - return ((IOuterJoinLoadable) joinable).GetPropertyColumnNames(uniqueKeyPropertyName); - } + return Persister.ToIdentifierColumns(Alias); } + + protected override string[] GetColumns() + { + return Persister.IdentifierColumnNames; + } + + public override string GetTableName(IAssociationType type) + { + return Persister.TableName; + } + + #endregion } + } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Loader/AbstractEntityJoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/AbstractEntityJoinWalker.cs 2009-10-18 13:19:08 UTC (rev 4773) +++ trunk/nhibernate/src/NHibernate/Loader/AbstractEntityJoinWalker.cs 2009-10-18 13:39:50 UTC (rev 4774) @@ -28,7 +28,7 @@ alias = rootSqlAlias; } - protected void InitAll(SqlString whereString, SqlString orderByString, LockMode lockMode) + protected virtual void InitAll(SqlString whereString, SqlString orderByString, LockMode lockMode) { WalkEntityTree(persister, Alias); IList<OuterJoinableAssociation> allAssociations = new List<OuterJoinableAssociation>(associations); @@ -99,7 +99,7 @@ public abstract string Comment { get; } - protected ILoadable Persister + protected IOuterJoinLoadable Persister { get { return persister; } } Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs 2009-10-18 13:19:08 UTC (rev 4773) +++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs 2009-10-18 13:39:50 UTC (rev 4774) @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Iesi.Collections.Generic; using log4net; @@ -57,6 +58,25 @@ userAliases = ArrayHelper.ToStringArray(userAliasList); } + protected override void InitAll(SqlString whereString, SqlString orderByString, LockMode lockMode) + { + // NH different behavior (NH-1760) + WalkCompositeComponentIdTree(); + base.InitAll(whereString, orderByString, lockMode); + } + + private void WalkCompositeComponentIdTree() + { + IType type = Persister.IdentifierType; + string propertyName = Persister.IdentifierPropertyName; + if (type != null && type.IsComponentType && !(type is EmbeddedComponentType)) + { + ILhsAssociationTypeSqlInfo associationTypeSQLInfo = JoinHelper.GetIdLhsSqlInfo(Alias, Persister, Factory); + WalkComponentTree((IAbstractComponentType) type, 0, Alias, SubPath(string.Empty, propertyName), 0, + associationTypeSQLInfo); + } + } + public IType[] ResultTypes { get { return resultTypes; } Modified: trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2009-10-18 13:19:08 UTC (rev 4773) +++ trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2009-10-18 13:39:50 UTC (rev 4774) @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using Iesi.Collections.Generic; using NHibernate.Collection; using NHibernate.Engine; @@ -218,20 +217,18 @@ } } - private void WalkEntityAssociationTree(IAssociationType associationType, IOuterJoinLoadable persister, int propertyNumber, - string alias, string path, bool nullable, int currentDepth) + private void WalkEntityAssociationTree(IAssociationType associationType, IOuterJoinLoadable persister, + int propertyNumber, string alias, string path, bool nullable, int currentDepth, + ILhsAssociationTypeSqlInfo associationTypeSQLInfo) { - string[] aliasedLhsColumns = - JoinHelper.GetAliasedLHSColumnNames(associationType, alias, propertyNumber, persister, Factory); + string[] aliasedLhsColumns = associationTypeSQLInfo.GetAliasedColumnNames(associationType, 0); + string[] lhsColumns = associationTypeSQLInfo.GetColumnNames(associationType, 0); + string lhsTable = associationTypeSQLInfo.GetTableName(associationType); - string[] lhsColumns = JoinHelper.GetLHSColumnNames(associationType, propertyNumber, persister, Factory); - string lhsTable = JoinHelper.GetLHSTableName(associationType, propertyNumber, persister); - string subpath = SubPath(path, persister.GetSubclassPropertyName(propertyNumber)); - JoinType joinType = - GetJoinType(associationType, persister.GetFetchMode(propertyNumber), subpath, lhsTable, lhsColumns, nullable, - currentDepth, persister.GetCascadeStyle(propertyNumber)); + JoinType joinType = GetJoinType(associationType, persister.GetFetchMode(propertyNumber), subpath, lhsTable, + lhsColumns, nullable, currentDepth, persister.GetCascadeStyle(propertyNumber)); AddAssociationToJoinTreeIfNecessary(associationType, aliasedLhsColumns, alias, subpath, currentDepth, joinType); } @@ -246,15 +243,16 @@ for (int i = 0; i < n; i++) { IType type = persister.GetSubclassPropertyType(i); + ILhsAssociationTypeSqlInfo associationTypeSQLInfo = JoinHelper.GetLhsSqlInfo(alias, i, persister, Factory); if (type.IsAssociationType) { - WalkEntityAssociationTree((IAssociationType)type, persister, i, alias, path, - persister.IsSubclassPropertyNullable(i), currentDepth); + WalkEntityAssociationTree((IAssociationType) type, persister, i, alias, path, + persister.IsSubclassPropertyNullable(i), currentDepth, associationTypeSQLInfo); } else if (type.IsComponentType) { - WalkComponentTree((IAbstractComponentType)type, i, 0, persister, alias, - SubPath(path, persister.GetSubclassPropertyName(i)), currentDepth); + WalkComponentTree((IAbstractComponentType) type, 0, alias, SubPath(path, persister.GetSubclassPropertyName(i)), + currentDepth, associationTypeSQLInfo); } } } @@ -262,8 +260,8 @@ /// <summary> /// For a component, add to a list of associations to be fetched by outerjoin /// </summary> - private void WalkComponentTree(IAbstractComponentType componentType, int propertyNumber, int begin, - IOuterJoinLoadable persister, string alias, string path, int currentDepth) + protected void WalkComponentTree(IAbstractComponentType componentType, int begin, string alias, string path, + int currentDepth, ILhsAssociationTypeSqlInfo associationTypeSQLInfo) { IType[] types = componentType.Subtypes; string[] propertyNames = componentType.PropertyNames; @@ -271,19 +269,18 @@ { if (types[i].IsAssociationType) { - IAssociationType associationType = (IAssociationType)types[i]; - string[] aliasedLhsColumns = - JoinHelper.GetAliasedLHSColumnNames(associationType, alias, propertyNumber, begin, persister, Factory); + var associationType = (IAssociationType) types[i]; - string[] lhsColumns = JoinHelper.GetLHSColumnNames(associationType, propertyNumber, begin, persister, Factory); - string lhsTable = JoinHelper.GetLHSTableName(associationType, propertyNumber, persister); + string[] aliasedLhsColumns = associationTypeSQLInfo.GetAliasedColumnNames(associationType, begin); + string[] lhsColumns = associationTypeSQLInfo.GetColumnNames(associationType, begin); + string lhsTable = associationTypeSQLInfo.GetTableName(associationType); string subpath = SubPath(path, propertyNames[i]); bool[] propertyNullability = componentType.PropertyNullability; - JoinType joinType = - GetJoinType(associationType, componentType.GetFetchMode(i), subpath, lhsTable, lhsColumns, - propertyNullability == null || propertyNullability[i], currentDepth, componentType.GetCascadeStyle(i)); + JoinType joinType = GetJoinType(associationType, componentType.GetFetchMode(i), subpath, lhsTable, lhsColumns, + propertyNullability == null || propertyNullability[i], currentDepth, + componentType.GetCascadeStyle(i)); AddAssociationToJoinTreeIfNecessary(associationType, aliasedLhsColumns, alias, subpath, currentDepth, joinType); } @@ -291,7 +288,7 @@ { string subpath = SubPath(path, propertyNames[i]); - WalkComponentTree((IAbstractComponentType)types[i], propertyNumber, begin, persister, alias, subpath, currentDepth); + WalkComponentTree((IAbstractComponentType) types[i], begin, alias, subpath, currentDepth, associationTypeSQLInfo); } begin += types[i].GetColumnSpan(Factory); } @@ -339,12 +336,9 @@ /// <summary> /// Extend the path by the given property name /// </summary> - private static string SubPath(string path, string property) + protected static string SubPath(string path, string property) { - if (path == null || path.Length == 0) - return property; - else - return StringHelper.Qualify(path, property); + return string.IsNullOrEmpty(path) ? property : StringHelper.Qualify(path, property); } /// <summary> Modified: trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2009-10-18 13:19:08 UTC (rev 4773) +++ trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2009-10-18 13:39:50 UTC (rev 4774) @@ -1852,6 +1852,18 @@ return result; } + public string[] ToIdentifierColumns(string name) + { + string alias = GenerateTableAlias(name, 0); + string[] cols = IdentifierColumnNames; + var result = new string[cols.Length]; + for (int j = 0; j < cols.Length; j++) + { + result[j] = StringHelper.Qualify(alias, cols[j]); + } + return result; + } + private int GetSubclassPropertyIndex(string propertyName) { return Array.IndexOf(subclassPropertyNameClosure, propertyName); Modified: trunk/nhibernate/src/NHibernate/Persister/Entity/IOuterJoinLoadable.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Persister/Entity/IOuterJoinLoadable.cs 2009-10-18 13:19:08 UTC (rev 4773) +++ trunk/nhibernate/src/NHibernate/Persister/Entity/IOuterJoinLoadable.cs 2009-10-18 13:39:50 UTC (rev 4774) @@ -108,5 +108,10 @@ /// Get the table name for the given property path /// </summary> string GetPropertyTableName(string propertyName); + + /// <summary> + /// Return the alised identifier column names + /// </summary> + string[] ToIdentifierColumns(string alias); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/DomainClass.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/DomainClass.cs 2009-10-18 13:19:08 UTC (rev 4773) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/DomainClass.cs 2009-10-18 13:39:50 UTC (rev 4774) @@ -4,22 +4,22 @@ { public class Customer { - public Int32 Id { get; set; } - public String Name { get; set; } + public virtual Int32 Id { get; set; } + public virtual String Name { get; set; } } public class TestClass { - public TestClassId Id { get; set; } - public String Value { get; set; } + public virtual TestClassId Id { get; set; } + public virtual String Value { get; set; } } public class TestClassId { - public Customer Customer { get; set; } - public Int32 SomeInt { get; set; } + public virtual Customer Customer { get; set; } + public virtual Int32 SomeInt { get; set; } - public bool Equals(TestClassId other) + public virtual bool Equals(TestClassId other) { if (ReferenceEquals(null, other)) { Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/Mappings.hbm.xml 2009-10-18 13:19:08 UTC (rev 4773) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/Mappings.hbm.xml 2009-10-18 13:39:50 UTC (rev 4774) @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" - namespace="NHibernate.Test.NHSpecificTest.NH1760" - default-lazy="false"> + namespace="NHibernate.Test.NHSpecificTest.NH1760"> <class name="Customer"> <id name="Id"> Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/SampleTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/SampleTest.cs 2009-10-18 13:19:08 UTC (rev 4773) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1760/SampleTest.cs 2009-10-18 13:39:50 UTC (rev 4774) @@ -14,7 +14,7 @@ { var customer = new Customer {Name = "Alkampfer"}; session.Save(customer); - var testClass = new TestClass {Id = new TestClassId{Customer = customer, SomeInt = 42}, Value = "TESTVALUE"}; + var testClass = new TestClass { Id = new TestClassId { Customer = customer, SomeInt = 42 }, Value = "TESTVALUE" }; session.Save(testClass); tx.Commit(); } @@ -25,13 +25,13 @@ using (ISession session = OpenSession()) using (var tx = session.BeginTransaction()) { - session.CreateQuery("from TestClass").ExecuteUpdate(); - session.CreateQuery("from Customer").ExecuteUpdate(); + session.CreateQuery("delete from TestClass").ExecuteUpdate(); + session.CreateQuery("delete from Customer").ExecuteUpdate(); tx.Commit(); } } - [Test, Ignore("Not fixed yet.")] + [Test] public void CanUseCriteria() { FillDb(); @@ -40,7 +40,7 @@ using (ISession session = OpenSession()) { IList<TestClass> retvalue = - session.CreateQuery("Select tc from TestClass tc where tc.Id.Customer.Name = :name").SetString("name", "Alkampfer") + session.CreateQuery("Select tc from TestClass tc join tc.Id.Customer cu where cu.Name = :name").SetString("name", "Alkampfer") .List<TestClass>(); hqlCount = retvalue.Count; } @@ -53,10 +53,31 @@ IList<TestClass> retvalue = c.List<TestClass>(); criteriaCount = retvalue.Count; } - Assert.That(hqlCount == criteriaCount); - Assert.That(hqlCount, Is.EqualTo(1)); + Assert.That(criteriaCount, Is.EqualTo(1)); + Assert.That(criteriaCount, Is.EqualTo(hqlCount)); Cleanup(); } + + [Test] + public void TheJoinShouldBeOptional() + { + FillDb(); + int criteriaCount; + + using (ISession session = OpenSession()) + { + using (var ls = new SqlLogSpy()) + { + ICriteria c = session.CreateCriteria(typeof(TestClass)); + IList<TestClass> retvalue = c.List<TestClass>(); + Assert.That(ls.GetWholeLog(), Text.DoesNotContain("join")); + criteriaCount = retvalue.Count; + } + } + Assert.That(criteriaCount, Is.EqualTo(1)); + + Cleanup(); + } } } \ 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...> - 2009-10-18 15:59:19
|
Revision: 4780 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4780&view=rev Author: fabiomaulo Date: 2009-10-18 15:59:11 +0000 (Sun, 18 Oct 2009) Log Message: ----------- Merge r4779 (refactoring fix NH-1936) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Event/AbstractEvent.cs trunk/nhibernate/src/NHibernate/Event/AbstractPreDatabaseOperationEvent.cs trunk/nhibernate/src/NHibernate/Event/PostDeleteEvent.cs trunk/nhibernate/src/NHibernate/Event/PostInsertEvent.cs trunk/nhibernate/src/NHibernate/Event/PostLoadEvent.cs trunk/nhibernate/src/NHibernate/Event/PostUpdateEvent.cs trunk/nhibernate/src/NHibernate/Event/PreLoadEvent.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Event/AbstractPostDatabaseOperationEvent.cs trunk/nhibernate/src/NHibernate/Event/IDatabaseEventArgs.cs trunk/nhibernate/src/NHibernate/Event/IPostDatabaseOperationEventArgs.cs trunk/nhibernate/src/NHibernate/Event/IPreDatabaseOperationEventArgs.cs Modified: trunk/nhibernate/src/NHibernate/Event/AbstractEvent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/AbstractEvent.cs 2009-10-18 15:53:31 UTC (rev 4779) +++ trunk/nhibernate/src/NHibernate/Event/AbstractEvent.cs 2009-10-18 15:59:11 UTC (rev 4780) @@ -6,7 +6,7 @@ /// Defines a base class for Session generated events. /// </summary> [Serializable] - public class AbstractEvent + public class AbstractEvent : IDatabaseEventArgs { /// <summary> /// Constructs an event from the given event session. Added: trunk/nhibernate/src/NHibernate/Event/AbstractPostDatabaseOperationEvent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/AbstractPostDatabaseOperationEvent.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Event/AbstractPostDatabaseOperationEvent.cs 2009-10-18 15:59:11 UTC (rev 4780) @@ -0,0 +1,36 @@ +using System; +using NHibernate.Persister.Entity; + +namespace NHibernate.Event +{ + /// <summary> + /// Represents an operation we performed against the database. + /// </summary> + [Serializable] + public class AbstractPostDatabaseOperationEvent : AbstractEvent, IPostDatabaseOperationEventArgs + { + /// <summary> Constructs an event containing the pertinent information. </summary> + /// <param name="source">The session from which the event originated. </param> + /// <param name="entity">The entity to be invloved in the database operation. </param> + /// <param name="id">The entity id to be invloved in the database operation. </param> + /// <param name="persister">The entity's persister. </param> + protected AbstractPostDatabaseOperationEvent(IEventSource source, object entity, object id, IEntityPersister persister) + : base(source) + { + Entity = entity; + Id = id; + Persister = persister; + } + + /// <summary> The entity involved in the database operation. </summary> + public object Entity { get; private set; } + + /// <summary> The id to be used in the database operation. </summary> + public object Id { get; private set; } + + /// <summary> + /// The persister for the <see cref="Entity"/>. + /// </summary> + public IEntityPersister Persister { get; private set; } + } +} Modified: trunk/nhibernate/src/NHibernate/Event/AbstractPreDatabaseOperationEvent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/AbstractPreDatabaseOperationEvent.cs 2009-10-18 15:53:31 UTC (rev 4779) +++ trunk/nhibernate/src/NHibernate/Event/AbstractPreDatabaseOperationEvent.cs 2009-10-18 15:59:11 UTC (rev 4780) @@ -8,7 +8,7 @@ /// Represents an operation we are about to perform against the database. /// </summary> [Serializable] - public abstract class AbstractPreDatabaseOperationEvent : AbstractEvent + public abstract class AbstractPreDatabaseOperationEvent : AbstractEvent, IPreDatabaseOperationEventArgs { /// <summary> Constructs an event containing the pertinent information. </summary> /// <param name="source">The session from which the event originated. </param> Added: trunk/nhibernate/src/NHibernate/Event/IDatabaseEventArgs.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/IDatabaseEventArgs.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Event/IDatabaseEventArgs.cs 2009-10-18 15:59:11 UTC (rev 4780) @@ -0,0 +1,11 @@ +namespace NHibernate.Event +{ + public interface IDatabaseEventArgs + { + /// <summary> + /// Returns the session event source for this event. + /// This is the underlying session from which this event was generated. + /// </summary> + IEventSource Session { get; } + } +} Added: trunk/nhibernate/src/NHibernate/Event/IPostDatabaseOperationEventArgs.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/IPostDatabaseOperationEventArgs.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Event/IPostDatabaseOperationEventArgs.cs 2009-10-18 15:59:11 UTC (rev 4780) @@ -0,0 +1,21 @@ +using NHibernate.Persister.Entity; + +namespace NHibernate.Event +{ + /// <summary> + /// Represents an operation we performed against the database. + /// </summary> + public interface IPostDatabaseOperationEventArgs : IDatabaseEventArgs + { + /// <summary> The entity involved in the database operation. </summary> + object Entity { get; } + + /// <summary> The id to be used in the database operation. </summary> + object Id { get; } + + /// <summary> + /// The persister for the <see cref="Entity"/>. + /// </summary> + IEntityPersister Persister { get; } + } +} Added: trunk/nhibernate/src/NHibernate/Event/IPreDatabaseOperationEventArgs.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/IPreDatabaseOperationEventArgs.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Event/IPreDatabaseOperationEventArgs.cs 2009-10-18 15:59:11 UTC (rev 4780) @@ -0,0 +1,18 @@ +using NHibernate.Persister.Entity; + +namespace NHibernate.Event +{ + public interface IPreDatabaseOperationEventArgs : IDatabaseEventArgs + { + /// <summary> The entity involved in the database operation. </summary> + object Entity { get; } + + /// <summary> The id to be used in the database operation. </summary> + object Id { get; } + + /// <summary> + /// The persister for the <see cref="Entity"/>. + /// </summary> + IEntityPersister Persister { get; } + } +} Modified: trunk/nhibernate/src/NHibernate/Event/PostDeleteEvent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/PostDeleteEvent.cs 2009-10-18 15:53:31 UTC (rev 4779) +++ trunk/nhibernate/src/NHibernate/Event/PostDeleteEvent.cs 2009-10-18 15:59:11 UTC (rev 4780) @@ -7,40 +7,14 @@ /// Occurs after deleting an item from the datastore /// </summary> [Serializable] - public class PostDeleteEvent : AbstractEvent + public class PostDeleteEvent : AbstractPostDatabaseOperationEvent { - private readonly object entity; - private readonly object id; - private readonly IEntityPersister persister; - private readonly object[] deletedState; - public PostDeleteEvent(object entity, object id, object[] deletedState, IEntityPersister persister, IEventSource source) - : base(source) + : base(source, entity, id, persister) { - this.entity = entity; - this.id = id; - this.persister = persister; - this.deletedState = deletedState; + DeletedState = deletedState; } - public object Entity - { - get { return entity; } - } - - public object Id - { - get { return id; } - } - - public IEntityPersister Persister - { - get { return persister; } - } - - public object[] DeletedState - { - get { return deletedState; } - } + public object[] DeletedState { get; private set; } } } Modified: trunk/nhibernate/src/NHibernate/Event/PostInsertEvent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/PostInsertEvent.cs 2009-10-18 15:53:31 UTC (rev 4779) +++ trunk/nhibernate/src/NHibernate/Event/PostInsertEvent.cs 2009-10-18 15:59:11 UTC (rev 4780) @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using NHibernate.Persister.Entity; namespace NHibernate.Event @@ -9,40 +7,14 @@ /// Occurs after inserting an item in the datastore /// </summary> [Serializable] - public class PostInsertEvent : AbstractEvent + public class PostInsertEvent : AbstractPostDatabaseOperationEvent { - private readonly object entity; - private readonly object id; - private readonly object[] state; - private readonly IEntityPersister persister; - public PostInsertEvent(object entity, object id, object[] state, IEntityPersister persister, IEventSource source) - : base(source) + : base(source, entity,id,persister) { - this.entity = entity; - this.id = id; - this.state = state; - this.persister = persister; + State = state; } - public object Entity - { - get { return entity; } - } - - public object Id - { - get { return id; } - } - - public object[] State - { - get { return state; } - } - - public IEntityPersister Persister - { - get { return persister; } - } + public object[] State { get; private set; } } } Modified: trunk/nhibernate/src/NHibernate/Event/PostLoadEvent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/PostLoadEvent.cs 2009-10-18 15:53:31 UTC (rev 4779) +++ trunk/nhibernate/src/NHibernate/Event/PostLoadEvent.cs 2009-10-18 15:59:11 UTC (rev 4780) @@ -7,7 +7,7 @@ /// Occurs after an an entity instance is fully loaded. /// </summary> [Serializable] - public class PostLoadEvent : AbstractEvent + public class PostLoadEvent : AbstractEvent, IPostDatabaseOperationEventArgs { private object entity; private object id; Modified: trunk/nhibernate/src/NHibernate/Event/PostUpdateEvent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/PostUpdateEvent.cs 2009-10-18 15:53:31 UTC (rev 4779) +++ trunk/nhibernate/src/NHibernate/Event/PostUpdateEvent.cs 2009-10-18 15:59:11 UTC (rev 4780) @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using NHibernate.Persister.Entity; namespace NHibernate.Event @@ -9,47 +7,17 @@ /// Occurs after the datastore is updated /// </summary> [Serializable] - public class PostUpdateEvent : AbstractEvent + public class PostUpdateEvent : AbstractPostDatabaseOperationEvent { - private readonly object entity; - private readonly object id; - private readonly object[] state; - private readonly object[] oldState; - private readonly IEntityPersister persister; - public PostUpdateEvent(object entity, object id, object[] state, object[] oldState, IEntityPersister persister, IEventSource source) - : base(source) + : base(source, entity, id, persister) { - this.entity = entity; - this.id = id; - this.state = state; - this.oldState = oldState; - this.persister = persister; + State = state; + OldState = oldState; } - public object Entity - { - get { return entity; } - } + public object[] State { get; private set; } - public object Id - { - get { return id; } - } - - public object[] State - { - get { return state; } - } - - public object[] OldState - { - get { return oldState; } - } - - public IEntityPersister Persister - { - get { return persister; } - } + public object[] OldState { get; private set; } } } Modified: trunk/nhibernate/src/NHibernate/Event/PreLoadEvent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Event/PreLoadEvent.cs 2009-10-18 15:53:31 UTC (rev 4779) +++ trunk/nhibernate/src/NHibernate/Event/PreLoadEvent.cs 2009-10-18 15:59:11 UTC (rev 4780) @@ -7,7 +7,7 @@ /// Called before injecting property values into a newly loaded entity instance. /// </summary> [Serializable] - public class PreLoadEvent : AbstractEvent + public class PreLoadEvent : AbstractEvent, IPreDatabaseOperationEventArgs { private object entity; private object[] state; Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-10-18 15:53:31 UTC (rev 4779) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-10-18 15:59:11 UTC (rev 4780) @@ -525,8 +525,12 @@ <Compile Include="Driver\IfxDriver.cs" /> <Compile Include="Driver\OracleLiteDataClientDriver.cs" /> <Compile Include="EntityModeEqualityComparer.cs" /> + <Compile Include="Event\AbstractPostDatabaseOperationEvent.cs" /> <Compile Include="Event\AbstractPreDatabaseOperationEvent.cs" /> + <Compile Include="Event\IDatabaseEventArgs.cs" /> <Compile Include="Event\IDestructible.cs" /> + <Compile Include="Event\IPostDatabaseOperationEventArgs.cs" /> + <Compile Include="Event\IPreDatabaseOperationEventArgs.cs" /> <Compile Include="Exceptions\AdoExceptionContextInfo.cs" /> <Compile Include="Exceptions\ReflectionBasedSqlStateExtracter.cs" /> <Compile Include="Exceptions\SqlStateExtracter.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-18 16:13:41
|
Revision: 4782 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4782&view=rev Author: fabiomaulo Date: 2009-10-18 16:13:35 +0000 (Sun, 18 Oct 2009) Log Message: ----------- Merge r4781 (fix NH-1980) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/BytecodeProviderFixture.cs Modified: trunk/nhibernate/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs 2009-10-18 16:11:42 UTC (rev 4781) +++ trunk/nhibernate/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs 2009-10-18 16:13:35 UTC (rev 4782) @@ -108,7 +108,7 @@ { throw new HibernateByteCodeException(type.FullName + " does not implement " + typeof(ICollectionTypeFactory).FullName); } - if (collectionTypeFactory != null) + if (collectionTypeFactory != null && !collectionTypeFactoryClass.Equals(type)) { throw new InvalidOperationException("CollectionTypeFactory in use, can't change it."); } Modified: trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/BytecodeProviderFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/BytecodeProviderFixture.cs 2009-10-18 16:11:42 UTC (rev 4781) +++ trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/BytecodeProviderFixture.cs 2009-10-18 16:13:35 UTC (rev 4782) @@ -123,7 +123,7 @@ var bcp = new BytecodeProviderImpl(); ctf = bcp.CollectionTypeFactory; // initialize the instance // try to set it - Assert.Throws<InvalidOperationException>(() => bcp.SetCollectionTypeFactoryClass(typeof(Type.DefaultCollectionTypeFactory))); + Assert.Throws<InvalidOperationException>(() => bcp.SetCollectionTypeFactoryClass(typeof(CustomCollectionTypeFactory))); } private class CustomCollectionTypeFactory : Type.DefaultCollectionTypeFactory @@ -153,5 +153,15 @@ cfg.AddResource("NHibernate.Test.Bytecode.Lightweight.ProductLine.hbm.xml", GetType().Assembly); Assert.That(Environment.BytecodeProvider.CollectionTypeFactory, Is.TypeOf<CustomCollectionTypeFactory>()); } + + [Test] + [Explicit("The BytecodeProvider is static and can't be different in the same application.")] + public void ShouldNotThrownAnExceptionWithTheSameTypeOfCollectionTypeFactory() + { + ICollectionTypeFactory ctf; + var bcp = new BytecodeProviderImpl(); + ctf = bcp.CollectionTypeFactory; // initialize the instance + Assert.DoesNotThrow(() => bcp.SetCollectionTypeFactoryClass(typeof (Type.DefaultCollectionTypeFactory))); + } } } \ 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...> - 2009-10-18 18:10:50
|
Revision: 4784 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4784&view=rev Author: fabiomaulo Date: 2009-10-18 18:10:42 +0000 (Sun, 18 Oct 2009) Log Message: ----------- Merge r4783 (fix NH-1785) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Domain.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Mappings.hbm.xml Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs 2009-10-18 18:08:11 UTC (rev 4783) +++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs 2009-10-18 18:10:42 UTC (rev 4784) @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using Iesi.Collections.Generic; using log4net; @@ -58,22 +57,21 @@ userAliases = ArrayHelper.ToStringArray(userAliasList); } - protected override void InitAll(SqlString whereString, SqlString orderByString, LockMode lockMode) + protected override void WalkEntityTree(IOuterJoinLoadable persister, string alias, string path, int currentDepth) { - // NH different behavior (NH-1760) - WalkCompositeComponentIdTree(); - base.InitAll(whereString, orderByString, lockMode); + // NH different behavior (NH-1476, NH-1760, NH-1785) + base.WalkEntityTree(persister, alias, path, currentDepth); + WalkCompositeComponentIdTree(persister, alias, path); } - private void WalkCompositeComponentIdTree() + private void WalkCompositeComponentIdTree(IOuterJoinLoadable persister, string alias, string path) { - IType type = Persister.IdentifierType; - string propertyName = Persister.IdentifierPropertyName; + IType type = persister.IdentifierType; + string propertyName = persister.IdentifierPropertyName; if (type != null && type.IsComponentType && !(type is EmbeddedComponentType)) { - ILhsAssociationTypeSqlInfo associationTypeSQLInfo = JoinHelper.GetIdLhsSqlInfo(Alias, Persister, Factory); - WalkComponentTree((IAbstractComponentType) type, 0, Alias, SubPath(string.Empty, propertyName), 0, - associationTypeSQLInfo); + ILhsAssociationTypeSqlInfo associationTypeSQLInfo = JoinHelper.GetIdLhsSqlInfo(alias, persister, Factory); + WalkComponentTree((IAbstractComponentType)type, 0, alias, SubPath(path, propertyName), 0, associationTypeSQLInfo); } } Modified: trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2009-10-18 18:08:11 UTC (rev 4783) +++ trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2009-10-18 18:10:42 UTC (rev 4784) @@ -237,7 +237,7 @@ /// For an entity class, add to a list of associations to be fetched /// by outerjoin /// </summary> - private void WalkEntityTree(IOuterJoinLoadable persister, string alias, string path, int currentDepth) + protected virtual void WalkEntityTree(IOuterJoinLoadable persister, string alias, string path, int currentDepth) { int n = persister.CountSubclassProperties(); for (int i = 0; i < n; i++) Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Domain.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Domain.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Domain.cs 2009-10-18 18:10:42 UTC (rev 4784) @@ -0,0 +1,59 @@ +using System; +using Iesi.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH1785 +{ + public class Entity1 + { + public virtual Guid Id { get; set; } + public virtual ISet<Entity2> Entities2 { get; set; } + } + + public class Entity2Id + { + public virtual Entity1 Entity1 { get; set; } + public virtual Entity3 Entity3 { get; set; } + + public bool Equals(Entity2Id other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return Equals(other.Entity1, Entity1) && Equals(other.Entity3, Entity3); + } + + public override bool Equals(object obj) + { + return Equals(obj as Entity2Id); + } + + public override int GetHashCode() + { + unchecked + { + return ((Entity1 != null ? Entity1.GetHashCode() : 0) * 397) ^ (Entity3 != null ? Entity3.GetHashCode() : 0); + } + } + } + + public class Entity2 + { + public virtual Entity2Id Id { get; set; } + } + + public class Entity3 + { + public virtual Guid Id { get; set; } + public virtual Entity4 Entity4 { get; set; } + } + + public class Entity4 + { + public virtual Guid Id { get; set; } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Fixture.cs 2009-10-18 18:10:42 UTC (rev 4784) @@ -0,0 +1,43 @@ +using System; +using NHibernate.Criterion; +using NHibernate.SqlCommand; +using NUnit.Framework; +using System.Text.RegularExpressions; + +namespace NHibernate.Test.NHSpecificTest.NH1785 +{ + [TestFixture] + public class Fixture : BugTestCase + { + [Test] + public void Bug() + { + using (var session = OpenSession()) + { + ICriteria criteria = session.CreateCriteria(typeof (Entity1)); + criteria.CreateAlias("Entities2", "ent2", JoinType.InnerJoin); + criteria.CreateAlias("ent2.Id.Entity3", "ent3", JoinType.InnerJoin); + criteria.CreateAlias("ent3.Entity4", "ent4", JoinType.InnerJoin); + criteria.Add(Restrictions.Eq("ent4.Id", Guid.NewGuid())); + Assert.DoesNotThrow(() => criteria.List<Entity1>()); + } + } + + [Test] + public void ShouldNotContainJoinWhereNotRequired() + { + using (var session = OpenSession()) + { + using (var ls = new SqlLogSpy()) + { + ICriteria criteria = session.CreateCriteria(typeof(Entity1)); + criteria.CreateAlias("Entities2", "ent2", JoinType.InnerJoin); + criteria.List<Entity1>(); + var sql = ls.GetWholeLog(); + var rx = new Regex(@"\bjoin\b"); + Assert.That(rx.Matches(sql).Count, Is.EqualTo(1)); + } + } + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1785/Mappings.hbm.xml 2009-10-18 18:10:42 UTC (rev 4784) @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH1785"> + + <class name="Entity1" table="Entity1"> + <id name="Id" type="Guid" column="id"> + <generator class="guid" /> + </id> + <set name="Entities2" lazy="true" inverse="true" table="Entity2"> + <key column="id"> + </key> + <one-to-many class="Entity2"/> + </set> + </class> + + <class name="Entity2" table="Entity2"> + <composite-id class="Entity2Id" name="Id"> + <key-many-to-one name="Entity1" class="Entity1" column="id1" /> + <key-many-to-one name="Entity3" class="Entity3" column="id3" /> + </composite-id> + </class> + + <class name="Entity3" table="Entity3"> + <id name="Id" type="Guid" column="id"> + <generator class="guid" /> + </id> + <many-to-one name="Entity4" class="Entity4" column="entity4_id" /> + </class> + + <class name="Entity4" table="Entity4"> + <id name="Id" type="Guid" column="id"> + <generator class="guid" /> + </id> + </class> +</hibernate-mapping> Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-18 18:08:11 UTC (rev 4783) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-18 18:10:42 UTC (rev 4784) @@ -397,6 +397,8 @@ <Compile Include="NHSpecificTest\Futures\FutureQueryOverFixture.cs" /> <Compile Include="NHSpecificTest\NH1255\Domain.cs" /> <Compile Include="NHSpecificTest\NH1255\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH1785\Domain.cs" /> + <Compile Include="NHSpecificTest\NH1785\Fixture.cs" /> <Compile Include="NHSpecificTest\NH1895\DomainClasses.cs" /> <Compile Include="NHSpecificTest\NH1895\SampleTest.cs" /> <Compile Include="NHSpecificTest\NH1922\Fixture.cs" /> @@ -2044,6 +2046,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\NH1785\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1255\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1895\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1985\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-18 19:18:09
|
Revision: 4788 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4788&view=rev Author: fabiomaulo Date: 2009-10-18 19:18:02 +0000 (Sun, 18 Oct 2009) Log Message: ----------- Fixed NH-1858 with 'Not supported exception.' Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Dialect/MsSql2000Dialect.cs trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs Modified: trunk/nhibernate/src/NHibernate/Dialect/MsSql2000Dialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/MsSql2000Dialect.cs 2009-10-18 19:16:19 UTC (rev 4787) +++ trunk/nhibernate/src/NHibernate/Dialect/MsSql2000Dialect.cs 2009-10-18 19:18:02 UTC (rev 4788) @@ -352,7 +352,7 @@ { return 6; } - return 0; + throw new NotSupportedException("The query should start with 'SELECT' or 'SELECT DISTINCT'"); } private bool NeedsLockHint(LockMode lockMode) Modified: trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs 2009-10-18 19:16:19 UTC (rev 4787) +++ trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs 2009-10-18 19:18:02 UTC (rev 4788) @@ -1,3 +1,4 @@ +using System; using NHibernate.Dialect; using NHibernate.Mapping; using NHibernate.SqlCommand; @@ -184,5 +185,12 @@ System.Console.WriteLine(ifExistsDropConstraint); Assert.AreEqual(expected, ifExistsDropConstraint); } + + [Test] + public void GetLimitStringWithSqlComments() + { + var d = new MsSql2005Dialect(); + Assert.Throws<NotSupportedException>(()=> d.GetLimitString(new SqlString(" /* criteria query */ SELECT p from lcdtm"), 0, 2)); + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-18 21:16:58
|
Revision: 4792 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4792&view=rev Author: fabiomaulo Date: 2009-10-18 21:16:47 +0000 (Sun, 18 Oct 2009) Log Message: ----------- Fix NH-1969 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1969/Fixture.cs Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2009-10-18 20:51:03 UTC (rev 4791) +++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2009-10-18 21:16:47 UTC (rev 4792) @@ -620,12 +620,12 @@ public TypedValue GetTypedValue(ICriteria subcriteria, string propertyName, object value) { // Detect discriminator values... - if (value is System.Type) + var entityClass = value as System.Type; + if (entityClass != null) { - System.Type entityClass = (System.Type)value; IQueryable q = helper.FindQueryableUsingImports(entityClass.FullName); - if (q != null) + if (q != null && q.DiscriminatorValue != null) { // NH Different implementation : We are using strongly typed parameter for SQL query (see DiscriminatorValue comment) return new TypedValue(q.DiscriminatorType, q.DiscriminatorValue, EntityMode.Poco); Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1969/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1969/Fixture.cs 2009-10-18 20:51:03 UTC (rev 4791) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1969/Fixture.cs 2009-10-18 21:16:47 UTC (rev 4792) @@ -41,7 +41,7 @@ } } - [Test, Ignore] + [Test] public void TestMappedTypeCriteria() { using (ISession s = OpenSession()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ste...@us...> - 2009-10-22 14:52:49
|
Revision: 4794 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4794&view=rev Author: steverstrong Date: 2009-10-22 14:52:39 +0000 (Thu, 22 Oct 2009) Log Message: ----------- Linq modifications to integrate with the HQL Query cache Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs trunk/nhibernate/src/NHibernate/IQueryExpression.cs trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs trunk/nhibernate/src/NHibernate/Linq/CommandData.cs trunk/nhibernate/src/NHibernate/Linq/HqlGeneratorExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs trunk/nhibernate/src/NHibernate/Linq/ProjectionEvaluator.cs trunk/nhibernate/src/NHibernate/Linq/QueryModelVisitor.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Modified: trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs 2009-10-18 21:21:57 UTC (rev 4793) +++ trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs 2009-10-22 14:52:39 UTC (rev 4794) @@ -132,11 +132,18 @@ querySpaces = new HashedSet<string>(translator.QuerySpaces); - // TODO - need to build parameterMetadata. Current function no good, since is parses the HQL. Might need to walk the AST here, - // probably inside the QueryTranslator. That's probably a better place for the parsing to be anyway; possibly worth moving for classic as well... - //parameterMetadata = BuildParameterMetadata(translator.GetParameterTranslations(), hql); - parameterMetadata = new ParameterMetadata(new OrdinalParameterDescriptor[0], new Dictionary<string, NamedParameterDescriptor>()); + var parameterTranslations = translator.GetParameterTranslations(); + var namedParamDescriptorMap = new Dictionary<string, NamedParameterDescriptor>(); + foreach (NamedParameterDescriptor entry in queryExpression.Parameters) + { + namedParamDescriptorMap[entry.Name] = + new NamedParameterDescriptor(entry.Name, parameterTranslations.GetNamedParameterExpectedType(entry.Name), + entry.SourceLocations, entry.JpaStyle); + } + + parameterMetadata = new ParameterMetadata(new OrdinalParameterDescriptor[0], namedParamDescriptorMap); + returnMetadata = new ReturnMetadata(translator.ReturnAliases, translator.ReturnTypes); } Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2009-10-18 21:21:57 UTC (rev 4793) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2009-10-22 14:52:39 UTC (rev 4794) @@ -117,6 +117,9 @@ switch (System.Type.GetTypeCode(type)) { + case TypeCode.Boolean: + _node.Text = "bool"; + break; case TypeCode.Int32: _node.Text = "integer"; break; @@ -126,6 +129,9 @@ case TypeCode.DateTime: _node.Text = "datetime"; break; + case TypeCode.String: + _node.Text = "string"; + break; default: throw new NotSupportedException(string.Format("Don't currently support idents of type {0}", type.Name)); } @@ -239,8 +245,9 @@ public class HqlParameter : HqlTreeNode { public HqlParameter(IASTFactory factory, string name) - : base(HqlSqlWalker.PARAM, name, factory) + : base(HqlSqlWalker.COLON, ":", factory) { + AddChild(new HqlIdent(factory, name)); } } Modified: trunk/nhibernate/src/NHibernate/IQueryExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/IQueryExpression.cs 2009-10-18 21:21:57 UTC (rev 4793) +++ trunk/nhibernate/src/NHibernate/IQueryExpression.cs 2009-10-22 14:52:39 UTC (rev 4794) @@ -1,4 +1,5 @@ -using NHibernate.Engine; +using System.Collections.Generic; +using NHibernate.Engine.Query; using NHibernate.Hql.Ast.ANTLR.Tree; using NHibernate.Impl; @@ -9,6 +10,7 @@ IASTNode Translate(ISessionFactory sessionFactory); string Key { get; } System.Type Type { get; } - void SetQueryParametersPriorToExecute(QueryImpl impl); + IList<NamedParameterDescriptor> Parameters { get; } + void SetQueryParametersPriorToExecute(QueryImpl impl); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs 2009-10-18 21:21:57 UTC (rev 4793) +++ trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs 2009-10-22 14:52:39 UTC (rev 4794) @@ -63,6 +63,11 @@ public override IList List() { + if (_queryExpression != null) + { + _queryExpression.SetQueryParametersPriorToExecute(this); + } + VerifyParameters(); IDictionary<string, TypedValue> namedParams = NamedParams; Before(); @@ -74,7 +79,6 @@ } else { - _queryExpression.SetQueryParametersPriorToExecute(this); return Session.List(_queryExpression, GetQueryParameters(namedParams)); } } Modified: trunk/nhibernate/src/NHibernate/Linq/CommandData.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/CommandData.cs 2009-10-18 21:21:57 UTC (rev 4793) +++ trunk/nhibernate/src/NHibernate/Linq/CommandData.cs 2009-10-22 14:52:39 UTC (rev 4794) @@ -8,28 +8,26 @@ { public class CommandData { - private readonly NamedParameter[] _namedParameters; - private readonly List<LambdaExpression> _itemTransformers; + private readonly List<LambdaExpression> _itemTransformers; private readonly List<LambdaExpression> _listTransformers; private readonly List<Action<IQuery>> _additionalCriteria; - public CommandData(HqlQuery statement, NamedParameter[] namedParameters, List<LambdaExpression> itemTransformers, List<LambdaExpression> listTransformers, List<Action<IQuery>> additionalCriteria) + public CommandData(HqlQuery statement, List<LambdaExpression> itemTransformers, List<LambdaExpression> listTransformers, List<Action<IQuery>> additionalCriteria) { _itemTransformers = itemTransformers; _listTransformers = listTransformers; Statement = statement; - _namedParameters = namedParameters; - _additionalCriteria = additionalCriteria; + _additionalCriteria = additionalCriteria; } public HqlQuery Statement { get; private set; } - public void SetParameters(IQuery query) + public void SetParameters(IQuery query, IDictionary<string, object> parameters) { - foreach (var parameter in _namedParameters) + foreach (var parameterName in query.NamedParameters) { - query.SetParameter(parameter.Name, parameter.Value); + query.SetParameter(parameterName, parameters[parameterName]); } } Modified: trunk/nhibernate/src/NHibernate/Linq/HqlGeneratorExpressionTreeVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/HqlGeneratorExpressionTreeVisitor.cs 2009-10-18 21:21:57 UTC (rev 4793) +++ trunk/nhibernate/src/NHibernate/Linq/HqlGeneratorExpressionTreeVisitor.cs 2009-10-22 14:52:39 UTC (rev 4794) @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using NHibernate.Engine.Query; using NHibernate.Hql.Ast; using Remotion.Data.Linq.Clauses.Expressions; using Remotion.Data.Linq.Clauses.ExpressionTreeVisitors; @@ -12,12 +13,14 @@ { protected readonly HqlTreeBuilder _hqlTreeBuilder; protected readonly HqlNodeStack _stack; - private readonly ParameterAggregator _parameterAggregator; + private readonly IDictionary<ConstantExpression, NamedParameter> _parameters; + private readonly IList<NamedParameterDescriptor> _requiredHqlParameters; - public HqlGeneratorExpressionTreeVisitor(ParameterAggregator parameterAggregator) + public HqlGeneratorExpressionTreeVisitor(IDictionary<ConstantExpression, NamedParameter> parameters, IList<NamedParameterDescriptor> requiredHqlParameters) { - _parameterAggregator = parameterAggregator; - _hqlTreeBuilder = new HqlTreeBuilder(); + _parameters = parameters; + _requiredHqlParameters = requiredHqlParameters; + _hqlTreeBuilder = new HqlTreeBuilder(); _stack = new HqlNodeStack(_hqlTreeBuilder); } @@ -33,7 +36,7 @@ protected override Expression VisitNhAverage(NhAverageExpression expression) { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); visitor.Visit(expression.Expression); _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Average(visitor.GetHqlTreeNodes().Single()), expression.Type)); @@ -43,7 +46,7 @@ protected override Expression VisitNhCount(NhCountExpression expression) { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); visitor.Visit(expression.Expression); _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Count(visitor.GetHqlTreeNodes().Single()), expression.Type)); @@ -53,7 +56,7 @@ protected override Expression VisitNhMin(NhMinExpression expression) { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); visitor.Visit(expression.Expression); _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Min(visitor.GetHqlTreeNodes().Single()), expression.Type)); @@ -63,7 +66,7 @@ protected override Expression VisitNhMax(NhMaxExpression expression) { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); visitor.Visit(expression.Expression); _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Max(visitor.GetHqlTreeNodes().Single()), expression.Type)); @@ -73,7 +76,7 @@ protected override Expression VisitNhSum(NhSumExpression expression) { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); visitor.Visit(expression.Expression); _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Sum(visitor.GetHqlTreeNodes().Single()), expression.Type)); @@ -83,7 +86,7 @@ protected override Expression VisitNhDistinct(NhDistinctExpression expression) { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); visitor.Visit(expression.Expression); _stack.PushLeaf(_hqlTreeBuilder.Distinct()); @@ -216,17 +219,19 @@ } } - /* - var namedParameter = _parameterAggregator.AddParameter(expression.Value); + NamedParameter namedParameter; - _expression = _hqlTreeBuilder.Parameter(namedParameter.Name); + if (_parameters.TryGetValue(expression, out namedParameter)) + { + _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Parameter(namedParameter.Name), namedParameter.Value.GetType())); + _requiredHqlParameters.Add(new NamedParameterDescriptor(namedParameter.Name, null, new []{ _requiredHqlParameters.Count + 1}, false)); + } + else + { + _stack.PushLeaf(_hqlTreeBuilder.Constant(expression.Value)); + } return expression; - */ - // TODO - get parameter support in place in the HQLQueryPlan - _stack.PushLeaf(_hqlTreeBuilder.Constant(expression.Value)); - - return expression; } protected override Expression VisitMethodCallExpression(MethodCallExpression expression) @@ -331,7 +336,7 @@ protected override Expression VisitSubQueryExpression(SubQueryExpression expression) { - CommandData query = QueryModelVisitor.GenerateHqlQuery(expression.QueryModel, _parameterAggregator); + CommandData query = QueryModelVisitor.GenerateHqlQuery(expression.QueryModel, _parameters, _requiredHqlParameters); _stack.PushLeaf(query.Statement); Modified: trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs 2009-10-18 21:21:57 UTC (rev 4793) +++ trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs 2009-10-22 14:52:39 UTC (rev 4794) @@ -1,9 +1,13 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using NHibernate.Engine.Query; using NHibernate.Hql.Ast.ANTLR.Tree; using NHibernate.Impl; using Remotion.Data.Linq; +using Remotion.Data.Linq.Parsing; +using Remotion.Data.Linq.Parsing.ExpressionTreeVisitors; using Remotion.Data.Linq.Parsing.Structure; namespace NHibernate.Linq @@ -75,15 +79,21 @@ { private readonly Expression _expression; private CommandData _commandData; + private readonly IDictionary<ConstantExpression, NamedParameter> _queryParameters; + private readonly IDictionary<string, object> _queryParameterValues; public NhLinqExpression(Expression expression) { - _expression = expression; + _expression = PartialEvaluatingExpressionTreeVisitor.EvaluateIndependentSubtrees(expression); - Key = expression.ToString(); + _queryParameters = ExpressionParameterVisitor.Visit(_expression); + _queryParameterValues = _queryParameters.Values.ToDictionary(p => p.Name, p => p.Value); - Type = expression.Type; + Key = ExpressionKeyVisitor.Visit(_expression, _queryParameters); + Type = _expression.Type; + ParameterValues = _queryParameters.Values; + // Note - re-linq handles return types via the GetOutputDataInfo method, and allows for SingleOrDefault here for the ChoiceResultOperator... ReturnType = NhLinqExpressionReturnType.Scalar; @@ -94,26 +104,57 @@ } } - public IASTNode Translate(ISessionFactory sessionFactory) + public IASTNode Translate(ISessionFactory sessionFactory) { + var requiredHqlParameters = new List<NamedParameterDescriptor>(); var queryModel = new QueryParser(new ExpressionTreeParser(MethodCallExpressionNodeTypeRegistry.CreateDefault())).GetParsedQuery(_expression); - _commandData = QueryModelVisitor.GenerateHqlQuery(queryModel); + _commandData = QueryModelVisitor.GenerateHqlQuery(queryModel, _queryParameters, requiredHqlParameters); + Parameters = requiredHqlParameters.AsReadOnly(); + return _commandData.Statement.AstNode; } public string Key { get; private set; } + public IList<NamedParameterDescriptor> Parameters { get; private set; } + + public ICollection<NamedParameter> ParameterValues { get; private set; } + public NhLinqExpressionReturnType ReturnType { get; private set; } public System.Type Type { get; private set; } public void SetQueryParametersPriorToExecute(QueryImpl impl) { - _commandData.SetParameters(impl); + _commandData.SetParameters(impl, _queryParameterValues); _commandData.SetResultTransformer(impl); _commandData.AddAdditionalCriteria(impl); } } + + public class ExpressionParameterVisitor : ExpressionTreeVisitor + { + private readonly Dictionary<ConstantExpression, NamedParameter> _parameters = new Dictionary<ConstantExpression, NamedParameter>(); + + public static IDictionary<ConstantExpression, NamedParameter> Visit(Expression expression) + { + var visitor = new ExpressionParameterVisitor(); + + visitor.VisitExpression(expression); + + return visitor._parameters; + } + + protected override Expression VisitConstantExpression(ConstantExpression expression) + { + if (!typeof(IQueryable).IsAssignableFrom(expression.Type)) + { + _parameters.Add(expression, new NamedParameter("p" + (_parameters.Count + 1), expression.Value)); + } + + return base.VisitConstantExpression(expression); + } + } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/ProjectionEvaluator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/ProjectionEvaluator.cs 2009-10-18 21:21:57 UTC (rev 4793) +++ trunk/nhibernate/src/NHibernate/Linq/ProjectionEvaluator.cs 2009-10-22 14:52:39 UTC (rev 4794) @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using NHibernate.Engine.Query; using NHibernate.Hql.Ast; using Remotion.Data.Linq.Parsing; @@ -10,18 +11,20 @@ { protected readonly HqlTreeBuilder _hqlTreeBuilder; protected readonly HqlNodeStack _stack; - private readonly ParameterAggregator _parameterAggregator; private HashSet<Expression> _hqlNodes; private readonly ParameterExpression _inputParameter; private readonly Func<Expression, bool> _predicate; - private int _iColumn; + private readonly IDictionary<ConstantExpression, NamedParameter> _parameters; + private readonly IList<NamedParameterDescriptor> _requiredHqlParameters; + private int _iColumn; - public ProjectionEvaluator(ParameterAggregator parameterAggregator, System.Type inputType, Func<Expression, bool> predicate) + public ProjectionEvaluator(System.Type inputType, Func<Expression, bool> predicate, IDictionary<ConstantExpression, NamedParameter> parameters, IList<NamedParameterDescriptor> requiredHqlParameters) { - _parameterAggregator = parameterAggregator; _inputParameter = Expression.Parameter(inputType, "input"); _predicate = predicate; - _hqlTreeBuilder = new HqlTreeBuilder(); + _parameters = parameters; + _requiredHqlParameters = requiredHqlParameters; + _hqlTreeBuilder = new HqlTreeBuilder(); _stack = new HqlNodeStack(_hqlTreeBuilder); } @@ -56,7 +59,7 @@ if (_hqlNodes.Contains(expression)) { // Pure HQL evaluation - var hqlVisitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var hqlVisitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); hqlVisitor.Visit(expression); hqlVisitor.GetHqlTreeNodes().ForEach(n =>_stack.PushLeaf(n) ); Modified: trunk/nhibernate/src/NHibernate/Linq/QueryModelVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/QueryModelVisitor.cs 2009-10-18 21:21:57 UTC (rev 4793) +++ trunk/nhibernate/src/NHibernate/Linq/QueryModelVisitor.cs 2009-10-22 14:52:39 UTC (rev 4794) @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using NHibernate.Engine.Query; using NHibernate.Hql.Ast; using Remotion.Data.Linq; using Remotion.Data.Linq.Clauses; @@ -14,7 +15,6 @@ public class QueryModelVisitor : QueryModelVisitorBase { private readonly HqlTreeBuilder _hqlTreeBuilder; - private readonly ParameterAggregator _parameterAggregator; private readonly List<Action<IQuery>> _additionalCriteria = new List<Action<IQuery>>(); private readonly List<LambdaExpression> _listTransformers = new List<LambdaExpression>(); @@ -27,20 +27,18 @@ private HqlSelect _selectClause; private ResultOperatorProcessingMode _resultOperatorProcessingMode; + private readonly IDictionary<ConstantExpression, NamedParameter> _parameters; + private readonly IList<NamedParameterDescriptor> _requiredHqlParameters; - private QueryModelVisitor(ParameterAggregator parameterAggregator) + private QueryModelVisitor(IDictionary<ConstantExpression, NamedParameter> parameters, IList<NamedParameterDescriptor> requiredHqlParameters) { + _parameters = parameters; + _requiredHqlParameters = requiredHqlParameters; _hqlTreeBuilder = new HqlTreeBuilder(); - _parameterAggregator = parameterAggregator; } - public static CommandData GenerateHqlQuery(QueryModel queryModel) + public static CommandData GenerateHqlQuery(QueryModel queryModel, IDictionary<ConstantExpression, NamedParameter> parameters, IList<NamedParameterDescriptor> requiredHqlParameters) { - return GenerateHqlQuery(queryModel, new ParameterAggregator()); - } - - public static CommandData GenerateHqlQuery(QueryModel queryModel, ParameterAggregator aggregator) - { // Merge aggregating result operators (distinct, count, sum etc) into the select clause new MergeAggregatingResultsRewriter().ReWrite(queryModel); @@ -56,7 +54,7 @@ // Flatten pointless subqueries new QueryReferenceExpressionFlattener().ReWrite(queryModel); - var visitor = new QueryModelVisitor(aggregator); + var visitor = new QueryModelVisitor(parameters, requiredHqlParameters); visitor.VisitQueryModel(queryModel); return visitor.GetHqlCommand(); } @@ -100,7 +98,6 @@ } return new CommandData(query, - _parameterAggregator.GetParameters(), _itemTransformers, _listTransformers, _additionalCriteria); @@ -144,7 +141,7 @@ public override void VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel) { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); visitor.Visit(fromClause.FromExpression); _fromClauses.Add(_hqlTreeBuilder.Range( @@ -278,7 +275,7 @@ private void ProcessGroupByOperator(GroupResultOperator resultOperator) { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); visitor.Visit(resultOperator.KeySelector); _groupByClause = _hqlTreeBuilder.GroupBy(); _groupByClause.AddChild(visitor.GetHqlTreeNodes().Single()); @@ -301,7 +298,7 @@ return; } - var visitor = new ProjectionEvaluator(_parameterAggregator, typeof(object[]), CanBeEvaluatedInHqlSelectStatement); + var visitor = new ProjectionEvaluator(typeof(object[]), CanBeEvaluatedInHqlSelectStatement, _parameters, _requiredHqlParameters); visitor.Visit(selectClause.Selector); @@ -318,7 +315,7 @@ public override void VisitWhereClause(WhereClause whereClause, QueryModel queryModel, int index) { // Visit the predicate to build the query - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); visitor.Visit(whereClause.Predicate); // There maybe a where clause in existence already, in which case we AND with it. @@ -331,7 +328,7 @@ foreach (Ordering clause in orderByClause.Orderings) { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); visitor.Visit(clause.Expression); _orderByClause.AddChild(visitor.GetHqlTreeNodes().Single()); @@ -345,13 +342,13 @@ public override void VisitJoinClause(JoinClause joinClause, QueryModel queryModel, int index) { - var fromVisitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var fromVisitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); fromVisitor.Visit(joinClause.InnerSequence); - var innerKey = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var innerKey = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); innerKey.Visit(joinClause.InnerKeySelector); - var outerKey = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var outerKey = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); outerKey.Visit(joinClause.OuterKeySelector); _whereClauses.Add(_hqlTreeBuilder.Equality(innerKey.GetHqlTreeNodes().Single(), outerKey.GetHqlTreeNodes().Single())); @@ -369,7 +366,7 @@ if (member.Expression is QuerySourceReferenceExpression) { // It's a join - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); + var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); visitor.Visit(fromClause.FromExpression); _fromClauses.Add(_hqlTreeBuilder.Join( Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-10-18 21:21:57 UTC (rev 4793) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-10-22 14:52:39 UTC (rev 4794) @@ -569,6 +569,7 @@ <Compile Include="Criterion\QueryOver.cs" /> <Compile Include="Impl\ExpressionProcessor.cs" /> <Compile Include="Impl\SessionIdLoggingContext.cs" /> + <Compile Include="Linq\ExpressionKeyVisitor.cs" /> <Compile Include="Linq\GroupByAggregateDetectionVisitor.cs" /> <Compile Include="Linq\AggregatingGroupByRewriter.cs" /> <Compile Include="Linq\AggregatingGroupJoinRewriter.cs" /> Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-18 21:21:57 UTC (rev 4793) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-22 14:52:39 UTC (rev 4794) @@ -62,6 +62,10 @@ <SpecificVersion>False</SpecificVersion> <HintPath>..\..\lib\net\3.5\nunit.framework.dll</HintPath> </Reference> + <Reference Include="Remotion.Data.Linq, Version=1.13.9.2, Culture=neutral, PublicKeyToken=cab60358ab4081ea, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\lib\net\3.5\Remotion.Data.Linq.dll</HintPath> + </Reference> <Reference Include="System" /> <Reference Include="System.configuration" /> <Reference Include="System.Core"> @@ -383,6 +387,7 @@ <Compile Include="Linq\Entities\Territory.cs" /> <Compile Include="Linq\LinqQuerySamples.cs" /> <Compile Include="Linq\LinqTestCase.cs" /> + <Compile Include="Linq\ParameterisedQueries.cs" /> <Compile Include="Linq\ReadonlyTestCase.cs" /> <Compile Include="MappingTest\NonReflectiveBinderFixture.cs" /> <Compile Include="MappingTest\Wicked.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ste...@us...> - 2009-10-22 20:27:29
|
Revision: 4796 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4796&view=rev Author: steverstrong Date: 2009-10-22 20:27:17 +0000 (Thu, 22 Oct 2009) Log Message: ----------- Updated Linq parameter handling Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs trunk/nhibernate/src/NHibernate/IQueryExpression.cs trunk/nhibernate/src/NHibernate/ISession.cs trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs trunk/nhibernate/src/NHibernate/Linq/CommandData.cs trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs Modified: trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs 2009-10-22 14:59:17 UTC (rev 4795) +++ trunk/nhibernate/src/NHibernate/Engine/Query/HQLQueryPlan.cs 2009-10-22 20:27:17 UTC (rev 4796) @@ -135,7 +135,7 @@ var parameterTranslations = translator.GetParameterTranslations(); var namedParamDescriptorMap = new Dictionary<string, NamedParameterDescriptor>(); - foreach (NamedParameterDescriptor entry in queryExpression.Parameters) + foreach (NamedParameterDescriptor entry in queryExpression.ParameterDescriptors) { namedParamDescriptorMap[entry.Name] = new NamedParameterDescriptor(entry.Name, parameterTranslations.GetNamedParameterExpectedType(entry.Name), Modified: trunk/nhibernate/src/NHibernate/IQueryExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/IQueryExpression.cs 2009-10-22 14:59:17 UTC (rev 4795) +++ trunk/nhibernate/src/NHibernate/IQueryExpression.cs 2009-10-22 20:27:17 UTC (rev 4796) @@ -10,7 +10,7 @@ IASTNode Translate(ISessionFactory sessionFactory); string Key { get; } System.Type Type { get; } - IList<NamedParameterDescriptor> Parameters { get; } - void SetQueryParametersPriorToExecute(QueryImpl impl); + IList<NamedParameterDescriptor> ParameterDescriptors { get; } + void SetQueryPropertiesPriorToExecute(IQuery impl); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/ISession.cs =================================================================== --- trunk/nhibernate/src/NHibernate/ISession.cs 2009-10-22 14:59:17 UTC (rev 4795) +++ trunk/nhibernate/src/NHibernate/ISession.cs 2009-10-22 20:27:17 UTC (rev 4796) @@ -803,7 +803,7 @@ /// <param name="queryString">A hibernate query string</param> /// <returns>The query</returns> IQuery CreateQuery(string queryString); - + /// <summary> /// Create a new instance of <c>Query</c> for the given query expression /// <param name="queryExpression"/>A hibernate query expression</param> Modified: trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs 2009-10-22 14:59:17 UTC (rev 4795) +++ trunk/nhibernate/src/NHibernate/Impl/AbstractSessionImpl.cs 2009-10-22 20:27:17 UTC (rev 4796) @@ -259,8 +259,10 @@ { CheckAndUpdateSessionStatus(); HQLQueryPlan queryPlan = GetHQLQueryPlan(queryExpression, false); - QueryImpl query = new QueryImpl(queryPlan.QueryExpression, this, - queryPlan.ParameterMetadata); + QueryImpl query = new QueryImpl(queryPlan.QueryExpression, + this, + queryPlan.ParameterMetadata + ); query.SetComment("[expression]"); return query; } Modified: trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs 2009-10-22 14:59:17 UTC (rev 4795) +++ trunk/nhibernate/src/NHibernate/Impl/QueryImpl.cs 2009-10-22 20:27:17 UTC (rev 4796) @@ -13,7 +13,7 @@ public class QueryImpl : AbstractQueryImpl { private readonly Dictionary<string, LockMode> lockModes = new Dictionary<string, LockMode>(2); - private readonly IQueryExpression _queryExpression; + private readonly IQueryExpression _queryExpression; public QueryImpl(string queryString, FlushMode flushMode, ISessionImplementor session, ParameterMetadata parameterMetadata) : base(queryString, flushMode, session, parameterMetadata) @@ -63,11 +63,6 @@ public override IList List() { - if (_queryExpression != null) - { - _queryExpression.SetQueryParametersPriorToExecute(this); - } - VerifyParameters(); IDictionary<string, TypedValue> namedParams = NamedParams; Before(); @@ -79,7 +74,8 @@ } else { - return Session.List(_queryExpression, GetQueryParameters(namedParams)); + _queryExpression.SetQueryPropertiesPriorToExecute(this); + return Session.List(_queryExpression, GetQueryParameters(namedParams)); } } finally Modified: trunk/nhibernate/src/NHibernate/Linq/CommandData.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/CommandData.cs 2009-10-22 14:59:17 UTC (rev 4795) +++ trunk/nhibernate/src/NHibernate/Linq/CommandData.cs 2009-10-22 20:27:17 UTC (rev 4796) @@ -23,14 +23,6 @@ public HqlQuery Statement { get; private set; } - public void SetParameters(IQuery query, IDictionary<string, object> parameters) - { - foreach (var parameterName in query.NamedParameters) - { - query.SetParameter(parameterName, parameters[parameterName]); - } - } - public void AddAdditionalCriteria(IQuery query) { foreach (var criteria in _additionalCriteria) Modified: trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs 2009-10-22 14:59:17 UTC (rev 4795) +++ trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs 2009-10-22 20:27:17 UTC (rev 4796) @@ -43,14 +43,18 @@ { var nhLinqExpression = new NhLinqExpression(expression); - var query = _session.CreateQuery(nhLinqExpression).List(); + var query = _session.CreateQuery(nhLinqExpression); + SetParameters(query, nhLinqExpression.ParameterValuesByName); + + var results = query.List(); + if (nhLinqExpression.ReturnType == NhLinqExpressionReturnType.Sequence) { - return query.AsQueryable(); + return results.AsQueryable(); } - return query[0]; + return results[0]; } public TResult Execute<TResult>(Expression expression) @@ -67,6 +71,14 @@ { return new NhQueryable<T>(this, expression); } + + void SetParameters(IQuery query, IDictionary<string, object> parameters) + { + foreach (var parameterName in query.NamedParameters) + { + query.SetParameter(parameterName, parameters[parameterName]); + } + } } public enum NhLinqExpressionReturnType @@ -80,14 +92,13 @@ private readonly Expression _expression; private CommandData _commandData; private readonly IDictionary<ConstantExpression, NamedParameter> _queryParameters; - private readonly IDictionary<string, object> _queryParameterValues; - public NhLinqExpression(Expression expression) + public NhLinqExpression(Expression expression) { _expression = PartialEvaluatingExpressionTreeVisitor.EvaluateIndependentSubtrees(expression); _queryParameters = ExpressionParameterVisitor.Visit(_expression); - _queryParameterValues = _queryParameters.Values.ToDictionary(p => p.Name, p => p.Value); + ParameterValuesByName = _queryParameters.Values.ToDictionary(p => p.Name, p => p.Value); Key = ExpressionKeyVisitor.Visit(_expression, _queryParameters); Type = _expression.Type; @@ -111,14 +122,14 @@ _commandData = QueryModelVisitor.GenerateHqlQuery(queryModel, _queryParameters, requiredHqlParameters); - Parameters = requiredHqlParameters.AsReadOnly(); + ParameterDescriptors = requiredHqlParameters.AsReadOnly(); return _commandData.Statement.AstNode; } public string Key { get; private set; } - public IList<NamedParameterDescriptor> Parameters { get; private set; } + public IList<NamedParameterDescriptor> ParameterDescriptors { get; private set; } public ICollection<NamedParameter> ParameterValues { get; private set; } @@ -126,9 +137,10 @@ public System.Type Type { get; private set; } - public void SetQueryParametersPriorToExecute(QueryImpl impl) + public IDictionary<string, object> ParameterValuesByName { get; private set; } + + public void SetQueryPropertiesPriorToExecute(IQuery impl) { - _commandData.SetParameters(impl, _queryParameterValues); _commandData.SetResultTransformer(impl); _commandData.AddAdditionalCriteria(impl); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ste...@us...> - 2009-10-23 12:21:37
|
Revision: 4798 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4798&view=rev Author: steverstrong Date: 2009-10-23 12:21:21 +0000 (Fri, 23 Oct 2009) Log Message: ----------- Restructured the Linq folder, it was getting messy Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Linq/NhNewExpression.cs trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs trunk/nhibernate/src/NHibernate/Linq/NhLinqExpressionReturnType.cs trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs trunk/nhibernate/src/NHibernate/Linq/ReWriters/ trunk/nhibernate/src/NHibernate/Linq/ReWriters/AggregatingGroupByRewriter.cs trunk/nhibernate/src/NHibernate/Linq/ReWriters/AggregatingGroupJoinRewriter.cs trunk/nhibernate/src/NHibernate/Linq/ReWriters/GroupBySelectClauseRewriter.cs trunk/nhibernate/src/NHibernate/Linq/ReWriters/MergeAggregatingResultsRewriter.cs trunk/nhibernate/src/NHibernate/Linq/ReWriters/NonAggregatingGroupByRewriter.cs trunk/nhibernate/src/NHibernate/Linq/ResultOperators/ trunk/nhibernate/src/NHibernate/Linq/ResultOperators/ClientSideTransformOperator.cs trunk/nhibernate/src/NHibernate/Linq/ResultOperators/NonAggregatingGroupBy.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/GroupByAggregateDetectionVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/GroupByKeySelectorVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/NhExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/NhThrowingExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/Nominator.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ProjectionEvaluator.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs Removed Paths: ------------- trunk/nhibernate/src/NHibernate/Linq/AggregatingGroupByRewriter.cs trunk/nhibernate/src/NHibernate/Linq/AggregatingGroupJoinRewriter.cs trunk/nhibernate/src/NHibernate/Linq/ClientSideTransformOperator.cs trunk/nhibernate/src/NHibernate/Linq/ExpressionKeyVisitor.cs trunk/nhibernate/src/NHibernate/Linq/GroupByAggregateDetectionVisitor.cs trunk/nhibernate/src/NHibernate/Linq/GroupByKeySelectorVisitor.cs trunk/nhibernate/src/NHibernate/Linq/GroupBySelectClauseRewriter.cs trunk/nhibernate/src/NHibernate/Linq/HqlGeneratorExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate/Linq/MergeAggregatingResultsRewriter.cs trunk/nhibernate/src/NHibernate/Linq/NhExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Nominator.cs trunk/nhibernate/src/NHibernate/Linq/NonAggregatingGroupBy.cs trunk/nhibernate/src/NHibernate/Linq/NonAggregatingGroupByRewriter.cs trunk/nhibernate/src/NHibernate/Linq/ProjectionEvaluator.cs trunk/nhibernate/src/NHibernate/Linq/QueryModelVisitor.cs Deleted: trunk/nhibernate/src/NHibernate/Linq/AggregatingGroupByRewriter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/AggregatingGroupByRewriter.cs 2009-10-22 20:30:27 UTC (rev 4797) +++ trunk/nhibernate/src/NHibernate/Linq/AggregatingGroupByRewriter.cs 2009-10-23 12:21:21 UTC (rev 4798) @@ -1,68 +0,0 @@ -using System; -using System.Linq; -using Remotion.Data.Linq; -using Remotion.Data.Linq.Clauses; -using Remotion.Data.Linq.Clauses.Expressions; -using Remotion.Data.Linq.Clauses.ResultOperators; - -namespace NHibernate.Linq -{ - public class AggregatingGroupByRewriter - { - public void ReWrite(QueryModel queryModel) - { - var subQueryExpression = queryModel.MainFromClause.FromExpression as SubQueryExpression; - - if ((subQueryExpression != null) && - (subQueryExpression.QueryModel.ResultOperators.Count() == 1) && - (subQueryExpression.QueryModel.ResultOperators[0] is GroupResultOperator) && - (IsAggregatingGroupBy(queryModel))) - { - FlattenSubQuery(subQueryExpression, queryModel.MainFromClause, queryModel); - } - } - - private static bool IsAggregatingGroupBy(QueryModel queryModel) - { - return new GroupByAggregateDetectionVisitor().Visit(queryModel.SelectClause.Selector); - } - - private void FlattenSubQuery(SubQueryExpression subQueryExpression, FromClauseBase fromClause, - QueryModel queryModel) - { - // Move the result operator up - if (queryModel.ResultOperators.Count != 0) - { - throw new NotImplementedException(); - } - - var groupBy = (GroupResultOperator) subQueryExpression.QueryModel.ResultOperators[0]; - - // Replace the outer select clause... - queryModel.SelectClause.TransformExpressions(s => GroupBySelectClauseRewriter.ReWrite(s, groupBy, subQueryExpression.QueryModel)); - - queryModel.SelectClause.TransformExpressions( - s => - new SwapQuerySourceVisitor(queryModel.MainFromClause, subQueryExpression.QueryModel.MainFromClause).Swap - (s)); - - - MainFromClause innerMainFromClause = subQueryExpression.QueryModel.MainFromClause; - CopyFromClauseData(innerMainFromClause, fromClause); - - foreach (var bodyClause in subQueryExpression.QueryModel.BodyClauses) - { - queryModel.BodyClauses.Add(bodyClause); - } - - queryModel.ResultOperators.Add(groupBy); - } - - protected void CopyFromClauseData(FromClauseBase source, FromClauseBase destination) - { - destination.FromExpression = source.FromExpression; - destination.ItemName = source.ItemName; - destination.ItemType = source.ItemType; - } - } -} \ No newline at end of file Deleted: trunk/nhibernate/src/NHibernate/Linq/AggregatingGroupJoinRewriter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/AggregatingGroupJoinRewriter.cs 2009-10-22 20:30:27 UTC (rev 4797) +++ trunk/nhibernate/src/NHibernate/Linq/AggregatingGroupJoinRewriter.cs 2009-10-23 12:21:21 UTC (rev 4798) @@ -1,321 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using Remotion.Data.Linq; -using Remotion.Data.Linq.Clauses; -using Remotion.Data.Linq.Clauses.Expressions; - -namespace NHibernate.Linq -{ - public class AggregatingGroupJoinRewriter - { - public void ReWrite(QueryModel model) - { - // We want to take queries like this: - - //var q = - // from c in db.Customers - // join o in db.Orders on c.CustomerId equals o.Customer.CustomerId into ords - // join e in db.Employees on c.Address.City equals e.Address.City into emps - // select new { c.ContactName, ords = ords.Count(), emps = emps.Count() }; - - // and turn them into this: - - //var q = - // from c in db.Customers - // select new - // { - // c.ContactName, - // ords = (from o2 in db.Orders where o2.Customer.CustomerId == c.CustomerId select o2).Count(), - // emps = (from e2 in db.Employees where e2.Address.City == c.Address.City select e2).Count() - // }; - - // so spot a group join where every use of the grouping in the selector is an aggregate - - // firstly, get the group join clauses - var groupJoin = model.BodyClauses.Where(bc => bc is GroupJoinClause).Cast<GroupJoinClause>(); - - if (groupJoin.Count() == 0) - { - // No group join here.. - return; - } - - // Now walk the tree to decide which groupings are fully aggregated (and can hence be done in hql) - var aggregateDetectorResults = IsAggregatingGroupJoin(model, groupJoin); - - if (aggregateDetectorResults.AggregatingClauses.Count > 0) - { - // Re-write the select expression - model.SelectClause.TransformExpressions(s => GroupJoinSelectClauseRewriter.ReWrite(s, aggregateDetectorResults)); - - // Remove the aggregating group joins - foreach (GroupJoinClause aggregatingGroupJoin in aggregateDetectorResults.AggregatingClauses) - { - model.BodyClauses.Remove(aggregatingGroupJoin); - } - } - } - - private static IsAggregatingResults IsAggregatingGroupJoin(QueryModel model, IEnumerable<GroupJoinClause> clause) - { - return new GroupJoinAggregateDetectionVisitor(clause).Visit(model.SelectClause.Selector); - } - } - - public class GroupJoinSelectClauseRewriter : NhExpressionTreeVisitor - { - private readonly IsAggregatingResults _results; - - public static Expression ReWrite(Expression expression, IsAggregatingResults results) - { - return new GroupJoinSelectClauseRewriter(results).VisitExpression(expression); - } - - private GroupJoinSelectClauseRewriter(IsAggregatingResults results) - { - _results = results; - } - - protected override Expression VisitSubQueryExpression(SubQueryExpression expression) - { - // If the sub queries main (and only) from clause is one of our aggregating group bys, then swap it - GroupJoinClause groupJoin = LocateGroupJoinQuerySource(expression.QueryModel); - - if (groupJoin != null) - { - Expression innerSelector = new SwapQuerySourceVisitor(groupJoin.JoinClause, expression.QueryModel.MainFromClause). - Swap(groupJoin.JoinClause.InnerKeySelector); - - expression.QueryModel.MainFromClause.FromExpression = groupJoin.JoinClause.InnerSequence; - - - // TODO - this only works if the key selectors are not composite. Needs improvement... - expression.QueryModel.BodyClauses.Add(new WhereClause(Expression.Equal(innerSelector, groupJoin.JoinClause.OuterKeySelector))); - } - - return expression; - } - - private GroupJoinClause LocateGroupJoinQuerySource(QueryModel model) - { - if (model.BodyClauses.Count > 0) - { - return null; - } - return new LocateGroupJoinQuerySource(_results).Detect(model.MainFromClause.FromExpression); - } - } - - public class SwapQuerySourceVisitor : NhExpressionTreeVisitor - { - private readonly IQuerySource _oldClause; - private readonly IQuerySource _newClause; - - public SwapQuerySourceVisitor(IQuerySource oldClause, IQuerySource newClause) - { - _oldClause = oldClause; - _newClause = newClause; - } - - public Expression Swap(Expression expression) - { - return VisitExpression(expression); - } - - protected override Expression VisitQuerySourceReferenceExpression(QuerySourceReferenceExpression expression) - { - if (expression.ReferencedQuerySource == _oldClause) - { - return new QuerySourceReferenceExpression(_newClause); - } - - // TODO - really don't like this drill down approach. Feels fragile - var mainFromClause = expression.ReferencedQuerySource as MainFromClause; - - if (mainFromClause != null) - { - mainFromClause.FromExpression = VisitExpression(mainFromClause.FromExpression); - } - - return expression; - } - - protected override Expression VisitSubQueryExpression(SubQueryExpression expression) - { - expression.QueryModel.TransformExpressions(VisitExpression); - return base.VisitSubQueryExpression(expression); - } - } - - public class LocateGroupJoinQuerySource : NhExpressionTreeVisitor - { - private readonly IsAggregatingResults _results; - private GroupJoinClause _groupJoin; - - public LocateGroupJoinQuerySource(IsAggregatingResults results) - { - _results = results; - } - - public GroupJoinClause Detect(Expression expression) - { - VisitExpression(expression); - return _groupJoin; - } - - protected override Expression VisitQuerySourceReferenceExpression(QuerySourceReferenceExpression expression) - { - if (_results.AggregatingClauses.Contains(expression.ReferencedQuerySource as GroupJoinClause)) - { - _groupJoin = expression.ReferencedQuerySource as GroupJoinClause; - } - - return base.VisitQuerySourceReferenceExpression(expression); - } - } - - public class IsAggregatingResults - { - public List<GroupJoinClause> NonAggregatingClauses { get; set; } - public List<GroupJoinClause> AggregatingClauses { get; set; } - public List<Expression> NonAggregatingExpressions { get; set; } - } - - internal class GroupJoinAggregateDetectionVisitor : NhExpressionTreeVisitor - { - private readonly HashSet<GroupJoinClause> _groupJoinClauses; - private readonly StackFlag _inAggregate = new StackFlag(); - private readonly StackFlag _parentExpressionProcessed = new StackFlag(); - - private readonly List<Expression> _nonAggregatingExpressions = new List<Expression>(); - private readonly List<GroupJoinClause> _nonAggregatingGroupJoins = new List<GroupJoinClause>(); - private readonly List<GroupJoinClause> _aggregatingGroupJoins = new List<GroupJoinClause>(); - - public GroupJoinAggregateDetectionVisitor(IEnumerable<GroupJoinClause> groupJoinClause) - { - _groupJoinClauses = new HashSet<GroupJoinClause>(groupJoinClause); - } - - public IsAggregatingResults Visit(Expression expression) - { - VisitExpression(expression); - - return new IsAggregatingResults { NonAggregatingClauses = _nonAggregatingGroupJoins, AggregatingClauses = _aggregatingGroupJoins, NonAggregatingExpressions = _nonAggregatingExpressions }; - } - - protected override Expression VisitSubQueryExpression(SubQueryExpression expression) - { - VisitExpression(expression.QueryModel.SelectClause.Selector); - return expression; - } - - protected override Expression VisitNhAverage(NhAverageExpression expression) - { - using (_inAggregate.SetFlag()) - { - return base.VisitNhAverage(expression); - } - } - - protected override Expression VisitNhCount(NhCountExpression expression) - { - using (_inAggregate.SetFlag()) - { - return base.VisitNhCount(expression); - } - } - - protected override Expression VisitNhMax(NhMaxExpression expression) - { - using (_inAggregate.SetFlag()) - { - return base.VisitNhMax(expression); - } - } - - protected override Expression VisitNhMin(NhMinExpression expression) - { - using (_inAggregate.SetFlag()) - { - return base.VisitNhMin(expression); - } - } - - protected override Expression VisitNhSum(NhSumExpression expression) - { - using (_inAggregate.SetFlag()) - { - return base.VisitNhSum(expression); - } - } - - protected override Expression VisitMemberExpression(MemberExpression expression) - { - if (_inAggregate.FlagIsFalse && _parentExpressionProcessed.FlagIsFalse) - { - _nonAggregatingExpressions.Add(expression); - } - - using (_parentExpressionProcessed.SetFlag()) - { - return base.VisitMemberExpression(expression); - } - } - - protected override Expression VisitQuerySourceReferenceExpression(QuerySourceReferenceExpression expression) - { - var fromClause = (FromClauseBase) expression.ReferencedQuerySource; - - if (fromClause.FromExpression is QuerySourceReferenceExpression) - { - var querySourceReference = (QuerySourceReferenceExpression) fromClause.FromExpression; - - if (_groupJoinClauses.Contains(querySourceReference.ReferencedQuerySource as GroupJoinClause)) - { - if (_inAggregate.FlagIsFalse) - { - _nonAggregatingGroupJoins.Add((GroupJoinClause) querySourceReference.ReferencedQuerySource); - } - else - { - _aggregatingGroupJoins.Add((GroupJoinClause) querySourceReference.ReferencedQuerySource); - } - } - } - - return base.VisitQuerySourceReferenceExpression(expression); - } - - internal class StackFlag - { - public bool FlagIsTrue { get; private set; } - - public bool FlagIsFalse { get { return !FlagIsTrue; } } - - public IDisposable SetFlag() - { - return new StackFlagDisposable(this); - } - - internal class StackFlagDisposable : IDisposable - { - private readonly StackFlag _parent; - private readonly bool _old; - - public StackFlagDisposable(StackFlag parent) - { - _parent = parent; - _old = parent.FlagIsTrue; - parent.FlagIsTrue = true; - } - - public void Dispose() - { - _parent.FlagIsTrue = _old; - } - } - } - } -} \ No newline at end of file Deleted: trunk/nhibernate/src/NHibernate/Linq/ClientSideTransformOperator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/ClientSideTransformOperator.cs 2009-10-22 20:30:27 UTC (rev 4797) +++ trunk/nhibernate/src/NHibernate/Linq/ClientSideTransformOperator.cs 2009-10-23 12:21:21 UTC (rev 4798) @@ -1,24 +0,0 @@ -using System; -using Remotion.Data.Linq.Clauses; -using Remotion.Data.Linq.Clauses.StreamedData; - -namespace NHibernate.Linq -{ - public class ClientSideTransformOperator : ResultOperatorBase - { - public override IStreamedData ExecuteInMemory(IStreamedData input) - { - throw new NotImplementedException(); - } - - public override IStreamedDataInfo GetOutputDataInfo(IStreamedDataInfo inputInfo) - { - throw new NotImplementedException(); - } - - public override ResultOperatorBase Clone(CloneContext cloneContext) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file Deleted: trunk/nhibernate/src/NHibernate/Linq/ExpressionKeyVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/ExpressionKeyVisitor.cs 2009-10-22 20:30:27 UTC (rev 4797) +++ trunk/nhibernate/src/NHibernate/Linq/ExpressionKeyVisitor.cs 2009-10-23 12:21:21 UTC (rev 4798) @@ -1,217 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq.Expressions; -using System.Text; -using Remotion.Data.Linq.Parsing; - -namespace NHibernate.Linq -{ - public class ExpressionKeyVisitor : ExpressionTreeVisitor - { - private readonly IDictionary<ConstantExpression, NamedParameter> _parameters; - readonly StringBuilder _string = new StringBuilder(); - - private ExpressionKeyVisitor(IDictionary<ConstantExpression, NamedParameter> parameters) - { - _parameters = parameters; - } - - public static string Visit(Expression expression, IDictionary<ConstantExpression, NamedParameter> parameters) - { - var visitor = new ExpressionKeyVisitor(parameters); - - visitor.VisitExpression(expression); - - return visitor.ToString(); - } - - public override string ToString() - { - return _string.ToString(); - } - - protected override Expression VisitBinaryExpression(BinaryExpression expression) - { - if (expression.Method != null) - { - _string.Append(expression.Method.DeclaringType.Name); - _string.Append("."); - _string.Append(expression.Method.Name); - } - else - { - _string.Append(expression.NodeType); - } - - _string.Append("("); - - VisitExpression(expression.Left); - _string.Append(", "); - VisitExpression(expression.Right); - - _string.Append(")"); - - return expression; - } - - protected override Expression VisitConditionalExpression(ConditionalExpression expression) - { - VisitExpression(expression.Test); - _string.Append(" ? "); - VisitExpression(expression.IfTrue); - _string.Append(" : "); - VisitExpression(expression.IfFalse); - - return expression; - } - - protected override Expression VisitConstantExpression(ConstantExpression expression) - { - NamedParameter param; - - if (_parameters.TryGetValue(expression, out param)) - { - _string.Append(param.Name); - } - else - { - _string.Append(expression.Value); - } - - return base.VisitConstantExpression(expression); - } - - protected override ElementInit VisitElementInit(ElementInit elementInit) - { - return base.VisitElementInit(elementInit); - } - - protected override ReadOnlyCollection<T> VisitExpressionList<T>(ReadOnlyCollection<T> expressions) - { - if (expressions.Count > 0) - { - VisitExpression(expressions[0]); - - for (var i = 1; i < expressions.Count; i++) - { - _string.Append(", "); - VisitExpression(expressions[i]); - } - } - - return expressions; - } - - protected override Expression VisitInvocationExpression(InvocationExpression expression) - { - return base.VisitInvocationExpression(expression); - } - - protected override Expression VisitLambdaExpression(LambdaExpression expression) - { - _string.Append('('); - VisitExpressionList(expression.Parameters); - _string.Append(") => ("); - VisitExpression(expression.Body); - _string.Append(')'); - - return expression; - } - - protected override Expression VisitListInitExpression(ListInitExpression expression) - { - return base.VisitListInitExpression(expression); - } - - protected override MemberBinding VisitMemberAssignment(MemberAssignment memberAssigment) - { - return base.VisitMemberAssignment(memberAssigment); - } - - protected override MemberBinding VisitMemberBinding(MemberBinding memberBinding) - { - return base.VisitMemberBinding(memberBinding); - } - - protected override Expression VisitMemberExpression(MemberExpression expression) - { - base.VisitMemberExpression(expression); - - _string.Append('.'); - _string.Append(expression.Member.Name); - - return expression; - } - - protected override Expression VisitMemberInitExpression(MemberInitExpression expression) - { - return base.VisitMemberInitExpression(expression); - } - - protected override MemberBinding VisitMemberListBinding(MemberListBinding listBinding) - { - return base.VisitMemberListBinding(listBinding); - } - - protected override MemberBinding VisitMemberMemberBinding(MemberMemberBinding binding) - { - return base.VisitMemberMemberBinding(binding); - } - - protected override Expression VisitMethodCallExpression(MethodCallExpression expression) - { - VisitExpression(expression.Object); - _string.Append('.'); - _string.Append(expression.Method.Name); - _string.Append('('); - VisitExpressionList(expression.Arguments); - _string.Append(')'); - - return expression; - } - - protected override Expression VisitNewArrayExpression(NewArrayExpression expression) - { - return base.VisitNewArrayExpression(expression); - } - - protected override Expression VisitNewExpression(NewExpression expression) - { - _string.Append("new "); - _string.Append(expression.Constructor.DeclaringType.Name); - _string.Append('('); - VisitExpressionList(expression.Arguments); - _string.Append(')'); - - return expression; - } - - protected override Expression VisitParameterExpression(ParameterExpression expression) - { - _string.Append(expression.Name); - - return expression; - } - - protected override Expression VisitTypeBinaryExpression(TypeBinaryExpression expression) - { - return base.VisitTypeBinaryExpression(expression); - } - - protected override Expression VisitUnaryExpression(UnaryExpression expression) - { - _string.Append(expression.NodeType); - _string.Append('('); - VisitExpression(expression.Operand); - _string.Append(')'); - - return expression; - } - - protected override Expression VisitUnknownExpression(Expression expression) - { - return base.VisitUnknownExpression(expression); - } - } -} \ No newline at end of file Deleted: trunk/nhibernate/src/NHibernate/Linq/GroupByAggregateDetectionVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/GroupByAggregateDetectionVisitor.cs 2009-10-22 20:30:27 UTC (rev 4797) +++ trunk/nhibernate/src/NHibernate/Linq/GroupByAggregateDetectionVisitor.cs 2009-10-23 12:21:21 UTC (rev 4798) @@ -1,83 +0,0 @@ -using System.Linq; -using System.Linq.Expressions; -using Remotion.Data.Linq.Clauses.Expressions; -using Remotion.Data.Linq.Clauses.ResultOperators; -using Remotion.Data.Linq.Parsing; - -namespace NHibernate.Linq -{ - // TODO: This needs strengthening. Possibly a lot in common with the GroupJoinAggregateDetectionVisitor class, which does many more checks - internal class GroupByAggregateDetectionVisitor : NhExpressionTreeVisitor - { - public bool ContainsAggregateMethods { get; private set; } - - public bool Visit(Expression expression) - { - ContainsAggregateMethods = false; - - VisitExpression(expression); - - return ContainsAggregateMethods; - } - - // TODO - this should not exist, since it should be handled either by re-linq or by the MergeAggregatingResultsRewriter - protected override Expression VisitMethodCallExpression(MethodCallExpression m) - { - if (m.Method.DeclaringType == typeof (Queryable) || - m.Method.DeclaringType == typeof (Enumerable)) - { - switch (m.Method.Name) - { - case "Count": - case "Min": - case "Max": - case "Sum": - case "Average": - ContainsAggregateMethods = true; - break; - } - } - - return m; - } - - // TODO - having a VisitNhAggregation method or something in the base class would remove this duplication... - protected override Expression VisitNhAverage(NhAverageExpression expression) - { - ContainsAggregateMethods = true; - return expression; - } - - protected override Expression VisitNhCount(NhCountExpression expression) - { - ContainsAggregateMethods = true; - return expression; - } - - protected override Expression VisitNhMax(NhMaxExpression expression) - { - ContainsAggregateMethods = true; - return expression; - } - - protected override Expression VisitNhMin(NhMinExpression expression) - { - ContainsAggregateMethods = true; - return expression; - } - - protected override Expression VisitNhSum(NhSumExpression expression) - { - ContainsAggregateMethods = true; - return expression; - } - - protected override Expression VisitSubQueryExpression(SubQueryExpression expression) - { - ContainsAggregateMethods = - new GroupByAggregateDetectionVisitor().Visit(expression.QueryModel.SelectClause.Selector); - - return expression; - } - } -} \ No newline at end of file Deleted: trunk/nhibernate/src/NHibernate/Linq/GroupByKeySelectorVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/GroupByKeySelectorVisitor.cs 2009-10-22 20:30:27 UTC (rev 4797) +++ trunk/nhibernate/src/NHibernate/Linq/GroupByKeySelectorVisitor.cs 2009-10-23 12:21:21 UTC (rev 4798) @@ -1,26 +0,0 @@ -using System.Linq.Expressions; -using Remotion.Data.Linq.Clauses.Expressions; -using Remotion.Data.Linq.Parsing; - -namespace NHibernate.Linq -{ - internal class GroupByKeySelectorVisitor : ExpressionTreeVisitor - { - private readonly ParameterExpression _parameter; - - public GroupByKeySelectorVisitor(ParameterExpression parameter) - { - _parameter = parameter; - } - - public Expression Visit(Expression expression) - { - return VisitExpression(expression); - } - - protected override Expression VisitQuerySourceReferenceExpression(QuerySourceReferenceExpression expression) - { - return _parameter; - } - } -} \ No newline at end of file Deleted: trunk/nhibernate/src/NHibernate/Linq/GroupBySelectClauseRewriter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/GroupBySelectClauseRewriter.cs 2009-10-22 20:30:27 UTC (rev 4797) +++ trunk/nhibernate/src/NHibernate/Linq/GroupBySelectClauseRewriter.cs 2009-10-23 12:21:21 UTC (rev 4798) @@ -1,202 +0,0 @@ -using System; -using System.Linq.Expressions; -using Remotion.Data.Linq; -using Remotion.Data.Linq.Clauses; -using Remotion.Data.Linq.Clauses.Expressions; -using Remotion.Data.Linq.Clauses.ResultOperators; - -namespace NHibernate.Linq -{ - internal class GroupBySelectClauseRewriter : NhExpressionTreeVisitor - { - public static Expression ReWrite(Expression expression, GroupResultOperator groupBy, QueryModel model) - { - var visitor = new GroupBySelectClauseRewriter(groupBy, model); - return visitor.VisitExpression(expression); - } - - private readonly GroupResultOperator _groupBy; - private readonly QueryModel _model; - - public GroupBySelectClauseRewriter(GroupResultOperator groupBy, QueryModel model) - { - _groupBy = groupBy; - _model = model; - } - - protected override Expression VisitQuerySourceReferenceExpression(QuerySourceReferenceExpression expression) - { - if (expression.ReferencedQuerySource == _groupBy) - { - return _groupBy.ElementSelector; - } - - return base.VisitQuerySourceReferenceExpression(expression); - } - - protected override Expression VisitMemberExpression(MemberExpression expression) - { - if (IsMemberOfModel(expression)) - { - if (expression.Member.Name == "Key") - { - return _groupBy.KeySelector; - } - else - { - Expression elementSelector = _groupBy.ElementSelector; - - if ((elementSelector is MemberExpression) || (elementSelector is QuerySourceReferenceExpression)) - { - // If ElementSelector is MemberExpression, just return - return base.VisitMemberExpression(expression); - } - else if (elementSelector is NewExpression) - { - // If ElementSelector is NewExpression, then search for member of name "get_" + originalMemberExpression.Member.Name - // TODO - this wouldn't handle nested initialisers. Should do a tree walk to find the correct member - var nex = elementSelector as NewExpression; - - int i = 0; - foreach (var member in nex.Members) - { - if (member.Name == "get_" + expression.Member.Name) - { - return nex.Arguments[i]; - } - i++; - } - - throw new NotImplementedException(); - } - else - { - throw new NotImplementedException(); - } - } - } - else - { - return base.VisitMemberExpression(expression); - } - } - - // TODO - dislike this code intensly. Should probably be a tree-walk in its own right - private bool IsMemberOfModel(MemberExpression expression) - { - var querySourceRef = expression.Expression as QuerySourceReferenceExpression; - - if (querySourceRef == null) - { - return false; - } - - var fromClause = querySourceRef.ReferencedQuerySource as FromClauseBase; - - if (fromClause == null) - { - return false; - } - - var subQuery = fromClause.FromExpression as SubQueryExpression; - - if (subQuery != null) - { - return subQuery.QueryModel == _model; - } - - var referencedQuery = fromClause.FromExpression as QuerySourceReferenceExpression; - - if (referencedQuery == null) - { - return false; - } - - var querySource = referencedQuery.ReferencedQuerySource as FromClauseBase; - - var subQuery2 = querySource.FromExpression as SubQueryExpression; - - return (subQuery2.QueryModel == _model); - } - - protected override Expression VisitSubQueryExpression(SubQueryExpression expression) - { - // TODO - is this safe? All we are extracting is the select clause from the sub-query. Assumes that everything - // else in the subquery has been removed. If there were two subqueries, one aggregating & one not, this may not be a - // valid assumption. Should probably be passed a list of aggregating subqueries that we are flattening so that we can check... - return GroupBySelectClauseRewriter.ReWrite(expression.QueryModel.SelectClause.Selector, _groupBy, _model); - } - } - - public enum NhExpressionType - { - Average = 10000, - Min, - Max, - Sum, - Count, - Distinct, - New - } - - public class NhAggregatedExpression : Expression - { - public Expression Expression { get; set; } - - public NhAggregatedExpression(Expression expression, NhExpressionType type) - : base((ExpressionType)type, expression.Type) - { - Expression = expression; - } - } - - public class NhAverageExpression : NhAggregatedExpression - { - public NhAverageExpression(Expression expression) : base(expression, NhExpressionType.Average) - { - } - } - - public class NhMinExpression : NhAggregatedExpression - { - public NhMinExpression(Expression expression) - : base(expression, NhExpressionType.Min) - { - } - } - - public class NhMaxExpression : NhAggregatedExpression - { - public NhMaxExpression(Expression expression) - : base(expression, NhExpressionType.Max) - { - } - } - - public class NhSumExpression : NhAggregatedExpression - { - public NhSumExpression(Expression expression) - : base(expression, NhExpressionType.Sum) - { - } - } - - public class NhDistinctExpression : NhAggregatedExpression - { - public NhDistinctExpression(Expression expression) - : base(expression, NhExpressionType.Distinct) - { - } - } - - public class NhCountExpression : Expression - { - public NhCountExpression(Expression expression) - : base((ExpressionType)NhExpressionType.Count, typeof(int)) - { - Expression = expression; - } - - public Expression Expression { get; private set; } - } -} Deleted: trunk/nhibernate/src/NHibernate/Linq/HqlGeneratorExpressionTreeVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/HqlGeneratorExpressionTreeVisitor.cs 2009-10-22 20:30:27 UTC (rev 4797) +++ trunk/nhibernate/src/NHibernate/Linq/HqlGeneratorExpressionTreeVisitor.cs 2009-10-23 12:21:21 UTC (rev 4798) @@ -1,361 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using NHibernate.Engine.Query; -using NHibernate.Hql.Ast; -using Remotion.Data.Linq.Clauses.Expressions; -using Remotion.Data.Linq.Clauses.ExpressionTreeVisitors; - -namespace NHibernate.Linq -{ - public class HqlGeneratorExpressionTreeVisitor : NhThrowingExpressionTreeVisitor - { - protected readonly HqlTreeBuilder _hqlTreeBuilder; - protected readonly HqlNodeStack _stack; - private readonly IDictionary<ConstantExpression, NamedParameter> _parameters; - private readonly IList<NamedParameterDescriptor> _requiredHqlParameters; - - public HqlGeneratorExpressionTreeVisitor(IDictionary<ConstantExpression, NamedParameter> parameters, IList<NamedParameterDescriptor> requiredHqlParameters) - { - _parameters = parameters; - _requiredHqlParameters = requiredHqlParameters; - _hqlTreeBuilder = new HqlTreeBuilder(); - _stack = new HqlNodeStack(_hqlTreeBuilder); - } - - public IEnumerable<HqlTreeNode> GetHqlTreeNodes() - { - return _stack.Finish(); - } - - public virtual void Visit(Expression expression) - { - VisitExpression(expression); - } - - protected override Expression VisitNhAverage(NhAverageExpression expression) - { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); - visitor.Visit(expression.Expression); - - _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Average(visitor.GetHqlTreeNodes().Single()), expression.Type)); - - return expression; - } - - protected override Expression VisitNhCount(NhCountExpression expression) - { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); - visitor.Visit(expression.Expression); - - _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Count(visitor.GetHqlTreeNodes().Single()), expression.Type)); - - return expression; - } - - protected override Expression VisitNhMin(NhMinExpression expression) - { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); - visitor.Visit(expression.Expression); - - _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Min(visitor.GetHqlTreeNodes().Single()), expression.Type)); - - return expression; - } - - protected override Expression VisitNhMax(NhMaxExpression expression) - { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); - visitor.Visit(expression.Expression); - - _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Max(visitor.GetHqlTreeNodes().Single()), expression.Type)); - - return expression; - } - - protected override Expression VisitNhSum(NhSumExpression expression) - { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); - visitor.Visit(expression.Expression); - - _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Sum(visitor.GetHqlTreeNodes().Single()), expression.Type)); - - return expression; - } - - protected override Expression VisitNhDistinct(NhDistinctExpression expression) - { - var visitor = new HqlGeneratorExpressionTreeVisitor(_parameters, _requiredHqlParameters); - visitor.Visit(expression.Expression); - - _stack.PushLeaf(_hqlTreeBuilder.Distinct()); - - foreach (var node in visitor.GetHqlTreeNodes()) - { - _stack.PushLeaf(node); - } - - return expression; - } - - protected override Expression VisitQuerySourceReferenceExpression(QuerySourceReferenceExpression expression) - { - _stack.PushLeaf(_hqlTreeBuilder.Ident(expression.ReferencedQuerySource.ItemName)); - - return expression; - } - - protected override Expression VisitBinaryExpression(BinaryExpression expression) - { - HqlTreeNode operatorNode = GetHqlOperatorNodeForBinaryOperator(expression); - - using (_stack.PushNode(operatorNode)) - { - VisitExpression(expression.Left); - - VisitExpression(expression.Right); - } - - return expression; - } - - private HqlTreeNode GetHqlOperatorNodeForBinaryOperator(BinaryExpression expression) - { - switch (expression.NodeType) - { - case ExpressionType.Equal: - return _hqlTreeBuilder.Equality(); - - case ExpressionType.NotEqual: - return _hqlTreeBuilder.Inequality(); - - case ExpressionType.And: - case ExpressionType.AndAlso: - return _hqlTreeBuilder.BooleanAnd(); - - case ExpressionType.Or: - case ExpressionType.OrElse: - return _hqlTreeBuilder.BooleanOr(); - - case ExpressionType.Add: - return _hqlTreeBuilder.Add(); - - case ExpressionType.Subtract: - return _hqlTreeBuilder.Subtract(); - - case ExpressionType.Multiply: - return _hqlTreeBuilder.Multiply(); - - case ExpressionType.Divide: - return _hqlTreeBuilder.Divide(); - - case ExpressionType.LessThan: - return _hqlTreeBuilder.LessThan(); - - case ExpressionType.LessThanOrEqual: - return _hqlTreeBuilder.LessThanOrEqual(); - - case ExpressionType.GreaterThan: - return _hqlTreeBuilder.GreaterThan(); - - case ExpressionType.GreaterThanOrEqual: - return _hqlTreeBuilder.GreaterThanOrEqual(); - } - - throw new InvalidOperationException(); - } - - protected override Expression VisitUnaryExpression(UnaryExpression expression) - { - HqlTreeNode operatorNode = GetHqlOperatorNodeforUnaryOperator(expression); - - using (_stack.PushNode(operatorNode)) - { - VisitExpression(expression.Operand); - } - - return expression; - } - - private HqlTreeNode GetHqlOperatorNodeforUnaryOperator(UnaryExpression expression) - { - switch (expression.NodeType) - { - case ExpressionType.Not: - return _hqlTreeBuilder.Not(); - } - - throw new InvalidOperationException(); - } - - protected override Expression VisitMemberExpression(MemberExpression expression) - { - using (_stack.PushNode(_hqlTreeBuilder.Dot())) - { - Expression newExpression = VisitExpression(expression.Expression); - - _stack.PushLeaf(_hqlTreeBuilder.Ident(expression.Member.Name)); - - if (newExpression != expression.Expression) - { - return Expression.MakeMemberAccess(newExpression, expression.Member); - } - } - - return expression; - } - - protected override Expression VisitConstantExpression(ConstantExpression expression) - { - if (expression.Value != null) - { - System.Type t = expression.Value.GetType(); - - if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof (NhQueryable<>)) - { - _stack.PushLeaf(_hqlTreeBuilder.Ident(t.GetGenericArguments()[0].Name)); - return expression; - } - } - - NamedParameter namedParameter; - - if (_parameters.TryGetValue(expression, out namedParameter)) - { - _stack.PushLeaf(_hqlTreeBuilder.Cast(_hqlTreeBuilder.Parameter(namedParameter.Name), namedParameter.Value.GetType())); - _requiredHqlParameters.Add(new NamedParameterDescriptor(namedParameter.Name, null, new []{ _requiredHqlParameters.Count + 1}, false)); - } - else - { - _stack.PushLeaf(_hqlTreeBuilder.Constant(expression.Value)); - } - - return expression; - } - - protected override Expression VisitMethodCallExpression(MethodCallExpression expression) - { - if (expression.Method.DeclaringType == typeof(Enumerable) || - expression.Method.DeclaringType == typeof(Queryable)) - { - switch (expression.Method.Name) - { - case "Any": - // Any has one or two arguments. Arg 1 is the source and arg 2 is the optional predicate - using (_stack.PushNode(_hqlTreeBuilder.Exists())) - { - using (_stack.PushNode(_hqlTreeBuilder.Query())) - { - using (_stack.PushNode(_hqlTreeBuilder.SelectFrom())) - { - using (_stack.PushNode(_hqlTreeBuilder.From())) - { - using (_stack.PushNode(_hqlTreeBuilder.Range())) - { - VisitExpression(expression.Arguments[0]); - - if (expression.Arguments.Count > 1) - { - var expr = (LambdaExpression) expression.Arguments[1]; - _stack.PushLeaf(_hqlTreeBuilder.Alias(expr.Parameters[0].Name)); - } - } - } - } - if (expression.Arguments.Count > 1) - { - using (_stack.PushNode(_hqlTreeBuilder.Where())) - { - VisitExpression(expression.Arguments[1]); - } - } - } - } - break; - case "Min": - using (_stack.PushNode(_hqlTreeBuilder.Min())) - { - VisitExpression(expression.Arguments[1]); - } - break; - case "Max": - using (_stack.PushNode(_hqlTreeBuilder.Max())) - { - VisitExpression(expression.Arguments[1]); - } - break; - default: - throw new NotSupportedException(string.Format("The Enumerable method {0} is not supported", expression.Method.Name)); - } - - return expression; - } - else - { - return base.VisitMethodCallExpression(expression); // throws - } - } - - protected override Expression VisitLambdaExpression(LambdaExpression expression) - { - VisitExpression(expression.Body); - - return expression; - } - - protected override Expression VisitParameterExpression(ParameterExpression expression) - { - _stack.PushLeaf(_hqlTreeBuilder.Ident(expression.Name)); - - return expression; - } - - protected override Expression VisitConditionalExpression(ConditionalExpression expression) - { - using (_stack.PushNode(_hqlTreeBuilder.Case())) - { - using (_stack.PushNode(_hqlTreeBuilder.When())) - { - VisitExpression(expression.Test); - - VisitExpression(expression.IfTrue); - } - - if (expression.IfFalse != null) - { - using (_stack.PushNode(_hqlTreeBuilder.Else())) - { - VisitExpression(expression.IfFalse); - } - } - } - - return expression; - } - - protected override Expression VisitSubQueryExpression(SubQueryExpression expression) - { - CommandData query = QueryModelVisitor.GenerateHqlQuery(expression.QueryModel, _parameters, _requiredHqlParameters); - - _stack.PushLeaf(query.Statement); - - return expression; - } - - - // Called when a LINQ expression type is not handled above. - protected override Exception CreateUnhandledItemException<T>(T unhandledItem, string visitMethod) - { - string itemText = FormatUnhandledItem(unhandledItem); - var message = string.Format("The expression '{0}' (type: {1}) is not supported by this LINQ provider.", itemText, typeof(T)); - return new NotSupportedException(message); - } - - private string FormatUnhandledItem<T>(T unhandledItem) - { - var itemAsExpression = unhandledItem as Expression; - return itemAsExpression != null ? FormattingExpressionTreeVisitor.Format(itemAsExpression) : unhandledItem.ToString(); - } - } -} \ No newline at end of file Deleted: trunk/nhibernate/src/NHibernate/Linq/MergeAggregatingResultsRewriter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/MergeAggregatingResultsRewriter.cs 2009-10-22 20:30:27 UTC (rev 4797) +++ trunk/nhibernate/src/NHibernate/Linq/MergeAggregatingResultsRewriter.cs 2009-10-23 12:21:21 UTC (rev 4798) @@ -1,123 +0,0 @@ -using System; -using System.Linq; -using System.Linq.Expressions; -using Remotion.Data.Linq; -using Remotion.Data.Linq.Clauses; -using Remotion.Data.Linq.Clauses.Expressions; -using Remotion.Data.Linq.Clauses.ResultOperators; -using Remotion.Data.Linq.Parsing; -using Remotion.Data.Linq.Parsing.ExpressionTreeVisitors; - -namespace NHibernate.Linq -{ - public class MergeAggregatingResultsRewriter : QueryModelVisitorBase - { - public void ReWrite(QueryModel model) - { - this.VisitQueryModel(model); - } - - public override void VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, int index) - { - if (resultOperator is SumResultOperator) - { - queryModel.SelectClause.Selector = new NhSumExpression(queryModel.SelectClause.Selector); - queryModel.ResultOperators.Remove(resultOperator); - } - else if (resultOperator is AverageResultOperator) - { - queryModel.SelectClause.Selector = new NhAverageExpression(queryModel.SelectClause.Selector); - queryModel.ResultOperators.Remove(resultOperator); - } - else if (resultOperator is MinResultOperator) - { - queryModel.SelectClause.Selector = new NhMinExpression(queryModel.SelectClause.Selector); - queryModel.ResultOperators.Remove(resultOperator); - } - else if (resultOperator is MaxResultOperator) - { - queryModel.SelectClause.Selector = new NhMaxExpression(queryModel.SelectClause.Selector); - queryModel.ResultOperators.Remove(resultOperator); - } - else if (resultOperator is DistinctResultOperator) - { - queryModel.SelectClause.Selector = new NhDistinctExpression(queryModel.SelectClause.Selector); - queryModel.ResultOperators.Remove(resultOperator); - } - else if (resultOperator is CountResultOperator) - { - queryModel.SelectClause.Selector = new NhCountExpression(queryModel.SelectClause.Selector); - queryModel.ResultOperators.Remove(resultOperator); - } - - base.VisitResultOperator(resultOperator, queryModel, index); - } - - public override void VisitSelectClause(SelectClause selectClause, QueryModel queryModel) - { - selectClause.TransformExpressions(s => new MergeAggregatingResultsInExpressionRewriter().Visit(s)); - } - } - - internal class MergeAggregatingResultsInExpressionRewriter : NhExpressionTreeVisitor - { - public Expression Visit(Expression expression) - { - return VisitExpression(expression); - } - - protected override Expression VisitSubQueryExpression(SubQueryExpression expression) - { - new MergeAggregatingResultsRewriter().ReWrite(expression.QueryModel); - return expression; - } - - protected override Expression VisitMethodCallExpression(MethodCallExpression m) - { - if (m.Method.DeclaringType == typeof(Queryable) || - m.Method.DeclaringType == typeof(Enumerable)) - { - // TODO - dynamic name generation needed here - switch (m.Method.Name) - { - case "Count": - return CreateAggregate(m.Arguments[0], (LambdaExpression)m.Arguments[1], - e => new NhCountExpression(e)); - case "Min": - return CreateAggregate(m.Arguments[0], (LambdaExpression) m.Arguments[1], - e => new NhMinExpression(e)); - case "Max": - return CreateAggregate(m.Arguments[0], (LambdaExpression)m.Arguments[1], - e => new NhMaxExpression(e)); - case "Sum": - return CreateAggregate(m.Arguments[0], (LambdaExpression)m.Arguments[1], - e => new NhSumExpression(e)); - case "Average": - return CreateAggregate(m.Arguments[0], (LambdaExpression)m.Arguments[1], - e => new NhAverageExpression(e)); - } - } - - return base.VisitMethodCallExpression(m); - } - - private Expression CreateAggregate(Expression fromClauseExpression, LambdaExpression body, Func<Expression,Expression> factory) - { - var fromClause = new MainFromClause("x2", body.Parameters[0].Type, fromClauseExpression); - var selectClause = body.Body; - selectClause = ReplacingExpressionTreeVisitor.Replace(body.Parameters[0], - new QuerySourceReferenceExpression( - fromClause), selectClause); - var queryModel = new QueryModel(fromClause, - new SelectClause(factory(selectClause))); - - queryModel.ResultOperators.Add(new AverageResultOperator()); - - var subQuery = new SubQueryExpression(queryModel); - - queryModel.ResultOperators.Clear(); - - return subQuery; - } - } -} \ No newline at end of file Deleted: trunk/nhibernate/src/NHibernate/Linq/NhExpressionTreeVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/NhExpressionTreeVisitor.cs 2009-10-22 20:30:27 UTC (rev 4797) +++ trunk/nhibernate/src/NHibernate/Linq/NhExpressionTreeVisitor.cs 2009-10-23 12:21:21 UTC (rev 4798) @@ -1,86 +0,0 @@ -using System; -using System.Linq.Expressions; -using Remotion.Data.Linq.Parsing; - -namespace NHibernate.Linq -{ - public class NhExpressionTreeVisitor : ExpressionTreeVisitor - { - protected override Expression VisitExpression(Expression expression) - { - if (expression == null) - { - return null; - } - - switch ((NhExpressionType) expression.NodeType) - { - case NhExpressionType.Average: - return VisitNhAverage((NhAverageExpression) expression); - case NhExpressionType.Min: - return VisitNhMin((NhMinExpression)expression); - case NhExpressionType.Max: - return VisitNhMax((NhMaxExpression)expression); - case NhExpressionType.Sum: - return VisitNhSum((NhSumExpression)expression); - case NhExpressionType.Count: - return VisitNhCount((NhCountExpression)expression); - case NhExpressionType.Distinct: - return VisitNhDistinct((NhDistinctExpression) expression); - case NhExpressionType.New: - return VisitNhNew((NhNewExpression) expression); - } - - return base.VisitExpression(expression); - } - - private Expression VisitNhNew(NhNewExpression expression) - { - var arguments = VisitExpressionList(expression.Arguments); - - return arguments != expression.Arguments ? new NhNewExpression(expression.Members, arguments) : expression; - } - - protected virtual Expression VisitNhDistinct(NhDistinctExpression expression) - { - ... [truncated message content] |
From: <ste...@us...> - 2009-10-25 20:48:12
|
Revision: 4800 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4800&view=rev Author: steverstrong Date: 2009-10-25 20:48:02 +0000 (Sun, 25 Oct 2009) Log Message: ----------- Added missing test file and support for Queryable.All() Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate.Test/Linq/LinqQuerySamples.cs Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/Linq/ParameterisedQueries.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2009-10-23 12:36:50 UTC (rev 4799) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2009-10-25 20:48:02 UTC (rev 4800) @@ -378,6 +378,10 @@ { return new HqlGroupBy(_factory); } + + public HqlAll All() + { + return new HqlAll(_factory); + } } - } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2009-10-23 12:36:50 UTC (rev 4799) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2009-10-25 20:48:02 UTC (rev 4800) @@ -620,4 +620,11 @@ } } + public class HqlAll : HqlTreeNode + { + public HqlAll(IASTFactory factory) + : base(HqlSqlWalker.ALL, "all", factory) + { + } + } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2009-10-23 12:36:50 UTC (rev 4799) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2009-10-25 20:48:02 UTC (rev 4800) @@ -246,35 +246,76 @@ // Any has one or two arguments. Arg 1 is the source and arg 2 is the optional predicate using (_stack.PushNode(_hqlTreeBuilder.Exists())) { - using (_stack.PushNode(_hqlTreeBuilder.Query())) - { - using (_stack.PushNode(_hqlTreeBuilder.SelectFrom())) - { - using (_stack.PushNode(_hqlTreeBuilder.From())) - { - using (_stack.PushNode(_hqlTreeBuilder.Range())) - { - VisitExpression(expression.Arguments[0]); + using (_stack.PushNode(_hqlTreeBuilder.Query())) + { + using (_stack.PushNode(_hqlTreeBuilder.SelectFrom())) + { + using (_stack.PushNode(_hqlTreeBuilder.From())) + { + using (_stack.PushNode(_hqlTreeBuilder.Range())) + { + VisitExpression(expression.Arguments[0]); - if (expression.Arguments.Count > 1) - { - var expr = (LambdaExpression) expression.Arguments[1]; - _stack.PushLeaf(_hqlTreeBuilder.Alias(expr.Parameters[0].Name)); - } - } - } - } - if (expression.Arguments.Count > 1) - { - using (_stack.PushNode(_hqlTreeBuilder.Where())) - { - VisitExpression(expression.Arguments[1]); - } - } - } + if (expression.Arguments.Count > 1) + { + var expr = (LambdaExpression) expression.Arguments[1]; + _stack.PushLeaf(_hqlTreeBuilder.Alias(expr.Parameters[0].Name)); + } + } + } + } + if (expression.Arguments.Count > 1) + { + using (_stack.PushNode(_hqlTreeBuilder.Where())) + { + VisitExpression(expression.Arguments[1]); + } + } + } } break; - case "Min": + + case "All": + // All has one or two arguments. Arg 1 is the source and arg 2 is the optional predicate + using (_stack.PushNode(_hqlTreeBuilder.Not())) + { + using (_stack.PushNode(_hqlTreeBuilder.Exists())) + { + using (_stack.PushNode(_hqlTreeBuilder.Query())) + { + using (_stack.PushNode(_hqlTreeBuilder.SelectFrom())) + { + using (_stack.PushNode(_hqlTreeBuilder.From())) + { + using (_stack.PushNode(_hqlTreeBuilder.Range())) + { + VisitExpression(expression.Arguments[0]); + + if (expression.Arguments.Count > 1) + { + var expr = (LambdaExpression) expression.Arguments[1]; + + _stack.PushLeaf(_hqlTreeBuilder.Alias(expr.Parameters[0].Name)); + } + } + } + } + if (expression.Arguments.Count > 1) + { + using (_stack.PushNode(_hqlTreeBuilder.Where())) + { + using (_stack.PushNode(_hqlTreeBuilder.Not())) + { + VisitExpression(expression.Arguments[1]); + } + } + } + } + } + } + break; + + case "Min": using (_stack.PushNode(_hqlTreeBuilder.Min())) { VisitExpression(expression.Arguments[1]); Modified: trunk/nhibernate/src/NHibernate.Test/Linq/LinqQuerySamples.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/LinqQuerySamples.cs 2009-10-23 12:36:50 UTC (rev 4799) +++ trunk/nhibernate/src/NHibernate.Test/Linq/LinqQuerySamples.cs 2009-10-25 20:48:02 UTC (rev 4800) @@ -219,11 +219,6 @@ "a shaped subset of the data about Customers.")] public void DLinq16() { - /* - * 1) bottom up search of select expression to identify nodes that can be done with hql and those that can't - * 2) top down walk; for the nodes that are hql, call the hql generator and create an objectArray[] expression - * 3) for the other nodes, ignore the hql and just return the linq expression - */ var q = from c in db.Customers select new @@ -1093,10 +1088,9 @@ [Category("EXISTS/IN/ANY/ALL")] [Test(Description = "This sample uses All to return Customers whom all of their orders " + "have been shipped to their own city or whom have no orders.")] - [Ignore("TODO")] public void DLinq54() { - IQueryable<Customer> q = + IQueryable<Customer> q = from c in db.Customers where c.Orders.All(o => o.ShippingAddress.City == c.Address.City) // where c.Orders.Cast<Order>().All(o => o.ShippingAddress.City == c.Address.City) Added: trunk/nhibernate/src/NHibernate.Test/Linq/ParameterisedQueries.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/ParameterisedQueries.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/Linq/ParameterisedQueries.cs 2009-10-25 20:48:02 UTC (rev 4800) @@ -0,0 +1,190 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using NHibernate.Linq; +using NHibernate.Test.Linq.Entities; +using NUnit.Framework; + +namespace NHibernate.Test.Linq +{ + [TestFixture] + public class ParameterisedQueries : ReadonlyTestCase + { + [Test] + public void Identical_Expressions_Return_The_Same_Key() + { + using (var s = OpenSession()) + { + var db = new Northwind(s); + + Expression<Func<IEnumerable<Customer>>> london1 = + () => from c in db.Customers where c.Address.City == "London" select c; + Expression<Func<IEnumerable<Customer>>> london2 = + () => from c in db.Customers where c.Address.City == "London" select c; + + var nhLondon1 = new NhLinqExpression(london1.Body); + var nhLondon2 = new NhLinqExpression(london2.Body); + + Assert.AreEqual(nhLondon1.Key, nhLondon2.Key); + } + } + + [Test] + public void Expressions_Differing_Only_By_Constants_Return_The_Same_Key() + { + using (var s = OpenSession()) + { + var db = new Northwind(s); + + Expression<Func<IEnumerable<Customer>>> london = + () => from c in db.Customers where c.Address.City == "London" select c; + + Expression<Func<IEnumerable<Customer>>> newYork = + () => from c in db.Customers where c.Address.City == "New York" select c; + + var nhLondon = new NhLinqExpression(london.Body); + var nhNewYork = new NhLinqExpression(newYork.Body); + + Assert.AreEqual(nhLondon.Key, nhNewYork.Key); + Assert.AreEqual(1, nhLondon.ParameterValues.Count); + Assert.AreEqual(1, nhNewYork.ParameterValues.Count); + Assert.AreEqual("London", nhLondon.ParameterValues.First().Value); + Assert.AreEqual("New York", nhNewYork.ParameterValues.First().Value); + } + } + + [Test] + public void Different_Where_Clauses_Return_Different_Keys() + { + using (var s = OpenSession()) + { + var db = new Northwind(s); + + Expression<Func<IEnumerable<Customer>>> london = + () => from c in db.Customers where c.Address.City == "London" select c; + Expression<Func<IEnumerable<Customer>>> company = + () => from c in db.Customers where c.CompanyName == "Acme" select c; + + var nhLondon = new NhLinqExpression(london.Body); + var nhNewYork = new NhLinqExpression(company.Body); + + Assert.AreNotEqual(nhLondon.Key, nhNewYork.Key); + } + } + + [Test] + public void Different_Select_Properties_Return_Different_Keys() + { + using (var s = OpenSession()) + { + var db = new Northwind(s); + + Expression<Func<IEnumerable<string>>> customerId = + () => from c in db.Customers select c.CustomerId; + Expression<Func<IEnumerable<string>>> title = + () => from c in db.Customers select c.ContactTitle; + + var nhLondon = new NhLinqExpression(customerId.Body); + var nhNewYork = new NhLinqExpression(title.Body); + + Assert.AreNotEqual(nhLondon.Key, nhNewYork.Key); + } + } + + [Test] + public void Different_Select_Types_Return_Different_Keys() + { + using (var s = OpenSession()) + { + var db = new Northwind(s); + + Expression<Func<IEnumerable>> newCustomerId = + () => from c in db.Customers select new {c.CustomerId}; + Expression<Func<IEnumerable>> customerId = + () => from c in db.Customers select c.CustomerId; + + var nhLondon = new NhLinqExpression(newCustomerId.Body); + var nhNewYork = new NhLinqExpression(customerId.Body); + + Assert.AreNotEqual(nhLondon.Key, nhNewYork.Key); + } + } + + [Test] + public void Different_Select_Member_Initialisation_Returns_Different_Keys() + { + using (var s = OpenSession()) + { + var db = new Northwind(s); + + Expression<Func<IEnumerable>> newCustomerId = + () => from c in db.Customers select new { Id = c.CustomerId, Title = c.ContactTitle }; + Expression<Func<IEnumerable>> customerId = + () => from c in db.Customers select new { Title = c.ContactTitle, Id = c.CustomerId }; + + var nhLondon = new NhLinqExpression(newCustomerId.Body); + var nhNewYork = new NhLinqExpression(customerId.Body); + + Assert.AreNotEqual(nhLondon.Key, nhNewYork.Key); + } + } + + [Test] + public void Different_Conditionals_Return_Different_Keys() + { + using (var s = OpenSession()) + { + var db = new Northwind(s); + + Expression<Func<IEnumerable>> newCustomerId = + () => from c in db.Customers select new { Desc = c.CustomerId == "1" ? "First" : "Not First" }; + Expression<Func<IEnumerable>> customerId = + () => from c in db.Customers select new { Desc = c.CustomerId != "1" ? "First" : "Not First" }; + + var nhLondon = new NhLinqExpression(newCustomerId.Body); + var nhNewYork = new NhLinqExpression(customerId.Body); + + Assert.AreNotEqual(nhLondon.Key, nhNewYork.Key); + } + } + + [Test] + public void Different_Unary_Operation_Returns_Different_Keys() + { + using (var s = OpenSession()) + { + var db = new Northwind(s); + + Expression<Func<IEnumerable>> newCustomerId = + () => from c in db.Customers where c.CustomerId == "1" select c; + Expression<Func<IEnumerable>> customerId = + () => from c in db.Customers where !(c.CustomerId == "1") select c; + + var nhLondon = new NhLinqExpression(newCustomerId.Body); + var nhNewYork = new NhLinqExpression(customerId.Body); + + Assert.AreNotEqual(nhLondon.Key, nhNewYork.Key); + } + } + + // TODO - different parameter names + + protected override IList Mappings + { + get { return new string[0]; } + } + + protected override bool PerformDbDataSetup + { + get { return false; } + } + + protected override bool PerformDbDataTeardown + { + get { return false; } + } + + } +} \ 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: <ric...@us...> - 2009-10-26 11:02:36
|
Revision: 4802 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4802&view=rev Author: ricbrown Date: 2009-10-26 11:02:27 +0000 (Mon, 26 Oct 2009) Log Message: ----------- Merge r4801 (Fix NH-847, Stored Procedures support with OracleDataClient) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs trunk/nhibernate/src/NHibernate/Driver/IDriver.cs trunk/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs trunk/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs trunk/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs trunk/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs trunk/nhibernate/src/NHibernate/Loader/Loader.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs trunk/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/OracleCustomSQLFixture.cs trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml Added Paths: ----------- trunk/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs trunk/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs Modified: trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -136,6 +136,11 @@ return cmd; } + public virtual int RegisterResultSetOutParameter(IDbCommand command, int position, bool hasReturnValue) + { + throw new NotImplementedException(GetType().Name + " does not support resultsets via stored procedures"); + } + private void SetCommandTimeout(IDbCommand cmd, object envTimeout) { if (commandTimeout >= 0) Modified: trunk/nhibernate/src/NHibernate/Driver/IDriver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/IDriver.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/Driver/IDriver.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -80,6 +80,17 @@ IDbCommand GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes); /// <summary> + /// Registers an OUT parameter which will be returing a + /// <see cref="IDataReader"/>. How this is accomplished varies greatly + /// from DB to DB, hence its inclusion here. + /// </summary> + /// <param name="command">The <see cref="IDbCommand"/> with CommandType.StoredProcedure.</param> + /// <param name="position">The bind position at which to register the OUT param.</param> + /// <param name="hasReturnValue">Whether the out parameter is a return value, or an out parameter.</param> + /// <returns>The number of (contiguous) bind positions used.</returns> + int RegisterResultSetOutParameter(IDbCommand command, int position, bool hasReturnValue); + + /// <summary> /// Prepare the <paramref name="command" /> by calling <see cref="IDbCommand.Prepare()" />. /// May be a no-op if the driver does not support preparing commands, or for any other reason. /// </summary> Modified: trunk/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -47,5 +47,12 @@ base.InitializeParameter(dbParam, name, sqlType); } } + + public override int RegisterResultSetOutParameter(IDbCommand command, int position, bool hasReturnValue) + { + throw new System.NotImplementedException(GetType().Name + + " does not support resultsets via stored procedures." + + " Consider using OracleDataClientDriver instead."); + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -1,6 +1,8 @@ using System.Data; +using System.Reflection; using NHibernate.AdoNet; using NHibernate.SqlTypes; +using NHibernate.Util; namespace NHibernate.Driver { @@ -14,7 +16,13 @@ /// </remarks> public class OracleDataClientDriver : ReflectionBasedDriver, IEmbeddedBatcherFactoryProvider { + private const string driverAssemblyName = "Oracle.DataAccess"; + private const string connectionTypeName = "Oracle.DataAccess.Client.OracleConnection"; + private const string commandTypeName = "Oracle.DataAccess.Client.OracleCommand"; private static readonly SqlType GuidSqlType = new SqlType(DbType.Binary, 16); + private readonly PropertyInfo oracleDbType; + private readonly object oracleDbTypeRefCursor; + /// <summary> /// Initializes a new instance of <see cref="OracleDataClientDriver"/>. /// </summary> @@ -23,10 +31,15 @@ /// </exception> public OracleDataClientDriver() : base( - "Oracle.DataAccess", - "Oracle.DataAccess.Client.OracleConnection", - "Oracle.DataAccess.Client.OracleCommand") + driverAssemblyName, + connectionTypeName, + commandTypeName) { + System.Type parameterType = ReflectHelper.TypeFromAssembly("Oracle.DataAccess.Client.OracleParameter", driverAssemblyName, false); + oracleDbType = parameterType.GetProperty("OracleDbType"); + + System.Type oracleDbTypeEnum = ReflectHelper.TypeFromAssembly("Oracle.DataAccess.Client.OracleDbType", driverAssemblyName, false); + oracleDbTypeRefCursor = System.Enum.Parse(oracleDbTypeEnum, "RefCursor"); } /// <summary></summary> @@ -69,6 +82,19 @@ } } + public override int RegisterResultSetOutParameter(IDbCommand command, int position, bool hasReturnValue) + { + IDbDataParameter outCursor = command.CreateParameter(); + outCursor.ParameterName = ""; + oracleDbType.SetValue(outCursor, oracleDbTypeRefCursor, null); + + outCursor.Direction = hasReturnValue ? ParameterDirection.ReturnValue : ParameterDirection.Output; + + command.Parameters.Insert(position, outCursor); + + return 1; + } + #region IEmbeddedBatcherFactoryProvider Members System.Type IEmbeddedBatcherFactoryProvider.BatcherFactoryClass Added: trunk/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -0,0 +1,33 @@ +using System; +using System.Text.RegularExpressions; +using NHibernate.Hql.Classic; +using NHibernate.Util; +using NHibernate.SqlCommand; + +namespace NHibernate.Engine.Query +{ + public static class CallableParser + { + private static readonly Regex functionNameFinder = new Regex(@"\{[\S\s]*call[\s]+([\w]+)[^\w]"); + private static readonly int NewLineLength = Environment.NewLine.Length; + + public static SqlString Parse(string sqlString) + { + bool isCallableSyntax = sqlString.IndexOf("{") == 0 && + sqlString.IndexOf("}") == (sqlString.Length - 1) && + sqlString.IndexOf("call") > 0; + + if (!isCallableSyntax) + throw new ParserException("Expected callable syntax {? = call procedure_name[(?, ?, ...)]} but got: " + sqlString); + + + Match functionMatch = functionNameFinder.Match(sqlString); + + if ((!functionMatch.Success) || (functionMatch.Groups.Count < 2)) + throw new HibernateException("Could not determine function name for callable SQL: " + sqlString); + + string function = functionMatch.Groups[1].Value; + return new SqlString(function); + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -13,6 +13,8 @@ private readonly List<int> ordinalParameterLocationList = new List<int>(); + private bool hasReturnValue = false; + /// <summary> /// Convenience method for creating a param location recognizer and /// initiating the parse. @@ -47,11 +49,16 @@ get { return ordinalParameterLocationList; } } + public bool HasReturnValue + { + get { return hasReturnValue; } + } + #region IRecognizer Members public void OutParameter(int position) { - // don't care... + hasReturnValue = true; } public void OrdinalParameter(int position) Modified: trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -12,8 +12,17 @@ private static readonly OrdinalParameterDescriptor[] EmptyOrdinals = new OrdinalParameterDescriptor[0]; private readonly OrdinalParameterDescriptor[] ordinalDescriptors; private readonly Dictionary<string, NamedParameterDescriptor> namedDescriptorMap; + private readonly bool hasReturnValue = false; public ParameterMetadata(OrdinalParameterDescriptor[] ordinalDescriptors, + IDictionary<string, NamedParameterDescriptor> namedDescriptorMap, + bool hasReturnValue) + : this (ordinalDescriptors, namedDescriptorMap) + { + this.hasReturnValue = hasReturnValue; + } + + public ParameterMetadata(OrdinalParameterDescriptor[] ordinalDescriptors, IDictionary<string, NamedParameterDescriptor> namedDescriptorMap) { if (ordinalDescriptors == null) @@ -43,6 +52,11 @@ get { return namedDescriptorMap.Keys; } } + public bool HasReturnValue + { + get { return hasReturnValue; } + } + public OrdinalParameterDescriptor GetOrdinalParameterDescriptor(int position) { if (position < 1 || position > ordinalDescriptors.Length) Modified: trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -171,7 +171,7 @@ new NamedParameterDescriptor(name, null, description.BuildPositionsArray(), description.JpaStyle); } - return new ParameterMetadata(ordinalDescriptors, namedParamDescriptorMap); + return new ParameterMetadata(ordinalDescriptors, namedParamDescriptorMap, recognizer.HasReturnValue); } [Serializable] Modified: trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -279,6 +279,8 @@ public bool Callable { get; set; } + public bool HasReturnValue { get; set; } + public bool ReadOnly { get { return _readOnly; } Modified: trunk/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -27,6 +27,7 @@ private readonly IList<INativeSQLQueryReturn> queryReturns; private readonly ICollection<string> querySpaces; private readonly bool callable; + private readonly bool hasReturnValue; private bool autoDiscoverTypes; /// <summary> Constructs a SQLQueryImpl given a sql query defined in the mappings. </summary> @@ -52,16 +53,9 @@ querySpaces = queryDef.QuerySpaces; callable = queryDef.IsCallable; + hasReturnValue = parameterMetadata.HasReturnValue; } - internal SqlQueryImpl(string sql, IList<INativeSQLQueryReturn> queryReturns, ICollection<string> querySpaces, FlushMode flushMode, bool callable, ISessionImplementor session, ParameterMetadata parameterMetadata) - : base(sql, flushMode, session, parameterMetadata) - { - this.queryReturns = queryReturns; - this.querySpaces = querySpaces; - this.callable = callable; - } - internal SqlQueryImpl(string sql, string[] returnAliases, System.Type[] returnClasses, LockMode[] lockModes, ISessionImplementor session, ICollection<string> querySpaces, FlushMode flushMode, ParameterMetadata parameterMetadata) : base(sql, flushMode, session, parameterMetadata) { @@ -180,6 +174,7 @@ { QueryParameters qp = base.GetQueryParameters(namedParams); qp.Callable = callable; + qp.HasReturnValue = hasReturnValue; qp.HasAutoDiscoverScalarTypes = autoDiscoverTypes; return qp; } Modified: trunk/nhibernate/src/NHibernate/Loader/Loader.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -11,6 +11,7 @@ using NHibernate.Cache; using NHibernate.Collection; using NHibernate.Engine; +using NHibernate.Engine.Query; using NHibernate.Event; using NHibernate.Exceptions; using NHibernate.Hql.Util; @@ -1104,7 +1105,8 @@ bool useLimit = UseLimit(selection, dialect); bool hasFirstRow = GetFirstRow(selection) > 0; bool useOffset = hasFirstRow && useLimit && dialect.SupportsLimitOffset; - // TODO NH bool callable = queryParameters.Callable; + bool isCallable = queryParameters.Callable; + bool hasReturnValue = queryParameters.HasReturnValue; if (useLimit) { @@ -1114,10 +1116,19 @@ sqlString = PreprocessSQL(sqlString, queryParameters, dialect); - // TODO NH: Callable for SP -> PrepareCallableQueryCommand - IDbCommand command = - session.Batcher.PrepareQueryCommand(CommandType.Text, sqlString, - GetParameterTypes(queryParameters, useLimit, useOffset)); + IDbCommand command = null; + if (isCallable) + { + command = + session.Batcher.PrepareQueryCommand(CommandType.StoredProcedure, CallableParser.Parse(sqlString.ToString()), + GetParameterTypes(queryParameters, useLimit, useOffset)); + } + else + { + command = + session.Batcher.PrepareQueryCommand(CommandType.Text, sqlString, + GetParameterTypes(queryParameters, useLimit, useOffset)); + } try { @@ -1133,12 +1144,13 @@ { colIndex += BindLimitParameters(command, colIndex, selection, session); } - // TODO NH - //if (callable) - //{ - // colIndex = dialect.RegisterResultSetOutParameter(command, col); - //} + if (isCallable) + { + colIndex += + session.Factory.ConnectionProvider.Driver.RegisterResultSetOutParameter(command, colIndex, hasReturnValue); + } + colIndex += BindParameterValues(command, queryParameters, colIndex, session); if (useLimit && !dialect.BindLimitParametersFirst) @@ -1263,7 +1275,7 @@ // NH Different behavior: // The responsibility of parameter binding was entirely moved to QueryParameters // to deal with positionslParameter+NamedParameter+ParameterOfFilters - return queryParameters.BindParameters(statement, GetNamedParameterLocs, 0, session); + return queryParameters.BindParameters(statement, GetNamedParameterLocs, startIndex, session); } public virtual int[] GetNamedParameterLocs(string name) Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-10-26 11:02:27 UTC (rev 4802) @@ -524,6 +524,7 @@ <Compile Include="Dialect\SybaseASA9Dialect.cs" /> <Compile Include="Driver\IfxDriver.cs" /> <Compile Include="Driver\OracleLiteDataClientDriver.cs" /> + <Compile Include="Engine\Query\CallableParser.cs" /> <Compile Include="EntityModeEqualityComparer.cs" /> <Compile Include="Event\AbstractPostDatabaseOperationEvent.cs" /> <Compile Include="Event\AbstractPreDatabaseOperationEvent.cs" /> Modified: trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -3332,20 +3332,20 @@ SqlCommandInfo defaultDelete = GenerateDeleteString(j); sqlInsertStrings[j] = customSQLInsert[j] != null - ? new SqlCommandInfo(customSQLInsert[j], defaultInsert.ParameterTypes) + ? new SqlCommandInfo(customSQLInsert[j], insertCallable[j], defaultInsert.ParameterTypes) : defaultInsert; sqlUpdateStrings[j] = customSQLUpdate[j] != null - ? new SqlCommandInfo(customSQLUpdate[j], defaultUpdate.ParameterTypes) + ? new SqlCommandInfo(customSQLUpdate[j], updateCallable[j], defaultUpdate.ParameterTypes) : defaultUpdate; // NH: in practice for lazy update de update sql is the same any way. sqlLazyUpdateStrings[j] = customSQLUpdate[j] != null - ? new SqlCommandInfo(customSQLUpdate[j], defaultUpdate.ParameterTypes) + ? new SqlCommandInfo(customSQLUpdate[j], updateCallable[j], defaultUpdate.ParameterTypes) : GenerateUpdateString(NonLazyPropertyUpdateability, j, false); sqlDeleteStrings[j] = customSQLDelete[j] != null - ? new SqlCommandInfo(customSQLDelete[j], defaultDelete.ParameterTypes) + ? new SqlCommandInfo(customSQLDelete[j], deleteCallable[j], defaultDelete.ParameterTypes) : defaultDelete; } Modified: trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs =================================================================== --- trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -1,10 +1,12 @@ using System.Data; +using NHibernate.Engine.Query; using NHibernate.SqlTypes; namespace NHibernate.SqlCommand { public class SqlCommandInfo { + private readonly CommandType commandType; private readonly SqlString text; private readonly SqlType[] parameterTypes; @@ -12,12 +14,22 @@ { this.text = text; this.parameterTypes = parameterTypes; + this.commandType = CommandType.Text; } + public SqlCommandInfo(SqlString text, bool isStoredProcedure, SqlType[] parameterTypes) + : this(text, parameterTypes) + { + if (isStoredProcedure) + { + this.commandType = CommandType.StoredProcedure; + this.text = CallableParser.Parse(text.ToString()); + } + } + public CommandType CommandType { - // Always Text for now - get { return CommandType.Text; } + get { return commandType; } } public SqlString Text Added: trunk/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -0,0 +1,40 @@ +using NUnit.Framework; +using NHibernate.Engine.Query; +using NHibernate.SqlCommand; +using NHibernate.Util; + +namespace NHibernate.Test.EngineTest +{ + [TestFixture] + public class CallableParserFixture + { + [Test] + public void CanFindCallableFunctionName() + { + string query = @"{ call myFunction(:name) }"; + + SqlString sqlFunction = CallableParser.Parse(query); + Assert.That(sqlFunction.ToString(), Is.EqualTo("myFunction")); + } + + [Test] + public void CanDetermineIsNotCallable() + { + string query = @"SELECT id FROM mytable"; + + Assert.Throws<ParserException>(() => + { + SqlString sqlFunction = CallableParser.Parse(query); + }); + } + + [Test] + public void CanFindCallableFunctionNameWithoutParameters() + { + string query = @"{ call myFunction }"; + + SqlString sqlFunction = CallableParser.Parse(query); + Assert.That(sqlFunction.ToString(), Is.EqualTo("myFunction")); + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -59,5 +59,22 @@ Assert.DoesNotThrow(() => p = recognizer.NamedParameterDescriptionMap["pizza"]); } + [Test] + public void CanRecogniseNoReturnValueParameter() + { + string query = "{ call myFunction(?) }"; + ParamLocationRecognizer recognizer = new ParamLocationRecognizer(); + ParameterParser.Parse(query, recognizer); + Assert.That(recognizer.HasReturnValue, Is.False); + } + + [Test] + public void CanRecogniseReturnValueParameter() + { + string query = "{ ? = call myFunction(?) }"; + ParamLocationRecognizer recognizer = new ParamLocationRecognizer(); + ParameterParser.Parse(query, recognizer); + Assert.That(recognizer.HasReturnValue, Is.True); + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-26 11:02:27 UTC (rev 4802) @@ -165,6 +165,7 @@ <Compile Include="Criteria\Reptile.cs" /> <Compile Include="DriverTest\SqlClientDriverFixture.cs" /> <Compile Include="DriverTest\SqlServerCeDriverFixture.cs" /> + <Compile Include="EngineTest\CallableParserFixture.cs" /> <Compile Include="EngineTest\NativeSQLQueryNonScalarReturnTest.cs" /> <Compile Include="EngineTest\NativeSQLQueryScalarReturnTest.cs" /> <Compile Include="EngineTest\NativeSQLQuerySpecificationTest.cs" /> Modified: trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml 2009-10-26 11:02:27 UTC (rev 4802) @@ -39,7 +39,7 @@ </id> <property name="name" not-null="true"/> <loader query-ref="person"/> - <sql-insert callable="true" check="none">call createPerson(?,?)</sql-insert> + <sql-insert callable="true" check="none">{ call createPerson(?, ?) }</sql-insert> <sql-update>UPDATE PERSON SET NAME=UPPER(?) WHERE PERID=?</sql-update> <sql-delete>DELETE FROM PERSON WHERE PERID=?</sql-delete> </class> @@ -187,6 +187,23 @@ <database-object> <create> + CREATE OR REPLACE PROCEDURE employmentsForRegion(rows OUT SYS_REFCURSOR, p_regionCode EMPLOYMENT.REGIONCODE%TYPE) + AS + BEGIN + OPEN rows FOR + SELECT EMPLOYEE, EMPLOYER, STARTDATE, ENDDATE, + REGIONCODE, EMPID, VALUE, CURRENCY + FROM EMPLOYMENT + WHERE REGIONCODE = p_regionCode; + END; + </create> + <drop> + DROP PROCEDURE employmentsForRegion + </drop> + </database-object> + + <database-object> + <create> CREATE OR REPLACE PROCEDURE createPerson(p_name PERSON.NAME%TYPE, p_id PERSON.PERID%TYPE) AS rowcount INTEGER; @@ -201,7 +218,7 @@ END; </create> <drop> - DROP PROCEDURE createPerson; + DROP PROCEDURE createPerson </drop> </database-object> Modified: trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/OracleCustomSQLFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/OracleCustomSQLFixture.cs 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/OracleCustomSQLFixture.cs 2009-10-26 11:02:27 UTC (rev 4802) @@ -4,7 +4,7 @@ namespace NHibernate.Test.SqlTest.Custom.Oracle { - [TestFixture, Ignore("Not supported yet.")] + [TestFixture] public class OracleCustomSQLFixture : CustomStoredProcSupportTest { protected override IList Mappings @@ -12,9 +12,49 @@ get { return new[] { "SqlTest.Custom.Oracle.Mappings.hbm.xml", "SqlTest.Custom.Oracle.StoredProcedures.hbm.xml" }; } } + protected override bool AppliesTo(NHibernate.Engine.ISessionFactoryImplementor factory) + { + return factory.ConnectionProvider.Driver is Driver.OracleDataClientDriver; + } + protected override bool AppliesTo(Dialect.Dialect dialect) { return dialect is Oracle8iDialect; } + + [Test] + public void RefCursorOutStoredProcedure() + { + ISession s = OpenSession(); + ITransaction t = s.BeginTransaction(); + + Organization ifa = new Organization("IFA"); + Organization jboss = new Organization("JBoss"); + Person gavin = new Person("Gavin"); + Person kevin = new Person("Kevin"); + Employment emp = new Employment(gavin, jboss, "AU"); + Employment emp2 = new Employment(kevin, ifa, "EU"); + s.Save(ifa); + s.Save(jboss); + s.Save(gavin); + s.Save(kevin); + s.Save(emp); + s.Save(emp2); + + IQuery namedQuery = s.GetNamedQuery("selectEmploymentsForRegion"); + namedQuery.SetString("regionCode", "EU"); + IList list = namedQuery.List(); + Assert.That(list.Count, Is.EqualTo(1)); + s.Delete(emp2); + s.Delete(emp); + s.Delete(ifa); + s.Delete(jboss); + s.Delete(kevin); + s.Delete(gavin); + + t.Commit(); + s.Close(); + } + } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml 2009-10-26 11:01:27 UTC (rev 4801) +++ trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml 2009-10-26 11:02:27 UTC (rev 4802) @@ -1,10 +1,6 @@ <?xml version="1.0" encoding="utf-8" ?> <!-- This version is for Oracle drivers handling of stored procedures/functions. - - - NOTE: so far this is the JAVA syntax, probably we will do something different in .NET - or we can use the same syntax and solve the problem in each Oracle drive --> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" @@ -15,19 +11,19 @@ <sql-query name="simpleScalar" callable="true"> <return-scalar column="name" type="string"/> <return-scalar column="value" type="long"/> - call simpleScalar(:number) + { ? = call simpleScalar(:number) } </sql-query> <sql-query name="paramhandling" callable="true"> <return-scalar column="value" type="long"/> <return-scalar column="value2" type="long"/> - call testParamHandling(?,?) + { ? = call testParamHandling(?, ?) } </sql-query> <sql-query name="paramhandling_mixed" callable="true"> <return-scalar column="value" type="long"/> <return-scalar column="value2" type="long"/> - call testParamHandling(?,:second) + { ? = call testParamHandling(?,:second) } </sql-query> <sql-query name="selectAllEmployments" callable="true"> @@ -43,7 +39,23 @@ <return-column name="CURRENCY"/> </return-property> </return> - call allEmployments() + { ? = call allEmployments } </sql-query> + <sql-query name="selectEmploymentsForRegion" callable="true"> + <return alias="emp" class="Employment"> + <return-property name="employee" column="EMPLOYEE"/> + <return-property name="employer" column="EMPLOYER"/> + <return-property name="startDate" column="STARTDATE"/> + <return-property name="endDate" column="ENDDATE"/> + <return-property name="regionCode" column="REGIONCODE"/> + <return-property name="employmentId" column="EMPID"/> + <return-property name="salary"> + <return-column name="VALUE"/> + <return-column name="CURRENCY"/> + </return-property> + </return> + { call employmentsForRegion(:regionCode) } + </sql-query> + </hibernate-mapping> \ 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...> - 2009-10-27 03:47:41
|
Revision: 4804 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4804&view=rev Author: fabiomaulo Date: 2009-10-27 03:47:26 +0000 (Tue, 27 Oct 2009) Log Message: ----------- Merge r4803 (fix NH-1997) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/ExceptionsTest/NullQueryTest.cs Modified: trunk/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs 2009-10-26 23:58:32 UTC (rev 4803) +++ trunk/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs 2009-10-27 03:47:26 UTC (rev 4804) @@ -36,7 +36,9 @@ public static Exception Convert(ISQLExceptionConverter converter, Exception sqlException, string message, SqlString sql) { - return Convert(converter, new AdoExceptionContextInfo {SqlException = sqlException, Message = message, Sql = sql.ToString()}); + return Convert(converter, + new AdoExceptionContextInfo + {SqlException = sqlException, Message = message, Sql = sql != null ? sql.ToString() : null}); } /// <summary> @@ -57,9 +59,9 @@ object[] parameterValues, IDictionary<string, TypedValue> namedParameters) { sql = TryGetActualSqlQuery(sqle, sql); - string extendMessage = ExtendMessage(message, sql.ToString(), parameterValues, namedParameters); + string extendMessage = ExtendMessage(message, sql != null ? sql.ToString() : null, parameterValues, namedParameters); ADOExceptionReporter.LogExceptions(sqle, extendMessage); - return new ADOException(extendMessage, sqle, sql.ToString()); + return new ADOException(extendMessage, sqle, sql != null ? sql.ToString() : SQLNotAvailable); } /// <summary> For the given <see cref="Exception"/>, locates the <see cref="System.Data.Common.DbException"/>. </summary> @@ -81,7 +83,7 @@ IDictionary<string, TypedValue> namedParameters) { var sb = new StringBuilder(); - sb.Append(message).Append(Environment.NewLine).Append("[ ").Append(sql).Append(" ]"); + sb.Append(message).Append(Environment.NewLine).Append("[ ").Append(sql ?? SQLNotAvailable).Append(" ]"); if (parameterValues != null && parameterValues.Length > 0) { sb.Append(Environment.NewLine).Append("Positional parameters: "); Added: trunk/nhibernate/src/NHibernate.Test/ExceptionsTest/NullQueryTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/ExceptionsTest/NullQueryTest.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/ExceptionsTest/NullQueryTest.cs 2009-10-27 03:47:26 UTC (rev 4804) @@ -0,0 +1,46 @@ +using System; +using System.Collections; +using System.Data; +using NHibernate.Exceptions; +using NUnit.Framework; + +namespace NHibernate.Test.ExceptionsTest +{ + /// <summary> + /// NH-1997 + /// </summary> + [TestFixture] + public class NullQueryTest : TestCase + { + #region Overrides of TestCase + + protected override IList Mappings + { + get { return new string[0]; } + } + + #endregion + [Test] + public void BadGrammar() + { + ISession session = OpenSession(); + IDbConnection connection = session.Connection; + try + { + IDbCommand ps = connection.CreateCommand(); + ps.CommandType = CommandType.Text; + ps.CommandText = "whatever"; + ps.ExecuteNonQuery(); + } + catch (Exception sqle) + { + Assert.DoesNotThrow( + () => ADOExceptionHelper.Convert(sessions.SQLExceptionConverter, sqle, "could not get or update next value", null)); + } + finally + { + session.Close(); + } + } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-26 23:58:32 UTC (rev 4803) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-27 03:47:26 UTC (rev 4804) @@ -169,6 +169,7 @@ <Compile Include="EngineTest\NativeSQLQueryNonScalarReturnTest.cs" /> <Compile Include="EngineTest\NativeSQLQueryScalarReturnTest.cs" /> <Compile Include="EngineTest\NativeSQLQuerySpecificationTest.cs" /> + <Compile Include="ExceptionsTest\NullQueryTest.cs" /> <Compile Include="ExpressionTest\RestrictionsFixture.cs" /> <Compile Include="Criteria\Student.cs" /> <Compile Include="Criteria\StudentDTO.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2009-10-29 14:31:43
|
Revision: 4806 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4806&view=rev Author: ricbrown Date: 2009-10-29 14:31:35 +0000 (Thu, 29 Oct 2009) Log Message: ----------- Merge r4805 (Updated fix for NH-847 moving responsibility to the driver) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs trunk/nhibernate/src/NHibernate/Driver/IDriver.cs trunk/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs trunk/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs trunk/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs trunk/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs trunk/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs trunk/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs trunk/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs trunk/nhibernate/src/NHibernate/Loader/Loader.cs trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs trunk/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs trunk/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml Modified: trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -136,11 +136,6 @@ return cmd; } - public virtual int RegisterResultSetOutParameter(IDbCommand command, int position, bool hasReturnValue) - { - throw new NotImplementedException(GetType().Name + " does not support resultsets via stored procedures"); - } - private void SetCommandTimeout(IDbCommand cmd, object envTimeout) { if (commandTimeout >= 0) @@ -215,12 +210,23 @@ public void PrepareCommand(IDbCommand command) { + OnBeforePrepare(command); + if (SupportsPreparingCommands && prepareSql) { command.Prepare(); } } + /// <summary> + /// Override to make any adjustments to the IDbCommand object. (e.g., Oracle custom OUT parameter) + /// Parameters have been bound by this point, so their order can be adjusted too. + /// This is analagous to the RegisterResultSetOutParameter() function in Hibernate. + /// </summary> + protected virtual void OnBeforePrepare(IDbCommand command) + { + } + public IDbDataParameter GenerateOutputParameter(IDbCommand command) { IDbDataParameter param = GenerateParameter(command, "ReturnValue", SqlTypeFactory.Int32); Modified: trunk/nhibernate/src/NHibernate/Driver/IDriver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/IDriver.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Driver/IDriver.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -80,17 +80,6 @@ IDbCommand GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes); /// <summary> - /// Registers an OUT parameter which will be returing a - /// <see cref="IDataReader"/>. How this is accomplished varies greatly - /// from DB to DB, hence its inclusion here. - /// </summary> - /// <param name="command">The <see cref="IDbCommand"/> with CommandType.StoredProcedure.</param> - /// <param name="position">The bind position at which to register the OUT param.</param> - /// <param name="hasReturnValue">Whether the out parameter is a return value, or an out parameter.</param> - /// <returns>The number of (contiguous) bind positions used.</returns> - int RegisterResultSetOutParameter(IDbCommand command, int position, bool hasReturnValue); - - /// <summary> /// Prepare the <paramref name="command" /> by calling <see cref="IDbCommand.Prepare()" />. /// May be a no-op if the driver does not support preparing commands, or for any other reason. /// </summary> Modified: trunk/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -1,5 +1,6 @@ using System.Data; using System.Data.OracleClient; +using NHibernate.Engine.Query; using NHibernate.SqlTypes; namespace NHibernate.Driver @@ -48,10 +49,17 @@ } } - public override int RegisterResultSetOutParameter(IDbCommand command, int position, bool hasReturnValue) + protected override void OnBeforePrepare(IDbCommand command) { + base.OnBeforePrepare(command); + + CallableParser.Detail detail = CallableParser.Parse(command.CommandText); + + if (!detail.IsCallable) + return; + throw new System.NotImplementedException(GetType().Name + - " does not support resultsets via stored procedures." + + " does not support CallableStatement syntax (stored procedures)." + " Consider using OracleDataClientDriver instead."); } } Modified: trunk/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -1,6 +1,7 @@ using System.Data; using System.Reflection; using NHibernate.AdoNet; +using NHibernate.Engine.Query; using NHibernate.SqlTypes; using NHibernate.Util; @@ -82,17 +83,24 @@ } } - public override int RegisterResultSetOutParameter(IDbCommand command, int position, bool hasReturnValue) + protected override void OnBeforePrepare(IDbCommand command) { + base.OnBeforePrepare(command); + + CallableParser.Detail detail = CallableParser.Parse(command.CommandText); + + if (!detail.IsCallable) + return; + + command.CommandType = CommandType.StoredProcedure; + command.CommandText = detail.FunctionName; + IDbDataParameter outCursor = command.CreateParameter(); - outCursor.ParameterName = ""; oracleDbType.SetValue(outCursor, oracleDbTypeRefCursor, null); - outCursor.Direction = hasReturnValue ? ParameterDirection.ReturnValue : ParameterDirection.Output; + outCursor.Direction = detail.HasReturn ? ParameterDirection.ReturnValue : ParameterDirection.Output; - command.Parameters.Insert(position, outCursor); - - return 1; + command.Parameters.Insert(0, outCursor); } #region IEmbeddedBatcherFactoryProvider Members Modified: trunk/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Text; using NHibernate.SqlCommand; +using NHibernate.Engine.Query; namespace NHibernate.Driver { @@ -15,6 +16,9 @@ private readonly Dictionary<int, int> queryIndexToNumberOfPreceedingParameters = new Dictionary<int, int>(); private readonly Dictionary<int, int> parameterIndexToQueryIndex = new Dictionary<int, int>(); + private bool hasReturnParameter = false; + private bool foundReturnParameter = false; + public SqlStringFormatter(ISqlParameterFormatter formatter, string multipleQueriesSeparator) { this.formatter = formatter; @@ -24,6 +28,7 @@ public void Format(SqlString text) { DetermineNumberOfPreceedingParametersForEachQuery(text); + foundReturnParameter = false; text.Visit(this); } @@ -44,6 +49,13 @@ void ISqlStringVisitor.Parameter(Parameter parameter) { + if (hasReturnParameter && !foundReturnParameter) + { + result.Append(parameter); + foundReturnParameter = true; + return; + } + string name; if (queryIndexToNumberOfPreceedingParameters.Count == 0) @@ -80,7 +92,14 @@ int currentParameterIndex = 0; int currentQueryParameterCount = 0; int currentQueryIndex = 0; + hasReturnParameter = false; + foundReturnParameter = false; + CallableParser.Detail callableDetail = CallableParser.Parse(text.ToString()); + + if (callableDetail.IsCallable && callableDetail.HasReturn) + hasReturnParameter = true; + foreach (object part in text.Parts) { if (part.ToString().Equals(multipleQueriesSeparator)) @@ -95,7 +114,14 @@ if (parameter != null) { - parameterIndexToQueryIndex[currentParameterIndex] = currentQueryIndex; + if (hasReturnParameter && !foundReturnParameter) + { + foundReturnParameter = true; + } + else + { + parameterIndexToQueryIndex[currentParameterIndex] = currentQueryIndex; + } currentQueryParameterCount++; currentParameterIndex++; } Modified: trunk/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -8,26 +8,42 @@ { public static class CallableParser { + + public class Detail + { + public bool IsCallable; + public bool HasReturn; + public string FunctionName; + } + private static readonly Regex functionNameFinder = new Regex(@"\{[\S\s]*call[\s]+([\w]+)[^\w]"); private static readonly int NewLineLength = Environment.NewLine.Length; - public static SqlString Parse(string sqlString) + public static Detail Parse(string sqlString) { - bool isCallableSyntax = sqlString.IndexOf("{") == 0 && - sqlString.IndexOf("}") == (sqlString.Length - 1) && - sqlString.IndexOf("call") > 0; + Detail callableDetail = new Detail(); - if (!isCallableSyntax) - throw new ParserException("Expected callable syntax {? = call procedure_name[(?, ?, ...)]} but got: " + sqlString); + callableDetail.IsCallable = sqlString.IndexOf("{") == 0 && + sqlString.IndexOf("}") == (sqlString.Length - 1) && + sqlString.IndexOf("call") > 0; + if (!callableDetail.IsCallable) + return callableDetail; Match functionMatch = functionNameFinder.Match(sqlString); if ((!functionMatch.Success) || (functionMatch.Groups.Count < 2)) throw new HibernateException("Could not determine function name for callable SQL: " + sqlString); - string function = functionMatch.Groups[1].Value; - return new SqlString(function); + callableDetail.FunctionName = functionMatch.Groups[1].Value; + + callableDetail.HasReturn = sqlString.IndexOf("call") > 0 && + sqlString.IndexOf("?") > 0 && + sqlString.IndexOf("=") > 0 && + sqlString.IndexOf("?") < sqlString.IndexOf("call") && + sqlString.IndexOf("=") < sqlString.IndexOf("call"); + + return callableDetail; } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -13,8 +13,6 @@ private readonly List<int> ordinalParameterLocationList = new List<int>(); - private bool hasReturnValue = false; - /// <summary> /// Convenience method for creating a param location recognizer and /// initiating the parse. @@ -49,16 +47,11 @@ get { return ordinalParameterLocationList; } } - public bool HasReturnValue - { - get { return hasReturnValue; } - } - #region IRecognizer Members public void OutParameter(int position) { - hasReturnValue = true; + // don't care... } public void OrdinalParameter(int position) Modified: trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -12,17 +12,8 @@ private static readonly OrdinalParameterDescriptor[] EmptyOrdinals = new OrdinalParameterDescriptor[0]; private readonly OrdinalParameterDescriptor[] ordinalDescriptors; private readonly Dictionary<string, NamedParameterDescriptor> namedDescriptorMap; - private readonly bool hasReturnValue = false; public ParameterMetadata(OrdinalParameterDescriptor[] ordinalDescriptors, - IDictionary<string, NamedParameterDescriptor> namedDescriptorMap, - bool hasReturnValue) - : this (ordinalDescriptors, namedDescriptorMap) - { - this.hasReturnValue = hasReturnValue; - } - - public ParameterMetadata(OrdinalParameterDescriptor[] ordinalDescriptors, IDictionary<string, NamedParameterDescriptor> namedDescriptorMap) { if (ordinalDescriptors == null) @@ -52,11 +43,6 @@ get { return namedDescriptorMap.Keys; } } - public bool HasReturnValue - { - get { return hasReturnValue; } - } - public OrdinalParameterDescriptor GetOrdinalParameterDescriptor(int position) { if (position < 1 || position > ordinalDescriptors.Length) Modified: trunk/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -44,8 +44,10 @@ public static void Parse(string sqlString, IRecognizer recognizer) { bool hasMainOutputParameter = sqlString.IndexOf("call") > 0 && - sqlString.IndexOf("?") < sqlString.IndexOf("call") && - sqlString.IndexOf("=") < sqlString.IndexOf("call"); + sqlString.IndexOf("?") > 0 && + sqlString.IndexOf("=") > 0 && + sqlString.IndexOf("?") < sqlString.IndexOf("call") && + sqlString.IndexOf("=") < sqlString.IndexOf("call"); bool foundMainOutputParam = false; int stringLength = sqlString.Length; Modified: trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -171,7 +171,7 @@ new NamedParameterDescriptor(name, null, description.BuildPositionsArray(), description.JpaStyle); } - return new ParameterMetadata(ordinalDescriptors, namedParamDescriptorMap, recognizer.HasReturnValue); + return new ParameterMetadata(ordinalDescriptors, namedParamDescriptorMap); } [Serializable] Modified: trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -279,8 +279,6 @@ public bool Callable { get; set; } - public bool HasReturnValue { get; set; } - public bool ReadOnly { get { return _readOnly; } Modified: trunk/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -27,7 +27,6 @@ private readonly IList<INativeSQLQueryReturn> queryReturns; private readonly ICollection<string> querySpaces; private readonly bool callable; - private readonly bool hasReturnValue; private bool autoDiscoverTypes; /// <summary> Constructs a SQLQueryImpl given a sql query defined in the mappings. </summary> @@ -53,9 +52,16 @@ querySpaces = queryDef.QuerySpaces; callable = queryDef.IsCallable; - hasReturnValue = parameterMetadata.HasReturnValue; } + internal SqlQueryImpl(string sql, IList<INativeSQLQueryReturn> queryReturns, ICollection<string> querySpaces, FlushMode flushMode, bool callable, ISessionImplementor session, ParameterMetadata parameterMetadata) + : base(sql, flushMode, session, parameterMetadata) + { + this.queryReturns = queryReturns; + this.querySpaces = querySpaces; + this.callable = callable; + } + internal SqlQueryImpl(string sql, string[] returnAliases, System.Type[] returnClasses, LockMode[] lockModes, ISessionImplementor session, ICollection<string> querySpaces, FlushMode flushMode, ParameterMetadata parameterMetadata) : base(sql, flushMode, session, parameterMetadata) { @@ -174,7 +180,6 @@ { QueryParameters qp = base.GetQueryParameters(namedParams); qp.Callable = callable; - qp.HasReturnValue = hasReturnValue; qp.HasAutoDiscoverScalarTypes = autoDiscoverTypes; return qp; } Modified: trunk/nhibernate/src/NHibernate/Loader/Loader.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -11,7 +11,6 @@ using NHibernate.Cache; using NHibernate.Collection; using NHibernate.Engine; -using NHibernate.Engine.Query; using NHibernate.Event; using NHibernate.Exceptions; using NHibernate.Hql.Util; @@ -1105,8 +1104,7 @@ bool useLimit = UseLimit(selection, dialect); bool hasFirstRow = GetFirstRow(selection) > 0; bool useOffset = hasFirstRow && useLimit && dialect.SupportsLimitOffset; - bool isCallable = queryParameters.Callable; - bool hasReturnValue = queryParameters.HasReturnValue; + // TODO NH bool callable = queryParameters.Callable; if (useLimit) { @@ -1116,19 +1114,10 @@ sqlString = PreprocessSQL(sqlString, queryParameters, dialect); - IDbCommand command = null; - if (isCallable) - { - command = - session.Batcher.PrepareQueryCommand(CommandType.StoredProcedure, CallableParser.Parse(sqlString.ToString()), - GetParameterTypes(queryParameters, useLimit, useOffset)); - } - else - { - command = - session.Batcher.PrepareQueryCommand(CommandType.Text, sqlString, - GetParameterTypes(queryParameters, useLimit, useOffset)); - } + // TODO NH: Callable for SP -> PrepareCallableQueryCommand + IDbCommand command = + session.Batcher.PrepareQueryCommand(CommandType.Text, sqlString, + GetParameterTypes(queryParameters, useLimit, useOffset)); try { @@ -1144,13 +1133,12 @@ { colIndex += BindLimitParameters(command, colIndex, selection, session); } + // TODO NH + //if (callable) + //{ + // colIndex = dialect.RegisterResultSetOutParameter(command, col); + //} - if (isCallable) - { - colIndex += - session.Factory.ConnectionProvider.Driver.RegisterResultSetOutParameter(command, colIndex, hasReturnValue); - } - colIndex += BindParameterValues(command, queryParameters, colIndex, session); if (useLimit && !dialect.BindLimitParametersFirst) @@ -1275,7 +1263,7 @@ // NH Different behavior: // The responsibility of parameter binding was entirely moved to QueryParameters // to deal with positionslParameter+NamedParameter+ParameterOfFilters - return queryParameters.BindParameters(statement, GetNamedParameterLocs, startIndex, session); + return queryParameters.BindParameters(statement, GetNamedParameterLocs, 0, session); } public virtual int[] GetNamedParameterLocs(string name) Modified: trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -3332,20 +3332,20 @@ SqlCommandInfo defaultDelete = GenerateDeleteString(j); sqlInsertStrings[j] = customSQLInsert[j] != null - ? new SqlCommandInfo(customSQLInsert[j], insertCallable[j], defaultInsert.ParameterTypes) + ? new SqlCommandInfo(customSQLInsert[j], defaultInsert.ParameterTypes) : defaultInsert; sqlUpdateStrings[j] = customSQLUpdate[j] != null - ? new SqlCommandInfo(customSQLUpdate[j], updateCallable[j], defaultUpdate.ParameterTypes) + ? new SqlCommandInfo(customSQLUpdate[j], defaultUpdate.ParameterTypes) : defaultUpdate; // NH: in practice for lazy update de update sql is the same any way. sqlLazyUpdateStrings[j] = customSQLUpdate[j] != null - ? new SqlCommandInfo(customSQLUpdate[j], updateCallable[j], defaultUpdate.ParameterTypes) + ? new SqlCommandInfo(customSQLUpdate[j], defaultUpdate.ParameterTypes) : GenerateUpdateString(NonLazyPropertyUpdateability, j, false); sqlDeleteStrings[j] = customSQLDelete[j] != null - ? new SqlCommandInfo(customSQLDelete[j], deleteCallable[j], defaultDelete.ParameterTypes) + ? new SqlCommandInfo(customSQLDelete[j], defaultDelete.ParameterTypes) : defaultDelete; } Modified: trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs =================================================================== --- trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -1,12 +1,10 @@ using System.Data; -using NHibernate.Engine.Query; using NHibernate.SqlTypes; namespace NHibernate.SqlCommand { public class SqlCommandInfo { - private readonly CommandType commandType; private readonly SqlString text; private readonly SqlType[] parameterTypes; @@ -14,22 +12,12 @@ { this.text = text; this.parameterTypes = parameterTypes; - this.commandType = CommandType.Text; } - public SqlCommandInfo(SqlString text, bool isStoredProcedure, SqlType[] parameterTypes) - : this(text, parameterTypes) - { - if (isStoredProcedure) - { - this.commandType = CommandType.StoredProcedure; - this.text = CallableParser.Parse(text.ToString()); - } - } - public CommandType CommandType { - get { return commandType; } + // Always Text for now + get { return CommandType.Text; } } public SqlString Text Modified: trunk/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -9,12 +9,12 @@ public class CallableParserFixture { [Test] - public void CanFindCallableFunctionName() + public void CanDetermineIsCallable() { string query = @"{ call myFunction(:name) }"; - SqlString sqlFunction = CallableParser.Parse(query); - Assert.That(sqlFunction.ToString(), Is.EqualTo("myFunction")); + CallableParser.Detail detail = CallableParser.Parse(query); + Assert.That(detail.IsCallable, Is.True); } [Test] @@ -22,19 +22,44 @@ { string query = @"SELECT id FROM mytable"; - Assert.Throws<ParserException>(() => - { - SqlString sqlFunction = CallableParser.Parse(query); - }); + CallableParser.Detail detail = CallableParser.Parse(query); + Assert.That(detail.IsCallable, Is.False); } [Test] + public void CanFindCallableFunctionName() + { + string query = @"{ call myFunction(:name) }"; + + CallableParser.Detail detail = CallableParser.Parse(query); + Assert.That(detail.FunctionName, Is.EqualTo("myFunction")); + } + + [Test] public void CanFindCallableFunctionNameWithoutParameters() { string query = @"{ call myFunction }"; - SqlString sqlFunction = CallableParser.Parse(query); - Assert.That(sqlFunction.ToString(), Is.EqualTo("myFunction")); + CallableParser.Detail detail = CallableParser.Parse(query); + Assert.That(detail.FunctionName, Is.EqualTo("myFunction")); } + + [Test] + public void CanDetermineHasReturn() + { + string query = @"{ ? = call myFunction(:name) }"; + + CallableParser.Detail detail = CallableParser.Parse(query); + Assert.That(detail.HasReturn, Is.True); + } + + [Test] + public void CanDetermineHasNoReturn() + { + string query = @"{ call myFunction(:name) }"; + + CallableParser.Detail detail = CallableParser.Parse(query); + Assert.That(detail.HasReturn, Is.False); + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs 2009-10-29 14:31:35 UTC (rev 4806) @@ -59,22 +59,5 @@ Assert.DoesNotThrow(() => p = recognizer.NamedParameterDescriptionMap["pizza"]); } - [Test] - public void CanRecogniseNoReturnValueParameter() - { - string query = "{ call myFunction(?) }"; - ParamLocationRecognizer recognizer = new ParamLocationRecognizer(); - ParameterParser.Parse(query, recognizer); - Assert.That(recognizer.HasReturnValue, Is.False); - } - - [Test] - public void CanRecogniseReturnValueParameter() - { - string query = "{ ? = call myFunction(?) }"; - ParamLocationRecognizer recognizer = new ParamLocationRecognizer(); - ParameterParser.Parse(query, recognizer); - Assert.That(recognizer.HasReturnValue, Is.True); - } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml 2009-10-29 14:31:35 UTC (rev 4806) @@ -39,7 +39,7 @@ </id> <property name="name" not-null="true"/> <loader query-ref="person"/> - <sql-insert callable="true" check="none">{ call createPerson(?, ?) }</sql-insert> + <sql-insert check="none">{ call createPerson(?, ?) }</sql-insert> <sql-update>UPDATE PERSON SET NAME=UPPER(?) WHERE PERID=?</sql-update> <sql-delete>DELETE FROM PERSON WHERE PERID=?</sql-delete> </class> @@ -204,7 +204,7 @@ <database-object> <create> - CREATE OR REPLACE PROCEDURE createPerson(p_name PERSON.NAME%TYPE, p_id PERSON.PERID%TYPE) + CREATE OR REPLACE PROCEDURE createPerson(unused OUT SYS_REFCURSOR, p_name PERSON.NAME%TYPE, p_id PERSON.PERID%TYPE) AS rowcount INTEGER; BEGIN Modified: trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml 2009-10-29 14:30:40 UTC (rev 4805) +++ trunk/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml 2009-10-29 14:31:35 UTC (rev 4806) @@ -8,25 +8,25 @@ namespace="NHibernate.Test.SqlTest" default-access="field"> - <sql-query name="simpleScalar" callable="true"> + <sql-query name="simpleScalar"> <return-scalar column="name" type="string"/> <return-scalar column="value" type="long"/> { ? = call simpleScalar(:number) } </sql-query> - <sql-query name="paramhandling" callable="true"> + <sql-query name="paramhandling"> <return-scalar column="value" type="long"/> <return-scalar column="value2" type="long"/> { ? = call testParamHandling(?, ?) } </sql-query> - <sql-query name="paramhandling_mixed" callable="true"> + <sql-query name="paramhandling_mixed"> <return-scalar column="value" type="long"/> <return-scalar column="value2" type="long"/> { ? = call testParamHandling(?,:second) } </sql-query> - <sql-query name="selectAllEmployments" callable="true"> + <sql-query name="selectAllEmployments"> <return alias="emp" class="Employment"> <return-property name="employee" column="EMPLOYEE"/> <return-property name="employer" column="EMPLOYER"/> @@ -42,7 +42,7 @@ { ? = call allEmployments } </sql-query> - <sql-query name="selectEmploymentsForRegion" callable="true"> + <sql-query name="selectEmploymentsForRegion"> <return alias="emp" class="Employment"> <return-property name="employee" column="EMPLOYEE"/> <return-property name="employer" column="EMPLOYER"/> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2009-10-30 10:55:45
|
Revision: 4808 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4808&view=rev Author: ricbrown Date: 2009-10-30 10:55:36 +0000 (Fri, 30 Oct 2009) Log Message: ----------- Merge r4807 (Fix NH-2003, not null constraint on identifier column) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassIdBinder.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Model.cs Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassIdBinder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassIdBinder.cs 2009-10-30 10:54:56 UTC (rev 4807) +++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassIdBinder.cs 2009-10-30 10:55:36 UTC (rev 4808) @@ -234,7 +234,7 @@ if (columnSchema.length != null) column.Length = int.Parse(columnSchema.length); - column.IsNullable = columnSchema.notnullSpecified ? columnSchema.notnull : false; + column.IsNullable = columnSchema.notnullSpecified ? !columnSchema.notnull : false; column.IsUnique = columnSchema.uniqueSpecified && columnSchema.unique; column.CheckConstraint = columnSchema.check ?? string.Empty; column.SqlType = columnSchema.sqltype; Property changes on: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003 ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Fixture.cs 2009-10-30 10:55:36 UTC (rev 4808) @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; +using NHibernate.Cfg; +using NHibernate.Tool.hbm2ddl; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH2003 +{ + [TestFixture] + public class Fixture : BugTestCase + { + [Test] + public void ShouldCreateNotNullIdColumn() + { + StringBuilder script = new StringBuilder(); + + Configuration cfg = TestConfigurationHelper.GetDefaultConfiguration(); + using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(MappingsAssembly + "." + (string)Mappings[0])) + cfg.AddInputStream(stream); + new SchemaExport(cfg).Execute(s => script.AppendLine(s), false, false); + + string wholeScript = script.ToString(); + Assert.That(wholeScript.ToLower(), Text.Contains("not null")); + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Mappings.hbm.xml 2009-10-30 10:55:36 UTC (rev 4808) @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.NH2003" + assembly="NHibernate.Test"> + + <class name="MyClass"> + <id name="Id"> + <column name="IdColumn" not-null="true"/> + <generator class="hilo" /> + </id> + </class> +</hibernate-mapping> + + Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Model.cs 2009-10-30 10:55:36 UTC (rev 4808) @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH2003 +{ + public class MyClass + { + public virtual int Id { get; set; } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-30 10:54:56 UTC (rev 4807) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-30 10:55:36 UTC (rev 4808) @@ -637,6 +637,8 @@ <Compile Include="NHSpecificTest\NH1985\SampleTest.cs" /> <Compile Include="NHSpecificTest\NH1990\Fixture.cs" /> <Compile Include="NHSpecificTest\NH1990\Model.cs" /> + <Compile Include="NHSpecificTest\NH2003\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2003\Model.cs" /> <Compile Include="NHSpecificTest\NH473\Child.cs" /> <Compile Include="NHSpecificTest\NH473\Fixture.cs" /> <Compile Include="NHSpecificTest\NH473\Parent.cs" /> @@ -2050,6 +2052,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\NH2003\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1356\MappingsBag.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1356\MappingsList.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1356\MappingsSet.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-31 15:26:32
|
Revision: 4810 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4810&view=rev Author: fabiomaulo Date: 2009-10-31 15:26:23 +0000 (Sat, 31 Oct 2009) Log Message: ----------- Merge r4809 (fix NH-2000) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/DomainClass.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/SampleTest.cs Modified: trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2009-10-31 15:22:21 UTC (rev 4809) +++ trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2009-10-31 15:26:23 UTC (rev 4810) @@ -2238,7 +2238,9 @@ using (new SessionIdLoggingContext(SessionId)) { CheckAndUpdateSessionStatus(); - return enabledFilters[filterName]; + IFilter result; + enabledFilters.TryGetValue(filterName, out result); + return result; } } Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/DomainClass.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/DomainClass.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/DomainClass.cs 2009-10-31 15:26:23 UTC (rev 4810) @@ -0,0 +1,9 @@ +namespace NHibernate.Test.NHSpecificTest.NH2000 +{ + public class DomainClass + { + public int Id { get; set; } + + public byte[] ByteData { get; set; } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/Mappings.hbm.xml 2009-10-31 15:26:23 UTC (rev 4810) @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH2000" + default-lazy="false"> + <class name="DomainClass"> + <id name="Id"> + <generator class="assigned" /> + </id> + <property name="ByteData" /> + <filter name="TestFilter" condition="True"></filter> + </class> + <filter-def name="TestFilter"> + </filter-def> +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/SampleTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/SampleTest.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/SampleTest.cs 2009-10-31 15:26:23 UTC (rev 4810) @@ -0,0 +1,19 @@ +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH2000 +{ + [TestFixture] + public class SampleTest : BugTestCase + { + // In this version of nHibernate, GetEnabledFilter throws an exception + // instead returning nothing like in previous versions. + [Test] + public void TestSessionGetEnableFilter() + { + using (ISession session = OpenSession()) + { + IFilter filter = session.GetEnabledFilter("TestFilter"); + } + } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-31 15:22:21 UTC (rev 4809) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-31 15:26:23 UTC (rev 4810) @@ -637,6 +637,8 @@ <Compile Include="NHSpecificTest\NH1985\SampleTest.cs" /> <Compile Include="NHSpecificTest\NH1990\Fixture.cs" /> <Compile Include="NHSpecificTest\NH1990\Model.cs" /> + <Compile Include="NHSpecificTest\NH2000\DomainClass.cs" /> + <Compile Include="NHSpecificTest\NH2000\SampleTest.cs" /> <Compile Include="NHSpecificTest\NH2003\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2003\Model.cs" /> <Compile Include="NHSpecificTest\NH473\Child.cs" /> @@ -2052,6 +2054,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\NH2000\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2003\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1356\MappingsBag.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1356\MappingsList.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-31 17:37:47
|
Revision: 4812 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4812&view=rev Author: fabiomaulo Date: 2009-10-31 17:37:39 +0000 (Sat, 31 Oct 2009) Log Message: ----------- Merge r4811 (fix NH-1998) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs trunk/nhibernate/src/NHibernate/Engine/FilterDefinition.cs trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs trunk/nhibernate/src/NHibernate/Util/FilterHelper.cs trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs 2009-10-31 17:33:40 UTC (rev 4811) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs 2009-10-31 17:37:39 UTC (rev 4812) @@ -4918,6 +4918,15 @@ /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string condition; + + /// <remarks/> + [System.Xml.Serialization.XmlAttributeAttribute("use-many-to-one")] + [System.ComponentModel.DefaultValueAttribute(true)] + public bool usemanytoone; + + public HbmFilterDef() { + this.usemanytoone = true; + } } /// <remarks/> Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs 2009-10-31 17:33:40 UTC (rev 4811) +++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs 2009-10-31 17:37:39 UTC (rev 4812) @@ -19,7 +19,7 @@ log.DebugFormat("Parsed filter-def [{0}]", filterDefSchema.name); - return new FilterDefinition(filterDefSchema.name, defaultCondition, parameterTypes); + return new FilterDefinition(filterDefSchema.name, defaultCondition, parameterTypes, filterDefSchema.usemanytoone); } private static IDictionary<string, IType> GetFilterParameterTypes(HbmFilterDef filterDefSchema) Modified: trunk/nhibernate/src/NHibernate/Engine/FilterDefinition.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/FilterDefinition.cs 2009-10-31 17:33:40 UTC (rev 4811) +++ trunk/nhibernate/src/NHibernate/Engine/FilterDefinition.cs 2009-10-31 17:37:39 UTC (rev 4812) @@ -14,22 +14,35 @@ private readonly string filterName; private readonly string defaultFilterCondition; private readonly IDictionary<string, IType> parameterTypes= new Dictionary<string, IType>(); + private readonly bool useInManyToOne; /// <summary> - /// Set the named parameter's value list for this filter. + /// Set the named parameter's value list for this filter. /// </summary> /// <param name="name">The name of the filter for which this configuration is in effect.</param> /// <param name="defaultCondition">The default filter condition.</param> - /// <param name="parameterTypes">A dictionary storing the NHibernate <see cref="IType" /> type + /// <param name="parameterTypes">A dictionary storing the NHibernate <see cref="IType"/> type /// of each parameter under its name.</param> - public FilterDefinition(string name, string defaultCondition, IDictionary<string, IType> parameterTypes) + /// <param name="useManyToOne">if set to <c>true</c> used in many to one rel</param> + public FilterDefinition(string name, string defaultCondition, IDictionary<string, IType> parameterTypes, + bool useManyToOne) { filterName = name; defaultFilterCondition = defaultCondition; this.parameterTypes = parameterTypes; + useInManyToOne = useManyToOne; } /// <summary> + /// Gets a value indicating whether to use this filter-def in manytoone refs. + /// </summary> + /// <value><c>true</c> if [use in many to one]; otherwise, <c>false</c>.</value> + public bool UseInManyToOne + { + get { return useInManyToOne; } + } + + /// <summary> /// Get the name of the filter this configuration defines. /// </summary> /// <returns>The filter name for this configuration.</returns> Modified: trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2009-10-31 17:33:40 UTC (rev 4811) +++ trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2009-10-31 17:37:39 UTC (rev 4812) @@ -184,14 +184,10 @@ { // NH Different behavior : NH1179 and NH1293 // Apply filters in Many-To-One association - if (string.IsNullOrEmpty(on) && enabledFilters.Count > 0) - { - condition = join.Joinable.FilterFragment(join.Alias, enabledFilters); - } - else - { - condition = on; - } + var enabledForManyToOne = FilterHelper.GetEnabledForManyToOne(enabledFilters); + condition = string.IsNullOrEmpty(on) && enabledForManyToOne.Count > 0 + ? join.Joinable.FilterFragment(join.Alias, enabledForManyToOne) + : on; } if (withClauseFragment != null) Modified: trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2009-10-31 17:33:40 UTC (rev 4811) +++ trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2009-10-31 17:37:39 UTC (rev 4812) @@ -17,6 +17,7 @@ protected readonly IList<OuterJoinableAssociation> associations = new List<OuterJoinableAssociation>(); private readonly ISet<AssociationKey> visitedAssociationKeys = new HashedSet<AssociationKey>(); private readonly IDictionary<string, IFilter> enabledFilters; + private readonly IDictionary<string, IFilter> enabledFiltersForManyToOne; private string[] suffixes; private string[] collectionSuffixes; @@ -113,6 +114,7 @@ { this.factory = factory; this.enabledFilters = enabledFilters; + enabledFiltersForManyToOne = FilterHelper.GetEnabledForManyToOne(enabledFilters); } /// <summary> @@ -566,12 +568,15 @@ oj.AddJoins(outerjoin); // NH Different behavior : NH1179 and NH1293 // Apply filters in Many-To-One association - if (enabledFilters.Count > 0) + if (enabledFiltersForManyToOne.Count > 0) { - var manyToOneFilterFragment = oj.Joinable.FilterFragment(oj.RHSAlias, enabledFilters); - var joinClauseDoesNotContainsFilterAlready = outerjoin.ToFromFragmentString.IndexOfCaseInsensitive(manyToOneFilterFragment) == -1; - if(joinClauseDoesNotContainsFilterAlready) + string manyToOneFilterFragment = oj.Joinable.FilterFragment(oj.RHSAlias, enabledFiltersForManyToOne); + bool joinClauseDoesNotContainsFilterAlready = + outerjoin.ToFromFragmentString.IndexOfCaseInsensitive(manyToOneFilterFragment) == -1; + if (joinClauseDoesNotContainsFilterAlready) + { outerjoin.AddCondition(manyToOneFilterFragment); + } } } last = oj; Modified: trunk/nhibernate/src/NHibernate/Util/FilterHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Util/FilterHelper.cs 2009-10-31 17:33:40 UTC (rev 4811) +++ trunk/nhibernate/src/NHibernate/Util/FilterHelper.cs 2009-10-31 17:37:39 UTC (rev 4812) @@ -67,5 +67,21 @@ } } } + + /// <summary> + /// Get only filters enabled for many-to-one association. + /// </summary> + /// <param name="enabledFilters">All enabled filters</param> + /// <returns>A new <see cref="IDictionary{TKey,TValue}"/> for filters enabled for many to one.</returns> + public static IDictionary<string, IFilter> GetEnabledForManyToOne(IDictionary<string, IFilter> enabledFilters) + { + var enabledFiltersForManyToOne = new Dictionary<string, IFilter>(); + foreach (var enabledFilter in enabledFilters) + { + if (enabledFilter.Value.FilterDefinition.UseInManyToOne) + enabledFiltersForManyToOne.Add(enabledFilter.Key, enabledFilter.Value); + } + return enabledFiltersForManyToOne; + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd =================================================================== --- trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2009-10-31 17:33:40 UTC (rev 4811) +++ trunk/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2009-10-31 17:37:39 UTC (rev 4812) @@ -468,6 +468,7 @@ </xs:choice> <xs:attribute name="name" use="required" type="xs:string" /> <xs:attribute name="condition" type="xs:string" /> + <xs:attribute name="use-many-to-one" default="true" type="xs:boolean"/> </xs:complexType> </xs:element> <xs:element name="filter-param"> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs 2009-10-31 17:37:39 UTC (rev 4812) @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.ManyToOneFilters20Behaviour +{ + [TestFixture] + public class Fixture : BugTestCase + { + private static IList<Parent> joinGraphUsingHql(ISession s) + { + const string hql = @"select p from Parent p + join p.Child c"; + return s.CreateQuery(hql).List<Parent>(); + } + + private static IList<Parent> joinGraphUsingCriteria(ISession s) + { + return s.CreateCriteria(typeof (Parent)).SetFetchMode("Child", FetchMode.Join).List<Parent>(); + } + + private static Parent createParent() + { + return new Parent {Child = new Child()}; + } + + private static void enableFilters(ISession s) + { + IFilter f = s.EnableFilter("activeChild"); + f.SetParameter("active", 1); + IFilter f2 = s.EnableFilter("alwaysValid"); + f2.SetParameter("always", 1); + } + + protected override void OnTearDown() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + s.Delete("from Parent"); + tx.Commit(); + } + } + } + + [Test] + public void VerifyAlwaysFilter() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + Parent p = createParent(); + p.Child.Always = false; + s.Save(p); + tx.Commit(); + } + } + + using (ISession s = OpenSession()) + { + enableFilters(s); + IList<Parent> resCriteria = joinGraphUsingCriteria(s); + IList<Parent> resHql = joinGraphUsingHql(s); + + Assert.AreEqual(0, resCriteria.Count); + Assert.AreEqual(0, resHql.Count); + } + } + + [Test] + public void VerifyFilterActiveButNotUsedInManyToOne() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + s.Save(createParent()); + tx.Commit(); + } + } + + using (ISession s = OpenSession()) + { + enableFilters(s); + IList<Parent> resCriteria = joinGraphUsingCriteria(s); + IList<Parent> resHql = joinGraphUsingHql(s); + + Assert.AreEqual(1, resCriteria.Count); + Assert.IsNotNull(resCriteria[0].Child); + + Assert.AreEqual(1, resHql.Count); + Assert.IsNotNull(resHql[0].Child); + } + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml 2009-10-31 17:37:39 UTC (rev 4812) @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.ManyToOneFilters20Behaviour" + assembly="NHibernate.Test"> + + <class name="Parent"> + <id name="Id"> + <generator class="guid.comb" /> + </id> + + <many-to-one name="Child" class="Child" cascade="all" not-null="true"/> + </class> + + <class name="Child"> + <id name="Id"> + <generator class="guid.comb" /> + </id> + <property name="IsActive"/> + <property name="Always"/> + <filter name="activeChild" condition=":active = IsActive" /> + <filter name="alwaysValid" condition=":always = Always" /> + </class> + + <filter-def name="activeChild" use-many-to-one="false"> + <filter-param name="active" type="int"/> + </filter-def> + + <filter-def name="alwaysValid"> + <filter-param name="always" type="int"/> + </filter-def> +</hibernate-mapping> + Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs 2009-10-31 17:37:39 UTC (rev 4812) @@ -0,0 +1,22 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.ManyToOneFilters20Behaviour +{ + public class Parent + { + public virtual Guid Id { get; set; } + public virtual Child Child { get; set; } + } + + public class Child + { + public Child() + { + Always = true; + } + + public virtual Guid Id { get; set; } + public virtual bool IsActive { get; set; } + public virtual bool Always { get; set; } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-31 17:33:40 UTC (rev 4811) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-31 17:37:39 UTC (rev 4812) @@ -402,6 +402,8 @@ <Compile Include="NHSpecificTest\ElementsEnums\IntEnumsBagFixture.cs" /> <Compile Include="NHSpecificTest\ElementsEnums\Something.cs" /> <Compile Include="NHSpecificTest\Futures\FutureQueryOverFixture.cs" /> + <Compile Include="NHSpecificTest\ManyToOneFilters20Behaviour\Fixture.cs" /> + <Compile Include="NHSpecificTest\ManyToOneFilters20Behaviour\Model.cs" /> <Compile Include="NHSpecificTest\NH1255\Domain.cs" /> <Compile Include="NHSpecificTest\NH1255\Fixture.cs" /> <Compile Include="NHSpecificTest\NH1785\Domain.cs" /> @@ -2054,6 +2056,7 @@ <EmbeddedResource Include="CfgTest\Loquacious\EntityToCache.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\ManyToOneFilters20Behaviour\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2000\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2003\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1356\MappingsBag.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2009-11-03 16:11:32
|
Revision: 4817 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4817&view=rev Author: ricbrown Date: 2009-11-03 16:11:25 +0000 (Tue, 03 Nov 2009) Log Message: ----------- Added overloads for IQueryOver.JoinQueryOver and IQueryOver.Join using aliases. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs trunk/nhibernate/src/NHibernate/Criterion/QueryOverJoinBuilder.cs trunk/nhibernate/src/NHibernate/IQueryOver.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs Modified: trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2009-10-31 18:34:16 UTC (rev 4816) +++ trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2009-11-03 16:11:25 UTC (rev 4817) @@ -161,6 +161,13 @@ ExpressionProcessor.FindMemberExpression(path.Body))); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path) + { + return new QueryOver<U>(_impl, + _criteria.CreateCriteria( + ExpressionProcessor.FindMemberExpression(path.Body))); + } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<T, U>> path, Expression<Func<U>> alias) { return new QueryOver<U>(_impl, @@ -169,6 +176,14 @@ ExpressionProcessor.FindMemberExpression(alias.Body))); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path, Expression<Func<U>> alias) + { + return new QueryOver<U>(_impl, + _criteria.CreateCriteria( + ExpressionProcessor.FindMemberExpression(path.Body), + ExpressionProcessor.FindMemberExpression(alias.Body))); + } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<T, U>> path, JoinType joinType) { return new QueryOver<U>(_impl, @@ -177,6 +192,14 @@ joinType)); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path, JoinType joinType) + { + return new QueryOver<U>(_impl, + _criteria.CreateCriteria( + ExpressionProcessor.FindMemberExpression(path.Body), + joinType)); + } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<T, U>> path, Expression<Func<U>> alias, JoinType joinType) { return new QueryOver<U>(_impl, @@ -186,6 +209,15 @@ joinType)); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path, Expression<Func<U>> alias, JoinType joinType) + { + return new QueryOver<U>(_impl, + _criteria.CreateCriteria( + ExpressionProcessor.FindMemberExpression(path.Body), + ExpressionProcessor.FindMemberExpression(alias.Body), + joinType)); + } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path, Expression<Func<U>> alias) { return new QueryOver<U>(_impl, @@ -194,6 +226,14 @@ ExpressionProcessor.FindMemberExpression(alias.Body))); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path, Expression<Func<U>> alias) + { + return new QueryOver<U>(_impl, + _criteria.CreateCriteria( + ExpressionProcessor.FindMemberExpression(path.Body), + ExpressionProcessor.FindMemberExpression(alias.Body))); + } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path) { return new QueryOver<U>(_impl, @@ -201,6 +241,13 @@ ExpressionProcessor.FindMemberExpression(path.Body))); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path) + { + return new QueryOver<U>(_impl, + _criteria.CreateCriteria( + ExpressionProcessor.FindMemberExpression(path.Body))); + } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path, Expression<Func<U>> alias, JoinType joinType) { return new QueryOver<U>(_impl, @@ -210,6 +257,15 @@ joinType)); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path, Expression<Func<U>> alias, JoinType joinType) + { + return new QueryOver<U>(_impl, + _criteria.CreateCriteria( + ExpressionProcessor.FindMemberExpression(path.Body), + ExpressionProcessor.FindMemberExpression(alias.Body), + joinType)); + } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path, JoinType joinType) { return new QueryOver<U>(_impl, @@ -218,6 +274,14 @@ joinType)); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path, JoinType joinType) + { + return new QueryOver<U>(_impl, + _criteria.CreateCriteria( + ExpressionProcessor.FindMemberExpression(path.Body), + joinType)); + } + public QueryOver<T> Join(Expression<Func<T, object>> path, Expression<Func<object>> alias) { return AddAlias( @@ -226,6 +290,14 @@ JoinType.InnerJoin); } + public QueryOver<T> Join(Expression<Func<object>> path, Expression<Func<object>> alias) + { + return AddAlias( + ExpressionProcessor.FindMemberExpression(path.Body), + ExpressionProcessor.FindMemberExpression(alias.Body), + JoinType.InnerJoin); + } + public QueryOver<T> Join(Expression<Func<T, object>> path, Expression<Func<object>> alias, JoinType joinType) { return AddAlias( @@ -234,6 +306,14 @@ joinType); } + public QueryOver<T> Join(Expression<Func<object>> path, Expression<Func<object>> alias, JoinType joinType) + { + return AddAlias( + ExpressionProcessor.FindMemberExpression(path.Body), + ExpressionProcessor.FindMemberExpression(alias.Body), + joinType); + } + public QueryOverJoinBuilder<T> Inner { get { return new QueryOverJoinBuilder<T>(this, JoinType.InnerJoin); } @@ -394,33 +474,63 @@ IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<T, U>> path) { return JoinQueryOver(path); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<U>> path) + { return JoinQueryOver(path); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<T, U>> path, Expression<Func<U>> alias) { return JoinQueryOver(path, alias); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<U>> path, Expression<Func<U>> alias) + { return JoinQueryOver(path, alias); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<T, U>> path, JoinType joinType) { return JoinQueryOver(path, joinType); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<U>> path, JoinType joinType) + { return JoinQueryOver(path, joinType); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<T, U>> path, Expression<Func<U>> alias, JoinType joinType) { return JoinQueryOver(path, alias, joinType); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<U>> path, Expression<Func<U>> alias, JoinType joinType) + { return JoinQueryOver(path, alias, joinType); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path) { return JoinQueryOver(path); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path) + { return JoinQueryOver(path); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path, Expression<Func<U>> alias) { return JoinQueryOver(path, alias); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path, Expression<Func<U>> alias) + { return JoinQueryOver(path, alias); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path, JoinType joinType) { return JoinQueryOver(path, joinType); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path, JoinType joinType) + { return JoinQueryOver(path, joinType); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path, Expression<Func<U>> alias, JoinType joinType) { return JoinQueryOver(path, alias, joinType); } + IQueryOver<U> IQueryOver<T>.JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path, Expression<Func<U>> alias, JoinType joinType) + { return JoinQueryOver(path, alias, joinType); } + IQueryOver<T> IQueryOver<T>.Join(Expression<Func<T, object>> path, Expression<Func<object>> alias) { return Join(path, alias); } + IQueryOver<T> IQueryOver<T>.Join(Expression<Func<object>> path, Expression<Func<object>> alias) + { return Join(path, alias); } + IQueryOver<T> IQueryOver<T>.Join(Expression<Func<T, object>> path, Expression<Func<object>> alias, JoinType joinType) { return Join(path, alias, joinType); } + IQueryOver<T> IQueryOver<T>.Join(Expression<Func<object>> path, Expression<Func<object>> alias, JoinType joinType) + { return Join(path, alias, joinType); } + IQueryOverJoinBuilder<T> IQueryOver<T>.Inner { get { return new IQueryOverJoinBuilder<T>(this, JoinType.InnerJoin); } } Modified: trunk/nhibernate/src/NHibernate/Criterion/QueryOverJoinBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/QueryOverJoinBuilder.cs 2009-10-31 18:34:16 UTC (rev 4816) +++ trunk/nhibernate/src/NHibernate/Criterion/QueryOverJoinBuilder.cs 2009-11-03 16:11:25 UTC (rev 4817) @@ -18,21 +18,41 @@ return root.JoinQueryOver<U>(path, joinType); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path) + { + return root.JoinQueryOver<U>(path, joinType); + } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<T, U>> path, Expression<Func<U>> alias) { return root.JoinQueryOver<U>(path, alias, joinType); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path, Expression<Func<U>> alias) + { + return root.JoinQueryOver<U>(path, alias, joinType); + } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path) { return root.JoinQueryOver<U>(path, joinType); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path) + { + return root.JoinQueryOver<U>(path, joinType); + } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path, Expression<Func<U>> alias) { return root.JoinQueryOver<U>(path, alias, joinType); } + public QueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path, Expression<Func<U>> alias) + { + return root.JoinQueryOver<U>(path, alias, joinType); + } + } public class IQueryOverJoinBuilder<T> : QueryOverJoinBuilderBase<IQueryOver<T>, T> @@ -44,21 +64,41 @@ return root.JoinQueryOver<U>(path, joinType); } + public IQueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path) + { + return root.JoinQueryOver<U>(path, joinType); + } + public IQueryOver<U> JoinQueryOver<U>(Expression<Func<T, U>> path, Expression<Func<U>> alias) { return root.JoinQueryOver<U>(path, alias, joinType); } + public IQueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path, Expression<Func<U>> alias) + { + return root.JoinQueryOver<U>(path, alias, joinType); + } + public IQueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path) { return root.JoinQueryOver<U>(path, joinType); } + public IQueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path) + { + return root.JoinQueryOver<U>(path, joinType); + } + public IQueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path, Expression<Func<U>> alias) { return root.JoinQueryOver<U>(path, alias, joinType); } + public IQueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path, Expression<Func<U>> alias) + { + return root.JoinQueryOver<U>(path, alias, joinType); + } + } public class QueryOverJoinBuilderBase<R, T> where R : IQueryOver<T> @@ -78,6 +118,11 @@ return (R)root.Join(path, alias, joinType); } + public R Join(Expression<Func<object>> path, Expression<Func<object>> alias) + { + return (R)root.Join(path, alias, joinType); + } + } } Modified: trunk/nhibernate/src/NHibernate/IQueryOver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/IQueryOver.cs 2009-10-31 18:34:16 UTC (rev 4816) +++ trunk/nhibernate/src/NHibernate/IQueryOver.cs 2009-11-03 16:11:25 UTC (rev 4817) @@ -155,7 +155,7 @@ IQueryOverLockBuilder<T> Lock(Expression<Func<object>> alias); /// <summary> - /// Creates a new NHibernate.ICriteria<T>, "rooted" at the associated entity + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity /// </summary> /// <typeparam name="U">Type of sub-criteria</typeparam> /// <param name="path">Lambda expression returning association path</param> @@ -163,35 +163,71 @@ IQueryOver<U> JoinQueryOver<U>(Expression<Func<T, U>> path); /// <summary> - /// Creates a new NHibernate.ICriteria<T>, "rooted" at the associated entity + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity /// </summary> /// <typeparam name="U">Type of sub-criteria</typeparam> /// <param name="path">Lambda expression returning association path</param> + /// <returns>The created "sub criteria"</returns> + IQueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path); + + /// <summary> + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity + /// </summary> + /// <typeparam name="U">Type of sub-criteria</typeparam> + /// <param name="path">Lambda expression returning association path</param> /// <param name="alias">Lambda expression returning alias reference</param> /// <returns>The created "sub criteria"</returns> IQueryOver<U> JoinQueryOver<U>(Expression<Func<T, U>> path, Expression<Func<U>> alias); /// <summary> - /// Creates a new NHibernate.ICriteria<T>, "rooted" at the associated entity + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity /// </summary> /// <typeparam name="U">Type of sub-criteria</typeparam> /// <param name="path">Lambda expression returning association path</param> + /// <param name="alias">Lambda expression returning alias reference</param> + /// <returns>The created "sub criteria"</returns> + IQueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path, Expression<Func<U>> alias); + + /// <summary> + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity + /// </summary> + /// <typeparam name="U">Type of sub-criteria</typeparam> + /// <param name="path">Lambda expression returning association path</param> /// <param name="joinType">Type of join</param> /// <returns>The created "sub criteria"</returns> IQueryOver<U> JoinQueryOver<U>(Expression<Func<T, U>> path, JoinType joinType); /// <summary> - /// Creates a new NHibernate.ICriteria<T>, "rooted" at the associated entity + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity /// </summary> /// <typeparam name="U">Type of sub-criteria</typeparam> /// <param name="path">Lambda expression returning association path</param> + /// <param name="joinType">Type of join</param> + /// <returns>The created "sub criteria"</returns> + IQueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path, JoinType joinType); + + /// <summary> + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity + /// </summary> + /// <typeparam name="U">Type of sub-criteria</typeparam> + /// <param name="path">Lambda expression returning association path</param> /// <param name="alias">Lambda expression returning alias reference</param> /// <param name="joinType">Type of join</param> /// <returns>The created "sub criteria"</returns> IQueryOver<U> JoinQueryOver<U>(Expression<Func<T, U>> path, Expression<Func<U>> alias, JoinType joinType); /// <summary> - /// Creates a new NHibernate.ICriteria<T>, "rooted" at the associated entity + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity + /// </summary> + /// <typeparam name="U">Type of sub-criteria</typeparam> + /// <param name="path">Lambda expression returning association path</param> + /// <param name="alias">Lambda expression returning alias reference</param> + /// <param name="joinType">Type of join</param> + /// <returns>The created "sub criteria"</returns> + IQueryOver<U> JoinQueryOver<U>(Expression<Func<U>> path, Expression<Func<U>> alias, JoinType joinType); + + /// <summary> + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity /// specifying a collection for the join. /// </summary> /// <typeparam name="U">Type of sub-criteria (type of the collection)</typeparam> @@ -200,37 +236,77 @@ IQueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path); /// <summary> - /// Creates a new NHibernate.ICriteria<T>, "rooted" at the associated entity + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity /// specifying a collection for the join. /// </summary> /// <typeparam name="U">Type of sub-criteria (type of the collection)</typeparam> /// <param name="path">Lambda expression returning association path</param> + /// <returns>The created "sub criteria"</returns> + IQueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path); + + /// <summary> + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity + /// specifying a collection for the join. + /// </summary> + /// <typeparam name="U">Type of sub-criteria (type of the collection)</typeparam> + /// <param name="path">Lambda expression returning association path</param> /// <param name="alias">Lambda expression returning alias reference</param> /// <returns>The created "sub criteria"</returns> IQueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path, Expression<Func<U>> alias); /// <summary> - /// Creates a new NHibernate.ICriteria<T>, "rooted" at the associated entity + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity /// specifying a collection for the join. /// </summary> /// <typeparam name="U">Type of sub-criteria (type of the collection)</typeparam> /// <param name="path">Lambda expression returning association path</param> + /// <param name="alias">Lambda expression returning alias reference</param> + /// <returns>The created "sub criteria"</returns> + IQueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path, Expression<Func<U>> alias); + + /// <summary> + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity + /// specifying a collection for the join. + /// </summary> + /// <typeparam name="U">Type of sub-criteria (type of the collection)</typeparam> + /// <param name="path">Lambda expression returning association path</param> /// <param name="joinType">Type of join</param> /// <returns>The created "sub criteria"</returns> IQueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path, JoinType joinType); /// <summary> - /// Creates a new NHibernate.ICriteria<T>, "rooted" at the associated entity + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity /// specifying a collection for the join. /// </summary> /// <typeparam name="U">Type of sub-criteria (type of the collection)</typeparam> /// <param name="path">Lambda expression returning association path</param> + /// <param name="joinType">Type of join</param> + /// <returns>The created "sub criteria"</returns> + IQueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path, JoinType joinType); + + /// <summary> + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity + /// specifying a collection for the join. + /// </summary> + /// <typeparam name="U">Type of sub-criteria (type of the collection)</typeparam> + /// <param name="path">Lambda expression returning association path</param> /// <param name="alias">Lambda expression returning alias reference</param> /// <param name="joinType">Type of join</param> /// <returns>The created "sub criteria"</returns> IQueryOver<U> JoinQueryOver<U>(Expression<Func<T, IEnumerable<U>>> path, Expression<Func<U>> alias, JoinType joinType); /// <summary> + /// Creates a new NHibernate.ICriteria<U>, "rooted" at the associated entity + /// specifying a collection for the join. + /// </summary> + /// <typeparam name="U">Type of sub-criteria (type of the collection)</typeparam> + /// <param name="path">Lambda expression returning association path</param> + /// <param name="alias">Lambda expression returning alias reference</param> + /// <param name="joinType">Type of join</param> + /// <returns>The created "sub criteria"</returns> + IQueryOver<U> JoinQueryOver<U>(Expression<Func<IEnumerable<U>>> path, Expression<Func<U>> alias, JoinType joinType); + + /// <summary> /// Join an association, assigning an alias to the joined entity /// </summary> /// <param name="path">Lambda expression returning association path</param> @@ -243,11 +319,28 @@ /// </summary> /// <param name="path">Lambda expression returning association path</param> /// <param name="alias">Lambda expression returning alias reference</param> + /// <returns>criteria instance</returns> + IQueryOver<T> Join(Expression<Func<object>> path, Expression<Func<object>> alias); + + /// <summary> + /// Join an association, assigning an alias to the joined entity + /// </summary> + /// <param name="path">Lambda expression returning association path</param> + /// <param name="alias">Lambda expression returning alias reference</param> /// <param name="joinType">Type of join</param> /// <returns>criteria instance</returns> IQueryOver<T> Join(Expression<Func<T, object>> path, Expression<Func<object>> alias, JoinType joinType); - IQueryOverJoinBuilder<T> Inner { get; } + /// <summary> + /// Join an association, assigning an alias to the joined entity + /// </summary> + /// <param name="path">Lambda expression returning association path</param> + /// <param name="alias">Lambda expression returning alias reference</param> + /// <param name="joinType">Type of join</param> + /// <returns>criteria instance</returns> + IQueryOver<T> Join(Expression<Func<object>> path, Expression<Func<object>> alias, JoinType joinType); + + IQueryOverJoinBuilder<T> Inner { get; } IQueryOverJoinBuilder<T> Left { get; } IQueryOverJoinBuilder<T> Right { get; } IQueryOverJoinBuilder<T> Full { get; } Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2009-10-31 18:34:16 UTC (rev 4816) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2009-11-03 16:11:25 UTC (rev 4817) @@ -179,6 +179,23 @@ } [Test] + public void SubCriteria_JoinQueryOver_ToOneAlias() + { + ICriteria expected = + CreateTestCriteria(typeof(Person), "personAlias") + .CreateCriteria("personAlias.Father") + .Add(Expression.Eq("Name", "test name")); + + Person personAlias = null; + IQueryOver<Person> actual = + CreateTestQueryOver<Person>(() => personAlias) + .JoinQueryOver(() => personAlias.Father) // sub-criteria + .Where(f => f.Name == "test name"); + + AssertCriteriaAreEqual(expected, actual); + } + + [Test] public void SubCriteria_JoinQueryOver_ToMany() { ICriteria expected = @@ -195,6 +212,23 @@ } [Test] + public void SubCriteria_JoinQueryOver_ToManyAlias() + { + ICriteria expected = + CreateTestCriteria(typeof(Person), "personAlias") + .CreateCriteria("personAlias.Children", JoinType.InnerJoin) + .Add(Expression.Eq("Nickname", "test name")); + + Person personAlias = null; + IQueryOver<Child> actual = + CreateTestQueryOver<Person>(() => personAlias) + .Inner.JoinQueryOver(() => personAlias.Children) // sub-criteria + .Where(c => c.Nickname == "test name"); + + AssertCriteriaAreEqual(expected, actual); + } + + [Test] public void SubCriteria_JoinQueryOverCombinations() { ICriteria expected = @@ -243,6 +277,25 @@ } [Test] + public void Alias_JoinAlias() + { + ICriteria expected = + CreateTestCriteria(typeof(Person), "personAlias") + .CreateAlias("personAlias.Father", "fatherAlias") + .CreateAlias("personAlias.Children", "childAlias", JoinType.InnerJoin); + + Person personAlias = null; + Person fatherAlias = null; + Child childAlias = null; + IQueryOver<Person> actual = + CreateTestQueryOver<Person>(() => personAlias) + .Join(() => personAlias.Father, () => fatherAlias) + .Inner.Join(() => personAlias.Children, () => childAlias); + + AssertCriteriaAreEqual(expected, actual); + } + + [Test] public void Alias_JoinCombinations() { ICriteria expected = This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2009-11-04 10:55:22
|
Revision: 4818 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4818&view=rev Author: ricbrown Date: 2009-11-04 10:55:10 +0000 (Wed, 04 Nov 2009) Log Message: ----------- Added QueryOver<T> constructor using alias. Protected internally used constructors. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/LambdaFixtureBase.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs Modified: trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2009-11-03 16:11:25 UTC (rev 4817) +++ trunk/nhibernate/src/NHibernate/Criterion/QueryOver.cs 2009-11-04 10:55:10 UTC (rev 4818) @@ -25,13 +25,20 @@ _criteria = _impl; } - public QueryOver(CriteriaImpl impl) + public QueryOver(Expression<Func<T>> alias) { + string aliasPath = ExpressionProcessor.FindMemberExpression(alias.Body); + _impl = new CriteriaImpl(typeof(T), aliasPath, null); + _criteria = _impl; + } + + protected internal QueryOver(CriteriaImpl impl) + { _impl = impl; _criteria = impl; } - public QueryOver(CriteriaImpl rootImpl, ICriteria criteria) + protected internal QueryOver(CriteriaImpl rootImpl, ICriteria criteria) { _impl = rootImpl; _criteria = criteria; Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/LambdaFixtureBase.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/LambdaFixtureBase.cs 2009-11-03 16:11:25 UTC (rev 4817) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/LambdaFixtureBase.cs 2009-11-04 10:55:10 UTC (rev 4818) @@ -32,13 +32,17 @@ protected IQueryOver<T> CreateTestQueryOver<T>() { - return new QueryOver<T>(new CriteriaImpl(typeof(T), null)); + return (IQueryOver<T>) + typeof(QueryOver<T>).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new System.Type[] { typeof(CriteriaImpl) }, null) + .Invoke(new object[] { new CriteriaImpl(typeof(T), null) }); } protected IQueryOver<T> CreateTestQueryOver<T>(Expression<Func<object>> alias) { string aliasContainer = ExpressionProcessor.FindMemberExpression(alias.Body); - return new QueryOver<T>(new CriteriaImpl(typeof(T), aliasContainer, null)); + return (IQueryOver<T>) + typeof(QueryOver<T>).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new System.Type[] { typeof(CriteriaImpl) }, null) + .Invoke(new object[] { new CriteriaImpl(typeof(T), aliasContainer, null) }); } protected void AssertCriteriaAreEqual(ICriteria expected, ICriteria actual) @@ -56,6 +60,20 @@ AssertObjectsAreEqual(expected, ((QueryOver<T>)actual).UnderlyingCriteria); } + protected void AssertCriteriaAreEqual<T>(DetachedCriteria expected, QueryOver<T> actual) + { + ICriteria criteria = actual.UnderlyingCriteria; + CriteriaImpl criteriaImpl = (CriteriaImpl) + typeof(QueryOver<T>).GetField("_impl", BindingFlags.NonPublic | BindingFlags.Instance) + .GetValue(actual); + + DetachedCriteria actualDetached = (DetachedCriteria) + typeof(DetachedCriteria).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new System.Type[] { typeof(CriteriaImpl), typeof(ICriteria) }, null) + .Invoke(new object[] { criteriaImpl, criteria }); + + AssertObjectsAreEqual(expected, actualDetached); + } + private void AssertDictionariesAreEqual(IDictionary expected, IDictionary actual) { Assert.AreEqual(expected.Keys.Count, actual.Keys.Count, _fieldPath.Peek() + ".Count"); Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2009-11-03 16:11:25 UTC (rev 4817) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/QueryOverFixture.cs 2009-11-04 10:55:10 UTC (rev 4818) @@ -447,6 +447,21 @@ AssertCriteriaAreEqual(expected, actual); } + [Test] + public void DetachedQueryOver() + { + DetachedCriteria expected = + DetachedCriteria.For<Person>("personAlias") + .Add(Restrictions.Eq("personAlias.Name", "test name")); + + Person personAlias = null; + QueryOver<Person> actual = + new QueryOver<Person>(() => personAlias) + .Where(() => personAlias.Name == "test name"); + + AssertCriteriaAreEqual(expected, actual); + } + } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |