private static SqlExpression GenericStringIndexOf(SqlExpression _this, SqlExpression substring, SqlExpression startIndex, SqlExpression length) { return(SqlDml.Coalesce(startIndex + SqlDml.NullIf(SqlDml.Position(substring, SqlDml.Substring(_this, startIndex, length)), -1), -1)); }
public static SqlExpression NullableGetValueOrDefault(MemberInfo memberInfo, SqlExpression _this, SqlExpression _default) { var context = ExpressionTranslationContext.Current; var @this = _this; var @default = _default; SqlContainer container = @this as SqlContainer; if (container != null) { if (container.Value.GetType().IsEnum) { @this = SqlDml.Literal(Convert.ChangeType(container.Value, Enum.GetUnderlyingType(container.Value.GetType()))); } } container = @default as SqlContainer; if (container != null) { if (container.Value.GetType().IsEnum) { @default = SqlDml.Literal(Convert.ChangeType(container.Value, Enum.GetUnderlyingType(container.Value.GetType()))); } } if (!IsBooleanSpecialCase(context, memberInfo)) { return(SqlDml.Coalesce(@this, @default)); } return(context.BooleanExpressionConverter.IntToBoolean(SqlDml.Coalesce( context.BooleanExpressionConverter.BooleanToInt(@this), context.BooleanExpressionConverter.BooleanToInt(@default)))); }
public static SqlExpression NullableGetValueOrDefault(MemberInfo memberInfo, SqlExpression _this) { var context = ExpressionTranslationContext.Current; var defaultValue = SqlDml.Literal(Activator.CreateInstance(memberInfo.DeclaringType.StripNullable())); if (!IsBooleanSpecialCase(context, memberInfo)) { return(SqlDml.Coalesce(_this, defaultValue)); } return(context.BooleanExpressionConverter.IntToBoolean( SqlDml.Coalesce(context.BooleanExpressionConverter.BooleanToInt(_this), defaultValue))); }
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 override void Visit(SqlFunctionCall node) { switch (node.FunctionType) { case SqlFunctionType.PadLeft: case SqlFunctionType.PadRight: SqlHelper.GenericPad(node).AcceptVisitor(this); return; case SqlFunctionType.DateTimeOffsetAddYears: case SqlFunctionType.DateTimeAddYears: DateTimeAddComponent(node.Arguments[0], node.Arguments[1], true).AcceptVisitor(this); return; case SqlFunctionType.DateTimeOffsetAddMonths: case SqlFunctionType.DateTimeAddMonths: DateTimeAddComponent(node.Arguments[0], node.Arguments[1], false).AcceptVisitor(this); return; case SqlFunctionType.IntervalConstruct: IntervalConstruct(node.Arguments[0]).AcceptVisitor(this); return; case SqlFunctionType.DateTimeConstruct: DateTimeConstruct(node.Arguments[0], node.Arguments[1], node.Arguments[2]).AcceptVisitor(this); return; case SqlFunctionType.IntervalAbs: SqlHelper.IntervalAbs(node.Arguments[0]).AcceptVisitor(this); return; case SqlFunctionType.IntervalToMilliseconds: SqlHelper.IntervalToMilliseconds(node.Arguments[0]).AcceptVisitor(this); return; case SqlFunctionType.IntervalToNanoseconds: SqlHelper.IntervalToNanoseconds(node.Arguments[0]).AcceptVisitor(this); return; case SqlFunctionType.Position: Position(node.Arguments[0], node.Arguments[1]).AcceptVisitor(this); return; case SqlFunctionType.CharLength: SqlDml.Coalesce(SqlDml.FunctionCall("LENGTH", node.Arguments[0]), 0).AcceptVisitor(this); return; case SqlFunctionType.DateTimeToStringIso: DateTimeToStringIso(node.Arguments[0]).AcceptVisitor(this); return; case SqlFunctionType.DateTimeOffsetConstruct: DateTimeOffsetConstruct(node.Arguments[0], node.Arguments[1]).AcceptVisitor(this); return; case SqlFunctionType.DateTimeOffsetTimeOfDay: DateTimeOffsetTimeOfDay(node.Arguments[0]).AcceptVisitor(this); return; case SqlFunctionType.DateTimeOffsetToLocalTime: DateTimeOffsetToLocalTime(node.Arguments[0]).AcceptVisitor(this); return; case SqlFunctionType.DateTimeToDateTimeOffset: DateTimeToDateTimeOffset(node.Arguments[0]).AcceptVisitor(this); return; case SqlFunctionType.DateTimeOffsetToUtcTime: DateTimeOffsetToUtcTime(node.Arguments[0]).AcceptVisitor(this); return; default: base.Visit(node); return; } }