[bcl] Update Reference Source to .NET Framework 4.6.2
[mono.git] / mcs / class / referencesource / System.Data / System / Data / Odbc / Odbc32.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="Odbc32.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 //------------------------------------------------------------------------------
8
9
10 namespace System.Data.Odbc {
11
12     using System;
13     using System.Data;
14     using System.Data.Common;
15     using System.Diagnostics;
16     using System.Globalization;
17     using System.Runtime.InteropServices;
18     using System.Runtime.ConstrainedExecution;
19     using System.Text;
20
21     internal static class ODBC {
22
23         static internal Exception ConnectionClosed() {
24             return ADP.InvalidOperation(Res.GetString(Res.Odbc_ConnectionClosed));
25         }
26
27         static internal Exception OpenConnectionNoOwner() {
28             return ADP.InvalidOperation(Res.GetString(Res.Odbc_OpenConnectionNoOwner));
29         }
30
31         static internal Exception UnknownSQLType(ODBC32.SQL_TYPE sqltype) {
32             return ADP.Argument(Res.GetString(Res.Odbc_UnknownSQLType, sqltype.ToString()));
33         }
34         static internal Exception ConnectionStringTooLong() {
35             return ADP.Argument(Res.GetString(Res.OdbcConnection_ConnectionStringTooLong,  ODBC32.MAX_CONNECTION_STRING_LENGTH));
36         }
37         static internal ArgumentException GetSchemaRestrictionRequired() {
38             return ADP.Argument(Res.GetString(Res.ODBC_GetSchemaRestrictionRequired));
39         }
40         static internal ArgumentOutOfRangeException NotSupportedEnumerationValue(Type type, int value) {
41             return ADP.ArgumentOutOfRange(Res.GetString(Res.ODBC_NotSupportedEnumerationValue, type.Name, value.ToString(System.Globalization.CultureInfo.InvariantCulture)), type.Name);
42         }
43         static internal ArgumentOutOfRangeException NotSupportedCommandType(CommandType value) {
44 #if DEBUG
45             switch(value) {
46             case CommandType.Text:
47             case CommandType.StoredProcedure:
48                 Debug.Assert(false, "valid CommandType " + value.ToString());
49                 break;
50             case CommandType.TableDirect:
51                 break;
52             default:
53                 Debug.Assert(false, "invalid CommandType " + value.ToString());
54                 break;
55             }
56 #endif
57             return ODBC.NotSupportedEnumerationValue(typeof(CommandType), (int)value);
58         }
59         static internal ArgumentOutOfRangeException NotSupportedIsolationLevel(IsolationLevel value) {
60 #if DEBUG
61             switch(value) {
62             case IsolationLevel.Unspecified:
63             case IsolationLevel.ReadUncommitted:
64             case IsolationLevel.ReadCommitted:
65             case IsolationLevel.RepeatableRead:
66             case IsolationLevel.Serializable:
67             case IsolationLevel.Snapshot:
68                 Debug.Assert(false, "valid IsolationLevel " + value.ToString());
69                 break;
70             case IsolationLevel.Chaos:
71                 break;
72             default:
73                 Debug.Assert(false, "invalid IsolationLevel " + value.ToString());
74                 break;
75             }
76 #endif
77             return ODBC.NotSupportedEnumerationValue(typeof(IsolationLevel), (int)value);
78         }
79
80         static internal InvalidOperationException NoMappingForSqlTransactionLevel(int value) {
81             return ADP.DataAdapter(Res.GetString(Res.Odbc_NoMappingForSqlTransactionLevel, value.ToString(CultureInfo.InvariantCulture)));
82         }
83
84         static internal Exception NegativeArgument() {
85             return ADP.Argument(Res.GetString(Res.Odbc_NegativeArgument));
86         }
87         static internal Exception CantSetPropertyOnOpenConnection() {
88             return ADP.InvalidOperation(Res.GetString(Res.Odbc_CantSetPropertyOnOpenConnection));
89         }
90         static internal Exception CantEnableConnectionpooling(ODBC32.RetCode retcode) {
91             return ADP.DataAdapter(Res.GetString(Res.Odbc_CantEnableConnectionpooling, ODBC32.RetcodeToString(retcode)));
92         }
93         static internal Exception CantAllocateEnvironmentHandle(ODBC32.RetCode retcode) {
94             return ADP.DataAdapter(Res.GetString(Res.Odbc_CantAllocateEnvironmentHandle, ODBC32.RetcodeToString(retcode)));
95         }
96         static internal Exception FailedToGetDescriptorHandle(ODBC32.RetCode retcode) {
97             return ADP.DataAdapter(Res.GetString(Res.Odbc_FailedToGetDescriptorHandle, ODBC32.RetcodeToString(retcode)));
98         }
99         static internal Exception NotInTransaction() {
100             return ADP.InvalidOperation(Res.GetString(Res.Odbc_NotInTransaction));
101         }
102         static internal Exception UnknownOdbcType(OdbcType odbctype) {
103             return ADP.InvalidEnumerationValue(typeof(OdbcType), (int) odbctype);
104         }
105         internal const string Pwd = "pwd";
106
107         static internal void TraceODBC(int level, string method, ODBC32.RetCode retcode) {
108             Bid.TraceSqlReturn("<odbc|API|ODBC|RET> %08X{SQLRETURN}, method=%ls\n", retcode, method);
109         }
110
111         internal static short ShortStringLength(string inputString) {
112             return checked((short)ADP.StringLength(inputString));
113         }
114     }
115
116
117     internal static class ODBC32 {
118
119         internal enum SQL_HANDLE : short {
120             ENV                 = 1,
121             DBC                 = 2,
122             STMT                = 3,
123             DESC                = 4,
124         }
125
126         // from .\public\sdk\inc\sqlext.h: and .\public\sdk\inc\sql.h
127         // must be public because it is serialized by OdbcException
128         [Serializable]
129         public enum RETCODE : int { // must be int instead of short for Everett OdbcException Serializablity.
130             SUCCESS             = 0,
131             SUCCESS_WITH_INFO   = 1,
132             ERROR               = -1,
133             INVALID_HANDLE      = -2,
134             NO_DATA             = 100,
135         }
136
137         // must be public because it is serialized by OdbcException
138         internal enum RetCode : short {
139             SUCCESS             = 0,
140             SUCCESS_WITH_INFO   = 1,
141             ERROR               = -1,
142             INVALID_HANDLE      = -2,
143             NO_DATA             = 100,
144         }
145
146         internal static string RetcodeToString(RetCode retcode) {
147             switch (retcode) {
148                 case RetCode.SUCCESS:           return "SUCCESS";
149                 case RetCode.SUCCESS_WITH_INFO: return "SUCCESS_WITH_INFO";
150                 case RetCode.ERROR:             return "ERROR";
151                 case RetCode.INVALID_HANDLE:    return "INVALID_HANDLE";
152                 case RetCode.NO_DATA:           return "NO_DATA";
153                 default:
154                     Debug.Assert(false, "Unknown enumerator passed to RetcodeToString method");
155                     goto case RetCode.ERROR;
156             }
157         }
158
159
160
161         internal enum SQL_CONVERT : ushort {
162             BIGINT              = 53,
163             BINARY              = 54,
164             BIT                 = 55,
165             CHAR                = 56,
166             DATE                = 57,
167             DECIMAL             = 58,
168             DOUBLE              = 59,
169             FLOAT               = 60,
170             INTEGER             = 61,
171             LONGVARCHAR         = 62,
172             NUMERIC             = 63,
173             REAL                = 64,
174             SMALLINT            = 65,
175             TIME                = 66,
176             TIMESTAMP           = 67,
177             TINYINT             = 68,
178             VARBINARY           = 69,
179             VARCHAR             = 70,
180             LONGVARBINARY       = 71,
181         }
182
183         [Flags]
184         internal enum SQL_CVT {
185             CHAR                = 0x00000001,
186             NUMERIC             = 0x00000002,
187             DECIMAL             = 0x00000004,
188             INTEGER             = 0x00000008,
189             SMALLINT            = 0x00000010,
190             FLOAT               = 0x00000020,
191             REAL                = 0x00000040,
192             DOUBLE              = 0x00000080,
193             VARCHAR             = 0x00000100,
194             LONGVARCHAR         = 0x00000200,
195             BINARY              = 0x00000400,
196             VARBINARY           = 0x00000800,
197             BIT                 = 0x00001000,
198             TINYINT             = 0x00002000,
199             BIGINT              = 0x00004000,
200             DATE                = 0x00008000,
201             TIME                = 0x00010000,
202             TIMESTAMP           = 0x00020000,
203             LONGVARBINARY       = 0x00040000,
204             INTERVAL_YEAR_MONTH = 0x00080000,
205             INTERVAL_DAY_TIME   = 0x00100000,
206             WCHAR               = 0x00200000,
207             WLONGVARCHAR        = 0x00400000,
208             WVARCHAR            = 0x00800000,
209             GUID                = 0x01000000,
210         }
211
212         internal enum STMT : short {
213             CLOSE               =  0,
214             DROP                =  1,
215             UNBIND              =  2,
216             RESET_PARAMS        =  3,
217         }
218
219         internal enum SQL_MAX{
220             NUMERIC_LEN     =   16,
221         }
222
223         internal enum SQL_IS{
224             POINTER         =   -4,
225             INTEGER         =   -6,
226             UINTEGER        =   -5,
227             SMALLINT        =   -8,
228         }
229
230
231         //SQL Server specific defines
232         //
233         internal enum SQL_HC                          // from Odbcss.h
234         {
235             OFF                 = 0,                //  FOR BROWSE columns are hidden
236             ON                  = 1,                //  FOR BROWSE columns are exposed
237         }
238
239         internal enum SQL_NB                          // from Odbcss.h
240         {
241             OFF                 = 0,                //  NO_BROWSETABLE is off
242             ON                  = 1,                //  NO_BROWSETABLE is on
243         }
244
245         //  SQLColAttributes driver specific defines.
246         //  SQLSet/GetDescField driver specific defines.
247         //  Microsoft has 1200 thru 1249 reserved for Microsoft SQL Server driver usage.
248         //
249         internal enum SQL_CA_SS                       // from Odbcss.h
250         {
251             BASE                =   1200,           // SQL_CA_SS_BASE
252
253             COLUMN_HIDDEN       =   BASE + 11,      //  Column is hidden (FOR BROWSE)
254             COLUMN_KEY          =   BASE + 12,      //  Column is key column (FOR BROWSE)
255             VARIANT_TYPE        =   BASE + 15,
256             VARIANT_SQL_TYPE    =   BASE + 16,
257             VARIANT_SERVER_TYPE =   BASE + 17,
258
259         }
260         internal enum SQL_SOPT_SS                     // from Odbcss.h
261         {
262             BASE                =   1225,           // SQL_SOPT_SS_BASE
263             HIDDEN_COLUMNS      =   BASE + 2,       // Expose FOR BROWSE hidden columns
264             NOBROWSETABLE       =   BASE + 3,       // Set NOBROWSETABLE option
265         }
266
267         internal const Int16 SQL_COMMIT              =   0;      //Commit
268         internal const Int16 SQL_ROLLBACK            =   1;      //Abort
269
270         static internal readonly IntPtr SQL_AUTOCOMMIT_OFF = ADP.PtrZero;
271         static internal readonly IntPtr SQL_AUTOCOMMIT_ON = new IntPtr(1);
272
273         internal enum SQL_TRANSACTION
274         {
275             READ_UNCOMMITTED    =   0x00000001,
276             READ_COMMITTED      =   0x00000002,
277             REPEATABLE_READ     =   0x00000004,
278             SERIALIZABLE        =   0x00000008,
279             SNAPSHOT            =   0x00000020, // VSDD 414121: SQL_TXN_SS_SNAPSHOT == 0x20 (sqlncli.h)
280         }
281
282         internal enum SQL_PARAM
283         {
284 // unused   TYPE_UNKNOWN        =   0,          // SQL_PARAM_TYPE_UNKNOWN
285             INPUT               =   1,          // SQL_PARAM_INPUT
286             INPUT_OUTPUT        =   2,          // SQL_PARAM_INPUT_OUTPUT
287 // unused   RESULT_COL          =   3,          // SQL_RESULT_COL
288             OUTPUT              =   4,          // SQL_PARAM_OUTPUT
289             RETURN_VALUE        =   5,          // SQL_RETURN_VALUE
290         }
291
292         // SQL_API_* values
293         // there are a gillion of these I am only defining the ones currently needed
294         // others can be added as needed
295         internal enum SQL_API : ushort
296         {
297             SQLCOLUMNS          = 40,
298             SQLEXECDIRECT       = 11,
299             SQLGETTYPEINFO      = 47,
300             SQLPROCEDURECOLUMNS = 66,
301             SQLPROCEDURES       = 67,
302             SQLSTATISTICS       = 53,
303             SQLTABLES           = 54,
304         }
305
306
307         internal enum SQL_DESC : short
308         {
309             // from sql.h (ODBCVER >= 3.0)
310             //
311             COUNT                  = 1001,
312             TYPE                   = 1002,
313             LENGTH                 = 1003,
314             OCTET_LENGTH_PTR       = 1004,
315             PRECISION              = 1005,
316             SCALE                  = 1006,
317             DATETIME_INTERVAL_CODE = 1007,
318             NULLABLE               = 1008,
319             INDICATOR_PTR          = 1009,
320             DATA_PTR               = 1010,
321             NAME                   = 1011,
322             UNNAMED                = 1012,
323             OCTET_LENGTH           = 1013,
324             ALLOC_TYPE             = 1099,
325
326             // from sqlext.h (ODBCVER >= 3.0)
327             //
328             CONCISE_TYPE           = SQL_COLUMN.TYPE,
329             DISPLAY_SIZE           = SQL_COLUMN.DISPLAY_SIZE,
330             UNSIGNED               = SQL_COLUMN.UNSIGNED,
331             UPDATABLE              = SQL_COLUMN.UPDATABLE,
332             AUTO_UNIQUE_VALUE      = SQL_COLUMN.AUTO_INCREMENT,
333
334             TYPE_NAME              = SQL_COLUMN.TYPE_NAME,
335             TABLE_NAME             = SQL_COLUMN.TABLE_NAME,
336             SCHEMA_NAME            = SQL_COLUMN.OWNER_NAME,
337             CATALOG_NAME           = SQL_COLUMN.QUALIFIER_NAME,
338
339             BASE_COLUMN_NAME       = 22,
340             BASE_TABLE_NAME        = 23,
341         }
342
343         // ODBC version 2.0 style attributes
344         // All IdentifierValues are ODBC 1.0 unless marked differently
345         //
346         internal enum SQL_COLUMN
347         {
348             COUNT                  = 0,
349             NAME                   = 1,
350             TYPE                   = 2,
351             LENGTH                 = 3,
352             PRECISION              = 4,
353             SCALE                  = 5,
354             DISPLAY_SIZE           = 6,
355             NULLABLE               = 7,
356             UNSIGNED               = 8,
357             MONEY                  = 9,
358             UPDATABLE              = 10,
359             AUTO_INCREMENT         = 11,
360             CASE_SENSITIVE         = 12,
361             SEARCHABLE             = 13,
362             TYPE_NAME              = 14,
363             TABLE_NAME             = 15,    // (ODBC 2.0)
364             OWNER_NAME             = 16,    // (ODBC 2.0)
365             QUALIFIER_NAME         = 17,    // (ODBC 2.0)
366             LABEL                  = 18,
367         }
368
369         internal enum SQL_GROUP_BY
370         {
371             NOT_SUPPORTED               = 0,    // SQL_GB_NOT_SUPPORTED
372             GROUP_BY_EQUALS_SELECT      = 1,    // SQL_GB_GROUP_BY_EQUALS_SELECT
373             GROUP_BY_CONTAINS_SELECT    = 2,    // SQL_GB_GROUP_BY_CONTAINS_SELECT
374             NO_RELATION                 = 3,    // SQL_GB_NO_RELATION
375             COLLATE                     = 4,    // SQL_GB_COLLATE - added in ODBC 3.0
376         }
377
378         // values from sqlext.h
379         internal enum SQL_SQL92_RELATIONAL_JOIN_OPERATORS
380         {
381             CORRESPONDING_CLAUSE   = 0x00000001,    // SQL_SRJO_CORRESPONDING_CLAUSE
382             CROSS_JOIN             = 0x00000002,    // SQL_SRJO_CROSS_JOIN
383             EXCEPT_JOIN            = 0x00000004,    // SQL_SRJO_EXCEPT_JOIN
384             FULL_OUTER_JOIN        = 0x00000008,    // SQL_SRJO_FULL_OUTER_JOIN
385             INNER_JOIN             = 0x00000010,    // SQL_SRJO_INNER_JOIN
386             INTERSECT_JOIN         = 0x00000020,    // SQL_SRJO_INTERSECT_JOIN
387             LEFT_OUTER_JOIN        = 0x00000040,    // SQL_SRJO_LEFT_OUTER_JOIN
388             NATURAL_JOIN           = 0x00000080,    // SQL_SRJO_NATURAL_JOIN
389             RIGHT_OUTER_JOIN       = 0x00000100,    // SQL_SRJO_RIGHT_OUTER_JOIN
390             UNION_JOIN             = 0x00000200,    // SQL_SRJO_UNION_JOIN
391         }
392
393         // values from sql.h
394         internal enum SQL_OJ_CAPABILITIES
395         {
396             LEFT   = 0x00000001,    // SQL_OJ_LEFT
397             RIGHT = 0x00000002,    // SQL_OJ_RIGHT
398             FULL  = 0x00000004,    // SQL_OJ_FULL
399             NESTED  = 0x00000008,    // SQL_OJ_NESTED
400             NOT_ORDERED  = 0x00000010,    // SQL_OJ_NOT_ORDERED
401             INNER  = 0x00000020,    // SQL_OJ_INNER
402             ALL_COMPARISON_OPS = 0x00000040,  //SQL_OJ_ALLCOMPARISION+OPS
403         }
404
405         internal enum SQL_UPDATABLE
406         {
407             READONLY                = 0,    // SQL_ATTR_READ_ONLY
408             WRITE                   = 1,    // SQL_ATTR_WRITE
409             READWRITE_UNKNOWN       = 2,    // SQL_ATTR_READWRITE_UNKNOWN
410         }
411
412         internal enum SQL_IDENTIFIER_CASE
413         {
414             UPPER       = 1,    // SQL_IC_UPPER
415             LOWER       = 2,    // SQL_IC_LOWER
416             SENSITIVE   = 3,    // SQL_IC_SENSITIVE
417             MIXED       = 4,    // SQL_IC_MIXED
418         }
419
420         // Uniqueness parameter in the SQLStatistics function
421         internal enum SQL_INDEX : short
422         {
423             UNIQUE      = 0,
424             ALL          = 1,
425         }
426
427         // Reserved parameter in the SQLStatistics function
428         internal enum SQL_STATISTICS_RESERVED : short
429         {
430             QUICK       = 0,                // SQL_QUICK
431             ENSURE      = 1,                // SQL_ENSURE
432         }
433
434         // Identifier type parameter in the SQLSpecialColumns function
435         internal enum SQL_SPECIALCOLS : ushort
436         {
437             BEST_ROWID      = 1,            // SQL_BEST_ROWID
438             ROWVER          = 2,            // SQL_ROWVER
439         }
440
441         // Scope parameter in the SQLSpecialColumns function
442         internal enum SQL_SCOPE : ushort
443         {
444             CURROW          = 0,            // SQL_SCOPE_CURROW
445             TRANSACTION      = 1,           // SQL_SCOPE_TRANSACTION
446             SESSION          = 2,           // SQL_SCOPE_SESSION
447         }
448
449         internal enum SQL_NULLABILITY : ushort
450         {
451             NO_NULLS    = 0,                // SQL_NO_NULLS
452             NULLABLE    = 1,                // SQL_NULLABLE
453             UNKNOWN     = 2,                // SQL_NULLABLE_UNKNOWN
454         }
455
456         internal enum SQL_SEARCHABLE
457         {
458             UNSEARCHABLE        = 0,        // SQL_UNSEARCHABLE
459             LIKE_ONLY           = 1,        // SQL_LIKE_ONLY
460             ALL_EXCEPT_LIKE     = 2,        // SQL_ALL_EXCEPT_LIKE
461             SEARCHABLE          = 3,        // SQL_SEARCHABLE
462         }
463
464         internal enum SQL_UNNAMED
465         {
466             NAMED    = 0,                   // SQL_NAMED
467             UNNAMED    = 1,                 // SQL_UNNAMED
468         }
469 // todo:move
470 // internal constants
471 // not odbc specific
472 //
473         internal enum HANDLER
474         {
475             IGNORE                  = 0x00000000,
476             THROW                   = 0x00000001,
477         }
478
479         // values for SQLStatistics TYPE column
480         internal enum SQL_STATISTICSTYPE
481         {
482             TABLE_STAT          = 0,                    // TABLE Statistics
483             INDEX_CLUSTERED     = 1,                    // CLUSTERED index statistics
484             INDEX_HASHED        = 2,                    // HASHED index statistics
485             INDEX_OTHER         = 3,                    // OTHER index statistics
486         }
487
488         // values for SQLProcedures PROCEDURE_TYPE column
489         internal enum SQL_PROCEDURETYPE
490         {
491             UNKNOWN         = 0,                    // procedure is of unknow type
492             PROCEDURE       = 1,                    // procedure is a procedure
493             FUNCTION        = 2,                    // procedure is a function
494         }
495
496 // private constants
497 // to define data types (see below)
498 //
499         private const Int32 SIGNED_OFFSET   =    -20;    // SQL_SIGNED_OFFSET
500         private const Int32 UNSIGNED_OFFSET =    -22;    // SQL_UNSIGNED_OFFSET
501
502         //C Data Types - used when getting data (SQLGetData)
503         internal enum SQL_C : short
504         {
505             CHAR            =    1,                     //SQL_C_CHAR
506             WCHAR           =   -8,                     //SQL_C_WCHAR
507             SLONG           =    4 + SIGNED_OFFSET,     //SQL_C_LONG+SQL_SIGNED_OFFSET
508 //          ULONG           =    4 + UNSIGNED_OFFSET,   //SQL_C_LONG+SQL_UNSIGNED_OFFSET
509             SSHORT          =    5 + SIGNED_OFFSET,     //SQL_C_SSHORT+SQL_SIGNED_OFFSET
510 //          USHORT          =    5 + UNSIGNED_OFFSET,   //SQL_C_USHORT+SQL_UNSIGNED_OFFSET
511             REAL            =    7,                     //SQL_C_REAL
512             DOUBLE          =    8,                     //SQL_C_DOUBLE
513             BIT             =   -7,                     //SQL_C_BIT
514 //          STINYINT        =   -6 + SIGNED_OFFSET,     //SQL_C_STINYINT+SQL_SIGNED_OFFSET
515             UTINYINT        =   -6 + UNSIGNED_OFFSET,   //SQL_C_UTINYINT+SQL_UNSIGNED_OFFSET
516             SBIGINT         =   -5 + SIGNED_OFFSET,     //SQL_C_SBIGINT+SQL_SIGNED_OFFSET
517             UBIGINT         =   -5 + UNSIGNED_OFFSET,   //SQL_C_UBIGINT+SQL_UNSIGNED_OFFSET
518             BINARY          =   -2,                     //SQL_C_BINARY
519             TIMESTAMP       =   11,                     //SQL_C_TIMESTAMP
520
521             TYPE_DATE       =   91,                     //SQL_C_TYPE_DATE
522             TYPE_TIME       =   92,                     //SQL_C_TYPE_TIME
523             TYPE_TIMESTAMP  =   93,                     //SQL_C_TYPE_TIMESTAMP
524
525             NUMERIC         =    2,                     //SQL_C_NUMERIC
526             GUID            =   -11,                    //SQL_C_GUID
527             DEFAULT         =   99,                     //SQL_C_DEFAULT
528             ARD_TYPE        =   -99,                    //SQL_ARD_TYPE
529         }
530
531         //SQL Data Types - returned as column types (SQLColAttribute)
532         internal enum SQL_TYPE : short
533         {
534             CHAR            =   SQL_C.CHAR,             //SQL_CHAR
535             VARCHAR         =   12,                     //SQL_VARCHAR
536             LONGVARCHAR     =   -1,                     //SQL_LONGVARCHAR
537             WCHAR           =   SQL_C.WCHAR,            //SQL_WCHAR
538             WVARCHAR        =   -9,                     //SQL_WVARCHAR
539             WLONGVARCHAR    =   -10,                    //SQL_WLONGVARCHAR
540             DECIMAL         =   3,                      //SQL_DECIMAL
541             NUMERIC         =   SQL_C.NUMERIC,          //SQL_NUMERIC
542             SMALLINT        =   5,                      //SQL_SMALLINT
543             INTEGER         =   4,                      //SQL_INTEGER
544             REAL            =   SQL_C.REAL,             //SQL_REAL
545             FLOAT           =   6,                      //SQL_FLOAT
546             DOUBLE          =   SQL_C.DOUBLE,           //SQL_DOUBLE
547             BIT             =   SQL_C.BIT,              //SQL_BIT
548             TINYINT         =   -6,                     //SQL_TINYINT
549             BIGINT          =   -5,                     //SQL_BIGINT
550             BINARY          =   SQL_C.BINARY,           //SQL_BINARY
551             VARBINARY       =   -3,                     //SQL_VARBINARY
552             LONGVARBINARY   =   -4,                     //SQL_LONGVARBINARY
553
554 //          DATE            =   9,                      //SQL_DATE
555             TYPE_DATE       =   SQL_C.TYPE_DATE,        //SQL_TYPE_DATE
556             TYPE_TIME       =   SQL_C.TYPE_TIME,        //SQL_TYPE_TIME
557             TIMESTAMP       =   SQL_C.TIMESTAMP,        //SQL_TIMESTAMP
558             TYPE_TIMESTAMP  =   SQL_C.TYPE_TIMESTAMP,   //SQL_TYPE_TIMESTAMP
559
560
561             GUID            =   SQL_C.GUID,             //SQL_GUID
562
563         //  from odbcss.h in mdac 9.0 sources!
564         //  Driver specific SQL type defines.
565         //  Microsoft has -150 thru -199 reserved for Microsoft SQL Server driver usage.
566         //
567             SS_VARIANT =                     -150,
568             SS_UDT =                         -151,
569             SS_XML =                         -152,
570             SS_UTCDATETIME =                 -153,
571             SS_TIME_EX =                     -154,
572         }
573
574         internal const Int16 SQL_ALL_TYPES = 0;
575         static internal readonly IntPtr  SQL_HANDLE_NULL  = ADP.PtrZero;
576         internal const Int32  SQL_NULL_DATA     = -1;   // sql.h
577         internal const Int32  SQL_NO_TOTAL      = -4;   // sqlext.h
578
579         internal const Int32  SQL_DEFAULT_PARAM= -5;
580 //      internal const Int32  SQL_IGNORE         = -6;
581
582 // column ordinals for SQLProcedureColumns result set
583 // this column ordinals are not defined in any c/c++ header but in the ODBC Programmer's Reference under SQLProcedureColumns
584 //
585         internal const Int32  COLUMN_NAME = 4;
586         internal const Int32  COLUMN_TYPE = 5;
587         internal const Int32  DATA_TYPE = 6;
588         internal const Int32  COLUMN_SIZE = 8;
589         internal const Int32  DECIMAL_DIGITS = 10;
590         internal const Int32  NUM_PREC_RADIX = 11;
591
592         internal enum SQL_ATTR
593         {
594             APP_ROW_DESC        =   10010,              // (ODBC 3.0)
595             APP_PARAM_DESC      =   10011,              // (ODBC 3.0)
596             IMP_ROW_DESC        =   10012,              // (ODBC 3.0)
597             IMP_PARAM_DESC      =   10013,              // (ODBC 3.0)
598             METADATA_ID         =   10014,              // (ODBC 3.0)
599             ODBC_VERSION        =   200,
600             CONNECTION_POOLING  =   201,
601             AUTOCOMMIT          =   102,
602             TXN_ISOLATION       =   108,
603             CURRENT_CATALOG     =   109,
604             LOGIN_TIMEOUT       =   103,
605             QUERY_TIMEOUT       =   0,                  // from sqlext.h
606             CONNECTION_DEAD     =   1209,               // from sqlext.h
607
608             // from sqlncli.h
609             SQL_COPT_SS_BASE          = 1200,
610             SQL_COPT_SS_ENLIST_IN_DTC = (SQL_COPT_SS_BASE + 7),
611             SQL_COPT_SS_TXN_ISOLATION = (SQL_COPT_SS_BASE + 27), // Used to set/get any driver-specific or ODBC-defined TXN iso level
612         }
613
614         //SQLGetInfo
615         internal enum SQL_INFO : ushort
616         {
617             DATA_SOURCE_NAME            = 2,    // SQL_DATA_SOURCE_NAME in sql.h
618             SERVER_NAME                 = 13,   // SQL_SERVER_NAME in sql.h
619             DRIVER_NAME                 = 6,    // SQL_DRIVER_NAME as defined in sqlext.h
620             DRIVER_VER                  = 7,    // SQL_DRIVER_VER as defined in sqlext.h
621             ODBC_VER                    = 10,   // SQL_ODBC_VER as defined in sqlext.h
622             SEARCH_PATTERN_ESCAPE       = 14,   // SQL_SEARCH_PATTERN_ESCAPE from sql.h
623             DBMS_VER                    = 18,
624             DBMS_NAME                   = 17,   // SQL_DBMS_NAME as defined in sqlext.h
625             IDENTIFIER_CASE             = 28,   // SQL_IDENTIFIER_CASE from sql.h
626             IDENTIFIER_QUOTE_CHAR       = 29,   // SQL_IDENTIFIER_QUOTE_CHAR from sql.h
627             CATALOG_NAME_SEPARATOR      = 41,   // SQL_CATALOG_NAME_SEPARATOR
628             DRIVER_ODBC_VER             = 77,   // SQL_DRIVER_ODBC_VER as defined in sqlext.h
629             GROUP_BY                    = 88,   // SQL_GROUP_BY as defined in  sqlext.h
630             KEYWORDS                    = 89,   // SQL_KEYWORDS as defined in sqlext.h
631             ORDER_BY_COLUMNS_IN_SELECT  = 90,   // SQL_ORDER_BY_COLUNS_IN_SELECT in sql.h
632             QUOTED_IDENTIFIER_CASE      = 93,   // SQL_QUOTED_IDENTIFIER_CASE in sqlext.h
633             SQL_OJ_CAPABILITIES_30 = 115, //SQL_OJ_CAPABILITIES from sql.h
634             SQL_OJ_CAPABILITIES_20 = 65003, //SQL_OJ_CAPABILITIES from sqlext.h
635             SQL_SQL92_RELATIONAL_JOIN_OPERATORS = 161, //SQL_SQL92_RELATIONAL_JOIN_OPERATORS from sqlext.h
636
637         }
638
639         static internal readonly IntPtr  SQL_OV_ODBC3      =  new IntPtr(3);
640         internal const Int32  SQL_NTS                 = -3;       //flags for null-terminated string
641
642         //Pooling
643         static internal readonly IntPtr  SQL_CP_OFF                        =  new IntPtr(0);       //Connection Pooling disabled
644         static internal readonly IntPtr  SQL_CP_ONE_PER_DRIVER  =  new IntPtr(1);       //One pool per driver
645         static internal readonly IntPtr  SQL_CP_ONE_PER_HENV     =  new IntPtr(2);       //One pool per environment
646
647         /* values for SQL_ATTR_CONNECTION_DEAD */
648         internal const Int32  SQL_CD_TRUE             = 1;
649         internal const Int32  SQL_CD_FALSE            = 0;
650
651         internal const Int32 SQL_DTC_DONE = 0;
652         internal const Int32 SQL_IS_POINTER = -4;
653         internal const Int32 SQL_IS_PTR = 1;
654
655         internal enum SQL_DRIVER
656         {
657             NOPROMPT            = 0,
658             COMPLETE            = 1,
659             PROMPT              = 2,
660             COMPLETE_REQUIRED   = 3,
661         }
662
663 // todo:move
664 // internal const. not odbc specific
665 //
666         // Connection string max length
667         internal const Int32 MAX_CONNECTION_STRING_LENGTH    = 1024;
668
669         // Column set for SQLPrimaryKeys
670         internal enum SQL_PRIMARYKEYS : short
671         {
672 /*
673             CATALOGNAME         = 1,                    // TABLE_CAT
674             SCHEMANAME          = 2,                    // TABLE_SCHEM
675             TABLENAME           = 3,                    // TABLE_NAME
676 */
677             COLUMNNAME          = 4,                    // COLUMN_NAME
678 /*
679             KEY_SEQ             = 5,                    // KEY_SEQ
680             PKNAME              = 6,                    // PK_NAME
681 */
682         }
683
684         // Column set for SQLStatistics
685         internal enum SQL_STATISTICS : short
686         {
687 /*
688             CATALOGNAME         = 1,                    // TABLE_CAT
689             SCHEMANAME          = 2,                    // TABLE_SCHEM
690             TABLENAME           = 3,                    // TABLE_NAME
691             NONUNIQUE           = 4,                    // NON_UNIQUE
692             INDEXQUALIFIER      = 5,                    // INDEX_QUALIFIER
693 */
694             INDEXNAME           = 6,                    // INDEX_NAME
695 /*
696             TYPE                = 7,                    // TYPE
697 */
698             ORDINAL_POSITION    = 8,                    // ORDINAL_POSITION
699             COLUMN_NAME         = 9,                    // COLUMN_NAME
700 /*
701             ASC_OR_DESC         = 10,                   // ASC_OR_DESC
702             CARDINALITY         = 11,                   // CARDINALITY
703             PAGES               = 12,                   // PAGES
704             FILTER_CONDITION    = 13,                   // FILTER_CONDITION
705 */
706         }
707
708         // Column set for SQLSpecialColumns
709         internal enum SQL_SPECIALCOLUMNSET : short
710         {
711 /*
712             SCOPE               = 1,                    // SCOPE
713 */
714             COLUMN_NAME         = 2,                    // COLUMN_NAME
715 /*
716             DATA_TYPE           = 3,                    // DATA_TYPE
717             TYPE_NAME           = 4,                    // TYPE_NAME
718             COLUMN_SIZE         = 5,                    // COLUMN_SIZE
719             BUFFER_LENGTH       = 6,                    // BUFFER_LENGTH
720             DECIMAL_DIGITS      = 7,                    // DECIMAL_DIGITS
721             PSEUDO_COLUMN       = 8,                    // PSEUDO_COLUMN
722 */
723         }
724
725         internal const short SQL_DIAG_SQLSTATE = 4;
726         internal const short SQL_RESULT_COL = 3;
727
728         // Helpers
729         static internal OdbcErrorCollection GetDiagErrors(string source, OdbcHandle hrHandle, RetCode retcode) {
730             OdbcErrorCollection errors = new OdbcErrorCollection();
731             GetDiagErrors(errors, source, hrHandle, retcode);
732             return errors;
733         }
734
735         static internal void GetDiagErrors(OdbcErrorCollection errors, string source, OdbcHandle hrHandle, RetCode retcode) {
736             Debug.Assert(retcode!=ODBC32.RetCode.INVALID_HANDLE, "retcode must never be ODBC32.RetCode.INVALID_HANDLE");
737             if (RetCode.SUCCESS != retcode) {
738                 Int32       NativeError;
739                 Int16       iRec            = 0;
740                 Int16       cchActual       = 0;
741
742                 StringBuilder message = new StringBuilder(1024);
743                 string sqlState;
744                 bool moreerrors = true;
745                 while(moreerrors) {
746
747                     ++iRec;
748
749                     retcode = hrHandle.GetDiagnosticRecord(iRec, out sqlState, message, out NativeError, out cchActual);
750                     if ((RetCode.SUCCESS_WITH_INFO == retcode) && (message.Capacity-1 < cchActual)) {
751                         message.Capacity = cchActual+1;
752                         retcode = hrHandle.GetDiagnosticRecord(iRec, out sqlState, message, out NativeError, out cchActual);
753                     }
754
755                     //Note: SUCCESS_WITH_INFO from SQLGetDiagRec would be because
756                     //the buffer is not large enough for the error string.
757                     moreerrors = (retcode == RetCode.SUCCESS || retcode == RetCode.SUCCESS_WITH_INFO);
758                     if(moreerrors) {
759                         //Sets up the InnerException as well...
760                         errors.Add(new OdbcError(
761                             source,
762                             message.ToString(),
763                             sqlState,
764                             NativeError
765                             )
766                         );
767                     }
768                 }
769             }
770         }
771     }
772
773    sealed internal class TypeMap { // MDAC 68988
774 //      private TypeMap                                           (OdbcType odbcType,         DbType dbType,                Type type,        ODBC32.SQL_TYPE sql_type,       ODBC32.SQL_C sql_c,          ODBC32.SQL_C param_sql_c,   int bsize, int csize, bool signType)
775 //      ---------------                                            ------------------         --------------                ----------        -------------------------       -------------------          -------------------------   -----------------------
776         static private  readonly TypeMap _BigInt     = new TypeMap(OdbcType.BigInt,           DbType.Int64,                 typeof(Int64),    ODBC32.SQL_TYPE.BIGINT,         ODBC32.SQL_C.SBIGINT,        ODBC32.SQL_C.SBIGINT,         8, 20, true);
777         static private  readonly TypeMap _Binary     = new TypeMap(OdbcType.Binary,           DbType.Binary,                typeof(byte[]),   ODBC32.SQL_TYPE.BINARY,         ODBC32.SQL_C.BINARY,         ODBC32.SQL_C.BINARY,         -1, -1, false);
778         static private  readonly TypeMap _Bit        = new TypeMap(OdbcType.Bit,              DbType.Boolean,               typeof(Boolean),  ODBC32.SQL_TYPE.BIT,            ODBC32.SQL_C.BIT,            ODBC32.SQL_C.BIT,             1,  1, false);
779         static internal readonly TypeMap _Char       = new TypeMap(OdbcType.Char,             DbType.AnsiStringFixedLength, typeof(String),   ODBC32.SQL_TYPE.CHAR,           ODBC32.SQL_C.WCHAR,          ODBC32.SQL_C.CHAR,           -1, -1, false);
780         static private  readonly TypeMap _DateTime   = new TypeMap(OdbcType.DateTime,         DbType.DateTime,              typeof(DateTime), ODBC32.SQL_TYPE.TYPE_TIMESTAMP, ODBC32.SQL_C.TYPE_TIMESTAMP, ODBC32.SQL_C.TYPE_TIMESTAMP, 16, 23, false);
781         static private  readonly TypeMap _Date       = new TypeMap(OdbcType.Date,             DbType.Date,                  typeof(DateTime), ODBC32.SQL_TYPE.TYPE_DATE,      ODBC32.SQL_C.TYPE_DATE,      ODBC32.SQL_C.TYPE_DATE,       6, 10, false);
782         static private  readonly TypeMap _Time       = new TypeMap(OdbcType.Time,             DbType.Time,                  typeof(TimeSpan), ODBC32.SQL_TYPE.TYPE_TIME,      ODBC32.SQL_C.TYPE_TIME,      ODBC32.SQL_C.TYPE_TIME,       6, 12, false);
783         static private  readonly TypeMap _Decimal    = new TypeMap(OdbcType.Decimal,          DbType.Decimal,               typeof(Decimal),  ODBC32.SQL_TYPE.DECIMAL,        ODBC32.SQL_C.NUMERIC,        ODBC32.SQL_C.NUMERIC,        19, ADP.DecimalMaxPrecision28, false);
784 //        static private  readonly TypeMap _Currency   = new TypeMap(OdbcType.Decimal,          DbType.Currency,              typeof(Decimal),  ODBC32.SQL_TYPE.DECIMAL,        ODBC32.SQL_C.NUMERIC,        ODBC32.SQL_C.NUMERIC,        19, ADP.DecimalMaxPrecision28, false);
785         static private  readonly TypeMap _Double     = new TypeMap(OdbcType.Double,           DbType.Double,                typeof(Double),   ODBC32.SQL_TYPE.DOUBLE,         ODBC32.SQL_C.DOUBLE,         ODBC32.SQL_C.DOUBLE,          8, 15, false);
786         static internal readonly TypeMap _Image      = new TypeMap(OdbcType.Image,            DbType.Binary,                typeof(Byte[]),   ODBC32.SQL_TYPE.LONGVARBINARY,  ODBC32.SQL_C.BINARY,         ODBC32.SQL_C.BINARY,         -1, -1, false);
787         static private  readonly TypeMap _Int        = new TypeMap(OdbcType.Int,              DbType.Int32,                 typeof(Int32),    ODBC32.SQL_TYPE.INTEGER,        ODBC32.SQL_C.SLONG,          ODBC32.SQL_C.SLONG,           4, 10, true);
788         static private  readonly TypeMap _NChar      = new TypeMap(OdbcType.NChar,            DbType.StringFixedLength,     typeof(String),   ODBC32.SQL_TYPE.WCHAR,          ODBC32.SQL_C.WCHAR,          ODBC32.SQL_C.WCHAR,          -1, -1, false);
789         static internal readonly TypeMap _NText      = new TypeMap(OdbcType.NText,            DbType.String,                typeof(String),   ODBC32.SQL_TYPE.WLONGVARCHAR,   ODBC32.SQL_C.WCHAR,          ODBC32.SQL_C.WCHAR,          -1, -1, false);
790         static private  readonly TypeMap _Numeric    = new TypeMap(OdbcType.Numeric,          DbType.Decimal,               typeof(Decimal),  ODBC32.SQL_TYPE.NUMERIC,        ODBC32.SQL_C.NUMERIC,        ODBC32.SQL_C.NUMERIC,        19, ADP.DecimalMaxPrecision28, false);
791         static internal readonly TypeMap _NVarChar   = new TypeMap(OdbcType.NVarChar,         DbType.String,                typeof(String),   ODBC32.SQL_TYPE.WVARCHAR,       ODBC32.SQL_C.WCHAR,          ODBC32.SQL_C.WCHAR,          -1, -1, false);
792         static private  readonly TypeMap _Real       = new TypeMap(OdbcType.Real,             DbType.Single,                typeof(Single),   ODBC32.SQL_TYPE.REAL,           ODBC32.SQL_C.REAL,           ODBC32.SQL_C.REAL,            4,  7, false);
793         static private  readonly TypeMap _UniqueId   = new TypeMap(OdbcType.UniqueIdentifier, DbType.Guid,                  typeof(Guid),     ODBC32.SQL_TYPE.GUID,           ODBC32.SQL_C.GUID,           ODBC32.SQL_C.GUID,           16, 36, false);
794         static private  readonly TypeMap _SmallDT    = new TypeMap(OdbcType.SmallDateTime,    DbType.DateTime,              typeof(DateTime), ODBC32.SQL_TYPE.TYPE_TIMESTAMP, ODBC32.SQL_C.TYPE_TIMESTAMP, ODBC32.SQL_C.TYPE_TIMESTAMP, 16, 23, false);
795         static private  readonly TypeMap _SmallInt   = new TypeMap(OdbcType.SmallInt,         DbType.Int16,                 typeof(Int16),    ODBC32.SQL_TYPE.SMALLINT,       ODBC32.SQL_C.SSHORT,         ODBC32.SQL_C.SSHORT,          2,  5, true);
796         static internal readonly TypeMap _Text       = new TypeMap(OdbcType.Text,             DbType.AnsiString,            typeof(String),   ODBC32.SQL_TYPE.LONGVARCHAR,    ODBC32.SQL_C.WCHAR,          ODBC32.SQL_C.CHAR,           -1, -1, false);
797         static private  readonly TypeMap _Timestamp  = new TypeMap(OdbcType.Timestamp,        DbType.Binary,                typeof(Byte[]),   ODBC32.SQL_TYPE.BINARY,         ODBC32.SQL_C.BINARY,         ODBC32.SQL_C.BINARY,         -1, -1, false);
798         static private  readonly TypeMap _TinyInt    = new TypeMap(OdbcType.TinyInt,          DbType.Byte,                  typeof(Byte),     ODBC32.SQL_TYPE.TINYINT,        ODBC32.SQL_C.UTINYINT,       ODBC32.SQL_C.UTINYINT,        1,  3, true);
799         static private  readonly TypeMap _VarBinary  = new TypeMap(OdbcType.VarBinary,        DbType.Binary,                typeof(Byte[]),   ODBC32.SQL_TYPE.VARBINARY,      ODBC32.SQL_C.BINARY,         ODBC32.SQL_C.BINARY,         -1, -1, false);
800         static internal readonly TypeMap _VarChar    = new TypeMap(OdbcType.VarChar,          DbType.AnsiString,            typeof(String),   ODBC32.SQL_TYPE.VARCHAR,        ODBC32.SQL_C.WCHAR,          ODBC32.SQL_C.CHAR,           -1, -1, false);
801         static private  readonly TypeMap _Variant    = new TypeMap(OdbcType.Binary,           DbType.Binary,                typeof(object),   ODBC32.SQL_TYPE.SS_VARIANT,     ODBC32.SQL_C.BINARY,         ODBC32.SQL_C.BINARY,         -1, -1, false);
802         static private  readonly TypeMap _UDT        = new TypeMap(OdbcType.Binary,           DbType.Binary,                typeof(object),   ODBC32.SQL_TYPE.SS_UDT,         ODBC32.SQL_C.BINARY,         ODBC32.SQL_C.BINARY,         -1, -1, false);
803         static private  readonly TypeMap _XML        = new TypeMap(OdbcType.Text,             DbType.AnsiString,            typeof(String),   ODBC32.SQL_TYPE.LONGVARCHAR,    ODBC32.SQL_C.WCHAR,          ODBC32.SQL_C.CHAR,           -1, -1, false);
804
805         internal readonly OdbcType _odbcType;
806         internal readonly DbType   _dbType;
807         internal readonly Type     _type;
808
809         internal readonly ODBC32.SQL_TYPE _sql_type;
810         internal readonly ODBC32.SQL_C    _sql_c;
811         internal readonly ODBC32.SQL_C    _param_sql_c;
812
813
814         internal readonly int _bufferSize;  // fixed length byte size to reserve for buffer
815         internal readonly int _columnSize;  // column size passed to SQLBindParameter
816         internal readonly bool _signType;   // this type may be has signature information
817
818         private TypeMap(OdbcType odbcType, DbType dbType, Type type, ODBC32.SQL_TYPE sql_type, ODBC32.SQL_C sql_c, ODBC32.SQL_C param_sql_c, int bsize, int csize, bool signType) {
819             _odbcType = odbcType;
820             _dbType = dbType;
821             _type = type;
822
823             _sql_type = sql_type;
824             _sql_c = sql_c;
825             _param_sql_c = param_sql_c; // alternative sql_c type for parameters
826
827             _bufferSize = bsize;
828             _columnSize = csize;
829             _signType = signType;
830         }
831
832         static internal TypeMap FromOdbcType(OdbcType odbcType) {
833             switch(odbcType) {
834             case OdbcType.BigInt: return _BigInt;
835             case OdbcType.Binary: return _Binary;
836             case OdbcType.Bit: return _Bit;
837             case OdbcType.Char: return _Char;
838             case OdbcType.DateTime: return _DateTime;
839             case OdbcType.Date: return _Date;
840             case OdbcType.Time: return _Time;
841             case OdbcType.Double: return _Double;
842             case OdbcType.Decimal: return _Decimal;
843             case OdbcType.Image: return _Image;
844             case OdbcType.Int: return _Int;
845             case OdbcType.NChar: return _NChar;
846             case OdbcType.NText: return _NText;
847             case OdbcType.Numeric: return _Numeric;
848             case OdbcType.NVarChar: return _NVarChar;
849             case OdbcType.Real: return _Real;
850             case OdbcType.UniqueIdentifier: return _UniqueId;
851             case OdbcType.SmallDateTime: return _SmallDT;
852             case OdbcType.SmallInt: return _SmallInt;
853             case OdbcType.Text: return _Text;
854             case OdbcType.Timestamp: return _Timestamp;
855             case OdbcType.TinyInt: return _TinyInt;
856             case OdbcType.VarBinary: return _VarBinary;
857             case OdbcType.VarChar: return _VarChar;
858             default: throw ODBC.UnknownOdbcType(odbcType);
859             }
860         }
861
862         static internal TypeMap FromDbType(DbType dbType) {
863             switch(dbType) {
864             case DbType.AnsiString: return _VarChar;
865             case DbType.AnsiStringFixedLength: return _Char;
866             case DbType.Binary:     return _VarBinary;
867             case DbType.Byte:       return _TinyInt;
868             case DbType.Boolean:    return _Bit;
869             case DbType.Currency:   return _Decimal;
870 //            case DbType.Currency:   return _Currency;
871             case DbType.Date:       return _Date;
872             case DbType.Time:       return _Time;
873             case DbType.DateTime:   return _DateTime;
874             case DbType.Decimal:    return _Decimal;
875             case DbType.Double:     return _Double;
876             case DbType.Guid:       return _UniqueId;
877             case DbType.Int16:      return _SmallInt;
878             case DbType.Int32:      return _Int;
879             case DbType.Int64:      return _BigInt;
880             case DbType.Single:     return _Real;
881             case DbType.String:     return _NVarChar;
882             case DbType.StringFixedLength: return _NChar;
883             case DbType.Object:
884             case DbType.SByte:
885             case DbType.UInt16:
886             case DbType.UInt32:
887             case DbType.UInt64:
888             case DbType.VarNumeric:
889             default: throw ADP.DbTypeNotSupported(dbType, typeof(OdbcType));
890             }
891         }
892
893         static internal TypeMap FromSystemType(Type dataType) {
894             switch(Type.GetTypeCode(dataType)) {
895             case TypeCode.Empty:     throw ADP.InvalidDataType(TypeCode.Empty);
896             case TypeCode.Object:
897                 if (dataType == typeof(System.Byte[])) {
898                     return _VarBinary;
899                 }
900                 else if (dataType == typeof(System.Guid)) {
901                     return _UniqueId;
902                 }
903                 else if (dataType == typeof(System.TimeSpan)) {
904                     return _Time;
905                 }
906                 else if (dataType == typeof(System.Char[])) {
907                     return _NVarChar;
908                 }
909                 throw ADP.UnknownDataType(dataType);
910
911             case TypeCode.DBNull:    throw ADP.InvalidDataType(TypeCode.DBNull);
912             case TypeCode.Boolean:   return _Bit;
913
914 // devnote: Char is actually not supported. Our _Char type is actually a fixed length string, not a single character
915 //            case TypeCode.Char:      return _Char;
916             case TypeCode.SByte:     return _SmallInt;
917             case TypeCode.Byte:      return _TinyInt;
918             case TypeCode.Int16:     return _SmallInt;
919             case TypeCode.UInt16:    return _Int;
920             case TypeCode.Int32:     return _Int;
921             case TypeCode.UInt32:    return _BigInt;
922             case TypeCode.Int64:     return _BigInt;
923             case TypeCode.UInt64:    return _Numeric;
924             case TypeCode.Single:    return _Real;
925             case TypeCode.Double:    return _Double;
926             case TypeCode.Decimal:   return _Numeric;
927             case TypeCode.DateTime:  return _DateTime;
928
929             case TypeCode.Char:
930             case TypeCode.String:    return _NVarChar;
931
932             default:                 throw ADP.UnknownDataTypeCode(dataType, Type.GetTypeCode(dataType));
933             }
934         }
935
936         static internal TypeMap FromSqlType(ODBC32.SQL_TYPE sqltype) {
937             switch(sqltype) {
938             case ODBC32.SQL_TYPE.CHAR: return _Char;
939             case ODBC32.SQL_TYPE.VARCHAR: return _VarChar;
940             case ODBC32.SQL_TYPE.LONGVARCHAR: return _Text;
941             case ODBC32.SQL_TYPE.WCHAR: return _NChar;
942             case ODBC32.SQL_TYPE.WVARCHAR: return _NVarChar;
943             case ODBC32.SQL_TYPE.WLONGVARCHAR: return _NText;
944             case ODBC32.SQL_TYPE.DECIMAL: return _Decimal;
945             case ODBC32.SQL_TYPE.NUMERIC: return _Numeric;
946             case ODBC32.SQL_TYPE.SMALLINT: return _SmallInt;
947             case ODBC32.SQL_TYPE.INTEGER: return _Int;
948             case ODBC32.SQL_TYPE.REAL: return _Real;
949             case ODBC32.SQL_TYPE.FLOAT: return _Double;
950             case ODBC32.SQL_TYPE.DOUBLE: return _Double;
951             case ODBC32.SQL_TYPE.BIT: return _Bit;
952             case ODBC32.SQL_TYPE.TINYINT: return _TinyInt;
953             case ODBC32.SQL_TYPE.BIGINT: return _BigInt;
954             case ODBC32.SQL_TYPE.BINARY: return _Binary;
955             case ODBC32.SQL_TYPE.VARBINARY: return _VarBinary;
956             case ODBC32.SQL_TYPE.LONGVARBINARY: return _Image;
957             case ODBC32.SQL_TYPE.TYPE_DATE: return _Date;
958             case ODBC32.SQL_TYPE.TYPE_TIME: return _Time;
959             case ODBC32.SQL_TYPE.TIMESTAMP:
960             case ODBC32.SQL_TYPE.TYPE_TIMESTAMP: return _DateTime;
961             case ODBC32.SQL_TYPE.GUID: return _UniqueId;
962             case ODBC32.SQL_TYPE.SS_VARIANT: return _Variant;
963             case ODBC32.SQL_TYPE.SS_UDT: return _UDT;
964             case ODBC32.SQL_TYPE.SS_XML: return _XML;
965
966             case ODBC32.SQL_TYPE.SS_UTCDATETIME:
967             case ODBC32.SQL_TYPE.SS_TIME_EX:
968                 throw ODBC.UnknownSQLType(sqltype);
969             default:
970                 throw ODBC.UnknownSQLType(sqltype);
971             }
972         }
973
974         // Upgrade integer datatypes to missinterpretaion of the highest bit
975         // (e.g. 0xff could be 255 if unsigned but is -1 if signed)
976         //
977         static internal TypeMap UpgradeSignedType(TypeMap typeMap, bool unsigned) {
978             // upgrade unsigned types to be able to hold data that has the highest bit set
979             //
980             if (unsigned == true) {
981                 switch (typeMap._dbType) {
982                     case DbType.Int64:
983                         return _Decimal;        // upgrade to decimal
984                     case DbType.Int32:
985                         return _BigInt;         // upgrade to 64 bit
986                     case DbType.Int16:
987                         return _Int;            // upgrade to 32 bit
988                     default:
989                         return typeMap;
990                 } // end switch
991             }
992             else {
993                 switch (typeMap._dbType) {
994                     case DbType.Byte:
995                         return _SmallInt;       // upgrade to 16 bit
996                     default:
997                         return typeMap;
998                 } // end switch
999             }
1000         } // end UpgradeSignedType
1001     }
1002 }