internal override SqlExpression DateTime_AddYears(SqlMethodCall mc) { var expr = mc.SourceExpression; var args = new[] { ValueFromObject("yyyy", expr), mc.Arguments[0], mc.Object }; return(FunctionCall(mc.ClrType, "DATEADD", args, expr)); }
internal override SqlExpression Math_Truncate(SqlMethodCall mc) { //var args = new[] { mc.Arguments[0], ValueFromObject(0, false, mc.SourceExpression), // ValueFromObject(1, false, mc.SourceExpression) }; //return FunctionCall(mc.Method.ReturnType, "TRUNC", mc.Arguments, mc.SourceExpression); throw SqlClient.Error.MethodHasNoSupportConversionToSql(mc); }
internal override SqlExpression DateTime_AddSeconds(SqlMethodCall mc) { var div = Binary(SqlNodeType.Div, mc.Arguments[0], ValueFromObject(24 * 60 * 60, mc.SourceExpression)); mc.Arguments[0] = div; return(DateTime_AddDays(mc)); }
private static bool IsVbCompareString(SqlMethodCall call) { return(call.Method.IsStatic && (call.Method.DeclaringType != null) && (call.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" || call.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.EmbeddedOperators") && call.Method.Name == "CompareString"); }
internal override SqlExpression Math_Truncate(SqlMethodCall mc) { var args = new[] { mc.Arguments[0], ValueFromObject(0, false, mc.SourceExpression), ValueFromObject(1, false, mc.SourceExpression) }; return(FunctionCall(mc.Method.ReturnType, "TRUNC", mc.Arguments, mc.SourceExpression)); }
internal override MethodSupport GetMethodSupport(SqlMethodCall mc) { if (mc.Object != null) { if (mc.Object.ClrType == typeof(DateTime)) { switch (mc.Method.Name) { case "Add": //case "AddDays": case "AddHours": case "AddMinutes": case "AddMonths": case "AddSeconds": //case "AddYears": return(MethodSupport.None); } } } if (mc.Method.Name == "Truncate") { return(MethodSupport.None); } return(base.GetMethodSupport(mc)); }
internal override SqlExpression DateTime_AddYears(SqlMethodCall mc) { var mul = Binary(SqlNodeType.Mul, mc.Arguments[0], ValueFromObject(12, mc.SourceExpression)); mc.Arguments[0] = mul; return(DateTime_AddMonths(mc)); }
internal override SqlExpression String_Remove(SqlMethodCall mc) { var clrType = mc.Method.ReturnType; Debug.Assert(clrType == typeof(string)); var startIndex = (int)((SqlValue)mc.Arguments[0]).Value; var sourceObject = (mc.Object); //var sourceString = var arg1 = mc.Object; var arg2 = ValueFromObject(startIndex, mc.SourceExpression);//Expression.Constant(startIndex)); var left = new SqlFunctionCall(typeof(string), TypeProvider.From(typeof(string)), "Left", new[] { arg1, arg2 }, mc.SourceExpression); if (mc.Arguments.Count == 2) { var count = (int)((SqlValue)mc.Arguments[1]).Value; SqlExpression len1 = ValueFromObject(startIndex + count, mc.SourceExpression); SqlExpression len2 = new SqlFunctionCall(typeof(int), TypeProvider.From(typeof(int)), "Length", new[] { sourceObject }, mc.SourceExpression); SqlExpression len = new SqlBinary(SqlNodeType.Sub, typeof(int), TypeProvider.From(typeof(int)), len2, len1); SqlExpression right = new SqlFunctionCall(typeof(string), TypeProvider.From(typeof(string)), "Right", new[] { sourceObject, len }, mc.SourceExpression); var result = new SqlBinary(SqlNodeType.Add, clrType, TypeProvider.From(clrType), left, right); return(result); } Debug.Assert(mc.Arguments.Count == 1); return(left); }
internal virtual SqlExpression VisitMethodCall(SqlMethodCall mc) { mc.Object = this.VisitExpression(mc.Object); for (int i = 0, n = mc.Arguments.Count; i < n; i++) { mc.Arguments[i] = this.VisitExpression(mc.Arguments[i]); } return mc; }
protected override MethodSupport GetDecimalMethodSupport(SqlMethodCall mc) { if (mc.Method.IsStatic) { if (mc.Arguments.Count == 2) { string str; if (((str = mc.Method.Name) != null) && ((((str == "Multiply") || (str == "Divide")) || ((str == "Subtract") || (str == "Add"))) || ((str == "Remainder") || (str == "Round")))) { return(MethodSupport.Method); } } else if (mc.Arguments.Count == 1) { string str2; if (((str2 = mc.Method.Name) != null) && (((str2 == "Negate") /*|| (str2 == "Floor")*/) || (/*(str2 == "Truncate") ||*/ (str2 == "Round")))) { return(MethodSupport.Method); } if (mc.Method.Name.StartsWith("To", StringComparison.Ordinal)) { return(MethodSupport.Method); } } } return(MethodSupport.None); }
internal override MethodSupport GetConvertMethodSupport(SqlMethodCall mc) { if ((mc.Method.IsStatic && (mc.Method.DeclaringType == typeof(Convert))) && (mc.Arguments.Count == 1)) { switch (mc.Method.Name) { case "ToBoolean": case "ToDecimal": //case "ToByte": case "ToChar": case "ToDouble": case "ToInt16": case "ToInt32": case "ToInt64": case "ToSingle": case "ToString": return(MethodSupport.Method); case "ToDateTime": if ((mc.Arguments[0].ClrType != typeof(string)) && (mc.Arguments[0].ClrType != typeof(DateTime))) { return(MethodSupport.MethodGroup); } return(MethodSupport.Method); } } return(MethodSupport.None); }
internal override SqlExpression String_Insert(SqlMethodCall mc) { var clrType = mc.Method.ReturnType; //var insertString = (string)((SqlValue)mc.Arguments[1]).Value; return(FunctionCall(clrType, "INSERT", new[] { mc.Object, Binary(SqlNodeType.Add, mc.Arguments[0], ValueFromObject(1, false, mc.SourceExpression)), ValueFromObject(0, mc.SourceExpression), mc.Arguments[1] }, mc.SourceExpression)); }
protected override SqlExpression TranslateStringInsertMethod(SqlMethodCall mc, Expression sourceExpression) { var clrType = mc.Method.ReturnType; var startIndex = (int)((SqlValue)mc.Arguments[0]).Value; var insertString = (string)((SqlValue)mc.Arguments[1]).Value; Debug.Assert(clrType == typeof(string)); Debug.Assert(startIndex >= 0); var arg1 = mc.Object;//VisitExpression(mc.Object); var arg2 = sql.ValueFromObject(startIndex, sourceExpression); var left = new SqlFunctionCall(clrType, sql.TypeProvider.From(clrType), "leftstr", new[] { arg1, arg2 }, sourceExpression); //return left; var result = new SqlBinary(SqlNodeType.Add, typeof(string), sql.TypeProvider.From(typeof(string)), left, sql.ValueFromObject(insertString, sourceExpression)); var len = new SqlFunctionCall(typeof(int), sql.TypeProvider.From(typeof(int)), "length", new[] { VisitExpression(mc.Object) }, sourceExpression); var binary = new SqlBinary(SqlNodeType.Sub, typeof(int), sql.TypeProvider.From(typeof(int)), len, arg2); var right = new SqlFunctionCall(typeof(string), sql.TypeProvider.From(typeof(string)), "rightstr", new[] { arg1, binary }, sourceExpression); result = new SqlBinary(SqlNodeType.Add, typeof(string), sql.TypeProvider.From(typeof(string)), result, right); return(result); }
internal override SqlExpression VisitBinaryOperator(SqlBinary bo) { if (IsCompareToValue(bo)) { SqlMethodCall call = (SqlMethodCall)bo.Left; if (IsCompareToMethod(call)) { int iValue = System.Convert.ToInt32(this.Eval(bo.Right), Globalization.CultureInfo.InvariantCulture); bo = this.MakeCompareTo(call.Object, call.Arguments[0], bo.NodeType, iValue) ?? bo; } else if (IsCompareMethod(call)) { int iValue = System.Convert.ToInt32(this.Eval(bo.Right), Globalization.CultureInfo.InvariantCulture); bo = this.MakeCompareTo(call.Arguments[0], call.Arguments[1], bo.NodeType, iValue) ?? bo; } } else if (IsVbCompareStringEqualsValue(bo)) { SqlMethodCall call = (SqlMethodCall)bo.Left; int iValue = System.Convert.ToInt32(this.Eval(bo.Right), Globalization.CultureInfo.InvariantCulture); //in VB, comparing a string with Nothing means comparing with "" SqlValue strValue = call.Arguments[1] as SqlValue; if (strValue != null && strValue.Value == null) { SqlValue emptyStr = new SqlValue(strValue.ClrType, strValue.SqlType, String.Empty, strValue.IsClientSpecified, strValue.SourceExpression); bo = this.MakeCompareTo(call.Arguments[0], emptyStr, bo.NodeType, iValue) ?? bo; } else { bo = this.MakeCompareTo(call.Arguments[0], call.Arguments[1], bo.NodeType, iValue) ?? bo; } } return(base.VisitBinaryOperator(bo)); }
internal override SqlExpression String_TrimStart(SqlMethodCall mc) { var expr = mc.SourceExpression; var args = new[] { VariableFromName("LEADING", expr), VariableFromName("FROM", expr), mc.Object }; return(FbFunctionCall(mc.ClrType, "TRIM", args, mc.SourceExpression)); }
internal override SqlExpression String_Insert(SqlMethodCall mc) { var clrType = mc.Method.ReturnType; var startIndex = (int)((SqlValue)mc.Arguments[0]).Value; //(int)((ConstantExpression)mc.Arguments[0]).Value; var insertString = (string)((SqlValue)mc.Arguments[1]).Value; //(string)((ConstantExpression)mc.Arguments[1]).Value; Debug.Assert(clrType == typeof(string)); Debug.Assert(startIndex >= 0); var arg1 = mc.Object; //VisitExpression(mc.Object); var arg2 = ValueFromObject(startIndex, mc.SourceExpression); //VisitExpression(Expression.Constant(startIndex)); var left = new SqlFunctionCall(clrType, TypeProvider.From(clrType), "LEFT", new[] { arg1, arg2 }, mc.SourceExpression); //return left; var result = new SqlBinary(SqlNodeType.Add, typeof(string), TypeProvider.From(typeof(string)), left, ValueFromObject(insertString, mc.SourceExpression)); var len = new SqlFunctionCall(typeof(int), TypeProvider.From(typeof(int)), "CHAR_LENGTH", new[] { (mc.Object) }, mc.SourceExpression); var binary = new SqlBinary(SqlNodeType.Sub, typeof(int), TypeProvider.From(typeof(int)), len, arg2); var right = new SqlFunctionCall(typeof(string), TypeProvider.From(typeof(string)), "RIGHT", new[] { arg1, binary }, mc.SourceExpression); result = new SqlBinary(SqlNodeType.Add, typeof(string), TypeProvider.From(typeof(string)), result, right); return(result); }
internal override SqlExpression DateTime_Add(SqlMethodCall mc) { var t = (TimeSpan)((SqlValue)mc.Arguments[0]).Value; var sb = new StringBuilder(); sb.Append(t.Days); sb.Append(" days"); if (t.Hours > 0) { sb.Append(" "); sb.Append(t.Hours); sb.Append(" hours"); } if (t.Minutes > 0) { sb.Append(" "); sb.Append(t.Minutes); sb.Append(" minutes"); } if (t.Seconds > 0) { sb.Append(" "); sb.Append(t.Seconds); sb.Append(" seconds"); } var f = FunctionCall(mc.ClrType, "INTERVAL", new[] { ValueFromObject(sb.ToString(), mc.SourceExpression) }, mc.SourceExpression); f.Comma = false; f.Brackets = false; return(Binary(SqlNodeType.Add, mc.Object, f)); }
internal override SqlExpression DateTime_AddMinutes(SqlMethodCall mc) { var expr = mc.SourceExpression; var args = new[] { mc.Arguments[0], VariableFromName("MINUTE", expr), VariableFromName("TO", expr), mc.Object }; return(FbFunctionCall(mc.ClrType, "DATEADD", args, mc.SourceExpression)); }
SqlExpression CreateDateTimeFunction(SqlMethodCall mc) { var s = mc.SourceExpression; var args = new[] { mc.Object, mc.Arguments[0] }; var func = FunctionCall(typeof(DateTime), mc.Method.Name, args, s); return(func); }
internal override SqlExpression Math_Log10(SqlMethodCall mc) { Debug.Assert(mc.Arguments.Count == 1); var value = ValueFromObject(10, mc.SourceExpression); mc.Arguments.Insert(0, value); return(CreateFunctionCallStatic2(typeof(double), "LOG", mc.Arguments, mc.SourceExpression)); }
internal override SqlExpression String_TrimEnd(SqlMethodCall mc) { //var arg0 = new FbFunctionArgument(mc.SourceExpression, "TRAILING", "From", mc.Object); var expr = mc.SourceExpression; var args = new[] { VariableFromName("TRAILING", expr), VariableFromName("FROM", expr), mc.Object }; return(FbFunctionCall(mc.ClrType, "TRIM", args, mc.SourceExpression)); }
internal override MethodSupport GetStringMethodSupport(SqlMethodCall mc) { if (mc.Method.Name == "IndexOf") { return(MethodSupport.None); } return(base.GetStringMethodSupport(mc)); }
protected override MethodSupport GetStringMethodSupport(SqlMethodCall mc) { if (mc.Method.Name == "TrimEnd") { return(MethodSupport.Method); } return(base.GetStringMethodSupport(mc)); }
internal override SqlExpression Math_Log10(SqlMethodCall mc) { Expression sourceExpression = mc.SourceExpression; SqlExpression first = this.FunctionCall(typeof(double), "LOG", new[] { mc.Arguments[0] }, sourceExpression); SqlExpression second = this.FunctionCall(typeof(double), "LOG", new[] { this.ValueFromObject(10, sourceExpression) }, sourceExpression); return(this.Divide(first, second)); }
internal override MethodSupport GetSqlMethodsMethodSupport(SqlMethodCall mc) { if (mc.Method.Name == "DateDiffMillisecond") { return(MethodSupport.None); } return(base.GetSqlMethodsMethodSupport(mc)); }
internal override MethodSupport GetMethodSupport(SqlMethodCall mc) { if (mc.Method.ReflectedType == typeof(Convert)) { return(sql.GetConvertMethodSupport(mc)); } return(base.GetMethodSupport(mc)); }
internal override MethodSupport GetSqlMethodsMethodSupport(SqlMethodCall mc) { if (mc.Method.Name.StartsWith("DateDiff")) { return(MethodSupport.None); } return(base.GetSqlMethodsMethodSupport(mc)); }
internal override SqlExpression DateTime_Add(SqlMethodCall mc) { var arg = Binary(SqlNodeType.Div, mc.Arguments[0], ValueFromObject(10000000, mc.SourceExpression)); //var args = new[] { mc.Object, mc.Arguments[0], arg }; var args = new[] { mc.Object, arg, ValueFromObject("SECOND", mc.SourceExpression) }; return(FunctionCall(mc.ClrType, "AddSeconds", args, mc.SourceExpression)); }
internal override SqlExpression VisitMethodCall(SqlMethodCall mc) { SqlExpression[] args = new SqlExpression[mc.Arguments.Count]; for (int i = 0, n = mc.Arguments.Count; i < n; i++) { args[i] = this.VisitExpression(mc.Arguments[i]); } return(new SqlMethodCall(mc.ClrType, mc.SqlType, mc.Method, this.VisitExpression(mc.Object), args, mc.SourceExpression)); }
protected override SqlExpression TranslateStringGetCharsMethod(SqlMethodCall mc, Expression sourceExpression) { if (mc.Arguments.Count != 1) { throw GetMethodSupportException(mc); } return(sql.FunctionCall(typeof(char), "SUBSTR", new[] { mc.Object, sql.Add(mc.Arguments[0], 1), sql.ValueFromObject(1, false, sourceExpression) }, sourceExpression)); }
internal override SqlExpression VisitMethodCall(SqlMethodCall mc) { if (mc.Arguments.Count==2 && mc.Method.Name=="op_Equality") { var r = mc.Arguments[1]; if (r.NodeType == SqlNodeType.Value) { var v = (SqlValue)r; v.SetSqlType(mc.Arguments[0].SqlType); } } return base.VisitMethodCall(mc); }
internal virtual SqlExpression VisitMethodCall(SqlMethodCall mc) { mc.Object = this.VisitExpression(mc.Object); for (int i = 0, n = mc.Arguments.Count; i < n; i++) { mc.Arguments[i] = this.VisitExpression(mc.Arguments[i]); } return mc; }
private SqlExpression TranslateGetValueOrDefaultMethod(SqlMethodCall mc) { if (mc.Arguments.Count == 0) { //mc.Object.ClrType must be Nullable<T> and T is a value type System.Type clrType = mc.Object.ClrType.GetGenericArguments()[0]; //the default value of clrType is obtained by Activator.CreateInstance(clrType) return sql.Binary(SqlNodeType.Coalesce, mc.Object, sql.ValueFromObject(Activator.CreateInstance(clrType), mc.SourceExpression)); } else { return sql.Binary(SqlNodeType.Coalesce, mc.Object, mc.Arguments[0]); } }
internal override SqlExpression VisitMethodCall(SqlMethodCall mc) { Type declType = mc.Method.DeclaringType; Expression source = mc.SourceExpression; SqlExpression returnValue = null; mc.Object = this.VisitExpression(mc.Object); for (int i = 0, n = mc.Arguments.Count; i < n; i++) { mc.Arguments[i] = this.VisitExpression(mc.Arguments[i]); } if (mc.Method.IsStatic) { if (mc.Method.Name == "op_Explicit" || mc.Method.Name == "op_Implicit") { if (mc.SqlType.CanBeColumn && mc.Arguments[0].SqlType.CanBeColumn) { returnValue = sql.ConvertTo(mc.ClrType, mc.Arguments[0]); } } else if (mc.Method.Name == "Compare" && mc.Arguments.Count == 2 && mc.Method.ReturnType == typeof(int)) { returnValue = this.CreateComparison(mc.Arguments[0], mc.Arguments[1], mc.SourceExpression); } else if (declType == typeof(System.Math)) { returnValue = TranslateMathMethod(mc); } else if (declType == typeof(System.String)) { returnValue = TranslateStringStaticMethod(mc); } else if (declType == typeof(System.Convert)) { returnValue = TranslateConvertStaticMethod(mc); } else if (declType == typeof(SqlMethods)) { returnValue = TranslateSqlMethodsMethod(mc); } else if (declType == typeof(decimal)) { returnValue = TranslateDecimalMethod(mc); } else if (IsVbConversionMethod(mc)) { return TranslateVbConversionMethod(mc); } else if (IsVbCompareString(mc)) { return TranslateVbCompareString(mc); } else if (IsVbLike(mc)) { return TranslateVbLikeString(mc); } //Recognized pattern has set return value so return if (returnValue != null) { // Assert here to verify that actual translation stays in [....] with // method support logic Debug.Assert(GetMethodSupport(mc) == MethodSupport.Method); return returnValue; } } else { // not static if (mc.Method.Name == "Equals" && mc.Arguments.Count == 1) { return sql.Binary(SqlNodeType.EQ, mc.Object, mc.Arguments[0]); } else if (mc.Method.Name == "GetValueOrDefault" && mc.Method.DeclaringType.IsGenericType && mc.Method.DeclaringType.GetGenericTypeDefinition() == typeof(Nullable<>)) { return TranslateGetValueOrDefaultMethod(mc); } else if (mc.Method.Name == "ToString" && mc.Arguments.Count == 0) { SqlExpression expr = mc.Object; if (!expr.SqlType.IsRuntimeOnlyType) { return sql.ConvertTo(typeof(string), expr); } throw Error.ToStringOnlySupportedForPrimitiveTypes(); } else if (declType == typeof(string)) { return TranslateStringMethod(mc); } else if (declType == typeof(TimeSpan)) { returnValue = TranslateTimeSpanInstanceMethod(mc); } else if (declType == typeof(DateTime)) { returnValue = TranslateDateTimeInstanceMethod(mc); } else if (declType == typeof(DateTimeOffset)) { returnValue = TranslateDateTimeOffsetInstanceMethod(mc); } if (returnValue != null) { // Assert here to verify that actual translation stays in [....] with // method support logic Debug.Assert(GetMethodSupport(mc) == MethodSupport.Method); return returnValue; } } throw GetMethodSupportException(mc); }
private static bool IsVbLike(SqlMethodCall mc) { return mc.Method.IsStatic && (mc.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.LikeOperator" && mc.Method.Name == "LikeString") || (mc.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" && mc.Method.Name == "LikeString"); }
private SqlExpression TranslateVbCompareString(SqlMethodCall mc) { if (mc.Arguments.Count >= 2) { return CreateComparison(mc.Arguments[0], mc.Arguments[1], mc.SourceExpression); } throw GetMethodSupportException(mc); }
private SqlExpression TranslateMathMethod(SqlMethodCall mc) { Expression source = mc.SourceExpression; switch (mc.Method.Name) { case "Abs": if (mc.Arguments.Count == 1) { return sql.FunctionCall(mc.Arguments[0].ClrType, "ABS", new SqlExpression[] { mc.Arguments[0] }, source); } break; case "Acos": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(typeof(double), "ACOS", mc.Arguments, source); } break; case "Asin": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(typeof(double), "ASIN", mc.Arguments, source); } break; case "Atan": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(typeof(double), "ATAN", mc.Arguments, source); } break; case "Atan2": if (mc.Arguments.Count == 2) { return this.CreateFunctionCallStatic2(typeof(double), "ATN2", mc.Arguments, source); } break; case "BigMul": if (mc.Arguments.Count == 2) { return sql.Multiply(sql.ConvertToBigint(mc.Arguments[0]), sql.ConvertToBigint(mc.Arguments[1])); } break; case "Ceiling": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(mc.Arguments[0].ClrType, "CEILING", mc.Arguments, source); } break; case "Cos": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(typeof(double), "COS", mc.Arguments, source); } break; case "Cosh": if (mc.Arguments.Count == 1) { SqlExpression x = mc.Arguments[0]; SqlExpression expX = sql.FunctionCall(typeof(double), "EXP", new SqlExpression[] { x }, source); SqlExpression minusX = sql.Unary(SqlNodeType.Negate, x, source); SqlExpression expMinusX = sql.FunctionCall(typeof(double), "EXP", new SqlExpression[] { minusX }, source); return sql.Divide(sql.Add(expX, expMinusX), 2); } break; // DivRem has out parameter case "Exp": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(typeof(double), "EXP", mc.Arguments, source); } break; case "Floor": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(mc.Arguments[0].ClrType, "FLOOR", mc.Arguments, source); } break; // Math.IEEERemainder - difficult to implement correctly since SQL rounds differently case "Log": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(typeof(double), "LOG", mc.Arguments, source); } else if (mc.Arguments.Count == 2) { // Math.Log(x,y) --> LOG(@x) / LOG(@y) SqlExpression log1 = sql.FunctionCall(typeof(double), "LOG", new SqlExpression[] { mc.Arguments[0] }, source); SqlExpression log2 = sql.FunctionCall(typeof(double), "LOG", new SqlExpression[] { mc.Arguments[1] }, source); return sql.Divide(log1, log2); } break; case "Log10": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(typeof(double), "LOG10", mc.Arguments, source); } break; case "Max": if (mc.Arguments.Count == 2) { // Max(a,b) --> CASE WHEN @a<@b THEN @b ELSE @a SqlExpression a = mc.Arguments[0]; SqlExpression b = mc.Arguments[1]; SqlExpression aLower = sql.Binary(SqlNodeType.LT, a, b); return new SqlSearchedCase(mc.Method.ReturnType, new SqlWhen[] { new SqlWhen(aLower, b) }, a, source); } break; case "Min": if (mc.Arguments.Count == 2) { // Min(a,b) --> CASE WHEN @a<@b THEN @a ELSE @b SqlExpression a = mc.Arguments[0]; SqlExpression b = mc.Arguments[1]; SqlExpression aLower = sql.Binary(SqlNodeType.LT, a, b); return sql.SearchedCase(new SqlWhen[] { new SqlWhen(aLower, a) }, b, source); } break; case "Pow": if (mc.Arguments.Count == 2) { return this.CreateFunctionCallStatic2(mc.ClrType, "POWER", mc.Arguments, source); } break; case "Round": int nParams = mc.Arguments.Count; if ((mc.Arguments[nParams - 1].ClrType != typeof(MidpointRounding))) { throw Error.MathRoundNotSupported(); } else { SqlExpression x = mc.Arguments[0]; SqlExpression i = null; if (nParams == 2) { i = sql.ValueFromObject(0, false, source); } else { i = mc.Arguments[1]; } SqlExpression roundingMethod = mc.Arguments[nParams - 1]; if (roundingMethod.NodeType != SqlNodeType.Value) { throw Error.NonConstantExpressionsNotSupportedForRounding(); } if ((MidpointRounding)this.Eval(roundingMethod) == MidpointRounding.AwayFromZero) { // round(x) --> round(@x,0) return sql.FunctionCall(x.ClrType, "round", new SqlExpression[] { x, i }, source); } else { // CASE WHEN 2*@x = ROUND(2*@x, @i) AND @x <> ROUND(@x, @i) // THEN 2 * ROUND(@x/2, @i) // ELSE ROUND(@x, @i) // END Type type = x.ClrType; SqlExpression roundX = sql.FunctionCall(type, "round", new SqlExpression[] { x, i }, source); SqlExpression twiceX = sql.Multiply(x, 2); SqlExpression round2X = sql.FunctionCall(type, "round", new SqlExpression[] { twiceX, i }, source); SqlExpression condition = sql.AndAccumulate(sql.Binary(SqlNodeType.EQ, twiceX, round2X), sql.Binary(SqlNodeType.NE, x, roundX)); SqlExpression specialCase = sql.Multiply(sql.FunctionCall(type, "round", new SqlExpression[] { sql.Divide(x, 2), i }, source), 2); return sql.SearchedCase(new SqlWhen[] { new SqlWhen(condition, specialCase) }, roundX, source); } } case "Sign": if (mc.Arguments.Count == 1) { return sql.FunctionCall(typeof(int), "SIGN", new SqlExpression[] { mc.Arguments[0] }, source); } break; case "Sin": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(typeof(double), "SIN", mc.Arguments, source); } break; case "Sinh": if (mc.Arguments.Count == 1) { SqlExpression x = mc.Arguments[0]; SqlExpression exp = sql.FunctionCall(typeof(double), "EXP", new SqlExpression[] { x }, source); SqlExpression minusX = sql.Unary(SqlNodeType.Negate, x, source); SqlExpression expMinus = sql.FunctionCall(typeof(double), "EXP", new SqlExpression[] { minusX }, source); return sql.Divide(sql.Subtract(exp, expMinus), 2); } break; case "Sqrt": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(typeof(double), "SQRT", mc.Arguments, source); } break; case "Tan": if (mc.Arguments.Count == 1) { return this.CreateFunctionCallStatic1(typeof(double), "TAN", mc.Arguments, source); } break; case "Tanh": if (mc.Arguments.Count == 1) { SqlExpression x = mc.Arguments[0]; SqlExpression expX = sql.FunctionCall(typeof(double), "EXP", new SqlExpression[] { x }, source); SqlExpression minusX = sql.Unary(SqlNodeType.Negate, x, source); SqlExpression expMinusX = sql.FunctionCall(typeof(double), "EXP", new SqlExpression[] { minusX }, source); return sql.Divide(sql.Subtract(expX, expMinusX), sql.Add(expX, expMinusX)); } break; case "Truncate": if (mc.Arguments.Count == 1) { // Truncate(x) --> ROUND (x, 0, 1) SqlExpression x = mc.Arguments[0]; return sql.FunctionCall(mc.Method.ReturnType, "ROUND", new SqlExpression[] { x, sql.ValueFromObject(0, false, source), sql.ValueFromObject(1, false, source) }, source); } break; } throw GetMethodSupportException(mc); }
private static MethodSupport GetObjectMethodSupport(SqlMethodCall mc) { if (!mc.Method.IsStatic) { switch (mc.Method.Name) { case "Equals": return MethodSupport.Method; case "ToString": if (mc.Object.SqlType.CanBeColumn) { return MethodSupport.Method; } return MethodSupport.None; case "GetType": if (mc.Arguments.Count == 0) { return MethodSupport.Method; } return MethodSupport.None; } } return MethodSupport.None; }
private static MethodSupport GetComparisonMethodSupport(SqlMethodCall mc) { if (mc.Method.IsStatic && mc.Method.Name == "Compare" && mc.Method.ReturnType == typeof(int)) { return MethodSupport.Method; } return MethodSupport.None; }
private static MethodSupport GetCoercionMethodSupport(SqlMethodCall mc) { if(mc.Method.IsStatic && mc.SqlType.CanBeColumn && (mc.Method.Name == "op_Implicit" || mc.Method.Name == "op_Explicit")){ return MethodSupport.Method; } return MethodSupport.None; }
private static bool IsVbCompareString(SqlMethodCall call) { return call.Method.IsStatic && call.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" && call.Method.Name == "CompareString"; }
private SqlExpression TranslateVbLikeString(SqlMethodCall mc) { // these should be true per the method signature Debug.Assert(mc.Arguments.Count == 3); Debug.Assert(mc.Arguments[0].ClrType == typeof(string)); Debug.Assert(mc.Arguments[1].ClrType == typeof(string)); bool needsEscape = true; Expression source = mc.SourceExpression; SqlExpression pattern = mc.Arguments[1]; if (pattern.NodeType == SqlNodeType.Value) { string unescapedText = (string)((SqlValue)pattern).Value; string patternText = SqlHelpers.TranslateVBLikePattern(unescapedText, '~'); pattern = sql.ValueFromObject(patternText, typeof(string), true, source); needsEscape = unescapedText != patternText; } else if (pattern.NodeType == SqlNodeType.ClientParameter) { SqlClientParameter cp = (SqlClientParameter)pattern; pattern = new SqlClientParameter( cp.ClrType, cp.SqlType, Expression.Lambda( Expression.Call(typeof(SqlHelpers), "TranslateVBLikePattern", Type.EmptyTypes, cp.Accessor.Body, Expression.Constant('~')), cp.Accessor.Parameters[0] ), cp.SourceExpression ); } else { throw Error.NonConstantExpressionsNotSupportedFor("LIKE"); } SqlExpression escape = needsEscape ? sql.ValueFromObject("~", false, mc.SourceExpression) : null; return sql.Like(mc.Arguments[0], pattern, escape, source); }
private static bool IsVbConversionMethod(SqlMethodCall mc) { if (mc.Method.IsStatic && mc.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Conversions") { switch (mc.Method.Name) { case "ToBoolean": case "ToSByte": case "ToByte": case "ToChar": case "ToCharArrayRankOne": case "ToDate": case "ToDecimal": case "ToDouble": case "ToInteger": case "ToUInteger": case "ToLong": case "ToULong": case "ToShort": case "ToUShort": case "ToSingle": case "ToString": return true; } } return false; }
private static MethodSupport GetDateTimeOffsetMethodSupport(SqlMethodCall mc) { if (!mc.Method.IsStatic && mc.Method.DeclaringType == typeof(DateTimeOffset)) { switch (mc.Method.Name) { case "CompareTo": case "AddTicks": case "AddMonths": case "AddYears": case "AddMilliseconds": case "AddSeconds": case "AddMinutes": case "AddHours": case "AddDays": return MethodSupport.Method; case "Add": if (mc.Arguments.Count == 1 && mc.Arguments[0].ClrType == typeof(TimeSpan)) { return MethodSupport.Method; } else { return MethodSupport.MethodGroup; } } } return MethodSupport.None; }
internal static Exception GetMethodSupportException(SqlMethodCall mc) { MethodSupport ms = GetMethodSupport(mc); if (ms == MethodSupport.MethodGroup) { // If the method is supported in some form, we want to give a // different exception message to the user return Error.MethodFormHasNoSupportConversionToSql(mc.Method.Name, mc.Method); } else { // No form of the method is supported return Error.MethodHasNoSupportConversionToSql(mc.Method); } }
private static MethodSupport GetTimeSpanMethodSupport(SqlMethodCall mc) { if (!mc.Method.IsStatic && mc.Method.DeclaringType == typeof(TimeSpan)) { switch (mc.Method.Name) { case "Add": case "Subtract": case "CompareTo": case "Duration": case "Negate": return MethodSupport.Method; } } return MethodSupport.None; }
internal override SqlExpression VisitMethodCall(SqlMethodCall mc) { // eventually we may support this type of stuff given the SQL CLR, but for now it is illegal throw Error.MethodHasNoSupportConversionToSql(mc.Method.Name); }
private static MethodSupport GetConvertMethodSupport(SqlMethodCall mc) { if (mc.Method.IsStatic && mc.Method.DeclaringType == typeof(Convert) && mc.Arguments.Count == 1) { switch (mc.Method.Name) { case "ToBoolean": case "ToDecimal": case "ToByte": case "ToChar": case "ToDouble": case "ToInt16": case "ToInt32": case "ToInt64": case "ToSingle": case "ToString": return MethodSupport.Method; case "ToDateTime": if (mc.Arguments[0].ClrType == typeof(string) || mc.Arguments[0].ClrType == typeof(DateTime)) { return MethodSupport.Method; } else { return MethodSupport.MethodGroup; } } } return MethodSupport.None; }
internal override SqlExpression VisitMethodCall(SqlMethodCall mc) { mc.Object = this.VisitExpression(mc.Object); System.Reflection.ParameterInfo[] pis = mc.Method.GetParameters(); for (int i = 0, n = mc.Arguments.Count; i < n; i++) { mc.Arguments[i] = this.VisitNamedExpression(mc.Arguments[i], pis[i].Name); } return mc; }
private static MethodSupport GetDecimalMethodSupport(SqlMethodCall mc) { if (mc.Method.IsStatic) { if (mc.Arguments.Count == 2) { switch (mc.Method.Name) { case "Multiply": case "Divide": case "Subtract": case "Add": case "Remainder": case "Round": return MethodSupport.Method; } } else if (mc.Arguments.Count == 1) { switch (mc.Method.Name) { case "Negate": case "Floor": case "Truncate": case "Round": return MethodSupport.Method; default: if (mc.Method.Name.StartsWith("To", StringComparison.Ordinal)) { return MethodSupport.Method; } break; } } } return MethodSupport.None; }
private SqlExpression ExpandTogether(List<SqlExpression> exprs) { switch (exprs[0].NodeType) { case SqlNodeType.MethodCall: { SqlMethodCall[] mcs = new SqlMethodCall[exprs.Count]; for (int i = 0; i < mcs.Length; ++i) { mcs[i] = (SqlMethodCall)exprs[i]; } List<SqlExpression> expandedArgs = new List<SqlExpression>(); for (int i = 0; i < mcs[0].Arguments.Count; ++i) { List<SqlExpression> args = new List<SqlExpression>(); for (int j = 0; j < mcs.Length; ++j) { args.Add(mcs[j].Arguments[i]); } SqlExpression expanded = this.ExpandTogether(args); expandedArgs.Add(expanded); } return factory.MethodCall(mcs[0].Method, mcs[0].Object, expandedArgs.ToArray(), mcs[0].SourceExpression); } case SqlNodeType.ClientCase: { // Are they all the same? SqlClientCase[] scs = new SqlClientCase[exprs.Count]; scs[0] = (SqlClientCase)exprs[0]; for (int i = 1; i < scs.Length; ++i) { scs[i] = (SqlClientCase)exprs[i]; } // Expand expressions together. List<SqlExpression> expressions = new List<SqlExpression>(); for (int i = 0; i < scs.Length; ++i) { expressions.Add(scs[i].Expression); } SqlExpression expression = this.ExpandTogether(expressions); // Expand individual expressions together. List<SqlClientWhen> whens = new List<SqlClientWhen>(); for (int i = 0; i < scs[0].Whens.Count; ++i) { List<SqlExpression> scos = new List<SqlExpression>(); for (int j = 0; j < scs.Length; ++j) { SqlClientWhen when = scs[j].Whens[i]; scos.Add(when.Value); } whens.Add(new SqlClientWhen(scs[0].Whens[i].Match, this.ExpandTogether(scos))); } return new SqlClientCase(scs[0].ClrType, expression, whens, scs[0].SourceExpression); } case SqlNodeType.TypeCase: { // Are they all the same? SqlTypeCase[] tcs = new SqlTypeCase[exprs.Count]; tcs[0] = (SqlTypeCase)exprs[0]; for (int i = 1; i < tcs.Length; ++i) { tcs[i] = (SqlTypeCase)exprs[i]; } // Expand discriminators together. List<SqlExpression> discriminators = new List<SqlExpression>(); for (int i = 0; i < tcs.Length; ++i) { discriminators.Add(tcs[i].Discriminator); } SqlExpression discriminator = this.ExpandTogether(discriminators); // Write expanded discriminators back in. for (int i = 0; i < tcs.Length; ++i) { tcs[i].Discriminator = discriminators[i]; } // Expand individual type bindings together. List<SqlTypeCaseWhen> whens = new List<SqlTypeCaseWhen>(); for (int i = 0; i < tcs[0].Whens.Count; ++i) { List<SqlExpression> scos = new List<SqlExpression>(); for (int j = 0; j < tcs.Length; ++j) { SqlTypeCaseWhen when = tcs[j].Whens[i]; scos.Add(when.TypeBinding); } SqlExpression expanded = this.ExpandTogether(scos); whens.Add(new SqlTypeCaseWhen(tcs[0].Whens[i].Match, expanded)); } return factory.TypeCase(tcs[0].ClrType, tcs[0].RowType, discriminator, whens, tcs[0].SourceExpression); } case SqlNodeType.New: { // first verify all are similar client objects... SqlNew[] cobs = new SqlNew[exprs.Count]; cobs[0] = (SqlNew)exprs[0]; for (int i = 1, n = exprs.Count; i < n; i++) { if (exprs[i] == null || exprs[i].NodeType != SqlNodeType.New) throw Error.UnionIncompatibleConstruction(); cobs[i] = (SqlNew)exprs[1]; if (cobs[i].Members.Count != cobs[0].Members.Count) throw Error.UnionDifferentMembers(); for (int m = 0, mn = cobs[0].Members.Count; m < mn; m++) { if (cobs[i].Members[m].Member != cobs[0].Members[m].Member) { throw Error.UnionDifferentMemberOrder(); } } } SqlMemberAssign[] bindings = new SqlMemberAssign[cobs[0].Members.Count]; for (int m = 0, mn = bindings.Length; m < mn; m++) { List<SqlExpression> mexprs = new List<SqlExpression>(); for (int i = 0, n = exprs.Count; i < n; i++) { mexprs.Add(cobs[i].Members[m].Expression); } bindings[m] = new SqlMemberAssign(cobs[0].Members[m].Member, this.ExpandTogether(mexprs)); for (int i = 0, n = exprs.Count; i < n; i++) { cobs[i].Members[m].Expression = mexprs[i]; } } SqlExpression[] arguments = new SqlExpression[cobs[0].Args.Count]; for (int m = 0, mn = arguments.Length; m < mn; ++m) { List<SqlExpression> mexprs = new List<SqlExpression>(); for (int i = 0, n = exprs.Count; i < n; i++) { mexprs.Add(cobs[i].Args[m]); } arguments[m] = ExpandTogether(mexprs); } return factory.New(cobs[0].MetaType, cobs[0].Constructor, arguments, cobs[0].ArgMembers, bindings, exprs[0].SourceExpression); } case SqlNodeType.Link: { SqlLink[] links = new SqlLink[exprs.Count]; links[0] = (SqlLink)exprs[0]; for (int i = 1, n = exprs.Count; i < n; i++) { if (exprs[i] == null || exprs[i].NodeType != SqlNodeType.Link) throw Error.UnionIncompatibleConstruction(); links[i] = (SqlLink)exprs[i]; if (links[i].KeyExpressions.Count != links[0].KeyExpressions.Count || links[i].Member != links[0].Member || (links[i].Expansion != null) != (links[0].Expansion != null)) throw Error.UnionIncompatibleConstruction(); } SqlExpression[] kexprs = new SqlExpression[links[0].KeyExpressions.Count]; List<SqlExpression> lexprs = new List<SqlExpression>(); for (int k = 0, nk = links[0].KeyExpressions.Count; k < nk; k++) { lexprs.Clear(); for (int i = 0, n = exprs.Count; i < n; i++) { lexprs.Add(links[i].KeyExpressions[k]); } kexprs[k] = this.ExpandTogether(lexprs); for (int i = 0, n = exprs.Count; i < n; i++) { links[i].KeyExpressions[k] = lexprs[i]; } } SqlExpression expansion = null; if (links[0].Expansion != null) { lexprs.Clear(); for (int i = 0, n = exprs.Count; i < n; i++) { lexprs.Add(links[i].Expansion); } expansion = this.ExpandTogether(lexprs); for (int i = 0, n = exprs.Count; i < n; i++) { links[i].Expansion = lexprs[i]; } } return new SqlLink(links[0].Id, links[0].RowType, links[0].ClrType, links[0].SqlType, links[0].Expression, links[0].Member, kexprs, expansion, links[0].SourceExpression); } case SqlNodeType.Value: { /* * ExprSet of all literals of the same value reduce to just a single literal. */ SqlValue val0 = (SqlValue)exprs[0]; for (int i = 1; i < exprs.Count; ++i) { SqlValue val = (SqlValue)exprs[i]; if (!object.Equals(val.Value, val0.Value)) return this.ExpandIntoExprSet(exprs); } return val0; } case SqlNodeType.OptionalValue: { if (exprs[0].SqlType.CanBeColumn) { goto default; } List<SqlExpression> hvals = new List<SqlExpression>(exprs.Count); List<SqlExpression> vals = new List<SqlExpression>(exprs.Count); for (int i = 0, n = exprs.Count; i < n; i++) { if (exprs[i] == null || exprs[i].NodeType != SqlNodeType.OptionalValue) { throw Error.UnionIncompatibleConstruction(); } SqlOptionalValue sov = (SqlOptionalValue)exprs[i]; hvals.Add(sov.HasValue); vals.Add(sov.Value); } return new SqlOptionalValue(this.ExpandTogether(hvals), this.ExpandTogether(vals)); } case SqlNodeType.OuterJoinedValue: { if (exprs[0].SqlType.CanBeColumn) { goto default; } List<SqlExpression> values = new List<SqlExpression>(exprs.Count); for (int i = 0, n = exprs.Count; i < n; i++) { if (exprs[i] == null || exprs[i].NodeType != SqlNodeType.OuterJoinedValue) { throw Error.UnionIncompatibleConstruction(); } SqlUnary su = (SqlUnary)exprs[i]; values.Add(su.Operand); } return factory.Unary(SqlNodeType.OuterJoinedValue, this.ExpandTogether(values)); } case SqlNodeType.DiscriminatedType: { SqlDiscriminatedType sdt0 = (SqlDiscriminatedType)exprs[0]; List<SqlExpression> foos = new List<SqlExpression>(exprs.Count); foos.Add(sdt0.Discriminator); for (int i = 1, n = exprs.Count; i < n; i++) { SqlDiscriminatedType sdtN = (SqlDiscriminatedType)exprs[i]; if (sdtN.TargetType != sdt0.TargetType) { throw Error.UnionIncompatibleConstruction(); } foos.Add(sdtN.Discriminator); } return factory.DiscriminatedType(this.ExpandTogether(foos), ((SqlDiscriminatedType)exprs[0]).TargetType); } case SqlNodeType.ClientQuery: case SqlNodeType.Multiset: case SqlNodeType.Element: case SqlNodeType.Grouping: throw Error.UnionWithHierarchy(); default: return this.ExpandIntoExprSet(exprs); } }
private static MethodSupport GetStringMethodSupport(SqlMethodCall mc) { if (mc.Method.DeclaringType == typeof(string)) { if (mc.Method.IsStatic) { if (mc.Method.Name == "Concat") { return MethodSupport.Method; } } else { switch (mc.Method.Name) { case "Contains": case "StartsWith": case "EndsWith": if (mc.Arguments.Count == 1) { return MethodSupport.Method; } return MethodSupport.MethodGroup; case "IndexOf": case "LastIndexOf": if (mc.Arguments.Count == 1 || mc.Arguments.Count == 2 || mc.Arguments.Count == 3) { return MethodSupport.Method; } return MethodSupport.MethodGroup; case "Insert": if (mc.Arguments.Count == 2) { return MethodSupport.Method; } return MethodSupport.MethodGroup; case "PadLeft": case "PadRight": case "Remove": case "Substring": if(mc.Arguments.Count == 1 || mc.Arguments.Count == 2) { return MethodSupport.Method; } return MethodSupport.MethodGroup; case "Replace": return MethodSupport.Method; case "Trim": case "ToLower": case "ToUpper": if (mc.Arguments.Count == 0) { return MethodSupport.Method; } return MethodSupport.MethodGroup; case "get_Chars": case "CompareTo": if (mc.Arguments.Count == 1) { return MethodSupport.Method; } return MethodSupport.MethodGroup; } } } return MethodSupport.None; }
internal override SqlExpression VisitMethodCall(SqlMethodCall mc) { mc.Object = this.FetchExpression(mc.Object); for (int i = 0, n = mc.Arguments.Count; i < n; i++) { mc.Arguments[i] = this.FetchExpression(mc.Arguments[i]); } return mc; }
private static MethodSupport GetMathMethodSupport(SqlMethodCall mc) { if (mc.Method.IsStatic && mc.Method.DeclaringType == typeof(Math)) { switch (mc.Method.Name) { case "Abs": case "Acos": case "Asin": case "Atan": case "Ceiling": case "Cos": case "Cosh": case "Exp": case "Floor": case "Log10": if(mc.Arguments.Count == 1) { return MethodSupport.Method; } return MethodSupport.MethodGroup; case "Log": if (mc.Arguments.Count == 1 || mc.Arguments.Count == 2) { return MethodSupport.Method; }; return MethodSupport.MethodGroup; case "Max": case "Min": case "Pow": case "Atan2": case "BigMul": if (mc.Arguments.Count == 2) { return MethodSupport.Method; } return MethodSupport.MethodGroup; case "Round": if (mc.Arguments[mc.Arguments.Count - 1].ClrType == typeof(MidpointRounding) && (mc.Arguments.Count == 2 || mc.Arguments.Count == 3)) { return MethodSupport.Method; } return MethodSupport.MethodGroup; case "Sign": case "Sin": case "Sinh": case "Sqrt": case "Tan": case "Tanh": case "Truncate": if (mc.Arguments.Count == 1) { return MethodSupport.Method; } return MethodSupport.MethodGroup; } } return MethodSupport.None; }
internal override SqlExpression VisitMethodCall(SqlMethodCall mc) { SqlExpression[] args = new SqlExpression[mc.Arguments.Count]; for (int i = 0, n = mc.Arguments.Count; i < n; i++) { args[i] = this.VisitExpression(mc.Arguments[i]); } return new SqlMethodCall(mc.ClrType, mc.SqlType, mc.Method, this.VisitExpression(mc.Object), args, mc.SourceExpression); }
private static MethodSupport GetVbHelperMethodSupport(SqlMethodCall mc) { if (IsVbConversionMethod(mc) || IsVbCompareString(mc) || IsVbLike(mc)) { return MethodSupport.Method; } return MethodSupport.None; }
private static MethodSupport GetNullableMethodSupport(SqlMethodCall mc) { if (mc.Method.Name == "GetValueOrDefault" && TypeSystem.IsNullableType(mc.Object.ClrType)) { return MethodSupport.Method; } return MethodSupport.None; }
private SqlExpression TranslateVbConversionMethod(SqlMethodCall mc) { Expression source = mc.SourceExpression; if (mc.Arguments.Count == 1) { SqlExpression expr = mc.Arguments[0]; Type targetType = null; switch (mc.Method.Name) { case "ToBoolean": targetType = typeof(bool); break; case "ToSByte": targetType = typeof(sbyte); break; case "ToByte": targetType = typeof(byte); break; case "ToChar": targetType = typeof(char); break; case "ToCharArrayRankOne": targetType = typeof(char[]); break; case "ToDate": targetType = typeof(DateTime); break; case "ToDecimal": targetType = typeof(decimal); break; case "ToDouble": targetType = typeof(double); break; case "ToInteger": targetType = typeof(Int32); break; case "ToUInteger": targetType = typeof(UInt32); break; case "ToLong": targetType = typeof(Int64); break; case "ToULong": targetType = typeof(UInt64); break; case "ToShort": targetType = typeof(Int16); break; case "ToUShort": targetType = typeof(UInt16); break; case "ToSingle": targetType = typeof(float); break; case "ToString": targetType = typeof(string); break; } if (targetType != null) { if ((targetType == typeof(int) || targetType == typeof(Single)) && expr.ClrType == typeof(bool)) { List<SqlExpression> matchesList = new List<SqlExpression>(); List<SqlExpression> valuesList = new List<SqlExpression>(); matchesList.Add(sql.ValueFromObject(true, false, source)); valuesList.Add(sql.ValueFromObject(-1, false, source)); matchesList.Add(sql.ValueFromObject(false, false, source)); valuesList.Add(sql.ValueFromObject(0, false, source)); return sql.Case(targetType, expr, matchesList, valuesList, source); } else if (mc.ClrType != mc.Arguments[0].ClrType) { // do the conversions that would be done for a cast "(<targetType>) expression" return sql.ConvertTo(targetType, expr); } else { return mc.Arguments[0]; } } } throw GetMethodSupportException(mc); }
internal override SqlExpression VisitMethodCall(SqlMethodCall mc) { if (!this.isDebugMode) { throw Error.InvalidFormatNode("MethodCall"); } if (mc.Method.IsStatic) { sb.Append(mc.Method.DeclaringType); } else { this.Visit(mc.Object); } sb.Append("."); sb.Append(mc.Method.Name); sb.Append("("); for (int i = 0, n = mc.Arguments.Count; i < n; i++) { if (i > 0) sb.Append(", "); this.Visit(mc.Arguments[i]); } sb.Append(")"); return mc; }
private static MethodSupport GetSqlMethodsMethodSupport(SqlMethodCall mc) { if (mc.Method.IsStatic && mc.Method.DeclaringType == typeof(SqlMethods)) { if (mc.Method.Name.StartsWith("DateDiff", StringComparison.Ordinal) && mc.Arguments.Count == 2) { foreach (string datePart in dateParts) { if (mc.Method.Name == "DateDiff" + datePart) { if (mc.Arguments.Count == 2) { return MethodSupport.Method; } else { return MethodSupport.MethodGroup; } } } } else if (mc.Method.Name == "Like") { if (mc.Arguments.Count == 2) { return MethodSupport.Method; } else if (mc.Arguments.Count == 3) { return MethodSupport.Method; } return MethodSupport.MethodGroup; } else if (mc.Method.Name == "RawLength") { return MethodSupport.Method; } } return MethodSupport.None; }