RETCODE SQL_API SQLGetDiagRec ( SQLSMALLINT pHandleType, SQLHANDLE pHandle, SQLSMALLINT pRecNum, SQLCHAR* pSqlstate, SQLINTEGER* pNativeErrorPtr, SQLCHAR* pMsgTxtPtr, SQLSMALLINT pMsgTxtSize, SQLSMALLINT* pMsgTxtSizePtr ) { __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLGetDiagRec called, HandleType: %d, RecNum: %d, BufLen: %d", pHandleType, pRecNum, pMsgTxtSize ) ); pODBCDiag diag; pODBCDiagRow diagrow; __CHK_HANDLE ( pHandle, pHandleType, SQL_ERROR ); diag = _SQLGetDiagHandle ( pHandleType, pHandle ); if ( !diag ) { return SQL_ERROR; } // now get the desired diag row if ( ( diagrow = _SQLGetDiagRowX ( diag, pRecNum ) ) == NULL ) { return SQL_NO_DATA; } // sql-state if ( pSqlstate ) { strcpy ( ( char* ) pSqlstate, diagrow->State ); } // native error code if ( pNativeErrorPtr ) { ( *pNativeErrorPtr ) = diagrow->NativeErrorCode; } // msg _SQLCopyCharData ( diag, pMsgTxtPtr, pMsgTxtSize, pMsgTxtSizePtr, 16, diagrow->Msg, -1 ); // debug __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLGetDiagRec msg: %s", pMsgTxtPtr ? ( StrPtr ) pMsgTxtPtr : "(unknown)" ) ); return ( pMsgTxtSizePtr && ( *pMsgTxtSizePtr ) > pMsgTxtSize ) ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS; }
RETCODE SQL_API SQLGetCursorName ( SQLHSTMT pStmt, SQLCHAR* pDataPtr, SQLSMALLINT pDataSize, SQLSMALLINT* pDataSizePtr ) { __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLGetCursorName called" ) ); __CHK_HANDLE ( pStmt, SQL_HANDLE_STMT, SQL_ERROR ); _SQLFreeDiag ( _DIAGSTMT ( pStmt ) ); _SQLCopyCharData ( _DIAGSTMT ( pStmt ), pDataPtr, pDataSize, pDataSizePtr, 32, "default", -1 ); return SQL_SUCCESS; }
RETCODE SQL_API SQLGetDiagField ( SQLSMALLINT pHandleType, SQLHANDLE pHandle, SQLSMALLINT pRecNum, SQLSMALLINT pFldID, SQLPOINTER pDataPtr, SQLSMALLINT pDataSize, SQLSMALLINT* pDataSizePtr ) { __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLGetDiagField called, HandleType: %d, RecNum: %d, InfoType: %d, BufLen: %d", pHandleType, pRecNum, pFldID, pDataSize ) ); bool c; pODBCDiag diag; pODBCDiagRow diagrow; SQLSMALLINT dummySize = 0;//used when pDataSizePtr is NULL if ( pDataSizePtr == NULL ) { pDataSizePtr = &dummySize; } __CHK_HANDLE ( pHandle, pHandleType, SQL_ERROR ); diag = _SQLGetDiagHandle ( pHandleType, pHandle ); if ( !diag ) { return SQL_ERROR; } // field may be in diag header c = FALSE; // check the field type - header fields switch ( pFldID ) { case SQL_DIAG_CURSOR_ROW_COUNT: case SQL_DIAG_ROW_COUNT: // rows affected by update/insert if ( pHandleType == SQL_HANDLE_STMT ) { if ( pDataPtr ) { * ( ( SQLLEN* ) pDataPtr ) = ( pHandle ) ? ( ( pODBCStmt ) pHandle )->RowCount : 0; } return SQL_SUCCESS; } else { return SQL_ERROR; } case SQL_DIAG_DYNAMIC_FUNCTION: if ( pHandleType == SQL_HANDLE_STMT ) { unique_ptr<char[]> p ( wchar2char ( ( ( pODBCStmt ) pHandle )->Stmt ) ); _SQLCopyCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, p.get(), ( ( pODBCStmt ) pHandle )->StmtLen ); return SQL_SUCCESS; } else { return SQL_ERROR; } return SQL_ERROR; case SQL_DIAG_DYNAMIC_FUNCTION_CODE: if ( pHandleType == SQL_HANDLE_STMT ) { if ( pDataPtr ) { * ( ( StrPtr ) pDataPtr ) = 1; } // ??? debug test only unique_ptr<char[]> p ( wchar2char ( ( ( pODBCStmt ) pHandle )->Stmt ) ); _SQLCopyCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, p.get(), ( ( ( pODBCStmt ) pHandle )->StmtLen ) ); return SQL_SUCCESS; } else { return SQL_ERROR; } case SQL_DIAG_NUMBER: { // number of rows in diag Word i; // check if there r any diag rows if ( diag->DiagRows ) { // loop to count the rows for ( i = 1, diagrow = diag->DiagRows; diagrow != NULL; diagrow = diagrow->Next, i ++ ); if ( pDataPtr ) { * ( ( Word* ) pDataPtr ) = i; } } else if ( pDataPtr ) { * ( ( Word* ) pDataPtr ) = 0; } return SQL_SUCCESS; } break; default: c = TRUE; } // check if only a header field was required if ( c == FALSE ) { return SQL_SUCCESS; } // check row and buffer if ( pRecNum <= 0 || pDataSize < 0 ) { __ODBCPOPMSG ( _ODBCPopMsg ( "GetDiagField xxx1" ) ); return SQL_ERROR; } // now get the desired row first if ( ( diagrow = _SQLGetDiagRowX ( diag, pRecNum ) ) == NULL ) { return SQL_NO_DATA; } // now set info as per the field required switch ( pFldID ) { case SQL_DIAG_CLASS_ORIGIN: _SQLCopyCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, "ODBC 3.0", -1 ); break; case SQL_DIAG_COLUMN_NUMBER: // needs to be implemented if ( pDataPtr ) { * ( ( Long* ) pDataPtr ) = diagrow->Col; } break; case SQL_DIAG_CONNECTION_NAME: if ( pDataPtr ) { * ( ( char* ) pDataPtr ) = 0; } if ( pDataSizePtr ) { *pDataSizePtr = 0; } break; case SQL_DIAG_MESSAGE_TEXT: return _SQLCopyCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, diagrow->Msg, -1 ); case SQL_DIAG_NATIVE: if ( pDataPtr ) { * ( ( Long* ) pDataPtr ) = diagrow->NativeErrorCode; } if ( pDataSizePtr ) { *pDataSizePtr = 0; } break; case SQL_DIAG_ROW_NUMBER: // needs to be implemented if ( pDataPtr ) { * ( ( Long* ) pDataPtr ) = diagrow->Row; } break; case SQL_DIAG_SERVER_NAME: { CStrPtr svr; // if handle type is connection if ( pHandleType == SQL_HANDLE_DBC ) { svr = ( ( pODBCConn ) pHandle )->Server; } else if ( pHandleType == SQL_HANDLE_STMT && ( ( pODBCStmt ) pHandle )->Conn ) { svr = ( ( pODBCStmt ) pHandle )->Conn->Server; } else { svr = ""; } return _SQLCopyCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, svr, -1 ); } case SQL_DIAG_SQLSTATE: return _SQLCopyCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, diagrow->State, -1 ); case SQL_DIAG_SUBCLASS_ORIGIN: // ??? dummy return _SQLCopyCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, diagrow->State, -1 ); default: __ODBCPOPMSG ( _ODBCPopMsg ( "SQLGetDiagField called, HandleType: %d, RecNum: %d, InfoType: %d, BufLen: %d", pHandleType, pRecNum, pFldID, pDataSize ) ); return SQL_ERROR; } return SQL_SUCCESS; }
//mhb TODO, check if the sqltype defined here match from c# RETCODE SQL_API _SQLColConvert ( pODBCStmt pStmt, void* pTgtDataPtr, Long* pTgtDataSizePtr, const wchar_t* pSrcColData, pARDItem pARDCol, bool isSigned ) { //check out this for SQL data type to C data type mapping //http://msdn.microsoft.com/en-us/library/ms714556(v=vs.85).aspx // note // this function actually determines the conversion // required to transfer the data Word pSrcDataType = pARDCol->SrcDataType; Word pTgtDataType = pARDCol->DataConciseType; Long pTgtDataSize = pARDCol->DataSize; __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "_SQLColConvert called" ) ); __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "The SrcDataType is %d, the TgtDataType is %d, the TgtDataSize is %d", pSrcDataType, pTgtDataType, pTgtDataSize ) ); // TARGET TYPE IS LEFT TO OUR DRIVER // check if target type is open if ( pTgtDataType == SQL_DEFAULT ) { __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "pTgtDataType is SQL_DEFAULT, use default type mapping." ) ); // determine targettype based on data-source type // check out this http://msdn.microsoft.com/en-us/library/ms716298(v=vs.85).aspx for default type mapping switch ( pSrcDataType ) { case SQL_CHAR: pTgtDataType = SQL_C_CHAR; break; case SQL_VARCHAR: pTgtDataType = SQL_C_CHAR; break; case SQL_WCHAR: pTgtDataType = SQL_C_WCHAR; break; case SQL_WVARCHAR: pTgtDataType = SQL_C_WCHAR; break; case SQL_DECIMAL: pTgtDataType = SQL_C_CHAR; break; case SQL_BIT: pTgtDataType = SQL_C_BIT; break; case SQL_TINYINT: if ( isSigned ) { pTgtDataType = SQL_C_STINYINT; } else { pTgtDataType = SQL_C_UTINYINT; } break; case SQL_SMALLINT: if ( isSigned ) { pTgtDataType = SQL_C_SSHORT; } else { pTgtDataType = SQL_C_USHORT; } break; case SQL_INTEGER: if ( isSigned ) { pTgtDataType = SQL_C_SLONG; } else { pTgtDataType = SQL_C_ULONG; } break; case SQL_BIGINT: if ( isSigned ) { pTgtDataType = SQL_C_SBIGINT; } else { pTgtDataType = SQL_C_UBIGINT; } break; case SQL_FLOAT: pTgtDataType = SQL_C_FLOAT; break; case SQL_DOUBLE: pTgtDataType = SQL_C_DOUBLE; break; case SQL_TYPE_DATE: pTgtDataType = SQL_C_CHAR; break; case SQL_TYPE_TIME: pTgtDataType = SQL_C_CHAR; break; case SQL_TYPE_TIMESTAMP: pTgtDataType = SQL_C_CHAR; break; //case SQL_C_SLONG: //case SQL_C_ULONG: // unsigned long //case SQL_C_USHORT: //case SQL_C_SSHORT: //case SQL_NUMERIC: //case SQL_REAL: // pTgtDataType = pSrcDataType; // break; default: __ODBCPOPMSG ( _ODBCPopMsg ( "The data type %d not implemented", pSrcDataType ) ); return SQL_ERROR; break; } } else { __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "pTgtDataType is NOT SQL_DEFAULT, it is %d", pTgtDataType ) ); } // TARGET TYPE IS CHAR // as an optimization, check if the application // or target data type is char. since the data from // server is already in char format. the data can // easily be transferred without incurring any // conversion overhead unique_ptr<char[]> pTextInAnsi ( wchar2char ( pSrcColData ) ); // check if char type if ( pTgtDataType == SQL_CHAR || pTgtDataType == SQL_VARCHAR ) { // only in case of src data being bool a conversion is required if ( pSrcDataType == SQL_BIT ) { // prepare a converted single char bool string Char src[2]; if ( pTextInAnsi.get() == NULL ) { src[0] = '0'; } else { src[0] = ( pTextInAnsi.get() [0] == 'T' || pTextInAnsi.get() [0] == '1' || pTextInAnsi.get() [0] == 't' ) ? '1' : '0'; } src[1] = 0; // transfer the bool string return _SQLCopyCharData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pARDCol->DataSize, pTgtDataSizePtr, 32, src, -1 ); } else { // transfer the string as it is return _SQLCopyCharData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pARDCol->DataSize, pTgtDataSizePtr, 32, pTextInAnsi.get(), -1 ); } } if ( pTgtDataType == SQL_WCHAR || pTgtDataType == SQL_WVARCHAR ) { return _SQLCopyWCharDataW ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pARDCol->DataSize, pTgtDataSizePtr, 32, pSrcColData, -1 ); } // TARGET TYPE IS NOT CHAR // try using a numeric conversion switch ( _SQLCopyNumData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pTgtDataType, pTextInAnsi.get(), pSrcDataType , pTgtDataSizePtr ) ) { case -1: return SQL_ERROR; case 0: return SQL_SUCCESS; default: break; } // try using a date/time conversion switch ( _SQLCopyDateTimeData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pTgtDataType, pTextInAnsi.get(), pSrcDataType ) ) { case -1: return SQL_ERROR; case 0: return SQL_SUCCESS; default: break; } // try using SQL_BIT data type ie bool if ( pTgtDataType == SQL_BIT ) { __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "the target data type is SQL_C_BIT" ) ); // prepare a converted single char bool string if ( pTextInAnsi.get() == NULL ) { * ( ( char* ) pTgtDataPtr ) = 0; } else { * ( ( char* ) pTgtDataPtr ) = ( pTextInAnsi.get() [0] == 'T' || pTextInAnsi.get() [0] == '1' || pTextInAnsi.get() [0] == 't' ) ? 1 : 0; } return SQL_SUCCESS; } // error condition __ODBCPOPMSG ( _ODBCPopMsg ( "_SQLColConvert - Unknown data type, Target: %d, Source: %d", pTgtDataType, pSrcDataType ) ); _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "_SQLColConvert", "01000", -1, "Unknown data type, Target: %d, Source: %d", pTgtDataType, pSrcDataType ); return SQL_ERROR; }
RETCODE SQL_API SQLGetConnectAttr ( SQLHDBC pConn, SQLINTEGER pAttr, SQLPOINTER pDataPtr, SQLINTEGER pDataSize, SQLINTEGER* pDataSizePtr ) { __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLGetConnectAttr, Attr: %d, DataPtr: %d, DataSize: %d", pAttr, pDataPtr, pDataSize ) ); __CHK_HANDLE ( pConn, SQL_HANDLE_DBC, SQL_ERROR ); _SQLFreeDiag ( _DIAGCONN ( pConn ) ); switch ( pAttr ) { case SQL_ATTR_ACCESS_MODE : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> AccessMode; break; case SQL_ATTR_ASYNC_ENABLE : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> AsyncEnable; break; case SQL_ATTR_AUTO_IPD : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> AutoIPD; break; case SQL_ATTR_AUTOCOMMIT : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> AutoCommit; break; case SQL_ATTR_CONNECTION_DEAD : * ( ( ULong* ) pDataPtr ) = SQL_CD_TRUE ; break; case SQL_ATTR_CONNECTION_TIMEOUT : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> TimeOut; break; case SQL_ATTR_CURRENT_CATALOG : // current database return _SQLCopyCharData ( _DIAGCONN ( pConn ), pDataPtr, pDataSize, pDataSizePtr, 32, "default", -1 ); case SQL_ATTR_LOGIN_TIMEOUT : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> LoginTimeOut; break; case SQL_ATTR_METADATA_ID : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> MetaDataID; break; case SQL_ATTR_ODBC_CURSORS : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> ODBCCursors; break; case SQL_ATTR_PACKET_SIZE : return SQL_ERROR; // not a typical option case SQL_ATTR_QUIET_MODE : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> Window; break; case SQL_ATTR_TRACE : // basically for driver manager break; case SQL_ATTR_TRACEFILE : // basically for driver manager break; case SQL_ATTR_TRANSLATE_LIB : // not implemented break; case SQL_ATTR_TRANSLATE_OPTION : // not implemented break; case SQL_ATTR_TXN_ISOLATION : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> TxnIsolation; break; case SQL_ATTR_MAX_ROWS : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> MaxRows; break; case SQL_ATTR_QUERY_TIMEOUT : * ( ( ULong* ) pDataPtr ) = ( ( pODBCConn ) pConn ) -> QueryTimeout; break; default : __ODBCPOPMSG ( _ODBCPopMsg ( "SQLGetConnectAttr not recognized, Attr: %d, DataPtr: %d, DataSize: %d", pAttr, pDataPtr, pDataSize ) ); return SQL_SUCCESS; } return SQL_SUCCESS; }