1 //------------------------------------------------------------------------------
2 // <copyright file="SqlEnums.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 //------------------------------------------------------------------------------
8 
9 namespace System.Data.SqlClient {
10 
11 
12     using System;
13     using System.Collections.Generic;
14     using System.ComponentModel;
15     using System.Data.Common;
16     using System.Data.OleDb;
17     using System.Data.SqlTypes;
18     using System.Diagnostics;
19     using System.Globalization;
20     using System.Xml;
21     using System.IO;
22     using System.Data.Sql;
23 
24     using MSS=Microsoft.SqlServer.Server;
25 
26     internal sealed class MetaType {
27         internal readonly Type      ClassType;   // com+ type
28         internal readonly Type      SqlType;
29 
30         internal readonly int       FixedLength; // fixed length size in bytes (-1 for variable)
31         internal readonly bool      IsFixed;     // true if fixed length, note that sqlchar and sqlbinary are not considered fixed length
32         internal readonly bool      IsLong;      // true if long
33         internal readonly bool      IsPlp;       // Column is Partially Length Prefixed (MAX)
34         internal readonly byte      Precision;   // maxium precision for numeric types // $
35         internal readonly byte      Scale;
36         internal readonly byte      TDSType;
37         internal readonly byte      NullableType;
38 
39         internal readonly string    TypeName;    // string name of this type
40         internal readonly SqlDbType SqlDbType;
41         internal readonly DbType    DbType;
42 
43         //  holds count of property bytes expected for a SQLVariant structure
44         internal readonly byte PropBytes;
45 
46 
47         // pre-computed fields
48         internal readonly bool IsAnsiType;
49         internal readonly bool IsBinType;
50         internal readonly bool IsCharType;
51         internal readonly bool IsNCharType;
52         internal readonly bool IsSizeInCharacters;
53         internal readonly bool IsNewKatmaiType;
54         internal readonly bool IsVarTime;
55 
56         internal readonly bool Is70Supported;
57         internal readonly bool Is80Supported;
58         internal readonly bool Is90Supported;
59         internal readonly bool Is100Supported;
60 
MetaType(byte precision, byte scale, int fixedLength, bool isFixed, bool isLong, bool isPlp, byte tdsType, byte nullableTdsType, string typeName, Type classType, Type sqlType, SqlDbType sqldbType, DbType dbType, byte propBytes)61         public MetaType(byte precision, byte scale, int fixedLength, bool isFixed, bool isLong, bool isPlp, byte tdsType, byte nullableTdsType, string typeName, Type classType, Type sqlType, SqlDbType sqldbType, DbType dbType, byte propBytes) {
62             this.Precision    = precision;
63             this.Scale        = scale;
64             this.FixedLength  = fixedLength;
65             this.IsFixed      = isFixed;
66             this.IsLong       = isLong;
67             this.IsPlp        = isPlp;
68             // can we get rid of this (?just have a mapping?)
69             this.TDSType      = tdsType;
70             this.NullableType = nullableTdsType;
71             this.TypeName     = typeName;
72             this.SqlDbType    = sqldbType;
73             this.DbType       = dbType;
74 
75             this.ClassType    = classType;
76             this.SqlType      = sqlType;
77             this.PropBytes    = propBytes;
78 
79             IsAnsiType  = _IsAnsiType(sqldbType);
80             IsBinType   = _IsBinType(sqldbType);
81             IsCharType  = _IsCharType(sqldbType);
82             IsNCharType = _IsNCharType(sqldbType);
83             IsSizeInCharacters = _IsSizeInCharacters(sqldbType);
84             IsNewKatmaiType = _IsNewKatmaiType(sqldbType);
85             IsVarTime = _IsVarTime(sqldbType);
86 
87             Is70Supported = _Is70Supported(SqlDbType);
88             Is80Supported = _Is80Supported(SqlDbType);
89             Is90Supported = _Is90Supported(SqlDbType);
90             Is100Supported = _Is100Supported(SqlDbType);
91         }
92 
93         // properties should be inlined so there should be no perf penalty for using these accessor functions
94         public int TypeId {             // partial length prefixed (xml, nvarchar(max),...)
95             get { return 0;}
96         }
97 
_IsAnsiType(SqlDbType type)98         private static bool _IsAnsiType(SqlDbType type) {
99             return(type == SqlDbType.Char ||
100                    type == SqlDbType.VarChar ||
101                    type == SqlDbType.Text);
102         }
103 
104         // is this type size expressed as count of characters or bytes?
_IsSizeInCharacters(SqlDbType type)105         private static bool _IsSizeInCharacters(SqlDbType type) {
106             return(type == SqlDbType.NChar ||
107                    type == SqlDbType.NVarChar ||
108                    type == SqlDbType.Xml ||
109                    type == SqlDbType.NText);
110         }
111 
_IsCharType(SqlDbType type)112         private static bool _IsCharType(SqlDbType type) {
113             return(type == SqlDbType.NChar ||
114                    type == SqlDbType.NVarChar ||
115                    type == SqlDbType.NText ||
116                    type == SqlDbType.Char ||
117                    type == SqlDbType.VarChar ||
118                    type == SqlDbType.Text ||
119                    type == SqlDbType.Xml);
120         }
121 
_IsNCharType(SqlDbType type)122         private static bool _IsNCharType(SqlDbType type) {
123             return(type == SqlDbType.NChar ||
124                    type == SqlDbType.NVarChar ||
125                    type == SqlDbType.NText ||
126                    type == SqlDbType.Xml);
127         }
128 
_IsBinType(SqlDbType type)129         private static bool _IsBinType(SqlDbType type) {
130             return(type == SqlDbType.Image ||
131                    type == SqlDbType.Binary ||
132                    type == SqlDbType.VarBinary ||
133                    type == SqlDbType.Timestamp ||
134                    type == SqlDbType.Udt ||
135                    (int) type == 24 /*SqlSmallVarBinary*/);
136         }
137 
_Is70Supported(SqlDbType type)138         private static bool _Is70Supported(SqlDbType type) {
139             return((type != SqlDbType.BigInt) && ((int)type > 0) &&
140                    ((int)type <= (int) SqlDbType.VarChar));
141         }
142 
_Is80Supported(SqlDbType type)143         private static bool _Is80Supported(SqlDbType type) {
144             return((int)type >= 0 &&
145                 ((int)type <= (int) SqlDbType.Variant));
146         }
147 
_Is90Supported(SqlDbType type)148         private static bool _Is90Supported(SqlDbType type) {
149             return _Is80Supported(type) ||
150                     SqlDbType.Xml == type ||
151                     SqlDbType.Udt == type;
152         }
153 
_Is100Supported(SqlDbType type)154         private static bool _Is100Supported(SqlDbType type) {
155             return _Is90Supported(type) ||
156                     SqlDbType.Date == type ||
157                     SqlDbType.Time == type ||
158                     SqlDbType.DateTime2 == type ||
159                     SqlDbType.DateTimeOffset == type;
160         }
161 
_IsNewKatmaiType(SqlDbType type)162         private static bool _IsNewKatmaiType(SqlDbType type) {
163             return SqlDbType.Structured == type;
164         }
165 
_IsVarTime(SqlDbType type)166         internal static bool _IsVarTime(SqlDbType type) {
167             return (type == SqlDbType.Time || type == SqlDbType.DateTime2 || type == SqlDbType.DateTimeOffset);
168         }
169 
170         //
171         // map SqlDbType to MetaType class
172         //
GetMetaTypeFromSqlDbType(SqlDbType target, bool isMultiValued)173         internal static MetaType GetMetaTypeFromSqlDbType(SqlDbType target, bool isMultiValued) { // WebData 113289
174             switch(target) {
175             case SqlDbType.BigInt:            return MetaBigInt;
176             case SqlDbType.Binary:            return MetaBinary;
177             case SqlDbType.Bit:               return MetaBit;
178             case SqlDbType.Char:              return MetaChar;
179             case SqlDbType.DateTime:          return MetaDateTime;
180             case SqlDbType.Decimal:           return MetaDecimal;
181             case SqlDbType.Float:             return MetaFloat;
182             case SqlDbType.Image:             return MetaImage;
183             case SqlDbType.Int:               return MetaInt;
184             case SqlDbType.Money:             return MetaMoney;
185             case SqlDbType.NChar:             return MetaNChar;
186             case SqlDbType.NText:             return MetaNText;
187             case SqlDbType.NVarChar:          return MetaNVarChar;
188             case SqlDbType.Real:              return MetaReal;
189             case SqlDbType.UniqueIdentifier:  return MetaUniqueId;
190             case SqlDbType.SmallDateTime:     return MetaSmallDateTime;
191             case SqlDbType.SmallInt:          return MetaSmallInt;
192             case SqlDbType.SmallMoney:        return MetaSmallMoney;
193             case SqlDbType.Text:              return MetaText;
194             case SqlDbType.Timestamp:         return MetaTimestamp;
195             case SqlDbType.TinyInt:           return MetaTinyInt;
196             case SqlDbType.VarBinary:         return MetaVarBinary;
197             case SqlDbType.VarChar:           return MetaVarChar;
198             case SqlDbType.Variant:           return MetaVariant;
199             case (SqlDbType)TdsEnums.SmallVarBinary: return MetaSmallVarBinary;
200             case SqlDbType.Xml:               return MetaXml;
201             case SqlDbType.Udt:               return MetaUdt;
202             case SqlDbType.Structured:
203                 if (isMultiValued) {
204                     return MetaTable;
205                 }
206                 else {
207                     return MetaSUDT;
208                 }
209             case SqlDbType.Date:              return MetaDate;
210             case SqlDbType.Time:              return MetaTime;
211             case SqlDbType.DateTime2:         return MetaDateTime2;
212             case SqlDbType.DateTimeOffset:    return MetaDateTimeOffset;
213             default:                          throw SQL.InvalidSqlDbType(target);
214             }
215         }
216 
217         //
218         // map DbType to MetaType class
219         //
GetMetaTypeFromDbType(DbType target)220         internal static MetaType GetMetaTypeFromDbType(DbType target) {
221             // if we can't map it, we need to throw
222             switch (target) {
223             case DbType.AnsiString:             return MetaVarChar;
224             case DbType.AnsiStringFixedLength:  return MetaChar;
225             case DbType.Binary:                 return MetaVarBinary;
226             case DbType.Byte:                   return MetaTinyInt;
227             case DbType.Boolean:                return MetaBit;
228             case DbType.Currency:               return MetaMoney;
229             case DbType.Date:
230             case DbType.DateTime:               return MetaDateTime;
231             case DbType.Decimal:                return MetaDecimal;
232             case DbType.Double:                 return MetaFloat;
233             case DbType.Guid:                   return MetaUniqueId;
234             case DbType.Int16:                  return MetaSmallInt;
235             case DbType.Int32:                  return MetaInt;
236             case DbType.Int64:                  return MetaBigInt;
237             case DbType.Object:                 return MetaVariant;
238             case DbType.Single:                 return MetaReal;
239             case DbType.String:                 return MetaNVarChar;
240             case DbType.StringFixedLength:      return MetaNChar;
241             case DbType.Time:                   return MetaDateTime;
242             case DbType.Xml:                    return MetaXml;
243             case DbType.DateTime2:              return MetaDateTime2;
244             case DbType.DateTimeOffset:         return MetaDateTimeOffset;
245             case DbType.SByte:                  // unsupported
246             case DbType.UInt16:
247             case DbType.UInt32:
248             case DbType.UInt64:
249             case DbType.VarNumeric:
250             default:                            throw ADP.DbTypeNotSupported(target, typeof(SqlDbType)); // no direct mapping, error out
251             }
252         }
253 
GetMaxMetaTypeFromMetaType(MetaType mt)254         internal static MetaType GetMaxMetaTypeFromMetaType(MetaType mt) {
255             // if we can't map it, we need to throw
256             switch (mt.SqlDbType) {
257             case SqlDbType.VarBinary:
258             case SqlDbType.Binary:
259                 return MetaMaxVarBinary;
260             case SqlDbType.VarChar:
261             case SqlDbType.Char:
262                 return MetaMaxVarChar;
263             case SqlDbType.NVarChar:
264             case SqlDbType.NChar:
265                 return MetaMaxNVarChar;
266             case SqlDbType.Udt:
267                 //
268                 return MetaMaxUdt;
269             default:
270                 return mt;
271            }
272         }
273 
274         //
275         // map COM+ Type to MetaType class
276         //
GetMetaTypeFromType(Type dataType)277         static internal MetaType GetMetaTypeFromType(Type dataType) {
278             return GetMetaTypeFromValue(dataType, null, false, true);
279         }
GetMetaTypeFromValue(object value, bool streamAllowed=true)280         static internal MetaType GetMetaTypeFromValue(object value, bool streamAllowed=true) {
281             return GetMetaTypeFromValue(value.GetType(), value, true, streamAllowed);
282         }
283 
GetMetaTypeFromValue(Type dataType, object value, bool inferLen, bool streamAllowed)284         static private MetaType GetMetaTypeFromValue(Type dataType, object value, bool inferLen, bool streamAllowed) {
285             switch (Type.GetTypeCode(dataType)) {
286                 case TypeCode.Empty:     throw ADP.InvalidDataType(TypeCode.Empty);
287                 case TypeCode.Object:
288                     if (dataType == typeof(System.Byte[])) {
289                         // mdac 90455 must not default to image if inferLen is false ...
290                         //
291                         if (!inferLen || ((byte[]) value).Length <= TdsEnums.TYPE_SIZE_LIMIT) {
292                             return MetaVarBinary;
293                         }
294                         else {
295                             return MetaImage;
296                         }
297                     }
298                     else if (dataType == typeof(System.Guid)) {
299                         return MetaUniqueId;
300                     }
301                     else if (dataType == typeof(System.Object)) {
302                         return MetaVariant;
303                     } // check sql types now
304                     else if (dataType == typeof(SqlBinary))
305                         return MetaVarBinary;
306                     else if (dataType == typeof(SqlBoolean))
307                         return MetaBit;
308                     else if (dataType == typeof(SqlByte))
309                         return MetaTinyInt;
310                     else if (dataType == typeof(SqlBytes))
311                         return MetaVarBinary;
312                     else if (dataType == typeof(SqlChars))
313                         return  MetaNVarChar; // MDAC 87587
314                     else if (dataType == typeof(SqlDateTime))
315                         return MetaDateTime;
316                     else if (dataType == typeof(SqlDouble))
317                         return MetaFloat;
318                     else if (dataType == typeof(SqlGuid))
319                         return MetaUniqueId;
320                     else if (dataType == typeof(SqlInt16))
321                         return MetaSmallInt;
322                     else if (dataType == typeof(SqlInt32))
323                         return MetaInt;
324                     else if (dataType == typeof(SqlInt64))
325                         return MetaBigInt;
326                     else if (dataType == typeof(SqlMoney))
327                         return MetaMoney;
328                     else if (dataType == typeof(SqlDecimal))
329                         return MetaDecimal;
330                     else if (dataType == typeof(SqlSingle))
331                         return MetaReal;
332                     else if (dataType == typeof(SqlXml))
333                         return MetaXml;
334                     else if (dataType == typeof(SqlString)) {
335                         return ((inferLen && !((SqlString)value).IsNull) ? PromoteStringType(((SqlString)value).Value) : MetaNVarChar); // MDAC 87587
336                     }
337                     else if (dataType == typeof(IEnumerable<DbDataRecord>) || dataType == typeof(DataTable)) {
338                         return MetaTable;
339                     } else if (dataType == typeof(TimeSpan)) {
340                         return MetaTime;
341                     }
342                     else if (dataType == typeof(DateTimeOffset)) {
343                         return MetaDateTimeOffset;
344                     }
345                     else {
346                         // UDT ?
347                         SqlUdtInfo attribs = SqlUdtInfo.TryGetFromType(dataType);
348                         if (attribs != null) {
349                             return MetaUdt;
350                         }
351                         if (streamAllowed) {
352                             // Derived from Stream ?
353                             if (typeof(Stream).IsAssignableFrom(dataType)) {
354                                 return MetaVarBinary;
355                             }
356                             // Derived from TextReader ?
357                             if (typeof(TextReader).IsAssignableFrom(dataType)) {
358                                 return MetaNVarChar;
359                             }
360                             // Derived from XmlReader ?
361                             if (typeof(System.Xml.XmlReader).IsAssignableFrom(dataType)) {
362                                 return MetaXml;
363                             }
364                         }
365                     }
366                     throw ADP.UnknownDataType(dataType);
367 
368                 case TypeCode.DBNull:    throw ADP.InvalidDataType(TypeCode.DBNull);
369                 case TypeCode.Boolean:   return MetaBit;
370                 case TypeCode.Char:      throw ADP.InvalidDataType(TypeCode.Char);
371                 case TypeCode.SByte:     throw ADP.InvalidDataType(TypeCode.SByte);
372                 case TypeCode.Byte:      return MetaTinyInt;
373                 case TypeCode.Int16:     return MetaSmallInt;
374                 case TypeCode.UInt16:    throw ADP.InvalidDataType(TypeCode.UInt16);
375                 case TypeCode.Int32:     return MetaInt;
376                 case TypeCode.UInt32:    throw ADP.InvalidDataType(TypeCode.UInt32);
377                 case TypeCode.Int64:     return MetaBigInt;
378                 case TypeCode.UInt64:    throw ADP.InvalidDataType(TypeCode.UInt64);
379                 case TypeCode.Single:    return MetaReal;
380                 case TypeCode.Double:    return MetaFloat;
381                 case TypeCode.Decimal:   return MetaDecimal;
382                 case TypeCode.DateTime:  return MetaDateTime;
383                 case TypeCode.String:    return (inferLen ? PromoteStringType((string)value) : MetaNVarChar);
384                 default:                 throw ADP.UnknownDataTypeCode(dataType, Type.GetTypeCode(dataType));
385             }
386         }
387 
GetNullSqlValue(Type sqlType)388         internal static object GetNullSqlValue(Type sqlType) {
389             if      (sqlType == typeof(SqlSingle))   return SqlSingle.Null;
390             else if (sqlType == typeof(SqlString))   return SqlString.Null;
391             else if (sqlType == typeof(SqlDouble))   return SqlDouble.Null;
392             else if (sqlType == typeof(SqlBinary))   return SqlBinary.Null;
393             else if (sqlType == typeof(SqlGuid))     return SqlGuid.Null;
394             else if (sqlType == typeof(SqlBoolean))  return SqlBoolean.Null;
395             else if (sqlType == typeof(SqlByte))     return SqlByte.Null;
396             else if (sqlType == typeof(SqlInt16))    return SqlInt16.Null;
397             else if (sqlType == typeof(SqlInt32))    return SqlInt32.Null;
398             else if (sqlType == typeof(SqlInt64))    return SqlInt64.Null;
399             else if (sqlType == typeof(SqlDecimal))  return SqlDecimal.Null;
400             else if (sqlType == typeof(SqlDateTime)) return SqlDateTime.Null;
401             else if (sqlType == typeof(SqlMoney))    return SqlMoney.Null;
402             else if (sqlType == typeof(SqlXml))      return SqlXml.Null;
403             else if (sqlType == typeof(object))      return DBNull.Value;
404             else if (sqlType == typeof(IEnumerable<DbDataRecord>))  return DBNull.Value;
405             else if (sqlType == typeof(DataTable))   return DBNull.Value;
406             else if (sqlType == typeof(DateTime))    return DBNull.Value;
407             else if (sqlType == typeof(TimeSpan))    return DBNull.Value;
408             else if (sqlType == typeof(DateTimeOffset))             return DBNull.Value;
409             else {
410                 Debug.Assert(false, "Unknown SqlType!");
411                 return DBNull.Value;
412             }
413         }
414 
PromoteStringType(string s)415         internal static MetaType PromoteStringType(string s) {
416             int len = s.Length;
417 
418             if ((len << 1) > TdsEnums.TYPE_SIZE_LIMIT) {
419                 return MetaVarChar; // try as var char since we can send a 8K characters
420             }
421             return MetaNVarChar; // send 4k chars, but send as unicode
422         }
423 
GetComValueFromSqlVariant(object sqlVal)424         internal static object GetComValueFromSqlVariant(object sqlVal) {
425             object comVal = null;
426 
427             if (ADP.IsNull(sqlVal))
428                 return comVal;
429 
430             if (sqlVal is SqlSingle)
431                 comVal = ((SqlSingle)sqlVal).Value;
432             else if (sqlVal is SqlString)
433                 comVal = ((SqlString)sqlVal).Value;
434             else if (sqlVal is SqlDouble)
435                 comVal = ((SqlDouble)sqlVal).Value;
436             else if (sqlVal is SqlBinary)
437                 comVal = ((SqlBinary)sqlVal).Value;
438             else if (sqlVal is SqlGuid)
439                 comVal = ((SqlGuid)sqlVal).Value;
440             else if (sqlVal is SqlBoolean)
441                 comVal = ((SqlBoolean)sqlVal).Value;
442             else if (sqlVal is SqlByte)
443                 comVal = ((SqlByte)sqlVal).Value;
444             else if (sqlVal is SqlInt16)
445                 comVal = ((SqlInt16)sqlVal).Value;
446             else if (sqlVal is SqlInt32)
447                 comVal = ((SqlInt32)sqlVal).Value;
448             else if (sqlVal is SqlInt64)
449                 comVal = ((SqlInt64)sqlVal).Value;
450             else if (sqlVal is SqlDecimal)
451                 comVal = ((SqlDecimal)sqlVal).Value;
452             else if (sqlVal is SqlDateTime)
453                 comVal = ((SqlDateTime)sqlVal).Value;
454             else if (sqlVal is SqlMoney)
455                 comVal = ((SqlMoney)sqlVal).Value;
456             else if (sqlVal is SqlXml)
457                 comVal = ((SqlXml)sqlVal).Value;
458             else
459             {
460                 AssertIsUserDefinedTypeInstance(sqlVal, "unknown SqlType class stored in sqlVal");
461             }
462 
463 
464             return comVal;
465         }
466 
467         /// <summary>
468         /// Assert that the supplied object is an instance of a SQL User-Defined Type (UDT).
469         /// </summary>
470         /// <param name="sqlValue">Object instance to be tested.</param>
471         /// <remarks>
472         /// This method is only compiled with debug builds, and it a helper method for the GetComValueFromSqlVariant method defined in this class.
473         ///
474         /// The presence of the SqlUserDefinedTypeAttribute on the object's type
475         /// is used to determine if the object is a UDT instance (if present it is a UDT, else it is not).
476         /// </remarks>
477         /// <exception cref="NullReferenceException">
478         /// If sqlValue is null.  Callers must ensure the object is non-null.
479         /// </exception>
480         [Conditional("DEBUG")]
AssertIsUserDefinedTypeInstance(object sqlValue, string failedAssertMessage)481         private static void AssertIsUserDefinedTypeInstance(object sqlValue, string failedAssertMessage)
482         {
483             Type type = sqlValue.GetType();
484             Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute[] attributes = (Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute[])type.GetCustomAttributes(typeof(Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute), true);
485 
486             Debug.Assert(attributes.Length > 0, failedAssertMessage);
487         }
488 
489         // devnote: This method should not be used with SqlDbType.Date and SqlDbType.DateTime2.
490         //          With these types the values should be used directly as CLR types instead of being converted to a SqlValue
GetSqlValueFromComVariant(object comVal)491         internal static object GetSqlValueFromComVariant(object comVal) {
492             object sqlVal = null;
493             if ((null != comVal) && (DBNull.Value != comVal)) {
494                 if (comVal is float)
495                     sqlVal = new SqlSingle((float)comVal);
496                 else if (comVal is string)
497                     sqlVal = new SqlString((string)comVal);
498                 else if (comVal is double)
499                     sqlVal = new SqlDouble((double)comVal);
500                 else if (comVal is System.Byte[])
501                     sqlVal = new SqlBinary((byte[])comVal);
502                 else if (comVal is System.Char)
503                     sqlVal = new SqlString(((char)comVal).ToString());
504                 else if (comVal is System.Char[])
505                     sqlVal = new SqlChars((System.Char[])comVal);
506                 else if (comVal is System.Guid)
507                     sqlVal = new SqlGuid((Guid)comVal);
508                 else if (comVal is bool)
509                     sqlVal = new SqlBoolean((bool)comVal);
510                 else if (comVal is byte)
511                     sqlVal = new SqlByte((byte)comVal);
512                 else if (comVal is Int16)
513                     sqlVal = new SqlInt16((Int16)comVal);
514                 else if (comVal is Int32)
515                     sqlVal = new SqlInt32((Int32)comVal);
516                 else if (comVal is Int64)
517                     sqlVal = new SqlInt64((Int64)comVal);
518                 else if (comVal is Decimal)
519                     sqlVal = new SqlDecimal((Decimal)comVal);
520                 else if (comVal is DateTime) {
521                     // devnote: Do not use with SqlDbType.Date and SqlDbType.DateTime2. See comment at top of method.
522                     sqlVal = new SqlDateTime((DateTime)comVal);
523                 } else if (comVal is XmlReader)
524                     sqlVal = new SqlXml((XmlReader)comVal);
525                 else if (comVal is TimeSpan || comVal is DateTimeOffset)
526                     sqlVal = comVal;
527 #if DEBUG
528                 else
529                     Debug.Assert(false, "unknown SqlType class stored in sqlVal");
530 #endif
531             }
532             return sqlVal;
533         }
534 
GetSqlDbTypeFromOleDbType(short dbType, string typeName)535         internal static SqlDbType GetSqlDbTypeFromOleDbType(short dbType, string typeName) {
536             SqlDbType sqlType = SqlDbType.Variant;
537             switch ((OleDbType)dbType) {
538                 case OleDbType.BigInt:
539                     sqlType = SqlDbType.BigInt;
540                     break;
541                 case OleDbType.Boolean:
542                     sqlType = SqlDbType.Bit;
543                     break;
544                 case OleDbType.Char:
545                 case OleDbType.VarChar:
546                     // these guys are ambiguous - server sends over DBTYPE_STR in both cases
547                     sqlType = (typeName == MetaTypeName.CHAR) ? SqlDbType.Char : SqlDbType.VarChar;
548                     break;
549                 case OleDbType.Currency:
550                     sqlType = (typeName == MetaTypeName.SMALLMONEY) ? SqlDbType.SmallMoney : SqlDbType.Money;
551                     break;
552                 case OleDbType.Date:
553                 case OleDbType.DBTimeStamp:
554                 case OleDbType.Filetime:
555                     switch (typeName) {
556                        case MetaTypeName.SMALLDATETIME:
557                             sqlType = SqlDbType.SmallDateTime;
558                             break;
559                         case MetaTypeName.DATETIME2:
560                             sqlType = SqlDbType.DateTime2;
561                             break;
562                        default:
563                             sqlType = SqlDbType.DateTime;
564                             break;
565                     }
566                     break;
567                 case OleDbType.Decimal:
568                 case OleDbType.Numeric:
569                     sqlType = SqlDbType.Decimal;
570                     break;
571                 case OleDbType.Double:
572                     sqlType = SqlDbType.Float;
573                     break;
574                 case OleDbType.Guid:
575                     sqlType = SqlDbType.UniqueIdentifier;
576                     break;
577                 case OleDbType.Integer:
578                     sqlType = SqlDbType.Int;
579                     break;
580                 case OleDbType.LongVarBinary:
581                     sqlType = SqlDbType.Image;
582                     break;
583                 case OleDbType.LongVarChar:
584                     sqlType = SqlDbType.Text;
585                     break;
586                 case OleDbType.LongVarWChar:
587                     sqlType = SqlDbType.NText;
588                     break;
589                 case OleDbType.Single:
590                     sqlType = SqlDbType.Real;
591                     break;
592                 case OleDbType.SmallInt:
593                 case OleDbType.UnsignedSmallInt:
594                     sqlType = SqlDbType.SmallInt;
595                     break;
596                 case OleDbType.TinyInt:
597                 case OleDbType.UnsignedTinyInt:
598                     sqlType = SqlDbType.TinyInt;
599                     break;
600                 case OleDbType.VarBinary:
601                 case OleDbType.Binary:
602                     sqlType = (typeName == MetaTypeName.BINARY) ? SqlDbType.Binary : SqlDbType.VarBinary;
603                     break;
604                 case OleDbType.Variant:
605                     sqlType = SqlDbType.Variant;
606                     break;
607                 case OleDbType.VarWChar:
608                 case OleDbType.WChar:
609                 case OleDbType.BSTR:
610                     // these guys are ambiguous - server sends over DBTYPE_WSTR in both cases
611                     // BSTR is always assumed to be NVARCHAR
612                     sqlType = (typeName == MetaTypeName.NCHAR) ? SqlDbType.NChar : SqlDbType.NVarChar;
613                     break;
614                 case OleDbType.DBDate: // Date
615                     sqlType = SqlDbType.Date;
616                     break;
617                 case (OleDbType)132: // Udt
618                     sqlType = SqlDbType.Udt;
619                     break;
620                 case (OleDbType)141: // Xml
621                     sqlType = SqlDbType.Xml;
622                     break;
623                 case (OleDbType)145: // Time
624                     sqlType = SqlDbType.Time;
625                     break;
626                 case (OleDbType)146: // DateTimeOffset
627                     sqlType = SqlDbType.DateTimeOffset;
628                     break;
629                 //
630                 default:
631                     break; // no direct mapping, just use SqlDbType.Variant;
632                 }
633 
634                 return sqlType;
635         }
636 
GetSqlDataType(int tdsType, UInt32 userType, int length)637         internal static MetaType GetSqlDataType(int tdsType, UInt32 userType, int length) {
638             switch (tdsType) {
639             case TdsEnums.SQLMONEYN:            return ((4 == length) ? MetaSmallMoney : MetaMoney);
640             case TdsEnums.SQLDATETIMN:          return ((4 == length) ? MetaSmallDateTime : MetaDateTime);
641             case TdsEnums.SQLINTN:              return ((4 <= length) ? ((4 == length) ? MetaInt : MetaBigInt) : ((2 == length) ? MetaSmallInt : MetaTinyInt));
642             case TdsEnums.SQLFLTN:              return ((4 == length) ? MetaReal : MetaFloat);
643             case TdsEnums.SQLTEXT:              return MetaText;
644             case TdsEnums.SQLVARBINARY:         return MetaSmallVarBinary;
645             case TdsEnums.SQLBIGVARBINARY:      return MetaVarBinary;
646 
647             case TdsEnums.SQLVARCHAR:           //goto TdsEnums.SQLBIGVARCHAR;
648             case TdsEnums.SQLBIGVARCHAR:        return MetaVarChar;
649 
650             case TdsEnums.SQLBINARY:            //goto TdsEnums.SQLBIGBINARY;
651             case TdsEnums.SQLBIGBINARY:         return ((TdsEnums.SQLTIMESTAMP == userType) ? MetaTimestamp : MetaBinary);
652 
653             case TdsEnums.SQLIMAGE:             return MetaImage;
654 
655             case TdsEnums.SQLCHAR:              //goto TdsEnums.SQLBIGCHAR;
656             case TdsEnums.SQLBIGCHAR:           return MetaChar;
657 
658             case TdsEnums.SQLINT1:              return MetaTinyInt;
659 
660             case TdsEnums.SQLBIT:               //goto TdsEnums.SQLBITN;
661             case TdsEnums.SQLBITN:              return MetaBit;
662 
663             case TdsEnums.SQLINT2:              return MetaSmallInt;
664             case TdsEnums.SQLINT4:              return MetaInt;
665             case TdsEnums.SQLINT8:              return MetaBigInt;
666             case TdsEnums.SQLMONEY:             return MetaMoney;
667             case TdsEnums.SQLDATETIME:          return MetaDateTime;
668             case TdsEnums.SQLFLT8:              return MetaFloat;
669             case TdsEnums.SQLFLT4:              return MetaReal;
670             case TdsEnums.SQLMONEY4:            return MetaSmallMoney;
671             case TdsEnums.SQLDATETIM4:          return MetaSmallDateTime;
672 
673             case TdsEnums.SQLDECIMALN:          //goto TdsEnums.SQLNUMERICN;
674             case TdsEnums.SQLNUMERICN:          return MetaDecimal;
675 
676             case TdsEnums.SQLUNIQUEID:          return MetaUniqueId ;
677             case TdsEnums.SQLNCHAR:             return MetaNChar;
678             case TdsEnums.SQLNVARCHAR:          return MetaNVarChar;
679             case TdsEnums.SQLNTEXT:             return MetaNText;
680             case TdsEnums.SQLVARIANT:           return MetaVariant;
681             case TdsEnums.SQLUDT:               return MetaUdt;
682             case TdsEnums.SQLXMLTYPE:           return MetaXml;
683             case TdsEnums.SQLTABLE:             return MetaTable;
684             case TdsEnums.SQLDATE:              return MetaDate;
685             case TdsEnums.SQLTIME:              return MetaTime;
686             case TdsEnums.SQLDATETIME2:         return MetaDateTime2;
687             case TdsEnums.SQLDATETIMEOFFSET:    return MetaDateTimeOffset;
688 
689             case TdsEnums.SQLVOID:
690             default:
691                 Debug.Assert(false, "Unknown type " + tdsType.ToString(CultureInfo.InvariantCulture));
692                 throw SQL.InvalidSqlDbType((SqlDbType)tdsType);
693             }// case
694         }
695 
GetDefaultMetaType()696         internal static MetaType GetDefaultMetaType() {
697             return MetaNVarChar;
698         }
699 
700         // Converts an XmlReader into String
GetStringFromXml(XmlReader xmlreader)701         internal static String GetStringFromXml(XmlReader  xmlreader) {
702             SqlXml sxml = new SqlXml(xmlreader);
703             return sxml.Value;
704         }
705 
706         private static readonly MetaType MetaBigInt = new MetaType
707             (19, 255, 8, true, false, false, TdsEnums.SQLINT8, TdsEnums.SQLINTN, MetaTypeName.BIGINT, typeof(System.Int64), typeof(SqlInt64), SqlDbType.BigInt, DbType.Int64, 0);
708 
709         private static readonly MetaType MetaFloat = new MetaType
710             (15, 255, 8, true, false, false, TdsEnums.SQLFLT8, TdsEnums.SQLFLTN, MetaTypeName.FLOAT, typeof(System.Double), typeof(SqlDouble), SqlDbType.Float, DbType.Double, 0);
711 
712         private static readonly MetaType MetaReal = new MetaType
713             (7, 255, 4, true, false, false, TdsEnums.SQLFLT4, TdsEnums.SQLFLTN, MetaTypeName.REAL, typeof(System.Single), typeof(SqlSingle), SqlDbType.Real, DbType.Single, 0);
714 
715         // MetaBinary has two bytes of properties for binary and varbinary
716         // 2 byte maxlen
717         private static readonly MetaType MetaBinary = new MetaType
718             (255, 255, -1, false, false, false, TdsEnums.SQLBIGBINARY, TdsEnums.SQLBIGBINARY, MetaTypeName.BINARY, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.Binary, DbType.Binary, 2);
719 
720         // syntatic sugar for the user...timestamps are 8-byte fixed length binary columns
721         private static readonly MetaType MetaTimestamp = new MetaType
722             (255, 255, -1, false, false, false, TdsEnums.SQLBIGBINARY, TdsEnums.SQLBIGBINARY, MetaTypeName.TIMESTAMP, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.Timestamp, DbType.Binary, 2);
723 
724         internal static readonly MetaType MetaVarBinary = new MetaType
725             (255, 255, -1, false, false, false, TdsEnums.SQLBIGVARBINARY, TdsEnums.SQLBIGVARBINARY, MetaTypeName.VARBINARY, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.VarBinary, DbType.Binary, 2);
726 
727         internal static readonly MetaType MetaMaxVarBinary = new MetaType
728             (255, 255, -1, false, true, true, TdsEnums.SQLBIGVARBINARY, TdsEnums.SQLBIGVARBINARY, MetaTypeName.VARBINARY, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.VarBinary, DbType.Binary, 2);
729 
730         // HACK!!!  We have an internal type for smallvarbinarys stored on TdsEnums.  We
731         // store on TdsEnums instead of SqlDbType because we do not want to expose
732         // this type to the user!
733         private static readonly MetaType MetaSmallVarBinary = new MetaType
734             (255, 255, -1, false, false, false, TdsEnums.SQLVARBINARY, TdsEnums.SQLBIGBINARY, ADP.StrEmpty, typeof(System.Byte[]), typeof(SqlBinary), TdsEnums.SmallVarBinary, DbType.Binary, 2);
735 
736         internal static readonly MetaType MetaImage = new MetaType
737             (255, 255, -1, false, true, false, TdsEnums.SQLIMAGE, TdsEnums.SQLIMAGE, MetaTypeName.IMAGE, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.Image, DbType.Binary, 0);
738 
739         private static readonly MetaType MetaBit = new MetaType
740             (255, 255, 1, true, false, false, TdsEnums.SQLBIT, TdsEnums.SQLBITN, MetaTypeName.BIT, typeof(System.Boolean), typeof(SqlBoolean), SqlDbType.Bit, DbType.Boolean, 0);
741 
742         private static readonly MetaType MetaTinyInt = new MetaType
743             (3, 255, 1, true, false, false, TdsEnums.SQLINT1, TdsEnums.SQLINTN, MetaTypeName.TINYINT, typeof(System.Byte), typeof(SqlByte), SqlDbType.TinyInt, DbType.Byte, 0);
744 
745         private static readonly MetaType MetaSmallInt = new MetaType
746             (5, 255, 2, true, false, false, TdsEnums.SQLINT2, TdsEnums.SQLINTN, MetaTypeName.SMALLINT, typeof(System.Int16), typeof(SqlInt16), SqlDbType.SmallInt, DbType.Int16, 0);
747 
748         private static readonly MetaType MetaInt = new MetaType
749             (10, 255, 4, true, false, false, TdsEnums.SQLINT4, TdsEnums.SQLINTN, MetaTypeName.INT, typeof(System.Int32), typeof(SqlInt32), SqlDbType.Int, DbType.Int32, 0);
750 
751         // MetaVariant has seven bytes of properties for MetaChar and MetaVarChar
752         // 5 byte tds collation
753         // 2 byte maxlen
754         private static readonly MetaType MetaChar = new MetaType
755             (255, 255, -1, false, false, false, TdsEnums.SQLBIGCHAR, TdsEnums.SQLBIGCHAR, MetaTypeName.CHAR, typeof(System.String), typeof(SqlString), SqlDbType.Char, DbType.AnsiStringFixedLength, 7);
756 
757         private static readonly MetaType MetaVarChar = new MetaType
758             (255, 255, -1, false, false, false, TdsEnums.SQLBIGVARCHAR, TdsEnums.SQLBIGVARCHAR, MetaTypeName.VARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.VarChar, DbType.AnsiString, 7);
759 
760         internal static readonly MetaType MetaMaxVarChar = new MetaType
761             (255, 255, -1, false, true, true, TdsEnums.SQLBIGVARCHAR, TdsEnums.SQLBIGVARCHAR, MetaTypeName.VARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.VarChar, DbType.AnsiString, 7);
762 
763         internal static readonly MetaType MetaText = new MetaType
764             (255, 255, -1, false, true, false, TdsEnums.SQLTEXT, TdsEnums.SQLTEXT, MetaTypeName.TEXT, typeof(System.String), typeof(SqlString), SqlDbType.Text, DbType.AnsiString, 0);
765 
766         // MetaVariant has seven bytes of properties for MetaNChar and MetaNVarChar
767         // 5 byte tds collation
768         // 2 byte maxlen
769         private static readonly MetaType MetaNChar = new MetaType
770             (255, 255, -1, false, false, false, TdsEnums.SQLNCHAR, TdsEnums.SQLNCHAR, MetaTypeName.NCHAR, typeof(System.String), typeof(SqlString), SqlDbType.NChar, DbType.StringFixedLength, 7);
771 
772         internal static readonly MetaType MetaNVarChar = new MetaType
773             (255, 255, -1, false, false, false, TdsEnums.SQLNVARCHAR, TdsEnums.SQLNVARCHAR, MetaTypeName.NVARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.NVarChar, DbType.String, 7);
774 
775         internal static readonly MetaType MetaMaxNVarChar = new MetaType
776             (255, 255, -1, false, true, true, TdsEnums.SQLNVARCHAR, TdsEnums.SQLNVARCHAR, MetaTypeName.NVARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.NVarChar, DbType.String, 7);
777 
778         internal static readonly MetaType MetaNText = new MetaType
779             (255, 255, -1, false, true, false, TdsEnums.SQLNTEXT, TdsEnums.SQLNTEXT, MetaTypeName.NTEXT, typeof(System.String), typeof(SqlString), SqlDbType.NText, DbType.String, 7);
780 
781         // MetaVariant has two bytes of properties for numeric/decimal types
782         // 1 byte precision
783         // 1 byte scale
784         internal static readonly MetaType MetaDecimal = new MetaType
785             (38, 4, 17, true, false, false, TdsEnums.SQLNUMERICN, TdsEnums.SQLNUMERICN, MetaTypeName.DECIMAL, typeof(System.Decimal), typeof(SqlDecimal), SqlDbType.Decimal, DbType.Decimal, 2);
786 
787         internal static readonly MetaType MetaXml = new MetaType
788             (255, 255, -1, false, true, true, TdsEnums.SQLXMLTYPE, TdsEnums.SQLXMLTYPE, MetaTypeName.XML, typeof(System.String), typeof(SqlXml), SqlDbType.Xml, DbType.Xml, 0);
789 
790         private static readonly MetaType MetaDateTime = new MetaType
791             (23, 3, 8, true, false, false, TdsEnums.SQLDATETIME, TdsEnums.SQLDATETIMN, MetaTypeName.DATETIME, typeof(System.DateTime), typeof(SqlDateTime), SqlDbType.DateTime, DbType.DateTime, 0);
792 
793         private static readonly MetaType MetaSmallDateTime = new MetaType
794             (16, 0, 4, true, false, false, TdsEnums.SQLDATETIM4, TdsEnums.SQLDATETIMN, MetaTypeName.SMALLDATETIME, typeof(System.DateTime), typeof(SqlDateTime), SqlDbType.SmallDateTime, DbType.DateTime, 0);
795 
796         private static readonly MetaType MetaMoney = new MetaType
797             (19, 255, 8, true, false, false, TdsEnums.SQLMONEY, TdsEnums.SQLMONEYN, MetaTypeName.MONEY, typeof(System.Decimal), typeof(SqlMoney), SqlDbType.Money, DbType.Currency, 0);
798 
799         private static readonly MetaType MetaSmallMoney = new MetaType
800             (10, 255, 4, true, false, false, TdsEnums.SQLMONEY4, TdsEnums.SQLMONEYN, MetaTypeName.SMALLMONEY, typeof(System.Decimal), typeof(SqlMoney), SqlDbType.SmallMoney, DbType.Currency, 0);
801 
802         private static readonly MetaType MetaUniqueId = new MetaType
803             (255, 255, 16, true, false, false, TdsEnums.SQLUNIQUEID, TdsEnums.SQLUNIQUEID, MetaTypeName.ROWGUID, typeof(System.Guid), typeof(SqlGuid), SqlDbType.UniqueIdentifier, DbType.Guid, 0);
804 
805         private static readonly MetaType MetaVariant = new MetaType
806             (255, 255, -1, true, false, false, TdsEnums.SQLVARIANT, TdsEnums.SQLVARIANT, MetaTypeName.VARIANT, typeof(System.Object), typeof(System.Object), SqlDbType.Variant, DbType.Object, 0);
807 
808         internal static readonly MetaType MetaUdt = new MetaType
809             (255, 255, -1, false, false, true, TdsEnums.SQLUDT, TdsEnums.SQLUDT, MetaTypeName.UDT, typeof(System.Object), typeof(System.Object), SqlDbType.Udt, DbType.Object, 0);
810 
811         private static readonly MetaType MetaMaxUdt = new MetaType
812             (255, 255, -1, false, true, true, TdsEnums.SQLUDT, TdsEnums.SQLUDT, MetaTypeName.UDT, typeof(System.Object), typeof(System.Object), SqlDbType.Udt, DbType.Object, 0);
813 
814         private static readonly MetaType MetaTable = new MetaType
815             (255, 255, -1, false, false, false, TdsEnums.SQLTABLE, TdsEnums.SQLTABLE, MetaTypeName.TABLE, typeof(IEnumerable<DbDataRecord>), typeof(IEnumerable<DbDataRecord>), SqlDbType.Structured, DbType.Object, 0);
816 
817         //
818 
819         private static readonly MetaType MetaSUDT = new MetaType
820             (255, 255, -1, false, false, false, TdsEnums.SQLVOID, TdsEnums.SQLVOID, "", typeof(MSS.SqlDataRecord), typeof(MSS.SqlDataRecord), SqlDbType.Structured, DbType.Object, 0);
821 
822         private static readonly MetaType MetaDate = new MetaType
823             (255, 255, 3, true, false, false, TdsEnums.SQLDATE, TdsEnums.SQLDATE, MetaTypeName.DATE, typeof(System.DateTime), typeof(System.DateTime), SqlDbType.Date, DbType.Date, 0);
824 
825         internal static readonly MetaType MetaTime = new MetaType
826             (255, 7, -1, false, false, false, TdsEnums.SQLTIME, TdsEnums.SQLTIME, MetaTypeName.TIME, typeof(System.TimeSpan), typeof(System.TimeSpan), SqlDbType.Time, DbType.Time, 1);
827 
828         private static readonly MetaType MetaDateTime2 = new MetaType
829             (255, 7, -1, false, false, false, TdsEnums.SQLDATETIME2, TdsEnums.SQLDATETIME2, MetaTypeName.DATETIME2, typeof(System.DateTime), typeof(System.DateTime), SqlDbType.DateTime2, DbType.DateTime2, 1);
830 
831         internal static readonly MetaType MetaDateTimeOffset = new MetaType
832             (255, 7, -1, false, false, false, TdsEnums.SQLDATETIMEOFFSET, TdsEnums.SQLDATETIMEOFFSET, MetaTypeName.DATETIMEOFFSET, typeof(System.DateTimeOffset), typeof(System.DateTimeOffset), SqlDbType.DateTimeOffset, DbType.DateTimeOffset, 1);
833 
FromDateTime(DateTime dateTime, byte cb)834         public static TdsDateTime FromDateTime(DateTime dateTime, byte cb) {
835             SqlDateTime sqlDateTime;
836             TdsDateTime tdsDateTime = new TdsDateTime();
837 
838             Debug.Assert(cb == 8 || cb == 4, "Invalid date time size!");
839 
840             if (cb == 8) {
841                 sqlDateTime = new SqlDateTime(dateTime);
842                 tdsDateTime.time = sqlDateTime.TimeTicks;
843             }
844             else {
845                 // note that smalldatetime is days&minutes.
846                 // Adding 30 seconds ensures proper roundup if the seconds are >= 30
847                 // The AddSeconds function handles eventual carryover
848                 sqlDateTime = new SqlDateTime(dateTime.AddSeconds(30));
849                 tdsDateTime.time = sqlDateTime.TimeTicks / SqlDateTime.SQLTicksPerMinute;
850             }
851             tdsDateTime.days = sqlDateTime.DayTicks;
852             return tdsDateTime;
853         }
854 
855 
ToDateTime(int sqlDays, int sqlTime, int length)856         public static DateTime ToDateTime(int sqlDays, int sqlTime, int length) {
857             if (length == 4) {
858                 return new SqlDateTime(sqlDays, sqlTime * SqlDateTime.SQLTicksPerMinute).Value;
859             }
860             else {
861                 Debug.Assert(length == 8, "invalid length for DateTime");
862                 return new SqlDateTime(sqlDays, sqlTime).Value;
863             }
864         }
865 
GetTimeSizeFromScale(byte scale)866         internal static int GetTimeSizeFromScale(byte scale)
867         {
868             // Disable the assert here since we do not properly handle wrong Scale value on the parameter,
869             // see VSTFDEVDIV 795578 for more details.
870             // But, this assert is still valid when we receive Time/DateTime2/DateTimeOffset scale from server over TDS,
871             // so it is moved to TdsParser.CommonProcessMetaData.
872             // For new scenarios, assert and/or validate the scale value before this call!
873             // Debug.Assert(0 <= scale && scale <= 7);
874 
875             if (scale <= 2)
876                 return 3;
877 
878             if (scale <= 4)
879                 return 4;
880 
881             return 5;
882         }
883 
884         //
885         // please leave string sorted alphabetically
886         // note that these names should only be used in the context of parameters.  We always send over BIG* and nullable types for SQL Server
887         //
888         private static class MetaTypeName {
889             public const string BIGINT         = "bigint";
890             public const string BINARY         = "binary";
891             public const string BIT            = "bit";
892             public const string CHAR           = "char";
893             public const string DATETIME       = "datetime";
894             public const string DECIMAL        = "decimal";
895             public const string FLOAT          = "float";
896             public const string IMAGE          = "image";
897             public const string INT            = "int";
898             public const string MONEY          = "money";
899             public const string NCHAR          = "nchar";
900             public const string NTEXT          = "ntext";
901             public const string NVARCHAR       = "nvarchar";
902             public const string REAL           = "real";
903             public const string ROWGUID        = "uniqueidentifier";
904             public const string SMALLDATETIME  = "smalldatetime";
905             public const string SMALLINT       = "smallint";
906             public const string SMALLMONEY     = "smallmoney";
907             public const string TEXT           = "text";
908             public const string TIMESTAMP      = "timestamp";
909             public const string TINYINT        = "tinyint";
910             public const string UDT            = "udt";
911             public const string VARBINARY      = "varbinary";
912             public const string VARCHAR        = "varchar";
913             public const string VARIANT        = "sql_variant";
914             public const string XML            = "xml";
915             public const string TABLE          = "table";
916             public const string DATE           = "date";
917             public const string TIME           = "time";
918             public const string DATETIME2      = "datetime2";
919             public const string DATETIMEOFFSET = "datetimeoffset";
920         }
921     }
922 
923     //
924     // note: it is the client's responsibility to know what size date time he is working with
925     //
926     internal struct TdsDateTime {
927         public int days;  // offset in days from 1/1/1900
928         //     private UInt32 time;  // if smalldatetime, this is # of minutes since midnight
929         // otherwise: # of 1/300th of a second since midnight
930         public int time; //
931     }
932 
933 }
934 
935