public static (QueryResponseCore queryResponse, IList <ToDoItem> items) Create( string itemIdPrefix, string continuationToken, string collectionRid, int itemCount = 50) { // Use -1 to represent a split response if (itemCount == QueryResponseMessageFactory.SPLIT) { return(CreateSplitResponse(collectionRid), new List <ToDoItem>().AsReadOnly()); } IList <ToDoItem> items = ToDoItem.CreateItems(itemCount, itemIdPrefix); MemoryStream memoryStream = (MemoryStream)cosmosSerializer.ToStream <IList <ToDoItem> >(items); long responseLengthBytes = memoryStream.Length; IJsonNavigator jsonNavigator = JsonNavigator.Create(memoryStream.ToArray()); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); CosmosArray cosmosArray = CosmosArray.Create(jsonNavigator, jsonNavigatorNode); QueryResponseCore message = QueryResponseCore.CreateSuccess( result: cosmosArray, continuationToken: continuationToken, disallowContinuationTokenMessage: null, activityId: Guid.NewGuid().ToString(), requestCharge: 42, queryMetricsText: null, queryMetrics: new Dictionary <string, QueryMetrics>(), requestStatistics: null, responseLengthBytes: responseLengthBytes); return(message, items); }
public void SqlArrayCreateScalarExpressionTest() { SqlArrayCreateScalarExpression inner = SqlArrayCreateScalarExpression.Create( SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(1)), SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(2)), SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(3))); AssertEvaluation( CosmosArray.Create( new List <CosmosElement>() { CosmosNumber64.Create(1), CosmosNumber64.Create(2), CosmosNumber64.Create(3), }), inner); SqlArrayCreateScalarExpression outer = SqlArrayCreateScalarExpression.Create(inner); AssertEvaluation( CosmosArray.Create( new List <CosmosElement>() { CosmosArray.Create( new List <CosmosElement>() { CosmosNumber64.Create(1), CosmosNumber64.Create(2), CosmosNumber64.Create(3), }) }), outer); }
public static (QueryResponse queryResponse, IList <ToDoItem> items) Create( string itemIdPrefix, string continuationToken, string collectionRid, int itemCount = 50) { // Use -1 to represent a split response if (itemCount == QueryResponseMessageFactory.SPLIT) { return(CreateSplitResponse(collectionRid), new List <ToDoItem>().AsReadOnly()); } IList <ToDoItem> items = ToDoItem.CreateItems(itemCount, itemIdPrefix); MemoryStream memoryStream = (MemoryStream)cosmosSerializer.ToStream <IList <ToDoItem> >(items); long responseLengthBytes = memoryStream.Length; IJsonNavigator jsonNavigator = JsonNavigator.Create(memoryStream.ToArray()); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); CosmosArray cosmosArray = CosmosArray.Create(jsonNavigator, jsonNavigatorNode); Headers headers = new Headers(); headers.ContinuationToken = continuationToken; headers.ActivityId = Guid.NewGuid().ToString(); QueryResponse message = QueryResponse.CreateSuccess( result: cosmosArray, count: itemCount, responseHeaders: CosmosQueryResponseMessageHeaders.ConvertToQueryHeaders(headers, ResourceType.Document, collectionRid), responseLengthBytes: responseLengthBytes); return(message, items); }
public void ArrayOrderMatters() { CosmosArray cosmosArray = (CosmosArray)Elements.ArrayWithItems; CosmosArray cosmosArrayReversed = CosmosArray.Create(cosmosArray.Reverse()); Assert.AreNotEqual(cosmosArray, cosmosArrayReversed); }
public static CosmosElement ToCosmosElement(OrderByContinuationToken orderByContinuationToken) { CosmosElement compositeContinuationToken = ParallelContinuationToken.ToCosmosElement(orderByContinuationToken.ParallelContinuationToken); List <CosmosElement> orderByItemsRaw = new List <CosmosElement>(); foreach (OrderByItem orderByItem in orderByContinuationToken.OrderByItems) { orderByItemsRaw.Add(OrderByItem.ToCosmosElement(orderByItem)); } CosmosArray orderByItems = CosmosArray.Create(orderByItemsRaw); CosmosElement filter = orderByContinuationToken.Filter == null?CosmosNull.Create() : (CosmosElement)CosmosString.Create(orderByContinuationToken.Filter); CosmosObject cosmosObject = CosmosObject.Create( new Dictionary <string, CosmosElement>() { { PropertyNames.CompositeToken, compositeContinuationToken }, { PropertyNames.OrderByItems, orderByItems }, { PropertyNames.Rid, CosmosString.Create(orderByContinuationToken.Rid) }, { PropertyNames.SkipCount, CosmosNumber64.Create(orderByContinuationToken.SkipCount) }, { PropertyNames.Filter, filter }, }); return(cosmosObject); }
public void ARRAY_CONCAT() { // ARRAY_CONCAT(["apples"], ["strawberries"], ["bananas"]) AssertEvaluation( CosmosArray.Create(CosmosString.Create("apples"), CosmosString.Create("strawberries"), CosmosString.Create("bananas")), SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.ArrayConcat, JTokenToSqlScalarExpression.Convert(new JArray("apples")), JTokenToSqlScalarExpression.Convert(new JArray("strawberries")), JTokenToSqlScalarExpression.Convert(new JArray("bananas")))); // ARRAY_CONCAT("apples", ["strawberries"], ["bananas"]) AssertEvaluation( Undefined, SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.ArrayConcat, JTokenToSqlScalarExpression.Convert("apples"), JTokenToSqlScalarExpression.Convert(new JArray("strawberries")), JTokenToSqlScalarExpression.Convert(new JArray("bananas")))); // ARRAY_CONCAT(undefined, ["strawberries"], ["bananas"]) AssertEvaluation( Undefined, SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.ArrayConcat, SqlLiteralScalarExpression.SqlUndefinedLiteralScalarExpression, JTokenToSqlScalarExpression.Convert(new JArray("strawberries")), JTokenToSqlScalarExpression.Convert(new JArray("bananas")))); }
public static QueryResponseCore CreateQueryResponse( IList <ToDoItem> items, bool isOrderByQuery, string continuationToken, string collectionRid) { MemoryStream memoryStream; string json; if (isOrderByQuery) { memoryStream = SerializeForOrderByQuery(items); using (StreamReader sr = new StreamReader(SerializeForOrderByQuery(items))) { json = sr.ReadToEnd(); } } else { memoryStream = (MemoryStream)MockCosmosUtil.Serializer.ToStream <IList <ToDoItem> >(items); } long responseLengthBytes = memoryStream.Length; IJsonNavigator jsonNavigator = JsonNavigator.Create(memoryStream.ToArray()); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); CosmosArray cosmosArray = CosmosArray.Create(jsonNavigator, jsonNavigatorNode); CosmosDiagnosticsContext diagnosticsContext = new CosmosDiagnosticsContextCore(); diagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics( activityId: Guid.NewGuid().ToString(), statusCode: HttpStatusCode.OK, subStatusCode: SubStatusCodes.Unknown, responseTimeUtc: DateTime.UtcNow, requestCharge: 4, errorMessage: null, method: HttpMethod.Post, requestUri: "http://localhost.com", requestSessionToken: null, responseSessionToken: null)); IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>() { new QueryPageDiagnostics( Guid.NewGuid(), "0", "SomeQueryMetricText", "SomeIndexUtilText", diagnosticsContext) }; QueryResponseCore message = QueryResponseCore.CreateSuccess( result: cosmosArray, requestCharge: 4, activityId: Guid.NewGuid().ToString(), responseLengthBytes: responseLengthBytes, disallowContinuationTokenMessage: null, continuationToken: continuationToken); return(message); }
public async Task TestDistinct_CosmosElementContinuationTokenAsync() { async Task ImplemenationAsync(Container container, IReadOnlyList <CosmosObject> documents) { // Run the ordered distinct query through the continuation api, should result in the same set // since the previous hash is passed in the continuation token. foreach (string query in new string[] { "SELECT {0} VALUE c.age FROM c ORDER BY c.age", "SELECT {0} VALUE c.name FROM c ORDER BY c.name", "SELECT {0} VALUE c.name from c", "SELECT {0} VALUE c.age from c", "SELECT {0} VALUE c.mixedTypeField from c", "SELECT {0} TOP 2147483647 VALUE c.city from c", "SELECT {0} VALUE c.age from c ORDER BY c.name", }) { string queryWithoutDistinct = string.Format(query, ""); MockDistinctMap documentsSeen = new MockDistinctMap(); List <CosmosElement> documentsFromWithoutDistinct = await QueryTestsBase.RunQueryCombinationsAsync( container, queryWithoutDistinct, new QueryRequestOptions() { MaxConcurrency = 10, MaxItemCount = 100, }, QueryDrainingMode.HoldState | QueryDrainingMode.CosmosElementContinuationToken); documentsFromWithoutDistinct = documentsFromWithoutDistinct .Where(document => documentsSeen.Add(document, out UInt128 hash)) .ToList(); foreach (int pageSize in new int[] { 1, 10, 100 }) { string queryWithDistinct = string.Format(query, "DISTINCT"); List <CosmosElement> documentsFromWithDistinct = await QueryTestsBase.RunQueryCombinationsAsync( container, queryWithDistinct, new QueryRequestOptions() { MaxConcurrency = 10, MaxItemCount = pageSize }, QueryDrainingMode.HoldState | QueryDrainingMode.CosmosElementContinuationToken); Assert.AreEqual( expected: CosmosArray.Create(documentsFromWithDistinct), actual: CosmosArray.Create(documentsFromWithoutDistinct), message: $"Documents didn't match for {queryWithDistinct} on a Partitioned container"); } } } await this.TestQueryDistinctBaseAsync(ImplemenationAsync); }
public static (QueryResponseCore queryResponse, IList <ToDoItem> items) Create( string itemIdPrefix, string continuationToken, string collectionRid, int itemCount = 50) { // Use -1 to represent a split response if (itemCount == QueryResponseMessageFactory.SPLIT) { return(CreateSplitResponse(collectionRid), new List <ToDoItem>().AsReadOnly()); } IList <ToDoItem> items = ToDoItem.CreateItems(itemCount, itemIdPrefix); MemoryStream memoryStream = (MemoryStream)MockCosmosUtil.Serializer.ToStream <IList <ToDoItem> >(items); long responseLengthBytes = memoryStream.Length; IJsonNavigator jsonNavigator = JsonNavigator.Create(memoryStream.ToArray()); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); CosmosArray cosmosArray = CosmosArray.Create(jsonNavigator, jsonNavigatorNode); double requestCharge = 42; string activityId = Guid.NewGuid().ToString(); CosmosDiagnosticsContext diagnosticsContext = new CosmosDiagnosticsContextCore(); diagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics( activityId: Guid.NewGuid().ToString(), statusCode: HttpStatusCode.OK, subStatusCode: SubStatusCodes.Unknown, responseTimeUtc: DateTime.UtcNow, requestCharge: requestCharge, errorMessage: null, method: HttpMethod.Post, requestUri: "http://localhost.com", requestSessionToken: null, responseSessionToken: null)); IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>() { new QueryPageDiagnostics( Guid.NewGuid(), "0", "SomeQueryMetricText", "SomeIndexUtilText", diagnosticsContext) }; QueryResponseCore message = QueryResponseCore.CreateSuccess( result: cosmosArray, continuationToken: continuationToken, disallowContinuationTokenMessage: null, activityId: activityId, requestCharge: requestCharge, responseLengthBytes: responseLengthBytes); return(message, items); }
public async ValueTask <bool> MoveNextAsync() { this.cancellationToken.ThrowIfCancellationRequested(); if (!await this.crossPartitionEnumerator.MoveNextAsync()) { this.Current = default; return(false); } TryCatch <CrossPartitionPage <ReadFeedPage, ReadFeedState> > monadicCrossPartitionPage = this.crossPartitionEnumerator.Current; if (monadicCrossPartitionPage.Failed) { this.Current = TryCatch <ReadFeedPage> .FromException(monadicCrossPartitionPage.Exception); return(true); } CrossPartitionPage <ReadFeedPage, ReadFeedState> crossPartitionPage = monadicCrossPartitionPage.Result; ReadFeedPage backendPage = crossPartitionPage.Page; CrossPartitionState <ReadFeedState> crossPartitionState = crossPartitionPage.State; ReadFeedState state; if (crossPartitionState != null) { IReadOnlyList <(FeedRangeInternal, ReadFeedState)> rangesAndStates = crossPartitionState.Value; List <CosmosElement> changeFeedContinuationTokens = new List <CosmosElement>(); foreach ((FeedRangeInternal range, ReadFeedState readFeedState) in rangesAndStates) { this.cancellationToken.ThrowIfCancellationRequested(); ReadFeedContinuationToken readFeedContinuationToken = new ReadFeedContinuationToken( range, readFeedState); CosmosElement cosmosElementChangeFeedContinuationToken = ReadFeedContinuationToken.ToCosmosElement(readFeedContinuationToken); changeFeedContinuationTokens.Add(cosmosElementChangeFeedContinuationToken); } CosmosArray cosmosElementTokens = CosmosArray.Create(changeFeedContinuationTokens); state = new ReadFeedState(cosmosElementTokens); } else { state = null; } ReadFeedPage compositePage = new ReadFeedPage(backendPage.Content, backendPage.RequestCharge, backendPage.ActivityId, backendPage.Diagnostics, state); this.Current = TryCatch <ReadFeedPage> .FromResult(compositePage); return(true); }
public CosmosElement ToCosmosElement() { List <CosmosElement> elements = new List <CosmosElement>(); foreach (FeedRangeState <ReadFeedState> readFeedFeedRangeState in this.FeedRangeStates.Span) { elements.Add(ReadFeedFeedRangeStateSerializer.ToCosmosElement(readFeedFeedRangeState)); } return(CosmosArray.Create(elements)); }
public void SqlArrayScalarExpressionTest() { CosmosObject tag = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["name"] = CosmosString.Create("asdf") }); CosmosObject tags = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["tags"] = CosmosArray.Create(new List <CosmosElement>() { tag }), ["_rid"] = CosmosString.Create("AYIMAMmFOw8YAAAAAAAAAA==") }); CosmosObject tagsWrapped = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["c"] = tags, ["_rid"] = CosmosString.Create("AYIMAMmFOw8YAAAAAAAAAA==") }); // ARRAY(SELECT VALUE t.name FROM t in c.tags) SqlArrayScalarExpression arrayScalarExpression = SqlArrayScalarExpression.Create( SqlQuery.Create( SqlSelectClause.Create( SqlSelectValueSpec.Create( TestUtils.CreatePathExpression("t", "name"))), SqlFromClause.Create( SqlArrayIteratorCollectionExpression.Create( SqlIdentifier.Create("t"), SqlInputPathCollection.Create( SqlIdentifier.Create("c"), SqlStringPathExpression.Create( null, SqlStringLiteral.Create("tags"))))), whereClause: null, groupByClause: null, orderByClause: null, offsetLimitClause: null)); CosmosArray tagNames = CosmosArray.Create(new List <CosmosElement>() { CosmosString.Create("asdf") }); AssertEvaluation(tagNames, arrayScalarExpression, tagsWrapped); }
public override CosmosElement Visit( SqlArrayScalarExpression scalarExpression, CosmosElement document) { // Only run on the current document since the subquery is always correlated. IEnumerable <CosmosElement> subqueryResults = SqlInterpreter.ExecuteQuery( new CosmosElement[] { document }, scalarExpression.SqlQuery); List <CosmosElement> arrayScalarResult = new List <CosmosElement>(); foreach (CosmosElement subQueryResult in subqueryResults) { arrayScalarResult.Add(subQueryResult); } return(CosmosArray.Create(subqueryResults)); }
public override CosmosElement Visit( SqlArrayCreateScalarExpression scalarExpression, CosmosElement document) { List <CosmosElement> arrayItems = new List <CosmosElement>(); foreach (SqlScalarExpression item in scalarExpression.Items) { CosmosElement value = item.Accept(this, document); if (value != Undefined) { arrayItems.Add(value); } } return(CosmosArray.Create(arrayItems)); }
public static QueryResponse CreateQueryResponse( IList <ToDoItem> items, bool isOrderByQuery, string continuationToken, string collectionRid) { MemoryStream memoryStream; string json; if (isOrderByQuery) { memoryStream = SerializeForOrderByQuery(items); using (StreamReader sr = new StreamReader(SerializeForOrderByQuery(items))) { json = sr.ReadToEnd(); } } else { memoryStream = (MemoryStream)cosmosSerializer.ToStream <IList <ToDoItem> >(items); } long responseLengthBytes = memoryStream.Length; IJsonNavigator jsonNavigator = JsonNavigator.Create(memoryStream.ToArray()); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); CosmosArray cosmosArray = CosmosArray.Create(jsonNavigator, jsonNavigatorNode); Headers headers = new Headers(); headers.ContinuationToken = continuationToken; headers.ActivityId = Guid.NewGuid().ToString(); QueryResponse message = QueryResponse.CreateSuccess( result: cosmosArray, count: items.Count, responseHeaders: CosmosQueryResponseMessageHeaders.ConvertToQueryHeaders(headers, ResourceType.Document, collectionRid), responseLengthBytes: responseLengthBytes); return(message); }
public void SqlMemberIndexerScalarExpressionTest() { CosmosObject alice = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["name"] = CosmosString.Create("Alice") }); CosmosObject bob = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["name"] = CosmosString.Create("Bob") }); CosmosObject document = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["name"] = CosmosString.Create("John"), ["kids"] = CosmosArray.Create(new List <CosmosElement>() { alice, bob }) }); CosmosObject wrappedDocument = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["c"] = document }); AssertEvaluation(CosmosString.Create("John"), TestUtils.CreatePathExpression("c", "name"), wrappedDocument); AssertEvaluation(alice, TestUtils.CreatePathExpression("c", "kids", 0), wrappedDocument); AssertEvaluation(CosmosString.Create("Alice"), TestUtils.CreatePathExpression("c", "kids", 0, "name"), wrappedDocument); // Indexing by a path that does not exist. AssertEvaluation(Undefined, TestUtils.CreatePathExpression("c", "NotARealPath"), wrappedDocument); // Indexing an object with a number. AssertEvaluation(Undefined, TestUtils.CreatePathExpression("c", 5), wrappedDocument); // Indexing an array with a string. AssertEvaluation(Undefined, TestUtils.CreatePathExpression("c", "kids", "invalid string index", "name"), wrappedDocument); }
public static QueryResponseCore CreateQueryResponse( IList <ToDoItem> items, bool isOrderByQuery, string continuationToken, string collectionRid) { MemoryStream memoryStream; string json; if (isOrderByQuery) { memoryStream = SerializeForOrderByQuery(items); using (StreamReader sr = new StreamReader(SerializeForOrderByQuery(items))) { json = sr.ReadToEnd(); } } else { memoryStream = (MemoryStream)cosmosSerializer.ToStream <IList <ToDoItem> >(items); } long responseLengthBytes = memoryStream.Length; IJsonNavigator jsonNavigator = JsonNavigator.Create(memoryStream.ToArray()); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); CosmosArray cosmosArray = CosmosArray.Create(jsonNavigator, jsonNavigatorNode); QueryResponseCore message = QueryResponseCore.CreateSuccess( result: cosmosArray, requestCharge: 4, activityId: Guid.NewGuid().ToString(), queryMetricsText: null, queryMetrics: null, requestStatistics: null, responseLengthBytes: responseLengthBytes, disallowContinuationTokenMessage: null, continuationToken: continuationToken); return(message); }
private static IEnumerable <Input> GenerateWrappedInputs(params Type[] types) { foreach (Type type in types) { foreach (FieldInfo p in type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) { object v = p.GetValue(null); yield return(new Input((CosmosElement)v)); yield return(new Input(CosmosArray.Create(new List <CosmosElement>() { (CosmosElement)v }))); yield return(new Input(CosmosObject.Create(new Dictionary <string, CosmosElement>() { { "prop", (CosmosElement)v } }))); } } }
public override CosmosElement GetCosmosElementContinuationToken() { Dictionary <string, CosmosElement> dictionary = new Dictionary <string, CosmosElement>() { { UnorderdDistinctMap.PropertyNames.Numbers, CosmosArray.Create(this.numbers.Select(x => CosmosNumber64.Create(x))) }, { UnorderdDistinctMap.PropertyNames.StringsLength4, CosmosArray.Create(this.stringsLength4.Select(x => CosmosUInt32.Create(x))) }, { UnorderdDistinctMap.PropertyNames.StringsLength8, CosmosArray.Create(this.stringsLength8.Select(x => CosmosInt64.Create((long)x))) }, { UnorderdDistinctMap.PropertyNames.StringsLength16, CosmosArray.Create(this.stringsLength16.Select(x => CosmosBinary.Create(UInt128.ToByteArray(x)))) }, { UnorderdDistinctMap.PropertyNames.StringsLength16Plus, CosmosArray.Create(this.stringsLength16Plus.Select(x => CosmosBinary.Create(UInt128.ToByteArray(x)))) }, { UnorderdDistinctMap.PropertyNames.Arrays, CosmosArray.Create(this.arrays.Select(x => CosmosBinary.Create(UInt128.ToByteArray(x)))) }, { UnorderdDistinctMap.PropertyNames.Object, CosmosArray.Create(this.objects.Select(x => CosmosBinary.Create(UInt128.ToByteArray(x)))) }, { UnorderdDistinctMap.PropertyNames.SimpleValues, CosmosString.Create(this.simpleValues.ToString()) } }; return(CosmosObject.Create(dictionary)); }
public async ValueTask <bool> MoveNextAsync() { this.cancellationToken.ThrowIfCancellationRequested(); if (this.bufferedException.HasValue) { this.Current = this.bufferedException.Value; this.bufferedException = null; return(true); } if (!await this.crossPartitionEnumerator.MoveNextAsync()) { throw new InvalidOperationException("ChangeFeed should always have a next page."); } TryCatch <CrossPartitionPage <ChangeFeedPage, ChangeFeedState> > monadicCrossPartitionPage = this.crossPartitionEnumerator.Current; if (monadicCrossPartitionPage.Failed) { this.Current = TryCatch <ChangeFeedPage> .FromException(monadicCrossPartitionPage.Exception); return(true); } CrossPartitionPage <ChangeFeedPage, ChangeFeedState> crossPartitionPage = monadicCrossPartitionPage.Result; ChangeFeedPage backendPage = crossPartitionPage.Page; if (backendPage is ChangeFeedNotModifiedPage) { // Keep draining the cross partition enumerator until // We get a non 304 page or we loop back to the same range or run into an exception FeedRangeInternal originalRange = this.crossPartitionEnumerator.CurrentRange; double totalRequestCharge = backendPage.RequestCharge; do { if (!await this.crossPartitionEnumerator.MoveNextAsync()) { throw new InvalidOperationException("ChangeFeed should always have a next page."); } monadicCrossPartitionPage = this.crossPartitionEnumerator.Current; if (monadicCrossPartitionPage.Failed) { // Buffer the exception, since we need to return the request charge so far. this.bufferedException = TryCatch <ChangeFeedPage> .FromException(monadicCrossPartitionPage.Exception); } else { crossPartitionPage = monadicCrossPartitionPage.Result; backendPage = crossPartitionPage.Page; totalRequestCharge += backendPage.RequestCharge; } }while (!(backendPage is ChangeFeedSuccessPage || this.crossPartitionEnumerator.CurrentRange.Equals(originalRange) || this.bufferedException.HasValue)); // Create a page with the aggregated request charge if (backendPage is ChangeFeedSuccessPage changeFeedSuccessPage) { backendPage = new ChangeFeedSuccessPage( changeFeedSuccessPage.Content, totalRequestCharge, changeFeedSuccessPage.ActivityId, changeFeedSuccessPage.State); } else { backendPage = new ChangeFeedNotModifiedPage( totalRequestCharge, backendPage.ActivityId, backendPage.State); } } CrossPartitionState <ChangeFeedState> crossPartitionState = crossPartitionPage.State; List <CosmosElement> changeFeedContinuationTokens = new List <CosmosElement>(); foreach ((FeedRangeInternal range, ChangeFeedState state)rangeAndState in crossPartitionState.Value) { ChangeFeedContinuationToken changeFeedContinuationToken = new ChangeFeedContinuationToken( rangeAndState.range, rangeAndState.state); CosmosElement cosmosElementChangeFeedContinuationToken = ChangeFeedContinuationToken.ToCosmosElement(changeFeedContinuationToken); changeFeedContinuationTokens.Add(cosmosElementChangeFeedContinuationToken); } CosmosArray cosmosElementTokens = CosmosArray.Create(changeFeedContinuationTokens); ChangeFeedState state = ChangeFeedState.Continuation(cosmosElementTokens); ChangeFeedPage compositePage; if (backendPage is ChangeFeedSuccessPage successPage) { compositePage = new ChangeFeedSuccessPage( successPage.Content, successPage.RequestCharge, successPage.ActivityId, state); } else { compositePage = new ChangeFeedNotModifiedPage( backendPage.RequestCharge, backendPage.ActivityId, state); } this.Current = TryCatch <ChangeFeedPage> .FromResult(compositePage); return(true); }
internal void GetDeserializedObjectsFromQueryResponseTest(JsonSerializationFormat jsonSerializationFormat) { // Constants to use for vertex document property key/values const string vertex1Id = "v_0"; const string vertex2Id = "v_1"; const string vertex1Label = "l_0"; const string vertex2Label = "l_1"; const string vertex1PkValue = "pk_0"; const string vertex2PkValue = "pk_1"; const string property1Name = "p_0"; const string vertex1Property1Value = "v_0_p_0_v_0"; const string vertex2Property1Value = "v_1_p_0_v_0"; const string property2Name = "p_1"; const double vertex1Property2Value = 12.34; const long vertex2Property2Value = 5678; // Compose two initial vertex documents using eager CosmosElements CosmosObject initialVertex1EagerObject = this.CreateVertexDocument( vertex1Id, vertex1Label, GremlinScenarioTests.PartitionKeyPropertyName, vertex1PkValue, new Tuple <string, IEnumerable <object> >[] { Tuple.Create <string, IEnumerable <object> >(property1Name, new object[] { vertex1Property1Value }), Tuple.Create <string, IEnumerable <object> >(property2Name, new object[] { vertex1Property2Value }), }); CosmosObject initialVertex2EagerObject = this.CreateVertexDocument( vertex2Id, vertex2Label, GremlinScenarioTests.PartitionKeyPropertyName, vertex2PkValue, new Tuple <string, IEnumerable <object> >[] { Tuple.Create <string, IEnumerable <object> >(property1Name, new object[] { vertex2Property1Value }), Tuple.Create <string, IEnumerable <object> >(property2Name, new object[] { vertex2Property2Value }), }); // Serialize the initial vertex object into a document using the specified serialization format IJsonWriter jsonWriter = JsonWriter.Create(jsonSerializationFormat); initialVertex1EagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> vertex1JsonWriterResult = jsonWriter.GetResult(); Assert.IsTrue(vertex1JsonWriterResult.Length > 0, "IJsonWriter result data is empty."); jsonWriter = JsonWriter.Create(jsonSerializationFormat); initialVertex2EagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> vertex2JsonWriterResult = jsonWriter.GetResult(); Assert.IsTrue(vertex2JsonWriterResult.Length > 0, "IJsonWriter result data is empty."); // Navigate into the serialized vertex documents using lazy CosmosElements CosmosElement vertex1LazyObject = CosmosElement.CreateFromBuffer(vertex1JsonWriterResult); CosmosElement vertex2LazyObject = CosmosElement.CreateFromBuffer(vertex2JsonWriterResult); // Create a dynamically-typed QueryResponse backed by the vertex document CosmosElements CosmosArray vertexArray = CosmosArray.Create( new CosmosElement[] { vertex1LazyObject, vertex2LazyObject, }); QueryResponse queryResponse = QueryResponse.CreateSuccess( vertexArray, count: 2, responseLengthBytes: vertex1JsonWriterResult.Length + vertex2JsonWriterResult.Length, serializationOptions: null, responseHeaders: CosmosQueryResponseMessageHeaders.ConvertToQueryHeaders( sourceHeaders: null, resourceType: ResourceType.Document, containerRid: GremlinScenarioTests.CreateRandomString(10)), diagnostics: null); QueryResponse <dynamic> cosmosElementQueryResponse = QueryResponse <dynamic> .CreateResponse <dynamic>( queryResponse, MockCosmosUtil.Serializer); // Assert that other objects (anything besides the lazy CosmosElements that we created earlier) are deserialized // from the backing CosmosElement contents rather than being directly returned as CosmosElements List <dynamic> responseCosmosElements = new List <dynamic>(cosmosElementQueryResponse.Resource); Assert.AreEqual(vertexArray.Count, responseCosmosElements.Count); Assert.AreNotSame(vertex1LazyObject, responseCosmosElements[0]); Assert.AreNotSame(vertex2LazyObject, responseCosmosElements[1]); }
internal void DeserializeModifyAndSerializeVertexDocumentTest(JsonSerializationFormat jsonSerializationFormat) { // Constants to use for vertex document property key/values const string idName = "id"; const string idValue = "v_0"; const string pkValue = "pk_0"; const string labelName = "label"; const string labelValue = "l_0"; const string property1Name = "p_0"; const string property1Value1Id = "3648bdcc-5113-43f8-86dd-c19fe793a2f8"; const string property1Value1 = "p_0_v_0"; const string property1Value2Id = "7546f541-a003-4e69-a25c-608372ed1321"; const long property1Value2 = 1234; const string property2Name = "p_1"; const string property2Value1Id = "b119c62a-82a2-48b2-b293-9963fa99fbe2"; const double property2Value1 = 34.56; const string property3Name = "p_2"; const string property3Value1Id = "98d27280-70ee-4edd-8461-7633a328539a"; const bool property3Value1 = true; const string property4Name = "p_3"; const string property4Value1Id = "f9bfcc22-221a-4c92-b5b9-be53cdedb092"; const string property4Value1 = "p_3_v_0"; // Compose the initial vertex document using eager CosmosElements Dictionary <string, CosmosElement> initialVertexDocumentProperties = new Dictionary <string, CosmosElement>() { { idName, CosmosString.Create(idValue) }, { GremlinScenarioTests.PartitionKeyPropertyName, CosmosString.Create(pkValue) }, { labelName, CosmosString.Create(labelValue) }, { property1Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property1Value1Id), CosmosString.Create(property1Value1)), } ) }, { property2Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property2Value1Id), CosmosNumber64.Create(property2Value1)), } ) }, { property3Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property3Value1Id), CosmosBoolean.Create(property3Value1)), } ) }, }; CosmosObject initialVertexEagerObject = CosmosObject.Create(initialVertexDocumentProperties); // Serialize the initial vertex object into a document using the specified serialization format IJsonWriter jsonWriter = JsonWriter.Create(jsonSerializationFormat); initialVertexEagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> initialJsonWriterResult = jsonWriter.GetResult(); Assert.IsTrue(initialJsonWriterResult.Length > 0, "IJsonWriter result data is empty."); // Navigate into the serialized vertex document using lazy CosmosElements CosmosElement rootLazyElement = CosmosElement.CreateFromBuffer(initialJsonWriterResult); // Root vertex document object CosmosObject vertexLazyObject = rootLazyElement as CosmosObject; Assert.IsNotNull(vertexLazyObject, $"Vertex document root is not {nameof(CosmosObject)}."); Assert.AreEqual(initialVertexDocumentProperties.Count, vertexLazyObject.Count); CosmosString idLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, idName); CosmosString pkLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, GremlinScenarioTests.PartitionKeyPropertyName); CosmosString labelLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, labelName); CosmosArray property2Array = this.GetAndAssertObjectProperty <CosmosArray>(vertexLazyObject, property2Name); // Compose a new vertex document using a combination of lazy and eager CosmosElements Dictionary <string, CosmosElement> modifiedVertexDocumentProperties = new Dictionary <string, CosmosElement>() { { idName, idLazyString }, { GremlinScenarioTests.PartitionKeyPropertyName, pkLazyString }, { labelName, labelLazyString }, // Property 1 is modified with a new value { property1Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property1Value2Id), CosmosNumber64.Create(property1Value2)), } ) }, // Property 2 is unmodified { property2Name, property2Array }, // Property 3 is deleted // Property 4 is newly added { property4Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property4Value1Id), CosmosString.Create(property4Value1)), } ) }, }; CosmosObject modifiedVertexEagerObject = CosmosObject.Create(modifiedVertexDocumentProperties); // Serialize the modified vertex object into a document using the specified serialization format jsonWriter = JsonWriter.Create(jsonSerializationFormat); modifiedVertexEagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> modifiedJsonWriterResult = jsonWriter.GetResult(); Assert.IsTrue(modifiedJsonWriterResult.Length > 0, "IJsonWriter result data is empty."); // Compose an expected vertex document using eager CosmosElements Dictionary <string, CosmosElement> expectedVertexDocumentProperties = new Dictionary <string, CosmosElement>() { { idName, CosmosString.Create(idValue) }, { GremlinScenarioTests.PartitionKeyPropertyName, CosmosString.Create(pkValue) }, { labelName, CosmosString.Create(labelValue) }, { property1Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property1Value2Id), CosmosNumber64.Create(property1Value2)), } ) }, { property2Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property2Value1Id), CosmosNumber64.Create(property2Value1)), } ) }, { property4Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property4Value1Id), CosmosString.Create(property4Value1)), } ) }, }; CosmosObject expectedVertexEagerObject = CosmosObject.Create(expectedVertexDocumentProperties); // Serialize the initial vertex object into a document using the specified serialization format jsonWriter = JsonWriter.Create(jsonSerializationFormat); expectedVertexEagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> expectedJsonWriterResult = jsonWriter.GetResult(); Assert.IsTrue(expectedJsonWriterResult.Length > 0, "IJsonWriter result data is empty."); // Verify that the modified serialized document matches the expected serialized document Assert.IsTrue(modifiedJsonWriterResult.Span.SequenceEqual(expectedJsonWriterResult.Span)); }
internal void SerializeAndDeserializeVertexDocumentTest(JsonSerializationFormat jsonSerializationFormat) { // Constants to use for vertex document property key/values const string idName = "id"; const string idValue = "v_0"; const string pkValue = "pk_0"; const string labelName = "label"; const string labelValue = "l_0"; const string boolName = "myBool"; const string boolId = "3648bdcc-5113-43f8-86dd-c19fe793a2f8"; const bool boolValue = true; const string intName = "myInteger"; const string intId = "7546f541-a003-4e69-a25c-608372ed1321"; const int intValue = 12345; const string longId = "b119c62a-82a2-48b2-b293-9963fa99fbe2"; const long longValue = 67890L; const string floatName = "myFloatingPoint"; const string floatId = "98d27280-70ee-4edd-8461-7633a328539a"; const float floatValue = 123.4f; const string doubleId = "f9bfcc22-221a-4c92-b5b9-be53cdedb092"; const double doubleValue = 56.78; const string stringName = "myString"; const string stringId = "6bb8ae5b-19ca-450e-b369-922a34c02729"; const string stringValue = "str_0"; const string metaProperty0Name = "myMetaProperty0"; const string metaProperty0Value = "m_0"; const string metaProperty1Name = "myMetaProperty1"; const int metaProperty1Value = 123; // Compose the vertex document using eager CosmosElements Dictionary <string, CosmosElement> vertexDocumentProperties = new Dictionary <string, CosmosElement>() { { idName, CosmosString.Create(idValue) }, { GremlinScenarioTests.PartitionKeyPropertyName, CosmosString.Create(pkValue) }, { labelName, CosmosString.Create(labelValue) }, { boolName, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(boolId), CosmosBoolean.Create(boolValue)), } ) }, { intName, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(intId), CosmosNumber64.Create(intValue)), this.CreateVertexPropertySingleComplexValue(CosmosString.Create(longId), CosmosNumber64.Create(longValue)), } ) }, { floatName, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(floatId), CosmosNumber64.Create(floatValue)), this.CreateVertexPropertySingleComplexValue(CosmosString.Create(doubleId), CosmosNumber64.Create(doubleValue)), } ) }, { stringName, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue( CosmosString.Create(stringId), CosmosString.Create(stringValue), Tuple.Create <string, CosmosElement>(metaProperty0Name, CosmosString.Create(metaProperty0Value)), Tuple.Create <string, CosmosElement>(metaProperty1Name, CosmosNumber64.Create(metaProperty1Value))), } ) }, }; CosmosObject vertexEagerObject = CosmosObject.Create(vertexDocumentProperties); // Serialize the vertex object into a document using the specified serialization format IJsonWriter jsonWriter = JsonWriter.Create(jsonSerializationFormat); vertexEagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> jsonResult = jsonWriter.GetResult(); Assert.IsTrue(jsonResult.Length > 0, "IJsonWriter result data is empty."); // Navigate into the serialized vertex document using lazy CosmosElements CosmosElement rootLazyElement = CosmosElement.CreateFromBuffer(jsonResult); // Validate the expected vertex document structure/values // Root vertex document object CosmosObject vertexLazyObject = rootLazyElement as CosmosObject; Assert.IsNotNull(vertexLazyObject, $"Vertex document root is not {nameof(CosmosObject)}."); Assert.AreEqual(vertexDocumentProperties.Count, vertexLazyObject.Count); // Vertex system document properties CosmosString idLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, idName); Assert.AreEqual(idValue, idLazyString.Value); CosmosString pkLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, GremlinScenarioTests.PartitionKeyPropertyName); Assert.AreEqual(pkValue, pkLazyString.Value); CosmosString labelLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, labelName); Assert.AreEqual(labelValue, labelLazyString.Value); // Vertex user properties CosmosArray boolLazyArray = this.GetAndAssertObjectProperty <CosmosArray>(vertexLazyObject, boolName); Assert.AreEqual(1, boolLazyArray.Count); // Bool value(s) CosmosObject boolValue0LazyObject = this.GetAndAssertArrayValue <CosmosObject>(boolLazyArray, 0); CosmosString boolValue0IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(boolValue0LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(boolId, boolValue0IdLazyString.Value); CosmosBoolean boolValue0ValueLazyBool = this.GetAndAssertObjectProperty <CosmosBoolean>(boolValue0LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(boolValue, boolValue0ValueLazyBool.Value); CosmosArray intLazyArray = this.GetAndAssertObjectProperty <CosmosArray>(vertexLazyObject, intName); Assert.AreEqual(2, intLazyArray.Count); // Integer value(s) CosmosObject intValue0LazyObject = this.GetAndAssertArrayValue <CosmosObject>(intLazyArray, 0); CosmosString intValue0IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(intValue0LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(intId, intValue0IdLazyString.Value); CosmosNumber intValue0ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(intValue0LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(CosmosNumberType.Number64, intValue0ValueLazyNumber.NumberType); Assert.IsTrue(intValue0ValueLazyNumber.IsInteger); Assert.AreEqual((long)intValue, intValue0ValueLazyNumber.AsInteger().Value); CosmosObject intValue1LazyObject = this.GetAndAssertArrayValue <CosmosObject>(intLazyArray, 1); CosmosString intValue1IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(intValue1LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(longId, intValue1IdLazyString.Value); CosmosNumber intValue1ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(intValue1LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(CosmosNumberType.Number64, intValue1ValueLazyNumber.NumberType); Assert.IsTrue(intValue1ValueLazyNumber.IsInteger); Assert.AreEqual(longValue, intValue1ValueLazyNumber.AsInteger().Value); // Floating point value(s) CosmosArray floatLazyArray = this.GetAndAssertObjectProperty <CosmosArray>(vertexLazyObject, floatName); Assert.AreEqual(2, floatLazyArray.Count); CosmosObject floatValue0LazyObject = this.GetAndAssertArrayValue <CosmosObject>(floatLazyArray, 0); CosmosString floatValue0IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(floatValue0LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(floatId, floatValue0IdLazyString.Value); CosmosNumber floatValue0ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(floatValue0LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(CosmosNumberType.Number64, floatValue0ValueLazyNumber.NumberType); Assert.IsTrue(floatValue0ValueLazyNumber.IsFloatingPoint); Assert.AreEqual((double)floatValue, floatValue0ValueLazyNumber.AsFloatingPoint().Value); CosmosObject floatValue1LazyObject = this.GetAndAssertArrayValue <CosmosObject>(floatLazyArray, 1); CosmosString floatValue1IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(floatValue1LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(doubleId, floatValue1IdLazyString.Value); CosmosNumber floatValue1ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(floatValue1LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(CosmosNumberType.Number64, floatValue1ValueLazyNumber.NumberType); Assert.IsTrue(floatValue1ValueLazyNumber.IsFloatingPoint); Assert.AreEqual(doubleValue, floatValue1ValueLazyNumber.AsFloatingPoint().Value); // String value(s) CosmosArray stringLazyArray = this.GetAndAssertObjectProperty <CosmosArray>(vertexLazyObject, stringName); Assert.AreEqual(1, stringLazyArray.Count); CosmosObject stringValue0LazyObject = this.GetAndAssertArrayValue <CosmosObject>(stringLazyArray, 0); CosmosString stringValue0IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(stringValue0LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(stringId, stringValue0IdLazyString.Value); CosmosString stringValue0ValueLazyString = this.GetAndAssertObjectProperty <CosmosString>(stringValue0LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(stringValue, stringValue0ValueLazyString.Value); // String value meta-properties CosmosObject stringValue0MetaLazyObject = this.GetAndAssertObjectProperty <CosmosObject>(stringValue0LazyObject, GremlinKeywords.KW_PROPERTY_META); Assert.AreEqual(2, stringValue0MetaLazyObject.Count); CosmosString stringValue0MetaValue0LazyString = this.GetAndAssertObjectProperty <CosmosString>(stringValue0MetaLazyObject, metaProperty0Name); Assert.AreEqual(metaProperty0Value, stringValue0MetaValue0LazyString.Value); CosmosNumber stringValue0MetaValue1LazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(stringValue0MetaLazyObject, metaProperty1Name); Assert.AreEqual(CosmosNumberType.Number64, stringValue0MetaValue1LazyNumber.NumberType); Assert.IsTrue(stringValue0MetaValue1LazyNumber.IsInteger); Assert.AreEqual((long)metaProperty1Value, stringValue0MetaValue1LazyNumber.AsInteger().Value); }
public ReadFeedIteratorCore( IDocumentContainer documentContainer, string continuationToken, ReadFeedPaginationOptions readFeedPaginationOptions, QueryRequestOptions queryRequestOptions, CancellationToken cancellationToken) { this.queryRequestOptions = queryRequestOptions; readFeedPaginationOptions ??= ReadFeedPaginationOptions.Default; if (!string.IsNullOrEmpty(continuationToken)) { bool isNewArrayFormat = (continuationToken.Length >= 2) && (continuationToken[0] == '[') && (continuationToken[continuationToken.Length - 1] == ']'); if (!isNewArrayFormat) { // One of the two older formats if (!FeedRangeContinuation.TryParse(continuationToken, out FeedRangeContinuation feedRangeContinuation)) { // Backward compatible with old format feedRangeContinuation = new FeedRangeCompositeContinuation( containerRid: string.Empty, FeedRangeEpk.FullRange, new List <Documents.Routing.Range <string> >() { new Documents.Routing.Range <string>( Documents.Routing.PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, Documents.Routing.PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey, isMinInclusive: true, isMaxInclusive: false) }, continuationToken); } // need to massage it a little List <CosmosElement> feedRangeStates = new List <CosmosElement>(); string oldContinuationFormat = feedRangeContinuation.ToString(); if (feedRangeContinuation.FeedRange is FeedRangePartitionKey feedRangePartitionKey) { CosmosObject cosmosObject = CosmosObject.Parse(oldContinuationFormat); CosmosArray continuations = (CosmosArray)cosmosObject["Continuation"]; if (continuations.Count != 1) { throw new InvalidOperationException("Expected only one continuation for partition key queries"); } CosmosElement continuation = continuations[0]; CosmosObject continuationObject = (CosmosObject)continuation; CosmosElement token = continuationObject["token"]; ReadFeedState state; if (token is CosmosNull) { state = ReadFeedState.Beginning(); } else { CosmosString tokenAsString = (CosmosString)token; state = ReadFeedState.Continuation(CosmosElement.Parse(tokenAsString.Value)); } FeedRangeState <ReadFeedState> feedRangeState = new FeedRangeState <ReadFeedState>(feedRangePartitionKey, state); feedRangeStates.Add(ReadFeedFeedRangeStateSerializer.ToCosmosElement(feedRangeState)); } else { CosmosObject cosmosObject = CosmosObject.Parse(oldContinuationFormat); CosmosArray continuations = (CosmosArray)cosmosObject["Continuation"]; foreach (CosmosElement continuation in continuations) { CosmosObject continuationObject = (CosmosObject)continuation; CosmosObject rangeObject = (CosmosObject)continuationObject["range"]; string min = ((CosmosString)rangeObject["min"]).Value; string max = ((CosmosString)rangeObject["max"]).Value; CosmosElement token = continuationObject["token"]; FeedRangeInternal feedRange = new FeedRangeEpk(new Documents.Routing.Range <string>(min, max, isMinInclusive: true, isMaxInclusive: false)); ReadFeedState state; if (token is CosmosNull) { state = ReadFeedState.Beginning(); } else { CosmosString tokenAsString = (CosmosString)token; state = ReadFeedState.Continuation(CosmosElement.Parse(tokenAsString.Value)); } FeedRangeState <ReadFeedState> feedRangeState = new FeedRangeState <ReadFeedState>(feedRange, state); feedRangeStates.Add(ReadFeedFeedRangeStateSerializer.ToCosmosElement(feedRangeState)); } } CosmosArray cosmosArrayContinuationTokens = CosmosArray.Create(feedRangeStates); continuationToken = cosmosArrayContinuationTokens.ToString(); } } TryCatch <ReadFeedCrossFeedRangeState> monadicReadFeedState; if (continuationToken == null) { FeedRange feedRange; if ((this.queryRequestOptions != null) && this.queryRequestOptions.PartitionKey.HasValue) { feedRange = new FeedRangePartitionKey(this.queryRequestOptions.PartitionKey.Value); } else if ((this.queryRequestOptions != null) && (this.queryRequestOptions.FeedRange != null)) { feedRange = this.queryRequestOptions.FeedRange; } else { feedRange = FeedRangeEpk.FullRange; } monadicReadFeedState = TryCatch <ReadFeedCrossFeedRangeState> .FromResult(ReadFeedCrossFeedRangeState.CreateFromBeginning(feedRange)); } else { monadicReadFeedState = ReadFeedCrossFeedRangeState.Monadic.Parse(continuationToken); } if (monadicReadFeedState.Failed) { this.monadicEnumerator = TryCatch <CrossPartitionReadFeedAsyncEnumerator> .FromException(monadicReadFeedState.Exception); } else { this.monadicEnumerator = TryCatch <CrossPartitionReadFeedAsyncEnumerator> .FromResult( CrossPartitionReadFeedAsyncEnumerator.Create( documentContainer, new CrossFeedRangeState <ReadFeedState>(monadicReadFeedState.Result.FeedRangeStates), readFeedPaginationOptions, cancellationToken)); } this.hasMoreResults = true; }
public void SqlSelectListSpecTest() { CosmosObject john = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["name"] = CosmosString.Create("John"), ["age"] = CosmosNumber64.Create(25) }); CosmosObject johnWrapped = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["c"] = john }); // { c.name, c.age } SqlScalarExpression cDotName = TestUtils.CreatePathExpression("c", "name"); SqlScalarExpression cDotAge = TestUtils.CreatePathExpression("c", "age"); SqlSelectListSpec listSpec = SqlSelectListSpec.Create( SqlSelectItem.Create(cDotName), SqlSelectItem.Create(cDotAge)); AssertEvaluation(john, listSpec, johnWrapped); // { c.name AS nameAlias } CosmosObject johnAliased = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["nameAlias"] = CosmosString.Create("John"), }); SqlSelectListSpec listSpecWithAlias = SqlSelectListSpec.Create(SqlSelectItem.Create(cDotName, SqlIdentifier.Create("nameAlias"))); AssertEvaluation(johnAliased, listSpecWithAlias, johnWrapped); // { 3 + 5 } CosmosObject johnNonPropertyName = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["$1"] = CosmosNumber64.Create(8) }); SqlLiteralScalarExpression five = SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(5)); SqlLiteralScalarExpression three = SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(3)); SqlBinaryScalarExpression fivePlusThree = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Add, five, three); SqlSelectListSpec listSpecNonMember = SqlSelectListSpec.Create(SqlSelectItem.Create(fivePlusThree)); AssertEvaluation(johnNonPropertyName, listSpecNonMember); // { 3 + 5 AS Five Plus Three } CosmosObject johnNonPropertyNameAliased = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["Five Plus Three"] = CosmosNumber64.Create(8) }); SqlSelectListSpec listSpecNonMemberAliased = SqlSelectListSpec.Create(SqlSelectItem.Create(fivePlusThree, SqlIdentifier.Create("Five Plus Three"))); AssertEvaluation(johnNonPropertyNameAliased, listSpecNonMemberAliased); // { c.blah[0] } CosmosObject numberIndex = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["blah"] = CosmosArray.Create( new List <CosmosElement>() { CosmosNumber64.Create(0), CosmosNumber64.Create(1), CosmosNumber64.Create(2) }) }); CosmosObject numberIndexWrapped = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["c"] = numberIndex }); CosmosObject numberIndexEval = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["$1"] = CosmosNumber64.Create(0) }); SqlScalarExpression cDotBlah0 = TestUtils.CreatePathExpression("c", "blah", 0); SqlSelectListSpec numberIndexSpec = SqlSelectListSpec.Create(SqlSelectItem.Create(cDotBlah0)); AssertEvaluation(numberIndexEval, numberIndexSpec, numberIndexWrapped); }
public void TestOrderByQueryLiterals() { StringBuilder sb = new StringBuilder(); CosmosElement element = CosmosObject.Create( new Dictionary <string, CosmosElement>() { { "item", CosmosString.Create("asdf") } }); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( @"{""item"":""asdf""}", sb.ToString()); element = CosmosObject.Create( new Dictionary <string, CosmosElement>() { { "item", CosmosBoolean.Create(true) } }); sb.Clear(); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( @"{""item"":true}", sb.ToString()); element = CosmosObject.Create( new Dictionary <string, CosmosElement>() { { "item", CosmosBoolean.Create(false) } }); sb.Clear(); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( @"{""item"":false}", sb.ToString()); element = CosmosObject.Create( new Dictionary <string, CosmosElement>() { { "item", CosmosNull.Create() } }); sb.Clear(); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( @"{""item"":null}", sb.ToString()); element = CosmosObject.Create( new Dictionary <string, CosmosElement>() { { "item", CosmosNumber64.Create(1.0) } }); sb.Clear(); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( @"{""item"":1}", sb.ToString()); element = CosmosObject.Create( new Dictionary <string, CosmosElement>() { { "item", CosmosNumber64.Create(1L) } }); sb.Clear(); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( @"{""item"":1}", sb.ToString()); element = CosmosObject.Create( new Dictionary <string, CosmosElement>() { { "item", CosmosInt8.Create(3) }, { "item2", CosmosInt16.Create(4) }, { "item3", CosmosInt32.Create(5) }, { "item5", CosmosUInt32.Create(7) }, { "item6", CosmosInt64.Create(8) }, { "item7", CosmosFloat32.Create(9.1f) }, { "item8", CosmosFloat64.Create(10.2) }, }); sb.Clear(); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( @"{""item"":C_Int8(3),""item2"":C_Int16(4),""item3"":C_Int32(5),""item5"":C_UInt32(7),""item6"":C_Int64(8)," + @"""item7"":C_Float32(9.1),""item8"":C_Float64(10.2)}", sb.ToString()); Guid guid = Guid.NewGuid(); byte[] randomBytes = Guid.NewGuid().ToByteArray(); string hexString = PartitionKeyInternal.HexConvert.ToHex(randomBytes, 0, randomBytes.Length); element = CosmosObject.Create( new Dictionary <string, CosmosElement>() { { "item", CosmosGuid.Create(guid) }, { "item2", CosmosBinary.Create(new ReadOnlyMemory <byte>(randomBytes)) }, }); sb.Clear(); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( $@"{{""item"":C_Guid(""{guid.ToString()}""),""item2"":C_Binary(""0x{hexString}"")}}", sb.ToString()); // deeply nested arrays and objects element = CosmosObject.Create( new Dictionary <string, CosmosElement>() { { "item", CosmosGuid.Create(guid) }, // empty array { "item2", CosmosArray.Create(new CosmosElement[] { }) }, // empty object { "item3", CosmosObject.Create(new Dictionary <string, CosmosElement>()) }, // array of objects with numbers { "item4", CosmosArray.Create(new CosmosElement[] { CosmosObject.Create(new Dictionary <string, CosmosElement>() { { "a", CosmosInt8.Create(3) }, { "b", CosmosString.Create("adf") }, }), CosmosInt16.Create(25) }) }, }); sb.Clear(); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( $@"{{""item"":C_Guid(""{guid.ToString()}""),""item2"":[],""item3"":{{}},""item4"":[{{""a"":C_Int8(3),""b"":""adf""}},C_Int16(25)]}}", sb.ToString()); }
public async Task TestCosmosOrderByQueryExecutionContextWithFailurePageAsync(bool createInitialContinuationToken) { int maxPageSize = 5; List <MockPartitionResponse[]> mockResponsesScenario = MockQueryFactory.GetFailureScenarios(); Mock <CosmosQueryClient> mockQueryClient = new Mock <CosmosQueryClient>(); foreach (MockPartitionResponse[] mockResponse in mockResponsesScenario) { string initialContinuationToken = null; string fullContinuationToken = null; if (createInitialContinuationToken) { ToDoItem itemToRepresentPreviousQuery = ToDoItem.CreateItems( 1, "itemToRepresentPreviousQuery", MockQueryFactory.DefaultCollectionRid).First(); initialContinuationToken = $" - RID:{itemToRepresentPreviousQuery._rid} ==#RT:1#TRC:1"; CompositeContinuationToken compositeContinuation = new CompositeContinuationToken() { Range = new Documents.Routing.Range <string>( min: MockQueryFactory.DefaultPartitionKeyRange.MinInclusive, max: MockQueryFactory.DefaultPartitionKeyRange.MaxExclusive, isMaxInclusive: false, isMinInclusive: true), Token = initialContinuationToken }; List <OrderByItem> orderByItems = new List <OrderByItem>() { new OrderByItem(CosmosObject.CreateFromBuffer(Encoding.UTF8.GetBytes("{\"item\":\"2c4ce711-13c3-4c93-817c-49287b71b6c3\"}"))) }; OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( compositeContinuationToken: compositeContinuation, orderByItems: orderByItems, rid: itemToRepresentPreviousQuery._rid, skipCount: 0, filter: null); fullContinuationToken = CosmosArray.Create( new List <CosmosElement>() { OrderByContinuationToken.ToCosmosElement(orderByContinuationToken) }).ToString(); } IList <ToDoItem> allItems = MockQueryFactory.GenerateAndMockResponse( mockQueryClient, isOrderByQuery: true, sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, containerRid: MockQueryFactory.DefaultCollectionRid, initContinuationToken: initialContinuationToken, maxPageSize: maxPageSize, mockResponseForSinglePartition: mockResponse, cancellationTokenForMocks: this.cancellationToken); // Order by drains the partitions until it finds an item // If there are no items then it's not possible to have a continuation token if (allItems.Count == 0 && createInitialContinuationToken) { continue; } CosmosQueryContext context = MockQueryFactory.CreateContext( mockQueryClient.Object); QueryInfo queryInfo = new QueryInfo() { OrderBy = new SortOrder[] { SortOrder.Ascending }, OrderByExpressions = new string[] { "id" } }; CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, collectionRid: MockQueryFactory.DefaultCollectionRid, partitionedQueryExecutionInfo: new PartitionedQueryExecutionInfo() { QueryInfo = queryInfo }, partitionKeyRanges: new List <PartitionKeyRange>() { MockQueryFactory.DefaultPartitionKeyRange }, initialPageSize: maxPageSize, maxConcurrency: null, maxItemCount: maxPageSize, maxBufferedItemCount: null, returnResultsInDeterministicOrder: true, testSettings: new TestInjections(simulate429s: false, simulateEmptyPages: false)); TryCatch <IDocumentQueryExecutionComponent> tryCreate = await CosmosOrderByItemQueryExecutionContext.TryCreateAsync( context, initParams, fullContinuationToken != null?CosmosElement.Parse(fullContinuationToken) : null, this.cancellationToken); if (tryCreate.Succeeded) { IDocumentQueryExecutionComponent executionContext = tryCreate.Result; Assert.IsTrue(!executionContext.IsDone); // Read all the pages from both splits List <ToDoItem> itemsRead = new List <ToDoItem>(); QueryResponseCore?failure = null; while (!executionContext.IsDone) { QueryResponseCore queryResponse = await executionContext.DrainAsync( maxPageSize, this.cancellationToken); if (queryResponse.IsSuccess) { string responseContinuationToken = queryResponse.ContinuationToken; foreach (CosmosElement element in queryResponse.CosmosElements) { string jsonValue = element.ToString(); ToDoItem item = JsonConvert.DeserializeObject <ToDoItem>(jsonValue); itemsRead.Add(item); } } else { Assert.IsNull(failure, "There should only be one error"); failure = queryResponse; } } Assert.IsNotNull(failure); Assert.AreEqual((HttpStatusCode)429, failure.Value.StatusCode); Assert.IsNotNull(failure.Value.CosmosException.ToString()); Assert.AreEqual(0 /*We don't get any items, since we don't buffer the failure anymore*/, itemsRead.Count); //CollectionAssert.AreEqual(allItems.ToList(), itemsRead, new ToDoItemComparer()); } else { QueryResponseCore queryResponseCore = QueryResponseFactory.CreateFromException(tryCreate.Exception); Assert.AreEqual((HttpStatusCode)429, queryResponseCore.StatusCode); } } }
public async Task TestCosmosCrossPartitionQueryExecutionContextWithEmptyPagesAndSplitAsync(bool createInitialContinuationToken) { int maxPageSize = 5; List <MockPartitionResponse[]> mockResponsesScenario = MockQueryFactory.GetSplitScenarios(); foreach (MockPartitionResponse[] mockResponse in mockResponsesScenario) { string initialContinuationToken = null; string fullContinuationToken = null; if (createInitialContinuationToken) { initialContinuationToken = " - RID:02FYAIvUH1kCAAAAAAAAAA ==#RT:1#TRC:1"; CompositeContinuationToken compositeContinuation = new CompositeContinuationToken() { Range = new Documents.Routing.Range <string>( min: MockQueryFactory.DefaultPartitionKeyRange.MinInclusive, max: MockQueryFactory.DefaultPartitionKeyRange.MaxExclusive, isMaxInclusive: false, isMinInclusive: true), Token = initialContinuationToken }; fullContinuationToken = CosmosArray.Create( new List <CosmosElement>() { CompositeContinuationToken.ToCosmosElement(compositeContinuation) }).ToString(); } Mock <CosmosQueryClient> mockQueryClient = new Mock <CosmosQueryClient>(); IList <ToDoItem> allItems = MockQueryFactory.GenerateAndMockResponse( mockQueryClient, isOrderByQuery: false, sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, containerRid: MockQueryFactory.DefaultCollectionRid, initContinuationToken: initialContinuationToken, maxPageSize: maxPageSize, mockResponseForSinglePartition: mockResponse, cancellationTokenForMocks: this.cancellationToken); CosmosQueryContext context = MockQueryFactory.CreateContext( mockQueryClient.Object); CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, collectionRid: MockQueryFactory.DefaultCollectionRid, partitionedQueryExecutionInfo: new PartitionedQueryExecutionInfo() { QueryInfo = new QueryInfo() }, partitionKeyRanges: new List <PartitionKeyRange> { MockQueryFactory.DefaultPartitionKeyRange }, initialPageSize: maxPageSize, maxConcurrency: null, maxItemCount: maxPageSize, maxBufferedItemCount: null, returnResultsInDeterministicOrder: true, testSettings: new TestInjections(simulate429s: false, simulateEmptyPages: false)); IDocumentQueryExecutionComponent executionContext = (await CosmosParallelItemQueryExecutionContext.TryCreateAsync( context, initParams, fullContinuationToken != null ? CosmosElement.Parse(fullContinuationToken) : null, this.cancellationToken)).Result; // Read all the pages from both splits List <ToDoItem> itemsRead = new List <ToDoItem>(); Assert.IsTrue(!executionContext.IsDone); while (!executionContext.IsDone) { QueryResponseCore queryResponse = await executionContext.DrainAsync(maxPageSize, this.cancellationToken); string responseContinuationToken = queryResponse.ContinuationToken; foreach (CosmosElement element in queryResponse.CosmosElements) { string jsonValue = element.ToString(); ToDoItem item = JsonConvert.DeserializeObject <ToDoItem>(jsonValue); itemsRead.Add(item); } } Assert.AreEqual(allItems.Count, itemsRead.Count); List <ToDoItem> exepected = allItems.OrderBy(x => x.id).ToList(); List <ToDoItem> actual = itemsRead.OrderBy(x => x.id).ToList(); CollectionAssert.AreEqual(exepected, actual, new ToDoItemComparer()); } }
public async ValueTask <bool> MoveNextAsync(ITrace trace) { this.cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { throw new ArgumentNullException(nameof(trace)); } if (!await this.crossPartitionRangePageAsyncEnumerator.MoveNextAsync(trace)) { this.Current = default; return(false); } TryCatch <CrossFeedRangePage <QueryPage, QueryState> > currentCrossPartitionPage = this.crossPartitionRangePageAsyncEnumerator.Current; if (currentCrossPartitionPage.Failed) { this.Current = TryCatch <QueryPage> .FromException(currentCrossPartitionPage.Exception); return(true); } CrossFeedRangePage <QueryPage, QueryState> crossPartitionPageResult = currentCrossPartitionPage.Result; QueryPage backendQueryPage = crossPartitionPageResult.Page; CrossFeedRangeState <QueryState> crossPartitionState = crossPartitionPageResult.State; QueryState queryState; if (crossPartitionState == null) { queryState = null; } else { // left most and any non null continuations IOrderedEnumerable <FeedRangeState <QueryState> > feedRangeStates = crossPartitionState .Value .ToArray() .OrderBy(tuple => ((FeedRangeEpk)tuple.FeedRange).Range.Min); List <ParallelContinuationToken> activeParallelContinuationTokens = new List <ParallelContinuationToken>(); { FeedRangeState <QueryState> firstState = feedRangeStates.First(); ParallelContinuationToken firstParallelContinuationToken = new ParallelContinuationToken( token: firstState.State != null ? ((CosmosString)firstState.State.Value).Value : null, range: ((FeedRangeEpk)firstState.FeedRange).Range); activeParallelContinuationTokens.Add(firstParallelContinuationToken); } foreach (FeedRangeState <QueryState> feedRangeState in feedRangeStates.Skip(1)) { this.cancellationToken.ThrowIfCancellationRequested(); if (feedRangeState.State != null) { ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( token: feedRangeState.State != null ? ((CosmosString)feedRangeState.State.Value).Value : null, range: ((FeedRangeEpk)feedRangeState.FeedRange).Range); activeParallelContinuationTokens.Add(parallelContinuationToken); } } IEnumerable <CosmosElement> cosmosElementContinuationTokens = activeParallelContinuationTokens .Select(token => ParallelContinuationToken.ToCosmosElement(token)); CosmosArray cosmosElementParallelContinuationTokens = CosmosArray.Create(cosmosElementContinuationTokens); queryState = new QueryState(cosmosElementParallelContinuationTokens); } QueryPage crossPartitionQueryPage = new QueryPage( backendQueryPage.Documents, backendQueryPage.RequestCharge, backendQueryPage.ActivityId, backendQueryPage.ResponseLengthInBytes, backendQueryPage.CosmosQueryExecutionInfo, backendQueryPage.DisallowContinuationTokenMessage, queryState); this.Current = TryCatch <QueryPage> .FromResult(crossPartitionQueryPage); return(true); }
public void SqlExistsScalarExpressionTest() { CosmosObject tag = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["name"] = CosmosString.Create("asdf") }); CosmosObject tags = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["tags"] = CosmosArray.Create(new List <CosmosElement>() { tag }), ["_rid"] = CosmosString.Create("AYIMAMmFOw8YAAAAAAAAAA==") }); CosmosObject tagsWrapped = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["c"] = tags, ["_rid"] = CosmosString.Create("AYIMAMmFOw8YAAAAAAAAAA==") }); // EXISTS(SELECT VALUE t.name FROM t in c.tags where t.name = "asdf") SqlExistsScalarExpression existsScalarExpressionMatched = SqlExistsScalarExpression.Create( SqlQuery.Create( SqlSelectClause.Create( SqlSelectValueSpec.Create( TestUtils.CreatePathExpression("t", "name"))), SqlFromClause.Create( SqlArrayIteratorCollectionExpression.Create( SqlIdentifier.Create("t"), SqlInputPathCollection.Create( SqlIdentifier.Create("c"), SqlStringPathExpression.Create( null, SqlStringLiteral.Create("tags"))))), SqlWhereClause.Create( SqlBinaryScalarExpression.Create( SqlBinaryScalarOperatorKind.Equal, TestUtils.CreatePathExpression("t", "name"), SqlLiteralScalarExpression.Create(SqlStringLiteral.Create("asdf")))), groupByClause: null, orderByClause: null, offsetLimitClause: null)); AssertEvaluation(CosmosBoolean.Create(true), existsScalarExpressionMatched, tagsWrapped); SqlExistsScalarExpression existsScalarExpressionNotMatched = SqlExistsScalarExpression.Create( SqlQuery.Create( SqlSelectClause.Create( SqlSelectValueSpec.Create( TestUtils.CreatePathExpression("t", "name"))), SqlFromClause.Create( SqlArrayIteratorCollectionExpression.Create( SqlIdentifier.Create("t"), SqlInputPathCollection.Create( SqlIdentifier.Create("c"), SqlStringPathExpression.Create( null, SqlStringLiteral.Create("tags"))))), SqlWhereClause.Create( SqlBinaryScalarExpression.Create( SqlBinaryScalarOperatorKind.NotEqual, TestUtils.CreatePathExpression("t", "name"), SqlLiteralScalarExpression.Create(SqlStringLiteral.Create("asdf")))), groupByClause: null, orderByClause: null, offsetLimitClause: null)); AssertEvaluation(CosmosBoolean.Create(false), existsScalarExpressionNotMatched, tagsWrapped); }