|
From: <jul...@us...> - 2010-08-15 13:31:30
|
Revision: 5157
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5157&view=rev
Author: julian-maughan
Date: 2010-08-15 13:31:20 +0000 (Sun, 15 Aug 2010)
Log Message:
-----------
Changed dialect to preserve parameter indices in Order By statement (NH-2133, NH-1424)
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs
trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs
trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs
Modified: trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs 2010-08-14 22:03:06 UTC (rev 5156)
+++ trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs 2010-08-15 13:31:20 UTC (rev 5157)
@@ -159,63 +159,65 @@
columnsOrAliases = new List<SqlString>();
aliasToColumn = new Dictionary<SqlString, SqlString>();
- IList<string> tokens = new QuotedAndParenthesisStringTokenizer(select.ToString()).GetTokens();
+ IList<SqlString> tokens = new QuotedAndParenthesisStringTokenizer(select).GetTokens();
int index = 0;
while (index < tokens.Count)
{
- string token = tokens[index];
- index += 1;
+ SqlString token = tokens[index];
+
+ int nextTokenIndex = index += 1;
+
+ if (token.StartsWithCaseInsensitive("select"))
+ continue;
- if ("select".Equals(token, StringComparison.InvariantCultureIgnoreCase))
- {
+ if (token.StartsWithCaseInsensitive("distinct"))
continue;
- }
- if ("distinct".Equals(token, StringComparison.InvariantCultureIgnoreCase))
- {
+
+ if (token.StartsWithCaseInsensitive(","))
continue;
- }
- if ("," == token)
- {
- continue;
- }
- if ("from".Equals(token, StringComparison.InvariantCultureIgnoreCase))
- {
+ if (token.StartsWithCaseInsensitive("from"))
break;
- }
- //handle composite expressions like 2 * 4 as foo
- while (index < tokens.Count && "as".Equals(tokens[index], StringComparison.InvariantCultureIgnoreCase) == false
- && "," != tokens[index])
+ // handle composite expressions like "2 * 4 as foo"
+ while ((nextTokenIndex < tokens.Count) && (tokens[nextTokenIndex].StartsWithCaseInsensitive("as") == false && tokens[nextTokenIndex].StartsWithCaseInsensitive(",") == false))
{
- token = token + " " + tokens[index];
- index += 1;
+ SqlString nextToken = tokens[nextTokenIndex];
+ token = token.Append(nextToken);
+ nextTokenIndex = index += 1;
}
- string alias = token;
+ // if there is no alias, the token and the alias will be the same
+ SqlString alias = token;
- bool isFunctionCallOrQuotedString = token.Contains("'") || token.Contains("(");
+ bool isFunctionCallOrQuotedString = token.IndexOfCaseInsensitive("'") >= 0 || token.IndexOfCaseInsensitive("(") >= 0;
+
// this is heuristic guess, if the expression contains ' or (, it is probably
// not appropriate to just slice parts off of it
if (isFunctionCallOrQuotedString == false)
{
- int dot = token.IndexOf('.');
+ // its a simple column reference, so lets set the alias to the
+ // column name minus the table qualifier if it exists
+ int dot = token.IndexOfCaseInsensitive(".");
if (dot != -1)
- {
alias = token.Substring(dot + 1);
- }
}
// notice! we are checking here the existence of "as" "alias", two
// tokens from the current one
- if (index + 1 < tokens.Count && "as".Equals(tokens[index], StringComparison.InvariantCultureIgnoreCase))
+ if (nextTokenIndex + 1 < tokens.Count)
{
- alias = tokens[index + 1];
- index += 2; //skip the "as" and the alias \
+ SqlString nextToken = tokens[nextTokenIndex];
+ if (nextToken.IndexOfCaseInsensitive("as") >= 0)
+ {
+ SqlString tokenAfterNext = tokens[nextTokenIndex + 1];
+ alias = tokenAfterNext;
+ index += 2; //skip the "as" and the alias
+ }
}
- columnsOrAliases.Add(new SqlString(alias));
- aliasToColumn[SqlString.Parse(alias)] = SqlString.Parse(token);
+ columnsOrAliases.Add(alias);
+ aliasToColumn[alias] = token;
}
}
@@ -313,137 +315,144 @@
/// Notice that we aren't differenciating between [ ) and ( ] on purpose, it would complicate
/// the code and it is not legal at any rate.
/// </summary>
- public class QuotedAndParenthesisStringTokenizer : IEnumerable<String>
+ public class QuotedAndParenthesisStringTokenizer : IEnumerable<SqlString>
{
- private readonly string original;
+ private readonly SqlString original;
- public QuotedAndParenthesisStringTokenizer(string original)
+ public QuotedAndParenthesisStringTokenizer(SqlString original)
{
this.original = original;
}
- IEnumerator<string> IEnumerable<string>.GetEnumerator()
+ IEnumerator<SqlString> IEnumerable<SqlString>.GetEnumerator()
{
- StringBuilder currentToken = new StringBuilder();
TokenizerState state = TokenizerState.WhiteSpace;
int parenthesisCount = 0;
bool escapeQuote = false;
- for (int i = 0; i < original.Length; i++)
+ int tokenStart = 0;
+ int tokenLength = 0;
+ string originalString = original.ToString();
+
+ for (int i = 0; i < originalString.Length; i++)
{
- char ch = original[i];
+ char ch = originalString[i];
switch (state)
{
case TokenizerState.WhiteSpace:
if (ch == '\'')
{
state = TokenizerState.Quoted;
- currentToken.Append(ch);
+ tokenLength += 1;
}
else if (ch == ',')
{
- yield return ",";
+ yield return new SqlString(",");
+ //tokenLength += 1?
}
else if (ch == '(' || ch == '[')
{
state = TokenizerState.InParenthesis;
- currentToken.Append(ch);
+ tokenLength += 1;
parenthesisCount = 1;
}
else if (char.IsWhiteSpace(ch) == false)
{
state = TokenizerState.Token;
- currentToken.Append(ch);
+ tokenLength += 1;
}
break;
case TokenizerState.Quoted:
if (escapeQuote)
{
escapeQuote = false;
- currentToken.Append(ch);
+ tokenLength += 1;
}
// handle escaping of ' by using '' or \'
- else if (ch == '\\' || (ch == '\'' && i + 1 < original.Length && original[i + 1] == '\''))
+ else if (ch == '\\' || (ch == '\'' && i + 1 < originalString.Length && originalString[i + 1] == '\''))
{
escapeQuote = true;
- currentToken.Append(ch);
+ tokenLength += 1;
}
else if (ch == '\'')
{
- currentToken.Append(ch);
- yield return currentToken.ToString();
+ yield return original.Substring(tokenStart, tokenLength);
+ tokenStart += tokenLength + 1;
+ tokenLength = 0;
state = TokenizerState.WhiteSpace;
- currentToken.Length = 0;
}
else
{
- currentToken.Append(ch);
+ tokenLength += 1;
}
break;
case TokenizerState.InParenthesis:
if (ch == ')' || ch == ']')
{
- currentToken.Append(ch);
+ tokenLength += 1;
parenthesisCount -= 1;
if (parenthesisCount == 0)
{
- yield return currentToken.ToString();
- currentToken.Length = 0;
+ yield return original.Substring(tokenStart, tokenLength);
+ tokenStart += tokenLength + 1;
+ tokenLength = 0;
state = TokenizerState.WhiteSpace;
}
}
else if (ch == '(' || ch == '[')
{
- currentToken.Append(ch);
+ tokenLength += 1;
parenthesisCount += 1;
}
else
{
- currentToken.Append(ch);
+ tokenLength += 1;
}
break;
case TokenizerState.Token:
if (char.IsWhiteSpace(ch))
{
- yield return currentToken.ToString();
- currentToken.Length = 0;
+ yield return original.Substring(tokenStart, tokenLength);
+ tokenStart += tokenLength + 1;
+ tokenLength = 0;
state = TokenizerState.WhiteSpace;
}
else if (ch == ',') // stop current token, and send the , as well
{
- yield return currentToken.ToString();
- currentToken.Length = 0;
- yield return ",";
+ yield return original.Substring(tokenStart, tokenLength);
+ yield return new SqlString(",");
+ tokenStart += tokenLength + 2;
+ tokenLength = 0;
state = TokenizerState.WhiteSpace;
}
else if (ch == '(' || ch == '[')
{
state = TokenizerState.InParenthesis;
parenthesisCount = 1;
- currentToken.Append(ch);
+ tokenLength += 1;
}
else if (ch == '\'')
{
state = TokenizerState.Quoted;
- currentToken.Append(ch);
+ tokenLength += 1;
}
else
{
- currentToken.Append(ch);
+ tokenLength += 1;
}
break;
default:
throw new InvalidExpressionException("Could not understand the string " + original);
}
}
- if (currentToken.Length > 0)
+ if (tokenLength > 0)
{
- yield return currentToken.ToString();
+ yield return original.Substring(tokenStart, tokenLength);
}
}
public IEnumerator GetEnumerator()
{
- return ((IEnumerable<string>)this).GetEnumerator();
+ return ((IEnumerable<SqlString>)this).GetEnumerator();
}
public enum TokenizerState
@@ -454,9 +463,9 @@
Token
}
- public IList<string> GetTokens()
+ public IList<SqlString> GetTokens()
{
- return new List<string>(this);
+ return new List<SqlString>(this);
}
}
}
Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs 2010-08-14 22:03:06 UTC (rev 5156)
+++ trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs 2010-08-15 13:31:20 UTC (rev 5157)
@@ -1,5 +1,6 @@
using System;
using System.Collections;
+using System.Collections.Generic;
using NHibernate.Dialect;
using NHibernate.Criterion;
using NHibernate.SqlCommand;
@@ -10,8 +11,6 @@
namespace NHibernate.Test.Criteria
{
- using System.Collections.Generic;
-
[TestFixture]
public class CriteriaQueryTest : TestCase
{
@@ -127,32 +126,32 @@
}
}
- [Test]
- public void TestSubcriteriaBeingNull()
- {
- ISession session = OpenSession();
- ITransaction t = session.BeginTransaction();
+ [Test]
+ public void TestSubcriteriaBeingNull()
+ {
+ ISession session = OpenSession();
+ ITransaction t = session.BeginTransaction();
- Course hibernateCourse = new Course();
- hibernateCourse.CourseCode = "HIB";
- hibernateCourse.Description = "Hibernate Training";
- session.Save(hibernateCourse);
+ Course hibernateCourse = new Course();
+ hibernateCourse.CourseCode = "HIB";
+ hibernateCourse.Description = "Hibernate Training";
+ session.Save(hibernateCourse);
- DetachedCriteria subcriteria = DetachedCriteria.For<Enrolment>("e");
- subcriteria.Add(Expression.EqProperty("e.CourseCode", "c.CourseCode"));
- subcriteria.SetProjection(Projections.Avg("Semester"));
+ DetachedCriteria subcriteria = DetachedCriteria.For<Enrolment>("e");
+ subcriteria.Add(Expression.EqProperty("e.CourseCode", "c.CourseCode"));
+ subcriteria.SetProjection(Projections.Avg("Semester"));
- DetachedCriteria criteria = DetachedCriteria.For<Course>("c");
- criteria.SetProjection(Projections.Count("id"));
- criteria.Add(Expression.Or(Subqueries.Le(5, subcriteria), Subqueries.IsNull(subcriteria)));
+ DetachedCriteria criteria = DetachedCriteria.For<Course>("c");
+ criteria.SetProjection(Projections.Count("id"));
+ criteria.Add(Expression.Or(Subqueries.Le(5, subcriteria), Subqueries.IsNull(subcriteria)));
- object o = criteria.GetExecutableCriteria(session).UniqueResult();
- Assert.AreEqual(1, o);
+ object o = criteria.GetExecutableCriteria(session).UniqueResult();
+ Assert.AreEqual(1, o);
- session.Delete(hibernateCourse);
- t.Commit();
- session.Close();
- }
+ session.Delete(hibernateCourse);
+ t.Commit();
+ session.Close();
+ }
[Test]
public void Subselect()
@@ -571,7 +570,6 @@
//it should not be already loaded
Enrolment shouldNotBeLoaded = (Enrolment)s.Load(typeof(Enrolment), key);
Assert.IsFalse(NHibernateUtil.IsInitialized(shouldNotBeLoaded));
-
}
using (ISession s = OpenSession())
@@ -1567,7 +1565,6 @@
}
}
-
[Test]
public void DetachedCriteriaInspection()
{
@@ -1645,15 +1642,16 @@
.SetMaxResults(3)
.List();
- Assert.AreEqual(2, result.Count);
- Assert.IsInstanceOfType(typeof(Student), result[0]);
- Assert.IsInstanceOfType(typeof(Student), result[1]);
+ Assert.That(result.Count, Is.EqualTo(2));
+ Assert.That(result[0], Is.InstanceOf(typeof(Student)));
+ Assert.That(result[1], Is.InstanceOf(typeof(Student)));
session.Delete(gavin);
session.Delete(bizarroGavin);
t.Commit();
session.Close();
}
+
[Test]
public void CacheDetachedCriteria()
{
@@ -1681,8 +1679,8 @@
Assert.That(sessions.Statistics.QueryCacheHitCount, Is.EqualTo(1));
sessions.Statistics.IsStatisticsEnabled = false;
}
-
}
+
[Test]
public void PropertyWithFormulaAndPagingTest()
{
@@ -1749,7 +1747,6 @@
}
}
-
[Test]
public void TransformToRowCountTest()
{
@@ -1776,19 +1773,68 @@
{
ICriteria criteria = session.CreateCriteria(typeof(Student), "c");
- criteria
- .AddOrder(Order.Asc(
- Projections.Conditional(
- Restrictions.Eq("StudentNumber", (long)1),
- Projections.Constant(0),
- Projections.Constant(1)
- )));
+ criteria.AddOrder(
+ Order.Asc(
+ Projections.Conditional(
+ Restrictions.Eq("StudentNumber", (long)1),
+ Projections.Constant(0),
+ Projections.Constant(1))));
criteria.List();
}
}
[Test]
+ public void OrderProjectionAliasedTest()
+ {
+ ISession session = OpenSession();
+ ITransaction t = session.BeginTransaction();
+
+ Course courseA = new Course();
+ courseA.CourseCode = "HIB-A";
+ courseA.Description = "Hibernate Training A";
+ session.Save(courseA);
+
+ Student gavin = new Student();
+ gavin.Name = "Gavin King";
+ gavin.StudentNumber = 232;
+ gavin.PreferredCourse = courseA;
+ session.Save(gavin);
+
+ Student leonardo = new Student();
+ leonardo.Name = "Leonardo Quijano";
+ leonardo.StudentNumber = 233;
+ leonardo.PreferredCourse = courseA;
+ session.Save(leonardo);
+
+ Student johnDoe = new Student();
+ johnDoe.Name = "John Doe";
+ johnDoe.StudentNumber = 235;
+ johnDoe.PreferredCourse = null;
+ session.Save(johnDoe);
+
+ IProjection conditional =
+ Projections.Conditional(
+ Restrictions.Eq("Name", "Gavin King"),
+ Projections.Constant("Name"),
+ Projections.Constant("AnotherName"));
+
+ ICriteria criteria = session.CreateCriteria(typeof(Student));
+ criteria.SetMaxResults(1);
+ criteria.SetFirstResult(1);
+ IList result = criteria.SetProjection(Projections.Alias(conditional, "CheckName"))
+ .AddOrder(Order.Asc("CheckName"))
+ .List();
+
+ session.Delete(gavin);
+ session.Delete(leonardo);
+ session.Delete(johnDoe);
+ session.Delete(courseA);
+ t.Commit();
+ session.Close();
+ }
+
+ [Test]
public void LikeProjectionTest()
{
Student john = new Student { Name = "John" };
@@ -1798,7 +1844,6 @@
session.Flush();
}
-
using (ISession session = this.OpenSession())
{
ICriteria criteria = session.CreateCriteria(typeof(Student), "c");
@@ -1850,7 +1895,6 @@
}
}
-
[Test]
public void AliasJoinCriterion()
{
@@ -1956,4 +2000,4 @@
}
}
}
-}
+}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs 2010-08-14 22:03:06 UTC (rev 5156)
+++ trunk/nhibernate/src/NHibernate.Test/DialectTest/MsSql2005DialectFixture.cs 2010-08-15 13:31:20 UTC (rev 5157)
@@ -112,7 +112,7 @@
{
MsSql2005Dialect.QuotedAndParenthesisStringTokenizer tokenizier =
new MsSql2005Dialect.QuotedAndParenthesisStringTokenizer(
- "select concat(a.Description,', ', a.Description) from Animal a");
+ new SqlString("select concat(a.Description,', ', a.Description) from Animal a"));
string[] expected = new string[]
{
"select",
@@ -122,9 +122,9 @@
"a"
};
int current = 0;
- foreach (string token in tokenizier)
+ foreach (SqlString token in tokenizier)
{
- Assert.AreEqual(expected[current], token);
+ Assert.AreEqual(expected[current], token.ToString());
current += 1;
}
Assert.AreEqual(current, expected.Length);
@@ -135,7 +135,7 @@
{
MsSql2005Dialect.QuotedAndParenthesisStringTokenizer tokenizier =
new MsSql2005Dialect.QuotedAndParenthesisStringTokenizer(
- "SELECT fish.id, cast('astring, with,comma' as string) as bar, f FROM fish");
+ new SqlString("SELECT fish.id, cast('astring, with,comma' as string) as bar, f FROM fish"));
string[] expected = new string[]
{
"SELECT",
@@ -150,10 +150,10 @@
"fish"
};
int current = 0;
- IList<string> tokens = tokenizier.GetTokens();
- foreach (string token in tokens)
+ IList<SqlString> tokens = tokenizier.GetTokens();
+ foreach (SqlString token in tokens)
{
- Assert.AreEqual(expected[current], token);
+ Assert.AreEqual(expected[current], token.ToString());
current += 1;
}
Assert.AreEqual(current, expected.Length);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|