public override PipelineContinuationTokenTestsOutput ExecuteTest( PipelineContinuationTokenTestsInput input) { TryCatch <CosmosElement> tryParse = CosmosElement.Monadic.Parse(input.ContinuationToken); if (tryParse.Failed) { return(new PipelineContinuationTokenTestsOutputNegative("Failed to parse token.")); } if (!PipelineContinuationToken.TryCreateFromCosmosElement( tryParse.Result, out PipelineContinuationToken pipelineContinuationToken)) { return(new PipelineContinuationTokenTestsOutputNegative("Failed to parse token.")); } if (!PipelineContinuationToken.TryConvertToLatest( pipelineContinuationToken, out PipelineContinuationTokenV1_1 latestPipelineContinuationToken)) { return(new PipelineContinuationTokenTestsOutputNegative("Failed to convert to latest")); } return(new PipelineContinuationTokenTestsOutputPositive( pipelineContinuationToken, latestPipelineContinuationToken)); }
internal PipelineContinuationTokenTestsOutputPositive( PipelineContinuationToken parsedToken, PipelineContinuationToken latestToken) { this.ParsedToken = parsedToken; this.LatestToken = latestToken; }
public override PipelineContinuationTokenTestsOutput ExecuteTest( PipelineContinuationTokenTestsInput input) { if (!CosmosElement.TryParse(input.ContinuationToken, out CosmosElement cosmosElementContinuationToken)) { return(new PipelineContinuationTokenTestsOutputNegative("Failed to parse token.")); } if (!PipelineContinuationToken.TryCreateFromCosmosElement( cosmosElementContinuationToken, out PipelineContinuationToken pipelineContinuationToken)) { return(new PipelineContinuationTokenTestsOutputNegative("Failed to parse token.")); } if (!PipelineContinuationToken.TryConvertToLatest( pipelineContinuationToken, out PipelineContinuationTokenV1_1 latestPipelineContinuationToken)) { return(new PipelineContinuationTokenTestsOutputNegative("Failed to convert to latest")); } return(new PipelineContinuationTokenTestsOutputPositive( pipelineContinuationToken, latestPipelineContinuationToken)); }
private static async Task <TryCatch <CosmosQueryExecutionContext> > TryCreateCoreContextAsync( CosmosQueryContext cosmosQueryContext, InputParameters inputParameters, CancellationToken cancellationToken) { // The default using (cosmosQueryContext.CreateDiagnosticScope("CreateQueryPipeline")) { // Try to parse the continuation token. CosmosElement continuationToken = inputParameters.InitialUserContinuationToken; PartitionedQueryExecutionInfo queryPlanFromContinuationToken = inputParameters.PartitionedQueryExecutionInfo; if (continuationToken != null) { if (!PipelineContinuationToken.TryCreateFromCosmosElement( continuationToken, out PipelineContinuationToken pipelineContinuationToken)) { return(TryCatch <CosmosQueryExecutionContext> .FromException( new MalformedContinuationTokenException( $"Malformed {nameof(PipelineContinuationToken)}: {continuationToken}."))); } if (PipelineContinuationToken.IsTokenFromTheFuture(pipelineContinuationToken)) { return(TryCatch <CosmosQueryExecutionContext> .FromException( new MalformedContinuationTokenException( $"{nameof(PipelineContinuationToken)} Continuation token is from a newer version of the SDK. " + $"Upgrade the SDK to avoid this issue." + $"{continuationToken}."))); } if (!PipelineContinuationToken.TryConvertToLatest( pipelineContinuationToken, out PipelineContinuationTokenV1_1 latestVersionPipelineContinuationToken)) { return(TryCatch <CosmosQueryExecutionContext> .FromException( new MalformedContinuationTokenException( $"{nameof(PipelineContinuationToken)}: '{continuationToken}' is no longer supported."))); } continuationToken = latestVersionPipelineContinuationToken.SourceContinuationToken; if (latestVersionPipelineContinuationToken.QueryPlan != null) { queryPlanFromContinuationToken = latestVersionPipelineContinuationToken.QueryPlan; } } CosmosQueryClient cosmosQueryClient = cosmosQueryContext.QueryClient; ContainerQueryProperties containerQueryProperties = await cosmosQueryClient.GetCachedContainerQueryPropertiesAsync( cosmosQueryContext.ResourceLink, inputParameters.PartitionKey, cancellationToken); cosmosQueryContext.ContainerResourceId = containerQueryProperties.ResourceId; PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; if (inputParameters.ForcePassthrough) { partitionedQueryExecutionInfo = new PartitionedQueryExecutionInfo() { QueryInfo = new QueryInfo() { Aggregates = null, DistinctType = DistinctQueryType.None, GroupByAliases = null, GroupByAliasToAggregateType = null, GroupByExpressions = null, HasSelectValue = false, Limit = null, Offset = null, OrderBy = null, OrderByExpressions = null, RewrittenQuery = null, Top = null, }, QueryRanges = new List <Documents.Routing.Range <string> >(), }; } else if (queryPlanFromContinuationToken != null) { partitionedQueryExecutionInfo = queryPlanFromContinuationToken; } else { // If the query would go to gateway, but we have a partition key, // then try seeing if we can execute as a passthrough using client side only logic. // This is to short circuit the need to go to the gateway to get the query plan. if (cosmosQueryContext.QueryClient.ByPassQueryParsing() && inputParameters.PartitionKey.HasValue) { bool parsed; SqlQuery sqlQuery; using (cosmosQueryContext.CreateDiagnosticScope("QueryParsing")) { parsed = SqlQuery.TryParse(inputParameters.SqlQuerySpec.QueryText, out sqlQuery); } if (parsed) { bool hasDistinct = sqlQuery.SelectClause.HasDistinct; bool hasGroupBy = sqlQuery.GroupByClause != default; bool hasAggregates = AggregateProjectionDetector.HasAggregate(sqlQuery.SelectClause.SelectSpec); bool createPassthroughQuery = !hasAggregates && !hasDistinct && !hasGroupBy; if (createPassthroughQuery) { TestInjections.ResponseStats responseStats = inputParameters?.TestInjections?.Stats; if (responseStats != null) { responseStats.PipelineType = TestInjections.PipelineType.Passthrough; } // Only thing that matters is that we target the correct range. Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); List <Documents.PartitionKeyRange> targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesByEpkStringAsync( cosmosQueryContext.ResourceLink, containerQueryProperties.ResourceId, inputParameters.PartitionKey.Value.InternalKey.GetEffectivePartitionKeyString(partitionKeyDefinition)); return(await CosmosQueryExecutionContextFactory.TryCreatePassthroughQueryExecutionContextAsync( cosmosQueryContext, inputParameters, partitionedQueryExecutionInfo : new PartitionedQueryExecutionInfo(), targetRanges, containerQueryProperties.ResourceId, cancellationToken)); } } } if (cosmosQueryContext.QueryClient.ByPassQueryParsing()) { // 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 partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanThroughGatewayAsync( cosmosQueryContext, inputParameters.SqlQuerySpec, cosmosQueryContext.ResourceLink, inputParameters.PartitionKey, cancellationToken); } else { using (cosmosQueryContext.CreateDiagnosticScope("ServiceInterop")) { Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanWithServiceInteropAsync( cosmosQueryContext.QueryClient, inputParameters.SqlQuerySpec, partitionKeyDefinition, inputParameters.PartitionKey != null, cancellationToken); } } } return(await TryCreateFromPartitionedQuerExecutionInfoAsync( partitionedQueryExecutionInfo, containerQueryProperties, cosmosQueryContext, inputParameters, cancellationToken)); } }
private static async Task <TryCatch <CosmosQueryExecutionContext> > TryCreateCoreContextAsync( CosmosQueryContext cosmosQueryContext, InputParameters inputParameters, CancellationToken cancellationToken) { // Try to parse the continuation token. string continuationToken = inputParameters.InitialUserContinuationToken; PartitionedQueryExecutionInfo queryPlanFromContinuationToken = inputParameters.PartitionedQueryExecutionInfo; if (continuationToken != null) { if (!PipelineContinuationToken.TryParse( continuationToken, out PipelineContinuationToken pipelineContinuationToken)) { return(TryCatch <CosmosQueryExecutionContext> .FromException( new MalformedContinuationTokenException( $"Malformed {nameof(PipelineContinuationToken)}: {continuationToken}."))); } if (PipelineContinuationToken.IsTokenFromTheFuture(pipelineContinuationToken)) { return(TryCatch <CosmosQueryExecutionContext> .FromException( new MalformedContinuationTokenException( $"{nameof(PipelineContinuationToken)} Continuation token is from a newer version of the SDK. " + $"Upgrade the SDK to avoid this issue." + $"{continuationToken}."))); } if (!PipelineContinuationToken.TryConvertToLatest( pipelineContinuationToken, out PipelineContinuationTokenV1_1 latestVersionPipelineContinuationToken)) { return(TryCatch <CosmosQueryExecutionContext> .FromException( new MalformedContinuationTokenException( $"{nameof(PipelineContinuationToken)}: '{continuationToken}' is no longer supported."))); } continuationToken = latestVersionPipelineContinuationToken.SourceContinuationToken; if (latestVersionPipelineContinuationToken.QueryPlan != null) { queryPlanFromContinuationToken = latestVersionPipelineContinuationToken.QueryPlan; } } CosmosQueryClient cosmosQueryClient = cosmosQueryContext.QueryClient; ContainerQueryProperties containerQueryProperties = await cosmosQueryClient.GetCachedContainerQueryPropertiesAsync( cosmosQueryContext.ResourceLink, inputParameters.PartitionKey, cancellationToken); cosmosQueryContext.ContainerResourceId = containerQueryProperties.ResourceId; PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; if (queryPlanFromContinuationToken != null) { partitionedQueryExecutionInfo = queryPlanFromContinuationToken; } else { if (cosmosQueryContext.QueryClient.ByPassQueryParsing()) { // 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 partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanThroughGatewayAsync( cosmosQueryContext.QueryClient, inputParameters.SqlQuerySpec, cosmosQueryContext.ResourceLink, inputParameters.PartitionKey, cancellationToken); } else { //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. Documents.PartitionKeyDefinition partitionKeyDefinition; if ((inputParameters.Properties != null) && inputParameters.Properties.TryGetValue(InternalPartitionKeyDefinitionProperty, out object partitionKeyDefinitionObject)) { if (partitionKeyDefinitionObject is Documents.PartitionKeyDefinition definition) { partitionKeyDefinition = definition; } else { throw new ArgumentException( "partitionkeydefinition has invalid type", nameof(partitionKeyDefinitionObject)); } } else { partitionKeyDefinition = containerQueryProperties.PartitionKeyDefinition; } partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanWithServiceInteropAsync( cosmosQueryContext.QueryClient, inputParameters.SqlQuerySpec, partitionKeyDefinition, inputParameters.PartitionKey != null, cancellationToken); } } return(await TryCreateFromPartitionedQuerExecutionInfoAsync( partitionedQueryExecutionInfo, containerQueryProperties, cosmosQueryContext, inputParameters, cancellationToken)); }
/// <summary> /// Creates a CosmosPipelinedItemQueryExecutionContext. /// </summary> /// <param name="executionEnvironment">The environment to execute on.</param> /// <param name="queryContext">The parameters for constructing the base class.</param> /// <param name="initParams">The initial parameters</param> /// <param name="requestContinuationToken">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( ExecutionEnvironment executionEnvironment, CosmosQueryContext queryContext, CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams, string requestContinuationToken, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (requestContinuationToken != null) { if (!PipelineContinuationToken.TryParse( requestContinuationToken, out PipelineContinuationToken pipelineContinuationToken)) { throw queryContext.QueryClient.CreateBadRequestException( $"Malformed {nameof(PipelineContinuationToken)}: {requestContinuationToken}."); } if (PipelineContinuationToken.IsTokenFromTheFuture(pipelineContinuationToken)) { throw queryContext.QueryClient.CreateBadRequestException( $"{nameof(PipelineContinuationToken)} Continuation token is from a newer version of the SDK. Upgrade the SDK to avoid this issue.\n {requestContinuationToken}."); } if (!PipelineContinuationToken.TryConvertToLatest( pipelineContinuationToken, out PipelineContinuationTokenV1_1 latestVersionPipelineContinuationToken)) { throw queryContext.QueryClient.CreateBadRequestException( $"{nameof(PipelineContinuationToken)}: '{requestContinuationToken}' is no longer supported."); } requestContinuationToken = latestVersionPipelineContinuationToken.SourceContinuationToken; } QueryInfo queryInfo = initParams.PartitionedQueryExecutionInfo.QueryInfo; int initialPageSize = initParams.InitialPageSize; CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams parameters = initParams; if (queryInfo.HasGroupBy) { // The query will block until all groupings are gathered so we might as well speed up the process. initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( sqlQuerySpec: initParams.SqlQuerySpec, collectionRid: initParams.CollectionRid, partitionedQueryExecutionInfo: initParams.PartitionedQueryExecutionInfo, partitionKeyRanges: initParams.PartitionKeyRanges, initialPageSize: int.MaxValue, maxConcurrency: initParams.MaxConcurrency, maxItemCount: int.MaxValue, maxBufferedItemCount: initParams.MaxBufferedItemCount); } Func <string, Task <IDocumentQueryExecutionComponent> > createOrderByComponentFunc = async(continuationToken) => { return(await CosmosOrderByItemQueryExecutionContext.CreateAsync( queryContext, initParams, continuationToken, cancellationToken)); }; Func <string, Task <IDocumentQueryExecutionComponent> > createParallelComponentFunc = async(continuationToken) => { return(await CosmosParallelItemQueryExecutionContext.CreateAsync( queryContext, initParams, continuationToken, cancellationToken)); }; return((CosmosQueryExecutionContext)await PipelinedDocumentQueryExecutionContext.CreateHelperAsync( executionEnvironment, queryContext.QueryClient, initParams.PartitionedQueryExecutionInfo.QueryInfo, initialPageSize, requestContinuationToken, createOrderByComponentFunc, createParallelComponentFunc)); }