Example #1
0
        public static Task<PartitionedQueryExecutionInfo> GetQueryPlanWithServiceInteropAsync(
            CosmosQueryClient queryClient,
            SqlQuerySpec sqlQuerySpec,
            PartitionKeyDefinition partitionKeyDefinition,
            bool hasLogicalPartitionKey,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (queryClient == null)
            {
                throw new ArgumentNullException(nameof(queryClient));
            }

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

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

            cancellationToken.ThrowIfCancellationRequested();
            QueryPlanHandler queryPlanHandler = new QueryPlanHandler(queryClient);

            return queryPlanHandler.GetQueryPlanAsync(
                    sqlQuerySpec,
                    partitionKeyDefinition,
                    QueryPlanRetriever.SupportedQueryFeatures,
                    hasLogicalPartitionKey,
                    cancellationToken);
        }
Example #2
0
        public static Task <PartitionedQueryExecutionInfo> GetQueryPlanThroughGatewayAsync(
            CosmosQueryClient client,
            SqlQuerySpec sqlQuerySpec,
            Uri resourceLink,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }

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

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

            cancellationToken.ThrowIfCancellationRequested();

            return(client.ExecuteQueryPlanRequestAsync(
                       resourceLink,
                       ResourceType.Document,
                       OperationType.QueryPlan,
                       sqlQuerySpec,
                       QueryPlanRetriever.SupportedQueryFeaturesString,
                       cancellationToken));
        }
        public static SingleGroupAggregator Create(
            CosmosQueryClient queryClient,
            AggregateOperator[] aggregates,
            IReadOnlyDictionary <string, AggregateOperator?> aggregateAliasToAggregateType,
            IReadOnlyList <string> orderedAliases,
            bool hasSelectValue,
            string continuationToken)
        {
            SingleGroupAggregator aggregateValues;

            if (hasSelectValue)
            {
                if (aggregates != null && aggregates.Any())
                {
                    // SELECT VALUE <AGGREGATE>
                    aggregateValues = SelectValueAggregateValues.Create(aggregates[0], continuationToken);
                }
                else
                {
                    // SELECT VALUE <NON AGGREGATE>
                    aggregateValues = SelectValueAggregateValues.Create(aggregateOperator: null, continuationToken: continuationToken);
                }
            }
            else
            {
                aggregateValues = SelectListAggregateValues.Create(queryClient, aggregateAliasToAggregateType, orderedAliases, continuationToken);
            }

            return(aggregateValues);
        }
 public CosmosQueryContextCore(
     CosmosQueryClient client,
     QueryRequestOptions queryRequestOptions,
     ResourceType resourceTypeEnum,
     OperationType operationType,
     Type resourceType,
     Uri resourceLink,
     Guid correlatedActivityId,
     bool isContinuationExpected,
     bool allowNonValueAggregateQuery,
     CosmosDiagnosticsContext diagnosticsContext,
     string containerResourceId = null)
     : base(
         client,
         resourceTypeEnum,
         operationType,
         resourceType,
         resourceLink,
         correlatedActivityId,
         isContinuationExpected,
         allowNonValueAggregateQuery,
         containerResourceId)
 {
     this.queryRequestOptions = queryRequestOptions;
     this.diagnosticsContext  = diagnosticsContext;
 }
        /// <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);
        }
Example #6
0
        /// <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);
        }
        public CosmosQueryContext(
            CosmosQueryClient client,
            ResourceType resourceTypeEnum,
            OperationType operationType,
            Type resourceType,
            SqlQuerySpec sqlQuerySpecFromUser,
            QueryRequestOptions queryRequestOptions,
            Uri resourceLink,
            bool getLazyFeedResponse,
            Guid correlatedActivityId,
            bool isContinuationExpected,
            bool allowNonValueAggregateQuery,
            string containerResourceId = null)
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }

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

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

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

            if (correlatedActivityId == Guid.Empty)
            {
                throw new ArgumentException(nameof(correlatedActivityId));
            }

            this.OperationTypeEnum           = operationType;
            this.QueryClient                 = client;
            this.ResourceTypeEnum            = resourceTypeEnum;
            this.ResourceType                = resourceType;
            this.SqlQuerySpec                = sqlQuerySpecFromUser;
            this.QueryRequestOptions         = queryRequestOptions;
            this.ResourceLink                = resourceLink;
            this.ContainerResourceId         = containerResourceId;
            this.IsContinuationExpected      = isContinuationExpected;
            this.AllowNonValueAggregateQuery = allowNonValueAggregateQuery;
            this.CorrelatedActivityId        = correlatedActivityId;
        }
        public static Task <PartitionedQueryExecutionInfo> GetQueryPlanWithServiceInteropAsync(
            CosmosQueryClient queryClient,
            SqlQuerySpec sqlQuerySpec,
            PartitionKeyDefinition partitionKeyDefinition,
            CancellationToken cancellationToken)
        {
            QueryPlanHandler queryPlanHandler = new QueryPlanHandler(queryClient);

            return(queryPlanHandler.GetQueryPlanAsync(
                       sqlQuerySpec,
                       partitionKeyDefinition,
                       SupportedQueryFeatures,
                       cancellationToken));
        }
            public static SelectListAggregateValues Create(
                CosmosQueryClient cosmosQueryClient,
                IReadOnlyDictionary <string, AggregateOperator?> aggregateAliasToAggregateType,
                IReadOnlyList <string> orderedAliases,
                string continuationToken)
            {
                CosmosObject aliasToContinuationToken;

                if (continuationToken != null)
                {
                    if (!CosmosElement.TryParse(continuationToken, out aliasToContinuationToken))
                    {
                        throw cosmosQueryClient.CreateBadRequestException(
                                  $"{nameof(SelectListAggregateValues)} continuation token is malformed: {continuationToken}.");
                    }
                }
                else
                {
                    aliasToContinuationToken = null;
                }

                Dictionary <string, AggregateValue> groupingTable = new Dictionary <string, AggregateValue>();

                foreach (KeyValuePair <string, AggregateOperator?> aliasToAggregate in aggregateAliasToAggregateType)
                {
                    string            alias             = aliasToAggregate.Key;
                    AggregateOperator?aggregateOperator = aliasToAggregate.Value;
                    string            aliasContinuationToken;
                    if (aliasToContinuationToken != null)
                    {
                        if (!(aliasToContinuationToken[alias] is CosmosString parsedAliasContinuationToken))
                        {
                            throw cosmosQueryClient.CreateBadRequestException(
                                      $"{nameof(SelectListAggregateValues)} continuation token is malformed: {continuationToken}.");
                        }

                        aliasContinuationToken = parsedAliasContinuationToken.Value;
                    }
                    else
                    {
                        aliasContinuationToken = null;
                    }

                    groupingTable[alias] = AggregateValue.Create(aggregateOperator, aliasContinuationToken);
                }

                return(new SelectListAggregateValues(groupingTable, orderedAliases));
            }
        public static Task <PartitionedQueryExecutionInfo> GetQueryPlanThroughGatewayAsync(
            CosmosQueryClient client,
            SqlQuerySpec sqlQuerySpec,
            Uri resourceLink,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            return(client.ExecuteQueryPlanRequestAsync(
                       resourceLink,
                       ResourceType.Document,
                       OperationType.QueryPlan,
                       sqlQuerySpec,
                       QueryPlanRetriever.SupportedQueryFeaturesString,
                       cancellationToken));
        }
        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));
        }
Example #12
0
        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));
        }
        /// <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);
        }
        public static Task <PartitionedQueryExecutionInfo> GetPartitionedQueryExecutionInfoAsync(
            CosmosQueryClient queryClient,
            SqlQuerySpec sqlQuerySpec,
            PartitionKeyDefinition partitionKeyDefinition,
            bool requireFormattableOrderByQuery,
            bool isContinuationExpected,
            bool allowNonValueAggregateQuery,
            CancellationToken cancellationToken)
        {
            // $ISSUE-felixfan-2016-07-13: We should probably get PartitionedQueryExecutionInfo from Gateway in GatewayMode

            return(queryClient.GetPartitionedQueryExecutionInfoAsync(
                       sqlQuerySpec,
                       partitionKeyDefinition,
                       requireFormattableOrderByQuery,
                       isContinuationExpected,
                       allowNonValueAggregateQuery,
                       cancellationToken));
        }
Example #15
0
        public static async Task <PartitionedQueryExecutionInfo> GetQueryPlanWithServiceInteropAsync(
            CosmosQueryClient queryClient,
            SqlQuerySpec sqlQuerySpec,
            PartitionKeyDefinition partitionKeyDefinition,
            bool hasLogicalPartitionKey,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (queryClient == null)
            {
                throw new ArgumentNullException(nameof(queryClient));
            }

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

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

            cancellationToken.ThrowIfCancellationRequested();
            QueryPlanHandler queryPlanHandler = new QueryPlanHandler(queryClient);

            TryCatch <PartitionedQueryExecutionInfo> tryGetQueryPlan = await queryPlanHandler.TryGetQueryPlanAsync(
                sqlQuerySpec,
                partitionKeyDefinition,
                QueryPlanRetriever.SupportedQueryFeatures,
                hasLogicalPartitionKey,
                cancellationToken);

            if (!tryGetQueryPlan.Succeeded)
            {
                throw new CosmosException(
                          System.Net.HttpStatusCode.BadRequest,
                          tryGetQueryPlan.Exception.Message);
            }

            return(tryGetQueryPlan.Result);
        }
        internal QueryIterator(
            CosmosQueryClient client,
            SqlQuerySpec sqlQuerySpec,
            string continuationToken,
            QueryRequestOptions queryRequestOptions,
            Uri resourceLink,
            bool isContinuationExpected,
            bool allowNonValueAggregateQuery)
        {
            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
            };

            this.cosmosSerializationFormatOptions = queryRequestOptions.CosmosSerializationFormatOptions;
            this.cosmosQueryExecutionContext      = new CosmosQueryExecutionContextFactory(
                cosmosQueryContext: context,
                inputParameters: inputParams);
        }
Example #17
0
        /// <summary>
        /// Initializes a new instance of the OrderByContinuationToken struct.
        /// </summary>
        /// <param name="queryClient">The query client</param>
        /// <param name="compositeContinuationToken">The composite continuation token (refer to property documentation).</param>
        /// <param name="orderByItems">The order by items (refer to property documentation).</param>
        /// <param name="rid">The rid (refer to property documentation).</param>
        /// <param name="skipCount">The skip count (refer to property documentation).</param>
        /// <param name="filter">The filter (refer to property documentation).</param>
        public OrderByContinuationToken(
            CosmosQueryClient queryClient,
            CompositeContinuationToken compositeContinuationToken,
            IList <OrderByItem> orderByItems,
            string rid,
            int skipCount,
            string filter)
        {
            if (compositeContinuationToken == null)
            {
                throw new ArgumentNullException($"{nameof(compositeContinuationToken)} can not be null.");
            }

            if (orderByItems == null)
            {
                throw new ArgumentNullException($"{nameof(orderByItems)} can not be null.");
            }

            if (orderByItems.Count == 0)
            {
                throw new ArgumentException($"{nameof(orderByItems)} can not be empty.");
            }

            if (string.IsNullOrWhiteSpace(rid))
            {
                throw new ArgumentNullException($"{nameof(rid)} can not be null or empty or whitespace.");
            }

            if (skipCount < 0)
            {
                throw new ArgumentException($"{nameof(skipCount)} can not be negative.");
            }

            //// filter is allowed to be null.
            this.CompositeContinuationToken = compositeContinuationToken;
            this.OrderByItems = orderByItems;
            this.Rid          = rid;
            this.SkipCount    = skipCount;
        }
 internal QueryIterator(
     CosmosQueryClient client,
     SqlQuerySpec sqlQuerySpec,
     string continuationToken,
     QueryRequestOptions queryRequestOptions,
     Uri resourceLink,
     bool isContinuationExpected,
     bool allowNonValueAggregateQuery)
 {
     this.cosmosQueryExecutionContext = new CosmosQueryExecutionContextFactory(
         client: client,
         resourceTypeEnum: Documents.ResourceType.Document,
         operationType: Documents.OperationType.Query,
         resourceType: typeof(QueryResponseCore),
         sqlQuerySpec: sqlQuerySpec,
         continuationToken: continuationToken,
         queryRequestOptions: queryRequestOptions,
         resourceLink: resourceLink,
         isContinuationExpected: isContinuationExpected,
         allowNonValueAggregateQuery: allowNonValueAggregateQuery,
         correlatedActivityId: Guid.NewGuid());
 }
Example #19
0
 public CosmosQueryContextCore(
     CosmosQueryClient client,
     ResourceType resourceTypeEnum,
     OperationType operationType,
     Type resourceType,
     string resourceLink,
     Guid correlatedActivityId,
     bool isContinuationExpected,
     bool allowNonValueAggregateQuery,
     string containerResourceId = null)
     : base(
         client,
         resourceTypeEnum,
         operationType,
         resourceType,
         resourceLink,
         correlatedActivityId,
         isContinuationExpected,
         allowNonValueAggregateQuery,
         containerResourceId)
 {
 }
Example #20
0
        public CosmosQueryContext(
            CosmosQueryClient client,
            ResourceType resourceTypeEnum,
            OperationType operationType,
            Type resourceType,
            Uri resourceLink,
            Guid correlatedActivityId,
            bool isContinuationExpected,
            bool allowNonValueAggregateQuery,
            string containerResourceId = null)
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }

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

            if (correlatedActivityId == Guid.Empty)
            {
                throw new ArgumentException(nameof(correlatedActivityId));
            }

            this.OperationTypeEnum           = operationType;
            this.QueryClient                 = client;
            this.ResourceTypeEnum            = resourceTypeEnum;
            this.ResourceType                = resourceType;
            this.ResourceLink                = resourceLink;
            this.ContainerResourceId         = containerResourceId;
            this.IsContinuationExpected      = isContinuationExpected;
            this.AllowNonValueAggregateQuery = allowNonValueAggregateQuery;
            this.CorrelatedActivityId        = correlatedActivityId;
        }
        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));
        }
Example #22
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));
        }
        /// <summary>
        /// Initializes a new instance of the CosmosCrossPartitionQueryExecutionContext class.
        /// </summary>
        /// <param name="queryContext">Constructor parameters for the base class.</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="moveNextComparer">Comparer used to figure out that document producer tree to serve documents from next.</param>
        /// <param name="fetchPrioirtyFunction">The priority function to determine which partition to fetch documents from next.</param>
        /// <param name="equalityComparer">Used to determine whether we need to return the continuation token for a partition.</param>
        protected CosmosCrossPartitionQueryExecutionContext(
            CosmosQueryContext queryContext,
            int?maxConcurrency,
            int?maxItemCount,
            int?maxBufferedItemCount,
            IComparer <ItemProducerTree> moveNextComparer,
            Func <ItemProducerTree, int> fetchPrioirtyFunction,
            IEqualityComparer <CosmosElement> equalityComparer)
        {
            if (moveNextComparer == null)
            {
                throw new ArgumentNullException(nameof(moveNextComparer));
            }

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

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

            this.queryContext            = queryContext ?? throw new ArgumentNullException(nameof(queryContext));
            this.queryClient             = queryContext.QueryClient ?? throw new ArgumentNullException(nameof(queryContext.QueryClient));
            this.itemProducerForest      = new PriorityQueue <ItemProducerTree>(moveNextComparer, isSynchronized: true);
            this.fetchPrioirtyFunction   = fetchPrioirtyFunction;
            this.comparableTaskScheduler = new ComparableTaskScheduler(maxConcurrency.GetValueOrDefault(0));
            this.equalityComparer        = equalityComparer;
            this.requestChargeTracker    = new RequestChargeTracker();
            this.diagnosticsPages        = new ConcurrentBag <QueryPageDiagnostics>();
            this.actualMaxPageSize       = maxItemCount.GetValueOrDefault(ParallelQueryConfig.GetConfig().ClientInternalMaxItemCount);

            if (this.actualMaxPageSize < 0)
            {
                throw new ArgumentOutOfRangeException("actualMaxPageSize should never be less than 0");
            }

            if (this.actualMaxPageSize > int.MaxValue)
            {
                throw new ArgumentOutOfRangeException("actualMaxPageSize should never be greater than int.MaxValue");
            }

            if (maxBufferedItemCount.HasValue)
            {
                this.actualMaxBufferedItemCount = maxBufferedItemCount.Value;
            }
            else
            {
                this.actualMaxBufferedItemCount = ParallelQueryConfig.GetConfig().DefaultMaximumBufferSize;
            }

            if (this.actualMaxBufferedItemCount < 0)
            {
                throw new ArgumentOutOfRangeException("actualMaxBufferedItemCount should never be less than 0");
            }

            if (this.actualMaxBufferedItemCount > int.MaxValue)
            {
                throw new ArgumentOutOfRangeException("actualMaxBufferedItemCount should never be greater than int.MaxValue");
            }

            this.CanPrefetch = maxConcurrency.HasValue && maxConcurrency.Value != 0;
        }
        private static async Task <PipelinedDocumentQueryExecutionContext> CreateHelperAsync(
            CosmosQueryClient queryClient,
            QueryInfo queryInfo,
            int initialPageSize,
            string requestContinuation,
            Func <string, Task <IDocumentQueryExecutionComponent> > createOrderByQueryExecutionContext,
            Func <string, Task <IDocumentQueryExecutionComponent> > createParallelQueryExecutionContext)
        {
            Func <string, Task <IDocumentQueryExecutionComponent> > createComponentFunc;

            if (queryInfo.HasOrderBy)
            {
                createComponentFunc = createOrderByQueryExecutionContext;
            }
            else
            {
                createComponentFunc = createParallelQueryExecutionContext;
            }

            if (queryInfo.HasAggregates && !queryInfo.HasGroupBy)
            {
                Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc;
                createComponentFunc = async(continuationToken) =>
                {
                    return(await AggregateDocumentQueryExecutionComponent.CreateAsync(
                               queryInfo.Aggregates,
                               queryInfo.GroupByAliasToAggregateType,
                               queryInfo.HasSelectValue,
                               continuationToken,
                               createSourceCallback));
                };
            }

            if (queryInfo.HasDistinct)
            {
                Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc;
                createComponentFunc = async(continuationToken) =>
                {
                    return(await DistinctDocumentQueryExecutionComponent.CreateAsync(
                               queryClient,
                               continuationToken,
                               createSourceCallback,
                               queryInfo.DistinctType));
                };
            }

            if (queryInfo.HasGroupBy)
            {
                Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc;
                createComponentFunc = async(continuationToken) =>
                {
                    return(await GroupByDocumentQueryExecutionComponent.CreateAsync(
                               continuationToken,
                               createSourceCallback,
                               queryInfo.GroupByAliasToAggregateType,
                               queryInfo.HasSelectValue));
                };
            }

            if (queryInfo.HasOffset)
            {
                Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc;
                createComponentFunc = async(continuationToken) =>
                {
                    return(await SkipDocumentQueryExecutionComponent.CreateAsync(
                               queryInfo.Offset.Value,
                               continuationToken,
                               createSourceCallback));
                };
            }

            if (queryInfo.HasLimit)
            {
                Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc;
                createComponentFunc = async(continuationToken) =>
                {
                    return(await TakeDocumentQueryExecutionComponent.CreateLimitDocumentQueryExecutionComponentAsync(
                               queryClient,
                               queryInfo.Limit.Value,
                               continuationToken,
                               createSourceCallback));
                };
            }

            if (queryInfo.HasTop)
            {
                Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc;
                createComponentFunc = async(continuationToken) =>
                {
                    return(await TakeDocumentQueryExecutionComponent.CreateTopDocumentQueryExecutionComponentAsync(
                               queryClient,
                               queryInfo.Top.Value,
                               continuationToken,
                               createSourceCallback));
                };
            }

            return(new PipelinedDocumentQueryExecutionContext(
                       await createComponentFunc(requestContinuation), initialPageSize));
        }
        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));
        }
        /// <summary>
        /// Initializes a new instance of the ItemProducerTree class.
        /// </summary>
        /// <param name="queryContext">query context.</param>
        /// <param name="querySpecForInit">query spec init.</param>
        /// <param name="partitionKeyRange">The partition key range.</param>
        /// <param name="produceAsyncCompleteCallback">Callback to invoke once a fetch finishes.</param>
        /// <param name="itemProducerTreeComparer">Comparer to determine, which tree to produce from.</param>
        /// <param name="equalityComparer">Comparer to see if we need to return the continuation token for a partition.</param>
        /// <param name="deferFirstPage">Whether or not to defer fetching the first page.</param>
        /// <param name="collectionRid">The collection to drain from.</param>
        /// <param name="initialPageSize">The initial page size.</param>
        /// <param name="initialContinuationToken">The initial continuation token.</param>
        public ItemProducerTree(
            CosmosQueryContext queryContext,
            SqlQuerySpec querySpecForInit,
            PartitionKeyRange partitionKeyRange,
            Action <ItemProducerTree, int, double, QueryMetrics, long, CancellationToken> produceAsyncCompleteCallback,
            IComparer <ItemProducerTree> itemProducerTreeComparer,
            IEqualityComparer <CosmosElement> equalityComparer,
            bool deferFirstPage,
            string collectionRid,
            long initialPageSize            = 50,
            string initialContinuationToken = null)
        {
            if (queryContext == null)
            {
                throw new ArgumentNullException($"{nameof(queryContext)}");
            }

            if (itemProducerTreeComparer == null)
            {
                throw new ArgumentNullException($"{nameof(itemProducerTreeComparer)}");
            }

            if (produceAsyncCompleteCallback == null)
            {
                throw new ArgumentNullException($"{nameof(produceAsyncCompleteCallback)}");
            }

            if (itemProducerTreeComparer == null)
            {
                throw new ArgumentNullException($"{nameof(itemProducerTreeComparer)}");
            }

            if (equalityComparer == null)
            {
                throw new ArgumentNullException($"{nameof(equalityComparer)}");
            }

            if (string.IsNullOrEmpty(collectionRid))
            {
                throw new ArgumentException($"{nameof(collectionRid)} can not be null or empty.");
            }

            this.Root = new ItemProducer(
                queryContext,
                querySpecForInit,
                partitionKeyRange,
                (itemProducer, itemsBuffered, resourceUnitUsage, queryMetrics, requestLength, token) => produceAsyncCompleteCallback(this, itemsBuffered, resourceUnitUsage, queryMetrics, requestLength, token),
                equalityComparer,
                initialPageSize,
                initialContinuationToken);

            this.queryClient    = queryContext.QueryClient;
            this.children       = new PriorityQueue <ItemProducerTree>(itemProducerTreeComparer, true);
            this.deferFirstPage = deferFirstPage;
            this.collectionRid  = collectionRid;
            this.createItemProducerTreeCallback = ItemProducerTree.CreateItemProducerTreeCallback(
                queryContext,
                querySpecForInit,
                produceAsyncCompleteCallback,
                itemProducerTreeComparer,
                equalityComparer,
                deferFirstPage,
                collectionRid,
                initialPageSize);
            this.executeWithSplitProofingSemaphore = new SemaphoreSlim(1, 1);
        }
        public CosmosQueryExecutionContextFactory(
            CosmosQueryClient client,
            ResourceType resourceTypeEnum,
            OperationType operationType,
            Type resourceType,
            SqlQuerySpec sqlQuerySpec,
            QueryRequestOptions queryRequestOptions,
            Uri resourceLink,
            bool isContinuationExpected,
            bool allowNonValueAggregateQuery,
            Guid correlatedActivityId)
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }

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

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

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

            // Prevent users from updating the values after creating the execution context.
            QueryRequestOptions cloneQueryRequestOptions = queryRequestOptions.Clone();

            // Swapping out negative values in feedOptions for int.MaxValue
            if (cloneQueryRequestOptions.MaxBufferedItemCount.HasValue && cloneQueryRequestOptions.MaxBufferedItemCount < 0)
            {
                cloneQueryRequestOptions.MaxBufferedItemCount = int.MaxValue;
            }

            if (cloneQueryRequestOptions.MaxConcurrency.HasValue && cloneQueryRequestOptions.MaxConcurrency < 0)
            {
                cloneQueryRequestOptions.MaxConcurrency = int.MaxValue;
            }

            if (cloneQueryRequestOptions.MaxItemCount.HasValue && cloneQueryRequestOptions.MaxItemCount < 0)
            {
                cloneQueryRequestOptions.MaxItemCount = int.MaxValue;
            }

            this.cosmosQueryContext = new CosmosQueryContext(
                client: client,
                resourceTypeEnum: resourceTypeEnum,
                operationType: operationType,
                resourceType: resourceType,
                sqlQuerySpecFromUser: sqlQuerySpec,
                queryRequestOptions: cloneQueryRequestOptions,
                resourceLink: resourceLink,
                getLazyFeedResponse: isContinuationExpected,
                isContinuationExpected: isContinuationExpected,
                allowNonValueAggregateQuery: allowNonValueAggregateQuery,
                correlatedActivityId: correlatedActivityId);
        }
        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));
        }