/// <summary> /// Gets the list of partition key ranges. /// 1. Check partition key range id /// 2. Check Partition key /// 3. Check the effective partition key /// 4. Get the range from the PartitionedQueryExecutionInfo /// </summary> internal static async Task <List <Documents.PartitionKeyRange> > GetTargetPartitionKeyRangesAsync( CosmosQueryClient queryClient, string resourceLink, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, ContainerQueryProperties containerQueryProperties, IDictionary <string, object> properties) { List <Documents.PartitionKeyRange> targetRanges; if (containerQueryProperties.EffectivePartitionKeyString != null) { targetRanges = await queryClient.GetTargetPartitionKeyRangesByEpkStringAsync( resourceLink, containerQueryProperties.ResourceId, containerQueryProperties.EffectivePartitionKeyString); } else if (TryGetEpkProperty(properties, out string effectivePartitionKeyString)) { targetRanges = await queryClient.GetTargetPartitionKeyRangesByEpkStringAsync( resourceLink, containerQueryProperties.ResourceId, effectivePartitionKeyString); } else { targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( resourceLink, containerQueryProperties.ResourceId, partitionedQueryExecutionInfo.QueryRanges); } return(targetRanges); }
/// <summary> /// Gets the list of partition key ranges. /// 1. Check partition key range id /// 2. Check Partition key /// 3. Check the effective partition key /// 4. Get the range from the PartitionedQueryExecutionInfo /// </summary> internal static async Task <List <PartitionKeyRange> > GetTargetPartitionKeyRanges( CosmosQueryClient queryClient, string resourceLink, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, CosmosContainerSettings collection, CosmosQueryRequestOptions queryRequestOptions) { List <PartitionKeyRange> targetRanges; if (queryRequestOptions.PartitionKey != null) { targetRanges = await queryClient.GetTargetPartitionKeyRangesByEpkString( resourceLink, collection.ResourceId, new PartitionKey(queryRequestOptions.PartitionKey).InternalKey.GetEffectivePartitionKeyString(collection.PartitionKey)); } else if (TryGetEpkProperty(queryRequestOptions, out string effectivePartitionKeyString)) { targetRanges = await queryClient.GetTargetPartitionKeyRangesByEpkString( resourceLink, collection.ResourceId, effectivePartitionKeyString); } else { targetRanges = await queryClient.GetTargetPartitionKeyRanges( resourceLink, collection.ResourceId, partitionedQueryExecutionInfo.QueryRanges); } return(targetRanges); }
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 TryCatch <PartitionedQueryExecutionInfo> TryGetPartitionedQueryExecutionInfo( SqlQuerySpec querySpec, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey) { TryCatch <PartitionedQueryExecutionInfoInternal> tryGetInternalQueryInfo = this.TryGetPartitionedQueryExecutionInfoInternal( querySpec, partitionKeyDefinition, requireFormattableOrderByQuery, isContinuationExpected, allowNonValueAggregateQuery, hasLogicalPartitionKey); if (!tryGetInternalQueryInfo.Succeeded) { return(TryCatch <PartitionedQueryExecutionInfo> .FromException(tryGetInternalQueryInfo.Exception)); } PartitionedQueryExecutionInfo queryInfo = this.ConvertPartitionedQueryExecutionInfo(tryGetInternalQueryInfo.Result, partitionKeyDefinition); return(TryCatch <PartitionedQueryExecutionInfo> .FromResult(queryInfo)); }
public async Task <CosmosQueryExecutionContext> CreateFromPartitionedQuerExecutionInfoAsync( PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, ContainerQueryProperties containerQueryProperties, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); List <Documents.PartitionKeyRange> targetRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync( this.CosmosQueryContext.QueryClient, this.CosmosQueryContext.ResourceLink.OriginalString, partitionedQueryExecutionInfo, containerQueryProperties, this.inputParameters.Properties); if (!string.IsNullOrEmpty(partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery)) { // We need pass down the rewritten query. this.inputParameters.SqlQuerySpec = new SqlQuerySpec() { QueryText = partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery, Parameters = this.inputParameters.SqlQuerySpec.Parameters }; } return(await CosmosQueryExecutionContextFactory.CreateSpecializedDocumentQueryExecutionContextAsync( this.CosmosQueryContext, this.inputParameters, partitionedQueryExecutionInfo, targetRanges, containerQueryProperties.ResourceId, cancellationToken)); }
/// <summary> /// Initializes a new instance of the InitParams struct. /// </summary> /// <param name="sqlQuerySpec">The Sql query spec</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="maxConcurrency">The max concurrency</param> /// <param name="maxBufferedItemCount">The max buffered item count</param> /// <param name="maxItemCount">Max item count</param> /// <param name="testSettings">Test settings.</param> public CrossPartitionInitParams( SqlQuerySpec sqlQuerySpec, string collectionRid, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, List <PartitionKeyRange> partitionKeyRanges, int initialPageSize, int?maxConcurrency, int?maxItemCount, int?maxBufferedItemCount, TestInjections testSettings) { if (string.IsNullOrWhiteSpace(collectionRid)) { throw new ArgumentException($"{nameof(collectionRid)} can not be null, empty, or white space."); } if (partitionedQueryExecutionInfo == null) { throw new ArgumentNullException($"{nameof(partitionedQueryExecutionInfo)} can not be null."); } if (partitionKeyRanges == null) { throw new ArgumentNullException($"{nameof(partitionKeyRanges)} can not be null."); } foreach (PartitionKeyRange partitionKeyRange in partitionKeyRanges) { if (partitionKeyRange == null) { throw new ArgumentNullException($"{nameof(partitionKeyRange)} can not be null."); } } if (initialPageSize <= 0) { throw new ArgumentOutOfRangeException($"{nameof(initialPageSize)} must be at least 1."); } if (sqlQuerySpec == null) { throw new ArgumentNullException($"{nameof(sqlQuerySpec)} can not be null."); } //// Request continuation is allowed to be null this.SqlQuerySpec = sqlQuerySpec; this.CollectionRid = collectionRid; this.PartitionedQueryExecutionInfo = partitionedQueryExecutionInfo; this.PartitionKeyRanges = partitionKeyRanges; this.InitialPageSize = initialPageSize; this.MaxBufferedItemCount = maxBufferedItemCount; this.MaxConcurrency = maxConcurrency; this.MaxItemCount = maxItemCount; this.TestSettings = testSettings; }
/// <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; 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, createOrderByComponentFunc, createParallelComponentFunc))); }
private static bool IsCrossPartitionQuery( ResourceType resourceTypeEnum, FeedOptions feedOptions, PartitionKeyDefinition partitionKeyDefinition, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { return(resourceTypeEnum.IsPartitioned() && (feedOptions.PartitionKey == null && feedOptions.EnableCrossPartitionQuery) && (partitionKeyDefinition.Paths.Count > 0) && !(partitionedQueryExecutionInfo.QueryRanges.Count == 1 && partitionedQueryExecutionInfo.QueryRanges[0].IsSingleValue)); }
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 async Task <FeedResponse <CosmosElement> > ExecuteNextAsync(CancellationToken token) { if (this.IsDone) { throw new InvalidOperationException(RMResources.DocumentQueryExecutionContextIsDone); } Error error; try { return(await this.innerExecutionContext.ExecuteNextAsync(token)); } catch (CosmosException ex) { if (ex.StatusCode != HttpStatusCode.BadRequest || ex.SubStatusCode != (int)SubStatusCodes.CrossPartitionQueryNotServable) { throw; } error = ex.Error; } PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = JsonConvert.DeserializeObject <PartitionedQueryExecutionInfo>(error.AdditionalErrorInfo); string rewrittenQuery = partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery; if (!string.IsNullOrEmpty(rewrittenQuery)) { this.queryContext.SqlQuerySpec.QueryText = rewrittenQuery; } List <PartitionKeyRange> partitionKeyRanges = await this.queryContext.QueryClient.GetTargetPartitionKeyRanges( this.queryContext.ResourceLink.OriginalString, this.containerSettings.ResourceId, partitionedQueryExecutionInfo.QueryRanges); this.innerExecutionContext = await CosmosQueryExecutionContextFactory.CreateSpecializedDocumentQueryExecutionContext( this.queryContext, partitionedQueryExecutionInfo, partitionKeyRanges, this.containerSettings.ResourceId, token); return(await this.innerExecutionContext.ExecuteNextAsync(token)); }
public static async Task <OrderByDocumentQueryExecutionContext> CreateAsync( IDocumentQueryClient client, ResourceType resourceTypeEnum, Type resourceType, Expression expression, FeedOptions feedOptions, string resourceLink, string collectionRid, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, List <PartitionKeyRange> partitionKeyRanges, int initialPageSize, bool isContinuationExpected, bool getLazyFeedResponse, string requestContinuation, CancellationToken token, Guid correlatedActivityId) { Debug.Assert( partitionedQueryExecutionInfo.QueryInfo.HasOrderBy, "OrderBy~Context must have order by query info."); OrderByDocumentQueryExecutionContext context = new OrderByDocumentQueryExecutionContext( client, resourceTypeEnum, resourceType, expression, feedOptions, resourceLink, partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery, isContinuationExpected, getLazyFeedResponse, new OrderByConsumeComparer(partitionedQueryExecutionInfo.QueryInfo.OrderBy), collectionRid, correlatedActivityId); await context.InitializeAsync( collectionRid, partitionedQueryExecutionInfo.QueryRanges, partitionKeyRanges, partitionedQueryExecutionInfo.QueryInfo.OrderBy, partitionedQueryExecutionInfo.QueryInfo.OrderByExpressions, initialPageSize, requestContinuation, token); return(context); }
public static QueryIterator Create( CosmosQueryClient client, SqlQuerySpec sqlQuerySpec, string continuationToken, QueryRequestOptions queryRequestOptions, Uri resourceLink, bool isContinuationExpected, bool allowNonValueAggregateQuery, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { if (queryRequestOptions == null) { queryRequestOptions = new QueryRequestOptions(); } CosmosQueryContext context = new CosmosQueryContextCore( client: client, queryRequestOptions: queryRequestOptions, resourceTypeEnum: Documents.ResourceType.Document, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), resourceLink: resourceLink, isContinuationExpected: isContinuationExpected, allowNonValueAggregateQuery: allowNonValueAggregateQuery, correlatedActivityId: Guid.NewGuid()); CosmosQueryExecutionContextFactory.InputParameters inputParams = new CosmosQueryExecutionContextFactory.InputParameters() { SqlQuerySpec = sqlQuerySpec, InitialUserContinuationToken = continuationToken, MaxBufferedItemCount = queryRequestOptions.MaxBufferedItemCount, MaxConcurrency = queryRequestOptions.MaxConcurrency, MaxItemCount = queryRequestOptions.MaxItemCount, PartitionKey = queryRequestOptions.PartitionKey, Properties = queryRequestOptions.Properties, PartitionedQueryExecutionInfo = partitionedQueryExecutionInfo, ExecutionEnvironment = queryRequestOptions.ExecutionEnvironment.GetValueOrDefault(Core.ExecutionContext.ExecutionEnvironment.Client), ResponseContinuationTokenLimitInKb = queryRequestOptions.ResponseContinuationTokenLimitInKb, }; return(new QueryIterator( new CosmosQueryExecutionContextFactory( cosmosQueryContext: context, inputParameters: inputParams), queryRequestOptions.CosmosSerializationFormatOptions)); }
public static QueryIterator Create( CosmosQueryClient client, SqlQuerySpec sqlQuerySpec, string continuationToken, QueryRequestOptions queryRequestOptions, Uri resourceLink, bool isContinuationExpected, bool allowNonValueAggregateQuery, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { if (queryRequestOptions == null) { queryRequestOptions = new QueryRequestOptions(); } CosmosQueryContext cosmosQueryContext = new CosmosQueryContextCore( client: client, queryRequestOptions: queryRequestOptions, resourceTypeEnum: Documents.ResourceType.Document, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), resourceLink: resourceLink, isContinuationExpected: isContinuationExpected, allowNonValueAggregateQuery: allowNonValueAggregateQuery, correlatedActivityId: Guid.NewGuid()); CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( sqlQuerySpec: sqlQuerySpec, initialUserContinuationToken: continuationToken, maxConcurrency: queryRequestOptions.MaxConcurrency, maxItemCount: queryRequestOptions.MaxItemCount, maxBufferedItemCount: queryRequestOptions.MaxBufferedItemCount, partitionKey: queryRequestOptions.PartitionKey, properties: queryRequestOptions.Properties, partitionedQueryExecutionInfo: partitionedQueryExecutionInfo, executionEnvironment: queryRequestOptions.ExecutionEnvironment, returnResultsInDeterministicOrder: queryRequestOptions.ReturnResultsInDeterministicOrder, testInjections: queryRequestOptions.TestSettings); return(new QueryIterator( cosmosQueryContext, CosmosQueryExecutionContextFactory.Create(cosmosQueryContext, inputParameters), queryRequestOptions.CosmosSerializationFormatOptions, queryRequestOptions)); }
public static bool TryParse(string serializedQueryPlan, out PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { if (serializedQueryPlan == null) { throw new ArgumentNullException(nameof(serializedQueryPlan)); } try { partitionedQueryExecutionInfo = JsonConvert.DeserializeObject <PartitionedQueryExecutionInfo>(serializedQueryPlan); return(true); } catch (JsonException) { partitionedQueryExecutionInfo = default(PartitionedQueryExecutionInfo); return(false); } }
/// <summary> /// Gets the list of partition key ranges. /// 1. Check partition key range id /// 2. Check Partition key /// 3. Check the effective partition key /// 4. Get the range from the PartitionedQueryExecutionInfo /// </summary> internal static async Task <List <PartitionKeyRange> > GetTargetPartitionKeyRangesAsync( CosmosQueryClient queryClient, string resourceLink, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, CosmosContainerSettings collection, QueryRequestOptions queryRequestOptions) { List <PartitionKeyRange> targetRanges; if (queryRequestOptions.PartitionKey != null) { // Dis-ambiguate the NonePK if used PartitionKeyInternal partitionKeyInternal = null; if (Object.ReferenceEquals(queryRequestOptions.PartitionKey, CosmosContainerSettings.NonePartitionKeyValue)) { partitionKeyInternal = collection.GetNoneValue(); } else { partitionKeyInternal = new PartitionKey(queryRequestOptions.PartitionKey).InternalKey; } targetRanges = await queryClient.GetTargetPartitionKeyRangesByEpkStringAsync( resourceLink, collection.ResourceId, partitionKeyInternal.GetEffectivePartitionKeyString(collection.PartitionKey)); } else if (TryGetEpkProperty(queryRequestOptions, out string effectivePartitionKeyString)) { targetRanges = await queryClient.GetTargetPartitionKeyRangesByEpkStringAsync( resourceLink, collection.ResourceId, effectivePartitionKeyString); } else { targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( resourceLink, collection.ResourceId, partitionedQueryExecutionInfo.QueryRanges); } return(targetRanges); }
/// <summary> /// Initializes a new instance of the InitParams struct. /// </summary> /// <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> public CrossPartitionInitParams( string collectionRid, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, List <PartitionKeyRange> partitionKeyRanges, int initialPageSize, string requestContinuation) { if (string.IsNullOrWhiteSpace(collectionRid)) { throw new ArgumentException($"{nameof(collectionRid)} can not be null, empty, or white space."); } if (partitionedQueryExecutionInfo == null) { throw new ArgumentNullException($"{nameof(partitionedQueryExecutionInfo)} can not be null."); } if (partitionKeyRanges == null) { throw new ArgumentNullException($"{nameof(partitionKeyRanges)} can not be null."); } foreach (PartitionKeyRange partitionKeyRange in partitionKeyRanges) { if (partitionKeyRange == null) { throw new ArgumentNullException($"{nameof(partitionKeyRange)} can not be null."); } } if (initialPageSize <= 0) { throw new ArgumentOutOfRangeException($"{nameof(initialPageSize)} must be atleast 1."); } //// Request continuation is allowed to be null this.CollectionRid = collectionRid; this.PartitionedQueryExecutionInfo = partitionedQueryExecutionInfo; this.PartitionKeyRanges = partitionKeyRanges; this.InitialPageSize = initialPageSize; this.RequestContinuation = requestContinuation; }
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); // Devnote this will get replace by the new v3 to v2 logic throw new NotSupportedException("v2 query excution context is currently not supported."); //return await this.innerExecutionContext.ExecuteNextFeedResponseAsync(token); }
/// <summary> /// Gets the list of partition key ranges. /// 1. Check partition key range id /// 2. Check Partition key /// 3. Check the effective partition key /// 4. Get the range from the PartitionedQueryExecutionInfo /// </summary> internal static async Task <List <PartitionKeyRange> > GetTargetPartitionKeyRangesAsync( DefaultDocumentQueryExecutionContext queryExecutionContext, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, ContainerProperties collection, FeedOptions feedOptions) { List <PartitionKeyRange> targetRanges = null; if (!string.IsNullOrEmpty(feedOptions.PartitionKeyRangeId)) { targetRanges = new List <PartitionKeyRange>() { await queryExecutionContext.GetTargetPartitionKeyRangeByIdAsync( collection.ResourceId, feedOptions.PartitionKeyRangeId) }; } else if (feedOptions.PartitionKey != null) { targetRanges = await queryExecutionContext.GetTargetPartitionKeyRangesByEpkStringAsync( collection.ResourceId, feedOptions.PartitionKey.InternalKey.GetEffectivePartitionKeyString(collection.PartitionKey)); } else if (TryGetEpkProperty(feedOptions, out string effectivePartitionKeyString)) { targetRanges = await queryExecutionContext.GetTargetPartitionKeyRangesByEpkStringAsync( collection.ResourceId, effectivePartitionKeyString); } else { targetRanges = await queryExecutionContext.GetTargetPartitionKeyRangesAsync( collection.ResourceId, partitionedQueryExecutionInfo.QueryRanges); } return(targetRanges); }
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); }
private static bool IsOffsetLimitQuery(PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { return(partitionedQueryExecutionInfo.QueryInfo.HasOffset && partitionedQueryExecutionInfo.QueryInfo.HasLimit); }
private static bool IsAggregateQueryWithoutContinuation(PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, bool isContinuationExpected) { return(IsAggregateQuery(partitionedQueryExecutionInfo) && !isContinuationExpected); }
private static bool IsAggregateQuery(PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { return((partitionedQueryExecutionInfo.QueryInfo != null) && (partitionedQueryExecutionInfo.QueryInfo.HasAggregates)); }
private static bool IsTopOrderByQuery(PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { return((partitionedQueryExecutionInfo.QueryInfo != null) && (partitionedQueryExecutionInfo.QueryInfo.HasOrderBy || partitionedQueryExecutionInfo.QueryInfo.HasTop)); }
/// <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)); }
public static QueryIterator Create( CosmosQueryClient client, SqlQuerySpec sqlQuerySpec, string continuationToken, QueryRequestOptions queryRequestOptions, Uri resourceLink, bool isContinuationExpected, bool allowNonValueAggregateQuery, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { if (queryRequestOptions == null) { queryRequestOptions = new QueryRequestOptions(); } CosmosQueryContext cosmosQueryContext = new CosmosQueryContextCore( client: client, queryRequestOptions: queryRequestOptions, resourceTypeEnum: Documents.ResourceType.Document, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), resourceLink: resourceLink, isContinuationExpected: isContinuationExpected, allowNonValueAggregateQuery: allowNonValueAggregateQuery, correlatedActivityId: Guid.NewGuid()); CosmosElement requestContinuationToken; switch (queryRequestOptions.ExecutionEnvironment.GetValueOrDefault(ExecutionEnvironment.Client)) { case ExecutionEnvironment.Client: if (continuationToken != null) { if (!CosmosElement.TryParse(continuationToken, out requestContinuationToken)) { return(new QueryIterator( cosmosQueryContext, new QueryExecutionContextWithException( new MalformedContinuationTokenException( $"Malformed Continuation Token: {requestContinuationToken}")), queryRequestOptions.CosmosSerializationFormatOptions, queryRequestOptions)); } } else { requestContinuationToken = null; } break; case ExecutionEnvironment.Compute: requestContinuationToken = queryRequestOptions.CosmosElementContinuationToken; break; default: throw new ArgumentOutOfRangeException($"Unknown {nameof(ExecutionEnvironment)}: {queryRequestOptions.ExecutionEnvironment.Value}."); } CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( sqlQuerySpec: sqlQuerySpec, initialUserContinuationToken: requestContinuationToken, maxConcurrency: queryRequestOptions.MaxConcurrency, maxItemCount: queryRequestOptions.MaxItemCount, maxBufferedItemCount: queryRequestOptions.MaxBufferedItemCount, partitionKey: queryRequestOptions.PartitionKey, properties: queryRequestOptions.Properties, partitionedQueryExecutionInfo: partitionedQueryExecutionInfo, executionEnvironment: queryRequestOptions.ExecutionEnvironment, returnResultsInDeterministicOrder: queryRequestOptions.ReturnResultsInDeterministicOrder, testInjections: queryRequestOptions.TestSettings); return(new QueryIterator( cosmosQueryContext, CosmosQueryExecutionContextFactory.Create(cosmosQueryContext, inputParameters), queryRequestOptions.CosmosSerializationFormatOptions, queryRequestOptions)); }
public static QueryIterator Create( ContainerCore containerCore, CosmosQueryClient client, CosmosClientContext clientContext, SqlQuerySpec sqlQuerySpec, string continuationToken, FeedRangeInternal feedRangeInternal, QueryRequestOptions queryRequestOptions, string resourceLink, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool forcePassthrough, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { if (queryRequestOptions == null) { queryRequestOptions = new QueryRequestOptions(); } CosmosQueryContextCore cosmosQueryContext = new CosmosQueryContextCore( client: client, resourceTypeEnum: Documents.ResourceType.Document, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), resourceLink: resourceLink, isContinuationExpected: isContinuationExpected, allowNonValueAggregateQuery: allowNonValueAggregateQuery, correlatedActivityId: Guid.NewGuid()); NetworkAttachedDocumentContainer networkAttachedDocumentContainer = new NetworkAttachedDocumentContainer( containerCore, client, queryRequestOptions); DocumentContainer documentContainer = new DocumentContainer(networkAttachedDocumentContainer); CosmosElement requestContinuationToken; switch (queryRequestOptions.ExecutionEnvironment.GetValueOrDefault(ExecutionEnvironment.Client)) { case ExecutionEnvironment.Client: if (continuationToken != null) { TryCatch <CosmosElement> tryParse = CosmosElement.Monadic.Parse(continuationToken); if (tryParse.Failed) { return(new QueryIterator( cosmosQueryContext, new FaultedQueryPipelineStage( new MalformedContinuationTokenException( message: $"Malformed Continuation Token: {continuationToken}", innerException: tryParse.Exception)), queryRequestOptions.CosmosSerializationFormatOptions, queryRequestOptions, clientContext)); } requestContinuationToken = tryParse.Result; } else { requestContinuationToken = null; } break; case ExecutionEnvironment.Compute: requestContinuationToken = queryRequestOptions.CosmosElementContinuationToken; break; default: throw new ArgumentOutOfRangeException($"Unknown {nameof(ExecutionEnvironment)}: {queryRequestOptions.ExecutionEnvironment.Value}."); } CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( sqlQuerySpec: sqlQuerySpec, initialUserContinuationToken: requestContinuationToken, initialFeedRange: feedRangeInternal, maxConcurrency: queryRequestOptions.MaxConcurrency, maxItemCount: queryRequestOptions.MaxItemCount, maxBufferedItemCount: queryRequestOptions.MaxBufferedItemCount, partitionKey: queryRequestOptions.PartitionKey, properties: queryRequestOptions.Properties, partitionedQueryExecutionInfo: partitionedQueryExecutionInfo, executionEnvironment: queryRequestOptions.ExecutionEnvironment, returnResultsInDeterministicOrder: queryRequestOptions.ReturnResultsInDeterministicOrder, forcePassthrough: forcePassthrough, testInjections: queryRequestOptions.TestSettings); return(new QueryIterator( cosmosQueryContext, CosmosQueryExecutionContextFactory.Create(documentContainer, cosmosQueryContext, inputParameters, NoOpTrace.Singleton), queryRequestOptions.CosmosSerializationFormatOptions, queryRequestOptions, clientContext)); }
private static bool IsDistinctQuery(PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { return(partitionedQueryExecutionInfo.QueryInfo.HasDistinct); }
public static async Task <CosmosQueryExecutionContext> CreateSpecializedDocumentQueryExecutionContextAsync( CosmosQueryContext cosmosQueryContext, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, List <PartitionKeyRange> targetRanges, string collectionRid, CancellationToken cancellationToken) { if (!string.IsNullOrEmpty(partitionedQueryExecutionInfo.QueryInfo?.RewrittenQuery)) { cosmosQueryContext.SqlQuerySpec = new SqlQuerySpec( partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery, cosmosQueryContext.SqlQuerySpec.Parameters); } // Figure out the optimal page size. long initialPageSize = cosmosQueryContext.QueryRequestOptions.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 (cosmosQueryContext.IsContinuationExpected) { if (initialPageSize < 0) { if (cosmosQueryContext.QueryRequestOptions.MaxBufferedItemCount.HasValue) { // Max of what the user is willing to buffer and the default (note this is broken if MaxBufferedItemCount = -1) initialPageSize = Math.Max(cosmosQueryContext.QueryRequestOptions.MaxBufferedItemCount.Value, ParallelQueryConfig.GetConfig().DefaultMaximumBufferSize); } else { initialPageSize = 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( cosmosQueryContext, collectionRid, partitionedQueryExecutionInfo, targetRanges, (int)initialPageSize, cosmosQueryContext.QueryRequestOptions.RequestContinuation, cancellationToken)); }
private static bool IsGroupByQuery(PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { return(partitionedQueryExecutionInfo.QueryInfo.HasGroupBy); }
/// <summary> /// Creates a CosmosPipelinedItemQueryExecutionContext. /// </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 CosmosPipelinedItemQueryExecutionContext.</returns> public static async Task <CosmosQueryExecutionContext> CreateAsync( CosmosQueryContext 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.QueryRequestOptions.MaxItemCount = int.MaxValue; } Func <string, Task <IDocumentQueryExecutionComponent> > createOrderByComponentFunc = async(continuationToken) => { CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( collectionRid, partitionedQueryExecutionInfo, partitionKeyRanges, initialPageSize, continuationToken); return(await CosmosOrderByItemQueryExecutionContext.CreateAsync( constructorParams, initParams, cancellationToken)); }; Func <string, Task <IDocumentQueryExecutionComponent> > createParallelComponentFunc = async(continuationToken) => { CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( collectionRid, partitionedQueryExecutionInfo, partitionKeyRanges, initialPageSize, continuationToken); return(await CosmosParallelItemQueryExecutionContext.CreateAsync( constructorParams, initParams, cancellationToken)); }; return((CosmosQueryExecutionContext)(await PipelinedDocumentQueryExecutionContext.CreateHelperAsync( partitionedQueryExecutionInfo.QueryInfo, initialPageSize, requestContinuation, constructorParams.QueryRequestOptions.EnableGroupBy, createOrderByComponentFunc, createParallelComponentFunc))); }