From: <ste...@us...> - 2009-11-11 13:37:59
|
Revision: 4828 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4828&view=rev Author: steverstrong Date: 2009-11-11 13:37:38 +0000 (Wed, 11 Nov 2009) Log Message: ----------- More Linq tests and improvement to the Hql tree generation code Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/ASTNode.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/ConstructorNode.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/HqlSqlWalkerTreeAdapter.cs trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/EqualityHqlGenerator.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ProjectionEvaluator.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate.Test/Linq/Entities/Northwind.cs trunk/nhibernate/src/NHibernate.Test/Linq/LinqTestCase.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Linq/Functions/ trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForMethod.cs trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForProperty.cs trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForType.cs trunk/nhibernate/src/NHibernate/Linq/Functions/DateTimeGenerator.cs trunk/nhibernate/src/NHibernate/Linq/Functions/FunctionRegistry.cs trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForMethod.cs trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForProperty.cs trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForType.cs trunk/nhibernate/src/NHibernate/Linq/Functions/QueryableGenerator.cs trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/IHqlExpressionVisitor.cs trunk/nhibernate/src/NHibernate.Test/Linq/BinaryBooleanExpressionTests.cs trunk/nhibernate/src/NHibernate.Test/Linq/Entities/Animal.cs trunk/nhibernate/src/NHibernate.Test/Linq/Entities/AnotherEntity.cs trunk/nhibernate/src/NHibernate.Test/Linq/Entities/Role.cs trunk/nhibernate/src/NHibernate.Test/Linq/Entities/Timesheet.cs trunk/nhibernate/src/NHibernate.Test/Linq/Entities/User.cs trunk/nhibernate/src/NHibernate.Test/Linq/Entities/UserComponent.cs trunk/nhibernate/src/NHibernate.Test/Linq/Mappings/Animal.hbm.xml trunk/nhibernate/src/NHibernate.Test/Linq/Mappings/AnotherEntity.hbm.xml trunk/nhibernate/src/NHibernate.Test/Linq/Mappings/Role.hbm.xml trunk/nhibernate/src/NHibernate.Test/Linq/Mappings/TimeSheet.hbm.xml trunk/nhibernate/src/NHibernate.Test/Linq/Mappings/User.hbm.xml Removed Paths: ------------- trunk/nhibernate/src/NHibernate/Linq/HqlNodeStack.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/BaseHqlGeneratorForProperty.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/ASTNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/ASTNode.cs 2009-11-10 18:07:01 UTC (rev 4827) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/ASTNode.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -17,11 +17,6 @@ private readonly IToken _token; private List<IASTNode> _children; - // TODO - currently just used for Constructor stuff in Linq. Should really have a subtype, - // and a new TreeFactory thingy for the Linq AST generator. But for now... - private object _hack; - public object Hack { get { return _hack; } set { _hack = value; } } - public ASTNode() : this((IToken)null) {} Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/ConstructorNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/ConstructorNode.cs 2009-11-10 18:07:01 UTC (rev 4827) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/ConstructorNode.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -109,16 +109,7 @@ } else { - if (Hack != null && Hack is ConstructorInfo) - { - // The Linq parser has the constructor information available, so it can pass it straight through. - // Currently using nasty Hack property :) This *will* be improved! - _constructor = (ConstructorInfo)Hack; - } - else - { - _constructor = ResolveConstructor(path); - } + _constructor = ResolveConstructor(path); } } Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/HqlSqlWalkerTreeAdapter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/HqlSqlWalkerTreeAdapter.cs 2009-11-10 18:07:01 UTC (rev 4827) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/HqlSqlWalkerTreeAdapter.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -176,15 +176,6 @@ { var dupped = (IASTNode) Create(node.Token); - // TODO - nasty hack for Linq. To be removed :). In general, should this just call the copy - // constructor or something? Then this may work for derived classes... (via a Create overload...) - ASTNode x = dupped as ASTNode; - ASTNode y = node as ASTNode; - if (x != null && y != null) - { - x.Hack = y.Hack; - } - dupped.Parent = node.Parent; return dupped; Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2009-11-10 18:07:01 UTC (rev 4827) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using NHibernate.Hql.Ast.ANTLR.Tree; namespace NHibernate.Hql.Ast @@ -70,11 +69,6 @@ return new HqlRange(_factory, ident); } - public HqlRange Range() - { - return new HqlRange(_factory); - } - public HqlRange Range(HqlTreeNode ident, HqlAlias alias) { return new HqlRange(_factory, ident, alias); @@ -95,49 +89,44 @@ return new HqlAlias(_factory, alias); } - public HqlEquality Equality() + public HqlEquality Equality(HqlExpression lhs, HqlExpression rhs) { - return new HqlEquality(_factory); - } - - public HqlEquality Equality(HqlTreeNode lhs, HqlTreeNode rhs) - { return new HqlEquality(_factory, lhs, rhs); } - public HqlBooleanAnd BooleanAnd() + public HqlBooleanAnd BooleanAnd(HqlBooleanExpression lhs, HqlBooleanExpression rhs) { - return new HqlBooleanAnd(_factory); + return new HqlBooleanAnd(_factory, lhs, rhs); } - public HqlBooleanOr BooleanOr() + public HqlBooleanOr BooleanOr(HqlBooleanExpression lhs, HqlBooleanExpression rhs) { - return new HqlBooleanOr(_factory); + return new HqlBooleanOr(_factory, lhs, rhs); } - public HqlAdd Add() + public HqlAdd Add(HqlExpression lhs, HqlExpression rhs) { - return new HqlAdd(_factory); + return new HqlAdd(_factory, lhs, rhs); } - public HqlSubtract Subtract() + public HqlSubtract Subtract(HqlExpression lhs, HqlExpression rhs) { - return new HqlSubtract(_factory); + return new HqlSubtract(_factory, lhs, rhs); } - public HqlMultiplty Multiply() + public HqlMultiplty Multiply(HqlExpression lhs, HqlExpression rhs) { - return new HqlMultiplty(_factory); + return new HqlMultiplty(_factory, lhs, rhs); } - public HqlDivide Divide() + public HqlDivide Divide(HqlExpression lhs, HqlExpression rhs) { - return new HqlDivide(_factory); + return new HqlDivide(_factory, lhs, rhs); } - public HqlDot Dot() + public HqlDot Dot(HqlExpression lhs, HqlExpression rhs) { - return new HqlDot(_factory); + return new HqlDot(_factory, lhs, rhs); } public HqlParameter Parameter(string name) @@ -145,16 +134,11 @@ return new HqlParameter(_factory, name); } - public HqlWhere Where(HqlTreeNode expression) + public HqlWhere Where(HqlExpression expression) { return new HqlWhere(_factory, expression); } - public HqlWhere Where() - { - return new HqlWhere(_factory); - } - // TODO - constant will be removed when we have parameter handling done properly. Particularly bad datetime handling here, so it'll be good to delete it :) public HqlConstant Constant(object value) { @@ -194,82 +178,72 @@ return new HqlOrderBy(_factory); } - public HqlOrderBy OrderBy(HqlTreeNode expression, HqlDirection hqlDirection) + public HqlSelect Select(HqlExpression expression) { - return new HqlOrderBy(_factory, expression, hqlDirection); - } - - public HqlSelect Select(HqlTreeNode expression) - { return new HqlSelect(_factory, expression); } - public HqlSelect Select(params HqlTreeNode[] expression) + public HqlSelect Select(params HqlExpression[] expression) { return new HqlSelect(_factory, expression); } - public HqlSelect Select(IEnumerable<HqlTreeNode> expressions) + public HqlSelect Select(IEnumerable<HqlExpression> expressions) { return new HqlSelect(_factory, expressions.ToArray()); } - public HqlConstructor Constructor(ConstructorInfo constructor) + public HqlCase Case(HqlWhen[] whenClauses) { - return new HqlConstructor(_factory, constructor); + return new HqlCase(_factory, whenClauses, null); } - public HqlNill Holder() + public HqlCase Case(HqlWhen[] whenClauses, HqlExpression ifFalse) { - return new HqlNill(_factory); + return new HqlCase(_factory, whenClauses, ifFalse); } - public HqlCase Case() + public HqlWhen When(HqlExpression predicate, HqlExpression ifTrue) { - return new HqlCase(_factory); + return new HqlWhen(_factory, predicate, ifTrue); } - public HqlWhen When() + public HqlElse Else(HqlExpression ifFalse) { - return new HqlWhen(_factory); + return new HqlElse(_factory, ifFalse); } - public HqlElse Else() + public HqlInequality Inequality(HqlExpression lhs, HqlExpression rhs) { - return new HqlElse(_factory); + return new HqlInequality(_factory, lhs, rhs); } - public HqlInequality Inequality() + public HqlLessThan LessThan(HqlExpression lhs, HqlExpression rhs) { - return new HqlInequality(_factory); + return new HqlLessThan(_factory, lhs, rhs); } - public HqlLessThan LessThan() + public HqlLessThanOrEqual LessThanOrEqual(HqlExpression lhs, HqlExpression rhs) { - return new HqlLessThan(_factory); + return new HqlLessThanOrEqual(_factory, lhs, rhs); } - public HqlLessThanOrEqual LessThanOrEqual() + public HqlGreaterThan GreaterThan(HqlExpression lhs, HqlExpression rhs) { - return new HqlLessThanOrEqual(_factory); + return new HqlGreaterThan(_factory, lhs, rhs); } - public HqlGreaterThan GreaterThan() + public HqlGreaterThanOrEqual GreaterThanOrEqual(HqlExpression lhs, HqlExpression rhs) { - return new HqlGreaterThan(_factory); + return new HqlGreaterThanOrEqual(_factory, lhs, rhs); } - public HqlGreaterThanOrEqual GreaterThanOrEqual() - { - return new HqlGreaterThanOrEqual(_factory); - } - public HqlCount Count() { return new HqlCount(_factory); } - public HqlCount Count(HqlTreeNode child) + public HqlCount Count(HqlExpression child) { return new HqlCount(_factory, child); } @@ -279,7 +253,7 @@ return new HqlRowStar(_factory); } - public HqlCast Cast(HqlTreeNode expression, System.Type type) + public HqlCast Cast(HqlExpression expression, System.Type type) { return new HqlCast(_factory, expression, type); } @@ -289,58 +263,33 @@ return new HqlBitwiseNot(_factory); } - public HqlNot Not() + public HqlNot Not(HqlBooleanExpression operand) { - return new HqlNot(_factory); + return new HqlNot(_factory, operand); } - public HqlAverage Average() + public HqlAverage Average(HqlExpression expression) { - return new HqlAverage(_factory); - } - - public HqlAverage Average(HqlTreeNode expression) - { return new HqlAverage(_factory, expression); } - public HqlSum Sum() + public HqlSum Sum(HqlExpression expression) { - return new HqlSum(_factory); - } - - public HqlSum Sum(HqlTreeNode expression) - { return new HqlSum(_factory, expression); } - public HqlMin Min() + public HqlMin Min(HqlExpression expression) { - return new HqlMin(_factory); - } - - public HqlMin Min(HqlTreeNode expression) - { return new HqlMin(_factory, expression); } - public HqlMax Max() + public HqlMax Max(HqlExpression expression) { - return new HqlMax(_factory); - } - - public HqlMax Max(HqlTreeNode expression) - { return new HqlMax(_factory, expression); } - public HqlAnd And(HqlTreeNode left, HqlTreeNode right) + public HqlJoin Join(HqlExpression expression, HqlAlias @alias) { - return new HqlAnd(_factory, left, right); - } - - public HqlJoin Join(HqlTreeNode expression, HqlAlias @alias) - { return new HqlJoin(_factory, expression, @alias); } @@ -349,9 +298,9 @@ return new HqlAny(_factory); } - public HqlExists Exists() + public HqlExists Exists(HqlQuery query) { - return new HqlExists(_factory); + return new HqlExists(_factory, query); } public HqlElements Elements() @@ -374,9 +323,9 @@ return new HqlDirectionDescending(_factory); } - public HqlGroupBy GroupBy() + public HqlGroupBy GroupBy(HqlExpression expression) { - return new HqlGroupBy(_factory); + return new HqlGroupBy(_factory, expression); } public HqlAll All() @@ -384,14 +333,14 @@ return new HqlAll(_factory); } - public HqlLike Like() + public HqlLike Like(HqlExpression lhs, HqlExpression rhs) { - return new HqlLike(_factory); + return new HqlLike(_factory, lhs, rhs); } - public HqlConcat Concat() + public HqlConcat Concat(params HqlExpression[] args) { - return new HqlConcat(_factory); + return new HqlConcat(_factory, args); } public HqlExpressionList ExpressionList() @@ -399,9 +348,14 @@ return new HqlExpressionList(_factory); } - public HqlMethodCall MethodCall() + public HqlMethodCall MethodCall(string methodName, HqlExpression parameter) { - return new HqlMethodCall(_factory); + return new HqlMethodCall(_factory, methodName, parameter); } + + public HqlDistinctHolder DistinctHolder(params HqlTreeNode[] children) + { + return new HqlDistinctHolder(_factory, children); + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2009-11-10 18:07:01 UTC (rev 4827) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Reflection; using NHibernate.Hql.Ast.ANTLR; using NHibernate.Hql.Ast.ANTLR.Tree; @@ -8,18 +7,37 @@ { public class HqlTreeNode { - protected readonly IASTNode _node; - protected readonly List<HqlTreeNode> _children; + private readonly IASTNode _node; + private readonly List<HqlTreeNode> _children; - protected HqlTreeNode(int type, string text, IASTFactory factory, params HqlTreeNode[] children) + protected HqlTreeNode(int type, string text, IASTFactory factory, IEnumerable<HqlTreeNode> children) { _node = factory.CreateNode(type, text); _children = new List<HqlTreeNode>(); + AddChildren(children); + } + + protected HqlTreeNode(int type, string text, IASTFactory factory, params HqlTreeNode[] children) : this(type, text, factory, (IEnumerable<HqlTreeNode>) children) + { + } + + private void AddChildren(IEnumerable<HqlTreeNode> children) + { foreach (var child in children) { - _children.Add(child); - _node.AddChild(child.AstNode); + if (child != null) + { + if (child is HqlDistinctHolder) + { + AddChildren(child.Children); + } + else + { + _children.Add(child); + _node.AddChild(child.AstNode); + } + } } } @@ -57,13 +75,7 @@ public IEnumerable<HqlTreeNode> Children { - get - { - foreach (var child in _children) - { - yield return child; - } - } + get { return _children; } } public void ClearChildren() @@ -72,6 +84,11 @@ _node.ClearChildren(); } + protected void SetText(string text) + { + _node.Text = text; + } + internal IASTNode AstNode { get { return _node; } @@ -79,28 +96,74 @@ internal void AddChild(HqlTreeNode child) { - _children.Add(child); - _node.AddChild(child.AstNode); + if (child is HqlDistinctHolder) + { + AddChildren(child.Children); + } + else + { + _children.Add(child); + _node.AddChild(child.AstNode); + } } - public void AddChild(int index, HqlTreeNode node) + public HqlExpression AsExpression() { - _children.Insert(index, node); - _node.InsertChild(index, node.AstNode); + // TODO - nice error handling if cast fails + return (HqlExpression) this; } + public virtual HqlBooleanExpression AsBooleanExpression() + { + // TODO - nice error handling if cast fails + return (HqlBooleanExpression)this; + } } - public class HqlQuery : HqlTreeNode + public abstract class HqlStatement : HqlTreeNode { - internal HqlQuery(IASTFactory factory, params HqlTreeNode[] children) + protected HqlStatement(int type, string text, IASTFactory factory, params HqlTreeNode[] children) + : base(type, text, factory, children) + { + } + } + + public abstract class HqlExpression : HqlTreeNode + { + protected HqlExpression(int type, string text, IASTFactory factory, IEnumerable<HqlTreeNode> children) + : base(type, text, factory, children) + { + } + + protected HqlExpression(int type, string text, IASTFactory factory, params HqlTreeNode[] children) + : base(type, text, factory, children) + { + } + } + + public abstract class HqlBooleanExpression : HqlExpression + { + protected HqlBooleanExpression(int type, string text, IASTFactory factory, IEnumerable<HqlTreeNode> children) + : base(type, text, factory, children) + { + } + + protected HqlBooleanExpression(int type, string text, IASTFactory factory, params HqlTreeNode[] children) + : base(type, text, factory, children) + { + } + } + + public class HqlQuery : HqlExpression + { + internal HqlQuery(IASTFactory factory, params HqlStatement[] children) : base(HqlSqlWalker.QUERY, "query", factory, children) { } } - public class HqlIdent : HqlTreeNode + public class HqlIdent : HqlExpression { internal HqlIdent(IASTFactory factory, string ident) : base(HqlSqlWalker.IDENT, ident, factory) @@ -118,24 +181,24 @@ switch (System.Type.GetTypeCode(type)) { case TypeCode.Boolean: - _node.Text = "bool"; + SetText("bool"); break; case TypeCode.Int32: - _node.Text = "integer"; + SetText("integer"); break; case TypeCode.Decimal: - _node.Text = "decimal"; + SetText("decimal"); break; case TypeCode.DateTime: - _node.Text = "datetime"; + SetText("datetime"); break; case TypeCode.String: - _node.Text = "string"; + SetText("string"); break; default: if (type == typeof(Guid)) { - _node.Text = "guid"; + SetText("guid"); break; } throw new NotSupportedException(string.Format("Don't currently support idents of type {0}", type.Name)); @@ -155,7 +218,7 @@ } - public class HqlRange : HqlTreeNode + public class HqlRange : HqlStatement { internal HqlRange(IASTFactory factory, params HqlTreeNode[] children) : base(HqlSqlWalker.RANGE, "range", factory, children) @@ -163,7 +226,7 @@ } } - public class HqlFrom : HqlTreeNode + public class HqlFrom : HqlStatement { internal HqlFrom(IASTFactory factory, params HqlTreeNode[] children) : base(HqlSqlWalker.FROM, "from", factory, children) @@ -171,7 +234,7 @@ } } - public class HqlSelectFrom : HqlTreeNode + public class HqlSelectFrom : HqlStatement { internal HqlSelectFrom(IASTFactory factory, params HqlTreeNode[] children) : base(HqlSqlWalker.SELECT_FROM, "select_from", factory, children) @@ -179,7 +242,7 @@ } } - public class HqlAlias : HqlTreeNode + public class HqlAlias : HqlExpression { public HqlAlias(IASTFactory factory, string @alias) : base(HqlSqlWalker.ALIAS, alias, factory) @@ -187,68 +250,63 @@ } } - public class HqlDivide : HqlTreeNode + public class HqlDivide : HqlExpression { - public HqlDivide(IASTFactory factory) - : base(HqlSqlWalker.DIV, "/", factory) + public HqlDivide(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) + : base(HqlSqlWalker.DIV, "/", factory, lhs, rhs) { } } - public class HqlMultiplty : HqlTreeNode + public class HqlMultiplty : HqlExpression { - public HqlMultiplty(IASTFactory factory) - : base(HqlSqlWalker.STAR, "*", factory) + public HqlMultiplty(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) + : base(HqlSqlWalker.STAR, "*", factory, lhs, rhs) { } } - public class HqlSubtract : HqlTreeNode + public class HqlSubtract : HqlExpression { - public HqlSubtract(IASTFactory factory) - : base(HqlSqlWalker.MINUS, "-", factory) + public HqlSubtract(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) + : base(HqlSqlWalker.MINUS, "-", factory, lhs, rhs) { } } - public class HqlAdd : HqlTreeNode + public class HqlAdd : HqlExpression { - public HqlAdd(IASTFactory factory) - : base(HqlSqlWalker.PLUS, "+", factory) + public HqlAdd(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) + : base(HqlSqlWalker.PLUS, "+", factory, lhs, rhs) { } } - public class HqlBooleanOr : HqlTreeNode + public class HqlBooleanOr : HqlBooleanExpression { - public HqlBooleanOr(IASTFactory factory) - : base(HqlSqlWalker.OR, "or", factory) + public HqlBooleanOr(IASTFactory factory, HqlBooleanExpression lhs, HqlBooleanExpression rhs) + : base(HqlSqlWalker.OR, "or", factory, lhs, rhs) { } } - public class HqlBooleanAnd : HqlTreeNode + public class HqlBooleanAnd : HqlBooleanExpression { - public HqlBooleanAnd(IASTFactory factory) - : base(HqlSqlWalker.AND, "/", factory) + public HqlBooleanAnd(IASTFactory factory, HqlBooleanExpression lhs, HqlBooleanExpression rhs) + : base(HqlSqlWalker.AND, "/", factory, lhs, rhs) { } } - public class HqlEquality : HqlTreeNode + public class HqlEquality : HqlBooleanExpression { - public HqlEquality(IASTFactory factory) - : base(HqlSqlWalker.EQ, "==", factory) - { - } - - public HqlEquality(IASTFactory factory, HqlTreeNode lhs, HqlTreeNode rhs) + public HqlEquality(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) : base(HqlSqlWalker.EQ, "==", factory, lhs, rhs) { } } - public class HqlParameter : HqlTreeNode + public class HqlParameter : HqlExpression { public HqlParameter(IASTFactory factory, string name) : base(HqlSqlWalker.COLON, ":", factory) @@ -257,28 +315,40 @@ } } - public class HqlDot : HqlTreeNode + public class HqlDot : HqlExpression { - public HqlDot(IASTFactory factory) - : base(HqlSqlWalker.DOT, ".", factory) + private readonly IASTFactory _factory; + + public HqlDot(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) + : base(HqlSqlWalker.DOT, ".", factory, lhs, rhs) { + _factory = factory; } + + public override HqlBooleanExpression AsBooleanExpression() + { + // If we are of boolean type, then we can acts as boolean expression + // TODO - implement type check + return new HqlBooleanDot(_factory, this); + } } - public class HqlWhere : HqlTreeNode + public class HqlBooleanDot : HqlBooleanExpression { - public HqlWhere(IASTFactory factory) - : base(HqlSqlWalker.WHERE, "where", factory) + public HqlBooleanDot(IASTFactory factory, HqlDot dot) : base(dot.AstNode.Type, dot.AstNode.Text, factory, dot.Children) { } + } - public HqlWhere(IASTFactory factory, HqlTreeNode expression) + public class HqlWhere : HqlStatement + { + public HqlWhere(IASTFactory factory, HqlExpression expression) : base(HqlSqlWalker.WHERE, "where", factory, expression) { } } - public class HqlConstant : HqlTreeNode + public class HqlConstant : HqlExpression { public HqlConstant(IASTFactory factory, int type, string value) : base(type, value, factory) @@ -334,19 +404,12 @@ } } - public class HqlOrderBy : HqlTreeNode + public class HqlOrderBy : HqlStatement { public HqlOrderBy(IASTFactory factory) : base(HqlSqlWalker.ORDER, "", factory) { } - - public HqlOrderBy(IASTFactory factory, HqlTreeNode expression, HqlDirection hqlDirection) - : base(HqlSqlWalker.ORDER, "", factory, expression, - hqlDirection == HqlDirection.Ascending ? - (HqlTreeNode)new HqlDirectionAscending(factory) : (HqlTreeNode)new HqlDirectionDescending(factory)) - { - } } public enum HqlDirection @@ -355,7 +418,7 @@ Descending } - public class HqlDirectionAscending : HqlTreeNode + public class HqlDirectionAscending : HqlStatement { public HqlDirectionAscending(IASTFactory factory) : base(HqlSqlWalker.ASCENDING, "asc", factory) @@ -363,7 +426,7 @@ } } - public class HqlDirectionDescending : HqlTreeNode + public class HqlDirectionDescending : HqlStatement { public HqlDirectionDescending(IASTFactory factory) : base(HqlSqlWalker.DESCENDING, "desc", factory) @@ -371,120 +434,107 @@ } } - public class HqlSelect : HqlTreeNode + public class HqlSelect : HqlStatement { - public HqlSelect(IASTFactory factory, params HqlTreeNode[] expression) + public HqlSelect(IASTFactory factory, params HqlExpression[] expression) : base(HqlSqlWalker.SELECT, "select", factory, expression) { } } - public class HqlConstructor : HqlTreeNode + public class HqlElse : HqlStatement { - public HqlConstructor(IASTFactory factory, ConstructorInfo ctor) - : base(HqlSqlWalker.CONSTRUCTOR, "ctor", factory) + public HqlElse(IASTFactory factory, HqlExpression ifFalse) + : base(HqlSqlWalker.ELSE, "else", factory, ifFalse) { - ((ASTNode)_node).Hack = ctor; } } - public class HqlNill : HqlTreeNode + public class HqlWhen : HqlStatement { - public HqlNill(IASTFactory factory) - : base(0, "nill", factory) + public HqlWhen(IASTFactory factory, HqlExpression predicate, HqlExpression ifTrue) + : base(HqlSqlWalker.WHEN, "when", factory, predicate, ifTrue) { } } - public class HqlElse : HqlTreeNode + public class HqlCase : HqlExpression { - public HqlElse(IASTFactory factory) - : base(HqlSqlWalker.ELSE, "else", factory) + public HqlCase(IASTFactory factory, HqlWhen[] whenClauses, HqlExpression ifFalse) + : base(HqlSqlWalker.CASE, "case", factory, whenClauses) { + if (ifFalse != null) + { + AddChild(new HqlElse(factory, ifFalse)); + } } } - public class HqlWhen : HqlTreeNode + public class HqlGreaterThanOrEqual : HqlBooleanExpression { - public HqlWhen(IASTFactory factory) - : base(HqlSqlWalker.WHEN, "when", factory) + public HqlGreaterThanOrEqual(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) + : base(HqlSqlWalker.GE, "ge", factory, lhs, rhs) { } } - public class HqlCase : HqlTreeNode + public class HqlGreaterThan : HqlBooleanExpression { - public HqlCase(IASTFactory factory) - : base(HqlSqlWalker.CASE, "case", factory) + public HqlGreaterThan(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) + : base(HqlSqlWalker.GT, "gt", factory, lhs, rhs) { } } - public class HqlGreaterThanOrEqual : HqlTreeNode + public class HqlLessThanOrEqual : HqlBooleanExpression { - public HqlGreaterThanOrEqual(IASTFactory factory) - : base(HqlSqlWalker.GE, "ge", factory) + public HqlLessThanOrEqual(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) + : base(HqlSqlWalker.LE, "le", factory, lhs, rhs) { } } - public class HqlGreaterThan : HqlTreeNode + public class HqlLessThan : HqlBooleanExpression { - public HqlGreaterThan(IASTFactory factory) - : base(HqlSqlWalker.GT, "gt", factory) + public HqlLessThan(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) + : base(HqlSqlWalker.LT, "lt", factory, lhs, rhs) { } } - public class HqlLessThanOrEqual : HqlTreeNode + public class HqlInequality : HqlBooleanExpression { - public HqlLessThanOrEqual(IASTFactory factory) - : base(HqlSqlWalker.LE, "le", factory) + public HqlInequality(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) + : base(HqlSqlWalker.NE, "ne", factory, lhs, rhs) { } } - public class HqlLessThan : HqlTreeNode + public class HqlRowStar : HqlStatement { - public HqlLessThan(IASTFactory factory) - : base(HqlSqlWalker.LT, "lt", factory) - { - } - } - - public class HqlInequality : HqlTreeNode - { - public HqlInequality(IASTFactory factory) - : base(HqlSqlWalker.NE, "ne", factory) - { - } - } - - public class HqlRowStar : HqlTreeNode - { public HqlRowStar(IASTFactory factory) : base(HqlSqlWalker.ROW_STAR, "*", factory) { } } - public class HqlCount : HqlTreeNode + public class HqlCount : HqlExpression { - public HqlCount(IASTFactory factory) : base(HqlSqlWalker.COUNT, "count", factory) { } - - public HqlCount(IASTFactory factory, HqlTreeNode child) + + public HqlCount(IASTFactory factory, HqlExpression child) : base(HqlSqlWalker.COUNT, "count", factory, child) { } } - public class HqlAs : HqlTreeNode + public class HqlAs : HqlExpression { - public HqlAs(IASTFactory factory, HqlTreeNode expression, System.Type type) : base(HqlSqlWalker.AS, "as", factory, expression) + public HqlAs(IASTFactory factory, HqlExpression expression, System.Type type) + : base(HqlSqlWalker.AS, "as", factory, expression) { switch (System.Type.GetTypeCode(type)) { @@ -497,136 +547,118 @@ } } - public class HqlCast : HqlTreeNode + public class HqlCast : HqlExpression { - public HqlCast(IASTFactory factory, HqlTreeNode expression, System.Type type) : base(HqlSqlWalker.METHOD_CALL, "method", factory) + public HqlCast(IASTFactory factory, HqlExpression expression, System.Type type) + : base(HqlSqlWalker.METHOD_CALL, "method", factory) { AddChild(new HqlIdent(factory, "cast")); AddChild(new HqlExpressionList(factory, expression, new HqlIdent(factory, type))); } } - public class HqlExpressionList : HqlTreeNode + public class HqlExpressionList : HqlStatement { public HqlExpressionList(IASTFactory factory, params HqlTreeNode[] expression) : base(HqlSqlWalker.EXPR_LIST, "expr_list", factory, expression) { } } - public class HqlNot : HqlTreeNode + public class HqlNot : HqlBooleanExpression { - public HqlNot(IASTFactory factory) : base(HqlSqlWalker.NOT, "not", factory) + public HqlNot(IASTFactory factory, HqlBooleanExpression operand) + : base(HqlSqlWalker.NOT, "not", factory, operand) { } } - public class HqlAverage : HqlTreeNode + public class HqlAverage : HqlExpression { - public HqlAverage(IASTFactory factory) - : base(HqlSqlWalker.AGGREGATE, "avg", factory) + public HqlAverage(IASTFactory factory, HqlExpression expression) + : base(HqlSqlWalker.AGGREGATE, "avg", factory, expression) { } - - public HqlAverage(IASTFactory factory, HqlTreeNode expression) : base(HqlSqlWalker.AGGREGATE, "avg", factory, expression) - { - } } - public class HqlBitwiseNot : HqlTreeNode + public class HqlBitwiseNot : HqlExpression { public HqlBitwiseNot(IASTFactory factory) : base(HqlSqlWalker.BNOT, "not", factory) { } } - public class HqlSum : HqlTreeNode + public class HqlSum : HqlExpression { public HqlSum(IASTFactory factory) : base(HqlSqlWalker.AGGREGATE, "sum", factory) { } - public HqlSum(IASTFactory factory, HqlTreeNode expression) + public HqlSum(IASTFactory factory, HqlExpression expression) : base(HqlSqlWalker.AGGREGATE, "sum", factory, expression) { } } - public class HqlMax : HqlTreeNode + public class HqlMax : HqlExpression { - public HqlMax(IASTFactory factory) : base(HqlSqlWalker.AGGREGATE, "max", factory) - { - } - - public HqlMax(IASTFactory factory, HqlTreeNode expression) + public HqlMax(IASTFactory factory, HqlExpression expression) : base(HqlSqlWalker.AGGREGATE, "max", factory, expression) { } } - public class HqlMin : HqlTreeNode + public class HqlMin : HqlExpression { - public HqlMin(IASTFactory factory) - : base(HqlSqlWalker.AGGREGATE, "min", factory) - { - } - - public HqlMin(IASTFactory factory, HqlTreeNode expression) + public HqlMin(IASTFactory factory, HqlExpression expression) : base(HqlSqlWalker.AGGREGATE, "min", factory, expression) { } } - public class HqlAnd : HqlTreeNode + public class HqlJoin : HqlStatement { - public HqlAnd(IASTFactory factory, HqlTreeNode left, HqlTreeNode right) : base(HqlSqlWalker.AND, "and", factory, left, right) + public HqlJoin(IASTFactory factory, HqlExpression expression, HqlAlias @alias) : base(HqlSqlWalker.JOIN, "join", factory, expression, @alias) { } } - public class HqlJoin : HqlTreeNode + public class HqlAny : HqlBooleanExpression { - public HqlJoin(IASTFactory factory, HqlTreeNode expression, HqlAlias @alias) : base(HqlSqlWalker.JOIN, "join", factory, expression, @alias) - { - } - } - - public class HqlAny : HqlTreeNode - { public HqlAny(IASTFactory factory) : base(HqlSqlWalker.ANY, "any", factory) { } } - public class HqlExists : HqlTreeNode + public class HqlExists : HqlBooleanExpression { - public HqlExists(IASTFactory factory) : base(HqlSqlWalker.EXISTS, "exists", factory) + public HqlExists(IASTFactory factory, HqlQuery query) : base(HqlSqlWalker.EXISTS, "exists", factory, query) { } } - public class HqlElements : HqlTreeNode + public class HqlElements : HqlBooleanExpression { public HqlElements(IASTFactory factory) : base(HqlSqlWalker.ELEMENTS, "elements", factory) { } } - public class HqlDistinct : HqlTreeNode + public class HqlDistinct : HqlStatement { public HqlDistinct(IASTFactory factory) : base(HqlSqlWalker.DISTINCT, "distinct", factory) { } } - public class HqlGroupBy : HqlTreeNode + public class HqlGroupBy : HqlStatement { - public HqlGroupBy(IASTFactory factory) : base(HqlSqlWalker.GROUP, "group by", factory) + public HqlGroupBy(IASTFactory factory, HqlExpression expression) : base(HqlSqlWalker.GROUP, "group by", factory, expression) { } } - public class HqlAll : HqlTreeNode + public class HqlAll : HqlBooleanExpression { public HqlAll(IASTFactory factory) : base(HqlSqlWalker.ALL, "all", factory) @@ -634,24 +666,38 @@ } } - public class HqlLike : HqlTreeNode + public class HqlLike : HqlBooleanExpression { - public HqlLike(IASTFactory factory) : base(HqlSqlWalker.LIKE, "like", factory) + public HqlLike(IASTFactory factory, HqlExpression lhs, HqlExpression rhs) + : base(HqlSqlWalker.LIKE, "like", factory, lhs, rhs) { } } - public class HqlConcat : HqlTreeNode + public class HqlConcat : HqlExpression { - public HqlConcat(IASTFactory factory) : base(HqlSqlWalker.METHOD_CALL, "method", factory) + public HqlConcat(IASTFactory factory, params HqlExpression[] args) + : base(HqlSqlWalker.METHOD_CALL, "method", factory) { + AddChild(new HqlIdent(factory, "concat")); + AddChild(new HqlExpressionList(factory, args)); } } - public class HqlMethodCall : HqlTreeNode + public class HqlMethodCall : HqlExpression { - public HqlMethodCall(IASTFactory factory) : base(HqlSqlWalker.METHOD_CALL, "method", factory) + public HqlMethodCall(IASTFactory factory, string methodName, HqlExpression parameter) + : base(HqlSqlWalker.METHOD_CALL, "method", factory) { + AddChild(new HqlIdent(factory, methodName)); + AddChild(new HqlExpressionList(factory, parameter)); } } + + public class HqlDistinctHolder : HqlExpression + { + public HqlDistinctHolder(IASTFactory factory, HqlTreeNode[] children) : base(int.MinValue, "distinct holder", factory, children) + { + } + } } \ No newline at end of file Property changes on: trunk/nhibernate/src/NHibernate/Linq/Functions ___________________________________________________________________ Added: bugtraq:url + http://jira.nhibernate.org/browse/%BUGID% Added: bugtraq:logregex + NH-\d+ Added: trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForMethod.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForMethod.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForMethod.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq.Expressions; +using System.Reflection; +using NHibernate.Hql.Ast; +using NHibernate.Linq.Visitors; + +namespace NHibernate.Linq.Functions +{ + public abstract class BaseHqlGeneratorForMethod : IHqlGeneratorForMethod + { + public IEnumerable<MethodInfo> SupportedMethods { get; protected set; } + + public abstract HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor); + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForProperty.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForProperty.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForProperty.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; +using NHibernate.Hql.Ast; +using NHibernate.Linq.Visitors; + +namespace NHibernate.Linq.Functions +{ + public abstract class BaseHqlGeneratorForProperty : IHqlGeneratorForProperty + { + public IEnumerable<MemberInfo> SupportedProperties { get; protected set; } + public abstract HqlTreeNode BuildHql(MemberInfo member, Expression expression, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor); + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForType.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForType.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Functions/BaseHqlGeneratorForType.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using NHibernate.Linq.Visitors; + +namespace NHibernate.Linq.Functions +{ + abstract public class BaseHqlGeneratorForType : IHqlGeneratorForType + { + protected readonly List<IHqlGeneratorForMethod> MethodRegistry = new List<IHqlGeneratorForMethod>(); + protected readonly List<IHqlGeneratorForProperty> PropertyRegistry = new List<IHqlGeneratorForProperty>(); + + public void Register(FunctionRegistry functionRegistry) + { + foreach (var generator in MethodRegistry) + { + foreach (var method in generator.SupportedMethods) + { + functionRegistry.RegisterMethodGenerator(method, generator); + } + } + + foreach (var generator in PropertyRegistry) + { + foreach (var property in generator.SupportedProperties) + { + functionRegistry.RegisterPropertyGenerator(property, generator); + } + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Linq/Functions/DateTimeGenerator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Functions/DateTimeGenerator.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Functions/DateTimeGenerator.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -0,0 +1,38 @@ +using System; +using System.Linq.Expressions; +using System.Reflection; +using NHibernate.Hql.Ast; +using NHibernate.Linq.Visitors; + +namespace NHibernate.Linq.Functions +{ + public class DateTimeGenerator : BaseHqlGeneratorForType + { + public DateTimeGenerator() + { + PropertyRegistry.Add(new DatePartGenerator()); + } + + public class DatePartGenerator : BaseHqlGeneratorForProperty + { + public DatePartGenerator() + { + SupportedProperties = new[] + { + ReflectionHelper.GetProperty((DateTime x) => x.Year), + ReflectionHelper.GetProperty((DateTime x) => x.Month), + ReflectionHelper.GetProperty((DateTime x) => x.Day), + ReflectionHelper.GetProperty((DateTime x) => x.Hour), + ReflectionHelper.GetProperty((DateTime x) => x.Minute), + ReflectionHelper.GetProperty((DateTime x) => x.Second), + }; + } + + public override HqlTreeNode BuildHql(MemberInfo member, Expression expression, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) + { + return treeBuilder.MethodCall(member.Name.ToLowerInvariant(), + visitor.Visit(expression).AsExpression()); + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Linq/Functions/FunctionRegistry.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Functions/FunctionRegistry.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Functions/FunctionRegistry.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace NHibernate.Linq.Functions +{ + public class FunctionRegistry + { + public static FunctionRegistry Initialise() + { + var registry = new FunctionRegistry(); + + // TODO - could use reflection here + registry.Register(new QueryableGenerator()); + registry.Register(new StringGenerator()); + registry.Register(new DateTimeGenerator()); + + return registry; + } + + private readonly Dictionary<MethodInfo, IHqlGeneratorForMethod> _registeredMethods = new Dictionary<MethodInfo, IHqlGeneratorForMethod>(); + private readonly Dictionary<MemberInfo, IHqlGeneratorForProperty> _registeredProperties = new Dictionary<MemberInfo, IHqlGeneratorForProperty>(); + + public IHqlGeneratorForMethod GetMethodGenerator(MethodInfo method) + { + IHqlGeneratorForMethod methodGenerator; + + if (method.IsGenericMethod) + { + method = method.GetGenericMethodDefinition(); + } + + if (_registeredMethods.TryGetValue(method, out methodGenerator)) + { + return methodGenerator; + } + + throw new NotSupportedException(method.ToString()); + } + + public IHqlGeneratorForProperty GetPropertyGenerator(MemberInfo member) + { + IHqlGeneratorForProperty propertyGenerator; + + if (_registeredProperties.TryGetValue(member, out propertyGenerator)) + { + return propertyGenerator; + } + + // TODO - different usage pattern to method generator + return null; + } + + public void RegisterMethodGenerator(MethodInfo method, IHqlGeneratorForMethod generator) + { + _registeredMethods.Add(method, generator); + } + + public void RegisterPropertyGenerator(MemberInfo property, IHqlGeneratorForProperty generator) + { + _registeredProperties.Add(property, generator); + } + + private void Register(IHqlGeneratorForType typeMethodGenerator) + { + typeMethodGenerator.Register(this); + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForMethod.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForMethod.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForMethod.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq.Expressions; +using System.Reflection; +using NHibernate.Hql.Ast; +using NHibernate.Linq.Visitors; + +namespace NHibernate.Linq.Functions +{ + public interface IHqlGeneratorForMethod + { + IEnumerable<MethodInfo> SupportedMethods { get; } + HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor); + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForProperty.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForProperty.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForProperty.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; +using NHibernate.Hql.Ast; +using NHibernate.Linq.Visitors; + +namespace NHibernate.Linq.Functions +{ + public interface IHqlGeneratorForProperty + { + IEnumerable<MemberInfo> SupportedProperties { get; } + HqlTreeNode BuildHql(MemberInfo member, Expression expression, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor); + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForType.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForType.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Functions/IHqlGeneratorForType.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -0,0 +1,7 @@ +namespace NHibernate.Linq.Functions +{ + public interface IHqlGeneratorForType + { + void Register(FunctionRegistry functionRegistry); + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Linq/Functions/QueryableGenerator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Functions/QueryableGenerator.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Functions/QueryableGenerator.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -0,0 +1,129 @@ +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.Functions +{ + public class QueryableGenerator : BaseHqlGeneratorForType + { + public QueryableGenerator() + { + // TODO - could use reflection + MethodRegistry.Add(new AnyGenerator()); + MethodRegistry.Add(new AllGenerator()); + MethodRegistry.Add(new MinGenerator()); + MethodRegistry.Add(new MaxGenerator()); + } + + class AnyGenerator : BaseHqlGeneratorForMethod + { + public AnyGenerator() + { + SupportedMethods = new[] + { + ReflectionHelper.GetMethod(() => Queryable.Any<object>(null)), + ReflectionHelper.GetMethod(() => Queryable.Any<object>(null, null)), + ReflectionHelper.GetMethod(() => Enumerable.Any<object>(null)), + ReflectionHelper.GetMethod(() => Enumerable.Any<object>(null, null)) + }; + } + + public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) + { + HqlAlias alias = null; + HqlWhere where = null; + + if (arguments.Count > 1) + { + var expr = (LambdaExpression)arguments[1]; + + alias = treeBuilder.Alias(expr.Parameters[0].Name); + where = treeBuilder.Where(visitor.Visit(arguments[1]).AsExpression()); + } + + return treeBuilder.Exists( + treeBuilder.Query( + treeBuilder.SelectFrom( + treeBuilder.From( + treeBuilder.Range( + visitor.Visit(arguments[0]), + alias) + ) + ), + where)); + } + } + + class AllGenerator : BaseHqlGeneratorForMethod + { + public AllGenerator() + { + SupportedMethods = new[] + { + ReflectionHelper.GetMethod(() => Queryable.All<object>(null, null)), + ReflectionHelper.GetMethod(() => Enumerable.All<object>(null, null)) + }; + } + + public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) + { + // All has two arguments. Arg 1 is the source and arg 2 is the predicate + var predicate = (LambdaExpression)arguments[1]; + + return treeBuilder.Not( + treeBuilder.Exists( + treeBuilder.Query( + treeBuilder.SelectFrom( + treeBuilder.From( + treeBuilder.Range( + visitor.Visit(arguments[0]), + treeBuilder.Alias(predicate.Parameters[0].Name)) + ) + ), + treeBuilder.Where( + treeBuilder.Not(visitor.Visit(arguments[1]).AsBooleanExpression()) + ) + ) + ) + ); + } + } + + class MinGenerator : BaseHqlGeneratorForMethod + { + public MinGenerator() + { + SupportedMethods = new[] + { + ReflectionHelper.GetMethod(() => Queryable.Min<object>(null)), + ReflectionHelper.GetMethod(() => Enumerable.Min<object>(null)) + }; + } + + public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) + { + return treeBuilder.Min(visitor.Visit(arguments[1]).AsExpression()); + } + } + + class MaxGenerator : BaseHqlGeneratorForMethod + { + public MaxGenerator() + { + SupportedMethods = new[] + { + ReflectionHelper.GetMethod(() => Queryable.Max<object>(null)), + ReflectionHelper.GetMethod(() => Enumerable.Max<object>(null)) + }; + } + + public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) + { + return treeBuilder.Max(visitor.Visit(arguments[1]).AsExpression()); + } + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Functions/StringGenerator.cs 2009-11-11 13:37:38 UTC (rev 4828) @@ -0,0 +1,133 @@ +using System.Collections.ObjectModel; +using System.Linq.Expressions; +using System.Reflection; +using NHibernate.Hql.Ast; +using NHibernate.Linq.Visitors; + +namespace NHibernate.Linq.Functions +{ + public class StringGenerator : BaseHqlGeneratorForType + { + public StringGenerator() + { + // TODO - could use reflection + MethodRegistry.Add(new StartsWithGenerator()); + MethodRegistry.Add(new EndsWithGenerator()); + MethodRegistry.Add(new ContainsGenerator()); + MethodRegistry.Add(new EqualsGenerator()); + MethodRegistry.Add(new ToUpperLowerGenerator()); + + PropertyRegistry.Add(new LengthGenerator()); + } + + public class LengthGenerator : BaseHqlGeneratorForProperty + { + public LengthGenerator() + {... [truncated message content] |