public virtual SqlExpression Translate( SqlExpression instance, MemberInfo member, System.Type returnType) { var declaringType = member.DeclaringType; if (declaringType == typeof(DateTime)) { var memberName = member.Name; if (s_datePartMapping.TryGetValue(memberName, out var datePart)) { var extract = _sqlExpressionFactory.Function( "EXTRACT", new[] { new SpannerTimestampExtractExpression(_sqlExpressionFactory, instance, datePart) }, returnType); if (datePart == "DAYOFWEEK") { // Cloud Spanner is 1-based, .NET is 0-based. return(_sqlExpressionFactory.ApplyDefaultTypeMapping(_sqlExpressionFactory.Subtract(extract, _sqlExpressionFactory.Constant(1)))); } return(_sqlExpressionFactory.ApplyDefaultTypeMapping(extract)); } } return(null); }
private SqlExpression TranslateIndexOf( SqlExpression instance, MethodInfo method, SqlExpression searchExpression, SqlExpression?startIndex) { var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, searchExpression) !; searchExpression = _sqlExpressionFactory.ApplyTypeMapping(searchExpression, stringTypeMapping); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); var charIndexArguments = new List <SqlExpression> { searchExpression, instance }; if (startIndex is not null) { charIndexArguments.Add(_sqlExpressionFactory.Add(startIndex, _sqlExpressionFactory.Constant(1))); } var argumentsPropagateNullability = Enumerable.Repeat(true, charIndexArguments.Count); SqlExpression charIndexExpression; var storeType = stringTypeMapping.StoreType; if (string.Equals(storeType, "nvarchar(max)", StringComparison.OrdinalIgnoreCase) || string.Equals(storeType, "varchar(max)", StringComparison.OrdinalIgnoreCase)) { charIndexExpression = _sqlExpressionFactory.Function( "CHARINDEX", charIndexArguments, nullable: true, argumentsPropagateNullability, typeof(long)); charIndexExpression = _sqlExpressionFactory.Convert(charIndexExpression, typeof(int)); } else { charIndexExpression = _sqlExpressionFactory.Function( "CHARINDEX", charIndexArguments, nullable: true, argumentsPropagateNullability, method.ReturnType); } charIndexExpression = _sqlExpressionFactory.Subtract(charIndexExpression, _sqlExpressionFactory.Constant(1)); return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.Equal( searchExpression, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), _sqlExpressionFactory.Constant(0)) }, charIndexExpression)); }
public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { Check.NotNull(member, nameof(member)); Check.NotNull(returnType, nameof(returnType)); if (typeof(Polygon).IsAssignableFrom(member.DeclaringType)) { Debug.Assert(instance.TypeMapping != null, "Instance must have typeMapping assigned."); var storeType = instance.TypeMapping.StoreType; var isGeography = string.Equals(storeType, "geography", StringComparison.OrdinalIgnoreCase); if (isGeography) { if (Equals(_exteriorRing, member)) { return(_sqlExpressionFactory.Function( instance, "RingN", new[] { _sqlExpressionFactory.Constant(1) }, returnType, _typeMappingSource.FindMapping(returnType, storeType))); } if (Equals(_numInteriorRings, member)) { return(_sqlExpressionFactory.Subtract( _sqlExpressionFactory.Function( instance, "NumRings", Array.Empty <SqlExpression>(), returnType), _sqlExpressionFactory.Constant(1))); } } if (_geometryMemberToFunctionName.TryGetValue(member, out var functionName)) { var resultTypeMapping = typeof(Geometry).IsAssignableFrom(returnType) ? _typeMappingSource.FindMapping(returnType, storeType) : _typeMappingSource.FindMapping(returnType); return(_sqlExpressionFactory.Function( instance, functionName, Array.Empty <SqlExpression>(), returnType, resultTypeMapping)); } } return(null); }
public virtual SqlExpression?Translate( SqlExpression?instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments, IDiagnosticsLogger <DbLoggerCategory.Query> logger) { Check.NotNull(method, nameof(method)); Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); if (instance != null) { if (_indexOfMethodInfo.Equals(method)) { var argument = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument); return(_sqlExpressionFactory.Subtract( _sqlExpressionFactory.Function( "instr", new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping) }, nullable: true, argumentsPropagateNullability: new[] { true, true }, method.ReturnType), _sqlExpressionFactory.Constant(1))); } if (_replaceMethodInfo.Equals(method)) { var firstArgument = arguments[0]; var secondArgument = arguments[1]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, firstArgument, secondArgument); return(_sqlExpressionFactory.Function( "replace", new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(firstArgument, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(secondArgument, stringTypeMapping) }, nullable: true, argumentsPropagateNullability: new[] { true, true, true }, method.ReturnType, stringTypeMapping)); } if (_toLowerMethodInfo.Equals(method) || _toUpperMethodInfo.Equals(method)) { return(_sqlExpressionFactory.Function( _toLowerMethodInfo.Equals(method) ? "lower" : "upper", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, method.ReturnType, instance.TypeMapping)); } if (_substringMethodInfo.Equals(method)) { return(_sqlExpressionFactory.Function( "substr", new[] { instance, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1)), arguments[1] }, nullable: true, argumentsPropagateNullability: new[] { true, true, true }, method.ReturnType, instance.TypeMapping)); } if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true || _trimStartMethodInfoWithCharArg?.Equals(method) == true || _trimStartMethodInfoWithCharArrayArg.Equals(method)) { return(ProcessTrimMethod(instance, arguments, "ltrim")); } if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true || _trimEndMethodInfoWithCharArg?.Equals(method) == true || _trimEndMethodInfoWithCharArrayArg.Equals(method)) { return(ProcessTrimMethod(instance, arguments, "rtrim")); } if (_trimMethodInfoWithoutArgs?.Equals(method) == true || _trimMethodInfoWithCharArg?.Equals(method) == true || _trimMethodInfoWithCharArrayArg.Equals(method)) { return(ProcessTrimMethod(instance, arguments, "trim")); } if (_containsMethodInfo.Equals(method)) { var pattern = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping); return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.Equal( pattern, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "instr", new[] { instance, pattern }, nullable: true, argumentsPropagateNullability: new[] { true, true }, typeof(int)), _sqlExpressionFactory.Constant(0)))); } if (_startsWithMethodInfo.Equals(method)) { return(TranslateStartsEndsWith(instance, arguments[0], true)); } if (_endsWithMethodInfo.Equals(method)) { return(TranslateStartsEndsWith(instance, arguments[0], false)); } } if (_isNullOrWhiteSpaceMethodInfo.Equals(method)) { var argument = arguments[0]; return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.IsNull(argument), _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( "trim", new[] { argument }, nullable: true, argumentsPropagateNullability: new[] { true }, argument.Type, argument.TypeMapping), _sqlExpressionFactory.Constant(string.Empty)))); } if (_firstOrDefaultMethodInfoWithoutArgs.Equals(method)) { var argument = arguments[0]; return(_sqlExpressionFactory.Function( "substr", new[] { argument, _sqlExpressionFactory.Constant(1), _sqlExpressionFactory.Constant(1) }, nullable: true, argumentsPropagateNullability: new[] { true, true, true }, method.ReturnType)); } if (_lastOrDefaultMethodInfoWithoutArgs.Equals(method)) { var argument = arguments[0]; return(_sqlExpressionFactory.Function( "substr", new[] { argument, _sqlExpressionFactory.Function( "length", new[] { argument }, nullable: true, argumentsPropagateNullability: new[] { true }, typeof(int)), _sqlExpressionFactory.Constant(1) }, nullable: true, argumentsPropagateNullability: new[] { true, true, true }, method.ReturnType)); } return(null); }
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); argument = _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping); var charIndexExpression = _sqlExpressionFactory.Subtract( _sqlExpressionFactory.Function( "CHARINDEX", new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, method.ReturnType), _sqlExpressionFactory.Constant(1)); return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.Equal( argument, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), _sqlExpressionFactory.Constant(0)) }, charIndexExpression)); } if (_replaceMethodInfo.Equals(method)) { var firstArgument = arguments[0]; var secondArgument = arguments[1]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, firstArgument, secondArgument); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); firstArgument = _sqlExpressionFactory.ApplyTypeMapping(firstArgument, stringTypeMapping); secondArgument = _sqlExpressionFactory.ApplyTypeMapping(secondArgument, stringTypeMapping); return(_sqlExpressionFactory.Function( "REPLACE", new[] { instance, firstArgument, secondArgument }, 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)) { var argument = arguments[0]; return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.IsNull(argument), _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( "LTRIM", new[] { _sqlExpressionFactory.Function( "RTRIM", new[] { argument }, argument.Type, argument.TypeMapping) }, argument.Type, argument.TypeMapping), _sqlExpressionFactory.Constant(string.Empty, argument.TypeMapping)))); } if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true || (_trimStartMethodInfoWithCharArrayArg.Equals(method) // SqlServer LTRIM does not take arguments && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { return(_sqlExpressionFactory.Function( "LTRIM", new[] { instance }, instance.Type, instance.TypeMapping)); } if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true || (_trimEndMethodInfoWithCharArrayArg.Equals(method) // SqlServer RTRIM does not take arguments && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { return(_sqlExpressionFactory.Function( "RTRIM", new[] { instance }, instance.Type, instance.TypeMapping)); } if (_trimMethodInfoWithoutArgs?.Equals(method) == true || (_trimMethodInfoWithCharArrayArg.Equals(method) // SqlServer LTRIM/RTRIM does not take arguments && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { return(_sqlExpressionFactory.Function( "LTRIM", new[] { _sqlExpressionFactory.Function( "RTRIM", new[] { instance }, instance.Type, instance.TypeMapping) }, instance.Type, instance.TypeMapping)); } if (_containsMethodInfo.Equals(method)) { var pattern = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping); if (pattern is SqlConstantExpression constantPattern) { if ((string)constantPattern.Value == string.Empty) { return(_sqlExpressionFactory.Constant(true)); } return(_sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "CHARINDEX", new[] { pattern, instance }, typeof(int)), _sqlExpressionFactory.Constant(0))); } return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.Equal( pattern, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "CHARINDEX", new[] { pattern, instance }, typeof(int)), _sqlExpressionFactory.Constant(0)))); } if (_startsWithMethodInfo.Equals(method)) { return(TranslateStartsEndsWith(instance, arguments[0], true)); } if (_endsWithMethodInfo.Equals(method)) { return(TranslateStartsEndsWith(instance, arguments[0], false)); } return(null); }
public virtual SqlExpression?Translate( SqlExpression?instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments, IDiagnosticsLogger <DbLoggerCategory.Query> logger) { Check.NotNull(method, nameof(method)); Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); if (instance != null) { if (_indexOfMethodInfo.Equals(method)) { var argument = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument) !; argument = _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping); SqlExpression charIndexExpression; var storeType = stringTypeMapping.StoreType; if (string.Equals(storeType, "nvarchar(max)", StringComparison.OrdinalIgnoreCase) || string.Equals(storeType, "varchar(max)", StringComparison.OrdinalIgnoreCase)) { charIndexExpression = _sqlExpressionFactory.Function( "CHARINDEX", new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, nullable: true, argumentsPropagateNullability: new[] { true, true }, typeof(long)); charIndexExpression = _sqlExpressionFactory.Convert(charIndexExpression, typeof(int)); } else { charIndexExpression = _sqlExpressionFactory.Function( "CHARINDEX", new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, nullable: true, argumentsPropagateNullability: new[] { true, true }, method.ReturnType); } charIndexExpression = _sqlExpressionFactory.Subtract(charIndexExpression, _sqlExpressionFactory.Constant(1)); return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.Equal( argument, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), _sqlExpressionFactory.Constant(0)) }, charIndexExpression)); } if (_replaceMethodInfo.Equals(method)) { var firstArgument = arguments[0]; var secondArgument = arguments[1]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, firstArgument, secondArgument); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); firstArgument = _sqlExpressionFactory.ApplyTypeMapping(firstArgument, stringTypeMapping); secondArgument = _sqlExpressionFactory.ApplyTypeMapping(secondArgument, stringTypeMapping); return(_sqlExpressionFactory.Function( "REPLACE", new[] { instance, firstArgument, secondArgument }, nullable: true, argumentsPropagateNullability: new[] { true, true, true }, method.ReturnType, stringTypeMapping)); } if (_toLowerMethodInfo.Equals(method) || _toUpperMethodInfo.Equals(method)) { return(_sqlExpressionFactory.Function( _toLowerMethodInfo.Equals(method) ? "LOWER" : "UPPER", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, method.ReturnType, instance.TypeMapping)); } if (_substringMethodInfo.Equals(method)) { return(_sqlExpressionFactory.Function( "SUBSTRING", new[] { instance, _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)), arguments[1] }, nullable: true, argumentsPropagateNullability: new[] { true, true, true }, method.ReturnType, instance.TypeMapping)); } if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true || (_trimStartMethodInfoWithCharArrayArg.Equals(method) // SqlServer LTRIM does not take arguments && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { return(_sqlExpressionFactory.Function( "LTRIM", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, instance.Type, instance.TypeMapping)); } if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true || (_trimEndMethodInfoWithCharArrayArg.Equals(method) // SqlServer RTRIM does not take arguments && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { return(_sqlExpressionFactory.Function( "RTRIM", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, instance.Type, instance.TypeMapping)); } if (_trimMethodInfoWithoutArgs?.Equals(method) == true || (_trimMethodInfoWithCharArrayArg.Equals(method) // SqlServer LTRIM/RTRIM does not take arguments && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { return(_sqlExpressionFactory.Function( "LTRIM", new[] { _sqlExpressionFactory.Function( "RTRIM", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, instance.Type, instance.TypeMapping) }, nullable: true, argumentsPropagateNullability: new[] { true }, instance.Type, instance.TypeMapping)); } if (_containsMethodInfo.Equals(method)) { var pattern = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping); if (pattern is SqlConstantExpression constantPattern) { if (!(constantPattern.Value is string patternValue)) { return(_sqlExpressionFactory.Like( instance, _sqlExpressionFactory.Constant(null, stringTypeMapping))); } if (patternValue.Length == 0) { return(_sqlExpressionFactory.Constant(true)); } return(patternValue.Any(IsLikeWildChar) ? _sqlExpressionFactory.Like( instance, _sqlExpressionFactory.Constant($"%{EscapeLikePattern(patternValue)}%"), _sqlExpressionFactory.Constant(LikeEscapeString)) : _sqlExpressionFactory.Like(instance, _sqlExpressionFactory.Constant($"%{patternValue}%"))); } return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.Like( pattern, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "CHARINDEX", new[] { pattern, instance }, nullable: true, argumentsPropagateNullability: new[] { true, true }, typeof(int)), _sqlExpressionFactory.Constant(0)))); } if (_startsWithMethodInfo.Equals(method)) { return(TranslateStartsEndsWith(instance, arguments[0], true)); } if (_endsWithMethodInfo.Equals(method)) { return(TranslateStartsEndsWith(instance, arguments[0], false)); } } if (_isNullOrEmptyMethodInfo.Equals(method)) { var argument = arguments[0]; return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.IsNull(argument), _sqlExpressionFactory.Like( argument, _sqlExpressionFactory.Constant(string.Empty)))); } if (_isNullOrWhiteSpaceMethodInfo.Equals(method)) { var argument = arguments[0]; return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.IsNull(argument), _sqlExpressionFactory.Equal( argument, _sqlExpressionFactory.Constant(string.Empty, argument.TypeMapping)))); } if (_firstOrDefaultMethodInfoWithoutArgs.Equals(method)) { var argument = arguments[0]; return(_sqlExpressionFactory.Function( "SUBSTRING", new[] { argument, _sqlExpressionFactory.Constant(1), _sqlExpressionFactory.Constant(1) }, nullable: true, argumentsPropagateNullability: new[] { true, true, true }, method.ReturnType)); } if (_lastOrDefaultMethodInfoWithoutArgs.Equals(method)) { var argument = arguments[0]; return(_sqlExpressionFactory.Function( "SUBSTRING", new[] { argument, _sqlExpressionFactory.Function( "LEN", new[] { argument }, nullable: true, argumentsPropagateNullability: new[] { true }, typeof(int)), _sqlExpressionFactory.Constant(1) }, nullable: true, argumentsPropagateNullability: new[] { true, true, true }, method.ReturnType)); } return(null); }
public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments) { if (s_containsMethodInfo.Equals(method)) { var pos = TranslateOneArgFunction("STRPOS", instance, arguments[0], typeof(long)); return(_sqlExpressionFactory.ApplyDefaultTypeMapping(_sqlExpressionFactory.GreaterThan(pos, _sqlExpressionFactory.Constant(0L)))); } if (s_startsWithMethodInfo.Equals(method)) { return(TranslateOneArgFunction("STARTS_WITH", instance, arguments[0], typeof(bool))); } if (s_endsWithMethodInfo.Equals(method)) { return(TranslateOneArgFunction("ENDS_WITH", instance, arguments[0], typeof(bool))); } if (s_indexOfMethodInfo.Equals(method)) { var pos = TranslateOneArgFunction("STRPOS", instance, arguments[0], typeof(long)); return(_sqlExpressionFactory.ApplyDefaultTypeMapping(_sqlExpressionFactory.Subtract(pos, _sqlExpressionFactory.Constant(1L)))); } if (s_replaceMethodInfo.Equals(method)) { return(TranslateTwoArgFunction("REPLACE", instance, arguments[0], arguments[1], typeof(string))); } if (s_toLowerMethodInfo.Equals(method)) { return(TranslateNoArgFunction("LOWER", instance, typeof(string))); } if (s_toUpperMethodInfo.Equals(method)) { return(TranslateNoArgFunction("UPPER", instance, typeof(string))); } if (s_substringMethodInfo.Equals(method)) { return(TranslateOneArgFunction("SUBSTR", instance, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1L)), typeof(string))); } if (s_substringWithLengthMethodInfo.Equals(method)) { return(TranslateTwoArgFunction("SUBSTR", instance, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1L)), arguments[1], typeof(string))); } if (s_trimStartMethodInfoWithoutArgs.Equals(method)) { return(TranslateNoArgFunction("LTRIM", instance, typeof(string))); } if (s_trimStartMethodInfoWithCharArg.Equals(method)) { return(TranslateOneArgFunction("LTRIM", instance, arguments[0], typeof(string))); } if (s_trimEndMethodInfoWithoutArgs.Equals(method)) { return(TranslateNoArgFunction("RTRIM", instance, typeof(string))); } if (s_trimEndMethodInfoWithCharArg.Equals(method)) { return(TranslateOneArgFunction("RTRIM", instance, arguments[0], typeof(string))); } if (s_trimMethodInfoWithoutArgs.Equals(method)) { return(TranslateNoArgFunction("TRIM", instance, typeof(string))); } if (s_trimMethodInfoWithCharArg.Equals(method)) { return(TranslateOneArgFunction("TRIM", instance, arguments[0], typeof(string))); } if (s_padLeftMethodInfo.Equals(method)) { return(TranslateOneArgFunction("LPAD", instance, arguments[0], typeof(string))); } if (s_padLeftWithStringMethodInfo.Equals(method)) { return(TranslateTwoArgFunction("LPAD", instance, arguments[0], arguments[1], typeof(string))); } if (s_padRightMethodInfo.Equals(method)) { return(TranslateOneArgFunction("RPAD", instance, arguments[0], typeof(string))); } if (s_padRightWithStringMethodInfo.Equals(method)) { return(TranslateTwoArgFunction("RPAD", instance, arguments[0], arguments[1], typeof(string))); } if (s_formatOneArgMethodInfo.Equals(method) || s_formatTwoArgMethodInfo.Equals(method) || s_formatThreeArgMethodInfo.Equals(method) || s_formatVarArgMethodInfo.Equals(method)) { return(TranslateStaticFunction("FORMAT", arguments, typeof(string))); } if (s_joinMethodInfo.Equals(method)) { return(TranslateTwoArgFunction("ARRAY_TO_STRING", arguments[1], arguments[0], _sqlExpressionFactory.Constant(""), typeof(string))); } return(null); }
public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { Check.NotNull(member, nameof(member)); Check.NotNull(returnType, nameof(returnType)); if (member.DeclaringType == typeof(DateTime)) { var memberName = member.Name; if (_datePartMapping.TryGetValue(memberName, out var datePart)) { return(_sqlExpressionFactory.Convert( SqliteExpression.Strftime( _sqlExpressionFactory, typeof(string), datePart, instance), returnType)); } if (string.Equals(memberName, nameof(DateTime.Ticks))) { return(_sqlExpressionFactory.Convert( _sqlExpressionFactory.Multiply( _sqlExpressionFactory.Subtract( _sqlExpressionFactory.Function( "julianday", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, typeof(double)), _sqlExpressionFactory.Constant(1721425.5)), // NB: Result of julianday('0001-01-01 00:00:00') _sqlExpressionFactory.Constant(TimeSpan.TicksPerDay)), typeof(long))); } if (string.Equals(memberName, nameof(DateTime.Millisecond))) { return(_sqlExpressionFactory.Modulo( _sqlExpressionFactory.Multiply( _sqlExpressionFactory.Convert( SqliteExpression.Strftime( _sqlExpressionFactory, typeof(string), "%f", instance), typeof(double)), _sqlExpressionFactory.Constant(1000)), _sqlExpressionFactory.Constant(1000))); } var format = "%Y-%m-%d %H:%M:%f"; SqlExpression timestring; var modifiers = new List <SqlExpression>(); switch (memberName) { case nameof(DateTime.Now): timestring = _sqlExpressionFactory.Constant("now"); modifiers.Add(_sqlExpressionFactory.Constant("localtime")); break; case nameof(DateTime.UtcNow): timestring = _sqlExpressionFactory.Constant("now"); break; case nameof(DateTime.Date): timestring = instance; modifiers.Add(_sqlExpressionFactory.Constant("start of day")); break; case nameof(DateTime.Today): timestring = _sqlExpressionFactory.Constant("now"); modifiers.Add(_sqlExpressionFactory.Constant("localtime")); modifiers.Add(_sqlExpressionFactory.Constant("start of day")); break; case nameof(DateTime.TimeOfDay): format = "%H:%M:%f"; timestring = instance; break; default: return(null); } Check.DebugAssert(timestring != null, "timestring is null"); return(_sqlExpressionFactory.Function( "rtrim", new SqlExpression[] { _sqlExpressionFactory.Function( "rtrim", new SqlExpression[] { SqliteExpression.Strftime( _sqlExpressionFactory, returnType, format, timestring, modifiers), _sqlExpressionFactory.Constant("0") }, nullable: true, argumentsPropagateNullability: new[] { true, false }, returnType), _sqlExpressionFactory.Constant(".") }, nullable: true, argumentsPropagateNullability: new[] { true, false }, returnType)); } return(null); }
public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments) { Check.NotNull(method, nameof(method)); Check.NotNull(arguments, nameof(arguments)); if (_indexOfMethodInfo.Equals(method)) { var argument = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument); argument = _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping); SqlExpression charIndexExpression; var storeType = stringTypeMapping.StoreType; if (string.Equals(storeType, "nvarchar(max)", StringComparison.OrdinalIgnoreCase) || string.Equals(storeType, "varchar(max)", StringComparison.OrdinalIgnoreCase)) { charIndexExpression = _sqlExpressionFactory.Function( "CHARINDEX", new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, nullable: true, argumentsPropagateNullability: new [] { true, true }, typeof(long)); charIndexExpression = _sqlExpressionFactory.Convert(charIndexExpression, typeof(int)); } else { charIndexExpression = _sqlExpressionFactory.Function( "CHARINDEX", new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, nullable: true, argumentsPropagateNullability: new[] { true, true }, method.ReturnType); } charIndexExpression = _sqlExpressionFactory.Subtract(charIndexExpression, _sqlExpressionFactory.Constant(1)); return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.Equal( argument, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), _sqlExpressionFactory.Constant(0)) }, charIndexExpression)); } if (_replaceMethodInfo.Equals(method)) { var firstArgument = arguments[0]; var secondArgument = arguments[1]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, firstArgument, secondArgument); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); firstArgument = _sqlExpressionFactory.ApplyTypeMapping(firstArgument, stringTypeMapping); secondArgument = _sqlExpressionFactory.ApplyTypeMapping(secondArgument, stringTypeMapping); return(_sqlExpressionFactory.Function( "REPLACE", new[] { instance, firstArgument, secondArgument }, nullable: true, argumentsPropagateNullability: new[] { true, true, true }, method.ReturnType, stringTypeMapping)); } if (_toLowerMethodInfo.Equals(method) || _toUpperMethodInfo.Equals(method)) { return(_sqlExpressionFactory.Function( _toLowerMethodInfo.Equals(method) ? "LOWER" : "UPPER", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, method.ReturnType, instance.TypeMapping)); } if (_substringMethodInfo.Equals(method)) { return(_sqlExpressionFactory.Function( "SUBSTRING", new[] { instance, _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)), arguments[1] }, nullable: true, argumentsPropagateNullability: new[] { true, true, true }, method.ReturnType, instance.TypeMapping)); } if (_isNullOrWhiteSpaceMethodInfo.Equals(method)) { var argument = arguments[0]; return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.IsNull(argument), _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( "LTRIM", new[] { _sqlExpressionFactory.Function( "RTRIM", new[] { argument }, nullable: true, argumentsPropagateNullability: new[] { true }, argument.Type, argument.TypeMapping) }, nullable: true, argumentsPropagateNullability: new[] { true }, argument.Type, argument.TypeMapping), _sqlExpressionFactory.Constant(string.Empty, argument.TypeMapping)))); } if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true || (_trimStartMethodInfoWithCharArrayArg.Equals(method) // SqlServer LTRIM does not take arguments && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { return(_sqlExpressionFactory.Function( "LTRIM", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, instance.Type, instance.TypeMapping)); } if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true || (_trimEndMethodInfoWithCharArrayArg.Equals(method) // SqlServer RTRIM does not take arguments && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { return(_sqlExpressionFactory.Function( "RTRIM", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, instance.Type, instance.TypeMapping)); } if (_trimMethodInfoWithoutArgs?.Equals(method) == true || (_trimMethodInfoWithCharArrayArg.Equals(method) // SqlServer LTRIM/RTRIM does not take arguments && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { return(_sqlExpressionFactory.Function( "LTRIM", new[] { _sqlExpressionFactory.Function( "RTRIM", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, instance.Type, instance.TypeMapping) }, nullable: true, argumentsPropagateNullability: new[] { true }, instance.Type, instance.TypeMapping)); } if (_containsMethodInfo.Equals(method)) { var pattern = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping); if (pattern is SqlConstantExpression constantPattern) { // Intentionally string.Empty since we don't want to match nulls here. #pragma warning disable CA1820 // Test for empty strings using string length if ((string)constantPattern.Value == string.Empty) #pragma warning restore CA1820 // Test for empty strings using string length { return(_sqlExpressionFactory.Constant(true)); } return(_sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "CHARINDEX", new[] { pattern, instance }, nullable: true, argumentsPropagateNullability: new[] { true, true }, typeof(int)), _sqlExpressionFactory.Constant(0))); } return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.Equal( pattern, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "CHARINDEX", new[] { pattern, instance }, nullable: true, argumentsPropagateNullability: new[] { true, true }, typeof(int)), _sqlExpressionFactory.Constant(0)))); } if (_startsWithMethodInfo.Equals(method)) { return(TranslateStartsEndsWith(instance, arguments[0], true)); } if (_endsWithMethodInfo.Equals(method)) { return(TranslateStartsEndsWith(instance, arguments[0], false)); } return(null); }
public virtual SqlExpression Translate( SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments, IDiagnosticsLogger <DbLoggerCategory.Query> logger) { if (method == IndexOfString || method == IndexOfChar) { var argument = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument); return(_sqlExpressionFactory.Subtract( _sqlExpressionFactory.Function( "strpos", new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping) }, nullable: true, argumentsPropagateNullability: TrueArrays[2], method.ReturnType), _sqlExpressionFactory.Constant(1))); } if (method == Replace) { var oldValue = arguments[0]; var newValue = arguments[1]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, oldValue, newValue); return(_sqlExpressionFactory.Function( "replace", new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(oldValue, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(newValue, stringTypeMapping) }, nullable: true, argumentsPropagateNullability: TrueArrays[3], method.ReturnType, stringTypeMapping)); } if (method == ToLower || method == ToUpper) { return(_sqlExpressionFactory.Function( method == ToLower ? "lower" : "upper", new[] { instance }, nullable: true, argumentsPropagateNullability: TrueArrays[1], method.ReturnType, instance.TypeMapping)); } if (method == Substring || method == SubstringWithLength) { var args = method == Substring ? new[] { instance, GenerateOneBasedIndexExpression(arguments[0]) } : new[] { instance, GenerateOneBasedIndexExpression(arguments[0]), arguments[1] }; return(_sqlExpressionFactory.Function( "substring", args, nullable: true, argumentsPropagateNullability: TrueArrays[args.Length], method.ReturnType, instance.TypeMapping)); } if (method == IsNullOrWhiteSpace) { var argument = arguments[0]; return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.IsNull(argument), _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( "btrim", new[] { argument, _whitespace }, nullable: true, argumentsPropagateNullability: TrueArrays[2], argument.Type, argument.TypeMapping), _sqlExpressionFactory.Constant(string.Empty, argument.TypeMapping)))); } var isTrimStart = method == TrimStartWithNoParam || method == TrimStartWithChars || method == TrimStartWithSingleChar; var isTrimEnd = method == TrimEndWithNoParam || method == TrimEndWithChars || method == TrimEndWithSingleChar; var isTrimBoth = method == TrimBothWithNoParam || method == TrimBothWithChars || method == TrimBothWithSingleChar; if (isTrimStart || isTrimEnd || isTrimBoth) { char[] trimChars = null; if (method == TrimStartWithChars || method == TrimStartWithSingleChar || method == TrimEndWithChars || method == TrimEndWithSingleChar || method == TrimBothWithChars || method == TrimBothWithSingleChar) { var constantTrimChars = arguments[0] as SqlConstantExpression; if (constantTrimChars == null) { return(null); // Don't translate if trim chars isn't a constant } trimChars = constantTrimChars.Value is char c ? new[] { c } : (char[])constantTrimChars.Value; } return(_sqlExpressionFactory.Function( isTrimStart ? "ltrim" : isTrimEnd ? "rtrim" : "btrim", new[] { instance, trimChars == null || trimChars.Length == 0 ? _whitespace : _sqlExpressionFactory.Constant(new string(trimChars)) }, nullable: true, argumentsPropagateNullability: TrueArrays[2], instance.Type, instance.TypeMapping)); } if (method == Contains) { var pattern = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping); var strposCheck = _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "strpos", new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping) }, nullable: true, argumentsPropagateNullability: TrueArrays[2], typeof(int)), _sqlExpressionFactory.Constant(0)); if (pattern is SqlConstantExpression constantPattern) { return((string)constantPattern.Value == string.Empty ? (SqlExpression)_sqlExpressionFactory.Constant(true) : strposCheck); } return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.Equal( pattern, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), strposCheck)); } if (method == PadLeft || method == PadLeftWithChar || method == PadRight || method == PadRightWithChar) { var args = method == PadLeft || method == PadRight ? new[] { instance, arguments[0] } : new[] { instance, arguments[0], arguments[1] }; return(_sqlExpressionFactory.Function( method == PadLeft || method == PadLeftWithChar ? "lpad" : "rpad", args, nullable: true, argumentsPropagateNullability: TrueArrays[args.Length], instance.Type, instance.TypeMapping)); } if (method == FirstOrDefaultMethodInfoWithoutArgs) { var argument = arguments[0]; return(_sqlExpressionFactory.Function( "substr", new[] { argument, _sqlExpressionFactory.Constant(1), _sqlExpressionFactory.Constant(1) }, nullable: true, argumentsPropagateNullability: TrueArrays[3], method.ReturnType)); } if (method == LastOrDefaultMethodInfoWithoutArgs) { var argument = arguments[0]; return(_sqlExpressionFactory.Function( "substr", new[] { argument, _sqlExpressionFactory.Function( "length", new[] { argument }, nullable: true, argumentsPropagateNullability: new[] { true }, typeof(int)), _sqlExpressionFactory.Constant(1) }, nullable: true, argumentsPropagateNullability: TrueArrays[3], method.ReturnType)); } if (method == DbFunctionsReverse) { return(_sqlExpressionFactory.Function( "reverse", new[] { arguments[1] }, nullable: true, argumentsPropagateNullability: TrueArrays[1], typeof(string), arguments[1].TypeMapping)); } if (method == StartsWith) { return(TranslateStartsEndsWith(instance, arguments[0], true)); } if (method == EndsWith) { return(TranslateStartsEndsWith(instance, arguments[0], false)); } return(null); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual SqlExpression?Translate( SqlExpression?instance, MemberInfo member, Type returnType, IDiagnosticsLogger <DbLoggerCategory.Query> logger) { if (typeof(Polygon).IsAssignableFrom(member.DeclaringType)) { Check.DebugAssert(instance !.TypeMapping != null, "Instance must have typeMapping assigned."); var storeType = instance.TypeMapping.StoreType; var isGeography = string.Equals(storeType, "geography", StringComparison.OrdinalIgnoreCase); if (isGeography) { if (Equals(ExteriorRing, member)) { return(_sqlExpressionFactory.Function( instance, "RingN", new[] { _sqlExpressionFactory.Constant(1) }, nullable: true, instancePropagatesNullability: true, argumentsPropagateNullability: new[] { false }, returnType, _typeMappingSource.FindMapping(returnType, storeType))); } if (Equals(NumInteriorRings, member)) { return(_sqlExpressionFactory.Subtract( _sqlExpressionFactory.Function( instance, "NumRings", Array.Empty <SqlExpression>(), nullable: true, instancePropagatesNullability: true, argumentsPropagateNullability: Array.Empty <bool>(), returnType), _sqlExpressionFactory.Constant(1))); } } if (GeometryMemberToFunctionName.TryGetValue(member, out var functionName)) { var resultTypeMapping = typeof(Geometry).IsAssignableFrom(returnType) ? _typeMappingSource.FindMapping(returnType, storeType) : _typeMappingSource.FindMapping(returnType); return(_sqlExpressionFactory.Function( instance, functionName, Array.Empty <SqlExpression>(), nullable: true, instancePropagatesNullability: true, argumentsPropagateNullability: Array.Empty <bool>(), returnType, resultTypeMapping)); } } return(null); }
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( "instr", new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping) }, true, null, method.ReturnType), _sqlExpressionFactory.Constant(1))); } if (_replaceMethodInfo.Equals(method)) { var firstArgument = arguments[0]; var secondArgument = arguments[1]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, firstArgument, secondArgument); return(_sqlExpressionFactory.Function( "replace", new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(firstArgument, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(secondArgument, stringTypeMapping) }, true, null, method.ReturnType, stringTypeMapping)); } if (_toLowerMethodInfo.Equals(method) || _toUpperMethodInfo.Equals(method)) { return(_sqlExpressionFactory.Function( _toLowerMethodInfo.Equals(method) ? "lower" : "upper", new[] { instance }, true, null, method.ReturnType, instance.TypeMapping)); } if (_substringMethodInfo.Equals(method)) { return(_sqlExpressionFactory.Function( "substr", new[] { instance, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1)), arguments[1] }, true, null, method.ReturnType, instance.TypeMapping)); } if (_isNullOrWhiteSpaceMethodInfo.Equals(method)) { var argument = arguments[0]; return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.IsNull(argument), _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( "trim", new[] { argument }, true, null, argument.Type, argument.TypeMapping), _sqlExpressionFactory.Constant(string.Empty)))); } if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true || _trimStartMethodInfoWithCharArg?.Equals(method) == true || _trimStartMethodInfoWithCharArrayArg.Equals(method)) { return(ProcessTrimMethod(instance, arguments, "ltrim")); } if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true || _trimEndMethodInfoWithCharArg?.Equals(method) == true || _trimEndMethodInfoWithCharArrayArg.Equals(method)) { return(ProcessTrimMethod(instance, arguments, "rtrim")); } if (_trimMethodInfoWithoutArgs?.Equals(method) == true || _trimMethodInfoWithCharArg?.Equals(method) == true || _trimMethodInfoWithCharArrayArg.Equals(method)) { return(ProcessTrimMethod(instance, arguments, "trim")); } if (_containsMethodInfo.Equals(method)) { var pattern = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping); return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.Equal( pattern, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "instr", new[] { instance, pattern }, true, null, typeof(int)), _sqlExpressionFactory.Constant(0)))); } if (_startsWithMethodInfo.Equals(method)) { return(TranslateStartsEndsWith(instance, arguments[0], true)); } if (_endsWithMethodInfo.Equals(method)) { return(TranslateStartsEndsWith(instance, arguments[0], false)); } return(null); }
public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments) { if (method == IndexOfString || method == IndexOfChar) { var argument = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument); return(_sqlExpressionFactory.Subtract( _sqlExpressionFactory.Function( "STRPOS", new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping) }, method.ReturnType), _sqlExpressionFactory.Constant(1))); } if (method == Replace) { var oldValue = arguments[0]; var newValue = arguments[1]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, oldValue, newValue); return(_sqlExpressionFactory.Function( "REPLACE", new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(oldValue, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(newValue, stringTypeMapping) }, method.ReturnType, stringTypeMapping)); } if (method == ToLower || method == ToUpper) { return(_sqlExpressionFactory.Function( method == ToLower ? "LOWER" : "UPPER", new[] { instance }, method.ReturnType, instance.TypeMapping)); } if (method == Substring || method == SubstringWithLength) { var args = method == Substring ? new[] { instance, GenerateOneBasedIndexExpression(arguments[0]) } : new[] { instance, GenerateOneBasedIndexExpression(arguments[0]), arguments[1] }; return(_sqlExpressionFactory.Function( "SUBSTRING", args, method.ReturnType, instance.TypeMapping)); } if (method == IsNullOrWhiteSpace) { var argument = arguments[0]; return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.IsNull(argument), _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( "BTRIM", new[] { argument, _whitespace }, argument.Type, argument.TypeMapping), _sqlExpressionFactory.Constant(string.Empty, argument.TypeMapping)))); } var isTrimStart = method == TrimStartWithNoParam || method == TrimStartWithChars || method == TrimStartWithSingleChar; var isTrimEnd = method == TrimEndWithNoParam || method == TrimEndWithChars || method == TrimEndWithSingleChar; var isTrimBoth = method == TrimBothWithNoParam || method == TrimBothWithChars || method == TrimBothWithSingleChar; if (isTrimStart || isTrimEnd || isTrimBoth) { char[] trimChars = null; if (method == TrimStartWithChars || method == TrimStartWithSingleChar || method == TrimEndWithChars || method == TrimEndWithSingleChar || method == TrimBothWithChars || method == TrimBothWithSingleChar) { var constantTrimChars = arguments[0] as SqlConstantExpression; if (constantTrimChars == null) { return(null); // Don't translate if trim chars isn't a constant } trimChars = constantTrimChars.Value is char c ? new[] { c } : (char[])constantTrimChars.Value; } return(_sqlExpressionFactory.Function( isTrimStart ? "LTRIM" : isTrimEnd ? "RTRIM" : "BTRIM", new[] { instance, trimChars == null || trimChars.Length == 0 ? _whitespace : _sqlExpressionFactory.Constant(new string(trimChars)) }, instance.Type, instance.TypeMapping)); } if (method == Contains) { var pattern = arguments[0]; var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping); var strposCheck = _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "STRPOS", new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping) }, typeof(int)), _sqlExpressionFactory.Constant(0)); if (pattern is SqlConstantExpression constantPattern) { return((string)constantPattern.Value == string.Empty ? (SqlExpression)_sqlExpressionFactory.Constant(true) : strposCheck); } return(_sqlExpressionFactory.OrElse( _sqlExpressionFactory.Equal( pattern, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), strposCheck)); } if (method == PadLeft || method == PadLeftWithChar || method == PadRight || method == PadRightWithChar) { var args = method == PadLeft || method == PadRight ? new[] { instance, arguments[0] } : new[] { instance, arguments[0], arguments[1] }; return(_sqlExpressionFactory.Function( method == PadLeft || method == PadLeftWithChar ? "lpad" : "rpad", args, instance.Type, instance.TypeMapping)); } if (method == StartsWith) { return(TranslateStartsEndsWith(instance, arguments[0], true)); } if (method == EndsWith) { return(TranslateStartsEndsWith(instance, arguments[0], false)); } return(null); }
private static SqlExpression GetAndoyerDistance( SqlExpression left, SqlExpression right, Type resultType, ISqlExpressionFactory sqlExpressionFactory) { SqlExpression toDegrees(SqlExpression coord) => sqlExpressionFactory.Divide( sqlExpressionFactory.Multiply( coord, sqlExpressionFactory.Function( "PI", Array.Empty <SqlExpression>(), resultType)), sqlExpressionFactory.Constant(180.0)); SqlExpression xCoord(SqlExpression point) => sqlExpressionFactory.Function( "ST_X", new[] { point }, resultType); SqlExpression yCoord(SqlExpression point) => sqlExpressionFactory.Function( "ST_Y", new[] { point }, resultType); var c0 = sqlExpressionFactory.Constant(0.0); var c1 = sqlExpressionFactory.Constant(1.0); var c2 = sqlExpressionFactory.Constant(2.0); var c3 = sqlExpressionFactory.Constant(3.0); var c2Int = sqlExpressionFactory.Constant(2); var lon1 = toDegrees(xCoord(left)); var lat1 = toDegrees(yCoord(left)); var lon2 = toDegrees(xCoord(right)); var lat2 = toDegrees(yCoord(right)); var g = sqlExpressionFactory.Divide( sqlExpressionFactory.Subtract( lat1, lat2), c2); var lambda = sqlExpressionFactory.Divide( sqlExpressionFactory.Subtract( lon1, lon2), c2); var f = sqlExpressionFactory.Divide( sqlExpressionFactory.Add( lat1, lat2), c2); var sinG2 = sqlExpressionFactory.Function( "POWER", new SqlExpression[] { sqlExpressionFactory.Function( "SIN", new[] { g }, resultType), c2Int }, resultType); var cosG2 = sqlExpressionFactory.Function( "POWER", new SqlExpression[] { sqlExpressionFactory.Function( "COS", new[] { g }, resultType), c2Int }, resultType); var sinF2 = sqlExpressionFactory.Function( "POWER", new SqlExpression[] { sqlExpressionFactory.Function( "SIN", new[] { f }, resultType), c2Int }, resultType); var cosF2 = sqlExpressionFactory.Function( "POWER", new SqlExpression[] { sqlExpressionFactory.Function( "COS", new[] { f }, resultType), c2Int }, resultType); var sinL2 = sqlExpressionFactory.Function( "POWER", new SqlExpression[] { sqlExpressionFactory.Function( "SIN", new[] { lambda }, resultType), c2Int }, resultType); var cosL2 = sqlExpressionFactory.Function( "POWER", new SqlExpression[] { sqlExpressionFactory.Function( "COS", new[] { lambda }, resultType), c2Int }, resultType); var s = sqlExpressionFactory.Add( sqlExpressionFactory.Multiply(sinG2, cosL2), sqlExpressionFactory.Multiply(cosF2, sinL2)); var c = sqlExpressionFactory.Add( sqlExpressionFactory.Multiply(cosG2, cosL2), sqlExpressionFactory.Multiply(sinF2, sinL2)); var radiusA = sqlExpressionFactory.Constant(6378137.0); var radiusB = sqlExpressionFactory.Constant(6356752.3142451793); var flattening = sqlExpressionFactory.Divide( sqlExpressionFactory.Subtract(radiusA, radiusB), radiusA); var omega = sqlExpressionFactory.Function( "ATAN", new[] { sqlExpressionFactory.Function( "SQRT", new[] { sqlExpressionFactory.Divide(s, c) }, resultType) }, resultType); var r3 = sqlExpressionFactory.Divide( sqlExpressionFactory.Multiply( c3, sqlExpressionFactory.Function( "SQRT", new[] { sqlExpressionFactory.Multiply(s, c) }, resultType)), omega); var d = sqlExpressionFactory.Multiply( sqlExpressionFactory.Multiply(c2, omega), radiusA); var h1 = sqlExpressionFactory.Divide( sqlExpressionFactory.Subtract(r3, c1), sqlExpressionFactory.Multiply(c2, c)); var h2 = sqlExpressionFactory.Divide( sqlExpressionFactory.Add(r3, c1), sqlExpressionFactory.Multiply(c2, s)); var andoyer = sqlExpressionFactory.Multiply( d, sqlExpressionFactory.Add( c1, sqlExpressionFactory.Multiply( flattening, sqlExpressionFactory.Subtract( sqlExpressionFactory.Multiply( sqlExpressionFactory.Multiply( h1, sinF2), cosG2), sqlExpressionFactory.Multiply( sqlExpressionFactory.Multiply( h2, cosF2), sinG2))))); return(sqlExpressionFactory.Case( new[] { new CaseWhenClause( sqlExpressionFactory.OrElse( sqlExpressionFactory.OrElse( sqlExpressionFactory.AndAlso( sqlExpressionFactory.Equal(lambda, c0), sqlExpressionFactory.Equal(g, c0)), sqlExpressionFactory.Equal(s, c0)), sqlExpressionFactory.Equal(c, c0)), c0), }, andoyer)); }
private static SqlExpression GetHaversineDistance( SqlExpression left, SqlExpression right, Type resultType, ISqlExpressionFactory sqlExpressionFactory) { // HAVERSINE = 6371000 * 2 * ASIN( // SQRT( // POWER(SIN((ST_Y(pt2) - ST_Y(pt1)) * pi()/180 / 2), 2) + // COS(ST_Y(pt1) * pi()/180) * // COS(ST_Y(pt2) * pi()/180) * // POWER(SIN((ST_X(pt2) - ST_X(pt1)) * pi()/180 / 2), 2) // ) // ) return(sqlExpressionFactory.Multiply( sqlExpressionFactory.Constant(6370986.0), // see https://postgis.net/docs/manual-1.4/ST_Distance_Sphere.html sqlExpressionFactory.Multiply( sqlExpressionFactory.Constant(2.0), sqlExpressionFactory.Function( "ASIN", new[] { sqlExpressionFactory.Function( "SQRT", new[] { sqlExpressionFactory.Add( sqlExpressionFactory.Function( "POWER", new SqlExpression[] { sqlExpressionFactory.Function( "SIN", new[] { sqlExpressionFactory.Divide( sqlExpressionFactory.Divide( sqlExpressionFactory.Multiply( sqlExpressionFactory.Subtract( sqlExpressionFactory.Function( "ST_Y", new[] { right }, resultType), sqlExpressionFactory.Function( "ST_Y", new[] { left }, resultType)), sqlExpressionFactory.Function( "PI", Array.Empty <SqlExpression>(), resultType)), sqlExpressionFactory.Constant(180.0)), sqlExpressionFactory.Constant(2.0)) }, resultType), sqlExpressionFactory.Constant(2), }, resultType), sqlExpressionFactory.Multiply( sqlExpressionFactory.Function( "COS", new[] { sqlExpressionFactory.Divide( sqlExpressionFactory.Multiply( sqlExpressionFactory.Function( "ST_Y", new[] { left }, resultType), sqlExpressionFactory.Function( "PI", Array.Empty <SqlExpression>(), resultType)), sqlExpressionFactory.Constant(180.0)), }, resultType), sqlExpressionFactory.Multiply( sqlExpressionFactory.Function( "COS", new[] { sqlExpressionFactory.Divide( sqlExpressionFactory.Multiply( sqlExpressionFactory.Function( "ST_Y", new[] { right }, resultType), sqlExpressionFactory.Function( "PI", Array.Empty <SqlExpression>(), resultType)), sqlExpressionFactory.Constant(180.0)), }, resultType), sqlExpressionFactory.Function( "POWER", new SqlExpression[] { sqlExpressionFactory.Function( "SIN", new[] { sqlExpressionFactory.Divide( sqlExpressionFactory.Divide( sqlExpressionFactory.Multiply( sqlExpressionFactory.Subtract( sqlExpressionFactory.Function( "ST_X", new[] { right }, resultType), sqlExpressionFactory.Function( "ST_X", new[] { left }, resultType)), sqlExpressionFactory.Function( "PI", Array.Empty <SqlExpression>(), resultType)), sqlExpressionFactory.Constant(180.0)), sqlExpressionFactory.Constant(2.0)) }, resultType), sqlExpressionFactory.Constant(2), }, resultType)))) }, resultType) }, resultType)))); }