private SqlNode ConvertDateToDateTime2(SqlExpression expr) { SqlExpression datetime2 = new SqlVariable(expr.ClrType, expr.SqlType, "DATETIME2", expr.SourceExpression); return _nodeFactory.FunctionCall(typeof(DateTime), "CONVERT", new SqlExpression[2] { datetime2, expr }, expr.SourceExpression); }
internal virtual SqlExpression VisitVariable(SqlVariable v) { return v; }
internal override SqlExpression VisitVariable(SqlVariable v) { return v; }
internal override SqlExpression VisitVariable(SqlVariable v) { _commandStringBuilder.Append(v.Name); return v; }
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(); }
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 == SqlServerProviderMode.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.FunctionCallStringLength(exp); } else if(baseClrTypeOfExpr == typeof(Binary) && member.Name == "Length") { return sql.FunctionCallDataLength(exp); } else if(baseClrTypeOfExpr == typeof(DateTime) || baseClrTypeOfExpr == typeof(DateTimeOffset)) { string datePart = GetDatePart(member.Name); if(datePart != null) { return sql.FunctionCallDatePart(datePart, exp); } else if(member.Name == "Date") { if(this.providerMode == SqlServerProviderMode.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.FunctionCallDatePart("MILLISECOND", exp); SqlExpression ss = sql.FunctionCallDatePart("SECOND", exp); SqlExpression mi = sql.FunctionCallDatePart("MINUTE", exp); SqlExpression hh = sql.FunctionCallDatePart("HOUR", exp); SqlExpression result = exp; result = sql.FunctionCallDateAdd("MILLISECOND", sql.Unary(SqlNodeType.Negate, ms), result); result = sql.FunctionCallDateAdd("SECOND", sql.Unary(SqlNodeType.Negate, ss), result); result = sql.FunctionCallDateAdd("MINUTE", sql.Unary(SqlNodeType.Negate, mi), result); result = sql.FunctionCallDateAdd("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.FunctionCallDatePart("HOUR", exp); SqlExpression minutes = sql.FunctionCallDatePart("MINUTE", exp); SqlExpression seconds = sql.FunctionCallDatePart("SECOND", exp); SqlExpression milliseconds = sql.FunctionCallDatePart("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.FunctionCallDatePart("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(sql.IsTimeType(exp)) { return this.sql.Divide( sql.ConvertToBigint( sql.Add( this.sql.Multiply(sql.ConvertToBigint(sql.FunctionCallDatePart("HOUR", exp)), 3600000000000), this.sql.Multiply(sql.ConvertToBigint(sql.FunctionCallDatePart("MINUTE", exp)), 60000000000), this.sql.Multiply(sql.ConvertToBigint(sql.FunctionCallDatePart("SECOND", exp)), 1000000000), sql.FunctionCallDatePart("NANOSECOND", exp)) ), 100 ); } return sql.ConvertToBigint(exp); case "TotalMilliseconds": if(sql.IsTimeType(exp)) { return this.sql.Add( this.sql.Multiply(sql.FunctionCallDatePart("HOUR", exp), 3600000), this.sql.Multiply(sql.FunctionCallDatePart("MINUTE", exp), 60000), this.sql.Multiply(sql.FunctionCallDatePart("SECOND", exp), 1000), this.sql.Divide(sql.ConvertToDouble(sql.ConvertToBigint(sql.FunctionCallDatePart("NANOSECOND", exp))), 1000000) ); } return sql.Divide(sql.ConvertToDouble(exp), TimeSpan.TicksPerMillisecond); case "TotalSeconds": if(sql.IsTimeType(exp)) { return this.sql.Add( this.sql.Multiply(sql.FunctionCallDatePart("HOUR", exp), 3600), this.sql.Multiply(sql.FunctionCallDatePart("MINUTE", exp), 60), this.sql.FunctionCallDatePart("SECOND", exp), this.sql.Divide(sql.ConvertToDouble(sql.ConvertToBigint(sql.FunctionCallDatePart("NANOSECOND", exp))), 1000000000) ); } return sql.Divide(sql.ConvertToDouble(exp), TimeSpan.TicksPerSecond); case "TotalMinutes": if(sql.IsTimeType(exp)) { return this.sql.Add( this.sql.Multiply(sql.FunctionCallDatePart("HOUR", exp), 60), this.sql.FunctionCallDatePart("MINUTE", exp), this.sql.Divide(sql.ConvertToDouble(sql.FunctionCallDatePart("SECOND", exp)), 60), this.sql.Divide(sql.ConvertToDouble(sql.ConvertToBigint(sql.FunctionCallDatePart("NANOSECOND", exp))), 60000000000) ); } return sql.Divide(sql.ConvertToDouble(exp), TimeSpan.TicksPerMinute); case "TotalHours": if(sql.IsTimeType(exp)) { return this.sql.Add( this.sql.FunctionCallDatePart("HOUR", exp), this.sql.Divide(sql.ConvertToDouble(sql.FunctionCallDatePart("MINUTE", exp)), 60), this.sql.Divide(sql.ConvertToDouble(sql.FunctionCallDatePart("SECOND", exp)), 3600), this.sql.Divide(sql.ConvertToDouble(sql.ConvertToBigint(sql.FunctionCallDatePart("NANOSECOND", exp))), 3600000000000) ); } return sql.Divide(sql.ConvertToDouble(exp), TimeSpan.TicksPerHour); case "TotalDays": if(sql.IsTimeType(exp)) { return this.sql.Divide( this.sql.Add( this.sql.FunctionCallDatePart("HOUR", exp), this.sql.Divide(sql.ConvertToDouble(sql.FunctionCallDatePart("MINUTE", exp)), 60), this.sql.Divide(sql.ConvertToDouble(sql.FunctionCallDatePart("SECOND", exp)), 3600), this.sql.Divide(sql.ConvertToDouble(sql.ConvertToBigint(sql.FunctionCallDatePart("NANOSECOND", exp))), 3600000000000)), 24 ); } return sql.Divide(sql.ConvertToDouble(exp), TimeSpan.TicksPerDay); case "Milliseconds": if(sql.IsTimeType(exp)) { return this.sql.FunctionCallDatePart("MILLISECOND", exp); } return sql.ConvertToInt(sql.Mod(sql.ConvertToBigint(sql.Divide(exp, TimeSpan.TicksPerMillisecond)), 1000)); case "Seconds": if(sql.IsTimeType(exp)) { return this.sql.FunctionCallDatePart("SECOND", exp); } return sql.ConvertToInt(sql.Mod(sql.ConvertToBigint(sql.Divide(exp, TimeSpan.TicksPerSecond)), 60)); case "Minutes": if(sql.IsTimeType(exp)) { return this.sql.FunctionCallDatePart("MINUTE", exp); } return sql.ConvertToInt(sql.Mod(sql.ConvertToBigint(sql.Divide(exp, TimeSpan.TicksPerMinute)), 60)); case "Hours": if(sql.IsTimeType(exp)) { return this.sql.FunctionCallDatePart("HOUR", exp); } return sql.ConvertToInt(sql.Mod(sql.ConvertToBigint(sql.Divide(exp, TimeSpan.TicksPerHour)), 24)); case "Days": if(sql.IsTimeType(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(sql.IsTimeType(bo.Right)) { SqlExpression ns = sql.FunctionCallDatePart("NANOSECOND", right); SqlExpression ss = sql.FunctionCallDatePart("SECOND", right); SqlExpression mi = sql.FunctionCallDatePart("MINUTE", right); SqlExpression hh = sql.FunctionCallDatePart("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(sql.IsTimeType(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; }
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.FunctionCallDataLength(mc.Arguments[0]); return length; } return returnValue; }