1003 lines
49 KiB
C#
1003 lines
49 KiB
C#
|
//------------------------------------------------------------------------------
|
||
|
// <copyright file="Odbc32.cs" company="Microsoft">
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
// </copyright>
|
||
|
// <owner current="true" primary="true">[....]</owner>
|
||
|
// <owner current="true" primary="false">[....]</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
|
||
|
}
|
||
|
}
|