📄 db2client.cpp
字号:
// db2Client.cpp: implementation of the Idb2Client class.
//
//////////////////////////////////////////////////////////////////////
#include <SQLAPI.h>
#include "db2Client.h"
#include <assert.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h> // strtol
#include <db2API.h>
#include "samisc.h"
#include "errmsg.h"
//////////////////////////////////////////////////////////////////////
// Idb2Connection Class
//////////////////////////////////////////////////////////////////////
class Idb2Connection : public ISAConnection
{
enum
{
MaxLongAtExecSize = 0x7fffffff+SQL_LEN_DATA_AT_EXEC(0)
};
friend class Idb2Cursor;
db2ConnectionHandles m_handles;
static void Check(
SQLRETURN return_code,
SQLSMALLINT HandleType,
SQLHANDLE Handle);
SQLINTEGER LenDataAtExec();
void issueIsolationLevel(
SAIsolationLevel_t eIsolationLevel);
protected:
virtual ~Idb2Connection();
public:
Idb2Connection(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
//////////////////////////////////////////////////////////////////////
Idb2Connection::Idb2Connection(
SAConnection *pSAConnection) : ISAConnection(pSAConnection)
{
}
Idb2Connection::~Idb2Connection()
{
}
/*virtual */
void Idb2Connection::InitializeClient()
{
::AddDB2Support();
}
/*virtual */
void Idb2Connection::UnInitializeClient()
{
::ReleaseDB2Support();
}
SQLINTEGER Idb2Connection::LenDataAtExec()
{
SQLSMALLINT retlen = 0;
char szValue[10];
Check(g_db2API.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 Idb2Connection::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 Idb2Connection::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 Idb2Connection::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 Idb2Connection::CnvtInternalToCursor(
SACommand * /*pCursor*/,
const void * /*pInternal*/)
{
assert(false);
}
/*virtual */
long Idb2Connection::GetClientVersion() const
{
if(g_nDB2DLLVersionLoaded == 0) // has not been detected
{
if(IsConnected())
{
char sInfoValue[1024];
SQLSMALLINT cbInfoValue;
g_db2API.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_nDB2DLLVersionLoaded;
}
/*virtual */
long Idb2Connection::GetServerVersion() const
{
char sInfoValue[1024];
SQLSMALLINT cbInfoValue;
g_db2API.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 SA_MAKELONG(nMinor, nMajor);
}
/*virtual */
SAString Idb2Connection::GetServerVersionString() const
{
char sInfoValue[1024];
SQLSMALLINT cbInfoValue;
g_db2API.SQLGetInfo(m_handles.m_hdbc, SQL_DBMS_NAME, sInfoValue, sizeof(sInfoValue), &cbInfoValue);
SAString s(sInfoValue, cbInfoValue);
s += " Release ";
g_db2API.SQLGetInfo(m_handles.m_hdbc, SQL_DBMS_VER, sInfoValue, sizeof(sInfoValue), &cbInfoValue);
s += SAString(sInfoValue, cbInfoValue);
return s;
}
/*static */
void Idb2Connection::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;
char sMsg[4096] = "";
SQLSMALLINT TextLength;
SQLRETURN rc = g_db2API.SQLGetDiagRec(HandleType, Handle, 1,
Sqlstate, &NativeError,
(SQLCHAR *)sMsg, sizeof(sMsg), &TextLength);
assert(rc == SQL_SUCCESS);
if(rc != SQL_SUCCESS)
throw SAException(
SA_RDBMS_API_Error,
return_code, -1,
"rc != SQL_SUCCESS");
throw SAException(
SA_RDBMS_API_Error,
NativeError, -1,
"%s", sMsg);
}
/*virtual */
bool Idb2Connection::IsConnected() const
{
return m_handles.m_hdbc != 0;
}
/*virtual */
void Idb2Connection::Connect(
const SAString &sDBString,
const SAString &sUserID,
const SAString &sPassword)
{
assert(!m_handles.m_hevn);
assert(!m_handles.m_hdbc);
g_db2API.SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_handles.m_hevn);
assert(m_handles.m_hevn);
try
{
Check(g_db2API.SQLSetEnvAttr(m_handles.m_hevn, SQL_ATTR_ODBC_VERSION, SQLPOINTER(SQL_OV_ODBC3), 0), SQL_HANDLE_ENV, m_handles.m_hevn);
Check(g_db2API.SQLAllocHandle(SQL_HANDLE_DBC, m_handles.m_hevn, &m_handles.m_hdbc), SQL_HANDLE_ENV, m_handles.m_hevn);
if(sDBString.Find('=') == -1) // it's not a valid connection string, but it can be DSN name
Check(g_db2API.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
Check(g_db2API.SQLDriverConnect(
m_handles.m_hdbc, NULL,
(SQLCHAR *)(const char*)sDBString, SQL_NTS, NULL, 0, 0, SQL_DRIVER_NOPROMPT),
SQL_HANDLE_DBC, m_handles.m_hdbc);
}
catch(SAException &)
{
// clean up
if(m_handles.m_hdbc)
{
g_db2API.SQLFreeHandle(SQL_HANDLE_DBC, m_handles.m_hdbc);
m_handles.m_hdbc = (SQLHDBC)NULL;
}
if(m_handles.m_hevn)
{
g_db2API.SQLFreeHandle(SQL_HANDLE_ENV, m_handles.m_hevn);
m_handles.m_hevn = (SQLHENV)NULL;
}
throw;
}
}
/*virtual */
void Idb2Connection::Disconnect()
{
assert(m_handles.m_hevn);
assert(m_handles.m_hdbc);
Check(g_db2API.SQLDisconnect(m_handles.m_hdbc), SQL_HANDLE_DBC, m_handles.m_hdbc);
Check(g_db2API.SQLFreeHandle(SQL_HANDLE_DBC, m_handles.m_hdbc), SQL_HANDLE_DBC, m_handles.m_hdbc);
m_handles.m_hdbc = (SQLHDBC)NULL;
Check(g_db2API.SQLFreeHandle(SQL_HANDLE_ENV, m_handles.m_hevn), SQL_HANDLE_ENV, m_handles.m_hevn);
m_handles.m_hevn = (SQLHENV)NULL;
}
/*virtual */
void Idb2Connection::Commit()
{
Check(g_db2API.SQLEndTran(SQL_HANDLE_DBC, m_handles.m_hdbc, SQL_COMMIT), SQL_HANDLE_DBC, m_handles.m_hdbc);
}
/*virtual */
void Idb2Connection::Rollback()
{
Check(g_db2API.SQLEndTran(SQL_HANDLE_DBC, m_handles.m_hdbc, SQL_ROLLBACK), SQL_HANDLE_DBC, m_handles.m_hdbc);
}
//////////////////////////////////////////////////////////////////////
// Idb2Client Class
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Idb2Client::Idb2Client()
{
}
Idb2Client::~Idb2Client()
{
}
ISAConnection *Idb2Client::QueryConnectionInterface(
SAConnection *pSAConnection)
{
return new Idb2Connection(pSAConnection);
}
//////////////////////////////////////////////////////////////////////
// Idb2Cursor Class
//////////////////////////////////////////////////////////////////////
class Idb2Cursor : public ISACursor
{
db2CommandHandles 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();
bool m_bResultSetCanBe;
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;
public:
Idb2Cursor(
Idb2Connection *pIdb2Connection,
SACommand *pCommand);
virtual ~Idb2Cursor();
virtual bool IsOpened();
virtual void Open();
virtual void Close();
virtual void Prepare(
const SAString &sStmt,
SACommandType_t eCmdType,
int nPlaceHolderCount,
saPlaceHolder **ppPlaceHolders);
// binds parameters
void Bind(
int nPlaceHolderCount,
saPlaceHolder **ppPlaceHolders);
// executes statement
virtual void Execute(
int nPlaceHolderCount,
saPlaceHolder **ppPlaceHolders);
// cleans up after execute if needed, so the statement can be reexecuted
virtual void UnExecute();
virtual void Cancel();
virtual bool ResultSetExists();
virtual void DescribeFields(
DescribeFields_cb_t fn);
virtual void SetSelectBuffers();
virtual bool FetchNext();
virtual long GetRowsAffected();
virtual void ReadLongOrLOB(
ValueType_t eValueType,
SAValueRead &vr,
void *pValue,
unsigned int nFieldBufSize,
saLongOrLobReader_t fnReader,
unsigned int nReaderWantedPieceSize,
void *pAddlData);
virtual void DescribeParamSP();
virtual saCommandHandles *NativeHandles();
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Idb2Cursor::Idb2Cursor(
Idb2Connection *pIdb2Connection,
SACommand *pCommand) :
ISACursor(pIdb2Connection, pCommand)
{
m_bResultSetCanBe = false;
}
/*virtual */
Idb2Cursor::~Idb2Cursor()
{
}
/*virtual */
unsigned int Idb2Cursor::InputBufferSize(
const SAParam &Param) const
{
if(!Param.isNull())
{
switch(Param.DataType())
{
case SA_dtBool:
return sizeof(unsigned char); // SQL_C_BIT
case SA_dtDateTime:
return sizeof(TIMESTAMP_STRUCT);
case SA_dtLongBinary:
case SA_dtLongChar:
case SA_dtBLob:
case SA_dtCLob:
return 0;
default:
break;
}
}
return ISACursor::InputBufferSize(Param);
}
SADataType_t Idb2Cursor::CnvtNativeToStd(
int dbtype,
int/* dbsubtype*/,
int/* dbsize*/,
int prec,
int scale) const
{
SADataType_t eDataType = SA_dtUnknown;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -