⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 db2client.cpp

📁 通用的数据库中间库
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// 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 + -