📄 odbcinfo.cpp
字号:
#include "stdafx.h"
#include "odbcinfo.hpp"
#define MAX_COLNAME 50
CODBCInfo::CODBCInfo(LPCSTR lpszDSN)
{
SQLRETURN rc;
m_henv = NULL;
m_hdbc = NULL;
m_bIsConnected = FALSE;
m_bIsInitialized = FALSE;
if (SQL_SUCCESS == (rc = ::SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv)))
{
if (SQL_SUCCESS == (rc = ::SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER)))
{
if (SQL_SUCCESS == (rc = ::SQLAllocHandle(SQL_HANDLE_DBC, m_henv, &m_hdbc)))
{
rc = ::SQLConnect(m_hdbc,
(unsigned char*)lpszDSN, SQL_NTS,
(unsigned char*)"", SQL_NTS, (unsigned char*)"", SQL_NTS);
if ((SQL_SUCCESS == rc)
|| (SQL_SUCCESS_WITH_INFO == rc))
{
m_bIsConnected = TRUE;
m_bIsInitialized = InternalGetTypeInfo();
}
}
}
}
}
CODBCInfo::~CODBCInfo()
{
if (m_bIsInitialized)
{
if (m_henv)
{
if (m_hdbc)
{
if (m_bIsConnected)
{
::SQLDisconnect(m_hdbc);
m_bIsConnected = FALSE;
}
::SQLFreeHandle(SQL_HANDLE_DBC, m_hdbc);
m_hdbc = NULL;
}
::SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
m_henv = NULL;
}
m_bIsInitialized = FALSE;
}
POSITION pos1;
WORD wKey;
CMapStringToOb* pmapColNameToDataAttr;
POSITION pos2;
CString strKey;
CDBVariant* pvarValue;
for (pos1 = m_mapDataTypeToDataAttrMap.GetStartPosition(); pos1 != NULL;)
{
m_mapDataTypeToDataAttrMap.GetNextAssoc(pos1, wKey, (CObject*&)pmapColNameToDataAttr);
for (pos2 = pmapColNameToDataAttr->GetStartPosition(); pos2 != NULL;)
{
pmapColNameToDataAttr->GetNextAssoc(pos2, strKey, (CObject*&)pvarValue);
delete pvarValue;
}
delete pmapColNameToDataAttr;
}
}
short CODBCInfo::GetFieldTypeFromSQLType(short nSQLType)
{
short nFieldType;
switch (nSQLType)
{
case SQL_BIT:
nFieldType = SQL_C_BIT;
break;
case SQL_TINYINT:
nFieldType = SQL_C_UTINYINT;
break;
case SQL_SMALLINT:
nFieldType = SQL_C_SSHORT;
break;
case SQL_INTEGER:
nFieldType = SQL_C_SLONG;
break;
case SQL_REAL:
nFieldType = SQL_C_FLOAT;
break;
case SQL_FLOAT:
case SQL_DOUBLE:
nFieldType = SQL_C_DOUBLE;
break;
case SQL_DATE:
case SQL_TIME:
case SQL_TIMESTAMP:
nFieldType = SQL_C_TIMESTAMP;
break;
case SQL_NUMERIC:
case SQL_DECIMAL:
case SQL_BIGINT:
case SQL_CHAR:
case SQL_VARCHAR:
case SQL_LONGVARCHAR:
nFieldType = SQL_C_CHAR;
break;
case SQL_BINARY:
case SQL_VARBINARY:
case SQL_LONGVARBINARY:
nFieldType = SQL_C_BINARY;
break;
default:
ASSERT(FALSE);
}
return nFieldType;
}
void* CODBCInfo::GetDataBuffer(CDBVariant* pvarValue,
short nFieldType, int* pnLen, short nSQLType, UDWORD nPrecision)
{
void* pvData = NULL;
switch (nFieldType)
{
case SQL_C_BIT:
pvData = &pvarValue->m_boolVal;
pvarValue->m_dwType = DBVT_BOOL;
*pnLen = sizeof(pvarValue->m_boolVal);
break;
case SQL_C_UTINYINT:
pvData = &pvarValue->m_chVal;
pvarValue->m_dwType = DBVT_UCHAR;
*pnLen = sizeof(pvarValue->m_chVal);
break;
case SQL_C_SSHORT:
pvData = &pvarValue->m_iVal;
pvarValue->m_dwType = DBVT_SHORT;
*pnLen = sizeof(pvarValue->m_iVal);
break;
case SQL_C_SLONG:
pvData = &pvarValue->m_lVal;
pvarValue->m_dwType = DBVT_LONG;
*pnLen = sizeof(pvarValue->m_lVal);
break;
case SQL_C_FLOAT:
pvData = &pvarValue->m_fltVal;
pvarValue->m_dwType = DBVT_SINGLE;
*pnLen = sizeof(pvarValue->m_fltVal);
break;
case SQL_C_DOUBLE:
pvData = &pvarValue->m_dblVal;
pvarValue->m_dwType = DBVT_DOUBLE;
*pnLen = sizeof(pvarValue->m_dblVal);
break;
case SQL_C_TIMESTAMP:
pvData = pvarValue->m_pdate = new TIMESTAMP_STRUCT;
pvarValue->m_dwType = DBVT_DATE;
*pnLen = sizeof(*pvarValue->m_pdate);
break;
case SQL_C_CHAR:
{
pvarValue->m_pstring = new CString;
pvarValue->m_dwType = DBVT_STRING;
// Need to have at least a length of 1 for the NULL terminator
*pnLen = 1;
if ((nSQLType != SQL_LONGVARCHAR)
&& (nSQLType != SQL_LONGVARBINARY))
{
*pnLen = nPrecision + 1;
// If type is Numeric or Decimal add 2 bytes for decimal
// point and sign
if ((nSQLType == SQL_NUMERIC)
|| (nSQLType == SQL_DECIMAL))
{
*pnLen += 2;
}
}
pvData = pvarValue->m_pstring->GetBufferSetLength(*pnLen);
}
break;
case SQL_C_BINARY:
pvarValue->m_pbinary = new CLongBinary;
pvarValue->m_dwType = DBVT_BINARY;
if (nSQLType == SQL_LONGVARBINARY)
{
*pnLen = 1;
}
else
{
*pnLen = nPrecision;
}
pvarValue->m_pbinary->m_hData = ::GlobalAlloc(GMEM_MOVEABLE, *pnLen);
pvarValue->m_pbinary->m_dwDataLength = *pnLen;
pvData = ::GlobalLock(pvarValue->m_pbinary->m_hData);
break;
default: ASSERT(FALSE);
}
return pvData;
}
long CODBCInfo::GetData(SQLHSTMT hstmt, short nFieldIndex, short nFieldType, LPVOID pvData, int nLen, short nSQLType)
{
UNUSED(nSQLType);
long nActualSize = -1;
SQLRETURN rc;
if (SQL_SUCCESS != (rc = ::SQLGetData(hstmt, nFieldIndex, nFieldType, pvData, nLen, &nActualSize)))
{
UCHAR lpszMsg[SQL_MAX_MESSAGE_LENGTH];
UCHAR lpszState[SQL_SQLSTATE_SIZE];
CString strMsg;
CString strState;
SDWORD lNative;
SWORD nOutlen;
::SQLError(m_henv, m_hdbc, hstmt, lpszState, &lNative,
lpszMsg, SQL_MAX_MESSAGE_LENGTH-1, &nOutlen);
TRACE1("SQLGetData failed: %s\n", lpszMsg);
}
return nActualSize;
}
BOOL CODBCInfo::InternalGetTypeInfo()
{
BOOL bSuccess = FALSE;
SQLRETURN rc;
SQLHSTMT hstmt = NULL;
int aiDataTypes[] = {
SQL_CHAR,
SQL_NUMERIC,
SQL_DECIMAL,
SQL_INTEGER,
SQL_SMALLINT,
SQL_FLOAT,
SQL_REAL,
SQL_DOUBLE,
#if (ODBCVER >= 0x0300)
SQL_DATETIME,
#endif
SQL_VARCHAR
};
int nDataTypes = (sizeof(aiDataTypes) / sizeof(aiDataTypes[0]));
for (int iCurrDataType = 0; iCurrDataType < nDataTypes; iCurrDataType++)
{
CMapStringToOb* pmapColNameToDataAttr = new CMapStringToOb();
m_mapDataTypeToDataAttrMap.SetAt(aiDataTypes[iCurrDataType], (CObject*)pmapColNameToDataAttr);
if (SQL_SUCCESS == (rc = ::SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &hstmt)))
{
if (SQL_SUCCESS == (rc = ::SQLGetTypeInfo(hstmt, aiDataTypes[iCurrDataType])))
{
if (SQL_SUCCESS == (rc = ::SQLFetch(hstmt)))
{
SWORD FAR iNumResultCols = 0;
if (SQL_SUCCESS == (rc = ::SQLNumResultCols(hstmt, &iNumResultCols)))
{
for (int iCurrDataTypeAttr = 1; iCurrDataTypeAttr <= iNumResultCols; iCurrDataTypeAttr++)
{
char lpszColName[MAX_COLNAME + 1];
SWORD nLen;
SWORD nSQLType;
UDWORD nPrecision;
SWORD nScale;
SWORD nNullability;
if (SQL_SUCCESS == (rc = ::SQLDescribeCol(hstmt, iCurrDataTypeAttr, (UCHAR*)lpszColName, MAX_COLNAME, &nLen,
&nSQLType, &nPrecision, &nScale, &nNullability)))
{
// Determine the default field type and get the data buffer
short nFieldType = GetFieldTypeFromSQLType(nSQLType);
CDBVariant* pvarValue = new CDBVariant();
pvarValue->Clear();
int nGetDataBufferLen = 0;
void* pvData = GetDataBuffer(pvarValue, nFieldType,
&nGetDataBufferLen, nSQLType, nPrecision);
long nActualSize = GetData(hstmt, iCurrDataTypeAttr,
nFieldType, pvData, nGetDataBufferLen, nSQLType);
if (nFieldType == SQL_C_CHAR)
{
// Release the string buffer
CString strValue = (*pvarValue->m_pstring);
strValue.ReleaseBuffer(nActualSize < nLen ? nActualSize : nLen);
}
pmapColNameToDataAttr->SetAt(lpszColName, (CObject*)pvarValue);
}
}
}
}
}
::SQLFreeHandle(SQL_HANDLE_STMT, &hstmt);
}
}
bSuccess = (0 < m_mapDataTypeToDataAttrMap.GetCount());
return bSuccess;
}
BOOL CODBCInfo::GetTypeInfo(UINT iDataType, LPCSTR lpszColName, CDBVariant** ppvarValue)
{
BOOL bSuccess = FALSE;
if (m_bIsInitialized)
{
CMapStringToOb* pmapColNameToDataAttr;
if (m_mapDataTypeToDataAttrMap.Lookup(iDataType, (CObject*&)pmapColNameToDataAttr))
{
if (pmapColNameToDataAttr->Lookup(lpszColName, (CObject*&)*ppvarValue))
{
bSuccess = TRUE;
}
}
}
return bSuccess;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -