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

📄 odbcinfo.cpp

📁 《Visual C++ Bible》或者说是《Visual C++ 宝典》的对应的源码文件
💻 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 + -