// Convert from TimeSpan, rounded to one three-hundredth second, due to loss of precision private static SqlDateTime FromTimeSpan(TimeSpan value) { if (value < MinTimeSpan || value > MaxTimeSpan) { throw new SqlTypeException(SQLResource.DateTimeOverflowMessage); } int day = value.Days; long ticks = value.Ticks - day * TimeSpan.TicksPerDay; if (ticks < 0L) { day--; ticks += TimeSpan.TicksPerDay; } int time = (int)((double)ticks / TimeSpan.TicksPerMillisecond * SQLTicksPerMillisecond + 0.5); if (time > MaxTime) { // Only rounding up could cause time to become greater than MaxTime. SQLDebug.Check(time == MaxTime + 1); // Make time to be zero, and increment day. time = 0; day++; } return(new SqlDateTime(day, time)); }
// Hash a byte array. // Trailing zeroes/spaces would affect the hash value, so caller needs to // perform trimming as necessary. internal static int HashByteArray(byte[] rgbValue, int length) { SQLDebug.Check(length >= 0); if (length <= 0) { return(0); } SQLDebug.Check(rgbValue.Length >= length); int ulValue = 0; int ulHi; // Size of CRC window (hashing bytes, ssstr, sswstr, numeric) const int x_cbCrcWindow = 4; // const int iShiftVal = (sizeof ulValue) * (8*sizeof(char)) - x_cbCrcWindow; const int iShiftVal = 4 * 8 - x_cbCrcWindow; for (int i = 0; i < length; i++) { ulHi = (ulValue >> iShiftVal) & 0xff; ulValue <<= x_cbCrcWindow; ulValue = ulValue ^ rgbValue[i] ^ ulHi; } return(ulValue); }
private void SetCompareInfo() { SQLDebug.Check(!IsNull); if (m_cmpInfo == null) { m_cmpInfo = (CultureInfo.GetCultureInfo(m_lcid)).CompareInfo; } }
// Builtin functions // utility functions private static void AssertValidSqlDateTime(SqlDateTime x) { SQLDebug.Check(!x.IsNull, "!x.IsNull", "Datetime: Null"); SQLDebug.Check(x.m_day >= MinDay && x.m_day <= MaxDay, "day >= MinDay && day <= MaxDay", "DateTime: Day out of range"); SQLDebug.Check(x.m_time >= MinTime && x.m_time <= MaxTime, "time >= MinTime && time <= MaxTime", "DateTime: Time out of range"); }
// Wide-character string comparison for Binary Unicode Collation // Return values: // -1 : wstr1 < wstr2 // 0 : wstr1 = wstr2 // 1 : wstr1 > wstr2 // // Does a memory comparison. private static int CompareBinary(SqlString x, SqlString y) { byte[] rgDataX = x_UnicodeEncoding.GetBytes(x.m_value); byte[] rgDataY = x_UnicodeEncoding.GetBytes(y.m_value); int cbX = rgDataX.Length; int cbY = rgDataY.Length; int cbMin = cbX < cbY ? cbX : cbY; int i; SQLDebug.Check(cbX % 2 == 0); SQLDebug.Check(cbY % 2 == 0); for (i = 0; i < cbMin; i++) { if (rgDataX[i] < rgDataY[i]) { return(-1); } else if (rgDataX[i] > rgDataY[i]) { return(1); } } i = cbMin; int iCh; int iSpace = (int)' '; if (cbX < cbY) { for (; i < cbY; i += 2) { iCh = ((int)rgDataY[i + 1]) << 8 + rgDataY[i]; if (iCh != iSpace) { return((iSpace > iCh) ? 1 : -1); } } } else { for (; i < cbX; i += 2) { iCh = ((int)rgDataX[i + 1]) << 8 + rgDataX[i]; if (iCh != iSpace) { return((iCh > iSpace) ? 1 : -1); } } } return(0); }
// StringCompare: Common compare function which is used by Compare and CompareTo // In the case of Compare (used by comparison operators) the int result needs to be converted to SqlBoolean type // while CompareTo needs the result in int type // Pre-requisite: the null condition of the both string needs to be checked and handled by the caller of this function private static int StringCompare(SqlString x, SqlString y) { SQLDebug.Check(!x.IsNull && !y.IsNull, "!x.IsNull && !y.IsNull", "Null condition should be handled by the caller of StringCompare method"); if (x.m_lcid != y.m_lcid || x.m_flag != y.m_flag) { throw new SqlTypeException(SQLResource.CompareDiffCollationMessage); } x.SetCompareInfo(); y.SetCompareInfo(); SQLDebug.Check(x.FBinarySort() || (x.m_cmpInfo != null && y.m_cmpInfo != null), "x.FBinarySort() || (x.m_cmpInfo != null && y.m_cmpInfo != null)", ""); int iCmpResult; if ((x.m_flag & SqlCompareOptions.BinarySort) != 0) { iCmpResult = CompareBinary(x, y); } else if ((x.m_flag & SqlCompareOptions.BinarySort2) != 0) { iCmpResult = CompareBinary2(x, y); } else { // SqlString can be padded with spaces (Padding is turn on by default in SQL Server 2008 // Trim the trailing space for comparison // Avoid using String.TrimEnd function to avoid extra string allocations string rgchX = x.m_value; string rgchY = y.m_value; int cwchX = rgchX.Length; int cwchY = rgchY.Length; while (cwchX > 0 && rgchX[cwchX - 1] == ' ') { cwchX--; } while (cwchY > 0 && rgchY[cwchY - 1] == ' ') { cwchY--; } CompareOptions options = CompareOptionsFromSqlCompareOptions(x.m_flag); iCmpResult = x.m_cmpInfo.Compare(x.m_value, 0, cwchX, y.m_value, 0, cwchY, options); } return(iCmpResult); }
// Wide-character string comparison for Binary2 Unicode Collation // Return values: // -1 : wstr1 < wstr2 // 0 : wstr1 = wstr2 // 1 : wstr1 > wstr2 // // Does a wchar comparison (different from memcmp of BinarySort). private static int CompareBinary2(SqlString x, SqlString y) { SQLDebug.Check(!x.IsNull && !y.IsNull); string rgDataX = x.m_value; string rgDataY = y.m_value; int cwchX = rgDataX.Length; int cwchY = rgDataY.Length; int cwchMin = cwchX < cwchY ? cwchX : cwchY; int i; for (i = 0; i < cwchMin; i++) { if (rgDataX[i] < rgDataY[i]) { return(-1); } else if (rgDataX[i] > rgDataY[i]) { return(1); } } // If compares equal up to one of the string terminates, // pad it with spaces and compare with the rest of the other one. // char chSpace = ' '; if (cwchX < cwchY) { for (i = cwchMin; i < cwchY; i++) { if (rgDataY[i] != chSpace) { return((chSpace > rgDataY[i]) ? 1 : -1); } } } else { for (i = cwchMin; i < cwchX; i++) { if (rgDataX[i] != chSpace) { return((rgDataX[i] > chSpace) ? 1 : -1); } } } return(0); }
// Unary operators /// <devdoc> /// <para> /// Performs a NOT operation on a <see cref='System.Data.SqlTypes.SqlBoolean'/> /// . /// </para> /// </devdoc> public static SqlBoolean operator !(SqlBoolean x) { switch (x.m_value) { case x_True: return(SqlBoolean.False); case x_False: return(SqlBoolean.True); default: SQLDebug.Check(x.m_value == x_Null); return(SqlBoolean.Null); } }
// Comparison operators private static SqlBoolean Compare(SqlString x, SqlString y, EComparison ecExpectedResult) { if (x.IsNull || y.IsNull) { return(SqlBoolean.Null); } int iCmpResult = StringCompare(x, y); bool fResult = false; switch (ecExpectedResult) { case EComparison.EQ: fResult = (iCmpResult == 0); break; case EComparison.LT: fResult = (iCmpResult < 0); break; case EComparison.LE: fResult = (iCmpResult <= 0); break; case EComparison.GT: fResult = (iCmpResult > 0); break; case EComparison.GE: fResult = (iCmpResult >= 0); break; default: SQLDebug.Check(false, "Invalid ecExpectedResult"); return(SqlBoolean.Null); } return(new SqlBoolean(fResult)); }
public SqlDateTime(int year, int month, int day, int hour, int minute, int second, double millisecond) { if (year >= MinYear && year <= MaxYear && month >= 1 && month <= 12) { int[] days = IsLeapYear(year)? DaysToMonth366: DaysToMonth365; if (day >= 1 && day <= days[month] - days[month - 1]) { int y = year - 1; int dayticks = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1; dayticks -= DayBase; if (dayticks >= MinDay && dayticks <= MaxDay && hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60 && millisecond >= 0 && millisecond < 1000.0) { double ticksForMilisecond = millisecond * SQLTicksPerMillisecond + 0.5; int timeticks = hour * SQLTicksPerHour + minute * SQLTicksPerMinute + second * SQLTicksPerSecond + (int)ticksForMilisecond; if (timeticks > MaxTime) { // Only rounding up could cause time to become greater than MaxTime. SQLDebug.Check(timeticks == MaxTime + 1); // Make time to be zero, and increment day. timeticks = 0; dayticks++; } // Success. Call ctor here which will again check dayticks and timeticks are within range. // All other cases will throw exception below. this = new SqlDateTime(dayticks, timeticks); return; } } } throw new SqlTypeException(SQLResource.InvalidDateTimeMessage); }
/// <include file='doc\SQLInt64.uex' path='docs/doc[@for="SqlInt64.operator*"]/*' /> /// <devdoc> /// <para>[To be supplied.]</para> /// </devdoc> public static SqlInt64 operator *(SqlInt64 x, SqlInt64 y) { if (x.IsNull || y.IsNull) { return(Null); } bool fNeg = false; long lOp1 = x.m_value; long lOp2 = y.m_value; long lResult; long lPartialResult = 0; if (lOp1 < 0) { fNeg = true; lOp1 = -lOp1; } if (lOp2 < 0) { fNeg = !fNeg; lOp2 = -lOp2; } long lLow1 = lOp1 & x_lLowIntMask; long lHigh1 = (lOp1 >> 32) & x_lLowIntMask; long lLow2 = lOp2 & x_lLowIntMask; long lHigh2 = (lOp2 >> 32) & x_lLowIntMask; // if both of the high order dwords are non-zero then overflow results if (lHigh1 != 0 && lHigh2 != 0) { throw new OverflowException(SQLResource.ArithOverflowMessage); } lResult = lLow1 * lLow2; if (lResult < 0) { throw new OverflowException(SQLResource.ArithOverflowMessage); } if (lHigh1 != 0) { SQLDebug.Check(lHigh2 == 0); lPartialResult = lHigh1 * lLow2; if (lPartialResult < 0 || lPartialResult > Int64.MaxValue) { throw new OverflowException(SQLResource.ArithOverflowMessage); } } else if (lHigh2 != 0) { SQLDebug.Check(lHigh1 == 0); lPartialResult = lLow1 * lHigh2; if (lPartialResult < 0 || lPartialResult > Int64.MaxValue) { throw new OverflowException(SQLResource.ArithOverflowMessage); } } lResult += lPartialResult << 32; if (lResult < 0) { throw new OverflowException(SQLResource.ArithOverflowMessage); } if (fNeg) { lResult = -lResult; } return(new SqlInt64(lResult)); }