📄 vmodbcconnection.cpp
字号:
// Turn back on auto commit
//
nRetCode = ::SQLSetConnectOption( m_hdbc,
SQL_AUTOCOMMIT,
SQL_AUTOCOMMIT_ON );
return( bSuccess );
}
/* End of function "VMODBCConnection::Rollback"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::Check
DESCRIPTION: called to check the status of the current statement
INPUT: nRetCode - the return code to evaluate
OUTPUT: none
RETURNS: true if return code indicates success
*/
bool VMODBCConnection::Check( RETCODE nRetCode )
{
return( CheckHstmt( nRetCode, SQL_NULL_HSTMT ) );
}
/* End of function "VMODBCConnection::Check"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::CheckHstmt
DESCRIPTION: evaluates the given return code
INPUT: nRetCode - the return code to evaluate
hstmt - statement handle, not used
OUTPUT:
RETURNS: true if return code indicates success, false otherwise
*/
bool VMODBCConnection::CheckHstmt( RETCODE nRetCode, HSTMT hstmt )
{
switch ( nRetCode )
{
case SQL_SUCCESS_WITH_INFO:
case SQL_SUCCESS:
case SQL_NO_DATA_FOUND:
return( true );
break;
default:
GetErrorMessages( SQL_HANDLE_STMT, hstmt );
return( false );
break;
}
return( false );
}
/* End of function "VMODBCConnection::CheckHstmt"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::ReplaceBrackets
DESCRIPTION: called by record set classes to replace brackets embedded
in an sql string
INPUT: pchSQL - pointer to the string to operate on
OUTPUT: none
RETURNS: void
*/
void VMODBCConnection::ReplaceBrackets( LPTSTR lpchSQL )
{
BOOL bInLiteral = FALSE;
LPTSTR lpchNewSQL = lpchSQL;
while ( *lpchSQL != '\0' )
{
if ( *lpchSQL == cachLiteralSeparator )
{
// Handle escaped literal
//
if ( *_tcsinc( lpchSQL ) == cachLiteralSeparator )
{
*lpchNewSQL = *lpchSQL;
lpchSQL = _tcsinc( lpchSQL );
lpchNewSQL = _tcsinc(lpchNewSQL);
}
else
{
bInLiteral = !bInLiteral;
}
*lpchNewSQL = *lpchSQL;
}
else
if ( !bInLiteral && ( *lpchSQL == '[' ) )
{
if ( *_tcsinc( lpchSQL) == '[' )
{
// Handle escaped left bracket by inserting one '['
//
*lpchNewSQL = *lpchSQL;
lpchSQL = _tcsinc(lpchSQL);
}
else
{
*lpchNewSQL = m_chIDQuoteChar;
}
}
else
if ( !bInLiteral && ( *lpchSQL == ']' ) )
{
if ( *_tcsinc( lpchSQL ) == ']' )
{
// Handle escaped right bracket by inserting one ']'
//
*lpchNewSQL = *lpchSQL;
lpchSQL = _tcsinc(lpchSQL);
}
else
{
*lpchNewSQL = m_chIDQuoteChar;
}
}
else
{
*lpchNewSQL = *lpchSQL;
}
lpchSQL = _tcsinc( lpchSQL );
lpchNewSQL = _tcsinc( lpchNewSQL );
}
}
/* End of function "VMODBCConnection::ReplaceBrackets"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::AllocConnect
DESCRIPTION: allocates a connection handle and if needed, will allocate
an environment handle for the application
INPUT: dwOptions - options to apply against the connection handle
OUTPUT: none
RETURNS: void
*/
void VMODBCConnection::AllocConnect( DWORD dwOptions )
{
if ( m_hdbc != SQL_NULL_HDBC )
{
return;
}
RETCODE nRetCode;
if ( m_henvAllConnections == SQL_NULL_HENV )
{
assert( m_nAllocatedConnections == 0 );
// need to allocate an environment for first connection
//
nRetCode = ::SQLAllocEnv( &m_henvAllConnections );
if ( !Check( nRetCode ) )
{
throw new VMException( __FILE__, __LINE__, "SQLAllocEnv Failed.", VMException::fatal );
}
}
assert( m_henvAllConnections != SQL_NULL_HENV );
nRetCode = ::SQLAllocConnect( m_henvAllConnections, &m_hdbc );
if ( !Check( nRetCode ) )
{
GetErrorMessages( SQL_HANDLE_DBC, m_hdbc );
throw new VMException( __FILE__, __LINE__, "SQLAllocConnect Failed.", VMException::fatal );
}
m_nAllocatedConnections++;
nRetCode = ::SQLSetConnectOption( m_hdbc,
SQL_LOGIN_TIMEOUT,
m_dwLoginTimeout );
if ( !m_bUpdatable )
{
nRetCode = ::SQLSetConnectOption( m_hdbc,
SQL_ACCESS_MODE,
SQL_MODE_READ_ONLY );
}
// Turn on cursor lib support
//
if ( dwOptions & useCursorLib )
{
nRetCode = ::SQLSetConnectOption( m_hdbc,
SQL_ODBC_CURSORS,
SQL_CUR_USE_ODBC );
// With cursor library added records immediately in result set
//
m_bIncRecordCountOnAdd = true;
}
}
/* End of function "VMODBCConnection::AllocConnect"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::Connect
DESCRIPTION: connects to the dbms
INPUT: dwOptions - options to use for the connection
OUTPUT: none
RETURNS: true if worked, false if not
*/
bool VMODBCConnection::Connect( DWORD dwOptions )
{
HWND hWnd = ::GetDesktopWindow();
UCHAR szConnectOutput[ MAX_CONNECT_LEN ];
RETCODE nRetCode;
SWORD nResult;
UWORD wConnectOption = SQL_DRIVER_COMPLETE;
if ( dwOptions & noOdbcDialog )
{
wConnectOption = SQL_DRIVER_NOPROMPT;
}
else
if ( dwOptions & forceOdbcDialog )
{
wConnectOption = SQL_DRIVER_PROMPT;
}
nRetCode = ::SQLDriverConnect( m_hdbc,
hWnd,
(unsigned char*)(const char*)m_oConnect,
SQL_NTS,
szConnectOutput,
sizeof( szConnectOutput ),
&nResult,
wConnectOption );
VerifySQLConnect( nRetCode, __FILE__, __LINE__ );
// If user hit 'Cancel'
//
if ( nRetCode == SQL_NO_DATA_FOUND )
{
Free();
return( false );
}
if ( !Check( nRetCode ) )
{
GetErrorMessages( SQL_HANDLE_DBC, m_hdbc );
throw new VMException( __FILE__, __LINE__, "SQLDriverConnect Failed.", VMException::fatal );
}
// Connect strings must have "ODBC;"
//
m_oConnect = "ODBC;";
// Save connect string returned from ODBC
//
m_oConnect += (char*)szConnectOutput;
return( true );
}
/* End of function "VMODBCConnection::Connect"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::VerifyConnect
DESCRIPTION: verifies that the connection attempt worked and that the
connection if 'good'
INPUT: void
OUTPUT: none
RETURNS: void
*/
void VMODBCConnection::VerifyConnect( void )
{
RETCODE nRetCode;
SWORD nResult;
SWORD nAPIConformance;
nRetCode = ::SQLGetInfo( m_hdbc,
SQL_ODBC_API_CONFORMANCE,
&nAPIConformance,
sizeof( nAPIConformance ),
&nResult );
if ( !Check( nRetCode ) )
{
GetErrorMessages( SQL_HANDLE_DBC, m_hdbc );
throw new VMException( __FILE__, __LINE__, "SQLGetInfo Failed.", VMException::fatal );
}
if ( nAPIConformance < SQL_OAC_LEVEL1 )
{
GetErrorMessages( SQL_HANDLE_DBC, m_hdbc );
throw new VMException( __FILE__, __LINE__, "[API]SQLConformanceLevel Failed.", VMException::fatal );
}
SWORD nSQLConformance;
nRetCode = ::SQLGetInfo( m_hdbc,
SQL_ODBC_SQL_CONFORMANCE,
&nSQLConformance,
sizeof( nSQLConformance ),
&nResult );
if ( !Check( nRetCode ) )
{
GetErrorMessages( SQL_HANDLE_DBC, m_hdbc );
throw new VMException( __FILE__, __LINE__, "[SQL]SQLConformanceLevel Failed.", VMException::fatal );
}
if ( nSQLConformance < SQL_OSC_MINIMUM )
{
GetErrorMessages( SQL_HANDLE_DBC, m_hdbc );
throw new VMException( __FILE__, __LINE__, "[SQL]SQLConformanceLevel Failed.", VMException::fatal );
}
}
/* End of function "VMODBCConnection::VerifyConnect"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::CheckForSQLErrors
DESCRIPTION: issues a call to the driver looking for error messages
INPUT: retCode : result of last operation
OUTPUT: none
RETURNS: SQL_SUCCESS if all is well, SQL_ERROR if not
*/
RETCODE VMODBCConnection::CheckForSQLErrors( RETCODE retCode, const char* pchFile, UINT uiLine )
{
return( SQL_SUCCESS );
if ( retCode == SQL_SUCCESS )
{
return( SQL_SUCCESS );
}
UCHAR auchSqlState[10];
SDWORD sNativeError;
SWORD sLength;
RETCODE re;
int iCount = 0;
char* pcBuf = (char*)m_auchErrorMsg;
char* pcBufEnd = pcBuf + ciErrorMsgSize;
char* pcBeg;
char* pcEnd;
// clear any previous messages
//
*pcBuf = 0;
while( 1 )
{
// get the next SQL error message
//
re = ::SQLError( m_henvAllConnections,
m_hdbc,
m_hstmt,
auchSqlState,
&sNativeError,
m_auchErrorMsg,
ciErrorMsgSize,
&sLength );
if ( re == SQL_NO_DATA_FOUND )
{
// end of error messages - this is where we exit the "infinite while" loop
//
break;
}
if ( !( re == SQL_SUCCESS || re == SQL_SUCCESS_WITH_INFO ) )
{
// this is a terminal error
//
throw new VMException( __FILE__, __LINE__, "Unable to retrieve SQL error", VMException::fatal );
}
// format this error message
//
iCount++;
pcBeg = (char*)m_auchErrorMsg;
pcEnd = pcBeg + strlen( (char*)m_auchErrorMsg );
while( pcBeg <= pcEnd )
{
pcEnd--;
if( *pcEnd == ']' )
{
pcEnd++;
break;
}
}
pcBuf += sprintf( pcBuf, "\nSQL Error Msg(%i): %s", iCount, pcEnd );
if ( pcBeg < pcEnd )
{
*pcEnd = 0;
pcBuf += sprintf( pcBuf,
"\nSQL State: %s Native State: %i Origin: %s",
(char*)auchSqlState,
(int)sNativeError,
pcBeg );
}
if ( pcBuf >= pcBufEnd )
{
throw new VMException( __FILE__, __LINE__, "SQL error message buffer too small", VMException::fatal );
}
}
if ( retCode == SQL_SUCCESS_WITH_INFO )
{
// the info message has been built - caller can get it if wanted
//
return( SQL_SUCCESS_WITH_INFO );
}
else
{
return( SQL_ERROR );
}
}
/* end of function "VMODBCConnection::CheckForSQLErrors" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::GetConnectInfo
DESCRIPTION: gets capabilities of the connected driver
INPUT: void
OUTPUT: none
RETURNS: void
*/
void VMODBCConnection::GetConnectInfo( void )
{
RETCODE nRetCode;
SWORD nResult;
// Reset the database update options
//
m_dwUpdateOptions = 0;
// Check for SQLSetPos support
//
UDWORD dwDriverPosOperations;
nRetCode = ::SQLGetInfo( m_hdbc,
SQL_POS_OPERATIONS,
&dwDriverPosOperations,
sizeof( dwDriverPosOperations ),
&nResult );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -