Skip to content

Commit 779900c

Browse files
committed
HQL: Support SKIP and TAKE. Support having clause without group by. Throw exception on unexpected trailing input.
SVN: trunk@5668
1 parent 70cd969 commit 779900c

File tree

13 files changed

+8221
-7340
lines changed

13 files changed

+8221
-7340
lines changed

src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public void OnlyOffsetLimit()
8787

8888
SqlString str = d.GetLimitString(new SqlString("select distinct c.Contact_Id as Contact1_19_0_, c._Rating as Rating2_19_0_ from dbo.Contact c where COALESCE(c.Rating, 0) > 0 order by c.Rating desc , c.Last_Name , c.First_Name"), 0, 10);
8989
System.Console.WriteLine(str);
90-
Assert.That(str.ToString(), Is.EqualTo("select distinct top 10 c.Contact_Id as Contact1_19_0_, c._Rating as Rating2_19_0_ from dbo.Contact c where COALESCE(c.Rating, 0) > 0 order by c.Rating desc , c.Last_Name , c.First_Name"));
90+
Assert.That(str.ToString(), Is.EqualTo("select distinct TOP (10) c.Contact_Id as Contact1_19_0_, c._Rating as Rating2_19_0_ from dbo.Contact c where COALESCE(c.Rating, 0) > 0 order by c.Rating desc , c.Last_Name , c.First_Name"));
9191
}
9292

9393
[Test]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using NHibernate.Hql.Ast.ANTLR;
6+
using NUnit.Framework;
7+
8+
namespace NHibernate.Test.Hql.Ast
9+
{
10+
[TestFixture]
11+
public class LimitClauseFixture : BaseFixture
12+
{
13+
protected override void OnSetUp()
14+
{
15+
ISession session = OpenSession();
16+
ITransaction txn = session.BeginTransaction();
17+
18+
var mother = new Human { BodyWeight = 10, Description = "mother" };
19+
var father = new Human { BodyWeight = 15, Description = "father" };
20+
var child1 = new Human { BodyWeight = 5, Description = "child1" };
21+
var child2 = new Human { BodyWeight = 6, Description = "child2" };
22+
var friend = new Human { BodyWeight = 20, Description = "friend" };
23+
24+
session.Save(mother);
25+
session.Save(father);
26+
session.Save(child1);
27+
session.Save(child2);
28+
session.Save(friend);
29+
30+
txn.Commit();
31+
session.Close();
32+
}
33+
34+
protected override void OnTearDown()
35+
{
36+
ISession session = OpenSession();
37+
ITransaction txn = session.BeginTransaction();
38+
session.CreateQuery("delete Human").ExecuteUpdate();
39+
txn.Commit();
40+
session.Close();
41+
}
42+
43+
[Test]
44+
public void None()
45+
{
46+
ISession s = OpenSession();
47+
ITransaction txn = s.BeginTransaction();
48+
49+
var actual = s.CreateQuery("from Human h order by h.bodyWeight").List<Human>().Select(h => h.BodyWeight).ToArray();
50+
var expected = new[] { 5, 6, 10, 15, 20 };
51+
CollectionAssert.AreEqual(expected, actual);
52+
53+
txn.Commit();
54+
s.Close();
55+
}
56+
57+
[Test]
58+
public void Skip()
59+
{
60+
ISession s = OpenSession();
61+
ITransaction txn = s.BeginTransaction();
62+
63+
var actual = s.CreateQuery("from Human h order by h.bodyWeight skip 2").List<Human>().Select(h => h.BodyWeight).ToArray();
64+
var expected = new[] { 10, 15, 20 };
65+
CollectionAssert.AreEqual(expected, actual);
66+
67+
txn.Commit();
68+
s.Close();
69+
}
70+
71+
[Test]
72+
public void Take()
73+
{
74+
ISession s = OpenSession();
75+
ITransaction txn = s.BeginTransaction();
76+
77+
var actual = s.CreateQuery("from Human h order by h.bodyWeight take 2").List<Human>().Select(h => h.BodyWeight).ToArray();
78+
var expected = new[] { 5, 6 };
79+
CollectionAssert.AreEqual(expected, actual);
80+
81+
txn.Commit();
82+
s.Close();
83+
}
84+
85+
[Test]
86+
public void SkipTake()
87+
{
88+
ISession s = OpenSession();
89+
ITransaction txn = s.BeginTransaction();
90+
91+
var actual = s.CreateQuery("from Human h order by h.bodyWeight skip 1 take 3").List<Human>().Select(h => h.BodyWeight).ToArray();
92+
var expected = new[] { 6, 10, 15 };
93+
CollectionAssert.AreEqual(expected, actual);
94+
95+
txn.Commit();
96+
s.Close();
97+
}
98+
99+
[Test]
100+
public void TakeSkip()
101+
{
102+
ISession s = OpenSession();
103+
ITransaction txn = s.BeginTransaction();
104+
105+
Assert.Throws<QuerySyntaxException>(() => s.CreateQuery("from Human h order by h.bodyWeight take 1 skip 2").List<Human>(), "take should not be allowed before skip");
106+
107+
txn.Commit();
108+
s.Close();
109+
}
110+
}
111+
}

src/NHibernate.Test/NHSpecificTest/NH1990/Fixture.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public void FetchingBySubqueryFilterParametersAndPositionalParametersAndNamedPar
111111

112112
var hql = new StringBuilder();
113113
hql.AppendLine("from NewsFeed");
114-
hql.AppendLine("where (Url = ? or Url = ?) and Title in (:TitleList)) ");
114+
hql.AppendLine("where (Url = ? or Url = ?) and Title in (:TitleList) ");
115115

116116
IQuery query = s.CreateQuery(hql.ToString());
117117
query.SetString(0, "Feed4Uri");

src/NHibernate.Test/NHibernate.Test.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@
414414
<Compile Include="Hql\Ast\Joiner.cs" />
415415
<Compile Include="Hql\Ast\KeyManyToOneEntity.cs" />
416416
<Compile Include="Hql\Ast\KeyManyToOneKeyEntity.cs" />
417+
<Compile Include="Hql\Ast\LimitClauseFixture.cs" />
417418
<Compile Include="Hql\Ast\Mammal.cs" />
418419
<Compile Include="Hql\Ast\Name.cs" />
419420
<Compile Include="Hql\Ast\ParsingFixture.cs" />

src/NHibernate/Dialect/MsSql2005Dialect.cs

+29-8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ protected override void RegisterKeywords()
2929
RegisterKeyword("xml");
3030
}
3131

32+
public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit)
33+
{
34+
return GetLimitString(querySqlString,
35+
offset == 0 ? null : new SqlString(offset.ToString()),
36+
limit == int.MaxValue ? null : new SqlString(limit.ToString()));
37+
}
38+
3239
/// <summary>
3340
/// Add a <c>LIMIT</c> clause to the given SQL <c>SELECT</c>
3441
/// </summary>
@@ -43,17 +50,29 @@ protected override void RegisterKeywords()
4350
/// </remarks>
4451
public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit, int? offsetParameterIndex, int? limitParameterIndex)
4552
{
53+
object limitObject = limitParameterIndex == null ? Parameter.Placeholder : Parameter.WithIndex(limitParameterIndex.Value);
54+
object offsetObject = null;
55+
if (offset != 0)
56+
offsetObject = offsetParameterIndex == null ? Parameter.Placeholder : Parameter.WithIndex(offsetParameterIndex.Value);
57+
return GetLimitString(querySqlString, offsetObject, limitObject);
58+
}
59+
60+
private SqlString GetLimitString(SqlString querySqlString, object offset, object limit)
61+
{
62+
if (offset == null && limit == null)
63+
return querySqlString;
64+
4665
SqlStringBuilder result = new SqlStringBuilder();
4766

48-
if (offset == 0)
67+
if (offset == null)
4968
{
5069
int insertPoint = this.GetAfterSelectInsertPoint(querySqlString);
5170

5271
return result
5372
.Add(querySqlString.Substring(0, insertPoint))
5473
.Add(" TOP (")
55-
.Add(limitParameterIndex == null ? Parameter.Placeholder : Parameter.WithIndex(limitParameterIndex.Value))
56-
.Add(")")
74+
.AddObject(limit)
75+
.Add(") ")
5776
.Add(querySqlString.Substring(insertPoint))
5877
.ToSqlString();
5978
}
@@ -84,10 +103,12 @@ public override SqlString GetLimitString(SqlString querySqlString, int offset, i
84103
sortExpressions = new[] {new SqlString("CURRENT_TIMESTAMP"),};
85104
}
86105

87-
result
88-
.Add("SELECT TOP (")
89-
.Add(limitParameterIndex == null ? Parameter.Placeholder : Parameter.WithIndex(limitParameterIndex.Value))
90-
.Add(") ")
106+
result.Add("SELECT ");
107+
108+
if (limit != null)
109+
result.Add("TOP (").AddObject(limit).Add(") ");
110+
111+
result
91112
.Add(StringHelper.Join(", ", columnsOrAliases))
92113
.Add(" FROM (")
93114
.Add(select)
@@ -99,7 +120,7 @@ public override SqlString GetLimitString(SqlString querySqlString, int offset, i
99120
.Add(") as __hibernate_sort_row ")
100121
.Add(fromAndWhere)
101122
.Add(") as query WHERE query.__hibernate_sort_row > ")
102-
.Add(offsetParameterIndex == null ? Parameter.Placeholder : Parameter.WithIndex(offsetParameterIndex.Value))
123+
.AddObject(offset)
103124
.Add(" ORDER BY query.__hibernate_sort_row");
104125

105126
return result.ToSqlString();

0 commit comments

Comments
 (0)