public DefaultDocumentQueryExecutionContext(
     DocumentQueryExecutionContextBase.InitParams constructorParams,
     bool isContinuationExpected)
     : base(constructorParams)
 {
     this.isContinuationExpected = isContinuationExpected;
     this.fetchSchedulingMetrics = new SchedulingStopwatch();
     this.fetchSchedulingMetrics.Ready();
     this.fetchExecutionRangeAccumulator = new FetchExecutionRangeAccumulator();
     this.providedRangesCache            = new Dictionary <string, IReadOnlyList <Range <string> > >();
     this.retries = -1;
     this.partitionRoutingHelper = new PartitionRoutingHelper();
 }
        public async Task <DocumentFeedResponse <CosmosElement> > ExecuteNextFeedResponseAsync(CancellationToken token)
        {
            if (this.IsDone)
            {
                throw new InvalidOperationException(RMResources.DocumentQueryExecutionContextIsDone);
            }

            Error error = null;

            try
            {
                return(await this.innerExecutionContext.ExecuteNextFeedResponseAsync(token));
            }
            catch (DocumentClientException ex)
            {
                if (ex.StatusCode != HttpStatusCode.BadRequest || ex.GetSubStatus() != SubStatusCodes.CrossPartitionQueryNotServable)
                {
                    throw;
                }

                error = ex.Error;
            }

            PartitionedQueryExecutionInfo partitionedQueryExecutionInfo =
                JsonConvert.DeserializeObject <PartitionedQueryExecutionInfo>(error.AdditionalErrorInfo);

            DefaultDocumentQueryExecutionContext queryExecutionContext =
                (DefaultDocumentQueryExecutionContext)this.innerExecutionContext;

            List <PartitionKeyRange> partitionKeyRanges =
                await
                queryExecutionContext.GetTargetPartitionKeyRangesAsync(collection.ResourceId,
                                                                       partitionedQueryExecutionInfo.QueryRanges);

            DocumentQueryExecutionContextBase.InitParams constructorParams = new DocumentQueryExecutionContextBase.InitParams(this.client, this.resourceTypeEnum, this.resourceType, this.expression, this.feedOptions, this.resourceLink, false, correlatedActivityId);
            this.innerExecutionContext = await DocumentQueryExecutionContextFactory.CreateSpecializedDocumentQueryExecutionContextAsync(
                constructorParams,
                partitionedQueryExecutionInfo,
                partitionKeyRanges,
                this.collection.ResourceId,
                this.isContinuationExpected,
                token);

            return(await this.innerExecutionContext.ExecuteNextFeedResponseAsync(token));
        }
Пример #3
0
        /// <summary>
        /// Creates a ParallelDocumentQueryExecutionContext
        /// </summary>
        /// <param name="constructorParams">The params the construct the base class.</param>
        /// <param name="initParams">The params to initialize the cross partition context.</param>
        /// <param name="token">The cancellation token.</param>
        /// <returns>A task to await on, which in turn returns a ParallelDocumentQueryExecutionContext.</returns>
        public static async Task <ParallelDocumentQueryExecutionContext> CreateAsync(
            DocumentQueryExecutionContextBase.InitParams constructorParams,
            CrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams,
            CancellationToken token)
        {
            Debug.Assert(
                !initParams.PartitionedQueryExecutionInfo.QueryInfo.HasOrderBy,
                "Parallel~Context must not have order by query info.");

            ParallelDocumentQueryExecutionContext context = new ParallelDocumentQueryExecutionContext(
                constructorParams,
                initParams.PartitionedQueryExecutionInfo.QueryInfo.RewrittenQuery);

            await context.InitializeAsync(
                initParams.CollectionRid,
                initParams.PartitionKeyRanges,
                initParams.InitialPageSize,
                initParams.RequestContinuation,
                token);

            return(context);
        }
        public static async Task <IDocumentQueryExecutionContext> CreateDocumentQueryExecutionContextAsync(
            IDocumentQueryClient client,
            ResourceType resourceTypeEnum,
            Type resourceType,
            Expression expression,
            FeedOptions feedOptions,
            string resourceLink,
            bool isContinuationExpected,
            CancellationToken token,
            Guid correlatedActivityId)
        {
            ContainerProperties collection = null;

            if (resourceTypeEnum.IsCollectionChild())
            {
                CollectionCache collectionCache = await client.GetCollectionCacheAsync();

                using (
                    DocumentServiceRequest request = DocumentServiceRequest.Create(
                        OperationType.Query,
                        resourceTypeEnum,
                        resourceLink,
                        AuthorizationTokenType.Invalid)) //this request doesnt actually go to server
                {
                    collection = await collectionCache.ResolveCollectionAsync(request, token);
                }

                if (feedOptions != null && feedOptions.PartitionKey != null && feedOptions.PartitionKey.Equals(Documents.PartitionKey.None))
                {
                    feedOptions.PartitionKey = Documents.PartitionKey.FromInternalKey(collection.GetNoneValue());
                }
            }

            DocumentQueryExecutionContextBase.InitParams constructorParams = new DocumentQueryExecutionContextBase.InitParams(
                client,
                resourceTypeEnum,
                resourceType,
                expression,
                feedOptions,
                resourceLink,
                false,
                correlatedActivityId);

            // For non-Windows platforms(like Linux and OSX) in .NET Core SDK, we cannot use ServiceInterop, so need to bypass in that case.
            // We are also now bypassing this for 32 bit host process running even on Windows as there are many 32 bit apps that will not work without this
            if (CustomTypeExtensions.ByPassQueryParsing())
            {
                // We create a ProxyDocumentQueryExecutionContext that will be initialized with DefaultDocumentQueryExecutionContext
                // which will be used to send the query to Gateway and on getting 400(bad request) with 1004(cross partition query not servable), we initialize it with
                // PipelinedDocumentQueryExecutionContext by providing the partition query execution info that's needed(which we get from the exception returned from Gateway).
                ProxyDocumentQueryExecutionContext proxyQueryExecutionContext =
                    ProxyDocumentQueryExecutionContext.Create(
                        client,
                        resourceTypeEnum,
                        resourceType,
                        expression,
                        feedOptions,
                        resourceLink,
                        token,
                        collection,
                        isContinuationExpected,
                        correlatedActivityId);

                return(proxyQueryExecutionContext);
            }

            DefaultDocumentQueryExecutionContext queryExecutionContext = await DefaultDocumentQueryExecutionContext.CreateAsync(
                constructorParams, isContinuationExpected, token);

            // If isContinuationExpected is false, we want to check if there are aggregates.
            if (
                resourceTypeEnum.IsCollectionChild() &&
                resourceTypeEnum.IsPartitioned() &&
                (feedOptions.EnableCrossPartitionQuery || !isContinuationExpected))
            {
                //todo:elasticcollections this may rely on information from collection cache which is outdated
                //if collection is deleted/created with same name.
                //need to make it not rely on information from collection cache.
                PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = await queryExecutionContext.GetPartitionedQueryExecutionInfoAsync(
                    partitionKeyDefinition : collection.PartitionKey,
                    requireFormattableOrderByQuery : true,
                    isContinuationExpected : isContinuationExpected,
                    allowNonValueAggregateQuery : true,
                    hasLogicalPartitionKey : feedOptions.PartitionKey != null,
                    cancellationToken : token);

                if (DocumentQueryExecutionContextFactory.ShouldCreateSpecializedDocumentQueryExecutionContext(
                        resourceTypeEnum,
                        feedOptions,
                        partitionedQueryExecutionInfo,
                        collection.PartitionKey,
                        isContinuationExpected))
                {
                    List <PartitionKeyRange> targetRanges = await GetTargetPartitionKeyRangesAsync(
                        queryExecutionContext,
                        partitionedQueryExecutionInfo,
                        collection,
                        feedOptions);

                    // Devnote this will get replace by the new v3 to v2 logic
                    throw new NotSupportedException("v2 query excution context is currently not supported.");
                }
            }

            return(queryExecutionContext);
        }
Пример #5
0
        /// <summary>
        /// Creates a PipelinedDocumentQueryExecutionContext.
        /// </summary>
        /// <param name="constructorParams">The parameters for constructing the base class.</param>
        /// <param name="collectionRid">The collection rid.</param>
        /// <param name="partitionedQueryExecutionInfo">The partitioned query execution info.</param>
        /// <param name="partitionKeyRanges">The partition key ranges.</param>
        /// <param name="initialPageSize">The initial page size.</param>
        /// <param name="requestContinuation">The request continuation.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A task to await on, which in turn returns a PipelinedDocumentQueryExecutionContext.</returns>
        public static async Task <IDocumentQueryExecutionContext> CreateDocumentQueryExecutionContextAsync(
            DocumentQueryExecutionContextBase.InitParams constructorParams,
            string collectionRid,
            PartitionedQueryExecutionInfo partitionedQueryExecutionInfo,
            List <PartitionKeyRange> partitionKeyRanges,
            int initialPageSize,
            string requestContinuation,
            CancellationToken cancellationToken)
        {
            DefaultTrace.TraceInformation(
                string.Format(
                    CultureInfo.InvariantCulture,
                    "{0}, CorrelatedActivityId: {1} | Pipelined~Context.CreateAsync",
                    DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture),
                    constructorParams.CorrelatedActivityId));

            QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo;

            int actualPageSize = initialPageSize;

            if (queryInfo.HasGroupBy)
            {
                initialPageSize = int.MaxValue;
                constructorParams.FeedOptions.MaxItemCount = int.MaxValue;
            }

            Func <string, Task <IDocumentQueryExecutionComponent> > createOrderByComponentFunc = async(continuationToken) =>
            {
                CrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CrossPartitionQueryExecutionContext.CrossPartitionInitParams(
                    collectionRid,
                    partitionedQueryExecutionInfo,
                    partitionKeyRanges,
                    initialPageSize,
                    continuationToken);

                return(await OrderByDocumentQueryExecutionContext.CreateAsync(
                           constructorParams,
                           initParams,
                           cancellationToken));
            };

            Func <string, Task <IDocumentQueryExecutionComponent> > createParallelComponentFunc = async(continuationToken) =>
            {
                CrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CrossPartitionQueryExecutionContext.CrossPartitionInitParams(
                    collectionRid,
                    partitionedQueryExecutionInfo,
                    partitionKeyRanges,
                    initialPageSize,
                    continuationToken);

                return(await ParallelDocumentQueryExecutionContext.CreateAsync(
                           constructorParams,
                           initParams,
                           cancellationToken));
            };

            return((IDocumentQueryExecutionContext)(await PipelinedDocumentQueryExecutionContext.CreateHelperAsync(
                                                        partitionedQueryExecutionInfo.QueryInfo,
                                                        initialPageSize,
                                                        requestContinuation,
                                                        constructorParams.FeedOptions.EnableGroupBy,
                                                        createOrderByComponentFunc,
                                                        createParallelComponentFunc)));
        }
Пример #6
0
        /// <summary>
        /// Initializes a new instance of the CrossPartitionQueryExecutionContext class.
        /// </summary>
        /// <param name="initParams">Constructor parameters for the base class.</param>
        /// <param name="rewrittenQuery">
        /// Queries will get rewritten for different reasons.
        /// You can read more about this in the details from the concrete classes.
        /// </param>
        /// <param name="moveNextComparer">Comparer used to figure out that document producer tree to serve documents from next.</param>
        /// <param name="fetchPrioirtyFunction">The priority function to determine which partition to fetch documents from next.</param>
        /// <param name="equalityComparer">Used to determine whether we need to return the continuation token for a partition.</param>
        protected CrossPartitionQueryExecutionContext(
            DocumentQueryExecutionContextBase.InitParams initParams,
            string rewrittenQuery,
            IComparer <DocumentProducerTree> moveNextComparer,
            Func <DocumentProducerTree, int> fetchPrioirtyFunction,
            IEqualityComparer <CosmosElement> equalityComparer)
            : base(initParams)
        {
            if (!string.IsNullOrWhiteSpace(rewrittenQuery))
            {
                this.querySpec = new SqlQuerySpec(rewrittenQuery, this.QuerySpec.Parameters);
            }

            if (moveNextComparer == null)
            {
                throw new ArgumentNullException($"{nameof(moveNextComparer)} can not be null");
            }

            if (fetchPrioirtyFunction == null)
            {
                throw new ArgumentNullException($"{nameof(fetchPrioirtyFunction)} can not be null");
            }

            if (equalityComparer == null)
            {
                throw new ArgumentNullException($"{nameof(equalityComparer)} can not be null");
            }

            this.documentProducerForest  = new PriorityQueue <DocumentProducerTree>(moveNextComparer, isSynchronized: true);
            this.fetchPrioirtyFunction   = fetchPrioirtyFunction;
            this.comparableTaskScheduler = new ComparableTaskScheduler(initParams.FeedOptions.MaxDegreeOfParallelism);
            this.equalityComparer        = equalityComparer;
            this.requestChargeTracker    = new RequestChargeTracker();
            this.partitionedQueryMetrics = new ConcurrentBag <Tuple <string, QueryMetrics> >();
            this.actualMaxPageSize       = this.MaxItemCount.GetValueOrDefault(ParallelQueryConfig.GetConfig().ClientInternalMaxItemCount);
            if (this.actualMaxPageSize < 0)
            {
                throw new OverflowException("actualMaxPageSize should never be less than 0");
            }

            if (this.actualMaxPageSize > int.MaxValue)
            {
                throw new OverflowException("actualMaxPageSize should never be greater than int.MaxValue");
            }

            if (IsMaxBufferedItemCountSet(this.MaxBufferedItemCount))
            {
                this.actualMaxBufferedItemCount = this.MaxBufferedItemCount;
            }
            else
            {
                this.actualMaxBufferedItemCount = ParallelQueryConfig.GetConfig().DefaultMaximumBufferSize;
            }

            if (this.actualMaxBufferedItemCount < 0)
            {
                throw new OverflowException("actualMaxBufferedItemCount should never be less than 0");
            }

            if (this.actualMaxBufferedItemCount > int.MaxValue)
            {
                throw new OverflowException("actualMaxBufferedItemCount should never be greater than int.MaxValue");
            }
        }
        public static async Task <IDocumentQueryExecutionContext> CreateSpecializedDocumentQueryExecutionContext(
            DocumentQueryExecutionContextBase.InitParams constructorParams,
            PartitionedQueryExecutionInfo partitionedQueryExecutionInfo,
            List <PartitionKeyRange> targetRanges,
            string collectionRid,
            bool isContinuationExpected,
            CancellationToken cancellationToken)
        {
            // Figure out the optimal page size.
            long initialPageSize = constructorParams.FeedOptions.MaxItemCount.GetValueOrDefault(ParallelQueryConfig.GetConfig().ClientInternalPageSize);

            if (initialPageSize < -1 || initialPageSize == 0)
            {
                throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, "Invalid MaxItemCount {0}", initialPageSize));
            }

            QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo;

            bool getLazyFeedResponse = queryInfo.HasTop;

            // We need to compute the optimal initial page size for order-by queries
            if (queryInfo.HasOrderBy)
            {
                int top;
                if (queryInfo.HasTop && (top = partitionedQueryExecutionInfo.QueryInfo.Top.Value) > 0)
                {
                    // All partitions should initially fetch about 1/nth of the top value.
                    long pageSizeWithTop = (long)Math.Min(
                        Math.Ceiling(top / (double)targetRanges.Count) * PageSizeFactorForTop,
                        top);

                    if (initialPageSize > 0)
                    {
                        initialPageSize = Math.Min(pageSizeWithTop, initialPageSize);
                    }
                    else
                    {
                        initialPageSize = pageSizeWithTop;
                    }
                }
                else if (isContinuationExpected)
                {
                    if (initialPageSize < 0)
                    {
                        // Max of what the user is willing to buffer and the default (note this is broken if MaxBufferedItemCount = -1)
                        initialPageSize = Math.Max(constructorParams.FeedOptions.MaxBufferedItemCount, ParallelQueryConfig.GetConfig().DefaultMaximumBufferSize);
                    }

                    initialPageSize = (long)Math.Min(
                        Math.Ceiling(initialPageSize / (double)targetRanges.Count) * PageSizeFactorForTop,
                        initialPageSize);
                }
            }

            Debug.Assert(initialPageSize > 0 && initialPageSize <= int.MaxValue,
                         string.Format(CultureInfo.InvariantCulture, "Invalid MaxItemCount {0}", initialPageSize));

            return(await PipelinedDocumentQueryExecutionContext.CreateAsync(
                       constructorParams,
                       collectionRid,
                       partitionedQueryExecutionInfo,
                       targetRanges,
                       (int)initialPageSize,
                       constructorParams.FeedOptions.RequestContinuation,
                       cancellationToken));
        }
        /// <summary>
        /// Creates a PipelinedDocumentQueryExecutionContext.
        /// </summary>
        /// <param name="constructorParams">The parameters for constructing the base class.</param>
        /// <param name="collectionRid">The collection rid.</param>
        /// <param name="partitionedQueryExecutionInfo">The partitioned query execution info.</param>
        /// <param name="partitionKeyRanges">The partition key ranges.</param>
        /// <param name="initialPageSize">The initial page size.</param>
        /// <param name="requestContinuation">The request continuation.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A task to await on, which in turn returns a PipelinedDocumentQueryExecutionContext.</returns>
        public static async Task <IDocumentQueryExecutionContext> CreateAsync(
            DocumentQueryExecutionContextBase.InitParams constructorParams,
            string collectionRid,
            PartitionedQueryExecutionInfo partitionedQueryExecutionInfo,
            List <PartitionKeyRange> partitionKeyRanges,
            int initialPageSize,
            string requestContinuation,
            CancellationToken cancellationToken)
        {
            DefaultTrace.TraceInformation(
                string.Format(
                    CultureInfo.InvariantCulture,
                    "{0}, CorrelatedActivityId: {1} | Pipelined~Context.CreateAsync",
                    DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture),
                    constructorParams.CorrelatedActivityId));

            Func <string, Task <IDocumentQueryExecutionComponent> > createComponentFunc;
            QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo;

            if (queryInfo.HasOrderBy)
            {
                createComponentFunc = async(continuationToken) =>
                {
                    CrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CrossPartitionQueryExecutionContext.CrossPartitionInitParams(
                        collectionRid,
                        partitionedQueryExecutionInfo,
                        partitionKeyRanges,
                        initialPageSize,
                        continuationToken);

                    return(await OrderByDocumentQueryExecutionContext.CreateAsync(
                               constructorParams,
                               initParams,
                               cancellationToken));
                };
            }
            else
            {
                createComponentFunc = async(continuationToken) =>
                {
                    CrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CrossPartitionQueryExecutionContext.CrossPartitionInitParams(
                        collectionRid,
                        partitionedQueryExecutionInfo,
                        partitionKeyRanges,
                        initialPageSize,
                        continuationToken);

                    return(await ParallelDocumentQueryExecutionContext.CreateAsync(
                               constructorParams,
                               initParams,
                               cancellationToken));
                };
            }

            if (queryInfo.HasAggregates)
            {
                Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc;
                createComponentFunc = async(continuationToken) =>
                {
                    return(await AggregateDocumentQueryExecutionComponent.CreateAsync(
                               queryInfo.Aggregates,
                               continuationToken,
                               createSourceCallback));
                };
            }

            if (queryInfo.HasDistinct)
            {
                Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc;
                createComponentFunc = async(continuationToken) =>
                {
                    return(await DistinctDocumentQueryExecutionComponent.CreateAsync(
                               continuationToken,
                               createSourceCallback,
                               queryInfo.DistinctType));
                };
            }

            if (queryInfo.HasOffset)
            {
                if (!constructorParams.FeedOptions.EnableCrossPartitionSkipTake)
                {
                    throw new ArgumentException("Cross Partition OFFSET / LIMIT is not supported.");
                }

                Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc;
                createComponentFunc = async(continuationToken) =>
                {
                    return(await SkipDocumentQueryExecutionComponent.CreateAsync(
                               queryInfo.Offset.Value,
                               continuationToken,
                               createSourceCallback));
                };
            }

            if (queryInfo.HasLimit)
            {
                if (!constructorParams.FeedOptions.EnableCrossPartitionSkipTake)
                {
                    throw new ArgumentException("Cross Partition OFFSET / LIMIT is not supported.");
                }

                Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc;
                createComponentFunc = async(continuationToken) =>
                {
                    return(await TakeDocumentQueryExecutionComponent.CreateLimitDocumentQueryExecutionComponentAsync(
                               queryInfo.Limit.Value,
                               continuationToken,
                               createSourceCallback));
                };
            }

            if (queryInfo.HasTop)
            {
                Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc;
                createComponentFunc = async(continuationToken) =>
                {
                    return(await TakeDocumentQueryExecutionComponent.CreateTopDocumentQueryExecutionComponentAsync(
                               queryInfo.Top.Value,
                               continuationToken,
                               createSourceCallback));
                };
            }

            return(new PipelinedDocumentQueryExecutionContext(
                       await createComponentFunc(requestContinuation), initialPageSize));
        }
Пример #9
0
        public static async Task <IDocumentQueryExecutionContext> CreateDocumentQueryExecutionContextAsync(
            IDocumentQueryClient client,
            ResourceType resourceTypeEnum,
            Type resourceType,
            Expression expression,
            FeedOptions feedOptions,
            string resourceLink,
            bool isContinuationExpected,
            CancellationToken token,
            Guid correlatedActivityId)
        {
            DocumentQueryExecutionContextBase.InitParams constructorParams = new DocumentQueryExecutionContextBase.InitParams(
                client,
                resourceTypeEnum,
                resourceType,
                expression,
                feedOptions,
                resourceLink,
                false,
                correlatedActivityId);

            CosmosContainerSettings collection = null;

            if (resourceTypeEnum.IsCollectionChild())
            {
                CollectionCache collectionCache = await client.GetCollectionCacheAsync();

                using (
                    DocumentServiceRequest request = DocumentServiceRequest.Create(
                        OperationType.Query,
                        resourceTypeEnum,
                        resourceLink,
                        AuthorizationTokenType.Invalid)) //this request doesnt actually go to server
                {
                    collection = await collectionCache.ResolveCollectionAsync(request, token);
                }
            }

            // For non-Windows platforms(like Linux and OSX) in .NET Core SDK, we cannot use ServiceInterop, so need to bypass in that case.
            // We are also now bypassing this for 32 bit host process running even on Windows as there are many 32 bit apps that will not work without this
            if (CustomTypeExtensions.ByPassQueryParsing())
            {
                // We create a ProxyDocumentQueryExecutionContext that will be initialized with DefaultDocumentQueryExecutionContext
                // which will be used to send the query to Gateway and on getting 400(bad request) with 1004(cross partition query not servable), we initialize it with
                // PipelinedDocumentQueryExecutionContext by providing the partition query execution info that's needed(which we get from the exception returned from Gateway).
                ProxyDocumentQueryExecutionContext proxyQueryExecutionContext =
                    ProxyDocumentQueryExecutionContext.CreateAsync(
                        client,
                        resourceTypeEnum,
                        resourceType,
                        expression,
                        feedOptions,
                        resourceLink,
                        token,
                        collection,
                        isContinuationExpected,
                        correlatedActivityId);

                return(proxyQueryExecutionContext);
            }

            DefaultDocumentQueryExecutionContext queryExecutionContext = await DefaultDocumentQueryExecutionContext.CreateAsync(
                constructorParams, isContinuationExpected, token);

            // If isContinuationExpected is false, we want to check if there are aggregates.
            if (
                resourceTypeEnum.IsCollectionChild() &&
                resourceTypeEnum.IsPartitioned() &&
                (feedOptions.EnableCrossPartitionQuery || !isContinuationExpected))
            {
                //todo:elasticcollections this may rely on information from collection cache which is outdated
                //if collection is deleted/created with same name.
                //need to make it not rely on information from collection cache.
                PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = await queryExecutionContext.GetPartitionedQueryExecutionInfoAsync(
                    collection.PartitionKey,
                    true,
                    isContinuationExpected,
                    token);

                if (DocumentQueryExecutionContextFactory.ShouldCreateSpecializedDocumentQueryExecutionContext(
                        resourceTypeEnum,
                        feedOptions,
                        partitionedQueryExecutionInfo,
                        collection.PartitionKey,
                        isContinuationExpected))
                {
                    List <PartitionKeyRange> targetRanges;
                    if (!string.IsNullOrEmpty(feedOptions.PartitionKeyRangeId))
                    {
                        targetRanges =
                            new List <PartitionKeyRange>
                        {
                            await queryExecutionContext.GetTargetPartitionKeyRangeById(
                                collection.ResourceId,
                                feedOptions.PartitionKeyRangeId)
                        };
                    }
                    else
                    {
                        List <Range <string> > queryRanges = partitionedQueryExecutionInfo.QueryRanges;
                        if (feedOptions.PartitionKey != null)
                        {
                            queryRanges = new List <Range <string> >
                            {
                                Range <string> .GetPointRange(
                                    feedOptions.PartitionKey.InternalKey.GetEffectivePartitionKeyString(
                                        collection.PartitionKey))
                            };
                        }

                        targetRanges =
                            await queryExecutionContext.GetTargetPartitionKeyRanges(collection.ResourceId, queryRanges);
                    }



                    return(await CreateSpecializedDocumentQueryExecutionContext(
                               constructorParams,
                               partitionedQueryExecutionInfo,
                               targetRanges,
                               collection.ResourceId,
                               isContinuationExpected,
                               token));
                }
            }

            return(queryExecutionContext);
        }