You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
(248) |
May
(82) |
Jun
(90) |
Jul
(177) |
Aug
(253) |
Sep
(157) |
Oct
(151) |
Nov
(143) |
Dec
(278) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(152) |
Feb
(107) |
Mar
(177) |
Apr
(133) |
May
(259) |
Jun
(81) |
Jul
(119) |
Aug
(306) |
Sep
(416) |
Oct
(240) |
Nov
(329) |
Dec
(206) |
2006 |
Jan
(466) |
Feb
(382) |
Mar
(153) |
Apr
(162) |
May
(133) |
Jun
(21) |
Jul
(18) |
Aug
(37) |
Sep
(97) |
Oct
(114) |
Nov
(110) |
Dec
(28) |
2007 |
Jan
(74) |
Feb
(65) |
Mar
(49) |
Apr
(76) |
May
(43) |
Jun
(15) |
Jul
(68) |
Aug
(55) |
Sep
(63) |
Oct
(59) |
Nov
(70) |
Dec
(66) |
2008 |
Jan
(71) |
Feb
(60) |
Mar
(120) |
Apr
(31) |
May
(48) |
Jun
(81) |
Jul
(107) |
Aug
(51) |
Sep
(80) |
Oct
(83) |
Nov
(83) |
Dec
(79) |
2009 |
Jan
(83) |
Feb
(110) |
Mar
(97) |
Apr
(91) |
May
(291) |
Jun
(250) |
Jul
(197) |
Aug
(58) |
Sep
(54) |
Oct
(122) |
Nov
(68) |
Dec
(34) |
2010 |
Jan
(50) |
Feb
(17) |
Mar
(63) |
Apr
(61) |
May
(84) |
Jun
(81) |
Jul
(138) |
Aug
(144) |
Sep
(78) |
Oct
(26) |
Nov
(30) |
Dec
(61) |
2011 |
Jan
(33) |
Feb
(35) |
Mar
(166) |
Apr
(221) |
May
(109) |
Jun
(76) |
Jul
(27) |
Aug
(37) |
Sep
(1) |
Oct
(4) |
Nov
(2) |
Dec
(1) |
2012 |
Jan
|
Feb
|
Mar
(2) |
Apr
(2) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2013 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(1) |
Sep
(3) |
Oct
(2) |
Nov
|
Dec
(1) |
2014 |
Jan
(1) |
Feb
(1) |
Mar
(3) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <fab...@us...> - 2009-10-31 18:27:44
|
Revision: 4815 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4815&view=rev Author: fabiomaulo Date: 2009-10-31 18:27:35 +0000 (Sat, 31 Oct 2009) Log Message: ----------- preparing release NH2.1.1GA Modified Paths: -------------- trunk/nhibernate/releasenotes.txt Modified: trunk/nhibernate/releasenotes.txt =================================================================== --- trunk/nhibernate/releasenotes.txt 2009-10-31 18:26:38 UTC (rev 4814) +++ trunk/nhibernate/releasenotes.txt 2009-10-31 18:27:35 UTC (rev 4815) @@ -1,3 +1,67 @@ +Build 2.1.1.GA (rev4814) +============================= + +** Sub-task + * [NH-1368] - Check same behavior for other persistent collection. + +** Bug + * [NH-1255] - key-many-to-one && not-found + * [NH-1476] - filtering by key-many-to-one causes invalid sql + * [NH-1760] - Missing table join when use a criteria on key-many-to-one part of a Composite Id + * [NH-1785] - Invalid SQL generated for join on composite id using Criteria API + * [NH-1858] - Problem with MsSql2000 and 2005 Dialects GetLimitString when using use_sql_comments=true + * [NH-1895] - delete-orphan mapping, NullReferenceException in DefaultDeleteEventListener.DeleteTransientEntity + * [NH-1898] - HQL query parser can't determine parameter type when using native sql function in hql query. + * [NH-1899] - SaveOrUpdateCopy throws InvalidCastException + * [NH-1902] - QBE don't set the '%' wildcards when using an other matchmode than Matchmode.Exact + * [NH-1904] - Protected properties and public properties cannot have the same name with different case + * [NH-1905] - Join used together with subquery generates wrong SQL + * [NH-1907] - IQuery.SetParameter<T> should use DetermineType + * [NH-1908] - Mishandling of filter parameters causes System.InvalidCastException + * [NH-1911] - Aggregate parameters in projection are not substituted + * [NH-1913] - AdoNet batcher not using CommandTimeout + * [NH-1914] - Collections with out native ID generation is not working + * [NH-1915] - CLONE -HQL AST-Parser: Null-Pointer Exception on Non-Exsistant Entity on Joins + * [NH-1917] - Not retrieving AUTO_INCREMENT identifier on MySQL because of connection closing + * [NH-1920] - Session Filters + collection + parametrized query = bug + * [NH-1926] - Oracle: Schema update crashes + * [NH-1931] - NativeSQLQuerySpecification.Equals compares collections by reference + * [NH-1938] - No 'lower' call in sql-query in LikeExpression with 'ignorecae' = true + * [NH-1939] - Missing <param> element in NHibernate mapping schema. + * [NH-1941] - Custom Enum-String mapping is not written to SQL statement + * [NH-1948] - Hibernate mapping file does not allow a value of 0 for the "scale" attribute of the "property" element + * [NH-1959] - Adding/Removing items to idbag in one transaction causes KeyNotFoundException + * [NH-1963] - System.InvalidCastException on cacheable query with byte array query parameter + * [NH-1964] - Byte array truncation to a length of 8000 + * [NH-1969] - Criteria API does not handle property of type "System.Type" correctly + * [NH-1973] - DateTime sent to dataase is not accurate to millisecond + * [NH-1979] - cast and parameter combination in HQL fails to parse + * [NH-1983] - Blobs and Clobs with Sql Server CE + * [NH-1985] - NHibernate is allowing deletion of immutable objects + * [NH-1987] - MultiQuery does not update statistics + * [NH-1990] - Subquery filter parameters are not set as variables in SQL + * [NH-1992] - BasicFormatter throws exceptions for certain types of data + * [NH-1997] - Original exception information lost when error occurs NHibernate.Engine.TransactionHelper.Work.DoWork + * [NH-2000] - Problem when calling ISession.GetEnableFIilter with a not enabled filter name + * [NH-2003] - IsNullable property is not set properly in ClassIdBinder.cs + +** Improvement + * [NH-847] - Oracle stored procedure with Ref Cursor out + * [NH-1525] - IResultTransformer should override Equals and GetHashCode + * [NH-1912] - Add decimal types to MySQL dialect. + * [NH-1943] - Fix introduction in docs so it won't mention VS 2003 + * [NH-1980] - Ignore exception when trying to set the same type of CollectionTypeFactory + +** New Feature + * [NH-1922] - Allow DetachedCriteria To Work with IStatelessSession + * [NH-1936] - Introduce new Interface IPostEvent in NHibernate.Event + * [NH-1998] - Possibility to turn off many-to-one filters + +** Patch + * [NH-1903] - GetEnumerator().Current inconsistent for generic + * [NH-1970] - SQLite dialect - Fix to substring function + * [NH-1993] - Patch for a bug in MySQLMetaData.cs + Build 2.1.0 ======================== ** Known BREAKING CHANGES from NH2.0.xGA to NH2.1.0 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-31 18:26:45
|
Revision: 4814 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4814&view=rev Author: fabiomaulo Date: 2009-10-31 18:26:38 +0000 (Sat, 31 Oct 2009) Log Message: ----------- preparing release NH2.1.1GA Modified Paths: -------------- branches/2.1.x/nhibernate/releasenotes.txt Modified: branches/2.1.x/nhibernate/releasenotes.txt =================================================================== --- branches/2.1.x/nhibernate/releasenotes.txt 2009-10-31 18:12:51 UTC (rev 4813) +++ branches/2.1.x/nhibernate/releasenotes.txt 2009-10-31 18:26:38 UTC (rev 4814) @@ -1,3 +1,68 @@ +Build 2.1.1.GA (rev4814) +============================= + +** Sub-task + * [NH-1368] - Check same behavior for other persistent collection. + +** Bug + * [NH-1255] - key-many-to-one && not-found + * [NH-1476] - filtering by key-many-to-one causes invalid sql + * [NH-1760] - Missing table join when use a criteria on key-many-to-one part of a Composite Id + * [NH-1785] - Invalid SQL generated for join on composite id using Criteria API + * [NH-1858] - Problem with MsSql2000 and 2005 Dialects GetLimitString when using use_sql_comments=true + * [NH-1895] - delete-orphan mapping, NullReferenceException in DefaultDeleteEventListener.DeleteTransientEntity + * [NH-1898] - HQL query parser can't determine parameter type when using native sql function in hql query. + * [NH-1899] - SaveOrUpdateCopy throws InvalidCastException + * [NH-1902] - QBE don't set the '%' wildcards when using an other matchmode than Matchmode.Exact + * [NH-1904] - Protected properties and public properties cannot have the same name with different case + * [NH-1905] - Join used together with subquery generates wrong SQL + * [NH-1907] - IQuery.SetParameter<T> should use DetermineType + * [NH-1908] - Mishandling of filter parameters causes System.InvalidCastException + * [NH-1911] - Aggregate parameters in projection are not substituted + * [NH-1913] - AdoNet batcher not using CommandTimeout + * [NH-1914] - Collections with out native ID generation is not working + * [NH-1915] - CLONE -HQL AST-Parser: Null-Pointer Exception on Non-Exsistant Entity on Joins + * [NH-1917] - Not retrieving AUTO_INCREMENT identifier on MySQL because of connection closing + * [NH-1920] - Session Filters + collection + parametrized query = bug + * [NH-1926] - Oracle: Schema update crashes + * [NH-1931] - NativeSQLQuerySpecification.Equals compares collections by reference + * [NH-1938] - No 'lower' call in sql-query in LikeExpression with 'ignorecae' = true + * [NH-1939] - Missing <param> element in NHibernate mapping schema. + * [NH-1941] - Custom Enum-String mapping is not written to SQL statement + * [NH-1948] - Hibernate mapping file does not allow a value of 0 for the "scale" attribute of the "property" element + * [NH-1959] - Adding/Removing items to idbag in one transaction causes KeyNotFoundException + * [NH-1963] - System.InvalidCastException on cacheable query with byte array query parameter + * [NH-1964] - Byte array truncation to a length of 8000 + * [NH-1969] - Criteria API does not handle property of type "System.Type" correctly + * [NH-1973] - DateTime sent to dataase is not accurate to millisecond + * [NH-1979] - cast and parameter combination in HQL fails to parse + * [NH-1983] - Blobs and Clobs with Sql Server CE + * [NH-1985] - NHibernate is allowing deletion of immutable objects + * [NH-1987] - MultiQuery does not update statistics + * [NH-1990] - Subquery filter parameters are not set as variables in SQL + * [NH-1992] - BasicFormatter throws exceptions for certain types of data + * [NH-1997] - Original exception information lost when error occurs NHibernate.Engine.TransactionHelper.Work.DoWork + * [NH-2000] - Problem when calling ISession.GetEnableFIilter with a not enabled filter name + * [NH-2003] - IsNullable property is not set properly in ClassIdBinder.cs + +** Improvement + * [NH-847] - Oracle stored procedure with Ref Cursor out + * [NH-1525] - IResultTransformer should override Equals and GetHashCode + * [NH-1912] - Add decimal types to MySQL dialect. + * [NH-1943] - Fix introduction in docs so it won't mention VS 2003 + * [NH-1980] - Ignore exception when trying to set the same type of CollectionTypeFactory + +** New Feature + * [NH-1922] - Allow DetachedCriteria To Work with IStatelessSession + * [NH-1936] - Introduce new Interface IPostEvent in NHibernate.Event + * [NH-1998] - Possibility to turn off many-to-one filters + +** Patch + * [NH-1903] - GetEnumerator().Current inconsistent for generic + * [NH-1970] - SQLite dialect - Fix to substring function + * [NH-1993] - Patch for a bug in MySQLMetaData.cs + + Build 2.1.0 ======================== ** Known BREAKING CHANGES from NH2.0.xGA to NH2.1.0 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2009-10-31 18:12:57
|
Revision: 4813 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4813&view=rev Author: fabiomaulo Date: 2009-10-31 18:12:51 +0000 (Sat, 31 Oct 2009) Log Message: ----------- preparing release Modified Paths: -------------- branches/2.1.x/nhibernate/build-common/common.xml Modified: branches/2.1.x/nhibernate/build-common/common.xml =================================================================== --- branches/2.1.x/nhibernate/build-common/common.xml 2009-10-31 17:37:39 UTC (rev 4812) +++ branches/2.1.x/nhibernate/build-common/common.xml 2009-10-31 18:12:51 UTC (rev 4813) @@ -76,7 +76,7 @@ effectively SP0). --> - <property name="project.version" value="2.1.0.GA" overwrite="false" /> + <property name="project.version" value="2.1.1.GA" overwrite="false" /> <!-- Compute short project version (major.minor) using a regex --> <regex input="${project.version}" pattern="^(?'shortversion'\d+\.\d+)" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 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: <fab...@us...> - 2009-10-31 17:33:49
|
Revision: 4811 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4811&view=rev Author: fabiomaulo Date: 2009-10-31 17:33:40 +0000 (Sat, 31 Oct 2009) Log Message: ----------- Fix NH-1998 Modified Paths: -------------- branches/2.1.x/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/FilterDefinition.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/JoinSequence.cs branches/2.1.x/nhibernate/src/NHibernate/Loader/JoinWalker.cs branches/2.1.x/nhibernate/src/NHibernate/Util/FilterHelper.cs branches/2.1.x/nhibernate/src/NHibernate/nhibernate-mapping.xsd branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs Modified: branches/2.1.x/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Cfg/MappingSchema/Hbm.generated.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -4918,6 +4918,15 @@ /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string condition; + + /// <remarks/> + [System.Xml.Serialization.XmlAttributeAttribute("use-many-to-one")] + [System.ComponentModel.DefaultValueAttribute(true)] + public bool usemanytoone; + + public HbmFilterDef() { + this.usemanytoone = true; + } } /// <remarks/> Modified: branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/FilterDefinitionFactory.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -19,7 +19,7 @@ log.DebugFormat("Parsed filter-def [{0}]", filterDefSchema.name); - return new FilterDefinition(filterDefSchema.name, defaultCondition, parameterTypes); + return new FilterDefinition(filterDefSchema.name, defaultCondition, parameterTypes, filterDefSchema.usemanytoone); } private static IDictionary<string, IType> GetFilterParameterTypes(HbmFilterDef filterDefSchema) Modified: branches/2.1.x/nhibernate/src/NHibernate/Engine/FilterDefinition.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/FilterDefinition.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/FilterDefinition.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -14,22 +14,35 @@ private readonly string filterName; private readonly string defaultFilterCondition; private readonly IDictionary<string, IType> parameterTypes= new Dictionary<string, IType>(); + private readonly bool useInManyToOne; /// <summary> - /// Set the named parameter's value list for this filter. + /// Set the named parameter's value list for this filter. /// </summary> /// <param name="name">The name of the filter for which this configuration is in effect.</param> /// <param name="defaultCondition">The default filter condition.</param> - /// <param name="parameterTypes">A dictionary storing the NHibernate <see cref="IType" /> type + /// <param name="parameterTypes">A dictionary storing the NHibernate <see cref="IType"/> type /// of each parameter under its name.</param> - public FilterDefinition(string name, string defaultCondition, IDictionary<string, IType> parameterTypes) + /// <param name="useManyToOne">if set to <c>true</c> used in many to one rel</param> + public FilterDefinition(string name, string defaultCondition, IDictionary<string, IType> parameterTypes, + bool useManyToOne) { filterName = name; defaultFilterCondition = defaultCondition; this.parameterTypes = parameterTypes; + useInManyToOne = useManyToOne; } /// <summary> + /// Gets a value indicating whether to use this filter-def in manytoone refs. + /// </summary> + /// <value><c>true</c> if [use in many to one]; otherwise, <c>false</c>.</value> + public bool UseInManyToOne + { + get { return useInManyToOne; } + } + + /// <summary> /// Get the name of the filter this configuration defines. /// </summary> /// <returns>The filter name for this configuration.</returns> Modified: branches/2.1.x/nhibernate/src/NHibernate/Engine/JoinSequence.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -184,14 +184,10 @@ { // NH Different behavior : NH1179 and NH1293 // Apply filters in Many-To-One association - if (string.IsNullOrEmpty(on) && enabledFilters.Count > 0) - { - condition = join.Joinable.FilterFragment(join.Alias, enabledFilters); - } - else - { - condition = on; - } + var enabledForManyToOne = FilterHelper.GetEnabledForManyToOne(enabledFilters); + condition = string.IsNullOrEmpty(on) && enabledForManyToOne.Count > 0 + ? join.Joinable.FilterFragment(join.Alias, enabledForManyToOne) + : on; } if (withClauseFragment != null) Modified: branches/2.1.x/nhibernate/src/NHibernate/Loader/JoinWalker.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -17,6 +17,7 @@ protected readonly IList<OuterJoinableAssociation> associations = new List<OuterJoinableAssociation>(); private readonly ISet<AssociationKey> visitedAssociationKeys = new HashedSet<AssociationKey>(); private readonly IDictionary<string, IFilter> enabledFilters; + private readonly IDictionary<string, IFilter> enabledFiltersForManyToOne; private string[] suffixes; private string[] collectionSuffixes; @@ -113,6 +114,7 @@ { this.factory = factory; this.enabledFilters = enabledFilters; + enabledFiltersForManyToOne = FilterHelper.GetEnabledForManyToOne(enabledFilters); } /// <summary> @@ -566,12 +568,15 @@ oj.AddJoins(outerjoin); // NH Different behavior : NH1179 and NH1293 // Apply filters in Many-To-One association - if (enabledFilters.Count > 0) + if (enabledFiltersForManyToOne.Count > 0) { - var manyToOneFilterFragment = oj.Joinable.FilterFragment(oj.RHSAlias, enabledFilters); - var joinClauseDoesNotContainsFilterAlready = outerjoin.ToFromFragmentString.IndexOfCaseInsensitive(manyToOneFilterFragment) == -1; - if(joinClauseDoesNotContainsFilterAlready) + string manyToOneFilterFragment = oj.Joinable.FilterFragment(oj.RHSAlias, enabledFiltersForManyToOne); + bool joinClauseDoesNotContainsFilterAlready = + outerjoin.ToFromFragmentString.IndexOfCaseInsensitive(manyToOneFilterFragment) == -1; + if (joinClauseDoesNotContainsFilterAlready) + { outerjoin.AddCondition(manyToOneFilterFragment); + } } } last = oj; Modified: branches/2.1.x/nhibernate/src/NHibernate/Util/FilterHelper.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Util/FilterHelper.cs 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/Util/FilterHelper.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -67,5 +67,21 @@ } } } + + /// <summary> + /// Get only filters enabled for many-to-one association. + /// </summary> + /// <param name="enabledFilters">All enabled filters</param> + /// <returns>A new <see cref="IDictionary{TKey,TValue}"/> for filters enabled for many to one.</returns> + public static IDictionary<string, IFilter> GetEnabledForManyToOne(IDictionary<string, IFilter> enabledFilters) + { + var enabledFiltersForManyToOne = new Dictionary<string, IFilter>(); + foreach (var enabledFilter in enabledFilters) + { + if (enabledFilter.Value.FilterDefinition.UseInManyToOne) + enabledFiltersForManyToOne.Add(enabledFilter.Key, enabledFilter.Value); + } + return enabledFiltersForManyToOne; + } } } \ No newline at end of file Modified: branches/2.1.x/nhibernate/src/NHibernate/nhibernate-mapping.xsd =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate/nhibernate-mapping.xsd 2009-10-31 17:33:40 UTC (rev 4811) @@ -468,6 +468,7 @@ </xs:choice> <xs:attribute name="name" use="required" type="xs:string" /> <xs:attribute name="condition" type="xs:string" /> + <xs:attribute name="use-many-to-one" default="true" type="xs:boolean"/> </xs:complexType> </xs:element> <xs:element name="filter-param"> Added: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Fixture.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.ManyToOneFilters20Behaviour +{ + [TestFixture] + public class Fixture : BugTestCase + { + private static IList<Parent> joinGraphUsingHql(ISession s) + { + const string hql = @"select p from Parent p + join p.Child c"; + return s.CreateQuery(hql).List<Parent>(); + } + + private static IList<Parent> joinGraphUsingCriteria(ISession s) + { + return s.CreateCriteria(typeof (Parent)).SetFetchMode("Child", FetchMode.Join).List<Parent>(); + } + + private static Parent createParent() + { + return new Parent {Child = new Child()}; + } + + private static void enableFilters(ISession s) + { + IFilter f = s.EnableFilter("activeChild"); + f.SetParameter("active", 1); + IFilter f2 = s.EnableFilter("alwaysValid"); + f2.SetParameter("always", 1); + } + + protected override void OnTearDown() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + s.Delete("from Parent"); + tx.Commit(); + } + } + } + + [Test] + public void VerifyAlwaysFilter() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + Parent p = createParent(); + p.Child.Always = false; + s.Save(p); + tx.Commit(); + } + } + + using (ISession s = OpenSession()) + { + enableFilters(s); + IList<Parent> resCriteria = joinGraphUsingCriteria(s); + IList<Parent> resHql = joinGraphUsingHql(s); + + Assert.AreEqual(0, resCriteria.Count); + Assert.AreEqual(0, resHql.Count); + } + } + + [Test] + public void VerifyFilterActiveButNotUsedInManyToOne() + { + using (ISession s = OpenSession()) + { + using (ITransaction tx = s.BeginTransaction()) + { + s.Save(createParent()); + tx.Commit(); + } + } + + using (ISession s = OpenSession()) + { + enableFilters(s); + IList<Parent> resCriteria = joinGraphUsingCriteria(s); + IList<Parent> resHql = joinGraphUsingHql(s); + + Assert.AreEqual(1, resCriteria.Count); + Assert.IsNotNull(resCriteria[0].Child); + + Assert.AreEqual(1, resHql.Count); + Assert.IsNotNull(resHql[0].Child); + } + } + } +} \ No newline at end of file Added: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Mappings.hbm.xml 2009-10-31 17:33:40 UTC (rev 4811) @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.ManyToOneFilters20Behaviour" + assembly="NHibernate.Test"> + + <class name="Parent"> + <id name="Id"> + <generator class="guid.comb" /> + </id> + + <many-to-one name="Child" class="Child" cascade="all" not-null="true"/> + </class> + + <class name="Child"> + <id name="Id"> + <generator class="guid.comb" /> + </id> + <property name="IsActive"/> + <property name="Always"/> + <filter name="activeChild" condition=":active = IsActive" /> + <filter name="alwaysValid" condition=":always = Always" /> + </class> + + <filter-def name="activeChild" use-many-to-one="false"> + <filter-param name="active" type="int"/> + </filter-def> + + <filter-def name="alwaysValid"> + <filter-param name="always" type="int"/> + </filter-def> +</hibernate-mapping> + Added: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/ManyToOneFilters20Behaviour/Model.cs 2009-10-31 17:33:40 UTC (rev 4811) @@ -0,0 +1,22 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.ManyToOneFilters20Behaviour +{ + public class Parent + { + public virtual Guid Id { get; set; } + public virtual Child Child { get; set; } + } + + public class Child + { + public Child() + { + Always = true; + } + + public virtual Guid Id { get; set; } + public virtual bool IsActive { get; set; } + public virtual bool Always { get; set; } + } +} \ No newline at end of file Modified: branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-31 15:26:23 UTC (rev 4810) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-31 17:33:40 UTC (rev 4811) @@ -368,6 +368,8 @@ <Compile Include="NHSpecificTest\ElementsEnums\IntEnumsBagPartialNameFixture.cs" /> <Compile Include="NHSpecificTest\ElementsEnums\IntEnumsBagFixture.cs" /> <Compile Include="NHSpecificTest\ElementsEnums\Something.cs" /> + <Compile Include="NHSpecificTest\ManyToOneFilters20Behaviour\Fixture.cs" /> + <Compile Include="NHSpecificTest\ManyToOneFilters20Behaviour\Model.cs" /> <Compile Include="NHSpecificTest\NH1025\Fixture.cs" /> <Compile Include="NHSpecificTest\NH1025\Model.cs" /> <Compile Include="NHSpecificTest\NH1255\Domain.cs" /> @@ -2017,6 +2019,7 @@ <EmbeddedResource Include="DriverTest\MultiTypeEntity.hbm.xml" /> <EmbeddedResource Include="DriverTest\SqlServerCeEntity.hbm.xml" /> <Content Include="DynamicEntity\package.html" /> + <EmbeddedResource Include="NHSpecificTest\ManyToOneFilters20Behaviour\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2000\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2003\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1356\MappingsBag.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
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 15:22:30
|
Revision: 4809 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4809&view=rev Author: fabiomaulo Date: 2009-10-31 15:22:21 +0000 (Sat, 31 Oct 2009) Log Message: ----------- Fix NH-2000 Modified Paths: -------------- branches/2.1.x/nhibernate/src/NHibernate/Impl/SessionImpl.cs branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/DomainClass.cs branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/Mappings.hbm.xml branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/SampleTest.cs Modified: branches/2.1.x/nhibernate/src/NHibernate/Impl/SessionImpl.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2009-10-30 10:55:36 UTC (rev 4808) +++ branches/2.1.x/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2009-10-31 15:22:21 UTC (rev 4809) @@ -2173,7 +2173,9 @@ using (new SessionIdLoggingContext(SessionId)) { CheckAndUpdateSessionStatus(); - return enabledFilters[filterName]; + IFilter result; + enabledFilters.TryGetValue(filterName, out result); + return result; } } Added: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/DomainClass.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/DomainClass.cs (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/DomainClass.cs 2009-10-31 15:22:21 UTC (rev 4809) @@ -0,0 +1,9 @@ +namespace NHibernate.Test.NHSpecificTest.NH2000 +{ + public class DomainClass + { + public int Id { get; set; } + + public byte[] ByteData { get; set; } + } +} \ No newline at end of file Added: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/Mappings.hbm.xml =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/Mappings.hbm.xml (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/Mappings.hbm.xml 2009-10-31 15:22:21 UTC (rev 4809) @@ -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> \ No newline at end of file Added: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/SampleTest.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/SampleTest.cs (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2000/SampleTest.cs 2009-10-31 15:22:21 UTC (rev 4809) @@ -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"); + } + } + } +} \ No newline at end of file Modified: branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-30 10:55:36 UTC (rev 4808) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-31 15:22:21 UTC (rev 4809) @@ -600,6 +600,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" /> @@ -2015,6 +2017,7 @@ <EmbeddedResource Include="DriverTest\MultiTypeEntity.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\MappingsSet.hbm.xml" /> 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: <ric...@us...> - 2009-10-30 10:55:05
|
Revision: 4807 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4807&view=rev Author: ricbrown Date: 2009-10-30 10:54:56 +0000 (Fri, 30 Oct 2009) Log Message: ----------- Fix NH-2003, not null constraint on identifier column Modified Paths: -------------- branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassIdBinder.cs branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Fixture.cs branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Mappings.hbm.xml branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Model.cs Modified: branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassIdBinder.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassIdBinder.cs 2009-10-29 14:31:35 UTC (rev 4806) +++ branches/2.1.x/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/ClassIdBinder.cs 2009-10-30 10:54:56 UTC (rev 4807) @@ -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; Added: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Fixture.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Fixture.cs (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Fixture.cs 2009-10-30 10:54:56 UTC (rev 4807) @@ -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")); + } + } +} \ No newline at end of file Added: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Mappings.hbm.xml =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Mappings.hbm.xml (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Mappings.hbm.xml 2009-10-30 10:54:56 UTC (rev 4807) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Model.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Model.cs (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2003/Model.cs 2009-10-30 10:54:56 UTC (rev 4807) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-29 14:31:35 UTC (rev 4806) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-30 10:54:56 UTC (rev 4807) @@ -600,6 +600,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" /> @@ -2013,6 +2015,7 @@ <EmbeddedResource Include="DriverTest\MultiTypeEntity.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\MappingsSet.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH1785\Mappings.hbm.xml" /> 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-29 14:30:52
|
Revision: 4805 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4805&view=rev Author: ricbrown Date: 2009-10-29 14:30:40 +0000 (Thu, 29 Oct 2009) Log Message: ----------- Updated fix for NH-847 moving responsibility to the driver Modified Paths: -------------- branches/2.1.x/nhibernate/src/NHibernate/Driver/DriverBase.cs branches/2.1.x/nhibernate/src/NHibernate/Driver/IDriver.cs branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs branches/2.1.x/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/QueryParameters.cs branches/2.1.x/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs branches/2.1.x/nhibernate/src/NHibernate/Loader/Loader.cs branches/2.1.x/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs branches/2.1.x/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml Modified: branches/2.1.x/nhibernate/src/NHibernate/Driver/DriverBase.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Driver/DriverBase.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Driver/DriverBase.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Driver/IDriver.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Driver/IDriver.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Driver/IDriver.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterParser.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -143,7 +143,7 @@ new NamedParameterDescriptor(name, null, description.BuildPositionsArray(), description.JpaStyle); } - return new ParameterMetadata(ordinalDescriptors, namedParamDescriptorMap, recognizer.HasReturnValue); + return new ParameterMetadata(ordinalDescriptors, namedParamDescriptorMap); } [Serializable] Modified: branches/2.1.x/nhibernate/src/NHibernate/Engine/QueryParameters.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -279,8 +279,6 @@ public bool Callable { get; set; } - public bool HasReturnValue { get; set; } - public bool ReadOnly { get { return _readOnly; } Modified: branches/2.1.x/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Loader/Loader.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Loader/Loader.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Loader/Loader.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml 2009-10-27 03:47:26 UTC (rev 4804) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml 2009-10-29 14:30:40 UTC (rev 4805) @@ -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: <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: <fab...@us...> - 2009-10-27 00:43:08
|
Revision: 4803 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4803&view=rev Author: fabiomaulo Date: 2009-10-26 23:58:32 +0000 (Mon, 26 Oct 2009) Log Message: ----------- Fix NH-1997 Modified Paths: -------------- branches/2.1.x/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- branches/2.1.x/nhibernate/src/NHibernate.Test/ExceptionsTest/NullQueryTest.cs Modified: branches/2.1.x/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs 2009-10-26 11:02:27 UTC (rev 4802) +++ branches/2.1.x/nhibernate/src/NHibernate/Exceptions/ADOExceptionHelper.cs 2009-10-26 23:58:32 UTC (rev 4803) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/ExceptionsTest/NullQueryTest.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/ExceptionsTest/NullQueryTest.cs (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/ExceptionsTest/NullQueryTest.cs 2009-10-26 23:58:32 UTC (rev 4803) @@ -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(); + } + } + } +} \ No newline at end of file Modified: branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-26 11:02:27 UTC (rev 4802) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-26 23:58:32 UTC (rev 4803) @@ -110,6 +110,7 @@ <Compile Include="EngineTest\NativeSQLQueryNonScalarReturnTest.cs" /> <Compile Include="EngineTest\NativeSQLQueryScalarReturnTest.cs" /> <Compile Include="EngineTest\NativeSQLQuerySpecificationTest.cs" /> + <Compile Include="ExceptionsTest\NullQueryTest.cs" /> <Compile Include="FilterTest\ConfigFixture.cs" /> <Compile Include="FilterTest\FilterSecondPassArgsFixture.cs" /> <Compile Include="CfgTest\HbmBinderFixture.cs" /> 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: <ric...@us...> - 2009-10-26 11:01:36
|
Revision: 4801 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4801&view=rev Author: ricbrown Date: 2009-10-26 11:01:27 +0000 (Mon, 26 Oct 2009) Log Message: ----------- Fix NH-847, Stored Procedures support with OracleDataClient Modified Paths: -------------- branches/2.1.x/nhibernate/src/NHibernate/Driver/DriverBase.cs branches/2.1.x/nhibernate/src/NHibernate/Driver/IDriver.cs branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs branches/2.1.x/nhibernate/src/NHibernate/Engine/QueryParameters.cs branches/2.1.x/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs branches/2.1.x/nhibernate/src/NHibernate/Loader/Loader.cs branches/2.1.x/nhibernate/src/NHibernate/NHibernate.csproj branches/2.1.x/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs branches/2.1.x/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/OracleCustomSQLFixture.cs branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml Added Paths: ----------- branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs Modified: branches/2.1.x/nhibernate/src/NHibernate/Driver/DriverBase.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Driver/DriverBase.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/Driver/DriverBase.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Driver/IDriver.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Driver/IDriver.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/Driver/IDriver.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleClientDriver.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/Driver/OracleDataClientDriver.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/CallableParser.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParamLocationRecognizer.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/ParameterMetadata.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/Query/QueryPlanCache.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -143,7 +143,7 @@ new NamedParameterDescriptor(name, null, description.BuildPositionsArray(), description.JpaStyle); } - return new ParameterMetadata(ordinalDescriptors, namedParamDescriptorMap); + return new ParameterMetadata(ordinalDescriptors, namedParamDescriptorMap, recognizer.HasReturnValue); } [Serializable] Modified: branches/2.1.x/nhibernate/src/NHibernate/Engine/QueryParameters.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -279,6 +279,8 @@ public bool Callable { get; set; } + public bool HasReturnValue { get; set; } + public bool ReadOnly { get { return _readOnly; } Modified: branches/2.1.x/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/Impl/SqlQueryImpl.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/Loader/Loader.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Loader/Loader.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/Loader/Loader.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/NHibernate.csproj 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/NHibernate.csproj 2009-10-26 11:01:27 UTC (rev 4801) @@ -479,6 +479,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: branches/2.1.x/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate/SqlCommand/SqlCommandInfo.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs (rev 0) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/CallableParserFixture.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/EngineTest/ParameterParserFixture.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-10-26 11:01:27 UTC (rev 4801) @@ -106,6 +106,7 @@ <Compile Include="CfgTest\ConfigurationSerializationTests.cs" /> <Compile Include="CfgTest\DefaultNsAssmFixture.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: branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/Mappings.hbm.xml 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/OracleCustomSQLFixture.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/OracleCustomSQLFixture.cs 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/OracleCustomSQLFixture.cs 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml 2009-10-25 20:48:02 UTC (rev 4800) +++ branches/2.1.x/nhibernate/src/NHibernate.Test/SqlTest/Custom/Oracle/StoredProcedures.hbm.xml 2009-10-26 11:01:27 UTC (rev 4801) @@ -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: <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: Lady C. S. <dmf...@gm...> - 2009-10-24 17:46:52
|
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;charset=iso-8859-1"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML><HEAD> <META http-equiv=Content-Type content="text/html; charset=iso-8859-1"> <META content="MSHTML 6.00.2900.2180" name=GENERATOR> <STYLE></STYLE> </HEAD> <BODY bgColor=#ffffff> <DIV><FONT face=Arial size=2>Hello Dear,</FONT></DIV> <DIV> </DIV><FONT face=Arial size=2> <DIV><BR>My name is Mrs. Catharina Sies; I am a dying woman who has decided to donate what I have to you for humanity services. I am 61 years old and I was diagnosed for cancer for about 2 years ago immediately after the death of my husband who has left me everything he worked for and because the doctors told me I will not live longer than some weeks because of my health I decided to WILL/donate the sum of USD 3, 500, 000:00 Three million five hundred thousand dollars to you for the good work of humanity and also to help the motherless and less privilege and also for the assistance of the widows. I wish you all the best and may the good Lord bless you abundantly and please use the funds well and always extend the good work to others.</DIV> <DIV> </DIV> <DIV><BR>Here is the Contact information of my Attorney below:</DIV> <DIV> </DIV> <DIV><BR>ABRAHAM WILLIAMS & ASSOCIATES<BR>Mr. John Foxy Esq<BR>Phone: +44-703-183-7885, +44-703-186-4655<BR>Fax: +44-871-264-1453<BR>Email: <A href="mailto:joh...@ai...">joh...@ai...</A></DIV> <DIV> </DIV> <DIV><BR>Tell him that I have WILLED USD 3,500 000.00 to you and I have also notified him. I know I don't know you but I have been directed to do this.</DIV> <DIV> </DIV> <DIV><BR>NB: I will appreciate your utmost confidentiality in this matter until the task is accomplished as i don't want anything that will jeopardize my wishes.</DIV> <DIV> </DIV> <DIV><BR>Sincerely,<BR>Mrs. Catharina Sies</FONT></DIV></BODY></HTML> |
From: <ste...@us...> - 2009-10-23 12:36:58
|
Revision: 4799 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4799&view=rev Author: steverstrong Date: 2009-10-23 12:36:50 +0000 (Fri, 23 Oct 2009) Log Message: ----------- Removed unwanted file from Linq folder Removed Paths: ------------- trunk/nhibernate/src/NHibernate/Linq/NhThrowingExpressionTreeVisitor.cs Deleted: trunk/nhibernate/src/NHibernate/Linq/NhThrowingExpressionTreeVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/NhThrowingExpressionTreeVisitor.cs 2009-10-23 12:21:21 UTC (rev 4798) +++ trunk/nhibernate/src/NHibernate/Linq/NhThrowingExpressionTreeVisitor.cs 2009-10-23 12:36:50 UTC (rev 4799) @@ -1,115 +0,0 @@ -using System.Linq.Expressions; -using Remotion.Data.Linq.Parsing; - -namespace NHibernate.Linq -{ - public abstract class NhThrowingExpressionTreeVisitor : ThrowingExpressionTreeVisitor - { - protected override Expression VisitExpression(Expression expression) - { - 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); - } - - protected virtual Expression VisitNhNew(NhNewExpression expression) - { - return VisitUnhandledItem<NhNewExpression, Expression>(expression, "VisitNhNew", BaseVisitNhNew); - } - - protected virtual Expression VisitNhDistinct(NhDistinctExpression expression) - { - return VisitUnhandledItem<NhDistinctExpression, Expression>(expression, "VisitNhDistinct", BaseVisitNhDistinct); - } - - protected virtual Expression VisitNhAverage(NhAverageExpression expression) - { - return VisitUnhandledItem<NhAverageExpression, Expression>(expression, "VisitNhAverage", BaseVisitNhAverage); - } - - protected virtual Expression VisitNhMin(NhMinExpression expression) - { - return VisitUnhandledItem<NhMinExpression, Expression>(expression, "VisitNhMin", BaseVisitNhMin); - } - - protected virtual Expression VisitNhMax(NhMaxExpression expression) - { - return VisitUnhandledItem<NhMaxExpression, Expression>(expression, "VisitNhMax", BaseVisitNhMax); - } - - protected virtual Expression VisitNhSum(NhSumExpression expression) - { - return VisitUnhandledItem<NhSumExpression, Expression>(expression, "VisitNhSum", BaseVisitNhSum); - } - - protected virtual Expression VisitNhCount(NhCountExpression expression) - { - return VisitUnhandledItem<NhCountExpression, Expression>(expression, "VisitNhCount", BaseVisitNhCount); - } - - protected virtual Expression BaseVisitNhCount(NhCountExpression expression) - { - Expression nx = base.VisitExpression(expression.Expression); - - return nx != expression.Expression ? new NhCountExpression(nx) : expression; - } - - protected virtual Expression BaseVisitNhSum(NhSumExpression expression) - { - Expression nx = base.VisitExpression(expression.Expression); - - return nx != expression.Expression ? new NhSumExpression(nx) : expression; - } - - protected virtual Expression BaseVisitNhMax(NhMaxExpression expression) - { - Expression nx = base.VisitExpression(expression.Expression); - - return nx != expression.Expression ? new NhMaxExpression(nx) : expression; - } - - protected virtual Expression BaseVisitNhMin(NhMinExpression expression) - { - Expression nx = base.VisitExpression(expression.Expression); - - return nx != expression.Expression ? new NhMinExpression(nx) : expression; - } - - protected virtual Expression BaseVisitNhAverage(NhAverageExpression expression) - { - Expression nx = base.VisitExpression(expression.Expression); - - return nx != expression.Expression ? new NhAverageExpression(nx) : expression; - } - - protected Expression BaseVisitNhDistinct(NhDistinctExpression expression) - { - Expression nx = base.VisitExpression(expression.Expression); - - return nx != expression.Expression ? new NhDistinctExpression(nx) : expression; - } - - protected Expression BaseVisitNhNew(NhNewExpression expression) - { - var arguments = base.VisitExpressionList(expression.Arguments); - - return arguments != expression.Arguments ? new NhNewExpression(expression.Members, arguments) : expression; - } - } -} \ 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: <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-22 20:30:39
|
Revision: 4797 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4797&view=rev Author: steverstrong Date: 2009-10-22 20:30:27 +0000 (Thu, 22 Oct 2009) Log Message: ----------- Added another Linq test Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/Linq/LinqQuerySamples.cs Modified: trunk/nhibernate/src/NHibernate.Test/Linq/LinqQuerySamples.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/LinqQuerySamples.cs 2009-10-22 20:27:17 UTC (rev 4796) +++ trunk/nhibernate/src/NHibernate.Test/Linq/LinqQuerySamples.cs 2009-10-22 20:30:27 UTC (rev 4797) @@ -45,6 +45,43 @@ }, x => x.CustomerId); } + [Category("WHERE")] + [Test(Description = "This sample uses WHERE to filter for Customers in London and then Madrid to ensure that the parameterization is working.")] + public void DLinq1b() + { + string city = "London"; + + IOrderedQueryable<Customer> q = + from c in db.Customers + where c.Address.City == city + orderby c.CustomerId + select c; + + AssertByIds(q, new[] + { + "AROUT", + "BSBEV", + "CONSH", + "EASTC", + "NORTS", + "SEVES" + }, x => x.CustomerId); + + city = "Madrid"; + + q = from c in db.Customers + where c.Address.City == city + orderby c.CustomerId + select c; + + AssertByIds(q, new[] + { + "BOLID", + "FISSA", + "ROMEY" + }, x => x.CustomerId); + } + [Category("SELECT/DISTINCT")] [Test( Description = 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-22 14:59:27
|
Revision: 4795 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4795&view=rev Author: steverstrong Date: 2009-10-22 14:59:17 +0000 (Thu, 22 Oct 2009) Log Message: ----------- Linq modifications to integrate with the HQL Query cache - added missing file from previous commit Added Paths: ----------- trunk/nhibernate/src/NHibernate/Linq/ExpressionKeyVisitor.cs Added: trunk/nhibernate/src/NHibernate/Linq/ExpressionKeyVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/ExpressionKeyVisitor.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/ExpressionKeyVisitor.cs 2009-10-22 14:59:17 UTC (rev 4795) @@ -0,0 +1,217 @@ +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 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: <fab...@us...> - 2009-10-18 21:22:07
|
Revision: 4793 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4793&view=rev Author: fabiomaulo Date: 2009-10-18 21:21:57 +0000 (Sun, 18 Oct 2009) Log Message: ----------- Merge r4792; back port of fix NH-1969 (only the fix, the test is in trunk) Modified Paths: -------------- branches/2.1.x/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs Modified: branches/2.1.x/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs =================================================================== --- branches/2.1.x/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2009-10-18 21:16:47 UTC (rev 4792) +++ branches/2.1.x/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2009-10-18 21:21:57 UTC (rev 4793) @@ -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); 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. |