Exemplo n.º 1
0
        private static SqlExpression Recurse(ref int i, bool useCompression, bool useSingleTable, Expression expression, bool isUnary = false, string prefix = null, string postfix = null)
        {
            if (expression is UnaryExpression unary)
            {
                return(SqlExpression.Concat(unary.NodeType.ToSqlString(), Recurse(ref i, useCompression, useSingleTable, unary.Operand, true)));
            }

            if (expression is BinaryExpression body)
            {
                return(SqlExpression.Concat(Recurse(ref i, useCompression, useSingleTable, body.Left), body.NodeType.ToSqlString(), Recurse(ref i, useCompression, useSingleTable, body.Right)));
            }

            if (expression is ConstantExpression constant)
            {
                var value = constant.Value;
                if (value is int)
                {
                    return(SqlExpression.TextOnly(value.ToString()));
                }

                if (value is string)
                {
                    value = prefix + (string)value + postfix;
                }

                if (value is bool && isUnary)
                {
                    return(SqlExpression.Concat(SqlExpression.WithSingleParameter(i++, value), "=", SqlExpression.TextOnly("1")));
                }

                return(SqlExpression.WithSingleParameter(i++, value));
            }

            if (expression is MemberExpression member)
            {
                var value = TryGetMemberValue(member);
                if (value != null)
                {
                    return(GetMemberValue(ref i, value, prefix, postfix));
                }

                if (member.Member is PropertyInfo property)
                {
                    if (isUnary && member.Type == typeof(bool))
                    {
                        return(SqlExpression.Concat(Recurse(ref i, useCompression, useSingleTable, expression), "=", SqlExpression.WithSingleParameter(i++, true)));
                    }

                    var name = expression.ToString();
                    if (name.Contains('.'))
                    {
                        name = string.Join(".", name.Split('.').Skip(1));
                    }

                    name = TableHelper.GetFixedLeftPart(name, useCompression, useSingleTable);

                    return(SqlExpression.TextOnly(name));
                }

                if (member.Member is FieldInfo)
                {
                    value = TryGetMemberValue(member);
                    return(GetMemberValue(ref i, value, prefix, postfix));
                }

                throw new Exception($"Expression does not refer to a property or field: {expression}");
            }

            if (expression is MethodCallExpression methodCall)
            {
                // LIKE queries:
                if (methodCall.Method == typeof(string).GetMethod(nameof(string.Contains), new[] { typeof(string) }))
                {
                    return(SqlExpression.Concat(Recurse(ref i, useCompression, useSingleTable, methodCall.Object), "LIKE", Recurse(ref i, useCompression, useSingleTable, methodCall.Arguments[0], prefix: "%", postfix: "%")));
                }

                if (methodCall.Method == typeof(string).GetMethod(nameof(string.StartsWith), new[] { typeof(string) }))
                {
                    return(SqlExpression.Concat(Recurse(ref i, useCompression, useSingleTable, methodCall.Object), "LIKE", Recurse(ref i, useCompression, useSingleTable, methodCall.Arguments[0], postfix: "%")));
                }

                if (methodCall.Method == typeof(string).GetMethod(nameof(string.EndsWith), new[] { typeof(string) }))
                {
                    return(SqlExpression.Concat(Recurse(ref i, useCompression, useSingleTable, methodCall.Object), "LIKE", Recurse(ref i, useCompression, useSingleTable, methodCall.Arguments[0], prefix: "%")));
                }

                // IN queries:
                if (methodCall.Method.Name == nameof(IList.Contains))
                {
                    Expression collection;
                    Expression property;
                    if (methodCall.Method.IsDefined(typeof(ExtensionAttribute)) && methodCall.Arguments.Count == 2)
                    {
                        collection = methodCall.Arguments[0];
                        property   = methodCall.Arguments[1];
                    }
                    else if (!methodCall.Method.IsDefined(typeof(ExtensionAttribute)) && methodCall.Arguments.Count == 1)
                    {
                        collection = methodCall.Object;
                        property   = methodCall.Arguments[0];
                    }
                    else
                    {
                        throw new Exception("Unsupported method call: " + methodCall.Method.Name);
                    }

                    var values = (IEnumerable)GetValue(collection);

                    return(SqlExpression.Concat(Recurse(ref i, useCompression, useSingleTable, property), "IN", SqlExpression.WithParameters(ref i, values)));
                }

                throw new Exception("Unsupported method call: " + methodCall.Method.Name);
            }

            throw new Exception("Unsupported expression: " + expression.GetType().Name);
        }