Example #1
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));
        }
Example #2
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;
        }
        protected override Expression VisitSubQuery(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);
        }
Example #4
0
        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;
        }
Example #5
0
        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 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);
        }