From 62b9827acb2e873470f490315f71a9d20db84e86 Mon Sep 17 00:00:00 2001 From: "REDMOND\\adityasa" Date: Fri, 12 Apr 2024 15:15:56 -0700 Subject: [PATCH 1/8] Turn of ODE by default. --- .../src/RequestOptions/QueryRequestOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index 1035fac1c9..ad15e0cd13 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -50,7 +50,7 @@ public class QueryRequestOptions : RequestOptions /// /// Direct (optimistic) execution offers improved performance for several kinds of queries such as a single partition streaming query. /// - public bool EnableOptimisticDirectExecution { get; set; } = ConfigurationManager.IsOptimisticDirectExecutionEnabled(defaultValue: true); + public bool EnableOptimisticDirectExecution { get; set; } = ConfigurationManager.IsOptimisticDirectExecutionEnabled(defaultValue: false); /// /// Gets or sets the maximum number of items that can be buffered client side during From 139d6e6c13a4009c05e81ef5f6f55b61bf6d825b Mon Sep 17 00:00:00 2001 From: "REDMOND\\adityasa" Date: Sat, 13 Apr 2024 14:28:36 -0700 Subject: [PATCH 2/8] Updated tests --- .../CosmosQueryExecutionContextFactory.cs | 17 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 341 +- ...TraceWriterBaselineTests.ReadManyAsync.xml | 1050 +-- ...lBaselineTests.TestDistinctTranslation.xml | 28 +- ...alBaselineTests.TestGroupByTranslation.xml | 2 + ...ralBaselineTests.TestThenByTranslation.xml | 7 +- .../Linq/LinqCleanupTests.cs | 2 +- .../Linq/LinqGeneralBaselineTests.cs | 6066 ++++++++--------- .../Linq/LinqTestsCommon.cs | 28 +- .../OptimisticDirectExecutionQueryTests.cs | 11 +- ...misticDirectExecutionQueryBaselineTests.cs | 108 +- .../Query/Pipeline/FullPipelineTests.cs | 2 +- 12 files changed, 3934 insertions(+), 3728 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index d778db2438..18b65b574f 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -33,7 +33,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"; @@ -758,19 +758,14 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP ITrace trace) { bool clientDisableOptimisticDirectExecution = await cosmosQueryContext.QueryClient.GetClientDisableOptimisticDirectExecutionAsync(); + bool isODEContinuationToken = inputParameters.InitialUserContinuationToken != null && + OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken); // Use the Ode code path only if ClientDisableOptimisticDirectExecution is false and EnableOptimisticDirectExecution is true - if (clientDisableOptimisticDirectExecution || !inputParameters.EnableOptimisticDirectExecution) + // But allow the query using ODE pipeline if it's earlier roundtrips are made using ODE continuation token. + if ((clientDisableOptimisticDirectExecution || !inputParameters.EnableOptimisticDirectExecution) && + !isODEContinuationToken) { - if (inputParameters.InitialUserContinuationToken != null - && OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken)) - { - string errorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + - "If the error persists after that, contact system administrator."; - - throw new MalformedContinuationTokenException($"{errorMessage} Continuation Token: {inputParameters.InitialUserContinuationToken}"); - } - return null; } 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 1a881f3a14..1724ef3266 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,12 +34,8 @@ │ │ ├── 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 │ └── [,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 @@ -52,6 +48,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -88,6 +85,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -124,6 +122,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -160,6 +159,7 @@ │ ├── 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 + │ ├── Get Collection Cache(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] @@ -218,26 +218,6 @@ "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 } ] }, @@ -276,6 +256,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -376,6 +360,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -476,6 +464,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -576,6 +568,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -759,12 +755,8 @@ │ │ ├── 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 │ │ └── [,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 @@ -777,6 +769,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -814,6 +807,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -851,6 +845,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -888,6 +883,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -938,16 +934,6 @@ "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, @@ -960,16 +946,6 @@ } ] }, - { - "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, @@ -1005,6 +981,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1109,6 +1089,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1213,6 +1197,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1317,6 +1305,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1505,12 +1497,8 @@ │ │ ├── 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 │ └── [,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 @@ -1523,6 +1511,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -1559,6 +1548,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -1595,6 +1585,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -1631,6 +1622,7 @@ │ ├── 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 + │ ├── Get Collection Cache(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] @@ -1689,26 +1681,6 @@ "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 } ] }, @@ -1747,6 +1719,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1847,6 +1823,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1947,6 +1927,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2047,6 +2031,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2231,12 +2219,8 @@ │ │ ├── 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 │ │ └── [,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 @@ -2249,6 +2233,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -2286,6 +2271,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -2323,6 +2309,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -2360,6 +2347,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -2410,16 +2398,6 @@ "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, @@ -2432,16 +2410,6 @@ } ] }, - { - "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, @@ -2477,6 +2445,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2581,6 +2553,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2685,6 +2661,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2789,6 +2769,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2985,6 +2969,7 @@ │ │ │ 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 │ │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds │ │ │ │ ( │ │ │ │ [System Info] @@ -3001,12 +2986,8 @@ │ │ │ [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 │ │ └── [,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 @@ -3019,6 +3000,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -3056,6 +3038,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -3093,6 +3076,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -3130,6 +3114,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -3187,6 +3172,10 @@ "name": "Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler", "duration in milliseconds": 0, "children": [ + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -3230,16 +3219,6 @@ } ] }, - { - "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, @@ -3252,16 +3231,6 @@ } ] }, - { - "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, @@ -3297,6 +3266,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -3401,6 +3374,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -3505,6 +3482,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -3609,6 +3590,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -3799,15 +3784,9 @@ │ │ ├── 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 │ └── [,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 @@ -3820,6 +3799,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -3856,6 +3836,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -3892,6 +3873,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -3928,6 +3910,7 @@ │ ├── 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 + │ ├── Get Collection Cache(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] @@ -3977,22 +3960,6 @@ "name": "Service Interop Query Plan", "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 - } - ] - } - ] - }, { "name": "Get Overlapping Feed Ranges", "duration in milliseconds": 0, @@ -4011,22 +3978,6 @@ } ] }, - { - "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": "MoveNextAsync", "duration in milliseconds": 0, @@ -4062,6 +4013,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -4162,6 +4117,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -4262,6 +4221,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -4362,6 +4325,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -4548,15 +4515,9 @@ │ │ ├── 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 │ │ └── [,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 @@ -4569,6 +4530,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -4606,6 +4568,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -4643,6 +4606,7 @@ │ │ │ ├── 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 + │ │ │ ├── Get Collection Cache(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] @@ -4680,6 +4644,7 @@ │ │ ├── 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 + │ │ ├── Get Collection Cache(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] @@ -4730,22 +4695,6 @@ "name": "Service Interop Query Plan", "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 - } - ] - } - ] - }, { "name": "Get Overlapping Feed Ranges", "duration in milliseconds": 0, @@ -4764,22 +4713,6 @@ } ] }, - { - "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": "MoveNextAsync", "duration in milliseconds": 0, @@ -4815,6 +4748,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -4919,6 +4856,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -5023,6 +4964,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -5127,6 +5072,10 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, + { + "name": "Get Collection Cache", + "duration in milliseconds": 0 + }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "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 5f242a1d00..650656ba7c 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,105 +25,120 @@ │ │ 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 - │ ├── 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 + │ │ ├── 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 + │ └── [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 + │ │ ├── Get Collection Cache(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 - │ ├── 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 + │ │ ├── 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 + │ └── [,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 + │ │ ├── Get Collection Cache(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 - ├── 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 + │ ├── 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 + └── [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 + │ ├── Get Collection Cache(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.TestGroupByTranslation.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml index f5256c787c..693eb62bb4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml @@ -320,6 +320,7 @@ SELECT VALUE root["id"] FROM root GROUP BY root["id"] ORDER BY root["id"] DESC]]> + @@ -334,6 +335,7 @@ FROM root WHERE (root["id"] != "a") GROUP BY root["id"] ORDER BY root["id"] 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 75054876fc..3fd9cd342d 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,6 +388,7 @@ FROM ( JOIN c0 IN root["Children"]) AS v1) AS r1 ORDER BY r1["FamilyId"] ASC, r1["FamilyNumber"] ASC ]]> + @@ -584,7 +585,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/Linq/LinqCleanupTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqCleanupTests.cs index 6e16380f90..d7f553f577 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqCleanupTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqCleanupTests.cs @@ -20,7 +20,7 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests [TestClass] public class LinqCleanupTests { - [Ignore] + //[Ignore] [TestMethod] public async Task CleanupLinqTestDatabases() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs index 3604a1e89b..9868dc687c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs @@ -1,3068 +1,3068 @@ -//----------------------------------------------------------------------- -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//----------------------------------------------------------------------- -namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Linq.Dynamic; - using System.Runtime.Serialization; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Linq; - using Microsoft.Azure.Cosmos.SDK.EmulatorTests; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json; - using BaselineTest; - using Microsoft.Azure.Documents; - using Microsoft.Azure.Cosmos.Scripts; - using static Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests.LinqGeneralBaselineTests; - - [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] - public class LinqGeneralBaselineTests : BaselineTests - { - private static CosmosClient cosmosClient; - private static Cosmos.Database testDb; - private static Container testContainer; - private static Func> getQuery; - - [ClassInitialize] - public async static Task Initialize(TestContext textContext) - { - cosmosClient = TestCommon.CreateCosmosClient(true); - DocumentClientSwitchLinkExtension.Reset("LinqTests"); - - string dbName = $"{nameof(LinqGeneralBaselineTests)}-{Guid.NewGuid().ToString("N")}"; - testDb = await cosmosClient.CreateDatabaseAsync(dbName); - - getQuery = LinqTestsCommon.GenerateFamilyCosmosData(testDb, out testContainer); - } - - [ClassCleanup] - public async static Task CleanUp() - { - if (testDb != null) - { - await testDb.DeleteStreamAsync(); - } - - cosmosClient?.Dispose(); - } - - public class Address - { - public string State; - public string County; - public string City; - } - - public class GuidClass : LinqTestObject - { - [JsonProperty(PropertyName = "id")] - public Guid Id; - } - - public class ListArrayClass : LinqTestObject - { - [JsonProperty(PropertyName = "id")] - public string Id; - - public int[] ArrayField; - public List ListField; - } - - [DataContract] - public class Sport : LinqTestObject - { - [DataMember(Name = "id")] - public string SportName; - - [JsonProperty(PropertyName = "json")] - [DataMember(Name = "data")] - public string SportType; - } - - public class Sport2 : LinqTestObject - { - [DataMember(Name = "data")] - public string id; - } - - [TestMethod] - public void TestSelectMany() +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Linq.Dynamic; + using System.Runtime.Serialization; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Linq; + using Microsoft.Azure.Cosmos.SDK.EmulatorTests; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using BaselineTest; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Cosmos.Scripts; + using static Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests.LinqGeneralBaselineTests; + + [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] + public class LinqGeneralBaselineTests : BaselineTests + { + private static CosmosClient cosmosClient; + private static Cosmos.Database testDb; + private static Container testContainer; + private static Func> getQuery; + + [ClassInitialize] + public async static Task Initialize(TestContext textContext) + { + cosmosClient = TestCommon.CreateCosmosClient(true); + DocumentClientSwitchLinkExtension.Reset("LinqTests"); + + string dbName = $"{nameof(LinqGeneralBaselineTests)}-{Guid.NewGuid().ToString("N")}"; + testDb = await cosmosClient.CreateDatabaseAsync(dbName); + + getQuery = LinqTestsCommon.GenerateFamilyCosmosData(testDb, out testContainer); + } + + [ClassCleanup] + public async static Task CleanUp() + { + if (testDb != null) + { + await testDb.DeleteStreamAsync(); + } + + cosmosClient?.Dispose(); + } + + public class Address + { + public string State; + public string County; + public string City; + } + + public class GuidClass : LinqTestObject + { + [JsonProperty(PropertyName = "id")] + public Guid Id; + } + + public class ListArrayClass : LinqTestObject + { + [JsonProperty(PropertyName = "id")] + public string Id; + + public int[] ArrayField; + public List ListField; + } + + [DataContract] + public class Sport : LinqTestObject + { + [DataMember(Name = "id")] + public string SportName; + + [JsonProperty(PropertyName = "json")] + [DataMember(Name = "data")] + public string SportType; + } + + public class Sport2 : LinqTestObject + { + [DataMember(Name = "data")] + public string id; + } + + [TestMethod] + public void TestSelectMany() + { + List inputs = new List(); + + inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet))))); + + inputs.Add(new LinqTestInput("SelectMany(Where -> SelectMany(Where -> Select))", + b => getQuery(b) + .SelectMany(family => family.Children.Where(c => c.Grade > 10) + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet))))); + + inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select new {}))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }))))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Select)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Where)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select) -> Select", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Select(n => n.Count()))); + + inputs.Add(new LinqTestInput("SelectMany()", b => getQuery(b).SelectMany(root => root.Children))); + + inputs.Add(new LinqTestInput("SelectMany -> SelectMany", b => getQuery(b).SelectMany(f => f.Children).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children).Where(c => c.Pets.Count() > 0).SelectMany(c => c.Pets.Select(p => p.GivenName)))); + + inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select new)", b => getQuery(b) + .SelectMany(f => f.Children) + .Where(c => c.Pets.Count() > 0) + .SelectMany(c => c.Pets.Select(p => new { PetName = p.GivenName, OwnerName = c.GivenName })))); + + inputs.Add(new LinqTestInput("Where -> SelectMany", b => getQuery(b).Where(f => f.Children.Count() > 0).SelectMany(f => f.Children))); + + inputs.Add(new LinqTestInput("SelectMany -> Select", b => getQuery(b).SelectMany(f => f.Children).Select(c => c.FamilyName))); + + inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); + + inputs.Add(new LinqTestInput("SelectMany(Select -> Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); + + inputs.Add(new LinqTestInput("SelectMany(Select -> Where)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); + + inputs.Add(new LinqTestInput("SelectMany(Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.Take(2).Where(c => c.FamilyName.Count() > 10)))); + + inputs.Add(new LinqTestInput("SelectMany(OrderBy -> Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.OrderBy(c => c.Grade).Take(2).Where(c => c.FamilyName.Count() > 10)))); + + inputs.Add(new LinqTestInput("SelectMany(Distinct -> Where)", b => getQuery(b).SelectMany(f => f.Children.Distinct().Where(c => c.FamilyName.Count() > 10)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestSimpleSubquery() + { + List inputs = new List(); + + inputs.Add(new LinqTestInput("Select -> Select", b => getQuery(b).Select(f => f.FamilyId).Select(n => n.Count()))); + + inputs.Add(new LinqTestInput("Select -> Where", b => getQuery(b).Select(f => f.FamilyId).Where(id => id.Count() > 10))); + + inputs.Add(new LinqTestInput("Select -> OrderBy -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(x => x).OrderBy(x => x).Take(10).Select(f => f.FamilyId).OrderBy(n => n.Count()).Take(5))); + + inputs.Add(new LinqTestInput("Select -> Orderby -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(f => f).OrderBy(f => f.Children.Count()).Take(3).Select(x => x).OrderBy(f => f.Parents.Count()).Take(2))); + + inputs.Add(new LinqTestInput("Orderby -> Take -> Orderby -> Take", b => getQuery(b).OrderBy(f => f.Children.Count()).Take(3).OrderBy(f => f.Parents.Count()).Take(2))); + + inputs.Add(new LinqTestInput("Take -> Orderby -> Take", b => getQuery(b).Take(10).OrderBy(f => f.FamilyId).Take(1))); + + inputs.Add(new LinqTestInput("Take -> Where -> Take -> Where -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Take(9).Where(f => f.Parents.Count() > 0).Take(8).Where(f => f.FamilyId.Count() > 10))); + + inputs.Add(new LinqTestInput("Take -> Where -> Distinct -> Select -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Distinct().Select(f => new { f }).Take(8).Where(f => f.f.FamilyId.Count() > 10))); + + inputs.Add(new LinqTestInput("Distinct -> Select -> Take -> Where -> Take -> Where", b => getQuery(b).Distinct().Select(f => new { f }).Take(10).Where(f => f.f.Children.Count() > 0).Take(9).Where(f => f.f.Parents.Count() > 0))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestQueryFlattening() + { + // these queries should make more sense when combined with where and orderby + // these tests verify the flattening part + List inputs = new List(); + inputs.Add(new LinqTestInput("array create", b => getQuery(b).Select(f => f.Int).Select(i => new int[] { i }))); + inputs.Add(new LinqTestInput("unary operation", b => getQuery(b).Select(f => f.Int).Select(i => -i))); + inputs.Add(new LinqTestInput("binary operation", b => getQuery(b).Select(f => f).Select(i => i.Int % 10 * i.Children.Count()))); + inputs.Add(new LinqTestInput("literal", b => getQuery(b).Select(f => f.Int).Select(i => 0))); + inputs.Add(new LinqTestInput("function call", b => getQuery(b).Select(f => f.Parents).Select(p => p.Count()))); + inputs.Add(new LinqTestInput("object create", b => getQuery(b).Select(f => f.Parents).Select(p => new { parentCount = p.Count() }))); + inputs.Add(new LinqTestInput("conditional", b => getQuery(b).Select(f => f.Children).Select(c => c.Count() > 0 ? "have kids" : "no kids"))); + inputs.Add(new LinqTestInput("property ref + indexer", b => getQuery(b).Select(f => f) + .Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0) + .Select(f => f.Children[0].Pets[0].GivenName))); + + inputs.Add(new LinqTestInput("array creation -> indexer", b => getQuery(b).Select(f => new int[] { f.Int }).Select(array => array[0]))); + inputs.Add(new LinqTestInput("unary, indexer, property, function call -> function call", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .Select(f => -f.Children[0].Pets.Count()).Select(i => Math.Abs(i)))); + inputs.Add(new LinqTestInput("binary operation, function call -> conditional", b => getQuery(b).Select(i => i.Int % 10 * i.Children.Count()).Select(i => i > 0 ? new int[] { i } : new int[] { }))); + inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b) + .Select(f => new { parentCount = f.Parents.Count(), childrenCount = f.Children.Count() }) + .Select(r => r.parentCount > 0 ? Math.Floor((double)r.childrenCount / r.parentCount) : 0))); + inputs.Add(new LinqTestInput("indexer -> function call", b => getQuery(b).Select(f => f.Parents[0]).Select(p => string.Concat(p.FamilyName, p.GivenName)))); + inputs.Add(new LinqTestInput("conditional -> object creation", b => getQuery(b).Select(f => f.Parents.Count() > 0 ? f.Parents : new Parent[0]).Select(p => new { parentCount = p.Count() }))); + inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { children = f.Children }).Select(c => c.children.Count() > 0 ? c.children[0].GivenName : "no kids"))); + inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { family = f, children = f.Children.Count() }).Select(f => f.children > 0 && f.family.Children[0].Pets.Count() > 0 ? f.family.Children[0].Pets[0].GivenName : "no kids"))); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestSubquery() + { + List inputs = new List(); + + // -------------------------------------- + // Subquery lambdas + // -------------------------------------- + + inputs.Add(new LinqTestInput( + "Select(Select)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Select(OrderBy)", b => getQuery(b) + .Select(f => f.Children.OrderBy(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Select(Take)", b => getQuery(b) + .Select(f => f.Children.Take(2)))); + + inputs.Add(new LinqTestInput( + "Select(Where)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Pets.Count() > 0)))); + + inputs.Add(new LinqTestInput( + "Select(Distinct)", b => getQuery(b) + .Select(f => f.Children.Distinct()))); + + inputs.Add(new LinqTestInput( + "Select(Count)", b => getQuery(b) + .Select(f => f.Children.Count(c => c.Grade > 80)))); + + inputs.Add(new LinqTestInput( + "Select(Sum)", b => getQuery(b) + .Select(f => f.Children.Sum(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "Where(Count)", b => getQuery(b) + .Where(f => f.Children.Count(c => c.Pets.Count() > 0) > 0))); + + inputs.Add(new LinqTestInput( + "Where(Sum)", b => getQuery(b) + .Where(f => f.Children.Sum(c => c.Grade) > 100))); + + inputs.Add(new LinqTestInput( + "OrderBy(Select)", b => getQuery(b) + .OrderBy(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "OrderBy(Sum)", b => getQuery(b) + .OrderBy(f => f.Children.Sum(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Count)", b => getQuery(b) + .OrderBy(f => f.Children.Count(c => c.Grade > 90)))); + + // ------------------------------------------------------------- + // Mutilpe-transformations subquery lambdas + // ------------------------------------------------------------- + + inputs.Add(new LinqTestInput( + "Select(Select -> Distinct -> Count)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Gender).Distinct().Count()))); + + inputs.Add(new LinqTestInput( + "Select(Select -> Sum)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade).Sum()))); + + inputs.Add(new LinqTestInput( + "Select(Select -> OrderBy -> Take)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.GivenName).OrderBy(n => n.Length).Take(1)))); + + inputs.Add(new LinqTestInput( + "Select(SelectMany -> Select)", b => getQuery(b) + .Select(f => f.Children.SelectMany(c => c.Pets).Select(c => c.GivenName.Count())))); + + inputs.Add(new LinqTestInput( + "Select(Where -> Count)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).Count()))); + + inputs.Add(new LinqTestInput( + "Select(Where -> OrderBy -> Take)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).OrderBy(c => c.Pets.Count()).Take(3)))); + + inputs.Add(new LinqTestInput( + "Select(Where -> Select -> Take)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets.Count()).Take(3)))); + + inputs.Add(new LinqTestInput( + "Select(Where -> Select(array) -> Take)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets).Take(3)))); + + inputs.Add(new LinqTestInput( + "Select(where -> Select -> Distinct)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50 && c.Pets.Count() > 0).Select(c => c.Gender).Distinct()))); + + inputs.Add(new LinqTestInput( + "Select(OrderBy -> Take -> Select)", b => getQuery(b) + .Select(f => f.Children.OrderBy(c => c.Grade).Take(1).Select(c => c.Gender)))); + + inputs.Add(new LinqTestInput( + "Select(OrderBy -> Take -> Select -> Average)", b => getQuery(b) + .Select(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Select(c => c.Grade).Average()))); + + inputs.Add(new LinqTestInput( + "Where(Select -> Count)", b => getQuery(b) + .Where(f => f.Children.Select(c => c.Pets.Count()).Count() > 0))); + + inputs.Add(new LinqTestInput( + "Where(Where -> Count)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() > 0))); + + inputs.Add(new LinqTestInput( + "Where(Where -> Sum)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Sum(c => c.Grade) < 200))); + + inputs.Add(new LinqTestInput( + "Where(Where -> OrderBy -> Take -> Select)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).OrderBy(c => c.Grade).Take(1).Where(c => c.Grade > 80).Count() > 0))); + + inputs.Add(new LinqTestInput( + "OrderBy(Select -> Where)", b => getQuery(b) + .OrderBy(f => f.Children.Select(c => c.Pets.Count()).Where(x => x > 1)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Where -> Count)", b => getQuery(b) + .OrderBy(f => f.Children.Where(c => c.Pets.Count() > 3).Count()))); + + inputs.Add(new LinqTestInput( + "OrderBy(Select -> Sum)", b => getQuery(b) + .OrderBy(f => f.Children.Select(c => c.Grade).Sum()))); + + inputs.Add(new LinqTestInput( + "OrderBy(OrderBy -> Take -> Sum)", b => getQuery(b) + .OrderBy(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Sum(c => c.Grade)))); + + // --------------------------------------------------------- + // Scalar and Built-in expressions with subquery lambdas + // --------------------------------------------------------- + + // Unary + + inputs.Add(new LinqTestInput( + "Where(unary (Where -> Count))", b => getQuery(b) + .Where(f => -f.Children.Where(c => c.Grade < 20).Count() == 0))); + + // Binary + + inputs.Add(new LinqTestInput( + "Select(binary with Count)", b => getQuery(b) + .Select(f => 5 + f.Children.Count(c => c.Pets.Count() > 0)))); + + inputs.Add(new LinqTestInput( + "Select(constant + Where -> Count)", b => getQuery(b) + .Select(f => 5 + f.Children.Where(c => c.Pets.Count() > 0).Count()))); + + inputs.Add(new LinqTestInput( + "Where((Where -> Count) % constant)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() % 2 == 1))); + + // Conditional + + inputs.Add(new LinqTestInput( + "Select(conditional Any ? Select : Select)", b => getQuery(b) + .Select(f => f.Children.Any() ? f.Children.Select(c => c.GivenName) : f.Parents.Select(p => p.GivenName)))); + + inputs.Add(new LinqTestInput( + "Select(conditional Any(filter) ? Max : Sum)", b => getQuery(b) + .Select(f => f.Children.Any(c => c.Grade > 97) ? f.Children.Max(c => c.Grade) : f.Children.Sum(c => c.Grade)))); + + // New array + + inputs.Add(new LinqTestInput( + "Select(new array)", b => getQuery(b) + .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); + + // New + member init + + inputs.Add(new LinqTestInput( + "Select(new)", b => getQuery(b) + .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); + + inputs.Add(new LinqTestInput( + "Select(Select new)", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenPetCount = f.Children.Select(c => c.Pets.Count()) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where)", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where)", b => getQuery(b) + .Select(f => new { f.FamilyId, GoodChildren = f.Children.Where(c => c.Grade > 90) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where -> Select)", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3).Select(c => c.GivenName) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where -> Count) -> Where", b => getQuery(b) + .Select(f => new { Family = f, ChildrenCount = f.Children.Where(c => c.Grade > 0).Count() }).Where(f => f.ChildrenCount > 0))); + + // Array builtin functions + + inputs.Add(new LinqTestInput( + "Select(Where -> Concat(Where))", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 90).Concat(f.Children.Where(c => c.Grade < 10))))); + + inputs.Add(new LinqTestInput( + "Select(Select -> Contains(Sum))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Sum(c => c.Pets.Count()))))); + + inputs.Add(new LinqTestInput( + "Select(Select -> Contains(Where -> Count))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Where(c => c.Grade > 50).Count())))); + + inputs.Add(new LinqTestInput( + "Where -> Select(array indexer)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) + .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[1]))); + + inputs.Add(new LinqTestInput( + "Where -> Select(array indexer)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) + .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[f.Children.Count() % 2]))); + + // Math builtin functions + + inputs.Add(new LinqTestInput( + "Select(Floor(sum(map), sum(map)))", b => getQuery(b) + .Select(f => Math.Floor(1.0 * f.Children.Sum(c => c.Grade) / (f.Children.Sum(c => c.Pets.Count()) + 1))))); + + inputs.Add(new LinqTestInput( + "Select(Pow(Sum(map), Count(Any)))", b => getQuery(b) + .Select(f => Math.Pow(f.Children.Sum(c => c.Pets.Count()), f.Children.Count(c => c.Pets.Any(p => p.GivenName.Count() == 0 || p.GivenName.Substring(0, 1) == "A")))))); + + inputs.Add(new LinqTestInput( + "OrderBy(Log(Where -> Count))", b => getQuery(b) + .OrderBy(f => Math.Log(f.Children.Where(c => c.Pets.Count() > 0).Count())))); + + // ------------------------------------------------------------------ + // Expression with subquery lambdas -> more transformations + // ------------------------------------------------------------------ + + inputs.Add(new LinqTestInput( + "Select(Select) -> Where", b => getQuery(b).Select(f => f.Children.Select(c => c.Pets.Count())).Where(x => x.Count() > 0))); + + // Customer requested scenario + inputs.Add(new LinqTestInput( + "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) + .Where(f => f.FamilyId.CompareTo("ABC") > 0 && f.SmartChildren.Count() > 0) + .OrderBy(f => f.ChildrenCount) + .Take(10))); + // TODO https://github.com/Azure/azure-cosmos-dotnet-v3/issues/375 + //inputs.Add(new LinqTestInput( + // "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) + // .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) + // .Where(f => f.ChildrenCount > 2 && f.SmartChildren.Count() > 1) + // .OrderBy(f => f.FamilyId) + // .Take(10))); + + inputs.Add(new LinqTestInput( + "Select(new { Select(Select), conditional Count Take }) -> Where -> Select(Select(Any))", b => getQuery(b) + .Select(f => new + { + f.FamilyId, + ChildrenPetFirstChars = f.Children.Select(c => c.Pets.Select(p => p.GivenName.Substring(0, 1))), + FirstChild = f.Children.Count() > 0 ? f.Children.Take(1) : null + }) + .Where(f => f.FirstChild != null) + .Select(f => f.ChildrenPetFirstChars.Select(chArray => chArray.Any(a => f.FamilyId.StartsWith(a)))))); + + inputs.Add(new LinqTestInput( + "Select(new (Select(new (Select, Select))))", b => getQuery(b) + .Select(f => new + { + f.FamilyId, + ChildrenProfile = f.Children.Select(c => new + { + Fullname = c.GivenName + " " + c.FamilyName, + PetNames = c.Pets.Select(p => p.GivenName), + ParentNames = f.Parents.Select(p => p.GivenName) + }) + }))); + + // ------------------------------------------------ + // Subquery lambda -> subquery lamda + // ------------------------------------------------ + + inputs.Add(new LinqTestInput( + "Select(array) -> Where(Sum(map))", b => getQuery(b) + .Select(f => f.Children).Where(children => children.Sum(c => c.Grade) > 100))); + + inputs.Add(new LinqTestInput( + "Select(Select) -> Select(Sum())", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade)).Select(children => children.Sum()))); + + inputs.Add(new LinqTestInput( + "Select(Select) -> Select(Sum(map))", b => getQuery(b) + .Select(f => f.Children).Select(children => children.Sum(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "Where(Any binary) -> Select(Sum(map))", b => getQuery(b) + .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) + .Select(f => f.Children.Sum(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Where(Any binary) -> OrderBy(Count(filter)) -> Select(Sum(map))", b => getQuery(b) + .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) + .OrderBy(f => f.Children.Count(c => c.Things.Count() > 3)) + .Select(f => f.Children.Sum(c => c.Pets.Count())))); + + // ------------------------------ + // Nested subquery lambdas + // ------------------------------ + + inputs.Add(new LinqTestInput( + "Select(Select(Select))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); + + inputs.Add(new LinqTestInput( + "Select(Select(Select))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Pets.Select(p => p))))); + + inputs.Add(new LinqTestInput( + "Select(Select(new Count))", b => getQuery(b) + .Select(f => f.Children + .Select(c => new + { + HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 + })))); + + inputs.Add(new LinqTestInput( + "Where -> Select(conditional ? Take : OrderBy -> Array indexer)", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .Select(f => f.Children.Count() == 1 ? f.Children.Take(1).ToArray()[0] : f.Children.OrderBy(c => c.Grade).ToArray()[1]))); + + inputs.Add(new LinqTestInput( + "Select(Where(Where -> Count) -> Select(new Count))", b => getQuery(b) + .Select(f => f.Children + .Where(c => c.Pets + .Where(p => p.GivenName.Count() > 10 && p.GivenName.Substring(0, 1) == "A") + .Count() > 0) + .Select(c => new + { + HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 + })))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select(Select))", b => getQuery(b) + .SelectMany(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where(Any))", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); + + inputs.Add(new LinqTestInput( + "Where(Where(Count) -> Count)", b => getQuery(b) + .Where(f => f.Parents.Where(p => p.FamilyName.Count() > 10).Count() > 1))); + + inputs.Add(new LinqTestInput( + "Where(Where(Where -> Count) -> Count)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Where(p => p.GivenName.Count() > 15).Count() > 0).Count() > 0))); + + inputs.Add(new LinqTestInput( + "Where(Select(Select -> Any))", b => getQuery(b) + .Where(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); + + // ------------------------------------- + // Expression -> Subquery lambdas + // ------------------------------------- + + inputs.Add(new LinqTestInput( + "Select(new) -> Select(Select)", b => getQuery(b) + .Select(f => new { f.FamilyId, Family = f }).Select(f => f.Family.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "SelectMany -> Select(Select)", b => getQuery(b) + .SelectMany(f => f.Children).Select(c => c.Pets.Select(p => p.GivenName.Count())))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where) -> Where(Any) -> Select(Select)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.Grade > 80)) + .Where(c => c.Pets.Any(p => p.GivenName.Count() > 20)) + .Select(c => c.Pets.Select(p => p.GivenName.Count())))); + + inputs.Add(new LinqTestInput( + "Distinct -> Select(new) -> Where(Select(Select -> Any))", b => getQuery(b) + .Distinct() + .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), Family = f }) + .Where(f => f.Family.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); + + inputs.Add(new LinqTestInput( + "Where -> Select(Select)", b => getQuery(b) + .Where(f => f.Children.Count() > 0).Select(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Distinct -> Select(Select)", b => getQuery(b) + .Distinct().Select(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Take -> Select(Select)", b => getQuery(b) + .Take(10).Select(f => f.Children.Select(c => c.Pets.Count())))); + + // ------------------ + // Any in lambda + // ------------------ + + inputs.Add(new LinqTestInput( + "Select(Any w const array)", b => getQuery(b) + .Select(f => new int[] { 1, 2, 3 }.Any()))); + + inputs.Add(new LinqTestInput( + "Select(Any)", b => getQuery(b) + .Select(f => f.Children.Any()))); + + inputs.Add(new LinqTestInput( + "Select(Any w lambda)", b => getQuery(b) + .Select(f => f.Children.Any(c => c.Grade > 80)))); + + inputs.Add(new LinqTestInput( + "Select(new Any)", b => getQuery(b) + .Select(f => new { f.FamilyId, HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); + + inputs.Add(new LinqTestInput( + "Select(new 2 Any)", b => getQuery(b) + .Select(f => new { HasChildrenWithPets = f.Children.Any(c => c.Pets.Count() > 0), HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); + + inputs.Add(new LinqTestInput( + "Select(Nested Any)", b => getQuery(b) + .Select(f => f.Children.Any(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); + + inputs.Add(new LinqTestInput( + "Where(Any)", b => getQuery(b) + .Where(f => f.Children.Any(c => c.Pets.Count() > 0)))); + + // Customer requested scenario + inputs.Add(new LinqTestInput( + "Where(simple expr && Any)", b => getQuery(b) + .Where(f => f.FamilyId.Contains("a") && f.Children.Any(c => c.Pets.Count() > 0)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Any)", b => getQuery(b) + .OrderBy(f => f.Children.Any(c => c.Pets.Count() > 3)))); + + // ------------------------------------------------ + // SelectMany with Take and OrderBy in lambda + // ------------------------------------------------ + + inputs.Add(new LinqTestInput( + "SelectMany(Take)", b => getQuery(b) + .SelectMany(f => f.Children.Take(2)))); + + inputs.Add(new LinqTestInput( + "SelectMany(OrderBy)", b => getQuery(b) + .SelectMany(f => f.Children.OrderBy(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where -> Take)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where -> Take -> Select)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2).Select(c => c.Grade)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestGroupByTranslation() + { + List inputs = new List(); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k /*keySelector*/, + (key, values) => key /*return the group by key */))); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => key /*return the group by key */))); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key Alias", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (stringField, values) => stringField /*return the group by key */))); + + + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Min(value => value.Int) /*return the Min of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Max(value => value.Int) /*return the Max of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Count() /*return the Count of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Average", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Average(value => value.Int) /*return the Count of each group */))); + + // Negative cases + + // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] + // but the behavior between LINQ and SQL is different + // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => values.Min() /*return the Min of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => values.Max() /*return the Max of each group */))); + + // Unsupported node type + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => "string" /* Unsupported Nodetype*/ ))); + + // Incorrect number of arguments + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy( + k => k.Int, + k2 => k2.Int, + (key, values) => "string" /* Unsupported Nodetype*/ ))); + + // Non-aggregate method calls + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Select(value => value.Int) /*Not an aggregate*/))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.OrderBy(f => f.FamilyId) /*Not an aggregate*/))); + + // Currently unsupported case + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, + (key, values) => new { familyId = key, familyIdCount = values.Count() } /*multi-value select */))); + + // Other methods followed by GroupBy + + inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) + .Select(x => x.Id) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) + .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) + .GroupBy(k => k.family1 /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) + .SelectMany(x => x.Children) + .GroupBy(k => k.Grade /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("SelectMany + GroupBy 2", b => getQuery(b) + .SelectMany(f => f.Children) + .Where(c => c.Pets.Count() > 0) + .SelectMany(c => c.Pets.Select(p => p.GivenName)) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) + .Skip(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) + .Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) + .Skip(10).Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // should this become a subquery with order by then group by? + inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) + .OrderBy(x => x.Int) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) + .OrderByDescending(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .OrderBy(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // The result for this is not correct yet - the select clause is wrong + inputs.Add(new LinqTestInput("Combination 2 + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .Where(x => x.Children.Min(y => y.Grade) > 10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // GroupBy followed by other methods + inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Select(x => x))); + + //We should support skip take + inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Skip(10))); + + inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Skip(10).Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Where(x => x == "a"))); + + inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .OrderBy(x => x))); + + inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .OrderByDescending(x => x))); + + inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Where(x => x == "a").Skip(10).Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestGroupByMultiValueTranslation() { List inputs = new List(); + inputs.Add(new LinqTestInput("GroupBy Multi Value Select Constant", b => getQuery(b).GroupBy(k => k /*keySelector*/, + (key, values) => + new { + stringField = "abv", + numField = 123 + }))); - inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet))))); - - inputs.Add(new LinqTestInput("SelectMany(Where -> SelectMany(Where -> Select))", - b => getQuery(b) - .SelectMany(family => family.Children.Where(c => c.Grade > 10) - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet))))); - - inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select new {}))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }))))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Select)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Where)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); + inputs.Add(new LinqTestInput("GroupBy Multi Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + Key = key, + key + }))); - inputs.Add(new LinqTestInput( - "SelectMany(Select) -> Select", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Select(n => n.Count()))); + inputs.Add(new LinqTestInput("GroupBy Multi Value Select Key and Constant", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + KeyAlias = key, + values = 123 /* intentionally have the same spelling as the IGrouping values */ + }))); - inputs.Add(new LinqTestInput("SelectMany()", b => getQuery(b).SelectMany(root => root.Children))); + inputs.Add(new LinqTestInput("GroupBy Multi Value With Aggregate", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + Min = values.Min(value => value.Int), + Max = values.Max(value => value.Int), + Avg = values.Average(value => value.Int), + Count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany -> SelectMany", b => getQuery(b).SelectMany(f => f.Children).SelectMany(c => c.Pets))); + inputs.Add(new LinqTestInput("GroupBy Multi Value With Property Ref and Aggregate", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, + (key, values) => new { + familyId = key, + familyIdCount = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children).Where(c => c.Pets.Count() > 0).SelectMany(c => c.Pets.Select(p => p.GivenName)))); + // Negative cases - inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select new)", b => getQuery(b) - .SelectMany(f => f.Children) - .Where(c => c.Pets.Count() > 0) - .SelectMany(c => c.Pets.Select(p => new { PetName = p.GivenName, OwnerName = c.GivenName })))); + // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] + // but the behavior between LINQ and SQL is different + // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null + inputs.Add(new LinqTestInput("GroupBy Multi Value With Aggregate On Root", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + Min = values.Min(), + Max = values.Max() + }))); - inputs.Add(new LinqTestInput("Where -> SelectMany", b => getQuery(b).Where(f => f.Children.Count() > 0).SelectMany(f => f.Children))); + // Non-aggregate method calls + inputs.Add(new LinqTestInput("GroupBy Multi Value With Non-Aggregate", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + valueSelect = values.Select(value => value.Int), + valueOrderBy = values.OrderBy(f => f.FamilyId) + }))); + // Other methods followed by GroupBy - inputs.Add(new LinqTestInput("SelectMany -> Select", b => getQuery(b).SelectMany(f => f.Children).Select(c => c.FamilyName))); + inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) + .Select(x => x.Id) + .GroupBy(k => k /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children.Select(c => c.Pets.Count())))); + inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) + .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) + .GroupBy(k => k.Id1 /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); + inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) + .SelectMany(x => x.Children) + .GroupBy(k => k /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Select -> Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); + inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) + .Skip(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Select -> Where)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); + inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) + .Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.Take(2).Where(c => c.FamilyName.Count() > 10)))); + inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) + .Skip(10).Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(OrderBy -> Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.OrderBy(c => c.Grade).Take(2).Where(c => c.FamilyName.Count() > 10)))); + inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Distinct -> Where)", b => getQuery(b).SelectMany(f => f.Children.Distinct().Where(c => c.FamilyName.Count() > 10)))); + // should this become a subquery with order by then group by? + inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) + .OrderBy(x => x.Int) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - this.ExecuteTestSuite(inputs); - } + inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) + .OrderByDescending(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - [TestMethod] - public void TestSimpleSubquery() - { - List inputs = new List(); + inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .OrderBy(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("Select -> Select", b => getQuery(b).Select(f => f.FamilyId).Select(n => n.Count()))); + // GroupBy followed by other methods + inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Select(x => x))); - inputs.Add(new LinqTestInput("Select -> Where", b => getQuery(b).Select(f => f.FamilyId).Where(id => id.Count() > 10))); + inputs.Add(new LinqTestInput("GroupBy + Select 2", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Select(x => x.keyAlias))); - inputs.Add(new LinqTestInput("Select -> OrderBy -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(x => x).OrderBy(x => x).Take(10).Select(f => f.FamilyId).OrderBy(n => n.Count()).Take(5))); + //We should support skip take + inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Skip(10))); - inputs.Add(new LinqTestInput("Select -> Orderby -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(f => f).OrderBy(f => f.Children.Count()).Take(3).Select(x => x).OrderBy(f => f.Parents.Count()).Take(2))); + inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Take(10))); - inputs.Add(new LinqTestInput("Orderby -> Take -> Orderby -> Take", b => getQuery(b).OrderBy(f => f.Children.Count()).Take(3).OrderBy(f => f.Parents.Count()).Take(2))); + inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Skip(10).Take(10))); - inputs.Add(new LinqTestInput("Take -> Orderby -> Take", b => getQuery(b).Take(10).OrderBy(f => f.FamilyId).Take(1))); + inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Where(x => x.keyAlias == "a"))); - inputs.Add(new LinqTestInput("Take -> Where -> Take -> Where -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Take(9).Where(f => f.Parents.Count() > 0).Take(8).Where(f => f.FamilyId.Count() > 10))); + inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .OrderBy(x => x.keyAlias))); - inputs.Add(new LinqTestInput("Take -> Where -> Distinct -> Select -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Distinct().Select(f => new { f }).Take(8).Where(f => f.f.FamilyId.Count() > 10))); + inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .OrderByDescending(x => x.count))); - inputs.Add(new LinqTestInput("Distinct -> Select -> Take -> Where -> Take -> Where", b => getQuery(b).Distinct().Select(f => new { f }).Take(10).Where(f => f.f.Children.Count() > 0).Take(9).Where(f => f.f.Parents.Count() > 0))); + inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Where(x => x.keyAlias == "a").Skip(10).Take(10))); - this.ExecuteTestSuite(inputs); - } + inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .GroupBy(k => k.count /*keySelector*/, (key, values) => key /*return the group by key */))); - [TestMethod] - public void TestQueryFlattening() - { - // these queries should make more sense when combined with where and orderby - // these tests verify the flattening part - List inputs = new List(); - inputs.Add(new LinqTestInput("array create", b => getQuery(b).Select(f => f.Int).Select(i => new int[] { i }))); - inputs.Add(new LinqTestInput("unary operation", b => getQuery(b).Select(f => f.Int).Select(i => -i))); - inputs.Add(new LinqTestInput("binary operation", b => getQuery(b).Select(f => f).Select(i => i.Int % 10 * i.Children.Count()))); - inputs.Add(new LinqTestInput("literal", b => getQuery(b).Select(f => f.Int).Select(i => 0))); - inputs.Add(new LinqTestInput("function call", b => getQuery(b).Select(f => f.Parents).Select(p => p.Count()))); - inputs.Add(new LinqTestInput("object create", b => getQuery(b).Select(f => f.Parents).Select(p => new { parentCount = p.Count() }))); - inputs.Add(new LinqTestInput("conditional", b => getQuery(b).Select(f => f.Children).Select(c => c.Count() > 0 ? "have kids" : "no kids"))); - inputs.Add(new LinqTestInput("property ref + indexer", b => getQuery(b).Select(f => f) - .Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0) - .Select(f => f.Children[0].Pets[0].GivenName))); + inputs.Add(new LinqTestInput("GroupBy + GroupBy2", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }) + .GroupBy(k => k.count /*keySelector*/, (key, values) => new { + keyAlias = key, + stringField = "abc" + }))); - inputs.Add(new LinqTestInput("array creation -> indexer", b => getQuery(b).Select(f => new int[] { f.Int }).Select(array => array[0]))); - inputs.Add(new LinqTestInput("unary, indexer, property, function call -> function call", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .Select(f => -f.Children[0].Pets.Count()).Select(i => Math.Abs(i)))); - inputs.Add(new LinqTestInput("binary operation, function call -> conditional", b => getQuery(b).Select(i => i.Int % 10 * i.Children.Count()).Select(i => i > 0 ? new int[] { i } : new int[] { }))); - inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b) - .Select(f => new { parentCount = f.Parents.Count(), childrenCount = f.Children.Count() }) - .Select(r => r.parentCount > 0 ? Math.Floor((double)r.childrenCount / r.parentCount) : 0))); - inputs.Add(new LinqTestInput("indexer -> function call", b => getQuery(b).Select(f => f.Parents[0]).Select(p => string.Concat(p.FamilyName, p.GivenName)))); - inputs.Add(new LinqTestInput("conditional -> object creation", b => getQuery(b).Select(f => f.Parents.Count() > 0 ? f.Parents : new Parent[0]).Select(p => new { parentCount = p.Count() }))); - inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { children = f.Children }).Select(c => c.children.Count() > 0 ? c.children[0].GivenName : "no kids"))); - inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { family = f, children = f.Children.Count() }).Select(f => f.children > 0 && f.family.Children[0].Pets.Count() > 0 ? f.family.Children[0].Pets[0].GivenName : "no kids"))); this.ExecuteTestSuite(inputs); } [TestMethod] - public void TestSubquery() - { - List inputs = new List(); - - // -------------------------------------- - // Subquery lambdas - // -------------------------------------- - - inputs.Add(new LinqTestInput( - "Select(Select)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Select(OrderBy)", b => getQuery(b) - .Select(f => f.Children.OrderBy(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Select(Take)", b => getQuery(b) - .Select(f => f.Children.Take(2)))); - - inputs.Add(new LinqTestInput( - "Select(Where)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Pets.Count() > 0)))); - - inputs.Add(new LinqTestInput( - "Select(Distinct)", b => getQuery(b) - .Select(f => f.Children.Distinct()))); - - inputs.Add(new LinqTestInput( - "Select(Count)", b => getQuery(b) - .Select(f => f.Children.Count(c => c.Grade > 80)))); - - inputs.Add(new LinqTestInput( - "Select(Sum)", b => getQuery(b) - .Select(f => f.Children.Sum(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "Where(Count)", b => getQuery(b) - .Where(f => f.Children.Count(c => c.Pets.Count() > 0) > 0))); - - inputs.Add(new LinqTestInput( - "Where(Sum)", b => getQuery(b) - .Where(f => f.Children.Sum(c => c.Grade) > 100))); - - inputs.Add(new LinqTestInput( - "OrderBy(Select)", b => getQuery(b) - .OrderBy(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "OrderBy(Sum)", b => getQuery(b) - .OrderBy(f => f.Children.Sum(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Count)", b => getQuery(b) - .OrderBy(f => f.Children.Count(c => c.Grade > 90)))); - - // ------------------------------------------------------------- - // Mutilpe-transformations subquery lambdas - // ------------------------------------------------------------- - - inputs.Add(new LinqTestInput( - "Select(Select -> Distinct -> Count)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Gender).Distinct().Count()))); - - inputs.Add(new LinqTestInput( - "Select(Select -> Sum)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade).Sum()))); - - inputs.Add(new LinqTestInput( - "Select(Select -> OrderBy -> Take)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.GivenName).OrderBy(n => n.Length).Take(1)))); - - inputs.Add(new LinqTestInput( - "Select(SelectMany -> Select)", b => getQuery(b) - .Select(f => f.Children.SelectMany(c => c.Pets).Select(c => c.GivenName.Count())))); - - inputs.Add(new LinqTestInput( - "Select(Where -> Count)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).Count()))); - - inputs.Add(new LinqTestInput( - "Select(Where -> OrderBy -> Take)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).OrderBy(c => c.Pets.Count()).Take(3)))); - - inputs.Add(new LinqTestInput( - "Select(Where -> Select -> Take)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets.Count()).Take(3)))); - - inputs.Add(new LinqTestInput( - "Select(Where -> Select(array) -> Take)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets).Take(3)))); - - inputs.Add(new LinqTestInput( - "Select(where -> Select -> Distinct)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50 && c.Pets.Count() > 0).Select(c => c.Gender).Distinct()))); - - inputs.Add(new LinqTestInput( - "Select(OrderBy -> Take -> Select)", b => getQuery(b) - .Select(f => f.Children.OrderBy(c => c.Grade).Take(1).Select(c => c.Gender)))); - - inputs.Add(new LinqTestInput( - "Select(OrderBy -> Take -> Select -> Average)", b => getQuery(b) - .Select(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Select(c => c.Grade).Average()))); - - inputs.Add(new LinqTestInput( - "Where(Select -> Count)", b => getQuery(b) - .Where(f => f.Children.Select(c => c.Pets.Count()).Count() > 0))); - - inputs.Add(new LinqTestInput( - "Where(Where -> Count)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() > 0))); - - inputs.Add(new LinqTestInput( - "Where(Where -> Sum)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Sum(c => c.Grade) < 200))); - - inputs.Add(new LinqTestInput( - "Where(Where -> OrderBy -> Take -> Select)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).OrderBy(c => c.Grade).Take(1).Where(c => c.Grade > 80).Count() > 0))); - - inputs.Add(new LinqTestInput( - "OrderBy(Select -> Where)", b => getQuery(b) - .OrderBy(f => f.Children.Select(c => c.Pets.Count()).Where(x => x > 1)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Where -> Count)", b => getQuery(b) - .OrderBy(f => f.Children.Where(c => c.Pets.Count() > 3).Count()))); - - inputs.Add(new LinqTestInput( - "OrderBy(Select -> Sum)", b => getQuery(b) - .OrderBy(f => f.Children.Select(c => c.Grade).Sum()))); - - inputs.Add(new LinqTestInput( - "OrderBy(OrderBy -> Take -> Sum)", b => getQuery(b) - .OrderBy(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Sum(c => c.Grade)))); - - // --------------------------------------------------------- - // Scalar and Built-in expressions with subquery lambdas - // --------------------------------------------------------- - - // Unary - - inputs.Add(new LinqTestInput( - "Where(unary (Where -> Count))", b => getQuery(b) - .Where(f => -f.Children.Where(c => c.Grade < 20).Count() == 0))); - - // Binary - - inputs.Add(new LinqTestInput( - "Select(binary with Count)", b => getQuery(b) - .Select(f => 5 + f.Children.Count(c => c.Pets.Count() > 0)))); - - inputs.Add(new LinqTestInput( - "Select(constant + Where -> Count)", b => getQuery(b) - .Select(f => 5 + f.Children.Where(c => c.Pets.Count() > 0).Count()))); - - inputs.Add(new LinqTestInput( - "Where((Where -> Count) % constant)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() % 2 == 1))); - - // Conditional - - inputs.Add(new LinqTestInput( - "Select(conditional Any ? Select : Select)", b => getQuery(b) - .Select(f => f.Children.Any() ? f.Children.Select(c => c.GivenName) : f.Parents.Select(p => p.GivenName)))); - - inputs.Add(new LinqTestInput( - "Select(conditional Any(filter) ? Max : Sum)", b => getQuery(b) - .Select(f => f.Children.Any(c => c.Grade > 97) ? f.Children.Max(c => c.Grade) : f.Children.Sum(c => c.Grade)))); - - // New array - - inputs.Add(new LinqTestInput( - "Select(new array)", b => getQuery(b) - .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); - - // New + member init - - inputs.Add(new LinqTestInput( - "Select(new)", b => getQuery(b) - .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); - - inputs.Add(new LinqTestInput( - "Select(Select new)", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenPetCount = f.Children.Select(c => c.Pets.Count()) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where)", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where)", b => getQuery(b) - .Select(f => new { f.FamilyId, GoodChildren = f.Children.Where(c => c.Grade > 90) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where -> Select)", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3).Select(c => c.GivenName) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where -> Count) -> Where", b => getQuery(b) - .Select(f => new { Family = f, ChildrenCount = f.Children.Where(c => c.Grade > 0).Count() }).Where(f => f.ChildrenCount > 0))); - - // Array builtin functions - - inputs.Add(new LinqTestInput( - "Select(Where -> Concat(Where))", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 90).Concat(f.Children.Where(c => c.Grade < 10))))); - - inputs.Add(new LinqTestInput( - "Select(Select -> Contains(Sum))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Sum(c => c.Pets.Count()))))); - - inputs.Add(new LinqTestInput( - "Select(Select -> Contains(Where -> Count))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Where(c => c.Grade > 50).Count())))); - - inputs.Add(new LinqTestInput( - "Where -> Select(array indexer)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) - .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[1]))); - - inputs.Add(new LinqTestInput( - "Where -> Select(array indexer)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) - .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[f.Children.Count() % 2]))); - - // Math builtin functions - - inputs.Add(new LinqTestInput( - "Select(Floor(sum(map), sum(map)))", b => getQuery(b) - .Select(f => Math.Floor(1.0 * f.Children.Sum(c => c.Grade) / (f.Children.Sum(c => c.Pets.Count()) + 1))))); - - inputs.Add(new LinqTestInput( - "Select(Pow(Sum(map), Count(Any)))", b => getQuery(b) - .Select(f => Math.Pow(f.Children.Sum(c => c.Pets.Count()), f.Children.Count(c => c.Pets.Any(p => p.GivenName.Count() == 0 || p.GivenName.Substring(0, 1) == "A")))))); - - inputs.Add(new LinqTestInput( - "OrderBy(Log(Where -> Count))", b => getQuery(b) - .OrderBy(f => Math.Log(f.Children.Where(c => c.Pets.Count() > 0).Count())))); - - // ------------------------------------------------------------------ - // Expression with subquery lambdas -> more transformations - // ------------------------------------------------------------------ - - inputs.Add(new LinqTestInput( - "Select(Select) -> Where", b => getQuery(b).Select(f => f.Children.Select(c => c.Pets.Count())).Where(x => x.Count() > 0))); - - // Customer requested scenario - inputs.Add(new LinqTestInput( - "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) - .Where(f => f.FamilyId.CompareTo("ABC") > 0 && f.SmartChildren.Count() > 0) - .OrderBy(f => f.ChildrenCount) - .Take(10))); - // TODO https://github.com/Azure/azure-cosmos-dotnet-v3/issues/375 - //inputs.Add(new LinqTestInput( - // "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) - // .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) - // .Where(f => f.ChildrenCount > 2 && f.SmartChildren.Count() > 1) - // .OrderBy(f => f.FamilyId) - // .Take(10))); - - inputs.Add(new LinqTestInput( - "Select(new { Select(Select), conditional Count Take }) -> Where -> Select(Select(Any))", b => getQuery(b) - .Select(f => new - { - f.FamilyId, - ChildrenPetFirstChars = f.Children.Select(c => c.Pets.Select(p => p.GivenName.Substring(0, 1))), - FirstChild = f.Children.Count() > 0 ? f.Children.Take(1) : null - }) - .Where(f => f.FirstChild != null) - .Select(f => f.ChildrenPetFirstChars.Select(chArray => chArray.Any(a => f.FamilyId.StartsWith(a)))))); - - inputs.Add(new LinqTestInput( - "Select(new (Select(new (Select, Select))))", b => getQuery(b) - .Select(f => new - { - f.FamilyId, - ChildrenProfile = f.Children.Select(c => new - { - Fullname = c.GivenName + " " + c.FamilyName, - PetNames = c.Pets.Select(p => p.GivenName), - ParentNames = f.Parents.Select(p => p.GivenName) - }) - }))); - - // ------------------------------------------------ - // Subquery lambda -> subquery lamda - // ------------------------------------------------ - - inputs.Add(new LinqTestInput( - "Select(array) -> Where(Sum(map))", b => getQuery(b) - .Select(f => f.Children).Where(children => children.Sum(c => c.Grade) > 100))); - - inputs.Add(new LinqTestInput( - "Select(Select) -> Select(Sum())", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade)).Select(children => children.Sum()))); - - inputs.Add(new LinqTestInput( - "Select(Select) -> Select(Sum(map))", b => getQuery(b) - .Select(f => f.Children).Select(children => children.Sum(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "Where(Any binary) -> Select(Sum(map))", b => getQuery(b) - .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) - .Select(f => f.Children.Sum(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Where(Any binary) -> OrderBy(Count(filter)) -> Select(Sum(map))", b => getQuery(b) - .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) - .OrderBy(f => f.Children.Count(c => c.Things.Count() > 3)) - .Select(f => f.Children.Sum(c => c.Pets.Count())))); - - // ------------------------------ - // Nested subquery lambdas - // ------------------------------ - - inputs.Add(new LinqTestInput( - "Select(Select(Select))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); - - inputs.Add(new LinqTestInput( - "Select(Select(Select))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Pets.Select(p => p))))); - - inputs.Add(new LinqTestInput( - "Select(Select(new Count))", b => getQuery(b) - .Select(f => f.Children - .Select(c => new - { - HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 - })))); - - inputs.Add(new LinqTestInput( - "Where -> Select(conditional ? Take : OrderBy -> Array indexer)", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .Select(f => f.Children.Count() == 1 ? f.Children.Take(1).ToArray()[0] : f.Children.OrderBy(c => c.Grade).ToArray()[1]))); - - inputs.Add(new LinqTestInput( - "Select(Where(Where -> Count) -> Select(new Count))", b => getQuery(b) - .Select(f => f.Children - .Where(c => c.Pets - .Where(p => p.GivenName.Count() > 10 && p.GivenName.Substring(0, 1) == "A") - .Count() > 0) - .Select(c => new - { - HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 - })))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select(Select))", b => getQuery(b) - .SelectMany(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where(Any))", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); - - inputs.Add(new LinqTestInput( - "Where(Where(Count) -> Count)", b => getQuery(b) - .Where(f => f.Parents.Where(p => p.FamilyName.Count() > 10).Count() > 1))); - - inputs.Add(new LinqTestInput( - "Where(Where(Where -> Count) -> Count)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Where(p => p.GivenName.Count() > 15).Count() > 0).Count() > 0))); - - inputs.Add(new LinqTestInput( - "Where(Select(Select -> Any))", b => getQuery(b) - .Where(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); - - // ------------------------------------- - // Expression -> Subquery lambdas - // ------------------------------------- - - inputs.Add(new LinqTestInput( - "Select(new) -> Select(Select)", b => getQuery(b) - .Select(f => new { f.FamilyId, Family = f }).Select(f => f.Family.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "SelectMany -> Select(Select)", b => getQuery(b) - .SelectMany(f => f.Children).Select(c => c.Pets.Select(p => p.GivenName.Count())))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where) -> Where(Any) -> Select(Select)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.Grade > 80)) - .Where(c => c.Pets.Any(p => p.GivenName.Count() > 20)) - .Select(c => c.Pets.Select(p => p.GivenName.Count())))); - - inputs.Add(new LinqTestInput( - "Distinct -> Select(new) -> Where(Select(Select -> Any))", b => getQuery(b) - .Distinct() - .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), Family = f }) - .Where(f => f.Family.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); - - inputs.Add(new LinqTestInput( - "Where -> Select(Select)", b => getQuery(b) - .Where(f => f.Children.Count() > 0).Select(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Distinct -> Select(Select)", b => getQuery(b) - .Distinct().Select(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Take -> Select(Select)", b => getQuery(b) - .Take(10).Select(f => f.Children.Select(c => c.Pets.Count())))); - - // ------------------ - // Any in lambda - // ------------------ - - inputs.Add(new LinqTestInput( - "Select(Any w const array)", b => getQuery(b) - .Select(f => new int[] { 1, 2, 3 }.Any()))); - - inputs.Add(new LinqTestInput( - "Select(Any)", b => getQuery(b) - .Select(f => f.Children.Any()))); - - inputs.Add(new LinqTestInput( - "Select(Any w lambda)", b => getQuery(b) - .Select(f => f.Children.Any(c => c.Grade > 80)))); - - inputs.Add(new LinqTestInput( - "Select(new Any)", b => getQuery(b) - .Select(f => new { f.FamilyId, HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); - - inputs.Add(new LinqTestInput( - "Select(new 2 Any)", b => getQuery(b) - .Select(f => new { HasChildrenWithPets = f.Children.Any(c => c.Pets.Count() > 0), HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); - - inputs.Add(new LinqTestInput( - "Select(Nested Any)", b => getQuery(b) - .Select(f => f.Children.Any(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); - - inputs.Add(new LinqTestInput( - "Where(Any)", b => getQuery(b) - .Where(f => f.Children.Any(c => c.Pets.Count() > 0)))); - - // Customer requested scenario - inputs.Add(new LinqTestInput( - "Where(simple expr && Any)", b => getQuery(b) - .Where(f => f.FamilyId.Contains("a") && f.Children.Any(c => c.Pets.Count() > 0)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Any)", b => getQuery(b) - .OrderBy(f => f.Children.Any(c => c.Pets.Count() > 3)))); - - // ------------------------------------------------ - // SelectMany with Take and OrderBy in lambda - // ------------------------------------------------ - - inputs.Add(new LinqTestInput( - "SelectMany(Take)", b => getQuery(b) - .SelectMany(f => f.Children.Take(2)))); - - inputs.Add(new LinqTestInput( - "SelectMany(OrderBy)", b => getQuery(b) - .SelectMany(f => f.Children.OrderBy(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where -> Take)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2)))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where -> Take -> Select)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2).Select(c => c.Grade)))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestGroupByTranslation() - { - List inputs = new List(); - inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k /*keySelector*/, - (key, values) => key /*return the group by key */))); - inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => key /*return the group by key */))); - inputs.Add(new LinqTestInput("GroupBy Single Value Select Key Alias", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (stringField, values) => stringField /*return the group by key */))); - - - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Min(value => value.Int) /*return the Min of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Max(value => value.Int) /*return the Max of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Count() /*return the Count of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Average", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Average(value => value.Int) /*return the Count of each group */))); - - // Negative cases - - // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] - // but the behavior between LINQ and SQL is different - // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, - (key, values) => values.Min() /*return the Min of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, - (key, values) => values.Max() /*return the Max of each group */))); - - // Unsupported node type - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, - (key, values) => "string" /* Unsupported Nodetype*/ ))); - - // Incorrect number of arguments - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy( - k => k.Int, - k2 => k2.Int, - (key, values) => "string" /* Unsupported Nodetype*/ ))); - - // Non-aggregate method calls - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Select(value => value.Int) /*Not an aggregate*/))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.OrderBy(f => f.FamilyId) /*Not an aggregate*/))); - - // Currently unsupported case - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, - (key, values) => new { familyId = key, familyIdCount = values.Count() } /*multi-value select */))); - - // Other methods followed by GroupBy - - inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) - .Select(x => x.Id) - .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) - .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) - .GroupBy(k => k.family1 /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) - .SelectMany(x => x.Children) - .GroupBy(k => k.Grade /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("SelectMany + GroupBy 2", b => getQuery(b) - .SelectMany(f => f.Children) - .Where(c => c.Pets.Count() > 0) - .SelectMany(c => c.Pets.Select(p => p.GivenName)) - .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) - .Skip(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) - .Take(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) - .Skip(10).Take(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - // should this become a subquery with order by then group by? - inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) - .OrderBy(x => x.Int) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) - .OrderByDescending(x => x.Id) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .OrderBy(x => x.Id) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - // The result for this is not correct yet - the select clause is wrong - inputs.Add(new LinqTestInput("Combination 2 + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .Where(x => x.Children.Min(y => y.Grade) > 10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - // GroupBy followed by other methods - inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Select(x => x))); - - //We should support skip take - inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Skip(10))); - - inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Skip(10).Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Where(x => x == "a"))); - - inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .OrderBy(x => x))); - - inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .OrderByDescending(x => x))); - - inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Where(x => x == "a").Skip(10).Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestGroupByMultiValueTranslation() - { - List inputs = new List(); - inputs.Add(new LinqTestInput("GroupBy Multi Value Select Constant", b => getQuery(b).GroupBy(k => k /*keySelector*/, - (key, values) => - new { - stringField = "abv", - numField = 123 - }))); - - inputs.Add(new LinqTestInput("GroupBy Multi Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => new { - Key = key, - key - }))); - - inputs.Add(new LinqTestInput("GroupBy Multi Value Select Key and Constant", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => new { - KeyAlias = key, - values = 123 /* intentionally have the same spelling as the IGrouping values */ - }))); - - inputs.Add(new LinqTestInput("GroupBy Multi Value With Aggregate", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => new { - Min = values.Min(value => value.Int), - Max = values.Max(value => value.Int), - Avg = values.Average(value => value.Int), - Count = values.Count() - }))); - - inputs.Add(new LinqTestInput("GroupBy Multi Value With Property Ref and Aggregate", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, - (key, values) => new { - familyId = key, - familyIdCount = values.Count() - }))); - - // Negative cases - - // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] - // but the behavior between LINQ and SQL is different - // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null - inputs.Add(new LinqTestInput("GroupBy Multi Value With Aggregate On Root", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => new { - Min = values.Min(), - Max = values.Max() - }))); - - // Non-aggregate method calls - inputs.Add(new LinqTestInput("GroupBy Multi Value With Non-Aggregate", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => new { - valueSelect = values.Select(value => value.Int), - valueOrderBy = values.OrderBy(f => f.FamilyId) - }))); - // Other methods followed by GroupBy - - inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) - .Select(x => x.Id) - .GroupBy(k => k /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) - .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) - .GroupBy(k => k.Id1 /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) - .SelectMany(x => x.Children) - .GroupBy(k => k /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) - .Skip(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) - .Take(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) - .Skip(10).Take(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - // should this become a subquery with order by then group by? - inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) - .OrderBy(x => x.Int) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) - .OrderByDescending(x => x.Id) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .OrderBy(x => x.Id) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - // GroupBy followed by other methods - inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Select(x => x))); - - inputs.Add(new LinqTestInput("GroupBy + Select 2", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Select(x => x.keyAlias))); - - //We should support skip take - inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Skip(10))); - - inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Skip(10).Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Where(x => x.keyAlias == "a"))); - - inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .OrderBy(x => x.keyAlias))); - - inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .OrderByDescending(x => x.count))); - - inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Where(x => x.keyAlias == "a").Skip(10).Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .GroupBy(k => k.count /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("GroupBy + GroupBy2", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }) - .GroupBy(k => k.count /*keySelector*/, (key, values) => new { - keyAlias = key, - stringField = "abc" - }))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - [Ignore] - public void DebuggingTest() - { - - } - - [TestMethod] - [Owner("khdang")] - [Ignore] - public void TestSkipTake() - { - //TODO - //V2 using V3 pipeline causing issue on accessing Continuation in CosmosQueryResponseMessageHeaders - //This will be fine once we convert these test cases to use V3 pipeline - - List inputs = new List(); - - // -------------------------------- - // Skip - Take combinations - // -------------------------------- - - inputs.Add(new LinqTestInput( - "Skip", b => getQuery(b) - .Skip(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take", b => getQuery(b) - .Skip(1).Take(2))); - - inputs.Add(new LinqTestInput( - "Skip(negative number) -> Take", b => getQuery(b) - .Skip(-1).Take(1))); - - inputs.Add(new LinqTestInput( - "Skip -> Take(negative number)", b => getQuery(b) - .Skip(1).Take(-2))); - - inputs.Add(new LinqTestInput( - "Skip -> Skip -> Take", b => getQuery(b) - .Skip(1).Skip(2).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Take", b => getQuery(b) - .Skip(3).Take(5).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Skip -> Take", b => getQuery(b) - .Skip(1).Take(2).Skip(3).Take(4))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Take -> Skip", b => getQuery(b) - .Skip(1).Take(2).Take(3).Skip(4))); - - inputs.Add(new LinqTestInput( - "Skip -> Skip -> Take -> Take", b => getQuery(b) - .Skip(5).Skip(2).Take(10).Take(3))); - - inputs.Add(new LinqTestInput( - "Take -> Skip", b => getQuery(b) - .Take(7).Skip(3))); - - inputs.Add(new LinqTestInput( - "Take -> Take -> Skip", b => getQuery(b) - .Take(2).Take(3).Skip(5))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Skip", b => getQuery(b) - .Take(3).Skip(1).Skip(2))); - - inputs.Add(new LinqTestInput( - "Take -> Take -> Skip -> Skip", b => getQuery(b) - .Take(5).Take(3).Skip(1).Skip(1))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Take -> Skip", b => getQuery(b) - .Take(10).Skip(2).Take(5).Skip(1))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Skip -> Take", b => getQuery(b) - .Take(10).Skip(4).Skip(2).Take(2))); - - // -------------------------- - // Select + Skip & Take - // -------------------------- - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take", b => getQuery(b) - .Select(f => f.FamilyId).Skip(1).Take(2))); - - inputs.Add(new LinqTestInput( - "Select -> Take -> Skip", b => getQuery(b) - .Select(f => f.FamilyId).Take(2).Skip(1))); - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take -> Select", b => getQuery(b) - .Select(f => f.FamilyId).Skip(7).Take(13).Select(f => f.Count()))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Select -> Take -> Skip", b => getQuery(b) - .Skip(5).Take(11).Select(f => f.Children.Count()).Take(7).Skip(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Select -> Take", b => getQuery(b) - .Skip(10).Select(f => f.FamilyId).Take(7))); - - inputs.Add(new LinqTestInput( - "Take -> Select -> Skip", b => getQuery(b) - .Take(7).Select(f => f.FamilyId).Skip(3))); - - // ------------------------------ - // SelectMany + Skip & Take - // ------------------------------ - - inputs.Add(new LinqTestInput( - "SelectMany -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Skip(7).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany -> Skip -> Take -> SelectMany", b => getQuery(b) - .SelectMany(f => f.Children).Skip(11).Take(3).SelectMany(c => c.Pets))); - - inputs.Add(new LinqTestInput( - "Skip -> SelectMany -> Take -> Skip -> SelectMany", b => getQuery(b) - .Skip(1).SelectMany(f => f.Children).Take(13).Skip(3).SelectMany(c => c.Pets))); - - inputs.Add(new LinqTestInput( - "SelectMany -> SelectMany -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).SelectMany(c => c.Pets).Skip(3).Take(4))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> SelectMany -> Skip -> SelectMany", b => getQuery(b) - .Take(50).Skip(25).SelectMany(f => f.Children).Skip(10).SelectMany(c => c.Pets))); - - // --------------------------- - // Where + Skip & Take - // --------------------------- - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(3).Take(5))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> Where -> Skip -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 0).Skip(7).Take(11).Where(f => f.Tags.Count() > 2).Skip(1).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Where -> Skip", b => getQuery(b) - .Skip(1).Take(25).Where(f => f.Int > 10).Skip(5))); - - inputs.Add(new LinqTestInput( - "Take -> Where -> Skip", b => getQuery(b) - .Take(25).Where(f => f.FamilyId.Contains("A")).Skip(10))); - - inputs.Add(new LinqTestInput( - "Where -> Take -> Skip -> Where", b => getQuery(b) - .Where(f => f.Children.Count() > 1).Take(10).Skip(3).Where(f => f.Int > 0))); - - // --------------------------- - // OrderBy + Skip & Take - // --------------------------- - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Int).Skip(3).Take(7))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> Take -> OrderBy -> Take -> Skip", b => getQuery(b) - .OrderBy(f => f.Int).Skip(3).Take(11).OrderBy(f => f.FamilyId).Take(7).Skip(1))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> OrderBy", b => getQuery(b) - .Skip(3).Take(43).OrderBy(f => f.IsRegistered))); - - inputs.Add(new LinqTestInput( - "Take -> OrderByDescending -> Skip", b => getQuery(b) - .Take(50).OrderByDescending(f => f.Int).Skip(13))); - - inputs.Add(new LinqTestInput( - "Skip -> OrderByDescending -> Take", b => getQuery(b) - .Skip(7).OrderByDescending(f => f.Int).Take(17))); - - // --------------------------- - // Distinct + Skip & Take - // --------------------------- - - inputs.Add(new LinqTestInput( - "Distinct -> Skip -> Take", b => getQuery(b) - .Distinct().Skip(3).Take(7))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Distinct", b => getQuery(b) - .Skip(3).Take(11).Distinct())); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Select -> Distinct -> Skip -> Take -> Distinct -> Skip", b => getQuery(b) - .Skip(10).Take(60).Select(f => f.Int).Distinct().Skip(15).Take(20).Distinct().Skip(7))); - - inputs.Add(new LinqTestInput( - "Skip -> Distinct -> Skip -> Take", b => getQuery(b) - .Skip(7).Distinct().Skip(20).Take(10))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Distinct -> Skip", b => getQuery(b) - .Take(30).Skip(10).Distinct().Skip(7))); - - // --------------------------------------------------------------------------------- - // Select, SelectMany, Where, OrderBy, Distinct with Skip & Take in between - // --------------------------------------------------------------------------------- - - // Select, SelectMany - - inputs.Add(new LinqTestInput( - "Select(new) -> SelectMany -> Skip -> Take", b => getQuery(b) - .Select(f => new { f.FamilyId, f.Children }).SelectMany(c => c.Children).Skip(3).Take(10))); - - inputs.Add(new LinqTestInput( - "SelectMany -> Select -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Select(c => c.GivenName).Skip(7).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) - .Skip(10).Take(20).SelectMany(f => f.Children).Skip(3).Select(c => c.GivenName).Take(5))); - - inputs.Add(new LinqTestInput( - "Skip -> SelectMany -> Take -> Skip -> Select -> Take", b => getQuery(b) - .Skip(10).SelectMany(f => f.Children).Take(10).Skip(1).Select(c => c.FamilyName).Take(7))); - - inputs.Add(new LinqTestInput( - "Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) - .Take(30).SelectMany(f => f.Children).Skip(10).Select(c => c.Grade).Take(3))); - - // Select, Where - - inputs.Add(new LinqTestInput( - "Select -> Where -> Skip -> Take", b => getQuery(b) - .Select(f => f.Children).Where(c => c.Count() > 0).Skip(3).Take(7))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> Select -> Skip", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(7).Take(3).Select(f => f.FamilyId).Skip(2))); - - // Select, OrderBy - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take -> OrderBy", b => getQuery(b) - .Select(f => f.FamilyId).Skip(1).Take(2).OrderBy(s => s))); - - inputs.Add(new LinqTestInput( - "OrderByDescending -> Take -> Skip -> Select", b => getQuery(b) - .OrderByDescending(f => f.Int).Take(10).Skip(3).Select(f => f.Int + 1))); - - // Select, Distinct - - inputs.Add(new LinqTestInput( - "Take -> Select -> Distinct -> Skip -> Take", b => getQuery(b) - .Take(7).Select(f => f.Int).Distinct().Skip(1).Take(5))); - - // SelectMany, Where - - inputs.Add(new LinqTestInput( - "SelectMany -> Where -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Where(c => c.Grade > 100).Skip(10).Take(20))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> SelectMany -> Take", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(10).SelectMany(f => f.Children).Take(7))); - - // SelectMany, OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> SelectMany -> SelectMany", b => getQuery(b) - .OrderBy(f => f.Int).Skip(10).SelectMany(f => f.Children).SelectMany(c => c.Pets))); - - inputs.Add(new LinqTestInput( - "SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); - - // SelectMany, Distinct - - inputs.Add(new LinqTestInput( - "SelectMany -> Distinct -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Distinct().Skip(7).Take(11))); - - inputs.Add(new LinqTestInput( - "Distinct -> Skip -> SelectMany", b => getQuery(b) - .Distinct().Skip(3).SelectMany(f => f.Children))); - - // Where, OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy -> Where -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Int).Where(f => f.IsRegistered).Skip(11).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Where -> Take -> OrderBy", b => getQuery(b) - .Skip(20).Where(f => f.Children.Count() > 0).Take(10).OrderBy(f => f.Int))); - - // Where, Distinct - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> Distinct", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(3).Take(17).Distinct())); - - inputs.Add(new LinqTestInput( - "Skip -> Distinct -> Where -> Take", b => getQuery(b) - .Skip(22).Distinct().Where(f => f.Parents.Count() > 0).Take(7))); - - // ----------------------------------------- - // All basic operations with Skip & Take - // ----------------------------------------- - - // Start with Select - - inputs.Add(new LinqTestInput( - "Select -> Where -> OrderBy -> Skip -> Take", b => getQuery(b) - .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10))); - - inputs.Add(new LinqTestInput( - "Select -> Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10) - .Select(id => id + "_suffix").Where(id => id.Count() > 12).Skip(2).Take(4))); - - inputs.Add(new LinqTestInput( - "Select -> Skip -> OrderBy -> Skip -> Distinct -> Skip", b => getQuery(b) - .Select(f => f.Records).Skip(5).OrderBy(r => r.Transactions.Count()).Skip(1).Distinct().Skip(3))); - - inputs.Add(new LinqTestInput( - "Select(new(new(new(new(new))))) -> (Skip -> Select) x 6 -> Skip -> Where -> Take", b => getQuery(b) - .Select(f => new { f.FamilyId, L1 = new { L2 = new { L3 = new { L4 = new { f.Records } } } } }) - .Skip(1).Select(f => f.L1) - .Skip(2).Select(f => f.L2) - .Skip(3).Select(f => f.L3) - .Skip(4).Select(f => f.L4) - .Skip(5).Select(f => f.Records) - .Skip(6).Select(f => f.Transactions) - .Skip(7).Where(t => t.Count() > 100) - .Take(20))); - - inputs.Add(new LinqTestInput( - "Select -> (Skip -> Select -> Where -> OrderBy -> Distinct -> Take) x 3 -> Skip -> Take", b => getQuery(b) - .Select(f => new { L1 = f }) - .Skip(1).Select(f => f.L1).Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Distinct().Take(100) - .Skip(2).Select(f => new { L2 = f }).Where(f => f.L2.FamilyId.CompareTo("A") > 0).OrderBy(f => f.L2.Int).Distinct().Take(50) - .Skip(3).Select(f => f.L2).Where(f => f.Children.Count() > 1).OrderBy(f => f.IsRegistered).Distinct().Take(40) - .Skip(4).Take(25))); - - // Start with Distinct - - inputs.Add(new LinqTestInput( - "Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Distinct().Select(f => f.Records).Where(r => r.Transactions.Count() > 2).Skip(1).Take(10))); - - // Start with Where - - inputs.Add(new LinqTestInput( - "Where -> OrderBy -> Skip -> Take", b => getQuery(b) - .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5))); - - inputs.Add(new LinqTestInput( - "Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5) - .Select(f => f.Records).Where(r => r.Transactions != null).Skip(1).Take(3))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) - .Where(f => f.Int > 20).Skip(5).Take(20) - .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(5).Take(10))); - - // Start with OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Int).Skip(1).Take(10) - .Select(f => f.Records).Where(r => r.Transactions.Count() > 10).Skip(2).Take(3))); - - // Start with Skip - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Skip(1).Take(10).Select(f => f.Children.Count()).Where(c => c > 1).Skip(1).Take(4))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Where -> Skip -> Take -> OrderBy -> Skip -> Take -> Select -> Skip -> Distinct -> Skip -> Take", b => getQuery(b) - .Skip(2).Take(10).Where(f => f.Int > 10) - .Skip(1).Take(9).OrderBy(f => f.FamilyId) - .Skip(3).Take(5).Select(f => f.Children.Count()) - .Skip(1).Distinct() - .Skip(1).Take(1))); - - // Start with Take - - inputs.Add(new LinqTestInput( - "Take -> Skip -> OrderBy -> Skip -> Take", b => getQuery(b) - .Take(10).Skip(2).Where(f => f.IsRegistered).OrderBy(f => f.Int).Skip(1).Take(9))); - - inputs.Add(new LinqTestInput( - "Take -> Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Take(10).Distinct().Select(f => f.Children).Where(c => c.Count() > 0).Skip(2).Take(5))); - - // ----------------------------------------------------------------------------- - // All basic operations with Skip & Take with SelectMany in the middle - // ----------------------------------------------------------------------------- - - // SelectMany after Take - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) - .Select(f => f.Records).Skip(1).Take(10) - .SelectMany(r => r.Transactions).Skip(1).Take(9))); - - // SelectMany after Where - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) - .Where(f => f.IsRegistered) - .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); - - // Start with SelectMany - - inputs.Add(new LinqTestInput( - "SelectMany -> Select -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children) - .Select(c => c.FamilyName).Skip(1).Take(20) - .Select(n => n.Count()).Where(l => l > 10).Skip(2).Take(50))); - - // ------------------------------------------------------------- - // Nested Skip & Take in Select, SelectMany, Where, OrderBy - // ------------------------------------------------------------- - - // Nested with Select - - inputs.Add(new LinqTestInput( - "Select(new(Where -> Skip)) -> Where", b => getQuery(b) - .Select(f => new { - id = f.FamilyId, - GoodChildren = f.Children.Where(c => c.Grade > 75).Skip(1) - }) - .Where(f => f.GoodChildren.Count() > 0))); - - inputs.Add(new LinqTestInput( - "Select(Skip -> Take) -> Skip -> Take", b => getQuery(b) - .Select(f => f.Children.Skip(1).Take(1)).Skip(3).Take(10))); - - inputs.Add(new LinqTestInput( - "Select(new(Skip -> Take, Skip, Take) -> Skip -> Take -> Where", b => getQuery(b) - .Select(f => new { - v0 = f.Children.Skip(1).Take(2), - v1 = f.Parents.Skip(1), - v2 = f.Records.Transactions.Take(10) - }) - .Skip(1).Take(20).Where(f => f.v0.Count() > 0).Take(10))); - - inputs.Add(new LinqTestInput( - "Select(new(SelectMany -> SelectMany -> Distinct, OrderByDescending -> Take -> SelectMany -> Skip, Select -> OrderBy -> Skip -> Take -> Sum) -> Where -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) - .Select(f => new { - v0 = f.Children.SelectMany(c => c.Pets.Skip(1).SelectMany(p => p.GivenName).Distinct()), - v1 = f.Children.OrderByDescending(c => c.Grade).Take(2).SelectMany(c => c.Pets.Select(p => p.GivenName).Skip(2)), - v2 = f.Records.Transactions.Select(t => t.Amount).OrderBy(a => a).Skip(10).Take(20).Sum() - }) - .Where(f => f.v2 > 100).Skip(5).Take(20) - .SelectMany(f => f.v1).Distinct().Skip(3).Take(22))); - - inputs.Add(new LinqTestInput( - "Select -> Skip -> SelectMany(Skip -> OrderBy)", b => getQuery(b) - .Select(f => f.Records).Skip(1).SelectMany(r => r.Transactions.Skip(10).OrderBy(t => t.Date)))); - - // Nested with Where - - inputs.Add(new LinqTestInput( - "Where -> Where(Skip -> Take -> Count) - > Skip -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 2).Where(f => f.Children.Skip(1).Take(10).Count() > 1).Skip(1).Take(10))); - - // Nested with OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy(Skip -> Take -> Count) -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Children.Skip(1).Take(5).Count()))); - - // Nested with SelectMany - - inputs.Add(new LinqTestInput( - "SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20))); - - inputs.Add(new LinqTestInput( - "SelectMany(Skip -> Take) -> Skip -> Take -> SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20) - .SelectMany(c => c.Pets.Skip(1).Take(2)).Skip(1).Take(10))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where -> OrderBy -> Skip -> Distinct)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.Grade > 10).OrderBy(c => c.Grade).Skip(1).Distinct()))); - - inputs.Add(new LinqTestInput( - "SelectMany(Skip -> SelectMany(Skip -> Select) -> Take)", b => getQuery(b) - .SelectMany(f => f.Children.Skip(1).SelectMany(c => c.Pets.Skip(1).Select(p => p.GivenName)).Take(10)))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - [Ignore] - public void TestUnsupportedScenarios() - { - List inputs = new List(); - - // -------------------- - // Dictionary type - // -------------------- - - // Iterating through Dictionary type - inputs.Add(new LinqTestInput("Iterating through Dictionary type", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Select(t => t.Key.Count() + t.Value.Count()))))); - - // Get a count of a Dictionary type - inputs.Add(new LinqTestInput("Getting Dictionary count", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Count())))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestOrderByTranslation() - { - List inputs = new List(); - - // Ascending - inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id))); - inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id).Select(x => x.Count()))); - inputs.Add(new LinqTestInput("Where -> OrderBy -> Select query", - b => from f in getQuery(b) - where f.Int == 5 && f.NullableInt != null - orderby f.IsRegistered - select f.FamilyId)); - inputs.Add(new LinqTestInput("Where -> OrderBy -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderBy(f => f.IsRegistered).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy query", - b => from f in getQuery(b) - orderby f.FamilyId - select f)); - inputs.Add(new LinqTestInput("OrderBy", b => getQuery(b).OrderBy(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy -> Select query", - b => from f in getQuery(b) - orderby f.FamilyId - select f.FamilyId)); - inputs.Add(new LinqTestInput("OrderBy -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); - - // Descending - inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id))); - inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id).Select(x => x.Count()))); - inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select query", - b => from f in getQuery(b) - where f.Int == 5 && f.NullableInt != null - orderby f.IsRegistered descending - select f.FamilyId)); - inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderByDescending(f => f.IsRegistered).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy Desc query", - b => from f in getQuery(b) - orderby f.FamilyId descending - select f)); - inputs.Add(new LinqTestInput("OrderBy Desc", b => getQuery(b).OrderByDescending(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy Desc -> Select query", - b => from f in getQuery(b) - orderby f.FamilyId descending - select f.FamilyId)); - inputs.Add(new LinqTestInput("OrderBy Desc -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); - inputs.Add(new LinqTestInput("OrderBy multiple expressions", - b => from f in getQuery(b) - orderby f.FamilyId, f.Int - select f.FamilyId)); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestLambdaReuse() - { - List inputs = new List(); - - System.Linq.Expressions.Expression> predicate = f => f.Int == 5; - inputs.Add(new LinqTestInput("Where -> Where with same predicate instance", b => getQuery(b).Where(predicate).Where(predicate))); - inputs.Add(new LinqTestInput("Where -> Select with same predicate instance", b => getQuery(b).Where(predicate).Select(predicate))); - - System.Linq.Expressions.Expression> predicate2 = f => f.ToString() == "a"; - inputs.Add(new LinqTestInput("Where -> Select -> Where with same predicate instance", - b => getQuery(b) - .Where(predicate2) - .Select(c => new { Int = 10, Result = c }) - .Where(predicate2))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestThenByTranslation() - { - List inputs = new List(); - - // Ascending and descending - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenBy(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenByDescending", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderByDescending -> ThenBy", b => getQuery(b) - .OrderByDescending(f => f.FamilyId) - .ThenBy(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderByDescending -> ThenByDescending", b => getQuery(b) - .OrderByDescending(f => f.FamilyId) - .ThenByDescending(f => f.Int))); - - // Subquery in OrderBy or in ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy subquery -> ThenBy", b => getQuery(b) - .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy subquery", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); - - inputs.Add(new LinqTestInput( - "OrderBy subquery -> ThenBy subquery", b => getQuery(b) - .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); - - // OrderBy and ThenBy by the same property (not a realistic scenario) - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenBy(f => f.FamilyId))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenByDescending", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.FamilyId))); - - inputs.Add(new LinqTestInput( - "OrderByDescending subquery -> ThenBy subquery", b => getQuery(b) - .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); - - // OrderBy and ThenBy with epxressions - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.Int * 2) - .ThenBy(f => f.FamilyId.Substring(2, 3)))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => !f.NullableInt.IsDefined()) - .ThenByDescending(f => f.Tags.Count() % 2))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderByDescending(f => f.IsRegistered ? f.FamilyId : f.Int.ToString()) - .ThenBy(f => f.Records.Transactions.Max(t => t.Amount) % 1000))); - - // Multiple OrderBy and ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy -> OrderBy -> ThenBy", b => getQuery(b) - .OrderByDescending(f => f.FamilyId) - .OrderBy(f => f.Int) - .ThenByDescending(f => f.IsRegistered))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenBy(f => f.Int) - .ThenByDescending(f => f.IsRegistered))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Orderby subquery -> ThenBy subquery", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy subquery -> ThenBy subquery", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()) - .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); - - // Nested ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy(OrderBy -> ThenBy -> Select)", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Select(p => p.FamilyName + p.GivenName)))); - - inputs.Add(new LinqTestInput( - "OrderBy(OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) - .OrderBy(f => f.Children - .OrderBy(c => c.Grade) - .ThenBy(c => c.Pets.Count)) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Select(p => p.FamilyName + p.GivenName)))); - - // Nested expressions with ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy(OrderBy -> ThenBy -> Take -> Select)", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Take(1) - .Select(p => p.FamilyName + p.GivenName)))); - - inputs.Add(new LinqTestInput( - "OrderBy(OrderBy -> ThenBy -> Take -> OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) - .OrderBy(f => f.Children - .OrderBy(c => c.Grade) - .ThenByDescending(c => c.Pets.Count) - .Take(10) - .OrderByDescending(c => c.GivenName) - .ThenBy(c => c.Gender)) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Select(p => p.FamilyName + p.GivenName)))); - - // On a new object - - inputs.Add(new LinqTestInput( - "Select -> OrderBy -> ThenBy", b => getQuery(b) - .Select(f => new - { - f.FamilyId, - FamilyNumber = f.Int, - ChildrenCount = f.Children.Count(), - ChildrenPetCount = f.Children.Select(c => c.Pets.Count()).Sum() - }) - .OrderBy(r => r.FamilyId) - .ThenBy(r => r.FamilyNumber))); - - inputs.Add(new LinqTestInput( - "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) - .SelectMany(f => f.Children.Select(c => new - { - f.FamilyId, - FamilyNumber = f.Int, - ChildrenCount = f.Children.Count(), - Name = c.GivenName, - SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() - }) - .OrderBy(r => r.FamilyId) - .ThenBy(r => r.FamilyNumber)))); - - inputs.Add(new LinqTestInput( - "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) - .SelectMany(f => f.Children.Select(c => new - { - f.FamilyId, - FamilyNumber = f.Int, - ChildrenCount = f.Children.Count(), - Name = c.GivenName, - SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() - })) - .OrderBy(r => r.FamilyId) - .ThenBy(r => r.FamilyNumber) - .Select(r => r.FamilyId))); - - inputs.Add(new LinqTestInput( - "Select(new(Where, Sum) -> OrderBy(Count) -> ThenBy)", b => getQuery(b) - .Select(f => new { - ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 0), - TotalExpenses = f.Records.Transactions.Sum(t => t.Amount) - }) - .OrderByDescending(r => r.ChildrenWithPets.Count()) - .ThenByDescending(r => r.TotalExpenses))); - - inputs.Add(new LinqTestInput( - "Select(new(Min, Count, SelectMany->Select->Distinct->Count)) -> OrderByDescending -> ThenBy", b => getQuery(b) - .Select(f => new { - ParentGivenName = f.Parents.Min(p => p.GivenName), - ParentCount = f.Parents.Count(), - GoodChildrenCount = f.Children.Where(c => c.Grade > 95).Count(), - UniquePetsNameCount = f.Children.SelectMany(c => c.Pets).Select(p => p.GivenName).Distinct().Count() - }) - .OrderByDescending(r => r.GoodChildrenCount) - .ThenBy(r => r.UniquePetsNameCount))); - - // With other LINQ operators: Where, SelectMany, Distinct, Skip, Take, and aggregates - - inputs.Add(new LinqTestInput( - "Where -> OrderBy -> ThenBy", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children) - .OrderBy(c => c.Grade) - .ThenByDescending(c => c.Pets.Count()) - .Take(3))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Skip -> Take -> Where -> Select -> Distinct", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children) - .OrderByDescending(c => c.Grade) - .ThenBy(c => c.GivenName) - .Skip(2) - .Take(20) - .Where(c => c.Pets.Where(p => p.GivenName.Length > 10).Count() > 0) - .Select(c => c.GivenName) - .Distinct())); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Select => Distinct => Take => OrderBy", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children) - .OrderBy(c => c.Grade) - .ThenByDescending(c => c.Pets.Count()) - .Select(c => c.GivenName) - .Distinct() - .Take(10) - .Skip(5) - .OrderBy(n => n.Length))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Records.Transactions) - .OrderBy(t => t.Type) - .ThenBy(t => t.Amount) - .Take(100))); - - inputs.Add(new LinqTestInput( - "Take -> OrderBy -> ThenBy", b => getQuery(b) - .Take(100) - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "Take -> OrderBy -> ThenBy -> Skip", b => getQuery(b) - .Take(100) - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int) - .Skip(5))); - - inputs.Add(new LinqTestInput( - "Distinct -> OrderBy -> ThenBy", b => getQuery(b) - .Distinct() - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany(Select(new Where->Count)) -> Distinct -> OrderBy -> ThenBy", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children.Select(c => new { - Name = c.GivenName, - PetWithLongNames = c.Pets.Where(p => p.GivenName.Length > 8).Count() - })) - .Distinct() - .OrderByDescending(r => r.Name) - .ThenBy(r => r.PetWithLongNames))); - - inputs.Add(new LinqTestInput( - "OrderBy(Any) -> ThenBy(Any)", b => getQuery(b) - .OrderBy(f => f.Children.Any(c => c.Grade > 90)) - .ThenByDescending(f => f.Parents.Any(p => p.GivenName.Length > 10)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Min) -> ThenBy(Max) -> ThenBy(Sum) -> ThenBy(Avg)", b => getQuery(b) - .OrderBy(f => f.Children.Min(c => c.GivenName)) - .ThenByDescending(f => f.Parents.Max(p => p.GivenName)) - .ThenBy(f => f.Records.Transactions.Sum(t => t.Amount)) - .ThenByDescending(f => f.Records.Transactions.Average(t => t.Amount)))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - [Ignore] - public void TestDistinctSelectManyIssues() - { - List inputs = new List(); - - // these tests need a fix in the ServiceInterop - inputs.Add(new LinqTestInput( - "Distinct -> OrderBy -> Take", - b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x).Take(10))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Distinct -> Take", - b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Distinct().Take(10))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestDistinctTranslation() - { - static LinqTestInput DistinctTestInput(string description, System.Linq.Expressions.Expression> expr) - { - return new LinqTestInput(description, expr, true); - } - - List inputs = new List(); - - // Simple distinct - // Select -> Distinct for all data types - inputs.Add(DistinctTestInput( - "Distinct string", - b => getQuery(b).Select(f => f.FamilyId).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct int", - b => getQuery(b).Select(f => f.Int).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct bool", - b => getQuery(b).Select(f => f.IsRegistered).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct nullable int", - b => getQuery(b).Where(f => f.NullableInt != null).Select(f => f.NullableInt).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct null", - b => getQuery(b).Where(f => f.NullObject != null).Select(f => f.NullObject).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct children", - b => getQuery(b).SelectMany(f => f.Children).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct parent", - b => getQuery(b).SelectMany(f => f.Parents).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct family", - b => getQuery(b).Distinct())); - - inputs.Add(DistinctTestInput( - "Multiple distincts", - b => getQuery(b).Distinct().Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct new obj", - b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct new obj", - b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Select(f => f.Parents).Distinct())); - - // Distinct + Take - inputs.Add(DistinctTestInput( - "Distinct -> Take", - b => getQuery(b).Select(f => f.Int).Distinct().Take(10))); - - inputs.Add(new LinqTestInput( - "Take -> Distinct", - b => getQuery(b).Select(f => f.Int).Take(10).Distinct())); - - // Distinct + Order By - inputs.Add(new LinqTestInput( - "Distinct -> OrderBy", - b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x))); - - inputs.Add(DistinctTestInput( - "OrderBy -> Distinct", - b => getQuery(b).OrderBy(f => f.Int).Distinct())); - - // Distinct + Order By + Take - inputs.Add(new LinqTestInput( - "Distinct -> Take -> OrderBy", - b => getQuery(b).Select(f => f.Int).Distinct().Take(10).OrderBy(x => x))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Take -> Distinct", - b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Take(10).Distinct())); - - // Distinct + Where - inputs.Add(DistinctTestInput( - "Where -> Distinct", - b => getQuery(b).Select(f => f.Int).Where(x => x > 10).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct -> Where", - b => getQuery(b).Select(f => f.Int).Distinct().Where(x => x > 10))); - - // SelectMany w Distinct - inputs.Add(DistinctTestInput( - "SelectMany(Select obj) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select)) -> Distinct", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet))) - .Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select -> Distinct))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet) - .Distinct())))); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select -> Select) -> Distinct)", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet.GivenName) - .Select(name => name.Count()))) - .Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select new {} -> Select) -> Distinct)", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }).Select(p => p.child)) - .Distinct()))); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select new {}) -> Distinct)", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }))) - .Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select new {} -> Distinct))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }) - .Distinct())))); - - // SelectMany(Distinct) - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Take(5).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct().Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> Take -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .Take(5).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .Where(f => f.FamilyName.Count() < 20))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Select", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Select -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()).Take(5))); - - // SelectMany(Select -> Distinct) - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Distinct) -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).OrderBy(n => n).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Distinct) -> Where -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10).OrderBy(n => n).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Select) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Select -> Distinct)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Distinct()))); - - inputs.Add(DistinctTestInput( - "SelectMany(Select -> Distinct) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Select -> Distinct) -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void ValidateDynamicLinq() - { - List inputs = new List(); - inputs.Add(new LinqTestInput("Select", b => getQuery(b).Select("FamilyId"))); - inputs.Add(new LinqTestInput("Where", b => getQuery(b).Where("FamilyId = \"some id\""))); - inputs.Add(new LinqTestInput("Where longer", b => getQuery(b).Where("FamilyId = \"some id\" AND IsRegistered = True OR Int > 101"))); - // with parameters - inputs.Add(new LinqTestInput("Where w/ parameters", b => getQuery(b).Where("FamilyId = @0 AND IsRegistered = @1 OR Int > @2", "some id", true, 101))); - inputs.Add(new LinqTestInput("Where -> Select", b => getQuery(b).Where("FamilyId = \"some id\"").Select("Int"))); - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public async Task ValidateLinqQueries() - { - Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString("N"), partitionKeyPath: "/id")); - - Parent mother = new Parent { FamilyName = "Wakefield", GivenName = "Robin" }; - Parent father = new Parent { FamilyName = "Miller", GivenName = "Ben" }; - Pet pet = new Pet { GivenName = "Fluffy" }; - Child child = new Child - { - FamilyName = "Merriam", - GivenName = "Jesse", - Gender = "female", - Grade = 1, - Pets = new List() { pet, new Pet() { GivenName = "koko" } }, - Things = new Dictionary() { { "A", "B" }, { "C", "D" } } - }; - - Address address = new Address { State = "NY", County = "Manhattan", City = "NY" }; - Family family = new Family { FamilyId = "WakefieldFamily", Parents = new Parent[] { mother, father }, Children = new Child[] { child }, IsRegistered = false, Int = 3, NullableInt = 5, Id = "WakefieldFamily" }; - - List fList = new List(); - fList.Add(family); - - container.CreateItemAsync(family).Wait(); - IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q1 = query.Select(f => f.Parents[0].FamilyName); - Assert.AreEqual(q1.FirstOrDefault(), family.Parents[0].FamilyName); - - IEnumerable q2 = query.Select(f => f.Children[0].Grade + 13); - Assert.AreEqual(q2.FirstOrDefault(), family.Children[0].Grade + 13); - - IEnumerable q3 = query.Where(f => f.Children[0].Pets[0].GivenName == "Fluffy"); - Assert.AreEqual(q3.FirstOrDefault().FamilyId, family.FamilyId); - - IEnumerable q4 = query.Where(f => f.Children[0].Things["A"] == "B"); - Assert.AreEqual(q4.FirstOrDefault().FamilyId, family.FamilyId); - - for (int index = 0; index < 2; index++) - { - IEnumerable q5 = query.Where(f => f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[index]); - Assert.AreEqual(q5.FirstOrDefault().GivenName, family.Children[0].Pets[index].GivenName); - } - - IEnumerable q6 = query.SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })); - Assert.AreEqual(q6.FirstOrDefault().Id, family.FamilyId); - - string nullString = null; - IEnumerable q7 = query.Where(f => nullString == f.FamilyId); - Assert.IsNull(q7.FirstOrDefault()); - - object nullObject = null; - q7 = query.Where(f => f.NullObject == nullObject); - Assert.AreEqual(q7.FirstOrDefault().FamilyId, family.FamilyId); - - q7 = query.Where(f => f.FamilyId == nullString); - Assert.IsNull(q7.FirstOrDefault()); - - IEnumerable q8 = query.Where(f => null == f.FamilyId); - Assert.IsNull(q8.FirstOrDefault()); - - IEnumerable q9 = query.Where(f => f.IsRegistered == false); - Assert.AreEqual(q9.FirstOrDefault().FamilyId, family.FamilyId); - - dynamic q10 = query.Where(f => f.FamilyId.Equals("WakefieldFamily")).AsEnumerable().FirstOrDefault(); - Assert.AreEqual(q10.FamilyId, family.FamilyId); - - GuidClass guidObject = new GuidClass() { Id = new Guid("098aa945-7ed8-4c50-b7b8-bd99eddb54bc") }; - container.CreateItemAsync(guidObject).Wait(); - List guidData = new List() { guidObject }; - - IOrderedQueryable guid = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IQueryable q11 = guid.Where(g => g.Id == guidObject.Id); - Assert.AreEqual(((IEnumerable)q11).FirstOrDefault().Id, guidObject.Id); - - IQueryable q12 = guid.Where(g => g.Id.ToString() == guidObject.Id.ToString()); - Assert.AreEqual(((IEnumerable)q12).FirstOrDefault().Id, guidObject.Id); - - ListArrayClass arrayObject = new ListArrayClass() { Id = "arrayObject", ArrayField = new int[] { 1, 2, 3 } }; - container.CreateItemAsync(arrayObject).Wait(); - - IOrderedQueryable listArrayQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q13 = listArrayQuery.Where(a => a.ArrayField == arrayObject.ArrayField); - Assert.AreEqual(q13.FirstOrDefault().Id, arrayObject.Id); - - int[] nullArray = null; - q13 = listArrayQuery.Where(a => a.ArrayField == nullArray); - Assert.IsNull(q13.FirstOrDefault()); - - ListArrayClass listObject = new ListArrayClass() { Id = "listObject", ListField = new List { 1, 2, 3 } }; - container.CreateItemAsync(listObject).Wait(); - List listArrayObjectData = new List() { arrayObject, listObject }; - - IEnumerable q14 = listArrayQuery.Where(a => a.ListField == listObject.ListField); - Assert.AreEqual(q14.FirstOrDefault().Id, listObject.Id); - - IEnumerable q15 = query.Where(f => f.NullableInt == null); - Assert.AreEqual(q15.ToList().Count, 0); - - int? nullInt = null; - q15 = query.Where(f => f.NullableInt == nullInt); - Assert.AreEqual(q15.ToList().Count, 0); - - q15 = query.Where(f => f.NullableInt == 5); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - nullInt = 5; - q15 = query.Where(f => f.NullableInt == nullInt); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - q15 = query.Where(f => f.NullableInt == nullInt.Value); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - nullInt = 3; - q15 = query.Where(f => f.Int == nullInt); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - q15 = query.Where(f => f.Int == nullInt.Value); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - nullInt = null; - q15 = query.Where(f => f.Int == nullInt); - Assert.AreEqual(q15.ToList().Count, 0); - - List v = fList.Where(f => f.Int > nullInt).ToList(); - - q15 = query.Where(f => f.Int < nullInt); - - string doc1Id = "document1:x:'!@TT){}\""; - Document doubleQoutesDocument = new Document() { Id = doc1Id }; - container.CreateItemAsync(doubleQoutesDocument).Wait(); - - IQueryable docQuery = from book in container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) - where book.Id == doc1Id - select book; - - Assert.AreEqual(docQuery.AsEnumerable().Single().Id, doc1Id); - - GreatFamily greatFamily = new GreatFamily() { Family = family }; - GreatGreatFamily greatGreatFamily = new GreatGreatFamily() { GreatFamilyId = Guid.NewGuid().ToString(), GreatFamily = greatFamily }; - container.CreateItemAsync(greatGreatFamily).Wait(); - List greatGreatFamilyData = new List() { greatGreatFamily }; - - IOrderedQueryable queryable = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q16 = queryable.SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)); - - Assert.AreEqual(q16.FirstOrDefault().GreatFamilyId, greatGreatFamily.GreatFamilyId); - - Sport sport = new Sport() { SportName = "Tennis", SportType = "Racquet" }; - container.CreateItemAsync(sport).Wait(); - List sportData = new List() { sport }; - - IOrderedQueryable sportQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q17 = sportQuery.Where(s => s.SportName == "Tennis"); - - Assert.AreEqual(sport.SportName, q17.FirstOrDefault().SportName); - - Sport2 sport2 = new Sport2() { id = "json" }; - container.CreateItemAsync(sport2).Wait(); - List sport2Data = new List() { sport2 }; - - IOrderedQueryable sport2Query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - Func> getGuidQuery = useQuery => useQuery ? guid : guidData.AsQueryable(); - Func> getListArrayQuery = useQuery => useQuery ? listArrayQuery : listArrayObjectData.AsQueryable(); - Func> getGreatFamilyQuery = useQuery => useQuery ? queryable : greatGreatFamilyData.AsQueryable(); - Func> getSportQuery = useQuery => useQuery ? sportQuery : sportData.AsQueryable(); - Func> getSport2Query = useQuery => useQuery ? sport2Query : sport2Data.AsQueryable(); - - int? nullIntVal = null; - int? nullableIntVal = 5; - - List inputs = new List(); - inputs.Add(new LinqTestInput("Select 1st parent family name", b => getQuery(b).Where(f => f.Parents.Count() > 0).Select(f => f.Parents[0].FamilyName))); - inputs.Add(new LinqTestInput("Select 1st children grade expr", b => getQuery(b).Where(f => f.Children.Count() > 0).Select(f => f.Children[0].Grade + 13))); - inputs.Add(new LinqTestInput("Filter 1st children's 1st pet name", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Pets[0].GivenName == "Fluffy"))); - inputs.Add(new LinqTestInput("Filter 1st children's thing A value", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Things["A"] == "B"))); - inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 1st pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[0]))); - inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 2nd pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 1 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[1]))); - inputs.Add(new LinqTestInput("Select FamilyId of all children", b => getQuery(b).SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })))); - inputs.Add(new LinqTestInput("Filter family with null Id", b => getQuery(b).Where(f => (string)null == f.FamilyId))); - inputs.Add(new LinqTestInput("Filter family with null Id #2", b => getQuery(b).Where(f => f.FamilyId == (string)null))); - inputs.Add(new LinqTestInput("Filter family with null object", b => getQuery(b).Where(f => f.NullObject == (object)null))); - inputs.Add(new LinqTestInput("Filter family with null Id #3", b => getQuery(b).Where(f => null == f.FamilyId))); - inputs.Add(new LinqTestInput("Filter registered family", b => getQuery(b).Where(f => f.IsRegistered == false))); - inputs.Add(new LinqTestInput("Filter family by FamilyId", b => getQuery(b).Where(f => f.FamilyId.Equals("WakefieldFamily")))); - inputs.Add(new LinqTestInput("Filter family nullable int", b => getQuery(b).Where(f => f.NullableInt == null))); - inputs.Add(new LinqTestInput("Filter family nullable int #2", b => getQuery(b).Where(f => f.NullableInt == nullIntVal))); - inputs.Add(new LinqTestInput("Filter family nullable int =", b => getQuery(b).Where(f => f.NullableInt == 5))); - inputs.Add(new LinqTestInput("Filter nullableInt = nullInt", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal))); - inputs.Add(new LinqTestInput("Filter nullableInt = nullInt value", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal.Value))); - inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullableIntVal))); - inputs.Add(new LinqTestInput("Filter int = nullInt value", b => getQuery(b).Where(f => f.Int == nullableIntVal.Value))); - inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullIntVal))); - inputs.Add(new LinqTestInput("Filter int < nullInt", b => getQuery(b).Where(f => f.Int < nullIntVal))); - - inputs.Add(new LinqTestInput("Guid filter by Id", b => getGuidQuery(b).Where(g => g.Id == guidObject.Id))); - inputs.Add(new LinqTestInput("Guid filter by Id #2", b => getGuidQuery(b).Where(g => g.Id.ToString() == guidObject.Id.ToString()))); - inputs.Add(new LinqTestInput("Array compare", b => getListArrayQuery(b).Where(a => a.ArrayField == arrayObject.ArrayField))); - inputs.Add(new LinqTestInput("Array compare null", b => getListArrayQuery(b).Where(a => a.ArrayField == nullArray))); - inputs.Add(new LinqTestInput("List compare", b => getListArrayQuery(b).Where(a => a.ListField == listObject.ListField))); - - inputs.Add(new LinqTestInput("Nested great family query filter children name", b => getGreatFamilyQuery(b).SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)))); - inputs.Add(new LinqTestInput("Sport filter sport name", b => getSportQuery(b).Where(s => s.SportName == "Tennis"))); - inputs.Add(new LinqTestInput("Sport filter sport type", b => getSportQuery(b).Where(s => s.SportType == "Racquet"))); - inputs.Add(new LinqTestInput("Sport2 filter by id", b => getSport2Query(b).Where(s => s.id == "json"))); - this.ExecuteTestSuite(inputs); - } - - internal static TValue CreateExecuteAndDeleteProcedure(DocumentClient client, - DocumentCollection collection, - string transientProcedure, - out StoredProcedureResponse response) - { - // create - StoredProcedure storedProcedure = new StoredProcedure - { - Id = "storedProcedure" + Guid.NewGuid().ToString(), - Body = transientProcedure - }; - StoredProcedure retrievedStoredProcedure = client.CreateStoredProcedureAsync(collection, storedProcedure).Result; - - // execute - response = client.ExecuteStoredProcedureAsync(retrievedStoredProcedure).Result; - - // delete - client.Delete(retrievedStoredProcedure.GetIdOrFullName()); - - return response.Response; - } - - [TestMethod] - public void ValidateBasicQuery() - { - this.ValidateBasicQueryAsync().Wait(); - } - - private async Task ValidateBasicQueryAsync() - { - DocumentClient client = TestCommon.CreateClient(true); - Documents.Database database = await client.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); - - string databaseName = database.Id; - - List queryResults = new List(); - //Simple Equality - IQueryable dbQuery = from db in client.CreateDatabaseQuery() - where db.Id == databaseName - select db; - IDocumentQuery documentQuery = dbQuery.AsDocumentQuery(); - - while (documentQuery.HasMoreResults) - { - DocumentFeedResponse pagedResponse = await documentQuery.ExecuteNextAsync(); - Assert.IsNotNull(pagedResponse.ResponseHeaders, "ResponseHeaders is null"); - Assert.IsNotNull(pagedResponse.ActivityId, "Query ActivityId is null"); - queryResults.AddRange(pagedResponse); - } - - Assert.AreEqual(1, queryResults.Count); - Assert.AreEqual(databaseName, queryResults[0].Id); - - //Logical Or - dbQuery = from db in client.CreateDatabaseQuery() - where db.Id == databaseName || db.ResourceId == database.ResourceId - select db; - documentQuery = dbQuery.AsDocumentQuery(); - - while (documentQuery.HasMoreResults) - { - queryResults.AddRange(await documentQuery.ExecuteNextAsync()); - } - - Assert.AreEqual(2, queryResults.Count); - Assert.AreEqual(databaseName, queryResults[0].Id); - - //Select Property - IQueryable idQuery = from db in client.CreateDatabaseQuery() - where db.Id == databaseName - select db.ResourceId; - IDocumentQuery documentIdQuery = idQuery.AsDocumentQuery(); - - List idResults = new List(); - while (documentIdQuery.HasMoreResults) - { - idResults.AddRange(await documentIdQuery.ExecuteNextAsync()); - } - - Assert.AreEqual(1, idResults.Count); - Assert.AreEqual(database.ResourceId, idResults[0]); - } - - [TestMethod] - public async Task ValidateTransformQuery() - { - PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/id" }), Kind = PartitionKind.Hash }; - DocumentCollection collection = new DocumentCollection - { - Id = Guid.NewGuid().ToString("N"), - PartitionKey = partitionKeyDefinition - }; - collection.IndexingPolicy.IndexingMode = IndexingMode.Consistent; - Database database = await cosmosClient.DocumentClient.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); - collection = cosmosClient.DocumentClient.Create(database.ResourceId, collection); - int documentsToCreate = 100; - for (int i = 0; i < documentsToCreate; i++) - { - dynamic myDocument = new Document(); - myDocument.Id = "doc" + i; - myDocument.Title = "MyBook"; //Simple Property. - myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property - myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property - myDocument.Price = 9.99; - myDocument = await cosmosClient.DocumentClient.CreateDocumentAsync(collection.DocumentsLink, myDocument); - } - - //Read response as dynamic. - IQueryable docQuery = cosmosClient.DocumentClient.CreateDocumentQuery(collection.DocumentsLink, @"select * from root r where r.Title=""MyBook""", new FeedOptions { EnableCrossPartitionQuery = true }); - - IDocumentQuery DocumentQuery = docQuery.AsDocumentQuery(); - DocumentFeedResponse queryResponse = await DocumentQuery.ExecuteNextAsync(); - - Assert.IsNotNull(queryResponse.ResponseHeaders, "ResponseHeaders is null"); - Assert.IsNotNull(queryResponse.ActivityId, "ActivityId is null"); - Assert.AreEqual(documentsToCreate, queryResponse.Count); - - foreach (dynamic myBook in queryResponse) - { - Assert.AreEqual(myBook.Title.ToString(), "MyBook"); - } - - cosmosClient.DocumentClient.DeleteDocumentCollectionAsync(collection.SelfLink).Wait(); - } - - [TestMethod] - public void ValidateDynamicDocumentQuery() //Ensure query on custom property of document. - { - Book myDocument = new Book(); - myDocument.Id = Guid.NewGuid().ToString(); - myDocument.Title = "My Book"; //Simple Property. - myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property - myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property - myDocument.Price = 9.99; - myDocument.Editions = new List() { new Edition() { Name = "First", Year = 2001 }, new Edition() { Name = "Second", Year = 2005 } }; - - //Create second document to make sure we have atleast one document which are filtered out of query. - Book secondDocument = new Book - { - Id = Guid.NewGuid().ToString(), - Title = "My Second Book", - Languages = new Language[] { new Language { Name = "Spanish", Copyright = "Mexico Publication" } }, - Author = new Author { Name = "Carlos", Location = "Cancun" }, - Price = 25, - Editions = new List() { new Edition() { Name = "First", Year = 1970 } } - }; - - //Unfiltered execution. - IOrderedQueryable bookDocQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - Func> getBookQuery = useQuery => useQuery ? bookDocQuery : new List().AsQueryable(); - - List inputs = new List(); - inputs.Add(new LinqTestInput("Simple Equality on custom property", - b => from book in getBookQuery(b) - where book.Title == "My Book" - select book)); - inputs.Add(new LinqTestInput("Nested Property access", - b => from book in getBookQuery(b) - where book.Author.Name == "Don" - select book)); - inputs.Add(new LinqTestInput("Array references & Project Author out..", - b => from book in getBookQuery(b) - where book.Languages[0].Name == "English" - select book.Author)); - inputs.Add(new LinqTestInput("SelectMany", - b => getBookQuery(b).SelectMany(book => book.Languages).Where(lang => lang.Name == "French").Select(lang => lang.Copyright))); - inputs.Add(new LinqTestInput("NumericRange query", - b => from book in getBookQuery(b) - where book.Price < 10 - select book.Author)); - inputs.Add(new LinqTestInput("Or query", - b => from book in getBookQuery(b) - where book.Title == "My Book" || book.Author.Name == "Don" - select book)); - inputs.Add(new LinqTestInput("SelectMany query on a List type.", - b => getBookQuery(b).SelectMany(book => book.Editions).Select(ed => ed.Name))); - // Below samples are strictly speaking not Any equivalent. But they join and filter "all" - // subchildren which match predicate. When SQL BE supports ANY, we can replace these with Any Flavor. - inputs.Add(new LinqTestInput("SelectMany", - b => getBookQuery(b).SelectMany(book => - book.Languages - .Where(lng => lng.Name == "English") - .Select(lng => book.Author)))); - inputs.Add(new LinqTestInput("SelectMany", - b => getBookQuery(b).SelectMany(book => - book.Editions - .Where(edition => edition.Year == 2001) - .Select(lng => book.Author)))); - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void ValidateDynamicAttachmentQuery() //Ensure query on custom property of attachment. - { - IOrderedQueryable attachmentQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - Document myDocument = new Document(); - Func> getAttachmentQuery = useQuery => useQuery ? attachmentQuery : new List().AsQueryable(); - - List inputs = new List(); - inputs.Add(new LinqTestInput("Filter equality on custom property", - b => from attachment in getAttachmentQuery(b) - where attachment.Title == "My Book Title2" - select attachment)); - inputs.Add(new LinqTestInput("Filter equality on custom property #2", - b => from attachment in getAttachmentQuery(b) - where attachment.Title == "My Book Title" - select attachment)); - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestLinqTypeSystem() - { - Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Book))); - Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Author))); - - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(Language[]))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(List))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IList))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IEnumerable))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(ICollection))); - - Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooItem[]))); - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(List))); - Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(MyList))); - Assert.AreEqual(typeof(Tuple), TypeSystem.GetElementType(typeof(MyTupleList))); - - Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooCollection))); - Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(FooStringCollection))); - - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - } - - #region DataDocument type tests - - public class BaseDocument - { - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Id { get; set; } - public string TypeName { get; set; } - } - - public class DataDocument : BaseDocument - { - public int Number { get; set; } - } - - private class QueryHelper - { - private readonly Container container; - - public QueryHelper(Container container) - { - this.container = container; - } - - public IQueryable Query() where T : BaseDocument - { - IQueryable query = this.container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) - .Where(d => d.TypeName == "Hello"); - string queryString = query.ToString(); - return query; - } - } - - [TestMethod] - public async Task ValidateLinqOnDataDocumentType() - { - Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: nameof(ValidateLinqOnDataDocumentType), partitionKeyPath: "/id")); - - DataDocument doc = new DataDocument() { Id = Guid.NewGuid().ToString("N"), Number = 0, TypeName = "Hello" }; - container.CreateItemAsync(doc).Wait(); - - QueryHelper queryHelper = new QueryHelper(container); - IEnumerable result = queryHelper.Query(); - Assert.AreEqual(1, result.Count()); - - BaseDocument baseDocument = result.FirstOrDefault(); - Assert.AreEqual(doc.Id, baseDocument.Id); - - BaseDocument iDocument = doc; - IOrderedQueryable q = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable iresult = from f in q - where f.Id == iDocument.Id - select f; - DataDocument id = iresult.FirstOrDefault(); - Assert.AreEqual(doc.Id, id.Id); - } - - #endregion - - #region Book type tests - public class Author - { - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Name { get; set; } - public string Location { get; set; } - } - - public class Language - { - public string Name { get; set; } - public string Copyright { get; set; } - } - - public class Edition - { - public string Name { get; set; } - public int Year { get; set; } - } - - public class Book - { - //Verify that we can override the propertyName but still can query them using .NET Property names. - [JsonProperty(PropertyName = "title")] - public string Title { get; set; } - [JsonProperty(PropertyName = "name")] - public string Name { get; set; } - public Language[] Languages { get; set; } - public Author Author { get; set; } - public double Price { get; set; } - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Id { get; set; } - public List Editions { get; set; } - } - - [TestMethod] - public async Task ValidateServerSideQueryEvalWithPagination() - { - await this.ValidateServerSideQueryEvalWithPaginationScenario(); - } - - private async Task ValidateServerSideQueryEvalWithPaginationScenario() - { - PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/title" }), Kind = PartitionKind.Hash }; - ContainerProperties cosmosContainerSettings = new ContainerProperties - { - Id = Guid.NewGuid().ToString(), - PartitionKey = partitionKeyDefinition, - }; - cosmosContainerSettings.IndexingPolicy.IndexingMode = Microsoft.Azure.Cosmos.IndexingMode.Consistent; - - Container collection = await testDb.CreateContainerAsync(cosmosContainerSettings); - - //Do script post to insert as many document as we could in a tight loop. - string script = @"function() { - var output = 0; - var client = getContext().getCollection(); - function callback(err, docCreated) { - if(err) throw 'Error while creating document'; - output++; - getContext().getResponse().setBody(output); - if(output < 50) - client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); - }; - client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); }"; - - StoredProcedureExecuteResponse scriptResponse = null; - int totalNumberOfDocuments = GatewayTests.CreateExecuteAndDeleteCosmosProcedure(collection, script, out scriptResponse, "My Book"); - - IOrderedQueryable linqQueryable = collection.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - int totalHit = linqQueryable.Where(book => book.Title == "My Book").Count(); - Assert.AreEqual(totalHit, totalNumberOfDocuments, "Didnt get all the documents"); - - } - - #endregion - - public class SpecialAttachment2 //Non attachemnt derived. - { - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Name { get; set; } - - [JsonProperty(PropertyName = "contentType")] - public string ContentType { get; set; } - - [JsonProperty(PropertyName = Constants.Properties.MediaLink)] - public string Media { get; set; } - - public string Author { get; set; } - public string Title { get; set; } - } - - #region TypeSystem test reference classes - public interface IFooItem { } - - public class FooItem : IFooItem { } - - public class DerivedFooItem : FooItem { } - - public class MyList : List { } - - public class MyTupleList : List> { } - - public class DerivedFooCollection : IList, IEnumerable - { - public int IndexOf(IFooItem item) - { - throw new NotImplementedException(); - } - - public void Insert(int index, IFooItem item) - { - throw new NotImplementedException(); - } - - public void RemoveAt(int index) - { - throw new NotImplementedException(); - } - - public IFooItem this[int index] - { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } - } - - public void Add(IFooItem item) - { - throw new NotImplementedException(); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public bool Contains(IFooItem item) - { - throw new NotImplementedException(); - } - - public void CopyTo(IFooItem[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - public int Count - { - get { throw new NotImplementedException(); } - } - - public bool IsReadOnly - { - get { throw new NotImplementedException(); } - } - - public bool Remove(IFooItem item) - { - throw new NotImplementedException(); - } - - public IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - } - - public class FooStringCollection : IList, IEnumerable - { - public int IndexOf(string item) - { - throw new NotImplementedException(); - } - - public void Insert(int index, string item) - { - throw new NotImplementedException(); - } - - public void RemoveAt(int index) - { - throw new NotImplementedException(); - } - - public string this[int index] - { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } - } - - public void Add(string item) - { - throw new NotImplementedException(); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public bool Contains(string item) - { - throw new NotImplementedException(); - } - - public void CopyTo(string[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - public int Count - { - get { throw new NotImplementedException(); } - } - - public bool IsReadOnly - { - get { throw new NotImplementedException(); } - } - - public bool Remove(string item) - { - throw new NotImplementedException(); - } - - public IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - } - - public class FooTCollection : List, IEnumerable - { - public new IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - } - #endregion - - public override LinqTestOutput ExecuteTest(LinqTestInput input) - { - return LinqTestsCommon.ExecuteTest(input); - } - } -} + [Ignore] + public void DebuggingTest() + { + + } + + [TestMethod] + [Owner("khdang")] + [Ignore] + public void TestSkipTake() + { + //TODO + //V2 using V3 pipeline causing issue on accessing Continuation in CosmosQueryResponseMessageHeaders + //This will be fine once we convert these test cases to use V3 pipeline + + List inputs = new List(); + + // -------------------------------- + // Skip - Take combinations + // -------------------------------- + + inputs.Add(new LinqTestInput( + "Skip", b => getQuery(b) + .Skip(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take", b => getQuery(b) + .Skip(1).Take(2))); + + inputs.Add(new LinqTestInput( + "Skip(negative number) -> Take", b => getQuery(b) + .Skip(-1).Take(1))); + + inputs.Add(new LinqTestInput( + "Skip -> Take(negative number)", b => getQuery(b) + .Skip(1).Take(-2))); + + inputs.Add(new LinqTestInput( + "Skip -> Skip -> Take", b => getQuery(b) + .Skip(1).Skip(2).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Take", b => getQuery(b) + .Skip(3).Take(5).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Skip -> Take", b => getQuery(b) + .Skip(1).Take(2).Skip(3).Take(4))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Take -> Skip", b => getQuery(b) + .Skip(1).Take(2).Take(3).Skip(4))); + + inputs.Add(new LinqTestInput( + "Skip -> Skip -> Take -> Take", b => getQuery(b) + .Skip(5).Skip(2).Take(10).Take(3))); + + inputs.Add(new LinqTestInput( + "Take -> Skip", b => getQuery(b) + .Take(7).Skip(3))); + + inputs.Add(new LinqTestInput( + "Take -> Take -> Skip", b => getQuery(b) + .Take(2).Take(3).Skip(5))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Skip", b => getQuery(b) + .Take(3).Skip(1).Skip(2))); + + inputs.Add(new LinqTestInput( + "Take -> Take -> Skip -> Skip", b => getQuery(b) + .Take(5).Take(3).Skip(1).Skip(1))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Take -> Skip", b => getQuery(b) + .Take(10).Skip(2).Take(5).Skip(1))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Skip -> Take", b => getQuery(b) + .Take(10).Skip(4).Skip(2).Take(2))); + + // -------------------------- + // Select + Skip & Take + // -------------------------- + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take", b => getQuery(b) + .Select(f => f.FamilyId).Skip(1).Take(2))); + + inputs.Add(new LinqTestInput( + "Select -> Take -> Skip", b => getQuery(b) + .Select(f => f.FamilyId).Take(2).Skip(1))); + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take -> Select", b => getQuery(b) + .Select(f => f.FamilyId).Skip(7).Take(13).Select(f => f.Count()))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Select -> Take -> Skip", b => getQuery(b) + .Skip(5).Take(11).Select(f => f.Children.Count()).Take(7).Skip(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Select -> Take", b => getQuery(b) + .Skip(10).Select(f => f.FamilyId).Take(7))); + + inputs.Add(new LinqTestInput( + "Take -> Select -> Skip", b => getQuery(b) + .Take(7).Select(f => f.FamilyId).Skip(3))); + + // ------------------------------ + // SelectMany + Skip & Take + // ------------------------------ + + inputs.Add(new LinqTestInput( + "SelectMany -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Skip(7).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany -> Skip -> Take -> SelectMany", b => getQuery(b) + .SelectMany(f => f.Children).Skip(11).Take(3).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput( + "Skip -> SelectMany -> Take -> Skip -> SelectMany", b => getQuery(b) + .Skip(1).SelectMany(f => f.Children).Take(13).Skip(3).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput( + "SelectMany -> SelectMany -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).SelectMany(c => c.Pets).Skip(3).Take(4))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> SelectMany -> Skip -> SelectMany", b => getQuery(b) + .Take(50).Skip(25).SelectMany(f => f.Children).Skip(10).SelectMany(c => c.Pets))); + + // --------------------------- + // Where + Skip & Take + // --------------------------- + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(3).Take(5))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> Where -> Skip -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 0).Skip(7).Take(11).Where(f => f.Tags.Count() > 2).Skip(1).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Where -> Skip", b => getQuery(b) + .Skip(1).Take(25).Where(f => f.Int > 10).Skip(5))); + + inputs.Add(new LinqTestInput( + "Take -> Where -> Skip", b => getQuery(b) + .Take(25).Where(f => f.FamilyId.Contains("A")).Skip(10))); + + inputs.Add(new LinqTestInput( + "Where -> Take -> Skip -> Where", b => getQuery(b) + .Where(f => f.Children.Count() > 1).Take(10).Skip(3).Where(f => f.Int > 0))); + + // --------------------------- + // OrderBy + Skip & Take + // --------------------------- + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Int).Skip(3).Take(7))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> Take -> OrderBy -> Take -> Skip", b => getQuery(b) + .OrderBy(f => f.Int).Skip(3).Take(11).OrderBy(f => f.FamilyId).Take(7).Skip(1))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> OrderBy", b => getQuery(b) + .Skip(3).Take(43).OrderBy(f => f.IsRegistered))); + + inputs.Add(new LinqTestInput( + "Take -> OrderByDescending -> Skip", b => getQuery(b) + .Take(50).OrderByDescending(f => f.Int).Skip(13))); + + inputs.Add(new LinqTestInput( + "Skip -> OrderByDescending -> Take", b => getQuery(b) + .Skip(7).OrderByDescending(f => f.Int).Take(17))); + + // --------------------------- + // Distinct + Skip & Take + // --------------------------- + + inputs.Add(new LinqTestInput( + "Distinct -> Skip -> Take", b => getQuery(b) + .Distinct().Skip(3).Take(7))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Distinct", b => getQuery(b) + .Skip(3).Take(11).Distinct())); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Select -> Distinct -> Skip -> Take -> Distinct -> Skip", b => getQuery(b) + .Skip(10).Take(60).Select(f => f.Int).Distinct().Skip(15).Take(20).Distinct().Skip(7))); + + inputs.Add(new LinqTestInput( + "Skip -> Distinct -> Skip -> Take", b => getQuery(b) + .Skip(7).Distinct().Skip(20).Take(10))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Distinct -> Skip", b => getQuery(b) + .Take(30).Skip(10).Distinct().Skip(7))); + + // --------------------------------------------------------------------------------- + // Select, SelectMany, Where, OrderBy, Distinct with Skip & Take in between + // --------------------------------------------------------------------------------- + + // Select, SelectMany + + inputs.Add(new LinqTestInput( + "Select(new) -> SelectMany -> Skip -> Take", b => getQuery(b) + .Select(f => new { f.FamilyId, f.Children }).SelectMany(c => c.Children).Skip(3).Take(10))); + + inputs.Add(new LinqTestInput( + "SelectMany -> Select -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Select(c => c.GivenName).Skip(7).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) + .Skip(10).Take(20).SelectMany(f => f.Children).Skip(3).Select(c => c.GivenName).Take(5))); + + inputs.Add(new LinqTestInput( + "Skip -> SelectMany -> Take -> Skip -> Select -> Take", b => getQuery(b) + .Skip(10).SelectMany(f => f.Children).Take(10).Skip(1).Select(c => c.FamilyName).Take(7))); + + inputs.Add(new LinqTestInput( + "Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) + .Take(30).SelectMany(f => f.Children).Skip(10).Select(c => c.Grade).Take(3))); + + // Select, Where + + inputs.Add(new LinqTestInput( + "Select -> Where -> Skip -> Take", b => getQuery(b) + .Select(f => f.Children).Where(c => c.Count() > 0).Skip(3).Take(7))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> Select -> Skip", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(7).Take(3).Select(f => f.FamilyId).Skip(2))); + + // Select, OrderBy + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take -> OrderBy", b => getQuery(b) + .Select(f => f.FamilyId).Skip(1).Take(2).OrderBy(s => s))); + + inputs.Add(new LinqTestInput( + "OrderByDescending -> Take -> Skip -> Select", b => getQuery(b) + .OrderByDescending(f => f.Int).Take(10).Skip(3).Select(f => f.Int + 1))); + + // Select, Distinct + + inputs.Add(new LinqTestInput( + "Take -> Select -> Distinct -> Skip -> Take", b => getQuery(b) + .Take(7).Select(f => f.Int).Distinct().Skip(1).Take(5))); + + // SelectMany, Where + + inputs.Add(new LinqTestInput( + "SelectMany -> Where -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Where(c => c.Grade > 100).Skip(10).Take(20))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> SelectMany -> Take", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(10).SelectMany(f => f.Children).Take(7))); + + // SelectMany, OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> SelectMany -> SelectMany", b => getQuery(b) + .OrderBy(f => f.Int).Skip(10).SelectMany(f => f.Children).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput( + "SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); + + // SelectMany, Distinct + + inputs.Add(new LinqTestInput( + "SelectMany -> Distinct -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Distinct().Skip(7).Take(11))); + + inputs.Add(new LinqTestInput( + "Distinct -> Skip -> SelectMany", b => getQuery(b) + .Distinct().Skip(3).SelectMany(f => f.Children))); + + // Where, OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy -> Where -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Int).Where(f => f.IsRegistered).Skip(11).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Where -> Take -> OrderBy", b => getQuery(b) + .Skip(20).Where(f => f.Children.Count() > 0).Take(10).OrderBy(f => f.Int))); + + // Where, Distinct + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> Distinct", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(3).Take(17).Distinct())); + + inputs.Add(new LinqTestInput( + "Skip -> Distinct -> Where -> Take", b => getQuery(b) + .Skip(22).Distinct().Where(f => f.Parents.Count() > 0).Take(7))); + + // ----------------------------------------- + // All basic operations with Skip & Take + // ----------------------------------------- + + // Start with Select + + inputs.Add(new LinqTestInput( + "Select -> Where -> OrderBy -> Skip -> Take", b => getQuery(b) + .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10))); + + inputs.Add(new LinqTestInput( + "Select -> Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10) + .Select(id => id + "_suffix").Where(id => id.Count() > 12).Skip(2).Take(4))); + + inputs.Add(new LinqTestInput( + "Select -> Skip -> OrderBy -> Skip -> Distinct -> Skip", b => getQuery(b) + .Select(f => f.Records).Skip(5).OrderBy(r => r.Transactions.Count()).Skip(1).Distinct().Skip(3))); + + inputs.Add(new LinqTestInput( + "Select(new(new(new(new(new))))) -> (Skip -> Select) x 6 -> Skip -> Where -> Take", b => getQuery(b) + .Select(f => new { f.FamilyId, L1 = new { L2 = new { L3 = new { L4 = new { f.Records } } } } }) + .Skip(1).Select(f => f.L1) + .Skip(2).Select(f => f.L2) + .Skip(3).Select(f => f.L3) + .Skip(4).Select(f => f.L4) + .Skip(5).Select(f => f.Records) + .Skip(6).Select(f => f.Transactions) + .Skip(7).Where(t => t.Count() > 100) + .Take(20))); + + inputs.Add(new LinqTestInput( + "Select -> (Skip -> Select -> Where -> OrderBy -> Distinct -> Take) x 3 -> Skip -> Take", b => getQuery(b) + .Select(f => new { L1 = f }) + .Skip(1).Select(f => f.L1).Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Distinct().Take(100) + .Skip(2).Select(f => new { L2 = f }).Where(f => f.L2.FamilyId.CompareTo("A") > 0).OrderBy(f => f.L2.Int).Distinct().Take(50) + .Skip(3).Select(f => f.L2).Where(f => f.Children.Count() > 1).OrderBy(f => f.IsRegistered).Distinct().Take(40) + .Skip(4).Take(25))); + + // Start with Distinct + + inputs.Add(new LinqTestInput( + "Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Distinct().Select(f => f.Records).Where(r => r.Transactions.Count() > 2).Skip(1).Take(10))); + + // Start with Where + + inputs.Add(new LinqTestInput( + "Where -> OrderBy -> Skip -> Take", b => getQuery(b) + .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5))); + + inputs.Add(new LinqTestInput( + "Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5) + .Select(f => f.Records).Where(r => r.Transactions != null).Skip(1).Take(3))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) + .Where(f => f.Int > 20).Skip(5).Take(20) + .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(5).Take(10))); + + // Start with OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Int).Skip(1).Take(10) + .Select(f => f.Records).Where(r => r.Transactions.Count() > 10).Skip(2).Take(3))); + + // Start with Skip + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Skip(1).Take(10).Select(f => f.Children.Count()).Where(c => c > 1).Skip(1).Take(4))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Where -> Skip -> Take -> OrderBy -> Skip -> Take -> Select -> Skip -> Distinct -> Skip -> Take", b => getQuery(b) + .Skip(2).Take(10).Where(f => f.Int > 10) + .Skip(1).Take(9).OrderBy(f => f.FamilyId) + .Skip(3).Take(5).Select(f => f.Children.Count()) + .Skip(1).Distinct() + .Skip(1).Take(1))); + + // Start with Take + + inputs.Add(new LinqTestInput( + "Take -> Skip -> OrderBy -> Skip -> Take", b => getQuery(b) + .Take(10).Skip(2).Where(f => f.IsRegistered).OrderBy(f => f.Int).Skip(1).Take(9))); + + inputs.Add(new LinqTestInput( + "Take -> Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Take(10).Distinct().Select(f => f.Children).Where(c => c.Count() > 0).Skip(2).Take(5))); + + // ----------------------------------------------------------------------------- + // All basic operations with Skip & Take with SelectMany in the middle + // ----------------------------------------------------------------------------- + + // SelectMany after Take + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) + .Select(f => f.Records).Skip(1).Take(10) + .SelectMany(r => r.Transactions).Skip(1).Take(9))); + + // SelectMany after Where + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) + .Where(f => f.IsRegistered) + .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); + + // Start with SelectMany + + inputs.Add(new LinqTestInput( + "SelectMany -> Select -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children) + .Select(c => c.FamilyName).Skip(1).Take(20) + .Select(n => n.Count()).Where(l => l > 10).Skip(2).Take(50))); + + // ------------------------------------------------------------- + // Nested Skip & Take in Select, SelectMany, Where, OrderBy + // ------------------------------------------------------------- + + // Nested with Select + + inputs.Add(new LinqTestInput( + "Select(new(Where -> Skip)) -> Where", b => getQuery(b) + .Select(f => new { + id = f.FamilyId, + GoodChildren = f.Children.Where(c => c.Grade > 75).Skip(1) + }) + .Where(f => f.GoodChildren.Count() > 0))); + + inputs.Add(new LinqTestInput( + "Select(Skip -> Take) -> Skip -> Take", b => getQuery(b) + .Select(f => f.Children.Skip(1).Take(1)).Skip(3).Take(10))); + + inputs.Add(new LinqTestInput( + "Select(new(Skip -> Take, Skip, Take) -> Skip -> Take -> Where", b => getQuery(b) + .Select(f => new { + v0 = f.Children.Skip(1).Take(2), + v1 = f.Parents.Skip(1), + v2 = f.Records.Transactions.Take(10) + }) + .Skip(1).Take(20).Where(f => f.v0.Count() > 0).Take(10))); + + inputs.Add(new LinqTestInput( + "Select(new(SelectMany -> SelectMany -> Distinct, OrderByDescending -> Take -> SelectMany -> Skip, Select -> OrderBy -> Skip -> Take -> Sum) -> Where -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) + .Select(f => new { + v0 = f.Children.SelectMany(c => c.Pets.Skip(1).SelectMany(p => p.GivenName).Distinct()), + v1 = f.Children.OrderByDescending(c => c.Grade).Take(2).SelectMany(c => c.Pets.Select(p => p.GivenName).Skip(2)), + v2 = f.Records.Transactions.Select(t => t.Amount).OrderBy(a => a).Skip(10).Take(20).Sum() + }) + .Where(f => f.v2 > 100).Skip(5).Take(20) + .SelectMany(f => f.v1).Distinct().Skip(3).Take(22))); + + inputs.Add(new LinqTestInput( + "Select -> Skip -> SelectMany(Skip -> OrderBy)", b => getQuery(b) + .Select(f => f.Records).Skip(1).SelectMany(r => r.Transactions.Skip(10).OrderBy(t => t.Date)))); + + // Nested with Where + + inputs.Add(new LinqTestInput( + "Where -> Where(Skip -> Take -> Count) - > Skip -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 2).Where(f => f.Children.Skip(1).Take(10).Count() > 1).Skip(1).Take(10))); + + // Nested with OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy(Skip -> Take -> Count) -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Children.Skip(1).Take(5).Count()))); + + // Nested with SelectMany + + inputs.Add(new LinqTestInput( + "SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20))); + + inputs.Add(new LinqTestInput( + "SelectMany(Skip -> Take) -> Skip -> Take -> SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20) + .SelectMany(c => c.Pets.Skip(1).Take(2)).Skip(1).Take(10))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where -> OrderBy -> Skip -> Distinct)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.Grade > 10).OrderBy(c => c.Grade).Skip(1).Distinct()))); + + inputs.Add(new LinqTestInput( + "SelectMany(Skip -> SelectMany(Skip -> Select) -> Take)", b => getQuery(b) + .SelectMany(f => f.Children.Skip(1).SelectMany(c => c.Pets.Skip(1).Select(p => p.GivenName)).Take(10)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + [Ignore] + public void TestUnsupportedScenarios() + { + List inputs = new List(); + + // -------------------- + // Dictionary type + // -------------------- + + // Iterating through Dictionary type + inputs.Add(new LinqTestInput("Iterating through Dictionary type", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Select(t => t.Key.Count() + t.Value.Count()))))); + + // Get a count of a Dictionary type + inputs.Add(new LinqTestInput("Getting Dictionary count", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Count())))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestOrderByTranslation() + { + List inputs = new List(); + + // Ascending + inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id))); + inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id).Select(x => x.Count()))); + inputs.Add(new LinqTestInput("Where -> OrderBy -> Select query", + b => from f in getQuery(b) + where f.Int == 5 && f.NullableInt != null + orderby f.IsRegistered + select f.FamilyId)); + inputs.Add(new LinqTestInput("Where -> OrderBy -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderBy(f => f.IsRegistered).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy query", + b => from f in getQuery(b) + orderby f.FamilyId + select f)); + inputs.Add(new LinqTestInput("OrderBy", b => getQuery(b).OrderBy(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy -> Select query", + b => from f in getQuery(b) + orderby f.FamilyId + select f.FamilyId)); + inputs.Add(new LinqTestInput("OrderBy -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); + + // Descending + inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id))); + inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id).Select(x => x.Count()))); + inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select query", + b => from f in getQuery(b) + where f.Int == 5 && f.NullableInt != null + orderby f.IsRegistered descending + select f.FamilyId)); + inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderByDescending(f => f.IsRegistered).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy Desc query", + b => from f in getQuery(b) + orderby f.FamilyId descending + select f)); + inputs.Add(new LinqTestInput("OrderBy Desc", b => getQuery(b).OrderByDescending(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy Desc -> Select query", + b => from f in getQuery(b) + orderby f.FamilyId descending + select f.FamilyId)); + inputs.Add(new LinqTestInput("OrderBy Desc -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); + inputs.Add(new LinqTestInput("OrderBy multiple expressions", + b => from f in getQuery(b) + orderby f.FamilyId, f.Int + select f.FamilyId)); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestLambdaReuse() + { + List inputs = new List(); + + System.Linq.Expressions.Expression> predicate = f => f.Int == 5; + inputs.Add(new LinqTestInput("Where -> Where with same predicate instance", b => getQuery(b).Where(predicate).Where(predicate))); + inputs.Add(new LinqTestInput("Where -> Select with same predicate instance", b => getQuery(b).Where(predicate).Select(predicate))); + + System.Linq.Expressions.Expression> predicate2 = f => f.ToString() == "a"; + inputs.Add(new LinqTestInput("Where -> Select -> Where with same predicate instance", + b => getQuery(b) + .Where(predicate2) + .Select(c => new { Int = 10, Result = c }) + .Where(predicate2))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestThenByTranslation() + { + List inputs = new List(); + + // Ascending and descending + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenBy(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenByDescending", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderByDescending -> ThenBy", b => getQuery(b) + .OrderByDescending(f => f.FamilyId) + .ThenBy(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderByDescending -> ThenByDescending", b => getQuery(b) + .OrderByDescending(f => f.FamilyId) + .ThenByDescending(f => f.Int))); + + // Subquery in OrderBy or in ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy subquery -> ThenBy", b => getQuery(b) + .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy subquery", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); + + inputs.Add(new LinqTestInput( + "OrderBy subquery -> ThenBy subquery", b => getQuery(b) + .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); + + // OrderBy and ThenBy by the same property (not a realistic scenario) + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenBy(f => f.FamilyId))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenByDescending", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.FamilyId))); + + inputs.Add(new LinqTestInput( + "OrderByDescending subquery -> ThenBy subquery", b => getQuery(b) + .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); + + // OrderBy and ThenBy with epxressions + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.Int * 2) + .ThenBy(f => f.FamilyId.Substring(2, 3)))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => !f.NullableInt.IsDefined()) + .ThenByDescending(f => f.Tags.Count() % 2))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderByDescending(f => f.IsRegistered ? f.FamilyId : f.Int.ToString()) + .ThenBy(f => f.Records.Transactions.Max(t => t.Amount) % 1000))); + + // Multiple OrderBy and ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy -> OrderBy -> ThenBy", b => getQuery(b) + .OrderByDescending(f => f.FamilyId) + .OrderBy(f => f.Int) + .ThenByDescending(f => f.IsRegistered))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenBy(f => f.Int) + .ThenByDescending(f => f.IsRegistered))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Orderby subquery -> ThenBy subquery", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy subquery -> ThenBy subquery", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()) + .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); + + // Nested ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy(OrderBy -> ThenBy -> Select)", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Select(p => p.FamilyName + p.GivenName)))); + + inputs.Add(new LinqTestInput( + "OrderBy(OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) + .OrderBy(f => f.Children + .OrderBy(c => c.Grade) + .ThenBy(c => c.Pets.Count)) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Select(p => p.FamilyName + p.GivenName)))); + + // Nested expressions with ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy(OrderBy -> ThenBy -> Take -> Select)", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Take(1) + .Select(p => p.FamilyName + p.GivenName)))); + + inputs.Add(new LinqTestInput( + "OrderBy(OrderBy -> ThenBy -> Take -> OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) + .OrderBy(f => f.Children + .OrderBy(c => c.Grade) + .ThenByDescending(c => c.Pets.Count) + .Take(10) + .OrderByDescending(c => c.GivenName) + .ThenBy(c => c.Gender)) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Select(p => p.FamilyName + p.GivenName)))); + + // On a new object + + inputs.Add(new LinqTestInput( + "Select -> OrderBy -> ThenBy", b => getQuery(b) + .Select(f => new + { + f.FamilyId, + FamilyNumber = f.Int, + ChildrenCount = f.Children.Count(), + ChildrenPetCount = f.Children.Select(c => c.Pets.Count()).Sum() + }) + .OrderBy(r => r.FamilyId) + .ThenBy(r => r.FamilyNumber))); + + inputs.Add(new LinqTestInput( + "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) + .SelectMany(f => f.Children.Select(c => new + { + f.FamilyId, + FamilyNumber = f.Int, + ChildrenCount = f.Children.Count(), + Name = c.GivenName, + SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() + }) + .OrderBy(r => r.FamilyId) + .ThenBy(r => r.FamilyNumber)))); + + inputs.Add(new LinqTestInput( + "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) + .SelectMany(f => f.Children.Select(c => new + { + f.FamilyId, + FamilyNumber = f.Int, + ChildrenCount = f.Children.Count(), + Name = c.GivenName, + SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() + })) + .OrderBy(r => r.FamilyId) + .ThenBy(r => r.FamilyNumber) + .Select(r => r.FamilyId))); + + inputs.Add(new LinqTestInput( + "Select(new(Where, Sum) -> OrderBy(Count) -> ThenBy)", b => getQuery(b) + .Select(f => new { + ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 0), + TotalExpenses = f.Records.Transactions.Sum(t => t.Amount) + }) + .OrderByDescending(r => r.ChildrenWithPets.Count()) + .ThenByDescending(r => r.TotalExpenses))); + + inputs.Add(new LinqTestInput( + "Select(new(Min, Count, SelectMany->Select->Distinct->Count)) -> OrderByDescending -> ThenBy", b => getQuery(b) + .Select(f => new { + ParentGivenName = f.Parents.Min(p => p.GivenName), + ParentCount = f.Parents.Count(), + GoodChildrenCount = f.Children.Where(c => c.Grade > 95).Count(), + UniquePetsNameCount = f.Children.SelectMany(c => c.Pets).Select(p => p.GivenName).Distinct().Count() + }) + .OrderByDescending(r => r.GoodChildrenCount) + .ThenBy(r => r.UniquePetsNameCount))); + + // With other LINQ operators: Where, SelectMany, Distinct, Skip, Take, and aggregates + + inputs.Add(new LinqTestInput( + "Where -> OrderBy -> ThenBy", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children) + .OrderBy(c => c.Grade) + .ThenByDescending(c => c.Pets.Count()) + .Take(3))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Skip -> Take -> Where -> Select -> Distinct", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children) + .OrderByDescending(c => c.Grade) + .ThenBy(c => c.GivenName) + .Skip(2) + .Take(20) + .Where(c => c.Pets.Where(p => p.GivenName.Length > 10).Count() > 0) + .Select(c => c.GivenName) + .Distinct())); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Select => Distinct => Take => OrderBy", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children) + .OrderBy(c => c.Grade) + .ThenByDescending(c => c.Pets.Count()) + .Select(c => c.GivenName) + .Distinct() + .Take(10) + .Skip(5) + .OrderBy(n => n.Length))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Records.Transactions) + .OrderBy(t => t.Type) + .ThenBy(t => t.Amount) + .Take(100))); + + inputs.Add(new LinqTestInput( + "Take -> OrderBy -> ThenBy", b => getQuery(b) + .Take(100) + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "Take -> OrderBy -> ThenBy -> Skip", b => getQuery(b) + .Take(100) + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int) + .Skip(5))); + + inputs.Add(new LinqTestInput( + "Distinct -> OrderBy -> ThenBy", b => getQuery(b) + .Distinct() + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany(Select(new Where->Count)) -> Distinct -> OrderBy -> ThenBy", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children.Select(c => new { + Name = c.GivenName, + PetWithLongNames = c.Pets.Where(p => p.GivenName.Length > 8).Count() + })) + .Distinct() + .OrderByDescending(r => r.Name) + .ThenBy(r => r.PetWithLongNames))); + + inputs.Add(new LinqTestInput( + "OrderBy(Any) -> ThenBy(Any)", b => getQuery(b) + .OrderBy(f => f.Children.Any(c => c.Grade > 90)) + .ThenByDescending(f => f.Parents.Any(p => p.GivenName.Length > 10)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Min) -> ThenBy(Max) -> ThenBy(Sum) -> ThenBy(Avg)", b => getQuery(b) + .OrderBy(f => f.Children.Min(c => c.GivenName)) + .ThenByDescending(f => f.Parents.Max(p => p.GivenName)) + .ThenBy(f => f.Records.Transactions.Sum(t => t.Amount)) + .ThenByDescending(f => f.Records.Transactions.Average(t => t.Amount)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + [Ignore] + public void TestDistinctSelectManyIssues() + { + List inputs = new List(); + + // these tests need a fix in the ServiceInterop + inputs.Add(new LinqTestInput( + "Distinct -> OrderBy -> Take", + b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x).Take(10))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Distinct -> Take", + b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Distinct().Take(10))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestDistinctTranslation() + { + static LinqTestInput DistinctTestInput(string description, System.Linq.Expressions.Expression> expr) + { + return new LinqTestInput(description, expr, true); + } + + List inputs = new List(); + + // Simple distinct + // Select -> Distinct for all data types + inputs.Add(DistinctTestInput( + "Distinct string", + b => getQuery(b).Select(f => f.FamilyId).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct int", + b => getQuery(b).Select(f => f.Int).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct bool", + b => getQuery(b).Select(f => f.IsRegistered).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct nullable int", + b => getQuery(b).Where(f => f.NullableInt != null).Select(f => f.NullableInt).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct null", + b => getQuery(b).Where(f => f.NullObject != null).Select(f => f.NullObject).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct children", + b => getQuery(b).SelectMany(f => f.Children).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct parent", + b => getQuery(b).SelectMany(f => f.Parents).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct family", + b => getQuery(b).Distinct())); + + inputs.Add(DistinctTestInput( + "Multiple distincts", + b => getQuery(b).Distinct().Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct new obj", + b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct new obj", + b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Select(f => f.Parents).Distinct())); + + // Distinct + Take + inputs.Add(DistinctTestInput( + "Distinct -> Take", + b => getQuery(b).Select(f => f.Int).Distinct().Take(10))); + + inputs.Add(new LinqTestInput( + "Take -> Distinct", + b => getQuery(b).Select(f => f.Int).Take(10).Distinct())); + + // Distinct + Order By + inputs.Add(new LinqTestInput( + "Distinct -> OrderBy", + b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x))); + + inputs.Add(DistinctTestInput( + "OrderBy -> Distinct", + b => getQuery(b).OrderBy(f => f.Int).Distinct())); + + // Distinct + Order By + Take + inputs.Add(new LinqTestInput( + "Distinct -> Take -> OrderBy", + b => getQuery(b).Select(f => f.Int).Distinct().Take(10).OrderBy(x => x))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Take -> Distinct", + b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Take(10).Distinct())); + + // Distinct + Where + inputs.Add(DistinctTestInput( + "Where -> Distinct", + b => getQuery(b).Select(f => f.Int).Where(x => x > 10).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct -> Where", + b => getQuery(b).Select(f => f.Int).Distinct().Where(x => x > 10))); + + // SelectMany w Distinct + inputs.Add(DistinctTestInput( + "SelectMany(Select obj) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select)) -> Distinct", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet))) + .Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select -> Distinct))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet) + .Distinct())))); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select -> Select) -> Distinct)", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet.GivenName) + .Select(name => name.Count()))) + .Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select new {} -> Select) -> Distinct)", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }).Select(p => p.child)) + .Distinct()))); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select new {}) -> Distinct)", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }))) + .Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select new {} -> Distinct))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }) + .Distinct())))); + + // SelectMany(Distinct) + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Take(5).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct().Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> Take -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .Take(5).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .Where(f => f.FamilyName.Count() < 20))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Select", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Select -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()).Take(5))); + + // SelectMany(Select -> Distinct) + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Distinct) -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).OrderBy(n => n).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Distinct) -> Where -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10).OrderBy(n => n).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Select) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Select -> Distinct)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Distinct()))); + + inputs.Add(DistinctTestInput( + "SelectMany(Select -> Distinct) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Select -> Distinct) -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void ValidateDynamicLinq() + { + List inputs = new List(); + inputs.Add(new LinqTestInput("Select", b => getQuery(b).Select("FamilyId"))); + inputs.Add(new LinqTestInput("Where", b => getQuery(b).Where("FamilyId = \"some id\""))); + inputs.Add(new LinqTestInput("Where longer", b => getQuery(b).Where("FamilyId = \"some id\" AND IsRegistered = True OR Int > 101"))); + // with parameters + inputs.Add(new LinqTestInput("Where w/ parameters", b => getQuery(b).Where("FamilyId = @0 AND IsRegistered = @1 OR Int > @2", "some id", true, 101))); + inputs.Add(new LinqTestInput("Where -> Select", b => getQuery(b).Where("FamilyId = \"some id\"").Select("Int"))); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public async Task ValidateLinqQueries() + { + Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString("N"), partitionKeyPath: "/id")); + + Parent mother = new Parent { FamilyName = "Wakefield", GivenName = "Robin" }; + Parent father = new Parent { FamilyName = "Miller", GivenName = "Ben" }; + Pet pet = new Pet { GivenName = "Fluffy" }; + Child child = new Child + { + FamilyName = "Merriam", + GivenName = "Jesse", + Gender = "female", + Grade = 1, + Pets = new List() { pet, new Pet() { GivenName = "koko" } }, + Things = new Dictionary() { { "A", "B" }, { "C", "D" } } + }; + + Address address = new Address { State = "NY", County = "Manhattan", City = "NY" }; + Family family = new Family { FamilyId = "WakefieldFamily", Parents = new Parent[] { mother, father }, Children = new Child[] { child }, IsRegistered = false, Int = 3, NullableInt = 5, Id = "WakefieldFamily" }; + + List fList = new List(); + fList.Add(family); + + container.CreateItemAsync(family).Wait(); + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q1 = query.Select(f => f.Parents[0].FamilyName); + Assert.AreEqual(q1.FirstOrDefault(), family.Parents[0].FamilyName); + + IEnumerable q2 = query.Select(f => f.Children[0].Grade + 13); + Assert.AreEqual(q2.FirstOrDefault(), family.Children[0].Grade + 13); + + IEnumerable q3 = query.Where(f => f.Children[0].Pets[0].GivenName == "Fluffy"); + Assert.AreEqual(q3.FirstOrDefault().FamilyId, family.FamilyId); + + IEnumerable q4 = query.Where(f => f.Children[0].Things["A"] == "B"); + Assert.AreEqual(q4.FirstOrDefault().FamilyId, family.FamilyId); + + for (int index = 0; index < 2; index++) + { + IEnumerable q5 = query.Where(f => f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[index]); + Assert.AreEqual(q5.FirstOrDefault().GivenName, family.Children[0].Pets[index].GivenName); + } + + IEnumerable q6 = query.SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })); + Assert.AreEqual(q6.FirstOrDefault().Id, family.FamilyId); + + string nullString = null; + IEnumerable q7 = query.Where(f => nullString == f.FamilyId); + Assert.IsNull(q7.FirstOrDefault()); + + object nullObject = null; + q7 = query.Where(f => f.NullObject == nullObject); + Assert.AreEqual(q7.FirstOrDefault().FamilyId, family.FamilyId); + + q7 = query.Where(f => f.FamilyId == nullString); + Assert.IsNull(q7.FirstOrDefault()); + + IEnumerable q8 = query.Where(f => null == f.FamilyId); + Assert.IsNull(q8.FirstOrDefault()); + + IEnumerable q9 = query.Where(f => f.IsRegistered == false); + Assert.AreEqual(q9.FirstOrDefault().FamilyId, family.FamilyId); + + dynamic q10 = query.Where(f => f.FamilyId.Equals("WakefieldFamily")).AsEnumerable().FirstOrDefault(); + Assert.AreEqual(q10.FamilyId, family.FamilyId); + + GuidClass guidObject = new GuidClass() { Id = new Guid("098aa945-7ed8-4c50-b7b8-bd99eddb54bc") }; + container.CreateItemAsync(guidObject).Wait(); + List guidData = new List() { guidObject }; + + IOrderedQueryable guid = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IQueryable q11 = guid.Where(g => g.Id == guidObject.Id); + Assert.AreEqual(((IEnumerable)q11).FirstOrDefault().Id, guidObject.Id); + + IQueryable q12 = guid.Where(g => g.Id.ToString() == guidObject.Id.ToString()); + Assert.AreEqual(((IEnumerable)q12).FirstOrDefault().Id, guidObject.Id); + + ListArrayClass arrayObject = new ListArrayClass() { Id = "arrayObject", ArrayField = new int[] { 1, 2, 3 } }; + container.CreateItemAsync(arrayObject).Wait(); + + IOrderedQueryable listArrayQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q13 = listArrayQuery.Where(a => a.ArrayField == arrayObject.ArrayField); + Assert.AreEqual(q13.FirstOrDefault().Id, arrayObject.Id); + + int[] nullArray = null; + q13 = listArrayQuery.Where(a => a.ArrayField == nullArray); + Assert.IsNull(q13.FirstOrDefault()); + + ListArrayClass listObject = new ListArrayClass() { Id = "listObject", ListField = new List { 1, 2, 3 } }; + container.CreateItemAsync(listObject).Wait(); + List listArrayObjectData = new List() { arrayObject, listObject }; + + IEnumerable q14 = listArrayQuery.Where(a => a.ListField == listObject.ListField); + Assert.AreEqual(q14.FirstOrDefault().Id, listObject.Id); + + IEnumerable q15 = query.Where(f => f.NullableInt == null); + Assert.AreEqual(q15.ToList().Count, 0); + + int? nullInt = null; + q15 = query.Where(f => f.NullableInt == nullInt); + Assert.AreEqual(q15.ToList().Count, 0); + + q15 = query.Where(f => f.NullableInt == 5); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + nullInt = 5; + q15 = query.Where(f => f.NullableInt == nullInt); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + q15 = query.Where(f => f.NullableInt == nullInt.Value); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + nullInt = 3; + q15 = query.Where(f => f.Int == nullInt); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + q15 = query.Where(f => f.Int == nullInt.Value); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + nullInt = null; + q15 = query.Where(f => f.Int == nullInt); + Assert.AreEqual(q15.ToList().Count, 0); + + List v = fList.Where(f => f.Int > nullInt).ToList(); + + q15 = query.Where(f => f.Int < nullInt); + + string doc1Id = "document1:x:'!@TT){}\""; + Document doubleQoutesDocument = new Document() { Id = doc1Id }; + container.CreateItemAsync(doubleQoutesDocument).Wait(); + + IQueryable docQuery = from book in container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) + where book.Id == doc1Id + select book; + + Assert.AreEqual(docQuery.AsEnumerable().Single().Id, doc1Id); + + GreatFamily greatFamily = new GreatFamily() { Family = family }; + GreatGreatFamily greatGreatFamily = new GreatGreatFamily() { GreatFamilyId = Guid.NewGuid().ToString(), GreatFamily = greatFamily }; + container.CreateItemAsync(greatGreatFamily).Wait(); + List greatGreatFamilyData = new List() { greatGreatFamily }; + + IOrderedQueryable queryable = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q16 = queryable.SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)); + + Assert.AreEqual(q16.FirstOrDefault().GreatFamilyId, greatGreatFamily.GreatFamilyId); + + Sport sport = new Sport() { SportName = "Tennis", SportType = "Racquet" }; + container.CreateItemAsync(sport).Wait(); + List sportData = new List() { sport }; + + IOrderedQueryable sportQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q17 = sportQuery.Where(s => s.SportName == "Tennis"); + + Assert.AreEqual(sport.SportName, q17.FirstOrDefault().SportName); + + Sport2 sport2 = new Sport2() { id = "json" }; + container.CreateItemAsync(sport2).Wait(); + List sport2Data = new List() { sport2 }; + + IOrderedQueryable sport2Query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + Func> getGuidQuery = useQuery => useQuery ? guid : guidData.AsQueryable(); + Func> getListArrayQuery = useQuery => useQuery ? listArrayQuery : listArrayObjectData.AsQueryable(); + Func> getGreatFamilyQuery = useQuery => useQuery ? queryable : greatGreatFamilyData.AsQueryable(); + Func> getSportQuery = useQuery => useQuery ? sportQuery : sportData.AsQueryable(); + Func> getSport2Query = useQuery => useQuery ? sport2Query : sport2Data.AsQueryable(); + + int? nullIntVal = null; + int? nullableIntVal = 5; + + List inputs = new List(); + inputs.Add(new LinqTestInput("Select 1st parent family name", b => getQuery(b).Where(f => f.Parents.Count() > 0).Select(f => f.Parents[0].FamilyName))); + inputs.Add(new LinqTestInput("Select 1st children grade expr", b => getQuery(b).Where(f => f.Children.Count() > 0).Select(f => f.Children[0].Grade + 13))); + inputs.Add(new LinqTestInput("Filter 1st children's 1st pet name", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Pets[0].GivenName == "Fluffy"))); + inputs.Add(new LinqTestInput("Filter 1st children's thing A value", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Things["A"] == "B"))); + inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 1st pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[0]))); + inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 2nd pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 1 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[1]))); + inputs.Add(new LinqTestInput("Select FamilyId of all children", b => getQuery(b).SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })))); + inputs.Add(new LinqTestInput("Filter family with null Id", b => getQuery(b).Where(f => (string)null == f.FamilyId))); + inputs.Add(new LinqTestInput("Filter family with null Id #2", b => getQuery(b).Where(f => f.FamilyId == (string)null))); + inputs.Add(new LinqTestInput("Filter family with null object", b => getQuery(b).Where(f => f.NullObject == (object)null))); + inputs.Add(new LinqTestInput("Filter family with null Id #3", b => getQuery(b).Where(f => null == f.FamilyId))); + inputs.Add(new LinqTestInput("Filter registered family", b => getQuery(b).Where(f => f.IsRegistered == false))); + inputs.Add(new LinqTestInput("Filter family by FamilyId", b => getQuery(b).Where(f => f.FamilyId.Equals("WakefieldFamily")))); + inputs.Add(new LinqTestInput("Filter family nullable int", b => getQuery(b).Where(f => f.NullableInt == null))); + inputs.Add(new LinqTestInput("Filter family nullable int #2", b => getQuery(b).Where(f => f.NullableInt == nullIntVal))); + inputs.Add(new LinqTestInput("Filter family nullable int =", b => getQuery(b).Where(f => f.NullableInt == 5))); + inputs.Add(new LinqTestInput("Filter nullableInt = nullInt", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal))); + inputs.Add(new LinqTestInput("Filter nullableInt = nullInt value", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal.Value))); + inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullableIntVal))); + inputs.Add(new LinqTestInput("Filter int = nullInt value", b => getQuery(b).Where(f => f.Int == nullableIntVal.Value))); + inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullIntVal))); + inputs.Add(new LinqTestInput("Filter int < nullInt", b => getQuery(b).Where(f => f.Int < nullIntVal))); + + inputs.Add(new LinqTestInput("Guid filter by Id", b => getGuidQuery(b).Where(g => g.Id == guidObject.Id))); + inputs.Add(new LinqTestInput("Guid filter by Id #2", b => getGuidQuery(b).Where(g => g.Id.ToString() == guidObject.Id.ToString()))); + inputs.Add(new LinqTestInput("Array compare", b => getListArrayQuery(b).Where(a => a.ArrayField == arrayObject.ArrayField))); + inputs.Add(new LinqTestInput("Array compare null", b => getListArrayQuery(b).Where(a => a.ArrayField == nullArray))); + inputs.Add(new LinqTestInput("List compare", b => getListArrayQuery(b).Where(a => a.ListField == listObject.ListField))); + + inputs.Add(new LinqTestInput("Nested great family query filter children name", b => getGreatFamilyQuery(b).SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)))); + inputs.Add(new LinqTestInput("Sport filter sport name", b => getSportQuery(b).Where(s => s.SportName == "Tennis"))); + inputs.Add(new LinqTestInput("Sport filter sport type", b => getSportQuery(b).Where(s => s.SportType == "Racquet"))); + inputs.Add(new LinqTestInput("Sport2 filter by id", b => getSport2Query(b).Where(s => s.id == "json"))); + this.ExecuteTestSuite(inputs); + } + + internal static TValue CreateExecuteAndDeleteProcedure(DocumentClient client, + DocumentCollection collection, + string transientProcedure, + out StoredProcedureResponse response) + { + // create + StoredProcedure storedProcedure = new StoredProcedure + { + Id = "storedProcedure" + Guid.NewGuid().ToString(), + Body = transientProcedure + }; + StoredProcedure retrievedStoredProcedure = client.CreateStoredProcedureAsync(collection, storedProcedure).Result; + + // execute + response = client.ExecuteStoredProcedureAsync(retrievedStoredProcedure).Result; + + // delete + client.Delete(retrievedStoredProcedure.GetIdOrFullName()); + + return response.Response; + } + + [TestMethod] + public void ValidateBasicQuery() + { + this.ValidateBasicQueryAsync().Wait(); + } + + private async Task ValidateBasicQueryAsync() + { + DocumentClient client = TestCommon.CreateClient(true); + Documents.Database database = await client.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); + + string databaseName = database.Id; + + List queryResults = new List(); + //Simple Equality + IQueryable dbQuery = from db in client.CreateDatabaseQuery() + where db.Id == databaseName + select db; + IDocumentQuery documentQuery = dbQuery.AsDocumentQuery(); + + while (documentQuery.HasMoreResults) + { + DocumentFeedResponse pagedResponse = await documentQuery.ExecuteNextAsync(); + Assert.IsNotNull(pagedResponse.ResponseHeaders, "ResponseHeaders is null"); + Assert.IsNotNull(pagedResponse.ActivityId, "Query ActivityId is null"); + queryResults.AddRange(pagedResponse); + } + + Assert.AreEqual(1, queryResults.Count); + Assert.AreEqual(databaseName, queryResults[0].Id); + + //Logical Or + dbQuery = from db in client.CreateDatabaseQuery() + where db.Id == databaseName || db.ResourceId == database.ResourceId + select db; + documentQuery = dbQuery.AsDocumentQuery(); + + while (documentQuery.HasMoreResults) + { + queryResults.AddRange(await documentQuery.ExecuteNextAsync()); + } + + Assert.AreEqual(2, queryResults.Count); + Assert.AreEqual(databaseName, queryResults[0].Id); + + //Select Property + IQueryable idQuery = from db in client.CreateDatabaseQuery() + where db.Id == databaseName + select db.ResourceId; + IDocumentQuery documentIdQuery = idQuery.AsDocumentQuery(); + + List idResults = new List(); + while (documentIdQuery.HasMoreResults) + { + idResults.AddRange(await documentIdQuery.ExecuteNextAsync()); + } + + Assert.AreEqual(1, idResults.Count); + Assert.AreEqual(database.ResourceId, idResults[0]); + } + + [TestMethod] + public async Task ValidateTransformQuery() + { + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/id" }), Kind = PartitionKind.Hash }; + DocumentCollection collection = new DocumentCollection + { + Id = Guid.NewGuid().ToString("N"), + PartitionKey = partitionKeyDefinition + }; + collection.IndexingPolicy.IndexingMode = IndexingMode.Consistent; + Database database = await cosmosClient.DocumentClient.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); + collection = cosmosClient.DocumentClient.Create(database.ResourceId, collection); + int documentsToCreate = 100; + for (int i = 0; i < documentsToCreate; i++) + { + dynamic myDocument = new Document(); + myDocument.Id = "doc" + i; + myDocument.Title = "MyBook"; //Simple Property. + myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property + myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property + myDocument.Price = 9.99; + myDocument = await cosmosClient.DocumentClient.CreateDocumentAsync(collection.DocumentsLink, myDocument); + } + + //Read response as dynamic. + IQueryable docQuery = cosmosClient.DocumentClient.CreateDocumentQuery(collection.DocumentsLink, @"select * from root r where r.Title=""MyBook""", new FeedOptions { EnableCrossPartitionQuery = true }); + + IDocumentQuery DocumentQuery = docQuery.AsDocumentQuery(); + DocumentFeedResponse queryResponse = await DocumentQuery.ExecuteNextAsync(); + + Assert.IsNotNull(queryResponse.ResponseHeaders, "ResponseHeaders is null"); + Assert.IsNotNull(queryResponse.ActivityId, "ActivityId is null"); + Assert.AreEqual(documentsToCreate, queryResponse.Count); + + foreach (dynamic myBook in queryResponse) + { + Assert.AreEqual(myBook.Title.ToString(), "MyBook"); + } + + cosmosClient.DocumentClient.DeleteDocumentCollectionAsync(collection.SelfLink).Wait(); + } + + [TestMethod] + public void ValidateDynamicDocumentQuery() //Ensure query on custom property of document. + { + Book myDocument = new Book(); + myDocument.Id = Guid.NewGuid().ToString(); + myDocument.Title = "My Book"; //Simple Property. + myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property + myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property + myDocument.Price = 9.99; + myDocument.Editions = new List() { new Edition() { Name = "First", Year = 2001 }, new Edition() { Name = "Second", Year = 2005 } }; + + //Create second document to make sure we have atleast one document which are filtered out of query. + Book secondDocument = new Book + { + Id = Guid.NewGuid().ToString(), + Title = "My Second Book", + Languages = new Language[] { new Language { Name = "Spanish", Copyright = "Mexico Publication" } }, + Author = new Author { Name = "Carlos", Location = "Cancun" }, + Price = 25, + Editions = new List() { new Edition() { Name = "First", Year = 1970 } } + }; + + //Unfiltered execution. + IOrderedQueryable bookDocQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + Func> getBookQuery = useQuery => useQuery ? bookDocQuery : new List().AsQueryable(); + + List inputs = new List(); + inputs.Add(new LinqTestInput("Simple Equality on custom property", + b => from book in getBookQuery(b) + where book.Title == "My Book" + select book)); + inputs.Add(new LinqTestInput("Nested Property access", + b => from book in getBookQuery(b) + where book.Author.Name == "Don" + select book)); + inputs.Add(new LinqTestInput("Array references & Project Author out..", + b => from book in getBookQuery(b) + where book.Languages[0].Name == "English" + select book.Author)); + inputs.Add(new LinqTestInput("SelectMany", + b => getBookQuery(b).SelectMany(book => book.Languages).Where(lang => lang.Name == "French").Select(lang => lang.Copyright))); + inputs.Add(new LinqTestInput("NumericRange query", + b => from book in getBookQuery(b) + where book.Price < 10 + select book.Author)); + inputs.Add(new LinqTestInput("Or query", + b => from book in getBookQuery(b) + where book.Title == "My Book" || book.Author.Name == "Don" + select book)); + inputs.Add(new LinqTestInput("SelectMany query on a List type.", + b => getBookQuery(b).SelectMany(book => book.Editions).Select(ed => ed.Name))); + // Below samples are strictly speaking not Any equivalent. But they join and filter "all" + // subchildren which match predicate. When SQL BE supports ANY, we can replace these with Any Flavor. + inputs.Add(new LinqTestInput("SelectMany", + b => getBookQuery(b).SelectMany(book => + book.Languages + .Where(lng => lng.Name == "English") + .Select(lng => book.Author)))); + inputs.Add(new LinqTestInput("SelectMany", + b => getBookQuery(b).SelectMany(book => + book.Editions + .Where(edition => edition.Year == 2001) + .Select(lng => book.Author)))); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void ValidateDynamicAttachmentQuery() //Ensure query on custom property of attachment. + { + IOrderedQueryable attachmentQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + Document myDocument = new Document(); + Func> getAttachmentQuery = useQuery => useQuery ? attachmentQuery : new List().AsQueryable(); + + List inputs = new List(); + inputs.Add(new LinqTestInput("Filter equality on custom property", + b => from attachment in getAttachmentQuery(b) + where attachment.Title == "My Book Title2" + select attachment)); + inputs.Add(new LinqTestInput("Filter equality on custom property #2", + b => from attachment in getAttachmentQuery(b) + where attachment.Title == "My Book Title" + select attachment)); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestLinqTypeSystem() + { + Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Book))); + Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Author))); + + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(Language[]))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(List))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IList))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IEnumerable))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(ICollection))); + + Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooItem[]))); + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(List))); + Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(MyList))); + Assert.AreEqual(typeof(Tuple), TypeSystem.GetElementType(typeof(MyTupleList))); + + Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooCollection))); + Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(FooStringCollection))); + + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + } + + #region DataDocument type tests + + public class BaseDocument + { + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Id { get; set; } + public string TypeName { get; set; } + } + + public class DataDocument : BaseDocument + { + public int Number { get; set; } + } + + private class QueryHelper + { + private readonly Container container; + + public QueryHelper(Container container) + { + this.container = container; + } + + public IQueryable Query() where T : BaseDocument + { + IQueryable query = this.container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) + .Where(d => d.TypeName == "Hello"); + string queryString = query.ToString(); + return query; + } + } + + [TestMethod] + public async Task ValidateLinqOnDataDocumentType() + { + Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: nameof(ValidateLinqOnDataDocumentType), partitionKeyPath: "/id")); + + DataDocument doc = new DataDocument() { Id = Guid.NewGuid().ToString("N"), Number = 0, TypeName = "Hello" }; + container.CreateItemAsync(doc).Wait(); + + QueryHelper queryHelper = new QueryHelper(container); + IEnumerable result = queryHelper.Query(); + Assert.AreEqual(1, result.Count()); + + BaseDocument baseDocument = result.FirstOrDefault(); + Assert.AreEqual(doc.Id, baseDocument.Id); + + BaseDocument iDocument = doc; + IOrderedQueryable q = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable iresult = from f in q + where f.Id == iDocument.Id + select f; + DataDocument id = iresult.FirstOrDefault(); + Assert.AreEqual(doc.Id, id.Id); + } + + #endregion + + #region Book type tests + public class Author + { + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Name { get; set; } + public string Location { get; set; } + } + + public class Language + { + public string Name { get; set; } + public string Copyright { get; set; } + } + + public class Edition + { + public string Name { get; set; } + public int Year { get; set; } + } + + public class Book + { + //Verify that we can override the propertyName but still can query them using .NET Property names. + [JsonProperty(PropertyName = "title")] + public string Title { get; set; } + [JsonProperty(PropertyName = "name")] + public string Name { get; set; } + public Language[] Languages { get; set; } + public Author Author { get; set; } + public double Price { get; set; } + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Id { get; set; } + public List Editions { get; set; } + } + + [TestMethod] + public async Task ValidateServerSideQueryEvalWithPagination() + { + await this.ValidateServerSideQueryEvalWithPaginationScenario(); + } + + private async Task ValidateServerSideQueryEvalWithPaginationScenario() + { + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/title" }), Kind = PartitionKind.Hash }; + ContainerProperties cosmosContainerSettings = new ContainerProperties + { + Id = Guid.NewGuid().ToString(), + PartitionKey = partitionKeyDefinition, + }; + cosmosContainerSettings.IndexingPolicy.IndexingMode = Microsoft.Azure.Cosmos.IndexingMode.Consistent; + + Container collection = await testDb.CreateContainerAsync(cosmosContainerSettings); + + //Do script post to insert as many document as we could in a tight loop. + string script = @"function() { + var output = 0; + var client = getContext().getCollection(); + function callback(err, docCreated) { + if(err) throw 'Error while creating document'; + output++; + getContext().getResponse().setBody(output); + if(output < 50) + client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); + }; + client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); }"; + + StoredProcedureExecuteResponse scriptResponse = null; + int totalNumberOfDocuments = GatewayTests.CreateExecuteAndDeleteCosmosProcedure(collection, script, out scriptResponse, "My Book"); + + IOrderedQueryable linqQueryable = collection.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + int totalHit = linqQueryable.Where(book => book.Title == "My Book").Count(); + Assert.AreEqual(totalHit, totalNumberOfDocuments, "Didnt get all the documents"); + + } + + #endregion + + public class SpecialAttachment2 //Non attachemnt derived. + { + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Name { get; set; } + + [JsonProperty(PropertyName = "contentType")] + public string ContentType { get; set; } + + [JsonProperty(PropertyName = Constants.Properties.MediaLink)] + public string Media { get; set; } + + public string Author { get; set; } + public string Title { get; set; } + } + + #region TypeSystem test reference classes + public interface IFooItem { } + + public class FooItem : IFooItem { } + + public class DerivedFooItem : FooItem { } + + public class MyList : List { } + + public class MyTupleList : List> { } + + public class DerivedFooCollection : IList, IEnumerable + { + public int IndexOf(IFooItem item) + { + throw new NotImplementedException(); + } + + public void Insert(int index, IFooItem item) + { + throw new NotImplementedException(); + } + + public void RemoveAt(int index) + { + throw new NotImplementedException(); + } + + public IFooItem this[int index] + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public void Add(IFooItem item) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(IFooItem item) + { + throw new NotImplementedException(); + } + + public void CopyTo(IFooItem[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public int Count + { + get { throw new NotImplementedException(); } + } + + public bool IsReadOnly + { + get { throw new NotImplementedException(); } + } + + public bool Remove(IFooItem item) + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + } + + public class FooStringCollection : IList, IEnumerable + { + public int IndexOf(string item) + { + throw new NotImplementedException(); + } + + public void Insert(int index, string item) + { + throw new NotImplementedException(); + } + + public void RemoveAt(int index) + { + throw new NotImplementedException(); + } + + public string this[int index] + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public void Add(string item) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(string item) + { + throw new NotImplementedException(); + } + + public void CopyTo(string[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public int Count + { + get { throw new NotImplementedException(); } + } + + public bool IsReadOnly + { + get { throw new NotImplementedException(); } + } + + public bool Remove(string item) + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + } + + public class FooTCollection : List, IEnumerable + { + public new IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + } + #endregion + + public override LinqTestOutput ExecuteTest(LinqTestInput input) + { + return LinqTestsCommon.ExecuteTest(input); + } + } +} 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 6e62be7cef..2e478abfd0 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,7 +311,7 @@ public static Func> GenerateTestCosmosData(Func query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); @@ -348,7 +348,7 @@ public static Func> GenerateSerializationTestCosmosData(F } FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions(); + QueryRequestOptions requestOptions = new QueryRequestOptions() { EnableOptimisticDirectExecution = false }; IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions, linqSerializerOptions: linqSerializerOptions); @@ -518,7 +518,7 @@ public static Func> GenerateSimpleCosmosData(Cosmos.Datab } FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions(); + QueryRequestOptions requestOptions = new QueryRequestOptions() { EnableOptimisticDirectExecution = false }; IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); @@ -570,27 +570,7 @@ public static string BuildExceptionMessageForTest(Exception ex) { if (ex is CosmosException cosmosException) { - // 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}"); - } + message.Append($"Status Code: {cosmosException.StatusCode}"); } else if (ex is DocumentClientException documentClientException) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs index 1753d3726f..431081ecb2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs @@ -585,8 +585,9 @@ await this.CreateIngestQueryDeleteAsync( [TestMethod] public async Task TestOdeEnvironmentVariable() { + bool defaultValue = false; QueryRequestOptions options = new QueryRequestOptions(); - Assert.IsTrue(options.EnableOptimisticDirectExecution); + Assert.AreEqual(defaultValue, options.EnableOptimisticDirectExecution); foreach ((string name, string value, bool expectedValue) in new[] { @@ -599,10 +600,10 @@ public async Task TestOdeEnvironmentVariable() ("AZURE_COSMOS_optimistic_direct_execution_enabled", "False", false), ("azure_cosmos_optimistic_direct_execution_enabled", "FALSE", false), ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", "false", false), - ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", string.Empty, true), - (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), "false", true), - (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), null, true), - ("enableode", "false", true) + ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", string.Empty, defaultValue), + (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), "false", defaultValue), + (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), null, defaultValue), + ("enableode", "false", defaultValue) }) { try 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 e0f94e3e64..77da82b247 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 @@ -100,6 +100,95 @@ public void PositiveOptimisticDirectExecutionOutput() }; this.ExecuteTestSuite(testVariations); + } + + [TestMethod] + [Owner("akotalwar")] + public async Task QueryWithODEContinuationTokenShouldUseODEPipelineRegardlessOfODESettings() + { + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Single Partition Key and Ode continuation token", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a", + continuationToken: CosmosElement.Parse( + "{\"OptimisticDirectExecutionToken\":{\"token\":\"{\\\"resourceId\\\":\\\"AQAAAMmFOw8LAAAAAAAAAA==\\\"," + + "\\\"skipCount\\\":1}\", \"range\":{\"min\":\"\",\"max\":\"FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF\"}}}")); + + foreach ((bool enableODE, bool clientForceDisableODEFromBackend) in new[] { (true, true), (true, false), (false, true), (false, false) }) + { + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: 100, + isMultiPartition: false, + expectedContinuationTokenCount: 9, + requiresDist: false, + enableOptimisticDirectExecution: enableODE, + clientDisableOde: clientForceDisableODEFromBackend); + Assert.AreEqual(90, result); + } + } + + [TestMethod] + [Owner("akotalwar")] + public async Task QueryWithoutODEContinuationTokenShouldHonorODESettings() + { + foreach ((bool enableODE, bool clientForceDisableODEFromBackend) in new[] { (true, true), (true, false), (false, true), (false, false) }) + { + int result = await this.GetPipelineAndDrainAsync( + CreateInput( + description: @"Single Partition Key and Ode continuation token", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: enableODE && !clientForceDisableODEFromBackend, + partitionKeyPath: @"/pk", + partitionKeyValue: "a", + continuationToken: null), + numItems: 100, + isMultiPartition: false, + expectedContinuationTokenCount: 10, + requiresDist: false, + enableOptimisticDirectExecution: enableODE, + clientDisableOde: clientForceDisableODEFromBackend); + Assert.AreEqual(100, result); + } + } + + [TestMethod] + public async Task TestQueriesWhichNeverRequireDistribution4() + { + // requiresDist = false + int numItems = 100; + List singlePartitionContainerTestCases = new List() + { + new RequiresDistributionTestCase("SELECT * FROM r", 10, 100), + new RequiresDistributionTestCase("SELECT VALUE r.id FROM r", 0, 10), + new RequiresDistributionTestCase("SELECT * FROM r WHERE r.id > 5", 0, 0), + new RequiresDistributionTestCase("SELECT r.id FROM r JOIN id IN r.id",0, 0), + new RequiresDistributionTestCase("SELECT TOP 5 r.id FROM r ORDER BY r.id", 0, 5), + new RequiresDistributionTestCase("SELECT TOP 5 r.id FROM r WHERE r.id > 5 ORDER BY r.id", 0, 0), + new RequiresDistributionTestCase("SELECT * FROM r OFFSET 5 LIMIT 3", 1, 3), + new RequiresDistributionTestCase("SELECT * FROM r WHERE r.id > 5 OFFSET 5 LIMIT 3", 0, 0) + }; + + foreach (RequiresDistributionTestCase testCase in singlePartitionContainerTestCases) + { + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Queries which will never require distribution", + query: testCase.Query, + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); + + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: numItems, + isMultiPartition: false, + expectedContinuationTokenCount: testCase.ExpectedContinuationTokenCount, + requiresDist: false); + + Assert.AreEqual(testCase.ExpectedDocumentCount, result); + } } [TestMethod] @@ -151,7 +240,7 @@ public void NegativeOptimisticDirectExecutionOutput() public void TestDefaultQueryRequestOptionsSettings() { QueryRequestOptions requestOptions = new QueryRequestOptions(); - Assert.AreEqual(true, requestOptions.EnableOptimisticDirectExecution); + Assert.AreEqual(false, requestOptions.EnableOptimisticDirectExecution); } // test checks that the pipeline can take a query to the backend and returns its associated document(s). @@ -749,17 +838,20 @@ private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestIn while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { TryCatch tryGetPage = queryPipelineStage.Current; - tryGetPage.ThrowIfFailed(); + tryGetPage.ThrowIfFailed(); + bool isODEContinuationToken = input.ContinuationToken != null && + OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(input.ContinuationToken); - if (clientDisableOde || !enableOptimisticDirectExecution) - { - Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + if (!isODEContinuationToken && (clientDisableOde || !enableOptimisticDirectExecution || requiresDist)) + { + Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); } - - if (!clientDisableOde && enableOptimisticDirectExecution && !requiresDist) + else { Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); - } + } + + Assert.AreEqual(input.ExpectedOptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value == TestInjections.PipelineType.OptimisticDirectExecution); documents.AddRange(tryGetPage.Result.Documents); 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 2b68a66ce3..dd548f09d0 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 @@ -274,7 +274,7 @@ public async Task OffsetLimitPageSize() 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: 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); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 100 LIMIT 0", expectedPageSize: 100, 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); From b4395fe484ef1dff453d508a0f3b270f5e33b92c Mon Sep 17 00:00:00 2001 From: "REDMOND\\adityasa" Date: Fri, 19 Apr 2024 17:13:22 -0700 Subject: [PATCH 3/8] Update --- .../CosmosQueryExecutionContextFactory.cs | 7 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 145 ------------------ ...TraceWriterBaselineTests.ReadManyAsync.xml | 30 ---- ...lBaselineTests.TestDistinctTranslation.xml | 28 ++-- ...alBaselineTests.TestGroupByTranslation.xml | 4 +- ...ralBaselineTests.TestThenByTranslation.xml | 6 +- ...misticDirectExecutionQueryBaselineTests.cs | 100 +----------- 7 files changed, 30 insertions(+), 290 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 18b65b574f..0e2877d4d6 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -33,7 +33,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"; @@ -812,6 +812,11 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP return targetRanges.Single(); } + if (isODEContinuationToken) + { + throw new InvalidOperationException("Execution of this query cannot resume due to partition split. Please retry the query."); + } + return null; } 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 1724ef3266..12e27e0576 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 @@ -48,7 +48,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -85,7 +84,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -122,7 +120,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -159,7 +156,6 @@ │ ├── 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 - │ ├── Get Collection Cache(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] @@ -256,10 +252,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -360,10 +352,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -464,10 +452,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -568,10 +552,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -769,7 +749,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -807,7 +786,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -845,7 +823,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -883,7 +860,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -981,10 +957,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1089,10 +1061,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1197,10 +1165,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1305,10 +1269,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1511,7 +1471,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -1548,7 +1507,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -1585,7 +1543,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -1622,7 +1579,6 @@ │ ├── 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 - │ ├── Get Collection Cache(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] @@ -1719,10 +1675,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1823,10 +1775,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1927,10 +1875,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2031,10 +1975,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2233,7 +2173,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -2271,7 +2210,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -2309,7 +2247,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -2347,7 +2284,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -2445,10 +2381,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2553,10 +2485,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2661,10 +2589,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2769,10 +2693,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -2969,7 +2889,6 @@ │ │ │ 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 │ │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds │ │ │ │ ( │ │ │ │ [System Info] @@ -3000,7 +2919,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -3038,7 +2956,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -3076,7 +2993,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -3114,7 +3030,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -3172,10 +3087,6 @@ "name": "Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler", "duration in milliseconds": 0, "children": [ - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -3266,10 +3177,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -3374,10 +3281,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -3482,10 +3385,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -3590,10 +3489,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -3799,7 +3694,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -3836,7 +3730,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -3873,7 +3766,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -3910,7 +3802,6 @@ │ ├── 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 - │ ├── Get Collection Cache(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] @@ -4013,10 +3904,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -4117,10 +4004,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -4221,10 +4104,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -4325,10 +4204,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -4530,7 +4405,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -4568,7 +4442,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -4606,7 +4479,6 @@ │ │ │ ├── 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 - │ │ │ ├── Get Collection Cache(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] @@ -4644,7 +4516,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -4748,10 +4619,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -4856,10 +4723,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -4964,10 +4827,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -5072,10 +4931,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "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 650656ba7c..cf7a291db0 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 @@ -43,7 +43,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -83,7 +82,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -123,7 +121,6 @@ │ ├── 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 - │ ├── Get Collection Cache(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] @@ -228,10 +225,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -366,10 +359,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -504,10 +493,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -628,7 +613,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -668,7 +652,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -708,7 +691,6 @@ │ │ ├── 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 - │ │ ├── Get Collection Cache(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] @@ -816,10 +798,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -954,10 +932,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, @@ -1092,10 +1066,6 @@ "name": "Try Get Overlapping Ranges", "duration in milliseconds": 0 }, - { - "name": "Get Collection Cache", - "duration in milliseconds": 0 - }, { "name": "Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler", "duration in milliseconds": 0, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestDistinctTranslation.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestDistinctTranslation.xml index 8aace2a199..612de0f747 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestDistinctTranslation.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestDistinctTranslation.xml @@ -404,7 +404,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 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.TestGroupByTranslation.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml index 693eb62bb4..48a78d9afb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml @@ -320,7 +320,7 @@ SELECT VALUE root["id"] FROM root GROUP BY root["id"] ORDER BY root["id"] DESC]]> - + @@ -335,7 +335,7 @@ FROM root WHERE (root["id"] != "a") GROUP BY root["id"] ORDER BY root["id"] 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 3fd9cd342d..3e3af720f4 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]]> - + @@ -585,7 +585,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.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 77da82b247..bfd5c35f55 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 @@ -278,51 +278,6 @@ public async Task TestPipelineForBackendDocumentsOnSinglePartitionAsync() Assert.AreEqual(100, documentCountInSinglePartition); } - [TestMethod] - public async Task TestOdeTokenWithSpecializedPipeline() - { - int numItems = 100; - ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( - token: Guid.NewGuid().ToString(), - range: new Documents.Routing.Range("A", "B", true, false)); - - OptimisticDirectExecutionContinuationToken optimisticDirectExecutionContinuationToken = new OptimisticDirectExecutionContinuationToken(parallelContinuationToken); - CosmosElement cosmosElementContinuationToken = OptimisticDirectExecutionContinuationToken.ToCosmosElement(optimisticDirectExecutionContinuationToken); - - OptimisticDirectExecutionTestInput input = CreateInput( - description: @"Single Partition Key and Value Field", - query: "SELECT VALUE COUNT(1) FROM c", - expectedOptimisticDirectExecution: false, - partitionKeyPath: @"/pk", - partitionKeyValue: "a", - continuationToken: cosmosElementContinuationToken); - - DocumentContainer documentContainer = await CreateDocumentContainerAsync(numItems, multiPartition: false); - QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: input.ExpectedOptimisticDirectExecution); - (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); - - IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( - documentContainer, - cosmosQueryContextCore, - inputParameters, - NoOpTrace.Singleton); - - string expectedErrorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + - "If the error persists after that, contact system administrator."; - - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) - { - if (queryPipelineStage.Current.Failed) - { - Assert.IsTrue(queryPipelineStage.Current.InnerMostException.ToString().Contains(expectedErrorMessage)); - return; - } - - Assert.IsFalse(true); - break; - } - } - [TestMethod] public async Task TestQueriesWhichNeverRequireDistribution() { @@ -568,7 +523,7 @@ public async Task TestPipelineForDistributedQueryAsync() OptimisticDirectExecutionTestInput input = CreateInput( description: @"Single Partition Key and Value Field", query: "SELECT AVG(c) FROM c", - expectedOptimisticDirectExecution: false, + expectedOptimisticDirectExecution: true, partitionKeyPath: @"/pk", partitionKeyValue: "a"); @@ -590,7 +545,7 @@ public async Task TestClientDisableOdeLogic() OptimisticDirectExecutionTestInput input = CreateInput( description: @"Single Partition Key and Value Field", query: "SELECT * FROM c", - expectedOptimisticDirectExecution: true, + expectedOptimisticDirectExecution: false, partitionKeyPath: @"/pk", partitionKeyValue: "a"); @@ -604,7 +559,8 @@ public async Task TestClientDisableOdeLogic() clientDisableOde: true); Assert.AreEqual(numItems, result); - + + input.ExpectedOptimisticDirectExecution = true; // Test with ClientDisableOde = false result = await this.GetPipelineAndDrainAsync( input, @@ -617,52 +573,6 @@ public async Task TestClientDisableOdeLogic() Assert.AreEqual(numItems, result); } - [TestMethod] - public async Task TestOdeFlagsWithContinuationToken() - { - ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( - token: Guid.NewGuid().ToString(), - range: new Range("A", "B", true, false)); - - OptimisticDirectExecutionContinuationToken optimisticDirectExecutionContinuationToken = new OptimisticDirectExecutionContinuationToken(parallelContinuationToken); - CosmosElement cosmosElementContinuationToken = OptimisticDirectExecutionContinuationToken.ToCosmosElement(optimisticDirectExecutionContinuationToken); - - OptimisticDirectExecutionTestInput input = CreateInput( - description: @"Single Partition Key and Ode continuation token", - query: "SELECT * FROM c", - expectedOptimisticDirectExecution: true, - partitionKeyPath: @"/pk", - partitionKeyValue: "a", - continuationToken: cosmosElementContinuationToken); - - // All of these cases should throw the same exception message. - await this.ValidateErrorMessageWithModifiedOdeFlags(input, enableOde: true, clientDisableOde: true); - await this.ValidateErrorMessageWithModifiedOdeFlags(input, enableOde: false, clientDisableOde: true); - await this.ValidateErrorMessageWithModifiedOdeFlags(input, enableOde: false, clientDisableOde: false); - } - - private async Task ValidateErrorMessageWithModifiedOdeFlags(OptimisticDirectExecutionTestInput input, bool enableOde, bool clientDisableOde) - { - string expectedErrorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + - "If the error persists after that, contact system administrator."; - try - { - int result = await this.GetPipelineAndDrainAsync( - input, - numItems: 100, - isMultiPartition: false, - expectedContinuationTokenCount: 10, - requiresDist: false, - enableOde, - clientDisableOde); - - Assert.Fail("A MalformedContinuationTokenException was expected in this scenario"); - } - catch (Exception ex) - { - Assert.IsTrue(ex.InnerException.Message.Contains(expectedErrorMessage)); - } - } [TestMethod] public void TestTextDistributionPlanParsingFromStream() @@ -842,7 +752,7 @@ private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestIn bool isODEContinuationToken = input.ContinuationToken != null && OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(input.ContinuationToken); - if (!isODEContinuationToken && (clientDisableOde || !enableOptimisticDirectExecution || requiresDist)) + if (!isODEContinuationToken && (clientDisableOde || !enableOptimisticDirectExecution)) { Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); } From 03dd5fbcabc7cbb8105af059de82015fecb80c71 Mon Sep 17 00:00:00 2001 From: "REDMOND\\adityasa" Date: Fri, 19 Apr 2024 19:02:36 -0700 Subject: [PATCH 4/8] Test fix --- .../LinqGeneralBaselineTests.TestThenByTranslation.xml | 1 + 1 file changed, 1 insertion(+) 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 3e3af720f4..73b8b19748 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 @@ -435,6 +435,7 @@ FROM ( WHERE (p0["GivenName"]["Length"] > 5)) AS v0) AS r0 ORDER BY r0["FamilyId"] ASC, r0["FamilyNumber"] ASC ]]> + From d89934b3f1c6661bf00a53ab7b023a52c210d26e Mon Sep 17 00:00:00 2001 From: "REDMOND\\adityasa" Date: Mon, 22 Apr 2024 19:01:35 -0700 Subject: [PATCH 5/8] Added test for query resumption with ODE token with partition split container (failure case). --- ...misticDirectExecutionQueryBaselineTests.cs | 87 +++++++++++++------ .../Query/Pipeline/FullPipelineTests.cs | 9 +- 2 files changed, 70 insertions(+), 26 deletions(-) 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 bfd5c35f55..d570931c8c 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 @@ -119,15 +119,36 @@ public async Task QueryWithODEContinuationTokenShouldUseODEPipelineRegardlessOfO foreach ((bool enableODE, bool clientForceDisableODEFromBackend) in new[] { (true, true), (true, false), (false, true), (false, false) }) { int result = await this.GetPipelineAndDrainAsync( - input, - numItems: 100, - isMultiPartition: false, - expectedContinuationTokenCount: 9, - requiresDist: false, - enableOptimisticDirectExecution: enableODE, - clientDisableOde: clientForceDisableODEFromBackend); + input, + numItems: 100, + isMultiPartition: false, + expectedContinuationTokenCount: 9, + requiresDist: false, + enableOptimisticDirectExecution: enableODE, + clientDisableOde: clientForceDisableODEFromBackend); Assert.AreEqual(90, result); } + + input.PartitionKeyValue = Cosmos.PartitionKey.None; + foreach ((bool enableODE, bool clientForceDisableODEFromBackend) in new[] { (true, true), (true, false), (false, true), (false, false) }) + { + try + { + await this.GetPipelineAndDrainAsync( + input, + numItems: 100, + isMultiPartition: true, + expectedContinuationTokenCount: 0, + requiresDist: false, + enableOptimisticDirectExecution: enableODE, + clientDisableOde: clientForceDisableODEFromBackend); + Assert.Fail("Expected exception. Received none."); + } + catch(InvalidOperationException ex) + { + Assert.IsTrue(ex.ToString().Contains("Execution of this query cannot resume due to partition split. Please retry the query.")); + } + } } [TestMethod] @@ -500,8 +521,15 @@ public async Task TestQueryValidityCheckWithODEAsync() public async Task TestPipelineForGoneExceptionOnSingleAndMultiplePartitionAsync() { Assert.IsTrue(await ExecuteGoneExceptionOnODEPipeline(isMultiPartition: false)); - - Assert.IsTrue(await ExecuteGoneExceptionOnODEPipeline(isMultiPartition: true)); + + // ISSUE-TODO-adityasa-2024/4/22 - Reenable this test. + // At the time of authoring this test, the TestCosmosQueryClient always simulated a single partition container scenario by returning a single 00-FF range + // in the GetTargetPartitionKeyRangesAsync call, regardless of whether test asks a MultiPartition container or not. + // As a result tests did not really simulate the multi-partition scenario, as far as CosmosQueryClient is concerned. + // While GetTargetPartitionKeyRangesAsync is now fixed to honor the container properties, GetCachedContainerQueryPropertiesAsync is still not fixed. + // Specifically it does not honor if the partition key is specified for query (container is multi-partition, but query is single partition). + // As a result, for following test, it does not use ODE pipeline which breaks the assertion in ExecuteGoneExceptionOnODEPipeline method. + // Assert.IsTrue(await ExecuteGoneExceptionOnODEPipeline(isMultiPartition: true)); } // test to check if failing fallback pipeline is handled properly @@ -742,7 +770,7 @@ private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestIn int continuationTokenCount = 0; List documents = new List(); QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution); - DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: isMultiPartition, requiresDist: requiresDist); + DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: isMultiPartition, requiresDist: requiresDist); IQueryPipelineStage queryPipelineStage = CreateOdePipeline(input, inMemoryCollection, queryRequestOptions, clientDisableOde); while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) @@ -809,7 +837,8 @@ internal static Tuple Get private static IQueryPipelineStage CreateOdePipeline(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions, bool clientDisableOde = false) { - (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions, clientDisableOde); + List containerRanges = documentContainer.GetFeedRangesAsync(NoOpTrace.Singleton, cancellationToken: default).Result; + (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions, containerRanges, clientDisableOde); IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( documentContainer, cosmosQueryContextCore, @@ -949,8 +978,9 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect // gets DocumentContainer IMonadicDocumentContainer monadicDocumentContainer = new InMemoryContainer(input.PartitionKeyDefinition); DocumentContainer documentContainer = new DocumentContainer(monadicDocumentContainer); - QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); - (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); + QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); + List containerRanges = documentContainer.GetFeedRangesAsync(NoOpTrace.Singleton, cancellationToken: default).Result; + (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions, containerRanges); IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( documentContainer, cosmosQueryContextCore, @@ -974,7 +1004,7 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect return new OptimisticDirectExecutionTestOutput(input.ExpectedOptimisticDirectExecution); } - private static Tuple CreateInputParamsAndQueryContext(OptimisticDirectExecutionTestInput input, QueryRequestOptions queryRequestOptions, bool clientDisableOde = false) + private static Tuple CreateInputParamsAndQueryContext(OptimisticDirectExecutionTestInput input, QueryRequestOptions queryRequestOptions, List containerRanges, bool clientDisableOde = false) { CosmosSerializerCore serializerCore = new(); using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(new SqlQuerySpec(input.Query), Documents.ResourceType.Document)); @@ -994,12 +1024,22 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect executionEnvironment: null, returnResultsInDeterministicOrder: null, enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, - testInjections: queryRequestOptions.TestSettings); + testInjections: queryRequestOptions.TestSettings); + + List targetPkRanges = new (); + foreach(FeedRangeEpk feedRangeEpk in containerRanges) + { + targetPkRanges.Add(new PartitionKeyRange + { + MinInclusive = feedRangeEpk.Range.Min, + MaxExclusive = feedRangeEpk.Range.Max, + }); + } string databaseId = "db1234"; string resourceLink = $"dbs/{databaseId}/colls"; CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( - client: new TestCosmosQueryClient(queryPartitionProvider), + client: new TestCosmosQueryClient(queryPartitionProvider, targetPkRanges), resourceTypeEnum: Documents.ResourceType.Document, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), @@ -1223,11 +1263,13 @@ public override void SerializeAsXml(XmlWriter xmlWriter) internal class TestCosmosQueryClient : CosmosQueryClient { - private readonly QueryPartitionProvider queryPartitionProvider; + private readonly QueryPartitionProvider queryPartitionProvider; + private readonly IReadOnlyList targetPartitionKeyRanges; - public TestCosmosQueryClient(QueryPartitionProvider queryPartitionProvider) + public TestCosmosQueryClient(QueryPartitionProvider queryPartitionProvider, IEnumerable targetPartitionKeyRanges) { - this.queryPartitionProvider = queryPartitionProvider; + this.queryPartitionProvider = queryPartitionProvider; + this.targetPartitionKeyRanges = targetPartitionKeyRanges.ToList(); } public override Action OnExecuteScalarQueryCallback => throw new NotImplementedException(); @@ -1285,12 +1327,7 @@ public override Task> GetTargetPartitionKeyRangeByFeedRa public override Task> GetTargetPartitionKeyRangesAsync(string resourceLink, string collectionResourceId, IReadOnlyList> providedRanges, bool forceRefresh, ITrace trace) { - return Task.FromResult(new List{new PartitionKeyRange() - { - MinInclusive = PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, - MaxExclusive = PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey - } - }); + return Task.FromResult(this.targetPartitionKeyRanges.ToList()); } public override Task> TryGetOverlappingRangesAsync(string collectionResourceId, Range range, bool forceRefresh = false) 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 dd548f09d0..c8ca339530 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 @@ -394,8 +394,15 @@ private async Task TestPageSizeAsync(string query, int expectedPageSize, int exp } ); + List targetPartitionKeyRanges = new (){ + new PartitionKeyRange() + { + MinInclusive = "", + MaxExclusive = "FF" + } + }; CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( - client: new TestCosmosQueryClient(GetQueryPartitionProvider()), + client: new TestCosmosQueryClient(GetQueryPartitionProvider(), targetPartitionKeyRanges), resourceTypeEnum: Documents.ResourceType.Document, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), From 7842b788080dd0506acae62f2561e5776d998c37 Mon Sep 17 00:00:00 2001 From: "REDMOND\\adityasa" Date: Mon, 22 Apr 2024 19:10:27 -0700 Subject: [PATCH 6/8] Update. --- .../Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs | 2 +- .../Linq/LinqCleanupTests.cs | 2 +- .../Query/OptimisticDirectExecutionQueryBaselineTests.cs | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 0e2877d4d6..ba071725fe 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -814,7 +814,7 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP if (isODEContinuationToken) { - throw new InvalidOperationException("Execution of this query cannot resume due to partition split. Please retry the query."); + throw new InvalidOperationException("Execution of this query cannot resume using ODE Continuation token due to partition split. Please restart the query without continuation token."); } return null; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqCleanupTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqCleanupTests.cs index d7f553f577..6e16380f90 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqCleanupTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqCleanupTests.cs @@ -20,7 +20,7 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests [TestClass] public class LinqCleanupTests { - //[Ignore] + [Ignore] [TestMethod] public async Task CleanupLinqTestDatabases() { 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 d570931c8c..4ae11728a5 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 @@ -103,7 +103,6 @@ public void PositiveOptimisticDirectExecutionOutput() } [TestMethod] - [Owner("akotalwar")] public async Task QueryWithODEContinuationTokenShouldUseODEPipelineRegardlessOfODESettings() { OptimisticDirectExecutionTestInput input = CreateInput( @@ -146,13 +145,12 @@ await this.GetPipelineAndDrainAsync( } catch(InvalidOperationException ex) { - Assert.IsTrue(ex.ToString().Contains("Execution of this query cannot resume due to partition split. Please retry the query.")); + Assert.IsTrue(ex.ToString().Contains("Execution of this query cannot resume using ODE Continuation token due to partition split. Please restart the query without continuation token.")); } } } [TestMethod] - [Owner("akotalwar")] public async Task QueryWithoutODEContinuationTokenShouldHonorODESettings() { foreach ((bool enableODE, bool clientForceDisableODEFromBackend) in new[] { (true, true), (true, false), (false, true), (false, false) }) From dbfaf3bc4a1acf071ef635fc0a98917f7a4bac31 Mon Sep 17 00:00:00 2001 From: "REDMOND\\adityasa" Date: Mon, 22 Apr 2024 20:47:00 -0700 Subject: [PATCH 7/8] Update Benchmark --- .../Contracts/BenchmarkResults.json | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) 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 3b597d3367..e11a346aff 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 @@ -1,9 +1,9 @@ { - "MasterKeyAuthorizationBenchmark.CreateSignatureGeneration;": 534, + "MasterKeyAuthorizationBenchmark.CreateSignatureGeneration;": 554, "MasterKeyAuthorizationBenchmark.ReadSignatureGeneration;": 544, - "MockedItemBenchmark.CreateItem;[Type=OfT]": 36356, - "MockedItemBenchmark.CreateItem;[Type=OfTCustom]": 36362, - "MockedItemBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 36359.5, + "MockedItemBenchmark.CreateItem;[Type=OfT]": 37261.25, + "MockedItemBenchmark.CreateItem;[Type=OfTCustom]": 37285, + "MockedItemBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 37280.25, "MockedItemBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 58900.5, "MockedItemBenchmark.CreateItem;[Type=Stream]": 25212.75, "MockedItemBenchmark.DeleteItemExists;[Type=OfT]": 33015.25, @@ -11,15 +11,15 @@ "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=OfT]": 43035, + "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTCustom]": 43030.5, + "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 43034.25, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithDiagnosticsToString]": 63338, "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=OfT]": 13293777.25, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTCustom]": 13298034.75, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithClientTelemetryEnabled]": 13298733.75, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithDiagnosticsToString]": 13517039.75, "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=Stream]": 5920952, "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfT]": 2241814, "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTCustom]": 2241810, @@ -30,25 +30,25 @@ "MockedItemBenchmark.ReadFeed;[Type=OfTCustom]": 555716, "MockedItemBenchmark.ReadFeed;[Type=OfTWithClientTelemetryEnabled]": 550898.25, "MockedItemBenchmark.ReadFeed;[Type=OfTWithDiagnosticsToString]": 573734.5, - "MockedItemBenchmark.ReadFeed;[Type=Stream]": 33434, - "MockedItemBenchmark.ReadItemExists;[Type=OfT]": 33630.5, - "MockedItemBenchmark.ReadItemExists;[Type=OfTCustom]": 33636.25, - "MockedItemBenchmark.ReadItemExists;[Type=OfTWithClientTelemetryEnabled]": 33627.75, - "MockedItemBenchmark.ReadItemExists;[Type=OfTWithDiagnosticsToString]": 55044, - "MockedItemBenchmark.ReadItemExists;[Type=Stream]": 26018.25, + "MockedItemBenchmark.ReadFeed;[Type=Stream]": 34192, + "MockedItemBenchmark.ReadItemExists;[Type=OfT]": 34509.75, + "MockedItemBenchmark.ReadItemExists;[Type=OfTCustom]": 34516, + "MockedItemBenchmark.ReadItemExists;[Type=OfTWithClientTelemetryEnabled]": 34515.5, + "MockedItemBenchmark.ReadItemExists;[Type=OfTWithDiagnosticsToString]": 56524.5, + "MockedItemBenchmark.ReadItemExists;[Type=Stream]": 26752.5, "MockedItemBenchmark.ReadItemNotExists;[Type=OfT]": 43489.25, "MockedItemBenchmark.ReadItemNotExists;[Type=OfTCustom]": 43490, "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 43489.25, "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithDiagnosticsToString]": 64764.75, - "MockedItemBenchmark.ReadItemNotExists;[Type=Stream]": 39044, - "MockedItemBenchmark.UpdateItem;[Type=OfT]": 36591, - "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": 36594.25, - "MockedItemBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 36587.25, + "MockedItemBenchmark.ReadItemNotExists;[Type=Stream]": 39876, + "MockedItemBenchmark.UpdateItem;[Type=OfT]": 37505.5, + "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": 37496.25, + "MockedItemBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 37516.5, "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=OfT]": 37487.5, + "MockedItemBenchmark.UpsertItem;[Type=OfTCustom]": 37486, + "MockedItemBenchmark.UpsertItem;[Type=OfTWithClientTelemetryEnabled]": 37490, "MockedItemBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 59613, "MockedItemBenchmark.UpsertItem;[Type=Stream]": 25445.5, "MockedItemBulkBenchmark.CreateItem;[Type=OfT]": 1196168, From 86ab8a2fb8a0f09dbc639ddaaa5d73f8fdd94698 Mon Sep 17 00:00:00 2001 From: "REDMOND\\adityasa" Date: Tue, 23 Apr 2024 14:11:17 -0700 Subject: [PATCH 8/8] Addressed comments. --- .../Core/Pipeline/CosmosQueryExecutionContextFactory.cs | 8 ++++---- .../Query/OptimisticDirectExecutionQueryBaselineTests.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index ba071725fe..7676270416 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -758,13 +758,13 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP ITrace trace) { bool clientDisableOptimisticDirectExecution = await cosmosQueryContext.QueryClient.GetClientDisableOptimisticDirectExecutionAsync(); - bool isODEContinuationToken = inputParameters.InitialUserContinuationToken != null && + bool isOdeContinuationToken = inputParameters.InitialUserContinuationToken != null && OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken); // Use the Ode code path only if ClientDisableOptimisticDirectExecution is false and EnableOptimisticDirectExecution is true // But allow the query using ODE pipeline if it's earlier roundtrips are made using ODE continuation token. if ((clientDisableOptimisticDirectExecution || !inputParameters.EnableOptimisticDirectExecution) && - !isODEContinuationToken) + !isOdeContinuationToken) { return null; } @@ -812,9 +812,9 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP return targetRanges.Single(); } - if (isODEContinuationToken) + if (isOdeContinuationToken) { - throw new InvalidOperationException("Execution of this query cannot resume using ODE Continuation token due to partition split. Please restart the query without continuation token."); + throw new InvalidOperationException("Execution of this query cannot resume using Optimistic Direct Execution continuation token due to partition split. Please restart the query without the continuation token."); } return null; 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 4ae11728a5..d723a57df7 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 @@ -145,7 +145,7 @@ await this.GetPipelineAndDrainAsync( } catch(InvalidOperationException ex) { - Assert.IsTrue(ex.ToString().Contains("Execution of this query cannot resume using ODE Continuation token due to partition split. Please restart the query without continuation token.")); + Assert.IsTrue(ex.ToString().Contains("Execution of this query cannot resume using Optimistic Direct Execution continuation token due to partition split. Please restart the query without the continuation token.")); } } }