📄 vmodbcconnection.cpp
字号:
if ( ( Check( nRetCode ) )
&& ( dwDriverPosOperations & SQL_POS_UPDATE )
&& ( dwDriverPosOperations & SQL_POS_DELETE )
&& ( dwDriverPosOperations & SQL_POS_ADD ) )
{
m_dwUpdateOptions |= SQL_SETPOSUPDATES;
}
// Check for positioned update SQL support
//
UDWORD dwPositionedStatements;
nRetCode = ::SQLGetInfo( m_hdbc,
SQL_POSITIONED_STATEMENTS,
&dwPositionedStatements,
sizeof( dwPositionedStatements ),
&nResult );
if ( ( Check( nRetCode ) )
&& ( dwPositionedStatements & SQL_PS_POSITIONED_DELETE )
&& ( dwPositionedStatements & SQL_PS_POSITIONED_UPDATE ) )
{
m_dwUpdateOptions |= SQL_POSITIONEDSQL;
}
// Check for transaction support
//
SWORD nTxnCapable;
nRetCode = ::SQLGetInfo( m_hdbc,
SQL_TXN_CAPABLE,
&nTxnCapable,
sizeof( nTxnCapable ),
&nResult );
if ( Check( nRetCode ) && nTxnCapable != SQL_TC_NONE )
{
m_bTransactions = true;
}
// Cache the effect of transactions on cursors
//
nRetCode = ::SQLGetInfo( m_hdbc,
SQL_CURSOR_COMMIT_BEHAVIOR,
&m_nCursorCommitBehavior,
sizeof( m_nCursorCommitBehavior ),
&nResult );
if ( !Check( nRetCode ) )
{
m_nCursorCommitBehavior = SQL_ERROR;
}
nRetCode = ::SQLGetInfo( m_hdbc,
SQL_CURSOR_ROLLBACK_BEHAVIOR,
&m_nCursorRollbackBehavior,
sizeof( m_nCursorRollbackBehavior ),
&nResult );
if ( !Check( nRetCode ) )
{
m_nCursorRollbackBehavior = SQL_ERROR;
}
// Cache bookmark attributes
//
nRetCode = ::SQLGetInfo( m_hdbc,
SQL_BOOKMARK_PERSISTENCE,
&m_dwBookmarkAttributes,
sizeof( m_dwBookmarkAttributes ),
&nResult );
Check( nRetCode );
UDWORD dwGetDataExtensions;
nRetCode = ::SQLGetInfo( m_hdbc,
SQL_GETDATA_EXTENSIONS,
&dwGetDataExtensions,
sizeof( dwGetDataExtensions ),
&nResult );
if ( !Check( nRetCode ) )
{
dwGetDataExtensions = 0;
}
if ( dwGetDataExtensions & SQL_GD_BOUND )
{
m_dwUpdateOptions |= SQL_GDBOUND;
}
if ( m_bUpdatable )
{
// Make sure data source is Updatable
//
char szReadOnly[10];
nRetCode = ::SQLGetInfo( m_hdbc,
SQL_DATA_SOURCE_READ_ONLY,
szReadOnly,
sizeof( szReadOnly ),
&nResult );
if ( Check( nRetCode ) && nResult == 1 )
{
m_bUpdatable = !( lstrcmpA( szReadOnly, "Y" ) == 0 );
}
else
{
m_bUpdatable = false;
}
}
else
{
// Make data source is !Updatable
//
nRetCode = ::SQLSetConnectOption( m_hdbc,
SQL_ACCESS_MODE,
SQL_MODE_READ_ONLY );
}
// Cache the quote char to use when constructing SQL
//
char szIDQuoteChar[2];
nRetCode = ::SQLGetInfo( m_hdbc,
SQL_IDENTIFIER_QUOTE_CHAR,
szIDQuoteChar,
sizeof( szIDQuoteChar ),
&nResult );
if ( Check( nRetCode ) && nResult == 1 )
{
m_chIDQuoteChar = szIDQuoteChar[0];
}
else
{
m_chIDQuoteChar = ' ';
}
}
/* End of function "VMODBCConnection::GetConnectInfo"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::VerifySQLConnect
DESCRIPTION: Special verification function for database connections.
INPUT: retCode - the return code to check
pcFile - pointer to source file name of SQL call
ulLine - souce file line number of SQL call
RETURNS: TRUE if no error
FALSE if correctable error is detected
throws CMSgLog* exception in non-correctable error is detected.
*/
bool VMODBCConnection::VerifySQLConnect( RETCODE retCode, const char* pcFile, UINT uiLine )
{
const char* pcMsg;
char* pcTest;
if ( retCode == SQL_SUCCESS || retCode == SQL_SUCCESS_WITH_INFO )
{
// no connection errors
//
return( true );
}
GetErrorMessages( SQL_HANDLE_DBC, m_hdbc );
pcMsg = (const char*)m_auchErrorMsg;
// filter out the exceptable failure conditions
//
pcTest = strstr( pcMsg, UNABLE_TO_CONNECT );
if( pcTest != NULL )
{
// unable to connect
return( false );
}
pcTest = strstr( pcMsg, ALREADY_IN_USE );
if ( pcTest != NULL )
{
// connection in use
return( false );
}
pcTest = strstr( pcMsg, COMM_LINK_FAILED );
if ( pcTest != NULL )
{
// communication link failure
return( false );
}
pcTest = strstr( pcMsg, COMM_LINK_FAILURE );
if ( pcTest != NULL )
{
// communication link failure
return( false );
}
// its not good, but we don't know what is wrong
return( false );
}
/* end of function "VMODBCConnection::VerifySQLConnect" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::OnTimerEvent
DESCRIPTION: Called at intervals when the database connection is broken
to attempt a reconnection.
INPUT: uiTimerID - ID of the timer being triggerred.
RETURNS: none
*/
void VMODBCConnection::OnTimerEvent( UINT uiTimerID )
{
try
{
if ( m_bReconnectTimer )
{
if ( Reconnect() )
{
// kill the reconnect timer
//
m_bReconnectTimer = false;
}
}
// IMPORTANT NOTE: This is the normal return from
// this method if the connection can be re-established
// with the target. See additional code AFTER the catch
// blocks for code that will execute whenever the
// subordinates fail to reconnect (and therefore throw)
//
return;
}
catch( VMException* poEx )
{
delete poEx;
m_iReconnectAttempts++;
}
catch( ... )
{
m_iReconnectAttempts++;
}
// this code should only execute after an exception has been
// thrown in one of this functions subordinates. In other words,
// the re-connection attempt failed.
//
char chMsg[1024];
ZeroMemory( chMsg, 1024 );
strcat( chMsg, "Could not connect to database." );
strcpy( chMsg, "" );
sprintf( chMsg,
"Have Tried To Connect %i Times.",
m_iReconnectAttempts );
strcpy( chMsg, "" );
sprintf( chMsg,
"Will Re-Attempt To Connect In %i Minutes.",
m_uiReconnectWait / 60000 );
}
/* end of function "VMODBCConnection::OnTimerEvent" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::Reconnect
DESCRIPTION: Attempts to reconnect a lost database connection.
INPUT: none
RETURNS: TRUE if the connection is restored, FALSE otherwise
*/
bool VMODBCConnection::Reconnect( void )
{
RETCODE re;
char acBuf[ 640 ];
SWORD sCountOut;
// verify the conditions for a reconnect
//
assert( m_bReconnectTimer == true );
assert( m_hdbc == SQL_NULL_HDBC );
assert( m_hstmt == SQL_NULL_HSTMT );
// attempt to connect
try
{
re = ::SQLAllocConnect( m_henvAllConnections, &m_hdbc );
GetErrorMessages( SQL_HANDLE_DBC, m_hdbc );
re = ::SQLDriverConnect( m_hdbc, HWND_DESKTOP,
(UCHAR*)(const char*)m_oConnect,
m_oConnect.GetLength(),
(UCHAR*)acBuf,
640,
&sCountOut,
SQL_DRIVER_NOPROMPT );
// test for success(TRUE), broken connection(FALSE) or error(throws exception)
//
if( VerifySQLConnect( re, __FILE__, __LINE__ ) )
{
// reconnected! - get a statement handle & allow insertions
//
re = ::SQLAllocStmt( m_hdbc, &m_hstmt );
GetErrorMessages( SQL_HANDLE_STMT, m_hstmt );
return( true );
}
}
catch( VMException* poEx )
{
// connection still broken - free the handle allocation
//
::SQLFreeConnect( m_hdbc );
m_hdbc = SQL_NULL_HDBC;
throw poEx;
}
return( false );
}
/* end of function "VMODBCConnection::Reconnect" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::BindParameters
DESCRIPTION: does nothing
INPUT: hStmt - statement handle
OUTPUT: none
RETURNS: void
*/
void VMODBCConnection::BindParameters( HSTMT hStmt )
{
// Must override and call SQLBindParameter directly
}
/* End of function "VMODBCConnection::BindParameters"
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: VMODBCConnection::GetErrorMessages
DESCRIPTION: Retrieve Errors from the ODBC Driver stack
INPUT: iHandleType - the type of handle to get errors for
hSqlHandle - the handle to get errors for
bIsConnected - true if drivers are connected to dbms
OUTPUT:
RETURNS: void
*/
void VMODBCConnection::GetErrorMessages( SQLSMALLINT iHandleType, SQLHANDLE hSqlHandle, bool bIsConnected )
{
return;
#define MAXBUFLEN 1024
RETCODE hRetCode = SQL_SUCCESS;
UCHAR achSqlState[ MAXBUFLEN ] = "";
UCHAR achErrorMsg[ MAXBUFLEN ] = "";
SDWORD dwNativeError = 0L;
SWORD wErrorMsg = 0;
SQLSMALLINT iRecordNumber = 1;
SDWORD dwMsgState = 0;
SDWORD dwSeverity = 0;
SQLINTEGER iRownumber = 0;
USHORT usLine;
SQLSMALLINT iProcessName;
SQLSMALLINT iServerName;
SQLCHAR achProcessName[ MAXNAME ];
SQLCHAR achServerName[ MAXNAME ];
while ( hRetCode != SQL_NO_DATA_FOUND )
{
hRetCode = SQLGetDiagRec( iHandleType,
hSqlHandle,
iRecordNumber,
achSqlState,
&dwNativeError,
achErrorMsg,
MAXBUFLEN - 1,
&wErrorMsg );
// Note that if the application has not yet made a
// successful connection, the SQLGetDiagField
// information has not yet been cached by ODBC
// Driver Manager and these calls to SQLGetDiagField
// will fail.
//
if ( hRetCode != SQL_NO_DATA_FOUND )
{
if ( bIsConnected )
{
hRetCode = SQLGetDiagField( iHandleType,
hSqlHandle,
iRecordNumber,
SQL_DIAG_ROW_NUMBER,
&iRownumber,
SQL_IS_INTEGER,
NULL );
hRetCode = SQLGetDiagField( iHandleType,
hSqlHandle,
iRecordNumber,
SQL_DIAG_SS_LINE,
&usLine,
SQL_IS_INTEGER,
NULL );
hRetCode = SQLGetDiagField( iHandleType,
hSqlHandle,
iRecordNumber,
SQL_DIAG_SS_MSGSTATE,
&dwMsgState,
SQL_IS_INTEGER,
NULL );
hRetCode = SQLGetDiagField( iHandleType,
hSqlHandle,
iRecordNumber,
SQL_DIAG_SS_SEVERITY,
&dwSeverity,
SQL_IS_INTEGER,
NULL );
hRetCode = SQLGetDiagField( iHandleType,
hSqlHandle,
iRecordNumber,
SQL_DIAG_SS_PROCNAME,
&achProcessName,
sizeof( achProcessName ),
&iProcessName );
hRetCode = SQLGetDiagField( iHandleType,
hSqlHandle,
iRecordNumber,
SQL_DIAG_SS_SRVNAME,
&achServerName,
sizeof( achServerName ),
&iServerName );
}
if ( bIsConnected )
{
}
}
iRecordNumber++;
}
}
/* End of function "VMODBCConnection::GetErrorMessages"
/*****************************************************************************/
/*****************************************************************************/
/* Check-in history */
/*
*$Log: $
*/
/*****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -