Example #1
0
        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));
        }
Example #2
0
 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);
 }
Example #3
0
        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");
 }
Example #5
0
        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));
        }
Example #6
0
 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));
 }
Example #7
0
        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));
        }
Example #8
0
        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);
        }
Example #9
0
 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;
 }
Example #10
0
 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);
 }
Example #11
0
        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);
        }
Example #12
0
        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));
        }
Example #13
0
            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);
            }
Example #14
0
 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));
 }
Example #15
0
        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));
        }
Example #16
0
        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);
        }
Example #17
0
        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));
        }
Example #18
0
        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));
        }
Example #19
0
        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);
        }
Example #20
0
        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));
        }
Example #21
0
        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));
        }
Example #22
0
 internal override MethodSupport GetStringMethodSupport(SqlMethodCall mc)
 {
     if (mc.Method.Name == "IndexOf")
     {
         return(MethodSupport.None);
     }
     return(base.GetStringMethodSupport(mc));
 }
Example #23
0
 protected override MethodSupport GetStringMethodSupport(SqlMethodCall mc)
 {
     if (mc.Method.Name == "TrimEnd")
     {
         return(MethodSupport.Method);
     }
     return(base.GetStringMethodSupport(mc));
 }
Example #24
0
        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));
        }
Example #25
0
 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));
 }
Example #27
0
        internal override MethodSupport GetSqlMethodsMethodSupport(SqlMethodCall mc)
        {
            if (mc.Method.Name.StartsWith("DateDiff"))
            {
                return(MethodSupport.None);
            }

            return(base.GetSqlMethodsMethodSupport(mc));
        }
Example #28
0
        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));
 }
Example #30
0
 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));
 }
Example #31
0
 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;
 }
Example #49
0
 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;
 }
Example #53
0
 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;
 }