📄 oraclient.cpp
字号:
main_errcode, nErrPos,
sErr);
case OCI_INVALID_HANDLE:
assert(false);
throw SAException(
SA_RDBMS_API_Error,
main_errcode, nErrPos,
"OCI_INVALID_HANDLE");
default:
assert(false);
}
}
// tests if both client and server support Temporary Lobs
// test is very simple
// we try to create it
bool Iora8Connection::IsTemporaryLobSupported()
{
if(m_eOra8TempLobSupport == SA_OCI8TempLobSupport_Unknown)
{
// client test
if(!g_ora8API.OCILobCreateTemporary)
m_eOra8TempLobSupport = SA_OCI8TempLobSupport_False;
else
{
// server test
OCILobLocator *pLoc = NULL;
try
{
Check(g_ora8API.OCIDescriptorAlloc(
m_handles.m_pOCIEnv,
(dvoid **)&pLoc,
OCI_DTYPE_LOB, 0,
NULL), m_handles.m_pOCIEnv, OCI_HTYPE_ENV);
Check(g_ora8API.OCILobCreateTemporary(
m_handles.m_pOCISvcCtx,
m_handles.m_pOCIError,
pLoc,
OCI_DEFAULT,
OCI_DEFAULT,
OCI_TEMP_BLOB,
OCI_ATTR_NOCACHE,
OCI_DURATION_SESSION), m_handles.m_pOCIError, OCI_HTYPE_ERROR);
m_eOra8TempLobSupport = SA_OCI8TempLobSupport_True;
}
catch(SAException &)
{
m_eOra8TempLobSupport = SA_OCI8TempLobSupport_False;
}
// clean up
try
{
if(m_eOra8TempLobSupport == SA_OCI8TempLobSupport_True)
Check(g_ora8API.OCILobFreeTemporary(
m_handles.m_pOCISvcCtx,
m_handles.m_pOCIError,
pLoc), m_handles.m_pOCIError, OCI_HTYPE_ERROR);
}
catch(SAException &)
{
assert(false);
}
try
{
if(pLoc)
Iora8Connection::Check(g_ora8API.OCIDescriptorFree(
pLoc, OCI_DTYPE_LOB), m_handles.m_pOCIError, OCI_HTYPE_ERROR);
}
catch(SAException &)
{
assert(false);
}
}
}
assert(m_eOra8TempLobSupport != SA_OCI8TempLobSupport_Unknown);
return m_eOra8TempLobSupport == SA_OCI8TempLobSupport_True;
}
/*virtual */
bool Iora8Connection::IsConnected() const
{
return m_handles.m_pOCIEnv != NULL;
}
/*virtual */
void Iora8Connection::Connect(
const SAString &sDBString,
const SAString &sUserID,
const SAString &sPassword)
{
assert(m_handles.m_pOCIEnv == NULL);
assert(m_handles.m_pOCIError == NULL);
assert(m_handles.m_pOCISvcCtx == NULL);
assert(m_handles.m_pOCIServer == NULL);
assert(m_handles.m_pOCISession == NULL);
short bServerAttach = 0;
short bSessionBegin = 0;
try
{
if(g_ora8API.OCIEnvCreate == NULL) // use 8.0.x method of initialization
{
Check(g_ora8API.OCIEnvInit(
&m_handles.m_pOCIEnv,
OCI_DEFAULT,
0, (dvoid**)0), m_handles.m_pOCIEnv, OCI_HTYPE_ENV);
}
else
{
Check(g_ora8API.OCIEnvCreate(
&m_handles.m_pOCIEnv,
OCI_THREADED | OCI_OBJECT,
NULL,
NULL, NULL, NULL,
0, (dvoid**)0),
m_handles.m_pOCIEnv,
OCI_HTYPE_ENV);
}
Check(g_ora8API.OCIHandleAlloc(m_handles.m_pOCIEnv, (dvoid**)&m_handles.m_pOCIError, OCI_HTYPE_ERROR, 0, (dvoid**)0), m_handles.m_pOCIEnv, OCI_HTYPE_ENV);
Check(g_ora8API.OCIHandleAlloc(m_handles.m_pOCIEnv, (dvoid**)&m_handles.m_pOCISvcCtx, OCI_HTYPE_SVCCTX, 0, (dvoid**)0), m_handles.m_pOCIEnv, OCI_HTYPE_ENV);
Check(g_ora8API.OCIHandleAlloc(m_handles.m_pOCIEnv, (dvoid**)&m_handles.m_pOCIServer, OCI_HTYPE_SERVER, 0, (dvoid**)0), m_handles.m_pOCIEnv, OCI_HTYPE_ENV);
Check(g_ora8API.OCIHandleAlloc(m_handles.m_pOCIEnv, (dvoid**)&m_handles.m_pOCISession, OCI_HTYPE_SESSION, 0, (dvoid**)0), m_handles.m_pOCIEnv, OCI_HTYPE_ENV);
Check(g_ora8API.OCIAttrSet(m_handles.m_pOCISession, OCI_HTYPE_SESSION, (dvoid*)(const char*)sUserID, (ub4)sUserID.GetLength(), OCI_ATTR_USERNAME, m_handles.m_pOCIError), m_handles.m_pOCIError, OCI_HTYPE_ERROR);
Check(g_ora8API.OCIAttrSet(m_handles.m_pOCISession, OCI_HTYPE_SESSION, (dvoid*)(const char*)sPassword, (ub4)sPassword.GetLength(), OCI_ATTR_PASSWORD, m_handles.m_pOCIError), m_handles.m_pOCIError, OCI_HTYPE_ERROR);
Check(g_ora8API.OCIServerAttach(m_handles.m_pOCIServer, m_handles.m_pOCIError, (CONST text *)(const char*)sDBString, (sb4)sDBString.GetLength(), OCI_DEFAULT), m_handles.m_pOCIError, OCI_HTYPE_ERROR);
bServerAttach = 1;
Check(g_ora8API.OCIAttrSet(m_handles.m_pOCISvcCtx, OCI_HTYPE_SVCCTX, (dvoid*)m_handles.m_pOCIServer, (ub4)0, OCI_ATTR_SERVER, m_handles.m_pOCIError), m_handles.m_pOCIError, OCI_HTYPE_ERROR);
Check(g_ora8API.OCISessionBegin(m_handles.m_pOCISvcCtx, m_handles.m_pOCIError, m_handles.m_pOCISession, OCI_CRED_RDBMS, OCI_DEFAULT), m_handles.m_pOCIError, OCI_HTYPE_ERROR);
bSessionBegin = 1;
Check(g_ora8API.OCIAttrSet(m_handles.m_pOCISvcCtx, OCI_HTYPE_SVCCTX, (dvoid*)m_handles.m_pOCISession, (ub4)0, OCI_ATTR_SESSION, m_handles.m_pOCIError), m_handles.m_pOCIError, OCI_HTYPE_ERROR);
}
catch(...)
{
// clean up
if(bSessionBegin)
g_ora8API.OCISessionEnd(m_handles.m_pOCISvcCtx, m_handles.m_pOCIError, m_handles.m_pOCISession, OCI_DEFAULT);
if(bServerAttach)
g_ora8API.OCIServerDetach(m_handles.m_pOCIServer, m_handles.m_pOCIError, OCI_DEFAULT);
if(m_handles.m_pOCIEnv != NULL)
{
// frees all child handles too
g_ora8API.OCIHandleFree(m_handles.m_pOCIEnv, OCI_HTYPE_ENV);
m_handles.m_pOCIEnv = NULL;
m_handles.m_pOCIError = NULL;
m_handles.m_pOCISvcCtx = NULL;
m_handles.m_pOCIServer = NULL;
m_handles.m_pOCISession = NULL;
}
throw;
}
}
/*virtual */
void Iora8Connection::Disconnect()
{
assert(m_handles.m_pOCIEnv != NULL);
assert(m_handles.m_pOCIError != NULL);
assert(m_handles.m_pOCISvcCtx != NULL);
assert(m_handles.m_pOCIServer != NULL);
assert(m_handles.m_pOCISession != NULL);
Check(g_ora8API.OCISessionEnd(m_handles.m_pOCISvcCtx, m_handles.m_pOCIError, m_handles.m_pOCISession, OCI_DEFAULT), m_handles.m_pOCIError, OCI_HTYPE_ERROR);
Check(g_ora8API.OCIServerDetach(m_handles.m_pOCIServer, m_handles.m_pOCIError, OCI_DEFAULT), m_handles.m_pOCIError, OCI_HTYPE_ERROR);
// frees all child handles too
Check(g_ora8API.OCIHandleFree(m_handles.m_pOCIEnv, OCI_HTYPE_ENV), m_handles.m_pOCIEnv, OCI_HTYPE_ENV);
m_handles.m_pOCIEnv = NULL;
m_handles.m_pOCIEnv = NULL;
m_handles.m_pOCIError = NULL;
m_handles.m_pOCISvcCtx = NULL;
m_handles.m_pOCIServer = NULL;
m_handles.m_pOCISession = NULL;
m_eOra8TempLobSupport = SA_OCI8TempLobSupport_Unknown;
}
/*virtual */
void Iora8Connection::Commit()
{
SAIsolationLevel_t eIsolationLevel;
if(m_eSwitchToIsolationLevelAfterCommit != SA_LevelUnknown)
{
eIsolationLevel = m_eSwitchToIsolationLevelAfterCommit;
m_eSwitchToIsolationLevelAfterCommit = SA_LevelUnknown;
}
else
eIsolationLevel = m_pSAConnection->IsolationLevel();
Check(g_ora8API.OCITransCommit(m_handles.m_pOCISvcCtx, m_handles.m_pOCIError, OCI_DEFAULT),
m_handles.m_pOCIError, OCI_HTYPE_ERROR);
if(eIsolationLevel != SA_LevelUnknown)
issueIsolationLevel(eIsolationLevel);
}
/*virtual */
void Iora8Connection::Rollback()
{
Check(g_ora8API.OCITransRollback(m_handles.m_pOCISvcCtx, m_handles.m_pOCIError, OCI_DEFAULT),
m_handles.m_pOCIError, OCI_HTYPE_ERROR);
SAIsolationLevel_t eIsolationLevel = m_pSAConnection->IsolationLevel();
if(eIsolationLevel != SA_LevelUnknown)
issueIsolationLevel(eIsolationLevel);
}
//////////////////////////////////////////////////////////////////////
// IoraClient Class
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IoraClient::IoraClient()
{
}
IoraClient::~IoraClient()
{
}
ISAConnection *IoraClient::QueryConnectionInterface(
SAConnection *pSAConnection)
{
SAString s = pSAConnection->Option("UseAPI");
if(s.CompareNoCase("OCI7") == 0)
return new Iora7Connection(pSAConnection);
if(s.CompareNoCase("OCI8") == 0)
return new Iora8Connection(pSAConnection);
if(CanBeLoadedOCI8())
return new Iora8Connection(pSAConnection);
return new Iora7Connection(pSAConnection);
}
//////////////////////////////////////////////////////////////////////
// IoraCursor Class
//////////////////////////////////////////////////////////////////////
typedef enum
{
LongContextNormal = 1,
LongContextPiecewiseDefine = 2,
LongContextPiecewiseBind = 4,
LongContextPiecewise = LongContextPiecewiseDefine | LongContextPiecewiseBind,
LongContextCallback = 8
} LongContextState_t;
typedef struct tagLongContext
{
LongContextState_t eState;
SAValueRead *pReader;
SAValue *pWriter;
sb2 *pInd;
unsigned char *pBuf;
ub4 Len;
} LongContext_t;
class IoraCursor : public ISACursor
{
protected:
SAString m_sInternalPrepareStmt;
SAString CallSubProgramSQL();
unsigned char m_PiecewiseNullCheckPreFetch[1];
bool m_bPiecewiseFetchPending;
IoraCursor(
IoraConnection *pIoraConnection,
SACommand *pCommand);
virtual ~IoraCursor();
virtual unsigned int InputBufferSize(
const SAParam &Param) const;
virtual unsigned int OutputBufferSize(
SADataType_t eDataType,
unsigned int nDataSize) const;
virtual SADataType_t CnvtNativeToStd(
int nNativeType,
int nNativeSubType,
int nSize,
int nPrec,
int nScale) const;
};
IoraCursor::IoraCursor(
IoraConnection *pIoraConnection,
SACommand *pCommand) :
ISACursor(pIoraConnection, pCommand)
{
m_bPiecewiseFetchPending = false;
}
/*virtual */
IoraCursor::~IoraCursor()
{
}
SAString IoraCursor::CallSubProgramSQL()
{
int nParams = m_pCommand->ParamCount();
SAString sSQL = "begin\n";
// check for Return parameter
int i;
for(i = 0; i < nParams; ++i)
{
SAParam &Param = m_pCommand->ParamByIndex(i);
if(Param.ParamDirType() == SA_ParamReturn)
{
sSQL += ":";
sSQL += Param.Name();
sSQL += ":=";
break;
}
}
sSQL += m_pCommand->CommandText();
// specify parameters
sSQL += "(";
SAString sParams;
for(i = 0; i < nParams; ++i)
{
SAParam &Param = m_pCommand->ParamByIndex(i);
if(Param.ParamDirType() == SA_ParamReturn)
continue;
if(!sParams.IsEmpty())
sParams += ", ";
sParams += Param.Name();
sParams += "=>:";
sParams += Param.Name();
}
sSQL += sParams;
sSQL += ");\nend;";
return sSQL;
}
/*virtual */
unsigned int IoraCursor::InputBufferSize(
const SAParam &Param) const
{
switch(Param.DataType())
{
case SA_dtBool:
// there is no "native" boolean type in Oracle,
// so treat boolean as 16-bit signed INTEGER in Oracle
return sizeof(short);
case SA_dtDateTime:
return sizeof(OraDate_t); // Oracle internal date/time representation
case SA_dtLongBinary:
case SA_dtLongChar:
return sizeof(LongContext_t);
default:
break;
}
return ISACursor::InputBufferSize(Param);
}
/*virtual */
unsigned int IoraCursor::OutputBufferSize(
SADataType_t eDataType,
unsigned int nDataSize) const
{
switch(eDataType)
{
case SA_dtDateTime:
return sizeof(OraDate_t);
case SA_dtBytes:
// Oracle can report nDataSize = 0 for output parameters
// under some conditions
return ISACursor::OutputBufferSize(eDataType, nDataSize? nDataSize : 4000);
case SA_dtString:
// Oracle can report nDataSize = 0 for output parameters
// under some conditions
return ISACursor::OutputBufferSize(eDataType, nDataSize? nDataSize : 4000);
case SA_dtLongBinary:
case SA_dtLongChar:
return sizeof(LongContext_t);
default:
break;
}
return ISACursor::OutputBufferSize(eDataType, nDataSize);
}
/*virtual */
SADataType_t IoraCursor::CnvtNativeToStd(
int dbtype,
int/* dbsubtype*/,
int/* dbsize*/,
int prec,
int scale) const
{
SADataType_t eDataType;
switch(dbtype)
{
case 1: // VARCHAR2 2000 (4000) bytes
eDataType = SA_dtString;
break;
case 2: // NUMBER 21 bytes
if(prec == 0 || scale != 0) // prec unknown or floating point exists?
eDataType = SA_dtDouble;
else // check for exact type
{
if(prec < 5) // -9,999 : 9,999
eDataType = SA_dtShort;
else if(prec < 10) // -999,999,999 : 999,999,999
eDataType = SA_dtLong;
else
eDataType = SA_dtDouble;
}
break;
case 8: // LONG 2^31-1 bytes
eDataType = SA_dtLongChar;
break;
case 11: // ROWID 6 (10) bytes
eDataType = SA_dtString;
break;
case 12: // DATE 7 bytes
eDataType = SA_dtDateTime;
break;
case 23: // RAW 255 bytes
eDataType = SA_dtBytes;
break;
case 24: // LONG RAW 2^31-2 bytes
eDataType = SA_dtLongBinary;
break;
case 96: // CHAR 255 (2000) bytes
eDataType = SA_dtString;
break;
case 102: // CURSOR VARIABLE
eDataType = SA_dtCursor;
break;
case 105: // MSLABEL 255 bytes
eDataType = SA_dtString;
break;
default:
assert(false);
eDataType = SA_dtUnknown;
}
return eDataType;
}
//////////////////////////////////////////////////////////////////////
// Iora7Cursor Class
//////////////////////////////////////////////////////////////////////
class Iora7Cursor : public IoraCursor
{
ora7CommandHandles m_handles;
bool m_bOpened;
bool m_bResultSetExist;
bool m_bResultSetCanBe;
bool m_bPiecewiseBindAllowed;
bool m_bPiecewiseFetchAllowed;
void BindLongs();
void DiscardPiecewiseFetch();
void CheckPiecewiseNull(bool bAfterExecute = false);
SAField *WhichFieldIsPiecewise() const;
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 int CnvtStdToNative(SADataType_t eDataType) const;
public:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -