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

📄 isaclient.cpp

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

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

#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>	// memcpy
#include "errmsg.h"

#define SA_Align16(x)	(((x+15) >> 4) << 4)

//////////////////////////////////////////////////////////////////////
// Helpers
//////////////////////////////////////////////////////////////////////

// Character sets conversion helpers

// returns number of chars written
int SAMultiByteToWideChar(
	wchar_t *pchDataTgt,
	const char *lpch, int nLength)
{
	wchar_t *pchData = pchDataTgt;
	const char *mbchar = lpch;
	size_t count = (size_t)nLength;
	while(count > 0)
	{
		int nLen = mbtowc(pchData, mbchar, count);
		if(nLen == -1)	// object that mbchar points to does not form a valid multibyte character within the first count characters
			break;	// stop conversion
		if(nLen == 0)	// mbchar is NULL or the object that it points to is a null character
		{
			// 1 = length of multi-byte '\0'
			++mbchar;
			--count;
		}
		else
		{
			// nLen = length of last multi-byte character
			mbchar += nLen;
			count -= nLen;
		}
		++pchData;
	}

	return pchData - pchDataTgt;
}

// returns number of chars written
// if pchDataTgt is NULL, function simply counts
int SAWideCharToMultiByte(
	char *pchDataTgt,
	const wchar_t *lpch, int nLength)
{
	int nWritten = 0;
	for(int i = 0; i < nLength; ++i)
	{
		int nLen;
		if(pchDataTgt)
			nLen = wctomb(pchDataTgt + nWritten, lpch[i]);
		else
		{
			char sTemp[128];
			nLen = wctomb(sTemp, lpch[i]);
		}
		if(nLen == -1)	// the conversion is not possible in the current locale
		{
			if(pchDataTgt)
				pchDataTgt[nWritten] = '?';
			++nWritten;
		}
		else
			nWritten += nLen;
	}

	return nWritten;
}


//////////////////////////////////////////////////////////////////////
// ISAClient Class
//////////////////////////////////////////////////////////////////////

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

ISAClient::ISAClient()
{
}

ISAClient::~ISAClient()
{
}

//////////////////////////////////////////////////////////////////////
// ISAConnection Class
//////////////////////////////////////////////////////////////////////

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

ISAConnection::ISAConnection(SAConnection *pSAConnection) :
	m_pSAConnection(pSAConnection)
{
}

ISAConnection::~ISAConnection()
{
}

SAConnection *ISAConnection::getSAConnection()
{
	return m_pSAConnection;
}

void ISAConnection::EnumCursors(EnumCursors_t fn, void *pAddlData)
{
	if(!m_pSAConnection)
		return;

	m_pSAConnection->EnumCursors(fn, pAddlData);
}

//////////////////////////////////////////////////////////////////////
// ISACursor Class
//////////////////////////////////////////////////////////////////////

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

ISACursor::ISACursor(
	ISAConnection *pISAConnection,
	SACommand *pCommand) :
	m_pISAConnection(pISAConnection),
	m_pCommand(pCommand)
{
	m_pParamBuffer = NULL;
	m_nParamIndSize = 0;
	m_nParamSizeSize = 0;

	m_pSelectBuffer = NULL;
	m_nIndSize = 0;
	m_nSizeSize = 0;
	m_nBulkReadingBufSize = 0;
}

/*virtual */
ISACursor::~ISACursor()
{
	if(m_pParamBuffer)
		free(m_pParamBuffer);
	if(m_pSelectBuffer)
		free(m_pSelectBuffer);
}

/*virtual */
unsigned int ISACursor::InputBufferSize(
	const SAParam &Param) const
{
	assert(Param.ParamDirType() == SA_ParamInput
		|| Param.ParamDirType() == SA_ParamInputOutput);

	if(Param.isNull())
		return 0;

	switch(Param.DataType())
	{
	case SA_dtUnknown:
		throw SAException(SA_Library_Error, -1, -1, IDS_UNKNOWN_PARAMETER_TYPE, (const SAChar*)Param.Name());
	case SA_dtBool:
		assert(false);	// sould be overloaded
		break;
	case SA_dtShort:
		return sizeof(short);
	case SA_dtLong:
		return sizeof(long);
	case SA_dtDouble:
		return sizeof(double);
	case SA_dtDateTime:
		assert(false);	// sould be overloaded
		return 0;
	case SA_dtString:
		// defualt implementation:
		// 1) no space for '\0' is reserved
		// 2) always returns size in single characters (converts to multi-byte under Unicode)
		// So, under Unicode this should be overloaded
		// by clients that bind Unicode strings directly
		// without converting them to multi-byte before binding
		return Param.asString().GetMultiByteCharsLength();
	case SA_dtBytes:
		// in bytes, not characters
		return Param.asBytes().GetBinaryLength();
	case SA_dtLongBinary:
	case SA_dtLongChar:
	case SA_dtBLob:
	case SA_dtCLob:
		assert(false);	// sould be overloaded
		return 0;
	case SA_dtCursor:
		assert(false);	// sould be overloaded
		return 0;
	default:
		assert(false);	// unknown type
	}

	return 0;
}

// align all members to 16-byte boundary
// it will speed up data access on Intel
// and it is very important on RISK 
// platforms (like SPARC Solaris) to avoid non-aligment
void ISACursor::AllocBindBuffer(
	unsigned int nIndSize,
	unsigned int nSizeSize)
{
	m_nParamIndSize = nIndSize;
	m_nParamSizeSize = nSizeSize;

	unsigned int nAllocatedSize = 0;

	int cParamCount = m_pCommand->ParamCount();
	for(int iParam = 0; iParam < cParamCount; ++iParam)
	{
		SAParam &Param = m_pCommand->ParamByIndex(iParam);

		unsigned int nCurParamSize = 0;
		nCurParamSize += SA_Align16(sizeof(unsigned int));	// space allocated for data
		nCurParamSize += SA_Align16(nIndSize);	// null indicator
		nCurParamSize += SA_Align16(nSizeSize);	// space for returned size

		unsigned int nDataSize;
		switch(Param.ParamDirType())
		{
		case SA_ParamInput:
			nDataSize = InputBufferSize(Param);
			break;
		case SA_ParamInputOutput:
			nDataSize = sa_max(InputBufferSize(Param), OutputBufferSize(Param.ParamType(), Param.ParamSize()));
			break;
		case SA_ParamOutput:
		case SA_ParamReturn:
			nDataSize = OutputBufferSize(Param.ParamType(), Param.ParamSize());
			break;
		default:
			nDataSize = 0;
			assert(false);
		}
		nCurParamSize += SA_Align16(nDataSize);

		m_pParamBuffer = realloc(
			m_pParamBuffer,
			nAllocatedSize + nCurParamSize);

		*(unsigned int*)((char*)m_pParamBuffer + nAllocatedSize) = nDataSize;
		nAllocatedSize += nCurParamSize;
	}
}

// align all members to 16-byte boundary
// it will speed up data access on Intel
// and it is very important on RISK 
// platforms (like Sun SPARC) to avoid non-aligment
void ISACursor::AllocBindBuffer(
	int nPlaceHolderCount,
	saPlaceHolder **ppPlaceHolders,
	unsigned int nIndSize,
	unsigned int nSizeSize,
	unsigned int nAddlSize,
	void **ppAddl)
{
	m_nParamIndSize = nIndSize;
	m_nParamSizeSize = nSizeSize;

	unsigned int nAllocatedSize = 0;

	for(int i = 0; i < nPlaceHolderCount; ++i)
	{
		SAParam &Param = *ppPlaceHolders[i]->getParam();

		unsigned int nCurParamSize = 0;
		nCurParamSize += SA_Align16(sizeof(unsigned int));	// space allocated for data
		nCurParamSize += SA_Align16(nIndSize);	// null indicator
		nCurParamSize += SA_Align16(nSizeSize);	// space for returned size

		unsigned int nDataSize;
		switch(Param.ParamDirType())
		{
		case SA_ParamInput:
			nDataSize = InputBufferSize(Param);
			break;
		case SA_ParamInputOutput:
			nDataSize = sa_max(InputBufferSize(Param), OutputBufferSize(Param.ParamType(), Param.ParamSize()));
			break;
		case SA_ParamOutput:
		case SA_ParamReturn:
			nDataSize = OutputBufferSize(Param.ParamType(), Param.ParamSize());
			break;
		default:
			nDataSize = 0;
			assert(false);
		}
		nCurParamSize += SA_Align16(nDataSize);

		m_pParamBuffer = ::realloc(
			m_pParamBuffer,
			nAllocatedSize + nCurParamSize);

		*(unsigned int*)((char*)m_pParamBuffer + nAllocatedSize) = nDataSize;
		nAllocatedSize += nCurParamSize;
	}

	// allocate additional block as requested by caller
	if(nAddlSize)
		m_pParamBuffer = ::realloc(
			m_pParamBuffer,
			nAllocatedSize + SA_Align16(nAddlSize));
	if(ppAddl)
		*ppAddl = (char*)m_pParamBuffer + nAllocatedSize;
}

/*virtual */
unsigned int ISACursor::OutputBufferSize(
	SADataType_t eDataType,
	unsigned int nDataSize) const
{
	switch(eDataType)
	{
		case SA_dtUnknown:
			throw SAException(SA_Library_Error, -1, -1, IDS_UNKNOWN_DATA_TYPE);
		case SA_dtBool:
			assert(false);	// sould be overloaded
			return 0;
		case SA_dtShort:
			return sizeof(short);
		case SA_dtLong:
			return sizeof(long);
		case SA_dtDouble:
			return sizeof(double);
		case SA_dtDateTime:
			assert(false);	// sould be overloaded
			return 0;
		case SA_dtBytes:
			return nDataSize;
		case SA_dtString:
			// No space for '\0' is reserved.
			// nDataSize is always (under Unicode or multi-byte builds)
			// assumed to be in bytes, not characters.
			// If above is not true, client should overload.
			return nDataSize;
		case SA_dtLongBinary:
		case SA_dtLongChar:
		case SA_dtBLob:
		case SA_dtCLob:
			assert(false);	// sould be overloaded
			return 0;
		case SA_dtCursor:
			assert(false);	// sould be overloaded
			return 0;
		default:
			assert(false);	// unknown type
	}

	return 0;
}

// align all members to 16-byte boundary
// it will speed up data access on Intel
// and it is very important on RISK 
// platforms (like Sun SPARC) to avoid non-aligment
void ISACursor::AllocSelectBuffer(
	unsigned int nIndSize,
	unsigned int nSizeSize,
	int nBulkReadingBufSize)
{
	m_nIndSize = nIndSize;
	m_nSizeSize = nSizeSize;
	m_nBulkReadingBufSize = nBulkReadingBufSize;

	unsigned int nAllocatedSize = 0;

	int cFieldCount = m_pCommand->FieldCount();
	int iField;
	for(iField = 1; iField <= cFieldCount; ++iField)
	{
		SAField &Field = m_pCommand->Field(iField);

		unsigned int nCurFieldSize = 0;
		nCurFieldSize += SA_Align16(sizeof(unsigned int));	// space allocated for data
		nCurFieldSize += SA_Align16(nIndSize * nBulkReadingBufSize);	// null indicator
		nCurFieldSize += SA_Align16(nSizeSize * nBulkReadingBufSize);	// space for returned size

		unsigned int nDataSize = OutputBufferSize(
			Field.FieldType(),
			Field.FieldSize());
		nCurFieldSize += SA_Align16(nDataSize * nBulkReadingBufSize);

		m_pSelectBuffer = ::realloc(
			m_pSelectBuffer,
			nAllocatedSize + nCurFieldSize);

		*(unsigned int*)((char*)m_pSelectBuffer + nAllocatedSize) = nDataSize;
		nAllocatedSize += nCurFieldSize;
	}

	void *pBuf = m_pSelectBuffer;
	for(iField = 1; iField <= cFieldCount; ++iField)
	{
		void *pInd;
		void *pSize;
		void *pValue;
		unsigned int nDataBufSize;

		IncFieldBuffer(pBuf, pInd, pSize, nDataBufSize, pValue);

		SetFieldBuffer(
			iField,
			pInd, nIndSize,
			pSize, nSizeSize,
			pValue, nDataBufSize);
	}
}

⌨️ 快捷键说明

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