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. |