internal ODBC32.SQLRETURN 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.SQLRETURN retcode = Interop.Odbc.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.SQLRETURN.SUCCESS) || (retcode == ODBC32.SQLRETURN.SUCCESS_WITH_INFO)) { sqlState = sb.ToString(); } else { sqlState = string.Empty; } return(retcode); }
internal string GetConnectAttrString(ODBC32.SQL_ATTR attribute) { string value = ""; int cbActual; byte[] buffer = new byte[100]; OdbcConnectionHandle?connectionHandle = ConnectionHandle; if (null != connectionHandle) { ODBC32.SQLRETURN retcode = connectionHandle.GetConnectionAttribute(attribute, buffer, out cbActual); if (buffer.Length + 2 <= cbActual) { // 2 bytes for unicode null-termination character // retry with cbActual because original buffer was too small buffer = new byte[cbActual + 2]; retcode = connectionHandle.GetConnectionAttribute(attribute, buffer, out cbActual); } if ((ODBC32.SQLRETURN.SUCCESS == retcode) || (ODBC32.SQLRETURN.SUCCESS_WITH_INFO == retcode)) { value = (BitConverter.IsLittleEndian ? Encoding.Unicode : Encoding.BigEndianUnicode).GetString(buffer, 0, Math.Min(cbActual, buffer.Length)); } else if (retcode == ODBC32.SQLRETURN.ERROR) { string sqlstate = GetDiagSqlState(); if (("HYC00" == sqlstate) || ("HY092" == sqlstate) || ("IM001" == sqlstate)) { FlagUnsupportedConnectAttr(attribute); } // not throwing errors if not supported or other failure } } return(value); }
public override void Commit() { OdbcConnection?connection = _connection; if (null == connection) { throw ADP.TransactionZombied(this); } connection.CheckState(ADP.CommitTransaction); // MDAC 68289 //Note: SQLEndTran success if not actually in a transaction, so we have to throw //since the IDbTransaction spec indicates this is an error for the managed packages if (null == _handle) { throw ODBC.NotInTransaction(); } ODBC32.SQLRETURN retcode = _handle.CompleteTransaction(ODBC32.SQL_COMMIT); if (retcode == ODBC32.SQLRETURN.ERROR) { //If an error has occurred, we will throw an exception in HandleError, //and leave the transaction active for the user to retry connection.HandleError(_handle, retcode); } //Transaction is complete... connection.LocalTransaction = null; _connection = null; _handle = null; }
internal int GetConnectAttr(ODBC32.SQL_ATTR attribute, ODBC32.HANDLER handler) { int retval = -1; byte[] buffer = new byte[4]; OdbcConnectionHandle?connectionHandle = ConnectionHandle; if (null != connectionHandle) { ODBC32.SQLRETURN retcode = connectionHandle.GetConnectionAttribute(attribute, buffer, out _); if ((ODBC32.SQLRETURN.SUCCESS == retcode) || (ODBC32.SQLRETURN.SUCCESS_WITH_INFO == retcode)) { retval = BitConverter.ToInt32(buffer, 0); } else { if (retcode == ODBC32.SQLRETURN.ERROR) { string sqlstate = GetDiagSqlState(); if (("HYC00" == sqlstate) || ("HY092" == sqlstate) || ("IM001" == sqlstate)) { FlagUnsupportedConnectAttr(attribute); } } if (handler == ODBC32.HANDLER.THROW) { this.HandleError(connectionHandle, retcode); } } } return(retval); }
internal ODBC32.SQLRETURN GetInfoInt32Unhandled(ODBC32.SQL_INFO info, out int resultValue) { byte[] buffer = new byte[4]; ODBC32.SQLRETURN retcode = ConnectionHandle !.GetInfo1(info, buffer); resultValue = BitConverter.ToInt32(buffer, 0); return(retcode); }
// non-throwing HandleError internal Exception?HandleErrorNoThrow(OdbcHandle hrHandle, ODBC32.SQLRETURN retcode) { Debug.Assert(retcode != ODBC32.SQLRETURN.INVALID_HANDLE, "retcode must never be ODBC32.RetCode.INVALID_HANDLE"); switch (retcode) { case ODBC32.SQLRETURN.SUCCESS: break; case ODBC32.SQLRETURN.SUCCESS_WITH_INFO: { //Optimize to only create the event objects and obtain error info if //the user is really interested in retrieveing the events... if (_infoMessageEventHandler != null) { OdbcErrorCollection errors = ODBC32.GetDiagErrors(null, hrHandle, retcode); errors.SetSource(this.Driver); OnInfoMessage(new OdbcInfoMessageEventArgs(errors)); } break; } default: OdbcException e = OdbcException.CreateException(ODBC32.GetDiagErrors(null, hrHandle, retcode), retcode); if (e != null) { e.Errors.SetSource(this.Driver); } ConnectionIsAlive(e); // this will close and throw if the connection is dead return(e); } return(null); }
private string?GetInfoStringUnhandled(ODBC32.SQL_INFO info, bool handleError) { //SQLGetInfo string?value = null; short cbActual; byte[] buffer = new byte[100]; OdbcConnectionHandle?connectionHandle = ConnectionHandle; if (null != connectionHandle) { ODBC32.SQLRETURN retcode = connectionHandle.GetInfo2(info, buffer, out cbActual); if (buffer.Length < cbActual - 2) { // 2 bytes for unicode null-termination character // retry with cbActual because original buffer was too small buffer = new byte[cbActual + 2]; retcode = connectionHandle.GetInfo2(info, buffer, out cbActual); } if (retcode == ODBC32.SQLRETURN.SUCCESS || retcode == ODBC32.SQLRETURN.SUCCESS_WITH_INFO) { value = (BitConverter.IsLittleEndian ? Encoding.Unicode : Encoding.BigEndianUnicode).GetString(buffer, 0, Math.Min(cbActual, buffer.Length)); } else if (handleError) { this.HandleError(connectionHandle, retcode); } } else if (handleError) { value = ""; } return(value); }
internal void Open_ChangeDatabase(string value) { CheckState(ADP.ChangeDatabase); // Database name must not be null, empty or whitspace if (string.IsNullOrWhiteSpace(value)) { // MDAC 62679 throw ADP.EmptyDatabaseName(); } if (1024 < value.Length * 2 + 2) { throw ADP.DatabaseNameTooLong(); } RollbackDeadTransaction(); //Set the database OdbcConnectionHandle connectionHandle = ConnectionHandle !; ODBC32.SQLRETURN retcode = connectionHandle.SetConnectionAttribute3(ODBC32.SQL_ATTR.CURRENT_CATALOG, value, checked ((int)value.Length * 2)); if (retcode != ODBC32.SQLRETURN.SUCCESS) { HandleError(connectionHandle, retcode); } }
// OdbcCommand.Cancel() // // In ODBC3.0 ... a call to SQLCancel when no processing is done has no effect at all // (ODBC Programmer's Reference ...) // public override void Cancel() { CMDWrapper?wrapper = _cmdWrapper; if (null != wrapper) { wrapper.Canceling = true; OdbcStatementHandle?stmt = wrapper.StatementHandle; if (null != stmt) { lock (stmt) { // Cancel the statement ODBC32.SQLRETURN retcode = stmt.Cancel(); // copy of StatementErrorHandler, because stmt may become null switch (retcode) { case ODBC32.SQLRETURN.SUCCESS: case ODBC32.SQLRETURN.SUCCESS_WITH_INFO: // don't fire info message events on cancel break; default: throw wrapper.Connection.HandleErrorNoThrow(stmt, retcode) !; } } } } }
private ODBC32.SQLRETURN CompleteTransaction(short transactionOperation, IntPtr handle) { // must only call this code from ReleaseHandle or DangerousAddRef region ODBC32.SQLRETURN retcode = ODBC32.SQLRETURN.SUCCESS; try { } finally { if (HandleState.TransactionInProgress == _handleState) { retcode = Interop.Odbc.SQLEndTran(HandleType, handle, transactionOperation); if ((ODBC32.SQLRETURN.SUCCESS == retcode) || (ODBC32.SQLRETURN.SUCCESS_WITH_INFO == retcode)) { _handleState = HandleState.Transacted; } } if (HandleState.Transacted == _handleState) { // AutoCommitOn retcode = Interop.Odbc.SQLSetConnectAttrW(handle, ODBC32.SQL_ATTR.AUTOCOMMIT, ODBC32.SQL_AUTOCOMMIT_ON, (int)ODBC32.SQL_IS.UINTEGER); _handleState = HandleState.Connected; } } //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); }
internal ODBC32.SQLRETURN Cancel() { // In ODBC3.0 ... a call to SQLCancel when no processing is done has no effect at all // (ODBC Programmer's Reference ...) ODBC32.SQLRETURN retcode = Interop.Odbc.SQLCancel(this); ODBC.TraceODBC(3, "SQLCancel", retcode); return(retcode); }
internal ODBC32.SQLRETURN SpecialColumns(string quotedTable) { ODBC32.SQLRETURN retcode = Interop.Odbc.SQLSpecialColumnsW(this, ODBC32.SQL_SPECIALCOLS.ROWVER, null, 0, null, 0, quotedTable, ODBC.ShortStringLength(quotedTable), ODBC32.SQL_SCOPE.SESSION, ODBC32.SQL_NULLABILITY.NO_NULLS); ODBC.TraceODBC(3, "SQLSpecialColumnsW", retcode); return(retcode); }
internal ODBC32.SQLRETURN RowCount(out SQLLEN rowCount) { IntPtr result; ODBC32.SQLRETURN retcode = Interop.Odbc.SQLRowCount(this, out result); rowCount = new SQLLEN(result); ODBC.TraceODBC(3, "SQLRowCount", retcode); return(retcode); }
internal ODBC32.SQLRETURN ColumnAttribute(int columnNumber, short fieldIdentifier, CNativeBuffer characterAttribute, out short stringLength, out SQLLEN numericAttribute) { IntPtr result; ODBC32.SQLRETURN retcode = Interop.Odbc.SQLColAttributeW(this, checked ((short)columnNumber), fieldIdentifier, characterAttribute, characterAttribute.ShortLength, out stringLength, out result); numericAttribute = new SQLLEN(result); ODBC.TraceODBC(3, "SQLColAttributeW", retcode); return(retcode); }
internal ODBC32.SQLRETURN PrimaryKeys(string?catalogName, string?schemaName, string tableName) { ODBC32.SQLRETURN retcode = Interop.Odbc.SQLPrimaryKeysW(this, catalogName, ODBC.ShortStringLength(catalogName), // CatalogName schemaName, ODBC.ShortStringLength(schemaName), // SchemaName tableName, ODBC.ShortStringLength(tableName) // TableName ); ODBC.TraceODBC(3, "SQLPrimaryKeysW", retcode); return(retcode); }
internal ODBC32.SQLRETURN GetData(int index, ODBC32.SQL_C sqlctype, CNativeBuffer buffer, int cb, out IntPtr cbActual) { ODBC32.SQLRETURN retcode = Interop.Odbc.SQLGetData(this, checked ((ushort)index), sqlctype, buffer, new IntPtr(cb), out cbActual); ODBC.TraceODBC(3, "SQLGetData", retcode); return(retcode); }
internal ODBC32.SQLRETURN Procedures(string procedureCatalog, string procedureSchema, string procedureName) { ODBC32.SQLRETURN retcode = Interop.Odbc.SQLProceduresW(this, procedureCatalog, ODBC.ShortStringLength(procedureCatalog), procedureSchema, ODBC.ShortStringLength(procedureSchema), procedureName, ODBC.ShortStringLength(procedureName)); ODBC.TraceODBC(3, "SQLProceduresW", retcode); return(retcode); }
internal ODBC32.SQLRETURN BindParameter(short ordinal, short parameterDirection, ODBC32.SQL_C sqlctype, ODBC32.SQL_TYPE sqltype, IntPtr cchSize, IntPtr scale, HandleRef buffer, IntPtr bufferLength, HandleRef intbuffer) { ODBC32.SQLRETURN retcode = Interop.Odbc.SQLBindParameter(this, checked ((ushort)ordinal), // Parameter Number parameterDirection, // InputOutputType sqlctype, // ValueType checked ((short)sqltype), // ParameterType cchSize, // ColumnSize scale, // DecimalDigits buffer, // ParameterValuePtr bufferLength, // BufferLength intbuffer); // StrLen_or_IndPtr ODBC.TraceODBC(3, "SQLBindParameter", retcode); return(retcode); }
internal void HandleError(OdbcHandle hrHandle, ODBC32.SQLRETURN retcode) { Exception?e = HandleErrorNoThrow(hrHandle, retcode); switch (retcode) { case ODBC32.SQLRETURN.SUCCESS: case ODBC32.SQLRETURN.SUCCESS_WITH_INFO: Debug.Assert(null == e, "success exception"); break; default: Debug.Assert(null != e, "failure without exception"); throw e; } }
internal static OdbcException CreateException(OdbcErrorCollection errors, ODBC32.SQLRETURN retcode) { StringBuilder builder = new StringBuilder(); foreach (OdbcError error in errors) { if (builder.Length > 0) { builder.Append(Environment.NewLine); } builder.Append(SR.GetString(SR.Odbc_ExceptionMessage, ODBC32.RetcodeToString(retcode), error.SQLState, error.Message)); // MDAC 68337 } OdbcException exception = new OdbcException(builder.ToString(), errors); return(exception); }
internal ODBC32.SQLRETURN 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.SQLRETURN retcode = Interop.Odbc.SQLGetDiagRecW(HandleType, this, record, sb, out nativeError, message, checked ((short)message.Capacity), out cchActual); ODBC.TraceODBC(3, "SQLGetDiagRecW", retcode); if ((retcode == ODBC32.SQLRETURN.SUCCESS) || (retcode == ODBC32.SQLRETURN.SUCCESS_WITH_INFO)) { sqlState = sb.ToString(); } else { sqlState = string.Empty; } return(retcode); }
internal ODBC32.SQLRETURN Tables(string tableCatalog, string tableSchema, string tableName, string tableType) { ODBC32.SQLRETURN retcode = Interop.Odbc.SQLTablesW(this, tableCatalog, ODBC.ShortStringLength(tableCatalog), tableSchema, ODBC.ShortStringLength(tableSchema), tableName, ODBC.ShortStringLength(tableName), tableType, ODBC.ShortStringLength(tableType)); ODBC.TraceODBC(3, "SQLTablesW", retcode); return(retcode); }
internal ODBC32.SQLRETURN CompleteTransaction(short transactionOperation) { bool mustRelease = false; try { DangerousAddRef(ref mustRelease); ODBC32.SQLRETURN retcode = CompleteTransaction(transactionOperation, base.handle); return(retcode); } finally { if (mustRelease) { DangerousRelease(); } } }
internal OdbcTransaction Open_BeginTransaction(IsolationLevel isolevel) { CheckState(ADP.BeginTransaction); // MDAC 68323 RollbackDeadTransaction(); if ((null != _weakTransaction) && _weakTransaction.IsAlive) { // regression from Dispose/Finalize work throw ADP.ParallelTransactionsNotSupported(this); } //Use the default for unspecified. switch (isolevel) { case IsolationLevel.Unspecified: case IsolationLevel.ReadUncommitted: case IsolationLevel.ReadCommitted: case IsolationLevel.RepeatableRead: case IsolationLevel.Serializable: case IsolationLevel.Snapshot: break; case IsolationLevel.Chaos: throw ODBC.NotSupportedIsolationLevel(isolevel); default: throw ADP.InvalidIsolationLevel(isolevel); } ; //Start the transaction OdbcConnectionHandle connectionHandle = ConnectionHandle !; ODBC32.SQLRETURN retcode = connectionHandle.BeginTransaction(ref isolevel); if (retcode == ODBC32.SQLRETURN.ERROR) { HandleError(connectionHandle, retcode); } OdbcTransaction transaction = new OdbcTransaction(this, isolevel, connectionHandle); _weakTransaction = new WeakReference(transaction); // MDAC 69188 return(transaction); }
internal ODBC32.SQLRETURN GetDiagnosticRecord(short record, out string sqlState, StringBuilder messageBuilder, out int nativeError, out short cchActual) { // ODBC (MSDN) documents it expects a buffer large enough to hold 4(+L'\0') unicode characters char[] buffer = new char[5]; char[] message = new char[1024]; ODBC32.SQLRETURN retcode = Interop.Odbc.SQLGetDiagRecW(HandleType, this, record, buffer, out nativeError, message, checked ((short)message.Length), out cchActual); ODBC.TraceODBC(3, "SQLGetDiagRecW", retcode); if ((retcode == ODBC32.SQLRETURN.SUCCESS) || (retcode == ODBC32.SQLRETURN.SUCCESS_WITH_INFO)) { sqlState = new string(buffer.AsSpan().Slice(0, buffer.AsSpan().IndexOf('\0'))); } else { sqlState = string.Empty; } messageBuilder.Append(new string(message.AsSpan().Slice(0, message.AsSpan().IndexOf('\0')))); return(retcode); }
protected override void Dispose(bool disposing) { if (disposing) { OdbcConnectionHandle?handle = _handle; _handle = null; if (null != handle) { try { ODBC32.SQLRETURN retcode = handle.CompleteTransaction(ODBC32.SQL_ROLLBACK); if (retcode == ODBC32.SQLRETURN.ERROR) { //don't throw an exception here, but trace it so it can be logged if (_connection != null) { Exception e = _connection.HandleErrorNoThrow(handle, retcode) !; ADP.TraceExceptionWithoutRethrow(e); } } } catch (Exception e) { // if (!ADP.IsCatchableExceptionType(e)) { throw; } } } if (_connection != null) { if (_connection.IsOpen) { _connection.LocalTransaction = null; } } _connection = null; _isolevel = IsolationLevel.Unspecified; } base.Dispose(disposing); }
internal ODBC32.SQLRETURN GetDiagnosticRecord(short record, out string sqlState, StringBuilder messageBuilder, out int nativeError, out short cchActual) { // SQLGetDiagRecW expects a buffer large enough to hold a five-character state code plus a null-terminator // See https://docs.microsoft.com/sql/odbc/reference/syntax/sqlgetdiagrec-function char[] buffer = new char[6]; char[] message = new char[1024]; ODBC32.SQLRETURN retcode = Interop.Odbc.SQLGetDiagRecW(HandleType, this, record, buffer, out nativeError, message, checked ((short)message.Length), out cchActual); ODBC.TraceODBC(3, "SQLGetDiagRecW", retcode); if ((retcode == ODBC32.SQLRETURN.SUCCESS) || (retcode == ODBC32.SQLRETURN.SUCCESS_WITH_INFO)) { sqlState = new string(buffer.AsSpan().Slice(0, buffer.AsSpan().IndexOf('\0'))); } else { sqlState = string.Empty; } messageBuilder.Append(new string(message.AsSpan().Slice(0, message.AsSpan().IndexOf('\0')))); return(retcode); }
internal ODBC32.SQLRETURN GetDiagnosticField(out string sqlState) { // ODBC (MSDN) documents it expects a buffer large enough to hold 5(+L'\0') unicode characters char[] buffer = new char[6]; ODBC32.SQLRETURN retcode = Interop.Odbc.SQLGetDiagFieldW( HandleType, this, (short)1, ODBC32.SQL_DIAG_SQLSTATE, buffer, checked ((short)(2 * buffer.Length)), // expects number of bytes, see \\kbinternal\kb\articles\294\1\69.HTM out _); ODBC.TraceODBC(3, "SQLGetDiagFieldW", retcode); if ((retcode == ODBC32.SQLRETURN.SUCCESS) || (retcode == ODBC32.SQLRETURN.SUCCESS_WITH_INFO)) { sqlState = new string(buffer.AsSpan().Slice(0, buffer.AsSpan().IndexOf('\0'))); } else { sqlState = string.Empty; } return(retcode); }
// DeriveParametersFromStoredProcedure ( // OdbcConnection connection, // OdbcCommand command); // // Uses SQLProcedureColumns to create an array of OdbcParameters // private static 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, SR.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.SQLRETURN 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.SQLRETURN.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.Fail("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()); }
internal static void TraceODBC(int level, string method, ODBC32.SQLRETURN retcode) { }