From 8d7b870012b6f9298d54b2caa732cb6ce1268c52 Mon Sep 17 00:00:00 2001 From: Julian Maughan Date: Wed, 16 May 2012 22:42:21 +0800 Subject: [PATCH] Fix SQL Server dialect paging bug (NH-3138) The MsSql2005DialectQueryPager was found to be incorrectly identifying columns in the ORDER BY expression of a query that contains a function with parameters separated by commas (e.g. "ORDER BY COALESCE(param1, param2)"). Employed a regular expression for a more sophisticated method of identifying the columns. --- .../NHSpecificTest/NH3138/FixtureByCode.cs | 65 +++++++++++++++++++ src/NHibernate.Test/NHibernate.Test.csproj | 1 + .../Dialect/MsSql2005DialectQueryPager.cs | 4 +- src/NHibernate/SqlCommand/SqlString.cs | 6 ++ 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/NHibernate.Test/NHSpecificTest/NH3138/FixtureByCode.cs diff --git a/src/NHibernate.Test/NHSpecificTest/NH3138/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/NH3138/FixtureByCode.cs new file mode 100644 index 00000000000..e2d0104b43a --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH3138/FixtureByCode.cs @@ -0,0 +1,65 @@ +using System; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH3138 +{ + [TestFixture] + public class FixtureByCode : TestCaseMappingByCode + { + protected override bool AppliesTo(Dialect.Dialect dialect) + { + return dialect is Dialect.MsSql2005Dialect; + } + + protected override Cfg.MappingSchema.HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + mapper.Class(ca => + { + ca.Lazy(false); + ca.Id(x => x.Id, map => map.Generator(Generators.GuidComb)); + ca.Property(x => x.EnglishName); + ca.Property(x => x.GermanName); + }); + + return mapper.CompileMappingForAllExplicitlyAddedEntities(); + } + + [Test] + public void PageQueryWithDistinctAndOrderByContainingFunctionWithCommaSeparatedParameters() + { + using (var session = OpenSession()) + { + Assert.DoesNotThrow(() => + session + .CreateQuery("select distinct e.Id, coalesce(e.EnglishName, e.GermanName) from Entity e order by coalesce(e.EnglishName, e.GermanName) asc") + .SetFirstResult(10) + .SetMaxResults(20) + .List()); + } + } + + [Test] + [Ignore("Failing")] + public void PageQueryWithDistinctAndOrderByContainingAliasedFunction() + { + using (var session = OpenSession()) + { + Assert.DoesNotThrow(() => + session + .CreateQuery("select distinct e.Id, coalesce(e.EnglishName, e.GermanName) as LocalizedName from Entity e order by LocalizedName asc") + .SetFirstResult(10) + .SetMaxResults(20) + .List()); + } + } + } + + class Entity + { + public Guid Id { get; set; } + public string EnglishName { get; set; } + public string GermanName { get; set; } + } +} \ No newline at end of file diff --git a/src/NHibernate.Test/NHibernate.Test.csproj b/src/NHibernate.Test/NHibernate.Test.csproj index 243b1544f2c..96a7a6c6e9e 100644 --- a/src/NHibernate.Test/NHibernate.Test.csproj +++ b/src/NHibernate.Test/NHibernate.Test.csproj @@ -963,6 +963,7 @@ + diff --git a/src/NHibernate/Dialect/MsSql2005DialectQueryPager.cs b/src/NHibernate/Dialect/MsSql2005DialectQueryPager.cs index fa9e2c231b5..81d68fc5097 100644 --- a/src/NHibernate/Dialect/MsSql2005DialectQueryPager.cs +++ b/src/NHibernate/Dialect/MsSql2005DialectQueryPager.cs @@ -67,8 +67,8 @@ private SqlString PageByLimitAndOffset(SqlString offset, SqlString limit) if (orderIndex > 0 && HasMatchingParens(_sourceQuery.Substring(orderIndex).ToString())) { fromAndWhere = _sourceQuery.Substring(fromIndex, orderIndex - fromIndex).Trim(); - SqlString orderBy = _sourceQuery.Substring(orderIndex).Trim(); - sortExpressions = orderBy.Substring(9).Split(","); + SqlString orderBy = _sourceQuery.Substring(orderIndex).Trim().Substring(9); + sortExpressions = orderBy.SplitWithRegex(@"(? SplitParts(string splitter) { var startIndex = 0;