private DbExpression RewriteCollection(DbExpression expression)
        {
            DbExpression        dbExpression      = expression;
            DbProjectExpression projectExpression = (DbProjectExpression)null;

            if (DbExpressionKind.Project == expression.ExpressionKind)
            {
                projectExpression = (DbProjectExpression)expression;
                dbExpression      = projectExpression.Input.Expression;
            }
            ObjectSpanRewriter.NavigationInfo navInfo = (ObjectSpanRewriter.NavigationInfo)null;
            if (this.RelationshipSpan)
            {
                dbExpression = ObjectSpanRewriter.RelationshipNavigationVisitor.FindNavigationExpression(dbExpression, this._aliasGenerator, out navInfo);
            }
            if (navInfo != null)
            {
                this.EnterNavigationCollection(navInfo);
            }
            else
            {
                this.EnterCollection();
            }
            DbExpression body = expression;

            if (projectExpression != null)
            {
                DbExpression projection = this.Rewrite(projectExpression.Projection);
                if (!object.ReferenceEquals((object)projectExpression.Projection, (object)projection))
                {
                    body = (DbExpression)dbExpression.BindAs(projectExpression.Input.VariableName).Project(projection);
                }
            }
            else
            {
                DbExpressionBinding input      = dbExpression.BindAs(this._aliasGenerator.Next());
                DbExpression        variable   = (DbExpression)input.Variable;
                DbExpression        projection = this.Rewrite(variable);
                if (!object.ReferenceEquals((object)variable, (object)projection))
                {
                    body = (DbExpression)input.Project(projection);
                }
            }
            this.ExitCollection();
            if (navInfo != null && navInfo.InUse)
            {
                body = (DbExpression)DbExpressionBuilder.Lambda(body, (IEnumerable <DbVariableReferenceExpression>) new List <DbVariableReferenceExpression>(1)
                {
                    navInfo.SourceVariable
                }).Invoke((IEnumerable <DbExpression>) new List <DbExpression>(1)
                {
                    navInfo.Source
                });
            }
            return(body);
        }
Пример #2
0
        /// <summary>
        /// Logicaly, <see cref="DbSkipExpression"/> translates to:
        /// SELECT Y.x1, Y.x2, ..., Y.xn
        /// FROM (
        ///     SELECT X.x1, X.x2, ..., X.xn,
        ///     FROM input AS X
        ///        EXCEPT
        ///     SELECT TOP(count) Z.x1, Z.x2, ..., Z.xn
        ///     FROM input AS Z
        ///     ORDER BY sk1, sk2, ...
        ///     ) AS Y
        /// ORDER BY sk1, sk2, ...
        ///
        /// Here, input refers to the input of the <see cref="DbSkipExpression"/>, and count to the count property of the <see cref="DbSkipExpression"/>.
        /// The implementation of EXCEPT is non-duplicate eliminating, and does equality comparison only over the
        /// equality comparable columns of the input.
        ///
        /// This corresponds to the following expression tree:
        ///
        /// SORT
        ///  |
        /// NON-DISTINCT EXCEPT  (specially translated, <see cref="TransformIntersectOrExcept(DbExpression left, DbExpression right, DbExpressionKind expressionKind, IList<DbPropertyExpression> sortExpressionsOverLeft, string sortExpressionsBindingVariableName)"/>
        ///  |
        ///  | - Left:  clone of input
        ///  | - Right:
        ///       |
        ///      Limit
        ///       |
        ///       | - Limit: Count
        ///       | - Input
        ///             |
        ///            Sort
        ///             |
        ///            input
        ///
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        public override DbExpression Visit(DbSkipExpression e)
        {
            //Build the right input of the except
            DbExpression rightInput = VisitExpressionBinding(e.Input).Sort(VisitSortOrder(e.SortOrder)).Limit(VisitExpression(e.Count));

            //Build the left input for the except
            DbExpression leftInput = VisitExpression(e.Input.Expression); //Another copy of the input

            IList <DbSortClause> sortOrder = VisitSortOrder(e.SortOrder); //Another copy of the sort order

            // Create a list of the sort expressions to be used for translating except
            IList <DbPropertyExpression> sortExpressions = new List <DbPropertyExpression>(e.SortOrder.Count);

            foreach (DbSortClause sortClause in sortOrder)
            {
                //We only care about property expressions, not about constants
                if (sortClause.Expression.ExpressionKind == DbExpressionKind.Property)
                {
                    sortExpressions.Add((DbPropertyExpression)sortClause.Expression);
                }
            }

            DbExpression exceptExpression = TransformIntersectOrExcept(leftInput, rightInput, DbExpressionKind.Skip, sortExpressions, e.Input.VariableName);

            DbExpression result = exceptExpression.BindAs(e.Input.VariableName).Sort(sortOrder);

            return(result);
        }
Пример #3
0
            public override DbExpression Visit(DbProjectExpression expression)
            {
                // Only allowed cases:
                // SELECT Deref(x) FROM <expression> AS x
                // SELECT x FROM <expression> as x
                DbExpression testExpr = expression.Projection;

                if (DbExpressionKind.Deref == testExpr.ExpressionKind)
                {
                    testExpr = ((DbDerefExpression)testExpr).Argument;
                }

                if (DbExpressionKind.VariableReference == testExpr.ExpressionKind)
                {
                    DbVariableReferenceExpression varRef = (DbVariableReferenceExpression)testExpr;
                    if (varRef.VariableName.Equals(expression.Input.VariableName, StringComparison.Ordinal))
                    {
                        DbExpression found = Find(expression.Input.Expression);
                        if (!object.ReferenceEquals(found, expression.Input.Expression))
                        {
                            return(found.BindAs(expression.Input.VariableName).Project(expression.Projection));
                        }
                    }
                }

                return(expression);
            }
            public override DbExpression Visit(DbSkipExpression expression)
            {
                Check.NotNull <DbSkipExpression>(expression, nameof(expression));
                DbExpression input = this.Find(expression.Input.Expression);

                if (!object.ReferenceEquals((object)input, (object)expression.Input.Expression))
                {
                    return((DbExpression)input.BindAs(expression.Input.VariableName).Skip((IEnumerable <DbSortClause>)expression.SortOrder, expression.Count));
                }
                return((DbExpression)expression);
            }
            public override DbExpression Visit(DbFilterExpression expression)
            {
                Check.NotNull <DbFilterExpression>(expression, nameof(expression));
                DbExpression input = this.Find(expression.Input.Expression);

                if (!object.ReferenceEquals((object)input, (object)expression.Input.Expression))
                {
                    return((DbExpression)input.BindAs(expression.Input.VariableName).Filter(expression.Predicate));
                }
                return((DbExpression)expression);
            }
Пример #6
0
                internal virtual DbExpression OfType(TypeUsage type)
                {
                    // s.OfType<T> is normally translated to s.Filter(e => e is T).Project(e => e as T)
                    DbExpressionBinding rootBinding   = _root.BindAs(_aliasGenerator.Next());
                    DbExpression        filter        = this.Filter(rootBinding.Filter(rootBinding.Variable.IsOf(type)));
                    OrderByLifterBase   filterLifter  = GetLifter(filter, _aliasGenerator);
                    DbExpressionBinding filterBinding = filter.BindAs(_aliasGenerator.Next());
                    DbExpression        project       = filterLifter.Project(filterBinding.Project(filterBinding.Variable.TreatAs(type)));

                    return(project);
                }
Пример #7
0
        private DbExpression GenerateStructuralTypeResultMappingView(
            DbExpression storeFunctionInvoke,
            out DiscriminatorMap discriminatorMap)
        {
            discriminatorMap = (DiscriminatorMap)null;
            DbExpression dbExpression = storeFunctionInvoke;
            DbExpression queryView;

            if (this.m_structuralTypeMappings.Count == 1)
            {
                Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> > structuralTypeMapping = this.m_structuralTypeMappings[0];
                StructuralType structuralType = structuralTypeMapping.Item1;
                List <ConditionPropertyMapping> conditions       = structuralTypeMapping.Item2;
                List <PropertyMapping>          propertyMappings = structuralTypeMapping.Item3;
                if (conditions.Count > 0)
                {
                    dbExpression = (DbExpression)dbExpression.Where((Func <DbExpression, DbExpression>)(row => FunctionImportMappingComposable.GenerateStructuralTypeConditionsPredicate(conditions, row)));
                }
                DbExpressionBinding input = dbExpression.BindAs("row");
                DbExpression        structuralTypeMappingView = FunctionImportMappingComposable.GenerateStructuralTypeMappingView(structuralType, propertyMappings, (DbExpression)input.Variable);
                queryView = (DbExpression)input.Project(structuralTypeMappingView);
            }
            else
            {
                DbExpressionBinding binding = dbExpression.BindAs("row");
                List <DbExpression> list    = this.m_structuralTypeMappings.Select <Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> >, DbExpression>((Func <Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> >, DbExpression>)(m => FunctionImportMappingComposable.GenerateStructuralTypeConditionsPredicate(m.Item2, (DbExpression)binding.Variable))).ToList <DbExpression>();
                binding = binding.Filter(Helpers.BuildBalancedTreeInPlace <DbExpression>((IList <DbExpression>)list.ToArray(), (Func <DbExpression, DbExpression, DbExpression>)((prev, next) => (DbExpression)prev.Or(next)))).BindAs("row");
                List <DbExpression> source = new List <DbExpression>(this.m_structuralTypeMappings.Count);
                foreach (Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> > structuralTypeMapping in this.m_structuralTypeMappings)
                {
                    StructuralType         structuralType   = structuralTypeMapping.Item1;
                    List <PropertyMapping> propertyMappings = structuralTypeMapping.Item3;
                    source.Add(FunctionImportMappingComposable.GenerateStructuralTypeMappingView(structuralType, propertyMappings, (DbExpression)binding.Variable));
                }
                DbExpression projection = (DbExpression)DbExpressionBuilder.Case(list.Take <DbExpression>(this.m_structuralTypeMappings.Count - 1), source.Take <DbExpression>(this.m_structuralTypeMappings.Count - 1), source[this.m_structuralTypeMappings.Count - 1]);
                queryView = (DbExpression)binding.Project(projection);
                DiscriminatorMap.TryCreateDiscriminatorMap(this.FunctionImport.EntitySet, queryView, out discriminatorMap);
            }
            return(queryView);
        }
Пример #8
0
            public override DbExpression Visit(DbSkipExpression expression)
            {
                DbExpression found = Find(expression.Input.Expression);

                if (!object.ReferenceEquals(found, expression.Input.Expression))
                {
                    return(found.BindAs(expression.Input.VariableName).Skip(expression.SortOrder, expression.Count));
                }
                else
                {
                    return(expression);
                }
            }
Пример #9
0
            // For Distinct, Limit, OfType there is no need to override the base visitor behavior.

            public override DbExpression Visit(DbFilterExpression expression)
            {
                // Only consider the Filter input
                DbExpression found = Find(expression.Input.Expression);

                if (!object.ReferenceEquals(found, expression.Input.Expression))
                {
                    return(found.BindAs(expression.Input.VariableName).Filter(expression.Predicate));
                }
                else
                {
                    return(expression);
                }
            }
            public override DbExpression Visit(DbProjectExpression expression)
            {
                Check.NotNull <DbProjectExpression>(expression, nameof(expression));
                DbExpression projection = expression.Projection;

                if (DbExpressionKind.Deref == projection.ExpressionKind)
                {
                    projection = ((DbUnaryExpression)projection).Argument;
                }
                if (DbExpressionKind.VariableReference == projection.ExpressionKind && ((DbVariableReferenceExpression)projection).VariableName.Equals(expression.Input.VariableName, StringComparison.Ordinal))
                {
                    DbExpression input = this.Find(expression.Input.Expression);
                    if (!object.ReferenceEquals((object)input, (object)expression.Input.Expression))
                    {
                        return((DbExpression)input.BindAs(expression.Input.VariableName).Project(expression.Projection));
                    }
                }
                return((DbExpression)expression);
            }
Пример #11
0
        private DbExpression RewriteCollection(DbExpression expression, CollectionType collectionType)
        {
            DbExpression target = expression;

            // If the collection expression is a project expression, get a strongly typed reference to it for later use.
            DbProjectExpression project = null;

            if (DbExpressionKind.Project == expression.ExpressionKind)
            {
                project = (DbProjectExpression)expression;
                target  = project.Input.Expression;
            }

            // If Relationship span is enabled and the source of this collection is (directly or indirectly)
            // a RelationshipNavigation operation, it may be possible to optimize the relationship span rewrite
            // for the Entities produced by the navigation.
            NavigationInfo navInfo = null;

            if (this.RelationshipSpan)
            {
                // Attempt to find a RelationshipNavigationExpression in the collection-defining expression
                target = RelationshipNavigationVisitor.FindNavigationExpression(target, _aliasGenerator, out navInfo);
            }

            // If a relationship navigation expression defines this collection, make the Ref that is the navigation source
            // and the source association end available for possible use when the projection over the collection is rewritten.
            if (navInfo != null)
            {
                this.EnterNavigationCollection(navInfo);
            }
            else
            {
                // Otherwise, add a null navigation info instance to the stack to indicate that relationship navigation
                // cannot be optimized for the entities produced by this collection expression (if it is a collection of entities).
                this.EnterCollection();
            }

            // If the expression is already a DbProjectExpression then simply visit the projection,
            // instead of introducing another projection over the existing one.
            DbExpression result = expression;

            if (project != null)
            {
                DbExpression newProjection = this.Rewrite(project.Projection);
                if (!object.ReferenceEquals(project.Projection, newProjection))
                {
                    result = target.BindAs(project.Input.VariableName).Project(newProjection);
                }
            }
            else
            {
                // This is not a recognized special case, so simply add the span projection over the original
                // collection-producing expression, if it is required.
                DbExpressionBinding collectionBinding = target.BindAs(_aliasGenerator.Next());
                DbExpression        projection        = collectionBinding.Variable;

                DbExpression spannedProjection = this.Rewrite(projection);

                if (!object.ReferenceEquals(projection, spannedProjection))
                {
                    result = collectionBinding.Project(spannedProjection);
                }
            }

            // Remove any navigation information from scope, if it was added
            this.ExitCollection();

            // If a navigation expression defines this collection and its navigation information was used to
            // short-circuit relationship span rewrites, then enclose the entire rewritten expression in a
            // Lambda binding that brings the source Ref of the navigation operation into scope. This ref is
            // refered to by VariableReferenceExpressions in the original navigation expression as well as any
            // short-circuited relationship span columns in the rewritten expression.
            if (navInfo != null && navInfo.InUse)
            {
                // Create a Lambda function that binds the original navigation source expression under the variable name
                // used in the navigation expression and the relationship span columns, and which has its Lambda body
                // defined by the rewritten collection expression.
                List <DbVariableReferenceExpression> formals = new List <DbVariableReferenceExpression>(1);
                formals.Add(navInfo.SourceVariable);

                List <DbExpression> args = new List <DbExpression>(1);
                args.Add(navInfo.Source);

                result = DbExpressionBuilder.Invoke(DbExpressionBuilder.Lambda(result, formals), args);
            }

            // Return the (possibly rewritten) collection expression.
            return(result);
        }
Пример #12
0
                protected DbSkipExpression RebindSkip(DbExpression input, DbSkipExpression skip, DbExpression k)
                {
                    DbExpressionBinding inputBinding = input.BindAs(skip.Input.VariableName);

                    return(inputBinding.Skip(skip.SortOrder, k));
                }
Пример #13
0
                protected DbSkipExpression ApplySortOrderToSkip(DbExpression input, DbSortExpression sort, DbExpression k)
                {
                    DbExpressionBinding inputBinding = input.BindAs(sort.Input.VariableName);

                    return(inputBinding.Skip(sort.SortOrder, k));
                }
Пример #14
0
                protected DbSortExpression ApplySkipOrderToSort(DbExpression input, DbSkipExpression sortSpec)
                {
                    DbExpressionBinding inputBinding = input.BindAs(sortSpec.Input.VariableName);

                    return(inputBinding.Sort(sortSpec.SortOrder));
                }
Пример #15
0
                protected DbSortExpression RebindSort(DbExpression input, DbSortExpression sort)
                {
                    DbExpressionBinding inputBinding = input.BindAs(sort.Input.VariableName);

                    return(inputBinding.Sort(sort.SortOrder));
                }
Пример #16
0
 protected DbFilterExpression RebindFilter(DbExpression input, DbFilterExpression filter)
 {
     DbExpressionBinding inputBinding = input.BindAs(filter.Input.VariableName);
     return inputBinding.Filter(filter.Predicate);
 }
Пример #17
0
                protected DbProjectExpression RebindProject(DbExpression input, DbProjectExpression project)
                {
                    DbExpressionBinding inputBinding = input.BindAs(project.Input.VariableName);

                    return(inputBinding.Project(project.Projection));
                }
Пример #18
0
        // Utility translator method for lambda expressions. Given a lambda expression and its translated
        // inputs, translates the lambda expression, assuming the input is a collection
        private DbExpression TranslateLambda(
            LambdaExpression lambda, DbExpression input, string bindingName, out DbExpressionBinding binding)
        {
            input = NormalizeSetSource(input);

            // create binding context for this lambda expression
            binding = input.BindAs(bindingName);

            return TranslateLambda(lambda, binding.Variable);
        }
Пример #19
0
 protected DbSkipExpression RebindSkip(DbExpression input, DbSkipExpression skip, DbExpression k)
 {
     DbExpressionBinding inputBinding = input.BindAs(skip.Input.VariableName);
     return inputBinding.Skip(skip.SortOrder, k);
 }
Пример #20
0
        private DbExpression GenerateStructuralTypeResultMappingView(DbExpression storeFunctionInvoke, IList <EdmSchemaError> errors, out DiscriminatorMap discriminatorMap)
        {
            Debug.Assert(m_structuralTypeMappings != null && m_structuralTypeMappings.Count > 0, "m_structuralTypeMappings != null && m_structuralTypeMappings.Count > 0");

            discriminatorMap = null;

            // Process explicit structural type mappings. The mapping is based on the direct call of the store function
            // wrapped into a projection constructing the mapped structural types.

            DbExpression queryExpression = storeFunctionInvoke;

            if (m_structuralTypeMappings.Count == 1)
            {
                var mapping = m_structuralTypeMappings[0];

                var type             = mapping.Item1;
                var conditions       = mapping.Item2;
                var propertyMappings = mapping.Item3;

                if (conditions.Count > 0)
                {
                    queryExpression = queryExpression.Where((row) => GenerateStructuralTypeConditionsPredicate(conditions, row));
                }

                var binding = queryExpression.BindAs("row");
                var entityTypeMappingView = GenerateStructuralTypeMappingView(type, propertyMappings, binding.Variable, errors);
                if (entityTypeMappingView == null)
                {
                    return(null);
                }

                queryExpression = binding.Project(entityTypeMappingView);
            }
            else
            {
                var binding = queryExpression.BindAs("row");

                // Make sure type projection is performed over a closed set where each row is guaranteed to produce a known type.
                // To do this, filter the store function output using the type conditions.
                Debug.Assert(m_structuralTypeMappings.All(m => m.Item2.Count > 0), "In multi-type mapping each type must have conditions.");
                List <DbExpression> structuralTypePredicates = m_structuralTypeMappings.Select(m => GenerateStructuralTypeConditionsPredicate(m.Item2, binding.Variable)).ToList();
                queryExpression = binding.Filter(Helpers.BuildBalancedTreeInPlace(
                                                     structuralTypePredicates.ToArray(), // clone, otherwise BuildBalancedTreeInPlace will change it
                                                     (prev, next) => prev.Or(next)));
                binding = queryExpression.BindAs("row");

                List <DbExpression> structuralTypeMappingViews = new List <DbExpression>(m_structuralTypeMappings.Count);
                foreach (var mapping in m_structuralTypeMappings)
                {
                    var type             = mapping.Item1;
                    var propertyMappings = mapping.Item3;

                    var structuralTypeMappingView = GenerateStructuralTypeMappingView(type, propertyMappings, binding.Variable, errors);
                    if (structuralTypeMappingView == null)
                    {
                        continue;
                    }
                    else
                    {
                        structuralTypeMappingViews.Add(structuralTypeMappingView);
                    }
                }
                Debug.Assert(structuralTypeMappingViews.Count == structuralTypePredicates.Count, "structuralTypeMappingViews.Count == structuralTypePredicates.Count");
                if (structuralTypeMappingViews.Count != m_structuralTypeMappings.Count)
                {
                    Debug.Assert(errors.Count > 0, "errors.Count > 0");
                    return(null);
                }

                // Because we are projecting over the closed set, we can convert the last WHEN THEN into ELSE.
                DbExpression typeConstructors = DbExpressionBuilder.Case(
                    structuralTypePredicates.Take(m_structuralTypeMappings.Count - 1),
                    structuralTypeMappingViews.Take(m_structuralTypeMappings.Count - 1),
                    structuralTypeMappingViews[m_structuralTypeMappings.Count - 1]);

                queryExpression = binding.Project(typeConstructors);

                if (DiscriminatorMap.TryCreateDiscriminatorMap(this.FunctionImport.EntitySet, queryExpression, out discriminatorMap))
                {
                    Debug.Assert(discriminatorMap != null, "discriminatorMap == null after it has been created");
                }
            }

            return(queryExpression);
        }
Пример #21
0
 protected DbSortExpression ApplySkipOrderToSort(DbExpression input, DbSkipExpression sortSpec)
 {
     DbExpressionBinding inputBinding = input.BindAs(sortSpec.Input.VariableName);
     return inputBinding.Sort(sortSpec.SortOrder);
 }
Пример #22
0
 protected DbSortExpression RebindSort(DbExpression input, DbSortExpression sort)
 {
     DbExpressionBinding inputBinding = input.BindAs(sort.Input.VariableName);
     return inputBinding.Sort(sort.SortOrder);
 }
Пример #23
0
                protected DbFilterExpression RebindFilter(DbExpression input, DbFilterExpression filter)
                {
                    DbExpressionBinding inputBinding = input.BindAs(filter.Input.VariableName);

                    return(inputBinding.Filter(filter.Predicate));
                }
Пример #24
0
 protected DbSkipExpression ApplySortOrderToSkip(DbExpression input, DbSortExpression sort, DbExpression k)
 {
     DbExpressionBinding inputBinding = input.BindAs(sort.Input.VariableName);
     return inputBinding.Skip(sort.SortOrder, k);
 }
Пример #25
0
 protected DbProjectExpression RebindProject(DbExpression input, DbProjectExpression project)
 {
     DbExpressionBinding inputBinding = input.BindAs(project.Input.VariableName);
     return inputBinding.Project(project.Projection);
 }