📄 oraclient.cpp
字号:
// 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 + -