Пример #1
0
        private void ProcessFlattenedJoin(GroupJoinClause nonAggregatingJoin, QuerySourceUsageLocator locator)
        {
            var nhJoin = locator.LeftJoin
                                ? new NhOuterJoinClause(nonAggregatingJoin.JoinClause)
                                : (IQuerySource)nonAggregatingJoin.JoinClause;

            // Need to:
            // 1. Remove the group join and replace it with a join
            // 2. Remove the corresponding "from" clause (the thing that was doing the flattening)
            // 3. Rewrite the query model to reference the "join" rather than the "from" clause
            SwapClause(nonAggregatingJoin, (IBodyClause)nhJoin);

            _model.BodyClauses.Remove((IBodyClause)locator.Usages[0]);

            SwapQuerySourceVisitor querySourceSwapper;

            if (locator.LeftJoin)
            {
                // As we wrapped the join clause we have to update all references to the wrapped clause
                querySourceSwapper = new SwapQuerySourceVisitor(nonAggregatingJoin.JoinClause, nhJoin);
                _model.TransformExpressions(querySourceSwapper.Swap);
            }

            querySourceSwapper = new SwapQuerySourceVisitor(locator.Usages[0], nhJoin);
            _model.TransformExpressions(querySourceSwapper.Swap);
        }
Пример #2
0
        private void ProcessFlattenedJoin(GroupJoinClause nonAggregatingJoin)
        {
            // Need to:
            // 1. Remove the group join and replace it with a join
            // 2. Remove the corresponding "from" clause (the thing that was doing the flattening)
            // 3. Rewrite the selector to reference the "join" rather than the "from" clause
            SwapClause(nonAggregatingJoin, nonAggregatingJoin.JoinClause);

            // TODO - don't like use of _locator here; would rather we got this passed in.  Ditto on next line (esp. the cast)
            _model.BodyClauses.Remove(_locator.Clauses[0]);

            var querySourceSwapper = new SwapQuerySourceVisitor((IQuerySource)_locator.Clauses[0], nonAggregatingJoin.JoinClause);

            _model.SelectClause.TransformExpressions(querySourceSwapper.Swap);
        }
		protected override Expression VisitSubQueryExpression(SubQueryExpression expression)
		{
			// If the sub query's main (and only) from clause is one of our aggregating group bys, then swap it
			GroupJoinClause groupJoin = LocateGroupJoinQuerySource(expression.QueryModel);

			if (groupJoin != null)
			{
				Expression innerSelector = new SwapQuerySourceVisitor(groupJoin.JoinClause, expression.QueryModel.MainFromClause).
					Swap(groupJoin.JoinClause.InnerKeySelector);

				expression.QueryModel.MainFromClause.FromExpression = groupJoin.JoinClause.InnerSequence;


				// TODO - this only works if the key selectors are not composite.  Needs improvement...
				expression.QueryModel.BodyClauses.Add(new WhereClause(Expression.Equal(innerSelector, groupJoin.JoinClause.OuterKeySelector)));
			}

			return expression;
		}
Пример #4
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;
		}
		private static void FlattenSubQuery(QueryModel queryModel, QueryModel subQueryModel)
		{
			// Move the result operator up 
			if (queryModel.ResultOperators.Count > 0 && queryModel.ResultOperators.Any(resultOperator => !_resultOperators.Contains(resultOperator.GetType())))
			{
				throw new NotImplementedException();
			}

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

			queryModel.ResultOperators.Insert(0, groupBy);

			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;
		}
		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;
		}
		private void ProcessFlattenedJoin(GroupJoinClause nonAggregatingJoin)
		{
			// Need to:
			// 1. Remove the group join and replace it with a join
			// 2. Remove the corresponding "from" clause (the thing that was doing the flattening)
			// 3. Rewrite the selector to reference the "join" rather than the "from" clause
			SwapClause(nonAggregatingJoin, nonAggregatingJoin.JoinClause);

			// TODO - don't like use of _locator here; would rather we got this passed in.  Ditto on next line (esp. the cast)
			_model.BodyClauses.Remove(_locator.Clauses[0]);

			var querySourceSwapper = new SwapQuerySourceVisitor((IQuerySource)_locator.Clauses[0], nonAggregatingJoin.JoinClause);
			_model.SelectClause.TransformExpressions(querySourceSwapper.Swap);
		}
Пример #8
0
		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 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);
		}