internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc) {
            // process the arguments
            SqlExpression result = base.VisitFunctionCall(fc);
            if (result is SqlFunctionCall) {
                SqlFunctionCall resultFunctionCall = (SqlFunctionCall)result;

                if (resultFunctionCall.Name == "LEN") {
                    SqlExpression expr = resultFunctionCall.Arguments[0];

                    if (expr.SqlType.IsLargeType && !expr.SqlType.SupportsLength) {
                        result = sql.DATALENGTH(expr);
                        
                        if (expr.SqlType.IsUnicodeType) {
                            result = sql.ConvertToInt(sql.Divide(result, sql.ValueFromObject(2, expr.SourceExpression)));
                        }
                    }
                }

                // If the return type of the sql function is not compatible with
                // the expected CLR type of the function, inject a conversion. This
                // step must be performed AFTER SqlRetyper has run.
                Type clrType = resultFunctionCall.SqlType.GetClosestRuntimeType();
                bool skipConversion = SqlMethodTransformer.SkipConversionForDateAdd(resultFunctionCall.Name,
                                                                                    resultFunctionCall.ClrType,
                                                                                    clrType);
                if ((resultFunctionCall.ClrType != clrType) && !skipConversion) {
                    result = sql.ConvertTo(resultFunctionCall.ClrType, resultFunctionCall);
                }
            }

            return result;
        }
 internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc) {
     for (int i = 0, n = fc.Arguments.Count; i < n; i++) {
         fc.Arguments[i] = this.FetchExpression(fc.Arguments[i]);
     }
     return fc;
 }
 internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc) {
     if (fc.Name == "LEN") {
         bool changed;
         fc.Arguments[0] = ConvertToMax(fc.Arguments[0],out changed);
         if (fc.Arguments[0].SqlType.IsLargeType) {
             this.annotations.Add(fc, new SqlServerCompatibilityAnnotation(
                                        Strings.LenOfTextOrNTextNotSupported(fc.SourceExpression), SqlProvider.ProviderMode.Sql2000));
         }
     }
     return base.VisitFunctionCall(fc);
 }
 internal virtual SqlExpression VisitFunctionCall(SqlFunctionCall fc) {
     for (int i = 0, n = fc.Arguments.Count; i < n; i++) {
         fc.Arguments[i] = this.VisitExpression(fc.Arguments[i]);
     }
     return fc;
 }
Beispiel #5
0
        internal override SqlExpression DATEPART(string partName, SqlExpression expr)
        {
            var           args = new[] { expr };
            var           s    = expr.SourceExpression;
            SqlExpression arg;
            IProviderType sqlType = null;
            Type          clrType = typeof(int);

            sqlType = TypeProvider.From(typeof(string));
            switch (partName.ToUpper())
            {
            case "HOUR":
                arg = ValueFromObject("HH24", true, s);
                break;

            case "MINUTE":
                arg = ValueFromObject("MI", true, s);
                break;

            case "SECOND":
                arg = ValueFromObject("SS", true, s);
                break;

            case "DAY":
                args = new[] { VariableFromName("DAY FROM", s), expr };
                return(new SqlFunctionCall(clrType, sqlType, "EXTRACT", args, s)
                {
                    Comma = false
                });

            case "MONTH":
                args = new[] { VariableFromName("MONTH FROM", s), expr };
                return(new SqlFunctionCall(clrType, sqlType, "EXTRACT", args, s)
                {
                    Comma = false
                });

            case "YEAR":
                args = new[] { VariableFromName("YEAR FROM", s), expr };
                return(new SqlFunctionCall(clrType, sqlType, "EXTRACT", args, s)
                {
                    Comma = false
                });

            case "DAYOFWEEK":
                clrType = typeof(DayOfWeek);
                sqlType = TypeProvider.From(typeof(int));
                arg     = ValueFromObject("D", true, s);
                var func = new SqlFunctionCall(clrType, sqlType, "TO_CHAR", new[] { expr, arg }, s);
                return(new SqlBinary(SqlNodeType.Sub, clrType, sqlType, func, ValueFromObject(1, s)));

            case "DAYOFYEAR":
                arg = ValueFromObject("DDD", true, s);
                break;

            case "TIMEOFDAY":
                arg = ValueFromObject("DDD", true, s);
                break;

            default:
                throw SqlClient.Error.MethodHasNoSupportConversionToSql(partName);
            }
            return(new SqlFunctionCall(clrType, sqlType, "TO_CHAR", new[] { expr, arg }, s));
        }
 internal abstract ProviderType ReturnTypeOfFunction(SqlFunctionCall functionCall);
Beispiel #7
0
        /// <inheritdoc/>
        public override void Visit(SqlFunctionCall node)
        {
            switch (node.FunctionType)
            {
            case SqlFunctionType.Truncate:
                var argument = node.Arguments[0];
                SqlDml.FunctionCall("TRUNCATE", argument, SqlDml.Literal(0)).AcceptVisitor(this);
                return;

            case SqlFunctionType.Concat:
                var exprs = new SqlExpression[node.Arguments.Count];
                node.Arguments.CopyTo(exprs, 0);
                Visit(SqlDml.Concat(exprs));
                return;

            case SqlFunctionType.CharLength:
                SqlDml.FunctionCall(translator.Translate(SqlFunctionType.CharLength), node.Arguments[0]).AcceptVisitor(this);
                //          SqlDml.CharLength(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.PadLeft:
            case SqlFunctionType.PadRight:
                SqlHelper.GenericPad(node).AcceptVisitor(this);
                return;

            case SqlFunctionType.Rand:
                SqlDml.FunctionCall(translator.Translate(SqlFunctionType.Rand)).AcceptVisitor(this);
                return;

            case SqlFunctionType.Square:
                SqlDml.Power(node.Arguments[0], 2).AcceptVisitor(this);
                return;

            case SqlFunctionType.IntervalToMilliseconds:
                Visit(CastToLong(node.Arguments[0]) / NanosecondsPerMillisecond);
                return;

            case SqlFunctionType.IntervalConstruct:
            case SqlFunctionType.IntervalToNanoseconds:
                Visit(CastToLong(node.Arguments[0]));
                return;

            case SqlFunctionType.DateTimeAddMonths:
                Visit(DateAddMonth(node.Arguments[0], node.Arguments[1]));
                return;

            case SqlFunctionType.DateTimeAddYears:
                Visit(DateAddYear(node.Arguments[0], node.Arguments[1]));
                return;

            case SqlFunctionType.DateTimeConstruct:
                Visit(DateAddDay(DateAddMonth(DateAddYear(SqlDml.Literal(new DateTime(2001, 1, 1)),
                                                          node.Arguments[0] - 2001),
                                              node.Arguments[1] - 1),
                                 node.Arguments[2] - 1));
                return;

            case SqlFunctionType.DateTimeToStringIso:
                Visit(DateTimeToStringIso(node.Arguments[0]));
                return;
            }

            base.Visit(node);
        }
 internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc) {
     if (fc.Name.Contains(".")) {
         // Assume UDF -- bracket the name.
         this.WriteName(fc.Name);
     } else {
         // No ".", so we assume it's a system function name and leave it alone.
         sb.Append(fc.Name);
     }
     
     sb.Append("(");
     for (int i = 0, n = fc.Arguments.Count; i < n; i++) {
         if (i > 0)
             sb.Append(", ");
         this.Visit(fc.Arguments[i]);
     }
     sb.Append(")");
     return fc;
 }
Beispiel #9
0
        internal static bool AreEqual(SqlNode node1, SqlNode node2)
        {
            if (node1 == node2)
            {
                return(true);
            }
            if ((node1 != null) && (node2 != null))
            {
                if (node1.NodeType == SqlNodeType.SimpleCase)
                {
                    node1 = UnwrapTrivialCaseExpression((SqlSimpleCase)node1);
                }
                if (node2.NodeType == SqlNodeType.SimpleCase)
                {
                    node2 = UnwrapTrivialCaseExpression((SqlSimpleCase)node2);
                }
                if (node1.NodeType != node2.NodeType)
                {
                    if (node1.NodeType == SqlNodeType.ExprSet)
                    {
                        SqlExprSet set   = (SqlExprSet)node1;
                        int        num   = 0;
                        int        count = set.Expressions.Count;
                        while (num < count)
                        {
                            if (AreEqual(set.Expressions[num], node2))
                            {
                                return(true);
                            }
                            num++;
                        }
                    }
                    else if (node2.NodeType == SqlNodeType.ExprSet)
                    {
                        SqlExprSet set2 = (SqlExprSet)node2;
                        int        num3 = 0;
                        int        num4 = set2.Expressions.Count;
                        while (num3 < num4)
                        {
                            if (AreEqual(node1, set2.Expressions[num3]))
                            {
                                return(true);
                            }
                            num3++;
                        }
                    }
                    return(false);
                }
                if (node1.Equals(node2))
                {
                    return(true);
                }
                switch (node1.NodeType)
                {
                case SqlNodeType.Add:
                case SqlNodeType.And:
                case SqlNodeType.BitAnd:
                case SqlNodeType.BitOr:
                case SqlNodeType.BitXor:
                case SqlNodeType.Concat:
                case SqlNodeType.Div:
                case SqlNodeType.EQ:
                case SqlNodeType.EQ2V:
                case SqlNodeType.LE:
                case SqlNodeType.LT:
                case SqlNodeType.GE:
                case SqlNodeType.GT:
                case SqlNodeType.Mod:
                case SqlNodeType.Mul:
                case SqlNodeType.NE:
                case SqlNodeType.NE2V:
                case SqlNodeType.Or:
                case SqlNodeType.Sub:
                {
                    SqlBinary binary  = (SqlBinary)node1;
                    SqlBinary binary2 = (SqlBinary)node2;
                    if (!AreEqual(binary.Left, binary2.Left))
                    {
                        return(false);
                    }
                    return(AreEqual(binary.Right, binary2.Right));
                }

                case SqlNodeType.Alias:
                    return(AreEqual(((SqlAlias)node1).Node, ((SqlAlias)node2).Node));

                case SqlNodeType.AliasRef:
                    return(AreEqual(((SqlAliasRef)node1).Alias, ((SqlAliasRef)node2).Alias));

                case SqlNodeType.Avg:
                case SqlNodeType.BitNot:
                case SqlNodeType.ClrLength:
                case SqlNodeType.Count:
                case SqlNodeType.Covar:
                case SqlNodeType.IsNotNull:
                case SqlNodeType.IsNull:
                case SqlNodeType.Max:
                case SqlNodeType.Min:
                case SqlNodeType.Negate:
                case SqlNodeType.Not:
                case SqlNodeType.Not2V:
                case SqlNodeType.OuterJoinedValue:
                case SqlNodeType.Stddev:
                case SqlNodeType.Sum:
                case SqlNodeType.ValueOf:
                    return(AreEqual(((SqlUnary)node1).Operand, ((SqlUnary)node2).Operand));

                case SqlNodeType.Between:
                {
                    SqlBetween between  = (SqlBetween)node1;
                    SqlBetween between2 = (SqlBetween)node1;
                    if (!AreEqual(between.Expression, between2.Expression) ||
                        !AreEqual(between.Start, between2.Start))
                    {
                        return(false);
                    }
                    return(AreEqual(between.End, between2.End));
                }

                case SqlNodeType.Cast:
                case SqlNodeType.Convert:
                case SqlNodeType.Treat:
                {
                    SqlUnary unary  = (SqlUnary)node1;
                    SqlUnary unary2 = (SqlUnary)node2;
                    if ((unary.ClrType != unary2.ClrType) || !(unary.SqlType == unary2.SqlType))
                    {
                        return(false);
                    }
                    return(AreEqual(unary.Operand, unary2.Operand));
                }

                case SqlNodeType.ClientCase:
                {
                    SqlClientCase case5 = (SqlClientCase)node1;
                    SqlClientCase case6 = (SqlClientCase)node2;
                    if (case5.Whens.Count == case6.Whens.Count)
                    {
                        int num9  = 0;
                        int num10 = case5.Whens.Count;
                        while (num9 < num10)
                        {
                            if (!AreEqual(case5.Whens[num9].Match, case6.Whens[num9].Match) ||
                                !AreEqual(case5.Whens[num9].Value, case6.Whens[num9].Value))
                            {
                                return(false);
                            }
                            num9++;
                        }
                        return(true);
                    }
                    return(false);
                }

                case SqlNodeType.Column:
                {
                    SqlColumn column  = (SqlColumn)node1;
                    SqlColumn column2 = (SqlColumn)node2;
                    return((column == column2) ||
                           (((column.Expression != null) && (column2.Expression != null)) &&
                            AreEqual(column.Expression, column2.Expression)));
                }

                case SqlNodeType.ColumnRef:
                {
                    SqlColumnRef cref = (SqlColumnRef)node1;
                    SqlColumnRef ref3 = (SqlColumnRef)node2;
                    return(GetBaseColumn(cref) == GetBaseColumn(ref3));
                }

                case SqlNodeType.DiscriminatedType:
                {
                    SqlDiscriminatedType type  = (SqlDiscriminatedType)node1;
                    SqlDiscriminatedType type2 = (SqlDiscriminatedType)node2;
                    return(AreEqual(type.Discriminator, type2.Discriminator));
                }

                case SqlNodeType.ExprSet:
                {
                    SqlExprSet set3 = (SqlExprSet)node1;
                    SqlExprSet set4 = (SqlExprSet)node2;
                    if (set3.Expressions.Count == set4.Expressions.Count)
                    {
                        int num17 = 0;
                        int num18 = set3.Expressions.Count;
                        while (num17 < num18)
                        {
                            if (!AreEqual(set3.Expressions[num17], set4.Expressions[num17]))
                            {
                                return(false);
                            }
                            num17++;
                        }
                        return(true);
                    }
                    return(false);
                }

                case SqlNodeType.FunctionCall:
                {
                    SqlFunctionCall call  = (SqlFunctionCall)node1;
                    SqlFunctionCall call2 = (SqlFunctionCall)node2;
                    if (!(call.Name != call2.Name))
                    {
                        if (call.Arguments.Count != call2.Arguments.Count)
                        {
                            return(false);
                        }
                        int num13 = 0;
                        int num14 = call.Arguments.Count;
                        while (num13 < num14)
                        {
                            if (!AreEqual(call.Arguments[num13], call2.Arguments[num13]))
                            {
                                return(false);
                            }
                            num13++;
                        }
                        return(true);
                    }
                    return(false);
                }

                case SqlNodeType.Link:
                {
                    SqlLink link  = (SqlLink)node1;
                    SqlLink link2 = (SqlLink)node2;
                    if (MetaPosition.AreSameMember(link.Member.Member, link2.Member.Member))
                    {
                        if (!AreEqual(link.Expansion, link2.Expansion))
                        {
                            return(false);
                        }
                        if (link.KeyExpressions.Count != link2.KeyExpressions.Count)
                        {
                            return(false);
                        }
                        int num15 = 0;
                        int num16 = link.KeyExpressions.Count;
                        while (num15 < num16)
                        {
                            if (!AreEqual(link.KeyExpressions[num15], link2.KeyExpressions[num15]))
                            {
                                return(false);
                            }
                            num15++;
                        }
                        return(true);
                    }
                    return(false);
                }

                case SqlNodeType.Like:
                {
                    SqlLike like  = (SqlLike)node1;
                    SqlLike like2 = (SqlLike)node2;
                    if (!AreEqual(like.Expression, like2.Expression) || !AreEqual(like.Pattern, like2.Pattern))
                    {
                        return(false);
                    }
                    return(AreEqual(like.Escape, like2.Escape));
                }

                case SqlNodeType.Member:
                    if (((SqlMember)node1).Member != ((SqlMember)node2).Member)
                    {
                        return(false);
                    }
                    return(AreEqual(((SqlMember)node1).Expression, ((SqlMember)node2).Expression));

                case SqlNodeType.OptionalValue:
                {
                    SqlOptionalValue value2 = (SqlOptionalValue)node1;
                    SqlOptionalValue value3 = (SqlOptionalValue)node2;
                    return(AreEqual(value2.Value, value3.Value));
                }

                case SqlNodeType.Parameter:
                    return(node1 == node2);

                case SqlNodeType.SearchedCase:
                {
                    SqlSearchedCase case3 = (SqlSearchedCase)node1;
                    SqlSearchedCase case4 = (SqlSearchedCase)node2;
                    if (case3.Whens.Count == case4.Whens.Count)
                    {
                        int num7 = 0;
                        int num8 = case3.Whens.Count;
                        while (num7 < num8)
                        {
                            if (!AreEqual(case3.Whens[num7].Match, case4.Whens[num7].Match) ||
                                !AreEqual(case3.Whens[num7].Value, case4.Whens[num7].Value))
                            {
                                return(false);
                            }
                            num7++;
                        }
                        return(AreEqual(case3.Else, case4.Else));
                    }
                    return(false);
                }

                case SqlNodeType.SimpleCase:
                {
                    SqlSimpleCase case7 = (SqlSimpleCase)node1;
                    SqlSimpleCase case8 = (SqlSimpleCase)node2;
                    if (case7.Whens.Count == case8.Whens.Count)
                    {
                        int num11 = 0;
                        int num12 = case7.Whens.Count;
                        while (num11 < num12)
                        {
                            if (!AreEqual(case7.Whens[num11].Match, case8.Whens[num11].Match) ||
                                !AreEqual(case7.Whens[num11].Value, case8.Whens[num11].Value))
                            {
                                return(false);
                            }
                            num11++;
                        }
                        return(true);
                    }
                    return(false);
                }

                case SqlNodeType.Table:
                    return(((SqlTable)node1).MetaTable == ((SqlTable)node2).MetaTable);

                case SqlNodeType.TypeCase:
                {
                    SqlTypeCase @case = (SqlTypeCase)node1;
                    SqlTypeCase case2 = (SqlTypeCase)node2;
                    if (AreEqual(@case.Discriminator, case2.Discriminator))
                    {
                        if (@case.Whens.Count != case2.Whens.Count)
                        {
                            return(false);
                        }
                        int num5 = 0;
                        int num6 = @case.Whens.Count;
                        while (num5 < num6)
                        {
                            if (!AreEqual(@case.Whens[num5].Match, case2.Whens[num5].Match))
                            {
                                return(false);
                            }
                            if (!AreEqual(@case.Whens[num5].TypeBinding, case2.Whens[num5].TypeBinding))
                            {
                                return(false);
                            }
                            num5++;
                        }
                        return(true);
                    }
                    return(false);
                }

                case SqlNodeType.Variable:
                {
                    SqlVariable variable  = (SqlVariable)node1;
                    SqlVariable variable2 = (SqlVariable)node2;
                    return(variable.Name == variable2.Name);
                }

                case SqlNodeType.Value:
                    return(object.Equals(((SqlValue)node1).Value, ((SqlValue)node2).Value));
                }
            }
            return(false);
        }
Beispiel #10
0
            //取消函数括号,即Limit(int,int) -> Limit int, int
            internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc)
            {
                switch (fc.Name)
                {
                case "Limit":
                {
                    Debug.Assert(fc.Arguments.Count == 2);
                    bool limited = false;
                    if (!(fc.Arguments[0] is SqlValue) || (int)((SqlValue)fc.Arguments[0]).Value > 0)
                    {
                        sb.Append("LIMIT ");
                        this.Visit(fc.Arguments[0]);
                        sb.Append(" ");
                        limited = true;
                    }

                    if (!(fc.Arguments[1] is SqlValue) || (int)((SqlValue)fc.Arguments[1]).Value > 0)
                    {
                        if (!limited)
                        {
                            sb.Append("LIMIT 18446744073709551615 ");
                        }

                        sb.Append("OFFSET ");
                        this.Visit(fc.Arguments[1]);
                    }

                    return(fc);
                }

                //case "DATE_FORMAT":
                //    sb.Append("CAST(");
                //    var result = base.VisitFunctionCall(fc);
                //    sb.Append(" AS SIGNED)");
                //    return result;
                //case "Date":
                //    sb.Append("Date(");
                //    Visit(fc.Arguments[0]);
                //    sb.Append(")");
                //    return fc;
                case "AddDays":
                case "AddHours":
                case "AddMinutes":
                case "AddMonths":
                case "AddSeconds":
                case "AddYears":
                    sb.Append("DATE_ADD(");
                    Visit(fc.Arguments[0]);
                    sb.Append(", INTERVAL ");
                    Visit(fc.Arguments[1]);
                    sb.Append(" ");
                    sb.Append(((SqlValue)fc.Arguments[2]).Value);
                    sb.Append(")");
                    return(fc);
                    //case "AddHours":
                    //    sb.Append("DATE_ADD(");
                    //    Visit(fc.Arguments[0]);
                    //    sb.Append(", INTERVAL ");
                    //    Visit(fc.Arguments[1]);
                    //    sb.Append(" DAY)");
                    //    return fc;
                }
                return(base.VisitFunctionCall(fc));
            }
 protected virtual SqlExpression VisitFunction(SqlFunctionCall expr)
 {
     return expr;
 }
Beispiel #12
0
        public override void Visit(SqlFunctionCall node)
        {
            switch (node.FunctionType)
            {
            case SqlFunctionType.PadLeft:
            case SqlFunctionType.PadRight:
                SqlHelper.GenericPad(node).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetAddYears:
            case SqlFunctionType.DateTimeAddYears:
                DateTimeAddComponent(node.Arguments[0], node.Arguments[1], true).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetAddMonths:
            case SqlFunctionType.DateTimeAddMonths:
                DateTimeAddComponent(node.Arguments[0], node.Arguments[1], false).AcceptVisitor(this);
                return;

            case SqlFunctionType.IntervalConstruct:
                IntervalConstruct(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeConstruct:
                DateTimeConstruct(node.Arguments[0], node.Arguments[1], node.Arguments[2]).AcceptVisitor(this);
                return;

            case SqlFunctionType.IntervalAbs:
                SqlHelper.IntervalAbs(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.IntervalToMilliseconds:
                SqlHelper.IntervalToMilliseconds(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.IntervalToNanoseconds:
                SqlHelper.IntervalToNanoseconds(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.Position:
                Position(node.Arguments[0], node.Arguments[1]).AcceptVisitor(this);
                return;

            case SqlFunctionType.CharLength:
                SqlDml.Coalesce(SqlDml.FunctionCall("LENGTH", node.Arguments[0]), 0).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeToStringIso:
                DateTimeToStringIso(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetConstruct:
                DateTimeOffsetConstruct(node.Arguments[0], node.Arguments[1]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetTimeOfDay:
                DateTimeOffsetTimeOfDay(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetToLocalTime:
                DateTimeOffsetToLocalTime(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeToDateTimeOffset:
                DateTimeToDateTimeOffset(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetToUtcTime:
                DateTimeOffsetToUtcTime(node.Arguments[0]).AcceptVisitor(this);
                return;

            default:
                base.Visit(node);
                return;
            }
        }
Beispiel #13
0
            internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc)
            {
                switch (fc.Name)
                {
                case "SkipTake":
                {
                    Debug.Assert(fc.Arguments.Count == 2);
                    var skip = (int)((SqlValue)fc.Arguments[0]).Value;
                    var take = (int)((SqlValue)fc.Arguments[1]).Value;
                    var str  = string.Empty;
                    if (take >= 0)
                    {
                        sb.Append("FIRST ");
                        sb.Append(take);
                        str = " ";
                    }
                    if (skip >= 0)
                    {
                        sb.Append(str);
                        sb.Append("SKIP ");
                        sb.Append(skip);
                    }
                    return(fc);
                }

                case "LEN":
                case "DATALENGTH":
                    sb.Append("OCTET_LENGTH( ");
                    Visit(fc.Arguments[0]);
                    sb.Append(" ) ");
                    return(fc);

                case "TrimEnd":
                    sb.Append("TRIM( TRAILING From ");
                    Visit(fc.Arguments[0]);
                    sb.Append(" )");
                    return(fc);

                case "TrimStart":
                    sb.Append("TRIM( LEADING From ");
                    Visit(fc.Arguments[0]);
                    sb.Append(" )");
                    return(fc);

                case "SUBSTRING":
                    sb.Append("SUBSTRING( ");
                    Visit(fc.Arguments[0]);
                    sb.Append(" FROM ");
                    Visit(fc.Arguments[1]);
                    if (fc.Arguments.Count > 2)
                    {
                        sb.Append(" FOR ");
                        Visit(fc.Arguments[2]);
                    }
                    sb.Append(")");
                    return(fc);

                case "Date":
                    sb.Append("CAST (");
                    Visit(fc.Arguments[0]);
                    sb.Append(" AS DATE)");
                    return(fc);
                }
                //if (fc.Name.StartsWith("GEN_ID"))
                //{
                //    sb.Append(fc.Name);
                //    sb.Append(" FROM RDB$DATABASE");
                //    return fc;
                //}
                return(base.VisitFunctionCall(fc));
            }
            protected override SqlExpression VisitFunction(SqlFunctionCall expr)
            {
                if (expr.Name.Contains("."))
                    WriteName(expr.Name);
                else
                    _builder.Append(expr.Name);
                
                _builder.Append("(");

                for (int i = 0; i < expr.Arguments.Expressions.Count; ++i)
                {
                    if (i > 0)
                        _builder.Append(", ");

                    Visit(expr.Arguments.Expressions[i]);
                }
                _builder.Append(")");
                
                return expr;
            }
        internal override ProviderType ReturnTypeOfFunction(SqlFunctionCall functionCall)
        {
            var argumentTypes = this.GetArgumentTypes(functionCall);

            SqlType arg0 = (SqlType)argumentTypes[0];
            SqlType arg1 = argumentTypes.Length > 1 ? (SqlType)argumentTypes[1] : (SqlType)null;

            switch (functionCall.Name)
            {
            case "LEN":
            case "DATALENGTH":
                switch (arg0.SqlDbType)
                {
                case SqlDbType.NVarChar:
                case SqlDbType.VarChar:
                case SqlDbType.VarBinary:
                    if (arg0.IsLargeType)
                    {
                        return(SqlTypeSystem.Create(SqlDbType.BigInt));
                    }
                    else
                    {
                        return(SqlTypeSystem.Create(SqlDbType.Int));
                    }

                default:
                    return(SqlTypeSystem.Create(SqlDbType.Int));
                }

            case "ABS":
            case "SIGN":
            case "ROUND":
            case "CEILING":
            case "FLOOR":
            case "POWER":
                switch (arg0.SqlDbType)
                {
                case SqlDbType.TinyInt:
                case SqlDbType.Int:
                case SqlDbType.SmallInt:
                    return(SqlTypeSystem.Create(SqlDbType.Int));

                case SqlDbType.Float:
                case SqlDbType.Real:
                    return(SqlTypeSystem.Create(SqlDbType.Float));

                default:
                    return(arg0);
                }

            case "PATINDEX":
            case "CHARINDEX":
                if (arg1.IsLargeType)
                {
                    return(SqlTypeSystem.Create(SqlDbType.BigInt));
                }
                return(SqlTypeSystem.Create(SqlDbType.Int));

            case "SUBSTRING":
                if (functionCall.Arguments[2].NodeType == SqlNodeType.Value)
                {
                    SqlValue val = (SqlValue)functionCall.Arguments[2];

                    if (val.Value is int)
                    {
                        switch (arg0.SqlDbType)
                        {
                        case SqlDbType.NVarChar:
                        case SqlDbType.NChar:
                        case SqlDbType.VarChar:
                        case SqlDbType.Char:
                            return(SqlTypeSystem.Create(arg0.SqlDbType, (int)val.Value));

                        default:
                            return(null);
                        }
                    }
                }
                switch (arg0.SqlDbType)
                {
                case SqlDbType.NVarChar:
                case SqlDbType.NChar:
                    return(SqlTypeSystem.Create(SqlDbType.NVarChar));

                case SqlDbType.VarChar:
                case SqlDbType.Char:
                    return(SqlTypeSystem.Create(SqlDbType.VarChar));

                default:
                    return(null);
                }

            case "STUFF":
                // if the stuff call is an insertion  and is strictly additive
                // (no deletion of characters) the return type is the same as
                // a concatenation
                if (functionCall.Arguments.Count == 4)
                {
                    SqlValue delLength = functionCall.Arguments[2] as SqlValue;
                    if (delLength != null && (int)delLength.Value == 0)
                    {
                        return(PredictTypeForBinary(SqlNodeType.Concat,
                                                    functionCall.Arguments[0].SqlType, functionCall.Arguments[3].SqlType));
                    }
                }
                return(null);

            case "LOWER":
            case "UPPER":
            case "RTRIM":
            case "LTRIM":
            case "INSERT":
            case "REPLACE":
            case "LEFT":
            case "RIGHT":
            case "REVERSE":
                return(arg0);

            default:
                return(null);
            }
        }
 internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc) {
     SqlExpression[] args = new SqlExpression[fc.Arguments.Count];
     for (int i = 0, n = fc.Arguments.Count; i < n; i++) {
         args[i] = this.VisitExpression(fc.Arguments[i]);
     }
     return new SqlFunctionCall(fc.ClrType, fc.SqlType, fc.Name, args, fc.SourceExpression);
 }
        /// <inheritdoc/>
        public override void Visit(SqlFunctionCall node)
        {
            switch (node.FunctionType)
            {
            case SqlFunctionType.CharLength:
                (SqlDml.FunctionCall("DATALENGTH", node.Arguments) / 2).AcceptVisitor(this);
                return;

            case SqlFunctionType.PadLeft:
            case SqlFunctionType.PadRight:
                GenericPad(node).AcceptVisitor(this);
                return;

            case SqlFunctionType.Round:
                // Round should always be called with 2 arguments
                if (node.Arguments.Count == 1)
                {
                    Visit(SqlDml.FunctionCall(
                              translator.Translate(SqlFunctionType.Round),
                              node.Arguments[0],
                              SqlDml.Literal(0)));
                    return;
                }
                break;

            case SqlFunctionType.Truncate:
                // Truncate is implemented as round(arg, 0, 1) call in MSSQL.
                // It's stupid, isn't it?
                Visit(SqlDml.FunctionCall(
                          translator.Translate(SqlFunctionType.Round),
                          node.Arguments[0],
                          SqlDml.Literal(0),
                          SqlDml.Literal(1)));
                return;

            case SqlFunctionType.Substring:
                if (node.Arguments.Count == 2)
                {
                    node = SqlDml.Substring(node.Arguments[0], node.Arguments[1]);
                    SqlExpression len = SqlDml.CharLength(node.Arguments[0]);
                    node.Arguments.Add(len);
                    Visit(node);
                    return;
                }
                break;

            case SqlFunctionType.IntervalToMilliseconds:
                Visit(CastToLong(node.Arguments[0]) / NanosecondsPerMillisecond);
                return;

            case SqlFunctionType.IntervalConstruct:
            case SqlFunctionType.IntervalToNanoseconds:
                Visit(CastToLong(node.Arguments[0]));
                return;

            case SqlFunctionType.DateTimeAddMonths:
                Visit(DateAddMonth(node.Arguments[0], node.Arguments[1]));
                return;

            case SqlFunctionType.DateTimeAddYears:
                Visit(DateAddYear(node.Arguments[0], node.Arguments[1]));
                return;

            case SqlFunctionType.DateTimeTruncate:
                DateTimeTruncate(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeConstruct:
                Visit(DateAddDay(DateAddMonth(DateAddYear(SqlDml.Literal(new DateTime(2001, 1, 1)),
                                                          node.Arguments[0] - 2001),
                                              node.Arguments[1] - 1),
                                 node.Arguments[2] - 1));
                return;

            case SqlFunctionType.DateTimeToStringIso:
                Visit(DateTimeToStringIso(node.Arguments[0]));
                return;
            }

            base.Visit(node);
        }
 internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc) {
     for (int i = 0, n = fc.Arguments.Count; i < n; i++) {
         fc.Arguments[i] = this.VisitExpression(fc.Arguments[i]);
     }
     if (fc.Arguments.Count > 0) {
         ProviderType oldType = fc.Arguments[0].SqlType;
         // if this has a real argument (not e.g. the symbol "DAY" in DATEDIFF(DAY,...))
         if (oldType != null) {
             ProviderType newType = this.typeProvider.ReturnTypeOfFunction(fc);
             if (newType != null) {
                 fc.SetSqlType(newType);
             }
         }
     }
     return fc;
 }
Beispiel #19
0
        protected override SqlNode VisitMethodCall(MethodCallExpression mc)
        {
            //´¦Àí×Ö·û´®º¯Êý¡£
            if (mc.Object != null && mc.Object.Type == typeof(string))
            {
                switch (mc.Method.Name)
                {
                case "Trim":
                {
                    var clrType     = mc.Method.ReturnType;
                    var expressions = new[] { VisitExpression(mc.Object) };
                    var node        = new SqlFunctionCall(clrType, typeProvider.From(clrType), "Trim", expressions,
                                                          dominatingExpression);
                    return(node);
                }

                case "TrimStart":
                {
                    var clrType     = mc.Method.ReturnType;
                    var expressions = new[] { VisitExpression(mc.Object) };
                    var node        = new SqlFunctionCall(clrType, typeProvider.From(clrType), "LTrim", expressions,
                                                          dominatingExpression);
                    return(node);
                }

                case "TrimEnd":
                {
                    var clrType     = mc.Method.ReturnType;
                    var expressions = new[] { VisitExpression(mc.Object) };
                    var node        = new SqlFunctionCall(clrType, typeProvider.From(clrType), "RTrim", expressions,
                                                          dominatingExpression);
                    return(node);
                }

                case "Remove":
                {
                    var clrType = mc.Method.ReturnType;
                    Debug.Assert(clrType == typeof(string));
                    var startIndex = (int)((ConstantExpression)mc.Arguments[0]).Value;

                    var arg1 = VisitExpression(mc.Object);
                    var arg2 = VisitExpression(Expression.Constant(1));
                    var arg3 = VisitExpression(Expression.Constant(startIndex));
                    var left = new SqlFunctionCall(typeof(string), typeProvider.From(typeof(string)), "SUBSTR",
                                                   new[] { arg1, arg2, arg3 }, dominatingExpression);

                    if (mc.Arguments.Count == 2)
                    {
                        var count = (int)((ConstantExpression)mc.Arguments[1]).Value;
                        arg2 = VisitExpression(Expression.Constant(startIndex + count));
                        SqlExpression right = new SqlFunctionCall(typeof(string), typeProvider.From(typeof(string)),
                                                                  "SUBSTR", new[] { arg1, arg2 }, dominatingExpression);
                        var result = new SqlBinary(SqlNodeType.Add, clrType, typeProvider.From(clrType), left, right);
                        return(result);
                    }
                    Debug.Assert(mc.Arguments.Count == 1);
                    return(left);
                }

                case "Replace":
                {
                    var clrType = mc.Method.ReturnType;
                    var sqlType = typeProvider.From(clrType);
                    Debug.Assert(clrType == typeof(string));
                    Debug.Assert(mc.Arguments.Count == 2);

                    var sourceObject = VisitExpression(mc.Object);
                    var oldValue     = VisitExpression(mc.Arguments[0]);
                    var newValue     = VisitExpression(mc.Arguments[1]);

                    var result = new SqlFunctionCall(clrType, sqlType, "Replace",
                                                     new[] { sourceObject, oldValue, newValue }, dominatingExpression);
                    return(result);
                }

                default:
                    return(base.VisitMethodCall(mc));
                }
            }
            return(base.VisitMethodCall(mc));
        }