private static bool ShouldCreateSpecializedDocumentQueryExecutionContext( ResourceType resourceTypeEnum, FeedOptions feedOptions, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, PartitionKeyDefinition partitionKeyDefinition, bool isContinuationExpected) { // We need to aggregate the total results with Pipelined~Context if isContinuationExpected is false. return ((DocumentQueryExecutionContextFactory.IsCrossPartitionQuery( resourceTypeEnum, feedOptions, partitionKeyDefinition, partitionedQueryExecutionInfo) && (DocumentQueryExecutionContextFactory.IsTopOrderByQuery(partitionedQueryExecutionInfo) || DocumentQueryExecutionContextFactory.IsAggregateQuery(partitionedQueryExecutionInfo) || DocumentQueryExecutionContextFactory.IsOffsetLimitQuery(partitionedQueryExecutionInfo) || DocumentQueryExecutionContextFactory.IsParallelQuery(feedOptions)) || !string.IsNullOrEmpty(feedOptions.PartitionKeyRangeId)) || // Even if it's single partition query we create a specialized context to aggregate the aggregates and distinct of distinct. DocumentQueryExecutionContextFactory.IsAggregateQueryWithoutContinuation( partitionedQueryExecutionInfo, isContinuationExpected) || DocumentQueryExecutionContextFactory.IsDistinctQuery(partitionedQueryExecutionInfo) || DocumentQueryExecutionContextFactory.IsGroupByQuery(partitionedQueryExecutionInfo)); }
public async Task <FeedResponse <dynamic> > ExecuteNextAsync(CancellationToken token) { if (this.IsDone) { throw new InvalidOperationException(RMResources.DocumentQueryExecutionContextIsDone); } Error error = null; try { return(await this.innerExecutionContext.ExecuteNextAsync(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.GetTargetPartitionKeyRanges(collection.ResourceId, partitionedQueryExecutionInfo.QueryRanges); this.innerExecutionContext = await DocumentQueryExecutionContextFactory.CreateSpecializedDocumentQueryExecutionContext( this.client, this.resourceTypeEnum, this.resourceType, this.expression, this.feedOptions, this.resourceLink, isContinuationExpected, partitionedQueryExecutionInfo, partitionKeyRanges, this.collection.ResourceId, token, this.correlatedActivityId); return(await this.innerExecutionContext.ExecuteNextAsync(token)); }
public static async Task <MultiCollectionDocumentQueryExecutionContext> CreateAsync( IDocumentQueryClient client, ResourceType resourceTypeEnum, Type resourceType, Expression expression, FeedOptions feedOptions, IEnumerable <string> documentFeedLinks, bool isContinuationExpected, CancellationToken token, Guid correlatedActivityId) { if (client == null) { throw new ArgumentNullException("client"); } if (feedOptions == null) { throw new ArgumentNullException("feedOptions"); } if (documentFeedLinks == null) { throw new ArgumentNullException("documentFeedLinks"); } List <IDocumentQueryExecutionContext> childQueryExecutionContexts = new List <IDocumentQueryExecutionContext>(); foreach (string link in documentFeedLinks) { childQueryExecutionContexts.Add(await DocumentQueryExecutionContextFactory.CreateDocumentQueryExecutionContextAsync( client, resourceTypeEnum, resourceType, expression, feedOptions, link, isContinuationExpected, token, correlatedActivityId)); } return(new MultiCollectionDocumentQueryExecutionContext(childQueryExecutionContexts)); }
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); }
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); }