/// <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 = requestOptions ?? new QueryRequestOptions();

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

                requestOptions.PartitionKey = null;
            }

            if (sqlQuerySpec == null)
            {
                return(FeedRangeIteratorCore.Create(
                           containerCore: this,
                           continuation: continuationToken,
                           feedRangeInternal: feedRange,
                           options: requestOptions));
            }

            return(QueryIterator.Create(
                       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 static ChangeFeedIteratorCore Create(
            ContainerInternal container,
            FeedRangeInternal feedRangeInternal,
            string continuation,
            ChangeFeedRequestOptions changeFeedRequestOptions)
        {
            if (!string.IsNullOrEmpty(continuation))
            {
                if (FeedRangeContinuation.TryParse(continuation, out FeedRangeContinuation feedRangeContinuation))
                {
                    return(new ChangeFeedIteratorCore(container, feedRangeContinuation, changeFeedRequestOptions));
                }
                else
                {
                    throw new ArgumentException(string.Format(ClientResources.FeedToken_UnknownFormat, continuation));
                }
            }

            feedRangeInternal = feedRangeInternal ?? FeedRangeEPK.ForCompleteRange();
            return(new ChangeFeedIteratorCore(container, feedRangeInternal, changeFeedRequestOptions));
        }
Пример #3
0
        public override async Task <List <PartitionKeyRange> > GetTargetPartitionKeyRangeByFeedRangeAsync(
            string resourceLink,
            string collectionResourceId,
            PartitionKeyDefinition partitionKeyDefinition,
            FeedRangeInternal feedRangeInternal,
            bool forceRefresh,
            ITrace trace)
        {
            using (ITrace childTrace = trace.StartChild("Get Overlapping Feed Ranges", TraceComponent.Routing, Tracing.TraceLevel.Info))
            {
                IRoutingMapProvider routingMapProvider = await this.GetRoutingMapProviderAsync();

                List <Range <string> > ranges = await feedRangeInternal.GetEffectiveRangesAsync(routingMapProvider, collectionResourceId, partitionKeyDefinition);

                return(await this.GetTargetPartitionKeyRangesAsync(
                           resourceLink,
                           collectionResourceId,
                           ranges,
                           forceRefresh,
                           childTrace));
            }
        }
        public override object ReadJson(
            JsonReader reader,
            Type objectType,
            object existingValue,
            JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
            {
                return(null);
            }

            if (reader.TokenType != JsonToken.StartObject)
            {
                throw new JsonReaderException();
            }

            JObject jObject = JObject.Load(reader);

            if (!jObject.TryGetValue(FeedRangeCompositeContinuationConverter.ContinuationPropertyName, out JToken continuationJToken))
            {
                throw new JsonReaderException();
            }

            string containerRid = null;

            if (jObject.TryGetValue(FeedRangeCompositeContinuationConverter.RidPropertyName, out JToken ridJToken))
            {
                containerRid = ridJToken.Value <string>();
            }

            List <CompositeContinuationToken> ranges = serializer.Deserialize <List <CompositeContinuationToken> >(continuationJToken.CreateReader());
            FeedRangeInternal feedRangeInternal      = FeedRangeInternalConverter.ReadJObject(jObject, serializer);

            return(new FeedRangeCompositeContinuation(
                       containerRid: containerRid,
                       feedRange: feedRangeInternal,
                       deserializedTokens: ranges));
        }
Пример #5
0
        /// <summary>
        /// Used for deserialization only
        /// </summary>
        public FeedRangeCompositeContinuation(
            string containerRid,
            FeedRangeInternal feedRange,
            IReadOnlyList <CompositeContinuationToken> deserializedTokens)
            : this(containerRid, feedRange)
        {
            if (deserializedTokens == null)
            {
                throw new ArgumentNullException(nameof(deserializedTokens));
            }

            if (deserializedTokens.Count == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(deserializedTokens));
            }

            foreach (CompositeContinuationToken token in deserializedTokens)
            {
                this.CompositeContinuationTokens.Enqueue(token);
            }

            this.CurrentToken = this.CompositeContinuationTokens.Peek();
        }
Пример #6
0
        public static bool TryParse(
            JObject jObject,
            JsonSerializer serializer,
            out FeedRangeInternal feedRangeInternal)
        {
            if (FeedRangeEPK.TryParse(jObject, serializer, out feedRangeInternal))
            {
                return(true);
            }

            if (FeedRangePartitionKey.TryParse(jObject, serializer, out feedRangeInternal))
            {
                return(true);
            }

            if (FeedRangePartitionKeyRange.TryParse(jObject, serializer, out feedRangeInternal))
            {
                return(true);
            }

            feedRangeInternal = null;
            return(false);
        }
Пример #7
0
 public abstract FeedIteratorInternal GetItemQueryStreamIteratorInternal(
     SqlQuerySpec sqlQuerySpec,
     bool isContinuationExcpected,
     string continuationToken,
     FeedRangeInternal feedRange,
     QueryRequestOptions requestOptions);
        /// <summary>
        /// Used in the compute gateway to support legacy gateway interface.
        /// </summary>
        public override async Task <TryExecuteQueryResult> TryExecuteQueryAsync(
            QueryFeatures supportedQueryFeatures,
            QueryDefinition queryDefinition,
            string continuationToken,
            FeedRangeInternal feedRangeInternal,
            QueryRequestOptions requestOptions,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (queryDefinition == null)
            {
                throw new ArgumentNullException(nameof(queryDefinition));
            }

            if (requestOptions == null)
            {
                throw new ArgumentNullException(nameof(requestOptions));
            }

            if (feedRangeInternal != null)
            {
                // The user has scoped down to a physical partition or logical partition.
                // In either case let the query execute as a passthrough.
                QueryIterator passthroughQueryIterator = QueryIterator.Create(
                    client: this.queryClient,
                    clientContext: this.ClientContext,
                    sqlQuerySpec: queryDefinition.ToSqlQuerySpec(),
                    continuationToken: continuationToken,
                    feedRangeInternal: feedRangeInternal,
                    queryRequestOptions: requestOptions,
                    resourceLink: this.LinkUri,
                    isContinuationExpected: false,
                    allowNonValueAggregateQuery: true,
                    forcePassthrough: true, // Forcing a passthrough, since we don't want to get the query plan nor try to rewrite it.
                    partitionedQueryExecutionInfo: null);

                return(new QueryPlanIsSupportedResult(passthroughQueryIterator));
            }

            cancellationToken.ThrowIfCancellationRequested();

            Documents.PartitionKeyDefinition partitionKeyDefinition;
            if (requestOptions.Properties != null &&
                requestOptions.Properties.TryGetValue("x-ms-query-partitionkey-definition", out object partitionKeyDefinitionObject))
            {
                if (partitionKeyDefinitionObject is Documents.PartitionKeyDefinition definition)
                {
                    partitionKeyDefinition = definition;
                }
                else
                {
                    throw new ArgumentException(
                              "partitionkeydefinition has invalid type",
                              nameof(partitionKeyDefinitionObject));
                }
            }
            else
            {
                ContainerQueryProperties containerQueryProperties = await this.queryClient.GetCachedContainerQueryPropertiesAsync(
                    this.LinkUri,
                    requestOptions.PartitionKey,
                    cancellationToken);

                partitionKeyDefinition = containerQueryProperties.PartitionKeyDefinition;
            }

            QueryPlanHandler queryPlanHandler = new QueryPlanHandler(this.queryClient);

            TryCatch <(PartitionedQueryExecutionInfo queryPlan, bool supported)> tryGetQueryInfoAndIfSupported = await queryPlanHandler.TryGetQueryInfoAndIfSupportedAsync(
                supportedQueryFeatures,
                queryDefinition.ToSqlQuerySpec(),
                partitionKeyDefinition,
                requestOptions.PartitionKey.HasValue,
                cancellationToken);

            if (tryGetQueryInfoAndIfSupported.Failed)
            {
                return(new FailedToGetQueryPlanResult(tryGetQueryInfoAndIfSupported.Exception));
            }

            (PartitionedQueryExecutionInfo queryPlan, bool supported) = tryGetQueryInfoAndIfSupported.Result;
            TryExecuteQueryResult tryExecuteQueryResult;

            if (supported)
            {
                QueryIterator queryIterator = QueryIterator.Create(
                    client: this.queryClient,
                    clientContext: this.ClientContext,
                    sqlQuerySpec: queryDefinition.ToSqlQuerySpec(),
                    continuationToken: continuationToken,
                    feedRangeInternal: feedRangeInternal,
                    queryRequestOptions: requestOptions,
                    resourceLink: this.LinkUri,
                    isContinuationExpected: false,
                    allowNonValueAggregateQuery: true,
                    forcePassthrough: false,
                    partitionedQueryExecutionInfo: queryPlan);

                tryExecuteQueryResult = new QueryPlanIsSupportedResult(queryIterator);
            }
            else
            {
                tryExecuteQueryResult = new QueryPlanNotSupportedResult(queryPlan);
            }

            return(tryExecuteQueryResult);
        }
        /// <summary>
        /// Used in the compute gateway to support legacy gateway interface.
        /// </summary>
        internal async Task <((Exception, PartitionedQueryExecutionInfo), (bool, QueryIterator))> TryExecuteQueryAsync(
            QueryFeatures supportedQueryFeatures,
            QueryDefinition queryDefinition,
            string continuationToken,
            FeedRangeInternal feedRangeInternal,
            QueryRequestOptions requestOptions,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (queryDefinition == null)
            {
                throw new ArgumentNullException(nameof(queryDefinition));
            }

            if (requestOptions == null)
            {
                throw new ArgumentNullException(nameof(requestOptions));
            }

            cancellationToken.ThrowIfCancellationRequested();

            Documents.PartitionKeyDefinition partitionKeyDefinition;
            if (requestOptions.Properties != null &&
                requestOptions.Properties.TryGetValue("x-ms-query-partitionkey-definition", out object partitionKeyDefinitionObject))
            {
                if (partitionKeyDefinitionObject is Documents.PartitionKeyDefinition definition)
                {
                    partitionKeyDefinition = definition;
                }
                else
                {
                    throw new ArgumentException(
                              "partitionkeydefinition has invalid type",
                              nameof(partitionKeyDefinitionObject));
                }
            }
            else
            {
                ContainerQueryProperties containerQueryProperties = await this.queryClient.GetCachedContainerQueryPropertiesAsync(
                    this.LinkUri,
                    requestOptions.PartitionKey,
                    cancellationToken);

                partitionKeyDefinition = containerQueryProperties.PartitionKeyDefinition;
            }

            QueryPlanHandler queryPlanHandler = new QueryPlanHandler(this.queryClient);

            ((Exception exception, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo), bool supported) = await queryPlanHandler.TryGetQueryInfoAndIfSupportedAsync(
                supportedQueryFeatures,
                queryDefinition.ToSqlQuerySpec(),
                partitionKeyDefinition,
                requestOptions.PartitionKey.HasValue,
                cancellationToken);

            if (exception != null)
            {
                return((exception, null), (false, null));
            }

            QueryIterator queryIterator;

            if (supported)
            {
                queryIterator = QueryIterator.Create(
                    client: this.queryClient,
                    clientContext: this.ClientContext,
                    sqlQuerySpec: queryDefinition.ToSqlQuerySpec(),
                    continuationToken: continuationToken,
                    feedRangeInternal: feedRangeInternal,
                    queryRequestOptions: requestOptions,
                    resourceLink: this.LinkUri,
                    isContinuationExpected: false,
                    allowNonValueAggregateQuery: true,
                    partitionedQueryExecutionInfo: partitionedQueryExecutionInfo);
            }
            else
            {
                queryIterator = null;
            }

            return((null, partitionedQueryExecutionInfo), (supported, queryIterator));
        }