Ejemplo n.º 1
0
        public virtual SqlExpression Translate(
            SqlExpression instance,
            MethodInfo method,
            IReadOnlyList <SqlExpression> arguments,
            IDiagnosticsLogger <DbLoggerCategory.Query> logger)
        {
            if (_methodInfoDateDiffMapping.TryGetValue(method, out var datePart))
            {
                var startDate   = arguments[1];
                var endDate     = arguments[2];
                var typeMapping = ExpressionExtensions.InferTypeMapping(startDate, endDate);

                startDate = _sqlExpressionFactory.ApplyTypeMapping(startDate, typeMapping);
                endDate   = _sqlExpressionFactory.ApplyTypeMapping(endDate, typeMapping);

                return(_sqlExpressionFactory.NullableFunction(
                           "TIMESTAMPDIFF",
                           new[]
                {
                    _sqlExpressionFactory.Fragment(datePart),
                    startDate,
                    endDate
                },
                           typeof(int),
                           typeMapping: null,
                           onlyNullWhenAnyNullPropagatingArgumentIsNull: true,
                           argumentsPropagateNullability: new [] { false, true, true }));
            }

            return(null);
        }
        public virtual SqlExpression Translate(
            SqlExpression instance,
            MethodInfo method,
            IReadOnlyList <SqlExpression> arguments,
            IDiagnosticsLogger <DbLoggerCategory.Query> logger)
        {
            if (_indexOfMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory, _options)
                       .MakeIndexOfExpression(instance, arguments[0]));
            }

            if (_replaceMethodInfo.Equals(method))
            {
                var stringTypeMapping   = ExpressionExtensions.InferTypeMapping(instance, arguments[0], arguments[1]);
                var replacementArgument = _sqlExpressionFactory.ApplyTypeMapping(arguments[1], stringTypeMapping);
                var replaceCall         = _sqlExpressionFactory.NullableFunction(
                    "REPLACE",
                    new[]
                {
                    _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping),
                    _sqlExpressionFactory.ApplyTypeMapping(arguments[0], stringTypeMapping),
                    _sqlExpressionFactory.ApplyTypeMapping(arguments[1], stringTypeMapping)
                },
                    method.ReturnType,
                    stringTypeMapping);

                // Due to a bug in all versions of MariaDB and all MySQL versions below 8.0.x (exact version that fixed the issue is
                // currently unclear), using `null` as the replacement argument in a REPLACE() call leads to unexpected results, in which
                // the call returns the original string, instead of `null`.
                // See https://jira.mariadb.org/browse/MDEV-24263
                return(_sqlExpressionFactory.Case(
                           new[]
                {
                    new CaseWhenClause(
                        _sqlExpressionFactory.IsNotNull(replacementArgument),
                        replaceCall)
                },
                           _sqlExpressionFactory.Constant(null, RelationalTypeMapping.NullMapping)));
            }

            if (_toLowerMethodInfo.Equals(method) ||
                _toUpperMethodInfo.Equals(method))
            {
                return(_sqlExpressionFactory.NullableFunction(
                           _toLowerMethodInfo.Equals(method) ? "LOWER" : "UPPER",
                           new[] { instance },
                           method.ReturnType,
                           instance.TypeMapping));
            }

            if (_substringMethodInfoWithOneArg.Equals(method))
            {
                return(_sqlExpressionFactory.Function(
                           "SUBSTRING",
                           new[]
                {
                    instance,
                    _sqlExpressionFactory.Add(
                        arguments[0],
                        _sqlExpressionFactory.Constant(1)),
                    _sqlExpressionFactory.NullableFunction(
                        "CHAR_LENGTH",
                        new[] { instance },
                        typeof(int))
                },
                           nullable: true,
                           argumentsPropagateNullability: new[] { true, true, true },
                           method.ReturnType,
                           instance.TypeMapping));
            }

            if (_substringMethodInfoWithTwoArgs.Equals(method))
            {
                return(_sqlExpressionFactory.NullableFunction(
                           "SUBSTRING",
                           new[]
                {
                    instance,
                    _sqlExpressionFactory.Add(
                        arguments[0],
                        _sqlExpressionFactory.Constant(1)),
                    arguments[1]
                },
                           method.ReturnType,
                           instance.TypeMapping));
            }

            if (_isNullOrWhiteSpaceMethodInfo.Equals(method))
            {
                return(_sqlExpressionFactory.OrElse(
                           _sqlExpressionFactory.IsNull(arguments[0]),
                           _sqlExpressionFactory.Equal(
                               ProcessTrimMethod(arguments[0], null, null),
                               _sqlExpressionFactory.Constant(string.Empty))));
            }

            if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimStartMethodInfoWithCharArg?.Equals(method) == true ||
                _trimStartMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, "LEADING"));
            }

            if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimEndMethodInfoWithCharArg?.Equals(method) == true ||
                _trimEndMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, "TRAILING"));
            }

            if (_trimMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimMethodInfoWithCharArg?.Equals(method) == true ||
                _trimMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, null));
            }

            if (_containsMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory, _options)
                       .MakeContainsExpression(instance, arguments[0]));
            }

            if (_startsWithMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory, _options)
                       .MakeStartsWithExpression(instance, arguments[0]));
            }

            if (_endsWithMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory, _options)
                       .MakeEndsWithExpression(instance, arguments[0]));
            }

            if (_padLeftWithOneArg.Equals(method))
            {
                return(TranslatePadLeftRight(
                           true,
                           instance,
                           arguments[0],
                           _sqlExpressionFactory.Constant(" "),
                           method.ReturnType));
            }

            if (_padRightWithOneArg.Equals(method))
            {
                return(TranslatePadLeftRight(
                           false,
                           instance,
                           arguments[0],
                           _sqlExpressionFactory.Constant(" "),
                           method.ReturnType));
            }

            if (_padLeftWithTwoArgs.Equals(method))
            {
                return(TranslatePadLeftRight(
                           true,
                           instance,
                           arguments[0],
                           arguments[1],
                           method.ReturnType));
            }

            if (_padRightWithTwoArgs.Equals(method))
            {
                return(TranslatePadLeftRight(
                           false,
                           instance,
                           arguments[0],
                           arguments[1],
                           method.ReturnType));
            }

            if (_firstOrDefaultMethodInfoWithoutArgs.Equals(method))
            {
                return(_sqlExpressionFactory.NullableFunction(
                           "SUBSTRING",
                           new[] { arguments[0], _sqlExpressionFactory.Constant(1), _sqlExpressionFactory.Constant(1) },
                           method.ReturnType));
            }

            if (_lastOrDefaultMethodInfoWithoutArgs.Equals(method))
            {
                return(_sqlExpressionFactory.NullableFunction(
                           "SUBSTRING",
                           new[]
                {
                    arguments[0],
                    _sqlExpressionFactory.NullableFunction(
                        "CHAR_LENGTH",
                        new[] { arguments[0] },
                        typeof(int)),
                    _sqlExpressionFactory.Constant(1)
                },
                           method.ReturnType));
            }

            if (_removeMethodInfoWithOneArg.Equals(method))
            {
                return(_sqlExpressionFactory.NullableFunction(
                           "SUBSTRING",
                           new[]
                {
                    instance,
                    _sqlExpressionFactory.Constant(1),
                    arguments[0],
                },
                           method.ReturnType,
                           instance.TypeMapping));
            }

            if (_removeMethodInfoWithTwoArgs.Equals(method))
            {
                var firstSubString = _sqlExpressionFactory.NullableFunction(
                    "SUBSTRING",
                    new[]
                {
                    instance,
                    _sqlExpressionFactory.Constant(1),
                    arguments[0]
                },
                    method.ReturnType,
                    instance.TypeMapping);

                var secondSubString = _sqlExpressionFactory.NullableFunction(
                    "SUBSTRING",
                    new[]
                {
                    instance,
                    _sqlExpressionFactory.Add(
                        _sqlExpressionFactory.Add(
                            arguments[0],
                            arguments[1]),
                        _sqlExpressionFactory.Constant(1)),
                    _sqlExpressionFactory.Subtract(
                        _sqlExpressionFactory.NullableFunction(
                            "CHAR_LENGTH",
                            new[] { instance },
                            typeof(int)),
                        _sqlExpressionFactory.Add(
                            arguments[0],
                            arguments[1])),
                },
                    method.ReturnType,
                    instance.TypeMapping);

                var concat = _sqlExpressionFactory.NullableFunction(
                    "CONCAT",
                    new[]
                {
                    firstSubString,
                    secondSubString
                },
                    method.ReturnType,
                    instance.TypeMapping);

                return(concat);
            }

            if (_concatMethodInfos.Contains(
                    (method.IsGenericMethod
                    ? method.GetGenericMethodDefinition()
                    : null) ?? method))
            {
                // Handle
                //     string[]
                //     IEnumerable<string>
                //     object[]
                //     IEnumerable<T>
                // and
                //     string, ...
                //     object, ...
                //
                // Some call signature variants can never reach this code, because they will be directly called and thus only their result
                // is translated.
                var concatArguments = arguments[0] is MySqlComplexFunctionArgumentExpression mySqlComplexFunctionArgumentExpression
                    ? new SqlExpression[] { mySqlComplexFunctionArgumentExpression }
                    : arguments.Select(
                    e => e switch
                {
                    SqlConstantExpression c => _sqlExpressionFactory.Constant(c.Value.ToString()),
                    SqlParameterExpression p => p.ApplyTypeMapping(
                        ((MySqlStringTypeMapping)_typeMappingSource.GetMapping(typeof(string))).Clone(forceToString: true)),
                    _ => e,
                })
Ejemplo n.º 3
0
        public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments)
        {
            if (_indexOfMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory)
                       .MakeIndexOfExpression(instance, arguments[0], _sqlExpressionFactory.Constant(StringComparison.CurrentCulture)));
            }

            if (_replaceMethodInfo.Equals(method))
            {
                var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, arguments[0], arguments[1]);

                return(_sqlExpressionFactory.Function(
                           "REPLACE",
                           new[]
                {
                    _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping),
                    _sqlExpressionFactory.ApplyTypeMapping(arguments[0], stringTypeMapping),
                    _sqlExpressionFactory.ApplyTypeMapping(arguments[1], stringTypeMapping)
                },
                           method.ReturnType,
                           stringTypeMapping));
            }

            if (_toLowerMethodInfo.Equals(method) ||
                _toUpperMethodInfo.Equals(method))
            {
                return(_sqlExpressionFactory.Function(
                           _toLowerMethodInfo.Equals(method) ? "LOWER" : "UPPER",
                           new[] { instance },
                           method.ReturnType,
                           instance.TypeMapping));
            }

            if (_substringMethodInfo.Equals(method))
            {
                return(_sqlExpressionFactory.Function(
                           "SUBSTRING",
                           new[]
                {
                    instance,
                    _sqlExpressionFactory.Add(
                        arguments[0],
                        _sqlExpressionFactory.Constant(1)),
                    arguments[1]
                },
                           method.ReturnType,
                           instance.TypeMapping));
            }

            if (_isNullOrWhiteSpaceMethodInfo.Equals(method))
            {
                return(_sqlExpressionFactory.OrElse(
                           _sqlExpressionFactory.IsNull(arguments[0]),
                           _sqlExpressionFactory.Equal(
                               ProcessTrimMethod(arguments[0], null, null),
                               _sqlExpressionFactory.Constant(string.Empty))));
            }

            if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimStartMethodInfoWithCharArg?.Equals(method) == true ||
                _trimStartMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, "LEADING"));
            }

            if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimEndMethodInfoWithCharArg?.Equals(method) == true ||
                _trimEndMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, "TRAILING"));
            }

            if (_trimMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimMethodInfoWithCharArg?.Equals(method) == true ||
                _trimMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, null));
            }

            if (_containsMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory)
                       .MakeContainsExpression(instance, arguments[0], _sqlExpressionFactory.Constant(StringComparison.Ordinal)));
            }

            if (_startsWithMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory)
                       .MakeStartsWithExpression(instance, arguments[0], _sqlExpressionFactory.Constant(StringComparison.CurrentCulture)));
            }

            if (_endsWithMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory)
                       .MakeEndsWithExpression(instance, arguments[0], _sqlExpressionFactory.Constant(StringComparison.CurrentCulture)));
            }

            if (_padLeftWithOneArg.Equals(method))
            {
                return(TranslatePadLeftRight(
                           true,
                           instance,
                           arguments[0],
                           _sqlExpressionFactory.Constant(" "),
                           method.ReturnType));
            }

            if (_padRightWithOneArg.Equals(method))
            {
                return(TranslatePadLeftRight(
                           false,
                           instance,
                           arguments[0],
                           _sqlExpressionFactory.Constant(" "),
                           method.ReturnType));
            }

            if (_padLeftWithTwoArgs.Equals(method))
            {
                return(TranslatePadLeftRight(
                           true,
                           instance,
                           arguments[0],
                           arguments[1],
                           method.ReturnType));
            }

            if (_padRightWithTwoArgs.Equals(method))
            {
                return(TranslatePadLeftRight(
                           false,
                           instance,
                           arguments[0],
                           arguments[1],
                           method.ReturnType));
            }

            return(null);
        }
        public virtual SqlExpression Translate(
            SqlExpression instance,
            MethodInfo method,
            IReadOnlyList <SqlExpression> arguments,
            IDiagnosticsLogger <DbLoggerCategory.Query> logger)
        {
            if (_indexOfMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory)
                       .MakeIndexOfExpression(instance, arguments[0]));
            }

            if (_replaceMethodInfo.Equals(method))
            {
                var stringTypeMapping   = ExpressionExtensions.InferTypeMapping(instance, arguments[0], arguments[1]);
                var replacementArgument = _sqlExpressionFactory.ApplyTypeMapping(arguments[1], stringTypeMapping);
                var replaceCall         = _sqlExpressionFactory.NullableFunction(
                    "REPLACE",
                    new[]
                {
                    _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping),
                    _sqlExpressionFactory.ApplyTypeMapping(arguments[0], stringTypeMapping),
                    _sqlExpressionFactory.ApplyTypeMapping(arguments[1], stringTypeMapping)
                },
                    method.ReturnType,
                    stringTypeMapping);

                // Due to a bug in all versions of MariaDB and all MySQL versions below 8.0.x (exact version that fixed the issue is
                // currently unclear), using `null` as the replacement argument in a REPLACE() call leads to unexpected results, in which
                // the call returns the original string, instead of `null`.
                // See https://jira.mariadb.org/browse/MDEV-24263
                return(_sqlExpressionFactory.Case(
                           new[]
                {
                    new CaseWhenClause(
                        _sqlExpressionFactory.IsNotNull(replacementArgument),
                        replaceCall)
                },
                           _sqlExpressionFactory.Constant(null, RelationalTypeMapping.NullMapping)));
            }

            if (_toLowerMethodInfo.Equals(method) ||
                _toUpperMethodInfo.Equals(method))
            {
                return(_sqlExpressionFactory.NullableFunction(
                           _toLowerMethodInfo.Equals(method) ? "LOWER" : "UPPER",
                           new[] { instance },
                           method.ReturnType,
                           instance.TypeMapping));
            }

            if (_substringMethodInfo.Equals(method))
            {
                return(_sqlExpressionFactory.NullableFunction(
                           "SUBSTRING",
                           new[]
                {
                    instance,
                    _sqlExpressionFactory.Add(
                        arguments[0],
                        _sqlExpressionFactory.Constant(1)),
                    arguments[1]
                },
                           method.ReturnType,
                           instance.TypeMapping));
            }

            if (_isNullOrWhiteSpaceMethodInfo.Equals(method))
            {
                return(_sqlExpressionFactory.OrElse(
                           _sqlExpressionFactory.IsNull(arguments[0]),
                           _sqlExpressionFactory.Equal(
                               ProcessTrimMethod(arguments[0], null, null),
                               _sqlExpressionFactory.Constant(string.Empty))));
            }

            if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimStartMethodInfoWithCharArg?.Equals(method) == true ||
                _trimStartMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, "LEADING"));
            }

            if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimEndMethodInfoWithCharArg?.Equals(method) == true ||
                _trimEndMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, "TRAILING"));
            }

            if (_trimMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimMethodInfoWithCharArg?.Equals(method) == true ||
                _trimMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, null));
            }

            if (_containsMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory)
                       .MakeContainsExpression(instance, arguments[0]));
            }

            if (_startsWithMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory)
                       .MakeStartsWithExpression(instance, arguments[0]));
            }

            if (_endsWithMethodInfo.Equals(method))
            {
                return(new MySqlStringComparisonMethodTranslator(_sqlExpressionFactory)
                       .MakeEndsWithExpression(instance, arguments[0]));
            }

            if (_padLeftWithOneArg.Equals(method))
            {
                return(TranslatePadLeftRight(
                           true,
                           instance,
                           arguments[0],
                           _sqlExpressionFactory.Constant(" "),
                           method.ReturnType));
            }

            if (_padRightWithOneArg.Equals(method))
            {
                return(TranslatePadLeftRight(
                           false,
                           instance,
                           arguments[0],
                           _sqlExpressionFactory.Constant(" "),
                           method.ReturnType));
            }

            if (_padLeftWithTwoArgs.Equals(method))
            {
                return(TranslatePadLeftRight(
                           true,
                           instance,
                           arguments[0],
                           arguments[1],
                           method.ReturnType));
            }

            if (_padRightWithTwoArgs.Equals(method))
            {
                return(TranslatePadLeftRight(
                           false,
                           instance,
                           arguments[0],
                           arguments[1],
                           method.ReturnType));
            }

            if (_firstOrDefaultMethodInfoWithoutArgs.Equals(method))
            {
                return(_sqlExpressionFactory.NullableFunction(
                           "SUBSTRING",
                           new[] { arguments[0], _sqlExpressionFactory.Constant(1), _sqlExpressionFactory.Constant(1) },
                           method.ReturnType));
            }

            if (_lastOrDefaultMethodInfoWithoutArgs.Equals(method))
            {
                return(_sqlExpressionFactory.NullableFunction(
                           "SUBSTRING",
                           new[]
                {
                    arguments[0],
                    _sqlExpressionFactory.NullableFunction(
                        "CHAR_LENGTH",
                        new[] { arguments[0] },
                        typeof(int)),
                    _sqlExpressionFactory.Constant(1)
                },
                           method.ReturnType));
            }

            if (_removeMethodInfoWithOneArg.Equals(method))
            {
                return(_sqlExpressionFactory.NullableFunction(
                           "SUBSTRING",
                           new[]
                {
                    instance,
                    _sqlExpressionFactory.Constant(1),
                    arguments[0],
                },
                           method.ReturnType,
                           instance.TypeMapping));
            }

            if (_removeMethodInfoWithTwoArgs.Equals(method))
            {
                var firstSubString = _sqlExpressionFactory.NullableFunction(
                    "SUBSTRING",
                    new[]
                {
                    instance,
                    _sqlExpressionFactory.Constant(1),
                    arguments[0]
                },
                    method.ReturnType,
                    instance.TypeMapping);

                var secondSubString = _sqlExpressionFactory.NullableFunction(
                    "SUBSTRING",
                    new[]
                {
                    instance,
                    _sqlExpressionFactory.Add(
                        _sqlExpressionFactory.Add(
                            arguments[0],
                            arguments[1]),
                        _sqlExpressionFactory.Constant(1)),
                    _sqlExpressionFactory.Subtract(
                        _sqlExpressionFactory.NullableFunction(
                            "CHAR_LENGTH",
                            new[] { instance },
                            typeof(int)),
                        _sqlExpressionFactory.Add(
                            arguments[0],
                            arguments[1])),
                },
                    method.ReturnType,
                    instance.TypeMapping);

                var concat = _sqlExpressionFactory.NullableFunction(
                    "CONCAT",
                    new[]
                {
                    firstSubString,
                    secondSubString
                },
                    method.ReturnType,
                    instance.TypeMapping);

                return(concat);
            }

            return(null);
        }
Ejemplo n.º 5
0
        public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments)
        {
            if (_indexOfMethodInfo.Equals(method))
            {
                var argument          = arguments[0];
                var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument);

                return(_sqlExpressionFactory.Subtract(
                           _sqlExpressionFactory.Function(
                               "LOCATE",
                               new[]
                {
                    _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping),
                    _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping)
                },
                               method.ReturnType),
                           _sqlExpressionFactory.Constant(1)));
            }

            if (_replaceMethodInfo.Equals(method))
            {
                var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, arguments[0], arguments[1]);

                return(_sqlExpressionFactory.Function(
                           "REPLACE",
                           new[]
                {
                    _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping),
                    _sqlExpressionFactory.ApplyTypeMapping(arguments[0], stringTypeMapping),
                    _sqlExpressionFactory.ApplyTypeMapping(arguments[1], stringTypeMapping)
                },
                           method.ReturnType,
                           stringTypeMapping));
            }

            if (_toLowerMethodInfo.Equals(method) ||
                _toUpperMethodInfo.Equals(method))
            {
                return(_sqlExpressionFactory.Function(
                           _toLowerMethodInfo.Equals(method) ? "LOWER" : "UPPER",
                           new[] { instance },
                           method.ReturnType,
                           instance.TypeMapping));
            }

            if (_substringMethodInfo.Equals(method))
            {
                return(_sqlExpressionFactory.Function(
                           "SUBSTRING",
                           new[]
                {
                    instance,
                    _sqlExpressionFactory.Add(
                        arguments[0],
                        _sqlExpressionFactory.Constant(1)),
                    arguments[1]
                },
                           method.ReturnType,
                           instance.TypeMapping));
            }

            if (_isNullOrWhiteSpaceMethodInfo.Equals(method))
            {
                return(_sqlExpressionFactory.OrElse(
                           _sqlExpressionFactory.IsNull(arguments[0]),
                           _sqlExpressionFactory.Equal(
                               ProcessTrimMethod(arguments[0], null, null),
                               _sqlExpressionFactory.Constant(string.Empty))));
            }

            if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimStartMethodInfoWithCharArg?.Equals(method) == true ||
                _trimStartMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, "LEADING"));
            }

            if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimEndMethodInfoWithCharArg?.Equals(method) == true ||
                _trimEndMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, "TRAILING"));
            }

            if (_trimMethodInfoWithoutArgs?.Equals(method) == true ||
                _trimMethodInfoWithCharArg?.Equals(method) == true ||
                _trimMethodInfoWithCharArrayArg.Equals(method))
            {
                return(ProcessTrimMethod(instance, arguments.Count > 0 ? arguments[0] : null, null));
            }

            if (_containsMethodInfo.Equals(method))
            {
                var pattern           = arguments[0];
                var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern);

                instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping);
                pattern  = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping);

                var locateCondition = _sqlExpressionFactory.GreaterThan(
                    _sqlExpressionFactory.Function(
                        "LOCATE",
                        new[]
                {
                    _sqlExpressionFactory.ComplexFunctionArgument(
                        new[]
                    {
                        _sqlExpressionFactory.Fragment("BINARY"),             // for case sensitivity
                        pattern,
                    },
                        typeof(string)),
                    instance,
                },
                        typeof(int)),
                    _sqlExpressionFactory.Constant(0));

                if (pattern is SqlConstantExpression constantPattern)
                {
                    if ((string)constantPattern.Value == string.Empty)
                    {
                        return(_sqlExpressionFactory.Constant(true));
                    }

                    return(locateCondition);
                }

                return(_sqlExpressionFactory.OrElse(
                           _sqlExpressionFactory.Equal(
                               pattern,
                               _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)),
                           locateCondition));
            }

            if (_startsWithMethodInfo.Equals(method))
            {
                return(TranslateStartsEndsWith(instance, arguments[0], true));
            }

            if (_endsWithMethodInfo.Equals(method))
            {
                return(TranslateStartsEndsWith(instance, arguments[0], false));
            }

            if (_padLeftWithOneArg.Equals(method))
            {
                return(TranslatePadLeftRight(
                           true,
                           instance,
                           arguments[0],
                           _sqlExpressionFactory.Constant(" "),
                           method.ReturnType));
            }

            if (_padRightWithOneArg.Equals(method))
            {
                return(TranslatePadLeftRight(
                           false,
                           instance,
                           arguments[0],
                           _sqlExpressionFactory.Constant(" "),
                           method.ReturnType));
            }

            if (_padLeftWithTwoArgs.Equals(method))
            {
                return(TranslatePadLeftRight(
                           true,
                           instance,
                           arguments[0],
                           arguments[1],
                           method.ReturnType));
            }

            if (_padRightWithTwoArgs.Equals(method))
            {
                return(TranslatePadLeftRight(
                           false,
                           instance,
                           arguments[0],
                           arguments[1],
                           method.ReturnType));
            }

            return(null);
        }