protected override Expression VisitSubQueryExpression(SubQueryExpression subQueryExpression)
        {
            bool isTopSubquery = false;

            if (topSubquery == null)
            {
                isTopSubquery = true;
                topSubquery   = subQueryExpression;
            }

            Visit(subQueryExpression.ProjectionExpression.ItemProjector.Item);
            var visitor = new ApplyParameterAccessVisitor(topSubquery.ApplyParameter, (mc, index) => {
                columns.Add(new Pair <int, Expression>(index, mc));
                return(mc);
            });
            var providerVisitor = new CompilableProviderVisitor((provider, expression) => visitor.Visit(expression));

            providerVisitor.VisitCompilable(subQueryExpression.ProjectionExpression.ItemProjector.DataSource);

            if (isTopSubquery)
            {
                topSubquery = null;
            }

            return(subQueryExpression);
        }
Example #2
0
        public static CompilableProvider Rewrite(CompilableProvider provider, Parameter <Tuple> parameterOfTuple, ApplyParameter applyParameter)
        {
            var expressionRewriter = new ApplyParameterToTupleParameterRewriter(parameterOfTuple, applyParameter);
            var providerRewriter   = new CompilableProviderVisitor(expressionRewriter.RewriteExpression);

            return(providerRewriter.VisitCompilable(provider));
        }
        public static CompilableProvider Rewrite(CompilableProvider provider, ApplyParameter oldParameter, ApplyParameter newParameter)
        {
            var expressionRewriter = new ApplyParameterRewriter(oldParameter, newParameter);
            var providerRewriter   = new CompilableProviderVisitor(expressionRewriter.RewriteExpression);

            return(providerRewriter.VisitCompilable(provider));
        }
        // Constructors

        protected ColumnMappingInspector(CompilableProvider originalProvider)
        {
            rootProvider = originalProvider;

            mappings          = new Dictionary <Provider, List <int> >();
            outerColumnUsages = new Dictionary <ApplyParameter, List <int> >();
            mappingsGatherer  = new TupleAccessGatherer((a, b) => { });

            var outerMappingsGatherer = new TupleAccessGatherer(RegisterOuterMapping);

            outerColumnUsageVisitor = new CompilableProviderVisitor((_, e) => {
                outerMappingsGatherer.Gather(e);
                return(e);
            });
        }
        public virtual Expression Remap(int[] map, Dictionary <Expression, Expression> processedExpressions)
        {
            // Don't check CanRemap - Remap always.

            // Save Subquery parameter
            var  remapContext  = RemapScope.CurrentContext;
            bool isTopSubquery = remapContext.SubqueryParameterExpression == null;

            if (isTopSubquery)
            {
                remapContext.SubqueryParameterExpression = OuterParameter;
            }

            // Remap recordset parameters
            var visitor         = new ApplyParameterAccessVisitor(ApplyParameter, (mc, index) => Call(mc.Object, mc.Method, Constant(map.IndexOf(index))));
            var providerVisitor = new CompilableProviderVisitor((provider, expression) => visitor.Visit(expression));
            var newDataSource   = providerVisitor.VisitCompilable(ProjectionExpression.ItemProjector.DataSource);

            // Remap Field parametrized parameters
            var item = GenericExpressionVisitor <IMappedExpression> .Process(ProjectionExpression.ItemProjector.Item, mapped => {
                var parametrizedExpression = mapped as ParameterizedExpression;
                if (parametrizedExpression != null && parametrizedExpression.OuterParameter == OuterParameter)
                {
                    return(mapped.Remap(map, new Dictionary <Expression, Expression>()));
                }
                return((Expression)mapped);
            });

            var newItemProjector        = new ItemProjectorExpression(item, newDataSource, ProjectionExpression.ItemProjector.Context);
            var newProjectionExpression = new ProjectionExpression(ProjectionExpression.Type, newItemProjector, ProjectionExpression.TupleParameterBindings);
            var result = new SubQueryExpression(Type, OuterParameter, DefaultIfEmpty, newProjectionExpression, ApplyParameter, ExtendedType);

            processedExpressions.Add(this, result);

            // Restore subquery parameter
            if (isTopSubquery)
            {
                remapContext.SubqueryParameterExpression = null;
            }

            return(result);
        }
Example #6
0
        // Constructors

        public ExtendedExpressionReplacer(Func <Expression, Expression> replaceDelegate)
        {
            this.replaceDelegate = replaceDelegate;
            providerVisitor      = new CompilableProviderVisitor(TranslateExpression);
        }
        /// <inheritdoc/>
        protected override SqlProvider VisitApply(ApplyProvider provider)
        {
            bool processViaCrossApply;

            switch (provider.SequenceType)
            {
            case ApplySequenceType.All:
                // apply is required
                if (!providerInfo.Supports(ProviderFeatures.Apply))
                {
                    throw new NotSupportedException();
                }
                processViaCrossApply = true;
                break;

            case ApplySequenceType.First:
            case ApplySequenceType.FirstOrDefault:
                // apply is prefered but is not required
                processViaCrossApply = providerInfo.Supports(ProviderFeatures.Apply);
                break;

            case ApplySequenceType.Single:
            case ApplySequenceType.SingleOrDefault:
                // apply is not allowed
                processViaCrossApply = false;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            var  left = Compile(provider.Left);
            bool shouldUseQueryReference;
            var  sourceSelect = left.Request.Statement;

            if (processViaCrossApply)
            {
                shouldUseQueryReference = ShouldUseQueryReference(provider, left);
            }
            else
            {
                var calculatedColumnIndexes = sourceSelect.Columns
                                              .Select((c, i) => IsCalculatedColumn(c) ? i : -1)
                                              .Where(i => i >= 0)
                                              .ToList();
                var groupByIsUsed = sourceSelect.GroupBy.Count > 0;

                var usedOuterColumns = new List <int>();
                var visitor          = new ApplyParameterAccessVisitor(provider.ApplyParameter, (mc, index) => {
                    usedOuterColumns.Add(index);
                    return(mc);
                });
                var providerVisitor = new CompilableProviderVisitor((p, e) => visitor.Visit(e));
                providerVisitor.VisitCompilable(provider.Right);
                shouldUseQueryReference = usedOuterColumns.Any(calculatedColumnIndexes.Contains) ||
                                          groupByIsUsed ||
                                          provider.Left.Type.In(ProviderType.Store, ProviderType.Include) ||
                                          left.Header.Columns.Count != left.Request.Statement.Columns.Count;
            }

            var binding = OuterReferences.Add(
                provider.ApplyParameter, new Pair <SqlProvider, bool>(left, shouldUseQueryReference));

            using (binding) {
                var right = Compile(provider.Right);

                var query = processViaCrossApply
          ? ProcessApplyViaCrossApply(provider, left, right)
          : ProcessApplyViaSubqueries(provider, left, right, shouldUseQueryReference);

                return(CreateProvider(query, provider, left, right));
            }
        }