public static SqlExpression operator |(SqlExpression left, SqlExpression right) { if (left.IsNullReference()) { return(right); } if (right.IsNullReference()) { return(left); } if (SqlValidator.IsBooleanExpression(left)) { return(SqlDml.Or(left, right)); } return(SqlDml.BitOr(left, right)); }
public override void Visit(SqlBinary node) { switch (node.NodeType) { // Bit XOR is not supported by SQLite // but it can be easily emulated using remaining bit operators case SqlNodeType.BitXor: // A ^ B = (A | B) & ~(A & B) var replacement = SqlDml.BitAnd( SqlDml.BitOr(node.Left, node.Right), SqlDml.BitNot(SqlDml.BitAnd(node.Left, node.Right))); replacement.AcceptVisitor(this); return; case SqlNodeType.DateTimePlusInterval: DateTimeAddInterval(node.Left, node.Right).AcceptVisitor(this); return; case SqlNodeType.DateTimeMinusInterval: DateTimeAddInterval(node.Left, -node.Right).AcceptVisitor(this); return; case SqlNodeType.DateTimeMinusDateTime: case SqlNodeType.DateTimeOffsetMinusDateTimeOffset: DateTimeSubtractDateTime(node.Left, node.Right).AcceptVisitor(this); return; case SqlNodeType.DateTimeOffsetPlusInterval: SqlDml.Concat( DateTimeAddInterval(DateTimeOffsetExtractDateTimeAsString(node.Left), node.Right), DateTimeOffsetExtractOffsetAsString(node.Left)) .AcceptVisitor(this); return; case SqlNodeType.DateTimeOffsetMinusInterval: SqlDml.Concat( DateTimeAddInterval(DateTimeOffsetExtractDateTimeAsString(node.Left), -node.Right), DateTimeOffsetExtractOffsetAsString(node.Left)) .AcceptVisitor(this); return; default: base.Visit(node); return; } }
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"); } }