public void SqlArrayCreateScalarExpressionTest()
        {
            SqlArrayCreateScalarExpression inner = SqlArrayCreateScalarExpression.Create(
                SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(1)),
                SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(2)),
                SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(3)));

            AssertEvaluation(
                CosmosArray.Create(
                    new List <CosmosElement>()
            {
                CosmosNumber64.Create(1),
                CosmosNumber64.Create(2),
                CosmosNumber64.Create(3),
            }),
                inner);

            SqlArrayCreateScalarExpression outer = SqlArrayCreateScalarExpression.Create(inner);

            AssertEvaluation(
                CosmosArray.Create(
                    new List <CosmosElement>()
            {
                CosmosArray.Create(
                    new List <CosmosElement>()
                {
                    CosmosNumber64.Create(1),
                    CosmosNumber64.Create(2),
                    CosmosNumber64.Create(3),
                })
            }),
                outer);
        }
        public override SqlObject Visit(SqlArrayCreateScalarExpression sqlArrayCreateScalarExpression)
        {
            List <SqlScalarExpression> items = new List <SqlScalarExpression>();

            foreach (SqlScalarExpression item in sqlArrayCreateScalarExpression.Items)
            {
                items.Add(item.Accept(this) as SqlScalarExpression);
            }

            return(SqlArrayCreateScalarExpression.Create(items.ToImmutableArray()));
        }
        public override SqlObject VisitArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context)
        {
            Contract.Requires(context != null);
            Contract.Requires(context.ChildCount >= 2); // start array and end array tokens

            List <SqlScalarExpression> arrayItems = new List <SqlScalarExpression>();

            if (context.scalar_expression_list() != null)
            {
                foreach (sqlParser.Scalar_expressionContext scalarExpressionContext in context.scalar_expression_list().scalar_expression())
                {
                    arrayItems.Add((SqlScalarExpression)this.Visit(scalarExpressionContext));
                }
            }

            return(SqlArrayCreateScalarExpression.Create(arrayItems.ToImmutableArray()));
        }
예제 #4
0
        /// <summary>
        /// Constructs <see cref="SqlScalarExpression"/> from a geometry <see cref="JToken"/>.
        /// </summary>
        /// <param name="jToken">Json token.</param>
        /// <returns>Instance of <see cref="SqlScalarExpression"/>.</returns>
        private static SqlScalarExpression FromJToken(JToken jToken)
        {
            switch (jToken.Type)
            {
            case JTokenType.Array:
                return(SqlArrayCreateScalarExpression.Create(jToken.Select(FromJToken).ToArray()));

            case JTokenType.Boolean:
                return(SqlLiteralScalarExpression.Create(SqlBooleanLiteral.Create(jToken.Value <bool>())));

            case JTokenType.Null:
                return(SqlLiteralScalarExpression.SqlNullLiteralScalarExpression);

            case JTokenType.String:
                return(SqlLiteralScalarExpression.Create(SqlStringLiteral.Create(jToken.Value <string>())));

            case JTokenType.Object:

                SqlObjectProperty[] properties =
                    ((JObject)jToken).Properties()
                    .Select(
                        p =>
                        SqlObjectProperty.Create(
                            SqlPropertyName.Create(p.Name),
                            FromJToken(p.Value)))
                    .ToArray();

                return(SqlObjectCreateScalarExpression.Create(properties));

            case JTokenType.Float:
            case JTokenType.Integer:
                SqlNumberLiteral sqlNumberLiteral = SqlNumberLiteral.Create(jToken.Value <double>());
                return(SqlLiteralScalarExpression.Create(sqlNumberLiteral));

            default:
                throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.UnexpectedTokenType, jToken.Type));
            }
        }
예제 #5
0
        public static SqlScalarExpression Substitute(SqlScalarExpression replacement, SqlIdentifier toReplace, SqlScalarExpression into)
        {
            if (into == null)
            {
                return(null);
            }

            if (replacement == null)
            {
                throw new ArgumentNullException("replacement");
            }

            switch (into.Kind)
            {
            case SqlObjectKind.ArrayCreateScalarExpression:
            {
                SqlArrayCreateScalarExpression arrayExp = into as SqlArrayCreateScalarExpression;
                if (arrayExp == null)
                {
                    throw new DocumentQueryException("Expected a SqlArrayCreateScalarExpression, got a " + into.GetType());
                }

                SqlScalarExpression[] items = new SqlScalarExpression[arrayExp.Items.Count];
                for (int i = 0; i < items.Length; i++)
                {
                    SqlScalarExpression item     = arrayExp.Items[i];
                    SqlScalarExpression replitem = Substitute(replacement, toReplace, item);
                    items[i] = replitem;
                }

                return(SqlArrayCreateScalarExpression.Create(items));
            }

            case SqlObjectKind.BinaryScalarExpression:
            {
                SqlBinaryScalarExpression binaryExp = into as SqlBinaryScalarExpression;
                if (binaryExp == null)
                {
                    throw new DocumentQueryException("Expected a BinaryScalarExpression, got a " + into.GetType());
                }

                SqlScalarExpression replleft  = Substitute(replacement, toReplace, binaryExp.LeftExpression);
                SqlScalarExpression replright = Substitute(replacement, toReplace, binaryExp.RightExpression);
                return(SqlBinaryScalarExpression.Create(binaryExp.OperatorKind, replleft, replright));
            }

            case SqlObjectKind.UnaryScalarExpression:
            {
                SqlUnaryScalarExpression unaryExp = into as SqlUnaryScalarExpression;
                if (unaryExp == null)
                {
                    throw new DocumentQueryException("Expected a SqlUnaryScalarExpression, got a " + into.GetType());
                }

                SqlScalarExpression repl = Substitute(replacement, toReplace, unaryExp.Expression);
                return(SqlUnaryScalarExpression.Create(unaryExp.OperatorKind, repl));
            }

            case SqlObjectKind.LiteralScalarExpression:
            {
                return(into);
            }

            case SqlObjectKind.FunctionCallScalarExpression:
            {
                SqlFunctionCallScalarExpression funcExp = into as SqlFunctionCallScalarExpression;
                if (funcExp == null)
                {
                    throw new DocumentQueryException("Expected a SqlFunctionCallScalarExpression, got a " + into.GetType());
                }

                SqlScalarExpression[] items = new SqlScalarExpression[funcExp.Arguments.Count];
                for (int i = 0; i < items.Length; i++)
                {
                    SqlScalarExpression item     = funcExp.Arguments[i];
                    SqlScalarExpression replitem = Substitute(replacement, toReplace, item);
                    items[i] = replitem;
                }

                return(SqlFunctionCallScalarExpression.Create(funcExp.Name, funcExp.IsUdf, items));
            }

            case SqlObjectKind.ObjectCreateScalarExpression:
            {
                SqlObjectCreateScalarExpression objExp = into as SqlObjectCreateScalarExpression;
                if (objExp == null)
                {
                    throw new DocumentQueryException("Expected a SqlObjectCreateScalarExpression, got a " + into.GetType());
                }

                return(SqlObjectCreateScalarExpression.Create(
                           objExp
                           .Properties
                           .Select(prop => SqlObjectProperty.Create(prop.Name, Substitute(replacement, toReplace, prop.Expression)))));
            }

            case SqlObjectKind.MemberIndexerScalarExpression:
            {
                SqlMemberIndexerScalarExpression memberExp = into as SqlMemberIndexerScalarExpression;
                if (memberExp == null)
                {
                    throw new DocumentQueryException("Expected a SqlMemberIndexerScalarExpression, got a " + into.GetType());
                }

                SqlScalarExpression replMember = Substitute(replacement, toReplace, memberExp.MemberExpression);
                SqlScalarExpression replIndex  = Substitute(replacement, toReplace, memberExp.IndexExpression);
                return(SqlMemberIndexerScalarExpression.Create(replMember, replIndex));
            }

            case SqlObjectKind.PropertyRefScalarExpression:
            {
                // This is the leaf of the recursion
                SqlPropertyRefScalarExpression propExp = into as SqlPropertyRefScalarExpression;
                if (propExp == null)
                {
                    throw new DocumentQueryException("Expected a SqlPropertyRefScalarExpression, got a " + into.GetType());
                }

                if (propExp.MemberExpression == null)
                {
                    if (propExp.PropertyIdentifier.Value == toReplace.Value)
                    {
                        return(replacement);
                    }
                    else
                    {
                        return(propExp);
                    }
                }
                else
                {
                    SqlScalarExpression replMember = Substitute(replacement, toReplace, propExp.MemberExpression);
                    return(SqlPropertyRefScalarExpression.Create(replMember, propExp.PropertyIdentifier));
                }
            }

            case SqlObjectKind.ConditionalScalarExpression:
            {
                SqlConditionalScalarExpression conditionalExpression = (SqlConditionalScalarExpression)into;
                if (conditionalExpression == null)
                {
                    throw new ArgumentException();
                }

                SqlScalarExpression condition = Substitute(replacement, toReplace, conditionalExpression.ConditionExpression);
                SqlScalarExpression first     = Substitute(replacement, toReplace, conditionalExpression.FirstExpression);
                SqlScalarExpression second    = Substitute(replacement, toReplace, conditionalExpression.SecondExpression);

                return(SqlConditionalScalarExpression.Create(condition, first, second));
            }

            case SqlObjectKind.InScalarExpression:
            {
                SqlInScalarExpression inExpression = (SqlInScalarExpression)into;
                if (inExpression == null)
                {
                    throw new ArgumentException();
                }

                SqlScalarExpression expression = Substitute(replacement, toReplace, inExpression.Expression);

                SqlScalarExpression[] items = new SqlScalarExpression[inExpression.Items.Count];
                for (int i = 0; i < items.Length; i++)
                {
                    items[i] = Substitute(replacement, toReplace, inExpression.Items[i]);
                }

                return(SqlInScalarExpression.Create(expression, inExpression.Not, items));
            }

            default:
                throw new ArgumentOutOfRangeException("Unexpected Sql Scalar expression kind " + into.Kind);
            }
        }
        public void SqlBinaryScalarExpressionTest()
        {
            SqlLiteralScalarExpression five             = SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(5));
            SqlLiteralScalarExpression three            = SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(3));
            SqlLiteralScalarExpression hello            = SqlLiteralScalarExpression.Create(SqlStringLiteral.Create("Hello"));
            SqlLiteralScalarExpression world            = SqlLiteralScalarExpression.Create(SqlStringLiteral.Create("World"));
            SqlLiteralScalarExpression trueBoolean      = SqlLiteralScalarExpression.Create(SqlBooleanLiteral.True);
            SqlLiteralScalarExpression falseBoolean     = SqlLiteralScalarExpression.Create(SqlBooleanLiteral.False);
            SqlLiteralScalarExpression nullLiteral      = SqlLiteralScalarExpression.Create(SqlNullLiteral.Singleton);
            SqlLiteralScalarExpression undefinedLiteral = SqlLiteralScalarExpression.Create(SqlUndefinedLiteral.Create());

            SqlArrayCreateScalarExpression  arrayCreateScalarExpresion1  = SqlArrayCreateScalarExpression.Create();
            SqlArrayCreateScalarExpression  arrayCreateScalarExpresion2  = SqlArrayCreateScalarExpression.Create(five);
            SqlObjectCreateScalarExpression objectCreateScalarExpression = SqlObjectCreateScalarExpression.Create();

            SqlBinaryScalarExpression fivePlusThree = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Add, five, three);

            AssertEvaluation(CosmosNumber64.Create(3 + 5), fivePlusThree);

            SqlBinaryScalarExpression trueAndFalse = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.And, trueBoolean, falseBoolean);

            AssertEvaluation(CosmosBoolean.Create(true && false), trueAndFalse);

            SqlBinaryScalarExpression falseAndUndefined = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.And, falseBoolean, undefinedLiteral);

            AssertEvaluation(CosmosBoolean.Create(false), falseAndUndefined);

            SqlBinaryScalarExpression trueAndUndefined = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.And, trueBoolean, undefinedLiteral);

            AssertEvaluation(Undefined, trueAndUndefined);

            try
            {
                SqlBinaryScalarExpression threeBitwiseAndFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.BitwiseAnd, three, five);
                AssertEvaluation(CosmosNumber64.Create(1), threeBitwiseAndFive);
            }
            catch (Exception)
            {
            }

            try
            {
                SqlBinaryScalarExpression threeBitwiseOrFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.BitwiseOr, three, five);
                AssertEvaluation(CosmosNumber64.Create(7), threeBitwiseOrFive);
            }
            catch (Exception)
            {
            }

            try
            {
                SqlBinaryScalarExpression threeBitwiseXorFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.BitwiseXor, three, five);
                AssertEvaluation(CosmosNumber64.Create(7), threeBitwiseXorFive);
            }
            catch (Exception)
            {
            }

            SqlBinaryScalarExpression nullCoalesceFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Coalesce, nullLiteral, five);

            AssertEvaluation(CosmosNull.Create(), nullCoalesceFive);

            SqlBinaryScalarExpression fiveDivideFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Divide, five, five);

            AssertEvaluation(CosmosNumber64.Create(5 / 5), fiveDivideFive);

            SqlBinaryScalarExpression fiveEqualFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Equal, five, five);

            AssertEvaluation(CosmosBoolean.Create(5 == 5), fiveEqualFive);

            SqlBinaryScalarExpression threeEqualFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Equal, three, five);

            AssertEvaluation(CosmosBoolean.Create(3 == 5), threeEqualFive);

            AssertEvaluation(
                CosmosBoolean.Create(true),
                SqlBinaryScalarExpression.Create(
                    SqlBinaryScalarOperatorKind.Equal,
                    arrayCreateScalarExpresion1,
                    arrayCreateScalarExpresion1));

            AssertEvaluation(
                CosmosBoolean.Create(false),
                SqlBinaryScalarExpression.Create(
                    SqlBinaryScalarOperatorKind.Equal,
                    arrayCreateScalarExpresion1,
                    arrayCreateScalarExpresion2));

            AssertEvaluation(
                CosmosBoolean.Create(false),
                SqlBinaryScalarExpression.Create(
                    SqlBinaryScalarOperatorKind.Equal,
                    arrayCreateScalarExpresion1,
                    objectCreateScalarExpression));

            SqlBinaryScalarExpression threeGreaterThanFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.GreaterThan, three, five);

            AssertEvaluation(CosmosBoolean.Create(3 > 5), threeGreaterThanFive);

            SqlBinaryScalarExpression fiveGreaterThanThree = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.GreaterThan, five, three);

            AssertEvaluation(CosmosBoolean.Create(5 > 3), fiveGreaterThanThree);

            SqlBinaryScalarExpression threeGreaterThanOrEqualFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.GreaterThanOrEqual, three, five);

            AssertEvaluation(CosmosBoolean.Create(3 >= 5), threeGreaterThanOrEqualFive);

            SqlBinaryScalarExpression fiveGreaterThanOrEqualThree = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.GreaterThanOrEqual, five, three);

            AssertEvaluation(CosmosBoolean.Create(5 >= 3), fiveGreaterThanOrEqualThree);

            SqlBinaryScalarExpression threeLessThanFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.LessThan, three, five);

            AssertEvaluation(CosmosBoolean.Create(3 < 5), threeLessThanFive);

            SqlBinaryScalarExpression fiveLessThanThree = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.LessThan, five, three);

            AssertEvaluation(CosmosBoolean.Create(5 < 3), fiveLessThanThree);

            SqlBinaryScalarExpression threeLessThanOrEqualFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.LessThanOrEqual, three, five);

            AssertEvaluation(CosmosBoolean.Create(3 <= 5), threeLessThanOrEqualFive);

            SqlBinaryScalarExpression fiveLessThanOrEqualThree = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.LessThanOrEqual, five, three);

            AssertEvaluation(CosmosBoolean.Create(5 <= 3), fiveLessThanOrEqualThree);

            SqlBinaryScalarExpression fiveModThree = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Modulo, five, three);

            AssertEvaluation(CosmosNumber64.Create(5 % 3), fiveModThree);

            SqlBinaryScalarExpression fiveMultiplyThree = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Multiply, five, three);

            AssertEvaluation(CosmosNumber64.Create(5 * 3), fiveMultiplyThree);

            SqlBinaryScalarExpression fiveNotEqualThree = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.NotEqual, five, three);

            AssertEvaluation(CosmosBoolean.Create(5 != 3), fiveNotEqualThree);

            SqlBinaryScalarExpression fiveNotEqualFive = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.NotEqual, five, five);

            AssertEvaluation(CosmosBoolean.Create(5 != 5), fiveNotEqualFive);

            SqlBinaryScalarExpression trueOrFalse = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Or, trueBoolean, falseBoolean);

            AssertEvaluation(CosmosBoolean.Create(true || false), trueOrFalse);

            SqlBinaryScalarExpression trueOrUndefined = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Or, trueBoolean, undefinedLiteral);

            AssertEvaluation(CosmosBoolean.Create(true), trueOrUndefined);

            SqlBinaryScalarExpression falseOrUndefined = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Or, falseBoolean, undefinedLiteral);

            AssertEvaluation(Undefined, falseOrUndefined);

            SqlBinaryScalarExpression helloConcatWorld = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.StringConcat, hello, world);

            AssertEvaluation(CosmosString.Create("Hello" + "World"), helloConcatWorld);

            SqlBinaryScalarExpression fiveSubtract3 = SqlBinaryScalarExpression.Create(SqlBinaryScalarOperatorKind.Subtract, five, three);

            AssertEvaluation(CosmosNumber64.Create(5 - 3), fiveSubtract3);
        }
예제 #7
0
        public void ARRAY_CONTAINS()
        {
            // ARRAY_CONTAINS(["apples", "strawberries", "bananas"], "apples")
            AssertEvaluation(
                expected: CosmosBoolean.Create(new string[] { "apples", "strawberries", "bananas" }.Contains("apples")),
                sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin(
                    SqlFunctionCallScalarExpression.Identifiers.ArrayContains,
                    JTokenToSqlScalarExpression.Convert(new JArray("apples", "strawberries", "bananas")),
                    SqlLiteralScalarExpression.Create(SqlStringLiteral.Create("apples"))));

            // ARRAY_CONTAINS(["apples", "strawberries", "bananas"], "mangoes")
            AssertEvaluation(
                expected: CosmosBoolean.Create(new string[] { "apples", "strawberries", "bananas" }.Contains("mangoes")),
                sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin(
                    SqlFunctionCallScalarExpression.Identifiers.ArrayContains,
                    JTokenToSqlScalarExpression.Convert(new JArray("apples", "strawberries", "bananas")),
                    SqlLiteralScalarExpression.Create(SqlStringLiteral.Create("mangoes"))));

            // ARRAY_CONTAINS([{"name": "apples", "fresh": true}, {"name": "strawberries", "fresh": true}], {"name": "apples"}, true)
            AssertEvaluation(
                expected: CosmosBoolean.Create(true),
                sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin(
                    SqlFunctionCallScalarExpression.Identifiers.ArrayContains,
                    JTokenToSqlScalarExpression.Convert(new JArray(
                                                            JObject.FromObject(new { name = "apples", fresh = true }),
                                                            JObject.FromObject(new { name = "strawberries", fresh = true }))),
                    JTokenToSqlScalarExpression.Convert(JObject.FromObject(new { name = "apples" })),
                    trueBoolean));

            // ARRAY_CONTAINS([{"name": "apples", "fresh": true}, {"name": "strawberries", "fresh": true}], {"name": "apples"}, undefined)
            AssertEvaluation(
                expected: CosmosBoolean.Create(false),
                sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin(
                    SqlFunctionCallScalarExpression.Identifiers.ArrayContains,
                    JTokenToSqlScalarExpression.Convert(new JArray(
                                                            JObject.FromObject(new { name = "apples", fresh = true }),
                                                            JObject.FromObject(new { name = "strawberries", fresh = true }))),
                    JTokenToSqlScalarExpression.Convert(JObject.FromObject(new { name = "apples" })),
                    SqlLiteralScalarExpression.Create(SqlUndefinedLiteral.Create())));

            // ARRAY_CONTAINS([{"name": "apples", "fresh": true}, {"name": "strawberries", "fresh": true}], {"name": "apples"})
            AssertEvaluation(
                expected: CosmosBoolean.Create(false),
                sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin(
                    SqlFunctionCallScalarExpression.Identifiers.ArrayContains,
                    JTokenToSqlScalarExpression.Convert(new JArray(
                                                            JObject.FromObject(new { name = "apples", fresh = true }),
                                                            JObject.FromObject(new { name = "strawberries", fresh = true }))),
                    JTokenToSqlScalarExpression.Convert(JObject.FromObject(new { name = "apples" }))));

            // ARRAY_CONTAINS([{"name": "apples", "fresh": true}, {"name": "strawberries", "fresh": true}], {"name": "mangoes"}, true)
            AssertEvaluation(
                expected: CosmosBoolean.Create(false),
                sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin(
                    SqlFunctionCallScalarExpression.Identifiers.ArrayContains,
                    JTokenToSqlScalarExpression.Convert(new JArray(
                                                            JObject.FromObject(new { name = "apples", fresh = true }),
                                                            JObject.FromObject(new { name = "strawberries", fresh = true }))),
                    JTokenToSqlScalarExpression.Convert(JObject.FromObject(new { name = "mangoes" })),
                    trueBoolean));

            // ARRAY_CONTAINS([SQUARE(2), POWER(2, 2)] 2)
            AssertEvaluation(
                expected: CosmosBoolean.Create(new double[] { 2 * 2, Math.Pow(2, 2) }.Contains(2)),
                sqlScalarExpression: SqlFunctionCallScalarExpression.CreateBuiltin(
                    SqlFunctionCallScalarExpression.Identifiers.ArrayContains,
                    SqlArrayCreateScalarExpression.Create(
                        SqlFunctionCallScalarExpression.CreateBuiltin(
                            SqlFunctionCallScalarExpression.Identifiers.Square,
                            SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(2))),
                        SqlFunctionCallScalarExpression.CreateBuiltin(
                            SqlFunctionCallScalarExpression.Identifiers.Power,
                            SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(2)),
                            SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(2)))),
                    JTokenToSqlScalarExpression.Convert(2)));
        }
        /// <summary>
        /// Converts a JToken to a semantically equivalent SqlScalarExpression.
        /// </summary>
        /// <param name="token">The JToken to convert.</param>
        /// <returns>The semantically equivalent SqlScalarExpression.</returns>
        public static SqlScalarExpression Convert(JToken token)
        {
            if (token == null)
            {
                return(Undefined);
            }

            switch (token.Type)
            {
            case JTokenType.Array:
            {
                List <SqlScalarExpression> items = new List <SqlScalarExpression>();
                foreach (JToken element in token)
                {
                    items.Add(JTokenToSqlScalarExpression.Convert(element));
                }

                return(SqlArrayCreateScalarExpression.Create(items.ToArray()));
            }

            case JTokenType.Boolean:
            {
                SqlBooleanLiteral literal = SqlBooleanLiteral.Create(token.ToObject <bool>());
                return(SqlLiteralScalarExpression.Create(literal));
            }

            case JTokenType.Null:
            {
                SqlNullLiteral literal = SqlNullLiteral.Singleton;
                return(SqlLiteralScalarExpression.Create(literal));
            }

            case JTokenType.Integer:
            case JTokenType.Float:
            {
                SqlNumberLiteral literal = SqlNumberLiteral.Create(token.ToObject <double>());
                return(SqlLiteralScalarExpression.Create(literal));
            }

            case JTokenType.Object:
            {
                List <SqlObjectProperty> properties = new List <SqlObjectProperty>();

                foreach (JProperty prop in (JToken)token)
                {
                    SqlPropertyName     name       = SqlPropertyName.Create(prop.Name);
                    JToken              value      = prop.Value;
                    SqlScalarExpression expression = JTokenToSqlScalarExpression.Convert(value);
                    SqlObjectProperty   property   = SqlObjectProperty.Create(name, expression);
                    properties.Add(property);
                }

                return(SqlObjectCreateScalarExpression.Create(properties.ToArray()));
            }

            case JTokenType.String:
            {
                SqlStringLiteral literal = SqlStringLiteral.Create(token.ToObject <string>());
                return(SqlLiteralScalarExpression.Create(literal));
            }

            default:
                throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, "Unsupported JsonType {0}", token.Type));
            }
        }
        public static SqlScalarExpression Substitute(SqlScalarExpression replacement, SqlIdentifier toReplace, SqlScalarExpression into)
        {
            if (into == null)
            {
                return(null);
            }

            if (replacement == null)
            {
                throw new ArgumentNullException("replacement");
            }

            switch (into)
            {
            case SqlArrayCreateScalarExpression arrayExp:
            {
                SqlScalarExpression[] items = new SqlScalarExpression[arrayExp.Items.Length];
                for (int i = 0; i < items.Length; i++)
                {
                    SqlScalarExpression item     = arrayExp.Items[i];
                    SqlScalarExpression replitem = Substitute(replacement, toReplace, item);
                    items[i] = replitem;
                }

                return(SqlArrayCreateScalarExpression.Create(items));
            }

            case SqlBinaryScalarExpression binaryExp:
            {
                SqlScalarExpression replleft  = Substitute(replacement, toReplace, binaryExp.LeftExpression);
                SqlScalarExpression replright = Substitute(replacement, toReplace, binaryExp.RightExpression);
                return(SqlBinaryScalarExpression.Create(binaryExp.OperatorKind, replleft, replright));
            }

            case SqlUnaryScalarExpression unaryExp:
            {
                SqlScalarExpression repl = Substitute(replacement, toReplace, unaryExp.Expression);
                return(SqlUnaryScalarExpression.Create(unaryExp.OperatorKind, repl));
            }

            case SqlLiteralScalarExpression literalScalarExpression:
            {
                return(into);
            }

            case SqlFunctionCallScalarExpression funcExp:
            {
                SqlScalarExpression[] items = new SqlScalarExpression[funcExp.Arguments.Length];
                for (int i = 0; i < items.Length; i++)
                {
                    SqlScalarExpression item     = funcExp.Arguments[i];
                    SqlScalarExpression replitem = Substitute(replacement, toReplace, item);
                    items[i] = replitem;
                }

                return(SqlFunctionCallScalarExpression.Create(funcExp.Name, funcExp.IsUdf, items));
            }

            case SqlObjectCreateScalarExpression objExp:
            {
                return(SqlObjectCreateScalarExpression.Create(
                           objExp
                           .Properties
                           .Select(prop => SqlObjectProperty.Create(prop.Name, Substitute(replacement, toReplace, prop.Value)))
                           .ToImmutableArray()));
            }

            case SqlMemberIndexerScalarExpression memberExp:
            {
                SqlScalarExpression replMember = Substitute(replacement, toReplace, memberExp.Member);
                SqlScalarExpression replIndex  = Substitute(replacement, toReplace, memberExp.Indexer);
                return(SqlMemberIndexerScalarExpression.Create(replMember, replIndex));
            }

            case SqlPropertyRefScalarExpression propExp:
            {
                // This is the leaf of the recursion
                if (propExp.Member == null)
                {
                    if (propExp.Identifier.Value == toReplace.Value)
                    {
                        return(replacement);
                    }
                    else
                    {
                        return(propExp);
                    }
                }
                else
                {
                    SqlScalarExpression replMember = Substitute(replacement, toReplace, propExp.Member);
                    return(SqlPropertyRefScalarExpression.Create(replMember, propExp.Identifier));
                }
            }

            case SqlConditionalScalarExpression conditionalExpression:
            {
                SqlScalarExpression condition = Substitute(replacement, toReplace, conditionalExpression.Condition);
                SqlScalarExpression first     = Substitute(replacement, toReplace, conditionalExpression.Consequent);
                SqlScalarExpression second    = Substitute(replacement, toReplace, conditionalExpression.Alternative);

                return(SqlConditionalScalarExpression.Create(condition, first, second));
            }

            case SqlInScalarExpression inExpression:
            {
                SqlScalarExpression expression = Substitute(replacement, toReplace, inExpression.Needle);

                SqlScalarExpression[] items = new SqlScalarExpression[inExpression.Haystack.Length];
                for (int i = 0; i < items.Length; i++)
                {
                    items[i] = Substitute(replacement, toReplace, inExpression.Haystack[i]);
                }

                return(SqlInScalarExpression.Create(expression, inExpression.Not, items));
            }

            default:
                throw new ArgumentOutOfRangeException("Unexpected Sql Scalar expression kind " + into.GetType());
            }
        }