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

📄 odbcclient.cpp

📁 通用的数据库中间库
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// odbcClient.cpp: implementation of the IodbcClient class.////////////////////////////////////////////////////////////////////////#include <SQLAPI.h>#include "odbcClient.h"#include <assert.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>	// strtol
#include <odbcAPI.h>#include "samisc.h"#include "errmsg.h"
//////////////////////////////////////////////////////////////////////// IodbcConnection Class//////////////////////////////////////////////////////////////////////class IodbcConnection : public ISAConnection{	enum
	{		MaxLongAtExecSize = 0x7fffffff+SQL_LEN_DATA_AT_EXEC(0)	};	friend class IodbcCursor;	odbcConnectionHandles m_handles;	static void Check(		SQLRETURN return_code,		SQLSMALLINT HandleType,		SQLHANDLE Handle);	SQLINTEGER LenDataAtExec();	void issueIsolationLevel(		SAIsolationLevel_t eIsolationLevel);protected:	virtual ~IodbcConnection();public:	IodbcConnection(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//////////////////////////////////////////////////////////////////////IodbcConnection::IodbcConnection(	SAConnection *pSAConnection) : ISAConnection(pSAConnection){}IodbcConnection::~IodbcConnection(){}
/*virtual */
void IodbcConnection::InitializeClient()
{
	::AddODBCSupport(m_pSAConnection);

	assert(!m_handles.m_hevn);

	g_odbcAPI.SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_handles.m_hevn);
	assert(m_handles.m_hevn);

	try
	{
		Check(g_odbcAPI.SQLSetEnvAttr(m_handles.m_hevn, SQL_ATTR_ODBC_VERSION, SQLPOINTER(SQL_OV_ODBC3), 0), SQL_HANDLE_ENV, m_handles.m_hevn);
	}
	catch(SAException &)	// clean up
	{
		if(m_handles.m_hevn)
		{
			g_odbcAPI.SQLFreeHandle(SQL_HANDLE_ENV, m_handles.m_hevn);
			m_handles.m_hevn = NULL;
		}

		throw;
	}
}

/*virtual */
void IodbcConnection::UnInitializeClient()
{
	assert(m_handles.m_hevn);

	Check(g_odbcAPI.SQLFreeHandle(SQL_HANDLE_ENV, m_handles.m_hevn), SQL_HANDLE_ENV, m_handles.m_hevn);
	m_handles.m_hevn = NULL;

	::ReleaseODBCSupport();
}
SQLINTEGER IodbcConnection::LenDataAtExec(){	SQLSMALLINT retlen = 0;	char szValue[10];	Check(g_odbcAPI.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 IodbcConnection::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 IodbcConnection::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 IodbcConnection::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 IodbcConnection::CnvtInternalToCursor(
	SACommand * /*pCursor*/,
	const void * /*pInternal*/)
{
	assert(false);
}
/*virtual */long IodbcConnection::GetClientVersion() const{
	if(g_nODBCDLLVersionLoaded == 0)	// has not been detected
	{
		if(IsConnected())
		{
			char sInfoValue[1024];
			SQLSMALLINT cbInfoValue;
			g_odbcAPI.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_nODBCDLLVersionLoaded;}/*virtual */long IodbcConnection::GetServerVersion() const{	char sInfoValue[1024];	SQLSMALLINT cbInfoValue;	g_odbcAPI.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 IodbcConnection::GetServerVersionString() const{	char sInfoValue[1024];	SQLSMALLINT cbInfoValue;	g_odbcAPI.SQLGetInfo(m_handles.m_hdbc, SQL_DBMS_NAME, sInfoValue, sizeof(sInfoValue), &cbInfoValue);	SAString s = SAString(sInfoValue, cbInfoValue);	s += " Release ";	g_odbcAPI.SQLGetInfo(m_handles.m_hdbc, SQL_DBMS_VER, sInfoValue, sizeof(sInfoValue), &cbInfoValue);	s += SAString(sInfoValue, cbInfoValue);	return s;}/*static */void IodbcConnection::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_odbcAPI.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 IodbcConnection::IsConnected() const{	return m_handles.m_hdbc != NULL;}/*virtual */void IodbcConnection::Connect(	const SAString &sDBString,	const SAString &sUserID,	const SAString &sPassword){	assert(m_handles.m_hevn);	// allocated in InitializeClient	assert(!m_handles.m_hdbc);	try	{		Check(g_odbcAPI.SQLAllocHandle(SQL_HANDLE_DBC, m_handles.m_hevn, &m_handles.m_hdbc), SQL_HANDLE_ENV, m_handles.m_hevn);
		// do not check errors from the next call
		// we only want this functionality if it is supported
		g_odbcAPI.SQLSetConnectAttr(
			m_handles.m_hdbc,
			SQL_ATTR_ODBC_CURSORS,
			(SQLPOINTER)SQL_CUR_USE_IF_NEEDED,
			0);
				if(sDBString.Find('=') == -1)	// it's not a valid connection string, but it can be DSN name			Check(g_odbcAPI.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
		{
			// we don't need StringLength2 on output, but UnixODBC manager can core dump
			// if we pass NULL instead of &StringLength2 (pointer to SQLSMALLINT)
			SQLSMALLINT StringLength2 = 0;			Check(g_odbcAPI.SQLDriverConnect(				m_handles.m_hdbc, NULL,				(SQLCHAR *)(const char*)sDBString, SQL_NTS, NULL, 0, 
				&StringLength2, SQL_DRIVER_NOPROMPT),				SQL_HANDLE_DBC, m_handles.m_hdbc);
		}	}	catch(SAException &)	{		// clean up		if(m_handles.m_hdbc)		{			g_odbcAPI.SQLFreeHandle(SQL_HANDLE_DBC, m_handles.m_hdbc);			m_handles.m_hdbc = NULL;		}		throw;	}}/*virtual */void IodbcConnection::Disconnect(){	assert(m_handles.m_hdbc);	Check(g_odbcAPI.SQLDisconnect(m_handles.m_hdbc), SQL_HANDLE_DBC, m_handles.m_hdbc);	Check(g_odbcAPI.SQLFreeHandle(SQL_HANDLE_DBC, m_handles.m_hdbc), SQL_HANDLE_DBC, m_handles.m_hdbc);	m_handles.m_hdbc = NULL;}/*virtual */void IodbcConnection::Commit(){	Check(g_odbcAPI.SQLEndTran(SQL_HANDLE_DBC, m_handles.m_hdbc, SQL_COMMIT), SQL_HANDLE_DBC, m_handles.m_hdbc);}/*virtual */void IodbcConnection::Rollback(){	Check(g_odbcAPI.SQLEndTran(SQL_HANDLE_DBC, m_handles.m_hdbc, SQL_ROLLBACK), SQL_HANDLE_DBC, m_handles.m_hdbc);}//////////////////////////////////////////////////////////////////////// IodbcClient Class////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////IodbcClient::IodbcClient(){}IodbcClient::~IodbcClient(){}ISAConnection *IodbcClient::QueryConnectionInterface(	SAConnection *pSAConnection){	return new IodbcConnection(pSAConnection);}//////////////////////////////////////////////////////////////////////// IodbcCursor Class//////////////////////////////////////////////////////////////////////class IodbcCursor : public ISACursor{	odbcCommandHandles	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;
	SQLINTEGER m_nRowsAffected;
	void ProcessBatchUntilEndOrResultSet();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:	IodbcCursor(		IodbcConnection *pIodbcConnection,		SACommand *pCommand);	virtual ~IodbcCursor();	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//////////////////////////////////////////////////////////////////////IodbcCursor::IodbcCursor(	IodbcConnection *pIodbcConnection,	SACommand *pCommand) :	ISACursor(pIodbcConnection, pCommand){
	m_bResultSetCanBe = false;
	m_nRowsAffected = -1;}/*virtual */IodbcCursor::~IodbcCursor(){}/*virtual */unsigned int IodbcCursor::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:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -