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

📄 oraclient.cpp

📁 通用的数据库中间库
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// oraClient.cpp: implementation of the IibClient class.
//
//////////////////////////////////////////////////////////////////////

#include <SQLAPI.h>
#include "oraClient.h"

#include <assert.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>	// strtol, atoi

#include "samisc.h"
#include "errmsg.h"

#include <oraAPI.h>
#include <ora7API.h>

typedef unsigned char OraDate_t[7];

//////////////////////////////////////////////////////////////////////
// IoraConnection Class
//////////////////////////////////////////////////////////////////////

class IoraConnection : public ISAConnection
{
protected:
	enum {
		MaxLongPiece = (unsigned int)0x7FFFFFFF
	};

	virtual ~IoraConnection();

	SAIsolationLevel_t m_eSwitchToIsolationLevelAfterCommit;
	void issueIsolationLevel(
		SAIsolationLevel_t eIsolationLevel);

public:
	IoraConnection(SAConnection *pSAConnection);

	virtual void setIsolationLevel(
		SAIsolationLevel_t eIsolationLevel);

	virtual void CnvtInternalToDateTime(
		SADateTime &date_time,
		const void *pInternal,
		int nInternalSize);
	static void CnvtInternalToDateTime(
		SADateTime &date_time,
		const OraDate_t *pInternal);
	static void CnvtDateTimeToInternal(
		const SADateTime &date_time,
		OraDate_t *pInternal);
};


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


IoraConnection::IoraConnection(
	SAConnection *pSAConnection) : ISAConnection(pSAConnection)
{
	m_eSwitchToIsolationLevelAfterCommit = SA_LevelUnknown;
}

IoraConnection::~IoraConnection()
{
}

/*virtual */
void IoraConnection::CnvtInternalToDateTime(
	SADateTime &date_time,
	const void *pInternal,
	int nInternalSize)
{
	assert(nInternalSize == sizeof(OraDate_t));
	if(nInternalSize != sizeof(OraDate_t))
		return;
	CnvtInternalToDateTime(date_time, (const OraDate_t*)pInternal);
}

/*static */
void IoraConnection::CnvtInternalToDateTime(
	SADateTime &date_time,
	const OraDate_t *pInternal)
{
	date_time = SADateTime(
		((*pInternal)[0]-100)*100 + ((*pInternal)[1]-100),
		(*pInternal)[2],
		(*pInternal)[3],
		(*pInternal)[4] - 1,
		(*pInternal)[5] - 1,
		(*pInternal)[6] - 1);

	// no milli, micro or nano seconds in Oracle
}

/*static */
void IoraConnection::CnvtDateTimeToInternal(
	const SADateTime &date_time,
	OraDate_t *pInternal)
{
	(*pInternal)[0] = (unsigned char)(((date_time.GetYear())/100) + 100);	// century in excess-100 notation
	(*pInternal)[1] = (unsigned char)(((date_time.GetYear())%100) + 100);	// year in excess-100 notation
	(*pInternal)[2] = (unsigned char)(date_time.GetMonth());				// month 1..12
	(*pInternal)[3] = (unsigned char)(date_time.GetDay());					// day 1..31
	(*pInternal)[4] = (unsigned char)(date_time.GetHour() + 1);				// hour 1..24
	(*pInternal)[5] = (unsigned char)(date_time.GetMinute() + 1);			// min 1..60
	(*pInternal)[6] = (unsigned char)(date_time.GetSecond() + 1);			// sec 1..60

	// no milli, micro or nano seconds in Oracle
}

//////////////////////////////////////////////////////////////////////
// Iora7Connection Class
//////////////////////////////////////////////////////////////////////

class Iora7Connection : public IoraConnection
{
	friend class Iora7Cursor;

	ora7ConnectionHandles m_handles;
	bool	m_bConnected;

	void Check(sword return_code, Cda_Def* pCda_Def);

	enum
	{
		MaxLongPortion = (unsigned int)0xFFFF
	};

protected:
	virtual ~Iora7Connection();

public:
	Iora7Connection(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 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 CnvtInternalToCursor(
		SACommand *pCursor,
		const void *pInternal);
	static void CnvtInternalToCursor(
		SACommand &Cursor,
		const Cda_Def *pInternal);
};

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Iora7Connection::Iora7Connection(
	SAConnection *pSAConnection) : IoraConnection(pSAConnection)
{
	m_bConnected = false;
}

Iora7Connection::~Iora7Connection()
{
}

/*virtual */
void Iora7Connection::InitializeClient()
{
	::AddORA7Support();
}

/*virtual */
void Iora7Connection::UnInitializeClient()
{
	::ReleaseORA7Support();
}

/*virtual */
long Iora7Connection::GetClientVersion() const
{
	return g_nORA7DLLVersionLoaded;
}

/*virtual */
long Iora7Connection::GetServerVersion() const
{
	SACommand cmd(m_pSAConnection,
		"select VERSION from PRODUCT_COMPONENT_VERSION where PRODUCT like '%Oracle%'");
	cmd.Execute();
	cmd.FetchNext();
	SAString sVersion = cmd.Field(1).asString();
	cmd.Close();

	char *sPoint;
	short nMajor = (short)strtol(sVersion, &sPoint, 10);
	assert(*sPoint == '.');
	sPoint++;
	short nMinor = (short)strtol(sPoint, &sPoint, 10);
	return nMinor + (nMajor << 16);
}

/*virtual */
SAString Iora7Connection::GetServerVersionString() const
{
	SACommand cmd(m_pSAConnection,
		"select"
		" PRODUCT || ' Release ' || VERSION || ' - ' || STATUS "
		"from"
		" PRODUCT_COMPONENT_VERSION "
		"where"
		" PRODUCT like '%Oracle%'");
	cmd.Execute();
	cmd.FetchNext();
	SAString sVersion = cmd.Field(1).asString();
	cmd.Close();
	return sVersion;
}

void Iora7Connection::Check(sword result_code, Cda_Def* pCda_Def)
{
	if(!result_code)
		return;

	char sMsg[512];
	g_ora7API.oerhms(&m_handles.m_lda, (sb2)result_code, (text*)sMsg, (sword)sizeof(sMsg));

	ub2 peo = pCda_Def? pCda_Def->peo : m_handles.m_lda.peo;
	ub2 rc = pCda_Def? pCda_Def->rc : m_handles.m_lda.rc;
	throw SAException(
		SA_RDBMS_API_Error,
		(int)rc, (int)peo,
		"%s", sMsg);
}

/*virtual */
bool Iora7Connection::IsConnected() const
{
	return m_bConnected;
}

/*virtual */
void Iora7Connection::Connect(
	const SAString &sDBString,
	const SAString &sUserID,
	const SAString &sPassword)
{
	assert(!m_bConnected);

	Check(
		g_ora7API.olog(&m_handles.m_lda, m_handles.m_hda,
		(text*)(const char*)sUserID, -1,
		(text*)(const char*)sPassword, -1,
		(text*)(const char*)sDBString, -1,
		OCI_LM_DEF), NULL);
	m_bConnected = true;
}

/*virtual */
void Iora7Connection::Disconnect()
{
	assert(m_bConnected);
	Check(g_ora7API.ologof(&m_handles.m_lda), NULL);
	m_bConnected = false;
}

/*virtual */
void Iora7Connection::Commit()
{
	SAIsolationLevel_t eIsolationLevel;
	if(m_eSwitchToIsolationLevelAfterCommit != SA_LevelUnknown)
	{
		eIsolationLevel = m_eSwitchToIsolationLevelAfterCommit;
		m_eSwitchToIsolationLevelAfterCommit = SA_LevelUnknown;
	}
	else
		eIsolationLevel = m_pSAConnection->IsolationLevel();

	Check(g_ora7API.ocom(&m_handles.m_lda), NULL);

	if(eIsolationLevel != SA_LevelUnknown)
		issueIsolationLevel(eIsolationLevel);
}

/*virtual */
void Iora7Connection::Rollback()
{
	Check(g_ora7API.orol(&m_handles.m_lda), NULL);

	SAIsolationLevel_t eIsolationLevel = m_pSAConnection->IsolationLevel();
	if(eIsolationLevel != SA_LevelUnknown)
		issueIsolationLevel(eIsolationLevel);
}

//////////////////////////////////////////////////////////////////////
// Iora8Connection Class
//////////////////////////////////////////////////////////////////////

typedef
enum
{
	SA_OCI8TempLobSupport_Unknown,
	SA_OCI8TempLobSupport_True,
	SA_OCI8TempLobSupport_False,
	_SA_OCI8TempLobSupport_Reserverd = (int)(((unsigned int)(-1))/2)
} SAOra8TempLobSupport_t;

class Iora8Connection : public IoraConnection
{
	friend class Iora8Cursor;

	ora8ConnectionHandles m_handles;

	static void Check(
		sword	status,
		dvoid	*hndlp,
		ub4		type,
		OCIStmt	*pOCIStmt = NULL);

	SAOra8TempLobSupport_t m_eOra8TempLobSupport;
	bool IsTemporaryLobSupported();

protected:
	virtual ~Iora8Connection();

public:
	Iora8Connection(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 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 CnvtInternalToCursor(
		SACommand *pCursor,
		const void *pInternal);
	static void CnvtInternalToCursor(
		SACommand &Cursor,
		const OCIStmt *pInternal);
};

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Iora8Connection::Iora8Connection(
	SAConnection *pSAConnection) : IoraConnection(pSAConnection)
{
	m_eOra8TempLobSupport = SA_OCI8TempLobSupport_Unknown;
}

Iora8Connection::~Iora8Connection()
{
}

/*virtual */
void Iora8Connection::InitializeClient()
{
	::AddORA8Support();
}

/*virtual */
void Iora8Connection::UnInitializeClient()
{
	::ReleaseORA8Support();
}

/*virtual */
long Iora8Connection::GetClientVersion() const
{
	return g_nORA8DLLVersionLoaded;
}

/*virtual */
long Iora8Connection::GetServerVersion() const
{
	return SAExtractVersionFromString(GetServerVersionString());
}

/*virtual */
SAString Iora8Connection::GetServerVersionString() const
{
	char sVersion[1024];

	Check(g_ora8API.OCIServerVersion(
		m_handles.m_pOCIServer,
		m_handles.m_pOCIError,
		(text*)sVersion,
		sizeof(sVersion)/sizeof(char),
		OCI_HTYPE_SERVER),
		m_handles.m_pOCIError, OCI_HTYPE_ERROR);

	return SAString(sVersion);
}

// based on OCIError or OCIEnv
/*static */
void Iora8Connection::Check(
	sword	status,
	dvoid	*hndlp,
	ub4		type,
	OCIStmt	*pOCIStmt/* = NULL*/)
{
	sb4 errcode, main_errcode = 0;
	char buf[512];
	SAString sErr;
	ub4 recordno = 1;
	sword ret;
	int nErrPos = -1;
	OCIError *pOCIError = NULL;
	if(type == OCI_HTYPE_ERROR)
		pOCIError = (OCIError *)hndlp;
	
	switch (status)
	{
	case OCI_SUCCESS:
		break;
	case OCI_SUCCESS_WITH_INFO:
		break;
	case OCI_NEED_DATA:
	case OCI_NO_DATA:
	case OCI_STILL_EXECUTING:
	case OCI_ERROR:
// According to Oracle Docs we should loop while ret == OCI_SUCCESS,
// but we can loop forever under some conditions if we will check 
// for OCI_SUCCESS. Oracle bug?
//		do
		{
			ret = g_ora8API.OCIErrorGet(hndlp, recordno, (text *)NULL, &errcode,
				(text*)buf, (ub4) sizeof(buf), type);

			if(ret == OCI_SUCCESS)
			{
//				if(recordno == 1)
					main_errcode = errcode;
//				if(recordno > 1)
//					sErr += "\n";
				sErr += buf;

//				++recordno;
			}
			else
				assert(ret == OCI_NO_DATA);
		}
//		while(ret == OCI_SUCCESS);

		if(pOCIStmt && pOCIError)
		{
			ub2 peo;
			ret = g_ora8API.OCIAttrGet(
				pOCIStmt, OCI_HTYPE_STMT,
				&peo, NULL,
				OCI_ATTR_PARSE_ERROR_OFFSET,
				pOCIError);
			if(ret == OCI_SUCCESS)
				nErrPos = (int)peo;
		}
	
		throw SAException(
			SA_RDBMS_API_Error,

⌨️ 快捷键说明

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