/// <summary>
        /// Helper method to create a stream feed iterator.
        /// It decides if it is a query or read feed and create
        /// the correct instance.
        /// </summary>
        public override FeedIteratorInternal GetItemQueryStreamIteratorInternal(
            SqlQuerySpec sqlQuerySpec,
            bool isContinuationExcpected,
            string continuationToken,
            FeedRangeInternal feedRange,
            QueryRequestOptions requestOptions)
        {
            requestOptions ??= new QueryRequestOptions();

            if (requestOptions.IsEffectivePartitionKeyRouting)
            {
                if (feedRange != null)
                {
                    throw new ArgumentException(nameof(feedRange), ClientResources.FeedToken_EffectivePartitionKeyRouting);
                }

                requestOptions.PartitionKey = null;
            }

            if (sqlQuerySpec == null)
            {
                NetworkAttachedDocumentContainer networkAttachedDocumentContainer = new NetworkAttachedDocumentContainer(
                    this,
                    this.queryClient,
                    requestOptions);

                DocumentContainer documentContainer = new DocumentContainer(networkAttachedDocumentContainer);

                ReadFeedPaginationOptions.PaginationDirection?direction = null;
                if ((requestOptions.Properties != null) && requestOptions.Properties.TryGetValue(HttpConstants.HttpHeaders.EnumerationDirection, out object enumerationDirection))
                {
                    direction = (byte)enumerationDirection == (byte)RntbdConstants.RntdbEnumerationDirection.Reverse ? ReadFeedPaginationOptions.PaginationDirection.Reverse : ReadFeedPaginationOptions.PaginationDirection.Forward;
                }

                ReadFeedPaginationOptions readFeedPaginationOptions = new ReadFeedPaginationOptions(
                    direction,
                    pageSizeHint: requestOptions.MaxItemCount ?? int.MaxValue);

                return(new ReadFeedIteratorCore(
                           documentContainer,
                           continuationToken,
                           readFeedPaginationOptions,
                           requestOptions,
                           cancellationToken: default));
            }

            return(QueryIterator.Create(
                       containerCore: this,
                       client: this.queryClient,
                       clientContext: this.ClientContext,
                       sqlQuerySpec: sqlQuerySpec,
                       continuationToken: continuationToken,
                       feedRangeInternal: feedRange,
                       queryRequestOptions: requestOptions,
                       resourceLink: this.LinkUri,
                       isContinuationExpected: isContinuationExcpected,
                       allowNonValueAggregateQuery: true,
                       forcePassthrough: false,
                       partitionedQueryExecutionInfo: null));
        }
 public Task <TryCatch <ReadFeedPage> > MonadicReadFeedAsync(
     FeedRangeState <ReadFeedState> feedRangeState,
     ReadFeedPaginationOptions readFeedPaginationOptions,
     ITrace trace,
     CancellationToken cancellationToken) => this.monadicDocumentContainer.MonadicReadFeedAsync(
     feedRangeState,
     readFeedPaginationOptions,
     trace,
     cancellationToken);
 public ReadFeedCrossFeedRangeAsyncEnumerable(
     IDocumentContainer documentContainer,
     ReadFeedCrossFeedRangeState state,
     ReadFeedPaginationOptions readFeedPaginationOptions)
 {
     this.documentContainer         = documentContainer ?? throw new ArgumentNullException(nameof(documentContainer));
     this.state                     = state;
     this.readFeedPaginationOptions = readFeedPaginationOptions;
 }
 public ReadFeedPartitionRangeEnumerator(
     IReadFeedDataSource readFeedDataSource,
     FeedRangeState <ReadFeedState> feedRangeState,
     ReadFeedPaginationOptions readFeedPaginationOptions,
     CancellationToken cancellationToken)
     : base(feedRangeState, cancellationToken)
 {
     this.readFeedDataSource        = readFeedDataSource ?? throw new ArgumentNullException(nameof(readFeedDataSource));
     this.readFeedPaginationOptions = readFeedPaginationOptions;
 }
        public override FeedIteratorInternal GetReadFeedIterator(
            QueryDefinition queryDefinition,
            QueryRequestOptions queryRequestOptions,
            string resourceLink,
            ResourceType resourceType,
            string continuationToken,
            int pageSize)
        {
            queryRequestOptions ??= new QueryRequestOptions();

            NetworkAttachedDocumentContainer networkAttachedDocumentContainer = new NetworkAttachedDocumentContainer(
                this,
                this.queryClient,
                queryRequestOptions,
                resourceLink: resourceLink,
                resourceType: resourceType);

            DocumentContainer documentContainer = new DocumentContainer(networkAttachedDocumentContainer);

            FeedIteratorInternal feedIterator;

            if (queryDefinition != null)
            {
                feedIterator = QueryIterator.Create(
                    containerCore: this,
                    client: this.queryClient,
                    clientContext: this.ClientContext,
                    sqlQuerySpec: queryDefinition.ToSqlQuerySpec(),
                    continuationToken: continuationToken,
                    feedRangeInternal: FeedRangeEpk.FullRange,
                    queryRequestOptions: queryRequestOptions,
                    resourceLink: resourceLink,
                    isContinuationExpected: false,
                    allowNonValueAggregateQuery: true,
                    forcePassthrough: false,
                    partitionedQueryExecutionInfo: null);
            }
            else
            {
                ReadFeedPaginationOptions.PaginationDirection?direction = null;
                if ((queryRequestOptions.Properties != null) && queryRequestOptions.Properties.TryGetValue(HttpConstants.HttpHeaders.EnumerationDirection, out object enumerationDirection))
                {
                    direction = (byte)enumerationDirection == (byte)RntbdConstants.RntdbEnumerationDirection.Reverse ? ReadFeedPaginationOptions.PaginationDirection.Reverse : ReadFeedPaginationOptions.PaginationDirection.Forward;
                }

                ReadFeedPaginationOptions readFeedPaginationOptions = new ReadFeedPaginationOptions(
                    direction,
                    pageSizeHint: queryRequestOptions.MaxItemCount ?? int.MaxValue);

                feedIterator = new ReadFeedIteratorCore(
                    documentContainer: documentContainer,
                    queryRequestOptions: queryRequestOptions,
                    continuationToken: continuationToken,
                    readFeedPaginationOptions: readFeedPaginationOptions,
                    cancellationToken: default);
 public Task <ReadFeedPage> ReadFeedAsync(
     FeedRangeState <ReadFeedState> feedRangeState,
     ReadFeedPaginationOptions readFeedPaginationOptions,
     ITrace trace,
     CancellationToken cancellationToken) => TryCatch <ReadFeedPage> .UnsafeGetResultAsync(
     this.MonadicReadFeedAsync(
         feedRangeState,
         readFeedPaginationOptions,
         trace,
         cancellationToken),
     cancellationToken);
        public ReadFeedIteratorCore(
            IDocumentContainer documentContainer,
            string continuationToken,
            ReadFeedPaginationOptions readFeedPaginationOptions,
            QueryRequestOptions queryRequestOptions,
            CancellationToken cancellationToken)
        {
            this.queryRequestOptions = queryRequestOptions;
            readFeedPaginationOptions ??= ReadFeedPaginationOptions.Default;

            if (!string.IsNullOrEmpty(continuationToken))
            {
                bool isNewArrayFormat = (continuationToken.Length >= 2) && (continuationToken[0] == '[') && (continuationToken[continuationToken.Length - 1] == ']');
                if (!isNewArrayFormat)
                {
                    // One of the two older formats
                    if (!FeedRangeContinuation.TryParse(continuationToken, out FeedRangeContinuation feedRangeContinuation))
                    {
                        // Backward compatible with old format
                        feedRangeContinuation = new FeedRangeCompositeContinuation(
                            containerRid: string.Empty,
                            FeedRangeEpk.FullRange,
                            new List <Documents.Routing.Range <string> >()
                        {
                            new Documents.Routing.Range <string>(
                                Documents.Routing.PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey,
                                Documents.Routing.PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey,
                                isMinInclusive: true,
                                isMaxInclusive: false)
                        },
                            continuationToken);
                    }

                    // need to massage it a little
                    List <CosmosElement> feedRangeStates = new List <CosmosElement>();
                    string oldContinuationFormat         = feedRangeContinuation.ToString();
                    if (feedRangeContinuation.FeedRange is FeedRangePartitionKey feedRangePartitionKey)
                    {
                        CosmosObject cosmosObject  = CosmosObject.Parse(oldContinuationFormat);
                        CosmosArray  continuations = (CosmosArray)cosmosObject["Continuation"];
                        if (continuations.Count != 1)
                        {
                            throw new InvalidOperationException("Expected only one continuation for partition key queries");
                        }

                        CosmosElement continuation       = continuations[0];
                        CosmosObject  continuationObject = (CosmosObject)continuation;
                        CosmosElement token = continuationObject["token"];
                        ReadFeedState state;
                        if (token is CosmosNull)
                        {
                            state = ReadFeedState.Beginning();
                        }
                        else
                        {
                            CosmosString tokenAsString = (CosmosString)token;
                            state = ReadFeedState.Continuation(CosmosElement.Parse(tokenAsString.Value));
                        }

                        FeedRangeState <ReadFeedState> feedRangeState = new FeedRangeState <ReadFeedState>(feedRangePartitionKey, state);
                        feedRangeStates.Add(ReadFeedFeedRangeStateSerializer.ToCosmosElement(feedRangeState));
                    }
                    else
                    {
                        CosmosObject cosmosObject  = CosmosObject.Parse(oldContinuationFormat);
                        CosmosArray  continuations = (CosmosArray)cosmosObject["Continuation"];

                        foreach (CosmosElement continuation in continuations)
                        {
                            CosmosObject  continuationObject = (CosmosObject)continuation;
                            CosmosObject  rangeObject        = (CosmosObject)continuationObject["range"];
                            string        min   = ((CosmosString)rangeObject["min"]).Value;
                            string        max   = ((CosmosString)rangeObject["max"]).Value;
                            CosmosElement token = continuationObject["token"];

                            FeedRangeInternal feedRange = new FeedRangeEpk(new Documents.Routing.Range <string>(min, max, isMinInclusive: true, isMaxInclusive: false));
                            ReadFeedState     state;
                            if (token is CosmosNull)
                            {
                                state = ReadFeedState.Beginning();
                            }
                            else
                            {
                                CosmosString tokenAsString = (CosmosString)token;
                                state = ReadFeedState.Continuation(CosmosElement.Parse(tokenAsString.Value));
                            }

                            FeedRangeState <ReadFeedState> feedRangeState = new FeedRangeState <ReadFeedState>(feedRange, state);
                            feedRangeStates.Add(ReadFeedFeedRangeStateSerializer.ToCosmosElement(feedRangeState));
                        }
                    }

                    CosmosArray cosmosArrayContinuationTokens = CosmosArray.Create(feedRangeStates);
                    continuationToken = cosmosArrayContinuationTokens.ToString();
                }
            }

            TryCatch <ReadFeedCrossFeedRangeState> monadicReadFeedState;

            if (continuationToken == null)
            {
                FeedRange feedRange;
                if ((this.queryRequestOptions != null) && this.queryRequestOptions.PartitionKey.HasValue)
                {
                    feedRange = new FeedRangePartitionKey(this.queryRequestOptions.PartitionKey.Value);
                }
                else if ((this.queryRequestOptions != null) && (this.queryRequestOptions.FeedRange != null))
                {
                    feedRange = this.queryRequestOptions.FeedRange;
                }
                else
                {
                    feedRange = FeedRangeEpk.FullRange;
                }

                monadicReadFeedState = TryCatch <ReadFeedCrossFeedRangeState> .FromResult(ReadFeedCrossFeedRangeState.CreateFromBeginning(feedRange));
            }
            else
            {
                monadicReadFeedState = ReadFeedCrossFeedRangeState.Monadic.Parse(continuationToken);
            }

            if (monadicReadFeedState.Failed)
            {
                this.monadicEnumerator = TryCatch <CrossPartitionReadFeedAsyncEnumerator> .FromException(monadicReadFeedState.Exception);
            }
            else
            {
                this.monadicEnumerator = TryCatch <CrossPartitionReadFeedAsyncEnumerator> .FromResult(
                    CrossPartitionReadFeedAsyncEnumerator.Create(
                        documentContainer,
                        new CrossFeedRangeState <ReadFeedState>(monadicReadFeedState.Result.FeedRangeStates),
                        readFeedPaginationOptions,
                        cancellationToken));
            }

            this.hasMoreResults = true;
        }