From: <ste...@us...> - 2010-02-26 20:47:16
|
Revision: 4948 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4948&view=rev Author: steverstrong Date: 2010-02-26 20:47:09 +0000 (Fri, 26 Feb 2010) Log Message: ----------- Eager loading support in Linq provider Modified Paths: -------------- trunk/nhibernate/lib/net/3.5/Remotion.Data.Linq.dll trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs trunk/nhibernate/src/NHibernate/Linq/LinqExtensionMethods.cs trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs trunk/nhibernate/src/NHibernate/Linq/ReWriters/AddLeftJoinsReWriter.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/NhExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/NhThrowingExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/Nominator.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/IResultOperatorProcessor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAggregate.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAll.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAny.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessClientSideSelect.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFirst.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFirstOrSingleBase.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessGroupBy.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessNonAggregatingGroupBy.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessResultOperatorReturn.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessSingle.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessSkip.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessTake.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ResultOperatorMap.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ResultOperatorProcessor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ResultOperatorProcessorBase.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate.Test/Linq/Entities/Customer.cs trunk/nhibernate/src/NHibernate.Test/Linq/Entities/Employee.cs trunk/nhibernate/src/NHibernate.Test/Linq/Entities/Order.cs trunk/nhibernate/src/NHibernate.Test/Linq/LinqTestCase.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Linq/EagerFetchingExtensionMethods.cs trunk/nhibernate/src/NHibernate/Linq/Expressions/AggregateExpressionNode.cs trunk/nhibernate/src/NHibernate/Linq/IntermediateHqlTree.cs trunk/nhibernate/src/NHibernate/Linq/NhRelinqQueryParser.cs trunk/nhibernate/src/NHibernate/Linq/ResultOperators/AggregateResultOperator.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/NameUnNamedParameters.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/QuerySourceLocator.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFetch.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFetchMany.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFetchOne.cs trunk/nhibernate/src/NHibernate.Test/Linq/EagerLoadTests.cs Property Changed: ---------------- trunk/nhibernate/src/ trunk/nhibernate/src/NHibernate/ Modified: trunk/nhibernate/lib/net/3.5/Remotion.Data.Linq.dll =================================================================== (Binary files differ) Property changes on: trunk/nhibernate/src ___________________________________________________________________ Modified: svn:ignore - *.suo CloverSrc _ReSharper* *.resharperoptions *.resharper.user CloverBuild Ankh.Load *.resharper ConsoleTest _UpgradeReport_Files NHibernate.userprefs NHibernate.usertasks UpgradeLog.XML UpgradeLog2.XML UpgradeLog3.XML UpgradeLog4.XML UpgradeLog5.XML UpgradeLog6.XML UpgradeLog7.XML UpgradeLog8.XML UpgradeLog9.XML NHibernate.sln.proj NHibernate.sln.AssemblySurfaceCache.user NHibernate.sln.cache .git + *.suo CloverSrc _ReSharper* *.resharperoptions *.resharper.user CloverBuild Ankh.Load *.resharper ConsoleTest _UpgradeReport_Files NHibernate.userprefs NHibernate.usertasks UpgradeLog.XML UpgradeLog2.XML UpgradeLog3.XML UpgradeLog4.XML UpgradeLog5.XML UpgradeLog6.XML UpgradeLog7.XML UpgradeLog8.XML UpgradeLog9.XML NHibernate.sln.proj NHibernate.sln.AssemblySurfaceCache.user NHibernate.sln.cache .git .gitignore NHibernate.5.0.ReSharper.user Property changes on: trunk/nhibernate/src/NHibernate ___________________________________________________________________ Modified: svn:ignore - obj .#* *.user *.xsx AssemblyInfo.cs *.aps *.eto [Bb]in [Dd]ebug [Rr]elease *resharper* _ReSharper.NHibernate NHibernate.pidb + obj .#* *.user *.xsx AssemblyInfo.cs *.aps *.eto [Bb]in [Dd]ebug [Rr]elease *resharper* _ReSharper.NHibernate NHibernate.pidb NHibernate.suo Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -391,9 +391,19 @@ return new HqlIn(_factory, itemExpression, source); } - public HqlTreeNode LeftJoin(HqlExpression expression, HqlAlias @alias) + public HqlLeftJoin LeftJoin(HqlExpression expression, HqlAlias @alias) { return new HqlLeftJoin(_factory, expression, @alias); } + + public HqlFetchJoin FetchJoin(HqlExpression expression, HqlAlias @alias) + { + return new HqlFetchJoin(_factory, expression, @alias); + } + + public HqlLeftFetchJoin LeftFetchJoin(HqlExpression expression, HqlAlias @alias) + { + return new HqlLeftFetchJoin(_factory, expression, @alias); + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -674,6 +674,22 @@ } } + public class HqlFetchJoin : HqlTreeNode + { + public HqlFetchJoin(IASTFactory factory, HqlExpression expression, HqlAlias @alias) + : base(HqlSqlWalker.JOIN, "join", factory, new HqlFetch(factory), expression, @alias) + { + } + } + + public class HqlLeftFetchJoin : HqlTreeNode + { + public HqlLeftFetchJoin(IASTFactory factory, HqlExpression expression, HqlAlias @alias) + : base(HqlSqlWalker.JOIN, "join", factory, new HqlLeft(factory), new HqlFetch(factory), expression, @alias) + { + } + } + public class HqlFetch : HqlTreeNode { public HqlFetch(IASTFactory factory) : base(HqlSqlWalker.FETCH, "fetch", factory) Added: trunk/nhibernate/src/NHibernate/Linq/EagerFetchingExtensionMethods.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/EagerFetchingExtensionMethods.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/EagerFetchingExtensionMethods.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using Remotion.Data.Linq.EagerFetching; +using Remotion.Data.Linq.Utilities; + +namespace NHibernate.Linq +{ + public static class EagerFetchingExtensionMethods + { + public static FluentFetchRequest<TOriginating, TRelated> Fetch<TOriginating, TRelated>( + this IQueryable<TOriginating> query, Expression<Func<TOriginating, TRelated>> relatedObjectSelector) + { + ArgumentUtility.CheckNotNull("query", query); + ArgumentUtility.CheckNotNull("relatedObjectSelector", relatedObjectSelector); + + var methodInfo = ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TOriginating), typeof(TRelated)); + return CreateFluentFetchRequest<TOriginating, TRelated>(methodInfo, query, relatedObjectSelector); + } + + public static FluentFetchRequest<TOriginating, TRelated> FetchMany<TOriginating, TRelated>( + this IQueryable<TOriginating> query, Expression<Func<TOriginating, IEnumerable<TRelated>>> relatedObjectSelector) + { + ArgumentUtility.CheckNotNull("query", query); + ArgumentUtility.CheckNotNull("relatedObjectSelector", relatedObjectSelector); + + var methodInfo = ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TOriginating), typeof(TRelated)); + return CreateFluentFetchRequest<TOriginating, TRelated>(methodInfo, query, relatedObjectSelector); + } + + public static FluentFetchRequest<TQueried, TRelated> ThenFetch<TQueried, TFetch, TRelated>( + this FluentFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, TRelated>> relatedObjectSelector) + { + ArgumentUtility.CheckNotNull("query", query); + ArgumentUtility.CheckNotNull("relatedObjectSelector", relatedObjectSelector); + + var methodInfo = ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TQueried), typeof(TFetch), typeof(TRelated)); + return CreateFluentFetchRequest<TQueried, TRelated>(methodInfo, query, relatedObjectSelector); + } + + public static FluentFetchRequest<TQueried, TRelated> ThenFetchMany<TQueried, TFetch, TRelated>( + this FluentFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, IEnumerable<TRelated>>> relatedObjectSelector) + { + ArgumentUtility.CheckNotNull("query", query); + ArgumentUtility.CheckNotNull("relatedObjectSelector", relatedObjectSelector); + + var methodInfo = ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TQueried), typeof(TFetch), typeof(TRelated)); + return CreateFluentFetchRequest<TQueried, TRelated>(methodInfo, query, relatedObjectSelector); + } + + private static FluentFetchRequest<TOriginating, TRelated> CreateFluentFetchRequest<TOriginating, TRelated>( + MethodInfo currentFetchMethod, + IQueryable<TOriginating> query, + LambdaExpression relatedObjectSelector) + { + var queryProvider = query.Provider; // ArgumentUtility.CheckNotNullAndType<QueryProviderBase>("query.Provider", query.Provider); + var callExpression = Expression.Call(currentFetchMethod, query.Expression, relatedObjectSelector); + return new FluentFetchRequest<TOriginating, TRelated>(queryProvider, callExpression); + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Linq/Expressions/AggregateExpressionNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Expressions/AggregateExpressionNode.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Expressions/AggregateExpressionNode.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -0,0 +1,43 @@ +using System; +using System.Linq.Expressions; +using NHibernate.Linq.ResultOperators; +using Remotion.Data.Linq.Clauses; +using Remotion.Data.Linq.Parsing.Structure.IntermediateModel; + +namespace NHibernate.Linq.Expressions +{ + public class AggregateExpressionNode : ResultOperatorExpressionNodeBase + { + public MethodCallExpressionParseInfo ParseInfo { get; set; } + public Expression OptionalSeed { get; set; } + public LambdaExpression Accumulator { get; set; } + public LambdaExpression OptionalSelector { get; set; } + + public AggregateExpressionNode(MethodCallExpressionParseInfo parseInfo, Expression arg1, Expression arg2, LambdaExpression optionalSelector) : base(parseInfo, null, optionalSelector) + { + ParseInfo = parseInfo; + + if (arg2 != null) + { + OptionalSeed = arg1; + Accumulator = (LambdaExpression) arg2; + } + else + { + Accumulator = (LambdaExpression) arg1; + } + + OptionalSelector = optionalSelector; + } + + public override Expression Resolve(ParameterExpression inputParameter, Expression expressionToBeResolved, ClauseGenerationContext clauseGenerationContext) + { + throw new NotImplementedException(); + } + + protected override ResultOperatorBase CreateResultOperator(ClauseGenerationContext clauseGenerationContext) + { + return new AggregateResultOperator(ParseInfo, OptionalSeed, Accumulator, OptionalSelector); + } + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Linq/IntermediateHqlTree.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/IntermediateHqlTree.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/IntermediateHqlTree.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -0,0 +1,145 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using NHibernate.Hql.Ast; +using NHibernate.Transform; +using NHibernate.Type; + +namespace NHibernate.Linq +{ + public class IntermediateHqlTree + { + private readonly bool _root; + private readonly List<Action<IQuery, IDictionary<string, Tuple<object, IType>>>> _additionalCriteria = new List<Action<IQuery, IDictionary<string, Tuple<object, IType>>>>(); + private readonly List<LambdaExpression> _listTransformers = new List<LambdaExpression>(); + private readonly List<LambdaExpression> _itemTransformers = new List<LambdaExpression>(); + private readonly List<LambdaExpression> _postExecuteTransformers = new List<LambdaExpression>(); + private bool _hasDistinctRootOperator; + + public HqlTreeNode Root { get; private set; } + public HqlTreeBuilder TreeBuilder { get; private set; } + + public IntermediateHqlTree(bool root) + { + _root = root; + TreeBuilder = new HqlTreeBuilder(); + Root = TreeBuilder.Query(TreeBuilder.SelectFrom(TreeBuilder.From())); + } + + public ExpressionToHqlTranslationResults GetTranslation() + { + if (_root) + { + DetectOuterExists(); + } + + return new ExpressionToHqlTranslationResults(Root, + _itemTransformers, + _listTransformers, + _postExecuteTransformers, + _additionalCriteria); + } + + public void AddDistinctRootOperator() + { + if (!_hasDistinctRootOperator) + { + Expression<Func<IEnumerable<object>, IList>> x = + l => new DistinctRootEntityResultTransformer().TransformList(l.ToList()); + + _listTransformers.Add(x); + _hasDistinctRootOperator = true; + } + } + + + public void AddItemTransformer(LambdaExpression transformer) + { + _itemTransformers.Add(transformer); + } + + public void AddFromClause(HqlTreeNode from) + { + Root.NodesPreOrder.Where(n => n is HqlFrom).First().AddChild(from); + } + + public void AddSelectClause(HqlTreeNode select) + { + Root.NodesPreOrder.Where(n => n is HqlSelectFrom).First().AddChild(select); + } + + public void AddGroupByClause(HqlGroupBy groupBy) + { + Root.As<HqlQuery>().AddChild(groupBy); + } + + public void AddOrderByClause(HqlExpression orderBy, HqlDirectionStatement direction) + { + var orderByRoot = Root.NodesPreOrder.Where(n => n is HqlOrderBy).FirstOrDefault(); + + if (orderByRoot == null) + { + orderByRoot = TreeBuilder.OrderBy(); + Root.As<HqlQuery>().AddChild(orderByRoot); + } + + orderByRoot.AddChild(orderBy); + orderByRoot.AddChild(direction); + } + + public void AddWhereClause(HqlBooleanExpression where) + { + var currentWhere = Root.NodesPreOrder.Where(n => n is HqlWhere).FirstOrDefault(); + + if (currentWhere == null) + { + currentWhere = TreeBuilder.Where(where); + Root.As<HqlQuery>().AddChild(currentWhere); + } + else + { + var currentClause = (HqlBooleanExpression)currentWhere.Children.Single(); + + currentWhere.ClearChildren(); + currentWhere.AddChild(TreeBuilder.BooleanAnd(currentClause, where)); + } + } + + private void DetectOuterExists() + { + if (Root is HqlExists) + { + Root = Root.Children.First(); + + _additionalCriteria.Add((q, p) => q.SetMaxResults(1)); + + Expression<Func<IEnumerable<object>, bool>> x = l => l.Any(); + + _listTransformers.Add(x); + } + } + + + public void AddAdditionalCriteria(Action<IQuery, IDictionary<string, Tuple<object, IType>>> criteria) + { + _additionalCriteria.Add(criteria); + } + + public void AddPostExecuteTransformer(LambdaExpression lambda) + { + _postExecuteTransformers.Add(lambda); + } + + public void AddListTransformer(LambdaExpression lambda) + { + _listTransformers.Add(lambda); + } + + public void SetRoot(HqlTreeNode newRoot) + { + Root = newRoot; + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/LinqExtensionMethods.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/LinqExtensionMethods.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/LinqExtensionMethods.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -19,6 +19,11 @@ } } + public static bool IsEnumerableOfT(this System.Type type) + { + return type.IsGenericType && type.GetGenericTypeDefinition() == typeof (IEnumerable<>); + } + public static bool IsNullable(this System.Type type) { return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)); Modified: trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/NhLinqExpression.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using NHibernate.Engine.Query; using NHibernate.Hql.Ast.ANTLR.Tree; -using NHibernate.Linq.ResultOperators; using NHibernate.Linq.Visitors; using NHibernate.Type; -using Remotion.Data.Linq; -using Remotion.Data.Linq.Clauses; using Remotion.Data.Linq.Parsing.ExpressionTreeVisitors; -using Remotion.Data.Linq.Parsing.Structure; -using Remotion.Data.Linq.Parsing.Structure.IntermediateModel; namespace NHibernate.Linq { @@ -83,118 +77,4 @@ return _astNode; } } - - public static class NhRelinqQueryParser - { - public static readonly MethodCallExpressionNodeTypeRegistry MethodCallRegistry = - MethodCallExpressionNodeTypeRegistry.CreateDefault(); - - static NhRelinqQueryParser() - { - MethodCallRegistry.Register( - new[] - { - MethodCallExpressionNodeTypeRegistry.GetRegisterableMethodDefinition(ReflectionHelper.GetMethod(() => Queryable.Aggregate<object>(null, null))), - MethodCallExpressionNodeTypeRegistry.GetRegisterableMethodDefinition(ReflectionHelper.GetMethod(() => Queryable.Aggregate<object, object>(null, null, null))) - }, - typeof (AggregateExpressionNode)); - - MethodCallRegistry.Register( - new [] - { - MethodCallExpressionNodeTypeRegistry.GetRegisterableMethodDefinition(ReflectionHelper.GetMethod((List<object> l) => l.Contains(null))), - - }, - typeof(ContainsExpressionNode)); - } - - public static QueryModel Parse(Expression expression) - { - return new QueryParser(new ExpressionTreeParser(MethodCallRegistry)).GetParsedQuery(expression); - } - } - - public class NameUnNamedParameters : NhExpressionTreeVisitor - { - public static Expression Visit(Expression expression) - { - var visitor = new NameUnNamedParameters(); - - return visitor.VisitExpression(expression); - } - - private readonly Dictionary<ParameterExpression, ParameterExpression> _renamedParameters = new Dictionary<ParameterExpression, ParameterExpression>(); - - protected override Expression VisitParameterExpression(ParameterExpression expression) - { - if (string.IsNullOrEmpty(expression.Name)) - { - ParameterExpression renamed; - - if (_renamedParameters.TryGetValue(expression, out renamed)) - { - return renamed; - } - - renamed = Expression.Parameter(expression.Type, Guid.NewGuid().ToString()); - - _renamedParameters.Add(expression, renamed); - - return renamed; - } - - return base.VisitParameterExpression(expression); - } - } - - public class AggregateExpressionNode : ResultOperatorExpressionNodeBase - { - public MethodCallExpressionParseInfo ParseInfo { get; set; } - public Expression OptionalSeed { get; set; } - public LambdaExpression Accumulator { get; set; } - public LambdaExpression OptionalSelector { get; set; } - - public AggregateExpressionNode(MethodCallExpressionParseInfo parseInfo, Expression arg1, Expression arg2, LambdaExpression optionalSelector) : base(parseInfo, null, optionalSelector) - { - ParseInfo = parseInfo; - - if (arg2 != null) - { - OptionalSeed = arg1; - Accumulator = (LambdaExpression) arg2; - } - else - { - Accumulator = (LambdaExpression) arg1; - } - - OptionalSelector = optionalSelector; - } - - public override Expression Resolve(ParameterExpression inputParameter, Expression expressionToBeResolved, ClauseGenerationContext clauseGenerationContext) - { - throw new NotImplementedException(); - } - - protected override ResultOperatorBase CreateResultOperator(ClauseGenerationContext clauseGenerationContext) - { - return new AggregateResultOperator(ParseInfo, OptionalSeed, Accumulator, OptionalSelector); - } - } - - public class AggregateResultOperator : ClientSideTransformOperator - { - public MethodCallExpressionParseInfo ParseInfo { get; set; } - public Expression OptionalSeed { get; set; } - public LambdaExpression Accumulator { get; set; } - public LambdaExpression OptionalSelector { get; set; } - - public AggregateResultOperator(MethodCallExpressionParseInfo parseInfo, Expression optionalSeed, LambdaExpression accumulator, LambdaExpression optionalSelector) - { - ParseInfo = parseInfo; - OptionalSeed = optionalSeed; - Accumulator = accumulator; - OptionalSelector = optionalSelector; - } - } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/NhQueryProvider.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -1,5 +1,4 @@ -using System; -using System.Collections; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; Added: trunk/nhibernate/src/NHibernate/Linq/NhRelinqQueryParser.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/NhRelinqQueryParser.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/NhRelinqQueryParser.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Remotion.Data.Linq; +using Remotion.Data.Linq.EagerFetching.Parsing; +using Remotion.Data.Linq.Parsing.Structure; +using Remotion.Data.Linq.Parsing.Structure.IntermediateModel; +using AggregateExpressionNode = NHibernate.Linq.Expressions.AggregateExpressionNode; + +namespace NHibernate.Linq +{ + public static class NhRelinqQueryParser + { + public static readonly MethodCallExpressionNodeTypeRegistry MethodCallRegistry = + MethodCallExpressionNodeTypeRegistry.CreateDefault(); + + static NhRelinqQueryParser() + { + MethodCallRegistry.Register( + new[] + { + MethodCallExpressionNodeTypeRegistry.GetRegisterableMethodDefinition( + ReflectionHelper.GetMethod(() => Queryable.Aggregate<object>(null, null))), + MethodCallExpressionNodeTypeRegistry.GetRegisterableMethodDefinition( + ReflectionHelper.GetMethod(() => Queryable.Aggregate<object, object>(null, null, null))) + }, + typeof (AggregateExpressionNode)); + + MethodCallRegistry.Register( + new[] + { + MethodCallExpressionNodeTypeRegistry.GetRegisterableMethodDefinition( + ReflectionHelper.GetMethod((List<object> l) => l.Contains(null))), + + }, + typeof (ContainsExpressionNode)); + + MethodCallRegistry.Register(new[] { typeof(EagerFetchingExtensionMethods).GetMethod("Fetch") }, typeof(FetchOneExpressionNode)); + MethodCallRegistry.Register(new[] { typeof(EagerFetchingExtensionMethods).GetMethod("FetchMany") }, typeof(FetchManyExpressionNode)); + MethodCallRegistry.Register(new[] { typeof(EagerFetchingExtensionMethods).GetMethod("ThenFetch") }, typeof(ThenFetchOneExpressionNode)); + MethodCallRegistry.Register(new[] { typeof(EagerFetchingExtensionMethods).GetMethod("ThenFetchMany") }, typeof(ThenFetchManyExpressionNode)); + + } + + public static QueryModel Parse(Expression expression) + { + return new QueryParser(new ExpressionTreeParser(MethodCallRegistry)).GetParsedQuery(expression); + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/ReWriters/AddLeftJoinsReWriter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/ReWriters/AddLeftJoinsReWriter.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/ReWriters/AddLeftJoinsReWriter.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -56,7 +56,7 @@ return swapper.VisitExpression(expression); } - protected override Expression VisitExpression(Expression expression) + public override Expression VisitExpression(Expression expression) { if (expression == null) { Added: trunk/nhibernate/src/NHibernate/Linq/ResultOperators/AggregateResultOperator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/ResultOperators/AggregateResultOperator.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/ResultOperators/AggregateResultOperator.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -0,0 +1,21 @@ +using System.Linq.Expressions; +using Remotion.Data.Linq.Parsing.Structure.IntermediateModel; + +namespace NHibernate.Linq.ResultOperators +{ + public class AggregateResultOperator : ClientSideTransformOperator + { + public MethodCallExpressionParseInfo ParseInfo { get; set; } + public Expression OptionalSeed { get; set; } + public LambdaExpression Accumulator { get; set; } + public LambdaExpression OptionalSelector { get; set; } + + public AggregateResultOperator(MethodCallExpressionParseInfo parseInfo, Expression optionalSeed, LambdaExpression accumulator, LambdaExpression optionalSelector) + { + ParseInfo = parseInfo; + OptionalSeed = optionalSeed; + Accumulator = accumulator; + OptionalSelector = optionalSelector; + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -2,7 +2,6 @@ using System.Collections.ObjectModel; using System.Linq.Expressions; using System.Text; -using Remotion.Data.Linq.Parsing; namespace NHibernate.Linq.Visitors { @@ -13,7 +12,7 @@ /// generate the same key as /// from c in Customers where c.City = "Madrid" /// </summary> - public class ExpressionKeyVisitor : ExpressionTreeVisitor + public class ExpressionKeyVisitor : NhExpressionTreeVisitor { private readonly IDictionary<ConstantExpression, NamedParameter> _constantToParameterMap; readonly StringBuilder _string = new StringBuilder(); @@ -93,22 +92,14 @@ return base.VisitElementInit(elementInit); } - protected override ReadOnlyCollection<T> VisitExpressionList<T>(ReadOnlyCollection<T> expressions) - { - if (expressions.Count > 0) - { - VisitExpression(expressions[0]); + private T AppendCommas<T>(T expression) where T : Expression + { + VisitExpression(expression); + _string.Append(", "); - for (var i = 1; i < expressions.Count; i++) - { - _string.Append(", "); - VisitExpression(expressions[i]); - } - } + return expression; + } - return expressions; - } - protected override Expression VisitInvocationExpression(InvocationExpression expression) { return base.VisitInvocationExpression(expression); @@ -117,7 +108,8 @@ protected override Expression VisitLambdaExpression(LambdaExpression expression) { _string.Append('('); - VisitExpressionList(expression.Parameters); + + VisitList(expression.Parameters, AppendCommas); _string.Append(") => ("); VisitExpression(expression.Body); _string.Append(')'); @@ -171,7 +163,7 @@ _string.Append('.'); _string.Append(expression.Method.Name); _string.Append('('); - VisitExpressionList(expression.Arguments); + VisitList(expression.Arguments, AppendCommas); _string.Append(')'); return expression; @@ -187,7 +179,7 @@ _string.Append("new "); _string.Append(expression.Constructor.DeclaringType.Name); _string.Append('('); - VisitExpressionList(expression.Arguments); + VisitList(expression.Arguments, AppendCommas); _string.Append(')'); return expression; Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionParameterVisitor.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -2,14 +2,13 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using Remotion.Data.Linq.Parsing; namespace NHibernate.Linq.Visitors { /// <summary> /// Locates constants in the expression tree and generates parameters for each one /// </summary> - public class ExpressionParameterVisitor : ExpressionTreeVisitor + public class ExpressionParameterVisitor : NhExpressionTreeVisitor { private readonly Dictionary<ConstantExpression, NamedParameter> _parameters = new Dictionary<ConstantExpression, NamedParameter>(); Added: trunk/nhibernate/src/NHibernate/Linq/Visitors/NameUnNamedParameters.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/NameUnNamedParameters.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/NameUnNamedParameters.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; + +namespace NHibernate.Linq.Visitors +{ + public class NameUnNamedParameters : NhExpressionTreeVisitor + { + public static Expression Visit(Expression expression) + { + var visitor = new NameUnNamedParameters(); + + return visitor.VisitExpression(expression); + } + + private readonly Dictionary<ParameterExpression, ParameterExpression> _renamedParameters = new Dictionary<ParameterExpression, ParameterExpression>(); + + protected override Expression VisitParameterExpression(ParameterExpression expression) + { + if (string.IsNullOrEmpty(expression.Name)) + { + ParameterExpression renamed; + + if (_renamedParameters.TryGetValue(expression, out renamed)) + { + return renamed; + } + + renamed = Expression.Parameter(expression.Type, Guid.NewGuid().ToString()); + + _renamedParameters.Add(expression, renamed); + + return renamed; + } + + return base.VisitParameterExpression(expression); + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/NhExpressionTreeVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/NhExpressionTreeVisitor.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/NhExpressionTreeVisitor.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -7,7 +7,7 @@ { public class NhExpressionTreeVisitor : ExpressionTreeVisitor { - protected override Expression VisitExpression(Expression expression) + public override Expression VisitExpression(Expression expression) { if (expression == null) { @@ -27,7 +27,6 @@ return VisitNhNew((NhNewExpression) expression); case NhExpressionType.Star: return VisitNhStar((NhStarExpression) expression); - } return base.VisitExpression(expression); @@ -42,7 +41,7 @@ protected virtual Expression VisitNhNew(NhNewExpression expression) { - var arguments = VisitExpressionList(expression.Arguments); + var arguments = VisitAndConvert(expression.Arguments, "VisitNhNew"); return arguments != expression.Arguments ? new NhNewExpression(expression.Members, arguments) : expression; } Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/NhThrowingExpressionTreeVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/NhThrowingExpressionTreeVisitor.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/NhThrowingExpressionTreeVisitor.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -7,7 +7,7 @@ { public abstract class NhThrowingExpressionTreeVisitor : ThrowingExpressionTreeVisitor { - protected override Expression VisitExpression(Expression expression) + public override Expression VisitExpression(Expression expression) { switch ((NhExpressionType)expression.NodeType) { @@ -125,7 +125,7 @@ protected Expression BaseVisitNhNew(NhNewExpression expression) { - var arguments = base.VisitExpressionList(expression.Arguments); + var arguments = base.VisitAndConvert(expression.Arguments, "BaseVisitNhNew"); return arguments != expression.Arguments ? new NhNewExpression(expression.Members, arguments) : expression; } Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/Nominator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/Nominator.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/Nominator.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -28,7 +28,7 @@ return _candidates; } - protected override Expression VisitExpression(Expression expression) + public override Expression VisitExpression(Expression expression) { if (expression != null) { Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using NHibernate.Hql.Ast; @@ -8,12 +7,13 @@ using NHibernate.Linq.ResultOperators; using NHibernate.Linq.ReWriters; using NHibernate.Linq.Visitors.ResultOperatorProcessors; -using NHibernate.Type; 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.EagerFetching; +using AggregateResultOperator = NHibernate.Linq.ResultOperators.AggregateResultOperator; namespace NHibernate.Linq.Visitors { @@ -48,23 +48,16 @@ var visitor = new QueryModelVisitor(parameters, root, queryModel); visitor.Visit(); - return visitor.GetTranslation(); + return visitor._hqlTree.GetTranslation(); } + private readonly IntermediateHqlTree _hqlTree; private static readonly ResultOperatorMap ResultOperatorMap; - - private readonly List<Action<IQuery, IDictionary<string, Tuple<object, IType>>>> _additionalCriteria = new List<Action<IQuery, IDictionary<string, Tuple<object, IType>>>>(); - private readonly List<LambdaExpression> _listTransformers = new List<LambdaExpression>(); - private readonly List<LambdaExpression> _itemTransformers = new List<LambdaExpression>(); - private readonly List<LambdaExpression> _postExecuteTransformers = new List<LambdaExpression>(); - private readonly bool _root; private bool _serverSide = true; - public HqlTreeNode Root { get; private set; } public VisitorParameters VisitorParameters { get; private set; } public IStreamedDataInfo CurrentEvaluationType { get; private set; } public IStreamedDataInfo PreviousEvaluationType { get; private set; } - public HqlTreeBuilder TreeBuilder { get; private set; } public QueryModel Model { get; private set; } static QueryModelVisitor() @@ -82,15 +75,16 @@ ResultOperatorMap.Add<ClientSideSelect, ProcessClientSideSelect>(); ResultOperatorMap.Add<AnyResultOperator, ProcessAny>(); ResultOperatorMap.Add<AllResultOperator, ProcessAll>(); + ResultOperatorMap.Add<FetchOneRequest, ProcessFetchOne>(); + ResultOperatorMap.Add<FetchManyRequest, ProcessFetchMany>(); } private QueryModelVisitor(VisitorParameters visitorParameters, bool root, QueryModel queryModel) { VisitorParameters = visitorParameters; Model = queryModel; - _root = root; - TreeBuilder = new HqlTreeBuilder(); - Root = TreeBuilder.Query(TreeBuilder.SelectFrom(TreeBuilder.From())); + + _hqlTree = new IntermediateHqlTree(root); } private void Visit() @@ -98,92 +92,15 @@ VisitQueryModel(Model); } - - private ExpressionToHqlTranslationResults GetTranslation() - { - if (_root) - { - DetectOuterExists(); - } - - return new ExpressionToHqlTranslationResults(Root, - _itemTransformers, - _listTransformers, - _postExecuteTransformers, - _additionalCriteria); - } - - private void DetectOuterExists() - { - if (Root is HqlExists) - { - Root = Root.Children.First(); - - _additionalCriteria.Add((q, p) => q.SetMaxResults(1)); - - Expression<Func<IEnumerable<object>, bool>> x = l => l.Any(); - - _listTransformers.Add(x); - } - } - public override void VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel) { - AddFromClause(TreeBuilder.Range( - HqlGeneratorExpressionTreeVisitor.Visit(fromClause.FromExpression, VisitorParameters), - TreeBuilder.Alias(fromClause.ItemName))); + _hqlTree.AddFromClause(_hqlTree.TreeBuilder.Range( + HqlGeneratorExpressionTreeVisitor.Visit(fromClause.FromExpression, VisitorParameters), + _hqlTree.TreeBuilder.Alias(fromClause.ItemName))); base.VisitMainFromClause(fromClause, queryModel); } - - private void AddWhereClause(HqlBooleanExpression where) - { - var currentWhere = Root.NodesPreOrder.Where(n => n is HqlWhere).FirstOrDefault(); - - if (currentWhere == null) - { - currentWhere = TreeBuilder.Where(where); - Root.As<HqlQuery>().AddChild(currentWhere); - } - else - { - var currentClause = (HqlBooleanExpression)currentWhere.Children.Single(); - - currentWhere.ClearChildren(); - currentWhere.AddChild(TreeBuilder.BooleanAnd(currentClause, where)); - } - } - - private void AddFromClause(HqlTreeNode from) - { - Root.NodesPreOrder.Where(n => n is HqlFrom).First().AddChild(from); - } - - private void AddSelectClause(HqlTreeNode select) - { - Root.NodesPreOrder.Where(n => n is HqlSelectFrom).First().AddChild(select); - } - - private void AddGroupByClause(HqlGroupBy groupBy) - { - Root.As<HqlQuery>().AddChild(groupBy); - } - - private void AddOrderByClause(HqlExpression orderBy, HqlDirectionStatement direction) - { - var orderByRoot = Root.NodesPreOrder.Where(n => n is HqlOrderBy).FirstOrDefault(); - - if (orderByRoot == null) - { - orderByRoot = TreeBuilder.OrderBy(); - Root.As<HqlQuery>().AddChild(orderByRoot); - } - - orderByRoot.AddChild(orderBy); - orderByRoot.AddChild(direction); - } - public override void VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, int index) { PreviousEvaluationType = CurrentEvaluationType; @@ -201,32 +118,7 @@ } } - var results = ResultOperatorMap.Process(resultOperator, this); - - if (results.AdditionalCriteria != null) - { - _additionalCriteria.Add(results.AdditionalCriteria); - } - if (results.GroupBy != null) - { - AddGroupByClause(results.GroupBy); - } - if (results.ListTransformer != null) - { - _listTransformers.Add(results.ListTransformer); - } - if (results.PostExecuteTransformer != null) - { - _postExecuteTransformers.Add(results.PostExecuteTransformer); - } - if (results.WhereClause != null) - { - AddWhereClause(results.WhereClause); - } - if (results.TreeNode != null) - { - Root = results.TreeNode; - } + ResultOperatorMap.Process(resultOperator, this, _hqlTree); } private void GroupBy<TSource, TKey, TResult>(Expression<Func<TSource, TKey>> keySelector, Expression<Func<TSource, TResult>> elementSelector) @@ -246,10 +138,10 @@ if (visitor.ProjectionExpression != null) { - _itemTransformers.Add(visitor.ProjectionExpression); + _hqlTree.AddItemTransformer(visitor.ProjectionExpression); } - AddSelectClause(TreeBuilder.Select(visitor.GetHqlNodes())); + _hqlTree.AddSelectClause(_hqlTree.TreeBuilder.Select(visitor.GetHqlNodes())); base.VisitSelectClause(selectClause, queryModel); } @@ -257,17 +149,17 @@ public override void VisitWhereClause(WhereClause whereClause, QueryModel queryModel, int index) { // Visit the predicate to build the query - AddWhereClause(HqlGeneratorExpressionTreeVisitor.Visit(whereClause.Predicate, VisitorParameters).AsBooleanExpression()); + _hqlTree.AddWhereClause(HqlGeneratorExpressionTreeVisitor.Visit(whereClause.Predicate, VisitorParameters).AsBooleanExpression()); } public override void VisitOrderByClause(OrderByClause orderByClause, QueryModel queryModel, int index) { foreach (Ordering clause in orderByClause.Orderings) { - AddOrderByClause(HqlGeneratorExpressionTreeVisitor.Visit(clause.Expression, VisitorParameters).AsExpression(), + _hqlTree.AddOrderByClause(HqlGeneratorExpressionTreeVisitor.Visit(clause.Expression, VisitorParameters).AsExpression(), clause.OrderingDirection == OrderingDirection.Asc - ? TreeBuilder.Ascending() - : (HqlDirectionStatement) TreeBuilder.Descending()); + ? _hqlTree.TreeBuilder.Ascending() + : (HqlDirectionStatement) _hqlTree.TreeBuilder.Descending()); } } @@ -276,10 +168,10 @@ var equalityVisitor = new EqualityHqlGenerator(VisitorParameters); var whereClause = equalityVisitor.Visit(joinClause.InnerKeySelector, joinClause.OuterKeySelector); - AddWhereClause(whereClause); + _hqlTree.AddWhereClause(whereClause); - AddFromClause(TreeBuilder.Range(HqlGeneratorExpressionTreeVisitor.Visit(joinClause.InnerSequence, VisitorParameters), - TreeBuilder.Alias(joinClause.ItemName))); + _hqlTree.AddFromClause(_hqlTree.TreeBuilder.Range(HqlGeneratorExpressionTreeVisitor.Visit(joinClause.InnerSequence, VisitorParameters), + _hqlTree.TreeBuilder.Alias(joinClause.ItemName))); } public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index) @@ -287,9 +179,9 @@ if (fromClause is LeftJoinClause) { // It's a left join - AddFromClause(TreeBuilder.LeftJoin( + _hqlTree.AddFromClause(_hqlTree.TreeBuilder.LeftJoin( HqlGeneratorExpressionTreeVisitor.Visit(fromClause.FromExpression, VisitorParameters).AsExpression(), - TreeBuilder.Alias(fromClause.ItemName))); + _hqlTree.TreeBuilder.Alias(fromClause.ItemName))); } else if (fromClause.FromExpression is MemberExpression) { @@ -298,9 +190,9 @@ if (member.Expression is QuerySourceReferenceExpression) { // It's a join - AddFromClause(TreeBuilder.Join( + _hqlTree.AddFromClause(_hqlTree.TreeBuilder.Join( HqlGeneratorExpressionTreeVisitor.Visit(fromClause.FromExpression, VisitorParameters).AsExpression(), - TreeBuilder.Alias(fromClause.ItemName))); + _hqlTree.TreeBuilder.Alias(fromClause.ItemName))); } else { @@ -311,9 +203,9 @@ else { // TODO - exact same code as in MainFromClause; refactor this out - AddFromClause(TreeBuilder.Range( + _hqlTree.AddFromClause(_hqlTree.TreeBuilder.Range( HqlGeneratorExpressionTreeVisitor.Visit(fromClause.FromExpression, VisitorParameters), - TreeBuilder.Alias(fromClause.ItemName))); + _hqlTree.TreeBuilder.Alias(fromClause.ItemName))); } Added: trunk/nhibernate/src/NHibernate/Linq/Visitors/QuerySourceLocator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/QuerySourceLocator.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/QuerySourceLocator.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -0,0 +1,37 @@ +using Remotion.Data.Linq; +using Remotion.Data.Linq.Clauses; + +namespace NHibernate.Linq.Visitors +{ + public class QuerySourceLocator : QueryModelVisitorBase + { + private readonly System.Type _type; + private IQuerySource _querySource; + + private QuerySourceLocator(System.Type type) + { + _type = type; + } + + public static IQuerySource FindQuerySource(QueryModel queryModel, System.Type type) + { + var finder = new QuerySourceLocator(type); + + finder.VisitQueryModel(queryModel); + + return finder._querySource; + } + + public override void VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel) + { + if (_type == fromClause.ItemType) + { + _querySource = fromClause; + } + else + { + base.VisitMainFromClause(fromClause, queryModel); + } + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/IResultOperatorProcessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/IResultOperatorProcessor.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/IResultOperatorProcessor.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -2,6 +2,6 @@ { public interface IResultOperatorProcessor<T> { - ProcessResultOperatorReturn Process(T resultOperator, QueryModelVisitor queryModelVisitor); + void Process(T resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAggregate.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAggregate.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAggregate.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -2,12 +2,13 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using NHibernate.Linq.ResultOperators; namespace NHibernate.Linq.Visitors.ResultOperatorProcessors { public class ProcessAggregate : IResultOperatorProcessor<AggregateResultOperator> { - public ProcessResultOperatorReturn Process(AggregateResultOperator resultOperator, QueryModelVisitor queryModelVisitor) + public void Process(AggregateResultOperator resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) { var inputType = resultOperator.Accumulator.Parameters[1].Type; var accumulatorType = resultOperator.Accumulator.Parameters[0].Type; @@ -57,7 +58,7 @@ ); } - return new ProcessResultOperatorReturn { ListTransformer = Expression.Lambda(call, inputList) }; + tree.AddListTransformer(Expression.Lambda(call, inputList)); } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAll.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAll.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAll.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -5,15 +5,13 @@ { public class ProcessAll : IResultOperatorProcessor<AllResultOperator> { - public ProcessResultOperatorReturn Process(AllResultOperator resultOperator, QueryModelVisitor queryModelVisitor) + public void Process(AllResultOperator resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) { - return new ProcessResultOperatorReturn - { - WhereClause = queryModelVisitor.TreeBuilder.BooleanNot( + tree.AddWhereClause(tree.TreeBuilder.BooleanNot( HqlGeneratorExpressionTreeVisitor.Visit(resultOperator.Predicate, queryModelVisitor.VisitorParameters). - AsBooleanExpression()), - TreeNode = queryModelVisitor.TreeBuilder.BooleanNot(queryModelVisitor.TreeBuilder.Exists((HqlQuery)queryModelVisitor.Root)) - }; + AsBooleanExpression())); + + tree.SetRoot(tree.TreeBuilder.BooleanNot(tree.TreeBuilder.Exists((HqlQuery) tree.Root))); } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAny.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAny.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessAny.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -5,12 +5,9 @@ { public class ProcessAny : IResultOperatorProcessor<AnyResultOperator> { - public ProcessResultOperatorReturn Process(AnyResultOperator anyOperator, QueryModelVisitor queryModelVisitor) + public void Process(AnyResultOperator anyOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) { - return new ProcessResultOperatorReturn - { - TreeNode = queryModelVisitor.TreeBuilder.Exists((HqlQuery) queryModelVisitor.Root) - }; + tree.SetRoot(tree.TreeBuilder.Exists((HqlQuery) tree.Root)); } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessClientSideSelect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessClientSideSelect.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessClientSideSelect.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -7,7 +7,7 @@ { public class ProcessClientSideSelect : IResultOperatorProcessor<ClientSideSelect> { - public ProcessResultOperatorReturn Process(ClientSideSelect resultOperator, QueryModelVisitor queryModelVisitor) + public void Process(ClientSideSelect resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) { var inputType = resultOperator.SelectClause.Parameters[0].Type; var outputType = resultOperator.SelectClause.Type.GetGenericArguments()[1]; @@ -22,7 +22,7 @@ Expression.Call(selectMethod, inputList, resultOperator.SelectClause)), inputList); - return new ProcessResultOperatorReturn {ListTransformer = lambda}; + tree.AddListTransformer(lambda); } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs 2010-02-24 21:23:13 UTC (rev 4947) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs 2010-02-26 20:47:09 UTC (rev 4948) @@ -6,30 +6,27 @@ { public class ProcessContains : IResultOperatorProcessor<ContainsResultOperator> { - public ProcessResultOperatorReturn Process(ContainsResultOperator resultOperator, QueryModelVisitor queryModelVisitor) + public void Process(ContainsResultOperator resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) { var itemExpression = HqlGeneratorExpressionTreeVisitor.Visit(resultOperator.Item, queryModelVisitor.VisitorParameters) .AsExpression(); - var from = GetFromRangeClause(queryModelVisitor.Root); + var from = GetFromRangeClause(tree.Root); var source = from.Children.First(); if (source is HqlParameter) { // This is an "in" style statement - return new ProcessResultOperatorReturn {TreeNode = queryModelVisitor.TreeBuilder.In(itemExpression, source)}; + tree.SetRoot(tree.TreeBuilder.In(itemExpression, source)); } else { // This is an "exists" style statement - return new ProcessResultOperatorReturn - { - ... [truncated message content] |