/// <summary>Sorts a query like a SQL ORDER BY clause does.</summary>
        /// <param name="service">Service with data and configuration.</param>
        /// <param name="source">Original source for query.</param>
        /// <param name="orderingInfo">Ordering definition to compose.</param>
        /// <returns>The composed query.</returns>
        internal static IQueryable OrderBy(IDataService service, IQueryable source, OrderingInfo orderingInfo)
        {
            Debug.Assert(service != null, "service != null");
            Debug.Assert(source != null, "source != null");
            Debug.Assert(orderingInfo != null, "orderingInfo != null");

            Expression queryExpr = source.Expression;
            string methodAsc = "OrderBy";
            string methodDesc = "OrderByDescending";
            foreach (OrderingExpression o in orderingInfo.OrderingExpressions)
            {
                LambdaExpression selectorLambda = (LambdaExpression)o.Expression;
                Type selectorType = selectorLambda.Body.Type;
                service.Provider.CheckIfOrderedType(selectorType);

                queryExpr = Expression.Call(
                    typeof(Queryable),
                    o.IsAscending ? methodAsc : methodDesc,
                    new Type[] { source.ElementType, selectorType },
                    queryExpr,
                    Expression.Quote(selectorLambda));

                methodAsc = "ThenBy";
                methodDesc = "ThenByDescending";
            }

            return source.Provider.CreateQuery(queryExpr);
        }
Esempio n. 2
0
 internal ExpandSegment(string name, Expression filter, int maxResultsExpected, ResourceSetWrapper container, ResourceType targetResourceType, ResourceProperty expandedProperty, System.Data.Services.Providers.OrderingInfo orderingInfo)
 {
     WebUtil.CheckArgumentNull <string>(name, "name");
     CheckFilterType(filter);
     this.name               = name;
     this.filter             = filter;
     this.container          = container;
     this.maxResultsExpected = maxResultsExpected;
     this.expandedProperty   = expandedProperty;
     this.orderingInfo       = orderingInfo;
     this.targetResourceType = targetResourceType;
 }
Esempio n. 3
0
 internal ExpandSegment(string name, Expression filter, int maxResultsExpected, ResourceSetWrapper container, ResourceType targetResourceType, ResourceProperty expandedProperty, System.Data.Services.Providers.OrderingInfo orderingInfo)
 {
     WebUtil.CheckArgumentNull<string>(name, "name");
     CheckFilterType(filter);
     this.name = name;
     this.filter = filter;
     this.container = container;
     this.maxResultsExpected = maxResultsExpected;
     this.expandedProperty = expandedProperty;
     this.orderingInfo = orderingInfo;
     this.targetResourceType = targetResourceType;
 }
Esempio n. 4
0
 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;
 }
Esempio n. 5
0
 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;
 }
Esempio n. 6
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;
 }
Esempio n. 7
0
        /// <summary>Creates new instance of node representing expanded navigation property.</summary>
        /// <param name="propertyName">The name of the property to project and expand.</param>
        /// <param name="property">The <see cref="ResourceProperty"/> for this property. Can only be null for the root node.</param>
        /// <param name="resourceSetWrapper">The resource set to which the expansion leads.</param>
        /// <param name="orderingInfo">The ordering info for this node. null means no ordering to be applied.</param>
        /// <param name="filter">The filter for this node. null means no filter to be applied.</param>
        /// <param name="skipCount">Number of results to skip. null means no results to be skipped.</param>
        /// <param name="takeCount">Maximum number of results to return. null means return all available results.</param>
        /// <param name="maxResultsExpected">Maximum number of expected results. Hint that the provider should return
        /// at least maxResultsExpected + 1 results (if available).</param>
        internal ExpandedProjectionNode(
            string propertyName,
            ResourceProperty property,
            ResourceSetWrapper resourceSetWrapper,
            OrderingInfo orderingInfo,
            Expression filter,
            int?skipCount,
            int?takeCount,
            int?maxResultsExpected)
            : base(propertyName, property)
        {
            Debug.Assert(resourceSetWrapper != null, "resourceSetWrapper != null");
            Debug.Assert(property != null || propertyName.Length == 0, "We don't support open navigation properties.");

            this.resourceSetWrapper = resourceSetWrapper;
            this.orderingInfo       = orderingInfo;
            this.filter             = filter;
            this.skipCount          = skipCount;
            this.takeCount          = takeCount;
            this.maxResultsExpected = maxResultsExpected;
            this.nodes = new List <ProjectionNode>();
        }
        /// <summary>Creates new root node for the projection tree.</summary>
        /// <param name="resourceSetWrapper">The resource set of the root level of the query.</param>
        /// <param name="orderingInfo">The ordering info for this node. null means no ordering to be applied.</param>
        /// <param name="filter">The filter for this node. null means no filter to be applied.</param>
        /// <param name="skipCount">Number of results to skip. null means no results to be skipped.</param>
        /// <param name="takeCount">Maximum number of results to return. null means return all available results.</param>
        /// <param name="maxResultsExpected">Maximum number of expected results. Hint that the provider should return
        /// at least maxResultsExpected + 1 results (if available).</param>
        /// <param name="expandPaths">The list of expanded paths.</param>
        /// <param name="baseResourceType">The resource type for all entities in this query.</param>
        internal RootProjectionNode(
            ResourceSetWrapper resourceSetWrapper,
            OrderingInfo orderingInfo,
            Expression filter,
            int? skipCount,
            int? takeCount,
            int? maxResultsExpected,
            List<ExpandSegmentCollection> expandPaths,
            ResourceType baseResourceType)
            : base(
                String.Empty,
                null,
                resourceSetWrapper,
                orderingInfo,
                filter,
                skipCount,
                takeCount,
                maxResultsExpected)
        {
            Debug.Assert(baseResourceType != null, "baseResourceType != null");

            this.expandPaths = expandPaths;
            this.baseResourceType = baseResourceType;
        }
Esempio n. 9
0
        /// <summary>Creates new root node for the projection tree.</summary>
        /// <param name="resourceSetWrapper">The resource set of the root level of the query.</param>
        /// <param name="orderingInfo">The ordering info for this node. null means no ordering to be applied.</param>
        /// <param name="filter">The filter for this node. null means no filter to be applied.</param>
        /// <param name="skipCount">Number of results to skip. null means no results to be skipped.</param>
        /// <param name="takeCount">Maximum number of results to return. null means return all available results.</param>
        /// <param name="maxResultsExpected">Maximum number of expected results. Hint that the provider should return
        /// at least maxResultsExpected + 1 results (if available).</param>
        /// <param name="expandPaths">The list of expanded paths.</param>
        /// <param name="baseResourceType">The resource type for all entities in this query.</param>
        internal RootProjectionNode(
            ResourceSetWrapper resourceSetWrapper,
            OrderingInfo orderingInfo,
            Expression filter,
            int?skipCount,
            int?takeCount,
            int?maxResultsExpected,
            List <ExpandSegmentCollection> expandPaths,
            ResourceType baseResourceType)
            : base(
                String.Empty,
                null,
                resourceSetWrapper,
                orderingInfo,
                filter,
                skipCount,
                takeCount,
                maxResultsExpected)
        {
            Debug.Assert(baseResourceType != null, "baseResourceType != null");

            this.expandPaths      = expandPaths;
            this.baseResourceType = baseResourceType;
        }
Esempio n. 10
0
 internal RootProjectionNode(ResourceSetWrapper resourceSetWrapper, OrderingInfo orderingInfo, Expression filter, int? skipCount, int? takeCount, int? maxResultsExpected, List<ExpandSegmentCollection> expandPaths, System.Data.Services.Providers.ResourceType baseResourceType) : base(string.Empty, null, null, resourceSetWrapper, orderingInfo, filter, skipCount, takeCount, maxResultsExpected)
 {
     this.expandPaths = expandPaths;
     this.baseResourceType = baseResourceType;
 }
        /// <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;
        }
            /// <summary>Makes the expression that is used as a filter corresponding to skip token.</summary>
            /// <param name="topLevelOrderingInfo">Ordering expression.</param>
            /// <param name="k">The provided skip token.</param>
            /// <returns>LambdaExpression corresponding to the skip token filter.</returns>
            internal LambdaExpression BuildSkipTokenFilter(OrderingInfo topLevelOrderingInfo, KeyInstance k)
            {
                ParameterExpression element = Expression.Parameter(this.typeForIt.InstanceType, "element");
                Expression lastCondition = Expression.Constant(true, typeof(bool));
                Expression lastMatch = Expression.Constant(false, typeof(bool));

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

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

                    Expression comparison = GenerateLogicalAnd(
                                                lastCondition,
                                                this.GenerateNullAwareComparison(fixedLambda, (String)v.Value, comparisonExp));

                    lastMatch = GenerateLogicalOr(lastMatch, comparison);

                    lastCondition = GenerateLogicalAnd(
                                        lastCondition,
                                        this.GenerateComparison(fixedLambda, (String)v.Value, Token.EqualsTo));
                }

                lastMatch = PrepareExpressionForWhere(lastMatch);

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

                return Expression.Lambda(lastMatch, element);
            }
Esempio n. 13
0
        /// <summary>Creates new instance of node representing expanded navigation property.</summary>
        /// <param name="propertyName">The name of the property to project and expand.</param>
        /// <param name="property">The <see cref="ResourceProperty"/> for this property. Can only be null for the root node.</param>
        /// <param name="resourceSetWrapper">The resource set to which the expansion leads.</param>
        /// <param name="orderingInfo">The ordering info for this node. null means no ordering to be applied.</param>
        /// <param name="filter">The filter for this node. null means no filter to be applied.</param>
        /// <param name="skipCount">Number of results to skip. null means no results to be skipped.</param>
        /// <param name="takeCount">Maximum number of results to return. null means return all available results.</param>
        /// <param name="maxResultsExpected">Maximum number of expected results. Hint that the provider should return
        /// at least maxResultsExpected + 1 results (if available).</param>
        internal ExpandedProjectionNode(
            string propertyName,
            ResourceProperty property,
            ResourceSetWrapper resourceSetWrapper,
            OrderingInfo orderingInfo,
            Expression filter,
            int? skipCount,
            int? takeCount,
            int? maxResultsExpected)
            : base(propertyName, property)
        {
            Debug.Assert(resourceSetWrapper != null, "resourceSetWrapper != null");
            Debug.Assert(property != null || propertyName.Length == 0, "We don't support open navigation properties.");

            this.resourceSetWrapper = resourceSetWrapper;
            this.orderingInfo = orderingInfo;
            this.filter = filter;
            this.skipCount = skipCount;
            this.takeCount = takeCount;
            this.maxResultsExpected = maxResultsExpected;
            this.nodes = new List<ProjectionNode>();
        }
Esempio n. 14
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;
 }
Esempio n. 15
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);
         }
     }
 }
Esempio n. 16
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;
        }
 /// <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;
 }
Esempio n. 18
0
 internal RootProjectionNode(ResourceSetWrapper resourceSetWrapper, OrderingInfo orderingInfo, Expression filter, int?skipCount, int?takeCount, int?maxResultsExpected, List <ExpandSegmentCollection> expandPaths, System.Data.Services.Providers.ResourceType baseResourceType) : base(string.Empty, null, null, resourceSetWrapper, orderingInfo, filter, skipCount, takeCount, maxResultsExpected)
 {
     this.expandPaths      = expandPaths;
     this.baseResourceType = baseResourceType;
 }