示例#1
0
        internal override DbExpression AsCqt(DbExpression row, MemberPath outputMember)
        {
            DbExpression cqt = null;

            AsCql(
                // createRef action
                (refScopeEntitySet, keyMemberOutputPaths) =>
            {
                // Construct a scoped reference: CreateRef(CPerson1Set, NewRow(pid1, pid2), CPerson1)
                EntityType refEntityType = (EntityType)(((RefType)outputMember.EdmType).ElementType);
                cqt = refScopeEntitySet.CreateRef(
                    refEntityType,
                    keyMemberOutputPaths.Select(km => row.Property(km.CqlFieldAlias)));
            },
                // createType action
                (membersOutputPaths) =>
            {
                // Construct an entity/complex/Association type in the Members order for fields: CPerson(CPerson1_Pid, CPerson1_Name)
                cqt = TypeUsage.Create(m_edmType).New(
                    membersOutputPaths.Select(m => row.Property(m.CqlFieldAlias)));
            },
                outputMember);

            return(cqt);
        }
示例#2
0
            internal DbExpression FindInput(DbExpression row)
            {
                DbExpression instance = row;

                for (int index = this.m_parentQualifiers.Count - 1; index >= this.m_indexInParentQualifiers; --index)
                {
                    instance = (DbExpression)instance.Property(this.m_parentQualifiers[index]);
                }
                return((DbExpression)instance.Property(this.m_leafQualifier));
            }
示例#3
0
            internal DbExpression FindInput(DbExpression row)
            {
                DbExpression cqt = row;

                for (int i = m_parentQualifiers.Count - 1; i >= m_indexInParentQualifiers; --i)
                {
                    cqt = cqt.Property(m_parentQualifiers[i]);
                }
                return(cqt.Property(m_leafQualifier));
            }
 internal override ObjectSpanRewriter.SpanTrackingInfo CreateEntitySpanTrackingInfo(
     DbExpression expression,
     EntityType entityType)
 {
     ObjectSpanRewriter.SpanTrackingInfo spanTrackingInfo = new ObjectSpanRewriter.SpanTrackingInfo();
     ObjectFullSpanRewriter.SpanPathInfo spanPathInfo     = this._currentSpanPath.Peek();
     if (spanPathInfo.Children != null)
     {
         int index = 1;
         foreach (KeyValuePair <NavigationProperty, ObjectFullSpanRewriter.SpanPathInfo> child in spanPathInfo.Children)
         {
             if (spanTrackingInfo.ColumnDefinitions == null)
             {
                 spanTrackingInfo = this.InitializeTrackingInfo(this.RelationshipSpan);
             }
             DbExpression expression1 = (DbExpression)expression.Property(child.Key);
             this._currentSpanPath.Push(child.Value);
             DbExpression dbExpression = this.Rewrite(expression1);
             this._currentSpanPath.Pop();
             spanTrackingInfo.ColumnDefinitions.Add(new KeyValuePair <string, DbExpression>(spanTrackingInfo.ColumnNames.Next(), dbExpression));
             AssociationEndMember propertyTargetEnd = this.GetNavigationPropertyTargetEnd(child.Key);
             spanTrackingInfo.SpannedColumns[index] = propertyTargetEnd;
             if (this.RelationshipSpan)
             {
                 spanTrackingInfo.FullSpannedEnds[propertyTargetEnd] = true;
             }
             ++index;
         }
     }
     return(spanTrackingInfo);
 }
        private static DbExpression GenerateColumnRef(DbExpression row, EdmProperty column)
        {
            Debug.Assert(row.ResultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.RowType, "Input type is expected to be a row type.");
            var rowType = (RowType)row.ResultType.EdmType;

            Debug.Assert(rowType.Properties.Contains(column.Name), "Column name must be resolvable in the TVF result type.");
            return(row.Property(column.Name));
        }
示例#6
0
        internal override SpanTrackingInfo CreateEntitySpanTrackingInfo(DbExpression expression, EntityType entityType)
        {
            var tracking = new SpanTrackingInfo();

            var currentInfo = _currentSpanPath.Peek();

            if (currentInfo.Children != null)
            {
                // The current SpanPathInfo instance on the top of the span path stack indicates
                // which navigation properties should be retrieved from this Entity-typed expression
                // and also specifies (in the form of child SpanPathInfo instances) which sub-paths
                // must be expanded for each of those navigation properties.
                // The SpanPathInfo instance may be the root instance or a SpanPathInfo that represents a sub-path.
                var idx = 1; // SpanRoot is always the first (zeroth) column, full- and relationship-span columns follow.
                foreach (var nextInfo in currentInfo.Children)
                {
                    // If the tracking information was not initialized yet, do so now.
                    if (null == tracking.ColumnDefinitions)
                    {
                        tracking = InitializeTrackingInfo(RelationshipSpan);
                    }

                    // Create a property expression that retrieves the specified navigation property from the Entity-typed expression.
                    // Note that the expression is cloned since it may be used as the instance of multiple property expressions.
                    DbExpression columnDef = expression.Property(nextInfo.Key);

                    // Rewrite the result of the navigation property. This is required for two reasons:
                    // 1. To continue spanning the current Include path.
                    // 2. To apply relationship span to the Entity or EntityCollection produced by the navigation property, if necessary.
                    //    Consider an Include path of "Order" for a query that returns OrderLines - the Include'd Orders should have
                    //    their associated Customer relationship spanned.
                    // Note that this will recursively call this method with the Entity type of the result of the
                    // navigation property, which will in turn call loop through the sub-paths of this navigation
                    // property and adjust the stack to track which Include path is being expanded and which
                    // element of that path is considered 'current'.
                    _currentSpanPath.Push(nextInfo.Value);
                    columnDef = Rewrite(columnDef);
                    _currentSpanPath.Pop();

                    // Add a new column to the tracked columns using the rewritten column definition
                    tracking.ColumnDefinitions.Add(new KeyValuePair <string, DbExpression>(tracking.ColumnNames.Next(), columnDef));
                    var targetEnd = GetNavigationPropertyTargetEnd(nextInfo.Key);
                    tracking.SpannedColumns[idx] = targetEnd;

                    // If full span and relationship span are both required, a relationship span may be rendered
                    // redundant by an already added full span. Therefore the association ends that have been expanded
                    // as part of full span are tracked using a dictionary.
                    if (RelationshipSpan)
                    {
                        tracking.FullSpannedEnds[targetEnd] = true;
                    }

                    idx++;
                }
            }

            return(tracking);
        }
示例#7
0
        // <summary>
        // Rebuild the current scope entry expression as the property chain off the <paramref name="parentVarRef" /> expression.
        // Also build
        // - <see cref="IGroupExpressionExtendedInfo.GroupVarBasedExpression" /> off the <paramref name="parentGroupVarRef" /> expression;
        // - <see cref="IGroupExpressionExtendedInfo.GroupAggBasedExpression" /> off the <paramref name="groupAggRef" /> expression.
        // This adjustment is reversable by <see cref="RollbackAdjustmentToGroupVar" />(...).
        // </summary>
        internal void AdjustToGroupVar(
            DbVariableReferenceExpression parentVarRef, DbVariableReferenceExpression parentGroupVarRef,
            DbVariableReferenceExpression groupAggRef)
        {
            // Adjustment is not reentrant.
            Debug.Assert(_groupVarBasedExpression == null, "_groupVarBasedExpression == null");
            Debug.Assert(_groupAggBasedExpression == null, "_groupAggBasedExpression == null");

            //
            // Let's assume this entry represents variable "x" in the following query:
            //      select x, y, z from {1, 2} as x join {2, 3} as y on x = y join {3, 4} as z on y = z
            // In this case _propRefs contains x._##join0._##join1 and the corresponding input expression looks like this:
            //     |_Input : '_##join1'
            //     | |_InnerJoin
            //     |   |_Left : '_##join0'
            //     |   | |_InnerJoin
            //     |   |   |_Left : 'x'
            //     |   |   |_Right : 'y'
            //     |   |_Right : 'z'
            // When we start processing a group by, like in this query:
            //      select k1, k2, k3 from {1, 2} as x join {2, 3} as y on x = y join {3, 4} as z on y = z group by x as k1, y as k2, z as k3
            // we are switching to the following input expression:
            //     |_Input : '_##geb2', '_##group3'
            //     | |_InnerJoin
            //     |   |_Left : '_##join0'
            //     |   | |_InnerJoin
            //     |   |   |_Left : 'x'
            //     |   |   |_Right : 'y'
            //     |   |_Right : 'z'
            // where _##join1 is replaced by _##geb2 for the regular expression and by _##group3 for the group var based expression.
            // So the switch, or the adjustment, is done by
            //      a. replacing _##join1 with _##geb2 in _propRefs and rebuilding the regular expression accordingly to get
            //         the following property chain: _##geb2._##join1.x
            //      b. building a group var based expression using _##group3 instead of _##geb2 to get
            //         the following property chain: _##group3._##join1.x
            //

            //
            // Rebuild ScopeEntry.Expression using the new parent var.
            //
            ReplaceParentVar(parentVarRef);

            //
            // Build the GroupVarBasedExpression and GroupAggBasedExpression,
            // take into account that parentVarRef has already been added to the _propRefs in the AdjustToParentVar(...) call, so ignore it.
            //
            _groupVarBasedExpression = parentGroupVarRef;
            _groupAggBasedExpression = groupAggRef;
            if (_propRefs != null)
            {
                for (var i = _propRefs.Count - 2 /*ignore the parentVarRef*/; i >= 0; --i)
                {
                    _groupVarBasedExpression = _groupVarBasedExpression.Property(_propRefs[i]);
                    _groupAggBasedExpression = _groupAggBasedExpression.Property(_propRefs[i]);
                }
            }
        }
 private void FlattenProperties(
     DbExpression input,
     IList <DbPropertyExpression> flattenedProperties)
 {
     foreach (EdmProperty property in input.ResultType.GetProperties())
     {
         DbPropertyExpression propertyExpression = input.Property(property);
         if (BuiltInTypeKind.PrimitiveType == property.TypeUsage.EdmType.BuiltInTypeKind)
         {
             flattenedProperties.Add(propertyExpression);
         }
         else
         {
             this.FlattenProperties((DbExpression)propertyExpression, flattenedProperties);
         }
     }
 }
示例#9
0
        /// <summary>
        /// Adds the flattened properties on the input to the flattenedProperties list.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="flattenedProperties"></param>
        private void FlattenProperties(DbExpression input, IList <DbPropertyExpression> flattenedProperties)
        {
            IList <EdmProperty> properties = TypeHelpers.GetProperties(input.ResultType);

            Debug.Assert(properties.Count != 0, "No nested properties when FlattenProperties called?");

            for (int i = 0; i < properties.Count; i++)
            {
                DbExpression propertyInput = input;

                DbPropertyExpression propertyExpression = propertyInput.Property(properties[i]);
                if (TypeSemantics.IsPrimitiveType(properties[i].TypeUsage))
                {
                    flattenedProperties.Add(propertyExpression);
                }
                else
                {
                    Debug.Assert(TypeSemantics.IsEntityType(properties[i].TypeUsage) || TypeSemantics.IsRowType(properties[i].TypeUsage),
                                 "The input to FlattenProperties is not of EntityType or RowType?");

                    FlattenProperties(propertyExpression, flattenedProperties);
                }
            }
        }
示例#10
0
        // <summary>
        // Prepend <paramref name="parentVarRef" /> to the property chain.
        // </summary>
        internal SourceScopeEntry AddParentVar(DbVariableReferenceExpression parentVarRef)
        {
            //
            // No parent var adjustment is allowed while adjusted to group var (see AdjustToGroupVar(...) for more info).
            //
            Debug.Assert(_groupVarBasedExpression == null, "_groupVarBasedExpression == null");
            Debug.Assert(_groupAggBasedExpression == null, "_groupAggBasedExpression == null");

            if (_propRefs == null)
            {
                Debug.Assert(_varBasedExpression is DbVariableReferenceExpression, "_varBasedExpression is DbVariableReferenceExpression");
                _propRefs = new List <string>(2);
                _propRefs.Add(((DbVariableReferenceExpression)_varBasedExpression).VariableName);
            }

            _varBasedExpression = parentVarRef;
            for (var i = _propRefs.Count - 1; i >= 0; --i)
            {
                _varBasedExpression = _varBasedExpression.Property(_propRefs[i]);
            }
            _propRefs.Add(parentVarRef.VariableName);

            return(this);
        }
示例#11
0
        /// <summary>
        ///     Prepend <paramref name="parentVarRef" /> to the property chain.
        /// </summary>
        internal SourceScopeEntry AddParentVar(DbVariableReferenceExpression parentVarRef)
        {
            //
            // No parent var adjustment is allowed while adjusted to group var (see AdjustToGroupVar(...) for more info).
            //
            Debug.Assert(_groupVarBasedExpression == null, "_groupVarBasedExpression == null");
            Debug.Assert(_groupAggBasedExpression == null, "_groupAggBasedExpression == null");

            if (_propRefs == null)
            {
                Debug.Assert(_varBasedExpression is DbVariableReferenceExpression, "_varBasedExpression is DbVariableReferenceExpression");
                _propRefs = new List<string>(2);
                _propRefs.Add(((DbVariableReferenceExpression)_varBasedExpression).VariableName);
            }

            _varBasedExpression = parentVarRef;
            for (var i = _propRefs.Count - 1; i >= 0; --i)
            {
                _varBasedExpression = _varBasedExpression.Property(_propRefs[i]);
            }
            _propRefs.Add(parentVarRef.VariableName);

            return this;
        }
 internal override DbExpression AsCqt(DbExpression row, bool skipIsNotNull)
 {
     // Get e.g., row._from1
     return(row.Property(SlotName));
 }
示例#13
0
 internal DbRelatedEntityRef AsCqt(DbExpression row)
 {
     return(DbExpressionBuilder.CreateRelatedEntityRef(this.m_fromEnd, this.m_toEnd, (DbExpression)this.m_toEndEntitySet.CreateRef(this.m_toEndEntityType, (IEnumerable <DbExpression>) this.m_toEndEntityKeyMemberPaths.Select <MemberPath, DbPropertyExpression>((Func <MemberPath, DbPropertyExpression>)(keyMember => row.Property(keyMember.CqlFieldAlias))))));
 }
 internal DbExpression AsCqt(DbExpression row)
 {
     this.AsCql((Action <string>)(memberName => row = (DbExpression)row.Property(memberName)), (Action)(() => row = (DbExpression)row.GetRefKey()), (Action <StructuralType>)(treatAsType => row = (DbExpression)row.TreatAs(TypeUsage.Create((EdmType)treatAsType))));
     return(row);
 }
示例#15
0
        private DbExpression RecursivelyRewriteEqualsExpression(DbExpression left, DbExpression right, EqualsPattern pattern)
        {
            // check if either side is an initializer type
            RowType leftType = left.ResultType.EdmType as RowType;
            RowType rightType = left.ResultType.EdmType as RowType;

            if (null != leftType || null != rightType)
            {
                if ((null != leftType && null != rightType) && leftType.EdmEquals(rightType))
                {
                    DbExpression shreddedEquals = null;
                    // if the types are the same, use struct equivalence semantics
                    foreach (EdmProperty property in leftType.Properties)
                    {
                        DbPropertyExpression leftElement = left.Property(property);
                        DbPropertyExpression rightElement = right.Property(property);
                        DbExpression elementsEquals = RecursivelyRewriteEqualsExpression(
                            leftElement, rightElement, pattern);

                        // build up and expression
                        if (null == shreddedEquals) { shreddedEquals = elementsEquals; }
                        else { shreddedEquals = shreddedEquals.And(elementsEquals); }
                    }
                    return shreddedEquals;
                }
                else
                {
                    // if one or both sides is an initializer and the types are not the same,
                    // "equals" always evaluates to false
                    return DbExpressionBuilder.False;
                }
            }
            else
            {
                return ImplementEquality(left, right, pattern);
            }
        }
示例#16
0
        internal override DbExpression AsCqt(DbExpression row, MemberPath outputMember)
        {
            DbExpression cqt = null;

            AsCql(
                // createRef action
                (refScopeEntitySet, keyMemberOutputPaths) =>
                {
                    // Construct a scoped reference: CreateRef(CPerson1Set, NewRow(pid1, pid2), CPerson1)
                    EntityType refEntityType = (EntityType)(((RefType)outputMember.EdmType).ElementType);
                    cqt = refScopeEntitySet.CreateRef(
                        refEntityType,
                        keyMemberOutputPaths.Select(km => row.Property(km.CqlFieldAlias)));
                },
                // createType action
                (membersOutputPaths) =>
                {
                    // Construct an entity/complex/Association type in the Members order for fields: CPerson(CPerson1_Pid, CPerson1_Name)
                    cqt = TypeUsage.Create(m_edmType).New(
                        membersOutputPaths.Select(m => row.Property(m.CqlFieldAlias)));
                },
                outputMember);

            return cqt;
        }
示例#17
0
        /// <summary>
        ///     Rebuild the current scope entry expression as the property chain off the <paramref name="parentVarRef" /> expression.
        ///     Also build 
        ///     - <see cref="IGroupExpressionExtendedInfo.GroupVarBasedExpression" /> off the <paramref name="parentGroupVarRef" /> expression;
        ///     - <see cref="IGroupExpressionExtendedInfo.GroupAggBasedExpression" /> off the <paramref name="groupAggRef" /> expression.
        ///     This adjustment is reversable by <see cref="RollbackAdjustmentToGroupVar" />(...).
        /// </summary>
        internal void AdjustToGroupVar(
            DbVariableReferenceExpression parentVarRef, DbVariableReferenceExpression parentGroupVarRef,
            DbVariableReferenceExpression groupAggRef)
        {
            // Adjustment is not reentrant.
            Debug.Assert(_groupVarBasedExpression == null, "_groupVarBasedExpression == null");
            Debug.Assert(_groupAggBasedExpression == null, "_groupAggBasedExpression == null");

            //
            // Let's assume this entry represents variable "x" in the following query:
            //      select x, y, z from {1, 2} as x join {2, 3} as y on x = y join {3, 4} as z on y = z
            // In this case _propRefs contains x._##join0._##join1 and the corresponding input expression looks like this:
            //     |_Input : '_##join1'
            //     | |_InnerJoin
            //     |   |_Left : '_##join0'
            //     |   | |_InnerJoin
            //     |   |   |_Left : 'x'
            //     |   |   |_Right : 'y'
            //     |   |_Right : 'z'
            // When we start processing a group by, like in this query:
            //      select k1, k2, k3 from {1, 2} as x join {2, 3} as y on x = y join {3, 4} as z on y = z group by x as k1, y as k2, z as k3
            // we are switching to the following input expression:
            //     |_Input : '_##geb2', '_##group3'
            //     | |_InnerJoin
            //     |   |_Left : '_##join0'
            //     |   | |_InnerJoin
            //     |   |   |_Left : 'x'
            //     |   |   |_Right : 'y'
            //     |   |_Right : 'z'
            // where _##join1 is replaced by _##geb2 for the regular expression and by _##group3 for the group var based expression.
            // So the switch, or the adjustment, is done by 
            //      a. replacing _##join1 with _##geb2 in _propRefs and rebuilding the regular expression accordingly to get
            //         the following property chain: _##geb2._##join1.x
            //      b. building a group var based expression using _##group3 instead of _##geb2 to get
            //         the following property chain: _##group3._##join1.x
            //

            //
            // Rebuild ScopeEntry.Expression using the new parent var.
            //
            ReplaceParentVar(parentVarRef);

            //
            // Build the GroupVarBasedExpression and GroupAggBasedExpression, 
            // take into account that parentVarRef has already been added to the _propRefs in the AdjustToParentVar(...) call, so ignore it.
            //
            _groupVarBasedExpression = parentGroupVarRef;
            _groupAggBasedExpression = groupAggRef;
            if (_propRefs != null)
            {
                for (var i = _propRefs.Count - 2 /*ignore the parentVarRef*/; i >= 0; --i)
                {
                    _groupVarBasedExpression = _groupVarBasedExpression.Property(_propRefs[i]);
                    _groupAggBasedExpression = _groupAggBasedExpression.Property(_propRefs[i]);
                }
            }
        }
 internal override DbExpression AsCqt(DbExpression row, bool skipIsNotNull)
 {
     return((DbExpression)row.Property(this.SlotName));
 }
示例#19
0
        private DbExpression RewriteRow(DbExpression expression, RowType rowType)
        {
            DbLambdaExpression lambdaExpression = expression as DbLambdaExpression;
            DbNewInstanceExpression newRow;

            if (lambdaExpression != null)
            {
                // NOTE: We rely on the fact that today span cannot be done over queries containing DbLambdaExpressions
                // created by users, because user-created expressions cannot be used for querying in O-space.
                // If that were to change, pushing span beyond a LambdaExpression could cause variable name 
                // collisions between the variable names used in the Lambda and the names generated by the
                // RelationshipNavigationVisitor.           
                newRow = lambdaExpression.Lambda.Body as DbNewInstanceExpression;
            }
            else
            {
                newRow = expression as DbNewInstanceExpression;
            }

            Dictionary<int, DbExpression> unmodifiedColumns = null;
            Dictionary<int, DbExpression> spannedColumns = null;
            for(int idx = 0; idx < rowType.Properties.Count; idx++)
            {
                // Retrieve the property that represents the current column
                EdmProperty columnProp = rowType.Properties[idx];

                // Construct an expression that defines the current column.
                DbExpression columnExpr = null;
                if(newRow != null)
                {
                    // For a row-constructing NewInstance expression, the corresponding argument can simply be used
                    columnExpr = newRow.Arguments[idx];
                }
                else
                {
                    // For all other expressions the property corresponding to the column name must be retrieved
                    // from the row-typed expression
                    columnExpr = expression.Property(columnProp.Name);
                }

                DbExpression spannedColumn = this.Rewrite(columnExpr);
                if (!object.ReferenceEquals(spannedColumn, columnExpr))
                {
                    // If so, then update the dictionary of column index to span information
                    if (null == spannedColumns)
                    {
                        spannedColumns = new Dictionary<int, DbExpression>();
                    }

                    spannedColumns[idx] = spannedColumn;
                }
                else
                {
                    // Otherwise, update the dictionary of column index to unmodified expression
                    if(null == unmodifiedColumns)
                    {
                        unmodifiedColumns = new Dictionary<int, DbExpression>();
                    }

                    unmodifiedColumns[idx] = columnExpr;
                }
            }
            
            // A new expression need only be built if at least one column was spanned
            if(null == spannedColumns)
            {
                // No columns were spanned, indicate that the original expression should remain.
                return expression;
            }
            else
            {
                // At least one column was spanned, so build a new row constructor that defines the new row, including spanned columns.
                List<DbExpression> columnArguments = new List<DbExpression>(rowType.Properties.Count);
                List<EdmProperty> properties = new List<EdmProperty>(rowType.Properties.Count);
                for (int idx = 0; idx < rowType.Properties.Count; idx++)
                {
                    EdmProperty columnProp = rowType.Properties[idx];
                    DbExpression columnDef = null;
                    if (!spannedColumns.TryGetValue(idx, out columnDef))
                    {
                        columnDef = unmodifiedColumns[idx];
                    }
                    columnArguments.Add(columnDef);
                    properties.Add(new EdmProperty(columnProp.Name, columnDef.ResultType));
                }

                // Copy over any eLinq initializer metadata (if present, or null if not).
                // Note that this initializer metadata does not strictly match the new row type
                // that includes spanned columns, but will be correct once the object materializer
                // has interpreted the query results to produce the correct value for each colum.
                RowType rewrittenRow = new RowType(properties, rowType.InitializerMetadata);
                TypeUsage rewrittenRowTypeUsage = TypeUsage.Create(rewrittenRow);
                DbExpression rewritten = rewrittenRowTypeUsage.New(columnArguments);
                
                // SQLBUDT #554182: If we insert a new projection we should should make sure to 
                // not interfere with the nullability of the input. 
                // In particular, if the input row is null and we construct a new row as a projection over its columns
                // we would get a row consisting of nulls, instead of a null row. 
                // Thus, given an input X, we rewritte it as:  if (X is null) then NULL else rewritten.
                if (newRow == null)
                {
                    DbExpression condition = DbExpressionBuilder.CreateIsNullExpressionAllowingRowTypeArgument(expression);
                    DbExpression nullExpression = DbExpressionBuilder.Null(rewrittenRowTypeUsage);
                    rewritten = DbExpressionBuilder.Case(
                        new List<DbExpression>(new DbExpression[] { condition }),
                        new List<DbExpression>(new DbExpression[] { nullExpression }),
                        rewritten);
                }
                
                // Add an entry to the spanned row type => original row type map for the new row type.
                AddSpannedRowType(rewrittenRow, expression.ResultType);
                
                if (lambdaExpression != null && newRow != null)
                {
                    rewritten = DbLambda.Create(rewritten, lambdaExpression.Lambda.Variables).Invoke(lambdaExpression.Arguments);
                }

                return rewritten;
            }
        }
示例#20
0
        internal override DbExpression AsCqt(DbExpression row, MemberPath outputMember)
        {
            DbExpression cqt = (DbExpression)null;

            this.AsCql((Action <EntitySet, IList <MemberPath> >)((refScopeEntitySet, keyMemberOutputPaths) =>
            {
                EntityType elementType = (EntityType)((RefType)outputMember.EdmType).ElementType;
                cqt = (DbExpression)refScopeEntitySet.CreateRef(elementType, (IEnumerable <DbExpression>)keyMemberOutputPaths.Select <MemberPath, DbPropertyExpression>((Func <MemberPath, DbPropertyExpression>)(km => row.Property(km.CqlFieldAlias))));
            }), (Action <IList <MemberPath> >)(membersOutputPaths => cqt = (DbExpression)TypeUsage.Create(this.m_edmType).New((IEnumerable <DbExpression>)membersOutputPaths.Select <MemberPath, DbPropertyExpression>((Func <MemberPath, DbPropertyExpression>)(m => row.Property(m.CqlFieldAlias))))), outputMember);
            return(cqt);
        }
示例#21
0
        // effects: unwraps any "structured" set sources such as IGrouping instances
        // (which acts as both a set and a structure containing a property)
        private DbExpression NormalizeSetSource(DbExpression input)
        {
            DebugCheck.NotNull(input);

            // If input looks like "select x from (...) as x", rewrite it as "(...)".
            // If input has span information attached to to it then leave it as is, otherwise 
            // span info will be lost.
            Span span;
            if (input.ExpressionKind == DbExpressionKind.Project
                && !TryGetSpan(input, out span))
            {
                var project = (DbProjectExpression)input;
                if (project.Projection
                    == project.Input.Variable)
                {
                    input = project.Input.Expression;
                }
            }

            // determine if the lambda input is an IGrouping or EntityCollection that needs to be unwrapped
            InitializerMetadata initializerMetadata;
            if (InitializerMetadata.TryGetInitializerMetadata(input.ResultType, out initializerMetadata))
            {
                if (initializerMetadata.Kind
                    == InitializerMetadataKind.Grouping)
                {
                    // for group by, redirect the binding to the group (rather than the property)
                    input = input.Property(GroupColumnName);
                }
                else if (initializerMetadata.Kind
                         == InitializerMetadataKind.EntityCollection)
                {
                    // for entity collection, redirect the binding to the children
                    input = input.Property(EntityCollectionElementsColumnName);
                }
            }
            return input;
        }
示例#22
0
 internal DbRelatedEntityRef AsCqt(DbExpression row)
 {
     return DbExpressionBuilder.CreateRelatedEntityRef(
         m_fromEnd,
         m_toEnd,
         m_toEndEntitySet.CreateRef(
             m_toEndEntityType, m_toEndEntityKeyMemberPaths.Select(keyMember => row.Property(keyMember.CqlFieldAlias))));
 }
示例#23
0
 internal DbRelatedEntityRef AsCqt(DbExpression row)
 {
     return(DbExpressionBuilder.CreateRelatedEntityRef(
                m_fromEnd,
                m_toEnd,
                m_toEndEntitySet.CreateRef(
                    m_toEndEntityType, m_toEndEntityKeyMemberPaths.Select(keyMember => row.Property(keyMember.CqlFieldAlias)))));
 }
 private DbExpression GenerateColumnRef(DbExpression row, EdmProperty column)
 {
     Debug.Assert(row.ResultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.RowType, "Input type is expected to be a row type.");
     var rowType = (RowType)row.ResultType.EdmType;
     Debug.Assert(rowType.Properties.Contains(column.Name), "Column name must be resolvable in the TVF result type.");
     return row.Property(column.Name);
 }
        internal override SpanTrackingInfo CreateEntitySpanTrackingInfo(DbExpression expression, EntityType entityType)
        {
            var tracking = new SpanTrackingInfo();

            var currentInfo = _currentSpanPath.Peek();
            if (currentInfo.Children != null)
            {
                // The current SpanPathInfo instance on the top of the span path stack indicates
                // which navigation properties should be retrieved from this Entity-typed expression
                // and also specifies (in the form of child SpanPathInfo instances) which sub-paths
                // must be expanded for each of those navigation properties.
                // The SpanPathInfo instance may be the root instance or a SpanPathInfo that represents a sub-path.
                var idx = 1; // SpanRoot is always the first (zeroth) column, full- and relationship-span columns follow.
                foreach (var nextInfo in currentInfo.Children)
                {
                    // If the tracking information was not initialized yet, do so now.
                    if (null == tracking.ColumnDefinitions)
                    {
                        tracking = InitializeTrackingInfo(RelationshipSpan);
                    }

                    // Create a property expression that retrieves the specified navigation property from the Entity-typed expression.
                    // Note that the expression is cloned since it may be used as the instance of multiple property expressions.
                    DbExpression columnDef = expression.Property(nextInfo.Key);

                    // Rewrite the result of the navigation property. This is required for two reasons:
                    // 1. To continue spanning the current Include path.
                    // 2. To apply relationship span to the Entity or EntityCollection produced by the navigation property, if necessary.
                    //    Consider an Include path of "Order" for a query that returns OrderLines - the Include'd Orders should have
                    //    their associated Customer relationship spanned.
                    // Note that this will recursively call this method with the Entity type of the result of the
                    // navigation property, which will in turn call loop through the sub-paths of this navigation
                    // property and adjust the stack to track which Include path is being expanded and which 
                    // element of that path is considered 'current'.
                    _currentSpanPath.Push(nextInfo.Value);
                    columnDef = Rewrite(columnDef);
                    _currentSpanPath.Pop();

                    // Add a new column to the tracked columns using the rewritten column definition
                    tracking.ColumnDefinitions.Add(new KeyValuePair<string, DbExpression>(tracking.ColumnNames.Next(), columnDef));
                    var targetEnd = GetNavigationPropertyTargetEnd(nextInfo.Key);
                    tracking.SpannedColumns[idx] = targetEnd;

                    // If full span and relationship span are both required, a relationship span may be rendered
                    // redundant by an already added full span. Therefore the association ends that have been expanded
                    // as part of full span are tracked using a dictionary.
                    if (RelationshipSpan)
                    {
                        tracking.FullSpannedEnds[targetEnd] = true;
                    }

                    idx++;
                }
            }

            return tracking;
        }
        private DbExpression RewriteRow(DbExpression expression, RowType rowType)
        {
            DbLambdaExpression             lambdaExpression   = expression as DbLambdaExpression;
            DbNewInstanceExpression        instanceExpression = lambdaExpression == null ? expression as DbNewInstanceExpression : lambdaExpression.Lambda.Body as DbNewInstanceExpression;
            Dictionary <int, DbExpression> dictionary1        = (Dictionary <int, DbExpression>)null;
            Dictionary <int, DbExpression> dictionary2        = (Dictionary <int, DbExpression>)null;

            for (int index = 0; index < rowType.Properties.Count; ++index)
            {
                EdmProperty  property     = rowType.Properties[index];
                DbExpression expression1  = instanceExpression == null ? (DbExpression)expression.Property(property.Name) : instanceExpression.Arguments[index];
                DbExpression dbExpression = this.Rewrite(expression1);
                if (!object.ReferenceEquals((object)dbExpression, (object)expression1))
                {
                    if (dictionary2 == null)
                    {
                        dictionary2 = new Dictionary <int, DbExpression>();
                    }
                    dictionary2[index] = dbExpression;
                }
                else
                {
                    if (dictionary1 == null)
                    {
                        dictionary1 = new Dictionary <int, DbExpression>();
                    }
                    dictionary1[index] = expression1;
                }
            }
            if (dictionary2 == null)
            {
                return(expression);
            }
            List <DbExpression> dbExpressionList = new List <DbExpression>(rowType.Properties.Count);
            List <EdmProperty>  edmPropertyList  = new List <EdmProperty>(rowType.Properties.Count);

            for (int key = 0; key < rowType.Properties.Count; ++key)
            {
                EdmProperty  property     = rowType.Properties[key];
                DbExpression dbExpression = (DbExpression)null;
                if (!dictionary2.TryGetValue(key, out dbExpression))
                {
                    dbExpression = dictionary1[key];
                }
                dbExpressionList.Add(dbExpression);
                edmPropertyList.Add(new EdmProperty(property.Name, dbExpression.ResultType));
            }
            RowType      spannedType   = new RowType((IEnumerable <EdmProperty>)edmPropertyList, rowType.InitializerMetadata);
            TypeUsage    typeUsage     = TypeUsage.Create((EdmType)spannedType);
            DbExpression dbExpression1 = (DbExpression)typeUsage.New((IEnumerable <DbExpression>)dbExpressionList);

            if (instanceExpression == null)
            {
                dbExpression1 = (DbExpression)DbExpressionBuilder.Case((IEnumerable <DbExpression>) new List <DbExpression>((IEnumerable <DbExpression>) new DbExpression[1]
                {
                    (DbExpression)expression.IsNull()
                }), (IEnumerable <DbExpression>) new List <DbExpression>((IEnumerable <DbExpression>) new DbExpression[1]
                {
                    (DbExpression)typeUsage.Null()
                }), dbExpression1);
            }
            this.AddSpannedRowType(spannedType, expression.ResultType);
            if (lambdaExpression != null && instanceExpression != null)
            {
                dbExpression1 = (DbExpression)DbLambda.Create(dbExpression1, (IEnumerable <DbVariableReferenceExpression>)lambdaExpression.Lambda.Variables).Invoke((IEnumerable <DbExpression>)lambdaExpression.Arguments);
            }
            return(dbExpression1);
        }
示例#27
0
        private DbExpression RewriteRow(DbExpression expression, RowType rowType)
        {
            DbLambdaExpression      lambdaExpression = expression as DbLambdaExpression;
            DbNewInstanceExpression newRow;

            if (lambdaExpression != null)
            {
                // NOTE: We rely on the fact that today span cannot be done over queries containing DbLambdaExpressions
                // created by users, because user-created expressions cannot be used for querying in O-space.
                // If that were to change, pushing span beyond a LambdaExpression could cause variable name
                // collisions between the variable names used in the Lambda and the names generated by the
                // RelationshipNavigationVisitor.
                newRow = lambdaExpression.Lambda.Body as DbNewInstanceExpression;
            }
            else
            {
                newRow = expression as DbNewInstanceExpression;
            }

            Dictionary <int, DbExpression> unmodifiedColumns = null;
            Dictionary <int, DbExpression> spannedColumns    = null;

            for (int idx = 0; idx < rowType.Properties.Count; idx++)
            {
                // Retrieve the property that represents the current column
                EdmProperty columnProp = rowType.Properties[idx];

                // Construct an expression that defines the current column.
                DbExpression columnExpr = null;
                if (newRow != null)
                {
                    // For a row-constructing NewInstance expression, the corresponding argument can simply be used
                    columnExpr = newRow.Arguments[idx];
                }
                else
                {
                    // For all other expressions the property corresponding to the column name must be retrieved
                    // from the row-typed expression
                    columnExpr = expression.Property(columnProp.Name);
                }

                DbExpression spannedColumn = this.Rewrite(columnExpr);
                if (!object.ReferenceEquals(spannedColumn, columnExpr))
                {
                    // If so, then update the dictionary of column index to span information
                    if (null == spannedColumns)
                    {
                        spannedColumns = new Dictionary <int, DbExpression>();
                    }

                    spannedColumns[idx] = spannedColumn;
                }
                else
                {
                    // Otherwise, update the dictionary of column index to unmodified expression
                    if (null == unmodifiedColumns)
                    {
                        unmodifiedColumns = new Dictionary <int, DbExpression>();
                    }

                    unmodifiedColumns[idx] = columnExpr;
                }
            }

            // A new expression need only be built if at least one column was spanned
            if (null == spannedColumns)
            {
                // No columns were spanned, indicate that the original expression should remain.
                return(expression);
            }
            else
            {
                // At least one column was spanned, so build a new row constructor that defines the new row, including spanned columns.
                List <DbExpression> columnArguments = new List <DbExpression>(rowType.Properties.Count);
                List <EdmProperty>  properties      = new List <EdmProperty>(rowType.Properties.Count);
                for (int idx = 0; idx < rowType.Properties.Count; idx++)
                {
                    EdmProperty  columnProp = rowType.Properties[idx];
                    DbExpression columnDef  = null;
                    if (!spannedColumns.TryGetValue(idx, out columnDef))
                    {
                        columnDef = unmodifiedColumns[idx];
                    }
                    columnArguments.Add(columnDef);
                    properties.Add(new EdmProperty(columnProp.Name, columnDef.ResultType));
                }

                // Copy over any eLinq initializer metadata (if present, or null if not).
                // Note that this initializer metadata does not strictly match the new row type
                // that includes spanned columns, but will be correct once the object materializer
                // has interpreted the query results to produce the correct value for each colum.
                RowType      rewrittenRow          = new RowType(properties, rowType.InitializerMetadata);
                TypeUsage    rewrittenRowTypeUsage = TypeUsage.Create(rewrittenRow);
                DbExpression rewritten             = rewrittenRowTypeUsage.New(columnArguments);

                // SQLBUDT #554182: If we insert a new projection we should should make sure to
                // not interfere with the nullability of the input.
                // In particular, if the input row is null and we construct a new row as a projection over its columns
                // we would get a row consisting of nulls, instead of a null row.
                // Thus, given an input X, we rewritte it as:  if (X is null) then NULL else rewritten.
                if (newRow == null)
                {
                    DbExpression condition      = DbExpressionBuilder.CreateIsNullExpressionAllowingRowTypeArgument(expression);
                    DbExpression nullExpression = DbExpressionBuilder.Null(rewrittenRowTypeUsage);
                    rewritten = DbExpressionBuilder.Case(
                        new List <DbExpression>(new DbExpression[] { condition }),
                        new List <DbExpression>(new DbExpression[] { nullExpression }),
                        rewritten);
                }

                // Add an entry to the spanned row type => original row type map for the new row type.
                AddSpannedRowType(rewrittenRow, expression.ResultType);

                if (lambdaExpression != null && newRow != null)
                {
                    rewritten = DbLambda.Create(rewritten, lambdaExpression.Lambda.Variables).Invoke(lambdaExpression.Arguments);
                }

                return(rewritten);
            }
        }
示例#28
0
        private DbExpression RecursivelyRewriteEqualsExpression(DbExpression left, DbExpression right, EqualsPattern pattern)
        {
            // check if either side is an initializer type
            var leftType = left.ResultType.EdmType as RowType;
            var rightType = right.ResultType.EdmType as RowType;

            if (null != leftType
                || null != rightType)
            {
                if (null != leftType && null != rightType)
                {
                    DbExpression shreddedEquals = null;
                    // if the types are the same, use struct equivalence semantics
                    foreach (var property in leftType.Properties)
                    {
                        var leftElement = left.Property(property);
                        var rightElement = right.Property(property);
                        var elementsEquals = RecursivelyRewriteEqualsExpression(
                            leftElement, rightElement, pattern);

                        // build up and expression
                        if (null == shreddedEquals)
                        {
                            shreddedEquals = elementsEquals;
                        }
                        else
                        {
                            shreddedEquals = shreddedEquals.And(elementsEquals);
                        }
                    }
                    return shreddedEquals;
                }
                else
                {
                    // if one or both sides is an initializer and the types are not the same,
                    // "equals" always evaluates to false
                    return DbExpressionBuilder.False;
                }
            }
            else
            {
                return
                    _funcletizer.RootContext.ContextOptions.UseCSharpNullComparisonBehavior
                        ? ImplementEquality(left, right, EqualsPattern.Store)
                        : ImplementEquality(left, right, pattern);
            }
        }
示例#29
0
 internal override DbExpression AsCqt(DbExpression row, bool skipIsNotNull)
 {
     // Get e.g., row._from1
     return row.Property(SlotName);
 }
示例#30
0
        private static DbExpression GenerateColumnRef(DbExpression row, EdmProperty column)
        {
            RowType edmType = (RowType)row.ResultType.EdmType;

            return((DbExpression)row.Property(column.Name));
        }