diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 01be3ffc83..e7a65b7457 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -34,7 +34,7 @@ internal static class CosmosQueryExecutionContextFactory { internal const string ClientDisableOptimisticDirectExecution = "clientDisableOptimisticDirectExecution"; private const string InternalPartitionKeyDefinitionProperty = "x-ms-query-partitionkey-definition"; - private const string QueryInspectionPattern = @"\s+(GROUP\s+BY\s+|COUNT\s*\(|MIN\s*\(|MAX\s*\(|AVG\s*\(|SUM\s*\(|DISTINCT\s+)"; + private const string QueryInspectionPattern = @"\s*(GROUP\s+BY\s+|COUNT\s*\(|MIN\s*\(|MAX\s*\(|AVG\s*\(|SUM\s*\(|DISTINCT\s+)"; private const string OptimisticDirectExecution = "OptimisticDirectExecution"; private const string Passthrough = "Passthrough"; private const string Specialized = "Specialized"; @@ -782,7 +782,7 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP Debug.Assert(containerQueryProperties.ResourceId != null, "CosmosQueryExecutionContextFactory Assert!", "Container ResourceId cannot be null!"); List targetRanges; - if (partitionedQueryExecutionInfo != null) + if (partitionedQueryExecutionInfo != null || inputParameters.InitialFeedRange != null) { targetRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync( cosmosQueryContext.QueryClient, diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index a4557da6d2..3e410c3892 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -50,15 +50,7 @@ public class QueryRequestOptions : RequestOptions /// /// Direct (optimistic) execution offers improved performance for several kinds of queries such as a single partition streaming query. /// -#if PREVIEW - public -#else - internal -#endif - bool EnableOptimisticDirectExecution { get; set; } -#if PREVIEW - = true; -#endif + public bool EnableOptimisticDirectExecution { get; set; } = true; /// /// Gets or sets the maximum number of items that can be buffered client side during diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index eeb3c0d890..ab07cd8448 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -34,8 +34,12 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -206,6 +210,16 @@ "name": "Service Interop Query Plan", "duration in milliseconds": 0 }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "Get Partition Key Ranges", "duration in milliseconds": 0, @@ -218,6 +232,16 @@ } ] }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "MoveNextAsync", "duration in milliseconds": 0, @@ -755,8 +779,12 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -931,6 +959,16 @@ "name": "Service Interop Query Plan", "duration in milliseconds": 0 }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "Get Partition Key Ranges", "duration in milliseconds": 0, @@ -943,6 +981,16 @@ } ] }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "MoveNextAsync", "duration in milliseconds": 0, @@ -1497,8 +1545,12 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1678,6 +1730,26 @@ "duration in milliseconds": 0 } ] + }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + } + ] + }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 } ] }, @@ -2219,8 +2291,12 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2395,6 +2471,16 @@ "name": "Service Interop Query Plan", "duration in milliseconds": 0 }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "Get Partition Key Ranges", "duration in milliseconds": 0, @@ -2407,6 +2493,16 @@ } ] }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "MoveNextAsync", "duration in milliseconds": 0, @@ -2985,8 +3081,12 @@ │ │ │ [PointOperationStatisticsTraceDatum] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) + │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -3220,6 +3320,26 @@ "duration in milliseconds": 0 } ] + }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + } + ] + }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 } ] }, @@ -3779,9 +3899,15 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -3967,6 +4093,38 @@ ] } ] + }, + { + "name": "Get Overlapping Feed Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + } + ] + } + ] + }, + { + "name": "Get Overlapping Feed Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] } ] }, @@ -4510,9 +4668,15 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -4702,6 +4866,38 @@ ] } ] + }, + { + "name": "Get Overlapping Feed Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + } + ] + } + ] + }, + { + "name": "Get Overlapping Feed Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] } ] }, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index af2afbcb73..55033eeb40 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -25,120 +25,105 @@ │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── Create Query Pipeline(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── [05C1CFFFFFFFF8,05C1DFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── [05C1CFFFFFFFF8,05C1DFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Query Metrics] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [System Info] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── [05C1CFFFFFFFF8,05C1DFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Query Metrics] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [System Info] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ├── Execute query for a partitionkeyrange(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds │ │ ( │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── Create Query Pipeline(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Query Metrics] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [System Info] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Query Metrics] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [System Info] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds └── Execute query for a partitionkeyrange(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds │ ( │ [Query Correlated ActivityId] │ Redacted To Not Change The Baselines From Run To Run │ ) ├── Create Query Pipeline(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - └── [05C1E7FFFFFFFA,FF) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - └── [05C1E7FFFFFFFA,FF) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Query Metrics] - │ Redacted To Not Change The Baselines From Run To Run - │ ) - ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [System Info] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) - └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds + │ └── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + └── [05C1E7FFFFFFFA,FF) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Query Metrics] + │ Redacted To Not Change The Baselines From Run To Run + │ ) + ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [System Info] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) + └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ]]> 10) ORDER BY v2 ASC ]]> - + @@ -423,7 +423,7 @@ JOIN ( WHERE ((LENGTH(v2["FamilyName"]) > 10) AND (LENGTH(v2["FamilyName"]) < 20)) ORDER BY v2 ASC ]]> - + @@ -442,7 +442,7 @@ JOIN ( WHERE ((LENGTH(v2["FamilyName"]) > 10) AND (LENGTH(v2["FamilyName"]) < 20)) ORDER BY v2 ASC ]]> - + @@ -482,7 +482,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -559,7 +559,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -578,7 +578,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -597,7 +597,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2["GivenName"]["Length"] ASC ]]> - + @@ -616,7 +616,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2["GivenName"]["Length"] ASC ]]> - + @@ -635,7 +635,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -654,7 +654,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -689,7 +689,7 @@ JOIN ( JOIN v0 IN root["Parents"]) AS v2 ORDER BY v2["FamilyName"] ASC ]]> - + @@ -707,7 +707,7 @@ JOIN ( JOIN v0 IN root["Parents"]) AS v2 ORDER BY v2["FamilyName"] ASC ]]> - + @@ -773,7 +773,7 @@ JOIN ( JOIN p0 IN root["Parents"]) AS v1 ORDER BY v1 ASC ]]> - + @@ -792,7 +792,7 @@ JOIN ( WHERE (LENGTH(v1) > 10) ORDER BY v1 ASC ]]> - + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml index 73b8b19748..75054876fc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml @@ -119,7 +119,7 @@ JOIN ( SELECT VALUE root FROM root ORDER BY root["FamilyId"] ASC, root["FamilyId"] ASC]]> - + @@ -132,7 +132,7 @@ ORDER BY root["FamilyId"] ASC, root["FamilyId"] ASC]]> SELECT VALUE root FROM root ORDER BY root["FamilyId"] ASC, root["FamilyId"] DESC]]> - + @@ -388,7 +388,6 @@ FROM ( JOIN c0 IN root["Children"]) AS v1) AS r1 ORDER BY r1["FamilyId"] ASC, r1["FamilyNumber"] ASC ]]> - @@ -435,7 +434,6 @@ FROM ( WHERE (p0["GivenName"]["Length"] > 5)) AS v0) AS r0 ORDER BY r0["FamilyId"] ASC, r0["FamilyNumber"] ASC ]]> - @@ -586,7 +584,7 @@ FROM root JOIN f0 IN root["Records"]["Transactions"] WHERE (ARRAY_LENGTH(root["Children"]) > 0) ORDER BY f0["Type"] ASC, f0["Amount"] ASC]]> - + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs index bfd6366104..a50ff87fe0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs @@ -240,9 +240,7 @@ public async Task QueryRequestRateTest(bool directMode) { MaxItemCount = 1, MaxConcurrency = 1, -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif + EnableOptimisticDirectExecution = false, })) { while (feedIterator.HasMoreResults) @@ -271,9 +269,7 @@ public async Task QueryRequestRateTest(bool directMode) { MaxItemCount = 1, MaxConcurrency = 1, -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif + EnableOptimisticDirectExecution = false, }); // First request should be a success @@ -803,7 +799,6 @@ public async Task TesOdeTokenCompatibilityWithNonOdePipeline() QueryRequestOptions queryRequestOptions = new QueryRequestOptions { MaxItemCount = 50, - EnableOptimisticDirectExecution = true }; FeedIteratorInternal feedIterator = @@ -833,7 +828,7 @@ public async Task TesOdeTokenCompatibilityWithNonOdePipeline() responseMessage = await feedIteratorNew.ReadNextAsync(CancellationToken.None); } - string expectedErrorMessage = "The continuation token supplied requires the Optimistic Direct Execution flag to be enabled in QueryRequestOptions for the query execution to resume. "; + string expectedErrorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. "; Assert.IsTrue(responseMessage.CosmosException.ToString().Contains(expectedErrorMessage)); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs index 241b60fb7f..7931bc607a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs @@ -83,9 +83,8 @@ public async Task QueryPlanRetryTimeoutTestAsync() QueryRequestOptions requestOptions = new QueryRequestOptions() { -#if PREVIEW + // ODE set to false in this scenario as using ODE could cause the query plan to not get invoked. EnableOptimisticDirectExecution = false -#endif }; using FeedIterator iterator = gatewayQueryPlanContainer.GetItemQueryIterator("select * From T order by T.status", requestOptions: requestOptions); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs index c76110f1fb..e967f495a6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs @@ -302,181 +302,185 @@ public async Task NoSessionTokenCaptureForThrottledUpsertRequestsTest() [TestMethod] public async Task InvalidSessionTokenAfterContainerRecreationAndCollectionCacheRefreshReproTest() { - // ingestionClinet is dedicated client simulating the writes / container recreation in - // the separate process - like Spark job - using CosmosClient ingestionClient = TestCommon.CreateCosmosClient(); - Cosmos.Database ingestionDatabase = ingestionClient.GetDatabase(this.database.Id); - - ContainerProperties multiPartitionContainerSettings = - new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/pk"); - Container ingestionContainer = - await ingestionDatabase.CreateContainerAsync(multiPartitionContainerSettings); - - const int itemCountToBeIngested = 10; - string pk = Guid.NewGuid().ToString("N"); - long? latestLsn = null; - Console.WriteLine("INGEST DOCUMENTS"); - for (int i = 0; i < itemCountToBeIngested; i++) + foreach (bool enableODE in new bool[] { false, true }) { - ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity(); - testItem.pk = pk; - - ItemResponse response = - await ingestionContainer.CreateItemAsync(item: testItem); - Assert.IsNotNull(response); - Assert.IsNotNull(response.Resource); - Assert.IsNotNull(response.Diagnostics); - long? lsnAfterCreate = await GetLSNFromSessionContainer( - ingestionContainer, multiPartitionContainerSettings, new PartitionKey(pk)); - Assert.IsNotNull(lsnAfterCreate); - Assert.IsTrue(latestLsn == null || lsnAfterCreate.Value > latestLsn.Value); - latestLsn = lsnAfterCreate; - CosmosTraceDiagnostics diagnostics = (CosmosTraceDiagnostics)response.Diagnostics; - Assert.IsFalse(diagnostics.IsGoneExceptionHit()); - Assert.IsFalse(string.IsNullOrEmpty(diagnostics.ToString())); - Assert.IsTrue(diagnostics.GetClientElapsedTime() > TimeSpan.Zero); - } + // ingestionClient is dedicated client simulating the writes / container recreation in + // the separate process - like Spark job + using CosmosClient ingestionClient = TestCommon.CreateCosmosClient(); + Cosmos.Database ingestionDatabase = ingestionClient.GetDatabase(this.database.Id); + + ContainerProperties multiPartitionContainerSettings = + new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/pk"); + Container ingestionContainer = + await ingestionDatabase.CreateContainerAsync(multiPartitionContainerSettings); + + const int itemCountToBeIngested = 10; + string pk = Guid.NewGuid().ToString("N"); + long? latestLsn = null; + Console.WriteLine("INGEST DOCUMENTS"); + for (int i = 0; i < itemCountToBeIngested; i++) + { + ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity(); + testItem.pk = pk; - // Dedciated query client used only for queries simulating the customer's app - string lastRequestedSessionToken = null; - Container queryContainer = TransportClientHelper.GetContainerWithIntercepter( - this.database.Id, - ingestionContainer.Id, - (uri, operation, request) => + ItemResponse response = + await ingestionContainer.CreateItemAsync(item: testItem); + Assert.IsNotNull(response); + Assert.IsNotNull(response.Resource); + Assert.IsNotNull(response.Diagnostics); + long? lsnAfterCreate = await GetLSNFromSessionContainer( + ingestionContainer, multiPartitionContainerSettings, new PartitionKey(pk)); + Assert.IsNotNull(lsnAfterCreate); + Assert.IsTrue(latestLsn == null || lsnAfterCreate.Value > latestLsn.Value); + latestLsn = lsnAfterCreate; + CosmosTraceDiagnostics diagnostics = (CosmosTraceDiagnostics)response.Diagnostics; + Assert.IsFalse(diagnostics.IsGoneExceptionHit()); + Assert.IsFalse(string.IsNullOrEmpty(diagnostics.ToString())); + Assert.IsTrue(diagnostics.GetClientElapsedTime() > TimeSpan.Zero); + } + + // Dedciated query client used only for queries simulating the customer's app + string lastRequestedSessionToken = null; + Container queryContainer = TransportClientHelper.GetContainerWithIntercepter( + this.database.Id, + ingestionContainer.Id, + (uri, operation, request) => + { + if (request.ResourceType == ResourceType.Document && + request.OperationType == OperationType.Query) + { + lastRequestedSessionToken = request.Headers[HttpConstants.HttpHeaders.SessionToken]; + } + }, + false, + null); + + long? lsnAfterQueryOnOldContainer = null; + + // Issueing two queries - first won't use session tokens yet + // second will provide session tokens captured from first request in the request to the backend + for (int i = 0; i < 2; i++) { - if (request.ResourceType == ResourceType.Document && - request.OperationType == OperationType.Query) + Console.WriteLine("RUN QUERY ON OLD CONTAINER ({0})", i); + using FeedIterator queryIteratorOldContainer = queryContainer.GetItemQueryIterator( + new QueryDefinition("Select c.id FROM c"), + continuationToken: null, + new QueryRequestOptions + { + ConsistencyLevel = Cosmos.ConsistencyLevel.Session, + PartitionKey = new Cosmos.PartitionKey(pk), + EnableOptimisticDirectExecution = enableODE + }); + int itemCountOldContainer = 0; + while (queryIteratorOldContainer.HasMoreResults) { - lastRequestedSessionToken = request.Headers[HttpConstants.HttpHeaders.SessionToken]; + FeedResponse response = await queryIteratorOldContainer.ReadNextAsync(); + if(i == 0) + { + string diagnosticString = response.Diagnostics.ToString(); + Assert.IsTrue(diagnosticString.Contains("PKRangeCache Info(")); + JObject diagnosticJobject = JObject.Parse(diagnosticString); + + JToken actualToken = diagnosticJobject.SelectToken(enableODE ? + "$.children[?(@.name=='Get Partition Key Ranges')].children[?(@.name=='Try Get Overlapping Ranges')].data" : + "$.children[0].children[?(@.name=='Get Partition Key Ranges')].children[?(@.name=='Try Get Overlapping Ranges')].data"); + JToken actualNode = actualToken.Children().First().First(); + + Assert.IsTrue(actualNode["Previous Continuation Token"].ToString().Length == 0); + Assert.IsTrue(actualNode["Continuation Token"].ToString().Length > 0); + } + + itemCountOldContainer += response.Count; } - }, - false, - null); - long? lsnAfterQueryOnOldContainer = null; + Assert.AreEqual(itemCountToBeIngested, itemCountOldContainer); + lsnAfterQueryOnOldContainer = await GetLSNFromSessionContainer( + queryContainer, multiPartitionContainerSettings, new PartitionKey(pk)); + Assert.IsNotNull(lsnAfterQueryOnOldContainer); + Assert.AreEqual(latestLsn.Value, lsnAfterQueryOnOldContainer.Value); + if (i == 0) + { + Assert.IsNull(lastRequestedSessionToken); + } + else + { + Assert.IsNotNull(lastRequestedSessionToken); + Assert.AreEqual(latestLsn.Value, SessionTokenHelper.Parse(lastRequestedSessionToken).LSN); + } + } - // Issueing two queries - first won't use session tokens yet - // second will provide session tokens captured from first request in the request to the backend - for (int i = 0; i < 2; i++) - { - Console.WriteLine("RUN QUERY ON OLD CONTAINER ({0})", i); - using FeedIterator queryIteratorOldContainer = queryContainer.GetItemQueryIterator( + Console.WriteLine( + "DELETE CONTAINER {0}", + (await queryContainer.ReadContainerAsync()).Resource.ResourceId); + await ingestionContainer.DeleteContainerAsync(); + + Console.WriteLine("RECREATING CONTAINER..."); + ContainerResponse ingestionContainerResponse = + await ingestionDatabase.CreateContainerAsync(multiPartitionContainerSettings); + ingestionContainer = ingestionContainerResponse.Container; + + string responseSessionTokenValue = + ingestionContainerResponse.Headers[HttpConstants.HttpHeaders.SessionToken]; + long? lsnAfterRecreatingContainerFromIngestionClient = responseSessionTokenValue != null ? + SessionTokenHelper.Parse(responseSessionTokenValue).LSN : null; + Console.WriteLine( + "RECREATED CONTAINER with new CollectionRid: {0} - LSN: {1}", + ingestionContainerResponse.Resource.ResourceId, + lsnAfterRecreatingContainerFromIngestionClient); + + // validates that the query container still uses the LSN captured from the old LSN + long? lsnAfterCreatingNewContainerFromQueryClient = await GetLSNFromSessionContainer( + queryContainer, multiPartitionContainerSettings, new PartitionKey(pk)); + Assert.IsNotNull(lsnAfterCreatingNewContainerFromQueryClient); + Assert.AreEqual(latestLsn.Value, lsnAfterCreatingNewContainerFromQueryClient.Value); + + Console.WriteLine("GET FEED RANGES"); + // this will force a CollectionCache refresh - because no pk ranegs can be identified + // for the old container anymore + _ = await queryContainer.GetFeedRangesAsync(); + + + Console.WriteLine("RUN QUERY ON NEW CONTAINER"); + int itemCountNewContainer = 0; + using FeedIterator queryIteratorNewContainer = queryContainer.GetItemQueryIterator( new QueryDefinition("Select c.id FROM c"), continuationToken: null, new QueryRequestOptions { ConsistencyLevel = Cosmos.ConsistencyLevel.Session, PartitionKey = new Cosmos.PartitionKey(pk), -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif }); - int itemCountOldContainer = 0; - while (queryIteratorOldContainer.HasMoreResults) + Console.WriteLine("Query iterator created"); + while (queryIteratorNewContainer.HasMoreResults) { - FeedResponse response = await queryIteratorOldContainer.ReadNextAsync(); - if(i == 0) + Console.WriteLine("Retrieving first page"); + try + { + FeedResponse response = await queryIteratorNewContainer.ReadNextAsync(); + Console.WriteLine("Request Diagnostics for query against new container: {0}", + response.Diagnostics.ToString()); + itemCountNewContainer += response.Count; + } + catch (CosmosException cosmosException) { - string diagnosticString = response.Diagnostics.ToString(); - Assert.IsTrue(diagnosticString.Contains("PKRangeCache Info(")); - JObject diagnosticJobject = JObject.Parse(diagnosticString); - JToken actualToken = diagnosticJobject.SelectToken("$.children[0].children[?(@.name=='Get Partition Key Ranges')].children[?(@.name=='Try Get Overlapping Ranges')].data"); - JToken actualNode = actualToken.Children().First().First(); - - Assert.IsTrue(actualNode["Previous Continuation Token"].ToString().Length == 0); - Assert.IsTrue(actualNode["Continuation Token"].ToString().Length > 0); + Console.WriteLine("COSMOS EXCEPTION: {0}", cosmosException); + throw; } - - itemCountOldContainer += response.Count; } - Assert.AreEqual(itemCountToBeIngested, itemCountOldContainer); - lsnAfterQueryOnOldContainer = await GetLSNFromSessionContainer( + Assert.AreEqual(0, itemCountNewContainer); + long? lsnAfterQueryOnNewContainer = await GetLSNFromSessionContainer( queryContainer, multiPartitionContainerSettings, new PartitionKey(pk)); - Assert.IsNotNull(lsnAfterQueryOnOldContainer); - Assert.AreEqual(latestLsn.Value, lsnAfterQueryOnOldContainer.Value); - if (i == 0) - { - Assert.IsNull(lastRequestedSessionToken); - } - else - { - Assert.IsNotNull(lastRequestedSessionToken); - Assert.AreEqual(latestLsn.Value, SessionTokenHelper.Parse(lastRequestedSessionToken).LSN); - } - } - - Console.WriteLine( - "DELETE CONTAINER {0}", - (await queryContainer.ReadContainerAsync()).Resource.ResourceId); - await ingestionContainer.DeleteContainerAsync(); - - Console.WriteLine("RECREATING CONTAINER..."); - ContainerResponse ingestionContainerResponse = - await ingestionDatabase.CreateContainerAsync(multiPartitionContainerSettings); - ingestionContainer = ingestionContainerResponse.Container; - - string responseSessionTokenValue = - ingestionContainerResponse.Headers[HttpConstants.HttpHeaders.SessionToken]; - long? lsnAfterRecreatingContainerFromIngestionClient = responseSessionTokenValue != null ? - SessionTokenHelper.Parse(responseSessionTokenValue).LSN : null; - Console.WriteLine( - "RECREATED CONTAINER with new CollectionRid: {0} - LSN: {1}", - ingestionContainerResponse.Resource.ResourceId, - lsnAfterRecreatingContainerFromIngestionClient); - - // validates that the query container still uses the LSN captured from the old LSN - long? lsnAfterCreatingNewContainerFromQueryClient = await GetLSNFromSessionContainer( - queryContainer, multiPartitionContainerSettings, new PartitionKey(pk)); - Assert.IsNotNull(lsnAfterCreatingNewContainerFromQueryClient); - Assert.AreEqual(latestLsn.Value, lsnAfterCreatingNewContainerFromQueryClient.Value); - - Console.WriteLine("GET FEED RANGES"); - // this will force a CollectionCache refresh - because no pk ranegs can be identified - // for the old container anymore - _ = await queryContainer.GetFeedRangesAsync(); - - - Console.WriteLine("RUN QUERY ON NEW CONTAINER"); - int itemCountNewContainer = 0; - using FeedIterator queryIteratorNewContainer = queryContainer.GetItemQueryIterator( - new QueryDefinition("Select c.id FROM c"), - continuationToken: null, - new QueryRequestOptions - { - ConsistencyLevel = Cosmos.ConsistencyLevel.Session, - PartitionKey = new Cosmos.PartitionKey(pk), - }); - Console.WriteLine("Query iterator created"); - while (queryIteratorNewContainer.HasMoreResults) - { - Console.WriteLine("Retrieving first page"); - try - { - FeedResponse response = await queryIteratorNewContainer.ReadNextAsync(); - Console.WriteLine("Request Diagnostics for query against new container: {0}", - response.Diagnostics.ToString()); - itemCountNewContainer += response.Count; - } - catch (CosmosException cosmosException) - { - Console.WriteLine("COSMOS EXCEPTION: {0}", cosmosException); - throw; - } + Assert.IsNotNull(lsnAfterQueryOnNewContainer); + Assert.IsTrue( + lastRequestedSessionToken == null || + SessionTokenHelper.Parse(lastRequestedSessionToken).LSN == + lsnAfterRecreatingContainerFromIngestionClient, + $"The requested session token {lastRequestedSessionToken} on the last query request should be null " + + $"or have LSN '{lsnAfterRecreatingContainerFromIngestionClient}' (which is the LSN after " + + "re-creating the container) if the session cache or the new CollectionName to Rid mapping was " + + "correctly populated in the SessionCache."); } - - Assert.AreEqual(0, itemCountNewContainer); - long? lsnAfterQueryOnNewContainer = await GetLSNFromSessionContainer( - queryContainer, multiPartitionContainerSettings, new PartitionKey(pk)); - Assert.IsNotNull(lsnAfterQueryOnNewContainer); - Assert.IsTrue( - lastRequestedSessionToken == null || - SessionTokenHelper.Parse(lastRequestedSessionToken).LSN == - lsnAfterRecreatingContainerFromIngestionClient, - $"The requested session token {lastRequestedSessionToken} on the last query request should be null " + - $"or have LSN '{lsnAfterRecreatingContainerFromIngestionClient}' (which is the LSN after " + - "re-creating the container) if the session cache or the new CollectionName to Rid mapping was " + - "correctly populated in the SessionCache."); } private static async Task GetPKRangeIdForPartitionKey( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs index eadb62da7c..09e3ccfa0f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs @@ -94,48 +94,64 @@ public async Task TestQueryWithCustomJsonSerializer() Assert.AreEqual(1, toStreamCount, "parameter should use custom serializer"); Assert.AreEqual(0, fromStreamCount); - toStreamCount = 0; - fromStreamCount = 0; - - FeedIterator itemIterator = container.GetItemQueryIterator( - query -#if PREVIEW - , requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = false } -#endif - ); - List items = new List(); - while (itemIterator.HasMoreResults) + foreach (bool enableODE in new bool[] { false, true }) { - items.AddRange(await itemIterator.ReadNextAsync()); - } - - Assert.AreEqual(2, toStreamCount); - Assert.AreEqual(1, fromStreamCount); - - toStreamCount = 0; - fromStreamCount = 0; + toStreamCount = 0; + fromStreamCount = 0; + + FeedIterator itemIterator = container.GetItemQueryIterator( + query, + requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = enableODE } + ); + List items = new List(); + while (itemIterator.HasMoreResults) + { + items.AddRange(await itemIterator.ReadNextAsync()); + } - // Verify that the custom serializer is actually being used via stream - FeedIterator itemStreamIterator = container.GetItemQueryStreamIterator( - query -#if PREVIEW - , requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = false } -#endif - ); - while (itemStreamIterator.HasMoreResults) - { - ResponseMessage response = await itemStreamIterator.ReadNextAsync(); - using (StreamReader reader = new StreamReader(response.Content)) + // The toStreamCount variable will differ between ODE and non-ODE pipelines due to the non-ODE pipelines needing to get the query plan which makes an additional serialization call during its initialization. + if (enableODE) { - string content = await reader.ReadToEndAsync(); - Assert.IsTrue(content.Contains("9001.42")); - Assert.IsFalse(content.Contains("description"), "Description should be ignored and not in the JSON"); + Assert.AreEqual(1, toStreamCount); + } + else + { + Assert.AreEqual(2, toStreamCount); + } + + Assert.AreEqual(1, fromStreamCount); + + toStreamCount = 0; + fromStreamCount = 0; + + // Verify that the custom serializer is actually being used via stream + FeedIterator itemStreamIterator = container.GetItemQueryStreamIterator( + query, + requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = enableODE } + ); + while (itemStreamIterator.HasMoreResults) + { + ResponseMessage response = await itemStreamIterator.ReadNextAsync(); + using (StreamReader reader = new StreamReader(response.Content)) + { + string content = await reader.ReadToEndAsync(); + Assert.IsTrue(content.Contains("9001.42")); + Assert.IsFalse(content.Contains("description"), "Description should be ignored and not in the JSON"); + } } - } - Assert.AreEqual(2, toStreamCount); - Assert.AreEqual(0, fromStreamCount); + // The toStreamCount variable will differ between ODE and non-ODE pipelines due to the non-ODE pipelines needing to get the query plan which makes an additional serialization call during its initialization. + if (enableODE) + { + Assert.AreEqual(1, toStreamCount); + } + else + { + Assert.AreEqual(2, toStreamCount); + } + Assert.AreEqual(0, fromStreamCount); + } } finally { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs index 5307145dfc..01e1fc5c66 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs @@ -447,64 +447,68 @@ public async Task MultiHashQueryItemTest() doc.SetValue("Type", "Goverment"); documents[2] = await this.container.CreateItemAsync(doc); - //Query - foreach (Document document in documents) + foreach (bool odeEnabled in new bool[] { false, true }) { - pKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("ZipCode")) - .Add(document.GetPropertyValue("City")) - .Build(); - - badPKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("City")) - .Build(); - - String query = $"SELECT * from c where c.id = \"{document.GetPropertyValue("id")}\""; - - using (FeedIterator feedIterator = this.container.GetItemQueryIterator( - query, - null, - new QueryRequestOptions() { PartitionKey = pKey })) + //Query + foreach (Document document in documents) { - Assert.IsTrue(feedIterator.HasMoreResults); + pKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("ZipCode")) + .Add(document.GetPropertyValue("City")) + .Build(); - FeedResponse queryDoc = await feedIterator.ReadNextAsync(); - queryDoc.First(); - Assert.IsTrue(queryDoc.Count == 1); - feedIterator.Dispose(); - } + badPKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("City")) + .Build(); - //Using an incomplete partition key with prefix of PK path definition - pKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("ZipCode")) - .Build(); - using (FeedIterator feedIterator = this.container.GetItemQueryIterator( - query, - null, - new QueryRequestOptions() { PartitionKey = pKey })) - { - Assert.IsTrue(feedIterator.HasMoreResults); + String query = $"SELECT * from c where c.id = \"{document.GetPropertyValue("id")}\""; - FeedResponse queryDoc = await feedIterator.ReadNextAsync(); - queryDoc.First(); - Assert.IsTrue(queryDoc.Count == 1); - feedIterator.Dispose(); - } + using (FeedIterator feedIterator = this.container.GetItemQueryIterator( + query, + null, + new QueryRequestOptions() { EnableOptimisticDirectExecution = odeEnabled, PartitionKey = pKey })) + { + Assert.IsTrue(feedIterator.HasMoreResults); - //Negative test - using incomplete partition key - using (FeedIterator badFeedIterator = this.container.GetItemQueryIterator( - query, - null, - new QueryRequestOptions() { PartitionKey = badPKey})) - { - FeedResponse queryDocBad = await badFeedIterator.ReadNextAsync(); - Assert.ThrowsException(() => - queryDocBad.First() - ); - badFeedIterator.Dispose(); + FeedResponse queryDoc = await feedIterator.ReadNextAsync(); + Document retrievedDocument = queryDoc.First(); + Assert.IsTrue(queryDoc.Count == 1); + Assert.AreEqual(document.Id, retrievedDocument.Id); + feedIterator.Dispose(); + } + + //Using an incomplete partition key with prefix of PK path definition + pKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("ZipCode")) + .Build(); + using (FeedIterator feedIterator = this.container.GetItemQueryIterator( + query, + null, + new QueryRequestOptions() { EnableOptimisticDirectExecution = odeEnabled, PartitionKey = pKey })) + { + Assert.IsTrue(feedIterator.HasMoreResults); + + FeedResponse queryDoc = await feedIterator.ReadNextAsync(); + Document retrievedDocument = queryDoc.First(); + Assert.IsTrue(queryDoc.Count == 1); + Assert.AreEqual(document.Id, retrievedDocument.Id); + feedIterator.Dispose(); + } + + //Negative test - using incomplete partition key + using (FeedIterator badFeedIterator = this.container.GetItemQueryIterator( + query, + null, + new QueryRequestOptions() { EnableOptimisticDirectExecution = odeEnabled, PartitionKey = badPKey })) + { + FeedResponse queryDocBad = await badFeedIterator.ReadNextAsync(); + Assert.ThrowsException(() => + queryDocBad.First() + ); + badFeedIterator.Dispose(); + } } } } - } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs index ce9723e7ee..a5652e1010 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs @@ -98,19 +98,19 @@ public async Task InexistentPKRangeId() string feedRangeSerialization = JsonConvert.SerializeObject(new { PKRangeId = "10" }); FeedRange feedRange = FeedRange.FromJsonString(feedRangeSerialization); - FeedIterator feedIterator = container.GetItemQueryIterator( - queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), - feedRange: feedRange, - continuationToken: null - -#if PREVIEW - , requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = false } -#endif - ); - - CosmosException exception = await Assert.ThrowsExceptionAsync(() => feedIterator.ReadNextAsync()); - Assert.AreEqual(HttpStatusCode.Gone, exception.StatusCode); - Assert.AreEqual((int)Documents.SubStatusCodes.PartitionKeyRangeGone, exception.SubStatusCode); + foreach (bool enableODE in new bool[] { false, true }) + { + FeedIterator feedIterator = container.GetItemQueryIterator( + queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), + feedRange: feedRange, + continuationToken: null, + requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = enableODE } + ); + + CosmosException exception = await Assert.ThrowsExceptionAsync(() => feedIterator.ReadNextAsync()); + Assert.AreEqual(HttpStatusCode.Gone, exception.StatusCode); + Assert.AreEqual((int)Documents.SubStatusCodes.PartitionKeyRangeGone, exception.SubStatusCode); + } } finally { @@ -151,65 +151,68 @@ public async Task ParallelizeQueryThroughTokens() Assert.IsTrue(feedTokens.Count > 1, " RUs of the container needs to be increased to ensure at least 2 partitions."); - List>> tasks = feedTokens.Select(async feedToken => + foreach (bool enableODE in new bool[] { false, true }) { - List results = new List(); - FeedIteratorInternal feedIterator = container.GetItemQueryStreamIterator( - queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), - feedRange: feedToken, - continuationToken: null, - requestOptions: new QueryRequestOptions() { MaxItemCount = 10 }) as FeedIteratorInternal; - string continuation = null; - while (feedIterator.HasMoreResults) + List>> tasks = feedTokens.Select(async feedToken => { - using (ResponseMessage responseMessage = - await feedIterator.ReadNextAsync(this.cancellationToken)) + List results = new List(); + FeedIteratorInternal feedIterator = container.GetItemQueryStreamIterator( + queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), + feedRange: feedToken, + continuationToken: null, + requestOptions: new QueryRequestOptions() { MaxItemCount = 10, EnableOptimisticDirectExecution = enableODE }) as FeedIteratorInternal; + string continuation = null; + while (feedIterator.HasMoreResults) { - if (responseMessage.IsSuccessStatusCode) + using (ResponseMessage responseMessage = + await feedIterator.ReadNextAsync(this.cancellationToken)) { - using (StreamReader reader = new StreamReader(responseMessage.Content)) + if (responseMessage.IsSuccessStatusCode) { - string json = await reader.ReadToEndAsync(); - JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); - foreach(JObject document in documents) + using (StreamReader reader = new StreamReader(responseMessage.Content)) { - results.Add(document.SelectToken("id").ToString()); + string json = await reader.ReadToEndAsync(); + JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); + foreach (JObject document in documents) + { + results.Add(document.SelectToken("id").ToString()); + } } } - } - continuation = responseMessage.ContinuationToken; - break; + continuation = responseMessage.ContinuationToken; + break; + } } - } - feedIterator = container.GetItemQueryStreamIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, continuationToken: continuation, requestOptions: new QueryRequestOptions() { MaxItemCount = 10 }) as FeedIteratorInternal; - while (feedIterator.HasMoreResults) - { - using (ResponseMessage responseMessage = - await feedIterator.ReadNextAsync(this.cancellationToken)) + feedIterator = container.GetItemQueryStreamIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, continuationToken: continuation, requestOptions: new QueryRequestOptions() { MaxItemCount = 10, EnableOptimisticDirectExecution = enableODE }) as FeedIteratorInternal; + while (feedIterator.HasMoreResults) { - if (responseMessage.IsSuccessStatusCode) + using (ResponseMessage responseMessage = + await feedIterator.ReadNextAsync(this.cancellationToken)) { - using (StreamReader reader = new StreamReader(responseMessage.Content)) + if (responseMessage.IsSuccessStatusCode) { - string json = await reader.ReadToEndAsync(); - JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); - foreach (JObject document in documents) + using (StreamReader reader = new StreamReader(responseMessage.Content)) { - results.Add(document.SelectToken("id").ToString()); + string json = await reader.ReadToEndAsync(); + JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); + foreach (JObject document in documents) + { + results.Add(document.SelectToken("id").ToString()); + } } } } } - } - return results; - }).ToList(); + return results; + }).ToList(); - await Task.WhenAll(tasks); + await Task.WhenAll(tasks); - CollectionAssert.AreEquivalent(generatedIds, tasks.SelectMany(t => t.Result).ToList()); + CollectionAssert.AreEquivalent(generatedIds, tasks.SelectMany(t => t.Result).ToList()); + } } finally { @@ -250,39 +253,42 @@ public async Task ParallelizeQueryThroughTokens_OfT() Assert.IsTrue(feedTokens.Count > 1, " RUs of the container needs to be increased to ensure at least 2 partitions."); - List>> tasks = feedTokens.Select(async feedToken => + foreach (bool enableODE in new bool[] { false, true }) { - List results = new List(); - FeedIterator feedIterator = container.GetItemQueryIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, requestOptions: new QueryRequestOptions() { MaxItemCount = 10 }); - string continuation = null; - while (feedIterator.HasMoreResults) + List>> tasks = feedTokens.Select(async feedToken => { - FeedResponse response = await feedIterator.ReadNextAsync(); - foreach (ToDoActivity toDoActivity in response) + List results = new List(); + FeedIterator feedIterator = container.GetItemQueryIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, requestOptions: new QueryRequestOptions() { MaxItemCount = 10, EnableOptimisticDirectExecution = enableODE }); + string continuation = null; + while (feedIterator.HasMoreResults) { - results.Add(toDoActivity.id); - } + FeedResponse response = await feedIterator.ReadNextAsync(); + foreach (ToDoActivity toDoActivity in response) + { + results.Add(toDoActivity.id); + } - continuation = response.ContinuationToken; - break; - } + continuation = response.ContinuationToken; + break; + } - feedIterator = container.GetItemQueryIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, continuationToken: continuation, requestOptions: new QueryRequestOptions() { MaxItemCount = 10 }); - while (feedIterator.HasMoreResults) - { - FeedResponse response = await feedIterator.ReadNextAsync(); - foreach (ToDoActivity toDoActivity in response) + feedIterator = container.GetItemQueryIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, continuationToken: continuation, requestOptions: new QueryRequestOptions() { MaxItemCount = 10, EnableOptimisticDirectExecution = enableODE }); + while (feedIterator.HasMoreResults) { - results.Add(toDoActivity.id); + FeedResponse response = await feedIterator.ReadNextAsync(); + foreach (ToDoActivity toDoActivity in response) + { + results.Add(toDoActivity.id); + } } - } - return results; - }).ToList(); + return results; + }).ToList(); - await Task.WhenAll(tasks); + await Task.WhenAll(tasks); - CollectionAssert.AreEquivalent(generatedIds, tasks.SelectMany(t => t.Result).ToList()); + CollectionAssert.AreEquivalent(generatedIds, tasks.SelectMany(t => t.Result).ToList()); + } } finally { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs index 8cc819014a..815de90537 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs @@ -311,12 +311,7 @@ public static Func> GenerateTestCosmosData(Func query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); @@ -353,12 +348,7 @@ public static Func> GenerateSerializationTestCosmosData(F } FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions() - { -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif - }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions, linqSerializerOptions: linqSerializerOptions); @@ -540,12 +530,7 @@ public static Func> GenerateSimpleCosmosData(Cosmos.Datab } FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions() - { -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif - }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); @@ -591,32 +576,52 @@ public static LinqTestOutput ExecuteTest(LinqTestInput input, bool serializeResu } public static string BuildExceptionMessageForTest(Exception ex) - { - StringBuilder message = new StringBuilder(); + { + StringBuilder message = new StringBuilder(); do { if (ex is CosmosException cosmosException) - { - message.Append($"Status Code: {cosmosException.StatusCode}"); + { + // ODE scenario: The backend generates an error response message with significant variations when compared to the Service Interop which gets called in the Non ODE scenario. + // The objective is to standardize and normalize the backend response for consistency. + Match match = Regex.Match(ex.Message, @"Reason:(.*?}]})", RegexOptions.IgnoreCase); + Match requestURIMatch = Regex.Match(ex.Message, @"Request URI", RegexOptions.IgnoreCase); + if (match.Success && requestURIMatch.Success) + { + string reason = match.Groups[1].Value; + reason = reason.Replace("\\", ""); + + string transformedString = "Status Code: " + reason; + transformedString = transformedString.Replace(" (", ""); + transformedString = transformedString.Replace("{\"code\":\"", ""); + transformedString = transformedString.Replace("\",\"message\":\"Message: {\"errors\":[", ",{\"errors\":["); + transformedString = transformedString.Replace("}]}", "}]},0x800A0B00"); + + return transformedString; + } + else + { + message.Append($"Status Code: {cosmosException.StatusCode}"); + } } else if (ex is DocumentClientException documentClientException) { message.Append(documentClientException.RawErrorMessage); } else - { - message.Append(ex.Message); + { + message.Append(ex.Message); } - + ex = ex.InnerException; if (ex != null) { message.Append(","); } } - while (ex != null); - - return message.ToString(); + while (ex != null); + + return message.ToString(); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs index f13a92da82..58aef32721 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs @@ -1219,12 +1219,7 @@ public void TestSelectTop() Tuple> generatedData = this.CreateDataTestSelectTop(); int seed = generatedData.Item1; List data = generatedData.Item2; - QueryRequestOptions requestOptions = new QueryRequestOptions() - { -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif - }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); IOrderedQueryable query = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); Func> getQuery = useQuery => useQuery ? query : data.AsQueryable(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs index d60f76f92c..d06fdc84d7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs @@ -14,7 +14,6 @@ using Microsoft.Azure.Cosmos.Json; using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json; using Newtonsoft.Json.Linq; [TestClass] @@ -62,66 +61,87 @@ await this.CreateIngestQueryDeleteAsync( ConnectionModes.Direct | ConnectionModes.Gateway, CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, documents, - ImplementationAsync, + NonOdeImplementationAsync, args, "/" + args.PartitionKey); - async Task ImplementationAsync( + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct | ConnectionModes.Gateway, + CollectionTypes.SinglePartition, + documents, + OdeImplementationAsync, + args, + "/" + args.PartitionKey); + + async Task NonOdeImplementationAsync( Container container, IReadOnlyList inputDocuments, AggregateTestArgs aggregateTestArgs) { - IReadOnlyList documentsWherePkIsANumber = inputDocuments - .Where(doc => - { - return double.TryParse( - doc[aggregateTestArgs.PartitionKey].ToString(), - out double result); - }) - .ToList(); - double numberSum = documentsWherePkIsANumber - .Sum(doc => + AggregateQueryArguments[] aggregateQueryArgumentsList = CreateAggregateQueryArguments(inputDocuments, aggregateTestArgs); + foreach (int maxDoP in new[] { 0, 10 }) + { + foreach (AggregateQueryArguments argument in aggregateQueryArgumentsList) { - if (!doc.TryGetValue(aggregateTestArgs.PartitionKey, out CosmosNumber number)) + string[] queryFormats = new[] { - Assert.Fail("Failed to get partition key from document"); - } + "SELECT VALUE {0}(r.{1}) FROM r WHERE {2}", + "SELECT VALUE {0}(r.{1}) FROM r WHERE {2} ORDER BY r.{1}" + }; - return Number64.ToDouble(number.Value); - }); - double count = documentsWherePkIsANumber.Count(); - AggregateQueryArguments[] aggregateQueryArgumentsList = new AggregateQueryArguments[] - { - new AggregateQueryArguments( - aggregateOperator: "AVG", - expectedValue: CosmosNumber64.Create(numberSum / count), - predicate: $"IS_NUMBER(r.{aggregateTestArgs.PartitionKey})"), - new AggregateQueryArguments( - aggregateOperator: "AVG", - expectedValue: CosmosUndefined.Create(), - predicate: "true"), - new AggregateQueryArguments( - aggregateOperator: "COUNT", - expectedValue: CosmosNumber64.Create(documents.Count()), - predicate: "true"), - new AggregateQueryArguments( - aggregateOperator: "MAX", - expectedValue: CosmosString.Create("xyz"), - predicate: "true"), - new AggregateQueryArguments( - aggregateOperator: "MIN", - expectedValue: CosmosBoolean.Create(false), - predicate: "true"), - new AggregateQueryArguments( - aggregateOperator: "SUM", - expectedValue: CosmosNumber64.Create(numberSum), - predicate: $"IS_NUMBER(r.{aggregateTestArgs.PartitionKey})"), - new AggregateQueryArguments( - aggregateOperator: "SUM", - expectedValue: CosmosUndefined.Create(), - predicate: $"true"), - }; + foreach (string queryFormat in queryFormats) + { + string query = string.Format( + CultureInfo.InvariantCulture, + queryFormat, + argument.AggregateOperator, + aggregateTestArgs.PartitionKey, + argument.Predicate); + string message = string.Format( + CultureInfo.InvariantCulture, + "query: {0}, data: {1}", + query, + argument.ToString()); + + List items = await QueryTestsBase.RunQueryAsync( + container, + query, + new QueryRequestOptions() + { + MaxConcurrency = maxDoP, + EnableOptimisticDirectExecution = false + }); + if (argument.ExpectedValue == null) + { + Assert.AreEqual(0, items.Count, message); + } + else + { + Assert.AreEqual(1, items.Count, message); + CosmosElement expected = argument.ExpectedValue; + CosmosElement actual = items.Single(); + + if ((expected is CosmosNumber expectedNumber) && (actual is CosmosNumber actualNumber)) + { + Assert.AreEqual(Number64.ToDouble(expectedNumber.Value), Number64.ToDouble(actualNumber.Value), .01); + } + else + { + Assert.AreEqual(expected, actual, message); + } + } + } + } + } + } + + async Task OdeImplementationAsync( + Container container, + IReadOnlyList inputDocuments, + AggregateTestArgs aggregateTestArgs) + { + AggregateQueryArguments[] aggregateQueryArgumentsList = CreateAggregateQueryArguments(inputDocuments, aggregateTestArgs); foreach (int maxDoP in new[] { 0, 10 }) { foreach (AggregateQueryArguments argument in aggregateQueryArgumentsList) @@ -152,12 +172,10 @@ async Task ImplementationAsync( new QueryRequestOptions() { MaxConcurrency = maxDoP, -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif + EnableOptimisticDirectExecution = true }); - if (argument.ExpectedValue == null) + if (argument.ExpectedValue == CosmosUndefined.Create()) { Assert.AreEqual(0, items.Count, message); } @@ -182,6 +200,64 @@ async Task ImplementationAsync( } } + private static AggregateQueryArguments[] CreateAggregateQueryArguments( + IReadOnlyList inputDocuments, + AggregateTestArgs aggregateTestArgs) + { + IReadOnlyList documentsWherePkIsANumber = inputDocuments + .Where(doc => + { + return double.TryParse( + doc[aggregateTestArgs.PartitionKey].ToString(), + out double result); + }) + .ToList(); + double numberSum = documentsWherePkIsANumber + .Sum(doc => + { + if (!doc.TryGetValue(aggregateTestArgs.PartitionKey, out CosmosNumber number)) + { + Assert.Fail("Failed to get partition key from document"); + } + + return Number64.ToDouble(number.Value); + }); + double count = documentsWherePkIsANumber.Count(); + AggregateQueryArguments[] aggregateQueryArgumentsList = new AggregateQueryArguments[] + { + new AggregateQueryArguments( + aggregateOperator: "AVG", + expectedValue: CosmosNumber64.Create(numberSum / count), + predicate: $"IS_NUMBER(r.{aggregateTestArgs.PartitionKey})"), + new AggregateQueryArguments( + aggregateOperator: "AVG", + expectedValue: CosmosUndefined.Create(), + predicate: "true"), + new AggregateQueryArguments( + aggregateOperator: "COUNT", + expectedValue: CosmosNumber64.Create(inputDocuments.Count()), + predicate: "true"), + new AggregateQueryArguments( + aggregateOperator: "MAX", + expectedValue: CosmosString.Create("xyz"), + predicate: "true"), + new AggregateQueryArguments( + aggregateOperator: "MIN", + expectedValue: CosmosBoolean.Create(false), + predicate: "true"), + new AggregateQueryArguments( + aggregateOperator: "SUM", + expectedValue: CosmosNumber64.Create(numberSum), + predicate: $"IS_NUMBER(r.{aggregateTestArgs.PartitionKey})"), + new AggregateQueryArguments( + aggregateOperator: "SUM", + expectedValue: CosmosUndefined.Create(), + predicate: $"true"), + }; + + return aggregateQueryArgumentsList; + } + private readonly struct AggregateTestArgs { public AggregateTestArgs( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs index 2074902249..48ae5d4464 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs @@ -538,9 +538,6 @@ static async Task ImplementationAsync(Container container, IReadOnlyList { foreach (Cosmos.PartitionKey? partitionKey in new Cosmos.PartitionKey?[] { new Cosmos.PartitionKey(5), default }) { + // ODE is set to false to allow for the testing of other pipelines in single partition scenarios QueryRequestOptions feedOptions = new QueryRequestOptions { MaxBufferedItemCount = 7000, MaxConcurrency = maxDegreeOfParallelism, MaxItemCount = maxItemCount, -#if PREVIEW EnableOptimisticDirectExecution = false -#endif }; async Task> AssertPassthroughAsync(string query, Cosmos.PartitionKey? pk = default) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index 6cd8905b07..923f892fa7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -484,12 +484,7 @@ public async Task ChangeFeedAsync() public async Task QueryAsync() { List inputs = new List(); - QueryRequestOptions requestOptions = new QueryRequestOptions() - { -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif - }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); int startLineNumber; int endLineNumber; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json index 8e45a72922..3b597d3367 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json @@ -4,28 +4,28 @@ "MockedItemBenchmark.CreateItem;[Type=OfT]": 36356, "MockedItemBenchmark.CreateItem;[Type=OfTCustom]": 36362, "MockedItemBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 36359.5, - "MockedItemBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 57472.25, - "MockedItemBenchmark.CreateItem;[Type=Stream]": 24673.25, - "MockedItemBenchmark.DeleteItemExists;[Type=OfT]": 32308.5, - "MockedItemBenchmark.DeleteItemExists;[Type=OfTCustom]": 32328, - "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithClientTelemetryEnabled]": 32321.25, - "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithDiagnosticsToString]": 53231.25, - "MockedItemBenchmark.DeleteItemExists;[Type=Stream]": 24696, + "MockedItemBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 58900.5, + "MockedItemBenchmark.CreateItem;[Type=Stream]": 25212.75, + "MockedItemBenchmark.DeleteItemExists;[Type=OfT]": 33015.25, + "MockedItemBenchmark.DeleteItemExists;[Type=OfTCustom]": 33007.75, + "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithClientTelemetryEnabled]": 33015.75, + "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithDiagnosticsToString]": 54402.75, + "MockedItemBenchmark.DeleteItemExists;[Type=Stream]": 25229.25, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfT]": 42172.5, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTCustom]": 42174.75, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 42166.5, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithDiagnosticsToString]": 63338, - "MockedItemBenchmark.DeleteItemNotExists;[Type=Stream]": 37610, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfT]": 13342232, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTCustom]": 13341058, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithClientTelemetryEnabled]": 13355160, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithDiagnosticsToString]": 13612338, + "MockedItemBenchmark.DeleteItemNotExists;[Type=Stream]": 38373.5, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfT]": 11988727, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTCustom]": 11988284.75, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithClientTelemetryEnabled]": 11988606.75, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithDiagnosticsToString]": 12198686.5, "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=Stream]": 5920952, "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfT]": 2241814, "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTCustom]": 2241810, "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithClientTelemetryEnabled]": 2244658, - "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithDiagnosticsToString]": 2310842, - "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=Stream]": 1005038, + "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithDiagnosticsToString]": 2251235.75, + "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=Stream]": 978459.25, "MockedItemBenchmark.ReadFeed;[Type=OfT]": 560692, "MockedItemBenchmark.ReadFeed;[Type=OfTCustom]": 555716, "MockedItemBenchmark.ReadFeed;[Type=OfTWithClientTelemetryEnabled]": 550898.25, @@ -44,13 +44,13 @@ "MockedItemBenchmark.UpdateItem;[Type=OfT]": 36591, "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": 36594.25, "MockedItemBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 36587.25, - "MockedItemBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": 57649, - "MockedItemBenchmark.UpdateItem;[Type=Stream]": 24894.75, + "MockedItemBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": 59152, + "MockedItemBenchmark.UpdateItem;[Type=Stream]": 25428, "MockedItemBenchmark.UpsertItem;[Type=OfT]": 36577.25, "MockedItemBenchmark.UpsertItem;[Type=OfTCustom]": 36583.75, "MockedItemBenchmark.UpsertItem;[Type=OfTWithClientTelemetryEnabled]": 36578.5, - "MockedItemBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 57732.5, - "MockedItemBenchmark.UpsertItem;[Type=Stream]": 24878.5, + "MockedItemBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 59613, + "MockedItemBenchmark.UpsertItem;[Type=Stream]": 25445.5, "MockedItemBulkBenchmark.CreateItem;[Type=OfT]": 1196168, "MockedItemBulkBenchmark.CreateItem;[Type=OfTCustom]": 1195808, "MockedItemBulkBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 1235418, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index 94aae6155b..c102e8075e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -488,59 +488,8 @@ }, "NestedTypes": {} }, - "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "Boolean EnableOptimisticDirectExecution": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} - }, "Microsoft.Azure.Cosmos.RequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": { - "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "Boolean EnableOptimisticDirectExecution": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} - } - }, + "Subclasses": {}, "Members": { "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index a336902647..9b73ab714a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -6439,6 +6439,18 @@ "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "Boolean EnableOptimisticDirectExecution": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions": { "Type": "Property", "Attributes": [], @@ -6593,6 +6605,13 @@ ], "MethodInfo": "Void set_EnableLowPrecisionOrderBy(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_EnableScanInQuery(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -7466,6 +7485,18 @@ "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "Boolean EnableOptimisticDirectExecution": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions": { "Type": "Property", "Attributes": [], @@ -7620,6 +7651,13 @@ ], "MethodInfo": "Void set_EnableLowPrecisionOrderBy(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_EnableScanInQuery(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 840e6c3ccf..9582b754e7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -150,14 +150,7 @@ public void NegativeOptimisticDirectExecutionOutput() public void TestDefaultQueryRequestOptionsSettings() { QueryRequestOptions requestOptions = new QueryRequestOptions(); - bool odeExpectedValue = -#if PREVIEW - true; -#else - false; -#endif - - Assert.AreEqual(odeExpectedValue, requestOptions.EnableOptimisticDirectExecution); + Assert.AreEqual(true, requestOptions.EnableOptimisticDirectExecution); } // test checks that the pipeline can take a query to the backend and returns its associated document(s). diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs index ce2d808304..97598ea59f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs @@ -270,11 +270,11 @@ public async Task OffsetLimitPageSize() DocumentContainer documentContainer = await CreateDocumentContainerAsync(documents, mockInMemoryContainer, numSplits: 4); // OFFSET/LIMIT with ORDER BY - await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 500", expectedPageSize: 315, expectedResults: 500, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 500", expectedPageSize: 500, expectedResults: 500, mockInMemoryContainer, documentContainer); await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10000 LIMIT 5000", expectedPageSize: 1000, expectedResults: 0, mockInMemoryContainer, documentContainer); - await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10 LIMIT 100", expectedPageSize: 70, expectedResults: 100, mockInMemoryContainer, documentContainer); - await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 100", expectedPageSize: 65, expectedResults: 100, mockInMemoryContainer, documentContainer); - await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 100 LIMIT 0", expectedPageSize: 65, expectedResults: 0, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10 LIMIT 100", expectedPageSize: 110, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 100", expectedPageSize: 100, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 100 LIMIT 0", expectedPageSize: 1000, expectedResults: 0, mockInMemoryContainer, documentContainer); // OFFSET/LIMIT without ORDER BY await this.TestPageSizeAsync("SELECT c.pk FROM c OFFSET 10 LIMIT 100", expectedPageSize: 1000, expectedResults: 100, mockInMemoryContainer, documentContainer); @@ -283,7 +283,7 @@ public async Task OffsetLimitPageSize() // TOP with ORDER BY await this.TestPageSizeAsync("SELECT TOP 5 c.pk FROM c ORDER BY c.pk", expectedPageSize: 5, expectedResults: 5, mockInMemoryContainer, documentContainer); - await this.TestPageSizeAsync("SELECT TOP 100 c.pk FROM c ORDER BY c.pk", expectedPageSize: 65, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 100 c.pk FROM c ORDER BY c.pk", expectedPageSize: 100, expectedResults: 100, mockInMemoryContainer, documentContainer); await this.TestPageSizeAsync("SELECT TOP 5000 c.pk FROM c ORDER BY c.pk", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); await this.TestPageSizeAsync("SELECT TOP 15000 c.pk FROM c ORDER BY c.pk", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); @@ -347,7 +347,6 @@ private async Task TestPageSizeAsync(string query, int expectedPageSize, int exp string databaseId = "db1234"; string resourceLink = $"dbs/{databaseId}/colls"; - const string suffix = "-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF"; List partitionKeyRanges = new List @@ -366,7 +365,7 @@ private async Task TestPageSizeAsync(string query, int expectedPageSize, int exp mockClient.Setup(x => x.GetTargetPartitionKeyRangesAsync( It.IsAny(), - It.IsAny(), + "HelloWorld", It.IsAny>>(), It.IsAny(), It.IsAny())) @@ -396,19 +395,48 @@ private async Task TestPageSizeAsync(string query, int expectedPageSize, int exp ); CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( - client: mockClient.Object, - resourceTypeEnum: Documents.ResourceType.Document, - operationType: Documents.OperationType.Query, - resourceType: typeof(QueryResponseCore), - resourceLink: resourceLink, - isContinuationExpected: true, - allowNonValueAggregateQuery: true, - useSystemPrefix: false, - correlatedActivityId: Guid.NewGuid()); + client: new TestCosmosQueryClient(GetQueryPartitionProvider()), + resourceTypeEnum: Documents.ResourceType.Document, + operationType: Documents.OperationType.Query, + resourceType: typeof(QueryResponseCore), + resourceLink: resourceLink, + isContinuationExpected: true, + allowNonValueAggregateQuery: true, + useSystemPrefix: false, + correlatedActivityId: Guid.NewGuid()); return Tuple.Create(inputParameters, cosmosQueryContextCore); } + internal static QueryPartitionProvider GetQueryPartitionProvider() + { + IDictionary DefaultQueryengineConfiguration = new Dictionary() + { + {"maxSqlQueryInputLength", 30720}, + {"maxJoinsPerSqlQuery", 5}, + {"maxLogicalAndPerSqlQuery", 200}, + {"maxLogicalOrPerSqlQuery", 200}, + {"maxUdfRefPerSqlQuery", 2}, + {"maxInExpressionItemsCount", 8000}, + {"queryMaxInMemorySortDocumentCount", 500}, + {"maxQueryRequestTimeoutFraction", 0.90}, + {"sqlAllowNonFiniteNumbers", false}, + {"sqlAllowAggregateFunctions", true}, + {"sqlAllowSubQuery", true}, + {"sqlAllowScalarSubQuery", false}, + {"allowNewKeywords", true}, + {"sqlAllowLike", true}, + {"sqlAllowGroupByClause", false}, + {"queryEnableMongoNativeRegex", true}, + {"maxSpatialQueryCells", 12}, + {"spatialMaxGeometryPointCount", 256}, + {"sqlDisableOptimizationFlags", 0}, + {"sqlEnableParameterExpansionCheck", true} + }; + + return new QueryPartitionProvider(DefaultQueryengineConfiguration); + } + internal static async Task> ExecuteQueryAsync( string query, IReadOnlyList documents,