public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
		{
			var subQuery = fromClause.FromExpression as SubQueryExpression;
			if (subQuery == null)
				return;

			var subQueryModel = subQuery.QueryModel;
			if (!IsLeftJoin(subQueryModel))
				return;

			var mainFromClause = subQueryModel.MainFromClause;

			var restrictions = subQueryModel.BodyClauses
				.OfType<WhereClause>()
				.Select(w => new NhWithClause(w.Predicate));

			var join = new NhJoinClause(mainFromClause.ItemName,
										mainFromClause.ItemType,
										mainFromClause.FromExpression,
										restrictions);

			var innerSelectorMapping = new QuerySourceMapping();
			innerSelectorMapping.AddMapping(fromClause, subQueryModel.SelectClause.Selector);

			queryModel.TransformExpressions(ex => ReferenceReplacingExpressionTreeVisitor.ReplaceClauseReferences(ex, innerSelectorMapping, false));

			queryModel.BodyClauses.RemoveAt(index);
			queryModel.BodyClauses.Insert(index, @join);
			InsertBodyClauses(subQueryModel.BodyClauses.Where(b => !(b is WhereClause)), queryModel, index + 1);

			var innerBodyClauseMapping = new QuerySourceMapping();
			innerBodyClauseMapping.AddMapping(mainFromClause, new QuerySourceReferenceExpression(@join));

			queryModel.TransformExpressions(ex => ReferenceReplacingExpressionTreeVisitor.ReplaceClauseReferences(ex, innerBodyClauseMapping, false));
		}
		private void FlattenSubQuery(SubQueryExpression subQueryExpression, QueryModel queryModel)
		{
			// Move the result operator up 
			if (queryModel.ResultOperators.Count != 0)
			{
				throw new NotImplementedException();
			}

			var groupBy = (GroupResultOperator) subQueryExpression.QueryModel.ResultOperators[0];

			queryModel.ResultOperators.Add(groupBy);

			foreach (var bodyClause in subQueryExpression.QueryModel.BodyClauses)
			{
				queryModel.BodyClauses.Add(bodyClause);
			}

			// Replace the outer select clause...
			queryModel.SelectClause.TransformExpressions(s => 
				GroupBySelectClauseRewriter.ReWrite(s, groupBy, subQueryExpression.QueryModel));

			// Point all query source references to the outer from clause
			queryModel.TransformExpressions(s =>
				new SwapQuerySourceVisitor(queryModel.MainFromClause, subQueryExpression.QueryModel.MainFromClause).Swap(s));

			// Replace the outer query source
			queryModel.MainFromClause = subQueryExpression.QueryModel.MainFromClause;
		}
		private static void FlattenSubQuery(SubQueryExpression subQueryExpression, FromClauseBase fromClause, QueryModel queryModel, int destinationIndex)
		{
			if (!CheckFlattenable(subQueryExpression.QueryModel))
				return;

			var mainFromClause = subQueryExpression.QueryModel.MainFromClause;
			CopyFromClauseData(mainFromClause, fromClause);

			var innerSelectorMapping = new QuerySourceMapping();
			innerSelectorMapping.AddMapping(fromClause, subQueryExpression.QueryModel.SelectClause.Selector);
			queryModel.TransformExpressions((ex => ReferenceReplacingExpressionTreeVisitor.ReplaceClauseReferences(ex, innerSelectorMapping, false)));

			InsertBodyClauses(subQueryExpression.QueryModel.BodyClauses, queryModel, destinationIndex);
			CopyResultOperators(subQueryExpression.QueryModel.ResultOperators, queryModel);

			var innerBodyClauseMapping = new QuerySourceMapping();
			innerBodyClauseMapping.AddMapping(mainFromClause, new QuerySourceReferenceExpression(fromClause));
			queryModel.TransformExpressions((ex => ReferenceReplacingExpressionTreeVisitor.ReplaceClauseReferences(ex, innerBodyClauseMapping, false)));
		}
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used 
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual ISet<IQuerySource> FindQuerySourcesRequiringMaterialization([NotNull] QueryModel queryModel)
        {
            _queryModel = queryModel;
            _selector = queryModel.SelectClause.Selector;

            _queryModel.TransformExpressions(Visit);

            var querySources
                = new HashSet<IQuerySource>(
                    _querySources.Where(kv => kv.Value > 0).Select(kv => kv.Key));

            return querySources;
        }
        private void ReWrite(QueryModel queryModel)
        {
            VisitQueryModel(queryModel);

            if (_joins.Count > 0)
            {
                MemberExpressionSwapper swap = new MemberExpressionSwapper(_expressionMap);
                queryModel.TransformExpressions(swap.VisitExpression);

                foreach (var join in _joins.Values)
                {
                    queryModel.BodyClauses.Add(join);
                }
            }
        }
		private static void FlattenSubQuery(SubQueryExpression subQueryExpression, QueryModel queryModel)
		{
			// Move the result operator up 
			if (queryModel.ResultOperators.Count != 0)
			{
				throw new NotImplementedException();
			}

			var groupBy = (GroupResultOperator) subQueryExpression.QueryModel.ResultOperators[0];

			queryModel.ResultOperators.Add(groupBy);

			for (int i = 0; i < queryModel.BodyClauses.Count; i++)
			{
				var clause = queryModel.BodyClauses[i];
				clause.TransformExpressions(s => GroupBySelectClauseRewriter.ReWrite(s, groupBy, subQueryExpression.QueryModel));

				//all outer where clauses actually are having clauses
				var whereClause = clause as WhereClause;
				if (whereClause != null)
				{
					queryModel.BodyClauses.RemoveAt(i);
					queryModel.BodyClauses.Insert(i, new NhHavingClause(whereClause.Predicate));
				}
			}

			foreach (var bodyClause in subQueryExpression.QueryModel.BodyClauses)
			{
				queryModel.BodyClauses.Add(bodyClause);
			}

			// Replace the outer select clause...
			queryModel.SelectClause.TransformExpressions(s => 
				GroupBySelectClauseRewriter.ReWrite(s, groupBy, subQueryExpression.QueryModel));

			// Point all query source references to the outer from clause
			queryModel.TransformExpressions(s =>
				new SwapQuerySourceVisitor(queryModel.MainFromClause, subQueryExpression.QueryModel.MainFromClause).Swap(s));

			// Replace the outer query source
			queryModel.MainFromClause = subQueryExpression.QueryModel.MainFromClause;
		}
Example #7
0
		private static void FlattenSubQuery(SubQueryExpression subQueryExpression, QueryModel queryModel)
		{
			// we can not flattern subquery if outer query has body clauses.
			var subQueryModel = subQueryExpression.QueryModel;
			var subQueryMainFromClause = subQueryModel.MainFromClause;
			if (queryModel.BodyClauses.Count == 0)
			{
				foreach (var resultOperator in subQueryModel.ResultOperators)
					queryModel.ResultOperators.Add(resultOperator);

				foreach (var bodyClause in subQueryModel.BodyClauses)
					queryModel.BodyClauses.Add(bodyClause);
			}
			else
			{
				var cro = new ContainsResultOperator(new QuerySourceReferenceExpression(subQueryMainFromClause));

				var newSubQueryModel = subQueryModel.Clone();
				newSubQueryModel.ResultOperators.Add(cro);
				newSubQueryModel.ResultTypeOverride = typeof (bool);

				var where = new WhereClause(new SubQueryExpression(newSubQueryModel));
				queryModel.BodyClauses.Add(where);

				if (!queryModel.BodyClauses.OfType<OrderByClause>().Any())
				{
					var orderByClauses = subQueryModel.BodyClauses.OfType<OrderByClause>();
					foreach (var orderByClause in orderByClauses)
						queryModel.BodyClauses.Add(orderByClause);
				}
			}

			var visitor1 = new PagingRewriterSelectClauseVisitor();
			queryModel.SelectClause.TransformExpressions(visitor1.Swap);

			// Point all query source references to the outer from clause
			var visitor2 = new SwapQuerySourceVisitor(queryModel.MainFromClause, subQueryMainFromClause);
			queryModel.TransformExpressions(visitor2.Swap);

			// Replace the outer query source
			queryModel.MainFromClause = subQueryMainFromClause;
		}
		public static void ReWrite(QueryModel model)
		{
			var visitor = new QueryReferenceExpressionFlattener(model);
			model.TransformExpressions(visitor.VisitExpression);
		}
		private static void FlattenSubQuery(QueryModel queryModel, QueryModel subQueryModel, GroupResultOperator groupBy)
		{
			foreach (var resultOperator in queryModel.ResultOperators.Where(resultOperator => !AcceptableOuterResultOperators.Contains(resultOperator.GetType())))
			{
				throw new NotImplementedException("Cannot use group by with the " + resultOperator.GetType().Name + " result operator.");
			}

			// Move the result operator up.
			SubQueryFromClauseFlattener.InsertResultOperators(subQueryModel.ResultOperators, queryModel);

			for (var i = 0; i < queryModel.BodyClauses.Count; i++)
			{
				var clause = queryModel.BodyClauses[i];
				clause.TransformExpressions(s => GroupBySelectClauseRewriter.ReWrite(s, groupBy, subQueryModel));

				//all outer where clauses actually are having clauses
				var whereClause = clause as WhereClause;
				if (whereClause != null)
				{
					queryModel.BodyClauses.RemoveAt(i);
					queryModel.BodyClauses.Insert(i, new NhHavingClause(whereClause.Predicate));
				}
			}

			foreach (var bodyClause in subQueryModel.BodyClauses)
				queryModel.BodyClauses.Add(bodyClause);

			// Replace the outer select clause...
			queryModel.SelectClause.TransformExpressions(s => 
				GroupBySelectClauseRewriter.ReWrite(s, groupBy, subQueryModel));

			// Point all query source references to the outer from clause
			var visitor = new SwapQuerySourceVisitor(queryModel.MainFromClause, subQueryModel.MainFromClause);
			queryModel.TransformExpressions(visitor.Swap);

			// Replace the outer query source
			queryModel.MainFromClause = subQueryModel.MainFromClause;
		}
		public static void ReWrite(QueryModel model)
		{
			var visitor = new ArrayIndexExpressionFlattener();
			model.TransformExpressions(visitor.VisitExpression);
		}
        /// <inheritdoc />
        public override void VisitQueryModel(QueryModel queryModel)
        {
            queryModel.TransformExpressions(e => new MixinExpressionVisitor(Model).Visit(e));

            base.VisitQueryModel(queryModel);
        }
            public bool RequiresBuffering(QueryModel queryModel)
            {
                queryModel.TransformExpressions(Visit);

                return _requiresBuffering;
            }
		private static Expression ProcessSubquery(ISessionFactory sessionFactory, ICollection<ExpressionHolder> elementExpression, QueryModel queryModel, Expression @group, QueryModel subQueryModel)
		{
			var subQueryMainFromClause = subQueryModel.MainFromClause;

			var restrictions = subQueryModel.BodyClauses
											.OfType<WhereClause>()
											.Select(w => new NhWithClause(w.Predicate));

			var join = new NhJoinClause(subQueryMainFromClause.ItemName,
										subQueryMainFromClause.ItemType,
										subQueryMainFromClause.FromExpression,
										restrictions);

			queryModel.BodyClauses.Add(@join);

			var visitor = new SwapQuerySourceVisitor(subQueryMainFromClause, @join);

			queryModel.TransformExpressions(visitor.Swap);

			var selector = subQueryModel.SelectClause.Selector;

			var collectionType = subQueryModel.GetResultType();
			
			var elementType = selector.Type;

			var source = new QuerySourceReferenceExpression(@join);

			return BuildSubCollectionQuery(sessionFactory, elementExpression, @group, source, selector, elementType, collectionType);
		}
            public bool AnyShadowAccess(QueryModel queryModel)
            {
                queryModel.TransformExpressions(Visit);

                return _anyShadowAccess;
            }
		public static void ReWrite(QueryModel queryModel, ISessionFactory sessionFactory)
		{
			var nsqmv = new NestedSelectDetector();
			nsqmv.VisitExpression(queryModel.SelectClause.Selector);
			if (!nsqmv.HasSubquery)
				return;

			var subQueryModel = nsqmv.Expression.QueryModel;

			var mainFromClause = subQueryModel.MainFromClause;

			var restrictions = subQueryModel.BodyClauses
				.OfType<WhereClause>()
				.Select(w => new NhWithClause(w.Predicate));

			var join = new NhJoinClause(mainFromClause.ItemName,
										mainFromClause.ItemType,
										mainFromClause.FromExpression,
										restrictions);

			queryModel.BodyClauses.Add(join);

			var visitor = new SwapQuerySourceVisitor(subQueryModel.MainFromClause, join);

			queryModel.TransformExpressions(visitor.Swap);

			var ctor = Tuple.Type.GetConstructor(System.Type.EmptyTypes);
			
			var key = Expression.Parameter(Tuple.Type, "key");

			var values = Expression.Parameter(typeof (IEnumerable<Tuple>), "values");

			var expressions = new List<ExpressionHolder>();

			var rewriter = new SelectClauseRewriter(key, values, expressions);

			var resultSelector = rewriter.VisitExpression(queryModel.SelectClause.Selector);

			var field = Tuple.Type.GetField("Items");

			var keySelector = CreateSelector(ctor, field, expressions, 0);

			var elementSelector = CreateSelector(ctor, field, expressions, 1);

			var cast = EnumerableHelper.GetMethod("Cast", new[] {typeof (IEnumerable)}, new[] {typeof (object[])});

			var groupBy = EnumerableHelper.GetMethod("GroupBy",
													 new[] {typeof (IEnumerable<>), typeof (Func<,>), typeof (Func<,>), typeof (Func<,,>)},
													 new[] {typeof (object[]), Tuple.Type, Tuple.Type, queryModel.SelectClause.Selector.Type});

			var toList = EnumerableHelper.GetMethod("ToList", new[] { typeof(IEnumerable<>) }, new[] { queryModel.SelectClause.Selector.Type });
			
			var input = Expression.Parameter(typeof (IEnumerable<object>), "input");

			var call = Expression.Call(toList,
									   Expression.Call(groupBy,
													   Expression.Call(cast, input),
													   keySelector,
													   elementSelector,
													   Expression.Lambda(resultSelector, key, values)));

			var lambda = Expression.Lambda(call, input);

			queryModel.ResultOperators.Add(new ClientSideSelect2(lambda));

			var initializers = expressions.Select(e => e.Expression == null
														   ? GetIdentifier(sessionFactory, expressions, e)
														   : ConvertToObject(e.Expression));

			queryModel.SelectClause.Selector = Expression.NewArrayInit(typeof (object), initializers);
		}
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used 
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected override Expression VisitSubQuery(SubQueryExpression expression)
        {
            var oldParentSelector = _selector;
            var oldQueryModel = _queryModel;

            _selector = expression.QueryModel.SelectClause.Selector;
            _queryModel = expression.QueryModel;

            _queryModel.TransformExpressions(Visit);

            _selector = oldParentSelector;
            _queryModel = oldQueryModel;

            var querySourceReferenceExpression
                = expression.QueryModel.SelectClause.Selector
                    as QuerySourceReferenceExpression;

            if (querySourceReferenceExpression != null)
            {
                var querySourceTracingExpressionVisitor = new QuerySourceTracingExpressionVisitor();

                if (expression.QueryModel.ResultOperators.LastOrDefault() is DefaultIfEmptyResultOperator)
                {
                    var underlyingQuerySource = (((querySourceReferenceExpression.ReferencedQuerySource as MainFromClause)
                        ?.FromExpression as QuerySourceReferenceExpression)
                        ?.ReferencedQuerySource as GroupJoinClause)?.JoinClause;

                    if (underlyingQuerySource != null)
                    {
                        AddQuerySource(underlyingQuerySource);
                    }
                }

                var resultQuerySource
                    = querySourceTracingExpressionVisitor
                        .FindResultQuerySourceReferenceExpression(
                            _selector,
                            querySourceReferenceExpression.ReferencedQuerySource);

                if ((resultQuerySource == null)
                    && !(expression.QueryModel.ResultOperators.LastOrDefault() is OfTypeResultOperator))
                {
                    _querySources[querySourceReferenceExpression.ReferencedQuerySource]--;
                }

                foreach (var sourceExpression in _queryModel.ResultOperators.Select(SetResultOperationSourceExpression).Where(e => e != null))
                {
                    if (sourceExpression.Equals(expression))
                    {
                        var parentQuerySource = _selector as QuerySourceReferenceExpression;
                        if ((parentQuerySource != null)
                            && (_querySources[parentQuerySource.ReferencedQuerySource] > 0)
                            && (parentQuerySource.Type == querySourceReferenceExpression.Type))
                        {
                            _querySources[querySourceReferenceExpression.ReferencedQuerySource]++;
                        }
                    }
                }
            }

            return expression;
        }