diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ClientDistributionPlanDeserializer.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ClientDistributionPlanDeserializer.cs new file mode 100644 index 0000000000..df19b88b3d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ClientDistributionPlanDeserializer.cs @@ -0,0 +1,561 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan +{ + using System; + using System.Collections.Generic; + using System.Reflection; + using Cql; + using Microsoft.Azure.Cosmos.CosmosElements; + + internal static class ClientDistributionPlanDeserializer + { + private static class Constants + { + public const string Arguments = "Arguments"; + public const string ArrayKind = "ArrayKind"; + public const string Aggregate = "Aggregate"; + public const string Aggregates = "Aggregates"; + public const string Builtin = "Builtin"; + public const string Cql = "Cql"; + public const string ConditionExpression = "ConditionExpression"; + public const string ClientDistributionPlan = "clientDistributionPlan"; + public const string DeclaredVariable = "DeclaredVariable"; + public const string DeclaredVariableExpression = "DeclaredVariableExpression"; + public const string Distinct = "Distinct"; + public const string EnumerationKind = "EnumerationKind"; + public const string Expression = "Expression"; + public const string FunctionKind = "FunctionKind"; + public const string GroupBy = "GroupBy"; + public const string Identifier = "Identifier"; + public const string Index = "Index"; + public const string Input = "Input"; + public const string Items = "Items"; + public const string KeyCount = "KeyCount"; + public const string Kind = "Kind"; + public const string LeftExpression = "LeftExpression"; + public const string Literal = "Literal"; + public const string MaxDepth = "MaxDepth"; + public const string Name = "Name"; + public const string ObjectKind = "ObjectKind"; + public const string OperatorKind = "OperatorKind"; + public const string Options = "Options"; + public const string OrderBy = "OrderBy"; + public const string Pattern = "Pattern"; + public const string Properties = "Properties"; + public const string PropertyName = "PropertyName"; + public const string RightExpression = "RightExpression"; + public const string ScalarAsEnumerable = "ScalarAsEnumerable"; + public const string Select = "Select"; + public const string SelectorExpression = "SelectorExpression"; + public const string SelectMany = "SelectMany"; + public const string SingletonKind = "SingletonKind"; + public const string SkipValue = "SkipValue"; + public const string SortOrder = "SortOrder"; + public const string SourceExpression = "SourceExpression"; + public const string Take = "Take"; + public const string TakeValue = "TakeValue"; + public const string Tuple = "Tuple"; + public const string Type = "Type"; + public const string UniqueId = "UniqueId"; + public const string Value = "Value"; + public const string Variable = "Variable"; + public const string Where = "Where"; + } + + public static ClientDistributionPlan DeserializeClientDistributionPlan(string jsonString) + { + CosmosObject cosmosObject = CosmosObject.Parse(jsonString); + CosmosObject clientDistributionPlanElement = GetValue(cosmosObject, Constants.ClientDistributionPlan); + CosmosObject cqlElement = GetValue(clientDistributionPlanElement, Constants.Cql); + CqlEnumerableExpression expression = DeserializeCqlEnumerableExpression(cqlElement); + + return new ClientDistributionPlan(expression); + } + + #region Enumerable Expressions + + private static CqlEnumerableExpression DeserializeCqlEnumerableExpression(CosmosObject cosmosObject) + { + CosmosString kindProperty = GetValue(cosmosObject, Constants.Kind); + switch (kindProperty.Value) + { + case Constants.Aggregate: + return DeserializeAggregateEnumerableExpression(cosmosObject); + case Constants.Distinct: + return DeserializeDistinctEnumerableExpression(cosmosObject); + case Constants.GroupBy: + return DeserializeGroupByEnumerableExpression(cosmosObject); + case Constants.Input: + return DeserializeInputEnumerableExpression(cosmosObject); + case Constants.OrderBy: + return DeserializeOrderByEnumerableExpression(cosmosObject); + case Constants.ScalarAsEnumerable: + return DeserializeScalarAsEnumerableExpression(cosmosObject); + case Constants.Select: + return DeserializeSelectEnumerableExpression(cosmosObject); + case Constants.SelectMany: + return DeserializeSelectManyEnumerableExpression(cosmosObject); + case Constants.Take: + return DeserializeTakeEnumerableExpression(cosmosObject); + case Constants.Where: + return DeserializeWhereEnumerableExpression(cosmosObject); + default: + throw new NotSupportedException($"Invalid CqlExpression kind: {kindProperty.Value}"); + } + } + + private static CqlAggregateEnumerableExpression DeserializeAggregateEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlAggregate aggregate = DeserializeAggregate(GetValue(cosmosObject, Constants.Aggregate)); + return new CqlAggregateEnumerableExpression(sourceExpression, aggregate); + } + + private static CqlDistinctEnumerableExpression DeserializeDistinctEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + IReadOnlyList expressions = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Expression)); + return new CqlDistinctEnumerableExpression(sourceExpression, declaredVariable, expressions); + } + + private static CqlGroupByEnumerableExpression DeserializeGroupByEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + long keyCount = Number64.ToLong(GetValue(cosmosObject, Constants.KeyCount).Value); + IReadOnlyList aggregates = DeserializeAggregateArray(GetValue(cosmosObject, Constants.Aggregates)); + return new CqlGroupByEnumerableExpression(sourceExpression, Convert.ToUInt64(keyCount), aggregates); + } + + private static CqlInputEnumerableExpression DeserializeInputEnumerableExpression(CosmosObject cosmosObject) + { + return new CqlInputEnumerableExpression(GetValue(cosmosObject, Constants.Name).Value); + } + + private static CqlOrderByEnumerableExpression DeserializeOrderByEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + IReadOnlyList orderByItems = DeserializeOrderByItemArray(GetValue(cosmosObject, Constants.Items)); + return new CqlOrderByEnumerableExpression(sourceExpression, declaredVariable, orderByItems); + } + + private static CqlScalarAsEnumerableExpression DeserializeScalarAsEnumerableExpression(CosmosObject cosmosObject) + { + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + CqlEnumerationKind enumerationKind = GetEnumValue(GetValue(cosmosObject, Constants.EnumerationKind).Value); + return new CqlScalarAsEnumerableExpression(expression, enumerationKind); + } + + private static CqlSelectEnumerableExpression DeserializeSelectEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + return new CqlSelectEnumerableExpression(sourceExpression, declaredVariable, expression); + } + + private static CqlSelectManyEnumerableExpression DeserializeSelectManyEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + CqlEnumerableExpression selectorExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SelectorExpression)); + return new CqlSelectManyEnumerableExpression(sourceExpression, declaredVariable, selectorExpression); + } + + private static CqlTakeEnumerableExpression DeserializeTakeEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + long skipValue = Number64.ToLong(GetValue(cosmosObject, Constants.SkipValue).Value); + long takeExpression = Number64.ToLong(GetValue(cosmosObject, Constants.TakeValue).Value); + return new CqlTakeEnumerableExpression(sourceExpression, Convert.ToUInt64(skipValue), Convert.ToUInt64(takeExpression)); + } + + private static CqlWhereEnumerableExpression DeserializeWhereEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + return new CqlWhereEnumerableExpression(sourceExpression, declaredVariable, expression); + } + + #endregion + + #region Scalar Expressions + + private static CqlScalarExpression DeserializeScalarExpression(CosmosObject cosmosObject) + { + CqlScalarExpressionKind scalarExpressionKind = GetEnumValue(GetValue(cosmosObject, Constants.Kind).Value); + switch (scalarExpressionKind) + { + case CqlScalarExpressionKind.ArrayCreate: + return DeserializeArrayCreateScalarExpression(cosmosObject); + case CqlScalarExpressionKind.ArrayIndexer: + return DeserializeArrayIndexerScalarExpression(cosmosObject); + case CqlScalarExpressionKind.BinaryOperator: + return DeserializeBinaryOperatorScalarExpression(cosmosObject); + case CqlScalarExpressionKind.IsOperator: + return DeserializeIsOperatorScalarExpression(cosmosObject); + case CqlScalarExpressionKind.Let: + return DeserializeLetScalarExpression(cosmosObject); + case CqlScalarExpressionKind.Literal: + return DeserializeLiteralScalarExpression(cosmosObject); + case CqlScalarExpressionKind.Mux: + return DeserializeMuxScalarExpression(cosmosObject); + case CqlScalarExpressionKind.ObjectCreate: + return DeserializeObjectCreateScalarExpression(cosmosObject); + case CqlScalarExpressionKind.PropertyRef: + return DeserializePropertyRefScalarExpression(cosmosObject); + case CqlScalarExpressionKind.SystemFunctionCall: + return DeserializeSystemFunctionCallScalarExpression(cosmosObject); + case CqlScalarExpressionKind.TupleCreate: + return DeserializeTupleCreateScalarExpression(cosmosObject); + case CqlScalarExpressionKind.TupleItemRef: + return DeserializeTupleItemRefScalarExpression(cosmosObject); + case CqlScalarExpressionKind.UnaryOperator: + return DeserializeUnaryScalarExpression(cosmosObject); + case CqlScalarExpressionKind.UserDefinedFunctionCall: + return DeserializeUserDefinedFunctionCallScalarExpression(cosmosObject); + case CqlScalarExpressionKind.VariableRef: + return DeserializeVariableRefScalarExpression(cosmosObject); + default: + throw new NotSupportedException($"Invalid CqlExpression kind: {scalarExpressionKind}"); + } + } + + private static CqlArrayCreateScalarExpression DeserializeArrayCreateScalarExpression(CosmosObject cosmosObject) + { + IReadOnlyList items = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Items)); + return new CqlArrayCreateScalarExpression(items); + } + + private static CqlArrayIndexerScalarExpression DeserializeArrayIndexerScalarExpression(CosmosObject cosmosObject) + { + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + long index = Number64.ToLong(GetValue(cosmosObject, Constants.Index).Value); + return new CqlArrayIndexerScalarExpression(expression, Convert.ToUInt64(index)); + } + + private static CqlBinaryScalarExpression DeserializeBinaryOperatorScalarExpression(CosmosObject cosmosObject) + { + CqlBinaryScalarOperatorKind operatorKind = GetEnumValue(GetValue(cosmosObject, Constants.OperatorKind).Value); + CqlScalarExpression leftExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.LeftExpression)); + CqlScalarExpression rightExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.RightExpression)); + return new CqlBinaryScalarExpression(operatorKind, leftExpression, rightExpression); + } + + private static CqlIsOperatorScalarExpression DeserializeIsOperatorScalarExpression(CosmosObject cosmosObject) + { + CqlIsOperatorKind operatorKind = GetEnumValue(GetValue(cosmosObject, Constants.OperatorKind).Value); + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + return new CqlIsOperatorScalarExpression(operatorKind, expression); + } + + private static CqlLetScalarExpression DeserializeLetScalarExpression(CosmosObject cosmosObject) + { + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + CqlScalarExpression declaredVariableExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.DeclaredVariableExpression)); + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + return new CqlLetScalarExpression(declaredVariable, declaredVariableExpression, expression); + } + + private static CqlLiteralScalarExpression DeserializeLiteralScalarExpression(CosmosObject cosmosObject) + { + CosmosObject literalObject = GetValue(cosmosObject, Constants.Literal); + return new CqlLiteralScalarExpression(DeserializeLiteral(literalObject)); + } + + private static CqlMuxScalarExpression DeserializeMuxScalarExpression(CosmosObject cosmosObject) + { + CqlScalarExpression conditionExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.ConditionExpression)); + CqlScalarExpression leftExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.LeftExpression)); + CqlScalarExpression rightExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.RightExpression)); + return new CqlMuxScalarExpression(conditionExpression, leftExpression, rightExpression); + } + + private static CqlObjectCreateScalarExpression DeserializeObjectCreateScalarExpression(CosmosObject cosmosObject) + { + IReadOnlyList properties = DeserializeObjectProperties(GetValue(cosmosObject, Constants.Properties)); + return new CqlObjectCreateScalarExpression(properties); + } + + private static CqlPropertyRefScalarExpression DeserializePropertyRefScalarExpression(CosmosObject cosmosObject) + { + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + string propertyName = GetValue(cosmosObject, Constants.PropertyName).Value; + return new CqlPropertyRefScalarExpression(expression, propertyName); + } + + private static CqlSystemFunctionCallScalarExpression DeserializeSystemFunctionCallScalarExpression(CosmosObject cosmosObject) + { + CqlBuiltinScalarFunctionKind functionKind = GetEnumValue(GetValue(cosmosObject, Constants.FunctionKind).Value); + IReadOnlyList arguments = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Arguments)); + return new CqlSystemFunctionCallScalarExpression(functionKind, arguments); + } + + private static CqlTupleCreateScalarExpression DeserializeTupleCreateScalarExpression(CosmosObject cosmosObject) + { + IReadOnlyList items = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Items)); + return new CqlTupleCreateScalarExpression(items); + } + + private static CqlTupleItemRefScalarExpression DeserializeTupleItemRefScalarExpression(CosmosObject cosmosObject) + { + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + long index = Number64.ToLong(GetValue(cosmosObject, Constants.Index).Value); + return new CqlTupleItemRefScalarExpression(expression, Convert.ToUInt64(index)); + } + + private static CqlUnaryScalarExpression DeserializeUnaryScalarExpression(CosmosObject cosmosObject) + { + CqlUnaryScalarOperatorKind operatorKind = GetEnumValue(GetValue(cosmosObject, Constants.OperatorKind).Value); + CqlScalarExpression scalarExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + return new CqlUnaryScalarExpression(operatorKind, scalarExpression); + } + + private static CqlUserDefinedFunctionCallScalarExpression DeserializeUserDefinedFunctionCallScalarExpression(CosmosObject cosmosObject) + { + string identifierString = GetValue(cosmosObject, Constants.Identifier).Value; + CqlFunctionIdentifier functionIdentifier = new CqlFunctionIdentifier(identifierString); + IReadOnlyList arguments = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Arguments)); + bool builtin = GetValue(cosmosObject, Constants.Builtin).Value; + return new CqlUserDefinedFunctionCallScalarExpression(functionIdentifier, arguments, builtin); + } + + private static CqlVariableRefScalarExpression DeserializeVariableRefScalarExpression(CosmosObject cosmosObject) + { + CqlVariable variable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.Variable)); + return new CqlVariableRefScalarExpression(variable); + } + + #endregion + + #region Aggregate + + private static IReadOnlyList DeserializeAggregateArray(CosmosArray cosmosArray) + { + List aggregates = new List(cosmosArray.Count); + foreach (CosmosElement aggregateElement in cosmosArray) + { + CosmosObject aggregateObject = CastToCosmosObject(aggregateElement); + aggregates.Add(DeserializeAggregate(aggregateObject)); + } + + return aggregates; + } + + private static CqlAggregate DeserializeAggregate(CosmosObject cosmosObject) + { + CqlAggregateKind aggregateKind = GetEnumValue(GetValue(cosmosObject, Constants.Kind).Value); + switch (aggregateKind) + { + case CqlAggregateKind.Builtin: + return DeserializeBuiltInAggregateExpression(cosmosObject); + case CqlAggregateKind.Tuple: + return DeserializeTupleAggregateExpression(cosmosObject); + default: + throw new NotSupportedException($"Invalid CqlExpression kind: {aggregateKind}"); + } + } + + private static CqlBuiltinAggregate DeserializeBuiltInAggregateExpression(CosmosObject cosmosObject) + { + CqlAggregateOperatorKind aggregateOperatorKind = GetEnumValue(GetValue(cosmosObject, Constants.OperatorKind).Value); + return new CqlBuiltinAggregate(aggregateOperatorKind); + } + + private static CqlTupleAggregate DeserializeTupleAggregateExpression(CosmosObject cosmosObject) + { + CosmosArray tupleArray = GetValue(cosmosObject, Constants.Items); + List aggregates = new List(tupleArray.Count); + + foreach (CosmosElement tupleElement in tupleArray) + { + CosmosObject tupleObject = CastToCosmosObject(tupleElement); + CqlAggregate aggregate = DeserializeAggregate(tupleObject); + aggregates.Add(aggregate); + } + + return new CqlTupleAggregate(aggregates); + } + + #endregion + + #region Literal + + private static CqlLiteral DeserializeLiteral(CosmosObject cosmosObject) + { + CqlLiteralKind literalKind = GetEnumValue(GetValue(cosmosObject, Constants.Kind).Value); + switch (literalKind) + { + case CqlLiteralKind.Array: + return new CqlArrayLiteral(DeserializeLiteralArray(GetValue(cosmosObject, Constants.Items))); + case CqlLiteralKind.Boolean: + return new CqlBooleanLiteral(GetValue(cosmosObject, Constants.Value).Value); + case CqlLiteralKind.Null: + return CqlNullLiteral.Singleton; + case CqlLiteralKind.Number: + return new CqlNumberLiteral(GetValue(cosmosObject, Constants.Value).Value); + case CqlLiteralKind.Object: + return new CqlObjectLiteral(DeserializeObjectLiteralArray(GetValue(cosmosObject, Constants.Properties))); + case CqlLiteralKind.String: + return new CqlStringLiteral(GetValue(cosmosObject, Constants.Value).Value); + case CqlLiteralKind.Undefined: + return CqlUndefinedLiteral.Singleton; + default: + throw new NotSupportedException($"Invalid CqlExpression kind: {literalKind}"); + } + } + + private static IReadOnlyList DeserializeLiteralArray(CosmosArray cosmosArray) + { + List literals = new List(cosmosArray.Count); + foreach (CosmosElement literalElement in cosmosArray) + { + CosmosObject literalObject = CastToCosmosObject(literalElement); + literals.Add(DeserializeLiteral(literalObject)); + } + + return literals; + } + + private static IReadOnlyList DeserializeObjectLiteralArray(CosmosArray cosmosArray) + { + List objectLiterals = new List(cosmosArray.Count); + foreach (CosmosElement objectLiteralElement in cosmosArray) + { + CosmosObject propertyObject = CastToCosmosObject(objectLiteralElement); + string name = GetValue(propertyObject, Constants.Name).Value; + CqlLiteral literal = DeserializeLiteral(propertyObject); + CqlObjectLiteralProperty objectLiteralProperty = new CqlObjectLiteralProperty(name, literal); + objectLiterals.Add(objectLiteralProperty); + } + + return objectLiterals; + } + + #endregion + + #region Helper Functions + + private static CqlVariable DeserializeCqlVariable(CosmosObject cosmosObject) + { + string name = GetValue(cosmosObject, Constants.Name).Value; + long uniqueId = Number64.ToLong(GetValue(cosmosObject, Constants.UniqueId).Value); + + return new CqlVariable(name, uniqueId); + } + + private static IReadOnlyList DeserializeObjectProperties(CosmosArray cosmosArray) + { + List properties = new List(cosmosArray.Count); + foreach (CosmosElement propertyElement in cosmosArray) + { + CosmosObject propertyObject = CastToCosmosObject(propertyElement); + string objectPropertyName = GetValue(propertyObject, Constants.Name).Value; + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(propertyObject, Constants.Expression)); + properties.Add(new CqlObjectProperty(objectPropertyName, expression)); + } + + return properties; + } + + private static IReadOnlyList DeserializeScalarExpressionArray(CosmosArray cosmosArray) + { + List expressions = new List(cosmosArray.Count); + foreach (CosmosElement itemElement in cosmosArray) + { + CosmosObject itemObject = CastToCosmosObject(itemElement); + CqlScalarExpression expression = DeserializeScalarExpression(itemObject); + expressions.Add(expression); + } + + return expressions; + } + + private static IReadOnlyList DeserializeOrderByItemArray(CosmosArray cosmosArray) + { + List expressions = new List(cosmosArray.Count); + foreach (CosmosElement itemElement in cosmosArray) + { + CosmosObject itemObject = CastToCosmosObject(itemElement); + CqlSortOrder sortOrder = GetEnumValue(GetValue(itemObject, Constants.SortOrder).Value); + CqlScalarExpression scalarExpression = DeserializeScalarExpression(itemObject); + expressions.Add(new CqlOrderByItem(scalarExpression, sortOrder)); + } + + return expressions; + } + + private static T GetValue(CosmosObject cosmosObject, string propertyName) + where T : CosmosElement + { + bool found = TryGetValue(cosmosObject, propertyName, out T value); + + if (!found) + { + throw new InvalidOperationException($"{GetExceptionMessage()} The required property {propertyName} was not found in {cosmosObject}"); + } + + return value; + } + + private static bool TryGetValue(CosmosObject cosmosObject, string propertyName, out T result) + where T : CosmosElement + { + bool found = cosmosObject.TryGetValue(propertyName, out CosmosElement value); + + if (found && value != null) + { + result = value as T; + if (result == null) + { + throw new InvalidOperationException($"{GetExceptionMessage()} Type mismatch for property {propertyName}. Expected {typeof(T)}, Actual {value?.GetType()}"); + } + + return found; + } + + result = default(T); + return found; + } + + private static TEnum GetEnumValue(string propertyName) + where TEnum : struct + { + bool success = Enum.TryParse(propertyName, ignoreCase: true, out TEnum result); + if (!success) + { + throw new InvalidOperationException($"{GetExceptionMessage()} The string representation of {propertyName} enumerated constant was not able to be converted to an equivalent enumerated object"); + } + + return result; + } + + private static string GetExceptionMessage() + { + Version sdkVersion = Assembly.GetAssembly(typeof(CosmosClient)).GetName().Version; + string clientSDKVersion = $"{sdkVersion.Major}.{sdkVersion.Minor}.{sdkVersion.Build}"; + + return $"Exception occurred while deserializing query plan. Version : '{clientSDKVersion}', Exception/Reason : "; + } + + private static CosmosObject CastToCosmosObject(CosmosElement cosmosElement) + { + CosmosObject propertyObject = cosmosElement as CosmosObject; + if (propertyObject != null) + { + return propertyObject; + } + else + { + throw new InvalidOperationException("Unable to cast CosmosElement to CosmosObject."); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/ClientDistributionPlan.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/ClientDistributionPlan.cs new file mode 100644 index 0000000000..51da84c03e --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/ClientDistributionPlan.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class ClientDistributionPlan + { + public ClientDistributionPlan(CqlEnumerableExpression cql) + { + this.Cql = cql ?? throw new ArgumentNullException(nameof(cql)); + } + + public CqlEnumerableExpression Cql { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregate.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregate.cs new file mode 100644 index 0000000000..3df9af326f --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregate.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal abstract class CqlAggregate + { + protected CqlAggregate(CqlAggregateKind kind) + { + this.Kind = kind; + } + + public CqlAggregateKind Kind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateEnumerableExpression.cs new file mode 100644 index 0000000000..eb4a09a966 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateEnumerableExpression.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlAggregateEnumerableExpression : CqlEnumerableExpression + { + public CqlAggregateEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlAggregate aggregate) + : base(CqlEnumerableExpressionKind.Aggregate) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.Aggregate = aggregate ?? throw new ArgumentNullException(nameof(aggregate)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlAggregate Aggregate { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateKind.cs new file mode 100644 index 0000000000..c25ae41bb8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateKind.cs @@ -0,0 +1,12 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlAggregateKind + { + Builtin, + Tuple, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateOperatorKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateOperatorKind.cs new file mode 100644 index 0000000000..57c1955b74 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateOperatorKind.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlAggregateOperatorKind + { + All, + Any, + Array, + Count, + First, + Last, + Max, + Min, + Sum, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayCreateScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayCreateScalarExpression.cs new file mode 100644 index 0000000000..84b829179c --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayCreateScalarExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlArrayCreateScalarExpression : CqlScalarExpression + { + private const string Array = "Array"; + + public CqlArrayCreateScalarExpression(IReadOnlyList items) + : base(CqlScalarExpressionKind.ArrayCreate) + { + this.ArrayKind = Array; + this.Items = items ?? throw new ArgumentNullException(nameof(items)); + } + + public string ArrayKind { get; } + + public IReadOnlyList Items { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayIndexerScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayIndexerScalarExpression.cs new file mode 100644 index 0000000000..65d280a02e --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayIndexerScalarExpression.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlArrayIndexerScalarExpression : CqlScalarExpression + { + public CqlArrayIndexerScalarExpression(CqlScalarExpression expression, ulong index) + : base(CqlScalarExpressionKind.ArrayIndexer) + { + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + this.Index = index; + } + + public CqlScalarExpression Expression { get; } + + public ulong Index { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayLiteral.cs new file mode 100644 index 0000000000..a50036123d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayLiteral.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlArrayLiteral : CqlLiteral + { + public CqlArrayLiteral(IReadOnlyList items) + : base(CqlLiteralKind.Array) + { + this.Items = items ?? throw new ArgumentNullException(nameof(items)); + } + + public IReadOnlyList Items { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarExpression.cs new file mode 100644 index 0000000000..9f3a382fd0 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlBinaryScalarExpression : CqlScalarExpression + { + public CqlBinaryScalarExpression(CqlBinaryScalarOperatorKind operatorKind, CqlScalarExpression leftExpression, CqlScalarExpression rightExpression) + : base(CqlScalarExpressionKind.BinaryOperator) + { + this.OperatorKind = operatorKind; + this.LeftExpression = leftExpression ?? throw new ArgumentNullException(nameof(leftExpression)); + this.RightExpression = rightExpression ?? throw new ArgumentNullException(nameof(rightExpression)); + } + + public CqlBinaryScalarOperatorKind OperatorKind { get; } + + public CqlScalarExpression LeftExpression { get; } + + public CqlScalarExpression RightExpression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarOperatorKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarOperatorKind.cs new file mode 100644 index 0000000000..c41a740994 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarOperatorKind.cs @@ -0,0 +1,29 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlBinaryScalarOperatorKind + { + Add, + And, + BitwiseAnd, + BitwiseOr, + BitwiseXor, + Divide, + Equal, + GreaterThan, + GreaterThanOrEqual, + LeftShift, + LessThan, + LessThanOrEqual, + Modulo, + Multiply, + NotEqual, + Or, + RightShift, + Subtract, + ZeroFillRightShift + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBooleanLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBooleanLiteral.cs new file mode 100644 index 0000000000..06f06b4e64 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBooleanLiteral.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal class CqlBooleanLiteral : CqlLiteral + { + public CqlBooleanLiteral(bool value) + : base(CqlLiteralKind.Boolean) + { + this.Value = value; + } + + public bool Value { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinAggregate.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinAggregate.cs new file mode 100644 index 0000000000..8dcebf5bb8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinAggregate.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal class CqlBuiltinAggregate : CqlAggregate + { + public CqlBuiltinAggregate(CqlAggregateOperatorKind operatorKind) + : base(CqlAggregateKind.Builtin) + { + this.OperatorKind = operatorKind; + } + + public CqlAggregateOperatorKind OperatorKind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinScalarFunctionKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinScalarFunctionKind.cs new file mode 100644 index 0000000000..ae59e55cf1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinScalarFunctionKind.cs @@ -0,0 +1,126 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlBuiltinScalarFunctionKind + { + Abs, + Acos, + All, + Any, + Array, + Array_Concat, + Array_Contains, + Array_Length, + Array_Slice, + Asin, + Atan, + Atn2, + Avg, + Ceiling, + Choose, + Concat, + Contains, + Cos, + Cot, + Count, + DateTimeAdd, + DateTimeBin, + DateTimeDiff, + DateTimeFromParts, + DateTimePart, + DateTimeToTicks, + DateTimeToTimestamp, + Degrees, + DocumentId, + EndsWith, + Exp, + First, + Floor, + GetCurrentDateTime, + GetCurrentDateTimeStatic, + GetCurrentTicks, + GetCurrentTicksStatic, + GetCurrentTimestamp, + GetCurrentTimestampStatic, + Iif, + Index_Of, + IntAdd, + IntBitAnd, + IntBitLeftShift, + IntBitNot, + IntBitOr, + IntBitRightShift, + IntBitXor, + IntDiv, + IntMod, + IntMul, + IntSub, + Is_Array, + Is_Bool, + Is_DateTime, + Is_Defined, + Is_Finite_Number, + Is_Integer, + Is_Null, + Is_Number, + Is_Object, + Is_Primitive, + Is_String, + Last, + LastIndexOf, + Left, + Length, + Like, + Log, + Log10, + Lower, + Ltrim, + Max, + Min, + NumberBin, + ObjectToArray, + Pi, + Power, + Radians, + Rand, + RegexMatch, + Replace, + Replicate, + Reverse, + Right, + Round, + Rtrim, + SetDifference, + SetIntersect, + SetUnion, + Sign, + Sin, + Sqrt, + Square, + ST_Area, + ST_Distance, + ST_Intersects, + ST_IsValid, + ST_IsValidDetailed, + ST_Within, + StartsWith, + StringEquals, + StringToArray, + StringToBoolean, + StringToNull, + StringToNumber, + StringToObject, + Substring, + Sum, + Tan, + TicksToDateTime, + TimestampToDateTime, + ToString, + Trim, + Trunc, + Upper + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlDistinctEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlDistinctEnumerableExpression.cs new file mode 100644 index 0000000000..8fa7515235 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlDistinctEnumerableExpression.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlDistinctEnumerableExpression : CqlEnumerableExpression + { + public CqlDistinctEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlVariable declaredVariable, IReadOnlyList expression) + : base(CqlEnumerableExpressionKind.Distinct) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlVariable DeclaredVariable { get; } + + public IReadOnlyList Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpression.cs new file mode 100644 index 0000000000..7b30bdc629 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpression.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal abstract class CqlEnumerableExpression + { + protected CqlEnumerableExpression(CqlEnumerableExpressionKind kind) + { + this.Kind = kind; + } + + public CqlEnumerableExpressionKind Kind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpressionKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpressionKind.cs new file mode 100644 index 0000000000..11b135895d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpressionKind.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlEnumerableExpressionKind + { + Aggregate, + Distinct, + GroupBy, + Input, + OrderBy, + ScalarAsEnumerable, + Select, + SelectMany, + Take, + Where, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerationKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerationKind.cs new file mode 100644 index 0000000000..60d96d2703 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerationKind.cs @@ -0,0 +1,14 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlEnumerationKind + { + ArrayItems, + PropertyValues, + Children, + Descendants, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlFunctionIdentifier.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlFunctionIdentifier.cs new file mode 100644 index 0000000000..16a717bdfe --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlFunctionIdentifier.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlFunctionIdentifier + { + public CqlFunctionIdentifier(string name) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + } + + public string Name { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlGroupByEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlGroupByEnumerableExpression.cs new file mode 100644 index 0000000000..b3efe8cb5d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlGroupByEnumerableExpression.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlGroupByEnumerableExpression : CqlEnumerableExpression + { + public CqlGroupByEnumerableExpression(CqlEnumerableExpression sourceExpression, ulong keyCount, IReadOnlyList aggregates) + : base(CqlEnumerableExpressionKind.GroupBy) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.KeyCount = keyCount; + this.Aggregates = aggregates ?? throw new ArgumentNullException(nameof(aggregates)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public ulong KeyCount { get; } + + public IReadOnlyList Aggregates { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlInputEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlInputEnumerableExpression.cs new file mode 100644 index 0000000000..a9a1ba8d6f --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlInputEnumerableExpression.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlInputEnumerableExpression : CqlEnumerableExpression + { + public CqlInputEnumerableExpression(string name) + : base(CqlEnumerableExpressionKind.Input) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + } + + public string Name { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorKind.cs new file mode 100644 index 0000000000..84a8e17601 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorKind.cs @@ -0,0 +1,11 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlIsOperatorKind + { + Defined, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorScalarExpression.cs new file mode 100644 index 0000000000..c1aa03907d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorScalarExpression.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlIsOperatorScalarExpression : CqlScalarExpression + { + public CqlIsOperatorScalarExpression(CqlIsOperatorKind operatorKind, CqlScalarExpression expression) + : base(CqlScalarExpressionKind.IsOperator) + { + this.OperatorKind = operatorKind; + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlIsOperatorKind OperatorKind { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLetScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLetScalarExpression.cs new file mode 100644 index 0000000000..329e2f36cd --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLetScalarExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlLetScalarExpression : CqlScalarExpression + { + public CqlLetScalarExpression(CqlVariable declaredVariable, CqlScalarExpression declaredVariableExpression, CqlScalarExpression expression) + : base(CqlScalarExpressionKind.Let) + { + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.DeclaredVariableExpression = declaredVariableExpression ?? throw new ArgumentNullException(nameof(declaredVariableExpression)); + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlVariable DeclaredVariable { get; } + + public CqlScalarExpression DeclaredVariableExpression { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteral.cs new file mode 100644 index 0000000000..d5b17b06ac --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteral.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal abstract class CqlLiteral + { + protected CqlLiteral(CqlLiteralKind kind) + { + this.Kind = kind; + } + + public CqlLiteralKind Kind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralKind.cs new file mode 100644 index 0000000000..e03b18a28a --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralKind.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlLiteralKind + { + Undefined, + Array, + Boolean, + Null, + Number, + Object, + String, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralScalarExpression.cs new file mode 100644 index 0000000000..ebc82d9048 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralScalarExpression.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlLiteralScalarExpression : CqlScalarExpression + { + public CqlLiteralScalarExpression(CqlLiteral literal) + : base(CqlScalarExpressionKind.Literal) + { + this.Literal = literal ?? throw new ArgumentNullException(nameof(literal)); + } + + public CqlLiteral Literal { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlMuxScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlMuxScalarExpression.cs new file mode 100644 index 0000000000..0ebb3cab53 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlMuxScalarExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlMuxScalarExpression : CqlScalarExpression + { + public CqlMuxScalarExpression(CqlScalarExpression conditionExpression, CqlScalarExpression leftExpression, CqlScalarExpression rightExpression) + : base(CqlScalarExpressionKind.Mux) + { + this.ConditionExpression = conditionExpression ?? throw new ArgumentNullException(nameof(conditionExpression)); + this.LeftExpression = leftExpression ?? throw new ArgumentNullException(nameof(leftExpression)); + this.RightExpression = rightExpression ?? throw new ArgumentNullException(nameof(rightExpression)); + } + + public CqlScalarExpression ConditionExpression { get; } + + public CqlScalarExpression LeftExpression { get; } + + public CqlScalarExpression RightExpression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNullLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNullLiteral.cs new file mode 100644 index 0000000000..53696840b1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNullLiteral.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal class CqlNullLiteral : CqlLiteral + { + public static readonly CqlNullLiteral Singleton = new CqlNullLiteral(); + + private CqlNullLiteral() + : base(CqlLiteralKind.Null) + { + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNumberLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNumberLiteral.cs new file mode 100644 index 0000000000..28769462d7 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNumberLiteral.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System.Collections.Generic; + + internal class CqlNumberLiteral : CqlLiteral + { + public CqlNumberLiteral(Number64 value) + : base(CqlLiteralKind.Number) + { + this.Value = value; + } + + public Number64 Value { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectCreateScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectCreateScalarExpression.cs new file mode 100644 index 0000000000..1bcd44e106 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectCreateScalarExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlObjectCreateScalarExpression : CqlScalarExpression + { + private const string Object = "Object"; + + public CqlObjectCreateScalarExpression(IReadOnlyList properties) + : base(CqlScalarExpressionKind.ObjectCreate) + { + this.Properties = properties ?? throw new ArgumentNullException(nameof(properties)); + this.ObjectKind = Object; + } + + public IReadOnlyList Properties { get; } + + public string ObjectKind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteral.cs new file mode 100644 index 0000000000..e5ba8ff343 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteral.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlObjectLiteral : CqlLiteral + { + public CqlObjectLiteral(IReadOnlyList properties) + : base(CqlLiteralKind.Object) + { + this.Properties = properties ?? throw new ArgumentNullException(nameof(properties)); + } + + public IReadOnlyList Properties { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteralProperty.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteralProperty.cs new file mode 100644 index 0000000000..4a063d4449 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteralProperty.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlObjectLiteralProperty + { + public CqlObjectLiteralProperty(string name, CqlLiteral literal) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + this.Literal = literal ?? throw new ArgumentNullException(nameof(literal)); + } + + public string Name { get; } + + public CqlLiteral Literal { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectProperty.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectProperty.cs new file mode 100644 index 0000000000..7b97de1620 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectProperty.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlObjectProperty + { + public CqlObjectProperty(string name, CqlScalarExpression expression) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public string Name { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByEnumerableExpression.cs new file mode 100644 index 0000000000..b4b9603841 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByEnumerableExpression.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlOrderByEnumerableExpression : CqlEnumerableExpression + { + public CqlOrderByEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlVariable declaredVariable, IReadOnlyList items) + : base(CqlEnumerableExpressionKind.OrderBy) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.Items = items ?? throw new ArgumentNullException(nameof(items)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlVariable DeclaredVariable { get; } + + public IReadOnlyList Items { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByItem.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByItem.cs new file mode 100644 index 0000000000..8fb4a73810 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByItem.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlOrderByItem + { + public CqlOrderByItem(CqlScalarExpression expression, CqlSortOrder sortOrder) + { + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + this.SortOrder = sortOrder; + } + + public CqlScalarExpression Expression { get; } + + public CqlSortOrder SortOrder { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlPropertyRefScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlPropertyRefScalarExpression.cs new file mode 100644 index 0000000000..e93a31fe3e --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlPropertyRefScalarExpression.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlPropertyRefScalarExpression : CqlScalarExpression + { + public CqlPropertyRefScalarExpression(CqlScalarExpression expression, string propertyName) + : base(CqlScalarExpressionKind.PropertyRef) + { + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + this.PropertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName)); + } + + public CqlScalarExpression Expression { get; } + + public string PropertyName { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarAsEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarAsEnumerableExpression.cs new file mode 100644 index 0000000000..0d69d8b424 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarAsEnumerableExpression.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlScalarAsEnumerableExpression : CqlEnumerableExpression + { + public CqlScalarAsEnumerableExpression(CqlScalarExpression expression, CqlEnumerationKind enumerationKind) + : base(CqlEnumerableExpressionKind.ScalarAsEnumerable) + { + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + this.EnumerationKind = enumerationKind; + } + + public CqlScalarExpression Expression { get; } + + public CqlEnumerationKind EnumerationKind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpression.cs new file mode 100644 index 0000000000..659bdc5f58 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpression.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal abstract class CqlScalarExpression + { + protected CqlScalarExpression(CqlScalarExpressionKind kind) + { + this.Kind = kind; + } + + public CqlScalarExpressionKind Kind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpressionKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpressionKind.cs new file mode 100644 index 0000000000..fede841576 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpressionKind.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlScalarExpressionKind + { + ArrayCreate, + ArrayIndexer, + BinaryOperator, + IsOperator, + Let, + Literal, + Mux, + ObjectCreate, + PropertyRef, + SystemFunctionCall, + TupleCreate, + TupleItemRef, + UnaryOperator, + UserDefinedFunctionCall, + VariableRef, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectEnumerableExpression.cs new file mode 100644 index 0000000000..0d052e980b --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectEnumerableExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlSelectEnumerableExpression : CqlEnumerableExpression + { + public CqlSelectEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlVariable declaredVariable, CqlScalarExpression expression) + : base(CqlEnumerableExpressionKind.Select) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlVariable DeclaredVariable { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectManyEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectManyEnumerableExpression.cs new file mode 100644 index 0000000000..e34d4ba874 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectManyEnumerableExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlSelectManyEnumerableExpression : CqlEnumerableExpression + { + public CqlSelectManyEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlVariable declaredVariable, CqlEnumerableExpression selectorExpression) + : base(CqlEnumerableExpressionKind.SelectMany) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.SelectorExpression = selectorExpression ?? throw new ArgumentNullException(nameof(selectorExpression)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlVariable DeclaredVariable { get; } + + public CqlEnumerableExpression SelectorExpression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSortOrder.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSortOrder.cs new file mode 100644 index 0000000000..efd5aaeb42 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSortOrder.cs @@ -0,0 +1,12 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlSortOrder + { + Ascending, + Descending + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlStringLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlStringLiteral.cs new file mode 100644 index 0000000000..a20947b0dd --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlStringLiteral.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlStringLiteral : CqlLiteral + { + public CqlStringLiteral(string value) + : base(CqlLiteralKind.String) + { + this.Value = value ?? throw new ArgumentNullException(nameof(value)); + } + + public string Value { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSystemFunctionCallScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSystemFunctionCallScalarExpression.cs new file mode 100644 index 0000000000..d42ee09f15 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSystemFunctionCallScalarExpression.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlSystemFunctionCallScalarExpression : CqlScalarExpression + { + public CqlSystemFunctionCallScalarExpression(CqlBuiltinScalarFunctionKind functionKind, IReadOnlyList arguments) + : base(CqlScalarExpressionKind.SystemFunctionCall) + { + this.FunctionKind = functionKind; + this.Arguments = arguments ?? throw new ArgumentNullException(nameof(arguments)); + } + + public CqlBuiltinScalarFunctionKind FunctionKind { get; } + + public IReadOnlyList Arguments { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTakeEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTakeEnumerableExpression.cs new file mode 100644 index 0000000000..0391db64fd --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTakeEnumerableExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlTakeEnumerableExpression : CqlEnumerableExpression + { + public CqlTakeEnumerableExpression(CqlEnumerableExpression sourceExpression, ulong skipValue, ulong takeValue) + : base(CqlEnumerableExpressionKind.Take) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.SkipValue = skipValue; + this.TakeValue = takeValue; + } + + public CqlEnumerableExpression SourceExpression { get; } + + public ulong SkipValue { get; } + + public ulong TakeValue { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleAggregate.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleAggregate.cs new file mode 100644 index 0000000000..6f553c1ec8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleAggregate.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlTupleAggregate : CqlAggregate + { + public CqlTupleAggregate(IReadOnlyList items) + : base(CqlAggregateKind.Tuple) + { + this.Items = items ?? throw new ArgumentNullException(nameof(items)); + } + + public IReadOnlyList Items { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleCreateScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleCreateScalarExpression.cs new file mode 100644 index 0000000000..0c30e79d33 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleCreateScalarExpression.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlTupleCreateScalarExpression : CqlScalarExpression + { + public CqlTupleCreateScalarExpression(IReadOnlyList items) + : base(CqlScalarExpressionKind.TupleCreate) + { + this.Items = items ?? throw new ArgumentNullException(nameof(items)); + } + + public IReadOnlyList Items { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleItemRefScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleItemRefScalarExpression.cs new file mode 100644 index 0000000000..bc011cecf7 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleItemRefScalarExpression.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlTupleItemRefScalarExpression : CqlScalarExpression + { + public CqlTupleItemRefScalarExpression(CqlScalarExpression expression, ulong index) + : base(CqlScalarExpressionKind.TupleItemRef) + { + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + this.Index = index; + } + + public CqlScalarExpression Expression { get; } + + public ulong Index { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarExpression.cs new file mode 100644 index 0000000000..8131ea618d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarExpression.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlUnaryScalarExpression : CqlScalarExpression + { + public CqlUnaryScalarExpression(CqlUnaryScalarOperatorKind operatorKind, CqlScalarExpression expression) + : base(CqlScalarExpressionKind.UnaryOperator) + { + this.OperatorKind = operatorKind; + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlUnaryScalarOperatorKind OperatorKind { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarOperatorKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarOperatorKind.cs new file mode 100644 index 0000000000..30c0cedc54 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarOperatorKind.cs @@ -0,0 +1,14 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlUnaryScalarOperatorKind + { + BitwiseNot, + Minus, + Not, + Plus + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUndefinedLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUndefinedLiteral.cs new file mode 100644 index 0000000000..ecc8d556b2 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUndefinedLiteral.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal class CqlUndefinedLiteral : CqlLiteral + { + public static readonly CqlUndefinedLiteral Singleton = new CqlUndefinedLiteral(); + + private CqlUndefinedLiteral() + : base(CqlLiteralKind.Undefined) + { + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUserDefinedFunctionCallScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUserDefinedFunctionCallScalarExpression.cs new file mode 100644 index 0000000000..fda301a6a1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUserDefinedFunctionCallScalarExpression.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlUserDefinedFunctionCallScalarExpression : CqlScalarExpression + { + public CqlUserDefinedFunctionCallScalarExpression(CqlFunctionIdentifier identifier, IReadOnlyList arguments, bool builtin) + : base(CqlScalarExpressionKind.UserDefinedFunctionCall) + { + this.Identifier = identifier ?? throw new ArgumentNullException(nameof(identifier)); + this.Arguments = arguments ?? throw new ArgumentNullException(nameof(arguments)); + this.Builtin = builtin; + } + + public CqlFunctionIdentifier Identifier { get; } + + public IReadOnlyList Arguments { get; } + + public bool Builtin { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariable.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariable.cs new file mode 100644 index 0000000000..73cbac8324 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariable.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlVariable + { + public CqlVariable(string name, long uniqueId) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + this.UniqueId = uniqueId; + } + + public string Name { get; } + + public long UniqueId { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariableRefScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariableRefScalarExpression.cs new file mode 100644 index 0000000000..a909fb39a1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariableRefScalarExpression.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlVariableRefScalarExpression : CqlScalarExpression + { + public CqlVariableRefScalarExpression(CqlVariable variable) + : base(CqlScalarExpressionKind.VariableRef) + { + this.Variable = variable ?? throw new ArgumentNullException(nameof(variable)); + } + + public CqlVariable Variable { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlWhereEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlWhereEnumerableExpression.cs new file mode 100644 index 0000000000..3f6db64aa2 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlWhereEnumerableExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlWhereEnumerableExpression : CqlEnumerableExpression + { + public CqlWhereEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlVariable declaredVariable, CqlScalarExpression expression) + : base(CqlEnumerableExpressionKind.Where) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlVariable DeclaredVariable { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ClientDistributionPlanBaselineTests.TestClientDistributionPlanDeserialization.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ClientDistributionPlanBaselineTests.TestClientDistributionPlanDeserialization.xml new file mode 100644 index 0000000000..c59b58aef1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ClientDistributionPlanBaselineTests.TestClientDistributionPlanDeserialization.xml @@ -0,0 +1,606 @@ + + + + Input Expression + {"clientDistributionPlan": {"Cql": {"Kind": "Input","Name": "root"}}} + + + { + "Cql": { + "Name": "root", + "Kind": 3 + } +} + + + + + Aggregate and ObjectCreate Expressions + {"clientDistributionPlan": {"Cql": {"Kind": "Select","DeclaredVariable": {"Name": "v0","UniqueId": 6},"Expression": {"Kind": "ObjectCreate","ObjectKind": "Object","Properties": [{"Name": "count_a","Expression": {"Kind": "VariableRef","Variable": {"Name": "v0","UniqueId": 6}}}]},"SourceExpression": {"Kind": "Aggregate","Aggregate": {"Kind": "Builtin","OperatorKind": "Sum"},"SourceExpression": {"Kind": "Input","Name": "root"}}}}} + + + { + "Cql": { + "SourceExpression": { + "SourceExpression": { + "Name": "root", + "Kind": 3 + }, + "Aggregate": { + "OperatorKind": 8, + "Kind": 0 + }, + "Kind": 0 + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Properties": [ + { + "Name": "count_a", + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 6 + }, + "Kind": 14 + } + } + ], + "ObjectKind": "Object", + "Kind": 7 + }, + "Kind": 6 + } +} + + + + + Select, Aggregate and BinaryOperator Expressions + {"clientDistributionPlan": {"Cql": { "Kind": "Select", "DeclaredVariable": {"Name": "v0","UniqueId": 10 }, "Expression": {"Kind": "ObjectCreate","ObjectKind": "Object","Properties": [ {"Name": "F1","Expression": { "Kind": "ObjectCreate", "ObjectKind": "Object", "Properties": [{ "Name": "FieldA", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 0 }},{ "Name": "FieldSum", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 1 }},{ "Name": "FieldAvg", "Expression": {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "Equal", "LeftExpression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 10} }, "Index": 2},"Index": 1 }, "RightExpression": {"Kind": "Literal","Literal": { "Kind": "Number", "Value": 0} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Undefined" }},"RightExpression": { "Kind": "BinaryOperator", "OperatorKind": "Divide", "LeftExpression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 10} }, "Index": 2},"Index": 0 }, "RightExpression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 10} }, "Index": 2},"Index": 1 }}}}]}}, {"Name": "F2","Expression": { "Kind": "ObjectCreate", "ObjectKind": "Object", "Properties": [{ "Name": "OtherFieldA", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 0 }},{ "Name": "OtherFieldMax", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 3 }} ]} }] }, "SourceExpression": {"Kind": "GroupBy","KeyCount": 1,"Aggregates": [ {"Kind": "Builtin","OperatorKind": "Sum" }, {"Kind": "Tuple","Items": [ {"Kind": "Builtin","OperatorKind": "Sum" }, {"Kind": "Builtin","OperatorKind": "Sum" }] }, {"Kind": "Builtin","OperatorKind": "Max" }],"SourceExpression": { "Kind": "Select", "DeclaredVariable": {"Name": "v0","UniqueId": 16 }, "Expression": {"Kind": "TupleCreate","Items": [ {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 0 }, {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "And", "LeftExpression": {"Kind": "BinaryOperator","OperatorKind": "NotEqual","LeftExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 1 }, "Index": 1},"RightExpression": { "Kind": "Literal", "Literal": {"Kind": "Number","Value": 0 }} }, "RightExpression": {"Kind": "UnaryOperator","OperatorKind": "Not","Expression": { "Kind": "SystemFunctionCall", "FunctionKind": "Is_Defined", "Arguments": [{ "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 1 }, "Index": 0} ]} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Array","Items": [] }},"RightExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 1 }, "Index": 0} }, {"Kind": "TupleCreate","Items": [ {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "And", "LeftExpression": {"Kind": "BinaryOperator","OperatorKind": "NotEqual","LeftExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 16} }, "Index": 2},"Index": 0 }, "Index": 1},"RightExpression": { "Kind": "Literal", "Literal": {"Kind": "Number","Value": 0 }} }, "RightExpression": {"Kind": "UnaryOperator","OperatorKind": "Not","Expression": { "Kind": "SystemFunctionCall", "FunctionKind": "Is_Defined", "Arguments": [{ "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 16} }, "Index": 2},"Index": 0 }, "Index": 0} ]} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Array","Items": [] }},"RightExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 2 }, "Index": 0} }, {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 16} }, "Index": 2},"Index": 1 }] }, {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "And", "LeftExpression": {"Kind": "BinaryOperator","OperatorKind": "NotEqual","LeftExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 3 }, "Index": 1},"RightExpression": { "Kind": "Literal", "Literal": {"Kind": "Number","Value": 0 }} }, "RightExpression": {"Kind": "UnaryOperator","OperatorKind": "Not","Expression": { "Kind": "SystemFunctionCall", "FunctionKind": "Is_Defined", "Arguments": [{ "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 3 }, "Index": 0} ]} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Array","Items": [] }},"RightExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16}},"Index": 3}, "Index": 0}}]}, "SourceExpression": {"Kind": "Input","Name": "root"}}}}}} + + + { + "Cql": { + "SourceExpression": { + "SourceExpression": { + "SourceExpression": { + "Name": "root", + "Kind": 3 + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 16 + }, + "Expression": { + "Items": [ + { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 0, + "Kind": 11 + }, + { + "ConditionExpression": { + "OperatorKind": 1, + "LeftExpression": { + "OperatorKind": 14, + "LeftExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 1, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + }, + "RightExpression": { + "Literal": { + "Value": 0, + "Kind": 4 + }, + "Kind": 5 + }, + "Kind": 2 + }, + "RightExpression": { + "OperatorKind": 2, + "Expression": { + "FunctionKind": 55, + "Arguments": [ + { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 1, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + } + ], + "Kind": 9 + }, + "Kind": 12 + }, + "Kind": 2 + }, + "LeftExpression": { + "Literal": { + "Items": [], + "Kind": 1 + }, + "Kind": 5 + }, + "RightExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 1, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "Kind": 6 + }, + { + "Items": [ + { + "ConditionExpression": { + "OperatorKind": 1, + "LeftExpression": { + "OperatorKind": 14, + "LeftExpression": { + "Expression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + }, + "RightExpression": { + "Literal": { + "Value": 0, + "Kind": 4 + }, + "Kind": 5 + }, + "Kind": 2 + }, + "RightExpression": { + "OperatorKind": 2, + "Expression": { + "FunctionKind": 55, + "Arguments": [ + { + "Expression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + } + ], + "Kind": 9 + }, + "Kind": 12 + }, + "Kind": 2 + }, + "LeftExpression": { + "Literal": { + "Items": [], + "Kind": 1 + }, + "Kind": 5 + }, + "RightExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "Kind": 6 + }, + { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + } + ], + "Kind": 10 + }, + { + "ConditionExpression": { + "OperatorKind": 1, + "LeftExpression": { + "OperatorKind": 14, + "LeftExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 3, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + }, + "RightExpression": { + "Literal": { + "Value": 0, + "Kind": 4 + }, + "Kind": 5 + }, + "Kind": 2 + }, + "RightExpression": { + "OperatorKind": 2, + "Expression": { + "FunctionKind": 55, + "Arguments": [ + { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 3, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + } + ], + "Kind": 9 + }, + "Kind": 12 + }, + "Kind": 2 + }, + "LeftExpression": { + "Literal": { + "Items": [], + "Kind": 1 + }, + "Kind": 5 + }, + "RightExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 3, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "Kind": 6 + } + ], + "Kind": 10 + }, + "Kind": 6 + }, + "KeyCount": 1, + "Aggregates": [ + { + "OperatorKind": 8, + "Kind": 0 + }, + { + "Items": [ + { + "OperatorKind": 8, + "Kind": 0 + }, + { + "OperatorKind": 8, + "Kind": 0 + } + ], + "Kind": 1 + }, + { + "OperatorKind": 6, + "Kind": 0 + } + ], + "Kind": 2 + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 10 + }, + "Expression": { + "Properties": [ + { + "Name": "F1", + "Expression": { + "Properties": [ + { + "Name": "FieldA", + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 0, + "Kind": 11 + } + }, + { + "Name": "FieldSum", + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 1, + "Kind": 11 + } + }, + { + "Name": "FieldAvg", + "Expression": { + "ConditionExpression": { + "OperatorKind": 6, + "LeftExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + }, + "RightExpression": { + "Literal": { + "Value": 0, + "Kind": 4 + }, + "Kind": 5 + }, + "Kind": 2 + }, + "LeftExpression": { + "Literal": { + "Kind": 0 + }, + "Kind": 5 + }, + "RightExpression": { + "OperatorKind": 5, + "LeftExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "RightExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + }, + "Kind": 2 + }, + "Kind": 6 + } + } + ], + "ObjectKind": "Object", + "Kind": 7 + } + }, + { + "Name": "F2", + "Expression": { + "Properties": [ + { + "Name": "OtherFieldA", + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 0, + "Kind": 11 + } + }, + { + "Name": "OtherFieldMax", + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 3, + "Kind": 11 + } + } + ], + "ObjectKind": "Object", + "Kind": 7 + } + } + ], + "ObjectKind": "Object", + "Kind": 7 + }, + "Kind": 6 + } +} + + + + + Select, Sum and VariableRef Expressions + {"clientDistributionPlan": {"Cql": {"Kind": "Select","DeclaredVariable": {"Name": "v0","UniqueId": 6},"Expression": {"Kind": "ObjectCreate","ObjectKind": "Object","Properties": [{"Name": "count_a_plus_five","Expression": {"Kind": "BinaryOperator","OperatorKind": "Add","LeftExpression": {"Kind": "VariableRef","Variable": {"Name": "v0","UniqueId": 6 }}, "RightExpression": { "Kind": "Literal", "Literal": { "Kind": "Number", "Value": 5 }}}}]}, "SourceExpression": { "Kind": "Aggregate", "Aggregate": { "Kind": "Builtin", "OperatorKind": "Sum" }, "SourceExpression": { "Kind": "Input", "Name": "root" }}}}} + + + { + "Cql": { + "SourceExpression": { + "SourceExpression": { + "Name": "root", + "Kind": 3 + }, + "Aggregate": { + "OperatorKind": 8, + "Kind": 0 + }, + "Kind": 0 + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Properties": [ + { + "Name": "count_a_plus_five", + "Expression": { + "OperatorKind": 0, + "LeftExpression": { + "Variable": { + "Name": "v0", + "UniqueId": 6 + }, + "Kind": 14 + }, + "RightExpression": { + "Literal": { + "Value": 5, + "Kind": 4 + }, + "Kind": 5 + }, + "Kind": 2 + } + } + ], + "ObjectKind": "Object", + "Kind": 7 + }, + "Kind": 6 + } +} + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj index 88450d8984..6f1657f37c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj @@ -79,6 +79,9 @@ + + PreserveNewest + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ClientDistributionPlanBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ClientDistributionPlanBaselineTests.cs new file mode 100644 index 0000000000..845f71d25e --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ClientDistributionPlanBaselineTests.cs @@ -0,0 +1,100 @@ +namespace Microsoft.Azure.Cosmos.Tests.Query +{ + using System.Collections.Generic; + using System.Xml; + using Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan; + using Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql; + using Microsoft.Azure.Cosmos.Test.BaselineTest; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + [TestClass] + public class ClientDistributionPlanBaselineTests : BaselineTests + { + [TestMethod] + [Owner("akotalwar")] + public void TestClientDistributionPlanDeserialization() + { + List testVariations = new List + { + CreateInput( + description: @"Input Expression", + clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": {\"Kind\": \"Input\",\"Name\": \"root\"}}}"), + + CreateInput( + description: @"Aggregate and ObjectCreate Expressions", + clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": {\"Kind\": \"Select\",\"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 6},\"Expression\": {\"Kind\": \"ObjectCreate\",\"ObjectKind\": \"Object\",\"Properties\": [{\"Name\": \"count_a\",\"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": {\"Name\": \"v0\",\"UniqueId\": 6}}}]},\"SourceExpression\": {\"Kind\": \"Aggregate\",\"Aggregate\": {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\"},\"SourceExpression\": {\"Kind\": \"Input\",\"Name\": \"root\"}}}}}"), + + CreateInput( + description: @"Select, Aggregate and BinaryOperator Expressions", + clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": { \"Kind\": \"Select\", \"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 10 }, \"Expression\": {\"Kind\": \"ObjectCreate\",\"ObjectKind\": \"Object\",\"Properties\": [ {\"Name\": \"F1\",\"Expression\": { \"Kind\": \"ObjectCreate\", \"ObjectKind\": \"Object\", \"Properties\": [{ \"Name\": \"FieldA\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 0 }},{ \"Name\": \"FieldSum\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 1 }},{ \"Name\": \"FieldAvg\", \"Expression\": {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"Equal\", \"LeftExpression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 10} }, \"Index\": 2},\"Index\": 1 }, \"RightExpression\": {\"Kind\": \"Literal\",\"Literal\": { \"Kind\": \"Number\", \"Value\": 0} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Undefined\" }},\"RightExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"Divide\", \"LeftExpression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 10} }, \"Index\": 2},\"Index\": 0 }, \"RightExpression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 10} }, \"Index\": 2},\"Index\": 1 }}}}]}}, {\"Name\": \"F2\",\"Expression\": { \"Kind\": \"ObjectCreate\", \"ObjectKind\": \"Object\", \"Properties\": [{ \"Name\": \"OtherFieldA\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 0 }},{ \"Name\": \"OtherFieldMax\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 3 }} ]} }] }, \"SourceExpression\": {\"Kind\": \"GroupBy\",\"KeyCount\": 1,\"Aggregates\": [ {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\" }, {\"Kind\": \"Tuple\",\"Items\": [ {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\" }, {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\" }] }, {\"Kind\": \"Builtin\",\"OperatorKind\": \"Max\" }],\"SourceExpression\": { \"Kind\": \"Select\", \"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 16 }, \"Expression\": {\"Kind\": \"TupleCreate\",\"Items\": [ {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 0 }, {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"And\", \"LeftExpression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"NotEqual\",\"LeftExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 1 }, \"Index\": 1},\"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Number\",\"Value\": 0 }} }, \"RightExpression\": {\"Kind\": \"UnaryOperator\",\"OperatorKind\": \"Not\",\"Expression\": { \"Kind\": \"SystemFunctionCall\", \"FunctionKind\": \"Is_Defined\", \"Arguments\": [{ \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 1 }, \"Index\": 0} ]} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Array\",\"Items\": [] }},\"RightExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 1 }, \"Index\": 0} }, {\"Kind\": \"TupleCreate\",\"Items\": [ {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"And\", \"LeftExpression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"NotEqual\",\"LeftExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 16} }, \"Index\": 2},\"Index\": 0 }, \"Index\": 1},\"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Number\",\"Value\": 0 }} }, \"RightExpression\": {\"Kind\": \"UnaryOperator\",\"OperatorKind\": \"Not\",\"Expression\": { \"Kind\": \"SystemFunctionCall\", \"FunctionKind\": \"Is_Defined\", \"Arguments\": [{ \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 16} }, \"Index\": 2},\"Index\": 0 }, \"Index\": 0} ]} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Array\",\"Items\": [] }},\"RightExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 2 }, \"Index\": 0} }, {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 16} }, \"Index\": 2},\"Index\": 1 }] }, {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"And\", \"LeftExpression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"NotEqual\",\"LeftExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 3 }, \"Index\": 1},\"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Number\",\"Value\": 0 }} }, \"RightExpression\": {\"Kind\": \"UnaryOperator\",\"OperatorKind\": \"Not\",\"Expression\": { \"Kind\": \"SystemFunctionCall\", \"FunctionKind\": \"Is_Defined\", \"Arguments\": [{ \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 3 }, \"Index\": 0} ]} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Array\",\"Items\": [] }},\"RightExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16}},\"Index\": 3}, \"Index\": 0}}]}, \"SourceExpression\": {\"Kind\": \"Input\",\"Name\": \"root\"}}}}}}"), + + CreateInput( + description: @"Select, Sum and VariableRef Expressions", + clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": {\"Kind\": \"Select\",\"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 6},\"Expression\": {\"Kind\": \"ObjectCreate\",\"ObjectKind\": \"Object\",\"Properties\": [{\"Name\": \"count_a_plus_five\",\"Expression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"Add\",\"LeftExpression\": {\"Kind\": \"VariableRef\",\"Variable\": {\"Name\": \"v0\",\"UniqueId\": 6 }}, \"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": { \"Kind\": \"Number\", \"Value\": 5 }}}}]}, \"SourceExpression\": { \"Kind\": \"Aggregate\", \"Aggregate\": { \"Kind\": \"Builtin\", \"OperatorKind\": \"Sum\" }, \"SourceExpression\": { \"Kind\": \"Input\", \"Name\": \"root\" }}}}}"), + }; + + this.ExecuteTestSuite(testVariations); + } + + + private static ClientDistributionPlanTestInput CreateInput( + string description, + string clientPlanJson) + { + return new ClientDistributionPlanTestInput(description, clientPlanJson); + } + + public override ClientDistributionPlanTestOutput ExecuteTest(ClientDistributionPlanTestInput input) + { + JsonSerializerSettings settings = new JsonSerializerSettings + { + Formatting = Newtonsoft.Json.Formatting.Indented + }; + + ClientDistributionPlan distributionPlan = ClientDistributionPlanDeserializer.DeserializeClientDistributionPlan(input.ClientPlanJson); + string serializedDistributionPlan = JsonConvert.SerializeObject(distributionPlan, settings); + + return new ClientDistributionPlanTestOutput(serializedDistributionPlan); + } + + public sealed class ClientDistributionPlanTestOutput : BaselineTestOutput + { + public ClientDistributionPlanTestOutput(string serializedclientPlanJson) + { + this.SerializedclientPlanJson = serializedclientPlanJson; + } + + public string SerializedclientPlanJson { get; } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + JObject jObject = JObject.Parse(this.SerializedclientPlanJson); + string jsonString = jObject.ToString(); + xmlWriter.WriteStartElement("SerializedClientPlanJson"); + xmlWriter.WriteString(jsonString); + xmlWriter.WriteEndElement(); + } + } + + public sealed class ClientDistributionPlanTestInput : BaselineTestInput + { + internal string ClientPlanJson { get; set; } + + internal ClientDistributionPlanTestInput( + string description, + string clientPlanJson) + : base(description) + { + this.ClientPlanJson = clientPlanJson; + } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + xmlWriter.WriteElementString("Description", this.Description); + xmlWriter.WriteElementString("ClientDistributionPlanJson", this.ClientPlanJson); + } + } + } +}