| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959 |
- //------------------------------------------------------------------------------
- // <copyright file="SqlDataReader.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">[....]</owner>
- // <owner current="true" primary="false">[....]</owner>
- // <owner current="true" primary="false">[....]</owner>
- //------------------------------------------------------------------------------
- namespace System.Data.SqlClient {
- using System.Threading;
- using System.Diagnostics;
- using System.Reflection;
- using System;
- using System.Data;
- using System.IO;
- using System.Collections;
- using System.Collections.Specialized;
- using System.Data.Sql;
- using System.Data.SqlTypes;
- using System.Data.Common;
- using System.Data.ProviderBase;
- using System.ComponentModel;
- using System.Globalization;
- using System.Xml;
- using System.Runtime.InteropServices;
- internal sealed class SqlBuffer {
- internal enum StorageType {
- Empty = 0,
- Boolean,
- Byte,
- DateTime,
- Decimal,
- Double,
- Int16,
- Int32,
- Int64,
- Money,
- Single,
- String,
- SqlBinary,
- SqlCachedBuffer,
- SqlGuid,
- SqlXml,
- Date,
- DateTime2,
- DateTimeOffset,
- Time,
- }
- internal struct DateTimeInfo {
- // This is used to store DateTime
- internal Int32 daypart;
- internal Int32 timepart;
- }
- internal struct NumericInfo {
- // This is used to store Decimal data
- internal Int32 data1;
- internal Int32 data2;
- internal Int32 data3;
- internal Int32 data4;
- internal Byte precision;
- internal Byte scale;
- internal Boolean positive;
- }
- internal struct TimeInfo {
- internal Int64 ticks;
- internal byte scale;
- }
- internal struct DateTime2Info {
- internal Int32 date;
- internal TimeInfo timeInfo;
- }
- internal struct DateTimeOffsetInfo {
- internal DateTime2Info dateTime2Info;
- internal Int16 offset;
- }
- [StructLayout(LayoutKind.Explicit)]
- internal struct Storage {
- [FieldOffset(0)] internal Boolean _boolean;
- [FieldOffset(0)] internal Byte _byte;
- [FieldOffset(0)] internal DateTimeInfo _dateTimeInfo;
- [FieldOffset(0)] internal Double _double;
- [FieldOffset(0)] internal NumericInfo _numericInfo;
- [FieldOffset(0)] internal Int16 _int16;
- [FieldOffset(0)] internal Int32 _int32;
- [FieldOffset(0)] internal Int64 _int64; // also used to store Money, UtcDateTime, Date , and Time
- [FieldOffset(0)] internal Single _single;
- [FieldOffset(0)] internal TimeInfo _timeInfo;
- [FieldOffset(0)] internal DateTime2Info _dateTime2Info;
- [FieldOffset(0)] internal DateTimeOffsetInfo _dateTimeOffsetInfo;
- }
- private bool _isNull;
- private StorageType _type;
- private Storage _value;
- private object _object; // String, SqlBinary, SqlCachedBuffer, SqlGuid, SqlString, SqlXml
- internal SqlBuffer() {
- }
- private SqlBuffer(SqlBuffer value) { // Clone
- // value types
- _isNull = value._isNull;
- _type = value._type;
- // ref types - should also be read only unless at some point we allow this data
- // to be mutable, then we will need to copy
- _value = value._value;
- _object = value._object;
- }
- internal bool IsEmpty {
- get {
- return (StorageType.Empty == _type);
- }
- }
- internal bool IsNull {
- get {
- return _isNull;
- }
- }
- internal StorageType VariantInternalStorageType
- {
- get { return _type; }
- }
- internal Boolean Boolean {
- get {
- ThrowIfNull();
- if (StorageType.Boolean == _type) {
- return _value._boolean;
- }
- return (Boolean)this.Value; // anything else we haven't thought of goes through boxing.
- }
- set {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _value._boolean = value;
- _type = StorageType.Boolean;
- _isNull = false;
- }
- }
- internal Byte Byte {
- get {
- ThrowIfNull();
- if (StorageType.Byte == _type) {
- return _value._byte;
- }
- return (Byte)this.Value; // anything else we haven't thought of goes through boxing.
- }
- set {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _value._byte = value;
- _type = StorageType.Byte;
- _isNull = false;
- }
- }
- internal Byte[] ByteArray {
- get {
- ThrowIfNull();
- return this.SqlBinary.Value; //
- }
- }
- internal DateTime DateTime {
- get {
- ThrowIfNull();
- if (StorageType.Date == _type) {
- return DateTime.MinValue.AddDays(_value._int32);
- }
- if (StorageType.DateTime2 == _type) {
- return new DateTime(GetTicksFromDateTime2Info(_value._dateTime2Info));
- }
- if (StorageType.DateTime == _type) {
- return SqlDateTime.ToDateTime(_value._dateTimeInfo.daypart, _value._dateTimeInfo.timepart);
- }
- return (DateTime)this.Value; // anything else we haven't thought of goes through boxing.
- }
- }
- internal Decimal Decimal {
- get {
- ThrowIfNull();
- if (StorageType.Decimal == _type) {
- if (_value._numericInfo.data4 != 0 || _value._numericInfo.scale > 28) {
- throw new OverflowException(SQLResource.ConversionOverflowMessage);
- }
- return new Decimal(_value._numericInfo.data1, _value._numericInfo.data2, _value._numericInfo.data3, !_value._numericInfo.positive, _value._numericInfo.scale);
- }
- if (StorageType.Money == _type) {
- long l = _value._int64;
- bool isNegative = false;
- if (l < 0) {
- isNegative = true;
- l = -l;
- }
- return new Decimal((int)(l & 0xffffffff), (int)(l >> 32), 0, isNegative, 4);
- }
- return (Decimal)this.Value; // anything else we haven't thought of goes through boxing.
- }
- }
- internal Double Double {
- get {
- ThrowIfNull();
- if (StorageType.Double == _type) {
- return _value._double;
- }
- return (Double)this.Value; // anything else we haven't thought of goes through boxing.
- }
- set {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _value._double = value;
- _type = StorageType.Double;
- _isNull = false;
- }
- }
- internal Guid Guid {
- get {
- //
- ThrowIfNull();
- return this.SqlGuid.Value;
- }
- }
- internal Int16 Int16 {
- get {
- ThrowIfNull();
- if (StorageType.Int16 == _type) {
- return _value._int16;
- }
- return (Int16)this.Value; // anything else we haven't thought of goes through boxing.
- }
- set {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _value._int16 = value;
- _type = StorageType.Int16;
- _isNull = false;
- }
- }
- internal Int32 Int32 {
- get {
- ThrowIfNull();
- if (StorageType.Int32 == _type) {
- return _value._int32;
- }
- return (Int32)this.Value; // anything else we haven't thought of goes through boxing.
- }
- set {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _value._int32 = value;
- _type = StorageType.Int32;
- _isNull = false;
- }
- }
- internal Int64 Int64 {
- get {
- ThrowIfNull();
- if (StorageType.Int64 == _type) {
- return _value._int64;
- }
- return (Int64)this.Value; // anything else we haven't thought of goes through boxing.
- }
- set {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _value._int64 = value;
- _type = StorageType.Int64;
- _isNull = false;
- }
- }
- internal Single Single {
- get {
- ThrowIfNull();
- if (StorageType.Single == _type) {
- return _value._single;
- }
- return (Single)this.Value; // anything else we haven't thought of goes through boxing.
- }
- set {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _value._single = value;
- _type = StorageType.Single;
- _isNull = false;
- }
- }
- internal String String {
- get {
- ThrowIfNull();
- if (StorageType.String == _type) {
- return (String)_object;
- }
- else if (StorageType.SqlCachedBuffer == _type) {
- return ((SqlCachedBuffer)(_object)).ToString();
- }
- return (String)this.Value; // anything else we haven't thought of goes through boxing.
- }
- }
- // use static list of format strings indexed by scale for perf!
- private static string[] __katmaiDateTimeOffsetFormatByScale = new string[] {
- "yyyy-MM-dd HH:mm:ss zzz",
- "yyyy-MM-dd HH:mm:ss.f zzz",
- "yyyy-MM-dd HH:mm:ss.ff zzz",
- "yyyy-MM-dd HH:mm:ss.fff zzz",
- "yyyy-MM-dd HH:mm:ss.ffff zzz",
- "yyyy-MM-dd HH:mm:ss.fffff zzz",
- "yyyy-MM-dd HH:mm:ss.ffffff zzz",
- "yyyy-MM-dd HH:mm:ss.fffffff zzz",
- };
- private static string[] __katmaiDateTime2FormatByScale = new string[] {
- "yyyy-MM-dd HH:mm:ss",
- "yyyy-MM-dd HH:mm:ss.f",
- "yyyy-MM-dd HH:mm:ss.ff",
- "yyyy-MM-dd HH:mm:ss.fff",
- "yyyy-MM-dd HH:mm:ss.ffff",
- "yyyy-MM-dd HH:mm:ss.fffff",
- "yyyy-MM-dd HH:mm:ss.ffffff",
- "yyyy-MM-dd HH:mm:ss.fffffff",
- };
- private static string[] __katmaiTimeFormatByScale = new string[] {
- "HH:mm:ss",
- "HH:mm:ss.f",
- "HH:mm:ss.ff",
- "HH:mm:ss.fff",
- "HH:mm:ss.ffff",
- "HH:mm:ss.fffff",
- "HH:mm:ss.ffffff",
- "HH:mm:ss.fffffff",
- };
- internal string KatmaiDateTimeString {
- get {
- ThrowIfNull();
- if (StorageType.Date == _type) {
- return this.DateTime.ToString("yyyy-MM-dd", DateTimeFormatInfo.InvariantInfo);
- }
- if (StorageType.Time == _type) {
- byte scale = _value._timeInfo.scale;
- return new DateTime(_value._timeInfo.ticks).ToString(__katmaiTimeFormatByScale[scale], DateTimeFormatInfo.InvariantInfo);
- }
- if (StorageType.DateTime2 == _type) {
- byte scale = _value._dateTime2Info.timeInfo.scale;
- return this.DateTime.ToString(__katmaiDateTime2FormatByScale[scale], DateTimeFormatInfo.InvariantInfo);
- }
- if (StorageType.DateTimeOffset == _type) {
- DateTimeOffset dto = this.DateTimeOffset;
- byte scale = _value._dateTimeOffsetInfo.dateTime2Info.timeInfo.scale;
- return dto.ToString(__katmaiDateTimeOffsetFormatByScale[scale], DateTimeFormatInfo.InvariantInfo);
- }
- return (String)this.Value; // anything else we haven't thought of goes through boxing.
- }
- }
- internal SqlString KatmaiDateTimeSqlString {
- get {
- if (StorageType.Date == _type ||
- StorageType.Time == _type ||
- StorageType.DateTime2 == _type ||
- StorageType.DateTimeOffset == _type) {
- if (IsNull) {
- return SqlString.Null;
- }
- return new SqlString(KatmaiDateTimeString);
- }
- return (SqlString)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal TimeSpan Time {
- get {
- ThrowIfNull();
- if (StorageType.Time == _type) {
- return new TimeSpan(_value._timeInfo.ticks);
- }
- return (TimeSpan)this.Value; // anything else we haven't thought of goes through boxing.
- }
- }
- internal DateTimeOffset DateTimeOffset {
- get {
- ThrowIfNull();
- if (StorageType.DateTimeOffset == _type) {
- TimeSpan offset = new TimeSpan(0, _value._dateTimeOffsetInfo.offset, 0);
- // datetime part presents time in UTC
- return new DateTimeOffset(GetTicksFromDateTime2Info(_value._dateTimeOffsetInfo.dateTime2Info) + offset.Ticks, offset);
- }
- return (DateTimeOffset)this.Value; // anything else we haven't thought of goes through boxing.
- }
- }
- private static long GetTicksFromDateTime2Info(DateTime2Info dateTime2Info) {
- return (dateTime2Info.date * TimeSpan.TicksPerDay + dateTime2Info.timeInfo.ticks);
- }
- internal SqlBinary SqlBinary {
- get {
- if (StorageType.SqlBinary == _type) {
- return (SqlBinary)_object;
- }
- return (SqlBinary)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- set {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _object = value;
- _type = StorageType.SqlBinary;
- _isNull = value.IsNull;
- }
- }
- internal SqlBoolean SqlBoolean {
- get {
- if (StorageType.Boolean == _type) {
- if (IsNull) {
- return SqlBoolean.Null;
- }
- return new SqlBoolean(_value._boolean);
- }
- return (SqlBoolean)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal SqlByte SqlByte {
- get {
- if (StorageType.Byte == _type) {
- if (IsNull) {
- return SqlByte.Null;
- }
- return new SqlByte(_value._byte);
- }
- return (SqlByte)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal SqlCachedBuffer SqlCachedBuffer {
- get {
- if (StorageType.SqlCachedBuffer == _type) {
- if (IsNull) {
- return SqlCachedBuffer.Null;
- }
- return (SqlCachedBuffer)_object;
- }
- return (SqlCachedBuffer)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- set {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _object = value;
- _type = StorageType.SqlCachedBuffer;
- _isNull = value.IsNull;
- }
- }
- internal SqlXml SqlXml {
- get {
- if (StorageType.SqlXml == _type) {
- if (IsNull) {
- return SqlXml.Null;
- }
- return (SqlXml)_object;
- }
- return (SqlXml)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- set {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _object = value;
- _type = StorageType.SqlXml;
- _isNull = value.IsNull;
- }
- }
- internal SqlDateTime SqlDateTime {
- get {
- if (StorageType.DateTime == _type) {
- if (IsNull) {
- return SqlDateTime.Null;
- }
- return new SqlDateTime(_value._dateTimeInfo.daypart, _value._dateTimeInfo.timepart);
- }
- return (SqlDateTime)SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal SqlDecimal SqlDecimal {
- get {
- if (StorageType.Decimal == _type) {
- if (IsNull) {
- return SqlDecimal.Null;
- }
- return new SqlDecimal(_value._numericInfo.precision,
- _value._numericInfo.scale,
- _value._numericInfo.positive,
- _value._numericInfo.data1,
- _value._numericInfo.data2,
- _value._numericInfo.data3,
- _value._numericInfo.data4
- );
- }
- return (SqlDecimal)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal SqlDouble SqlDouble {
- get {
- if (StorageType.Double == _type) {
- if (IsNull) {
- return SqlDouble.Null;
- }
- return new SqlDouble(_value._double);
- }
- return (SqlDouble)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal SqlGuid SqlGuid {
- get {
- if (StorageType.SqlGuid == _type) {
- return (SqlGuid)_object;
- }
- return (SqlGuid)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- set {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _object = value;
- _type = StorageType.SqlGuid;
- _isNull = value.IsNull;
- }
- }
- internal SqlInt16 SqlInt16 {
- get {
- if (StorageType.Int16 == _type) {
- if (IsNull) {
- return SqlInt16.Null;
- }
- return new SqlInt16(_value._int16);
- }
- return (SqlInt16)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal SqlInt32 SqlInt32 {
- get {
- if (StorageType.Int32 == _type) {
- if (IsNull) {
- return SqlInt32.Null;
- }
- return new SqlInt32(_value._int32);
- }
- return (SqlInt32)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal SqlInt64 SqlInt64 {
- get {
- if (StorageType.Int64 == _type) {
- if (IsNull) {
- return SqlInt64.Null;
- }
- return new SqlInt64(_value._int64);
- }
- return (SqlInt64)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal SqlMoney SqlMoney {
- get {
- if (StorageType.Money == _type) {
- if (IsNull) {
- return SqlMoney.Null;
- }
- return new SqlMoney(_value._int64, 1/*ignored*/);
- }
- return (SqlMoney)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal SqlSingle SqlSingle {
- get {
- if (StorageType.Single == _type) {
- if (IsNull) {
- return SqlSingle.Null;
- }
- return new SqlSingle(_value._single);
- }
- return (SqlSingle)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal SqlString SqlString {
- get {
- if (StorageType.String == _type) {
- if (IsNull) {
- return SqlString.Null;
- }
- return new SqlString((String)_object);
- }
- else if (StorageType.SqlCachedBuffer == _type) {
- SqlCachedBuffer data = (SqlCachedBuffer)(_object);
- if (data.IsNull) {
- return SqlString.Null;
- }
- return data.ToSqlString();
- }
- return (SqlString)this.SqlValue; // anything else we haven't thought of goes through boxing.
- }
- }
- internal object SqlValue {
- get {
- switch (_type) {
- case StorageType.Empty: return DBNull.Value;
- case StorageType.Boolean: return SqlBoolean;
- case StorageType.Byte: return SqlByte;
- case StorageType.DateTime: return SqlDateTime;
- case StorageType.Decimal: return SqlDecimal;
- case StorageType.Double: return SqlDouble;
- case StorageType.Int16: return SqlInt16;
- case StorageType.Int32: return SqlInt32;
- case StorageType.Int64: return SqlInt64;
- case StorageType.Money: return SqlMoney;
- case StorageType.Single: return SqlSingle;
- case StorageType.String: return SqlString;
- case StorageType.SqlCachedBuffer:
- {
- SqlCachedBuffer data = (SqlCachedBuffer)(_object);
- if (data.IsNull) {
- return SqlXml.Null;
- }
- return data.ToSqlXml();
- }
- case StorageType.SqlBinary:
- case StorageType.SqlGuid:
- return _object;
- case StorageType.SqlXml: {
- if (_isNull) {
- return SqlXml.Null;
- }
- Debug.Assert(null != _object);
- return (SqlXml) _object;
- }
- case StorageType.Date:
- case StorageType.DateTime2:
- if (_isNull) {
- return DBNull.Value;
- }
- return DateTime;
- case StorageType.DateTimeOffset:
- if (_isNull) {
- return DBNull.Value;
- }
- return DateTimeOffset;
- case StorageType.Time:
- if (_isNull) {
- return DBNull.Value;
- }
- return Time;
- }
- return null; // need to return the value as an object of some SQL type
- }
- }
- internal object Value {
- get {
- if (IsNull) {
- return DBNull.Value;
- }
- switch (_type) {
- case StorageType.Empty: return DBNull.Value;
- case StorageType.Boolean: return Boolean;
- case StorageType.Byte: return Byte;
- case StorageType.DateTime: return DateTime;
- case StorageType.Decimal: return Decimal;
- case StorageType.Double: return Double;
- case StorageType.Int16: return Int16;
- case StorageType.Int32: return Int32;
- case StorageType.Int64: return Int64;
- case StorageType.Money: return Decimal;
- case StorageType.Single: return Single;
- case StorageType.String: return String;
- case StorageType.SqlBinary: return ByteArray;
- case StorageType.SqlCachedBuffer:
- {
- // If we have a CachedBuffer, it's because it's an XMLTYPE column
- // and we have to return a string when they're asking for the CLS
- // value of the column.
- return ((SqlCachedBuffer)(_object)).ToString();
- }
- case StorageType.SqlGuid: return Guid;
- case StorageType.SqlXml: {
- // XMLTYPE columns must be returned as string when asking for the CLS value
- SqlXml data = (SqlXml)_object;
- string s = data.Value;
- return s;
- }
- case StorageType.Date: return DateTime;
- case StorageType.DateTime2: return DateTime;
- case StorageType.DateTimeOffset: return DateTimeOffset;
- case StorageType.Time: return Time;
- }
- return null; // need to return the value as an object of some CLS type
- }
- }
- internal Type GetTypeFromStorageType (bool isSqlType) {
- if (isSqlType) {
- switch (_type) {
- case SqlBuffer.StorageType.Empty: return null;
- case SqlBuffer.StorageType.Boolean: return typeof(SqlBoolean);
- case SqlBuffer.StorageType.Byte: return typeof(SqlByte);
- case SqlBuffer.StorageType.DateTime: return typeof(SqlDateTime);
- case SqlBuffer.StorageType.Decimal: return typeof(SqlDecimal);
- case SqlBuffer.StorageType.Double: return typeof(SqlDouble);
- case SqlBuffer.StorageType.Int16: return typeof(SqlInt16);
- case SqlBuffer.StorageType.Int32: return typeof(SqlInt32);
- case SqlBuffer.StorageType.Int64: return typeof(SqlInt64);
- case SqlBuffer.StorageType.Money: return typeof(SqlMoney);
- case SqlBuffer.StorageType.Single: return typeof(SqlSingle);
- case SqlBuffer.StorageType.String: return typeof(SqlString);
- case SqlBuffer.StorageType.SqlCachedBuffer: return typeof(SqlString);
- case SqlBuffer.StorageType.SqlBinary: return typeof(object);
- case SqlBuffer.StorageType.SqlGuid: return typeof(object);
- case SqlBuffer.StorageType.SqlXml: return typeof(SqlXml);
- }
- }
- else { //Is CLR Type
- switch (_type) {
- case SqlBuffer.StorageType.Empty: return null;
- case SqlBuffer.StorageType.Boolean: return typeof(Boolean);
- case SqlBuffer.StorageType.Byte: return typeof(Byte);
- case SqlBuffer.StorageType.DateTime: return typeof(DateTime);
- case SqlBuffer.StorageType.Decimal: return typeof(Decimal);
- case SqlBuffer.StorageType.Double: return typeof(Double);
- case SqlBuffer.StorageType.Int16: return typeof(Int16);
- case SqlBuffer.StorageType.Int32: return typeof(Int32);
- case SqlBuffer.StorageType.Int64: return typeof(Int64);
- case SqlBuffer.StorageType.Money: return typeof(Decimal);
- case SqlBuffer.StorageType.Single: return typeof(Single);
- case SqlBuffer.StorageType.String: return typeof(String);
- case SqlBuffer.StorageType.SqlBinary: return typeof(Byte[]);
- case SqlBuffer.StorageType.SqlCachedBuffer: return typeof(string);
- case SqlBuffer.StorageType.SqlGuid: return typeof(Guid);
- case SqlBuffer.StorageType.SqlXml: return typeof(string);
- }
- }
- return null; // need to return the value as an object of some CLS type
- }
- internal static SqlBuffer[] CreateBufferArray(int length) {
- SqlBuffer[] buffers = new SqlBuffer[length];
- for(int i = 0; i < buffers.Length; ++i) {
- buffers[i] = new SqlBuffer();
- }
- return buffers;
- }
- internal static SqlBuffer[] CloneBufferArray(SqlBuffer[] values) {
- SqlBuffer[] copy = new SqlBuffer[values.Length];
- for (int i=0; i<values.Length; i++) {
- copy[i] = new SqlBuffer(values[i]);
- }
- return copy;
- }
- internal static void Clear(SqlBuffer[] values) {
- if (null != values) {
- for(int i = 0; i < values.Length; ++i) {
- values[i].Clear();
- }
- }
- }
- internal void Clear() {
- _isNull = false;
- _type = StorageType.Empty;
- _object = null;
- }
- internal void SetToDateTime(int daypart, int timepart) {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _value._dateTimeInfo.daypart = daypart;
- _value._dateTimeInfo.timepart = timepart;
- _type = StorageType.DateTime;
- _isNull = false;
- }
- internal void SetToDecimal(byte precision, byte scale, bool positive, int[] bits) {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _value._numericInfo.precision = precision;
- _value._numericInfo.scale = scale;
- _value._numericInfo.positive = positive;
- _value._numericInfo.data1 = bits[0];
- _value._numericInfo.data2 = bits[1];
- _value._numericInfo.data3 = bits[2];
- _value._numericInfo.data4 = bits[3];
- _type = StorageType.Decimal;
- _isNull = false;
- }
- internal void SetToMoney(long value) {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _value._int64 = value;
- _type = StorageType.Money;
- _isNull = false;
- }
- internal void SetToNullOfType(StorageType storageType) {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _type = storageType;
- _isNull = true;
- _object = null;
- }
- internal void SetToString(string value) {
- Debug.Assert (IsEmpty, "setting value a second time?");
- _object = value;
- _type = StorageType.String;
- _isNull = false;
- }
- internal void SetToDate(byte[] bytes) {
- Debug.Assert(IsEmpty, "setting value a second time?");
- _type = StorageType.Date;
- _value._int32 = GetDateFromByteArray(bytes, 0);
- _isNull = false;
- }
- internal void SetToDate(DateTime date) {
- Debug.Assert(IsEmpty, "setting value a second time?");
- _type = StorageType.Date;
- _value._int32 = date.Subtract(DateTime.MinValue).Days;
- _isNull = false;
- }
- internal void SetToTime(byte[] bytes, int length, byte scale, byte denormalizedScale) {
- Debug.Assert(IsEmpty, "setting value a second time?");
- _type = StorageType.Time;
- FillInTimeInfo(ref _value._timeInfo, bytes, length, scale, denormalizedScale);
- _isNull = false;
- }
- internal void SetToTime(TimeSpan timeSpan, byte scale) {
- Debug.Assert(IsEmpty, "setting value a second time?");
- _type = StorageType.Time;
- _value._timeInfo.ticks = timeSpan.Ticks;
- _value._timeInfo.scale = scale;
- _isNull = false;
- }
- internal void SetToDateTime2(byte[] bytes, int length, byte scale, byte denormalizedScale) {
- Debug.Assert(IsEmpty, "setting value a second time?");
- _type = StorageType.DateTime2;
- FillInTimeInfo(ref _value._dateTime2Info.timeInfo, bytes, length - 3, scale, denormalizedScale); // remaining 3 bytes is for date
- _value._dateTime2Info.date = GetDateFromByteArray(bytes, length - 3); // 3 bytes for date
- _isNull = false;
- }
- internal void SetToDateTime2(DateTime dateTime, byte scale) {
- Debug.Assert(IsEmpty, "setting value a second time?");
- _type = StorageType.DateTime2;
- _value._dateTime2Info.timeInfo.ticks = dateTime.TimeOfDay.Ticks;
- _value._dateTime2Info.timeInfo.scale = scale;
- _value._dateTime2Info.date = dateTime.Subtract(DateTime.MinValue).Days;
- _isNull = false;
- }
- internal void SetToDateTimeOffset(byte[] bytes, int length, byte scale, byte denormalizedScale) {
- Debug.Assert(IsEmpty, "setting value a second time?");
- _type = StorageType.DateTimeOffset;
- FillInTimeInfo(ref _value._dateTimeOffsetInfo.dateTime2Info.timeInfo, bytes, length - 5, scale, denormalizedScale); // remaining 5 bytes are for date and offset
- _value._dateTimeOffsetInfo.dateTime2Info.date = GetDateFromByteArray(bytes, length - 5); // 3 bytes for date
- _value._dateTimeOffsetInfo.offset = (Int16)(bytes[length - 2] + (bytes[length - 1] << 8)); // 2 bytes for offset (Int16)
- _isNull = false;
- }
- internal void SetToDateTimeOffset(DateTimeOffset dateTimeOffset, byte scale) {
- Debug.Assert(IsEmpty, "setting value a second time?");
- _type = StorageType.DateTimeOffset;
- DateTime utcDateTime = dateTimeOffset.UtcDateTime; // timeInfo stores the utc datetime of a datatimeoffset
- _value._dateTimeOffsetInfo.dateTime2Info.timeInfo.ticks = utcDateTime.TimeOfDay.Ticks;
- _value._dateTimeOffsetInfo.dateTime2Info.timeInfo.scale = scale;
- _value._dateTimeOffsetInfo.dateTime2Info.date = utcDateTime.Subtract(DateTime.MinValue).Days;
- _value._dateTimeOffsetInfo.offset = (Int16)dateTimeOffset.Offset.TotalMinutes;
- _isNull = false;
- }
- private static void FillInTimeInfo(ref TimeInfo timeInfo, byte[] timeBytes, int length, byte scale, byte denormalizedScale) {
- Debug.Assert(3 <= length && length <= 5, "invalid data length for timeInfo: " + length);
- Debug.Assert(0 <= scale && scale <= 7, "invalid scale: " + scale);
- Debug.Assert(0 <= denormalizedScale && denormalizedScale <= 7, "invalid denormalized scale: " + denormalizedScale);
- Int64 tickUnits = (Int64)timeBytes[0] + ((Int64)timeBytes[1] << 8) + ((Int64)timeBytes[2] << 16);
- if (length > 3) {
- tickUnits += ((Int64)timeBytes[3] << 24);
- }
- if (length > 4) {
- tickUnits += ((Int64)timeBytes[4] << 32);
- }
- timeInfo.ticks = tickUnits * TdsEnums.TICKS_FROM_SCALE[scale];
- // Once the deserialization has been completed using the value scale, we need to set the actual denormalized scale,
- // coming from the data type, on the original result, so that it has the proper scale setting.
- // This only applies for values that got serialized/deserialized for encryption. Otherwise, both scales should be equal.
- timeInfo.scale = denormalizedScale;
- }
- private static Int32 GetDateFromByteArray(byte[] buf, int offset) {
- return buf[offset] + (buf[offset + 1] << 8) + (buf[offset + 2] << 16);
- }
- private void ThrowIfNull() {
- if (IsNull) {
- throw new SqlNullValueException();
- }
- }
- }
- }// namespace
|