/// <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);
        }
예제 #2
0
        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));
        }
        private async Task <CosmosQueryExecutionContext> CreateItemQueryExecutionContextAsync(
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            CosmosQueryClient        cosmosQueryClient        = this.CosmosQueryContext.QueryClient;
            ContainerQueryProperties containerQueryProperties = await cosmosQueryClient.GetCachedContainerQueryPropertiesAsync(
                this.CosmosQueryContext.ResourceLink,
                this.inputParameters.PartitionKey,
                cancellationToken);

            this.CosmosQueryContext.ContainerResourceId = containerQueryProperties.ResourceId;

            PartitionedQueryExecutionInfo partitionedQueryExecutionInfo;

            if (this.CosmosQueryContext.QueryClient.ByPassQueryParsing() && TestFlag)
            {
                // 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(
                    this.CosmosQueryContext.QueryClient,
                    this.inputParameters.SqlQuerySpec,
                    this.CosmosQueryContext.ResourceLink,
                    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;
                object partitionKeyDefinitionObject;
                if (this.inputParameters.Properties != null &&
                    this.inputParameters.Properties.TryGetValue(InternalPartitionKeyDefinitionProperty, out 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(
                    this.CosmosQueryContext.QueryClient,
                    this.inputParameters.SqlQuerySpec,
                    partitionKeyDefinition,
                    this.inputParameters.PartitionKey != null,
                    cancellationToken);
            }

            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));
        }
예제 #4
0
        private async Task <CosmosQueryExecutionContext> CreateItemQueryExecutionContextAsync(
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            string continuationToken = this.inputParameters.InitialUserContinuationToken;

            if (this.inputParameters.InitialUserContinuationToken != null)
            {
                if (!PipelineContinuationToken.TryParse(
                        continuationToken,
                        out PipelineContinuationToken pipelineContinuationToken))
                {
                    throw this.CosmosQueryContext.QueryClient.CreateBadRequestException(
                              $"Malformed {nameof(PipelineContinuationToken)}: {continuationToken}.");
                }

                if (PipelineContinuationToken.IsTokenFromTheFuture(pipelineContinuationToken))
                {
                    throw this.CosmosQueryContext.QueryClient.CreateBadRequestException(
                              $"{nameof(PipelineContinuationToken)} Continuation token is from a newer version of the SDK. Upgrade the SDK to avoid this issue.\n {continuationToken}.");
                }

                if (!PipelineContinuationToken.TryConvertToLatest(
                        pipelineContinuationToken,
                        out PipelineContinuationTokenV1_1 latestVersionPipelineContinuationToken))
                {
                    throw this.CosmosQueryContext.QueryClient.CreateBadRequestException(
                              $"{nameof(PipelineContinuationToken)}: '{continuationToken}' is no longer supported.");
                }

                continuationToken = latestVersionPipelineContinuationToken.SourceContinuationToken;

                this.inputParameters.InitialUserContinuationToken = continuationToken;
                if (latestVersionPipelineContinuationToken.QueryPlan != null)
                {
                    this.inputParameters.PartitionedQueryExecutionInfo = latestVersionPipelineContinuationToken.QueryPlan;
                }
            }

            CosmosQueryClient        cosmosQueryClient        = this.CosmosQueryContext.QueryClient;
            ContainerQueryProperties containerQueryProperties = await cosmosQueryClient.GetCachedContainerQueryPropertiesAsync(
                this.CosmosQueryContext.ResourceLink,
                this.inputParameters.PartitionKey,
                cancellationToken);

            this.CosmosQueryContext.ContainerResourceId = containerQueryProperties.ResourceId;

            PartitionedQueryExecutionInfo partitionedQueryExecutionInfo;

            if (this.inputParameters.PartitionedQueryExecutionInfo != null)
            {
                partitionedQueryExecutionInfo = this.inputParameters.PartitionedQueryExecutionInfo;
            }
            else
            {
                if (this.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(
                        this.CosmosQueryContext.QueryClient,
                        this.inputParameters.SqlQuerySpec,
                        this.CosmosQueryContext.ResourceLink,
                        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;
                    object partitionKeyDefinitionObject;
                    if (this.inputParameters.Properties != null &&
                        this.inputParameters.Properties.TryGetValue(InternalPartitionKeyDefinitionProperty, out 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(
                        this.CosmosQueryContext.QueryClient,
                        this.inputParameters.SqlQuerySpec,
                        partitionKeyDefinition,
                        this.inputParameters.PartitionKey != null,
                        cancellationToken);
                }
            }

            this.partitionedQueryExecutionInfo = partitionedQueryExecutionInfo;

            return(await this.CreateFromPartitionedQuerExecutionInfoAsync(
                       partitionedQueryExecutionInfo,
                       containerQueryProperties,
                       cancellationToken));
        }