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

📄 sqlapi.cpp

📁 通用的数据库中间库
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// SQLAPI.cpp : Defines the entry point for the DLL application.
//

#include <SQLAPI.h>

#include "ISAClient.h"
#include "errmsg.h"

#ifdef SQLAPI_AllClients
#define SQLAPI_odbcClient
#define SQLAPI_oraClient
#define SQLAPI_ssClient
#define SQLAPI_ibClient
#define SQLAPI_sbClient
#define SQLAPI_db2Client
#define SQLAPI_infClient
#define SQLAPI_sybClient
#define SQLAPI_myClient
#define SQLAPI_pgClient
#endif

#ifdef SQLAPI_odbcClient
#include "odbcClient.h"
#endif
#ifdef SQLAPI_oraClient
#include "oraClient.h"
#endif
#ifdef SQLAPI_ssClient
#include "ssClient.h"
#endif
#ifdef SQLAPI_ibClient
#include "ibClient.h"
#endif
#ifdef SQLAPI_sbClient
#include "sbClient.h"
#endif
#ifdef SQLAPI_db2Client
#include "db2Client.h"
#endif
#ifdef SQLAPI_infClient
#include "infClient.h"
#endif
#ifdef SQLAPI_sybClient
#include "sybClient.h"
#endif
#ifdef SQLAPI_myClient
#include "myClient.h"
#endif
#ifdef SQLAPI_pgClient
#include "pgClient.h"
#endif

#include <malloc.h>
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <limits.h>

#ifdef LINUX
#include <wchar.h>
#include <wctype.h>
#endif

#ifdef SQLAPI_odbcClient
static IodbcClient odbcClient;	// ODBC client
#endif
#ifdef SQLAPI_oraClient
static IoraClient oraClient;	// Oracle client
#endif
#ifdef SQLAPI_ssClient
static IssClient ssClient;		// Microsoft SQL Server client
#endif
#ifdef SQLAPI_ibClient
static IibClient ibClient;		// InterBase client
#endif
#ifdef SQLAPI_sbClient
static IsbClient sbClient;		// Centura SqlBase client
#endif
#ifdef SQLAPI_db2Client
static Idb2Client db2Client;	// DB2 client
#endif
#ifdef SQLAPI_infClient
static IinfClient infClient;	// Informix client
#endif
#ifdef SQLAPI_sybClient
static IsybClient sybClient;	// Sybase client
#endif
#ifdef SQLAPI_myClient
static ImyClient myClient;	// MySQL client
#endif
#ifdef SQLAPI_pgClient
static IpgClient pgClient;	// MySQL client
#endif

static ISAClient *stat_SAClients[] =
{
	NULL,
#ifdef SQLAPI_odbcClient
	&odbcClient,
#else
	NULL,
#endif
#ifdef SQLAPI_oraClient
	&oraClient,
#else
	NULL,
#endif
#ifdef SQLAPI_ssClient
	&ssClient,
#else
	NULL,
#endif
#ifdef SQLAPI_ibClient
	&ibClient,
#else
	NULL,
#endif
#ifdef SQLAPI_sbClient
	&sbClient,
#else
	NULL,
#endif
#ifdef SQLAPI_db2Client
	&db2Client,
#else
	NULL,
#endif
#ifdef SQLAPI_infClient
	&infClient,
#else
	NULL,
#endif
#ifdef SQLAPI_sybClient
	&sybClient,
#else
	NULL,
#endif
#ifdef SQLAPI_myClient
	&myClient,
#else
	NULL,
#endif
#ifdef SQLAPI_pgClient
	&pgClient
#else
	NULL
#endif
};

struct sa_Commands
{
	SACommand	*pCommand;
	ISACursor	*pISACursor;
	sa_Commands	*Next;
};

saLongOrLobWriter_t saDefaultLongOrLobWriter = NULL;
saLongOrLobReader_t saDefaultLongOrLobReader = NULL;

#if !defined(SA_NO_TRIAL)

const char *sTrialText =
	"Thank you for trying SQLAPI++ Library.\n"
	"\n"
	"This version is for evaluation purpose only.\n"
	"You can register SQLAPI++ using online registration service.\n"
	"\n"
	"For additional information visit:\n"
	"    SQLAPI++ Home (http://www.sqlapi.com)\n"
	"For help on using the Library e-mail to:\n"
	"    howto@sqlapi.com";

const char *sTrialCaption =
	"SQLAPI++ Registration Reminder";

static void CheckTrial()
{
	static bool bCheckedTrial = false;
	if(!bCheckedTrial)
	{
		#if defined(WIN32) || defined(_WINDOWS)
		::MessageBox(NULL, 
			sTrialText,
			sTrialCaption, 0);
		bCheckedTrial = true;
		#else	// never set bCheckedTrial = true; in Linux/Unix
		srand((unsigned)time(NULL));
		int nRand = rand();
		if(nRand % 5 == 0)
			SAException::throwUserException(-1, "Trial version exception:\n%s", sTrialText);
		printf("%s\n\n", sTrialText);
		#endif	// defined(WIN32) || defined(_WINDOWS)
	}
}

#endif	// !defined(SA_NO_TRIAL)

//////////////////////////////////////////////////////////////////////
// SAString Class
//////////////////////////////////////////////////////////////////////

// For an empty string, m_pchData will point here
// (note: avoids special case of checking for NULL m_pchData)
// empty string data (and locked)
static int _saInitData[] = {
	0,	// pConvertedData
#ifdef SA_UNICODE
	0,	// nBinaryDataLengthDiff
#endif	// SA_UNICODE
	-1,	// nRefs
	0,	// nDataLength
	0,	// nAllocLength
	0	// SAChar data[nAllocLength]
};
static SAStringData *_saDataNil = (SAStringData *)&_saInitData;
static const SAChar *_saPchNil = (const SAChar *)(((unsigned char*)&_saInitData)+sizeof(SAStringData));
// special function to make saEmptyString work even during initialization
static const SAString &saGetEmptyString()
{
	return *(SAString *)&_saPchNil;
}
#define saEmptyString saGetEmptyString()

void SAString::AllocBuffer(int nLen)
// always allocate one extra character for '\0' termination
// assumes [optimistically] that data length will equal allocation length
{
	assert(nLen >= 0);
	assert(nLen <= INT_MAX-1);    // max size (enough room for 1 extra)

	if (nLen == 0)
		Init();
	else
	{
		SAStringData *pData;
		pData = (SAStringData*)
			new unsigned char[sizeof(SAStringData) + (nLen+1)*sizeof(SAChar)];
		pData->nAllocLength = nLen;

		// start of SAString special
		pData->pConvertedData = NULL;
#ifdef SA_UNICODE
		pData->nBinaryDataLengthDiff = 0;
#endif	// SA_UNICODE
		// end of SAString special

		pData->nRefs = 1;
		pData->data()[nLen] = _SA('\0');
		pData->nDataLength = nLen;
		m_pchData = pData->data();
	}
}

/*static */
void SAString::FreeData(SAStringData *pData)
{
	delete [] (unsigned char*)pData->pConvertedData;
	delete[] (unsigned char*)pData;
}

//////////////////////////////////////////////////////////////////////////////
// concatenate in place

#ifdef SA_UNICODE

void SAString::ConcatBinaryInPlace(int nSrcLenInBytes, const void *pSrcData)
{
	// concatenating an empty string is a no-op!
	if (nSrcLenInBytes == 0)
		return;

	// if a conversion has been made already, it is not valid any more
	delete [] (unsigned char*)GetData()->pConvertedData;
	GetData()->pConvertedData = NULL;

	// if the buffer is too small, or we have a width mis-match, just
	//   allocate a new buffer (slow but sure)
	int nNewLenInBytes = GetBinaryLength() + nSrcLenInBytes;
	int nBinaryDataLengthDiff = nNewLenInBytes % sizeof(SAChar);
	// allocate at least so many characters that all binary data could be stored (round up if necessary)
	int nNewLenInChars = nNewLenInBytes / sizeof(SAChar) + (nBinaryDataLengthDiff? 1 : 0);
	if (GetData()->nRefs > 1 || nNewLenInChars > GetData()->nAllocLength)
	{
		// we have to grow the buffer, use the ConcatCopy routine
		SAStringData *pOldData = GetData();
		ConcatBinaryCopy(GetBinaryLength(), (const void*)m_pchData, nSrcLenInBytes, pSrcData);
		assert(pOldData != NULL);
		SAString::Release(pOldData);
	}
	else
	{
		// fast concatenation when buffer big enough
		memcpy((unsigned char*)m_pchData+GetBinaryLength(), pSrcData, nSrcLenInBytes);
		GetData()->nDataLength = nNewLenInChars;
		GetData()->nBinaryDataLengthDiff = nBinaryDataLengthDiff;
		assert(GetData()->nDataLength <= GetData()->nAllocLength);
		m_pchData[GetData()->nDataLength] = _SA('\0');
	}
}

#endif	// SA_UNICODE

void SAString::ConcatInPlace(int nSrcLen, const SAChar *lpszSrcData)
{
	//  -- the main routine for += operators

	// concatenating an empty string is a no-op!
	if (nSrcLen == 0)
		return;

	// if a conversion has been made already, it is not valid any more
	delete [] (unsigned char*)GetData()->pConvertedData;
	GetData()->pConvertedData = NULL;
	// whether we have binary data or not
	// it will no longer be binary after we apply SAChar* concatenation
#ifdef SA_UNICODE
	GetData()->nBinaryDataLengthDiff = 0;
#endif

	// if the buffer is too small, or we have a width mis-match, just
	//   allocate a new buffer (slow but sure)
	if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength)
	{
		// we have to grow the buffer, use the ConcatCopy routine
		SAStringData *pOldData = GetData();
		ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData);
		assert(pOldData != NULL);
		SAString::Release(pOldData);
	}
	else
	{
		// fast concatenation when buffer big enough
		memcpy(m_pchData+GetData()->nDataLength, lpszSrcData, nSrcLen*sizeof(SAChar));
		GetData()->nDataLength += nSrcLen;
		assert(GetData()->nDataLength <= GetData()->nAllocLength);
		m_pchData[GetData()->nDataLength] = '\0';
	}
}

const SAString &SAString::operator+=(const SAChar *lpsz)
{
	ConcatInPlace(SafeStrlen(lpsz), lpsz);
	return *this;
}

const SAString &SAString::operator+=(SAChar ch)
{
	ConcatInPlace(1, &ch);
	return *this;
}

#ifdef SA_UNICODE
const SAString &SAString::operator+=(char ch)
{
	*this += (SAChar)ch;
	return *this;
}
#endif	// SA_UNICODE


const SAString& SAString::operator+=(const SAString &string)
{
#ifdef SA_UNICODE

	// Under Unicode we should be aware that *this or string (or both)
	// can be binary string with length not being multiply of sizeof(SAChar),
	// so we should concatinate bytes, not characters
	ConcatBinaryInPlace(string.GetBinaryLength(), (const void*)string);
	return *this;

#else	// !SA_UNICODE

	// byte == character in non-Unicode build
	ConcatInPlace(string.GetData()->nDataLength, string.m_pchData);
	return *this;

#endif	// !SA_UNICODE
}

///////////////////////////////////////////////////////////////////////////////
// Advanced direct buffer access

SAChar *SAString::GetBuffer(int nMinBufLength)
{
	assert(nMinBufLength >= 0);

	if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)
	{
		// we have to grow the buffer
		SAStringData *pOldData = GetData();
		int nOldLen = GetData()->nDataLength;   // AllocBuffer will tromp it
		if (nMinBufLength < nOldLen)
			nMinBufLength = nOldLen;
		AllocBuffer(nMinBufLength);
		memcpy(m_pchData, pOldData->data(), (nOldLen+1)*sizeof(SAChar));
		GetData()->nDataLength = nOldLen;
		SAString::Release(pOldData);
	}
	assert(GetData()->nRefs <= 1);

	// return a pointer to the character storage for this string
	assert(m_pchData != NULL);
	return m_pchData;
}

void SAString::ReleaseBuffer(int nNewLength)
{
	CopyBeforeWrite();  // just in case GetBuffer was not called

	if (nNewLength == -1)
		nNewLength = sa_strlen(m_pchData); // zero terminated

	assert(nNewLength <= GetData()->nAllocLength);
	GetData()->nDataLength = nNewLength;
	m_pchData[nNewLength] = '\0';

#ifdef SA_UNICODE
	GetData()->nBinaryDataLengthDiff = 0;
#endif	// SA_UNICODE
}

SAChar *SAString::LockBuffer()
{
	SAChar *lpsz = GetBuffer(0);
	GetData()->nRefs = -1;
	return lpsz;
}

void SAString::UnlockBuffer()
{
	assert(GetData()->nRefs == -1);
	if (GetData() != _saDataNil)
		GetData()->nRefs = 1;
}

void SAString::CopyBeforeWrite()
{
	if (GetData()->nRefs > 1)
	{
		SAStringData *pData = GetData();
		Release();
		AllocBuffer(pData->nDataLength);
		memcpy(m_pchData, pData->data(), (pData->nDataLength+1)*sizeof(SAChar));
	}
	// start of SAString special
	else
	{
		// if a conversion has been made already, it is not valid any more
		delete [] (unsigned char*)GetData()->pConvertedData;
		GetData()->pConvertedData = NULL;

#ifdef SA_UNICODE
		GetData()->nBinaryDataLengthDiff = 0;
#endif	// SA_UNICODE
	}
	// end of SAString special
	assert(GetData()->nRefs <= 1);
}

void SAString::AllocBeforeWrite(int nLen)
{
	if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
	{
		Release();
		AllocBuffer(nLen);
	}
	// start of SAString special
	else
	{
		// if a conversion has been made already, it is not valid any more
		delete [] (unsigned char*)GetData()->pConvertedData;
		GetData()->pConvertedData = NULL;

#ifdef SA_UNICODE
		GetData()->nBinaryDataLengthDiff = 0;
#endif	// SA_UNICODE
	}
	// end of SAString special
	assert(GetData()->nRefs <= 1);
}

void SAString::Release()
{
	if (GetData() != _saDataNil)
	{
		assert(GetData()->nRefs != 0);
		if(--GetData()->nRefs <= 0)
			FreeData(GetData());
		Init();
	}
}

/*static */
void SAString::Release(SAStringData *pData)
{
	if (pData != _saDataNil)
	{
		assert(pData->nRefs != 0);
		if (--pData->nRefs <= 0)
			FreeData(pData);
	}
}

void SAString::Init()
{
	m_pchData = saEmptyString.m_pchData;
}

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

SAStringData *SAString::GetData() const
{
	assert(m_pchData != NULL);
	return ((SAStringData *)m_pchData)-1;
}

SAString::SAString()
{
	Init();
}

SAString::SAString(const SAString &stringSrc)
{
	assert(stringSrc.GetData()->nRefs != 0);
	if (stringSrc.GetData()->nRefs >= 0)
	{
		assert(stringSrc.GetData() != _saDataNil);
		m_pchData = stringSrc.m_pchData;
		++GetData()->nRefs;
	}
	else
	{
		Init();
		*this = stringSrc;	//*this = stringSrc.m_pchData; - not right, will not copy strings with embedded '\0'
	}
}

SAString::SAString(const SAChar *lpsz)
{
	Init();

⌨️ 快捷键说明

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