Skip to content

Commit

Permalink
Fix SQL Server dialect paging bug (NH-3138)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
julian-maughan committed May 16, 2012
1 parent 7a7e91f commit 8d7b870
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 2 deletions.
65 changes: 65 additions & 0 deletions 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<Entity>(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<Entity>());
}
}

[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<Entity>());
}
}
}

class Entity
{
public Guid Id { get; set; }
public string EnglishName { get; set; }
public string GermanName { get; set; }
}
}
1 change: 1 addition & 0 deletions src/NHibernate.Test/NHibernate.Test.csproj
Expand Up @@ -963,6 +963,7 @@
<Compile Include="NHSpecificTest\NH3074\Fixture.cs" />
<Compile Include="NHSpecificTest\NH3074\Model.cs" />
<Compile Include="NHSpecificTest\NH3124\FixtureByCode.cs" />
<Compile Include="NHSpecificTest\NH3138\FixtureByCode.cs" />
<Compile Include="NHSpecificTest\NH941\Domain.cs" />
<Compile Include="NHSpecificTest\NH941\Fixture.cs" />
<Compile Include="NHSpecificTest\NH941\FixtureUsingList.cs" />
Expand Down
4 changes: 2 additions & 2 deletions src/NHibernate/Dialect/MsSql2005DialectQueryPager.cs
Expand Up @@ -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(@"(?<!\([^\)]*),{1}");
}
else
{
Expand Down
6 changes: 6 additions & 0 deletions src/NHibernate/SqlCommand/SqlString.cs
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Text;
using System.Collections;
using System.Text.RegularExpressions;

namespace NHibernate.SqlCommand
{
Expand Down Expand Up @@ -557,6 +558,11 @@ public SqlString[] Split(string splitter)
return SplitParts(splitter).ToArray();
}

internal SqlString[] SplitWithRegex(string pattern)
{
return Regex.Split(ToString(), pattern).Select(Parse).ToArray();
}

private IEnumerable<SqlString> SplitParts(string splitter)
{
var startIndex = 0;
Expand Down

0 comments on commit 8d7b870

Please sign in to comment.