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)); }
/// <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) { }