Esempio n. 1
0
 protected override Expression VisitProjection(ProjectionExpression node)
 {
     // visit mapping in reverse order
     Expression projector = Visit(node.Projector);
     var source = (SelectExpression) Visit(node.Source);
     if (projector != node.Projector || source != node.Source)
     {
         return new ProjectionExpression(source, projector, node.Aggregator);
     }
     return node;
 }
 protected override Expression VisitProjection(ProjectionExpression node)
 {
     node = (ProjectionExpression) base.VisitProjection(node);
     if (node.Source.From is SelectExpression)
     {
         List<SelectExpression> redundant = RedundantSubqueryGatherer.Gather(node.Source);
         if (redundant != null)
         {
             node = SubqueryRemover.Remove(node, redundant);
         }
     }
     return node;
 }
Esempio n. 3
0
 protected virtual Expression VisitProjection(ProjectionExpression node)
 {
     var source = (SelectExpression) Visit(node.Source);
     Expression projector = Visit(node.Projector);
     if (source != node.Source || projector != node.Projector)
     {
         return new ProjectionExpression(source, projector);
     }
     return node;
 }
Esempio n. 4
0
        private Expression BindGroupBy(Expression source, LambdaExpression keySelector, LambdaExpression elementSelector,
                                       LambdaExpression resultSelector)
        {
            ProjectionExpression projection = VisitSequence(source);

            _map[keySelector.Parameters[0]] = projection.Projector;
            Expression keyExpr = Visit(keySelector.Body);

            Expression elemExpr = projection.Projector;
            if (elementSelector != null)
            {
                _map[elementSelector.Parameters[0]] = projection.Projector;
                elemExpr = Visit(elementSelector.Body);
            }

            // Use ProjectColumns to get group-by expressions from key expression
            ProjectedColumns keyProjection = ProjectColumns(keyExpr, projection.Source.Alias, projection.Source.Alias);
            IEnumerable<Expression> groupExprs = keyProjection.Columns.Select(c => c.Expression);

            // make duplicate of source query as basis of element subquery by visiting the source again
            ProjectionExpression subqueryBasis = VisitSequence(source);

            // recompute key _columns for group expressions relative to subquery (need these for doing the correlation predicate)
            _map[keySelector.Parameters[0]] = subqueryBasis.Projector;
            Expression subqueryKey = Visit(keySelector.Body);

            // use same projection trick to get group-by expressions based on subquery
            var subqueryKeyPc = ProjectColumns(subqueryKey, subqueryBasis.Source.Alias,
                                                            subqueryBasis.Source.Alias);
            IEnumerable<Expression> subqueryGroupExprs = subqueryKeyPc.Columns.Select(c => c.Expression);
            Expression subqueryCorrelation = BuildPredicateWithNullsEqual(subqueryGroupExprs, groupExprs);

            // compute element based on duplicated subquery
            Expression subqueryElemExpr = subqueryBasis.Projector;
            if (elementSelector != null)
            {
                _map[elementSelector.Parameters[0]] = subqueryBasis.Projector;
                subqueryElemExpr = Visit(elementSelector.Body);
            }

            // build subquery that projects the desired element
            SourceAlias elementAlias = GetNextAlias();
            ProjectedColumns elementPc = ProjectColumns(subqueryElemExpr, elementAlias, subqueryBasis.Source.Alias);
            var elementSubquery =
                new ProjectionExpression(
                    new SelectExpression(elementAlias, elementPc.Columns, subqueryBasis.Source, subqueryCorrelation),
                    elementPc.Projector
                    );
            SourceAlias alias = GetNextAlias();

            // make it possible to tie _aggregates back to this group-by
            var info = new GroupByInfo(alias, elemExpr);
            _groupByMap.Add(elementSubquery, info);

            Expression resultExpr;
            if (resultSelector != null)
            {
                Expression saveGroupElement = _currentGroupElement;
                _currentGroupElement = elementSubquery;
                // compute result expression based on key & element-subquery
                _map[resultSelector.Parameters[0]] = keyProjection.Projector;
                _map[resultSelector.Parameters[1]] = elementSubquery;
                resultExpr = Visit(resultSelector.Body);
                _currentGroupElement = saveGroupElement;
            }
            else
            {
                // result must be IGrouping<K,E>
                resultExpr = Expression.New(
                    typeof (Grouping<,>).MakeGenericType(keyExpr.Type, subqueryElemExpr.Type).GetConstructors()[0],
                    new[] {keyExpr, elementSubquery}
                    );
            }

            ProjectedColumns pc = ProjectColumns(resultExpr, alias, projection.Source.Alias);

            // make it possible to tie _aggregates back to this group-by
            //Expression projectedElementSubquery = ((NewExpression)pc.Projector).Arguments[1];
            //_groupByMap.Add(projectedElementSubquery, info);

            return new ProjectionExpression(
                new SelectExpression(alias, pc.Columns, projection.Source, null, null, groupExprs),
                pc.Projector
                );
        }
Esempio n. 5
0
 internal static ProjectionExpression Remove(ProjectionExpression projection,
                                             IEnumerable<SelectExpression> selectsToRemove)
 {
     return (ProjectionExpression) new SubqueryRemover(selectsToRemove).Visit(projection);
 }