static async Task ImplementationAsync(Container container, IReadOnlyList <CosmosObject> documents) { Assert.AreEqual(0, (await QueryTestsBase.RunQueryAsync( container, @"SELECT * FROM Root r WHERE false", new QueryRequestOptions() { MaxConcurrency = 1, })).Count); object[] keys = new object[] { "A", 5, Undefined.Value }; for (int i = 0; i < keys.Length; ++i) { List <string> expected = documents .Skip(i * 3) .Take(3) .Select(doc => ((CosmosString)doc["id"]).Value.ToString()) .ToList(); string expectedResult = string.Join(",", expected); // Order-by List <string> expectedCopy = new List <string>(expected); expectedCopy.Reverse(); string expectedOrderByResult = string.Join(",", expectedCopy); List <(string, string)> queries = new List <(string, string)>() { ($@"SELECT * FROM Root r WHERE r.id IN (""{expected[0]}"", ""{expected[1]}"", ""{expected[2]}"")", expectedResult), (@"SELECT * FROM Root r WHERE r.prop BETWEEN 1 AND 3", expectedResult), (@"SELECT VALUE r FROM Root r JOIN c IN r.shortArray WHERE c.a BETWEEN 5 and 7", expectedResult), ($@"SELECT TOP 10 * FROM Root r WHERE r.id IN (""{expected[0]}"", ""{expected[1]}"", ""{expected[2]}"")", expectedResult), (@"SELECT TOP 10 * FROM Root r WHERE r.prop BETWEEN 1 AND 3", expectedResult), (@"SELECT TOP 10 VALUE r FROM Root r JOIN c IN r.shortArray WHERE c.a BETWEEN 5 and 7", expectedResult), ($@"SELECT * FROM Root r WHERE r.id IN (""{expected[0]}"", ""{expected[1]}"", ""{expected[2]}"") ORDER BY r.prop", expectedOrderByResult), (@"SELECT * FROM Root r WHERE r.prop BETWEEN 1 AND 3 ORDER BY r.prop", expectedOrderByResult), (@"SELECT DISTINCT * FROM Root r WHERE r.prop BETWEEN 1 AND 3 ORDER BY r.prop", expectedOrderByResult), (@"SELECT VALUE r FROM Root r JOIN c IN r.shortArray WHERE c.a BETWEEN 5 and 7 ORDER BY r.prop", expectedOrderByResult), }; if (i < keys.Length - 1) { string key = keys[i] is string? "'" + keys[i].ToString() + "'" : keys[i].ToString(); queries.Add((string.Format(CultureInfo.InvariantCulture, @"SELECT * FROM Root r WHERE r.key = {0} ORDER BY r.prop", key), expectedOrderByResult)); } foreach ((string, string)queryAndExpectedResult in queries) { FeedIterator <Document> resultSetIterator = container.GetItemQueryIterator <Document>( queryText: queryAndExpectedResult.Item1, requestOptions: new QueryRequestOptions() { MaxItemCount = 1, PartitionKey = new Cosmos.PartitionKey(keys[i]), }); List <Document> result = new List <Document>(); while (resultSetIterator.HasMoreResults) { result.AddRange(await resultSetIterator.ReadNextAsync()); } string resultDocIds = string.Join(",", result.Select(doc => doc.Id)); Assert.AreEqual( queryAndExpectedResult.Item2, resultDocIds, $"Query: {queryAndExpectedResult.Item1} with partition key: {keys[i]} failed."); } } }
public async Task TestQueryPlanGatewayAndServiceInteropAsync() { int seed = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; uint numberOfDocuments = 100; QueryOracleUtil util = new QueryOracle2(seed); IEnumerable <string> inputDocuments = util.GetDocuments(numberOfDocuments); await this.CreateIngestQueryDeleteAsync( ConnectionModes.Direct, CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, inputDocuments, ImplementationAsync); async Task ImplementationAsync(Container container, IReadOnlyList <CosmosObject> documents) { ContainerCore containerCore = (ContainerInlineCore)container; foreach (bool isGatewayQueryPlan in new bool[] { true, false }) { MockCosmosQueryClient cosmosQueryClientCore = new MockCosmosQueryClient( containerCore.ClientContext, containerCore, isGatewayQueryPlan); ContainerCore containerWithForcedPlan = new ContainerCore( containerCore.ClientContext, (DatabaseCore)containerCore.Database, containerCore.Id, cosmosQueryClientCore); int numOfQueries = 0; foreach (int maxDegreeOfParallelism in new int[] { 1, 100 }) { foreach (int maxItemCount in new int[] { 10, 100 }) { numOfQueries++; QueryRequestOptions feedOptions = new QueryRequestOptions { MaxBufferedItemCount = 7000, MaxConcurrency = maxDegreeOfParallelism, MaxItemCount = maxItemCount, }; List <CosmosElement> queryResults = await QueryTestsBase.RunQueryAsync( containerWithForcedPlan, "SELECT * FROM c ORDER BY c._ts", feedOptions); Assert.AreEqual(documents.Count(), queryResults.Count); } } if (isGatewayQueryPlan) { Assert.IsTrue(cosmosQueryClientCore.QueryPlanCalls > numOfQueries); } else { Assert.AreEqual(0, cosmosQueryClientCore.QueryPlanCalls, "ServiceInterop mode should not be calling gateway plan retriever"); } } } }
public async Task TestAggregateFunctionsAsync() { AggregateTestArgs args = new AggregateTestArgs( numberOfDocumentsDifferentPartitionKey: 43, numberOfDocsWithSamePartitionKey: 37, partitionKey: "key", uniquePartitionKey: "uniquePartitionKey", field: "field", values: new List <object>() { false, true, "abc", "cdfg", "opqrs", "ttttttt", "xyz" }); List <string> documents = new List <string>(args.NumberOfDocumentsDifferentPartitionKey + args.NumberOfDocsWithSamePartitionKey); foreach (object val in args.Values) { Document doc; doc = new Document(); doc.SetPropertyValue(args.PartitionKey, val); doc.SetPropertyValue("id", Guid.NewGuid().ToString()); documents.Add(doc.ToString()); } for (int i = 0; i < args.NumberOfDocsWithSamePartitionKey; ++i) { Document doc = new Document(); doc.SetPropertyValue(args.PartitionKey, args.UniquePartitionKey); documents.Add(doc.ToString()); } Random random = new Random(); for (int i = 0; i < args.NumberOfDocumentsDifferentPartitionKey; ++i) { Document doc = new Document(); doc.SetPropertyValue(args.PartitionKey, random.NextDouble()); documents.Add(doc.ToString()); } await this.CreateIngestQueryDeleteAsync <AggregateTestArgs>( ConnectionModes.Direct | ConnectionModes.Gateway, CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, documents, ImplementationAsync, args, "/" + args.PartitionKey); async Task ImplementationAsync( Container container, IReadOnlyList <CosmosObject> inputDocuments, AggregateTestArgs aggregateTestArgs) { IReadOnlyList <CosmosObject> documentsWherePkIsANumber = inputDocuments .Where(doc => { return(double.TryParse( doc[aggregateTestArgs.PartitionKey].ToString(), out double result)); }) .ToList(); double numberSum = documentsWherePkIsANumber .Sum(doc => { if (!doc.TryGetValue(aggregateTestArgs.PartitionKey, out CosmosNumber number)) { Assert.Fail("Failed to get partition key from document"); } return(Number64.ToDouble(number.Value)); }); double count = documentsWherePkIsANumber.Count(); AggregateQueryArguments[] aggregateQueryArgumentsList = new AggregateQueryArguments[] { new AggregateQueryArguments( aggregateOperator: "AVG", expectedValue: CosmosNumber64.Create(numberSum / count), predicate: $"IS_NUMBER(r.{aggregateTestArgs.PartitionKey})"), new AggregateQueryArguments( aggregateOperator: "AVG", expectedValue: null, predicate: "true"), new AggregateQueryArguments( aggregateOperator: "COUNT", expectedValue: CosmosNumber64.Create(documents.Count()), predicate: "true"), new AggregateQueryArguments( aggregateOperator: "MAX", expectedValue: CosmosString.Create("xyz"), predicate: "true"), new AggregateQueryArguments( aggregateOperator: "MIN", expectedValue: CosmosBoolean.Create(false), predicate: "true"), new AggregateQueryArguments( aggregateOperator: "SUM", expectedValue: CosmosNumber64.Create(numberSum), predicate: $"IS_NUMBER(r.{aggregateTestArgs.PartitionKey})"), new AggregateQueryArguments( aggregateOperator: "SUM", expectedValue: null, predicate: $"true"), }; foreach (int maxDoP in new[] { 0, 10 }) { foreach (AggregateQueryArguments argument in aggregateQueryArgumentsList) { string[] queryFormats = new[] { "SELECT VALUE {0}(r.{1}) FROM r WHERE {2}", "SELECT VALUE {0}(r.{1}) FROM r WHERE {2} ORDER BY r.{1}" }; foreach (string queryFormat in queryFormats) { string query = string.Format( CultureInfo.InvariantCulture, queryFormat, argument.AggregateOperator, aggregateTestArgs.PartitionKey, argument.Predicate); string message = string.Format( CultureInfo.InvariantCulture, "query: {0}, data: {1}", query, JsonConvert.SerializeObject(argument)); List <CosmosElement> items = await QueryTestsBase.RunQueryAsync( container, query, new QueryRequestOptions() { MaxConcurrency = maxDoP, }); if (argument.ExpectedValue == null) { Assert.AreEqual(0, items.Count, message); } else { Assert.AreEqual(1, items.Count, message); CosmosElement expected = argument.ExpectedValue; CosmosElement actual = items.Single(); if ((expected is CosmosNumber expectedNumber) && (actual is CosmosNumber actualNumber)) { Assert.AreEqual(Number64.ToDouble(expectedNumber.Value), Number64.ToDouble(actualNumber.Value), .01); }
public async Task TestPassthroughQueryAsync() { string[] inputDocs = new[] { @"{""id"":""documentId1"",""key"":""A"",""prop"":3,""shortArray"":[{""a"":5}]}", @"{""id"":""documentId2"",""key"":""A"",""prop"":2,""shortArray"":[{""a"":6}]}", @"{""id"":""documentId3"",""key"":""A"",""prop"":1,""shortArray"":[{""a"":7}]}", @"{""id"":""documentId4"",""key"":5,""prop"":3,""shortArray"":[{""a"":5}]}", @"{""id"":""documentId5"",""key"":5,""prop"":2,""shortArray"":[{""a"":6}]}", @"{""id"":""documentId6"",""key"":5,""prop"":1,""shortArray"":[{""a"":7}]}", @"{""id"":""documentId10"",""prop"":3,""shortArray"":[{""a"":5}]}", @"{""id"":""documentId11"",""prop"":2,""shortArray"":[{""a"":6}]}", @"{""id"":""documentId12"",""prop"":1,""shortArray"":[{""a"":7}]}", }; await this.CreateIngestQueryDeleteAsync( ConnectionModes.Direct, CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, inputDocs, ImplementationAsync, "/key"); async Task ImplementationAsync(Container container, IReadOnlyList <CosmosObject> documents) { foreach (int maxDegreeOfParallelism in new int[] { 1, 100 }) { foreach (int maxItemCount in new int[] { 10, 100 }) { QueryRequestOptions feedOptions = new QueryRequestOptions { MaxBufferedItemCount = 7000, MaxConcurrency = maxDegreeOfParallelism, MaxItemCount = maxItemCount, }; foreach (string query in new string[] { "SELECT * FROM c WHERE c.key = 5", "SELECT * FROM c WHERE c.key = 5 ORDER BY c._ts", }) { feedOptions.TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, responseStats: new TestInjections.ResponseStats()); List <CosmosElement> queryResults = await QueryTestsBase.RunQueryAsync( container, query, feedOptions); Assert.IsTrue(feedOptions.TestSettings.Stats.PipelineType.HasValue); Assert.AreEqual(TestInjections.PipelineType.Passthrough, feedOptions.TestSettings.Stats.PipelineType.Value); Assert.AreEqual( 3, queryResults.Count, $"query: {query} failed with {nameof(maxDegreeOfParallelism)}: {maxDegreeOfParallelism}, {nameof(maxItemCount)}: {maxItemCount}"); } { feedOptions.TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, responseStats: new TestInjections.ResponseStats()); string query = "SELECT TOP 2 c.id FROM c WHERE c.key = 5"; List <CosmosElement> queryResults = await QueryTestsBase.RunQueryAsync( container, query, feedOptions); Assert.IsTrue(feedOptions.TestSettings.Stats.PipelineType.HasValue); Assert.AreEqual(TestInjections.PipelineType.Passthrough, feedOptions.TestSettings.Stats.PipelineType.Value); Assert.AreEqual( 2, queryResults.Count, $"query: {query} failed with {nameof(maxDegreeOfParallelism)}: {maxDegreeOfParallelism}, {nameof(maxItemCount)}: {maxItemCount}"); } { feedOptions.TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, responseStats: new TestInjections.ResponseStats()); string query = "SELECT c.id FROM c WHERE c.key = 5 OFFSET 1 LIMIT 1"; List <CosmosElement> queryResults = await QueryTestsBase.RunQueryAsync( container, query, feedOptions); Assert.IsTrue(feedOptions.TestSettings.Stats.PipelineType.HasValue); Assert.AreEqual(TestInjections.PipelineType.Passthrough, feedOptions.TestSettings.Stats.PipelineType.Value); Assert.AreEqual( 1, queryResults.Count, $"query: {query} failed with {nameof(maxDegreeOfParallelism)}: {maxDegreeOfParallelism}, {nameof(maxItemCount)}: {maxItemCount}"); } { feedOptions.TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, responseStats: new TestInjections.ResponseStats()); string query = "SELECT VALUE COUNT(1) FROM c WHERE c.key = 5"; List <CosmosElement> queryResults = await QueryTestsBase.RunQueryAsync( container, query, feedOptions); Assert.IsTrue(feedOptions.TestSettings.Stats.PipelineType.HasValue); Assert.AreEqual(TestInjections.PipelineType.Specialized, feedOptions.TestSettings.Stats.PipelineType.Value); Assert.AreEqual( 1, queryResults.Count, $"query: {query} failed with {nameof(maxDegreeOfParallelism)}: {maxDegreeOfParallelism}, {nameof(maxItemCount)}: {maxItemCount}"); Assert.AreEqual( 3, Number64.ToLong((queryResults.First() as CosmosNumber64).GetValue()), $"query: {query} failed with {nameof(maxDegreeOfParallelism)}: {maxDegreeOfParallelism}, {nameof(maxItemCount)}: {maxItemCount}"); } { feedOptions.TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, responseStats: new TestInjections.ResponseStats()); string query = "SELECT VALUE c.key FROM c WHERE c.key = 5 GROUP BY c.key"; List <CosmosElement> queryResults = await QueryTestsBase.RunQueryCombinationsAsync( container, query, feedOptions, QueryDrainingMode.HoldState | QueryDrainingMode.CosmosElementContinuationToken); Assert.IsTrue(feedOptions.TestSettings.Stats.PipelineType.HasValue); Assert.AreEqual(TestInjections.PipelineType.Specialized, feedOptions.TestSettings.Stats.PipelineType.Value); Assert.AreEqual( 1, queryResults.Count, $"query: {query} failed with {nameof(maxDegreeOfParallelism)}: {maxDegreeOfParallelism}, {nameof(maxItemCount)}: {maxItemCount}"); } { feedOptions.TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, responseStats: new TestInjections.ResponseStats()); string query = "SELECT DISTINCT VALUE c.key FROM c WHERE c.key = 5"; List <CosmosElement> queryResults = await QueryTestsBase.RunQueryCombinationsAsync( container, query, feedOptions, QueryDrainingMode.HoldState | QueryDrainingMode.CosmosElementContinuationToken); Assert.IsTrue(feedOptions.TestSettings.Stats.PipelineType.HasValue); Assert.AreEqual(TestInjections.PipelineType.Specialized, feedOptions.TestSettings.Stats.PipelineType.Value); Assert.AreEqual( 1, queryResults.Count, $"query: {query} failed with {nameof(maxDegreeOfParallelism)}: {maxDegreeOfParallelism}, {nameof(maxItemCount)}: {maxItemCount}"); } } } } }
public async Task TestQueryWithPartitionKeyAsync() { string[] inputDocs = new[] { @"{""id"":""documentId1"",""key"":""A"",""prop"":3,""shortArray"":[{""a"":5}]}", @"{""id"":""documentId2"",""key"":""A"",""prop"":2,""shortArray"":[{""a"":6}]}", @"{""id"":""documentId3"",""key"":""A"",""prop"":1,""shortArray"":[{""a"":7}]}", @"{""id"":""documentId4"",""key"":5,""prop"":3,""shortArray"":[{""a"":5}]}", @"{""id"":""documentId5"",""key"":5,""prop"":2,""shortArray"":[{""a"":6}]}", @"{""id"":""documentId6"",""key"":5,""prop"":1,""shortArray"":[{""a"":7}]}", @"{""id"":""documentId10"",""prop"":3,""shortArray"":[{""a"":5}]}", @"{""id"":""documentId11"",""prop"":2,""shortArray"":[{""a"":6}]}", @"{""id"":""documentId12"",""prop"":1,""shortArray"":[{""a"":7}]}", }; await this.CreateIngestQueryDeleteAsync( ConnectionModes.Direct | ConnectionModes.Gateway, CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, inputDocs, ImplementationAsync, "/key"); async Task ImplementationAsync(Container container, IReadOnlyList <CosmosObject> documents) { Assert.AreEqual(0, (await QueryTestsBase.RunQueryAsync( container, @"SELECT * FROM Root r WHERE false", new QueryRequestOptions() { MaxConcurrency = 1, })).Count); object[] keys = new object[] { "A", 5, Undefined.Value }; for (int i = 0; i < keys.Length; ++i) { List <string> expected = documents .Skip(i * 3) .Take(3) .Select(doc => ((CosmosString)doc["id"]).Value) .ToList(); string expectedResult = string.Join(",", expected); // Order-by List <string> expectedCopy = new List <string>(expected); expectedCopy.Reverse(); string expectedOrderByResult = string.Join(",", expectedCopy); List <(string, string)> queries = new List <(string, string)>() { ($@"SELECT * FROM Root r WHERE r.id IN (""{expected[0]}"", ""{expected[1]}"", ""{expected[2]}"")", expectedResult), (@"SELECT * FROM Root r WHERE r.prop BETWEEN 1 AND 3", expectedResult), (@"SELECT VALUE r FROM Root r JOIN c IN r.shortArray WHERE c.a BETWEEN 5 and 7", expectedResult), ($@"SELECT TOP 10 * FROM Root r WHERE r.id IN (""{expected[0]}"", ""{expected[1]}"", ""{expected[2]}"")", expectedResult), (@"SELECT TOP 10 * FROM Root r WHERE r.prop BETWEEN 1 AND 3", expectedResult), (@"SELECT TOP 10 VALUE r FROM Root r JOIN c IN r.shortArray WHERE c.a BETWEEN 5 and 7", expectedResult), ($@"SELECT * FROM Root r WHERE r.id IN (""{expected[0]}"", ""{expected[1]}"", ""{expected[2]}"") ORDER BY r.prop", expectedOrderByResult), (@"SELECT * FROM Root r WHERE r.prop BETWEEN 1 AND 3 ORDER BY r.prop", expectedOrderByResult), (@"SELECT VALUE r FROM Root r JOIN c IN r.shortArray WHERE c.a BETWEEN 5 and 7 ORDER BY r.prop", expectedOrderByResult), }; if (i < keys.Length - 1) { string key; if (keys[i] is string) { key = "'" + keys[i].ToString() + "'"; } else { key = keys[i].ToString(); } queries.Add((string.Format(CultureInfo.InvariantCulture, @"SELECT * FROM Root r WHERE r.key = {0} ORDER BY r.prop", key), expectedOrderByResult)); } foreach ((string, string)queryAndExpectedResult in queries) { FeedIterator <Document> resultSetIterator = container.GetItemQueryIterator <Document>( queryText: queryAndExpectedResult.Item1, requestOptions: new QueryRequestOptions() { MaxItemCount = 1, PartitionKey = new Cosmos.PartitionKey(keys[i]), }); List <Document> result = new List <Document>(); while (resultSetIterator.HasMoreResults) { result.AddRange(await resultSetIterator.ReadNextAsync()); } string resultDocIds = string.Join(",", result.Select(doc => doc.Id)); Assert.AreEqual(queryAndExpectedResult.Item2, resultDocIds); } } } }
public async Task TestQueryCrossPartitionOffsetLimitAsync() { int seed = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; uint numberOfDocuments = 10; Random rand = new Random(seed); List <Person> people = new List <Person>(); for (int i = 0; i < numberOfDocuments; i++) { // Generate random people Person person = PersonGenerator.GetRandomPerson(rand); for (int j = 0; j < rand.Next(0, 4); j++) { // Force an exact duplicate people.Add(person); } } List <string> documentsToInsert = new List <string>(); // Shuffle them so that they end up in different pages. people = people.OrderBy((person) => Guid.NewGuid()).ToList(); foreach (Person person in people) { documentsToInsert.Add(JsonConvert.SerializeObject(person)); } await this.CreateIngestQueryDeleteAsync( ConnectionModes.Direct, CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, documentsToInsert, ImplementationAsync, "/id"); async Task ImplementationAsync( Container container, IReadOnlyList <CosmosObject> documents) { foreach (int offsetCount in new int[] { 0, 1, 10, documents.Count }) { foreach (int limitCount in new int[] { 0, 1, 10, documents.Count }) { foreach (int pageSize in new int[] { 1, 10, documents.Count }) { string query = $@" SELECT VALUE c.guid FROM c ORDER BY c.guid OFFSET {offsetCount} LIMIT {limitCount}"; QueryRequestOptions queryRequestOptions = new QueryRequestOptions() { MaxItemCount = pageSize, MaxBufferedItemCount = 1000, MaxConcurrency = 2 }; IEnumerable <CosmosElement> expectedResults = documents; // ORDER BY expectedResults = expectedResults.OrderBy(x => (x as CosmosObject)["guid"].ToString(), StringComparer.Ordinal); // SELECT VALUE c.name expectedResults = expectedResults.Select(document => (document as CosmosObject)["guid"]); // SKIP TAKE expectedResults = expectedResults.Skip(offsetCount); expectedResults = expectedResults.Take(limitCount); List <CosmosElement> queryResults = await QueryTestsBase.RunQueryAsync( container, query, queryRequestOptions : queryRequestOptions); Assert.IsTrue( expectedResults.SequenceEqual(queryResults), $@" {query} (without continuations) didn't match expected: {JsonConvert.SerializeObject(expectedResults)} actual: {JsonConvert.SerializeObject(queryResults)}"); } } } } }