Imported Upstream version 4.6.0.125

Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-08-03 10:59:49 +00:00
parent a569aebcfd
commit e79aa3c0ed
17047 changed files with 3137615 additions and 392334 deletions

View File

@@ -0,0 +1,150 @@
//------------------------------------------------------------------------------
// <copyright file="DbDataRecord.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.ComponentModel; //Component
using System.Data;
using System.Runtime.InteropServices; //Marshal
using System.Reflection; //Missing
namespace System.Data.Odbc {
sealed internal class DbSchemaInfo {
internal DbSchemaInfo() {
}
internal string _name;
internal string _typename;
internal Type _type;
internal ODBC32.SQL_TYPE? _dbtype;
internal object _scale;
internal object _precision;
// extension to allow BindCol
//
internal int _columnlength; //
internal int _valueOffset; // offset to the data in the row buffer
internal int _lengthOffset; // offset to the length in the row buffer
internal ODBC32.SQL_C _sqlctype; // need this to bind the value
internal ODBC32.SQL_TYPE _sql_type; // need that to properly marshal the value
}
/////////////////////////////////////////////////////////////////////////////
// Cache
//
// This is a on-demand cache, only caching what the user requests.
// The reational is that for ForwardOnly access (the default and LCD of drivers)
// we cannot obtain the data more than once, and even GetData(0) (to determine is-null)
// still obtains data for fixed lenght types.
// So simple code like:
// if(!rReader.IsDBNull(i))
// rReader.GetInt32(i)
//
// Would fail, unless we cache on the IsDBNull call, and return the cached
// item for GetInt32. This actually improves perf anyway, (even if the driver could
// support it), since we are not making a seperate interop call...
// We do not cache all columns, so reading out of order is still not
//
/////////////////////////////////////////////////////////////////////////////
sealed internal class DbCache {
//Data
private bool[] _isBadValue;
private DbSchemaInfo[] _schema;
private object[] _values;
private OdbcDataReader _record;
internal int _count;
internal bool _randomaccess = true;
//Constructor
internal DbCache(OdbcDataReader record, int count) {
_count = count;
_record = record;
_randomaccess = (!record.IsBehavior(CommandBehavior.SequentialAccess));
_values = new object[count];
_isBadValue = new bool[count];
}
//Accessor
internal object this[int i] {
get {
if(_isBadValue[i]) {
OverflowException innerException = (OverflowException)Values[i];
throw new OverflowException(innerException.Message, innerException);
}
return Values[i];
}
set {
Values[i] = value;
_isBadValue[i] = false;
}
}
internal int Count {
get {
return _count;
}
}
internal void InvalidateValue(int i) {
_isBadValue[i] = true;
}
internal object[] Values {
get {
return _values;
}
}
internal object AccessIndex(int i) {
//Note: We could put this directly in this[i], instead of having an explicit overload.
//However that means that EVERY access into the cache takes the hit of checking, so
//something as simple as the following code would take two hits. It's nice not to
//have to take the hit when you know what your doing.
//
// if(cache[i] == null)
// ....
// return cache[i];
object[] values = this.Values;
if(_randomaccess) {
//Random
//Means that the user can ask for the values int any order (ie: out of order).
// In order to acheive this on a forward only stream, we need to actually
// retreive all the value in between so they can go back to values they've skipped
for(int c = 0; c < i; c++) {
if(values[c] == null) {
values[c] = _record.GetValue(c);
}
}
}
return values[i];
}
internal DbSchemaInfo GetSchema(int i) {
if(_schema == null) {
_schema = new DbSchemaInfo[Count];
}
if(_schema[i] == null) {
_schema[i] = new DbSchemaInfo();
}
return _schema[i];
}
internal void FlushValues() {
//Set all objects to null (to explcitly release them)
//Note: SchemaInfo remains the same for all rows - no need to reget those...
int count = _values.Length;
for(int i = 0; i < count; ++i) {
_values[i] = null;
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,327 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcCommandBuilder.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Data.ProviderBase;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Globalization;
using System.Text;
namespace System.Data.Odbc {
public sealed class OdbcCommandBuilder : DbCommandBuilder {
public OdbcCommandBuilder() : base() {
GC.SuppressFinalize(this);
}
public OdbcCommandBuilder(OdbcDataAdapter adapter) : this() {
DataAdapter = adapter;
}
[
DefaultValue(null),
ResCategoryAttribute(Res.DataCategory_Update),
ResDescriptionAttribute(Res.OdbcCommandBuilder_DataAdapter), // MDAC 60524
]
new public OdbcDataAdapter DataAdapter {
get {
return (base.DataAdapter as OdbcDataAdapter);
}
set {
base.DataAdapter = value;
}
}
private void OdbcRowUpdatingHandler(object sender, OdbcRowUpdatingEventArgs ruevent) {
RowUpdatingHandler(ruevent);
}
new public OdbcCommand GetInsertCommand() {
return (OdbcCommand) base.GetInsertCommand();
}
new public OdbcCommand GetInsertCommand(bool useColumnsForParameterNames) {
return (OdbcCommand) base.GetInsertCommand(useColumnsForParameterNames);
}
new public OdbcCommand GetUpdateCommand() {
return (OdbcCommand) base.GetUpdateCommand();
}
new public OdbcCommand GetUpdateCommand(bool useColumnsForParameterNames) {
return (OdbcCommand) base.GetUpdateCommand(useColumnsForParameterNames);
}
new public OdbcCommand GetDeleteCommand() {
return (OdbcCommand) base.GetDeleteCommand();
}
new public OdbcCommand GetDeleteCommand(bool useColumnsForParameterNames) {
return (OdbcCommand) base.GetDeleteCommand(useColumnsForParameterNames);
}
override protected string GetParameterName(int parameterOrdinal) {
return "p" + parameterOrdinal.ToString(System.Globalization.CultureInfo.InvariantCulture);
}
override protected string GetParameterName(string parameterName) {
return parameterName;
}
override protected string GetParameterPlaceholder(int parameterOrdinal) {
return "?";
}
override protected void ApplyParameterInfo(DbParameter parameter, DataRow datarow, StatementType statementType, bool whereClause) {
OdbcParameter p = (OdbcParameter) parameter;
object valueType = datarow[SchemaTableColumn.ProviderType];
p.OdbcType = (OdbcType) valueType;
object bvalue = datarow[SchemaTableColumn.NumericPrecision];
if (DBNull.Value != bvalue) {
byte bval = (byte)(short)bvalue;
p.PrecisionInternal = ((0xff != bval) ? bval : (byte)0);
}
bvalue = datarow[SchemaTableColumn.NumericScale];
if (DBNull.Value != bvalue) {
byte bval = (byte)(short)bvalue;
p.ScaleInternal = ((0xff != bval) ? bval : (byte)0);
}
}
static public void DeriveParameters(OdbcCommand command) {
// MDAC 65927
OdbcConnection.ExecutePermission.Demand();
if (null == command) {
throw ADP.ArgumentNull("command");
}
switch (command.CommandType) {
case System.Data.CommandType.Text:
throw ADP.DeriveParametersNotSupported(command);
case System.Data.CommandType.StoredProcedure:
break;
case System.Data.CommandType.TableDirect:
// CommandType.TableDirect - do nothing, parameters are not supported
throw ADP.DeriveParametersNotSupported(command);
default:
throw ADP.InvalidCommandType(command.CommandType);
}
if (ADP.IsEmpty(command.CommandText)) {
throw ADP.CommandTextRequired(ADP.DeriveParameters);
}
OdbcConnection connection = command.Connection;
if (null == connection) {
throw ADP.ConnectionRequired(ADP.DeriveParameters);
}
ConnectionState state = connection.State;
if (ConnectionState.Open != state) {
throw ADP.OpenConnectionRequired(ADP.DeriveParameters, state);
}
OdbcParameter[] list = DeriveParametersFromStoredProcedure(connection, command);
OdbcParameterCollection parameters = command.Parameters;
parameters.Clear();
int count = list.Length;
if (0 < count) {
for(int i = 0; i < list.Length; ++i) {
parameters.Add(list[i]);
}
}
}
// DeriveParametersFromStoredProcedure (
// OdbcConnection connection,
// OdbcCommand command);
//
// Uses SQLProcedureColumns to create an array of OdbcParameters
//
static private OdbcParameter[] DeriveParametersFromStoredProcedure(OdbcConnection connection, OdbcCommand command) {
List<OdbcParameter> rParams = new List<OdbcParameter>();
// following call ensures that the command has a statement handle allocated
CMDWrapper cmdWrapper = command.GetStatementHandle();
OdbcStatementHandle hstmt = cmdWrapper.StatementHandle;
int cColsAffected;
// maps an enforced 4-part qualified string as follows
// parts[0] = null - ignored but removal would be a run-time breaking change from V1.0
// parts[1] = CatalogName (optional, may be null)
// parts[2] = SchemaName (optional, may be null)
// parts[3] = ProcedureName
//
string quote = connection.QuoteChar(ADP.DeriveParameters);
string[] parts = MultipartIdentifier.ParseMultipartIdentifier(command.CommandText, quote, quote, '.', 4, true, Res.ODBC_ODBCCommandText, false);
if (null == parts[3]) { // match everett behavior, if the commandtext is nothing but whitespace set the command text to the whitespace
parts[3] = command.CommandText;
}
// note: native odbc appears to ignore all but the procedure name
ODBC32.RetCode retcode = hstmt.ProcedureColumns(parts[1], parts[2], parts[3], null);
// Note: the driver does not return an error if the given stored procedure does not exist
// therefore we cannot handle that case and just return not parameters.
if (ODBC32.RetCode.SUCCESS != retcode) {
connection.HandleError(hstmt, retcode);
}
using (OdbcDataReader reader = new OdbcDataReader(command, cmdWrapper, CommandBehavior.Default)) {
reader.FirstResult();
cColsAffected = reader.FieldCount;
// go through the returned rows and filter out relevant parameter data
//
while (reader.Read()) {
// devnote: column types are specified in the ODBC Programmer's Reference
// COLUMN_TYPE Smallint 16bit
// COLUMN_SIZE Integer 32bit
// DECIMAL_DIGITS Smallint 16bit
// NUM_PREC_RADIX Smallint 16bit
OdbcParameter parameter = new OdbcParameter();
parameter.ParameterName = reader.GetString(ODBC32.COLUMN_NAME-1);
switch ((ODBC32.SQL_PARAM)reader.GetInt16(ODBC32.COLUMN_TYPE-1)){
case ODBC32.SQL_PARAM.INPUT:
parameter.Direction = ParameterDirection.Input;
break;
case ODBC32.SQL_PARAM.OUTPUT:
parameter.Direction = ParameterDirection.Output;
break;
case ODBC32.SQL_PARAM.INPUT_OUTPUT:
parameter.Direction = ParameterDirection.InputOutput;
break;
case ODBC32.SQL_PARAM.RETURN_VALUE:
parameter.Direction = ParameterDirection.ReturnValue;
break;
default:
Debug.Assert(false, "Unexpected Parametertype while DeriveParamters");
break;
}
parameter.OdbcType = TypeMap.FromSqlType((ODBC32.SQL_TYPE)reader.GetInt16(ODBC32.DATA_TYPE-1))._odbcType;
parameter.Size = (int)reader.GetInt32(ODBC32.COLUMN_SIZE-1);
switch(parameter.OdbcType){
case OdbcType.Decimal:
case OdbcType.Numeric:
parameter.ScaleInternal = (Byte)reader.GetInt16(ODBC32.DECIMAL_DIGITS-1);
parameter.PrecisionInternal = (Byte)reader.GetInt16(ODBC32.NUM_PREC_RADIX-1);
break;
}
rParams.Add (parameter);
}
}
retcode = hstmt.CloseCursor();
return rParams.ToArray();;
}
public override string QuoteIdentifier(string unquotedIdentifier){
return QuoteIdentifier(unquotedIdentifier, null /* use DataAdapter.SelectCommand.Connection if available */);
}
public string QuoteIdentifier( string unquotedIdentifier, OdbcConnection connection){
ADP.CheckArgumentNull(unquotedIdentifier, "unquotedIdentifier");
// if the user has specificed a prefix use the user specified prefix and suffix
// otherwise get them from the provider
string quotePrefix = QuotePrefix;
string quoteSuffix = QuoteSuffix;
if (ADP.IsEmpty(quotePrefix) == true) {
if (connection == null) {
// VSTFDEVDIV 479567: use the adapter's connection if QuoteIdentifier was called from
// DbCommandBuilder instance (which does not have an overload that gets connection object)
connection = base.GetConnection() as OdbcConnection;
if (connection == null) {
throw ADP.QuotePrefixNotSet(ADP.QuoteIdentifier);
}
}
quotePrefix = connection.QuoteChar(ADP.QuoteIdentifier);
quoteSuffix = quotePrefix;
}
// by the ODBC spec "If the data source does not support quoted identifiers, a blank is returned."
// So if a blank is returned the string is returned unchanged. Otherwise the returned string is used
// to quote the string
if ((ADP.IsEmpty(quotePrefix) == false) && (quotePrefix != " ")) {
return ADP.BuildQuotedString(quotePrefix,quoteSuffix,unquotedIdentifier);
}
else {
return unquotedIdentifier;
}
}
override protected void SetRowUpdatingHandler(DbDataAdapter adapter) {
Debug.Assert(adapter is OdbcDataAdapter, "!OdbcDataAdapter");
if (adapter == base.DataAdapter) { // removal case
((OdbcDataAdapter)adapter).RowUpdating -= OdbcRowUpdatingHandler;
}
else { // adding case
((OdbcDataAdapter)adapter).RowUpdating += OdbcRowUpdatingHandler;
}
}
public override string UnquoteIdentifier( string quotedIdentifier){
return UnquoteIdentifier(quotedIdentifier, null /* use DataAdapter.SelectCommand.Connection if available */);
}
public string UnquoteIdentifier(string quotedIdentifier, OdbcConnection connection){
ADP.CheckArgumentNull(quotedIdentifier, "quotedIdentifier");
// if the user has specificed a prefix use the user specified prefix and suffix
// otherwise get them from the provider
string quotePrefix = QuotePrefix;
string quoteSuffix = QuoteSuffix;
if (ADP.IsEmpty(quotePrefix) == true) {
if (connection == null) {
// VSTFDEVDIV 479567: use the adapter's connection if UnquoteIdentifier was called from
// DbCommandBuilder instance (which does not have an overload that gets connection object)
connection = base.GetConnection() as OdbcConnection;
if (connection == null) {
throw ADP.QuotePrefixNotSet(ADP.UnquoteIdentifier);
}
}
quotePrefix = connection.QuoteChar(ADP.UnquoteIdentifier);
quoteSuffix = quotePrefix;
}
String unquotedIdentifier;
// by the ODBC spec "If the data source does not support quoted identifiers, a blank is returned."
// So if a blank is returned the string is returned unchanged. Otherwise the returned string is used
// to unquote the string
if ((ADP.IsEmpty(quotePrefix) == false) || (quotePrefix != " ")) {
// ignoring the return value because it is acceptable for the quotedString to not be quoted in this
// context.
ADP.RemoveStringQuotes(quotePrefix, quoteSuffix, quotedIdentifier, out unquotedIdentifier);
}
else {
unquotedIdentifier = quotedIdentifier;
}
return unquotedIdentifier;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,186 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcConnectionFactory.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.Common;
using System.Data.ProviderBase;
using System.Diagnostics;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Runtime.Versioning;
sealed internal class OdbcConnectionFactory : DbConnectionFactory {
private OdbcConnectionFactory() : base() {}
// At this time, the ODBC Provider doesn't have any connection pool counters
// because we'd only confuse people with "non-pooled" connections that are
// actually being pooled by the native pooler.
private const string _MetaData = ":MetaDataXml";
private const string _defaultMetaDataXml = "defaultMetaDataXml";
public static readonly OdbcConnectionFactory SingletonInstance = new OdbcConnectionFactory();
override public DbProviderFactory ProviderFactory {
get {
return OdbcFactory.Instance;
}
}
override protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject) {
DbConnectionInternal result = new OdbcConnectionOpen(owningObject as OdbcConnection, options as OdbcConnectionString);
return result;
}
override protected DbConnectionOptions CreateConnectionOptions(string connectionString, DbConnectionOptions previous) {
Debug.Assert(!ADP.IsEmpty(connectionString), "empty connectionString");
OdbcConnectionString result = new OdbcConnectionString(connectionString, (null != previous));
return result;
}
override protected DbConnectionPoolGroupOptions CreateConnectionPoolGroupOptions( DbConnectionOptions connectionOptions ) {
// At this time, the ODBC provider only supports native pooling so we
// simply return NULL to indicate that.
return null;
}
override internal DbConnectionPoolGroupProviderInfo CreateConnectionPoolGroupProviderInfo (DbConnectionOptions connectionOptions) {
return new OdbcConnectionPoolGroupProviderInfo();
}
// SxS (VSDD 545786): metadata files are opened from <.NetRuntimeFolder>\CONFIG\<metadatafilename.xml>
// this operation is safe in SxS because the file is opened in read-only mode and each NDP runtime accesses its own copy of the metadata
// under the runtime folder.
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
override protected DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection, out bool cacheMetaDataFactory){
Debug.Assert (internalConnection != null,"internalConnection may not be null.");
cacheMetaDataFactory = false;
OdbcConnection odbcOuterConnection = ((OdbcConnectionOpen)internalConnection).OuterConnection;
Debug.Assert(odbcOuterConnection != null,"outer connection may not be null.");
NameValueCollection settings = (NameValueCollection)PrivilegedConfigurationManager.GetSection("system.data.odbc");
Stream XMLStream =null;
// get the DBMS Name
object driverName = null;
string stringValue = odbcOuterConnection.GetInfoStringUnhandled(ODBC32.SQL_INFO.DRIVER_NAME);
if (stringValue != null) {
driverName = stringValue;
}
if (settings != null){
string [] values = null;
string metaDataXML = null;
// first try to get the provider specific xml
// if driver name is not supported we can't build the settings key needed to
// get the provider specific XML path
if (driverName != null){
metaDataXML = ((string)driverName) + _MetaData;
values = settings.GetValues(metaDataXML);
}
// if we did not find provider specific xml see if there is new default xml
if (values == null) {
metaDataXML = _defaultMetaDataXml;
values = settings.GetValues(metaDataXML);
}
// If there is an XML file get it
if (values != null) {
XMLStream = ADP.GetXmlStreamFromValues(values,metaDataXML);
}
}
// use the embedded xml if the user did not over ride it
if (XMLStream == null){
XMLStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("System.Data.Odbc.OdbcMetaData.xml");
cacheMetaDataFactory = true;
}
Debug.Assert (XMLStream != null,"XMLstream may not be null.");
String versionString = odbcOuterConnection.GetInfoStringUnhandled(ODBC32.SQL_INFO.DBMS_VER);
return new OdbcMetaDataFactory (XMLStream,
versionString,
versionString,
odbcOuterConnection);
}
override internal DbConnectionPoolGroup GetConnectionPoolGroup(DbConnection connection) {
OdbcConnection c = (connection as OdbcConnection);
if (null != c) {
return c.PoolGroup;
}
return null;
}
override internal DbConnectionInternal GetInnerConnection(DbConnection connection) {
OdbcConnection c = (connection as OdbcConnection);
if (null != c) {
return c.InnerConnection;
}
return null;
}
override protected int GetObjectId(DbConnection connection) {
OdbcConnection c = (connection as OdbcConnection);
if (null != c) {
return c.ObjectID;
}
return 0;
}
override internal void PermissionDemand(DbConnection outerConnection) {
OdbcConnection c = (outerConnection as OdbcConnection);
if (null != c) {
c.PermissionDemand();
}
}
override internal void SetConnectionPoolGroup(DbConnection outerConnection, DbConnectionPoolGroup poolGroup) {
OdbcConnection c = (outerConnection as OdbcConnection);
if (null != c) {
c.PoolGroup = poolGroup;
}
}
override internal void SetInnerConnectionEvent(DbConnection owningObject, DbConnectionInternal to) {
OdbcConnection c = (owningObject as OdbcConnection);
if (null != c) {
c.SetInnerConnectionEvent(to);
}
}
override internal bool SetInnerConnectionFrom(DbConnection owningObject, DbConnectionInternal to, DbConnectionInternal from) {
OdbcConnection c = (owningObject as OdbcConnection);
if (null != c) {
return c.SetInnerConnectionFrom(to, from);
}
return false;
}
override internal void SetInnerConnectionTo(DbConnection owningObject, DbConnectionInternal to) {
OdbcConnection c = (owningObject as OdbcConnection);
if (null != c) {
c.SetInnerConnectionTo(to);
}
}
}
}

View File

@@ -0,0 +1,265 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcConnectionHandle.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Runtime.ConstrainedExecution;
namespace System.Data.Odbc {
sealed internal class OdbcConnectionHandle : OdbcHandle {
private HandleState _handleState;
private enum HandleState {
Allocated = 0,
Connected = 1,
Transacted = 2,
TransactionInProgress = 3,
}
internal OdbcConnectionHandle(OdbcConnection connection, OdbcConnectionString constr, OdbcEnvironmentHandle environmentHandle) : base(ODBC32.SQL_HANDLE.DBC, environmentHandle) {
if(null == connection) {
throw ADP.ArgumentNull("connection");
}
if(null == constr) {
throw ADP.ArgumentNull("constr");
}
ODBC32.RetCode retcode;
//Set connection timeout (only before open).
//Note: We use login timeout since its odbc 1.0 option, instead of using
//connectiontimeout (which affects other things besides just login) and its
//a odbc 3.0 feature. The ConnectionTimeout on the managed providers represents
//the login timeout, nothing more.
int connectionTimeout = connection.ConnectionTimeout;
retcode = SetConnectionAttribute2(ODBC32.SQL_ATTR.LOGIN_TIMEOUT, (IntPtr)connectionTimeout, (Int32)ODBC32.SQL_IS.UINTEGER);
string connectionString = constr.UsersConnectionString(false);
// Connect to the driver. (Using the connection string supplied)
//Note: The driver doesn't filter out the password in the returned connection string
//so their is no need for us to obtain the returned connection string
// Prepare to handle a ThreadAbort Exception between SQLDriverConnectW and update of the state variables
retcode = Connect(connectionString);
connection.HandleError(this, retcode);
}
private ODBC32.RetCode AutoCommitOff() {
ODBC32.RetCode retcode;
Debug.Assert(HandleState.Connected <= _handleState, "AutoCommitOff while in wrong state?");
// Avoid runtime injected errors in the following block.
// must call SQLSetConnectAttrW and set _handleState
RuntimeHelpers.PrepareConstrainedRegions();
try {} finally {
retcode = UnsafeNativeMethods.SQLSetConnectAttrW(this, ODBC32.SQL_ATTR.AUTOCOMMIT, ODBC32.SQL_AUTOCOMMIT_OFF, (Int32)ODBC32.SQL_IS.UINTEGER);
switch(retcode) {
case ODBC32.RetCode.SUCCESS:
case ODBC32.RetCode.SUCCESS_WITH_INFO:
_handleState = HandleState.Transacted;
break;
}
}
ODBC.TraceODBC(3, "SQLSetConnectAttrW", retcode);
return retcode;
}
internal ODBC32.RetCode BeginTransaction(ref IsolationLevel isolevel) {
ODBC32.RetCode retcode = ODBC32.RetCode.SUCCESS;
ODBC32.SQL_ATTR isolationAttribute;
if(IsolationLevel.Unspecified != isolevel) {
ODBC32.SQL_TRANSACTION sql_iso;
switch(isolevel) {
case IsolationLevel.ReadUncommitted:
sql_iso = ODBC32.SQL_TRANSACTION.READ_UNCOMMITTED;
isolationAttribute = ODBC32.SQL_ATTR.TXN_ISOLATION;
break;
case IsolationLevel.ReadCommitted:
sql_iso = ODBC32.SQL_TRANSACTION.READ_COMMITTED;
isolationAttribute = ODBC32.SQL_ATTR.TXN_ISOLATION;
break;
case IsolationLevel.RepeatableRead:
sql_iso = ODBC32.SQL_TRANSACTION.REPEATABLE_READ;
isolationAttribute = ODBC32.SQL_ATTR.TXN_ISOLATION;
break;
case IsolationLevel.Serializable:
sql_iso = ODBC32.SQL_TRANSACTION.SERIALIZABLE;
isolationAttribute = ODBC32.SQL_ATTR.TXN_ISOLATION;
break;
case IsolationLevel.Snapshot:
sql_iso = ODBC32.SQL_TRANSACTION.SNAPSHOT;
// VSDD 414121: Snapshot isolation level must be set through SQL_COPT_SS_TXN_ISOLATION (http://msdn.microsoft.com/en-us/library/ms131709.aspx)
isolationAttribute = ODBC32.SQL_ATTR.SQL_COPT_SS_TXN_ISOLATION;
break;
case IsolationLevel.Chaos:
throw ODBC.NotSupportedIsolationLevel(isolevel);
default:
throw ADP.InvalidIsolationLevel(isolevel);
}
//Set the isolation level (unless its unspecified)
retcode = SetConnectionAttribute2(isolationAttribute, (IntPtr)sql_iso, (Int32)ODBC32.SQL_IS.INTEGER);
//Note: The Driver can return success_with_info to indicate it "rolled" the
//isolevel to the next higher value. If this is the case, we need to requery
//the value if th euser asks for it...
//We also still propagate the info, since it could be other info as well...
if(ODBC32.RetCode.SUCCESS_WITH_INFO == retcode) {
isolevel = IsolationLevel.Unspecified;
}
}
switch(retcode) {
case ODBC32.RetCode.SUCCESS:
case ODBC32.RetCode.SUCCESS_WITH_INFO:
//Turn off auto-commit (which basically starts the transaction)
retcode = AutoCommitOff();
_handleState = HandleState.TransactionInProgress;
break;
}
return retcode;
}
internal ODBC32.RetCode CompleteTransaction(short transactionOperation) {
bool mustRelease = false;
RuntimeHelpers.PrepareConstrainedRegions();
try {
DangerousAddRef(ref mustRelease);
ODBC32.RetCode retcode = CompleteTransaction(transactionOperation, base.handle);
return retcode;
}
finally {
if (mustRelease) {
DangerousRelease();
}
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
private ODBC32.RetCode CompleteTransaction(short transactionOperation, IntPtr handle) {
// must only call this code from ReleaseHandle or DangerousAddRef region
ODBC32.RetCode retcode = ODBC32.RetCode.SUCCESS;
// using ConstrainedRegions to make the native ODBC call and change the _handleState
RuntimeHelpers.PrepareConstrainedRegions();
try { } finally {
if (HandleState.TransactionInProgress == _handleState) {
retcode = UnsafeNativeMethods.SQLEndTran(HandleType, handle, transactionOperation);
if((ODBC32.RetCode.SUCCESS == retcode) || (ODBC32.RetCode.SUCCESS_WITH_INFO == retcode)) {
_handleState = HandleState.Transacted;
}
Bid.TraceSqlReturn("<odbc.SQLEndTran|API|ODBC|RET> %08X{SQLRETURN}\n", retcode);
}
if (HandleState.Transacted == _handleState) { // AutoCommitOn
retcode = UnsafeNativeMethods.SQLSetConnectAttrW(handle, ODBC32.SQL_ATTR.AUTOCOMMIT, ODBC32.SQL_AUTOCOMMIT_ON, (Int32)ODBC32.SQL_IS.UINTEGER);
_handleState = HandleState.Connected;
Bid.TraceSqlReturn("<odbc.SQLSetConnectAttr|API|ODBC|RET> %08X{SQLRETURN}\n", retcode);
}
}
//Overactive assert which fires if handle was allocated - but failed to connect to the server
//it can more legitmately fire if transaction failed to rollback - but there isn't much we can do in that situation
//Debug.Assert((HandleState.Connected == _handleState) || (HandleState.TransactionInProgress == _handleState), "not expected HandleState.Connected");
return retcode;
}
private ODBC32.RetCode Connect(string connectionString) {
Debug.Assert(HandleState.Allocated == _handleState, "SQLDriverConnect while in wrong state?");
ODBC32.RetCode retcode;
// Avoid runtime injected errors in the following block.
RuntimeHelpers.PrepareConstrainedRegions();
try {} finally {
short cbActualSize;
retcode = UnsafeNativeMethods.SQLDriverConnectW(this, ADP.PtrZero, connectionString, ODBC32.SQL_NTS, ADP.PtrZero, 0, out cbActualSize, (short)ODBC32.SQL_DRIVER.NOPROMPT);
switch(retcode) {
case ODBC32.RetCode.SUCCESS:
case ODBC32.RetCode.SUCCESS_WITH_INFO:
_handleState = HandleState.Connected;
break;
}
}
ODBC.TraceODBC(3, "SQLDriverConnectW", retcode);
return retcode;
}
override protected bool ReleaseHandle() {
// NOTE: The SafeHandle class guarantees this will be called exactly once and is non-interrutible.
ODBC32.RetCode retcode;
// must call complete the transaction rollback, change handle state, and disconnect the connection
retcode = CompleteTransaction(ODBC32.SQL_ROLLBACK, handle);
if ((HandleState.Connected == _handleState) || (HandleState.TransactionInProgress == _handleState)) {
retcode = UnsafeNativeMethods.SQLDisconnect(handle);
_handleState = HandleState.Allocated;
Bid.TraceSqlReturn("<odbc.SQLDisconnect|API|ODBC|RET> %08X{SQLRETURN}\n", retcode);
}
Debug.Assert(HandleState.Allocated == _handleState, "not expected HandleState.Allocated");
return base.ReleaseHandle();
}
internal ODBC32.RetCode GetConnectionAttribute(ODBC32.SQL_ATTR attribute, byte[] buffer, out int cbActual) {
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetConnectAttrW(this, attribute, buffer, buffer.Length, out cbActual);
Bid.Trace("<odbc.SQLGetConnectAttr|ODBC> SQLRETURN=%d, Attribute=%d, BufferLength=%d, StringLength=%d\n", (int)retcode, (int)attribute, buffer.Length, (int)cbActual);
return retcode;
}
internal ODBC32.RetCode GetFunctions(ODBC32.SQL_API fFunction, out Int16 fExists) {
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetFunctions(this, fFunction, out fExists);
ODBC.TraceODBC(3, "SQLGetFunctions", retcode);
return retcode;
}
internal ODBC32.RetCode GetInfo2(ODBC32.SQL_INFO info, byte[] buffer, out short cbActual) {
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetInfoW(this, info, buffer, checked((short)buffer.Length), out cbActual);
Bid.Trace("<odbc.SQLGetInfo|ODBC> SQLRETURN=%d, InfoType=%d, BufferLength=%d, StringLength=%d\n", (int)retcode, (int)info, buffer.Length, (int)cbActual);
return retcode;
}
internal ODBC32.RetCode GetInfo1(ODBC32.SQL_INFO info, byte[] buffer) {
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetInfoW(this, info, buffer, checked((short)buffer.Length), ADP.PtrZero);
Bid.Trace("<odbc.SQLGetInfo|ODBC> SQLRETURN=%d, InfoType=%d, BufferLength=%d\n", (int)retcode, (int)info, buffer.Length);
return retcode;
}
internal ODBC32.RetCode SetConnectionAttribute2(ODBC32.SQL_ATTR attribute, IntPtr value, Int32 length) {
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLSetConnectAttrW(this, attribute, value, length);
ODBC.TraceODBC(3, "SQLSetConnectAttrW", retcode);
return retcode;
}
internal ODBC32.RetCode SetConnectionAttribute3(ODBC32.SQL_ATTR attribute, string buffer, Int32 length) {
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLSetConnectAttrW(this, attribute, buffer, length);
Bid.Trace("<odbc.SQLSetConnectAttr|ODBC> SQLRETURN=%d, Attribute=%d, BufferLength=%d\n", (int)retcode, (int)attribute, buffer.Length);
return retcode;
}
internal ODBC32.RetCode SetConnectionAttribute4(ODBC32.SQL_ATTR attribute, System.Transactions.IDtcTransaction transaction, Int32 length) {
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLSetConnectAttrW(this, attribute, transaction, length);
ODBC.TraceODBC(3, "SQLSetConnectAttrW", retcode);
return retcode;
}
}
}

View File

@@ -0,0 +1,84 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcConnectionOpen.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.Data;
using System.Data.Common;
using System.Data.ProviderBase;
using System.Threading;
using SysTx = System.Transactions;
namespace System.Data.Odbc {
sealed internal class OdbcConnectionOpen : DbConnectionInternal {
// Construct from a compiled connection string
internal OdbcConnectionOpen(OdbcConnection outerConnection, OdbcConnectionString connectionOptions) {
#if DEBUG
try { // use this to help validate this object is only created after the following permission has been previously demanded in the current codepath
if (null != outerConnection) {
outerConnection.UserConnectionOptions.DemandPermission();
}
else {
connectionOptions.DemandPermission();
}
}
catch(System.Security.SecurityException) {
System.Diagnostics.Debug.Assert(false, "unexpected SecurityException for current codepath");
throw;
}
#endif
OdbcEnvironmentHandle environmentHandle = OdbcEnvironment.GetGlobalEnvironmentHandle();
outerConnection.ConnectionHandle = new OdbcConnectionHandle(outerConnection, connectionOptions, environmentHandle);
}
internal OdbcConnection OuterConnection {
get {
OdbcConnection outerConnection = (OdbcConnection)Owner;
if (null == outerConnection)
throw ODBC.OpenConnectionNoOwner();
return outerConnection;
}
}
override public string ServerVersion {
get {
return OuterConnection.Open_GetServerVersion();
}
}
override protected void Activate(SysTx.Transaction transaction) {
OdbcConnection.ExecutePermission.Demand();
}
override public DbTransaction BeginTransaction(IsolationLevel isolevel) {
return BeginOdbcTransaction(isolevel);
}
internal OdbcTransaction BeginOdbcTransaction(IsolationLevel isolevel) {
return OuterConnection.Open_BeginTransaction(isolevel);
}
override public void ChangeDatabase(string value) {
OuterConnection.Open_ChangeDatabase(value);
}
override protected DbReferenceCollection CreateReferenceCollection() {
return new OdbcReferenceCollection();
}
override protected void Deactivate() {
NotifyWeakReference(OdbcReferenceCollection.Closing);
}
override public void EnlistTransaction(SysTx.Transaction transaction) {
OuterConnection.Open_EnlistTransaction(transaction);
}
}
}

View File

@@ -0,0 +1,202 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcConnectionPoolProviderInfo.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.ProviderBase;
sealed internal class OdbcConnectionPoolGroupProviderInfo : DbConnectionPoolGroupProviderInfo {
private string _driverName;
private string _driverVersion;
private string _quoteChar;
private char _escapeChar;
private bool _hasQuoteChar;
private bool _hasEscapeChar;
private bool _isV3Driver;
private int _supportedSQLTypes;
private int _testedSQLTypes;
private int _restrictedSQLBindTypes; // These, otherwise supported types, are not available for binding
// flags for unsupported Attributes
private bool _noCurrentCatalog;
private bool _noConnectionDead;
private bool _noQueryTimeout;
private bool _noSqlSoptSSNoBrowseTable;
private bool _noSqlSoptSSHiddenColumns;
// SSS_WARNINGS_OFF
private bool _noSqlCASSColumnKey;
// SSS_WARNINGS_ON
// flags for unsupported Functions
private bool _noSqlPrimaryKeys;
internal string DriverName {
get {
return _driverName;
}
set {
_driverName = value;
}
}
internal string DriverVersion {
get {
return _driverVersion;
}
set {
_driverVersion = value;
}
}
internal bool HasQuoteChar {
// the value is set together with the QuoteChar (see set_QuoteChar);
get {
return _hasQuoteChar;
}
}
internal bool HasEscapeChar {
// the value is set together with the EscapeChar (see set_EscapeChar);
get {
return _hasEscapeChar;
}
}
internal string QuoteChar {
get {
return _quoteChar;
}
set {
_quoteChar = value;
_hasQuoteChar = true;
}
}
internal char EscapeChar {
get {
return _escapeChar;
}
set {
_escapeChar = value;
_hasEscapeChar = true;
}
}
internal bool IsV3Driver {
get {
return _isV3Driver;
}
set {
_isV3Driver = value;
}
}
internal int SupportedSQLTypes {
get {
return _supportedSQLTypes;
}
set {
_supportedSQLTypes = value;
}
}
internal int TestedSQLTypes {
get {
return _testedSQLTypes;
}
set {
_testedSQLTypes = value;
}
}
internal int RestrictedSQLBindTypes {
get {
return _restrictedSQLBindTypes;
}
set {
_restrictedSQLBindTypes = value;
}
}
internal bool NoCurrentCatalog {
get {
return _noCurrentCatalog;
}
set {
_noCurrentCatalog = value;
}
}
internal bool NoConnectionDead {
get {
return _noConnectionDead;
}
set {
_noConnectionDead = value;
}
}
internal bool NoQueryTimeout {
get {
return _noQueryTimeout;
}
set {
_noQueryTimeout = value;
}
}
internal bool NoSqlSoptSSNoBrowseTable {
get {
return _noSqlSoptSSNoBrowseTable;
}
set {
_noSqlSoptSSNoBrowseTable = value;
}
}
internal bool NoSqlSoptSSHiddenColumns {
get {
return _noSqlSoptSSHiddenColumns;
}
set {
_noSqlSoptSSHiddenColumns = value;
}
}
// SSS_WARNINGS_OFF
internal bool NoSqlCASSColumnKey {
get {
return _noSqlCASSColumnKey;
}
set {
_noSqlCASSColumnKey = value;
}
}
// SSS_WARNINGS_ON
internal bool NoSqlPrimaryKeys {
get {
return _noSqlPrimaryKeys;
}
set {
_noSqlPrimaryKeys = value;
}
}
}
}

View File

@@ -0,0 +1,65 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcConnectionString.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.Collections;
using System.Data;
using System.Data.Common;
using System.Security;
using System.Security.Permissions;
using System.Text;
internal sealed class OdbcConnectionString : DbConnectionOptions {
// instances of this class are intended to be immutable, i.e readonly
// used by pooling classes so it is much easier to verify correctness
// when not worried about the class being modified during execution
private static class KEY {
internal const string SaveFile = "savefile";
}
private readonly string _expandedConnectionString;
internal OdbcConnectionString(string connectionString, bool validate) : base(connectionString, null, true) {
if (!validate) {
string filename = null;
int position = 0;
_expandedConnectionString = ExpandDataDirectories(ref filename, ref position);
}
if (validate || (null == _expandedConnectionString)) {
// do not check string length if it was expanded because the final result may be shorter than the original
if ((null != connectionString) && (ODBC32.MAX_CONNECTION_STRING_LENGTH < connectionString.Length)) { // MDAC 83536
throw ODBC.ConnectionStringTooLong();
}
}
}
protected internal override System.Security.PermissionSet CreatePermissionSet() {
System.Security.PermissionSet permissionSet;
if (ContainsKey(KEY.SaveFile)) {
permissionSet = new NamedPermissionSet("FullTrust");
}
else {
permissionSet = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
permissionSet.AddPermission(new OdbcPermission(this));
}
return permissionSet;
}
protected internal override string Expand() {
if (null != _expandedConnectionString) {
return _expandedConnectionString;
}
else {
return base.Expand();
}
}
}
}

View File

@@ -0,0 +1,334 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcConnectionStringBuilder.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Text;
namespace System.Data.Odbc {
[DefaultProperty("Driver")]
[System.ComponentModel.TypeConverterAttribute(typeof(OdbcConnectionStringBuilder.OdbcConnectionStringBuilderConverter))]
public sealed class OdbcConnectionStringBuilder : DbConnectionStringBuilder {
private enum Keywords { // must maintain same ordering as _validKeywords array
// NamedConnection,
Dsn,
Driver,
}
private static readonly string[] _validKeywords;
private static readonly Dictionary<string,Keywords> _keywords;
private string[] _knownKeywords;
private string _dsn = DbConnectionStringDefaults.Dsn;
// private string _namedConnection = DbConnectionStringDefaults.NamedConnection;
private string _driver = DbConnectionStringDefaults.Driver;
static OdbcConnectionStringBuilder() {
string[] validKeywords = new string[2];
validKeywords[(int)Keywords.Driver] = DbConnectionStringKeywords.Driver;
validKeywords[(int)Keywords.Dsn] = DbConnectionStringKeywords.Dsn;
// validKeywords[(int)Keywords.NamedConnection] = DbConnectionStringKeywords.NamedConnection;
_validKeywords = validKeywords;
Dictionary<string,Keywords> hash = new Dictionary<string,Keywords>(2, StringComparer.OrdinalIgnoreCase);
hash.Add(DbConnectionStringKeywords.Driver, Keywords.Driver);
hash.Add(DbConnectionStringKeywords.Dsn, Keywords.Dsn);
// hash.Add(DbConnectionStringKeywords.NamedConnection, Keywords.NamedConnection);
Debug.Assert(2 == hash.Count, "initial expected size is incorrect");
_keywords = hash;
}
public OdbcConnectionStringBuilder() : this((string)null) {
}
public OdbcConnectionStringBuilder(string connectionString) : base(true) {
if (!ADP.IsEmpty(connectionString)) {
ConnectionString = connectionString;
}
}
public override object this[string keyword] {
get {
ADP.CheckArgumentNull(keyword, "keyword");
Keywords index;
if (_keywords.TryGetValue(keyword, out index)) {
return GetAt(index);
}
else {
return base[keyword];
}
}
set {
ADP.CheckArgumentNull(keyword, "keyword");
if (null != value) {
Keywords index;
if (_keywords.TryGetValue(keyword, out index)) {
switch(index) {
case Keywords.Driver: Driver = ConvertToString(value); break;
case Keywords.Dsn: Dsn = ConvertToString(value); break;
// case Keywords.NamedConnection: NamedConnection = ConvertToString(value); break;
default:
Debug.Assert(false, "unexpected keyword");
throw ADP.KeywordNotSupported(keyword);
}
}
else {
base[keyword] = value;
ClearPropertyDescriptors();
_knownKeywords = null;
}
}
else {
Remove(keyword);
}
}
}
[DisplayName(DbConnectionStringKeywords.Driver)]
[ResCategoryAttribute(Res.DataCategory_Source)]
[ResDescriptionAttribute(Res.DbConnectionString_Driver)]
[RefreshPropertiesAttribute(RefreshProperties.All)]
public string Driver {
get { return _driver; }
set {
SetValue(DbConnectionStringKeywords.Driver, value);
_driver = value;
}
}
[DisplayName(DbConnectionStringKeywords.Dsn)]
[ResCategoryAttribute(Res.DataCategory_NamedConnectionString)]
[ResDescriptionAttribute(Res.DbConnectionString_DSN)]
[RefreshPropertiesAttribute(RefreshProperties.All)]
public string Dsn {
get { return _dsn; }
set {
SetValue(DbConnectionStringKeywords.Dsn, value);
_dsn = value;
}
}
/*
[DisplayName(DbConnectionStringKeywords.NamedConnection)]
[ResCategoryAttribute(Res.DataCategory_NamedConnectionString)]
[ResDescriptionAttribute(Res.DbConnectionString_NamedConnection)]
[RefreshPropertiesAttribute(RefreshProperties.All)]
[TypeConverter(typeof(NamedConnectionStringConverter))]
public string NamedConnection {
get { return _namedConnection; }
set {
SetValue(DbConnectionStringKeywords.NamedConnection, value);
_namedConnection = value;
}
}
*/
public override ICollection Keys {
get {
string[] knownKeywords = _knownKeywords;
if (null == knownKeywords) {
knownKeywords = _validKeywords;
int count = 0;
foreach(string keyword in base.Keys) {
bool flag = true;
foreach(string s in knownKeywords) {
if (s == keyword) {
flag = false;
break;
}
}
if (flag) {
count++;
}
}
if (0 < count) {
string[] tmp = new string[knownKeywords.Length + count];
knownKeywords.CopyTo(tmp, 0);
int index = knownKeywords.Length;
foreach(string keyword in base.Keys) {
bool flag = true;
foreach(string s in knownKeywords) {
if (s == keyword) {
flag = false;
break;
}
}
if (flag) {
tmp[index++] = keyword;
}
}
knownKeywords = tmp;
}
_knownKeywords = knownKeywords;
}
return new System.Data.Common.ReadOnlyCollection<string>(knownKeywords);
}
}
public override void Clear() {
base.Clear();
for(int i = 0; i < _validKeywords.Length; ++i) {
Reset((Keywords)i);
}
_knownKeywords = _validKeywords;
}
public override bool ContainsKey(string keyword) {
ADP.CheckArgumentNull(keyword, "keyword");
return _keywords.ContainsKey(keyword) || base.ContainsKey(keyword);
}
private static string ConvertToString(object value) {
return DbConnectionStringBuilderUtil.ConvertToString(value);
}
private object GetAt(Keywords index) {
switch(index) {
case Keywords.Driver: return Driver;
case Keywords.Dsn: return Dsn;
// case Keywords.NamedConnection: return NamedConnection;
default:
Debug.Assert(false, "unexpected keyword");
throw ADP.KeywordNotSupported(_validKeywords[(int)index]);
}
}
/*
protected override void GetProperties(Hashtable propertyDescriptors) {
object value;
if (TryGetValue(DbConnectionStringSynonyms.TRUSTEDCONNECTION, out value)) {
bool trusted = false;
if (value is bool) {
trusted = (bool)value;
}
else if ((value is string) && !Boolean.TryParse((string)value, out trusted)) {
trusted = false;
}
if (trusted) {
Attribute[] attributes = new Attribute[] {
BrowsableAttribute.Yes,
RefreshPropertiesAttribute.All,
};
DbConnectionStringBuilderDescriptor descriptor;
descriptor = new DbConnectionStringBuilderDescriptor(DbConnectionStringSynonyms.TRUSTEDCONNECTION,
this.GetType(), typeof(bool), false, attributes);
descriptor.RefreshOnChange = true;
propertyDescriptors[DbConnectionStringSynonyms.TRUSTEDCONNECTION] = descriptor;
if (ContainsKey(DbConnectionStringSynonyms.Pwd)) {
descriptor = new DbConnectionStringBuilderDescriptor(DbConnectionStringSynonyms.Pwd,
this.GetType(), typeof(string), true, attributes);
propertyDescriptors[DbConnectionStringSynonyms.Pwd] = descriptor;
}
if (ContainsKey(DbConnectionStringSynonyms.UID)) {
descriptor = new DbConnectionStringBuilderDescriptor(DbConnectionStringSynonyms.UID,
this.GetType(), typeof(string), true, attributes);
propertyDescriptors[DbConnectionStringSynonyms.UID] = descriptor;
}
}
}
base.GetProperties(propertyDescriptors);
}
*/
public override bool Remove(string keyword) {
ADP.CheckArgumentNull(keyword, "keyword");
if (base.Remove(keyword)) {
Keywords index;
if (_keywords.TryGetValue(keyword, out index)) {
Reset(index);
}
else {
ClearPropertyDescriptors();
_knownKeywords = null;
}
return true;
}
return false;
}
private void Reset(Keywords index) {
switch(index) {
case Keywords.Driver:
_driver = DbConnectionStringDefaults.Driver;
break;
case Keywords.Dsn:
_dsn = DbConnectionStringDefaults.Dsn;
break;
// case Keywords.NamedConnection:
// _namedConnection = DbConnectionStringDefaults.NamedConnection;
// break;
default:
Debug.Assert(false, "unexpected keyword");
throw ADP.KeywordNotSupported(_validKeywords[(int)index]);
}
}
private void SetValue(string keyword, string value) {
ADP.CheckArgumentNull(value, keyword);
base[keyword] = value;
}
public override bool TryGetValue(string keyword, out object value) {
ADP.CheckArgumentNull(keyword, "keyword");
Keywords index;
if (_keywords.TryGetValue(keyword, out index)) {
value = GetAt(index);
return true;
}
return base.TryGetValue(keyword, out value);
}
sealed internal class OdbcConnectionStringBuilderConverter : ExpandableObjectConverter {
// converter classes should have public ctor
public OdbcConnectionStringBuilderConverter() {
}
override public bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) {
if (typeof(System.ComponentModel.Design.Serialization.InstanceDescriptor) == destinationType) {
return true;
}
return base.CanConvertTo(context, destinationType);
}
override public object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
if (destinationType == null) {
throw ADP.ArgumentNull("destinationType");
}
if (typeof(System.ComponentModel.Design.Serialization.InstanceDescriptor) == destinationType) {
OdbcConnectionStringBuilder obj = (value as OdbcConnectionStringBuilder);
if (null != obj) {
return ConvertToInstanceDescriptor(obj);
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
private System.ComponentModel.Design.Serialization.InstanceDescriptor ConvertToInstanceDescriptor(OdbcConnectionStringBuilder options) {
Type[] ctorParams = new Type[] { typeof(string) };
object[] ctorValues = new object[] { options.ConnectionString };
System.Reflection.ConstructorInfo ctor = typeof(OdbcConnectionStringBuilder).GetConstructor(ctorParams);
return new System.ComponentModel.Design.Serialization.InstanceDescriptor(ctor, ctorValues);
}
}
}
}

View File

@@ -0,0 +1,177 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcDataAdapter.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Threading;
namespace System.Data.Odbc {
[
DefaultEvent("RowUpdated"),
ToolboxItem("Microsoft.VSDesigner.Data.VS.OdbcDataAdapterToolboxItem, " + AssemblyRef.MicrosoftVSDesigner), // WebData 97832
Designer("Microsoft.VSDesigner.Data.VS.OdbcDataAdapterDesigner, " + AssemblyRef.MicrosoftVSDesigner)
]
public sealed class OdbcDataAdapter : DbDataAdapter, IDbDataAdapter, ICloneable {
static private readonly object EventRowUpdated = new object();
static private readonly object EventRowUpdating = new object();
private OdbcCommand _deleteCommand, _insertCommand, _selectCommand, _updateCommand;
public OdbcDataAdapter() : base() {
GC.SuppressFinalize(this);
}
public OdbcDataAdapter(OdbcCommand selectCommand) : this() {
SelectCommand = selectCommand;
}
public OdbcDataAdapter(string selectCommandText, OdbcConnection selectConnection) : this() {
SelectCommand = new OdbcCommand(selectCommandText, selectConnection);
}
public OdbcDataAdapter(string selectCommandText, string selectConnectionString) : this() {
OdbcConnection connection = new OdbcConnection(selectConnectionString);
SelectCommand = new OdbcCommand(selectCommandText, connection);
}
private OdbcDataAdapter(OdbcDataAdapter from) : base(from) {
GC.SuppressFinalize(this);
}
[
DefaultValue(null),
ResCategoryAttribute(Res.DataCategory_Update),
ResDescriptionAttribute(Res.DbDataAdapter_DeleteCommand),
Editor("Microsoft.VSDesigner.Data.Design.DBCommandEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
]
new public OdbcCommand DeleteCommand {
get { return _deleteCommand; }
set { _deleteCommand = value; }
}
IDbCommand IDbDataAdapter.DeleteCommand {
get { return _deleteCommand; }
set { _deleteCommand = (OdbcCommand)value; }
}
[
DefaultValue(null),
ResCategoryAttribute(Res.DataCategory_Update),
ResDescriptionAttribute(Res.DbDataAdapter_InsertCommand),
Editor("Microsoft.VSDesigner.Data.Design.DBCommandEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
]
new public OdbcCommand InsertCommand {
get { return _insertCommand; }
set { _insertCommand = value; }
}
IDbCommand IDbDataAdapter.InsertCommand {
get { return _insertCommand; }
set { _insertCommand = (OdbcCommand)value; }
}
[
DefaultValue(null),
ResCategoryAttribute(Res.DataCategory_Fill),
ResDescriptionAttribute(Res.DbDataAdapter_SelectCommand),
Editor("Microsoft.VSDesigner.Data.Design.DBCommandEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
]
new public OdbcCommand SelectCommand {
get { return _selectCommand; }
set { _selectCommand = value; }
}
IDbCommand IDbDataAdapter.SelectCommand {
get { return _selectCommand; }
set { _selectCommand = (OdbcCommand)value; }
}
[
DefaultValue(null),
ResCategoryAttribute(Res.DataCategory_Update),
ResDescriptionAttribute(Res.DbDataAdapter_UpdateCommand),
Editor("Microsoft.VSDesigner.Data.Design.DBCommandEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
]
new public OdbcCommand UpdateCommand {
get { return _updateCommand; }
set { _updateCommand = value; }
}
IDbCommand IDbDataAdapter.UpdateCommand {
get { return _updateCommand; }
set { _updateCommand = (OdbcCommand)value; }
}
[
ResCategoryAttribute(Res.DataCategory_Update),
ResDescriptionAttribute(Res.DbDataAdapter_RowUpdated),
]
public event OdbcRowUpdatedEventHandler RowUpdated {
add {
Events.AddHandler(EventRowUpdated, value); }
remove {
Events.RemoveHandler(EventRowUpdated, value); }
}
[
ResCategoryAttribute(Res.DataCategory_Update),
ResDescriptionAttribute(Res.DbDataAdapter_RowUpdating),
]
public event OdbcRowUpdatingEventHandler RowUpdating {
add {
OdbcRowUpdatingEventHandler handler = (OdbcRowUpdatingEventHandler) Events[EventRowUpdating];
// MDAC 58177, 64513
// prevent someone from registering two different command builders on the adapter by
// silently removing the old one
if ((null != handler) && (value.Target is OdbcCommandBuilder)) {
OdbcRowUpdatingEventHandler d = (OdbcRowUpdatingEventHandler) ADP.FindBuilder(handler);
if (null != d) {
Events.RemoveHandler(EventRowUpdating, d);
}
}
Events.AddHandler(EventRowUpdating, value);
}
remove {
Events.RemoveHandler(EventRowUpdating, value); }
}
object ICloneable.Clone() {
return new OdbcDataAdapter(this);
}
override protected RowUpdatedEventArgs CreateRowUpdatedEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) {
return new OdbcRowUpdatedEventArgs(dataRow, command, statementType, tableMapping);
}
override protected RowUpdatingEventArgs CreateRowUpdatingEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) {
return new OdbcRowUpdatingEventArgs(dataRow, command, statementType, tableMapping);
}
override protected void OnRowUpdated(RowUpdatedEventArgs value) {
OdbcRowUpdatedEventHandler handler = (OdbcRowUpdatedEventHandler) Events[EventRowUpdated];
if ((null != handler) && (value is OdbcRowUpdatedEventArgs)) {
handler(this, (OdbcRowUpdatedEventArgs) value);
}
base.OnRowUpdated(value);
}
override protected void OnRowUpdating(RowUpdatingEventArgs value) {
OdbcRowUpdatingEventHandler handler = (OdbcRowUpdatingEventHandler) Events[EventRowUpdating];
if ((null != handler) && (value is OdbcRowUpdatingEventArgs)) {
handler(this, (OdbcRowUpdatingEventArgs) value);
}
base.OnRowUpdating(value);
}
}
}

View File

@@ -0,0 +1 @@
2428b5e4901324f1ae0fa38fc81536ebb2c3cdb2

View File

@@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcEnvironment.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.Data;
using System.Data.Common;
using System.Threading;
namespace System.Data.Odbc {
sealed internal class OdbcEnvironment {
static private object _globalEnvironmentHandle;
static private object _globalEnvironmentHandleLock = new object();
private OdbcEnvironment () {} // default const.
static internal OdbcEnvironmentHandle GetGlobalEnvironmentHandle() {
OdbcEnvironmentHandle globalEnvironmentHandle = _globalEnvironmentHandle as OdbcEnvironmentHandle;
if(null == globalEnvironmentHandle) {
ADP.CheckVersionMDAC(true);
lock(_globalEnvironmentHandleLock) {
globalEnvironmentHandle = _globalEnvironmentHandle as OdbcEnvironmentHandle;
if(null == globalEnvironmentHandle) {
globalEnvironmentHandle = new OdbcEnvironmentHandle();
_globalEnvironmentHandle = globalEnvironmentHandle;
}
}
}
return globalEnvironmentHandle;
}
static internal void ReleaseObjectPool() {
object globalEnvironmentHandle = Interlocked.Exchange(ref _globalEnvironmentHandle, null);
if(null != globalEnvironmentHandle) {
(globalEnvironmentHandle as OdbcEnvironmentHandle).Dispose(); // internally refcounted so will happen correctly
}
}
}
}

View File

@@ -0,0 +1,64 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcEnvironmentHandle.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Runtime.Versioning;
namespace System.Data.Odbc {
sealed internal class OdbcEnvironmentHandle : OdbcHandle {
// SxS: this method uses SQLSetEnvAttr to setup ODBC environment handle settings. Environment handle is safe in SxS.
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
internal OdbcEnvironmentHandle() : base(ODBC32.SQL_HANDLE.ENV, null) {
ODBC32.RetCode retcode;
//Set the expected driver manager version
//
retcode = UnsafeNativeMethods.SQLSetEnvAttr(
this,
ODBC32.SQL_ATTR.ODBC_VERSION,
ODBC32.SQL_OV_ODBC3,
ODBC32.SQL_IS.INTEGER);
// ignore retcode
//Turn on connection pooling
//Note: the env handle controls pooling. Only those connections created under that
//handle are pooled. So we have to keep it alive and not create a new environment
//for every connection.
//
retcode = UnsafeNativeMethods.SQLSetEnvAttr(
this,
ODBC32.SQL_ATTR.CONNECTION_POOLING,
ODBC32.SQL_CP_ONE_PER_HENV,
ODBC32.SQL_IS.INTEGER);
switch(retcode) {
case ODBC32.RetCode.SUCCESS:
case ODBC32.RetCode.SUCCESS_WITH_INFO:
break;
default:
Dispose();
throw ODBC.CantEnableConnectionpooling(retcode);
}
}
}
}

View File

@@ -0,0 +1,61 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcError.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.Data;
namespace System.Data.Odbc
{
[Serializable]
public sealed class OdbcError {
//Data
internal string _message;
internal string _state;
internal int _nativeerror;
internal string _source;
internal OdbcError(string source, string message, string state, int nativeerror) {
_source = source;
_message = message;
_state = state;
_nativeerror= nativeerror;
}
public string Message {
get {
return ((null != _message) ? _message : String.Empty);
}
}
public string SQLState {
get {
return _state;
}
}
public int NativeError {
get {
return _nativeerror;
}
}
public string Source {
get {
return ((null != _source) ? _source : String.Empty);
}
}
internal void SetSource (string Source) {
_source = Source;
}
override public string ToString() {
return Message;
}
}
}

View File

@@ -0,0 +1,64 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcErrorCollection.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.Collections;
using System.Data;
[Serializable]
public sealed class OdbcErrorCollection : ICollection {
private ArrayList _items = new ArrayList();
internal OdbcErrorCollection() {
}
Object System.Collections.ICollection.SyncRoot {
get { return this; }
}
bool System.Collections.ICollection.IsSynchronized {
get { return false; }
}
public int Count {
get {
return _items.Count;
}
}
public OdbcError this[int i] {
get {
return (OdbcError)_items[i];
}
}
internal void Add(OdbcError error) {
_items.Add(error);
}
public void CopyTo (Array array, int i) {
_items.CopyTo(array, i);
}
public void CopyTo (OdbcError[] array, int i) {
_items.CopyTo(array, i);
}
public IEnumerator GetEnumerator() {
return _items.GetEnumerator();
}
internal void SetSource (string Source) {
foreach (object error in _items) {
((OdbcError)error).SetSource(Source);
}
}
}
}

View File

@@ -0,0 +1,80 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcException.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.ComponentModel; //Component
using System.Collections; //ICollection
using System.Data;
using System.Data.Common;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
namespace System.Data.Odbc {
[Serializable]
public sealed class OdbcException : System.Data.Common.DbException {
OdbcErrorCollection odbcErrors = new OdbcErrorCollection();
ODBC32.RETCODE _retcode; // DO NOT REMOVE! only needed for serialization purposes, because Everett had it.
static internal OdbcException CreateException(OdbcErrorCollection errors, ODBC32.RetCode retcode) {
StringBuilder builder = new StringBuilder();
foreach (OdbcError error in errors) {
if (builder.Length > 0) {
builder.Append(Environment.NewLine);
}
builder.Append(Res.GetString(Res.Odbc_ExceptionMessage, ODBC32.RetcodeToString(retcode), error.SQLState, error.Message)); // MDAC 68337
}
OdbcException exception = new OdbcException(builder.ToString(), errors);
return exception;
}
internal OdbcException(string message, OdbcErrorCollection errors) : base(message) {
odbcErrors = errors;
HResult = HResults.OdbcException;
}
// runtime will call even if private...
private OdbcException(SerializationInfo si, StreamingContext sc) : base(si, sc) {
_retcode = (ODBC32.RETCODE) si.GetValue("odbcRetcode", typeof(ODBC32.RETCODE));
odbcErrors = (OdbcErrorCollection) si.GetValue("odbcErrors", typeof(OdbcErrorCollection));
HResult = HResults.OdbcException;
}
public OdbcErrorCollection Errors {
get {
return odbcErrors;
}
}
[System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Flags=System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)]
override public void GetObjectData(SerializationInfo si, StreamingContext context) {
// MDAC 72003
if (null == si) {
throw new ArgumentNullException("si");
}
si.AddValue("odbcRetcode", _retcode, typeof(ODBC32.RETCODE));
si.AddValue("odbcErrors", odbcErrors, typeof(OdbcErrorCollection));
base.GetObjectData(si, context);
}
// mdac bug 62559 - if we don't have it return nothing (empty string)
override public string Source {
get {
if (0 < Errors.Count) {
string source = Errors[0].Source;
return ADP.IsEmpty(source) ? "" : source; // base.Source;
}
return ""; // base.Source;
}
}
}
}

View File

@@ -0,0 +1,52 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcFactory.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.Data;
using System.Data.Common;
using System.Security;
using System.Security.Permissions;
namespace System.Data.Odbc {
public sealed class OdbcFactory : DbProviderFactory {
public static readonly OdbcFactory Instance = new OdbcFactory();
private OdbcFactory() {
}
public override DbCommand CreateCommand() {
return new OdbcCommand();
}
public override DbCommandBuilder CreateCommandBuilder() {
return new OdbcCommandBuilder();
}
public override DbConnection CreateConnection() {
return new OdbcConnection();
}
public override DbConnectionStringBuilder CreateConnectionStringBuilder() {
return new OdbcConnectionStringBuilder();
}
public override DbDataAdapter CreateDataAdapter() {
return new OdbcDataAdapter();
}
public override DbParameter CreateParameter() {
return new OdbcParameter();
}
public override CodeAccessPermission CreatePermission(PermissionState state) {
return new OdbcPermission(state);
}
}
}

View File

@@ -0,0 +1,235 @@
//------------------------------------------------------------------------------
// <copyright file="OdbcHandle.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Runtime.ConstrainedExecution;
namespace System.Data.Odbc {
internal abstract class OdbcHandle : SafeHandle {
private ODBC32.SQL_HANDLE _handleType;
private OdbcHandle _parentHandle;
protected OdbcHandle(ODBC32.SQL_HANDLE handleType, OdbcHandle parentHandle) : base(IntPtr.Zero, true) {
_handleType = handleType;
bool mustRelease = false;
ODBC32.RetCode retcode = ODBC32.RetCode.SUCCESS;
// using ConstrainedRegions to make the native ODBC call and AddRef the parent
RuntimeHelpers.PrepareConstrainedRegions();
try {
// validate handleType
switch(handleType) {
case ODBC32.SQL_HANDLE.ENV:
Debug.Assert(null == parentHandle, "did not expect a parent handle");
retcode = UnsafeNativeMethods.SQLAllocHandle(handleType, IntPtr.Zero, out base.handle);
break;
case ODBC32.SQL_HANDLE.DBC:
case ODBC32.SQL_HANDLE.STMT:
// must addref before calling native so it won't be released just after
Debug.Assert(null != parentHandle, "expected a parent handle"); // safehandle can't be null
parentHandle.DangerousAddRef(ref mustRelease);
retcode = UnsafeNativeMethods.SQLAllocHandle(handleType, parentHandle, out base.handle);
break;
// case ODBC32.SQL_HANDLE.DESC:
default:
Debug.Assert(false, "unexpected handleType");
break;
}
}
finally {
if (mustRelease) {
switch(handleType) {
case ODBC32.SQL_HANDLE.DBC:
case ODBC32.SQL_HANDLE.STMT:
if (IntPtr.Zero != base.handle) {
// must assign _parentHandle after a handle is actually created
// since ReleaseHandle will only call DangerousRelease if a handle exists
_parentHandle = parentHandle;
}
else {
// without a handle, ReleaseHandle may not be called
parentHandle.DangerousRelease();
}
break;
}
}
}
Bid.TraceSqlReturn("<odbc.SQLAllocHandle|API|ODBC|RET> %08X{SQLRETURN}\n", retcode);
if((ADP.PtrZero == base.handle) || (ODBC32.RetCode.SUCCESS != retcode)) {
//
throw ODBC.CantAllocateEnvironmentHandle(retcode);
}
}
internal OdbcHandle(OdbcStatementHandle parentHandle, ODBC32.SQL_ATTR attribute) : base(IntPtr.Zero, true) {
Debug.Assert((ODBC32.SQL_ATTR.APP_PARAM_DESC == attribute) || (ODBC32.SQL_ATTR.APP_ROW_DESC == attribute), "invalid attribute");
_handleType = ODBC32.SQL_HANDLE.DESC;
int cbActual;
ODBC32.RetCode retcode;
bool mustRelease = false;
RuntimeHelpers.PrepareConstrainedRegions();
try {
// must addref before calling native so it won't be released just after
parentHandle.DangerousAddRef(ref mustRelease);
retcode = parentHandle.GetStatementAttribute(attribute, out base.handle, out cbActual);
}
finally {
if (mustRelease) {
if (IntPtr.Zero != base.handle) {
// must call DangerousAddRef after a handle is actually created
// since ReleaseHandle will only call DangerousRelease if a handle exists
_parentHandle = parentHandle;
}
else {
// without a handle, ReleaseHandle may not be called
parentHandle.DangerousRelease();
}
}
}
if (ADP.PtrZero == base.handle) {
throw ODBC.FailedToGetDescriptorHandle(retcode);
}
// no info-message handle on getting a descriptor handle
}
internal ODBC32.SQL_HANDLE HandleType {
get {
return _handleType;
}
}
public override bool IsInvalid {
get {
// we should not have a parent if we do not have a handle
return (IntPtr.Zero == base.handle);
}
}
override protected bool ReleaseHandle() {
// NOTE: The SafeHandle class guarantees this will be called exactly once and is non-interrutible.
IntPtr handle = base.handle;
base.handle = IntPtr.Zero;
if (IntPtr.Zero != handle) {
ODBC32.SQL_HANDLE handleType = HandleType;
switch (handleType) {
case ODBC32.SQL_HANDLE.DBC:
// Disconnect happens in OdbcConnectionHandle.ReleaseHandle
case ODBC32.SQL_HANDLE.ENV:
case ODBC32.SQL_HANDLE.STMT:
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLFreeHandle(handleType, handle);
Bid.TraceSqlReturn("<odbc.SQLFreeHandle|API|ODBC|RET> %08X{SQLRETURN}\n", retcode);
break;
case ODBC32.SQL_HANDLE.DESC:
// nothing to free on the handle
break;
// case 0: ThreadAbortException setting handle before HandleType
default:
Debug.Assert(ADP.PtrZero == handle, "unknown handle type");
break;
}
}
// If we ended up getting released, then we have to release
// our reference on our parent.
OdbcHandle parentHandle = _parentHandle;
_parentHandle = null;
if (null != parentHandle) {
parentHandle.DangerousRelease();
parentHandle = null;
}
return true;
}
internal ODBC32.RetCode GetDiagnosticField (out string sqlState) {
short cbActual;
// ODBC (MSDN) documents it expects a buffer large enough to hold 5(+L'\0') unicode characters
StringBuilder sb = new StringBuilder(6);
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetDiagFieldW(
HandleType,
this,
(short)1,
ODBC32.SQL_DIAG_SQLSTATE,
sb,
checked((short)(2*sb.Capacity)), // expects number of bytes, see \\kbinternal\kb\articles\294\1\69.HTM
out cbActual);
ODBC.TraceODBC(3, "SQLGetDiagFieldW", retcode);
if ((retcode == ODBC32.RetCode.SUCCESS) || (retcode == ODBC32.RetCode.SUCCESS_WITH_INFO)) {
sqlState = sb.ToString();
}
else {
sqlState = ADP.StrEmpty;
}
return retcode;
}
internal ODBC32.RetCode GetDiagnosticRecord(short record, out string sqlState, StringBuilder message, out int nativeError, out short cchActual) {
// ODBC (MSDN) documents it expects a buffer large enough to hold 4(+L'\0') unicode characters
StringBuilder sb = new StringBuilder(5);
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetDiagRecW(HandleType, this, record, sb, out nativeError, message, checked((short)message.Capacity), out cchActual);
ODBC.TraceODBC(3, "SQLGetDiagRecW", retcode);
if ((retcode == ODBC32.RetCode.SUCCESS) || (retcode == ODBC32.RetCode.SUCCESS_WITH_INFO)) {
sqlState = sb.ToString();
}
else {
sqlState = ADP.StrEmpty;
}
return retcode;
}
}
sealed internal class OdbcDescriptorHandle : OdbcHandle {
internal OdbcDescriptorHandle(OdbcStatementHandle statementHandle, ODBC32.SQL_ATTR attribute) : base(statementHandle, attribute) {
}
internal ODBC32.RetCode GetDescriptionField(int i, ODBC32.SQL_DESC attribute, CNativeBuffer buffer, out int numericAttribute) {
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetDescFieldW(this, checked((short)i), attribute, buffer, buffer.ShortLength, out numericAttribute);
ODBC.TraceODBC(3, "SQLGetDescFieldW", retcode);
return retcode;
}
internal ODBC32.RetCode SetDescriptionField1(short ordinal, ODBC32.SQL_DESC type, IntPtr value) {
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLSetDescFieldW(this, ordinal, type, value, 0);
ODBC.TraceODBC(3, "SQLSetDescFieldW", retcode);
return retcode;
}
internal ODBC32.RetCode SetDescriptionField2(short ordinal, ODBC32.SQL_DESC type, HandleRef value) {
ODBC32.RetCode retcode = UnsafeNativeMethods.SQLSetDescFieldW(this, ordinal, type, value, 0);
ODBC.TraceODBC(3, "SQLSetDescFieldW", retcode);
return retcode;
}
}
}

Some files were not shown because too many files have changed in this diff Show More