Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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;
        }
Пример #4
0
        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);
        }
Пример #5
0
 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);
 }
Пример #6
0
        // 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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
            }
        }
Пример #9
0
        // 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) !;
                        }
                    }
                }
            }
        }
Пример #10
0
        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);
        }
Пример #11
0
 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);
 }
Пример #12
0
 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);
 }
Пример #13
0
        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);
        }
Пример #14
0
        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);
        }
Пример #15
0
 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);
 }
Пример #16
0
 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);
 }
Пример #17
0
        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);
        }
Пример #18
0
 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);
 }
Пример #19
0
        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;
            }
        }
Пример #20
0
        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);
        }
Пример #21
0
        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);
        }
Пример #22
0
        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);
        }
Пример #23
0
        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();
                }
            }
        }
Пример #24
0
        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);
        }
Пример #25
0
        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);
        }
Пример #26
0
 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);
 }
Пример #27
0
        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);
        }
Пример #28
0
 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);
 }
Пример #29
0
        // 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());
        }
Пример #30
0
 internal static void TraceODBC(int level, string method, ODBC32.SQLRETURN retcode)
 {
 }