📄 infclient.cpp
字号:
// infClient.cpp: implementation of the IinfClient class.////////////////////////////////////////////////////////////////////////#include <SQLAPI.h>#include "infClient.h"#include <assert.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h> // strtol
#include <infAPI.h>
#include "samisc.h"#include "errmsg.h"//////////////////////////////////////////////////////////////////////// IinfConnection Class//////////////////////////////////////////////////////////////////////class IinfConnection : public ISAConnection{ enum { MaxLongAtExecSize = 0x7fffffff+SQL_LEN_DATA_AT_EXEC(0) }; friend class IinfCursor; infConnectionHandles m_handles; long m_nDriverODBCVer; static void Check( SQLRETURN return_code, SQLSMALLINT HandleType, SQLHANDLE Handle); SQLINTEGER LenDataAtExec(); void issueIsolationLevel( SAIsolationLevel_t eIsolationLevel); void SafeAllocEnv(); void SafeAllocConnect(); void SafeFreeEnv(); void SafeFreeConnect(); void SafeSetEnvAttr(); void SafeCommit(); void SafeRollback(); void SafeSetConnectOption( SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);protected: virtual ~IinfConnection();public: IinfConnection(SAConnection *pSAConnection); virtual void InitializeClient();
virtual void UnInitializeClient();
virtual long GetClientVersion() const; virtual long GetServerVersion() const; virtual SAString GetServerVersionString() const; virtual bool IsConnected() const; virtual void Connect( const SAString &sDBString, const SAString &sUserID, const SAString &sPassword); virtual void Disconnect(); virtual void setIsolationLevel( SAIsolationLevel_t eIsolationLevel); virtual void setAutoCommit( SAAutoCommit_t eAutoCommit); virtual void Commit(); virtual void Rollback(); virtual saAPI *NativeAPI() const; virtual saConnectionHandles *NativeHandles(); virtual ISACursor *NewCursor(SACommand *m_pCommand); virtual void CnvtInternalToDateTime( SADateTime &date_time, const void *pInternal, int nInternalSize); static void CnvtInternalToDateTime( SADateTime &date_time, const TIMESTAMP_STRUCT &Internal); static void CnvtDateTimeToInternal( const SADateTime &date_time, TIMESTAMP_STRUCT &Internal);
virtual void CnvtInternalToCursor(
SACommand *pCursor,
const void *pInternal);
};//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////IinfConnection::IinfConnection( SAConnection *pSAConnection) : ISAConnection(pSAConnection){ m_nDriverODBCVer = 0;}IinfConnection::~IinfConnection(){}
/*virtual */
void IinfConnection::InitializeClient()
{
::AddInfSupport();
}
/*virtual */
void IinfConnection::UnInitializeClient()
{
::ReleaseInfSupport();
}
SQLINTEGER IinfConnection::LenDataAtExec(){ SQLSMALLINT retlen = 0; char szValue[10]; Check(g_infAPI.SQLGetInfo( m_handles.m_hdbc, SQL_NEED_LONG_DATA_LEN, szValue, sizeof(szValue), &retlen), SQL_HANDLE_DBC, m_handles.m_hdbc); if(retlen > 0 && (*szValue == 'Y' || *szValue == 'y')) return SQL_LEN_DATA_AT_EXEC(MaxLongAtExecSize); return SQL_DATA_AT_EXEC;}/*virtual */void IinfConnection::CnvtInternalToDateTime( SADateTime &date_time, const void *pInternal, int nInternalSize){ assert(nInternalSize == sizeof(TIMESTAMP_STRUCT));
if(nInternalSize != sizeof(TIMESTAMP_STRUCT))
return; CnvtInternalToDateTime(date_time, *(const TIMESTAMP_STRUCT*)pInternal);}/*static */void IinfConnection::CnvtInternalToDateTime( SADateTime &date_time, const TIMESTAMP_STRUCT &Internal){ date_time = SADateTime(
Internal.year,
Internal.month,
Internal.day,
Internal.hour,
Internal.minute,
Internal.second);
date_time.Fraction() = Internal.fraction;
}/*static */void IinfConnection::CnvtDateTimeToInternal( const SADateTime &date_time, TIMESTAMP_STRUCT &Internal){ Internal.year = (SQLSMALLINT)(date_time.GetYear());
Internal.month = (SQLUSMALLINT)(date_time.GetMonth());
Internal.day = (SQLUSMALLINT)date_time.GetDay();
Internal.hour = (SQLUSMALLINT)date_time.GetHour();
Internal.minute = (SQLUSMALLINT)date_time.GetMinute();
Internal.second = (SQLUSMALLINT)date_time.GetSecond();
Internal.fraction = date_time.Fraction();}
/*virtual */
void IinfConnection::CnvtInternalToCursor(
SACommand * /*pCursor*/,
const void * /*pInternal*/)
{
assert(false);
}
/*virtual */long IinfConnection::GetClientVersion() const{ if(g_nInfDLLVersionLoaded == 0) // has not been detected
{
if(IsConnected())
{
char sInfoValue[1024];
SQLSMALLINT cbInfoValue;
g_infAPI.SQLGetInfo(m_handles.m_hdbc, SQL_DRIVER_VER, sInfoValue, sizeof(sInfoValue), &cbInfoValue);
sInfoValue[cbInfoValue] = 0;
char *sPoint;
short nMajor = (short)strtol(sInfoValue, &sPoint, 10);
assert(*sPoint == '.');
sPoint++;
short nMinor = (short)strtol(sPoint, &sPoint, 10);
return SA_MAKELONG(nMinor, nMajor);
}
}
return g_nInfDLLVersionLoaded;
}/*virtual */long IinfConnection::GetServerVersion() const{ char sInfoValue[1024]; SQLSMALLINT cbInfoValue; g_infAPI.SQLGetInfo(m_handles.m_hdbc, SQL_DBMS_VER, sInfoValue, sizeof(sInfoValue), &cbInfoValue); sInfoValue[cbInfoValue] = 0; char *sPoint; short nMajor = (short)strtol(sInfoValue, &sPoint, 10); assert(*sPoint == '.'); sPoint++; short nMinor = (short)strtol(sPoint, &sPoint, 10); return nMinor + (nMajor << 16);}/*virtual */SAString IinfConnection::GetServerVersionString() const{ char sInfoValue[1024]; SQLSMALLINT cbInfoValue; g_infAPI.SQLGetInfo(m_handles.m_hdbc, SQL_DBMS_NAME, sInfoValue, sizeof(sInfoValue), &cbInfoValue); SAString s = SAString(sInfoValue, cbInfoValue); s += " Release "; g_infAPI.SQLGetInfo(m_handles.m_hdbc, SQL_DBMS_VER, sInfoValue, sizeof(sInfoValue), &cbInfoValue); s += SAString(sInfoValue, cbInfoValue); return s;}/*static */void IinfConnection::Check( SQLRETURN return_code, SQLSMALLINT HandleType, SQLHANDLE Handle){ if(return_code == SQL_SUCCESS) return; if(return_code == SQL_SUCCESS_WITH_INFO) return; SQLCHAR Sqlstate[5+1]; SQLINTEGER NativeError = 0; char sMsg[4096] = ""; SQLSMALLINT TextLength; SQLRETURN rc = 0; if(g_infAPI.SQLGetDiagRec) { rc = g_infAPI.SQLGetDiagRec(HandleType, Handle, 1, Sqlstate, &NativeError, (SQLCHAR *)sMsg, sizeof(sMsg), &TextLength); } else { switch(HandleType) { case SQL_HANDLE_ENV: rc = g_infAPI.SQLError( Handle, NULL, NULL, Sqlstate, &NativeError, (SQLCHAR *)sMsg, sizeof(sMsg), &TextLength); break; case SQL_HANDLE_DBC: rc = g_infAPI.SQLError( NULL, Handle, NULL, Sqlstate, &NativeError, (SQLCHAR *)sMsg, sizeof(sMsg), &TextLength); break; case SQL_HANDLE_STMT: rc = g_infAPI.SQLError( NULL, NULL, Handle, Sqlstate, &NativeError, (SQLCHAR *)sMsg, sizeof(sMsg), &TextLength); break; default: assert(false); } } switch(rc) { case SQL_INVALID_HANDLE: strcpy(sMsg, "SQL_INVALID_HANDLE"); break; case SQL_NO_DATA: strcpy(sMsg, "SQL_NO_DATA"); break; } throw SAException( SA_RDBMS_API_Error, NativeError, -1, "%s", sMsg);}/*virtual */bool IinfConnection::IsConnected() const{ return m_handles.m_hdbc != NULL;}void IinfConnection::SafeAllocEnv(){ if(g_infAPI.SQLAllocHandle) g_infAPI.SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_handles.m_hevn); else g_infAPI.SQLAllocEnv(&m_handles.m_hevn); assert(m_handles.m_hevn);}void IinfConnection::SafeAllocConnect(){ if(g_infAPI.SQLAllocHandle) Check(g_infAPI.SQLAllocHandle(SQL_HANDLE_DBC, m_handles.m_hevn, &m_handles.m_hdbc), SQL_HANDLE_ENV, m_handles.m_hevn); else Check(g_infAPI. SQLAllocConnect(m_handles.m_hevn, &m_handles.m_hdbc), SQL_HANDLE_ENV, m_handles.m_hevn);}void IinfConnection::SafeFreeEnv(){ if(g_infAPI.SQLFreeHandle) Check(g_infAPI.SQLFreeHandle(SQL_HANDLE_ENV, m_handles.m_hevn), SQL_HANDLE_ENV, m_handles.m_hevn); else Check(g_infAPI. SQLFreeEnv(m_handles.m_hevn), SQL_HANDLE_ENV, m_handles.m_hevn); m_handles.m_hevn = NULL;}void IinfConnection::SafeFreeConnect(){ if(g_infAPI.SQLFreeHandle) Check(g_infAPI.SQLFreeHandle(SQL_HANDLE_DBC, m_handles.m_hdbc), SQL_HANDLE_DBC, m_handles.m_hdbc); else Check(g_infAPI.SQLFreeConnect(m_handles.m_hdbc), SQL_HANDLE_DBC, m_handles.m_hdbc); m_handles.m_hdbc = NULL;}void IinfConnection::SafeSetEnvAttr(){ if(g_infAPI.SQLSetEnvAttr) Check(g_infAPI.SQLSetEnvAttr(m_handles.m_hevn, SQL_ATTR_ODBC_VERSION, SQLPOINTER(SQL_OV_ODBC3), 0), SQL_HANDLE_ENV, m_handles.m_hevn);}/*virtual */void IinfConnection::Connect( const SAString &sDBString, const SAString &sUserID, const SAString &sPassword){ assert(!m_handles.m_hevn); assert(!m_handles.m_hdbc); SafeAllocEnv(); try { SafeSetEnvAttr(); SafeAllocConnect(); if(sDBString.Find('=') == -1) // it's not a valid connection string, but it can be DSN name Check(g_infAPI.SQLConnect(m_handles.m_hdbc, (SQLCHAR *)(const char*)sDBString, SQL_NTS, (SQLCHAR *)(const char*)sUserID, SQL_NTS, (SQLCHAR *)(const char*)sPassword, SQL_NTS), SQL_HANDLE_DBC, m_handles.m_hdbc); else
{
SAString s = sDBString;
if(!sUserID.IsEmpty())
{
s += ";UID=";
s += sUserID;
}
if(!sPassword.IsEmpty())
{
s += ";PWD=";
s += sPassword;
}
Check(g_infAPI.SQLDriverConnect( m_handles.m_hdbc, NULL, (SQLCHAR *)(const char*)s, SQL_NTS, NULL, 0, 0, SQL_DRIVER_NOPROMPT), SQL_HANDLE_DBC, m_handles.m_hdbc);
} char sVer[512]; SQLSMALLINT StringLength; Check(g_infAPI. SQLGetInfo( m_handles.m_hdbc, SQL_DRIVER_ODBC_VER, sVer, sizeof(sVer), &StringLength), SQL_HANDLE_DBC, m_handles.m_hdbc); m_nDriverODBCVer = SAExtractVersionFromString(sVer); } catch(...) { // clean up if(m_handles.m_hdbc) { try { SafeFreeConnect(); } catch(SAException &) { } } if(m_handles.m_hevn) { try { SafeFreeEnv(); } catch(SAException &) { } } throw; }}/*virtual */void IinfConnection::Disconnect(){ assert(m_handles.m_hevn); assert(m_handles.m_hdbc); Check(g_infAPI.SQLDisconnect(m_handles.m_hdbc), SQL_HANDLE_DBC, m_handles.m_hdbc); SafeFreeConnect(); SafeFreeEnv(); m_nDriverODBCVer = 0;}void IinfConnection::SafeCommit(){ if(g_infAPI.SQLEndTran) Check(g_infAPI.SQLEndTran(SQL_HANDLE_DBC, m_handles.m_hdbc, SQL_COMMIT), SQL_HANDLE_DBC, m_handles.m_hdbc); else Check(g_infAPI. SQLTransact(m_handles.m_hevn, m_handles.m_hdbc, SQL_COMMIT), SQL_HANDLE_DBC, m_handles.m_hdbc);}void IinfConnection::SafeRollback(){ if(g_infAPI.SQLEndTran) Check(g_infAPI.SQLEndTran(SQL_HANDLE_DBC, m_handles.m_hdbc, SQL_ROLLBACK), SQL_HANDLE_DBC, m_handles.m_hdbc); else Check(g_infAPI. SQLTransact(m_handles.m_hevn, m_handles.m_hdbc, SQL_ROLLBACK), SQL_HANDLE_DBC, m_handles.m_hdbc);}/*virtual */void IinfConnection::Commit(){ SafeCommit();}/*virtual */void IinfConnection::Rollback(){ SafeRollback();}//////////////////////////////////////////////////////////////////////// IinfClient Class////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////IinfClient::IinfClient(){}IinfClient::~IinfClient(){}ISAConnection *IinfClient::QueryConnectionInterface( SAConnection *pSAConnection){ return new IinfConnection(pSAConnection);}//////////////////////////////////////////////////////////////////////// IinfCursor Class//////////////////////////////////////////////////////////////////////class IinfCursor : public ISACursor{ infCommandHandles m_handles; SAString CallSubProgramSQL(); SADataType_t CnvtNativeToStd( int nNativeType, int nNativeSubType, int nSize, int nPrec, int nScale) const; virtual int CnvtStdToNative(SADataType_t eDataType) const; int CnvtStdToNativeValueType(SADataType_t eDataType) const; void BindLongs(); void SafeAllocStmt(); void SafeFreeStmt();protected: virtual unsigned int InputBufferSize( const SAParam &Param) const; virtual unsigned int OutputBufferSize( SADataType_t eDataType, unsigned int nDataSize) const; virtual void SetFieldBuffer( int nCol, // 1-based void *pInd, unsigned int nIndSize, void *pSize, unsigned int nSizeSize, void *pValue, unsigned int nValueSize); virtual bool IndicatorIsNull( int nPos, // 1-based SAValueRead &vr, ValueType_t eValueType, void *pInd, unsigned int nIndSize, void *pSize, unsigned int nSizeSize, unsigned int &nRealSize,
int nBulkReadingBufPos) const;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -