1 //------------------------------------------------------------------------------
2 // <copyright file="Odbc32.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 //------------------------------------------------------------------------------
10 namespace System.Data.Odbc {
14 using System.Data.Common;
15 using System.Diagnostics;
16 using System.Globalization;
17 using System.Runtime.InteropServices;
18 using System.Runtime.ConstrainedExecution;
21 internal static class ODBC {
23 static internal Exception ConnectionClosed() {
24 return ADP.InvalidOperation(Res.GetString(Res.Odbc_ConnectionClosed));
27 static internal Exception OpenConnectionNoOwner() {
28 return ADP.InvalidOperation(Res.GetString(Res.Odbc_OpenConnectionNoOwner));
31 static internal Exception UnknownSQLType(ODBC32.SQL_TYPE sqltype) {
32 return ADP.Argument(Res.GetString(Res.Odbc_UnknownSQLType, sqltype.ToString()));
34 static internal Exception ConnectionStringTooLong() {
35 return ADP.Argument(Res.GetString(Res.OdbcConnection_ConnectionStringTooLong, ODBC32.MAX_CONNECTION_STRING_LENGTH));
37 static internal ArgumentException GetSchemaRestrictionRequired() {
38 return ADP.Argument(Res.GetString(Res.ODBC_GetSchemaRestrictionRequired));
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);
43 static internal ArgumentOutOfRangeException NotSupportedCommandType(CommandType value) {
46 case CommandType.Text:
47 case CommandType.StoredProcedure:
48 Debug.Assert(false, "valid CommandType " + value.ToString());
50 case CommandType.TableDirect:
53 Debug.Assert(false, "invalid CommandType " + value.ToString());
57 return ODBC.NotSupportedEnumerationValue(typeof(CommandType), (int)value);
59 static internal ArgumentOutOfRangeException NotSupportedIsolationLevel(IsolationLevel 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());
70 case IsolationLevel.Chaos:
73 Debug.Assert(false, "invalid IsolationLevel " + value.ToString());
77 return ODBC.NotSupportedEnumerationValue(typeof(IsolationLevel), (int)value);
80 static internal InvalidOperationException NoMappingForSqlTransactionLevel(int value) {
81 return ADP.DataAdapter(Res.GetString(Res.Odbc_NoMappingForSqlTransactionLevel, value.ToString(CultureInfo.InvariantCulture)));
84 static internal Exception NegativeArgument() {
85 return ADP.Argument(Res.GetString(Res.Odbc_NegativeArgument));
87 static internal Exception CantSetPropertyOnOpenConnection() {
88 return ADP.InvalidOperation(Res.GetString(Res.Odbc_CantSetPropertyOnOpenConnection));
90 static internal Exception CantEnableConnectionpooling(ODBC32.RetCode retcode) {
91 return ADP.DataAdapter(Res.GetString(Res.Odbc_CantEnableConnectionpooling, ODBC32.RetcodeToString(retcode)));
93 static internal Exception CantAllocateEnvironmentHandle(ODBC32.RetCode retcode) {
94 return ADP.DataAdapter(Res.GetString(Res.Odbc_CantAllocateEnvironmentHandle, ODBC32.RetcodeToString(retcode)));
96 static internal Exception FailedToGetDescriptorHandle(ODBC32.RetCode retcode) {
97 return ADP.DataAdapter(Res.GetString(Res.Odbc_FailedToGetDescriptorHandle, ODBC32.RetcodeToString(retcode)));
99 static internal Exception NotInTransaction() {
100 return ADP.InvalidOperation(Res.GetString(Res.Odbc_NotInTransaction));
102 static internal Exception UnknownOdbcType(OdbcType odbctype) {
103 return ADP.InvalidEnumerationValue(typeof(OdbcType), (int) odbctype);
105 internal const string Pwd = "pwd";
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);
111 internal static short ShortStringLength(string inputString) {
112 return checked((short)ADP.StringLength(inputString));
117 internal static class ODBC32 {
119 internal enum SQL_HANDLE : short {
126 // from .\public\sdk\inc\sqlext.h: and .\public\sdk\inc\sql.h
127 // must be public because it is serialized by OdbcException
129 public enum RETCODE : int { // must be int instead of short for Everett OdbcException Serializablity.
131 SUCCESS_WITH_INFO = 1,
137 // must be public because it is serialized by OdbcException
138 internal enum RetCode : short {
140 SUCCESS_WITH_INFO = 1,
146 internal static string RetcodeToString(RetCode 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";
154 Debug.Assert(false, "Unknown enumerator passed to RetcodeToString method");
155 goto case RetCode.ERROR;
161 internal enum SQL_CONVERT : ushort {
184 internal enum SQL_CVT {
186 NUMERIC = 0x00000002,
187 DECIMAL = 0x00000004,
188 INTEGER = 0x00000008,
189 SMALLINT = 0x00000010,
193 VARCHAR = 0x00000100,
194 LONGVARCHAR = 0x00000200,
196 VARBINARY = 0x00000800,
198 TINYINT = 0x00002000,
202 TIMESTAMP = 0x00020000,
203 LONGVARBINARY = 0x00040000,
204 INTERVAL_YEAR_MONTH = 0x00080000,
205 INTERVAL_DAY_TIME = 0x00100000,
207 WLONGVARCHAR = 0x00400000,
208 WVARCHAR = 0x00800000,
212 internal enum STMT : short {
219 internal enum SQL_MAX{
223 internal enum SQL_IS{
231 //SQL Server specific defines
233 internal enum SQL_HC // from Odbcss.h
235 OFF = 0, // FOR BROWSE columns are hidden
236 ON = 1, // FOR BROWSE columns are exposed
239 internal enum SQL_NB // from Odbcss.h
241 OFF = 0, // NO_BROWSETABLE is off
242 ON = 1, // NO_BROWSETABLE is on
245 // SQLColAttributes driver specific defines.
246 // SQLSet/GetDescField driver specific defines.
247 // Microsoft has 1200 thru 1249 reserved for Microsoft SQL Server driver usage.
249 internal enum SQL_CA_SS // from Odbcss.h
251 BASE = 1200, // SQL_CA_SS_BASE
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,
260 internal enum SQL_SOPT_SS // from Odbcss.h
262 BASE = 1225, // SQL_SOPT_SS_BASE
263 HIDDEN_COLUMNS = BASE + 2, // Expose FOR BROWSE hidden columns
264 NOBROWSETABLE = BASE + 3, // Set NOBROWSETABLE option
267 internal const Int16 SQL_COMMIT = 0; //Commit
268 internal const Int16 SQL_ROLLBACK = 1; //Abort
270 static internal readonly IntPtr SQL_AUTOCOMMIT_OFF = ADP.PtrZero;
271 static internal readonly IntPtr SQL_AUTOCOMMIT_ON = new IntPtr(1);
273 internal enum SQL_TRANSACTION
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)
282 internal enum SQL_PARAM
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
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
300 SQLPROCEDURECOLUMNS = 66,
307 internal enum SQL_DESC : short
309 // from sql.h (ODBCVER >= 3.0)
314 OCTET_LENGTH_PTR = 1004,
317 DATETIME_INTERVAL_CODE = 1007,
319 INDICATOR_PTR = 1009,
326 // from sqlext.h (ODBCVER >= 3.0)
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,
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,
339 BASE_COLUMN_NAME = 22,
340 BASE_TABLE_NAME = 23,
343 // ODBC version 2.0 style attributes
344 // All IdentifierValues are ODBC 1.0 unless marked differently
346 internal enum SQL_COLUMN
363 TABLE_NAME = 15, // (ODBC 2.0)
364 OWNER_NAME = 16, // (ODBC 2.0)
365 QUALIFIER_NAME = 17, // (ODBC 2.0)
369 internal enum SQL_GROUP_BY
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
378 // values from sqlext.h
379 internal enum SQL_SQL92_RELATIONAL_JOIN_OPERATORS
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
394 internal enum SQL_OJ_CAPABILITIES
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
405 internal enum SQL_UPDATABLE
407 READONLY = 0, // SQL_ATTR_READ_ONLY
408 WRITE = 1, // SQL_ATTR_WRITE
409 READWRITE_UNKNOWN = 2, // SQL_ATTR_READWRITE_UNKNOWN
412 internal enum SQL_IDENTIFIER_CASE
414 UPPER = 1, // SQL_IC_UPPER
415 LOWER = 2, // SQL_IC_LOWER
416 SENSITIVE = 3, // SQL_IC_SENSITIVE
417 MIXED = 4, // SQL_IC_MIXED
420 // Uniqueness parameter in the SQLStatistics function
421 internal enum SQL_INDEX : short
427 // Reserved parameter in the SQLStatistics function
428 internal enum SQL_STATISTICS_RESERVED : short
430 QUICK = 0, // SQL_QUICK
431 ENSURE = 1, // SQL_ENSURE
434 // Identifier type parameter in the SQLSpecialColumns function
435 internal enum SQL_SPECIALCOLS : ushort
437 BEST_ROWID = 1, // SQL_BEST_ROWID
438 ROWVER = 2, // SQL_ROWVER
441 // Scope parameter in the SQLSpecialColumns function
442 internal enum SQL_SCOPE : ushort
444 CURROW = 0, // SQL_SCOPE_CURROW
445 TRANSACTION = 1, // SQL_SCOPE_TRANSACTION
446 SESSION = 2, // SQL_SCOPE_SESSION
449 internal enum SQL_NULLABILITY : ushort
451 NO_NULLS = 0, // SQL_NO_NULLS
452 NULLABLE = 1, // SQL_NULLABLE
453 UNKNOWN = 2, // SQL_NULLABLE_UNKNOWN
456 internal enum SQL_SEARCHABLE
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
464 internal enum SQL_UNNAMED
466 NAMED = 0, // SQL_NAMED
467 UNNAMED = 1, // SQL_UNNAMED
470 // internal constants
473 internal enum HANDLER
479 // values for SQLStatistics TYPE column
480 internal enum SQL_STATISTICSTYPE
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
488 // values for SQLProcedures PROCEDURE_TYPE column
489 internal enum SQL_PROCEDURETYPE
491 UNKNOWN = 0, // procedure is of unknow type
492 PROCEDURE = 1, // procedure is a procedure
493 FUNCTION = 2, // procedure is a function
497 // to define data types (see below)
499 private const Int32 SIGNED_OFFSET = -20; // SQL_SIGNED_OFFSET
500 private const Int32 UNSIGNED_OFFSET = -22; // SQL_UNSIGNED_OFFSET
502 //C Data Types - used when getting data (SQLGetData)
503 internal enum SQL_C : short
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
521 TYPE_DATE = 91, //SQL_C_TYPE_DATE
522 TYPE_TIME = 92, //SQL_C_TYPE_TIME
523 TYPE_TIMESTAMP = 93, //SQL_C_TYPE_TIMESTAMP
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
531 //SQL Data Types - returned as column types (SQLColAttribute)
532 internal enum SQL_TYPE : short
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
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
561 GUID = SQL_C.GUID, //SQL_GUID
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.
570 SS_UTCDATETIME = -153,
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
579 internal const Int32 SQL_DEFAULT_PARAM= -5;
580 // internal const Int32 SQL_IGNORE = -6;
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
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;
592 internal enum SQL_ATTR
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)
600 CONNECTION_POOLING = 201,
603 CURRENT_CATALOG = 109,
605 QUERY_TIMEOUT = 0, // from sqlext.h
606 CONNECTION_DEAD = 1209, // from sqlext.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
615 internal enum SQL_INFO : ushort
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
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
639 static internal readonly IntPtr SQL_OV_ODBC3 = new IntPtr(3);
640 internal const Int32 SQL_NTS = -3; //flags for null-terminated string
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
647 /* values for SQL_ATTR_CONNECTION_DEAD */
648 internal const Int32 SQL_CD_TRUE = 1;
649 internal const Int32 SQL_CD_FALSE = 0;
651 internal const Int32 SQL_DTC_DONE = 0;
652 internal const Int32 SQL_IS_POINTER = -4;
653 internal const Int32 SQL_IS_PTR = 1;
655 internal enum SQL_DRIVER
660 COMPLETE_REQUIRED = 3,
664 // internal const. not odbc specific
666 // Connection string max length
667 internal const Int32 MAX_CONNECTION_STRING_LENGTH = 1024;
669 // Column set for SQLPrimaryKeys
670 internal enum SQL_PRIMARYKEYS : short
673 CATALOGNAME = 1, // TABLE_CAT
674 SCHEMANAME = 2, // TABLE_SCHEM
675 TABLENAME = 3, // TABLE_NAME
677 COLUMNNAME = 4, // COLUMN_NAME
679 KEY_SEQ = 5, // KEY_SEQ
680 PKNAME = 6, // PK_NAME
684 // Column set for SQLStatistics
685 internal enum SQL_STATISTICS : short
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
694 INDEXNAME = 6, // INDEX_NAME
698 ORDINAL_POSITION = 8, // ORDINAL_POSITION
699 COLUMN_NAME = 9, // COLUMN_NAME
701 ASC_OR_DESC = 10, // ASC_OR_DESC
702 CARDINALITY = 11, // CARDINALITY
704 FILTER_CONDITION = 13, // FILTER_CONDITION
708 // Column set for SQLSpecialColumns
709 internal enum SQL_SPECIALCOLUMNSET : short
714 COLUMN_NAME = 2, // COLUMN_NAME
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
725 internal const short SQL_DIAG_SQLSTATE = 4;
726 internal const short SQL_RESULT_COL = 3;
729 static internal OdbcErrorCollection GetDiagErrors(string source, OdbcHandle hrHandle, RetCode retcode) {
730 OdbcErrorCollection errors = new OdbcErrorCollection();
731 GetDiagErrors(errors, source, hrHandle, retcode);
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) {
742 StringBuilder message = new StringBuilder(1024);
744 bool moreerrors = true;
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);
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);
759 //Sets up the InnerException as well...
760 errors.Add(new OdbcError(
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);
805 internal readonly OdbcType _odbcType;
806 internal readonly DbType _dbType;
807 internal readonly Type _type;
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;
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
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;
823 _sql_type = sql_type;
825 _param_sql_c = param_sql_c; // alternative sql_c type for parameters
829 _signType = signType;
832 static internal TypeMap FromOdbcType(OdbcType 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);
862 static internal TypeMap FromDbType(DbType 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;
888 case DbType.VarNumeric:
889 default: throw ADP.DbTypeNotSupported(dbType, typeof(OdbcType));
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[])) {
900 else if (dataType == typeof(System.Guid)) {
903 else if (dataType == typeof(System.TimeSpan)) {
906 else if (dataType == typeof(System.Char[])) {
909 throw ADP.UnknownDataType(dataType);
911 case TypeCode.DBNull: throw ADP.InvalidDataType(TypeCode.DBNull);
912 case TypeCode.Boolean: return _Bit;
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;
930 case TypeCode.String: return _NVarChar;
932 default: throw ADP.UnknownDataTypeCode(dataType, Type.GetTypeCode(dataType));
936 static internal TypeMap FromSqlType(ODBC32.SQL_TYPE 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;
966 case ODBC32.SQL_TYPE.SS_UTCDATETIME:
967 case ODBC32.SQL_TYPE.SS_TIME_EX:
968 throw ODBC.UnknownSQLType(sqltype);
970 throw ODBC.UnknownSQLType(sqltype);
974 // Upgrade integer datatypes to missinterpretaion of the highest bit
975 // (e.g. 0xff could be 255 if unsigned but is -1 if signed)
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
980 if (unsigned == true) {
981 switch (typeMap._dbType) {
983 return _Decimal; // upgrade to decimal
985 return _BigInt; // upgrade to 64 bit
987 return _Int; // upgrade to 32 bit
993 switch (typeMap._dbType) {
995 return _SmallInt; // upgrade to 16 bit
1000 } // end UpgradeSignedType