|
From: <ste...@us...> - 2009-08-31 10:01:52
|
Revision: 4703
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4703&view=rev
Author: steverstrong
Date: 2009-08-31 10:01:43 +0000 (Mon, 31 Aug 2009)
Log Message:
-----------
New files for linq provider
Added Paths:
-----------
trunk/nhibernate/lib/net/3.5/Remotion.Data.Linq.dll
trunk/nhibernate/lib/net/3.5/Remotion.Interfaces.dll
trunk/nhibernate/lib/net/3.5/Remotion.dll
trunk/nhibernate/src/NHibernate/Hql/Ast/HqlExpression.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs
trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs
trunk/nhibernate/src/NHibernate/Linq/CommandData.cs
trunk/nhibernate/src/NHibernate/Linq/HqlNodeStack.cs
trunk/nhibernate/src/NHibernate/Linq/NamedParameter.cs
trunk/nhibernate/src/NHibernate/Linq/NhExpressionTreeVisitor.cs
trunk/nhibernate/src/NHibernate/Linq/NhQueryExecutor.cs
trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs
trunk/nhibernate/src/NHibernate/Linq/Nominator.cs
trunk/nhibernate/src/NHibernate/Linq/ParameterAggregator.cs
trunk/nhibernate/src/NHibernate/Linq/ProjectionEvaluator.cs
trunk/nhibernate/src/NHibernate/Linq/QueryModelVisitor.cs
trunk/nhibernate/src/NHibernate/Linq/ResultTransformer.cs
trunk/nhibernate/src/NHibernate.Test/Linq/LinqQuerySamples.cs
trunk/nhibernate/src/NHibernate.Test/Linq/ReadonlyTestCase.cs
Added: trunk/nhibernate/lib/net/3.5/Remotion.Data.Linq.dll
===================================================================
(Binary files differ)
Property changes on: trunk/nhibernate/lib/net/3.5/Remotion.Data.Linq.dll
___________________________________________________________________
Added: svn:executable
+ *
Added: svn:mime-type
+ application/octet-stream
Added: trunk/nhibernate/lib/net/3.5/Remotion.Interfaces.dll
===================================================================
(Binary files differ)
Property changes on: trunk/nhibernate/lib/net/3.5/Remotion.Interfaces.dll
___________________________________________________________________
Added: svn:executable
+ *
Added: svn:mime-type
+ application/octet-stream
Added: trunk/nhibernate/lib/net/3.5/Remotion.dll
===================================================================
(Binary files differ)
Property changes on: trunk/nhibernate/lib/net/3.5/Remotion.dll
___________________________________________________________________
Added: svn:executable
+ *
Added: svn:mime-type
+ application/octet-stream
Added: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlExpression.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlExpression.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlExpression.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,36 @@
+using System.Collections.Generic;
+using System.Reflection;
+using NHibernate.Hql.Ast.ANTLR;
+using NHibernate.Hql.Ast.ANTLR.Tree;
+
+namespace NHibernate.Hql.Ast
+{
+ public class HqlExpression : IQueryExpression
+ {
+ private readonly IASTNode _node;
+ private readonly System.Type _type;
+ private readonly string _key;
+
+ public HqlExpression(HqlQuery node, System.Type type)
+ {
+ _node = node.AstNode;
+ _type = type;
+ _key = _node.ToStringTree();
+ }
+
+ public IASTNode Translate(ISessionFactory sessionFactory)
+ {
+ return _node;
+ }
+
+ public string Key
+ {
+ get { return _key; }
+ }
+
+ public System.Type Type
+ {
+ get { return _type; }
+ }
+ }
+}
Property changes on: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlExpression.cs
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,332 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using NHibernate.Hql.Ast.ANTLR.Tree;
+
+namespace NHibernate.Hql.Ast
+{
+ public class HqlTreeBuilder
+ {
+ private readonly ASTFactory _factory;
+
+ public HqlTreeBuilder()
+ {
+ _factory = new ASTFactory(new ASTTreeAdaptor());
+ }
+
+ public HqlQuery Query()
+ {
+ return new HqlQuery(_factory);
+ }
+
+ public HqlQuery Query(HqlSelectFrom selectFrom)
+ {
+ return new HqlQuery(_factory, selectFrom);
+ }
+
+ public HqlQuery Query(HqlSelectFrom selectFrom, HqlWhere where)
+ {
+ return new HqlQuery(_factory, selectFrom, where);
+ }
+
+ public HqlTreeNode Query(HqlSelectFrom selectFrom, HqlWhere where, HqlOrderBy orderBy)
+ {
+ return new HqlQuery(_factory, selectFrom, where, orderBy);
+ }
+
+ public HqlSelectFrom SelectFrom()
+ {
+ return new HqlSelectFrom(_factory);
+ }
+
+ public HqlSelectFrom SelectFrom(HqlSelect select)
+ {
+ return new HqlSelectFrom(_factory, select);
+ }
+
+ public HqlSelectFrom SelectFrom(HqlFrom @from, HqlSelect select)
+ {
+ return new HqlSelectFrom(_factory, @from, select);
+ }
+
+ public HqlSelectFrom SelectFrom(HqlFrom @from)
+ {
+ return new HqlSelectFrom(_factory, @from);
+ }
+
+ public HqlFrom From(HqlRange range)
+ {
+ return new HqlFrom(_factory, range);
+ }
+
+ public HqlFrom From()
+ {
+ return new HqlFrom(_factory);
+ }
+
+ public HqlRange Range(HqlIdent ident)
+ {
+ 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);
+ }
+
+ public HqlIdent Ident(string ident)
+ {
+ return new HqlIdent(_factory, ident);
+ }
+
+ public HqlAlias Alias(string alias)
+ {
+ return new HqlAlias(_factory, alias);
+ }
+
+ public HqlEquality Equality()
+ {
+ return new HqlEquality(_factory);
+ }
+
+ public HqlBooleanAnd BooleanAnd()
+ {
+ return new HqlBooleanAnd(_factory);
+ }
+
+ public HqlBooleanOr BooleanOr()
+ {
+ return new HqlBooleanOr(_factory);
+ }
+
+ public HqlAdd Add()
+ {
+ return new HqlAdd(_factory);
+ }
+
+ public HqlSubtract Subtract()
+ {
+ return new HqlSubtract(_factory);
+ }
+
+ public HqlMultiplty Multiply()
+ {
+ return new HqlMultiplty(_factory);
+ }
+
+ public HqlDivide Divide()
+ {
+ return new HqlDivide(_factory);
+ }
+
+ public HqlDot Dot()
+ {
+ return new HqlDot(_factory);
+ }
+
+ public HqlParameter Parameter(string name)
+ {
+ return new HqlParameter(_factory, name);
+ }
+
+ public HqlWhere Where(HqlTreeNode 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)
+ {
+ if (value == null)
+ {
+ return new HqlNull(_factory);
+ }
+ else
+ {
+ 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));
+ }
+ }
+ }
+
+ public HqlOrderBy OrderBy(HqlTreeNode expression, HqlDirection hqlDirection)
+ {
+ return new HqlOrderBy(_factory, expression, hqlDirection);
+ }
+
+ public HqlSelect Select(HqlTreeNode expression)
+ {
+ return new HqlSelect(_factory, expression);
+ }
+
+ public HqlSelect Select(params HqlTreeNode[] expression)
+ {
+ return new HqlSelect(_factory, expression);
+ }
+
+ public HqlSelect Select(IEnumerable<HqlTreeNode> expressions)
+ {
+ return new HqlSelect(_factory, expressions.ToArray());
+ }
+
+ public HqlConstructor Constructor(ConstructorInfo constructor)
+ {
+ return new HqlConstructor(_factory, constructor);
+ }
+
+ public HqlNill Holder()
+ {
+ return new HqlNill(_factory);
+ }
+
+ public HqlCase Case()
+ {
+ return new HqlCase(_factory);
+ }
+
+ public HqlWhen When()
+ {
+ return new HqlWhen(_factory);
+ }
+
+ public HqlElse Else()
+ {
+ return new HqlElse(_factory);
+ }
+
+ public HqlInequality Inequality()
+ {
+ return new HqlInequality(_factory);
+ }
+
+ public HqlLessThan LessThan()
+ {
+ return new HqlLessThan(_factory);
+ }
+
+ public HqlLessThanOrEqual LessThanOrEqual()
+ {
+ return new HqlLessThanOrEqual(_factory);
+ }
+
+ public HqlGreaterThan GreaterThan()
+ {
+ return new HqlGreaterThan(_factory);
+ }
+
+ public HqlGreaterThanOrEqual GreaterThanOrEqual()
+ {
+ return new HqlGreaterThanOrEqual(_factory);
+ }
+
+ public HqlCount Count(HqlTreeNode child)
+ {
+ return new HqlCount(_factory, child);
+ }
+
+ public HqlRowStar RowStar()
+ {
+ return new HqlRowStar(_factory);
+ }
+
+ public HqlCast Cast(HqlTreeNode expression, System.Type type)
+ {
+ return new HqlCast(_factory, expression, type);
+ }
+
+ public HqlBitwiseNot BitwiseNot()
+ {
+ return new HqlBitwiseNot(_factory);
+ }
+
+ public HqlNot Not()
+ {
+ return new HqlNot(_factory);
+ }
+
+ public HqlAverage Average()
+ {
+ return new HqlAverage(_factory);
+ }
+
+ public HqlAverage Average(HqlTreeNode expression)
+ {
+ return new HqlAverage(_factory, expression);
+ }
+
+ public HqlSum Sum()
+ {
+ return new HqlSum(_factory);
+ }
+
+ public HqlSum Sum(HqlTreeNode expression)
+ {
+ return new HqlSum(_factory, expression);
+ }
+
+ public HqlMin Min()
+ {
+ return new HqlMin(_factory);
+ }
+
+ public HqlMax Max()
+ {
+ return new HqlMax(_factory);
+ }
+
+ public HqlAnd And(HqlTreeNode left, HqlTreeNode right)
+ {
+ return new HqlAnd(_factory, left, right);
+ }
+
+ public HqlJoin Join(HqlTreeNode expression, HqlAlias @alias)
+ {
+ return new HqlJoin(_factory, expression, @alias);
+ }
+
+ public HqlAny Any()
+ {
+ return new HqlAny(_factory);
+ }
+
+ public HqlExists Exists()
+ {
+ return new HqlExists(_factory);
+ }
+
+ public HqlElements Elements()
+ {
+ return new HqlElements(_factory);
+ }
+ }
+}
\ No newline at end of file
Property changes on: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,566 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using NHibernate.Hql.Ast.ANTLR;
+using NHibernate.Hql.Ast.ANTLR.Tree;
+
+namespace NHibernate.Hql.Ast
+{
+ public class HqlTreeNode
+ {
+ protected readonly IASTNode _node;
+ protected readonly List<HqlTreeNode> _children;
+
+ protected HqlTreeNode(int type, string text, IASTFactory factory, params HqlTreeNode[] children)
+ {
+ _node = factory.CreateNode(type, text);
+ _children = new List<HqlTreeNode>();
+
+ foreach (var child in children)
+ {
+ _children.Add(child);
+ _node.AddChild(child.AstNode);
+ }
+ }
+
+ public IEnumerable<HqlTreeNode> NodesPreOrder
+ {
+ get
+ {
+ yield return this;
+
+ foreach (var child in _children)
+ {
+ foreach (var node in child.NodesPreOrder)
+ {
+ yield return node;
+ }
+ }
+ }
+ }
+
+ public IEnumerable<HqlTreeNode> NodesPostOrder
+ {
+ get
+ {
+ foreach (var child in _children)
+ {
+ foreach (var node in child.NodesPostOrder)
+ {
+ yield return node;
+ }
+ }
+
+ yield return this;
+ }
+ }
+
+ public IEnumerable<HqlTreeNode> Children
+ {
+ get
+ {
+ foreach (var child in _children)
+ {
+ yield return child;
+ }
+ }
+ }
+
+ public void ClearChildren()
+ {
+ _children.Clear();
+ _node.ClearChildren();
+ }
+
+ internal IASTNode AstNode
+ {
+ get { return _node; }
+ }
+
+ internal void AddChild(HqlTreeNode child)
+ {
+ _children.Add(child);
+ _node.AddChild(child.AstNode);
+ }
+ }
+
+ public class HqlQuery : HqlTreeNode
+ {
+ internal HqlQuery(IASTFactory factory, params HqlTreeNode[] children)
+ : base(HqlSqlWalker.QUERY, "query", factory, children)
+ {
+ }
+ }
+
+
+ public class HqlIdent : HqlTreeNode
+ {
+ internal HqlIdent(IASTFactory factory, string ident)
+ : base(HqlSqlWalker.IDENT, ident, factory)
+ {
+ }
+ }
+
+ public class HqlRange : HqlTreeNode
+ {
+ internal HqlRange(IASTFactory factory, params HqlTreeNode[] children)
+ : base(HqlSqlWalker.RANGE, "range", factory, children)
+ {
+ }
+ }
+
+ public class HqlFrom : HqlTreeNode
+ {
+ internal HqlFrom(IASTFactory factory, params HqlTreeNode[] children)
+ : base(HqlSqlWalker.FROM, "from", factory, children)
+ {
+ }
+ }
+
+ public class HqlSelectFrom : HqlTreeNode
+ {
+ internal HqlSelectFrom(IASTFactory factory, params HqlTreeNode[] children)
+ : base(HqlSqlWalker.SELECT_FROM, "select_from", factory, children)
+ {
+ }
+ }
+
+ public class HqlAlias : HqlTreeNode
+ {
+ public HqlAlias(IASTFactory factory, string @alias)
+ : base(HqlSqlWalker.ALIAS, alias, factory)
+ {
+ }
+ }
+
+ public class HqlDivide : HqlTreeNode
+ {
+ public HqlDivide(IASTFactory factory)
+ : base(HqlSqlWalker.DIV, "/", factory)
+ {
+ }
+ }
+
+ public class HqlMultiplty : HqlTreeNode
+ {
+ public HqlMultiplty(IASTFactory factory)
+ : base(HqlSqlWalker.STAR, "*", factory)
+ {
+ }
+ }
+
+ public class HqlSubtract : HqlTreeNode
+ {
+ public HqlSubtract(IASTFactory factory)
+ : base(HqlSqlWalker.MINUS, "-", factory)
+ {
+ }
+ }
+
+ public class HqlAdd : HqlTreeNode
+ {
+ public HqlAdd(IASTFactory factory)
+ : base(HqlSqlWalker.PLUS, "+", factory)
+ {
+ }
+ }
+
+ public class HqlBooleanOr : HqlTreeNode
+ {
+ public HqlBooleanOr(IASTFactory factory)
+ : base(HqlSqlWalker.OR, "or", factory)
+ {
+ }
+ }
+
+ public class HqlBooleanAnd : HqlTreeNode
+ {
+ public HqlBooleanAnd(IASTFactory factory)
+ : base(HqlSqlWalker.AND, "/", factory)
+ {
+ }
+ }
+
+ public class HqlEquality : HqlTreeNode
+ {
+ public HqlEquality(IASTFactory factory)
+ : base(HqlSqlWalker.EQ, "==", factory)
+ {
+ }
+ }
+
+ public class HqlParameter : HqlTreeNode
+ {
+ public HqlParameter(IASTFactory factory, string name)
+ : base(HqlSqlWalker.PARAM, name, factory)
+ {
+ }
+ }
+
+ public class HqlDot : HqlTreeNode
+ {
+ public HqlDot(IASTFactory factory)
+ : base(HqlSqlWalker.DOT, ".", factory)
+ {
+ }
+ }
+
+ public class HqlWhere : HqlTreeNode
+ {
+ public HqlWhere(IASTFactory factory)
+ : base(HqlSqlWalker.WHERE, "where", factory)
+ {
+ }
+
+ public HqlWhere(IASTFactory factory, HqlTreeNode expression)
+ : base(HqlSqlWalker.WHERE, "where", factory, expression)
+ {
+ }
+ }
+
+ public class HqlConstant : HqlTreeNode
+ {
+ public HqlConstant(IASTFactory factory, int type, string value)
+ : base(type, value, factory)
+ {
+ }
+ }
+
+ public class HqlStringConstant : HqlConstant
+ {
+ public HqlStringConstant(IASTFactory factory, string s)
+ : base(factory, HqlSqlWalker.QUOTED_String, s)
+ {
+ }
+ }
+
+ public class HqlDoubleConstant : HqlConstant
+ {
+ public HqlDoubleConstant(IASTFactory factory, string s)
+ : base(factory, HqlSqlWalker.NUM_DOUBLE, s)
+ {
+ }
+ }
+
+ public class HqlFloatConstant : HqlConstant
+ {
+ public HqlFloatConstant(IASTFactory factory, string s)
+ : base(factory, HqlSqlWalker.NUM_FLOAT, s)
+ {
+ }
+ }
+
+ public class HqlIntegerConstant : HqlConstant
+ {
+ public HqlIntegerConstant(IASTFactory factory, string s)
+ : base(factory, HqlSqlWalker.NUM_INT, s)
+ {
+ }
+ }
+
+ public class HqlDecimalConstant : HqlConstant
+ {
+ public HqlDecimalConstant(IASTFactory factory, string s)
+ : base(factory, HqlSqlWalker.NUM_DECIMAL, s)
+ {
+ }
+ }
+
+ public class HqlNull : HqlConstant
+ {
+ public HqlNull(IASTFactory factory)
+ : base(factory, HqlSqlWalker.NULL, "null")
+ {
+ }
+ }
+
+ public class HqlOrderBy : HqlTreeNode
+ {
+ 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
+ {
+ Ascending,
+ Descending
+ }
+
+ public class HqlDirectionAscending : HqlTreeNode
+ {
+ public HqlDirectionAscending(IASTFactory factory)
+ : base(HqlSqlWalker.ASCENDING, "asc", factory)
+ {
+ }
+ }
+
+ public class HqlDirectionDescending : HqlTreeNode
+ {
+ public HqlDirectionDescending(IASTFactory factory)
+ : base(HqlSqlWalker.DESCENDING, "desc", factory)
+ {
+ }
+ }
+
+ public class HqlSelect : HqlTreeNode
+ {
+ public HqlSelect(IASTFactory factory, params HqlTreeNode[] expression)
+ : base(HqlSqlWalker.SELECT, "select", factory, expression)
+ {
+ }
+ }
+
+ public class HqlConstructor : HqlTreeNode
+ {
+ public HqlConstructor(IASTFactory factory, ConstructorInfo ctor)
+ : base(HqlSqlWalker.CONSTRUCTOR, "ctor", factory)
+ {
+ ((ASTNode)_node).Hack = ctor;
+ }
+ }
+
+ public class HqlNill : HqlTreeNode
+ {
+ public HqlNill(IASTFactory factory)
+ : base(0, "nill", factory)
+ {
+ }
+ }
+
+ public class HqlElse : HqlTreeNode
+ {
+ public HqlElse(IASTFactory factory)
+ : base(HqlSqlWalker.ELSE, "else", factory)
+ {
+ }
+ }
+
+ public class HqlWhen : HqlTreeNode
+ {
+ public HqlWhen(IASTFactory factory)
+ : base(HqlSqlWalker.WHEN, "when", factory)
+ {
+ }
+ }
+
+ public class HqlCase : HqlTreeNode
+ {
+ public HqlCase(IASTFactory factory)
+ : base(HqlSqlWalker.CASE, "case", factory)
+ {
+ }
+ }
+
+ public class HqlGreaterThanOrEqual : HqlTreeNode
+ {
+ public HqlGreaterThanOrEqual(IASTFactory factory)
+ : base(HqlSqlWalker.GE, "ge", factory)
+ {
+ }
+ }
+
+ public class HqlGreaterThan : HqlTreeNode
+ {
+ public HqlGreaterThan(IASTFactory factory)
+ : base(HqlSqlWalker.GT, "gt", factory)
+ {
+ }
+ }
+
+ public class HqlLessThanOrEqual : HqlTreeNode
+ {
+ public HqlLessThanOrEqual(IASTFactory factory)
+ : base(HqlSqlWalker.LE, "le", factory)
+ {
+ }
+ }
+
+ public class HqlLessThan : HqlTreeNode
+ {
+ 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 HqlCount(IASTFactory factory, HqlTreeNode child)
+ : base(HqlSqlWalker.COUNT, "count", factory, child)
+ {
+ }
+ }
+
+ public class HqlAs : HqlTreeNode
+ {
+ public HqlAs(IASTFactory factory, HqlTreeNode expression, System.Type type) : base(HqlSqlWalker.AS, "as", factory, expression)
+ {
+ switch (System.Type.GetTypeCode(type))
+ {
+ case TypeCode.Int32:
+ AddChild(new HqlIdent(factory, "integer"));
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+ }
+
+ public class HqlCast : HqlTreeNode
+ {
+ public HqlCast(IASTFactory factory, HqlTreeNode expression, System.Type type) : base(HqlSqlWalker.METHOD_CALL, "method", factory)
+ {
+ HqlIdent typeIdent;
+
+ if (IsNullableType(type))
+ {
+ type = ExtractUnderlyingTypeFromNullable(type);
+ }
+
+ switch (System.Type.GetTypeCode(type))
+ {
+ case TypeCode.Int32:
+ typeIdent = new HqlIdent(factory, "integer");
+ break;
+ case TypeCode.Decimal:
+ typeIdent = new HqlIdent(factory, "decimal");
+ break;
+ case TypeCode.DateTime:
+ typeIdent = new HqlIdent(factory, "datetime");
+ break;
+ default:
+ throw new NotSupportedException(string.Format("Don't currently support casts to {0}", type.Name));
+ }
+
+ AddChild(new HqlIdent(factory, "cast"));
+ AddChild(new HqlExpressionList(factory, expression, typeIdent));
+ }
+
+ private static System.Type ExtractUnderlyingTypeFromNullable(System.Type type)
+ {
+ return type.GetGenericArguments()[0];
+ }
+
+ private static bool IsNullableType(System.Type type)
+ {
+ return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>));
+ }
+ }
+
+ public class HqlExpressionList : HqlTreeNode
+ {
+ public HqlExpressionList(IASTFactory factory, params HqlTreeNode[] expression) : base(HqlSqlWalker.EXPR_LIST, "expr_list", factory, expression)
+ {
+ }
+ }
+
+ public class HqlNot : HqlTreeNode
+ {
+ public HqlNot(IASTFactory factory) : base(HqlSqlWalker.NOT, "not", factory)
+ {
+ }
+ }
+
+ public class HqlAverage : HqlTreeNode
+ {
+ public HqlAverage(IASTFactory factory)
+ : base(HqlSqlWalker.AGGREGATE, "avg", factory)
+ {
+ }
+
+ public HqlAverage(IASTFactory factory, HqlTreeNode expression) : base(HqlSqlWalker.AGGREGATE, "avg", factory, expression)
+ {
+ }
+ }
+
+ public class HqlBitwiseNot : HqlTreeNode
+ {
+ public HqlBitwiseNot(IASTFactory factory) : base(HqlSqlWalker.BNOT, "not", factory)
+ {
+ }
+ }
+
+ public class HqlSum : HqlTreeNode
+ {
+ public HqlSum(IASTFactory factory)
+ : base(HqlSqlWalker.AGGREGATE, "sum", factory)
+ {
+ }
+
+ public HqlSum(IASTFactory factory, HqlTreeNode expression)
+ : base(HqlSqlWalker.AGGREGATE, "sum", factory, expression)
+ {
+ }
+ }
+
+ public class HqlMax : HqlTreeNode
+ {
+ public HqlMax(IASTFactory factory) : base(HqlSqlWalker.AGGREGATE, "max", factory)
+ {
+ }
+ }
+
+ public class HqlMin : HqlTreeNode
+ {
+ public HqlMin(IASTFactory factory)
+ : base(HqlSqlWalker.AGGREGATE, "min", factory)
+ {
+ }
+ }
+
+ public class HqlAnd : HqlTreeNode
+ {
+ public HqlAnd(IASTFactory factory, HqlTreeNode left, HqlTreeNode right) : base(HqlSqlWalker.AND, "and", factory, left, right)
+ {
+ }
+ }
+
+ public class HqlJoin : HqlTreeNode
+ {
+ 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 HqlExists(IASTFactory factory) : base(HqlSqlWalker.EXISTS, "exists", factory)
+ {
+ }
+ }
+
+ public class HqlElements : HqlTreeNode
+ {
+ public HqlElements(IASTFactory factory) : base(HqlSqlWalker.ELEMENTS, "elements", factory)
+ {
+ }
+ }
+
+}
\ No newline at end of file
Property changes on: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/nhibernate/src/NHibernate/Linq/CommandData.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/CommandData.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Linq/CommandData.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using NHibernate.Hql.Ast;
+
+namespace NHibernate.Linq
+{
+ public class CommandData
+ {
+ public CommandData(HqlQuery statement, NamedParameter[] namedParameters, LambdaExpression projectionExpression, List<Action<IQuery>> additionalCriteria)
+ {
+ Statement = statement;
+ NamedParameters = namedParameters;
+ ProjectionExpression = projectionExpression;
+ AdditionalCriteria = additionalCriteria;
+ }
+
+ public HqlQuery Statement { get; private set; }
+ public NamedParameter[] NamedParameters { get; private set; }
+ public LambdaExpression ProjectionExpression { get; set; }
+ public List<Action<IQuery>> AdditionalCriteria { get; set; }
+
+ public IQuery CreateQuery(ISession session, System.Type type)
+ {
+ var query = session.CreateQuery(new HqlExpression(Statement, type));
+
+ foreach (var parameter in NamedParameters)
+ query.SetParameter(parameter.Name, parameter.Value);
+
+ if (ProjectionExpression != null)
+ {
+ query.SetResultTransformer(new ResultTransformer(ProjectionExpression));
+ }
+
+ foreach (var criteria in AdditionalCriteria)
+ {
+ criteria(query);
+ }
+
+ return query;
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Linq/HqlNodeStack.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/HqlNodeStack.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Linq/HqlNodeStack.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using NHibernate.Hql.Ast;
+
+namespace NHibernate.Linq
+{
+ public class HqlNodeStack
+ {
+ private readonly Stack<HqlTreeNode> _stack = new Stack<HqlTreeNode>();
+ private readonly HqlNill _root;
+
+ public HqlNodeStack(HqlTreeBuilder builder)
+ {
+ _root = builder.Holder();
+ _stack.Push(_root);
+ }
+
+ public IEnumerable<HqlTreeNode> NodesPreOrder
+ {
+ get { return _root.NodesPreOrder; }
+ }
+
+ public IEnumerable<HqlTreeNode> Finish()
+ {
+ var holder = (HqlNill) _stack.Pop();
+
+ return holder.Children;
+ }
+
+ public void PushAndPop(HqlTreeNode query)
+ {
+ Push(query).Dispose();
+ }
+
+ public IDisposable Push(HqlTreeNode query)
+ {
+ _stack.Peek().AddChild(query);
+
+ _stack.Push(query);
+
+ var stackEntry = new HqlNodeStackEntry(this, query);
+
+ return stackEntry;
+ }
+
+ private HqlTreeNode Peek()
+ {
+ return _stack.Peek();
+ }
+
+ private void Pop()
+ {
+ _stack.Pop();
+ }
+
+ public class HqlNodeStackEntry : IDisposable
+ {
+ private readonly HqlNodeStack _parent;
+ private readonly HqlTreeNode _node;
+
+ internal HqlNodeStackEntry(HqlNodeStack parent, HqlTreeNode node)
+ {
+ _parent = parent;
+ _node = node;
+ }
+
+ public void Dispose()
+ {
+ if (_parent.Peek() != _node)
+ {
+ throw new InvalidOperationException();
+ }
+
+ _parent.Pop();
+ }
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Linq/NamedParameter.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/NamedParameter.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Linq/NamedParameter.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,14 @@
+namespace NHibernate.Linq
+{
+ public class NamedParameter
+ {
+ public NamedParameter(string name, object value)
+ {
+ Name = name;
+ Value = value;
+ }
+
+ public string Name { get; set; }
+ public object Value { get; set; }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Linq/NhExpressionTreeVisitor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/NhExpressionTreeVisitor.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Linq/NhExpressionTreeVisitor.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,286 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using NHibernate.Hql.Ast;
+using Remotion.Data.Linq.Clauses.Expressions;
+using Remotion.Data.Linq.Clauses.ExpressionTreeVisitors;
+using Remotion.Data.Linq.Parsing;
+
+namespace NHibernate.Linq
+{
+ public class NhExpressionTreeVisitor : ThrowingExpressionTreeVisitor
+ {
+ protected readonly HqlTreeBuilder _hqlTreeBuilder;
+ protected readonly HqlNodeStack _stack;
+ private readonly ParameterAggregator _parameterAggregator;
+
+ public NhExpressionTreeVisitor(ParameterAggregator parameterAggregator)
+ {
+ _parameterAggregator = parameterAggregator;
+ _hqlTreeBuilder = new HqlTreeBuilder();
+ _stack = new HqlNodeStack(_hqlTreeBuilder);
+ }
+
+ public IEnumerable<HqlTreeNode> GetAstBuilderNode()
+ {
+ return _stack.Finish();
+ }
+
+ public virtual void Visit(Expression expression)
+ {
+ VisitExpression(expression);
+ }
+
+ protected override Expression VisitQuerySourceReferenceExpression(QuerySourceReferenceExpression expression)
+ {
+ _stack.PushAndPop(_hqlTreeBuilder.Ident(expression.ReferencedQuerySource.ItemName));
+
+ return expression;
+ }
+
+ protected override Expression VisitBinaryExpression(BinaryExpression expression)
+ {
+ HqlTreeNode operatorNode = GetHqlOperatorNodeForBinaryOperator(expression);
+
+ using (_stack.Push(operatorNode))
+ {
+ VisitExpression(expression.Left);
+
+ VisitExpression(expression.Right);
+ }
+
+ return expression;
+ }
+
+ private HqlTreeNode GetHqlOperatorNodeForBinaryOperator(BinaryExpression expression)
+ {
+ switch (expression.NodeType)
+ {
+ case ExpressionType.Equal:
+ return _hqlTreeBuilder.Equality();
+
+ case ExpressionType.NotEqual:
+ return _hqlTreeBuilder.Inequality();
+
+ case ExpressionType.And:
+ case ExpressionType.AndAlso:
+ return _hqlTreeBuilder.BooleanAnd();
+
+ case ExpressionType.Or:
+ case ExpressionType.OrElse:
+ return _hqlTreeBuilder.BooleanOr();
+
+ case ExpressionType.Add:
+ return _hqlTreeBuilder.Add();
+
+ case ExpressionType.Subtract:
+ return _hqlTreeBuilder.Subtract();
+
+ case ExpressionType.Multiply:
+ return _hqlTreeBuilder.Multiply();
+
+ case ExpressionType.Divide:
+ return _hqlTreeBuilder.Divide();
+
+ case ExpressionType.LessThan:
+ return _hqlTreeBuilder.LessThan();
+
+ case ExpressionType.LessThanOrEqual:
+ return _hqlTreeBuilder.LessThanOrEqual();
+
+ case ExpressionType.GreaterThan:
+ return _hqlTreeBuilder.GreaterThan();
+
+ case ExpressionType.GreaterThanOrEqual:
+ return _hqlTreeBuilder.GreaterThanOrEqual();
+ }
+
+ throw new InvalidOperationException();
+ }
+
+ protected override Expression VisitUnaryExpression(UnaryExpression expression)
+ {
+ HqlTreeNode operatorNode = GetHqlOperatorNodeforUnaryOperator(expression);
+
+ using (_stack.Push(operatorNode))
+ {
+ VisitExpression(expression.Operand);
+ }
+
+ return expression;
+ }
+
+ private HqlTreeNode GetHqlOperatorNodeforUnaryOperator(UnaryExpression expression)
+ {
+ switch (expression.NodeType)
+ {
+ case ExpressionType.Not:
+ return _hqlTreeBuilder.Not();
+ }
+
+ throw new InvalidOperationException();
+ }
+
+ protected override Expression VisitMemberExpression(MemberExpression expression)
+ {
+ using (_stack.Push(_hqlTreeBuilder.Dot()))
+ {
+ Expression newExpression = VisitExpression(expression.Expression);
+
+ _stack.PushAndPop(_hqlTreeBuilder.Ident(expression.Member.Name));
+
+ if (newExpression != expression.Expression)
+ {
+ return Expression.MakeMemberAccess(newExpression, expression.Member);
+ }
+ }
+
+ return expression;
+ }
+
+ protected override Expression VisitConstantExpression(ConstantExpression expression)
+ {
+ if (expression.Value != null)
+ {
+ System.Type t = expression.Value.GetType();
+
+ if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof (NhQueryable<>))
+ {
+ _stack.PushAndPop(_hqlTreeBuilder.Ident(t.GetGenericArguments()[0].Name));
+ return expression;
+ }
+ }
+
+ /*
+ var namedParameter = _parameterAggregator.AddParameter(expression.Value);
+
+ _expression = _hqlTreeBuilder.Parameter(namedParameter.Name);
+
+ return expression;
+ */
+ // TODO - get parameter support in place in the HQLQueryPlan
+ _stack.PushAndPop(_hqlTreeBuilder.Constant(expression.Value));
+
+ return expression;
+ }
+
+ protected override Expression VisitMethodCallExpression(MethodCallExpression expression)
+ {
+ if (expression.Method.DeclaringType == typeof(Enumerable))
+ {
+ switch (expression.Method.Name)
+ {
+ case "Any":
+ // Any has one or two arguments. Arg 1 is the source and arg 2 is the optional predicate
+ using (_stack.Push(_hqlTreeBuilder.Exists()))
+ {
+ using (_stack.Push(_hqlTreeBuilder.Query()))
+ {
+ using (_stack.Push(_hqlTreeBuilder.SelectFrom()))
+ {
+ using (_stack.Push(_hqlTreeBuilder.From()))
+ {
+ using (_stack.Push(_hqlTreeBuilder.Range()))
+ {
+ VisitExpression(expression.Arguments[0]);
+
+ if (expression.Arguments.Count > 1)
+ {
+ var expr = (LambdaExpression) expression.Arguments[1];
+ _stack.PushAndPop(_hqlTreeBuilder.Alias(expr.Parameters[0].Name));
+ }
+ }
+ }
+ }
+ if (expression.Arguments.Count > 1)
+ {
+ using (_stack.Push(_hqlTreeBuilder.Where()))
+ {
+ VisitExpression(expression.Arguments[1]);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ throw new NotSupportedException(string.Format("The Enumerable method {0} is not supported", expression.Method.Name));
+ }
+
+ return expression;
+ }
+ else
+ {
+ return base.VisitMethodCallExpression(expression); // throws
+ }
+ }
+
+ protected override Expression VisitLambdaExpression(LambdaExpression expression)
+ {
+ VisitExpression(expression.Body);
+
+ return expression;
+ }
+
+ protected override Expression VisitParameterExpression(ParameterExpression expression)
+ {
+ _stack.PushAndPop(_hqlTreeBuilder.Ident(expression.Name));
+
+ return expression;
+ }
+
+ protected override Expression VisitConditionalExpression(ConditionalExpression expression)
+ {
+ using (_stack.Push(_hqlTreeBuilder.Case()))
+ {
+ using (_stack.Push(_hqlTreeBuilder.When()))
+ {
+ VisitExpression(expression.Test);
+
+ VisitExpression(expression.IfTrue);
+ }
+
+ if (expression.IfFalse != null)
+ {
+ using (_stack.Push(_hqlTreeBuilder.Else()))
+ {
+ VisitExpression(expression.IfFalse);
+ }
+ }
+ }
+
+ return expression;
+ }
+
+ protected override Expression VisitSubQueryExpression(SubQueryExpression expression)
+ {
+ CommandData query = QueryModelVisitor.GenerateHqlQuery(expression.QueryModel, _parameterAggregator);
+
+ if (query.ProjectionExpression != null)
+ {
+ throw new InvalidOperationException();
+ }
+
+ // TODO - what if there was a projection expression?
+
+ _stack.PushAndPop(query.Statement);
+
+ return expression;
+ }
+
+
+ // Called when a LINQ expression type is not handled above.
+ protected override Exception CreateUnhandledItemException<T>(T unhandledItem, string visitMethod)
+ {
+ string itemText = FormatUnhandledItem(unhandledItem);
+ var message = string.Format("The expression '{0}' (type: {1}) is not supported by this LINQ provider.", itemText, typeof(T));
+ return new NotSupportedException(message);
+ }
+
+ private string FormatUnhandledItem<T>(T unhandledItem)
+ {
+ var itemAsExpression = unhandledItem as Expression;
+ return itemAsExpression != null ? FormattingExpressionTreeVisitor.Format(itemAsExpression) : unhandledItem.ToString();
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Linq/NhQueryExecutor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/NhQueryExecutor.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Linq/NhQueryExecutor.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,39 @@
+using System.Collections.Generic;
+using System.Linq;
+using Remotion.Data.Linq;
+
+namespace NHibernate.Linq
+{
+ public class NhQueryExecutor : IQueryExecutor
+ {
+ private readonly ISession _session;
+
+ public NhQueryExecutor(ISession session)
+ {
+ _session = session;
+ }
+
+ // Executes a query with a scalar result, i.e. a query that ends with a result operator such as Count, Sum, or Average.
+ public T ExecuteScalar<T>(QueryModel queryModel)
+ {
+ return ExecuteCollection<T>(queryModel).Single();
+ }
+
+ // Executes a query with a single result object, i.e. a query that ends with a result operator such as First, Last, Single, Min, or Max.
+ public T ExecuteSingle<T>(QueryModel queryModel, bool returnDefaultWhenEmpty)
+ {
+ return returnDefaultWhenEmpty ? ExecuteCollection<T>(queryModel).SingleOrDefault() : ExecuteCollection<T>(queryModel).Single();
+ }
+
+ // Executes a query with a collection result.
+ public IEnumerable<T> ExecuteCollection<T>(QueryModel queryModel)
+ {
+ var commandData = QueryModelVisitor.GenerateHqlQuery(queryModel);
+
+ var query = commandData.CreateQuery(_session, typeof(T));
+
+ // TODO - check which call on Query makes most sense...
+ return (IEnumerable<T>) query.List();
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Linq/NhQueryable.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,29 @@
+using System.Linq;
+using System.Linq.Expressions;
+using Remotion.Data.Linq;
+
+namespace NHibernate.Linq
+{
+ /// <summary>
+ /// Provides the main entry point to a LINQ query.
+ /// </summary>
+ public class NhQueryable<T> : QueryableBase<T>
+ {
+ private static IQueryExecutor CreateExecutor(ISession session)
+ {
+ return new NhQueryExecutor(session);
+ }
+
+ // This constructor is called by our users, create a new IQueryExecutor.
+ public NhQueryable(ISession session)
+ : base(CreateExecutor(session))
+ {
+ }
+
+ // This constructor is called indirectly by LINQ's query methods, just pass to base.
+ public NhQueryable(IQueryProvider provider, Expression expression)
+ : base(provider, expression)
+ {
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Linq/Nominator.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/Nominator.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Linq/Nominator.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using Remotion.Data.Linq.Parsing;
+
+namespace NHibernate.Linq
+{
+ /// <summary>
+ /// Performs bottom-up analysis to determine which nodes that match a certain predicate
+ /// </summary>
+ class Nominator : ExpressionTreeVisitor
+ {
+ readonly Func<Expression, bool> _fnIsCandidate;
+ HashSet<Expression> _candidates;
+ bool _cannotBeCandidate;
+
+ internal Nominator(Func<Expression, bool> fnIsCandidate)
+ {
+ _fnIsCandidate = fnIsCandidate;
+ }
+
+ internal HashSet<Expression> Nominate(Expression expression)
+ {
+ _candidates = new HashSet<Expression>();
+ VisitExpression(expression);
+ return _candidates;
+ }
+
+ protected override Expression VisitExpression(Expression expression)
+ {
+ if (expression != null)
+ {
+ bool saveCannotBeEvaluated = _cannotBeCandidate;
+ _cannotBeCandidate = false;
+
+ base.VisitExpression(expression);
+
+ if (!_cannotBeCandidate)
+ {
+ if (_fnIsCandidate(expression))
+ {
+ _candidates.Add(expression);
+ }
+ else
+ {
+ _cannotBeCandidate = true;
+ }
+ }
+
+ _cannotBeCandidate |= saveCannotBeEvaluated;
+ }
+
+ return expression;
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Linq/ParameterAggregator.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/ParameterAggregator.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Linq/ParameterAggregator.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+
+namespace NHibernate.Linq
+{
+ public class ParameterAggregator
+ {
+ private readonly List<NamedParameter> _parameters = new List<NamedParameter>();
+
+ public NamedParameter AddParameter(object value)
+ {
+ var parameter = new NamedParameter("p" + (_parameters.Count + 1), value);
+ _parameters.Add(parameter);
+ return parameter;
+ }
+
+ public NamedParameter[] GetParameters()
+ {
+ return _parameters.ToArray();
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Linq/ProjectionEvaluator.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/ProjectionEvaluator.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Linq/ProjectionEvaluator.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,77 @@
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using NHibernate.Hql.Ast;
+using Remotion.Data.Linq.Parsing;
+
+namespace NHibernate.Linq
+{
+ public class ProjectionEvaluator : ExpressionTreeVisitor
+ {
+ protected readonly HqlTreeBuilder _hqlTreeBuilder;
+ protected readonly HqlNodeStack _stack;
+ private readonly ParameterAggregator _parameterAggregator;
+ private HashSet<Expression> _hqlNodes;
+ private readonly ParameterExpression _objectArray;
+ private Expression _projectionExpression;
+ private int _iColumn;
+
+ public ProjectionEvaluator(ParameterAggregator parameterAggregator, ParameterExpression objectArray)
+ {
+ _parameterAggregator = parameterAggregator;
+ _objectArray = objectArray;
+ _hqlTreeBuilder = new HqlTreeBuilder();
+ _stack = new HqlNodeStack(_hqlTreeBuilder);
+ }
+
+ public Expression ProjectionExpression
+ {
+ get { return _projectionExpression; }
+ }
+
+ public IEnumerable<HqlTreeNode> GetAstBuilderNode()
+ {
+ return _stack.Finish();
+ }
+
+ public void Visit(Expression expression)
+ {
+ // First, find the sub trees that can be expressed purely in HQL
+ _hqlNodes = new Nominator(CanBeEvaluatedInHql).Nominate(expression);
+
+ // Now visit the tree
+ Expression projection = VisitExpression(expression);
+
+ if ((projection != expression) && !_hqlNodes.Contains(expression))
+ {
+ _projectionExpression = projection;
+ }
+ }
+
+ protected override Expression VisitExpression(Expression expression)
+ {
+ if (expression == null)
+ {
+ return null;
+ }
+
+ if (_hqlNodes.Contains(expression))
+ {
+ // Pure HQL evaluation
+ var hqlVisitor = new NhExpressionTreeVisitor(_parameterAggregator);
+ hqlVisitor.Visit(expression);
+ hqlVisitor.GetAstBuilderNode().ForEach(n =>_stack.PushAndPop(n) );
+
+ return Expression.Convert(Expression.ArrayIndex(_objectArray, Expression.Constant(_iColumn++)),
+ expression.Type);
+ }
+
+ // Can't handle this node with HQL. Just recurse down, and emit the expression
+ return base.VisitExpression(expression);
+ }
+
+ private static bool CanBeEvaluatedInHql(Expression expression)
+ {
+ return (expression.NodeType != ExpressionType.MemberInit) && (expression.NodeType != ExpressionType.New);
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Linq/QueryModelVisitor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/QueryModelVisitor.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Linq/QueryModelVisitor.cs 2009-08-31 10:01:43 UTC (rev 4703)
@@ -0,0 +1,309 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using NHibernate.Hql.Ast;
+using Remotion.Data.Linq;
+using Remotion.Data.Linq.Clauses;
+using Remotion.Data.Linq.Clauses.Expressions;
+using Remotion.Data.Linq.Clauses.ResultOperators;
+using Remotion.Data.Linq.Clauses.StreamedData;
+using Remotion.Data.Linq.Transformations;
+
+namespace NHibernate.Linq
+{
+ public class QueryModelVisitor : QueryModelVisitorBase
+ {
+ public static CommandData GenerateHqlQuery(QueryModel queryModel)
+ {
+ return GenerateHqlQuery(queryModel, new ParameterAggregator());
+ }
+
+ public static CommandData GenerateHqlQuery(QueryModel queryModel, ParameterAggregator aggregator)
+ {
+ // SubQueryFromClauseFlattener flattener = new SubQueryFromClauseFlattener();
+ // flattener.VisitQueryModel(queryModel);
+
+ var visitor = new QueryModelVisitor(aggregator);
+ visitor.VisitQueryModel(queryModel);
+ return visitor.GetHqlCommand();
+ }
+
+ private readonly HqlTreeBuilder _hqlTreeBuilder;
+ private readonly ParameterAggregator _parameterAggregator;
+ private readonly ParameterExpression _objectArray;
+ private Expression _projectionExpression;
+ private IStreamedDataInfo _inputInfo;
+ readonly List<Action<IQuery>> _additionalCriteria = new List<Action<IQuery>>();
+
+
+ private HqlWhere _whereClause;
+ private HqlSelect _selectClause;
+ private HqlFrom _fromClause;
+ private readonly List<HqlTreeNode> _orderByClauses = new List<HqlTreeNode>();
+
+ private QueryModelVisitor(ParameterAggregator parameterAggregator)
+ {
+ _hqlTreeBuilder = new HqlTreeBuilder();
+ _parameterAggregator = parameterAggregator;
+ _objectArray = Expression.Parameter(typeof (object[]), "objectArray");
+ }
+
+ public CommandData GetHqlCommand()
+ {
+ HqlSelectFrom selectFrom = _hqlTreeBuilder.SelectFrom();
+
+ if (_fromClause != null)
+ {
+ selectFrom.AddChild(_fromClause);
+ }
+
+ if (_selectClause != null)
+ {
+ selectFrom.AddChild(_selectClause);
+ }
+
+ HqlQuery query = _hqlTreeBuilder.Query(selectFrom);
+
+ if (_whereClause != null)
+ {
+ query.AddChild(_whereClause);
+ }
+
+ foreach (var orderByClause in _orderByClauses)
+ {
+ query.AddChild(orderByClause);
+ }
+
+ return new CommandData(query,
+ _parameterAggregator.GetParameters(),
+ _projectionExpression == null ? null : Expression.Lambda(_projectionExpression, _objectArray),
+ _additionalCriteria);
+ }
+
+ public override void VisitQueryModel(QueryModel queryModel)
+ {
+ if (queryModel.MainFromClause != null)
+ {
+ queryModel.MainFromClause.Accept(this, queryModel);
+ }
+
+ if (queryModel.SelectClause != null)
+ {
+ queryModel.SelectClause.Accept(this, queryModel);
+ }
+
+ VisitBodyClauses(queryModel.BodyClauses, queryModel);
+
+ VisitResultOperators(queryModel.ResultOperators, queryModel);
+ }
+
+ public override void VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel)
+ {
+ var visitor = new NhExpressionTreeVisitor(_parameterAggregator);
+ visitor.Visit(fromClause.FromExpression);
+
+ _fromClause = _hqlTreeBuilder.From(
+ _hqlTreeBuilder.Range(
+ visitor.GetAstBuilderNode().Single(),
+ _hqlTreeBuilder.Alias(fromClause.ItemName)));
+
+ base.VisitMainFromClause(fromClause, queryModel);
+ }
+
+
+ public override void VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, int index)
+ {
+ if (IsCountOperator(resultOperator))
+ {
+ ProcessCountOperator(resultOperator);
+ }
+ else if (IsAggregateOperator(resultOperator))
+ {
+ ProcessAggregateOperator(resultOperator);
+ }
+ else if (IsPositionalOperator(resultOperator))
+ {
+ ProcessPositionalOperator(resultOperator);
+ }
+ else
+ {
+ throw new NotSupportedException(string.Format("The {0} result operator is not current supported",
+ resultOperator.GetType().Name));
+ }
+
+ base.VisitResultOperator(resultOperator, queryModel, index);
+ }
+
+ private void ProcessPositionalOperator(ResultOperatorBase resultOperator)
+ {
+ var first = (FirstResultOperator) resultOperator;
+
+ _additionalCriteria.Add(q => q.SetMaxResults(1));
+ }
+
+ private bool IsPositionalOperator(ResultOperatorBase resultOperator)
+ {
+ return resultOperator is FirstResultOperator;
+ }
+
+ private void ProcessAggregateOperator(ResultOperatorBase resultOperator)
+ {
+ HqlTreeNode aggregateNode;
+
+ if (resultOperator is AverageResultOperator)
+ {
+ aggregateNode = _hqlTreeBuilder.Average();
+ }
+ else if (resultOperator is SumResultOperator)
+ {
+ aggregateNode = _hqlTreeBuilder.Sum();
+ }
+ else if (resultOperator is MinResultOperator)
+ {
+ aggregateNode = _hqlTreeBuilder.Min();
+ }
+ else
+ {
+ aggregateNode = _hqlTreeBuilder.Max();
+ }
+
+ _inputInfo = resultOperator.GetOutputDataInfo(_inputInfo);
+
+ HqlTreeNode child = _selectClause.Children.Single();
+
+ _selectClause.ClearChildren();
+
+ aggregateNode.AddChild(child);
+
+ _selectClause.AddChild(_hqlTreeBuilder.Cast(aggregateNode, _inputInfo.DataType));
+ }
+
+ private void ProcessCountOperator(ResultOperatorBase resultOperator)
+ {
+ HqlTreeNode count = _hqlTreeBuilder.Count(_hqlTreeBuilder.RowStar());
+
+ if (resultOperator is CountResultOperator)
+ {
+ // Need to cast to an int (Hql defaults to long counts)
+ count = _hqlTreeB...
[truncated message content] |