📄 sqldata.cpp
字号:
//////////////////////////////////////////////////////////////////////
//
// DB2 Access Object Version 1.0
//
// Developer: Jeff Lee
// Jan 10, 2003
//
//////////////////////////////////////////////////////////////////////
#include "SqlData.h"
#include "Sqldb2.h"
#if defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__)
#include <extension.h>
#endif
#ifdef _MSC_VER
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#endif // _MSC_VER
#pragma warning(disable:4786)
#pragma warning(disable:4312)
//////////////////////////////////////////////////////////////////////
// class CSqlVariant - The base class that represents a variant
// which has standard SQL data type
//////////////////////////////////////////////////////////////////////
// default data conversion table:
const CSqlVariant::CDataType CSqlVariant::m_tblDataType[] =
{
{ SQL_BIGINT, SQL_C_SBIGINT, sizeof(SQLBIGINT), 20 },
{ SQL_BLOB, SQL_C_BINARY, 0, 0 },
{ SQL_BLOB_LOCATOR, SQL_C_BLOB_LOCATOR, sizeof(SQLINTEGER), 11 },
{ SQL_CHAR, SQL_C_CHAR, 0, 0 },
{ SQL_BINARY, SQL_C_BINARY, 0, 0 },
{ SQL_CLOB, SQL_C_CHAR, 0, 0 },
{ SQL_CLOB_LOCATOR, SQL_C_CLOB_LOCATOR, sizeof(SQLINTEGER), 11 },
{ SQL_TYPE_DATE, SQL_C_TYPE_DATE, sizeof(DATE_STRUCT), 10 },
{ SQL_DBCLOB, SQL_C_DBCHAR, 0, 0 },
{ SQL_DBCLOB_LOCATOR, SQL_C_DBCLOB_LOCATOR, sizeof(SQLINTEGER), 11 },
{ SQL_DECIMAL, SQL_C_CHAR, 0, 0 },
{ SQL_DOUBLE, SQL_C_DOUBLE, sizeof(SQLDOUBLE), 22 },
{ SQL_FLOAT, SQL_C_DOUBLE, sizeof(SQLDOUBLE), 22 },
{ SQL_GRAPHIC, SQL_C_DBCHAR, 0, 0 },
{ SQL_INTEGER, SQL_C_LONG, sizeof(SQLINTEGER), 11 },
{ SQL_LONGVARCHAR, SQL_C_CHAR, 0, 0 },
{ SQL_LONGVARBINARY, SQL_C_BINARY, 0, 0 },
{ SQL_LONGVARGRAPHIC, SQL_C_DBCHAR, 0, 0 },
{ SQL_NUMERIC, SQL_C_CHAR, 0, 0 },
{ SQL_REAL, SQL_C_FLOAT, sizeof(SQLREAL), 13 },
{ SQL_SMALLINT, SQL_C_SHORT, sizeof(SQLSMALLINT), 6 },
{ SQL_TYPE_TIME, SQL_C_TYPE_TIME, sizeof(TIME_STRUCT), 8 },
{ SQL_TYPE_TIMESTAMP, SQL_C_TYPE_TIMESTAMP, sizeof(TIMESTAMP_STRUCT), 19 },
{ SQL_VARCHAR, SQL_C_CHAR, 0, 0 },
{ SQL_VARBINARY, SQL_C_BINARY, 0, 0 },
{ SQL_VARGRAPHIC, SQL_C_DBCHAR, 0, 0 }
};
// For an uninitialized CSqlVariant object, its m_pData points to here
const CSqlVariant::CSqlBuffer CSqlVariant::m_defData =
{ SQL_DEFAULT, 0, 0, SQL_C_DEFAULT, 0, 1, SQL_NULL_DATA };
CSqlVariant::CSqlVariant()
{
InitData();
}
CSqlVariant::CSqlVariant(const CSqlVariant& rVar)
{
InitData();
CopyData(rVar);
}
CSqlVariant::~CSqlVariant()
{
FreeBuffer();
}
// Allocates buffer for the variant
BOOL CSqlVariant::AllocBuffer(SQLINTEGER nDataSize)
{
FreeBuffer();
if (nDataSize <= 0)
return FALSE;
SQLINTEGER nSize = sizeof(CSqlBuffer) + nDataSize + 4;
m_pData = (CSqlBuffer*) new SQLCHAR[nSize];
if (!m_pData)
{
InitData();
return FALSE;
}
::memset(m_pData, 0, nSize);
m_pData->nBufferSize = nDataSize;
m_pData->nRefs = 1;
m_pData->nDataType = SQL_C_DEFAULT;
m_pData->nSqlType = SQL_DEFAULT;
m_pData->nIndicator = SQL_NULL_DATA;
return TRUE;
}
// Frees buffer
void CSqlVariant::FreeBuffer()
{
if (!IsDefault())
{
ASSERT(m_pData != NULL);
m_pData->nRefs--;
if (!m_pData->nRefs)
delete[] (SQLCHAR*)m_pData;
InitData();
}
}
// Allocates the buffer according to SQL data type and precision
BOOL CSqlVariant::CreateBuffer(SQLSMALLINT nSqlType, SQLUINTEGER nPrecision)
{
// find the data type in the default conversion table
for (int n=0; n<MAX_SQL_TYPE; n++)
if (nSqlType == m_tblDataType[n].nSqlType)
break;
// determine the corresponding C data type and buffer length
SQLSMALLINT nDataType;
SQLINTEGER nDataSize;
if (n < MAX_SQL_TYPE) // the data type was found
{
nDataType = m_tblDataType[n].nDataType;
nDataSize = m_tblDataType[n].nDataSize;
if (nDataSize <= 0) // this is not a fix-length data type
{
nDataSize = nPrecision + 1; // add 1 for the terminated null
if (SQL_DECIMAL == nSqlType ||
SQL_NUMERIC == nSqlType)
nDataSize += 2; // add 2 for for sign and decimal point
}
// For double-byte string, column size (precision) is in unit of double-byte,
// buffer length is in unit of single-byte.
if (SQL_C_DBCHAR == nDataType)
nDataSize <<= 1;
}
else // unknown SQL type, convert to CHAR as default
{
nDataType = SQL_C_CHAR;
nDataSize = nPrecision + 1;
}
if (!AllocBuffer(nDataSize))
return FALSE;
m_pData->nSqlType = nSqlType;
m_pData->nDataType = nDataType;
m_pData->nPrecision = nPrecision;
return TRUE;
}
// Copies object
void CSqlVariant::CopyData(const CSqlVariant& rValue)
{
if (this != &rValue)
{
FreeBuffer();
m_pData = rValue.m_pData;
if (!IsDefault())
{
ASSERT(m_pData != NULL);
m_pData->nRefs++;
}
}
}
// Unbinds the variant and frees buffer
BOOL CSqlVariant::Unbind(CSqlCommand* pStmt, int nOrdinal)
{
FreeBuffer();
return TRUE;
}
// Returns the maximum number of bytes needed to display data as a string
SQLINTEGER CSqlVariant::GetDisplaySize() const
{
SQLSMALLINT nDataType = m_pData->nDataType;
SQLINTEGER nDisplaySize = 0;
BOOL bDoubleByte = FALSE;
for (int n=0; n<MAX_SQL_TYPE; n++)
{
if (nDataType == m_tblDataType[n].nDataType)
{
nDisplaySize = m_tblDataType[n].nDisplaySize;
bDoubleByte = (SQL_C_DBCHAR == m_tblDataType[n].nDataType);
break;
}
}
if (SQL_C_TYPE_TIMESTAMP == m_pData->nDataType)
nDisplaySize += m_pData->nScale + 1;
if (nDisplaySize <= 0)
{
nDisplaySize = m_pData->nIndicator;
if (nDisplaySize < 0)
nDisplaySize = 0;
//if (nDisplaySize <= 0)
//{
// nDisplaySize = m_pData->nPrecision;
// if (nDisplaySize <= 0)
// nDisplaySize = m_pData->nBufferSize;
// else
// {
// if (SQL_DECIMAL == m_pData->nSqlType ||
// SQL_NUMERIC == m_pData->nSqlType)
// nDisplaySize += 2; // add 2 for sign and decimal point
// if (bDoubleByte)
// nDisplaySize <<= 1;
// }
//}
}
return nDisplaySize;
}
// Sets value of the variant
BOOL CSqlVariant::SetValue(const void* pValue, SQLINTEGER nValueSize)
{
ASSERT(!IsDefault());
BOOL bOK = TRUE;
SQLINTEGER nSize = nValueSize;
if (!nSize)
{
if (SQL_C_CHAR == m_pData->nDataType)
nSize = (int)::strlen((const char*) pValue);
else
nSize = GetMaxSize();
}
if (nSize > GetMaxSize())
{
nSize = GetMaxSize();
bOK = FALSE;
}
::memcpy(GetBuffer(), pValue, nSize);
m_pData->pVal[nSize] = 0;
m_pData->nIndicator = nSize;
return bOK;
}
// Sets value by converting from int
BOOL CSqlVariant::FromInteger(int nValue)
{
if (SQL_C_CHAR == m_pData->nDataType)
{
char szBuf[64];
if (m_pData->nScale > 0)
::sprintf(szBuf, "%d.%0*d", nValue, m_pData->nScale, 0);
else
::itoa(nValue, szBuf, 10);
return SetValue(szBuf, (int)::strlen(szBuf));
}
if (SQL_C_DOUBLE == m_pData->nDataType)
{
SQLDOUBLE dVal = nValue;
return SetValue(&dVal, sizeof(SQLDOUBLE));
}
if (SQL_C_FLOAT == m_pData->nDataType)
{
SQLREAL fltVal = (SQLREAL) nValue;
return SetValue(&fltVal, sizeof(SQLREAL));
}
return SetValue(&nValue, sizeof(int));
}
// Sets value by converting from double
BOOL CSqlVariant::FromDouble(double nValue)
{
if (SQL_C_CHAR == m_pData->nDataType)
{
char szBuf[64];
::sprintf(szBuf, "%.*lf", m_pData->nScale, nValue);
return SetValue(szBuf, (int)::strlen(szBuf));
}
if (SQL_C_LONG == m_pData->nDataType ||
SQL_C_SHORT == m_pData->nDataType)
{
SQLINTEGER iVal = (SQLINTEGER) nValue;
return SetValue(&iVal, sizeof(SQLINTEGER));
}
if (SQL_C_FLOAT == m_pData->nDataType)
{
SQLREAL fltVal = (SQLREAL) nValue;
return SetValue(&fltVal, sizeof(SQLREAL));
}
return SetValue(&nValue, sizeof(double));
}
// Sets value by converting from string
BOOL CSqlVariant::FromString(const char* pszValue)
{
ASSERT(!IsDefault());
switch (m_pData->nDataType)
{
case SQL_C_CHAR:
return SetValue(pszValue);
case SQL_C_LONG:
m_pData->nVal = ::atoi(pszValue);
m_pData->nIndicator = sizeof(SQLINTEGER);
break;
case SQL_C_SHORT:
m_pData->iVal = ::atoi(pszValue);
m_pData->nIndicator = sizeof(SQLSMALLINT);
break;
case SQL_C_SBIGINT:
#if defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__)
{
char* pEndOfString;
m_pData->lVal = ::strtoll(pszValue, &pEndOfString, 10);
}
#else
m_pData->lVal = ::_atoi64(pszValue);
#endif
m_pData->nIndicator = sizeof(SQLBIGINT);
break;
case SQL_C_DOUBLE:
m_pData->dbVal = ::atof(pszValue);
m_pData->nIndicator = sizeof(SQLDOUBLE);
break;
case SQL_C_FLOAT:
m_pData->fltVal = (SQLREAL)::atof(pszValue);
m_pData->nIndicator = sizeof(SQLREAL);
break;
case SQL_C_TYPE_DATE:
::sscanf(pszValue, "%d-%d-%d", &m_pData->dtVal.year,
&m_pData->dtVal.month, &m_pData->dtVal.day);
m_pData->nIndicator = sizeof(DATE_STRUCT);
break;
case SQL_C_TYPE_TIME:
::sscanf(pszValue, "%d:%d:%d", &m_pData->tmVal.hour,
&m_pData->tmVal.minute, &m_pData->tmVal.second);
m_pData->nIndicator = sizeof(TIME_STRUCT);
break;
case SQL_C_TYPE_TIMESTAMP:
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -