|
From: <ste...@us...> - 2009-11-13 15:44:48
|
Revision: 4829
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4829&view=rev
Author: steverstrong
Date: 2009-11-13 15:44:38 +0000 (Fri, 13 Nov 2009)
Log Message:
-----------
More Linq test cases added
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Dialect/MsSql2000Dialect.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs
trunk/nhibernate/src/NHibernate/Linq/Functions/FunctionRegistry.cs
trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs
trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs
trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs
trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs
trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs
trunk/nhibernate/src/NHibernate.Test/Linq/Entities/Northwind.cs
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/lib/net/3.5/System.Linq.Dynamic.dll
trunk/nhibernate/src/NHibernate.Test/Linq/BinaryExpressionOrdererTests.cs
trunk/nhibernate/src/NHibernate.Test/Linq/DynamicQueryTests.cs
trunk/nhibernate/src/NHibernate.Test/Linq/EnumTests.cs
trunk/nhibernate/src/NHibernate.Test/Linq/ExtensionMethods.cs
trunk/nhibernate/src/NHibernate.Test/Linq/FunctionTests.cs
Added: trunk/nhibernate/lib/net/3.5/System.Linq.Dynamic.dll
===================================================================
(Binary files differ)
Property changes on: trunk/nhibernate/lib/net/3.5/System.Linq.Dynamic.dll
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Modified: trunk/nhibernate/src/NHibernate/Dialect/MsSql2000Dialect.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Dialect/MsSql2000Dialect.cs 2009-11-11 13:37:38 UTC (rev 4828)
+++ trunk/nhibernate/src/NHibernate/Dialect/MsSql2000Dialect.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -106,7 +106,9 @@
RegisterFunction("left", new SQLFunctionTemplate(NHibernateUtil.String, "left(?1, ?2)"));
RegisterFunction("right", new SQLFunctionTemplate(NHibernateUtil.String, "right(?1, ?2)"));
+ RegisterFunction("locate", new StandardSQLFunction("charindex", NHibernateUtil.Int32));
+
RegisterFunction("current_timestamp", new NoArgSQLFunction("getdate", NHibernateUtil.DateTime, true));
RegisterFunction("second", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(second, ?1)"));
RegisterFunction("minute", new SQLFunctionTemplate(NHibernateUtil.Int32, "datepart(minute, ?1)"));
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2009-11-11 13:37:38 UTC (rev 4828)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -146,30 +146,28 @@
{
return new HqlNull(_factory);
}
- else
+
+ switch (System.Type.GetTypeCode(value.GetType()))
{
- switch (System.Type.GetTypeCode(value.GetType()))
- {
- case TypeCode.Int16:
- case TypeCode.Int32:
- case TypeCode.Int64:
- return new HqlIntegerConstant(_factory, value.ToString());
- case TypeCode.Single:
- return new HqlFloatConstant(_factory, value.ToString());
- case TypeCode.Double:
- return new HqlDoubleConstant(_factory, value.ToString());
- case TypeCode.Decimal:
- return new HqlDecimalConstant(_factory, value.ToString());
- case TypeCode.String:
- case TypeCode.Char:
- return new HqlStringConstant(_factory, "\'" + value + "\'");
- case TypeCode.DateTime:
- return new HqlStringConstant(_factory, "\'" + ((DateTime)value).ToString() + "\'");
- case TypeCode.Boolean:
- return new HqlStringConstant(_factory, "\'" + (((bool)value) ? "true" : "false") + "\'");
- default:
- throw new NotSupportedException(string.Format("The constant for '{0}' is not supported", value));
- }
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ return new HqlIntegerConstant(_factory, value.ToString());
+ case TypeCode.Single:
+ return new HqlFloatConstant(_factory, value.ToString());
+ case TypeCode.Double:
+ return new HqlDoubleConstant(_factory, value.ToString());
+ case TypeCode.Decimal:
+ return new HqlDecimalConstant(_factory, value.ToString());
+ case TypeCode.String:
+ case TypeCode.Char:
+ return new HqlStringConstant(_factory, "\'" + value + "\'");
+ case TypeCode.DateTime:
+ return new HqlStringConstant(_factory, "\'" + (DateTime)value + "\'");
+ case TypeCode.Boolean:
+ return new HqlStringConstant(_factory, "\'" + ((bool)value ? "true" : "false") + "\'");
+ default:
+ throw new NotSupportedException(string.Format("The constant for '{0}' is not supported", value));
}
}
@@ -348,11 +346,16 @@
return new HqlExpressionList(_factory);
}
- public HqlMethodCall MethodCall(string methodName, HqlExpression parameter)
+ public HqlMethodCall MethodCall(string methodName, IEnumerable<HqlExpression> parameters)
{
- return new HqlMethodCall(_factory, methodName, parameter);
+ return new HqlMethodCall(_factory, methodName, parameters);
}
+ public HqlMethodCall MethodCall(string methodName, params HqlExpression[] parameters)
+ {
+ return new HqlMethodCall(_factory, methodName, parameters);
+ }
+
public HqlDistinctHolder DistinctHolder(params HqlTreeNode[] children)
{
return new HqlDistinctHolder(_factory, children);
Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2009-11-11 13:37:38 UTC (rev 4828)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using NHibernate.Hql.Ast.ANTLR;
using NHibernate.Hql.Ast.ANTLR.Tree;
@@ -126,6 +127,11 @@
: base(type, text, factory, children)
{
}
+
+ protected HqlStatement(int type, string text, IASTFactory factory, IEnumerable<HqlTreeNode> children)
+ : base(type, text, factory, children)
+ {
+ }
}
public abstract class HqlExpression : HqlTreeNode
@@ -407,7 +413,7 @@
public class HqlOrderBy : HqlStatement
{
public HqlOrderBy(IASTFactory factory)
- : base(HqlSqlWalker.ORDER, "", factory)
+ : base(HqlSqlWalker.ORDER, "order by", factory)
{
}
}
@@ -559,9 +565,15 @@
public class HqlExpressionList : HqlStatement
{
- public HqlExpressionList(IASTFactory factory, params HqlTreeNode[] expression) : base(HqlSqlWalker.EXPR_LIST, "expr_list", factory, expression)
+ public HqlExpressionList(IASTFactory factory, params HqlExpression[] expressions)
+ : base(HqlSqlWalker.EXPR_LIST, "expr_list", factory, expressions)
{
}
+
+ public HqlExpressionList(IASTFactory factory, IEnumerable<HqlExpression> expressions)
+ : base(HqlSqlWalker.EXPR_LIST, "expr_list", factory, expressions.Cast<HqlTreeNode>())
+ {
+ }
}
public class HqlNot : HqlBooleanExpression
@@ -686,11 +698,11 @@
public class HqlMethodCall : HqlExpression
{
- public HqlMethodCall(IASTFactory factory, string methodName, HqlExpression parameter)
+ public HqlMethodCall(IASTFactory factory, string methodName, IEnumerable<HqlExpression> parameters)
: base(HqlSqlWalker.METHOD_CALL, "method", factory)
{
AddChild(new HqlIdent(factory, methodName));
- AddChild(new HqlExpressionList(factory, parameter));
+ AddChild(new HqlExpressionList(factory, parameters));
}
}
Modified: trunk/nhibernate/src/NHibernate/Linq/Functions/FunctionRegistry.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Functions/FunctionRegistry.cs 2009-11-11 13:37:38 UTC (rev 4828)
+++ trunk/nhibernate/src/NHibernate/Linq/Functions/FunctionRegistry.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -1,7 +1,29 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Linq.Expressions;
using System.Reflection;
+using NHibernate.Hql.Ast;
+using NHibernate.Linq.Visitors;
+namespace NHibernate.Linq
+{
+ public class LinqExtensionMethodAttribute : Attribute
+ {
+ public string Name { get; private set; }
+
+ public LinqExtensionMethodAttribute()
+ {
+ }
+
+ public LinqExtensionMethodAttribute(string name)
+ {
+ Name = name;
+ }
+ }
+}
+
namespace NHibernate.Linq.Functions
{
public class FunctionRegistry
@@ -35,6 +57,15 @@
return methodGenerator;
}
+ // No method generator registered. Look to see if it's a standard LinqExtensionMethod
+ var attr = (LinqExtensionMethodAttribute) method.GetCustomAttributes(typeof (LinqExtensionMethodAttribute), false)[0];
+ if (attr != null)
+ {
+ // It is
+ // TODO - cache this? Is it worth it?
+ return new HqlGeneratorForExtensionMethod(attr, method);
+ }
+
throw new NotSupportedException(method.ToString());
}
@@ -66,4 +97,36 @@
typeMethodGenerator.Register(this);
}
}
+
+ public class HqlGeneratorForExtensionMethod : BaseHqlGeneratorForMethod
+ {
+ private readonly string _name;
+
+ public HqlGeneratorForExtensionMethod(LinqExtensionMethodAttribute attribute, MethodInfo method)
+ {
+ _name = string.IsNullOrEmpty(attribute.Name) ? method.Name : attribute.Name;
+ }
+
+ public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
+ {
+ var args = visitor.Visit(targetObject)
+ .Union(arguments.Select(a => visitor.Visit(a)))
+ .Cast<HqlExpression>();
+
+ return treeBuilder.MethodCall(_name, args);
+ }
+ }
+
+ static class UnionExtension
+ {
+ public static IEnumerable<HqlTreeNode> Union(this HqlTreeNode first, IEnumerable<HqlTreeNode> rest)
+ {
+ yield return first;
+
+ foreach (var x in rest)
+ {
+ yield return x;
+ }
+ }
+ }
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs 2009-11-11 13:37:38 UTC (rev 4828)
+++ trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -16,6 +16,9 @@
MethodRegistry.Add(new ContainsGenerator());
MethodRegistry.Add(new EqualsGenerator());
MethodRegistry.Add(new ToUpperLowerGenerator());
+ MethodRegistry.Add(new SubStringGenerator());
+ MethodRegistry.Add(new IndexOfGenerator());
+ MethodRegistry.Add(new ReplaceGenerator());
PropertyRegistry.Add(new LengthGenerator());
}
@@ -129,5 +132,78 @@
return treeBuilder.MethodCall(methodName, visitor.Visit(targetObject).AsExpression());
}
}
+
+ class SubStringGenerator : BaseHqlGeneratorForMethod
+ {
+ public SubStringGenerator()
+ {
+ SupportedMethods = new[]
+ {
+ ReflectionHelper.GetMethod<string>(s => s.Substring(0)),
+ ReflectionHelper.GetMethod<string>(s => s.Substring(0, 0))
+ };
+ }
+ public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
+ {
+ if (arguments.Count == 1)
+ {
+ return treeBuilder.MethodCall("substring", visitor.Visit(targetObject).AsExpression(),
+ treeBuilder.Constant(0),
+ visitor.Visit(arguments[0]).AsExpression());
+ }
+
+ return treeBuilder.MethodCall("substring", visitor.Visit(targetObject).AsExpression(),
+ visitor.Visit(arguments[0]).AsExpression(),
+ visitor.Visit(arguments[1]).AsExpression());
+ }
+ }
+
+ class IndexOfGenerator : BaseHqlGeneratorForMethod
+ {
+ public IndexOfGenerator()
+ {
+ SupportedMethods = new[]
+ {
+ ReflectionHelper.GetMethod<string>(s => s.IndexOf(' ')),
+ ReflectionHelper.GetMethod<string>(s => s.IndexOf(" ")),
+ ReflectionHelper.GetMethod<string>(s => s.IndexOf(' ', 0)),
+ ReflectionHelper.GetMethod<string>(s => s.IndexOf(" ", 0))
+ };
+ }
+ public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
+ {
+ if (arguments.Count == 1)
+ {
+ return treeBuilder.MethodCall("locate",
+ visitor.Visit(arguments[0]).AsExpression(),
+ visitor.Visit(targetObject).AsExpression(),
+ treeBuilder.Constant(0));
+ }
+ return treeBuilder.MethodCall("locate",
+ visitor.Visit(arguments[0]).AsExpression(),
+ visitor.Visit(targetObject).AsExpression(),
+ visitor.Visit(arguments[1]).AsExpression());
+ }
+ }
+
+ class ReplaceGenerator : BaseHqlGeneratorForMethod
+ {
+ public ReplaceGenerator()
+ {
+ SupportedMethods = new[]
+ {
+ ReflectionHelper.GetMethod<string>(s => s.Replace(' ', ' ')),
+ ReflectionHelper.GetMethod<string>(s => s.Replace("", ""))
+ };
+ }
+
+ public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
+ {
+ return treeBuilder.MethodCall("replace",
+ visitor.Visit(targetObject).AsExpression(),
+ visitor.Visit(arguments[0]).AsExpression(),
+ visitor.Visit(arguments[1]).AsExpression());
+ }
+ }
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs 2009-11-11 13:37:38 UTC (rev 4828)
+++ trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -39,6 +39,8 @@
{
_expression = PartialEvaluatingExpressionTreeVisitor.EvaluateIndependentSubtrees(expression);
+ _expression = NameUnNamedParameters.Visit(_expression);
+
_queryParameters = ExpressionParameterVisitor.Visit(_expression);
ParameterValuesByName = _queryParameters.Values.ToDictionary(p => p.Name, p => p.Value);
@@ -57,9 +59,10 @@
}
}
- public IASTNode Translate(ISessionFactory sessionFactory)
+ public IASTNode Translate(ISessionFactory sessionFactory)
{
var requiredHqlParameters = new List<NamedParameterDescriptor>();
+
// TODO - can we cache any of this?
var queryModel = new QueryParser(new ExpressionTreeParser(MethodCallRegistry)).GetParsedQuery(_expression);
@@ -89,6 +92,39 @@
}
}
+ public class NameUnNamedParameters : NhExpressionTreeVisitor
+ {
+ public static Expression Visit(Expression expression)
+ {
+ var visitor = new NameUnNamedParameters();
+
+ return visitor.VisitExpression(expression);
+ }
+
+ private readonly Dictionary<ParameterExpression, ParameterExpression> _renamedParameters = new Dictionary<ParameterExpression, ParameterExpression>();
+
+ protected override Expression VisitParameterExpression(ParameterExpression expression)
+ {
+ if (string.IsNullOrEmpty(expression.Name))
+ {
+ ParameterExpression renamed;
+
+ if (_renamedParameters.TryGetValue(expression, out renamed))
+ {
+ return renamed;
+ }
+
+ renamed = Expression.Parameter(expression.Type, Guid.NewGuid().ToString());
+
+ _renamedParameters.Add(expression, renamed);
+
+ return renamed;
+ }
+
+ return base.VisitParameterExpression(expression);
+ }
+ }
+
public class AggregateExpressionNode : ResultOperatorExpressionNodeBase
{
public MethodCallExpressionParseInfo ParseInfo { get; set; }
Modified: trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs 2009-11-11 13:37:38 UTC (rev 4828)
+++ trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -39,7 +39,9 @@
public IQueryable CreateQuery(Expression expression)
{
- throw new NotImplementedException();
+ var m = ReflectionHelper.GetMethod((NhQueryProvider p) => p.CreateQuery<object>(null)).MakeGenericMethod(expression.Type.GetGenericArguments()[0]);
+
+ return (IQueryable) m.Invoke(this, new[] {expression});
}
public IQueryable<T> CreateQuery<T>(Expression expression)
Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2009-11-11 13:37:38 UTC (rev 4828)
+++ trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -264,9 +264,11 @@
{
case ExpressionType.Not:
return _hqlTreeBuilder.Not(VisitExpression(expression.Operand).AsBooleanExpression());
+ case ExpressionType.Convert:
+ return VisitExpression(expression.Operand);
}
-
- throw new InvalidOperationException();
+
+ throw new NotSupportedException(expression.ToString());
}
protected HqlTreeNode VisitMemberExpression(MemberExpression expression)
@@ -313,7 +315,7 @@
_hqlTreeBuilder.Constant(1));
}
- return _hqlTreeBuilder.Cast(_hqlTreeBuilder.Parameter(namedParameter.Name).AsExpression(), namedParameter.Value.GetType());
+ return _hqlTreeBuilder.Parameter(namedParameter.Name).AsExpression();
}
return _hqlTreeBuilder.Constant(expression.Value);
@@ -346,7 +348,7 @@
ifFalse = VisitExpression(expression.IfFalse).AsExpression();
}
- return _hqlTreeBuilder.Case(new []{when}, ifFalse);
+ return _hqlTreeBuilder.Cast(_hqlTreeBuilder.Case(new []{when}, ifFalse), expression.Type);
}
protected HqlTreeNode VisitSubQueryExpression(SubQueryExpression expression)
Modified: trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs 2009-11-11 13:37:38 UTC (rev 4828)
+++ trunk/nhibernate/src/NHibernate.Test/HQL/HQLFunctions.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -18,7 +18,7 @@
static HQLFunctions()
{
notSupportedStandardFunction.Add("locate",
- new[] { typeof(MsSql2000Dialect), typeof(MsSql2005Dialect), typeof(MsSql2008Dialect) ,typeof(FirebirdDialect), typeof(PostgreSQLDialect) });
+ new[] { typeof(FirebirdDialect), typeof(PostgreSQLDialect) });
notSupportedStandardFunction.Add("bit_length",
new[] { typeof(MsSql2000Dialect), typeof(MsSql2005Dialect), typeof(MsSql2008Dialect), typeof(Oracle8iDialect), typeof(Oracle9iDialect), typeof(Oracle10gDialect) });
notSupportedStandardFunction.Add("extract",
Added: trunk/nhibernate/src/NHibernate.Test/Linq/BinaryExpressionOrdererTests.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Linq/BinaryExpressionOrdererTests.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/Linq/BinaryExpressionOrdererTests.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -0,0 +1,90 @@
+using System.Linq;
+using NUnit.Framework;
+
+namespace NHibernate.Test.Linq
+{
+ [TestFixture]
+ public class BinaryExpressionOrdererTests : LinqTestCase
+ {
+ [Test]
+ public void ValuePropertySwapsToPropertyValue()
+ {
+ var query = (from user in db.Users
+ where ("ayende" == user.Name)
+ select user).ToList();
+ Assert.AreEqual(1, query.Count);
+ }
+
+ [Test]
+ public void PropertyValueDoesntSwaps()
+ {
+ var query = (from user in db.Users
+ where (user.Name == "ayende")
+ select user).ToList();
+ Assert.AreEqual(1, query.Count);
+ }
+
+ [Test]
+ public void PropertyPropertyDoesntSwap()
+ {
+ var query = (from user in db.Users
+ where (user.Name == user.Name)
+ select user).ToList();
+ Assert.AreEqual(3, query.Count);
+ }
+
+ [Test]
+ public void EqualsSwapsToEquals()
+ {
+ var query = (from user in db.Users
+ where ("ayende" == user.Name)
+ select user).ToList();
+ Assert.AreEqual(1, query.Count);
+ }
+
+ [Test]
+ public void NotEqualsSwapsToNotEquals()
+ {
+ var query = (from user in db.Users
+ where ("ayende" != user.Name)
+ select user).ToList();
+ Assert.AreEqual(2, query.Count);
+ }
+
+ [Test]
+ public void GreaterThanSwapsToLessThan()
+ {
+ var query = (from user in db.Users
+ where (3 > user.Id)
+ select user).ToList();
+ Assert.AreEqual(2, query.Count);
+ }
+
+ [Test]
+ public void GreaterThanOrEqualToSwapsToLessThanOrEqualTo()
+ {
+ var query = (from user in db.Users
+ where (2 >= user.Id)
+ select user).ToList();
+ Assert.AreEqual(2, query.Count);
+ }
+
+ [Test]
+ public void LessThanSwapsToGreaterThan()
+ {
+ var query = (from user in db.Users
+ where (1 < user.Id)
+ select user).ToList();
+ Assert.AreEqual(2, query.Count);
+ }
+
+ [Test]
+ public void LessThanOrEqualToSwapsToGreaterThanOrEqualTo()
+ {
+ var query = (from user in db.Users
+ where (2 <= user.Id)
+ select user).ToList();
+ Assert.AreEqual(2, query.Count);
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate.Test/Linq/DynamicQueryTests.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Linq/DynamicQueryTests.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/Linq/DynamicQueryTests.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -0,0 +1,32 @@
+using System;
+using System.Linq;
+using System.Linq.Dynamic;
+using NHibernate.Test.Linq.Entities;
+using NUnit.Framework;
+
+namespace NHibernate.Test.Linq
+{
+ [TestFixture]
+ public class DynamicQueryTests : LinqTestCase
+ {
+ [Test]
+ public void CanQueryWithDynamicOrderBy()
+ {
+ var query = from user in db.Users
+ select user;
+
+ //dynamic orderby clause
+ query = query.OrderBy("RegisteredAt");
+
+ var list = query.ToList();
+
+ //assert list was returned in order
+ DateTime previousDate = DateTime.MinValue;
+ list.Each(delegate(User user)
+ {
+ Assert.IsTrue(previousDate <= user.RegisteredAt);
+ previousDate = user.RegisteredAt;
+ });
+ }
+ }
+}
Modified: trunk/nhibernate/src/NHibernate.Test/Linq/Entities/Northwind.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Linq/Entities/Northwind.cs 2009-11-11 13:37:38 UTC (rev 4828)
+++ trunk/nhibernate/src/NHibernate.Test/Linq/Entities/Northwind.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -56,5 +56,10 @@
{
get { return _session.Query<Mammal>(); }
}
+
+ public IQueryable<User> Users
+ {
+ get { return _session.Query<User>(); }
+ }
}
}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate.Test/Linq/EnumTests.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Linq/EnumTests.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/Linq/EnumTests.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -0,0 +1,55 @@
+using System.Linq;
+using NHibernate.Test.Linq.Entities;
+using NUnit.Framework;
+
+namespace NHibernate.Test.Linq
+{
+ [TestFixture]
+ public class EnumTests : LinqTestCase
+ {
+ [Test]
+ public void CanQueryOnEnumStoredAsInt32_High_1()
+ {
+ CanQueryOnEnumStoredAsInt32(EnumStoredAsInt32.High, 1);
+ }
+
+ [Test]
+ public void CanQueryOnEnumStoredAsInt32_Unspecified_2()
+ {
+ CanQueryOnEnumStoredAsInt32(EnumStoredAsInt32.Unspecified, 2);
+ }
+
+
+ public void CanQueryOnEnumStoredAsInt32(EnumStoredAsInt32 type, int expectedCount)
+ {
+ var query = (from user in db.Users
+ where user.Enum2 == type
+ select user).ToList();
+
+ Assert.AreEqual(expectedCount, query.Count);
+ }
+
+ [Test]
+ public void CanQueryOnEnumStoredAsString_Meduim_2()
+ {
+ CanQueryOnEnumStoredAsString(EnumStoredAsString.Medium, 2);
+
+ }
+
+ [Test]
+ public void CanQueryOnEnumStoredAsString_Small_1()
+ {
+ CanQueryOnEnumStoredAsString(EnumStoredAsString.Small, 1);
+
+ }
+
+ public void CanQueryOnEnumStoredAsString(EnumStoredAsString type, int expectedCount)
+ {
+ var query = (from user in db.Users
+ where user.Enum1 == type
+ select user).ToList();
+
+ Assert.AreEqual(expectedCount, query.Count);
+ }
+ }
+}
Added: trunk/nhibernate/src/NHibernate.Test/Linq/ExtensionMethods.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Linq/ExtensionMethods.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/Linq/ExtensionMethods.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -0,0 +1,19 @@
+using NHibernate.Linq;
+
+namespace NHibernate.Test.Linq
+{
+ static class ExtensionMethods
+ {
+ [LinqExtensionMethod("Replace")]
+ public static string ReplaceExtension(this string subject, string search, string replaceWith)
+ {
+ return null;
+ }
+
+ [LinqExtensionMethod]
+ public static string Replace(this string subject, string search, string replaceWith)
+ {
+ return null;
+ }
+ }
+}
Added: trunk/nhibernate/src/NHibernate.Test/Linq/FunctionTests.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Linq/FunctionTests.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/Linq/FunctionTests.cs 2009-11-13 15:44:38 UTC (rev 4829)
@@ -0,0 +1,85 @@
+using System.Linq;
+using NUnit.Framework;
+
+namespace NHibernate.Test.Linq
+{
+ [TestFixture]
+ public class FunctionTests : LinqTestCase
+ {
+ [Test]
+ public void SubstringFunction()
+ {
+ var query = from e in db.Employees
+ where e.FirstName.Substring(1, 2) == "An"
+ select e;
+
+ ObjectDumper.Write(query);
+ }
+
+ [Test]
+ public void LeftFunction()
+ {
+ var query = from e in db.Employees
+ where e.FirstName.Substring(1, 2) == "An"
+ select e.FirstName.Substring(3);
+
+ ObjectDumper.Write(query);
+ }
+
+ [Test]
+ public void ReplaceFunction()
+ {
+ var query = from e in db.Employees
+ where e.FirstName.StartsWith("An")
+ select new
+ {
+ Before = e.FirstName,
+ AfterMethod = e.FirstName.Replace("An", "Zan"),
+ AfterExtension = ExtensionMethods.Replace(e.FirstName, "An", "Zan"),
+ AfterExtension2 = e.FirstName.ReplaceExtension("An", "Zan")
+ };
+
+ string s = ObjectDumper.Write(query);
+ }
+
+ [Test]
+ public void CharIndexFunction()
+ {
+ var query = from e in db.Employees
+ where e.FirstName.IndexOf('A') == 1
+ select e.FirstName;
+
+ ObjectDumper.Write(query);
+ }
+
+ [Test]
+ public void IndexOfFunctionExpression()
+ {
+ var query = from e in db.Employees
+ where e.FirstName.IndexOf("An") == 1
+ select e.FirstName;
+
+ ObjectDumper.Write(query);
+ }
+
+ [Test]
+ public void IndexOfFunctionProjection()
+ {
+ var query = from e in db.Employees
+ where e.FirstName.Contains("a")
+ select e.FirstName.IndexOf('A', 3);
+
+ ObjectDumper.Write(query);
+ }
+
+ [Test]
+ public void TwoFunctionExpression()
+ {
+ var query = from e in db.Employees
+ where e.FirstName.IndexOf("A") == e.BirthDate.Value.Month
+ select e.FirstName;
+
+ ObjectDumper.Write(query);
+ }
+ }
+}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-11-11 13:37:38 UTC (rev 4828)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-11-13 15:44:38 UTC (rev 4829)
@@ -73,6 +73,10 @@
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Data.OracleClient" />
+ <Reference Include="System.Linq.Dynamic, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\lib\net\3.5\System.Linq.Dynamic.dll</HintPath>
+ </Reference>
<Reference Include="System.Transactions" />
<Reference Include="System.Xml" />
</ItemGroup>
@@ -377,6 +381,8 @@
<Compile Include="LazyProperty\LazyPropertyFixture.cs" />
<Compile Include="Linq\AggregateTests.cs" />
<Compile Include="Linq\BinaryBooleanExpressionTests.cs" />
+ <Compile Include="Linq\BinaryExpressionOrdererTests.cs" />
+ <Compile Include="Linq\DynamicQueryTests.cs" />
<Compile Include="Linq\Entities\Address.cs" />
<Compile Include="Linq\Entities\Animal.cs" />
<Compile Include="Linq\Entities\AnotherEntity.cs" />
@@ -396,6 +402,9 @@
<Compile Include="Linq\Entities\Timesheet.cs" />
<Compile Include="Linq\Entities\User.cs" />
<Compile Include="Linq\Entities\UserComponent.cs" />
+ <Compile Include="Linq\EnumTests.cs" />
+ <Compile Include="Linq\ExtensionMethods.cs" />
+ <Compile Include="Linq\FunctionTests.cs" />
<Compile Include="Linq\LinqQuerySamples.cs" />
<Compile Include="Linq\LinqTestCase.cs" />
<Compile Include="Linq\MiscellaneousTextFixture.cs" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|