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); }
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); }
// 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)); } }