database.cpp
上传用户:tt_chan
上传日期:2009-12-03
资源大小:4523k
文件大小:8k
源码类别:

模拟服务器

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "database.h"
  3. /*
  4. Implement CDatabase methods
  5. */
  6. CDatabase::CDatabase()
  7. {
  8. m_hEnv = NULL;
  9. }
  10. CDatabase::~CDatabase()
  11. {
  12. }
  13. bool CDatabase::Init()
  14. {
  15. if ( SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_hEnv ) != SQL_SUCCESS )
  16.    return false;
  17.    if ( SQLSetEnvAttr( m_hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER ) != SQL_SUCCESS )
  18.    return false;
  19.    return true;
  20. }
  21. void CDatabase::Uninit()
  22. {
  23. if ( m_hEnv )
  24. {
  25. SQLFreeHandle( SQL_HANDLE_ENV, m_hEnv );
  26. m_hEnv = NULL;
  27. }
  28. }
  29. void CDatabase::EnumDSN( void (*pfnEnum)( char *pSrcName, char *pSrcDesc ) )
  30. {
  31. int nResult;
  32. int nDirection = SQL_FETCH_FIRST;
  33. char szName[DB_MAXBUF], szDesc[DB_MAXBUF];
  34. int  nNameLen, nDescLen;
  35. while ( true )
  36. {
  37. nResult = SQLDataSourcesA( m_hEnv, 
  38.   nDirection, 
  39.   (byte *) szName, DB_MAXBUF, (short *) &nNameLen,
  40.   (byte *) szDesc, DB_MAXBUF, (short *) &nDescLen );
  41. if ( nResult == SQL_ERROR || nResult == SQL_NO_DATA )
  42. break;
  43. pfnEnum( szName, szDesc );
  44. nDirection = SQL_FETCH_NEXT;
  45. }
  46. }
  47. CConnection * CDatabase::CreateConnection( char *pDSN, char *pID, char *pPassword )
  48. {
  49. CConnection *pConn = new CConnection;
  50. if ( pConn == NULL )
  51. return NULL;
  52. if ( pConn->Init( m_hEnv, pDSN, pID, pPassword ) == false )
  53. {
  54. delete pConn;
  55. return NULL;
  56. }
  57. return pConn;
  58. }
  59. void CDatabase::DestroyConnection( CConnection *pConn )
  60. {
  61. pConn->Uninit();
  62. delete pConn;
  63. }
  64. /*
  65. Implement diagnostic record functions
  66. */
  67. static void (*g_pfnRecord)( char *pState, int nErrCode, char *pDesc );
  68. void CDatabase::SetDiagRec( void (*pfnRecord)( char *pState, int nErrCode, char *pDesc ) )
  69. {
  70. g_pfnRecord = pfnRecord;
  71. }
  72. void CDatabase::UnsetDiagRec()
  73. {
  74. g_pfnRecord = NULL;
  75. }
  76. void CDatabase::DiagRec( int nHandleType, SQLHANDLE hHandle )
  77. {
  78. if ( g_pfnRecord == NULL )
  79. return;
  80. char szState[SQL_SQLSTATE_SIZE + 1];
  81. char szDesc[SQL_MAX_MESSAGE_LENGTH + 1];
  82. int  nDescLen;
  83. int  nNativeError;
  84. int  nResult;
  85. int  nRecCnt = 1;
  86. while ( true )
  87. {
  88. nResult = SQLGetDiagRecA( nHandleType, 
  89.  hHandle, 
  90.  nRecCnt++, 
  91.  (byte *) szState, 
  92.  (long *) &nNativeError, 
  93.  (byte *) szDesc, 
  94.  SQL_MAX_MESSAGE_LENGTH,
  95.  (short *) &nDescLen );
  96. if ( nResult == SQL_NO_DATA || nResult == SQL_ERROR || nResult == SQL_INVALID_HANDLE )
  97. break;
  98. g_pfnRecord( szState, nNativeError, szDesc );
  99. }
  100. }
  101. /*
  102. Implement CConnection methods
  103. */
  104. CConnection::CConnection()
  105. {
  106. m_hDBConn = NULL;
  107. }
  108. CConnection::~CConnection()
  109. {
  110. }
  111. bool CConnection::Init( SQLHENV hEnv, char *pDSN, char *pID, char *pPassword )
  112. {
  113. int nResult;
  114. nResult = SQLAllocHandle( SQL_HANDLE_DBC, hEnv, &m_hDBConn );
  115. if ( nResult != SQL_SUCCESS )
  116. {
  117. CDatabase::DiagRec( SQL_HANDLE_ENV, hEnv );
  118. return false;
  119. }
  120. nResult = SQLConnectA( m_hDBConn, 
  121.   (byte *) pDSN, SQL_NTS, 
  122.   (byte *) pID, SQL_NTS, 
  123.   (byte *) pPassword, SQL_NTS );
  124. if ( nResult != SQL_SUCCESS )
  125. {
  126. CDatabase::DiagRec( SQL_HANDLE_DBC, m_hDBConn );
  127. if ( nResult != SQL_SUCCESS_WITH_INFO )
  128. return false;
  129. }
  130. return true;
  131. }
  132. void CConnection::Uninit()
  133. {
  134. if ( m_hDBConn )
  135. {
  136. SQLDisconnect( m_hDBConn );
  137. SQLFreeHandle( SQL_HANDLE_DBC, m_hDBConn );
  138. m_hDBConn = NULL;
  139. }
  140. }
  141. CRecordset * CConnection::CreateRecordset()
  142. {
  143. CRecordset *pRec = new CRecordset;
  144. if ( pRec == NULL )
  145. return NULL;
  146. if ( pRec->Init( m_hDBConn ) == false )
  147. {
  148. delete pRec;
  149. return NULL;
  150. }
  151. return pRec;
  152. }
  153. void CConnection::DestroyRecordset( CRecordset *pRec )
  154. {
  155. pRec->Uninit();
  156. delete pRec;
  157. }
  158. /*
  159. Implement CRecordset methods
  160. */
  161. CRecordset::CRecordset()
  162. {
  163. m_hStmt = NULL;
  164. m_nRowCount = 0;
  165. m_nCols = 0;
  166. m_pColInfo = NULL;
  167. m_pColData = NULL;
  168. }
  169. CRecordset::~CRecordset()
  170. {
  171. }
  172. bool CRecordset::Init( SQLHDBC hDBConn )
  173. {
  174. if ( SQLAllocHandle( SQL_HANDLE_STMT, hDBConn, &m_hStmt ) != SQL_SUCCESS )
  175. {
  176. CDatabase::DiagRec( SQL_HANDLE_STMT, m_hStmt );
  177. return false;
  178. }
  179. return true;
  180. }
  181. void CRecordset::Uninit()
  182. {
  183. if ( m_pColInfo )
  184. {
  185. delete[] m_pColInfo;
  186. m_pColInfo = NULL;
  187. }
  188. if ( m_pColData )
  189. {
  190. delete[] m_pColData;
  191. m_pColData = NULL;
  192. }
  193. if ( m_hStmt )
  194. {
  195. SQLFreeHandle( SQL_HANDLE_STMT, m_hStmt );
  196. m_hStmt = NULL;
  197. }
  198. }
  199. bool CRecordset::Execute( char *pQuery )
  200. {
  201. int nResult;
  202. int nCount;
  203. nResult = SQLExecDirectA( m_hStmt, (byte *) pQuery, SQL_NTS );
  204. if ( nResult != SQL_SUCCESS )
  205. {
  206. CDatabase::DiagRec( SQL_HANDLE_STMT, m_hStmt );
  207. if ( nResult != SQL_SUCCESS_WITH_INFO )
  208. return false;
  209. }
  210. m_nCols = 0;
  211. nResult = SQLNumResultCols( m_hStmt, (short *) &m_nCols );
  212. if ( nResult != SQL_SUCCESS && nResult != SQL_SUCCESS_WITH_INFO )
  213. {
  214. CDatabase::DiagRec( SQL_HANDLE_STMT, m_hStmt );
  215. return false;
  216. }
  217. // If cols is 0, the statement probably was a non-SELECT simply return.
  218. if ( m_nCols == 0 )
  219. {
  220. m_nRowCount = 0;
  221. SQLRowCount( m_hStmt, (long *) &m_nRowCount );
  222. return true;
  223. }
  224. m_pColInfo = new CColumnInfo[ m_nCols ];
  225. if ( m_pColInfo == NULL )
  226. return false;
  227. for ( nCount = 0; nCount < m_nCols; nCount++ )
  228. {
  229. nResult = SQLDescribeColA( m_hStmt, 
  230.   nCount + 1, 
  231.   (byte *) m_pColInfo[nCount].szColName, DB_MAXBUF,
  232.   (short *) &m_pColInfo[nCount].nColNameSize,
  233.   (short *) &m_pColInfo[nCount].nColType,
  234.   (ULONG *) &m_pColInfo[nCount].nColSize,
  235.   (short *) &m_pColInfo[nCount].nAllowDecimalDigit,
  236.   (short *) &m_pColInfo[nCount].nAllowNull );
  237. if ( nResult != SQL_SUCCESS )
  238. {
  239. CDatabase::DiagRec( SQL_HANDLE_STMT, m_hStmt );
  240. if ( nResult != SQL_SUCCESS_WITH_INFO )
  241. return false;
  242. }
  243. }
  244. m_pColData = new CColumnData[ m_nCols ];
  245. if ( m_pColData == NULL )
  246. return false;
  247. for ( nCount = 0; nCount < m_nCols; nCount++ )
  248. {
  249. if ( m_pColData[nCount].AllocMemory( m_pColInfo[nCount].nColSize + 1 ) == false )
  250. return false;
  251. nResult = SQLBindCol( m_hStmt, 
  252.   nCount + 1, 
  253.   SQL_C_CHAR,
  254.   m_pColData[nCount].pData,
  255.   m_pColInfo[nCount].nColSize + 1,
  256.   (long *) &m_pColData[nCount].nDataSize );
  257. if ( nResult != SQL_SUCCESS )
  258. {
  259. CDatabase::DiagRec( SQL_HANDLE_STMT, m_hStmt );
  260. if ( nResult != SQL_SUCCESS_WITH_INFO )
  261. return false;
  262. }
  263. }
  264. return true;
  265. }
  266. bool CRecordset::Fetch()
  267. {
  268. int nResult;
  269. nResult = SQLFetch( m_hStmt );
  270. if ( nResult != SQL_SUCCESS )
  271. {
  272. CDatabase::DiagRec( SQL_HANDLE_STMT, m_hStmt );
  273. if ( nResult != SQL_SUCCESS_WITH_INFO )
  274. return false;
  275. }
  276. return true;
  277. }
  278. int CRecordset::GetRowCount()
  279. {
  280. return m_nRowCount;
  281. }
  282. int CRecordset::GetCols()
  283. {
  284. return m_nCols;
  285. }
  286. char * CRecordset::Get( char *pColName )
  287. {
  288. for ( int nCount = 0; nCount < m_nCols; nCount++ )
  289. {
  290. if ( stricmp( m_pColInfo[nCount].szColName, pColName ) == 0 )
  291. return m_pColData[nCount].pData;
  292. }
  293. return NULL;
  294. }
  295. char * CRecordset::Get( int nCol )
  296. {
  297. if ( nCol < 0 || nCol >= m_nCols )
  298. return NULL;
  299. return m_pColData[ nCol ].pData;
  300. }
  301. CRecordset::CColumnInfo * CRecordset::GetColInfo( char *pColName )
  302. {
  303. for ( int nCount = 0; nCount < m_nCols; nCount++ )
  304. {
  305. if ( stricmp( m_pColInfo[nCount].szColName, pColName ) == 0 )
  306. return &m_pColInfo[nCount];
  307. }
  308. return NULL;
  309. }
  310. CRecordset::CColumnInfo * CRecordset::GetColInfo( int nCol )
  311. {
  312. if ( nCol < 0 || nCol >= m_nCols )
  313. return NULL;
  314. return &m_pColInfo[nCol];
  315. }
  316. /*
  317. Implement CRecordset::CColumnInfo methods
  318. */
  319. CRecordset::CColumnInfo::CColumnInfo()
  320. {
  321. nColNameSize = 0;
  322. szColName[0] = '';
  323. nColType = 0;
  324. nColSize = 0;
  325. nAllowDecimalDigit = 0;
  326. nAllowNull = 0;
  327. }
  328. CRecordset::CColumnInfo::~CColumnInfo()
  329. {
  330. }
  331. /*
  332. Implement CRecordset::CColumnData methods
  333. */
  334. CRecordset::CColumnData::CColumnData()
  335. {
  336. pData = NULL;
  337. nDataSize = 0;
  338. }
  339. CRecordset::CColumnData::~CColumnData()
  340. {
  341. if ( pData )
  342. delete[] pData;
  343. }
  344. bool CRecordset::CColumnData::AllocMemory( int nSize )
  345. {
  346. pData = new char[ nSize ];
  347. if ( pData == NULL )
  348. return false;
  349. memset( pData, 0, nSize );
  350. return true;
  351. }