Exemple #1
0
        private static FastAccessList <object> DeserializeReferenceTracking(BinaryReader input)
        {
            var bf = SerializationHelper.DefaultFormatter;
            var referenceTracking = new FastAccessList <object>();

            var nbRef = input.ReadInt32();

            for (var i = 0; i < nbRef; i++)
            {
                var tag  = input.ReadInt32();
                var type = SerializationHelper.TagToType[tag];

                if (type == typeof(SqlVariable))
                {
                    referenceTracking.Add(SqlVariable.Deserialize(input));
                }
                else if (type == typeof(TableMetadata))
                {
                    referenceTracking.Add(TableMetadata.Deserialize(input));
                }
                else
                {
                    referenceTracking.Add(bf.Deserialize(input.BaseStream));
                }
            }

            return(referenceTracking);
        }
        protected override SqlExpression GetInsertIdentityExpression(MetaDataMember member)
        {
            var exp = new SqlVariable(member.Type, typeProvider.From(member.Type),
                                      OracleSqlBuilder.GetSequenceName(member, translator.Provider.SqlIdentifier) + ".NEXTVAL", dominatingExpression);

            return(exp);
        }
        protected override SqlExpression GetInsertIdentityExpression(MetaDataMember member)
        {
            var exp = new SqlVariable(member.Type, typeProvider.From(member.Type),
                                      "NEXT VALUE FOR " + FirebirdSqlBuilder.GetSequenceName(member), dominatingExpression);

            return(exp);
        }
        public void SqlWhileCloneTest()
        {
            SqlVariable i = SqlDml.Variable("i", SqlType.Int32);
            SqlWhile    w = SqlDml.While(i <= 1000);
            SqlBatch    b = SqlDml.Batch();

            b.Add(SqlDml.Assign(i, i + 1));
            SqlTableRef t = SqlDml.TableRef(table1);
            SqlSelect   s = SqlDml.Select(t);

            s.Columns.Add(t["Name"]);
            s.Where = t[0] == i;
            SqlIf f = SqlDml.If(SqlDml.SubQuery(s) == "Unkown", SqlDml.Break, SqlDml.Continue);

            b.Add(f);
            w.Statement = b;

            SqlWhile wClone = (SqlWhile)w.Clone();

            Assert.AreNotEqual(w, wClone);
            Assert.AreEqual(w.NodeType, wClone.NodeType);
            Assert.AreNotEqual(w.Condition, wClone.Condition);
            Assert.AreEqual(w.Condition.NodeType, wClone.Condition.NodeType);
            Assert.AreNotEqual(w.Statement, wClone.Statement);
            Assert.AreEqual(w.Statement.NodeType, wClone.Statement.NodeType);
        }
Exemple #5
0
        private InsertStep CreateExecutionStep(TableIdentifier tiSource, TableIdentifier tiDestination, TableMetadata table, object[] destinationRow, int level)
        {
            var step = new InsertStep
            {
                StepId           = _nextStepId++,
                SourceTable      = tiSource,
                DestinationTable = tiDestination,
                TableMetadata    = table,
                Depth            = level
            };

            //Renseignement des variables à générer
            foreach (var col in table.ColumnsDefinition)
            {
                var colName = col.Name;

                var valueToGenerate = ((col.IsPrimary && !col.IsAutoIncrement) || col.IsUniqueKey) && !col.IsForeignKey;
                var pkToGenerate    = col.IsPrimary && col.IsAutoIncrement;

                if (valueToGenerate | pkToGenerate)
                {
                    var sqlVar = new SqlVariable(_nextVariableId++);
                    step.Variables.Add(sqlVar);

                    var pos = table.ColumnsDefinition.IndexOf(c => c.Name == colName);
                    destinationRow[pos] = sqlVar;
                }
            }

            step.Datarow = destinationRow;
            AddInsertStep(step);
            return(step);
        }
        public void SqlVariableCloneTest()
        {
            SqlVariable v      = SqlDml.Variable("v", SqlType.Int32);
            SqlVariable vClone = (SqlVariable)v.Clone();

            Assert.AreNotEqual(v, vClone);
            Assert.AreEqual(v.NodeType, vClone.NodeType);
            Assert.AreEqual(v.Name, vClone.Name);
        }
        public void AddTest()
        {
            SqlLiteral <int> l1 = SqlDml.Literal(1);
            SqlLiteral <int> l2 = SqlDml.Literal(2);
            SqlBinary        b  = l1 + l2;

            Assert.AreEqual(b.NodeType, SqlNodeType.Add);

            b = b - ~l1;
            Assert.AreEqual(b.NodeType, SqlNodeType.Subtract);
            Assert.AreEqual(b.Right.NodeType, SqlNodeType.BitNot);

            SqlSelect s = SqlDml.Select();

            s.Columns.Add(1, "id");
            b = b / s;
            Assert.AreEqual(b.NodeType, SqlNodeType.Divide);
            Assert.AreEqual(b.Right.NodeType, SqlNodeType.SubSelect);

            SqlCast c = SqlDml.Cast(l1, SqlType.Decimal);

            Assert.AreEqual(c.NodeType, SqlNodeType.Cast);

            SqlFunctionCall l = SqlDml.CharLength(SqlDml.Literal("name"));

            b = c % l;
            Assert.AreEqual(b.NodeType, SqlNodeType.Modulo);
            Assert.AreEqual(b.Right.NodeType, SqlNodeType.FunctionCall);

            b = l1 * (-l2);
            Assert.AreEqual(b.NodeType, SqlNodeType.Multiply);
            Assert.AreEqual(b.Right.NodeType, SqlNodeType.Negate);

            SqlBatch    batch = SqlDml.Batch();
            SqlVariable v1    = SqlDml.Variable("v1", SqlType.Double);

            batch.Add(v1.Declare());
            batch.Add(SqlDml.Assign(v1, 1.0));
            s = SqlDml.Select();
            s.Columns.Add(b, "value");
            batch.Add(s);
        }
        public void SqlDeclareVariableCloneTest()
        {
            {
                SqlVariable dv      = SqlDml.Variable("v", SqlType.Char, 5);
                SqlVariable dvClone = (SqlVariable)dv.Clone();

                Assert.AreNotEqual(dv, dvClone);
                Assert.AreEqual(dv.NodeType, dvClone.NodeType);
                Assert.IsTrue(dv.Type.Equals(dvClone.Type));
                Assert.AreEqual(dv.Name, dvClone.Name);
            }

            {
                SqlVariable dv      = SqlDml.Variable("v", SqlType.Decimal, 6, 4);
                SqlVariable dvClone = (SqlVariable)dv.Clone();

                Assert.AreNotEqual(dv, dvClone);
                Assert.AreEqual(dv.NodeType, dvClone.NodeType);
                Assert.IsTrue(dv.Type.Equals(dvClone.Type));
                Assert.AreEqual(dv.Name, dvClone.Name);
            }
        }
        public void SqlVariableReplacingTest()
        {
            SqlVariable v          = SqlDml.Variable("vOld", SqlType.Int32);
            SqlVariable vReplacing = SqlDml.Variable("vNew", SqlType.Int32);

            v.ReplaceWith(vReplacing);

            bool passed = false;

            try {
                v.ReplaceWith(1);
            }
            catch
            {
                passed = true;
            }

            Assert.IsTrue(passed);
            Assert.AreNotEqual(v, vReplacing);
            Assert.AreEqual(v.NodeType, vReplacing.NodeType);
            Assert.AreEqual(v.Name, vReplacing.Name);
        }
Exemple #10
0
            internal override SqlExpression TranslateDateTimeBinary(SqlBinary bo)
            {
                bool asNullable      = TypeSystem.IsNullableType(bo.ClrType);
                var  nonNullableType = TypeSystem.GetNonNullableType(bo.Right.ClrType);
                var  nodeType        = bo.NodeType;

                if (nodeType != SqlNodeType.Add)
                {
                    if (nodeType != SqlNodeType.Sub)
                    {
                        return(bo);
                    }
                    if (nonNullableType == typeof(DateTime))
                    {
                        var clrType     = bo.ClrType;
                        var left        = bo.Left;
                        var right       = bo.Right;
                        var expression3 = new SqlVariable(typeof(void), null, "DAY", bo.SourceExpression);
                        var expression4 = new SqlVariable(typeof(void), null, "MILLISECOND", bo.SourceExpression);
                        var expr        = sql.FunctionCall(typeof(int), "DATEDIFF", new[] { expression3, right, left }, bo.SourceExpression);
                        var expression6 = sql.FunctionCall(typeof(DateTime), "DATEADD", new[] { expression3, expr, right }, bo.SourceExpression);
                        var expression7 = sql.FunctionCall(typeof(int), "DATEDIFF", new[] { expression4, expression6, left }, bo.SourceExpression);
                        var expression8 = sql.Multiply(sql.Add(new[] { sql.Multiply(sql.ConvertToBigint(expr), 0x5265c00L), expression7 }), 0x2710L);
                        return(sql.ConvertTo(clrType, expression8));
                    }
                    if (nonNullableType != typeof(TimeSpan))
                    {
                        return(bo);
                    }
                    return(CreateDateTimeFromDateAndTicks(bo.Left, sql.Unary(SqlNodeType.Negate, bo.Right, bo.SourceExpression), bo.SourceExpression, asNullable));
                }
                if (nonNullableType == typeof(TimeSpan))
                {
                    return(CreateDateTimeFromDateAndTicks(bo.Left, bo.Right, bo.SourceExpression, asNullable));
                }
                return(bo);
            }
Exemple #11
0
 private SqlNode ConvertDateToDateTime2(SqlExpression expr) {
     SqlExpression datetime2 = new SqlVariable(expr.ClrType, expr.SqlType, "DATETIME2", expr.SourceExpression);
     return sql.FunctionCall(typeof(DateTime), "CONVERT", new SqlExpression[2] { datetime2, expr }, expr.SourceExpression);
 }
            private SqlExpression TranslateNewDateTimeOffset(SqlNew sox) {
                Expression source = sox.SourceExpression;
                if (sox.ClrType == typeof(DateTimeOffset)) {
                    // DateTimeOffset(DateTime dateTime)
                    // --> CONVERT(DATETIMEOFFSET, @dateTime)
                    if (sox.Args.Count == 1 && sox.Args[0].ClrType == typeof(DateTime)) {
                        return sql.FunctionCall(typeof(DateTimeOffset), "TODATETIMEOFFSET", 
                                                new SqlExpression[2] { sox.Args[0], sql.ValueFromObject(0, false, source) }, 
                                                source);
                    }
                    // DateTimeOffset(DateTime dateTime, TimeSpan timeSpan)
                    // --> DATEADD(DATETIMEOFFSET, @dateTimePart)
                    if (sox.Args.Count == 2 && sox.Args[0].ClrType == typeof(DateTime) && sox.Args[1].ClrType == typeof(TimeSpan)) {
                        return sql.FunctionCall(typeof(DateTimeOffset), "TODATETIMEOFFSET",
                                                new SqlExpression[2] 
                                                { 
                                                    sox.Args[0], 
                                                    sql.ConvertToInt(sql.ConvertToBigint(sql.Divide(sql.ConvertTimeToDouble(sox.Args[1]), TimeSpan.TicksPerMinute)))
                                                },
                                                source);
                    }
                    // DateTimeOffset(year, month, day, hour, minute, second, [millisecond,] timeSpan) 
                    //
                    if (sox.Args.Count >= 7 &&
                        sox.Args[0].ClrType == typeof(int) && sox.Args[1].ClrType == typeof(int) && sox.Args[2].ClrType == typeof(int) &&
                        sox.Args[3].ClrType == typeof(int) && sox.Args[4].ClrType == typeof(int) && sox.Args[5].ClrType == typeof(int)) {

                        SqlExpression char2 = sql.FunctionCall(typeof(void), "NCHAR", new SqlExpression[1] { sql.ValueFromObject(2, false, source) }, source);
                        SqlExpression char4 = sql.FunctionCall(typeof(void), "NCHAR", new SqlExpression[1] { sql.ValueFromObject(4, false, source) }, source);
                        SqlExpression char5 = sql.FunctionCall(typeof(void), "NCHAR", new SqlExpression[1] { sql.ValueFromObject(5, false, source) }, source);

                        // add leading zeros to year by RIGHT(CONVERT(NCHAR(5),10000+@ms),4) 
                        SqlExpression yyRaw = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] {char5,
                                       sql.Add(sql.ValueFromObject(10000, false, source),sox.Args[0])}, source);
                        SqlExpression year = sql.FunctionCall(typeof(string), "RIGHT", new SqlExpression[2] { yyRaw, sql.ValueFromObject(4, false, source) }, source);

                        SqlExpression month = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[1] }, source);
                        SqlExpression day = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[2] }, source);

                        SqlExpression hour = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[3] }, source);
                        SqlExpression minute = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[4] }, source);
                        SqlExpression second = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[5] }, source);
                        SqlExpression date = sql.Concat(year, sql.ValueFromObject("-", false, source), month, sql.ValueFromObject("-", false, source), day);
                        SqlExpression time = sql.Concat(hour, sql.ValueFromObject(":", false, source), minute, sql.ValueFromObject(":", false, source), second);

                        SqlExpression datetimeoffset = new SqlVariable(typeof(void), null, "DATETIMEOFFSET", source);
                        SqlExpression result, dateAndTime;
                        int timeSpanIndex;

                        if (sox.Args.Count == 7 && sox.Args[6].ClrType == typeof(TimeSpan)) {
                            timeSpanIndex = 6;
                            dateAndTime = sql.Concat(date, sql.ValueFromObject(' ', false, source), time);
                            result = sql.FunctionCall(typeof(DateTimeOffset), "CONVERT", new SqlExpression[3] { datetimeoffset, dateAndTime, sql.ValueFromObject(120, false, source) }, source);
                        }
                        else if (sox.Args.Count == 8 && sox.Args[6].ClrType == typeof(int) && sox.Args[7].ClrType == typeof(TimeSpan)) {
                            timeSpanIndex = 7;
                            // add leading zeros to milliseconds by RIGHT(CONVERT(NCHAR(4),1000+@ms),3) 
                            SqlExpression msRaw = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] {char4,
                                       sql.Add(sql.ValueFromObject(1000, false, source),sox.Args[6])}, source);
                            SqlExpression ms = sql.FunctionCall(typeof(string), "RIGHT", new SqlExpression[2] { msRaw, sql.ValueFromObject(3, false, source) }, source);
                            dateAndTime = sql.Concat(date, sql.ValueFromObject(' ', false, source), time, sql.ValueFromObject('.', false, source), ms);
                            result = sql.FunctionCall(typeof(DateTimeOffset), "CONVERT", new SqlExpression[3] { datetimeoffset, dateAndTime, sql.ValueFromObject(121, false, source) }, source);
                        }
                        else {
                            throw Error.UnsupportedDateTimeOffsetConstructorForm();
                        }

                        return sql.FunctionCall(typeof(DateTimeOffset), "TODATETIMEOFFSET",
                                                new SqlExpression[2] 
                                                { 
                                                    result, 
                                                    sql.ConvertToInt(sql.ConvertToBigint(sql.Divide(sql.ConvertTimeToDouble(sox.Args[timeSpanIndex]), TimeSpan.TicksPerMinute)))
                                                },
                                                source);
                    }
                }
                throw Error.UnsupportedDateTimeOffsetConstructorForm();
            }
Exemple #13
0
 protected virtual SqlExpression VisitVariable(SqlVariable expr)
 {
     return(expr);
 }
 protected override SqlExpression VisitVariable(SqlVariable expr)
 {
     _builder.Append(expr.Name);
     return expr;
 }
Exemple #15
0
 public void Visit(SqlVariable node)
 {
 }
 internal override SqlExpression VisitVariable(SqlVariable v)
 {
     return(v);
 }
 public virtual void Visit(SqlVariable node)
 {
 }
            private SqlExpression TranslateSqlMethodsMethod(SqlMethodCall mc) {
                Expression source = mc.SourceExpression;
                SqlExpression returnValue = null;
                string name = mc.Method.Name;
                if (name.StartsWith("DateDiff", StringComparison.Ordinal) && mc.Arguments.Count == 2) {
                    foreach (string datePart in dateParts) {
                        if (mc.Method.Name == "DateDiff" + datePart) {
                            SqlExpression start = mc.Arguments[0];
                            SqlExpression end = mc.Arguments[1];
                            SqlExpression unit = new SqlVariable(typeof(void), null, datePart, source);
                            return sql.FunctionCall(typeof(int), "DATEDIFF",
                                                    new SqlExpression[] { unit, start, end }, source);
                        }
                    }
                }
                else if (name == "Like") {
                    if (mc.Arguments.Count == 2) {
                        return sql.Like(mc.Arguments[0], mc.Arguments[1], null, source);
                    }
                    else if (mc.Arguments.Count == 3) {
                        return sql.Like(mc.Arguments[0], mc.Arguments[1], sql.ConvertTo(typeof(string), mc.Arguments[2]), source);
                    }
                }
                else if (name == "RawLength") {
                    SqlExpression length = sql.DATALENGTH(mc.Arguments[0]);
                    return length;
                }

                return returnValue;
            }
Exemple #19
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);
        }
Exemple #20
0
 protected override SqlExpression VisitVariable(SqlVariable expr)
 {
     _builder.Append(expr.Name);
     return(expr);
 }
Exemple #21
0
 internal virtual SqlExpression VisitVariable(SqlVariable v) {
     return v;
 }
 internal override SqlExpression VisitVariable(SqlVariable v) {
     return v;
 }
            private SqlExpression TranslateNewDateTime(SqlNew sox) {
                Expression source = sox.SourceExpression;

                // DateTime(int year, int month, int day) 
                // --> CONVERT(DATETIME, CONVERT(nchar(2),@month) + '/' + CONVERT(nchar(2),@day) + '/' + CONVERT(nchar(4),@year),101)
                if (sox.ClrType == typeof(DateTime) && sox.Args.Count >= 3 &&
                    sox.Args[0].ClrType == typeof(int) && sox.Args[1].ClrType == typeof(int) && sox.Args[2].ClrType == typeof(int)) {
                    SqlExpression char2 = sql.FunctionCall(typeof(void), "NCHAR", new SqlExpression[1] { sql.ValueFromObject(2, false, source) }, source);
                    SqlExpression char4 = sql.FunctionCall(typeof(void), "NCHAR", new SqlExpression[1] { sql.ValueFromObject(4, false, source) }, source);
                    SqlExpression year = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char4, sox.Args[0] }, source);
                    SqlExpression month = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[1] }, source);
                    SqlExpression day = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[2] }, source);
                    SqlExpression datetime = new SqlVariable(typeof(void), null, "DATETIME", source);
                    if (sox.Args.Count == 3) {
                        SqlExpression date = sql.Concat(month, sql.ValueFromObject("/", false, source), day, sql.ValueFromObject("/", false, source), year);
                        return sql.FunctionCall(typeof(DateTime), "CONVERT", new SqlExpression[3] { datetime, date, sql.ValueFromObject(101, false, source) }, source);
                    }
                    if (sox.Args.Count >= 6 &&
                        sox.Args[3].ClrType == typeof(int) && sox.Args[4].ClrType == typeof(int) && sox.Args[5].ClrType == typeof(int)) {
                        // DateTime(year, month, day, hour, minute, second ) 
                        // --> CONVERT(DATETIME, CONVERT(nchar(2),@month) + '-' + CONVERT(nchar(2),@day) + '-' + CONVERT(nchar(4),@year) +
                        //                 ' ' + CONVERT(nchar(2),@hour) + ':' + CONVERT(nchar(2),@minute) + ':' + CONVERT(nchar(2),@second)  ,120)
                        SqlExpression hour = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[3] }, source);
                        SqlExpression minute = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[4] }, source);
                        SqlExpression second = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[5] }, source);
                        SqlExpression date = sql.Concat(year, sql.ValueFromObject("-", false, source), month, sql.ValueFromObject("-", false, source), day);
                        SqlExpression time = sql.Concat(hour, sql.ValueFromObject(":", false, source), minute, sql.ValueFromObject(":", false, source), second);
                        SqlExpression dateAndTime = sql.Concat(date, sql.ValueFromObject(' ', false, source), time);
                        if (sox.Args.Count == 6) {
                            return sql.FunctionCall(typeof(DateTime), "CONVERT", new SqlExpression[3] { datetime, dateAndTime, sql.ValueFromObject(120, false, source) }, source);
                        }
                        if ((sox.Args.Count == 7) && (sox.Args[6].ClrType == typeof(int))) {
                            // DateTime(year, month, day, hour, minute, second, millisecond ) 
                            // add leading zeros to milliseconds by RIGHT(CONVERT(NCHAR(4),1000+@ms),3) 
                            SqlExpression msRaw = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] {char4,
                                       sql.Add(sql.ValueFromObject(1000, false, source),sox.Args[6])}, source);
                            SqlExpression ms;
                            if (this.providerMode == SqlProvider.ProviderMode.SqlCE) {
                                //SqlCE doesn't have "RIGHT", so need to use "SUBSTRING"
                                SqlExpression len = sql.FunctionCall(typeof(int), "LEN", new SqlExpression[1] { msRaw }, source);
                                SqlExpression startIndex = sql.Binary(SqlNodeType.Sub, len, sql.ValueFromObject(2, false, source));
                                ms = sql.FunctionCall(typeof(string), "SUBSTRING", new SqlExpression[3] { msRaw, startIndex, sql.ValueFromObject(3, false, source) }, source);
                            }
                            else {
                                ms = sql.FunctionCall(typeof(string), "RIGHT", new SqlExpression[2] { msRaw, sql.ValueFromObject(3, false, source) }, source);
                            }
                            dateAndTime = sql.Concat(dateAndTime, sql.ValueFromObject('.', false, source), ms);
                            return sql.FunctionCall(typeof(DateTime), "CONVERT", new SqlExpression[3] { datetime, dateAndTime, sql.ValueFromObject(121, false, source) }, source);
                        }
                    }
                }
                throw Error.UnsupportedDateTimeConstructorForm();
            }
            internal override SqlNode VisitMember(SqlMember m) {
                SqlExpression exp = this.VisitExpression(m.Expression);
                MemberInfo member = m.Member;
                Expression source = m.SourceExpression;

                Type baseClrTypeOfExpr = TypeSystem.GetNonNullableType(exp.ClrType);
                if (baseClrTypeOfExpr == typeof(string) && member.Name == "Length") {
                    // This gives a different result than .Net would if the string ends in spaces.
                    // We decided not to fix this up (e.g. LEN(@s+'#') - 1) since it would incur a performance hit and 
                    // people may actually expect that it translates to the SQL LEN function.
                    return sql.LEN(exp);
                }
                else if (baseClrTypeOfExpr == typeof(Binary) && member.Name == "Length") {
                    return sql.DATALENGTH(exp);
                }
                else if (baseClrTypeOfExpr == typeof(DateTime) || baseClrTypeOfExpr == typeof(DateTimeOffset)) {
                    string datePart = GetDatePart(member.Name);
                    if (datePart != null) {
                        return sql.DATEPART(datePart, exp);
                    }
                    else if (member.Name == "Date") {
                        if (this.providerMode == SqlProvider.ProviderMode.Sql2008) {
                            SqlExpression date = new SqlVariable(typeof(void), null, "DATE", source);
                            return sql.FunctionCall(typeof(DateTime), "CONVERT", new SqlExpression[2] { date, exp }, source);
                        }
                        // date --> dateadd(hh, -(datepart(hh, @date)), 
                        //          dateadd(mi, -(datepart(mi, @date)), 
                        //          dateadd(ss, -(datepart(ss, @date)), 
                        //          dateadd(ms, -(datepart(ms, @date)), 
                        //          @date))))

                        SqlExpression ms = sql.DATEPART("MILLISECOND", exp);
                        SqlExpression ss = sql.DATEPART("SECOND", exp);
                        SqlExpression mi = sql.DATEPART("MINUTE", exp);
                        SqlExpression hh = sql.DATEPART("HOUR", exp);

                        SqlExpression result = exp;

                        result = sql.DATEADD("MILLISECOND", sql.Unary(SqlNodeType.Negate, ms), result);
                        result = sql.DATEADD("SECOND", sql.Unary(SqlNodeType.Negate, ss), result);
                        result = sql.DATEADD("MINUTE", sql.Unary(SqlNodeType.Negate, mi), result);
                        result = sql.DATEADD("HOUR", sql.Unary(SqlNodeType.Negate, hh), result);

                        return result;
                    }
                    else if (member.Name == "DateTime") {
                        Debug.Assert(baseClrTypeOfExpr == typeof(DateTimeOffset), "'DateTime' property supported only for instances of DateTimeOffset.");
                        SqlExpression datetime = new SqlVariable(typeof(void), null, "DATETIME", source);
                        return sql.FunctionCall(typeof(DateTime), "CONVERT", new SqlExpression[2] { datetime, exp }, source);
                    }
                    else if (member.Name == "TimeOfDay") {
                        SqlExpression hours = sql.DATEPART("HOUR", exp);
                        SqlExpression minutes = sql.DATEPART("MINUTE", exp);
                        SqlExpression seconds = sql.DATEPART("SECOND", exp);
                        SqlExpression milliseconds = sql.DATEPART("MILLISECOND", exp);

                        SqlExpression ticksFromHour = sql.Multiply(sql.ConvertToBigint(hours), TimeSpan.TicksPerHour);
                        SqlExpression ticksFromMinutes = sql.Multiply(sql.ConvertToBigint(minutes), TimeSpan.TicksPerMinute);
                        SqlExpression ticksFromSeconds = sql.Multiply(sql.ConvertToBigint(seconds), TimeSpan.TicksPerSecond);
                        SqlExpression ticksFromMs = sql.Multiply(sql.ConvertToBigint(milliseconds), TimeSpan.TicksPerMillisecond);
                        return sql.ConvertTo(typeof(TimeSpan), sql.Add(ticksFromHour, ticksFromMinutes, ticksFromSeconds, ticksFromMs));
                    }
                    else if (member.Name == "DayOfWeek") {
                        //(DATEPART(dw,@date) + @@Datefirst + 6) % 7 to make it independent from SQL settings
                        SqlExpression sqlDay = sql.DATEPART("dw", exp);

                        // 
                        // .DayOfWeek returns a System.DayOfWeek, so ConvertTo that enum.
                        return sql.ConvertTo(typeof(DayOfWeek),
                                sql.Mod(
                                  sql.Add(sqlDay,
                                     sql.Add(new SqlVariable(typeof(int), sql.Default(typeof(int)), "@@DATEFIRST", source), 6)
                                  )
                                , 7));
                    }
                }
                else if (baseClrTypeOfExpr == typeof(System.TimeSpan)) {
                    switch (member.Name) {
                        case "Ticks":
                            if (SqlFactory.IsSqlTimeType(exp)) {
                                return this.sql.Divide(
                                            sql.ConvertToBigint(
                                                sql.Add(
                                                    this.sql.Multiply(sql.ConvertToBigint(sql.DATEPART("HOUR", exp)), 3600000000000),
                                                    this.sql.Multiply(sql.ConvertToBigint(sql.DATEPART("MINUTE", exp)), 60000000000),
                                                    this.sql.Multiply(sql.ConvertToBigint(sql.DATEPART("SECOND", exp)), 1000000000),
                                                    sql.DATEPART("NANOSECOND", exp))
                                                ),
                                            100
                                    );
                            }
                            return sql.ConvertToBigint(exp);
                        case "TotalMilliseconds":
                            if (SqlFactory.IsSqlTimeType(exp)) {
                                return this.sql.Add(
                                            this.sql.Multiply(sql.DATEPART("HOUR", exp), 3600000),
                                            this.sql.Multiply(sql.DATEPART("MINUTE", exp), 60000),
                                            this.sql.Multiply(sql.DATEPART("SECOND", exp), 1000),
                                            this.sql.Divide(sql.ConvertToDouble(sql.ConvertToBigint(sql.DATEPART("NANOSECOND", exp))), 1000000)
                                        );
                            }
                            return sql.Divide(sql.ConvertToDouble(exp), TimeSpan.TicksPerMillisecond);
                        case "TotalSeconds":
                            if (SqlFactory.IsSqlTimeType(exp)) {
                                return this.sql.Add(
                                            this.sql.Multiply(sql.DATEPART("HOUR", exp), 3600),
                                            this.sql.Multiply(sql.DATEPART("MINUTE", exp), 60),
                                            this.sql.DATEPART("SECOND", exp),
                                            this.sql.Divide(sql.ConvertToDouble(sql.ConvertToBigint(sql.DATEPART("NANOSECOND", exp))), 1000000000)
                                        );
                            }
                            return sql.Divide(sql.ConvertToDouble(exp), TimeSpan.TicksPerSecond);
                        case "TotalMinutes":
                            if (SqlFactory.IsSqlTimeType(exp)) {
                                return this.sql.Add(
                                            this.sql.Multiply(sql.DATEPART("HOUR", exp), 60),
                                            this.sql.DATEPART("MINUTE", exp),
                                            this.sql.Divide(sql.ConvertToDouble(sql.DATEPART("SECOND", exp)), 60),
                                            this.sql.Divide(sql.ConvertToDouble(sql.ConvertToBigint(sql.DATEPART("NANOSECOND", exp))), 60000000000)
                                        );
                            }
                            return sql.Divide(sql.ConvertToDouble(exp), TimeSpan.TicksPerMinute);
                        case "TotalHours":
                            if (SqlFactory.IsSqlTimeType(exp)) {
                                return this.sql.Add(
                                            this.sql.DATEPART("HOUR", exp),
                                            this.sql.Divide(sql.ConvertToDouble(sql.DATEPART("MINUTE", exp)), 60),
                                            this.sql.Divide(sql.ConvertToDouble(sql.DATEPART("SECOND", exp)), 3600),
                                            this.sql.Divide(sql.ConvertToDouble(sql.ConvertToBigint(sql.DATEPART("NANOSECOND", exp))), 3600000000000)
                                        );
                            }
                            return sql.Divide(sql.ConvertToDouble(exp), TimeSpan.TicksPerHour);
                        case "TotalDays":
                            if (SqlFactory.IsSqlTimeType(exp)) {
                                return this.sql.Divide(
                                            this.sql.Add(
                                                this.sql.DATEPART("HOUR", exp),
                                                this.sql.Divide(sql.ConvertToDouble(sql.DATEPART("MINUTE", exp)), 60),
                                                this.sql.Divide(sql.ConvertToDouble(sql.DATEPART("SECOND", exp)), 3600),
                                                this.sql.Divide(sql.ConvertToDouble(sql.ConvertToBigint(sql.DATEPART("NANOSECOND", exp))), 3600000000000)),
                                            24
                                        );
                            }
                            return sql.Divide(sql.ConvertToDouble(exp), TimeSpan.TicksPerDay);
                        case "Milliseconds":
                            if (SqlFactory.IsSqlTimeType(exp)) {
                                return this.sql.DATEPART("MILLISECOND", exp);
                            }
                            return sql.ConvertToInt(sql.Mod(sql.ConvertToBigint(sql.Divide(exp, TimeSpan.TicksPerMillisecond)), 1000));
                        case "Seconds":
                            if (SqlFactory.IsSqlTimeType(exp)) {
                                return this.sql.DATEPART("SECOND", exp);
                            }
                            return sql.ConvertToInt(sql.Mod(sql.ConvertToBigint(sql.Divide(exp, TimeSpan.TicksPerSecond)), 60));
                        case "Minutes":
                            if (SqlFactory.IsSqlTimeType(exp)) {
                                return this.sql.DATEPART("MINUTE", exp);
                            }
                            return sql.ConvertToInt(sql.Mod(sql.ConvertToBigint(sql.Divide(exp, TimeSpan.TicksPerMinute)), 60));
                        case "Hours":
                            if (SqlFactory.IsSqlTimeType(exp)) {
                                return this.sql.DATEPART("HOUR", exp);
                            }
                            return sql.ConvertToInt(sql.Mod(sql.ConvertToBigint(sql.Divide(exp, TimeSpan.TicksPerHour)), 24));
                        case "Days":
                            if (SqlFactory.IsSqlTimeType(exp)) {
                                return this.sql.ValueFromObject(0, false, exp.SourceExpression);
                            }
                            return sql.ConvertToInt(sql.Divide(exp, TimeSpan.TicksPerDay));
                        default:
                            throw Error.MemberCannotBeTranslated(member.DeclaringType, member.Name);
                    }
                }
                throw Error.MemberCannotBeTranslated(member.DeclaringType, member.Name);
            }
            private SqlExpression TranslateDateTimeBinary(SqlBinary bo) {
                bool resultNullable = TypeSystem.IsNullableType(bo.ClrType);
                Type rightType = TypeSystem.GetNonNullableType(bo.Right.ClrType);
                switch (bo.NodeType) {
                    case SqlNodeType.Sub:
                        if (rightType == typeof(DateTime)) {
                            // if either of the arguments is nullable, set result type to nullable.
                            Type resultType = bo.ClrType;
                            SqlExpression end = bo.Left;
                            SqlExpression start = bo.Right;
                            SqlExpression day = new SqlVariable(typeof(void), null, "DAY", bo.SourceExpression);
                            SqlExpression ms = new SqlVariable(typeof(void), null, "MILLISECOND", bo.SourceExpression);

                            // DATEDIFF(MILLISECONDS,...) does not work for more then 24 days, since result has to fit int. 
                            // So compute the number of days first, and then find out the number of milliseconds needed in addition to that.
                            SqlExpression intDays = sql.FunctionCall(typeof(int), "DATEDIFF",
                                                        new SqlExpression[] { day, start, end }, bo.SourceExpression);
                            SqlExpression startPlusDays = sql.FunctionCall(
                                                          typeof(DateTime), "DATEADD", new SqlExpression[] { day, intDays, start }, bo.SourceExpression);
                            SqlExpression intMSec = sql.FunctionCall(typeof(int), "DATEDIFF",
                                                        new SqlExpression[] { ms, startPlusDays, end }, bo.SourceExpression);
                            SqlExpression result = sql.Multiply(sql.Add(sql.Multiply(sql.ConvertToBigint(intDays), 86400000), intMSec), 10000); // 1 millisecond = 10000 ticks
                            return sql.ConvertTo(resultType, result);
                        }
                        if (rightType == typeof(DateTimeOffset)) {
                            Debug.Assert(TypeSystem.GetNonNullableType(bo.Left.ClrType) == typeof(DateTimeOffset));
                            // if either of the arguments is nullable, set result type to nullable.
                            Type resultType = bo.ClrType;
                            SqlExpression end = bo.Left;
                            SqlExpression start = bo.Right;
                            SqlExpression day = new SqlVariable(typeof(void), null, "DAY", bo.SourceExpression);
                            SqlExpression ms = new SqlVariable(typeof(void), null, "MILLISECOND", bo.SourceExpression);
                            SqlExpression us = new SqlVariable(typeof(void), null, "MICROSECOND", bo.SourceExpression);
                            SqlExpression ns = new SqlVariable(typeof(void), null, "NANOSECOND", bo.SourceExpression);

                            // compute the number of days first, and then find out the number of milliseconds needed in addition to that.
                            SqlExpression intDays = sql.FunctionCall(typeof(int), "DATEDIFF", new SqlExpression[] { day, start, end }, bo.SourceExpression);
                            SqlExpression startPlusDays = sql.FunctionCall(typeof(DateTimeOffset), "DATEADD", new SqlExpression[] { day, intDays, start }, bo.SourceExpression);
                            SqlExpression intMSec = sql.FunctionCall(typeof(int), "DATEDIFF", new SqlExpression[] { ms, startPlusDays, end }, bo.SourceExpression);
                            SqlExpression startPlusDaysPlusMsec = sql.FunctionCall(typeof(DateTimeOffset), "DATEADD", new SqlExpression[] { ms, intMSec, startPlusDays }, bo.SourceExpression);
                            SqlExpression intUSec = sql.FunctionCall(typeof(int), "DATEDIFF", new SqlExpression[] { us, startPlusDaysPlusMsec, end }, bo.SourceExpression);
                            SqlExpression startPlusDaysPlusMsecPlusUSec = sql.FunctionCall(typeof(DateTimeOffset), "DATEADD", new SqlExpression[] { us, intUSec, startPlusDaysPlusMsec }, bo.SourceExpression);
                            SqlExpression intNSec = sql.FunctionCall(typeof(int), "DATEDIFF", new SqlExpression[] { ns, startPlusDaysPlusMsecPlusUSec, end }, bo.SourceExpression);
                            SqlExpression startPlusDaysPlusMsecPlusUSecPlusNSec = sql.FunctionCall(typeof(DateTimeOffset), "DATEADD", new SqlExpression[] { ns, intNSec, startPlusDaysPlusMsecPlusUSec }, bo.SourceExpression);

                            SqlExpression result = sql.Add(
                                                        sql.Divide(intNSec, 100),
                                                        sql.Multiply(intUSec, 10),
                                                        sql.Multiply(
                                                            sql.Add(
                                                                sql.Multiply(sql.ConvertToBigint(intDays), 86400000), 
                                                                intMSec
                                                            ), 
                                                            10000)
                                                   );

                            return sql.ConvertTo(resultType, result);
                        }
                        else if (rightType == typeof(TimeSpan)) {
                            SqlExpression right = bo.Right;
                            if (SqlFactory.IsSqlTimeType(bo.Right)) {
                                SqlExpression ns = sql.DATEPART("NANOSECOND", right);
                                SqlExpression ss = sql.DATEPART("SECOND", right);
                                SqlExpression mi = sql.DATEPART("MINUTE", right);
                                SqlExpression hh = sql.DATEPART("HOUR", right);

                                right = sql.Add(
                                            sql.Divide(ns, 100),
                                            sql.Multiply(
                                                        sql.Add(
                                                            sql.Multiply(sql.ConvertToBigint(hh), 3600000),
                                                            sql.Multiply(sql.ConvertToBigint(mi), 60000),
                                                            sql.Multiply(sql.ConvertToBigint(ss), 1000)
                                                          ),
                                                        10000   // 1 millisecond = 10000 ticks
                                                    )
                                            );
                            } 
                            
                            return TypeSystem.GetNonNullableType(bo.Left.ClrType) == typeof(DateTimeOffset) ?           
                                                CreateDateTimeOffsetFromDateAndTicks(
                                                    bo.Left,
                                                    sql.Unary(SqlNodeType.Negate, right, bo.SourceExpression),
                                                    bo.SourceExpression, resultNullable
                                                ) :
                                                CreateDateTimeFromDateAndTicks(
                                                    bo.Left,
                                                    sql.Unary(SqlNodeType.Negate, right, bo.SourceExpression),
                                                    bo.SourceExpression, resultNullable
                                                );
                        }
                        break;
                    case SqlNodeType.Add:
                        if (rightType == typeof(TimeSpan)) {
                            if (SqlFactory.IsSqlTimeType(bo.Right)) {
                                return sql.AddTimeSpan(bo.Left, bo.Right, resultNullable);
                            } else if (TypeSystem.GetNonNullableType(bo.Left.ClrType) == typeof(DateTimeOffset)) {
                                return CreateDateTimeOffsetFromDateAndTicks(bo.Left, bo.Right, bo.SourceExpression, resultNullable);
                            }

                            return CreateDateTimeFromDateAndTicks(bo.Left, bo.Right, bo.SourceExpression, resultNullable);
                        }
                        break;
                }
                return bo;
            }
        internal static bool AreEqual(SqlNode node1, SqlNode node2)
        {
            if (node1 == node2)
            {
                return(true);
            }
            if (node1 == null || node2 == null)
            {
                return(false);
            }

            if (node1.NodeType == SqlNodeType.SimpleCase)
            {
                node1 = UnwrapTrivialCaseExpression((SqlSimpleCase)node1);
            }

            if (node2.NodeType == SqlNodeType.SimpleCase)
            {
                node2 = UnwrapTrivialCaseExpression((SqlSimpleCase)node2);
            }

            if (node1.NodeType != node2.NodeType)
            {
                // allow expression sets to compare against single expressions
                if (node1.NodeType == SqlNodeType.ExprSet)
                {
                    SqlExprSet eset = (SqlExprSet)node1;
                    for (int i = 0, n = eset.Expressions.Count; i < n; i++)
                    {
                        if (AreEqual(eset.Expressions[i], node2))
                        {
                            return(true);
                        }
                    }
                }
                else if (node2.NodeType == SqlNodeType.ExprSet)
                {
                    SqlExprSet eset = (SqlExprSet)node2;
                    for (int i = 0, n = eset.Expressions.Count; i < n; i++)
                    {
                        if (AreEqual(node1, eset.Expressions[i]))
                        {
                            return(true);
                        }
                    }
                }
                return(false);
            }
            if (node1.Equals(node2))
            {
                return(true);
            }

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

            case SqlNodeType.Add:
            case SqlNodeType.Sub:
            case SqlNodeType.Mul:
            case SqlNodeType.Div:
            case SqlNodeType.Mod:
            case SqlNodeType.BitAnd:
            case SqlNodeType.BitOr:
            case SqlNodeType.BitXor:
            case SqlNodeType.And:
            case SqlNodeType.Or:
            case SqlNodeType.GE:
            case SqlNodeType.GT:
            case SqlNodeType.LE:
            case SqlNodeType.LT:
            case SqlNodeType.EQ:
            case SqlNodeType.NE:
            case SqlNodeType.EQ2V:
            case SqlNodeType.NE2V:
            case SqlNodeType.Concat:
                SqlBinary firstNode  = (SqlBinary)node1;
                SqlBinary secondNode = (SqlBinary)node2;
                return(AreEqual(firstNode.Left, secondNode.Left) &&
                       AreEqual(firstNode.Right, secondNode.Right));

            case SqlNodeType.Convert:
            case SqlNodeType.Treat:
            {
                SqlUnary sun1 = (SqlUnary)node1;
                SqlUnary sun2 = (SqlUnary)node2;
                return(sun1.ClrType == sun2.ClrType && sun1.SqlType == sun2.SqlType && AreEqual(sun1.Operand, sun2.Operand));
            }

            case SqlNodeType.Between:
            {
                SqlBetween b1 = (SqlBetween)node1;
                SqlBetween b2 = (SqlBetween)node1;
                return(AreEqual(b1.Expression, b2.Expression) &&
                       AreEqual(b1.Start, b2.Start) &&
                       AreEqual(b1.End, b2.End));
            }

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

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

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

            case SqlNodeType.Column:
                SqlColumn col1 = (SqlColumn)node1;
                SqlColumn col2 = (SqlColumn)node2;
                return(col1 == col2 || (col1.Expression != null && col2.Expression != null && AreEqual(col1.Expression, col2.Expression)));

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

            case SqlNodeType.Member:
                return((((SqlMember)node1).Member == ((SqlMember)node2).Member) &&
                       AreEqual(((SqlMember)node1).Expression, ((SqlMember)node2).Expression));

            case SqlNodeType.ColumnRef:
                SqlColumnRef cref1 = (SqlColumnRef)node1;
                SqlColumnRef cref2 = (SqlColumnRef)node2;
                return(GetBaseColumn(cref1) == GetBaseColumn(cref2));

            case SqlNodeType.Value:
                return(Object.Equals(((SqlValue)node1).Value, ((SqlValue)node2).Value));

            case SqlNodeType.TypeCase:
            {
                SqlTypeCase c1 = (SqlTypeCase)node1;
                SqlTypeCase c2 = (SqlTypeCase)node2;
                if (!AreEqual(c1.Discriminator, c2.Discriminator))
                {
                    return(false);
                }
                if (c1.Whens.Count != c2.Whens.Count)
                {
                    return(false);
                }
                for (int i = 0, c = c1.Whens.Count; i < c; ++i)
                {
                    if (!AreEqual(c1.Whens[i].Match, c2.Whens[i].Match))
                    {
                        return(false);
                    }
                    if (!AreEqual(c1.Whens[i].TypeBinding, c2.Whens[i].TypeBinding))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            case SqlNodeType.SearchedCase:
            {
                SqlSearchedCase c1 = (SqlSearchedCase)node1;
                SqlSearchedCase c2 = (SqlSearchedCase)node2;
                if (c1.Whens.Count != c2.Whens.Count)
                {
                    return(false);
                }
                for (int i = 0, n = c1.Whens.Count; i < n; i++)
                {
                    if (!AreEqual(c1.Whens[i].Match, c2.Whens[i].Match) ||
                        !AreEqual(c1.Whens[i].Value, c2.Whens[i].Value))
                    {
                        return(false);
                    }
                }
                return(AreEqual(c1.Else, c2.Else));
            }

            case SqlNodeType.ClientCase:
            {
                SqlClientCase c1 = (SqlClientCase)node1;
                SqlClientCase c2 = (SqlClientCase)node2;
                if (c1.Whens.Count != c2.Whens.Count)
                {
                    return(false);
                }
                for (int i = 0, n = c1.Whens.Count; i < n; i++)
                {
                    if (!AreEqual(c1.Whens[i].Match, c2.Whens[i].Match) ||
                        !AreEqual(c1.Whens[i].Value, c2.Whens[i].Value))
                    {
                        return(false);
                    }
                }
                return(true);
            }

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

            case SqlNodeType.SimpleCase:
            {
                SqlSimpleCase c1 = (SqlSimpleCase)node1;
                SqlSimpleCase c2 = (SqlSimpleCase)node2;
                if (c1.Whens.Count != c2.Whens.Count)
                {
                    return(false);
                }
                for (int i = 0, n = c1.Whens.Count; i < n; i++)
                {
                    if (!AreEqual(c1.Whens[i].Match, c2.Whens[i].Match) ||
                        !AreEqual(c1.Whens[i].Value, c2.Whens[i].Value))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.Like:
            {
                SqlLike like1 = (SqlLike)node1;
                SqlLike like2 = (SqlLike)node2;
                return(AreEqual(like1.Expression, like2.Expression) &&
                       AreEqual(like1.Pattern, like2.Pattern) &&
                       AreEqual(like1.Escape, like2.Escape));
            }

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

            case SqlNodeType.FunctionCall:
            {
                SqlFunctionCall f1 = (SqlFunctionCall)node1;
                SqlFunctionCall f2 = (SqlFunctionCall)node2;
                if (f1.Name != f2.Name)
                {
                    return(false);
                }
                if (f1.Arguments.Count != f2.Arguments.Count)
                {
                    return(false);
                }
                for (int i = 0, n = f1.Arguments.Count; i < n; i++)
                {
                    if (!AreEqual(f1.Arguments[i], f2.Arguments[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.Link:
            {
                SqlLink l1 = (SqlLink)node1;
                SqlLink l2 = (SqlLink)node2;
                if (!MetaPosition.AreSameMember(l1.Member.Member, l2.Member.Member))
                {
                    return(false);
                }
                if (!AreEqual(l1.Expansion, l2.Expansion))
                {
                    return(false);
                }
                if (l1.KeyExpressions.Count != l2.KeyExpressions.Count)
                {
                    return(false);
                }
                for (int i = 0, c = l1.KeyExpressions.Count; i < c; ++i)
                {
                    if (!AreEqual(l1.KeyExpressions[i], l2.KeyExpressions[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.ExprSet:
                SqlExprSet es1 = (SqlExprSet)node1;
                SqlExprSet es2 = (SqlExprSet)node2;
                if (es1.Expressions.Count != es2.Expressions.Count)
                {
                    return(false);
                }
                for (int i = 0, n = es1.Expressions.Count; i < n; i++)
                {
                    if (!AreEqual(es1.Expressions[i], es2.Expressions[i]))
                    {
                        return(false);
                    }
                }
                return(true);

            case SqlNodeType.OptionalValue:
                SqlOptionalValue ov1 = (SqlOptionalValue)node1;
                SqlOptionalValue ov2 = (SqlOptionalValue)node2;
                return(AreEqual(ov1.Value, ov2.Value));

            case SqlNodeType.Row:
            case SqlNodeType.UserQuery:
            case SqlNodeType.StoredProcedureCall:
            case SqlNodeType.UserRow:
            case SqlNodeType.UserColumn:
            case SqlNodeType.Multiset:
            case SqlNodeType.ScalarSubSelect:
            case SqlNodeType.Element:
            case SqlNodeType.Exists:
            case SqlNodeType.Join:
            case SqlNodeType.Select:
            case SqlNodeType.New:
            case SqlNodeType.ClientQuery:
            case SqlNodeType.ClientArray:
            case SqlNodeType.Insert:
            case SqlNodeType.Update:
            case SqlNodeType.Delete:
            case SqlNodeType.MemberAssign:
            case SqlNodeType.Assign:
            case SqlNodeType.Block:
            case SqlNodeType.Union:
            case SqlNodeType.DoNotVisit:
            case SqlNodeType.MethodCall:
            case SqlNodeType.Nop:
            default:
                return(false);
            }
        }
 internal virtual SqlExpression VisitVariable(SqlVariable v) {
     return v;
 }
 internal override SqlExpression VisitVariable(SqlVariable v) {
     sb.Append(v.Name);
     return v;
 }
 protected virtual SqlExpression VisitVariable(SqlVariable expr)
 {
     return expr;
 }