private SqlExpression TryTranslateCompareExpression(BinaryExpression expression) { bool isGoodExpression = expression.Left.NodeType == ExpressionType.Call && expression.Right.NodeType == ExpressionType.Constant || expression.Right.NodeType == ExpressionType.Call && expression.Left.NodeType == ExpressionType.Constant; if (!isGoodExpression) { return(null); } MethodCallExpression callExpression; ConstantExpression constantExpression; bool swapped; if (expression.Left.NodeType == ExpressionType.Call) { callExpression = (MethodCallExpression)expression.Left; constantExpression = (ConstantExpression)expression.Right; swapped = false; } else { callExpression = (MethodCallExpression)expression.Right; constantExpression = (ConstantExpression)expression.Left; swapped = true; } var method = (MethodInfo)callExpression.Method.GetInterfaceMember() ?? callExpression.Method; var methodType = method.DeclaringType; // There no methods in IComparable except CompareTo so checking only DeclatingType. bool isCompareTo = methodType == typeof(IComparable) || methodType.IsGenericType && methodType.GetGenericTypeDefinition() == typeof(IComparable <>); bool isVbStringCompare = method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" && method.Name == "CompareString" && method.GetParameters().Length == 3 && method.IsStatic; bool isCompare = method.Name == "Compare" && method.GetParameters().Length == 2 && method.IsStatic; if (!isCompareTo && !isCompare && !isVbStringCompare) { return(null); } if (constantExpression.Value == null) { return(null); } if (!(constantExpression.Value is int)) { return(null); } var constant = (int)constantExpression.Value; SqlExpression leftComparand = null; SqlExpression rightComparand = null; if (isCompareTo) { leftComparand = Visit(callExpression.Object); rightComparand = Visit(callExpression.Arguments[0]); } if (isCompare || isVbStringCompare) { leftComparand = Visit(callExpression.Arguments[0]); rightComparand = Visit(callExpression.Arguments[1]); } if (swapped) { var tmp = leftComparand; leftComparand = rightComparand; rightComparand = tmp; } if (constant > 0) { switch (expression.NodeType) { case ExpressionType.Equal: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: return(SqlDml.GreaterThan(leftComparand, rightComparand)); case ExpressionType.NotEqual: case ExpressionType.LessThanOrEqual: case ExpressionType.LessThan: return(SqlDml.LessThanOrEquals(leftComparand, rightComparand)); default: return(null); } } if (constant < 0) { switch (expression.NodeType) { case ExpressionType.NotEqual: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: return(SqlDml.GreaterThanOrEquals(leftComparand, rightComparand)); case ExpressionType.Equal: case ExpressionType.LessThanOrEqual: case ExpressionType.LessThan: return(SqlDml.LessThan(leftComparand, rightComparand)); default: return(null); } } switch (expression.NodeType) { case ExpressionType.GreaterThan: return(SqlDml.GreaterThan(leftComparand, rightComparand)); case ExpressionType.GreaterThanOrEqual: return(SqlDml.GreaterThanOrEquals(leftComparand, rightComparand)); case ExpressionType.Equal: return(SqlDml.Equals(leftComparand, rightComparand)); case ExpressionType.NotEqual: return(SqlDml.NotEquals(leftComparand, rightComparand)); case ExpressionType.LessThanOrEqual: return(SqlDml.LessThanOrEquals(leftComparand, rightComparand)); case ExpressionType.LessThan: return(SqlDml.LessThan(leftComparand, rightComparand)); default: return(null); } }
public static SqlBinary operator >(SqlExpression left, SqlExpression right) { return(SqlDml.GreaterThan(left, right)); }
protected override SqlExpression VisitBinary(BinaryExpression expression) { // handle x.CompareTo(y) > 0 and similar comparisons SqlExpression result = TryTranslateCompareExpression(expression); if (!result.IsNullReference()) { return(result); } SqlExpression left; SqlExpression right; bool isEqualityCheck = expression.NodeType == ExpressionType.Equal || expression.NodeType == ExpressionType.NotEqual; bool isBooleanFixRequired = fixBooleanExpressions && (isEqualityCheck || expression.NodeType == ExpressionType.Coalesce) && (IsBooleanExpression(expression.Left) || IsBooleanExpression(expression.Right)); if (IsCharToIntConvert(expression.Left) && IsCharToIntConvert(expression.Right)) { // chars are compared as integers, but we store them as strings and should compare them like strings. left = Visit(GetOperand(expression.Left), isEqualityCheck); right = Visit(GetOperand(expression.Right), isEqualityCheck); } else if (IsCharToIntConvert(expression.Left) && IsIntConstant(expression.Right)) { // another case of char comparison left = Visit(GetOperand(expression.Left), isEqualityCheck); right = ConvertIntConstantToSingleCharString(expression.Right); } else if (IsIntConstant(expression.Left) && IsCharToIntConvert(expression.Right)) { // another case of char comparison left = ConvertIntConstantToSingleCharString(expression.Left); right = Visit(GetOperand(expression.Right), isEqualityCheck); } else { // regular case left = Visit(expression.Left, isEqualityCheck); right = Visit(expression.Right, isEqualityCheck); } if (isBooleanFixRequired) { // boolean expressions should be compared as integers. // additional check is required because some type information might be lost. // we assume they already have correct format in that case. if (IsBooleanExpression(expression.Left)) { left = booleanExpressionConverter.BooleanToInt(left); } if (IsBooleanExpression(expression.Right)) { right = booleanExpressionConverter.BooleanToInt(right); } } //handle SQLite DateTime comparsion if (dateTimeEmulation && left.NodeType != SqlNodeType.Null && right.NodeType != SqlNodeType.Null && IsComparisonExpression(expression) && (IsDateTimeExpression(expression.Left) || IsDateTimeExpression(expression.Right))) { left = SqlDml.Cast(left, SqlType.DateTime); right = SqlDml.Cast(right, SqlType.DateTime); } //handle SQLite DateTimeOffset comparsion if (dateTimeOffsetEmulation && left.NodeType != SqlNodeType.Null && right.NodeType != SqlNodeType.Null && IsComparisonExpression(expression) && (IsDateTimeOffsetExpression(expression.Left) || IsDateTimeOffsetExpression(expression.Right))) { left = SqlDml.Cast(left, SqlType.DateTimeOffset); right = SqlDml.Cast(right, SqlType.DateTimeOffset); } // handle special cases result = TryTranslateBinaryExpressionSpecialCases(expression, left, right); if (!result.IsNullReference()) { return(result); } // handle overloaded operators if (expression.Method != null) { return(CompileMember(expression.Method, null, left, right)); } //handle wrapped enums SqlContainer container = left as SqlContainer; if (container != null) { left = TryUnwrapEnum(container); } container = right as SqlContainer; if (container != null) { right = TryUnwrapEnum(container); } switch (expression.NodeType) { case ExpressionType.Add: case ExpressionType.AddChecked: return(SqlDml.Add(left, right)); case ExpressionType.And: return(IsBooleanExpression(expression.Left) ? SqlDml.And(left, right) : SqlDml.BitAnd(left, right)); case ExpressionType.AndAlso: return(SqlDml.And(left, right)); case ExpressionType.Coalesce: SqlExpression coalesce = SqlDml.Coalesce(left, right); if (isBooleanFixRequired) { coalesce = booleanExpressionConverter.IntToBoolean(coalesce); } return(coalesce); case ExpressionType.Divide: return(SqlDml.Divide(left, right)); case ExpressionType.Equal: return(SqlDml.Equals(left, right)); case ExpressionType.ExclusiveOr: return(SqlDml.BitXor(left, right)); case ExpressionType.GreaterThan: return(SqlDml.GreaterThan(left, right)); case ExpressionType.GreaterThanOrEqual: return(SqlDml.GreaterThanOrEquals(left, right)); case ExpressionType.LessThan: return(SqlDml.LessThan(left, right)); case ExpressionType.LessThanOrEqual: return(SqlDml.LessThanOrEquals(left, right)); case ExpressionType.Modulo: return(SqlDml.Modulo(left, right)); case ExpressionType.Multiply: case ExpressionType.MultiplyChecked: return(SqlDml.Multiply(left, right)); case ExpressionType.NotEqual: return(SqlDml.NotEquals(left, right)); case ExpressionType.Or: return(IsBooleanExpression(expression.Left) ? SqlDml.Or(left, right) : SqlDml.BitOr(left, right)); case ExpressionType.OrElse: return(SqlDml.Or(left, right)); case ExpressionType.Subtract: case ExpressionType.SubtractChecked: return(SqlDml.Subtract(left, right)); default: throw new ArgumentOutOfRangeException("expression"); } }
public static SqlExpression StringGreaterThan( [Type(typeof(string))] SqlExpression _this, [Type(typeof(string))] SqlExpression value) { return(SqlDml.GreaterThan(_this, value)); }