protected override Expression VisitExtension(Expression extensionExpression) { Check.NotNull(extensionExpression, nameof(extensionExpression)); if (extensionExpression is ShapedQueryExpression shapedQueryExpression) { return(shapedQueryExpression.Update(Visit(shapedQueryExpression.QueryExpression), shapedQueryExpression.ShaperExpression)); } // Only applies to 'CASE WHEN condition...' not 'CASE operand WHEN...' if (extensionExpression is CaseExpression caseExpression && caseExpression.Operand == null && caseExpression.ElseResult is CaseExpression nestedCaseExpression && nestedCaseExpression.Operand == null) { return(VisitExtension( _sqlExpressionFactory.Case( caseExpression.WhenClauses.Union(nestedCaseExpression.WhenClauses).ToList(), nestedCaseExpression.ElseResult))); } if (extensionExpression is SqlBinaryExpression sqlBinaryExpression) { return(SimplifySqlBinary(sqlBinaryExpression)); } return(base.VisitExtension(extensionExpression)); }
/// <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) { Check.NotNull(member, nameof(member)); Check.NotNull(returnType, nameof(returnType)); Check.NotNull(logger, nameof(logger)); if (_memberToFunctionName.TryGetValue(member, out var functionName)) { return(returnType == typeof(bool) ? _sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), _sqlExpressionFactory.Function( functionName, new[] { instance }, nullable: false, argumentsPropagateNullability: new[] { false }, returnType)) }, null) : (SqlExpression)_sqlExpressionFactory.Function( functionName, new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, returnType)); } return(null); }
public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { Check.NotNull(member, nameof(member)); Check.NotNull(returnType, nameof(returnType)); if (_memberToFunctionName.TryGetValue(member, out var functionName)) { SqlExpression translation = _sqlExpressionFactory.Function( functionName, new[] { instance }, returnType); if (returnType == typeof(bool)) { translation = _sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), translation) }, null); } return(translation); } return(null); }
// If the distance should be calculated, use `ST_Distance_Sphere()` for SRID 4326 and // `ST_Distance()` for all other cases. private SqlExpression GetDistanceCallBySrid( SqlExpression left, SqlExpression right, Type resultType, RelationalTypeMapping resultTypeMapping) { return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( "ST_SRID", new[] { left }, typeof(int), _typeMappingSource.FindMapping(typeof(int))), _sqlExpressionFactory.Constant(4326)), MySqlSpatialDbFunctionsExtensionsMethodTranslator.GetStDistanceSphereFunctionCall( left, right, SpatialDistanceAlgorithm.Native, resultType, resultTypeMapping, _sqlExpressionFactory, _options)), }, MySqlSpatialDbFunctionsExtensionsMethodTranslator.GetStDistanceFunctionCall( left, right, resultType, resultTypeMapping, _sqlExpressionFactory))); }
/// <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) { Check.NotNull(member, nameof(member)); Check.NotNull(returnType, nameof(returnType)); Check.NotNull(logger, nameof(logger)); if (Equals(member, _isClosed) && instance != null) { return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), _sqlExpressionFactory.Function( "IsClosed", new[] { instance }, nullable: false, argumentsPropagateNullability: new[] { false }, returnType)) }, null)); } 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) { if (Equals(member, _isClosed)) { SqlExpression sqlExpression = _sqlExpressionFactory.Function( "ST_IsClosed", new [] { instance }, returnType); // ST_IsRing and others returns TRUE for a NULL value in MariaDB, which is inconsistent with NTS' implementation. // We return the following instead: // CASE // WHEN instance IS NULL THEN NULL // ELSE expression // END if (returnType == typeof(bool)) { sqlExpression = _sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.IsNull(instance), _sqlExpressionFactory.Constant(null, RelationalTypeMapping.NullMapping)) }, sqlExpression); } return(sqlExpression); } return(null); }
public virtual SqlExpression Translate( SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments, IDiagnosticsLogger <DbLoggerCategory.Query> logger) { if (instance == null || method.Name != nameof(ToString) || arguments.Count != 0) { return(null); } if (instance.Type == typeof(bool)) { return(instance is ColumnExpression columnExpression && columnExpression.IsNullable ? _sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.Equal(instance, _sqlExpressionFactory.Constant(false)), _sqlExpressionFactory.Constant(false.ToString())), new CaseWhenClause( _sqlExpressionFactory.Equal(instance, _sqlExpressionFactory.Constant(true)), _sqlExpressionFactory.Constant(true.ToString())) }, _sqlExpressionFactory.Constant(null)) : _sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.Equal(instance, _sqlExpressionFactory.Constant(false)), _sqlExpressionFactory.Constant(false.ToString())) }, _sqlExpressionFactory.Constant(true.ToString()))); } // Translates parameterless Object.ToString() calls. return(_supportedTypes.Contains(instance.Type.UnwrapNullableType()) ? _sqlExpressionFactory.Convert(instance, typeof(string)) : 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> protected override Expression VisitExtension(Expression extensionExpression) { if (extensionExpression is ShapedQueryExpression shapedQueryExpression) { return(shapedQueryExpression.Update(Visit(shapedQueryExpression.QueryExpression), shapedQueryExpression.ShaperExpression)); } // Only applies to 'CASE WHEN condition...' not 'CASE operand WHEN...' if (extensionExpression is CaseExpression caseExpression && caseExpression.Operand == null && caseExpression.ElseResult is CaseExpression nestedCaseExpression && nestedCaseExpression.Operand == null) { return(VisitExtension( _sqlExpressionFactory.Case( caseExpression.WhenClauses.Union(nestedCaseExpression.WhenClauses).ToList(), nestedCaseExpression.ElseResult))); } if (extensionExpression is SqlBinaryExpression sqlBinaryExpression) { return(SimplifySqlBinary(sqlBinaryExpression)); } if (extensionExpression is SqlFunctionExpression sqlFunctionExpression && IsCoalesce(sqlFunctionExpression)) { var arguments = new List <SqlExpression>(); foreach (var argument in sqlFunctionExpression.Arguments !) { var newArgument = (SqlExpression)Visit(argument); if (IsCoalesce(newArgument)) { arguments.AddRange(((SqlFunctionExpression)newArgument).Arguments !); } else { arguments.Add(newArgument); } } var distinctArguments = arguments.Distinct().ToList(); return(distinctArguments.Count > 1 ? new SqlFunctionExpression( sqlFunctionExpression.Name, distinctArguments, sqlFunctionExpression.IsNullable, argumentsPropagateNullability: distinctArguments.Select(_ => false).ToArray(), sqlFunctionExpression.Type, sqlFunctionExpression.TypeMapping) : distinctArguments[0]); } return(base.VisitExtension(extensionExpression));
public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (_memberToFunctionName.TryGetValue(member, out var functionName)) { Debug.Assert(instance.TypeMapping != null, "Instance must have typeMapping assigned."); var storeType = instance.TypeMapping.StoreType; var resultTypeMapping = typeof(Geometry).IsAssignableFrom(returnType) ? _typeMappingSource.FindMapping(returnType, storeType) : _typeMappingSource.FindMapping(returnType); // Emulate ST_IsRing if not supported. var sqlExpression = functionName != "ST_IsRing" || _options.ServerVersion.SupportsSpatialIsRingFunction ? (SqlExpression)_sqlExpressionFactory.Function( functionName, new[] { instance }, returnType, resultTypeMapping) : _sqlExpressionFactory.AndAlso( _sqlExpressionFactory.Function( "ST_IsClosed", new[] { instance }, returnType, resultTypeMapping), _sqlExpressionFactory.Function( "ST_IsSimple", new[] { instance }, returnType, resultTypeMapping) ); // ST_IsRing and others returns TRUE for a NULL value in MariaDB, which is inconsistent with NTS' implementation. // We return the following instead: // CASE // WHEN instance IS NULL THEN NULL // ELSE expression // END if (returnType == typeof(bool)) { sqlExpression = _sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.IsNull(instance), _sqlExpressionFactory.Constant(null, RelationalTypeMapping.NullMapping)) }, sqlExpression); } return(sqlExpression); } return(null); }
private SqlExpression ConvertToValue(SqlExpression sqlExpression, bool condition) => condition ? _sqlExpressionFactory.Case( new[] { new CaseWhenClause( SimplifyNegatedBinary(sqlExpression), _sqlExpressionFactory.ApplyDefaultTypeMapping(_sqlExpressionFactory.Constant(true))) }, _sqlExpressionFactory.Constant(false)) : sqlExpression;
private Expression ConvertToValue(SqlExpression sqlExpression, bool condition) { return(condition ? _sqlExpressionFactory.Case(new[] { new CaseWhenClause( sqlExpression, _sqlExpressionFactory.ApplyDefaultTypeMapping(_sqlExpressionFactory.Constant(true))) }, _sqlExpressionFactory.Constant(false)) : sqlExpression); }
protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { Check.NotNull(conditionalExpression, nameof(conditionalExpression)); var test = Visit(conditionalExpression.Test); var ifTrue = Visit(conditionalExpression.IfTrue); var ifFalse = Visit(conditionalExpression.IfFalse); return(TranslationFailed(conditionalExpression.Test, test, out var sqlTest) || TranslationFailed(conditionalExpression.IfTrue, ifTrue, out var sqlIfTrue) || TranslationFailed(conditionalExpression.IfFalse, ifFalse, out var sqlIfFalse) ? null : _sqlExpressionFactory.Case(new[] { new CaseWhenClause(sqlTest, sqlIfTrue) }, sqlIfFalse)); }
protected override Expression VisitExtension(Expression node) { // Only applies to 'CASE WHEN condition...' not 'CASE operand WHEN...' if (node is CaseExpression caseExpression && caseExpression.Operand == null) { if (caseExpression.ElseResult is CaseExpression nestedCaseExpression && nestedCaseExpression.Operand == null) { return(VisitExtension(_sqlExpressionFactory.Case( caseExpression.WhenClauses.Union(nestedCaseExpression.WhenClauses).ToList(), nestedCaseExpression.ElseResult))); } } return(base.VisitExtension(node)); }
/// <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, 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 (method.ReturnType == typeof(int)) { SqlExpression?left = null; SqlExpression?right = null; if (method.Name == nameof(string.Compare) && arguments.Count == 2 && arguments[0].Type == arguments[1].Type) { left = arguments[0]; right = arguments[1]; } else if (method.Name == nameof(string.CompareTo) && arguments.Count == 1 && instance != null && instance.Type == arguments[0].Type) { left = instance; right = arguments[0]; } if (left != null && right != null) { return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.Equal(left, right), _sqlExpressionFactory.Constant(0)), new CaseWhenClause( _sqlExpressionFactory.GreaterThan(left, right), _sqlExpressionFactory.Constant(1)), new CaseWhenClause( _sqlExpressionFactory.LessThan(left, right), _sqlExpressionFactory.Constant(-1)) }, null)); } } return(null); }
public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList <SqlExpression> arguments) { method = method.OnInterface(typeof(IGeometry)); if (_methodToFunctionName.TryGetValue(method, out var functionName)) { SqlExpression translation = _sqlExpressionFactory.Function( functionName, new[] { instance }.Concat(arguments), method.ReturnType); if (method.ReturnType == typeof(bool)) { translation = _sqlExpressionFactory.Case( new[] { new CaseWhenClause(_sqlExpressionFactory.IsNotNull(instance), translation) }, null); } return(translation); } if (Equals(method, _getGeometryN)) { return(_sqlExpressionFactory.Function( "GeometryN", new[] { instance, _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)) }, method.ReturnType)); } if (Equals(method, _isWithinDistance)) { return(_sqlExpressionFactory.LessThanOrEqual( _sqlExpressionFactory.Function( "Distance", new[] { instance, arguments[0] }, typeof(double)), arguments[1])); } return(null); }
public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (Equals(member, _isClosed)) { return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), _sqlExpressionFactory.Function( "IsClosed", new[] { instance }, returnType)) }, null)); } return(null); }
protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { var test = (SqlExpression)Visit(conditionalExpression.Test); var ifTrue = (SqlExpression)Visit(conditionalExpression.IfTrue); var ifFalse = (SqlExpression)Visit(conditionalExpression.IfFalse); if (TranslationFailed(conditionalExpression.Test, test) || TranslationFailed(conditionalExpression.IfTrue, ifTrue) || TranslationFailed(conditionalExpression.IfFalse, ifFalse)) { return(null); } return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause(test, ifTrue) }, ifFalse)); }
public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments) { if (method.ReturnType == typeof(int)) { SqlExpression left = null; SqlExpression right = null; if (method.Name == nameof(string.Compare) && arguments.Count == 2 && arguments[0].Type.UnwrapNullableType() == arguments[1].Type.UnwrapNullableType()) { left = arguments[0]; right = arguments[1]; } else if (method.Name == nameof(string.CompareTo) && arguments.Count == 1 && instance != null && instance.Type.UnwrapNullableType() == arguments[0].Type.UnwrapNullableType()) { left = instance; right = arguments[0]; } if (left != null && right != null) { return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.Equal(left, right), _sqlExpressionFactory.Constant(0)), new CaseWhenClause( _sqlExpressionFactory.GreaterThan(left, right), _sqlExpressionFactory.Constant(1)), new CaseWhenClause( _sqlExpressionFactory.LessThan(left, right), _sqlExpressionFactory.Constant(-1)) }, null)); } } 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) { Check.NotNull(member, nameof(member)); Check.NotNull(returnType, nameof(returnType)); if (Equals(member, _isClosed)) { return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), _sqlExpressionFactory.Function( "IsClosed", new[] { instance }, nullable: false, argumentsPropagateNullability: new[] { false }, returnType)) }, null)); } return(null); }
public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (_memberToFunctionName.TryGetValue(member.OnInterface(typeof(ICurve)), out var functionName)) { SqlExpression translation = _sqlExpressionFactory.Function( functionName, new[] { instance }, returnType); if (returnType == typeof(bool)) { translation = _sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), translation) }, null); } return(translation); } 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) { Check.NotNull(member, nameof(member)); Check.NotNull(returnType, nameof(returnType)); if (_memberToFunctionName.TryGetValue(member, out var functionName)) { return(returnType == typeof(bool) ? _sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), _sqlExpressionFactory.Function( functionName, new[] { instance }, nullable: false, argumentsPropagateNullability: new[] { false }, returnType)) }, null) : (SqlExpression)_sqlExpressionFactory.Function( functionName, new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, returnType)); } if (Equals(member, _geometryType)) { return(_sqlExpressionFactory.Case( _sqlExpressionFactory.Function( "rtrim", new SqlExpression[] { _sqlExpressionFactory.Function( "GeometryType", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, returnType), _sqlExpressionFactory.Constant(" ZM") }, nullable: true, argumentsPropagateNullability: new[] { true }, returnType), new[] { new CaseWhenClause(_sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant("Point")), new CaseWhenClause(_sqlExpressionFactory.Constant("LINESTRING"), _sqlExpressionFactory.Constant("LineString")), new CaseWhenClause(_sqlExpressionFactory.Constant("POLYGON"), _sqlExpressionFactory.Constant("Polygon")), new CaseWhenClause(_sqlExpressionFactory.Constant("MULTIPOINT"), _sqlExpressionFactory.Constant("MultiPoint")), new CaseWhenClause( _sqlExpressionFactory.Constant("MULTILINESTRING"), _sqlExpressionFactory.Constant("MultiLineString")), new CaseWhenClause(_sqlExpressionFactory.Constant("MULTIPOLYGON"), _sqlExpressionFactory.Constant("MultiPolygon")), new CaseWhenClause( _sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), _sqlExpressionFactory.Constant("GeometryCollection")) }, null)); } if (Equals(member, _ogcGeometryType)) { return(_sqlExpressionFactory.Case( _sqlExpressionFactory.Function( "rtrim", new SqlExpression[] { _sqlExpressionFactory.Function( "GeometryType", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, typeof(string)), _sqlExpressionFactory.Constant(" ZM") }, nullable: true, argumentsPropagateNullability: new[] { true }, typeof(string)), new[] { new CaseWhenClause(_sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant(OgcGeometryType.Point)), new CaseWhenClause( _sqlExpressionFactory.Constant("LINESTRING"), _sqlExpressionFactory.Constant(OgcGeometryType.LineString)), new CaseWhenClause(_sqlExpressionFactory.Constant("POLYGON"), _sqlExpressionFactory.Constant(OgcGeometryType.Polygon)), new CaseWhenClause( _sqlExpressionFactory.Constant("MULTIPOINT"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiPoint)), new CaseWhenClause( _sqlExpressionFactory.Constant("MULTILINESTRING"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiLineString)), new CaseWhenClause( _sqlExpressionFactory.Constant("MULTIPOLYGON"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiPolygon)), new CaseWhenClause( _sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), _sqlExpressionFactory.Constant(OgcGeometryType.GeometryCollection)) }, null)); } 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, MethodInfo method, IReadOnlyList <SqlExpression> arguments, IDiagnosticsLogger <DbLoggerCategory.Query> logger) { if (instance != null) { if (MethodToFunctionName.TryGetValue(method, out var functionName)) { var finalArguments = new[] { instance }.Concat(arguments); if (method.ReturnType == typeof(bool)) { var nullCheck = (SqlExpression)_sqlExpressionFactory.IsNotNull(instance); foreach (var argument in arguments) { nullCheck = _sqlExpressionFactory.AndAlso( nullCheck, _sqlExpressionFactory.IsNotNull(argument)); } return(_sqlExpressionFactory.Case( new[] { new CaseWhenClause( nullCheck, _sqlExpressionFactory.Function( functionName, finalArguments, nullable: false, finalArguments.Select(a => false), method.ReturnType)) }, null)); } return(_sqlExpressionFactory.Function( functionName, finalArguments, nullable: true, finalArguments.Select(a => true), method.ReturnType)); } if (Equals(method, GetGeometryN)) { return(_sqlExpressionFactory.Function( "GeometryN", new[] { instance, _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)) }, nullable: true, argumentsPropagateNullability: new[] { true, true }, method.ReturnType)); } if (Equals(method, IsWithinDistance)) { return(_sqlExpressionFactory.LessThanOrEqual( _sqlExpressionFactory.Function( "Distance", new[] { instance, arguments[0] }, nullable: true, argumentsPropagateNullability: new[] { true, true }, typeof(double)), arguments[1])); } } 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, MemberInfo member, Type returnType) { Check.NotNull(member, nameof(member)); Check.NotNull(returnType, nameof(returnType)); if (typeof(Geometry).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 (_memberToFunctionName.TryGetValue(member, out var functionName) || (!isGeography && _geometryMemberToFunctionName.TryGetValue(member, out functionName))) { var resultTypeMapping = typeof(Geometry).IsAssignableFrom(returnType) ? _typeMappingSource.FindMapping(returnType, storeType) : _typeMappingSource.FindMapping(returnType); return(_sqlExpressionFactory.Function( instance, functionName, Array.Empty <SqlExpression>(), nullResultAllowed: true, instancePropagatesNullability: true, argumentsPropagateNullability: Array.Empty <bool>(), returnType, resultTypeMapping)); } if (Equals(member, _ogcGeometryType)) { var whenClauses = new List <CaseWhenClause> { new CaseWhenClause( _sqlExpressionFactory.Constant("Point"), _sqlExpressionFactory.Constant(OgcGeometryType.Point)), new CaseWhenClause( _sqlExpressionFactory.Constant("LineString"), _sqlExpressionFactory.Constant(OgcGeometryType.LineString)), new CaseWhenClause( _sqlExpressionFactory.Constant("Polygon"), _sqlExpressionFactory.Constant(OgcGeometryType.Polygon)), new CaseWhenClause( _sqlExpressionFactory.Constant("MultiPoint"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiPoint)), new CaseWhenClause( _sqlExpressionFactory.Constant("MultiLineString"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiLineString)), new CaseWhenClause( _sqlExpressionFactory.Constant("MultiPolygon"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiPolygon)), new CaseWhenClause( _sqlExpressionFactory.Constant("GeometryCollection"), _sqlExpressionFactory.Constant(OgcGeometryType.GeometryCollection)), new CaseWhenClause( _sqlExpressionFactory.Constant("CircularString"), _sqlExpressionFactory.Constant(OgcGeometryType.CircularString)), new CaseWhenClause( _sqlExpressionFactory.Constant("CompoundCurve"), _sqlExpressionFactory.Constant(OgcGeometryType.CompoundCurve)), new CaseWhenClause( _sqlExpressionFactory.Constant("CurvePolygon"), _sqlExpressionFactory.Constant(OgcGeometryType.CurvePolygon)) }; if (isGeography) { whenClauses.Add( new CaseWhenClause( _sqlExpressionFactory.Constant("FullGlobe"), _sqlExpressionFactory.Constant((OgcGeometryType)126))); } return(_sqlExpressionFactory.Case( _sqlExpressionFactory.Function( instance, "STGeometryType", Array.Empty <SqlExpression>(), nullResultAllowed: true, instancePropagatesNullability: true, argumentsPropagateNullability: Array.Empty <bool>(), typeof(string)), whenClauses.ToArray())); } if (Equals(member, _srid)) { return(_sqlExpressionFactory.Function( instance, "STSrid", nullResultAllowed: true, instancePropagatesNullability: true, 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, MemberInfo member, Type returnType, IDiagnosticsLogger <DbLoggerCategory.Query> logger) { var declaringType = member.DeclaringType; if (instance is null || !typeof(Geometry).IsAssignableFrom(declaringType)) { return(null); } var typeMapping = instance.TypeMapping; Debug.Assert(typeMapping is not null, "Instance must have typeMapping assigned."); var storeType = instance.TypeMapping !.StoreType; if (typeof(Point).IsAssignableFrom(declaringType)) { var function = member.Name switch { nameof(Point.X) => "ST_X", nameof(Point.Y) => "ST_Y", nameof(Point.Z) => "ST_Z", nameof(Point.M) => "ST_M", _ => null }; if (function is not null) { return(Function(function, new[] { instance }, typeof(double))); } } if (typeof(LineString).IsAssignableFrom(declaringType)) { if (member.Name == "Count") { return(Function("ST_NumPoints", new[] { instance }, typeof(int))); } } return(member.Name switch { nameof(Geometry.Area) => Function("ST_Area", new[] { instance }, typeof(double)), nameof(Geometry.Boundary) => Function("ST_Boundary", new[] { instance }, typeof(Geometry), ResultGeometryMapping()), nameof(Geometry.Centroid) => Function("ST_Centroid", new[] { instance }, typeof(Point), ResultGeometryMapping()), nameof(GeometryCollection.Count) => Function("ST_NumGeometries", new[] { instance }, typeof(int)), nameof(Geometry.Dimension) => Function("ST_Dimension", new[] { instance }, typeof(Dimension)), nameof(LineString.EndPoint) => Function("ST_EndPoint", new[] { instance }, typeof(Point), ResultGeometryMapping()), nameof(Geometry.Envelope) => Function("ST_Envelope", new[] { instance }, typeof(Geometry), ResultGeometryMapping()), nameof(Polygon.ExteriorRing) => Function("ST_ExteriorRing", new[] { instance }, typeof(LineString), ResultGeometryMapping()), nameof(Geometry.GeometryType) => Function("GeometryType", new[] { instance }, typeof(string)), nameof(LineString.IsClosed) => Function("ST_IsClosed", new[] { instance }, typeof(bool)), nameof(Geometry.IsEmpty) => Function("ST_IsEmpty", new[] { instance }, typeof(bool)), nameof(LineString.IsRing) => Function("ST_IsRing", new[] { instance }, typeof(bool)), nameof(Geometry.IsSimple) => Function("ST_IsSimple", new[] { instance }, typeof(bool)), nameof(Geometry.IsValid) => Function("ST_IsValid", new[] { instance }, typeof(bool)), nameof(Geometry.Length) => Function("ST_Length", new[] { instance }, typeof(double)), nameof(Geometry.NumGeometries) => Function("ST_NumGeometries", new[] { instance }, typeof(int)), nameof(Polygon.NumInteriorRings) => Function("ST_NumInteriorRings", new[] { instance }, typeof(int)), nameof(Geometry.NumPoints) => Function("ST_NumPoints", new[] { instance }, typeof(int)), nameof(Geometry.PointOnSurface) => Function("ST_PointOnSurface", new[] { instance }, typeof(Geometry), ResultGeometryMapping()), nameof(Geometry.InteriorPoint) => Function("ST_PointOnSurface", new[] { instance }, typeof(Geometry), ResultGeometryMapping()), nameof(Geometry.SRID) => Function("ST_SRID", new[] { instance }, typeof(int)), nameof(LineString.StartPoint) => Function("ST_StartPoint", new[] { instance }, typeof(Point), ResultGeometryMapping()), nameof(Geometry.OgcGeometryType) => _sqlExpressionFactory.Case( Function("ST_GeometryType", new[] { instance }, typeof(string)), _ogcGeometryTypeWhenThenList, elseResult: null), _ => null });
public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { member = member.OnInterface(typeof(IGeometry)); if (_memberToFunctionName.TryGetValue(member, out var functionName)) { SqlExpression translation = _sqlExpressionFactory.Function(functionName, new[] { instance }, returnType); if (returnType == typeof(bool)) { translation = _sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), translation) }, null); } return(translation); } if (Equals(member, _geometryType)) { return(_sqlExpressionFactory.Case( _sqlExpressionFactory.Function( "rtrim", new SqlExpression[] { _sqlExpressionFactory.Function( "GeometryType", new [] { instance, }, returnType), _sqlExpressionFactory.Constant(" ZM") }, returnType), new CaseWhenClause(_sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant("Point")), new CaseWhenClause(_sqlExpressionFactory.Constant("LINESTRING"), _sqlExpressionFactory.Constant("LineString")), new CaseWhenClause(_sqlExpressionFactory.Constant("POLYGON"), _sqlExpressionFactory.Constant("Polygon")), new CaseWhenClause(_sqlExpressionFactory.Constant("MULTIPOINT"), _sqlExpressionFactory.Constant("MultiPoint")), new CaseWhenClause(_sqlExpressionFactory.Constant("MULTILINESTRING"), _sqlExpressionFactory.Constant("MultiLineString")), new CaseWhenClause(_sqlExpressionFactory.Constant("MULTIPOLYGON"), _sqlExpressionFactory.Constant("MultiPolygon")), new CaseWhenClause(_sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), _sqlExpressionFactory.Constant("GeometryCollection")))); } if (Equals(member, _ogcGeometryType)) { return(_sqlExpressionFactory.Case( _sqlExpressionFactory.Function( "rtrim", new SqlExpression[] { _sqlExpressionFactory.Function( "GeometryType", new [] { instance, }, typeof(string)), _sqlExpressionFactory.Constant(" ZM") }, typeof(string)), new CaseWhenClause(_sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant(OgcGeometryType.Point)), new CaseWhenClause(_sqlExpressionFactory.Constant("LINESTRING"), _sqlExpressionFactory.Constant(OgcGeometryType.LineString)), new CaseWhenClause(_sqlExpressionFactory.Constant("POLYGON"), _sqlExpressionFactory.Constant(OgcGeometryType.Polygon)), new CaseWhenClause(_sqlExpressionFactory.Constant("MULTIPOINT"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiPoint)), new CaseWhenClause(_sqlExpressionFactory.Constant("MULTILINESTRING"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiLineString)), new CaseWhenClause(_sqlExpressionFactory.Constant("MULTIPOLYGON"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiPolygon)), new CaseWhenClause(_sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), _sqlExpressionFactory.Constant(OgcGeometryType.GeometryCollection)))); } 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 (instance != null) { if (MemberToFunctionName.TryGetValue(member, out var functionName)) { return(returnType == typeof(bool) ? _sqlExpressionFactory.Case( new[] { new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), _sqlExpressionFactory.Function( functionName, new[] { instance }, nullable: false, argumentsPropagateNullability: new[] { false }, returnType)) }, null) : _sqlExpressionFactory.Function( functionName, new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, returnType)); } if (Equals(member, GeometryType)) { return(_sqlExpressionFactory.Case( _sqlExpressionFactory.Function( "rtrim", new SqlExpression[] { _sqlExpressionFactory.Function( "GeometryType", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, returnType), _sqlExpressionFactory.Constant(" ZM") }, nullable: true, argumentsPropagateNullability: new[] { true }, returnType), new[] { new CaseWhenClause(_sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant("Point")), new CaseWhenClause(_sqlExpressionFactory.Constant("LINESTRING"), _sqlExpressionFactory.Constant("LineString")), new CaseWhenClause(_sqlExpressionFactory.Constant("POLYGON"), _sqlExpressionFactory.Constant("Polygon")), new CaseWhenClause(_sqlExpressionFactory.Constant("MULTIPOINT"), _sqlExpressionFactory.Constant("MultiPoint")), new CaseWhenClause( _sqlExpressionFactory.Constant("MULTILINESTRING"), _sqlExpressionFactory.Constant("MultiLineString")), new CaseWhenClause( _sqlExpressionFactory.Constant("MULTIPOLYGON"), _sqlExpressionFactory.Constant("MultiPolygon")), new CaseWhenClause( _sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), _sqlExpressionFactory.Constant("GeometryCollection")) }, null)); } if (Equals(member, OgcGeometryType)) { return(_sqlExpressionFactory.Case( _sqlExpressionFactory.Function( "rtrim", new SqlExpression[] { _sqlExpressionFactory.Function( "GeometryType", new[] { instance }, nullable: true, argumentsPropagateNullability: new[] { true }, typeof(string)), _sqlExpressionFactory.Constant(" ZM") }, nullable: true, argumentsPropagateNullability: new[] { true }, typeof(string)), new[] { new CaseWhenClause( _sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant(NetTopologySuite.Geometries.OgcGeometryType.Point)), new CaseWhenClause( _sqlExpressionFactory.Constant("LINESTRING"), _sqlExpressionFactory.Constant(NetTopologySuite.Geometries.OgcGeometryType.LineString)), new CaseWhenClause( _sqlExpressionFactory.Constant("POLYGON"), _sqlExpressionFactory.Constant(NetTopologySuite.Geometries.OgcGeometryType.Polygon)), new CaseWhenClause( _sqlExpressionFactory.Constant("MULTIPOINT"), _sqlExpressionFactory.Constant(NetTopologySuite.Geometries.OgcGeometryType.MultiPoint)), new CaseWhenClause( _sqlExpressionFactory.Constant("MULTILINESTRING"), _sqlExpressionFactory.Constant(NetTopologySuite.Geometries.OgcGeometryType.MultiLineString)), new CaseWhenClause( _sqlExpressionFactory.Constant("MULTIPOLYGON"), _sqlExpressionFactory.Constant(NetTopologySuite.Geometries.OgcGeometryType.MultiPolygon)), new CaseWhenClause( _sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), _sqlExpressionFactory.Constant(NetTopologySuite.Geometries.OgcGeometryType.GeometryCollection)) }, null)); } } return(null); }