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);
        }
Exemple #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));
        }
        protected override Provider VisitApply(ApplyProvider provider)
        {
            // split

            List <int> leftMapping;
            List <int> rightMapping;

            SplitMappings(provider, out leftMapping, out rightMapping);

            ApplyParameter applyParameter     = provider.ApplyParameter;
            var            currentOuterUsages = new List <int>();

            outerColumnUsages.Add(applyParameter, currentOuterUsages);
            outerColumnUsageVisitor.VisitCompilable(provider.Right);
            outerColumnUsages.Remove(applyParameter);

            leftMapping = Merge(leftMapping, currentOuterUsages);

            if (leftMapping.Count == 0)
            {
                leftMapping.Add(0);
            }

            // visit

            var oldMappings = ReplaceMappings(provider.Left, leftMapping);
            CompilableProvider newLeftProvider = VisitCompilable(provider.Left);

            leftMapping = mappings[provider.Left];

            ReplaceMappings(provider.Right, rightMapping);
            outerColumnUsages.Add(applyParameter, leftMapping);
            CompilableProvider newRightProvider = VisitCompilable(provider.Right);

            outerColumnUsages.Remove(applyParameter);

            var pair = OverrideRightApplySource(provider, newRightProvider, rightMapping);

            if (pair.First == null)
            {
                rightMapping = mappings[provider.Right];
            }
            else
            {
                newRightProvider = pair.First;
                rightMapping     = pair.Second;
            }
            RestoreMappings(oldMappings);

            mappings[provider] = Merge(leftMapping, rightMapping.Select(map => map + provider.Left.Header.Length));

            if (newLeftProvider == provider.Left && newRightProvider == provider.Right)
            {
                return(provider);
            }
            return(new ApplyProvider(applyParameter, newLeftProvider, newRightProvider, provider.IsInlined, provider.SequenceType, provider.ApplyType));
        }
Exemple #5
0
        protected override Expression VisitProjectionExpression(ProjectionExpression projectionExpression)
        {
            var item            = Visit(projectionExpression.ItemProjector.Item);
            var provider        = providerVisitor.VisitCompilable(projectionExpression.ItemProjector.DataSource);
            var providerChanged = provider != projectionExpression.ItemProjector.DataSource;
            var itemChanged     = item != projectionExpression.ItemProjector.Item;

            if (providerChanged || itemChanged)
            {
                var itemProjector = new ItemProjectorExpression(item, provider, projectionExpression.ItemProjector.Context);
                return(new ProjectionExpression(
                           projectionExpression.Type,
                           itemProjector,
                           projectionExpression.TupleParameterBindings,
                           projectionExpression.ResultAccessMethod));
            }
            return(projectionExpression);
        }
        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);
        }
        /// <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));
            }
        }