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); }
/// <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); }
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); }
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); }
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); }
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); } }
// 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); }
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); }
protected DbSkipExpression RebindSkip(DbExpression input, DbSkipExpression skip, DbExpression k) { DbExpressionBinding inputBinding = input.BindAs(skip.Input.VariableName); return(inputBinding.Skip(skip.SortOrder, k)); }
protected DbSkipExpression ApplySortOrderToSkip(DbExpression input, DbSortExpression sort, DbExpression k) { DbExpressionBinding inputBinding = input.BindAs(sort.Input.VariableName); return(inputBinding.Skip(sort.SortOrder, k)); }
protected DbSortExpression ApplySkipOrderToSort(DbExpression input, DbSkipExpression sortSpec) { DbExpressionBinding inputBinding = input.BindAs(sortSpec.Input.VariableName); return(inputBinding.Sort(sortSpec.SortOrder)); }
protected DbSortExpression RebindSort(DbExpression input, DbSortExpression sort) { DbExpressionBinding inputBinding = input.BindAs(sort.Input.VariableName); return(inputBinding.Sort(sort.SortOrder)); }
protected DbFilterExpression RebindFilter(DbExpression input, DbFilterExpression filter) { DbExpressionBinding inputBinding = input.BindAs(filter.Input.VariableName); return inputBinding.Filter(filter.Predicate); }
protected DbProjectExpression RebindProject(DbExpression input, DbProjectExpression project) { DbExpressionBinding inputBinding = input.BindAs(project.Input.VariableName); return(inputBinding.Project(project.Projection)); }
// 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); }
protected DbSkipExpression RebindSkip(DbExpression input, DbSkipExpression skip, DbExpression k) { DbExpressionBinding inputBinding = input.BindAs(skip.Input.VariableName); return inputBinding.Skip(skip.SortOrder, k); }
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); }
protected DbSortExpression ApplySkipOrderToSort(DbExpression input, DbSkipExpression sortSpec) { DbExpressionBinding inputBinding = input.BindAs(sortSpec.Input.VariableName); return inputBinding.Sort(sortSpec.SortOrder); }
protected DbSortExpression RebindSort(DbExpression input, DbSortExpression sort) { DbExpressionBinding inputBinding = input.BindAs(sort.Input.VariableName); return inputBinding.Sort(sort.SortOrder); }
protected DbFilterExpression RebindFilter(DbExpression input, DbFilterExpression filter) { DbExpressionBinding inputBinding = input.BindAs(filter.Input.VariableName); return(inputBinding.Filter(filter.Predicate)); }
protected DbSkipExpression ApplySortOrderToSkip(DbExpression input, DbSortExpression sort, DbExpression k) { DbExpressionBinding inputBinding = input.BindAs(sort.Input.VariableName); return inputBinding.Skip(sort.SortOrder, k); }
protected DbProjectExpression RebindProject(DbExpression input, DbProjectExpression project) { DbExpressionBinding inputBinding = input.BindAs(project.Input.VariableName); return inputBinding.Project(project.Projection); }