예제 #1
0
        public void SetUp()
        {
            _detailSource = ExpressionHelper.CreateQueryable <Kitchen>();
            _sectorSource = ExpressionHelper.CreateQueryable <Restaurant>();

            var query = from s1 in ExpressionHelper.CreateQueryable <Cook>()
                        from sd in
                        (from sector in _sectorSource
                         where sector.ID > 10
                         select sector.SubKitchen)
                        from s2 in s1.Assistants
                        where sd.Name == "Maths"
                        select new NonTransformedTuple <Cook, Kitchen> (s1, sd);

            _queryModel = ExpressionHelper.ParseQuery(query);

            _mainFromClause        = _queryModel.MainFromClause;
            _additionalFromClause1 = (AdditionalFromClause)_queryModel.BodyClauses[0];
            _additionalFromClause2 = (AdditionalFromClause)_queryModel.BodyClauses[1];
            _whereClause           = (WhereClause)_queryModel.BodyClauses[2];
            _selectClause          = _queryModel.SelectClause;

            var subQueryExpressionA = (SubQueryExpression)_additionalFromClause1.FromExpression;

            _innerMainFromClauseA = subQueryExpressionA.QueryModel.MainFromClause;
            _innerWhereClauseA    = (WhereClause)subQueryExpressionA.QueryModel.BodyClauses[0];

            _visitor = new SubQueryFromClauseFlattener();
        }
예제 #2
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;
        }
예제 #3
0
        private static Expression ProcessSubquery(ISessionFactory sessionFactory, ICollection <ExpressionHolder> elementExpression, QueryModel queryModel, Expression @group, QueryModel subQueryModel)
        {
            var resultTypeOverride = subQueryModel.ResultTypeOverride;

            if (resultTypeOverride != null && !resultTypeOverride.IsArray && !IsEnumerableOfT(resultTypeOverride))
            {
                return(null);
            }

            SubQueryFromClauseFlattener.ReWrite(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));
        }
예제 #4
0
        public static ExpressionToHqlTranslationResults GenerateHqlQuery(QueryModel queryModel, VisitorParameters parameters, bool root,
                                                                         NhLinqExpressionReturnType?rootReturnType)
        {
            // Expand conditionals in subquery FROM clauses into multiple subqueries
            if (root)
            {
                // This expander works recursively
                SubQueryConditionalExpander.ReWrite(queryModel);
            }

            NestedSelectRewriter.ReWrite(queryModel, parameters.SessionFactory);

            // Remove unnecessary body operators
            RemoveUnnecessaryBodyOperators.ReWrite(queryModel);

            // Merge aggregating result operators (distinct, count, sum etc) into the select clause
            MergeAggregatingResultsRewriter.ReWrite(queryModel);

            // Swap out non-aggregating group-bys
            NonAggregatingGroupByRewriter.ReWrite(queryModel);

            // Rewrite aggregate group-by statements
            AggregatingGroupByRewriter.ReWrite(queryModel);

            // Rewrite aggregating group-joins
            AggregatingGroupJoinRewriter.ReWrite(queryModel);

            // Rewrite non-aggregating group-joins
            NonAggregatingGroupJoinRewriter.ReWrite(queryModel);

            SubQueryFromClauseFlattener.ReWrite(queryModel);

            // Rewrite left-joins
            LeftJoinRewriter.ReWrite(queryModel);

            // Rewrite paging
            PagingRewriter.ReWrite(queryModel);

            // Flatten pointless subqueries
            QueryReferenceExpressionFlattener.ReWrite(queryModel);

            // Flatten array index access to query references
            ArrayIndexExpressionFlattener.ReWrite(queryModel);

            // Add joins for references
            AddJoinsReWriter.ReWrite(queryModel, parameters);

            // Expand coalesced and conditional joins to their logical equivalents
            ConditionalQueryReferenceExpander.ReWrite(queryModel);

            // Move OrderBy clauses to end
            MoveOrderByToEndRewriter.ReWrite(queryModel);

            // Give a rewriter provided by the session factory a chance to
            // rewrite the query.
            var rewriterFactory = parameters.SessionFactory.Settings.QueryModelRewriterFactory;

            if (rewriterFactory != null)
            {
                var customVisitor = rewriterFactory.CreateVisitor(parameters);
                if (customVisitor != null)
                {
                    customVisitor.VisitQueryModel(queryModel);
                }
            }

            // rewrite any operators that should be applied on the outer query
            // by flattening out the sub-queries that they are located in
            var result = ResultOperatorRewriter.Rewrite(queryModel);

            // Identify and name query sources
            QuerySourceIdentifier.Visit(parameters.QuerySourceNamer, queryModel);

            var visitor = new QueryModelVisitor(parameters, root, queryModel, rootReturnType)
            {
                RewrittenOperatorResult = result,
            };

            visitor.Visit();

            return(visitor._hqlTree.GetTranslation());
        }