Example #1
0
        /// <summary>
        /// Obtains a collection of resource properties that are needed for skip token generation
        /// </summary>
        /// <param name="orderingInfo">Input orderingInfo.</param>
        /// <param name="rt">Resource type for which to collect the skip token properties</param>
        /// <returns>Collection of resource properties used in $skiptoken</returns>
        internal static ICollection <ResourceProperty> CollectSkipTokenProperties(OrderingInfo orderingInfo, ResourceType rt)
        {
            Debug.Assert(orderingInfo != null, "Must have valid ordering information to collect skip token properties");
            Debug.Assert(orderingInfo.IsPaged, "Must have paging enabled to collection skip token properties");

            List <ResourceProperty> resourceProperties = new List <ResourceProperty>();

            foreach (OrderingExpression o in orderingInfo.OrderingExpressions)
            {
                LambdaExpression     l       = (LambdaExpression)o.Expression;
                NeedSkipTokenVisitor visitor = new NeedSkipTokenVisitor(rt);
                visitor.Visit(l.Body);
                if (visitor.NeedSkipToken)
                {
                    return(null);
                }
                else
                {
                    Debug.Assert(visitor.Property != null, "Must have a valid property if skip token is not needed");
                    resourceProperties.Add(visitor.Property);
                }
            }

            return(resourceProperties);
        }
Example #2
0
        /// <summary>Sorts a query like a SQL ORDER BY clause does.</summary>
        /// <param name="source">Original source for query.</param>
        /// <param name="orderingInfo">Ordering definition to compose.</param>
        /// <returns>The composed query.</returns>
        internal static Expression OrderBy(Expression source, OrderingInfo orderingInfo)
        {
            Debug.Assert(source != null, "source != null");
            Debug.Assert(orderingInfo != null, "orderingInfo != null");

            Expression queryExpr  = source;
            bool       useOrderBy = true;

            foreach (OrderingExpression o in orderingInfo.OrderingExpressions)
            {
                LambdaExpression selectorLambda = (LambdaExpression)o.Expression;

                Type selectorType = selectorLambda.Body.Type;
                Debug.Assert(selectorType != null, "type != null");

                // ensure either the expression type is orderable (ie, primitive) or its an open expression.
                if (!WebUtil.IsPrimitiveType(selectorType) && !OpenTypeMethods.IsOpenExpression(selectorLambda.Body))
                {
                    throw DataServiceException.CreateBadRequestError(Strings.RequestQueryParser_OrderByDoesNotSupportType(WebUtil.GetTypeName(selectorType)));
                }

                if (useOrderBy)
                {
                    queryExpr = o.IsAscending ? queryExpr.QueryableOrderBy(selectorLambda) : queryExpr.QueryableOrderByDescending(selectorLambda);
                }
                else
                {
                    queryExpr = o.IsAscending ? queryExpr.QueryableThenBy(selectorLambda) : queryExpr.QueryableThenByDescending(selectorLambda);
                }

                useOrderBy = false;
            }

            return(queryExpr);
        }
Example #3
0
        private void UpdateOrderingInfoWithSkipTokenWrapper(Type resultWrapperType)
        {
            OrderingInfo        info       = new OrderingInfo(true);
            ParameterExpression expression = Expression.Parameter(resultWrapperType, "w");

            foreach (OrderingExpression expression2 in this.topLevelOrderingInfo.OrderingExpressions)
            {
                LambdaExpression expression3 = (LambdaExpression)expression2.Expression;
                Expression       body        = ParameterReplacerVisitor.Replace(expression3.Body, expression3.Parameters[0], Expression.MakeMemberAccess(expression, resultWrapperType.GetProperty("ExpandedElement")));
                info.Add(new OrderingExpression(Expression.Lambda(body, new ParameterExpression[] { expression }), expression2.IsAscending));
            }
            this.topLevelOrderingInfo = info;
        }
 /// <summary>Initializes a new <see cref="ExpandSegment"/> instance.</summary>
 /// <param name="name">Segment name.</param>
 /// <param name="filter">Filter expression for segment, possibly null.</param>
 /// <param name="maxResultsExpected">
 /// Expand providers may choose to return at most MaxResultsExpected + 1 elements to allow the
 /// data service to detect a failure to meet this constraint.
 /// </param>
 /// <param name="container">Container to which the segment belongs; possibly null.</param>
 /// <param name="expandedProperty">Property expanded by this expand segment</param>
 /// <param name="orderingInfo">Collection of ordering information for this segment, used for paging</param>
 internal ExpandSegment(
     string name,
     Expression filter,
     int maxResultsExpected,
     ResourceSetWrapper container,
     ResourceProperty expandedProperty,
     OrderingInfo orderingInfo)
 {
     WebUtil.CheckArgumentNull(name, "name");
     CheckFilterType(filter);
     this.name               = name;
     this.filter             = filter;
     this.container          = container;
     this.maxResultsExpected = maxResultsExpected;
     this.expandedProperty   = expandedProperty;
     this.orderingInfo       = orderingInfo;
 }
 internal static bool IsSkipTokenRequired(OrderingInfo orderingInfo)
 {
     if ((orderingInfo != null) && orderingInfo.IsPaged)
     {
         foreach (OrderingExpression expression in orderingInfo.OrderingExpressions)
         {
             LambdaExpression     expression2 = (LambdaExpression)expression.Expression;
             NeedSkipTokenVisitor visitor     = new NeedSkipTokenVisitor();
             visitor.Visit(expression2.Body);
             if (visitor.NeedSkipToken)
             {
                 return(true);
             }
         }
     }
     return(false);
 }
        internal static ICollection <ResourceProperty> CollectSkipTokenProperties(OrderingInfo orderingInfo, ResourceType rt)
        {
            List <ResourceProperty> list = new List <ResourceProperty>();

            foreach (OrderingExpression expression in orderingInfo.OrderingExpressions)
            {
                LambdaExpression     expression2 = (LambdaExpression)expression.Expression;
                NeedSkipTokenVisitor visitor     = new NeedSkipTokenVisitor(rt);
                visitor.Visit(expression2.Body);
                if (visitor.NeedSkipToken)
                {
                    return(null);
                }
                list.Add(visitor.Property);
            }
            return(list);
        }
Example #7
0
 private RequestQueryProcessor(IDataService service, RequestDescription description)
 {
     this.service               = service;
     this.description           = description;
     this.orderApplied          = false;
     this.skipCount             = null;
     this.topCount              = null;
     this.queryExpression       = description.RequestExpression;
     this.filterQueryApplicable = (((description.TargetKind == RequestTargetKind.Resource) || (description.TargetKind == RequestTargetKind.OpenProperty)) || (description.TargetKind == RequestTargetKind.ComplexObject)) || (description.CountOption == RequestQueryCountOption.ValueOnly);
     this.setQueryApplicable    = ((description.TargetKind == RequestTargetKind.Resource) && !description.IsSingleResult) || (description.CountOption == RequestQueryCountOption.ValueOnly);
     this.pagingApplicable      = (((description.TargetKind == RequestTargetKind.Resource) && !description.IsSingleResult) && ((description.CountOption != RequestQueryCountOption.ValueOnly) && !description.IsRequestForEnumServiceOperation)) && ((service.OperationContext.Host.HttpVerb == HttpVerbs.GET) || (description.SegmentInfos[0].TargetSource == RequestTargetSource.ServiceOperation));
     this.appliedCustomPaging   = false;
     this.expandPaths           = null;
     this.expandPathsAsText     = null;
     this.rootProjectionNode    = null;
     this.orderingParser        = null;
     this.topLevelOrderingInfo  = null;
 }
Example #8
0
        /// <summary>Makes the expression that is used as a filter corresponding to skip token.</summary>
        /// <param name="topLevelOrderingInfo">Ordering expression.</param>
        /// <param name="skipToken">The provided skip token.</param>
        /// <param name="parameterType">The parameter type of the lambda.</param>
        /// <returns>LambdaExpression corresponding to the skip token filter.</returns>
        internal LambdaExpression BuildSkipTokenFilter(OrderingInfo topLevelOrderingInfo, IList <object> skipToken, Type parameterType)
        {
            ParameterExpression element       = Expression.Parameter(parameterType, "element");
            Expression          lastCondition = Expression.Constant(true, typeof(bool));
            Expression          lastMatch     = Expression.Constant(false, typeof(bool));

            foreach (var v in WebUtil.Zip(topLevelOrderingInfo.OrderingExpressions, skipToken, (x, y) => new { Order = x, Value = y }))
            {
                BinaryOperatorKind comparisonExp = v.Order.IsAscending ? BinaryOperatorKind.GreaterThan : BinaryOperatorKind.LessThan;

                Expression fixedLambda = ParameterReplacerVisitor.Replace(
                    ((LambdaExpression)v.Order.Expression).Body,
                    ((LambdaExpression)v.Order.Expression).Parameters[0],
                    element);

                // TODO: this will be an EnumNode if $skiptoken contains enum constant.
                ConstantNode node;
                var          lexer   = new ExpressionLexer((string)v.Value);
                bool         success = TokenToQueryNodeTranslator.TryCreateLiteral(lexer.CurrentToken, out node);
                Debug.Assert(success, "Was not a literal");

                node = this.EnsureCorrectTypeAndPrecisionForLFDM(node, fixedLambda.Type);
                Expression right      = this.nodeToExpressionTranslator.TranslateNode(node);
                Expression comparison = ExpressionGenerator.GenerateLogicalAnd(
                    lastCondition,
                    this.GenerateNullAwareComparison(fixedLambda, right, comparisonExp));

                lastMatch = ExpressionGenerator.GenerateLogicalOr(lastMatch, comparison);

                lastCondition = ExpressionGenerator.GenerateLogicalAnd(
                    lastCondition,
                    this.GenerateComparisonExpression(fixedLambda, right, BinaryOperatorKind.Equal));
            }

            lastMatch = ExpressionUtils.EnsurePredicateExpressionIsBoolean(lastMatch);

            Debug.Assert(lastMatch.Type == typeof(bool), "Skip token should generate boolean expression.");

            return(Expression.Lambda(lastMatch, element));
        }
Example #9
0
        private void ObtainOrderingExpressions()
        {
            StringBuilder builder = new StringBuilder(this.service.OperationContext.Host.GetQueryStringItem("$orderby"));

            if (builder.Length > 0)
            {
                this.CheckSetQueryApplicable();
            }
            ResourceType targetResourceType = this.description.TargetResourceType;

            this.topLevelOrderingInfo = new OrderingInfo(this.IsStandardPaged);
            if ((this.IsStandardPaged || this.topCount.HasValue) || this.skipCount.HasValue)
            {
                string str = (builder.Length > 0) ? "," : string.Empty;
                foreach (ResourceProperty property in this.description.TargetResourceSet.GetKeyPropertiesForOrderBy())
                {
                    builder.Append(str).Append(property.Name).Append(' ').Append("asc");
                    str = ",";
                }
            }
            string str2 = builder.ToString();

            if (!string.IsNullOrEmpty(str2))
            {
                ParameterExpression parameterForIt = Expression.Parameter(targetResourceType.InstanceType, "element");
                this.orderingParser = new RequestQueryParser.ExpressionParser(this.service, this.description, parameterForIt, str2);
                foreach (OrderingExpression expression2 in this.orderingParser.ParseOrdering())
                {
                    this.topLevelOrderingInfo.Add(new OrderingExpression(Expression.Lambda(expression2.Expression, new ParameterExpression[] { parameterForIt }), expression2.IsAscending));
                }
                if (this.IsStandardPaged)
                {
                    this.description.SkipTokenExpressionCount = this.topLevelOrderingInfo.OrderingExpressions.Count;
                    this.description.SkipTokenProperties      = NeedSkipTokenVisitor.CollectSkipTokenProperties(this.topLevelOrderingInfo, targetResourceType);
                }
            }
        }
Example #10
0
        private ExpandSegmentCollection CheckSingleExpandPath(List <string> path)
        {
            ResourceType            targetResourceType = this.description.TargetResourceType;
            ResourceSetWrapper      targetContainer    = this.description.LastSegmentInfo.TargetContainer;
            ExpandSegmentCollection segments           = new ExpandSegmentCollection(path.Count);
            bool flag = false;
            bool previousSegmentIsTypeSegment = false;

            for (int i = 0; i < path.Count; i++)
            {
                string propertyName                     = path[i];
                ResourcePropertyKind stream             = ResourcePropertyKind.Stream;
                ResourceProperty     navigationProperty = targetResourceType.TryResolvePropertyName(propertyName, stream);
                if (navigationProperty == null)
                {
                    ResourceType type2 = WebUtil.ResolveTypeIdentifier(this.service.Provider, propertyName, targetResourceType, previousSegmentIsTypeSegment);
                    if (type2 == null)
                    {
                        if (targetResourceType.IsOpenType)
                        {
                            throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.OpenNavigationPropertiesNotSupportedOnOpenTypes(propertyName));
                        }
                        throw DataServiceException.CreateSyntaxError(System.Data.Services.Strings.RequestUriProcessor_PropertyNotFound(targetResourceType.FullName, propertyName));
                    }
                    this.description.VerifyProtocolVersion(RequestDescription.Version3Dot0, this.service);
                    targetResourceType           = type2;
                    previousSegmentIsTypeSegment = true;
                }
                else
                {
                    previousSegmentIsTypeSegment = false;
                    if (navigationProperty.TypeKind == ResourceTypeKind.EntityType)
                    {
                        targetContainer = this.service.Provider.GetContainer(targetContainer, targetResourceType, navigationProperty);
                        if (targetContainer == null)
                        {
                            throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.BadRequest_InvalidPropertyNameSpecified(navigationProperty.Name, targetResourceType.FullName));
                        }
                        bool singleResult = navigationProperty.Kind == ResourcePropertyKind.ResourceReference;
                        DataServiceConfiguration.CheckResourceRightsForRead(targetContainer, singleResult);
                        Expression filter = DataServiceConfiguration.ComposeQueryInterceptors(this.service, targetContainer);
                        if (((targetContainer.PageSize != 0) && !singleResult) && !this.IsCustomPaged)
                        {
                            OrderingInfo        orderingInfo = new OrderingInfo(true);
                            ParameterExpression expression   = Expression.Parameter(targetContainer.ResourceType.InstanceType, "p");
                            foreach (ResourceProperty property2 in targetContainer.GetKeyPropertiesForOrderBy())
                            {
                                Expression expression3;
                                if (property2.CanReflectOnInstanceTypeProperty)
                                {
                                    expression3 = Expression.Property(expression, targetContainer.ResourceType.GetPropertyInfo(property2));
                                }
                                else
                                {
                                    expression3 = Expression.Convert(Expression.Call(null, DataServiceProviderMethods.GetValueMethodInfo, expression, Expression.Constant(property2)), property2.Type);
                                }
                                orderingInfo.Add(new OrderingExpression(Expression.Lambda(expression3, new ParameterExpression[] { expression }), true));
                            }
                            segments.Add(new ExpandSegment(navigationProperty.Name, filter, targetContainer.PageSize, targetContainer, targetResourceType, navigationProperty, orderingInfo));
                            this.description.VerifyProtocolVersion(RequestDescription.Version2Dot0, this.service);
                            this.description.VerifyAndRaiseResponseVersion(RequestDescription.Version2Dot0, this.service);
                        }
                        else
                        {
                            if (!singleResult && this.IsCustomPaged)
                            {
                                this.CheckAndApplyCustomPaging(null);
                            }
                            segments.Add(new ExpandSegment(navigationProperty.Name, filter, this.service.Configuration.MaxResultsPerCollection, targetContainer, targetResourceType, navigationProperty, null));
                        }
                        this.description.UpdateAndCheckEpmFeatureVersion(targetContainer, this.service);
                        this.description.UpdateVersions(this.service.OperationContext.Host.RequestAccept, targetContainer, this.service);
                        flag = false;
                        targetResourceType = navigationProperty.ResourceType;
                    }
                    else
                    {
                        flag = true;
                    }
                }
            }
            if (previousSegmentIsTypeSegment)
            {
                throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.RequestQueryProcessor_QueryParametersPathCannotEndInTypeIdentifier("$expand", targetResourceType.FullName));
            }
            if (!flag)
            {
                return(segments);
            }
            return(null);
        }