From: <aye...@us...> - 2008-07-18 07:32:52
|
Revision: 3640 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=3640&view=rev Author: ayenderahien Date: 2008-07-18 07:32:56 +0000 (Fri, 18 Jul 2008) Log Message: ----------- NH-1359 - Applying patch from Will Shaver to create an IProjection from a DetachedCriteria Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Criterion/Projections.cs trunk/nhibernate/src/NHibernate/Criterion/Subqueries.cs trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs trunk/nhibernate/src/NHibernate/Loader/Loader.cs trunk/nhibernate/src/NHibernate/NHibernate-2.0.csproj trunk/nhibernate/src/NHibernate/NHibernate-3.5.csproj trunk/nhibernate/src/NHibernate/SqlCommand/InFragment.cs trunk/nhibernate/src/NHibernate/SqlCommand/SubselectClauseExtractor.cs trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1101/Domain.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test-2.0.csproj trunk/nhibernate/src/NHibernate.Test/NHibernate.Test-3.5.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Criterion/SelectSubqueryExpression.cs trunk/nhibernate/src/NHibernate/Criterion/SubqueryProjection.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Person.cs Modified: trunk/nhibernate/src/NHibernate/Criterion/Projections.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/Projections.cs 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate/Criterion/Projections.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -241,5 +241,11 @@ { return new ConditionalProjection(criterion, whenTrue, whenFalse); } + + public static IProjection SubQuery(DetachedCriteria detachedCriteria) + { + SelectSubqueryExpression expr = new SelectSubqueryExpression(detachedCriteria); + return new SubqueryProjection(expr); + } } -} \ No newline at end of file +} Added: trunk/nhibernate/src/NHibernate/Criterion/SelectSubqueryExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/SelectSubqueryExpression.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Criterion/SelectSubqueryExpression.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -0,0 +1,23 @@ +using System; +using NHibernate.SqlCommand; + +namespace NHibernate.Criterion +{ + /// <summary> + /// A comparison between a property value in the outer query and the + /// result of a subquery + /// </summary> + [Serializable] + public class SelectSubqueryExpression : SubqueryExpression + { + internal SelectSubqueryExpression(DetachedCriteria dc) + : base(null, null, dc) + { + } + + protected override SqlString ToLeftSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery) + { + return SqlString.Empty; + } + } +} Modified: trunk/nhibernate/src/NHibernate/Criterion/Subqueries.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/Subqueries.cs 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate/Criterion/Subqueries.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -190,5 +190,10 @@ { return new SimpleSubqueryExpression(value, "<=", "some", dc); } + + public static AbstractCriterion Select(DetachedCriteria detachedCriteria) + { + return new SelectSubqueryExpression(detachedCriteria); + } } -} \ No newline at end of file +} Modified: trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -27,7 +27,7 @@ this.op = op; } - protected IType[] GetTypes() + public IType[] GetTypes() { return types; } @@ -98,7 +98,7 @@ return null; } - private void InitializeInnerQueryAndParameters(ICriteriaQuery criteriaQuery) + public void InitializeInnerQueryAndParameters(ICriteriaQuery criteriaQuery) { ISessionFactoryImplementor factory = criteriaQuery.Factory; innerQuery = @@ -115,4 +115,4 @@ get { return criteriaImpl; } } } -} \ No newline at end of file +} Added: trunk/nhibernate/src/NHibernate/Criterion/SubqueryProjection.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/SubqueryProjection.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Criterion/SubqueryProjection.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -0,0 +1,59 @@ +using System; +using NHibernate.Impl; +using NHibernate.SqlCommand; +using NHibernate.Type; + +namespace NHibernate.Criterion +{ + using System.Collections.Generic; + + /// <summary> + /// A property value, or grouped property value + /// </summary> + [Serializable] + public class SubqueryProjection : SimpleProjection + { + private SelectSubqueryExpression _subQuery; + + protected internal SubqueryProjection(SelectSubqueryExpression subquery) + { + _subQuery = subquery; + } + public override string ToString() + { + return _subQuery.ToString(); + } + + public override bool IsGrouped + { + get { return false; } + } + + public override bool IsAggregate + { + get { return false; } + } + + public override IType[] GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuery) + { + _subQuery.InitializeInnerQueryAndParameters(criteriaQuery); + return _subQuery.GetTypes(); + } + + public override SqlString ToSqlString(ICriteria criteria, int loc, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters) + { + SqlString sqlStringSubquery = _subQuery.ToSqlString(criteria, criteriaQuery, enabledFilters); + return sqlStringSubquery.Append(new SqlString(new object[] + { + " as y", + loc.ToString(), + "_" + })); + } + + public override SqlString ToGroupSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters) + { + throw new InvalidOperationException("not a grouping projection"); + } + } +} Modified: trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -73,7 +73,7 @@ .Add(StringHelper.Join(", ", columnsOrAliases)) .Add(" FROM (SELECT ROW_NUMBER() OVER(ORDER BY "); - AppendSortExpressions(sortExpressions, result); + AppendSortExpressions(columnsOrAliases, sortExpressions, result); result.Add(") as row, "); @@ -84,22 +84,27 @@ if (notLastColumn) result.Add(", "); } - - for (int i = 1; i <= sortExpressions.Length; ++i) + for (int i = 0; i < sortExpressions.Length; i++) { - result.Add(", query.__hibernate_sort_expr_") - .Add(i.ToString()) - .Add("__"); + string sortExpression = RemoveSortOrderDirection(sortExpressions[i]); + if(!columnsOrAliases.Contains(sortExpression)) + { + result.Add(", query.__hibernate_sort_expr_") + .Add(i.ToString()) + .Add("__"); + } } result.Add(" FROM (") .Add(select); - for (int i = 1; i <= sortExpressions.Length; i++) + for (int i = 0; i < sortExpressions.Length; i++) { - // Drop the ASC/DESC at the end of the sort expression which might look like "count(distinct frog.Id)desc" or "frog.Name asc". - string sortExpression = Regex.Replace(sortExpressions[i - 1].Trim(), @"(\)|\s)(?i:asc|desc)$", "$1").Trim(); + string sortExpression = RemoveSortOrderDirection(sortExpressions[i]); + if(columnsOrAliases.Contains(sortExpression)) + continue; + if (aliasToColumn.ContainsKey(sortExpression)) sortExpression = aliasToColumn[sortExpression]; @@ -116,23 +121,36 @@ .Add(offset.ToString()) .Add(" ORDER BY "); - AppendSortExpressions(sortExpressions, result); + AppendSortExpressions(columnsOrAliases, sortExpressions, result); return result.ToSqlString(); } - private void AppendSortExpressions(string[] sortExpressions, SqlStringBuilder result) + private static string RemoveSortOrderDirection(string sortExpression) { - for (int i = 1; i <= sortExpressions.Length; i++) + // Drop the ASC/DESC at the end of the sort expression which might look like "count(distinct frog.Id)desc" or "frog.Name asc". + return Regex.Replace(sortExpression.Trim(), @"(\)|\s)(?i:asc|desc)$", "$1").Trim(); + } + + private static void AppendSortExpressions(ICollection<string> columnsOrAliases, string[] sortExpressions, SqlStringBuilder result) + { + for (int i = 0; i < sortExpressions.Length; i++) { - if (i > 1) + if(i > 1) result.Add(", "); - result.Add("__hibernate_sort_expr_") - .Add(i.ToString()) - .Add("__"); - - if (sortExpressions[i - 1].Trim().ToLower().EndsWith("desc")) + string sortExpression = RemoveSortOrderDirection(sortExpressions[i]); + if(columnsOrAliases.Contains(sortExpression)) + { + result.Add(sortExpression); + } + else + { + result.Add("__hibernate_sort_expr_") + .Add(i.ToString()) + .Add("__"); + } + if (sortExpressions[i].Trim().ToLower().EndsWith("desc")) result.Add(" DESC"); } } @@ -181,6 +199,8 @@ index += 1; } + string alias = token; + bool isFunctionCallOrQuotedString = token.Contains("'") || token.Contains("("); // this is heuristic guess, if the expression contains ' or (, it is probably // not appropriate to just slice parts off of it @@ -188,11 +208,9 @@ { int dot = token.IndexOf('.'); if (dot != -1) - token = token.Substring(dot + 1); + alias = token.Substring(dot + 1); } - string alias = token; - // notice! we are checking here the existence of "as" "alias", two // tokens from the current one if (index + 1 < tokens.Count && Modified: trunk/nhibernate/src/NHibernate/Loader/Loader.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -391,7 +391,7 @@ int entitySpan = EntityPersisters.Length; ArrayList hydratedObjects = entitySpan == 0 ? null : new ArrayList(entitySpan * 10); - ; + IDbCommand st = PrepareQueryCommand(queryParameters, false, session); IDataReader rs = @@ -1830,4 +1830,4 @@ #endregion } -} \ No newline at end of file +} Modified: trunk/nhibernate/src/NHibernate/NHibernate-2.0.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate-2.0.csproj 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate/NHibernate-2.0.csproj 2008-07-18 07:32:56 UTC (rev 3640) @@ -586,6 +586,7 @@ <Compile Include="Dialect\Lock\UpdateLockingStrategy.cs" /> <Compile Include="Dialect\MsSqlCeDialect.cs" /> <Compile Include="Dialect\MySQL5Dialect.cs" /> + <Compile Include="Criterion\SelectSubqueryExpression.cs" /> <Compile Include="Dialect\PostgreSQL82Dialect.cs" /> <Compile Include="Dialect\Schema\FirebirdMetaData.cs" /> <Compile Include="Dialect\Schema\ITableMetadata.cs" /> @@ -594,6 +595,7 @@ <Compile Include="Dialect\Sybase11Dialect.cs" /> <Compile Include="Driver\ISqlParameterFormatter.cs" /> <Compile Include="Driver\SqlStringFormatter.cs" /> + <Compile Include="Criterion\SubqueryProjection.cs" /> <Compile Include="EmptyInterceptor.cs" /> <Compile Include="Engine\ActionQueue.cs" /> <Compile Include="Engine\AssociationKey.cs" /> Modified: trunk/nhibernate/src/NHibernate/NHibernate-3.5.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate-3.5.csproj 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate/NHibernate-3.5.csproj 2008-07-18 07:32:56 UTC (rev 3640) @@ -586,6 +586,7 @@ <Compile Include="Criterion\Restrictions.cs" /> <Compile Include="Criterion\RowCountInt64Projection.cs" /> <Compile Include="Criterion\RowCountProjection.cs" /> + <Compile Include="Criterion\SelectSubqueryExpression.cs" /> <Compile Include="Criterion\SimpleExpression.cs" /> <Compile Include="Criterion\SimpleProjection.cs" /> <Compile Include="Criterion\SimpleSubqueryExpression.cs" /> @@ -594,6 +595,7 @@ <Compile Include="Criterion\SQLProjection.cs" /> <Compile Include="Criterion\Subqueries.cs" /> <Compile Include="Criterion\SubqueryExpression.cs" /> + <Compile Include="Criterion\SubqueryProjection.cs" /> <Compile Include="DebugHelpers\DictionaryProxy.cs" /> <Compile Include="DebugHelpers\CollectionProxy.cs" /> <Compile Include="Dialect\Function\AnsiExtractFunction.cs" /> Modified: trunk/nhibernate/src/NHibernate/SqlCommand/InFragment.cs =================================================================== --- trunk/nhibernate/src/NHibernate/SqlCommand/InFragment.cs 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate/SqlCommand/InFragment.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -1,3 +1,4 @@ + using System; using System.Collections; using NHibernate.Util; @@ -119,6 +120,8 @@ } else { + if(values.Count == 0) + throw new ArgumentOutOfRangeException("Attempting to parse a null value into an sql string."); object value = values[0]; if (Null.Equals(value)) { @@ -136,4 +139,4 @@ return buf.ToSqlString(); } } -} \ No newline at end of file +} Modified: trunk/nhibernate/src/NHibernate/SqlCommand/SubselectClauseExtractor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/SqlCommand/SubselectClauseExtractor.cs 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate/SqlCommand/SubselectClauseExtractor.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -16,7 +16,7 @@ private int lastOrderByIndex; private int lastOrderByPartIndex; - + private int parenNestCount; private object[] sqlParts; /// <summary> @@ -72,7 +72,7 @@ public SqlString GetSqlString() { IEnumerator partEnumerator = sqlParts.GetEnumerator(); - + parenNestCount = 0; // Process the parts until FROM is found while (partEnumerator.MoveNext()) { @@ -94,12 +94,11 @@ return builder.ToSqlString(); } - private static int FindFromClauseInPart(string part) + private int FindFromClauseInPart(string part) { int afterLastClosingParenIndex = 0; int fromIndex = StringHelper.IndexOfCaseInsensitive(part, FromClauseToken); - int parenNestCount = 0; - + for (int i = 0; i < part.Length; i++) { if (parenNestCount == 0 && i > fromIndex) @@ -129,6 +128,9 @@ fromIndex = StringHelper.IndexOfCaseInsensitive(part, FromClauseToken); } + if(parenNestCount > 0) + return -1; + return fromIndex; } Modified: trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -17,49 +17,49 @@ SqlString str = d.GetLimitString(new SqlString("SELECT fish.id FROM fish"), 0, 10); Assert.AreEqual( - "SELECT TOP 10 id FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__) as row, query.id, query.__hibernate_sort_expr_1__ FROM (SELECT fish.id, CURRENT_TIMESTAMP as __hibernate_sort_expr_1__ FROM fish) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_1__", + "SELECT TOP 10 id FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.id, query.__hibernate_sort_expr_0__ FROM (SELECT fish.id, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", str.ToString()); str = d.GetLimitString(new SqlString("SELECT DISTINCT fish_.id FROM fish fish_"), 0, 10); Assert.AreEqual( - "SELECT TOP 10 id FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__) as row, query.id, query.__hibernate_sort_expr_1__ FROM (SELECT DISTINCT fish_.id, CURRENT_TIMESTAMP as __hibernate_sort_expr_1__ FROM fish fish_) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_1__", + "SELECT TOP 10 id FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.id, query.__hibernate_sort_expr_0__ FROM (SELECT DISTINCT fish_.id, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish fish_) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", str.ToString()); str = d.GetLimitString(new SqlString("SELECT DISTINCT fish_.id as ixx9_ FROM fish fish_"), 0, 10); Assert.AreEqual( - "SELECT TOP 10 ixx9_ FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__) as row, query.ixx9_, query.__hibernate_sort_expr_1__ FROM (SELECT DISTINCT fish_.id as ixx9_, CURRENT_TIMESTAMP as __hibernate_sort_expr_1__ FROM fish fish_) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_1__", + "SELECT TOP 10 ixx9_ FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.ixx9_, query.__hibernate_sort_expr_0__ FROM (SELECT DISTINCT fish_.id as ixx9_, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish fish_) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", str.ToString()); str = d.GetLimitString(new SqlString("SELECT * FROM fish ORDER BY name"), 5, 15); Assert.AreEqual( - "SELECT TOP 15 * FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__) as row, query.*, query.__hibernate_sort_expr_1__ FROM (SELECT *, name as __hibernate_sort_expr_1__ FROM fish) query ) page WHERE page.row > 5 ORDER BY __hibernate_sort_expr_1__", + "SELECT TOP 15 * FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.*, query.__hibernate_sort_expr_0__ FROM (SELECT *, name as __hibernate_sort_expr_0__ FROM fish) query ) page WHERE page.row > 5 ORDER BY __hibernate_sort_expr_0__", str.ToString()); str = d.GetLimitString(new SqlString("SELECT fish.id, fish.name FROM fish ORDER BY name DESC"), 7, 28); Assert.AreEqual( - "SELECT TOP 28 id, name FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__ DESC) as row, query.id, query.name, query.__hibernate_sort_expr_1__ FROM (SELECT fish.id, fish.name, name as __hibernate_sort_expr_1__ FROM fish) query ) page WHERE page.row > 7 ORDER BY __hibernate_sort_expr_1__ DESC", + "SELECT TOP 28 id, name FROM (SELECT ROW_NUMBER() OVER(ORDER BY name DESC) as row, query.id, query.name FROM (SELECT fish.id, fish.name FROM fish) query ) page WHERE page.row > 7 ORDER BY name DESC", str.ToString()); str = d.GetLimitString( new SqlString("SELECT * FROM fish LEFT JOIN (SELECT * FROM meat ORDER BY weight) AS t ORDER BY name DESC"), 10, 20); Assert.AreEqual( - "SELECT TOP 20 * FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__ DESC) as row, query.*, query.__hibernate_sort_expr_1__ FROM (SELECT *, name as __hibernate_sort_expr_1__ FROM fish LEFT JOIN (SELECT * FROM meat ORDER BY weight) AS t) query ) page WHERE page.row > 10 ORDER BY __hibernate_sort_expr_1__ DESC", + "SELECT TOP 20 * FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__ DESC) as row, query.*, query.__hibernate_sort_expr_0__ FROM (SELECT *, name as __hibernate_sort_expr_0__ FROM fish LEFT JOIN (SELECT * FROM meat ORDER BY weight) AS t) query ) page WHERE page.row > 10 ORDER BY __hibernate_sort_expr_0__ DESC", str.ToString()); str = d.GetLimitString(new SqlString("SELECT *, (SELECT COUNT(1) FROM fowl WHERE fish_id = fish.id) AS some_count FROM fish"), 0, 10); Assert.AreEqual( - "SELECT TOP 10 *, some_count FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__) as row, query.*, query.some_count, query.__hibernate_sort_expr_1__ FROM (SELECT *, (SELECT COUNT(1) FROM fowl WHERE fish_id = fish.id) AS some_count, CURRENT_TIMESTAMP as __hibernate_sort_expr_1__ FROM fish) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_1__", + "SELECT TOP 10 *, some_count FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.*, query.some_count, query.__hibernate_sort_expr_0__ FROM (SELECT *, (SELECT COUNT(1) FROM fowl WHERE fish_id = fish.id) AS some_count, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", str.ToString()); str = d.GetLimitString(new SqlString("SELECT * FROM fish WHERE scales = ", Parameter.Placeholder), 0, 10); Assert.AreEqual( - "SELECT TOP 10 * FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__) as row, query.*, query.__hibernate_sort_expr_1__ FROM (SELECT *, CURRENT_TIMESTAMP as __hibernate_sort_expr_1__ FROM fish WHERE scales = ?) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_1__", + "SELECT TOP 10 * FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.*, query.__hibernate_sort_expr_0__ FROM (SELECT *, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish WHERE scales = ?) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", str.ToString()); str = d.GetLimitString(new SqlString("SELECT f.Type, COUNT(DISTINCT f.Name) AS Name FROM Fish f GROUP BY f.Type ORDER BY COUNT(DISTINCT f.Name)"), 0, 10); Assert.AreEqual( - "SELECT TOP 10 Type, Name FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__) as row, query.Type, query.Name, query.__hibernate_sort_expr_1__ FROM (SELECT f.Type, COUNT(DISTINCT f.Name) AS Name, COUNT(DISTINCT f.Name) as __hibernate_sort_expr_1__ FROM Fish f GROUP BY f.Type) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_1__", + "SELECT TOP 10 Type, Name FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.Type, query.Name, query.__hibernate_sort_expr_0__ FROM (SELECT f.Type, COUNT(DISTINCT f.Name) AS Name, COUNT(DISTINCT f.Name) as __hibernate_sort_expr_0__ FROM Fish f GROUP BY f.Type) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", str.ToString()); } @@ -69,13 +69,13 @@ MsSql2005Dialect d = new MsSql2005Dialect(); SqlString result = d.GetLimitString(new SqlString("select concat(a.Description,', ', a.Description) as desc from Animal a"), 0, 10); - Assert.AreEqual("SELECT TOP 10 desc FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__) as row, query.desc, query.__hibernate_sort_expr_1__ FROM (select concat(a.Description,', ', a.Description) as desc, CURRENT_TIMESTAMP as __hibernate_sort_expr_1__ from Animal a) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_1__", result.ToString()); + Assert.AreEqual("SELECT TOP 10 desc FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.desc, query.__hibernate_sort_expr_0__ FROM (select concat(a.Description,', ', a.Description) as desc, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ from Animal a) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", result.ToString()); // The test use the function "cast" because cast need the keyWork "as" too SqlString str = d.GetLimitString(new SqlString("SELECT fish.id, cast('astring, with,comma' as string) as bar FROM fish"), 0, 10); Assert.AreEqual( - "SELECT TOP 10 id, bar FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_1__) as row, query.id, query.bar, query.__hibernate_sort_expr_1__ FROM (SELECT fish.id, cast('astring, with,comma' as string) as bar, CURRENT_TIMESTAMP as __hibernate_sort_expr_1__ FROM fish) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_1__", + "SELECT TOP 10 id, bar FROM (SELECT ROW_NUMBER() OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.id, query.bar, query.__hibernate_sort_expr_0__ FROM (SELECT fish.id, cast('astring, with,comma' as string) as bar, CURRENT_TIMESTAMP as __hibernate_sort_expr_0__ FROM fish) query ) page WHERE page.row > 0 ORDER BY __hibernate_sort_expr_0__", str.ToString()); } [Test] Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1101/Domain.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1101/Domain.cs 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1101/Domain.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -2,7 +2,9 @@ { public class A { +#pragma warning disable 649 private int id; +#pragma warning restore 649 private string descript; private B b; public A() {} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Fixture.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -0,0 +1,196 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using NHibernate.Criterion; +using NHibernate.Transform; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH1359 +{ + [TestFixture] + public class Fixture : BugTestCase + { + public override string BugNumber + { + get { return "NH1359"; } + } + + protected override void OnTearDown() + { + base.OnTearDown(); + using(ISession session = OpenSession()) + { + using(ITransaction tx = session.BeginTransaction()) + { + session.Delete("from Person"); + tx.Commit(); + } + } + } + + protected override void OnSetUp() + { + using(ISession s = OpenSession()) + { + using(ITransaction tx = s.BeginTransaction()) + { + Person e1 = new Person("Joe", 10, 9); + Person e2 = new Person("Sally", 20, 8); + Person e3 = new Person("Tim", 20, 7); //20 + Person e4 = new Person("Fred", 40, 40); + Person e5 = new Person("Fred", 50, 50); + s.Save(e1); + s.Save(e2); + s.Save(e3); + s.Save(e4); + s.Save(e5); + Pet p = new Pet("Fido", "Dog", 25, e1); + Pet p2 = new Pet("Biff", "Dog", 10, e1); + s.Save(p); + s.Save(p2); + tx.Commit(); + } + } + } + + [Test] + public void CanSetSubQueryProjectionFromDetachedCriteriaWithCountProjection() + { + using(ISession s = OpenSession()) + { + // This query doesn't make sense at all + DetachedCriteria dc = DetachedCriteria.For<Person>() + .SetProjection(Projections.Count("Id")); + + ICriteria c = s.CreateCriteria(typeof(Person)) + .SetProjection(Projections.SubQuery(dc)) + .Add(Expression.Eq("Name", "Fred")); + + IList list = c.List(); + Assert.AreEqual(2, list.Count); + foreach(object item in list) + { + Assert.AreEqual(5, item); + } + } + } + + public class HeaviestPet + { + public string Name; + public double Weight; + } + + [Test] + public void CanSubqueryRelatedObjectsNotInMainQuery() + { + using(ISession s = OpenSession()) + { + DetachedCriteria dc = DetachedCriteria.For<Person>().CreateCriteria("Pets", "pets") + .SetProjection(Projections.Max("pets.Weight")); + ICriteria c = s.CreateCriteria(typeof(Person)) + .SetProjection(Projections.ProjectionList() + .Add(Projections.SubQuery(dc), "Weight") + .Add(Projections.Property("Name"), "Name")) + .Add(Restrictions.Eq("Name", "Joe")); + c.SetResultTransformer(Transformers.AliasToBean(typeof(HeaviestPet))); + + IList<HeaviestPet> list = c.List<HeaviestPet>(); + Assert.AreEqual(1, list.Count); + foreach(HeaviestPet pet in list) + { + Assert.AreEqual("Joe", pet.Name); + Assert.AreEqual(25, pet.Weight); + } + } + } + + [Test] + public void CanGetSelectSubqueryWithSpecifiedParameter() + { + using (ISession s = OpenSession()) + { + DetachedCriteria dc = DetachedCriteria.For<Person>().Add(Restrictions.Eq("Name", "Joe")) + .SetProjection(Projections.Max("Name")); + ICriteria c = s.CreateCriteria(typeof(Person)) + .SetProjection(Projections.ProjectionList() + .Add(Projections.SubQuery(dc), "Name")) + .Add(Restrictions.Eq("Name", "Joe")); + c.SetResultTransformer(Transformers.AliasToBean(typeof(HeaviestPet))); + IList<HeaviestPet> list = c.List<HeaviestPet>(); + Assert.AreEqual(1, list.Count); + foreach(HeaviestPet pet in list) + { + Assert.AreEqual("Joe", pet.Name); + } + } + } + + + [Test] + public void CanPageAndSortResultsWithParametersAndFilters() + { + using(ISession s = OpenSession()) + { + s.EnableFilter("ExampleFilter").SetParameter("WeightVal", 100); + DetachedCriteria dc = DetachedCriteria.For<Person>().CreateCriteria("Pets", "pets") + .SetProjection(Projections.Max("pets.Weight")) + .Add(Restrictions.Eq("pets.Weight", 10.0)); + ICriteria c = s.CreateCriteria(typeof(Person)) + .SetProjection(Projections.ProjectionList() + .Add(Projections.SubQuery(dc), "Weight") + .Add(Projections.Property("Name"), "Name")) + .Add(Restrictions.Eq("Name", "Joe")); + + c.SetResultTransformer(Transformers.AliasToBean(typeof(HeaviestPet))); + c.SetMaxResults(1); + c.AddOrder(new Order("Id", true)); + IList<HeaviestPet> list = c.List<HeaviestPet>(); + Assert.AreEqual(1, list.Count); + foreach(HeaviestPet pet in list) + { + Assert.AreEqual("Joe", pet.Name); + Assert.AreEqual(10.0, pet.Weight); + } + } + } + + [Test] + public void CanPageAndSortWithMultipleColumnsOfSameName() + { + using(ISession s = OpenSession()) + { + ICriteria c = s.CreateCriteria(typeof(Person),"root") + .CreateCriteria("root.Pets","pets") + .SetProjection(Projections.ProjectionList() + .Add(Projections.Property("root.Id"), "Id") + .Add(Projections.Property("root.Name"), "Name")) + .Add(Restrictions.Eq("Name", "Fido")); + c.AddOrder(new Order("Id", true)); + c.SetResultTransformer(Transformers.AliasToBean(typeof(Person))); + c.SetMaxResults(1); + IList<Person> list = c.List<Person>(); + Assert.AreEqual(1, list.Count); + } + } + + [Test] + public void CanOrderByNamedSubquery() + { + using(ISession s = OpenSession()) + { + DetachedCriteria dc = DetachedCriteria.For<Person>().Add(Restrictions.Eq("Name", "Joe")) + .SetProjection(Projections.Max("Name")); + ICriteria c = s.CreateCriteria(typeof(Person)) + .SetProjection(Projections.ProjectionList() + .Add(Projections.SubQuery(dc), "NameSubquery")) + .Add(Restrictions.Eq("Name", "Joe")); + c.AddOrder(new Order("NameSubquery", true)); + c.SetMaxResults(1); + IList list = c.List(); + Assert.AreEqual(1, list.Count); + } + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Mappings.hbm.xml 2008-07-18 07:32:56 UTC (rev 3640) @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + assembly="NHibernate.Test" + namespace="NHibernate.Test.NHSpecificTest.NH1359"> + + <class name="Person" lazy="false"> + <id name="Id"> + <generator class="native" /> + </id> + <bag name="Pets" inverse="true" lazy="false" cascade="all-delete-orphan"> + <key column="PersonId" /> + <one-to-many class="Pet"/> + <filter name="ExampleFilter" condition=":WeightVal >= Weight" /> + </bag> + <property name="Name"/> + <property name="IQ"/> + <property name="ShoeSize"/> + </class> + + <class name="Pet" lazy="false"> + <id name="Id"> + <generator class="native" /> + </id> + <many-to-one name="Owner" column="PersonId" not-null="true"/> + <property name="Name"/> + <property name="Species"/> + <property name="Weight"/> + </class> + + <filter-def name="ExampleFilter"> + <filter-param name="WeightVal" type="int"/> + </filter-def> + +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Person.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Person.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1359/Person.cs 2008-07-18 07:32:56 UTC (rev 3640) @@ -0,0 +1,107 @@ +using System.Collections; + +namespace NHibernate.Test.NHSpecificTest.NH1359 +{ + public class Person + { + private int id; + private int iq; + private string name; + private IList pets; + private int shoeSize; + + public Person() + { + Pets = new ArrayList(); + } + + public Person(string name, int iq, int shoeSize) + { + this.name = name; + this.iq = iq; + this.shoeSize = shoeSize; + Pets = new ArrayList(); + } + + public virtual int Id + { + get { return id; } + set { id = value; } + } + + public virtual string Name + { + get { return name; } + set { name = value; } + } + + public virtual int IQ + { + get { return iq; } + set { iq = value; } + } + + public virtual int ShoeSize + { + get { return shoeSize; } + set { shoeSize = value; } + } + + public virtual IList Pets + { + get { return pets; } + protected set { pets = value; } + } + } + + public class Pet + { + private int id; + private string name; + private Person owner; + private string species; + private double weight; + + public Pet() + { + } + + public Pet(string name, string species, int weight, Person owner) + { + this.name = name; + this.species = species; + this.weight = weight; + this.owner = owner; + } + + public virtual int Id + { + get { return id; } + set { id = value; } + } + + public virtual string Name + { + get { return name; } + set { name = value; } + } + + public virtual string Species + { + get { return species; } + set { species = value; } + } + + public virtual double Weight + { + get { return weight; } + set { weight = value; } + } + + public virtual Person Owner + { + get { return owner; } + set { owner = value; } + } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test-2.0.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test-2.0.csproj 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test-2.0.csproj 2008-07-18 07:32:56 UTC (rev 3640) @@ -390,6 +390,8 @@ <Compile Include="NHSpecificTest\Docs\Associations\BiM21\Person.cs" /> <Compile Include="NHSpecificTest\Docs\ExampleParentChild\Child.cs" /> <Compile Include="NHSpecificTest\Docs\ExampleParentChild\Parent.cs" /> + <Compile Include="NHSpecificTest\NH1359\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH1359\Person.cs" /> <Compile Include="NHSpecificTest\Docs\ExampleParentChild\UpdateFixture.cs" /> <Compile Include="NHSpecificTest\Docs\PersistentClasses\Cat.cs" /> <Compile Include="NHSpecificTest\EmptyMappingsFixture.cs" /> @@ -1316,6 +1318,7 @@ <EmbeddedResource Include="UserCollection\Parameterized\Mapping.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH1359\Mappings.hbm.xml" /> <EmbeddedResource Include="IdTest\Car.hbm.xml" /> <EmbeddedResource Include="IdTest\Plane.hbm.xml" /> <EmbeddedResource Include="IdTest\Product.hbm.xml" /> Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test-3.5.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test-3.5.csproj 2008-07-18 06:52:02 UTC (rev 3639) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test-3.5.csproj 2008-07-18 07:32:56 UTC (rev 3640) @@ -390,6 +390,8 @@ <Compile Include="NHSpecificTest\NH1355\UserTypeTimestamp.cs"> <SubType>Code</SubType> </Compile> + <Compile Include="NHSpecificTest\NH1359\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH1359\Person.cs" /> <Compile Include="NHSpecificTest\NH1362\Fixture.cs"> <SubType>Code</SubType> </Compile> @@ -1316,6 +1318,9 @@ <EmbeddedResource Include="NHSpecificTest\NH693\SpaceTableName.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH1359\Mappings.hbm.xml" /> + </ItemGroup> + <ItemGroup> <Folder Include="Properties\" /> <Folder Include="Unionsubclass2\" /> </ItemGroup> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |