|
//------------------------------------------------------------------------------
// <copyright file="Odbc32.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
// <owner current="true" primary="false">Microsoft</owner>
//------------------------------------------------------------------------------
namespace System.Data.Odbc {
using System;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.ConstrainedExecution;
using System.Text;
internal static class ODBC {
static internal Exception ConnectionClosed() {
return ADP.InvalidOperation(Res.GetString(Res.Odbc_ConnectionClosed));
}
static internal Exception OpenConnectionNoOwner() {
return ADP.InvalidOperation(Res.GetString(Res.Odbc_OpenConnectionNoOwner));
}
static internal Exception UnknownSQLType(ODBC32.SQL_TYPE sqltype) {
return ADP.Argument(Res.GetString(Res.Odbc_UnknownSQLType, sqltype.ToString()));
}
static internal Exception ConnectionStringTooLong() {
return ADP.Argument(Res.GetString(Res.OdbcConnection_ConnectionStringTooLong, ODBC32.MAX_CONNECTION_STRING_LENGTH));
}
static internal ArgumentException GetSchemaRestrictionRequired() {
return ADP.Argument(Res.GetString(Res.ODBC_GetSchemaRestrictionRequired));
}
static internal ArgumentOutOfRangeException NotSupportedEnumerationValue(Type type, int value) {
return ADP.ArgumentOutOfRange(Res.GetString(Res.ODBC_NotSupportedEnumerationValue, type.Name, value.ToString(System.Globalization.CultureInfo.InvariantCulture)), type.Name);
}
static internal ArgumentOutOfRangeException NotSupportedCommandType(CommandType value) {
#if DEBUG
switch(value) {
case CommandType.Text:
case CommandType.StoredProcedure:
Debug.Assert(false, "valid CommandType " + value.ToString());
break;
case CommandType.TableDirect:
break;
default:
Debug.Assert(false, "invalid CommandType " + value.ToString());
break;
}
#endif
return ODBC.NotSupportedEnumerationValue(typeof(CommandType), (int)value);
}
static internal ArgumentOutOfRangeException NotSupportedIsolationLevel(IsolationLevel value) {
#if DEBUG
switch(value) {
case IsolationLevel.Unspecified:
case IsolationLevel.ReadUncommitted:
case IsolationLevel.ReadCommitted:
case IsolationLevel.RepeatableRead:
case IsolationLevel.Serializable:
case IsolationLevel.Snapshot:
Debug.Assert(false, "valid IsolationLevel " + value.ToString());
break;
case IsolationLevel.Chaos:
break;
default:
Debug.Assert(false, "invalid IsolationLevel " + value.ToString());
break;
}
#endif
return ODBC.NotSupportedEnumerationValue(typeof(IsolationLevel), (int)value);
}
static internal InvalidOperationException NoMappingForSqlTransactionLevel(int value) {
return ADP.DataAdapter(Res.GetString(Res.Odbc_NoMappingForSqlTransactionLevel, value.ToString(CultureInfo.InvariantCulture)));
}
static internal Exception NegativeArgument() {
return ADP.Argument(Res.GetString(Res.Odbc_NegativeArgument));
}
static internal Exception CantSetPropertyOnOpenConnection() {
return ADP.InvalidOperation(Res.GetString(Res.Odbc_CantSetPropertyOnOpenConnection));
}
static internal Exception CantEnableConnectionpooling(ODBC32.RetCode retcode) {
return ADP.DataAdapter(Res.GetString(Res.Odbc_CantEnableConnectionpooling, ODBC32.RetcodeToString(retcode)));
}
static internal Exception CantAllocateEnvironmentHandle(ODBC32.RetCode retcode) {
return ADP.DataAdapter(Res.GetString(Res.Odbc_CantAllocateEnvironmentHandle, ODBC32.RetcodeToString(retcode)));
}
static internal Exception FailedToGetDescriptorHandle(ODBC32.RetCode retcode) {
return ADP.DataAdapter(Res.GetString(Res.Odbc_FailedToGetDescriptorHandle, ODBC32.RetcodeToString(retcode)));
}
static internal Exception NotInTransaction() {
return ADP.InvalidOperation(Res.GetString(Res.Odbc_NotInTransaction));
}
static internal Exception UnknownOdbcType(OdbcType odbctype) {
return ADP.InvalidEnumerationValue(typeof(OdbcType), (int) odbctype);
}
internal const string Pwd = "pwd";
static internal void TraceODBC(int level, string method, ODBC32.RetCode retcode) {
Bid.TraceSqlReturn("<odbc|API|ODBC|RET> %08X{SQLRETURN}, method=%ls\n", retcode, method);
}
internal static short ShortStringLength(string inputString) {
return checked((short)ADP.StringLength(inputString));
}
}
internal static class ODBC32 {
internal enum SQL_HANDLE : short {
ENV = 1,
DBC = 2,
STMT = 3,
DESC = 4,
}
// from .\public\sdk\inc\sqlext.h: and .\public\sdk\inc\sql.h
// must be public because it is serialized by OdbcException
[Serializable]
public enum RETCODE : int { // must be int instead of short for Everett OdbcException Serializablity.
SUCCESS = 0,
SUCCESS_WITH_INFO = 1,
ERROR = -1,
INVALID_HANDLE = -2,
NO_DATA = 100,
}
// must be public because it is serialized by OdbcException
internal enum RetCode : short {
SUCCESS = 0,
SUCCESS_WITH_INFO = 1,
ERROR = -1,
INVALID_HANDLE = -2,
NO_DATA = 100,
}
internal static string RetcodeToString(RetCode retcode) {
switch (retcode) {
case RetCode.SUCCESS: return "SUCCESS";
case RetCode.SUCCESS_WITH_INFO: return "SUCCESS_WITH_INFO";
case RetCode.ERROR: return "ERROR";
case RetCode.INVALID_HANDLE: return "INVALID_HANDLE";
case RetCode.NO_DATA: return "NO_DATA";
default:
Debug.Assert(false, "Unknown enumerator passed to RetcodeToString method");
goto case RetCode.ERROR;
}
}
internal enum SQL_CONVERT : ushort {
BIGINT = 53,
BINARY = 54,
BIT = 55,
CHAR = 56,
DATE = 57,
DECIMAL = 58,
DOUBLE = 59,
FLOAT = 60,
INTEGER = 61,
LONGVARCHAR = 62,
NUMERIC = 63,
REAL = 64,
SMALLINT = 65,
TIME = 66,
TIMESTAMP = 67,
TINYINT = 68,
VARBINARY = 69,
VARCHAR = 70,
LONGVARBINARY = 71,
}
[Flags]
internal enum SQL_CVT {
CHAR = 0x00000001,
NUMERIC = 0x00000002,
DECIMAL = 0x00000004,
INTEGER = 0x00000008,
SMALLINT = 0x00000010,
FLOAT = 0x00000020,
REAL = 0x00000040,
DOUBLE = 0x00000080,
VARCHAR = 0x00000100,
LONGVARCHAR = 0x00000200,
BINARY = 0x00000400,
VARBINARY = 0x00000800,
BIT = 0x00001000,
TINYINT = 0x00002000,
BIGINT = 0x00004000,
DATE = 0x00008000,
TIME = 0x00010000,
TIMESTAMP = 0x00020000,
LONGVARBINARY = 0x00040000,
INTERVAL_YEAR_MONTH = 0x00080000,
INTERVAL_DAY_TIME = 0x00100000,
WCHAR = 0x00200000,
WLONGVARCHAR = 0x00400000,
WVARCHAR = 0x00800000,
GUID = 0x01000000,
}
internal enum STMT : short {
CLOSE = 0,
DROP = 1,
UNBIND = 2,
RESET_PARAMS = 3,
}
internal enum SQL_MAX{
NUMERIC_LEN = 16,
}
internal enum SQL_IS{
POINTER = -4,
INTEGER = -6,
UINTEGER = -5,
SMALLINT = -8,
}
//SQL Server specific defines
//
internal enum SQL_HC // from Odbcss.h
{
OFF = 0, // FOR BROWSE columns are hidden
ON = 1, // FOR BROWSE columns are exposed
}
internal enum SQL_NB // from Odbcss.h
{
OFF = 0, // NO_BROWSETABLE is off
ON = 1, // NO_BROWSETABLE is on
}
// SQLColAttributes driver specific defines.
// SQLSet/GetDescField driver specific defines.
// Microsoft has 1200 thru 1249 reserved for Microsoft SQL Server driver usage.
//
internal enum SQL_CA_SS // from Odbcss.h
{
BASE = 1200, // SQL_CA_SS_BASE
COLUMN_HIDDEN = BASE + 11, // Column is hidden (FOR BROWSE)
COLUMN_KEY = BASE + 12, // Column is key column (FOR BROWSE)
VARIANT_TYPE = BASE + 15,
VARIANT_SQL_TYPE = BASE + 16,
VARIANT_SERVER_TYPE = BASE + 17,
}
internal enum SQL_SOPT_SS // from Odbcss.h
{
BASE = 1225, // SQL_SOPT_SS_BASE
HIDDEN_COLUMNS = BASE + 2, // Expose FOR BROWSE hidden columns
NOBROWSETABLE = BASE + 3, // Set NOBROWSETABLE option
}
internal const Int16 SQL_COMMIT = 0; //Commit
internal const Int16 SQL_ROLLBACK = 1; //Abort
static internal readonly IntPtr SQL_AUTOCOMMIT_OFF = ADP.PtrZero;
static internal readonly IntPtr SQL_AUTOCOMMIT_ON = new IntPtr(1);
internal enum SQL_TRANSACTION
{
READ_UNCOMMITTED = 0x00000001,
READ_COMMITTED = 0x00000002,
REPEATABLE_READ = 0x00000004,
SERIALIZABLE = 0x00000008,
SNAPSHOT = 0x00000020, // VSDD 414121: SQL_TXN_SS_SNAPSHOT == 0x20 (sqlncli.h)
}
internal enum SQL_PARAM
{
// unused TYPE_UNKNOWN = 0, // SQL_PARAM_TYPE_UNKNOWN
INPUT = 1, // SQL_PARAM_INPUT
INPUT_OUTPUT = 2, // SQL_PARAM_INPUT_OUTPUT
// unused RESULT_COL = 3, // SQL_RESULT_COL
OUTPUT = 4, // SQL_PARAM_OUTPUT
RETURN_VALUE = 5, // SQL_RETURN_VALUE
}
// SQL_API_* values
// there are a gillion of these I am only defining the ones currently needed
// others can be added as needed
internal enum SQL_API : ushort
{
SQLCOLUMNS = 40,
SQLEXECDIRECT = 11,
SQLGETTYPEINFO = 47,
SQLPROCEDURECOLUMNS = 66,
SQLPROCEDURES = 67,
SQLSTATISTICS = 53,
SQLTABLES = 54,
}
internal enum SQL_DESC : short
{
// from sql.h (ODBCVER >= 3.0)
//
COUNT = 1001,
TYPE = 1002,
LENGTH = 1003,
OCTET_LENGTH_PTR = 1004,
PRECISION = 1005,
SCALE = 1006,
DATETIME_INTERVAL_CODE = 1007,
NULLABLE = 1008,
INDICATOR_PTR = 1009,
DATA_PTR = 1010,
NAME = 1011,
UNNAMED = 1012,
OCTET_LENGTH = 1013,
ALLOC_TYPE = 1099,
// from sqlext.h (ODBCVER >= 3.0)
//
CONCISE_TYPE = SQL_COLUMN.TYPE,
DISPLAY_SIZE = SQL_COLUMN.DISPLAY_SIZE,
UNSIGNED = SQL_COLUMN.UNSIGNED,
UPDATABLE = SQL_COLUMN.UPDATABLE,
AUTO_UNIQUE_VALUE = SQL_COLUMN.AUTO_INCREMENT,
TYPE_NAME = SQL_COLUMN.TYPE_NAME,
TABLE_NAME = SQL_COLUMN.TABLE_NAME,
SCHEMA_NAME = SQL_COLUMN.OWNER_NAME,
CATALOG_NAME = SQL_COLUMN.QUALIFIER_NAME,
BASE_COLUMN_NAME = 22,
BASE_TABLE_NAME = 23,
}
// ODBC version 2.0 style attributes
// All IdentifierValues are ODBC 1.0 unless marked differently
//
internal enum SQL_COLUMN
{
COUNT = 0,
NAME = 1,
TYPE = 2,
LENGTH = 3,
PRECISION = 4,
SCALE = 5,
DISPLAY_SIZE = 6,
NULLABLE = 7,
UNSIGNED = 8,
MONEY = 9,
UPDATABLE = 10,
AUTO_INCREMENT = 11,
CASE_SENSITIVE = 12,
SEARCHABLE = 13,
TYPE_NAME = 14,
TABLE_NAME = 15, // (ODBC 2.0)
OWNER_NAME = 16, // (ODBC 2.0)
QUALIFIER_NAME = 17, // (ODBC 2.0)
LABEL = 18,
}
internal enum SQL_GROUP_BY
{
NOT_SUPPORTED = 0, // SQL_GB_NOT_SUPPORTED
GROUP_BY_EQUALS_SELECT = 1, // SQL_GB_GROUP_BY_EQUALS_SELECT
GROUP_BY_CONTAINS_SELECT = 2, // SQL_GB_GROUP_BY_CONTAINS_SELECT
NO_RELATION = 3, // SQL_GB_NO_RELATION
COLLATE = 4, // SQL_GB_COLLATE - added in ODBC 3.0
}
// values from sqlext.h
internal enum SQL_SQL92_RELATIONAL_JOIN_OPERATORS
{
CORRESPONDING_CLAUSE = 0x00000001, // SQL_SRJO_CORRESPONDING_CLAUSE
CROSS_JOIN = 0x00000002, // SQL_SRJO_CROSS_JOIN
EXCEPT_JOIN = 0x00000004, // SQL_SRJO_EXCEPT_JOIN
FULL_OUTER_JOIN = 0x00000008, // SQL_SRJO_FULL_OUTER_JOIN
INNER_JOIN = 0x00000010, // SQL_SRJO_INNER_JOIN
INTERSECT_JOIN = 0x00000020, // SQL_SRJO_INTERSECT_JOIN
LEFT_OUTER_JOIN = 0x00000040, // SQL_SRJO_LEFT_OUTER_JOIN
NATURAL_JOIN = 0x00000080, // SQL_SRJO_NATURAL_JOIN
RIGHT_OUTER_JOIN = 0x00000100, // SQL_SRJO_RIGHT_OUTER_JOIN
UNION_JOIN = 0x00000200, // SQL_SRJO_UNION_JOIN
}
// values from sql.h
internal enum SQL_OJ_CAPABILITIES
{
LEFT = 0x00000001, // SQL_OJ_LEFT
RIGHT = 0x00000002, // SQL_OJ_RIGHT
FULL = 0x00000004, // SQL_OJ_FULL
NESTED = 0x00000008, // SQL_OJ_NESTED
NOT_ORDERED = 0x00000010, // SQL_OJ_NOT_ORDERED
INNER = 0x00000020, // SQL_OJ_INNER
ALL_COMPARISON_OPS = 0x00000040, //SQL_OJ_ALLCOMPARISION+OPS
}
internal enum SQL_UPDATABLE
{
READONLY = 0, // SQL_ATTR_READ_ONLY
WRITE = 1, // SQL_ATTR_WRITE
READWRITE_UNKNOWN = 2, // SQL_ATTR_READWRITE_UNKNOWN
}
internal enum SQL_IDENTIFIER_CASE
{
UPPER = 1, // SQL_IC_UPPER
LOWER = 2, // SQL_IC_LOWER
SENSITIVE = 3, // SQL_IC_SENSITIVE
MIXED = 4, // SQL_IC_MIXED
}
// Uniqueness parameter in the SQLStatistics function
internal enum SQL_INDEX : short
{
UNIQUE = 0,
ALL = 1,
}
// Reserved parameter in the SQLStatistics function
internal enum SQL_STATISTICS_RESERVED : short
{
QUICK = 0, // SQL_QUICK
ENSURE = 1, // SQL_ENSURE
}
// Identifier type parameter in the SQLSpecialColumns function
internal enum SQL_SPECIALCOLS : ushort
{
BEST_ROWID = 1, // SQL_BEST_ROWID
ROWVER = 2, // SQL_ROWVER
}
// Scope parameter in the SQLSpecialColumns function
internal enum SQL_SCOPE : ushort
{
CURROW = 0, // SQL_SCOPE_CURROW
TRANSACTION = 1, // SQL_SCOPE_TRANSACTION
SESSION = 2, // SQL_SCOPE_SESSION
}
internal enum SQL_NULLABILITY : ushort
{
NO_NULLS = 0, // SQL_NO_NULLS
NULLABLE = 1, // SQL_NULLABLE
UNKNOWN = 2, // SQL_NULLABLE_UNKNOWN
}
internal enum SQL_SEARCHABLE
{
UNSEARCHABLE = 0, // SQL_UNSEARCHABLE
LIKE_ONLY = 1, // SQL_LIKE_ONLY
ALL_EXCEPT_LIKE = 2, // SQL_ALL_EXCEPT_LIKE
SEARCHABLE = 3, // SQL_SEARCHABLE
}
internal enum SQL_UNNAMED
{
NAMED = 0, // SQL_NAMED
UNNAMED = 1, // SQL_UNNAMED
}
// todo:move
// internal constants
// not odbc specific
//
internal enum HANDLER
{
IGNORE = 0x00000000,
THROW = 0x00000001,
}
// values for SQLStatistics TYPE column
internal enum SQL_STATISTICSTYPE
{
TABLE_STAT = 0, // TABLE Statistics
INDEX_CLUSTERED = 1, // CLUSTERED index statistics
INDEX_HASHED = 2, // HASHED index statistics
INDEX_OTHER = 3, // OTHER index statistics
}
// values for SQLProcedures PROCEDURE_TYPE column
internal enum SQL_PROCEDURETYPE
{
UNKNOWN = 0, // procedure is of unknow type
PROCEDURE = 1, // procedure is a procedure
FUNCTION = 2, // procedure is a function
}
// private constants
// to define data types (see below)
//
private const Int32 SIGNED_OFFSET = -20; // SQL_SIGNED_OFFSET
private const Int32 UNSIGNED_OFFSET = -22; // SQL_UNSIGNED_OFFSET
//C Data Types - used when getting data (SQLGetData)
internal enum SQL_C : short
{
CHAR = 1, //SQL_C_CHAR
WCHAR = -8, //SQL_C_WCHAR
SLONG = 4 + SIGNED_OFFSET, //SQL_C_LONG+SQL_SIGNED_OFFSET
// ULONG = 4 + UNSIGNED_OFFSET, //SQL_C_LONG+SQL_UNSIGNED_OFFSET
SSHORT = 5 + SIGNED_OFFSET, //SQL_C_SSHORT+SQL_SIGNED_OFFSET
// USHORT = 5 + UNSIGNED_OFFSET, //SQL_C_USHORT+SQL_UNSIGNED_OFFSET
REAL = 7, //SQL_C_REAL
DOUBLE = 8, //SQL_C_DOUBLE
BIT = -7, //SQL_C_BIT
// STINYINT = -6 + SIGNED_OFFSET, //SQL_C_STINYINT+SQL_SIGNED_OFFSET
UTINYINT = -6 + UNSIGNED_OFFSET, //SQL_C_UTINYINT+SQL_UNSIGNED_OFFSET
SBIGINT = -5 + SIGNED_OFFSET, //SQL_C_SBIGINT+SQL_SIGNED_OFFSET
UBIGINT = -5 + UNSIGNED_OFFSET, //SQL_C_UBIGINT+SQL_UNSIGNED_OFFSET
BINARY = -2, //SQL_C_BINARY
TIMESTAMP = 11, //SQL_C_TIMESTAMP
TYPE_DATE = 91, //SQL_C_TYPE_DATE
TYPE_TIME = 92, //SQL_C_TYPE_TIME
TYPE_TIMESTAMP = 93, //SQL_C_TYPE_TIMESTAMP
NUMERIC = 2, //SQL_C_NUMERIC
GUID = -11, //SQL_C_GUID
DEFAULT = 99, //SQL_C_DEFAULT
ARD_TYPE = -99, //SQL_ARD_TYPE
}
//SQL Data Types - returned as column types (SQLColAttribute)
internal enum SQL_TYPE : short
{
CHAR = SQL_C.CHAR, //SQL_CHAR
VARCHAR = 12, //SQL_VARCHAR
LONGVARCHAR = -1, //SQL_LONGVARCHAR
WCHAR = SQL_C.WCHAR, //SQL_WCHAR
WVARCHAR = -9, //SQL_WVARCHAR
WLONGVARCHAR = -10, //SQL_WLONGVARCHAR
DECIMAL = 3, //SQL_DECIMAL
NUMERIC = SQL_C.NUMERIC, //SQL_NUMERIC
SMALLINT = 5, //SQL_SMALLINT
INTEGER = 4, //SQL_INTEGER
REAL = SQL_C.REAL, //SQL_REAL
FLOAT = 6, //SQL_FLOAT
DOUBLE = SQL_C.DOUBLE, //SQL_DOUBLE
BIT = SQL_C.BIT, //SQL_BIT
TINYINT = -6, //SQL_TINYINT
BIGINT = -5, //SQL_BIGINT
BINARY = SQL_C.BINARY, //SQL_BINARY
VARBINARY = -3, //SQL_VARBINARY
LONGVARBINARY = -4, //SQL_LONGVARBINARY
// DATE = 9, //SQL_DATE
TYPE_DATE = SQL_C.TYPE_DATE, //SQL_TYPE_DATE
TYPE_TIME = SQL_C.TYPE_TIME, //SQL_TYPE_TIME
TIMESTAMP = SQL_C.TIMESTAMP, //SQL_TIMESTAMP
TYPE_TIMESTAMP = SQL_C.TYPE_TIMESTAMP, //SQL_TYPE_TIMESTAMP
GUID = SQL_C.GUID, //SQL_GUID
// from odbcss.h in mdac 9.0 sources!
// Driver specific SQL type defines.
// Microsoft has -150 thru -199 reserved for Microsoft SQL Server driver usage.
//
SS_VARIANT = -150,
SS_UDT = -151,
SS_XML = -152,
SS_UTCDATETIME = -153,
SS_TIME_EX = -154,
}
internal const Int16 SQL_ALL_TYPES = 0;
static internal readonly IntPtr SQL_HANDLE_NULL = ADP.PtrZero;
internal const Int32 SQL_NULL_DATA = -1; // sql.h
internal const Int32 SQL_NO_TOTAL = -4; // sqlext.h
internal const Int32 SQL_DEFAULT_PARAM= -5;
// internal const Int32 SQL_IGNORE = -6;
// column ordinals for SQLProcedureColumns result set
// this column ordinals are not defined in any c/c++ header but in the ODBC Programmer's Reference under SQLProcedureColumns
//
internal const Int32 COLUMN_NAME = 4;
internal const Int32 COLUMN_TYPE = 5;
internal const Int32 DATA_TYPE = 6;
internal const Int32 COLUMN_SIZE = 8;
internal const Int32 DECIMAL_DIGITS = 10;
internal const Int32 NUM_PREC_RADIX = 11;
internal enum SQL_ATTR
{
APP_ROW_DESC = 10010, // (ODBC 3.0)
APP_PARAM_DESC = 10011, // (ODBC 3.0)
IMP_ROW_DESC = 10012, // (ODBC 3.0)
IMP_PARAM_DESC = 10013, // (ODBC 3.0)
METADATA_ID = 10014, // (ODBC 3.0)
ODBC_VERSION = 200,
CONNECTION_POOLING = 201,
AUTOCOMMIT = 102,
TXN_ISOLATION = 108,
CURRENT_CATALOG = 109,
LOGIN_TIMEOUT = 103,
QUERY_TIMEOUT = 0, // from sqlext.h
CONNECTION_DEAD = 1209, // from sqlext.h
// from sqlncli.h
SQL_COPT_SS_BASE = 1200,
SQL_COPT_SS_ENLIST_IN_DTC = (SQL_COPT_SS_BASE + 7),
SQL_COPT_SS_TXN_ISOLATION = (SQL_COPT_SS_BASE + 27), // Used to set/get any driver-specific or ODBC-defined TXN iso level
}
//SQLGetInfo
internal enum SQL_INFO : ushort
{
DATA_SOURCE_NAME = 2, // SQL_DATA_SOURCE_NAME in sql.h
SERVER_NAME = 13, // SQL_SERVER_NAME in sql.h
DRIVER_NAME = 6, // SQL_DRIVER_NAME as defined in sqlext.h
DRIVER_VER = 7, // SQL_DRIVER_VER as defined in sqlext.h
ODBC_VER = 10, // SQL_ODBC_VER as defined in sqlext.h
SEARCH_PATTERN_ESCAPE = 14, // SQL_SEARCH_PATTERN_ESCAPE from sql.h
DBMS_VER = 18,
DBMS_NAME = 17, // SQL_DBMS_NAME as defined in sqlext.h
IDENTIFIER_CASE = 28, // SQL_IDENTIFIER_CASE from sql.h
IDENTIFIER_QUOTE_CHAR = 29, // SQL_IDENTIFIER_QUOTE_CHAR from sql.h
CATALOG_NAME_SEPARATOR = 41, // SQL_CATALOG_NAME_SEPARATOR
DRIVER_ODBC_VER = 77, // SQL_DRIVER_ODBC_VER as defined in sqlext.h
GROUP_BY = 88, // SQL_GROUP_BY as defined in sqlext.h
KEYWORDS = 89, // SQL_KEYWORDS as defined in sqlext.h
ORDER_BY_COLUMNS_IN_SELECT = 90, // SQL_ORDER_BY_COLUNS_IN_SELECT in sql.h
QUOTED_IDENTIFIER_CASE = 93, // SQL_QUOTED_IDENTIFIER_CASE in sqlext.h
SQL_OJ_CAPABILITIES_30 = 115, //SQL_OJ_CAPABILITIES from sql.h
SQL_OJ_CAPABILITIES_20 = 65003, //SQL_OJ_CAPABILITIES from sqlext.h
SQL_SQL92_RELATIONAL_JOIN_OPERATORS = 161, //SQL_SQL92_RELATIONAL_JOIN_OPERATORS from sqlext.h
}
static internal readonly IntPtr SQL_OV_ODBC3 = new IntPtr(3);
internal const Int32 SQL_NTS = -3; //flags for null-terminated string
//Pooling
static internal readonly IntPtr SQL_CP_OFF = new IntPtr(0); //Connection Pooling disabled
static internal readonly IntPtr SQL_CP_ONE_PER_DRIVER = new IntPtr(1); //One pool per driver
static internal readonly IntPtr SQL_CP_ONE_PER_HENV = new IntPtr(2); //One pool per environment
/* values for SQL_ATTR_CONNECTION_DEAD */
internal const Int32 SQL_CD_TRUE = 1;
internal const Int32 SQL_CD_FALSE = 0;
internal const Int32 SQL_DTC_DONE = 0;
internal const Int32 SQL_IS_POINTER = -4;
internal const Int32 SQL_IS_PTR = 1;
internal enum SQL_DRIVER
{
NOPROMPT = 0,
COMPLETE = 1,
PROMPT = 2,
COMPLETE_REQUIRED = 3,
}
// todo:move
// internal const. not odbc specific
//
// Connection string max length
internal const Int32 MAX_CONNECTION_STRING_LENGTH = 1024;
// Column set for SQLPrimaryKeys
internal enum SQL_PRIMARYKEYS : short
{
/*
CATALOGNAME = 1, // TABLE_CAT
SCHEMANAME = 2, // TABLE_SCHEM
TABLENAME = 3, // TABLE_NAME
*/
COLUMNNAME = 4, // COLUMN_NAME
/*
KEY_SEQ = 5, // KEY_SEQ
PKNAME = 6, // PK_NAME
*/
}
// Column set for SQLStatistics
internal enum SQL_STATISTICS : short
{
/*
CATALOGNAME = 1, // TABLE_CAT
SCHEMANAME = 2, // TABLE_SCHEM
TABLENAME = 3, // TABLE_NAME
NONUNIQUE = 4, // NON_UNIQUE
INDEXQUALIFIER = 5, // INDEX_QUALIFIER
*/
INDEXNAME = 6, // INDEX_NAME
/*
TYPE = 7, // TYPE
*/
ORDINAL_POSITION = 8, // ORDINAL_POSITION
COLUMN_NAME = 9, // COLUMN_NAME
/*
ASC_OR_DESC = 10, // ASC_OR_DESC
CARDINALITY = 11, // CARDINALITY
PAGES = 12, // PAGES
FILTER_CONDITION = 13, // FILTER_CONDITION
*/
}
// Column set for SQLSpecialColumns
internal enum SQL_SPECIALCOLUMNSET : short
{
/*
SCOPE = 1, // SCOPE
*/
COLUMN_NAME = 2, // COLUMN_NAME
/*
DATA_TYPE = 3, // DATA_TYPE
TYPE_NAME = 4, // TYPE_NAME
COLUMN_SIZE = 5, // COLUMN_SIZE
BUFFER_LENGTH = 6, // BUFFER_LENGTH
DECIMAL_DIGITS = 7, // DECIMAL_DIGITS
PSEUDO_COLUMN = 8, // PSEUDO_COLUMN
*/
}
internal const short SQL_DIAG_SQLSTATE = 4;
internal const short SQL_RESULT_COL = 3;
// Helpers
static internal OdbcErrorCollection GetDiagErrors(string source, OdbcHandle hrHandle, RetCode retcode) {
OdbcErrorCollection errors = new OdbcErrorCollection();
GetDiagErrors(errors, source, hrHandle, retcode);
return errors;
}
static internal void GetDiagErrors(OdbcErrorCollection errors, string source, OdbcHandle hrHandle, RetCode retcode) {
Debug.Assert(retcode!=ODBC32.RetCode.INVALID_HANDLE, "retcode must never be ODBC32.RetCode.INVALID_HANDLE");
if (RetCode.SUCCESS != retcode) {
Int32 NativeError;
Int16 iRec = 0;
Int16 cchActual = 0;
StringBuilder message = new StringBuilder(1024);
string sqlState;
bool moreerrors = true;
while(moreerrors) {
++iRec;
retcode = hrHandle.GetDiagnosticRecord(iRec, out sqlState, message, out NativeError, out cchActual);
if ((RetCode.SUCCESS_WITH_INFO == retcode) && (message.Capacity-1 < cchActual)) {
message.Capacity = cchActual+1;
retcode = hrHandle.GetDiagnosticRecord(iRec, out sqlState, message, out NativeError, out cchActual);
}
//Note: SUCCESS_WITH_INFO from SQLGetDiagRec would be because
//the buffer is not large enough for the error string.
moreerrors = (retcode == RetCode.SUCCESS || retcode == RetCode.SUCCESS_WITH_INFO);
if(moreerrors) {
//Sets up the InnerException as well...
errors.Add(new OdbcError(
source,
message.ToString(),
sqlState,
NativeError
)
);
}
}
}
}
}
sealed internal class TypeMap { // MDAC 68988
// 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)
// --------------- ------------------ -------------- ---------- ------------------------- ------------------- ------------------------- -----------------------
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);
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);
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);
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);
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);
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);
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);
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);
// 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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
internal readonly OdbcType _odbcType;
internal readonly DbType _dbType;
internal readonly Type _type;
internal readonly ODBC32.SQL_TYPE _sql_type;
internal readonly ODBC32.SQL_C _sql_c;
internal readonly ODBC32.SQL_C _param_sql_c;
internal readonly int _bufferSize; // fixed length byte size to reserve for buffer
internal readonly int _columnSize; // column size passed to SQLBindParameter
internal readonly bool _signType; // this type may be has signature information
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) {
_odbcType = odbcType;
_dbType = dbType;
_type = type;
_sql_type = sql_type;
_sql_c = sql_c;
_param_sql_c = param_sql_c; // alternative sql_c type for parameters
_bufferSize = bsize;
_columnSize = csize;
_signType = signType;
}
static internal TypeMap FromOdbcType(OdbcType odbcType) {
switch(odbcType) {
case OdbcType.BigInt: return _BigInt;
case OdbcType.Binary: return _Binary;
case OdbcType.Bit: return _Bit;
case OdbcType.Char: return _Char;
case OdbcType.DateTime: return _DateTime;
case OdbcType.Date: return _Date;
case OdbcType.Time: return _Time;
case OdbcType.Double: return _Double;
case OdbcType.Decimal: return _Decimal;
case OdbcType.Image: return _Image;
case OdbcType.Int: return _Int;
case OdbcType.NChar: return _NChar;
case OdbcType.NText: return _NText;
case OdbcType.Numeric: return _Numeric;
case OdbcType.NVarChar: return _NVarChar;
case OdbcType.Real: return _Real;
case OdbcType.UniqueIdentifier: return _UniqueId;
case OdbcType.SmallDateTime: return _SmallDT;
case OdbcType.SmallInt: return _SmallInt;
case OdbcType.Text: return _Text;
case OdbcType.Timestamp: return _Timestamp;
case OdbcType.TinyInt: return _TinyInt;
case OdbcType.VarBinary: return _VarBinary;
case OdbcType.VarChar: return _VarChar;
default: throw ODBC.UnknownOdbcType(odbcType);
}
}
static internal TypeMap FromDbType(DbType dbType) {
switch(dbType) {
case DbType.AnsiString: return _VarChar;
case DbType.AnsiStringFixedLength: return _Char;
case DbType.Binary: return _VarBinary;
case DbType.Byte: return _TinyInt;
case DbType.Boolean: return _Bit;
case DbType.Currency: return _Decimal;
// case DbType.Currency: return _Currency;
case DbType.Date: return _Date;
case DbType.Time: return _Time;
case DbType.DateTime: return _DateTime;
case DbType.Decimal: return _Decimal;
case DbType.Double: return _Double;
case DbType.Guid: return _UniqueId;
case DbType.Int16: return _SmallInt;
case DbType.Int32: return _Int;
case DbType.Int64: return _BigInt;
case DbType.Single: return _Real;
case DbType.String: return _NVarChar;
case DbType.StringFixedLength: return _NChar;
case DbType.Object:
case DbType.SByte:
case DbType.UInt16:
case DbType.UInt32:
case DbType.UInt64:
case DbType.VarNumeric:
default: throw ADP.DbTypeNotSupported(dbType, typeof(OdbcType));
}
}
static internal TypeMap FromSystemType(Type dataType) {
switch(Type.GetTypeCode(dataType)) {
case TypeCode.Empty: throw ADP.InvalidDataType(TypeCode.Empty);
case TypeCode.Object:
if (dataType == typeof(System.Byte[])) {
return _VarBinary;
}
else if (dataType == typeof(System.Guid)) {
return _UniqueId;
}
else if (dataType == typeof(System.TimeSpan)) {
return _Time;
}
else if (dataType == typeof(System.Char[])) {
return _NVarChar;
}
throw ADP.UnknownDataType(dataType);
case TypeCode.DBNull: throw ADP.InvalidDataType(TypeCode.DBNull);
case TypeCode.Boolean: return _Bit;
// devnote: Char is actually not supported. Our _Char type is actually a fixed length string, not a single character
// case TypeCode.Char: return _Char;
case TypeCode.SByte: return _SmallInt;
case TypeCode.Byte: return _TinyInt;
case TypeCode.Int16: return _SmallInt;
case TypeCode.UInt16: return _Int;
case TypeCode.Int32: return _Int;
case TypeCode.UInt32: return _BigInt;
case TypeCode.Int64: return _BigInt;
case TypeCode.UInt64: return _Numeric;
case TypeCode.Single: return _Real;
case TypeCode.Double: return _Double;
case TypeCode.Decimal: return _Numeric;
case TypeCode.DateTime: return _DateTime;
case TypeCode.Char:
case TypeCode.String: return _NVarChar;
default: throw ADP.UnknownDataTypeCode(dataType, Type.GetTypeCode(dataType));
}
}
static internal TypeMap FromSqlType(ODBC32.SQL_TYPE sqltype) {
switch(sqltype) {
case ODBC32.SQL_TYPE.CHAR: return _Char;
case ODBC32.SQL_TYPE.VARCHAR: return _VarChar;
case ODBC32.SQL_TYPE.LONGVARCHAR: return _Text;
case ODBC32.SQL_TYPE.WCHAR: return _NChar;
case ODBC32.SQL_TYPE.WVARCHAR: return _NVarChar;
case ODBC32.SQL_TYPE.WLONGVARCHAR: return _NText;
case ODBC32.SQL_TYPE.DECIMAL: return _Decimal;
case ODBC32.SQL_TYPE.NUMERIC: return _Numeric;
case ODBC32.SQL_TYPE.SMALLINT: return _SmallInt;
case ODBC32.SQL_TYPE.INTEGER: return _Int;
case ODBC32.SQL_TYPE.REAL: return _Real;
case ODBC32.SQL_TYPE.FLOAT: return _Double;
case ODBC32.SQL_TYPE.DOUBLE: return _Double;
case ODBC32.SQL_TYPE.BIT: return _Bit;
case ODBC32.SQL_TYPE.TINYINT: return _TinyInt;
case ODBC32.SQL_TYPE.BIGINT: return _BigInt;
case ODBC32.SQL_TYPE.BINARY: return _Binary;
case ODBC32.SQL_TYPE.VARBINARY: return _VarBinary;
case ODBC32.SQL_TYPE.LONGVARBINARY: return _Image;
case ODBC32.SQL_TYPE.TYPE_DATE: return _Date;
case ODBC32.SQL_TYPE.TYPE_TIME: return _Time;
case ODBC32.SQL_TYPE.TIMESTAMP:
case ODBC32.SQL_TYPE.TYPE_TIMESTAMP: return _DateTime;
case ODBC32.SQL_TYPE.GUID: return _UniqueId;
case ODBC32.SQL_TYPE.SS_VARIANT: return _Variant;
case ODBC32.SQL_TYPE.SS_UDT: return _UDT;
case ODBC32.SQL_TYPE.SS_XML: return _XML;
case ODBC32.SQL_TYPE.SS_UTCDATETIME:
case ODBC32.SQL_TYPE.SS_TIME_EX:
throw ODBC.UnknownSQLType(sqltype);
default:
throw ODBC.UnknownSQLType(sqltype);
}
}
// Upgrade integer datatypes to missinterpretaion of the highest bit
// (e.g. 0xff could be 255 if unsigned but is -1 if signed)
//
static internal TypeMap UpgradeSignedType(TypeMap typeMap, bool unsigned) {
// upgrade unsigned types to be able to hold data that has the highest bit set
//
if (unsigned == true) {
switch (typeMap._dbType) {
case DbType.Int64:
return _Decimal; // upgrade to decimal
case DbType.Int32:
return _BigInt; // upgrade to 64 bit
case DbType.Int16:
return _Int; // upgrade to 32 bit
default:
return typeMap;
} // end switch
}
else {
switch (typeMap._dbType) {
case DbType.Byte:
return _SmallInt; // upgrade to 16 bit
default:
return typeMap;
} // end switch
}
} // end UpgradeSignedType
}
}
|