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

📄 oraclient.cpp

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