Exemple #1
0
        public static Task <PartitionedQueryExecutionInfo> GetQueryPlanThroughGatewayAsync(
            CosmosQueryContext queryContext,
            SqlQuerySpec sqlQuerySpec,
            Uri resourceLink,
            PartitionKey?partitionKey,
            CancellationToken cancellationToken = default)
        {
            if (queryContext == null)
            {
                throw new ArgumentNullException(nameof(queryContext));
            }

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

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

            cancellationToken.ThrowIfCancellationRequested();

            return(queryContext.ExecuteQueryPlanRequestAsync(
                       resourceLink,
                       ResourceType.Document,
                       OperationType.QueryPlan,
                       sqlQuerySpec,
                       partitionKey,
                       QueryPlanRetriever.SupportedQueryFeaturesString,
                       cancellationToken));
        }
 /// <summary>
 /// Callback to create a child document producer tree based on the partition key range.
 /// </summary>
 /// <param name="queryContext">request context</param>
 /// <param name="querySpecForInit">query spec for initialization</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="testFlags">Test flags.</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>
 /// <returns>A function that given a partition key range and continuation token will create a document producer.</returns>
 private static Func <Documents.PartitionKeyRange, string, ItemProducerTree> CreateItemProducerTreeCallback(
     CosmosQueryContext queryContext,
     SqlQuerySpec querySpecForInit,
     ProduceAsyncCompleteDelegate produceAsyncCompleteCallback,
     IComparer <ItemProducerTree> itemProducerTreeComparer,
     IEqualityComparer <CosmosElement> equalityComparer,
     TestInjections testFlags,
     bool deferFirstPage,
     string collectionRid,
     long initialPageSize = 50)
 {
     return((partitionKeyRange, continuationToken) =>
     {
         return new ItemProducerTree(
             queryContext,
             querySpecForInit,
             partitionKeyRange,
             produceAsyncCompleteCallback,
             itemProducerTreeComparer,
             equalityComparer,
             testFlags,
             deferFirstPage,
             collectionRid,
             initialPageSize,
             continuationToken);
     });
 }
        public static CosmosQueryExecutionContext Create(
            CosmosQueryContext cosmosQueryContext,
            InputParameters inputParameters)
        {
            if (cosmosQueryContext == null)
            {
                throw new ArgumentNullException(nameof(cosmosQueryContext));
            }

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

            CosmosQueryExecutionContextWithNameCacheStaleRetry cosmosQueryExecutionContextWithNameCacheStaleRetry = new CosmosQueryExecutionContextWithNameCacheStaleRetry(
                cosmosQueryContext: cosmosQueryContext,
                cosmosQueryExecutionContextFactory: () =>
            {
                // Query Iterator requires that the creation of the query context is deferred until the user calls ReadNextAsync
                AsyncLazy <TryCatch <CosmosQueryExecutionContext> > lazyTryCreateCosmosQueryExecutionContext = new AsyncLazy <TryCatch <CosmosQueryExecutionContext> >(valueFactory: (innerCancellationToken) =>
                {
                    innerCancellationToken.ThrowIfCancellationRequested();
                    return(CosmosQueryExecutionContextFactory.TryCreateCoreContextAsync(
                               cosmosQueryContext,
                               inputParameters,
                               innerCancellationToken));
                });
                LazyCosmosQueryExecutionContext lazyCosmosQueryExecutionContext = new LazyCosmosQueryExecutionContext(lazyTryCreateCosmosQueryExecutionContext);
                return(lazyCosmosQueryExecutionContext);
            });

            CatchAllCosmosQueryExecutionContext catchAllCosmosQueryExecutionContext = new CatchAllCosmosQueryExecutionContext(cosmosQueryExecutionContextWithNameCacheStaleRetry);

            return(catchAllCosmosQueryExecutionContext);
        }
        private static Task <TryCatch <CosmosQueryExecutionContext> > TryCreatePassthroughQueryExecutionContextAsync(
            CosmosQueryContext cosmosQueryContext,
            InputParameters inputParameters,
            PartitionedQueryExecutionInfo partitionedQueryExecutionInfo,
            List <Documents.PartitionKeyRange> targetRanges,
            string collectionRid,
            CancellationToken cancellationToken)
        {
            CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams(
                sqlQuerySpec: inputParameters.SqlQuerySpec,
                collectionRid: collectionRid,
                partitionedQueryExecutionInfo: partitionedQueryExecutionInfo,
                partitionKeyRanges: targetRanges,
                initialPageSize: inputParameters.MaxItemCount,
                maxConcurrency: inputParameters.MaxConcurrency,
                maxItemCount: inputParameters.MaxItemCount,
                maxBufferedItemCount: inputParameters.MaxBufferedItemCount,
                returnResultsInDeterministicOrder: inputParameters.ReturnResultsInDeterministicOrder,
                testSettings: inputParameters.TestInjections);

            return(PipelinedDocumentQueryExecutionContext.TryCreatePassthroughAsync(
                       inputParameters.ExecutionEnvironment,
                       cosmosQueryContext,
                       initParams,
                       inputParameters.InitialUserContinuationToken,
                       cancellationToken));
        }
Exemple #5
0
        /// <summary>
        /// Initializes a new instance of the ItemProducer class.
        /// </summary>
        /// <param name="queryContext">request context</param>
        /// <param name="querySpecForInit">query spec for initialization</param>
        /// <param name="partitionKeyRange">The partition key range.</param>
        /// <param name="produceAsyncCompleteCallback">The callback to call once you are done fetching.</param>
        /// <param name="equalityComparer">The comparer to use to determine whether the producer has seen a new document.</param>
        /// <param name="testFlags">Flags used to help faciliate testing.</param>
        /// <param name="initialPageSize">The initial page size.</param>
        /// <param name="initialContinuationToken">The initial continuation token.</param>
        public ItemProducer(
            CosmosQueryContext queryContext,
            SqlQuerySpec querySpecForInit,
            PartitionKeyRange partitionKeyRange,
            ProduceAsyncCompleteDelegate produceAsyncCompleteCallback,
            IEqualityComparer <CosmosElement> equalityComparer,
            TestInjections testFlags,
            long initialPageSize            = 50,
            string initialContinuationToken = null)
        {
            this.bufferedPages = new AsyncCollection <QueryResponseCore>();

            // We use a binary semaphore to get the behavior of a mutex,
            // since fetching documents from the backend using a continuation token is a critical section.
            this.fetchSemaphore               = new SemaphoreSlim(1, 1);
            this.queryContext                 = queryContext;
            this.querySpecForInit             = querySpecForInit;
            this.PartitionKeyRange            = partitionKeyRange ?? throw new ArgumentNullException(nameof(partitionKeyRange));
            this.produceAsyncCompleteCallback = produceAsyncCompleteCallback ?? throw new ArgumentNullException(nameof(produceAsyncCompleteCallback));
            this.equalityComparer             = equalityComparer ?? throw new ArgumentNullException(nameof(equalityComparer));
            this.pageSize = initialPageSize;
            this.CurrentContinuationToken  = initialContinuationToken;
            this.BackendContinuationToken  = initialContinuationToken;
            this.PreviousContinuationToken = initialContinuationToken;
            if (!string.IsNullOrEmpty(initialContinuationToken))
            {
                this.hasStartedFetching = true;
                this.IsActive           = true;
            }

            this.testFlags = testFlags;

            this.HasMoreResults = true;
        }
Exemple #6
0
        public static IQueryPipelineStage Create(
            DocumentContainer documentContainer,
            CosmosQueryContext cosmosQueryContext,
            InputParameters inputParameters,
            ITrace trace)
        {
            if (cosmosQueryContext == null)
            {
                throw new ArgumentNullException(nameof(cosmosQueryContext));
            }

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

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

            NameCacheStaleRetryQueryPipelineStage nameCacheStaleRetryQueryPipelineStage = new NameCacheStaleRetryQueryPipelineStage(
                cosmosQueryContext: cosmosQueryContext,
                queryPipelineStageFactory: () =>
            {
                // Query Iterator requires that the creation of the query context is deferred until the user calls ReadNextAsync
                AsyncLazy <TryCatch <IQueryPipelineStage> > lazyTryCreateStage = new AsyncLazy <TryCatch <IQueryPipelineStage> >(
                    valueFactory: (trace, innerCancellationToken) => CosmosQueryExecutionContextFactory.TryCreateCoreContextAsync(
                        documentContainer,
                        cosmosQueryContext,
                        inputParameters,
                        trace,
                        innerCancellationToken));

                LazyQueryPipelineStage lazyQueryPipelineStage = new LazyQueryPipelineStage(lazyTryCreateStage: lazyTryCreateStage, cancellationToken: default);
        public static async Task <TryCatch <CosmosParallelItemQueryExecutionContext> > TryCreateAsync(
            CosmosQueryContext queryContext,
            CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams,
            string requestContinuationToken,
            CancellationToken cancellationToken)
        {
            Debug.Assert(
                !initParams.PartitionedQueryExecutionInfo.QueryInfo.HasOrderBy,
                "Parallel~Context must not have order by query info.");

            cancellationToken.ThrowIfCancellationRequested();

            CosmosParallelItemQueryExecutionContext context = new CosmosParallelItemQueryExecutionContext(
                queryContext: queryContext,
                maxConcurrency: initParams.MaxConcurrency,
                maxItemCount: initParams.MaxItemCount,
                maxBufferedItemCount: initParams.MaxBufferedItemCount,
                testSettings: initParams.TestSettings);

            return(await context.TryInitializeAsync(
                       sqlQuerySpec : initParams.SqlQuerySpec,
                       collectionRid : initParams.CollectionRid,
                       partitionKeyRanges : initParams.PartitionKeyRanges,
                       initialPageSize : initParams.InitialPageSize,
                       requestContinuation : requestContinuationToken,
                       cancellationToken : cancellationToken));
        }
        public QueryingEnumerable(
            CosmosQueryContext cosmosQueryContext,
            ISqlExpressionFactory sqlExpressionFactory,
            IQuerySqlGeneratorFactory querySqlGeneratorFactory,
            SelectExpression selectExpression,
            Func <CosmosQueryContext, JObject, T> shaper,
            Type contextType,
            string partitionKeyFromExtension,
            bool standAloneStateManager,
            bool threadSafetyChecksEnabled)
        {
            _cosmosQueryContext       = cosmosQueryContext;
            _sqlExpressionFactory     = sqlExpressionFactory;
            _querySqlGeneratorFactory = querySqlGeneratorFactory;
            _selectExpression         = selectExpression;
            _shaper                    = shaper;
            _contextType               = contextType;
            _queryLogger               = cosmosQueryContext.QueryLogger;
            _standAloneStateManager    = standAloneStateManager;
            _threadSafetyChecksEnabled = threadSafetyChecksEnabled;

            var partitionKey = selectExpression.GetPartitionKey(cosmosQueryContext.ParameterValues);

            if (partitionKey != null && partitionKeyFromExtension != null && partitionKeyFromExtension != partitionKey)
            {
                throw new InvalidOperationException(CosmosStrings.PartitionKeyMismatch(partitionKeyFromExtension, partitionKey));
            }

            _partitionKey = partitionKey ?? partitionKeyFromExtension;
        }
Exemple #9
0
        /// <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>
        /// <param name="returnResultsInDeterministicOrder">Whether or not to return results in deterministic order.</param>
        /// <param name="testSettings">Test settings.</param>
        protected CosmosCrossPartitionQueryExecutionContext(
            CosmosQueryContext queryContext,
            int?maxConcurrency,
            int?maxItemCount,
            int?maxBufferedItemCount,
            IComparer <ItemProducerTree> moveNextComparer,
            Func <ItemProducerTree, int> fetchPrioirtyFunction,
            IEqualityComparer <CosmosElement> equalityComparer,
            bool returnResultsInDeterministicOrder,
            TestInjections testSettings)
        {
            if (moveNextComparer == null)
            {
                throw new ArgumentNullException(nameof(moveNextComparer));
            }

            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 ?? throw new ArgumentNullException(nameof(fetchPrioirtyFunction));
            this.comparableTaskScheduler = new ComparableTaskScheduler(maxConcurrency.GetValueOrDefault(0));
            this.equalityComparer        = equalityComparer ?? throw new ArgumentNullException(nameof(equalityComparer));
            this.testSettings            = testSettings;
            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;

            this.returnResultsInDeterministicOrder = returnResultsInDeterministicOrder;
        }
 public NameCacheStaleRetryQueryPipelineStage(
     CosmosQueryContext cosmosQueryContext,
     Func <IQueryPipelineStage> queryPipelineStageFactory)
 {
     this.cosmosQueryContext        = cosmosQueryContext ?? throw new ArgumentNullException(nameof(cosmosQueryContext));
     this.queryPipelineStageFactory = queryPipelineStageFactory ?? throw new ArgumentNullException(nameof(queryPipelineStageFactory));
     this.currentQueryPipelineStage = queryPipelineStageFactory();
 }
 public NetworkAttachedDocumentContainer(
     ContainerCore container,
     CosmosQueryContext cosmosQueryContext)
 {
     this.container          = container ?? throw new ArgumentNullException(nameof(container));
     this.cosmosQueryContext = cosmosQueryContext ?? throw new ArgumentNullException(nameof(cosmosQueryContext));
     this.executeQueryBasedOnFeedRangeVisitor = new ExecuteQueryBasedOnFeedRangeVisitor(this);
 }
 public CosmosQueryExecutionContextWithNameCacheStaleRetry(
     CosmosQueryContext cosmosQueryContext,
     Func <CosmosQueryExecutionContext> cosmosQueryExecutionContextFactory)
 {
     this.cosmosQueryContext = cosmosQueryContext ?? throw new ArgumentNullException(nameof(cosmosQueryContext));
     this.cosmosQueryExecutionContextFactory = cosmosQueryExecutionContextFactory ?? throw new ArgumentNullException(nameof(cosmosQueryExecutionContextFactory));
     this.currentCosmosQueryExecutionContext = cosmosQueryExecutionContextFactory();
 }
Exemple #13
0
        private static async Task <TryCatch <CosmosQueryExecutionContext> > TryCreateSpecializedDocumentQueryExecutionContextAsync(
            CosmosQueryContext cosmosQueryContext,
            InputParameters inputParameters,
            PartitionedQueryExecutionInfo partitionedQueryExecutionInfo,
            List <Documents.PartitionKeyRange> targetRanges,
            string collectionRid,
            CancellationToken cancellationToken)
        {
            QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo;

            bool getLazyFeedResponse = queryInfo.HasTop;

            // We need to compute the optimal initial page size for order-by queries
            long optimalPageSize = inputParameters.MaxItemCount;

            if (queryInfo.HasOrderBy)
            {
                int top;
                if (queryInfo.HasTop && (top = partitionedQueryExecutionInfo.QueryInfo.Top.Value) > 0)
                {
                    // All partitions should initially fetch about 1/nth of the top value.
                    long pageSizeWithTop = (long)Math.Min(
                        Math.Ceiling(top / (double)targetRanges.Count) * CosmosQueryExecutionContextFactory.PageSizeFactorForTop,
                        top);

                    optimalPageSize = Math.Min(pageSizeWithTop, optimalPageSize);
                }
                else if (cosmosQueryContext.IsContinuationExpected)
                {
                    optimalPageSize = (long)Math.Min(
                        Math.Ceiling(optimalPageSize / (double)targetRanges.Count) * CosmosQueryExecutionContextFactory.PageSizeFactorForTop,
                        optimalPageSize);
                }
            }

            Debug.Assert(
                (optimalPageSize > 0) && (optimalPageSize <= int.MaxValue),
                $"Invalid MaxItemCount {optimalPageSize}");

            CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams(
                sqlQuerySpec: inputParameters.SqlQuerySpec,
                collectionRid: collectionRid,
                partitionedQueryExecutionInfo: partitionedQueryExecutionInfo,
                partitionKeyRanges: targetRanges,
                initialPageSize: (int)optimalPageSize,
                maxConcurrency: inputParameters.MaxConcurrency,
                maxItemCount: inputParameters.MaxItemCount,
                maxBufferedItemCount: inputParameters.MaxBufferedItemCount,
                returnResultsInDeterministicOrder: inputParameters.ReturnResultsInDeterministicOrder,
                testSettings: inputParameters.TestInjections);

            return(await PipelinedDocumentQueryExecutionContext.TryCreateAsync(
                       inputParameters.ExecutionEnvironment,
                       cosmosQueryContext,
                       initParams,
                       inputParameters.InitialUserContinuationToken,
                       cancellationToken));
        }
Exemple #14
0
        public static async Task <TryCatch <CosmosQueryExecutionContext> > TryCreatePassthroughAsync(
            ExecutionEnvironment executionEnvironment,
            CosmosQueryContext queryContext,
            CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams,
            CosmosElement requestContinuationToken,
            CancellationToken cancellationToken)
        {
            if (queryContext == null)
            {
                throw new ArgumentNullException(nameof(queryContext));
            }

            cancellationToken.ThrowIfCancellationRequested();

            // Modify query plan
            PartitionedQueryExecutionInfo passThroughQueryInfo = 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 = initParams.PartitionedQueryExecutionInfo.QueryRanges,
            };

            initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams(
                sqlQuerySpec: initParams.SqlQuerySpec,
                collectionRid: initParams.CollectionRid,
                partitionedQueryExecutionInfo: passThroughQueryInfo,
                partitionKeyRanges: initParams.PartitionKeyRanges,
                initialPageSize: initParams.MaxItemCount.GetValueOrDefault(1000),
                maxConcurrency: initParams.MaxConcurrency,
                maxItemCount: initParams.MaxItemCount,
                maxBufferedItemCount: initParams.MaxBufferedItemCount,
                returnResultsInDeterministicOrder: initParams.ReturnResultsInDeterministicOrder,
                testSettings: initParams.TestSettings);

            // Return a parallel context, since we still want to be able to handle splits and concurrency / buffering.
            return((await CosmosParallelItemQueryExecutionContext.TryCreateAsync(
                        queryContext,
                        initParams,
                        requestContinuationToken,
                        cancellationToken))
                   .Try <CosmosQueryExecutionContext>((source) => new PipelinedDocumentQueryExecutionContext(
                                                          source,
                                                          initParams.InitialPageSize)));
        }
        public async Task TestMoveNextWithEmptyPagesAndSplitAsync(string initialContinuationToken)
        {
            int maxPageSize = 5;

            List <MockPartitionResponse[]> mockResponsesScenario = MockQueryFactory.GetSplitScenarios();

            foreach (MockPartitionResponse[] mockResponse in mockResponsesScenario)
            {
                Mock <CosmosQueryClient> mockQueryClient = new Mock <CosmosQueryClient>();
                IList <ToDoItem>         allItems        = MockQueryFactory.GenerateAndMockResponse(
                    mockQueryClient,
                    isOrderByQuery: false,
                    sqlQuerySpec: MockQueryFactory.DefaultQuerySpec,
                    containerRid: MockQueryFactory.DefaultCollectionRid,
                    initContinuationToken: initialContinuationToken,
                    maxPageSize: maxPageSize,
                    mockResponseForSinglePartition: mockResponse,
                    cancellationTokenForMocks: this.cancellationToken);

                CosmosQueryContext context = MockQueryFactory.CreateContext(
                    mockQueryClient.Object);

                ItemProducerTree itemProducerTree = new ItemProducerTree(
                    context,
                    MockQueryFactory.DefaultQuerySpec,
                    mockResponse[0].PartitionKeyRange,
                    MockItemProducerFactory.DefaultTreeProduceAsyncCompleteDelegate,
                    new ParallelItemProducerTreeComparer(),
                    CosmosElementEqualityComparer.Value,
                    true,
                    MockQueryFactory.DefaultCollectionRid,
                    maxPageSize,
                    initialContinuationToken: initialContinuationToken);

                Assert.IsTrue(itemProducerTree.HasMoreResults);

                List <ToDoItem> itemsRead = new List <ToDoItem>();
                while ((await itemProducerTree.MoveNextAsync(this.cancellationToken)).successfullyMovedNext)
                {
                    Assert.IsTrue(itemProducerTree.HasMoreResults);
                    if (itemProducerTree.Current != null)
                    {
                        string   jsonValue = itemProducerTree.Current.ToString();
                        ToDoItem item      = JsonConvert.DeserializeObject <ToDoItem>(jsonValue);
                        itemsRead.Add(item);
                    }
                }

                Assert.IsFalse(itemProducerTree.HasMoreResults);

                Assert.AreEqual(allItems.Count, itemsRead.Count);
                List <ToDoItem> exepected = allItems.OrderBy(x => x.id).ToList();
                List <ToDoItem> actual    = itemsRead.OrderBy(x => x.id).ToList();

                CollectionAssert.AreEqual(exepected, actual, new ToDoItemComparer());
            }
        }
        public async Task TestMoveNextWithEmptyPagesAsync(string initialContinuationToken)
        {
            int maxPageSize = 5;

            List <MockPartitionResponse[]> mockResponses = MockQueryFactory.GetAllCombinationWithEmptyPage();

            foreach (MockPartitionResponse[] mockResponse in mockResponses)
            {
                Mock <CosmosQueryClient> mockQueryClient = new Mock <CosmosQueryClient>();
                IList <ToDoItem>         allItems        = MockQueryFactory.GenerateAndMockResponse(
                    mockQueryClient,
                    isOrderByQuery: false,
                    sqlQuerySpec: MockQueryFactory.DefaultQuerySpec,
                    containerRid: MockQueryFactory.DefaultCollectionRid,
                    initContinuationToken: initialContinuationToken,
                    maxPageSize: maxPageSize,
                    mockResponseForSinglePartition: mockResponse,
                    cancellationTokenForMocks: this.cancellationToken);

                CosmosQueryContext context = MockQueryFactory.CreateContext(
                    mockQueryClient.Object);

                ItemProducerTree itemProducerTree = new ItemProducerTree(
                    queryContext: context,
                    querySpecForInit: MockQueryFactory.DefaultQuerySpec,
                    partitionKeyRange: mockResponse[0].PartitionKeyRange,
                    produceAsyncCompleteCallback: MockItemProducerFactory.DefaultTreeProduceAsyncCompleteDelegate,
                    itemProducerTreeComparer: new ParallelItemProducerTreeComparer(),
                    equalityComparer: CosmosElementEqualityComparer.Value,
                    testSettings: new TestInjections(simulate429s: false, simulateEmptyPages: false),
                    deferFirstPage: true,
                    collectionRid: MockQueryFactory.DefaultCollectionRid,
                    initialPageSize: maxPageSize,
                    initialContinuationToken: initialContinuationToken);

                Assert.IsTrue(itemProducerTree.HasMoreResults);

                List <ToDoItem> itemsRead = new List <ToDoItem>();
                while ((await itemProducerTree.TryMoveNextPageAsync(this.cancellationToken)).movedToNextPage)
                {
                    while (itemProducerTree.TryMoveNextDocumentWithinPage())
                    {
                        Assert.IsTrue(itemProducerTree.HasMoreResults);
                        string   jsonValue = itemProducerTree.Current.ToString();
                        ToDoItem item      = JsonConvert.DeserializeObject <ToDoItem>(jsonValue);
                        itemsRead.Add(item);
                    }
                }

                Assert.IsFalse(itemProducerTree.HasMoreResults);

                Assert.AreEqual(allItems.Count, itemsRead.Count);

                CollectionAssert.AreEqual(itemsRead, allItems.ToList(), new ToDoItemComparer());
            }
        }
        internal IDocumentQuery <T> CreateDocumentQuery <T>(
            SqlQuerySpec sqlQuerySpec,
            FeedOptions feedOptions = null)
        {
            EnsureArg.IsNotNull(sqlQuerySpec, nameof(sqlQuerySpec));

            var context = new CosmosQueryContext(_collectionUri, sqlQuerySpec, feedOptions);

            return(_cosmosDocumentQueryFactory.Create <T>(_documentClient.Value, context));
        }
Exemple #18
0
 public Enumerator(QueryingEnumerable <T> queryingEnumerable)
 {
     _cosmosQueryContext       = queryingEnumerable._cosmosQueryContext;
     _shaper                   = queryingEnumerable._shaper;
     _selectExpression         = queryingEnumerable._selectExpression;
     _sqlExpressionFactory     = queryingEnumerable._sqlExpressionFactory;
     _querySqlGeneratorFactory = queryingEnumerable._querySqlGeneratorFactory;
     _contextType              = queryingEnumerable._contextType;
     _logger                   = queryingEnumerable._logger;
 }
Exemple #19
0
 public AsyncEnumerator(AsyncQueryingEnumerable <T> queryingEnumerable, CancellationToken cancellationToken)
 {
     _cosmosQueryContext       = queryingEnumerable._cosmosQueryContext;
     _shaper                   = queryingEnumerable._shaper;
     _selectExpression         = queryingEnumerable._selectExpression;
     _sqlExpressionFactory     = queryingEnumerable._sqlExpressionFactory;
     _querySqlGeneratorFactory = queryingEnumerable._querySqlGeneratorFactory;
     _contextType              = queryingEnumerable._contextType;
     _logger                   = queryingEnumerable._logger;
     _cancellationToken        = cancellationToken;
 }
        public static async Task <TryCatch <IDocumentQueryExecutionComponent> > TryCreateAsync(
            CosmosQueryContext queryContext,
            CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams,
            CosmosElement requestContinuationToken,
            CancellationToken cancellationToken)
        {
            Debug.Assert(
                initParams.PartitionedQueryExecutionInfo.QueryInfo.HasOrderBy,
                "OrderBy~Context must have order by query info.");

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

            cancellationToken.ThrowIfCancellationRequested();

            // TODO (brchon): For now we are not honoring non deterministic ORDER BY queries, since there is a bug in the continuation logic.
            // We can turn it back on once the bug is fixed.
            // This shouldn't hurt any query results.
            OrderByItemProducerTreeComparer        orderByItemProducerTreeComparer = new OrderByItemProducerTreeComparer(initParams.PartitionedQueryExecutionInfo.QueryInfo.OrderBy.ToArray());
            CosmosOrderByItemQueryExecutionContext context = new CosmosOrderByItemQueryExecutionContext(
                initPararms: queryContext,
                maxConcurrency: initParams.MaxConcurrency,
                maxItemCount: initParams.MaxItemCount,
                maxBufferedItemCount: initParams.MaxBufferedItemCount,
                consumeComparer: orderByItemProducerTreeComparer,
                testSettings: initParams.TestSettings);

            IReadOnlyList <string>    orderByExpressions = initParams.PartitionedQueryExecutionInfo.QueryInfo.OrderByExpressions;
            IReadOnlyList <SortOrder> sortOrders         = initParams.PartitionedQueryExecutionInfo.QueryInfo.OrderBy;

            if (orderByExpressions.Count != sortOrders.Count)
            {
                throw new ArgumentException("order by expressions count does not match sort order");
            }

            IReadOnlyList <OrderByColumn> columns = orderByExpressions
                                                    .Zip(sortOrders, (expression, order) => new OrderByColumn(expression, order))
                                                    .ToList();

            return((await context.TryInitializeAsync(
                        sqlQuerySpec: initParams.SqlQuerySpec,
                        requestContinuation: requestContinuationToken,
                        collectionRid: initParams.CollectionRid,
                        partitionKeyRanges: initParams.PartitionKeyRanges,
                        initialPageSize: initParams.InitialPageSize,
                        orderByColumns: columns,
                        cancellationToken: cancellationToken))
                   .Try <IDocumentQueryExecutionComponent>(() => context));
        }
Exemple #21
0
            public Enumerator(QueryingEnumerable <T> queryingEnumerable)
            {
                _queryingEnumerable     = queryingEnumerable;
                _cosmosQueryContext     = queryingEnumerable._cosmosQueryContext;
                _shaper                 = queryingEnumerable._shaper;
                _selectExpression       = queryingEnumerable._selectExpression;
                _contextType            = queryingEnumerable._contextType;
                _partitionKey           = queryingEnumerable._partitionKey;
                _queryLogger            = queryingEnumerable._queryLogger;
                _standAloneStateManager = queryingEnumerable._standAloneStateManager;

                _concurrencyDetector = queryingEnumerable._threadSafetyChecksEnabled
                    ? _cosmosQueryContext.ConcurrencyDetector
                    : null;
            }
Exemple #22
0
            public Enumerator(ReadItemQueryingEnumerable <T> readItemEnumerable, CancellationToken cancellationToken = default)
            {
                _cosmosQueryContext     = readItemEnumerable._cosmosQueryContext;
                _readItemExpression     = readItemEnumerable._readItemExpression;
                _shaper                 = readItemEnumerable._shaper;
                _contextType            = readItemEnumerable._contextType;
                _queryLogger            = readItemEnumerable._queryLogger;
                _standAloneStateManager = readItemEnumerable._standAloneStateManager;
                _readItemEnumerable     = readItemEnumerable;
                _cancellationToken      = cancellationToken;

                _concurrencyDetector = readItemEnumerable._threadSafetyChecksEnabled
                    ? _cosmosQueryContext.ConcurrencyDetector
                    : null;
            }
        /// <inheritdoc />
        public ICosmosQuery <T> Create <T>(Container container, CosmosQueryContext context)
        {
            EnsureArg.IsNotNull(container, nameof(container));
            EnsureArg.IsNotNull(context, nameof(context));

            var documentQuery = container
                                .GetItemQueryIterator <T>(
                context.SqlQuerySpec,
                continuationToken: context.ContinuationToken,
                requestOptions: context.FeedOptions);

            return(new CosmosQuery <T>(
                       context,
                       documentQuery,
                       _logger));
        }
Exemple #24
0
 public ReadItemQueryingEnumerable(
     CosmosQueryContext cosmosQueryContext,
     ReadItemExpression readItemExpression,
     Func <CosmosQueryContext, JObject, T> shaper,
     Type contextType,
     bool standAloneStateManager,
     bool threadSafetyChecksEnabled)
 {
     _cosmosQueryContext        = cosmosQueryContext;
     _readItemExpression        = readItemExpression;
     _shaper                    = shaper;
     _contextType               = contextType;
     _queryLogger               = _cosmosQueryContext.QueryLogger;
     _standAloneStateManager    = standAloneStateManager;
     _threadSafetyChecksEnabled = threadSafetyChecksEnabled;
 }
        public static async Task <TryCatch <CosmosQueryExecutionContext> > TryCreateFromPartitionedQuerExecutionInfoAsync(
            PartitionedQueryExecutionInfo partitionedQueryExecutionInfo,
            ContainerQueryProperties containerQueryProperties,
            CosmosQueryContext cosmosQueryContext,
            InputParameters inputParameters,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            List <Documents.PartitionKeyRange> targetRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync(
                cosmosQueryContext.QueryClient,
                cosmosQueryContext.ResourceLink.OriginalString,
                partitionedQueryExecutionInfo,
                containerQueryProperties,
                inputParameters.Properties);

            if (!string.IsNullOrEmpty(partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery))
            {
                // We need pass down the rewritten query.
                SqlQuerySpec rewrittenQuerySpec = new SqlQuerySpec()
                {
                    QueryText  = partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery,
                    Parameters = inputParameters.SqlQuerySpec.Parameters
                };

                inputParameters = new InputParameters(
                    rewrittenQuerySpec,
                    inputParameters.InitialUserContinuationToken,
                    inputParameters.MaxConcurrency,
                    inputParameters.MaxItemCount,
                    inputParameters.MaxBufferedItemCount,
                    inputParameters.PartitionKey,
                    inputParameters.Properties,
                    inputParameters.PartitionedQueryExecutionInfo,
                    inputParameters.ExecutionEnvironment,
                    inputParameters.ReturnResultsInDeterministicOrder,
                    inputParameters.TestInjections);
            }

            return(await CosmosQueryExecutionContextFactory.TryCreateSpecializedDocumentQueryExecutionContextAsync(
                       cosmosQueryContext,
                       inputParameters,
                       partitionedQueryExecutionInfo,
                       targetRanges,
                       containerQueryProperties.ResourceId,
                       cancellationToken));
        }
Exemple #26
0
 public AsyncQueryingEnumerable(
     CosmosQueryContext cosmosQueryContext,
     ISqlExpressionFactory sqlExpressionFactory,
     IQuerySqlGeneratorFactory querySqlGeneratorFactory,
     SelectExpression selectExpression,
     Func <QueryContext, JObject, T> shaper,
     Type contextType,
     IDiagnosticsLogger <DbLoggerCategory.Query> logger)
 {
     _cosmosQueryContext       = cosmosQueryContext;
     _sqlExpressionFactory     = sqlExpressionFactory;
     _querySqlGeneratorFactory = querySqlGeneratorFactory;
     _selectExpression         = selectExpression;
     _shaper      = shaper;
     _contextType = contextType;
     _logger      = logger;
 }
            public AsyncEnumerator(QueryingEnumerable <T> queryingEnumerable, CancellationToken cancellationToken)
            {
                _queryingEnumerable     = queryingEnumerable;
                _cosmosQueryContext     = queryingEnumerable._cosmosQueryContext;
                _shaper                 = queryingEnumerable._shaper;
                _selectExpression       = queryingEnumerable._selectExpression;
                _contextType            = queryingEnumerable._contextType;
                _partitionKey           = queryingEnumerable._partitionKey;
                _queryLogger            = queryingEnumerable._queryLogger;
                _standAloneStateManager = queryingEnumerable._standAloneStateManager;
                _exceptionDetector      = _cosmosQueryContext.ExceptionDetector;
                _cancellationToken      = cancellationToken;

                _concurrencyDetector = queryingEnumerable._threadSafetyChecksEnabled
                    ? _cosmosQueryContext.ConcurrencyDetector
                    : null;
            }
 /// <summary>
 /// Initializes a new instance of the CosmosParallelItemQueryExecutionContext class.
 /// </summary>
 /// <param name="queryContext">The parameters for constructing 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="testSettings">Test settings.</param>
 private CosmosParallelItemQueryExecutionContext(
     CosmosQueryContext queryContext,
     int?maxConcurrency,
     int?maxItemCount,
     int?maxBufferedItemCount,
     TestInjections testSettings)
     : base(
         queryContext: queryContext,
         maxConcurrency: maxConcurrency,
         maxItemCount: maxItemCount,
         maxBufferedItemCount: maxBufferedItemCount,
         moveNextComparer: CosmosParallelItemQueryExecutionContext.MoveNextComparer,
         fetchPrioirtyFunction: CosmosParallelItemQueryExecutionContext.FetchPriorityFunction,
         equalityComparer: CosmosParallelItemQueryExecutionContext.EqualityComparer,
         testSettings: testSettings)
 {
 }
Exemple #29
0
        public static Task <PartitionedQueryExecutionInfo> GetQueryPlanThroughGatewayAsync(
            CosmosQueryContext queryContext,
            SqlQuerySpec sqlQuerySpec,
            string resourceLink,
            PartitionKey?partitionKey,
            ITrace trace,
            CancellationToken cancellationToken = default)
        {
            if (queryContext == null)
            {
                throw new ArgumentNullException(nameof(queryContext));
            }

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

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

            cancellationToken.ThrowIfCancellationRequested();

            using (ITrace gatewayQueryPlanTrace = trace.StartChild("Gateway QueryPlan", TraceComponent.Query, TraceLevel.Info))
            {
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
                    Documents.ServiceInteropWrapper.Is64BitProcess)
                {
                    // It's Windows and x64, should have loaded the DLL
                    gatewayQueryPlanTrace.AddDatum("ServiceInterop unavailable", true);
                }

                return(queryContext.ExecuteQueryPlanRequestAsync(
                           resourceLink,
                           ResourceType.Document,
                           OperationType.QueryPlan,
                           sqlQuerySpec,
                           partitionKey,
                           QueryPlanRetriever.SupportedQueryFeaturesString,
                           trace,
                           cancellationToken));
            }
        }
Exemple #30
0
 /// <summary>
 /// Initializes a new instance of the CosmosOrderByItemQueryExecutionContext class.
 /// </summary>
 /// <param name="initPararms">The params used to construct the base class.</param>
 /// For cross partition order by queries a query like "SELECT c.id, c.field_0 ORDER BY r.field_7 gets rewritten as:
 /// <![CDATA[
 /// SELECT r._rid, [{"item": r.field_7}] AS orderByItems, {"id": r.id, "field_0": r.field_0} AS payload
 /// FROM r
 /// WHERE({ document db - formattable order by query - filter})
 /// ORDER BY r.field_7]]>
 /// This is needed because we need to add additional filters to the query when we resume from a continuation,
 /// and it lets us easily parse out the _rid orderByItems, and payload without parsing the entire document (and having to remember the order by field).
 /// <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="consumeComparer">Comparer used to internally compare documents from different sorted partitions.</param>
 /// <param name="testSettings">Test settings.</param>
 private CosmosOrderByItemQueryExecutionContext(
     CosmosQueryContext initPararms,
     int?maxConcurrency,
     int?maxItemCount,
     int?maxBufferedItemCount,
     OrderByItemProducerTreeComparer consumeComparer,
     TestInjections testSettings)
     : base(
         queryContext: initPararms,
         maxConcurrency: maxConcurrency,
         maxItemCount: maxItemCount,
         maxBufferedItemCount: maxBufferedItemCount,
         moveNextComparer: consumeComparer,
         fetchPrioirtyFunction: CosmosOrderByItemQueryExecutionContext.FetchPriorityFunction,
         equalityComparer: new OrderByEqualityComparer(consumeComparer),
         returnResultsInDeterministicOrder: true,
         testSettings: testSettings)
 {
 }