public void SqlLiteralScalarExpressionTest() { SqlLiteralScalarExpression numberLiteral = SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(1)); AssertEvaluation(CosmosNumber64.Create(1), numberLiteral); SqlLiteralScalarExpression stringLiteral = SqlLiteralScalarExpression.Create(SqlStringLiteral.Create("Hello")); AssertEvaluation(CosmosString.Create("Hello"), stringLiteral); SqlLiteralScalarExpression trueLiteral = SqlLiteralScalarExpression.Create(SqlBooleanLiteral.True); AssertEvaluation(CosmosBoolean.Create(true), trueLiteral); SqlLiteralScalarExpression falseLiteral = SqlLiteralScalarExpression.Create(SqlBooleanLiteral.False); AssertEvaluation(CosmosBoolean.Create(false), falseLiteral); SqlLiteralScalarExpression nullLiteral = SqlLiteralScalarExpression.Create(SqlNullLiteral.Singleton); AssertEvaluation(CosmosNull.Create(), nullLiteral); SqlLiteralScalarExpression undefinedLiteral = SqlLiteralScalarExpression.Create(SqlUndefinedLiteral.Create()); AssertEvaluation(Undefined, undefinedLiteral); }
private static PartitionKey CosmosElementToPartitionKeyObject(IReadOnlyList <CosmosElement> cosmosElementList) { PartitionKeyBuilder partitionKeyBuilder = new PartitionKeyBuilder(); foreach (CosmosElement cosmosElement in cosmosElementList) { if (cosmosElement == null) { partitionKeyBuilder.AddNoneType(); } else { _ = cosmosElement switch { CosmosString cosmosString => partitionKeyBuilder.Add(cosmosString.Value), CosmosNumber cosmosNumber => partitionKeyBuilder.Add(Number64.ToDouble(cosmosNumber.Value)), CosmosBoolean cosmosBoolean => partitionKeyBuilder.Add(cosmosBoolean.Value), CosmosNull _ => partitionKeyBuilder.AddNullValue(), _ => throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, RMResources.UnsupportedPartitionKeyComponentValue, cosmosElement)), }; } } return(partitionKeyBuilder.Build()); }
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")))); }
private CosmosElement CreateVertexPropertyPrimitiveValueElement(object value) { switch (value) { case bool boolValue: return(CosmosBoolean.Create(boolValue)); case double doubleValue: return(CosmosNumber64.Create(doubleValue)); case float floatValue: return(CosmosNumber64.Create(floatValue)); case int intValue: return(CosmosNumber64.Create(intValue)); case long longValue: return(CosmosNumber64.Create(longValue)); case string stringValue: return(CosmosString.Create(stringValue)); default: throw new AssertFailedException($"Invalid Gremlin property value object type: {value.GetType().Name}."); } }
private PartitionKey CosmosElementToPartitionKeyObject(CosmosElement cosmosElement) { // TODO: Leverage original serialization and avoid re-serialization (bug) switch (cosmosElement.Type) { case CosmosElementType.String: CosmosString cosmosString = cosmosElement as CosmosString; return(new PartitionKey(cosmosString.Value)); case CosmosElementType.Number: CosmosNumber cosmosNumber = cosmosElement as CosmosNumber; double value = Number64.ToDouble(cosmosNumber.Value); return(new PartitionKey(value)); case CosmosElementType.Boolean: CosmosBoolean cosmosBool = cosmosElement as CosmosBoolean; return(new PartitionKey(cosmosBool.Value)); case CosmosElementType.Null: return(PartitionKey.Null); default: throw new ArgumentException( string.Format(CultureInfo.InvariantCulture, RMResources.UnsupportedPartitionKeyComponentValue, cosmosElement)); } }
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); }
private CosmosObject CreateVertexDocument(string id, string label, string pkName, string pkValue, IEnumerable <Tuple <string, IEnumerable <object> > > userProperties) { Dictionary <string, CosmosElement> vertexDocumentProperties = new Dictionary <string, CosmosElement>() { { GremlinKeywords.KW_DOC_ID, CosmosString.Create(id) }, { GremlinKeywords.KW_VERTEX_LABEL, CosmosString.Create(label) }, }; if (!string.IsNullOrEmpty(pkName) && !string.IsNullOrEmpty(pkValue)) { vertexDocumentProperties.Add(pkName, CosmosString.Create(pkValue)); } foreach (Tuple <string, IEnumerable <object> > userProperty in userProperties) { List <CosmosElement> singleValues = new List <CosmosElement>(); foreach (object userPropertyValue in userProperty.Item2) { string propertyId = Guid.NewGuid().ToString(); singleValues.Add( this.CreateVertexPropertySingleComplexValue( CosmosString.Create(propertyId), this.CreateVertexPropertyPrimitiveValueElement(userPropertyValue))); } } return(CosmosObject.Create(vertexDocumentProperties)); }
public void LEFT() { // LEFT("Hello", -3) AssertEvaluation( expected: CosmosString.Empty, sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.Left, hello, negativeThree)); // LEFT("Hello", 0) AssertEvaluation( expected: CosmosString.Empty, sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.Left, hello, SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(0)))); // LEFT("Hello", 2) AssertEvaluation( expected: CosmosString.Create("He"), sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.Left, hello, SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(2)))); // LEFT("Hello", 6) AssertEvaluation( expected: CosmosString.Create("Hello"), sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.Left, hello, six)); }
private object CosmosElementToPartitionKeyObject(CosmosElement cosmosElement) { // TODO: Leverage original serialization and avoid re-serialization (bug) switch (cosmosElement.Type) { case CosmosElementType.String: CosmosString cosmosString = cosmosElement as CosmosString; return(cosmosString.Value); case CosmosElementType.Number: CosmosNumber cosmosNumber = cosmosElement as CosmosNumber; return(cosmosNumber.AsFloatingPoint()); case CosmosElementType.Boolean: CosmosBoolean cosmosBool = cosmosElement as CosmosBoolean; return(cosmosBool.Value); case CosmosElementType.Guid: CosmosGuid cosmosGuid = cosmosElement as CosmosGuid; return(cosmosGuid.Value); default: throw new ArgumentException( string.Format(CultureInfo.InvariantCulture, RMResources.UnsupportedPartitionKeyComponentValue, cosmosElement)); } }
public string ToString(int lengthLimitInBytes) { string queryPlanString = this.QueryPlan?.ToString(); bool shouldSerializeQueryPlan; if (queryPlanString == null) { shouldSerializeQueryPlan = false; } else { shouldSerializeQueryPlan = (queryPlanString.Length + this.SourceContinuationToken.ToString().Length) < lengthLimitInBytes; } return(CosmosObject.Create(new Dictionary <string, CosmosElement>() { { PipelineContinuationToken.VersionPropertyName, CosmosString.Create(this.Version.ToString()) }, { PipelineContinuationTokenV1_1.QueryPlanPropertyName, shouldSerializeQueryPlan ? CosmosString.Create(queryPlanString) : (CosmosElement)CosmosNull.Create() }, { PipelineContinuationTokenV1_1.SourceContinuationTokenPropertyName, this.SourceContinuationToken }, }).ToString()); }
public void Strings() { List <Input> inputs = new List <Input>() { new Input( description: "Empty String", partitionKeyValue: CosmosString.Create(string.Empty)), new Input( description: "short string", partitionKeyValue: CosmosString.Create("asdf")), new Input( description: "99 byte string", partitionKeyValue: CosmosString.Create(new string('a', 99))), new Input( description: "100 byte string", partitionKeyValue: CosmosString.Create(new string('a', 100))), new Input( description: "101 byte string", partitionKeyValue: CosmosString.Create(new string('a', 101))), new Input( description: "2kb byte string", partitionKeyValue: CosmosString.Create(new string('a', 2 * 1024))), }; this.ExecuteTestSuite(inputs); }
/// <summary> /// Gets the hash of a JSON object. /// </summary> /// <param name="cosmosObject">The object to hash.</param> /// <param name="seed">The seed to use.</param> /// <returns>The hash of a JSON object.</returns> private static UInt192 GetObjectHash(CosmosObject cosmosObject, UInt192 seed) { // Start the object with a distinct hash, so that empty object doesn't hash to another value. UInt192 hash = DistinctHash.GetHash(DistinctHash.ObjectHashSeed, seed); //// Intermediate hashes of all the properties, which we don't want to xor with the final hash //// otherwise the following will collide: ////{ //// "pet":{ //// "name":"alice", //// "age":5 //// }, //// "pet2":{ //// "name":"alice", //// "age":5 //// } ////} //// ////{ //// "pet":{ //// "name":"bob", //// "age":5 //// }, //// "pet2":{ //// "name":"bob", //// "age":5 //// } ////} //// because they only differ on the name, but it gets repeated meaning that //// hash({"name":"bob", "age":5}) ^ hash({"name":"bob", "age":5}) is the same as //// hash({"name":"alice", "age":5}) ^ hash({"name":"alice", "age":5}) UInt192 intermediateHash = 0; // Property order should not result in a different hash. // This is consistent with equality comparison. foreach (KeyValuePair <string, CosmosElement> kvp in cosmosObject) { UInt192 nameHash = DistinctHash.GetHash( CosmosString.Create(kvp.Key), DistinctHash.PropertyNameHashSeed); UInt192 propertyHash = DistinctHash.GetHash(kvp.Value, nameHash); //// xor is symmetric meaning that a ^ b = b ^ a //// Which is great since now we can add the property hashes to the intermediate hash //// in any order and get the same result, which upholds our definition of equality. //// Note that we don't have to worry about a ^ a = 0 = b ^ b for duplicate property values, //// since the hash of property values are seeded with the hash of property names, //// which are unique within an object. intermediateHash ^= propertyHash; } // Only if the object was not empty do we want to bring in the intermediate hash. if (intermediateHash > 0) { hash = DistinctHash.GetHash(intermediateHash, hash); } return(hash); }
public CosmosElement Visit(FeedRangePartitionKeyRange feedRange) { return(CosmosObject.Create(new Dictionary <string, CosmosElement>() { { TypePropertyName, PhysicalPartitionKeyRangeIdCosmosElement }, { ValuePropertyName, CosmosString.Create(feedRange.PartitionKeyRangeId) }, })); }
public override string ToString() { return(CosmosObject.Create(new Dictionary <string, CosmosElement>() { { nameof(this.GroupingTableContinuationToken), CosmosString.Create(this.GroupingTableContinuationToken) }, { nameof(this.SourceContinuationToken), CosmosString.Create(this.SourceContinuationToken) } }).ToString()); }
public void TestString() { string value = "asdf"; ReadOnlyMemory <byte> result = JsonSerializer.Serialize(value); CosmosString cosmosString = (CosmosString)CosmosElement.CreateFromBuffer(result); Assert.AreEqual(expected: value, actual: cosmosString.Value.ToString()); }
public CosmosElement Visit(FeedRangePartitionKey feedRange) { return(CosmosObject.Create(new Dictionary <string, CosmosElement>() { { TypePropertyName, LogicalPartitionKeyCosmosElement }, { ValuePropertyName, CosmosString.Create(feedRange.PartitionKey.ToJsonString()) }, })); }
/// <summary> /// Visits a SqlAliasedCollectionExpression and transforms the documents accordingly. /// </summary> /// <param name="collectionExpression">The collection expression to visit.</param> /// <param name="documents">The documents to transform.</param> /// <returns>The transformed documents according to the collection expression.</returns> public override IEnumerable <CosmosElement> Visit(SqlAliasedCollectionExpression collectionExpression, IEnumerable <CosmosElement> documents) { //If the query was: //SELECT * //FROM c //and the document was: //{ // "name" : "John" //} //Then this function would return: //{ // "c" : { "name" : "John" } //} //which is just wrapping the original document in the identifier. // Get the sub collection CollectionEvaluationResult collectionEvaluationResult = collectionExpression.Collection.Accept( SqlInterpreterCollectionVisitor.Singleton, documents); string identifer = collectionEvaluationResult.Identifer; // Figure out what the alias should be int aliasCounter = 0; string alias; if (collectionExpression.Alias != null) { alias = collectionExpression.Alias.Value; } else if (identifer != null) { alias = identifer; } else { alias = $"#{aliasCounter++}"; } // Wrap the collection in the alias so it's easier to bind later foreach (Tuple <CosmosElement, string> subDocumentAndRid in collectionEvaluationResult.SubDocumentsAndRids) { Dictionary <string, CosmosElement> wrappedDocument = new Dictionary <string, CosmosElement> { [alias] = subDocumentAndRid.Item1, //// Add the _rid so that we can break ties for sort later ["_rid"] = CosmosString.Create(subDocumentAndRid.Item2) }; yield return(CosmosObject.Create(wrappedDocument)); } }
public static CosmosElement ToCosmosElement(VersionedAndRidCheckedCompositeToken token) { return(CosmosObject.Create( new Dictionary <string, CosmosElement>() { { PropertyNames.Version, CosmosNumber64.Create((long)token.VersionNumber) }, { PropertyNames.Rid, CosmosString.Create(token.Rid) }, { PropertyNames.Continuation, token.ContinuationToken }, })); }
public void UPPER() { // UPPER("\u00B5") // MICRO SIGN does not have an upper casing AssertEvaluation( expected: CosmosString.Create("\u00B5"), sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.Upper, SqlLiteralScalarExpression.Create(SqlStringLiteral.Create("\u00B5")))); }
public UInt128 Visit(CosmosString cosmosString, UInt128 seed) { UInt128 hash = seed == RootHashSeed ? RootCache.String : MurmurHash3.Hash128(HashSeeds.String, seed); UtfAnyString utfAnyString = cosmosString.Value; hash = utfAnyString.IsUtf8 ? MurmurHash3.Hash128(utfAnyString.ToUtf8String().Span.Span, hash) : MurmurHash3.Hash128(utfAnyString.ToString(), hash); return(hash); }
private static QueryState CreateQueryState(int count) { return(new QueryState( CosmosString.Create( CosmosObject.Create( new Dictionary <string, CosmosElement>() { { "continuationCount", CosmosNumber64.Create(++count) }, }) .ToString()))); }
private CosmosElement CreateVertexPropertyPrimitiveValueElement(object value) { return(value switch { bool boolValue => CosmosBoolean.Create(boolValue), double doubleValue => CosmosNumber64.Create(doubleValue), float floatValue => CosmosNumber64.Create(floatValue), int intValue => CosmosNumber64.Create(intValue), long longValue => CosmosNumber64.Create(longValue), string stringValue => CosmosString.Create(stringValue), _ => throw new AssertFailedException($"Invalid Gremlin property value object type: {value.GetType().Name}."), });
public void VerifyStringSort() { List <CosmosElement> manuallySortedList = new List <CosmosElement>() { CosmosString.Create(string.Empty), CosmosString.Create("a"), CosmosString.Create("b"), CosmosString.Create("c"), }; VerifySort(manuallySortedList); }
public override TryCatch <CrossPartitionState <ChangeFeedState> > Visit(ChangeFeedStartFromContinuationAndFeedRange startFromContinuationAndFeedRange) { ChangeFeedState state = ChangeFeedState.Continuation(CosmosString.Create(startFromContinuationAndFeedRange.Etag)); List <(FeedRangeInternal, ChangeFeedState)> rangesAndStates = new List <(FeedRangeInternal, ChangeFeedState)>() { (startFromContinuationAndFeedRange.FeedRange, state) }; CrossPartitionState <ChangeFeedState> crossPartitionState = new CrossPartitionState <ChangeFeedState>(rangesAndStates); return(TryCatch <CrossPartitionState <ChangeFeedState> > .FromResult(crossPartitionState)); }
public void SqlObjectCreateScalarExpressionTest() { CosmosObject expected = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["name"] = CosmosString.Create("John") }); SqlObjectCreateScalarExpression john = SqlObjectCreateScalarExpression.Create( SqlObjectProperty.Create(SqlPropertyName.Create("name"), SqlLiteralScalarExpression.Create(SqlStringLiteral.Create("John")))); AssertEvaluation(expected, john); }
public override string GetContinuationToken() { Dictionary <string, CosmosElement> aliasToContinuationToken = new Dictionary <string, CosmosElement>(); foreach (KeyValuePair <string, AggregateValue> kvp in this.aliasToValue) { aliasToContinuationToken[kvp.Key] = CosmosString.Create(kvp.Value.GetContinuationToken()); } CosmosObject cosmosObject = CosmosObject.Create(aliasToContinuationToken); return(cosmosObject.ToString()); }
public override string ToString() { return(CosmosObject.Create(new Dictionary <string, CosmosElement>() { { PipelineContinuationToken.VersionPropertyName, CosmosString.Create(this.Version.ToString()) }, { PipelineContinuationTokenV1.SourceContinuationTokenPropertyName, this.SourceContinuationToken }, }).ToString()); }
/// <summary> /// Visits a SqlArrayIteratorCollectionExpression and transforms the documents accordingly. /// </summary> /// <param name="collectionExpression">The collection expression to visit.</param> /// <param name="documents">The documents to transform.</param> /// <returns>The transformed documents according to the collection expression.</returns> public override IEnumerable <CosmosElement> Visit(SqlArrayIteratorCollectionExpression collectionExpression, IEnumerable <CosmosElement> documents) { //If the query was: //SELECT p //FROM p in c.parents //and the document was //{ // "parents" : [{"name" : "John"}, {"name" : "Sally"}] //} //then the results would be: //{ "p" : {"name" : "John"} } //and //{ "p" : {"name" : "Sally"} } //Notice that the result set is larger than the input //This is because we emitted one document for each parent in the original document //and wrapped it in the provided alias. // throw away the identifer since we always have an alias CollectionEvaluationResult collectionEvaluationResult = collectionExpression.Collection.Accept( SqlInterpreterCollectionVisitor.Singleton, documents); // Wrap the collection in the alias so it's easier to bind later foreach (Tuple <CosmosElement, string> subDocumentAndRid in collectionEvaluationResult.SubDocumentsAndRids) { CosmosElement document = subDocumentAndRid.Item1; string rid = subDocumentAndRid.Item2; if (document is CosmosArray array) { foreach (CosmosElement item in array) { Dictionary <string, CosmosElement> wrappedDocument = new Dictionary <string, CosmosElement> { [collectionExpression.Identifier.Value] = item, //// Add the _rid so that we can break ties for sort later ["_rid"] = CosmosString.Create(rid), }; yield return(CosmosObject.Create(wrappedDocument)); } } } }
public void RIGHT() { // Right("Hello", -3) AssertEvaluation( expected: CosmosString.Empty, sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.Right, hello, negativeThree)); // Right("Hello", 1.5) AssertEvaluation( expected: Undefined, sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.Right, hello, floatingPoint)); // Right("Hello", 0) AssertEvaluation( expected: CosmosString.Empty, sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.Right, hello, SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(0)))); // Right("Hello", 2) AssertEvaluation( expected: CosmosString.Create("lo"), sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.Right, hello, SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(2)))); // Right("Hello", 6) AssertEvaluation( expected: CosmosString.Create("Hello"), sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.Right, hello, six)); // Right("Hello", int.MaxValue + 1) AssertEvaluation( expected: CosmosString.Create("Hello"), sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin( SqlFunctionCallScalarExpression.Identifiers.Right, hello, SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create((long)int.MaxValue + 1)))); }
public CosmosElement Transform(ChangeFeedStateTime changeFeedStateTime) { return(CosmosObject.Create( new Dictionary <string, CosmosElement>() { { TypePropertyName, TimeTypeValueSingleton }, { ValuePropertyName, CosmosString.Create(changeFeedStateTime.StartTime.ToString( "o", CultureInfo.InvariantCulture)) } })); }