Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1073 lines
34 KiB

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #ifndef __AFXDB_H__
  11. #define __AFXDB_H__
  12. #ifdef _AFX_NO_DB_SUPPORT
  13. #error Database classes not supported in this library variant.
  14. #endif
  15. #ifndef __AFXEXT_H__
  16. #include <afxext.h>
  17. #endif
  18. #ifndef __AFXDB__H__
  19. #include <afxdb_.h> // shared header DAO database classes
  20. #endif
  21. // include standard SQL/ODBC "C" APIs
  22. #ifndef __SQL
  23. #define SQL_NOUNICODEMAP
  24. #include <sql.h> // core
  25. #endif
  26. #ifndef __SQLEXT
  27. #include <sqlext.h> // extensions
  28. #endif
  29. #ifdef _AFX_MINREBUILD
  30. #pragma component(minrebuild, off)
  31. #endif
  32. #ifndef _AFX_FULLTYPEINFO
  33. #pragma component(mintypeinfo, on)
  34. #endif
  35. #ifndef _AFX_NOFORCE_LIBS
  36. /////////////////////////////////////////////////////////////////////////////
  37. // Win32 libraries
  38. #ifdef _AFXDLL
  39. #if defined(_DEBUG) && !defined(_AFX_MONOLITHIC)
  40. #ifndef _UNICODE
  41. #pragma comment(lib, "mfcd42d.lib")
  42. #else
  43. #pragma comment(lib, "mfcd42ud.lib")
  44. #endif
  45. #endif
  46. #endif
  47. #pragma comment(lib, "odbc32.lib")
  48. #pragma comment(lib, "odbccp32.lib")
  49. #endif //!_AFX_NOFORCE_LIBS
  50. /////////////////////////////////////////////////////////////////////////////
  51. #ifdef _AFX_PACKING
  52. #pragma pack(push, _AFX_PACKING)
  53. #endif
  54. /////////////////////////////////////////////////////////////////////////////
  55. // AFXDB - MFC SQL/ODBC/Database support
  56. // Classes declared in this file
  57. //CException
  58. class CDBException; // abnormal return value
  59. //CFieldExchange
  60. class CFieldExchange; // Recordset Field Exchange
  61. //CObject
  62. class CDatabase; // Connecting to databases
  63. class CRecordset; // Data result sets
  64. //CObject
  65. //CCmdTarget;
  66. //CWnd
  67. //CView
  68. //CScrollView
  69. //CFormView
  70. class CRecordView; // view records with a form
  71. // Non CObject classes
  72. class CDBVariant;
  73. struct CRecordsetStatus;
  74. struct CFieldInfo;
  75. struct CODBCFieldInfo;
  76. struct CODBCParamInfo;
  77. /////////////////////////////////////////////////////////////////////////////
  78. // ODBC helpers
  79. // return code left in 'nRetCode'
  80. // This MACRO is now out-of-date (kept for backward compatibility)
  81. #define AFX_ODBC_CALL(SQLFunc) \
  82. do \
  83. { \
  84. } while ((nRetCode = (SQLFunc)) == SQL_STILL_EXECUTING)
  85. // Not really required, but kept for compatibilty
  86. #define AFX_SQL_SYNC(SQLFunc) \
  87. do \
  88. { \
  89. nRetCode = SQLFunc; \
  90. } while (0)
  91. // Now out-of-date (prs not used) but kept for compatibility
  92. #define AFX_SQL_ASYNC(prs, SQLFunc) AFX_ODBC_CALL(SQLFunc)
  93. // Max display length in chars of timestamp (date & time) value
  94. #define TIMESTAMP_PRECISION 23
  95. // AFXDLL support
  96. #undef AFX_DATA
  97. #define AFX_DATA AFX_DB_DATA
  98. // Miscellaneous sizing info
  99. #define MAX_CURRENCY 30 // Max size of Currency($) string
  100. #define MAX_TNAME_LEN 64 // Max size of table names
  101. #if _MFC_VER >= 0x0600
  102. #define MAX_FNAME_LEN 256 // Max size of field names
  103. #else
  104. #define MAX_FNAME_LEN 64 // Max size of field names
  105. #endif
  106. #define MAX_DBNAME_LEN 32 // Max size of a database name
  107. #define MAX_DNAME_LEN 256 // Max size of Recordset names
  108. #define MAX_CONNECT_LEN 512 // Max size of Connect string
  109. #define MAX_CURSOR_NAME 18 // Max size of a cursor name
  110. #define DEFAULT_FIELD_TYPE SQL_TYPE_NULL // pick "C" data type to match SQL data type
  111. // Timeout and net wait defaults
  112. #define DEFAULT_LOGIN_TIMEOUT 15 // seconds to before fail on connect
  113. #define DEFAULT_QUERY_TIMEOUT 15 // seconds to before fail waiting for results
  114. // Field Flags, used to indicate status of fields
  115. #define AFX_SQL_FIELD_FLAG_DIRTY 0x1
  116. #define AFX_SQL_FIELD_FLAG_NULL 0x2
  117. // Update options flags
  118. #define AFX_SQL_SETPOSUPDATES 0x0001
  119. #define AFX_SQL_POSITIONEDSQL 0x0002
  120. #define AFX_SQL_GDBOUND 0x0004
  121. /////////////////////////////////////////////////////////////////////////////
  122. // CDBException - something gone wrong
  123. // Dbkit extended error codes
  124. #define AFX_SQL_ERROR 1000
  125. #define AFX_SQL_ERROR_CONNECT_FAIL AFX_SQL_ERROR+1
  126. #define AFX_SQL_ERROR_RECORDSET_FORWARD_ONLY AFX_SQL_ERROR+2
  127. #define AFX_SQL_ERROR_EMPTY_COLUMN_LIST AFX_SQL_ERROR+3
  128. #define AFX_SQL_ERROR_FIELD_SCHEMA_MISMATCH AFX_SQL_ERROR+4
  129. #define AFX_SQL_ERROR_ILLEGAL_MODE AFX_SQL_ERROR+5
  130. #define AFX_SQL_ERROR_MULTIPLE_ROWS_AFFECTED AFX_SQL_ERROR+6
  131. #define AFX_SQL_ERROR_NO_CURRENT_RECORD AFX_SQL_ERROR+7
  132. #define AFX_SQL_ERROR_NO_ROWS_AFFECTED AFX_SQL_ERROR+8
  133. #define AFX_SQL_ERROR_RECORDSET_READONLY AFX_SQL_ERROR+9
  134. #define AFX_SQL_ERROR_SQL_NO_TOTAL AFX_SQL_ERROR+10
  135. #define AFX_SQL_ERROR_ODBC_LOAD_FAILED AFX_SQL_ERROR+11
  136. #define AFX_SQL_ERROR_DYNASET_NOT_SUPPORTED AFX_SQL_ERROR+12
  137. #define AFX_SQL_ERROR_SNAPSHOT_NOT_SUPPORTED AFX_SQL_ERROR+13
  138. #define AFX_SQL_ERROR_API_CONFORMANCE AFX_SQL_ERROR+14
  139. #define AFX_SQL_ERROR_SQL_CONFORMANCE AFX_SQL_ERROR+15
  140. #define AFX_SQL_ERROR_NO_DATA_FOUND AFX_SQL_ERROR+16
  141. #define AFX_SQL_ERROR_ROW_UPDATE_NOT_SUPPORTED AFX_SQL_ERROR+17
  142. #define AFX_SQL_ERROR_ODBC_V2_REQUIRED AFX_SQL_ERROR+18
  143. #define AFX_SQL_ERROR_NO_POSITIONED_UPDATES AFX_SQL_ERROR+19
  144. #define AFX_SQL_ERROR_LOCK_MODE_NOT_SUPPORTED AFX_SQL_ERROR+20
  145. #define AFX_SQL_ERROR_DATA_TRUNCATED AFX_SQL_ERROR+21
  146. #define AFX_SQL_ERROR_ROW_FETCH AFX_SQL_ERROR+22
  147. #define AFX_SQL_ERROR_INCORRECT_ODBC AFX_SQL_ERROR+23
  148. #define AFX_SQL_ERROR_UPDATE_DELETE_FAILED AFX_SQL_ERROR+24
  149. #define AFX_SQL_ERROR_DYNAMIC_CURSOR_NOT_SUPPORTED AFX_SQL_ERROR+25
  150. #define AFX_SQL_ERROR_FIELD_NOT_FOUND AFX_SQL_ERROR+26
  151. #define AFX_SQL_ERROR_BOOKMARKS_NOT_SUPPORTED AFX_SQL_ERROR+27
  152. #define AFX_SQL_ERROR_BOOKMARKS_NOT_ENABLED AFX_SQL_ERROR+28
  153. #define AFX_SQL_ERROR_MAX AFX_SQL_ERROR+29
  154. class CDBException : public CException
  155. {
  156. DECLARE_DYNAMIC(CDBException)
  157. // Attributes
  158. public:
  159. RETCODE m_nRetCode;
  160. CString m_strError;
  161. CString m_strStateNativeOrigin;
  162. // Implementation (use AfxThrowDBException to create)
  163. public:
  164. CDBException(RETCODE nRetCode = SQL_SUCCESS);
  165. virtual void BuildErrorString(CDatabase* pdb, HSTMT hstmt,
  166. BOOL bTrace = TRUE);
  167. void Empty();
  168. virtual ~CDBException();
  169. virtual BOOL GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
  170. PUINT pnHelpContext = NULL);
  171. #ifdef _DEBUG
  172. void TraceErrorMessage(LPCTSTR szTrace) const;
  173. #endif // DEBUG
  174. };
  175. void AFXAPI AfxThrowDBException(RETCODE nRetCode, CDatabase* pdb, HSTMT hstmt);
  176. //////////////////////////////////////////////////////////////////////////////
  177. // CDatabase - a SQL Database
  178. class CDatabase : public CObject
  179. {
  180. DECLARE_DYNAMIC(CDatabase)
  181. // Constructors
  182. public:
  183. CDatabase();
  184. enum DbOpenOptions
  185. {
  186. openExclusive = 0x0001, // Not implemented
  187. openReadOnly = 0x0002, // Open database read only
  188. useCursorLib = 0x0004, // Use ODBC cursor lib
  189. noOdbcDialog = 0x0008, // Don't display ODBC Connect dialog
  190. forceOdbcDialog = 0x0010, // Always display ODBC connect dialog
  191. };
  192. virtual BOOL Open(LPCTSTR lpszDSN, BOOL bExclusive = FALSE,
  193. BOOL bReadonly = FALSE, LPCTSTR lpszConnect = _T("ODBC;"),
  194. BOOL bUseCursorLib = TRUE);
  195. virtual BOOL OpenEx(LPCTSTR lpszConnectString, DWORD dwOptions = 0);
  196. virtual void Close();
  197. // Attributes
  198. public:
  199. HDBC m_hdbc;
  200. BOOL IsOpen() const; // Database successfully opened?
  201. BOOL CanUpdate() const;
  202. BOOL CanTransact() const; // Are Transactions supported?
  203. CString GetDatabaseName() const;
  204. const CString& GetConnect() const;
  205. DWORD GetBookmarkPersistence() const;
  206. int GetCursorCommitBehavior() const;
  207. int GetCursorRollbackBehavior() const;
  208. // Operations
  209. public:
  210. void SetLoginTimeout(DWORD dwSeconds);
  211. void SetQueryTimeout(DWORD dwSeconds);
  212. // transaction control
  213. BOOL BeginTrans();
  214. BOOL CommitTrans();
  215. BOOL Rollback();
  216. void ExecuteSQL(LPCTSTR lpszSQL);
  217. // Cancel asynchronous operation
  218. void Cancel();
  219. // Overridables
  220. public:
  221. // set special options
  222. virtual void OnSetOptions(HSTMT hstmt);
  223. // Implementation
  224. public:
  225. virtual ~CDatabase();
  226. #ifdef _DEBUG
  227. virtual void AssertValid() const;
  228. virtual void Dump(CDumpContext& dc) const;
  229. BOOL m_bTransactionPending;
  230. #endif //_DEBUG
  231. // general error check
  232. virtual BOOL Check(RETCODE nRetCode) const;
  233. BOOL PASCAL CheckHstmt(RETCODE, HSTMT hstmt) const;
  234. // Note: CDatabase::BindParameters is now documented and is no longer
  235. // officially 'implementation.' Feel free to use it. It stays here
  236. // because moving it would break binary compatibility.
  237. virtual void BindParameters(HSTMT hstmt);
  238. void ReplaceBrackets(LPTSTR lpchSQL);
  239. BOOL m_bStripTrailingSpaces;
  240. BOOL m_bIncRecordCountOnAdd;
  241. BOOL m_bAddForUpdate;
  242. char m_chIDQuoteChar;
  243. char m_reserved1[3]; // pad to even 4 bytes
  244. void SetSynchronousMode(BOOL bSynchronous); // Obsolete, doe nothing
  245. protected:
  246. CString m_strConnect;
  247. CPtrList m_listRecordsets; // maintain list to ensure CRecordsets all closed
  248. int nRefCount;
  249. BOOL m_bUpdatable;
  250. BOOL m_bTransactions;
  251. SWORD m_nTransactionCapable;
  252. SWORD m_nCursorCommitBehavior;
  253. SWORD m_nCursorRollbackBehavior;
  254. DWORD m_dwUpdateOptions;
  255. DWORD m_dwBookmarkAttributes; // cache driver bookmark persistence
  256. DWORD m_dwLoginTimeout;
  257. HSTMT m_hstmt;
  258. DWORD m_dwQueryTimeout;
  259. virtual void ThrowDBException(RETCODE nRetCode);
  260. void AllocConnect(DWORD dwOptions);
  261. BOOL Connect(DWORD dwOptions);
  262. void VerifyConnect();
  263. void GetConnectInfo();
  264. void Free();
  265. // friend classes that call protected CDatabase overridables
  266. friend class CRecordset;
  267. friend class CFieldExchange;
  268. friend class CDBException;
  269. };
  270. //////////////////////////////////////////////////////////////////////////////
  271. // CFieldExchange - for field exchange
  272. class CFieldExchange
  273. {
  274. // Attributes
  275. public:
  276. enum RFX_Operation
  277. {
  278. BindParam, // register users parameters with ODBC SQLBindParameter
  279. RebindParam, // migrate param values to proxy array before Requery
  280. BindFieldToColumn, // register users fields with ODBC SQLBindCol
  281. BindFieldForUpdate, // temporarily bind columns before update (via SQLSetPos)
  282. UnbindFieldForUpdate, // unbind columns after update (via SQLSetPos)
  283. Fixup, // Set string lengths, clear status bits
  284. MarkForAddNew, // Prepare fields and flags for addnew operation
  285. MarkForUpdate, // Prepare fields and flags for update operation
  286. Name, // append dirty field name
  287. NameValue, // append dirty name=value
  288. Value, // append dirty value or parameter marker
  289. SetFieldNull, // Set status bit for null value
  290. StoreField, // archive values of current record
  291. LoadField, // reload archived values into current record
  292. AllocCache, // allocate cache used for dirty field check
  293. AllocMultiRowBuffer, // allocate buffer holding multi rows of data
  294. DeleteMultiRowBuffer, // delete buffer holding multi rows of data
  295. #ifdef _DEBUG
  296. DumpField, // dump bound field name and value
  297. #endif
  298. };
  299. UINT m_nOperation; // Type of exchange operation
  300. CRecordset* m_prs; // recordset handle
  301. // Operations
  302. enum FieldType
  303. {
  304. noFieldType = -1,
  305. outputColumn = 0,
  306. param = SQL_PARAM_INPUT,
  307. inputParam = param,
  308. outputParam = SQL_PARAM_OUTPUT,
  309. inoutParam = SQL_PARAM_INPUT_OUTPUT,
  310. };
  311. // Operations (for implementors of RFX procs)
  312. BOOL IsFieldType(UINT* pnField);
  313. // Indicate purpose of subsequent RFX calls
  314. void SetFieldType(UINT nFieldType);
  315. // Implementation
  316. CFieldExchange(UINT nOperation, CRecordset* prs, void* pvField = NULL);
  317. void Default(LPCTSTR szName,
  318. void* pv, LONG* plLength, int nCType, UINT cbValue, UINT cbPrecision);
  319. // long binary helpers
  320. long GetLongBinarySize(int nField);
  321. void GetLongBinaryData(int nField, CLongBinary& lb, long* plSize);
  322. BYTE* ReallocLongBinary(CLongBinary& lb, long lSizeRequired,
  323. long lReallocSize);
  324. // Current type of field
  325. UINT m_nFieldType;
  326. UINT m_nFieldFound;
  327. CString* m_pstr; // Field name or destination for building various SQL clauses
  328. BOOL m_bField; // Value to set for SetField operation
  329. void* m_pvField; // For indicating an operation on a specific field
  330. LPCTSTR m_lpszSeparator; // append after field names
  331. UINT m_nFields; // count of fields for various operations
  332. UINT m_nParams; // count of fields for various operations
  333. UINT m_nParamFields; // count of fields for various operations
  334. HSTMT m_hstmt; // For SQLBindParameter on update statement
  335. long m_lDefaultLBFetchSize; // For fetching CLongBinary data of unknown len
  336. long m_lDefaultLBReallocSize; // For fetching CLongBinary data of unknown len
  337. #ifdef _DEBUG
  338. CDumpContext* m_pdcDump;
  339. #endif //_DEBUG
  340. };
  341. #if _MFC_VER >= 0x0600
  342. /////////////////////////////////////////////////////////////////////////////
  343. // Global helper
  344. HENV AFXAPI AfxGetHENV();
  345. #endif
  346. /////////////////////////////////////////////////////////////////////////////
  347. // Recordset Field Exchange helpers
  348. void AFXAPI AfxStoreField(CRecordset& rs, UINT nField, void* pvField);
  349. void AFXAPI AfxLoadField(CRecordset& rs, UINT nField,
  350. void* pvField, long* plLength);
  351. BOOL AFXAPI AfxCompareValueByRef(void* pvData, void* pvCache, int nDataType);
  352. void AFXAPI AfxCopyValueByRef(void* pvCache, void* pvData,
  353. long* plLength, int nDataType);
  354. /////////////////////////////////////////////////////////////////////////////
  355. // Standard Recordset Field Exchange routines
  356. // text data
  357. void AFXAPI RFX_Text(CFieldExchange* pFX, LPCTSTR szName, CString& value,
  358. // Default max length for char and varchar, default datasource type
  359. int nMaxLength = 255, int nColumnType = SQL_VARCHAR, short nScale = 0);
  360. #if _MFC_VER >= 0x0600
  361. void AFXAPI RFX_Text(CFieldExchange* pFX, LPCTSTR szName, LPTSTR value,
  362. int nMaxLength, int nColumnType = SQL_VARCHAR, short nScale = 0);
  363. #endif
  364. // boolean data
  365. void AFXAPI RFX_Bool(CFieldExchange* pFX, LPCTSTR szName, BOOL& value);
  366. // integer data
  367. void AFXAPI RFX_Long(CFieldExchange* pFX, LPCTSTR szName, long& value);
  368. void AFXAPI RFX_Int(CFieldExchange* pFX, LPCTSTR szName, int& value);
  369. void AFXAPI RFX_Single(CFieldExchange* pFX, LPCTSTR szName, float& value);
  370. void AFXAPI RFX_Double(CFieldExchange* pFX, LPCTSTR szName, double& value);
  371. // date and time
  372. void AFXAPI RFX_Date(CFieldExchange* pFX, LPCTSTR szName, CTime& value);
  373. void AFXAPI RFX_Date(CFieldExchange* pFX, LPCTSTR szName, TIMESTAMP_STRUCT& value);
  374. #if _MFC_VER >= 0x0600
  375. void AFXAPI RFX_Date(CFieldExchange* pFX, LPCTSTR szName, COleDateTime& value);
  376. #endif
  377. // Binary data
  378. void AFXAPI RFX_Binary(CFieldExchange* pFX, LPCTSTR szName, CByteArray& value,
  379. // Default max length is for binary and varbinary
  380. int nMaxLength = 255);
  381. void AFXAPI RFX_Byte(CFieldExchange* pFX, LPCTSTR szName, BYTE& value);
  382. void AFXAPI RFX_LongBinary(CFieldExchange* pFX, LPCTSTR szName, CLongBinary& value);
  383. /////////////////////////////////////////////////////////////////////////////
  384. // Bulk Recordset Field Exchange helpers
  385. void AFXAPI AfxRFXBulkDefault(CFieldExchange* pFX, LPCTSTR szName,
  386. void* pv, long* rgLengths, int nCType, UINT cbValue);
  387. /////////////////////////////////////////////////////////////////////////////
  388. // Bulk Recordset Field Exchange routines
  389. void AFXAPI RFX_Text_Bulk(CFieldExchange* pFX, LPCTSTR szName,
  390. LPSTR* prgStrVals, long** prgLengths, int nMaxLength);
  391. void AFXAPI RFX_Bool_Bulk(CFieldExchange* pFX, LPCTSTR szName,
  392. BOOL** prgBoolVals, long** prgLengths);
  393. void AFXAPI RFX_Int_Bulk(CFieldExchange* pFX, LPCTSTR szName,
  394. int** prgIntVals, long** prgLengths);
  395. void AFXAPI RFX_Long_Bulk(CFieldExchange* pFX, LPCTSTR szName,
  396. long** prgLongVals, long** prgLengths);
  397. void AFXAPI RFX_Single_Bulk(CFieldExchange* pFX, LPCTSTR szName,
  398. float** prgFltVals, long** prgLengths);
  399. void AFXAPI RFX_Double_Bulk(CFieldExchange* pFX, LPCTSTR szName,
  400. double** prgDblVals, long** prgLengths);
  401. void AFXAPI RFX_Date_Bulk(CFieldExchange* pFX, LPCTSTR szName,
  402. TIMESTAMP_STRUCT** prgTSVals, long** prgLengths);
  403. void AFXAPI RFX_Byte_Bulk(CFieldExchange* pFX, LPCTSTR szName,
  404. BYTE** prgByteVals, long** prgLengths);
  405. void AFXAPI RFX_Binary_Bulk(CFieldExchange* pFX, LPCTSTR szName,
  406. BYTE** prgByteVals, long** prgLengths, int nMaxLength);
  407. /////////////////////////////////////////////////////////////////////////////
  408. // Database Dialog Data Exchange cover routines
  409. // Cover routines provide database semantics on top of DDX routines
  410. // simple text operations
  411. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, BYTE& value,
  412. CRecordset* pRecordset);
  413. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, int& value,
  414. CRecordset* pRecordset);
  415. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, UINT& value,
  416. CRecordset* pRecordset);
  417. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, long& value,
  418. CRecordset* pRecordset);
  419. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, DWORD& value,
  420. CRecordset* pRecordset);
  421. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, CString& value,
  422. CRecordset* pRecordset);
  423. #if _MFC_VER >= 0x0600
  424. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, LPTSTR pstrValue,
  425. int nMaxLen, CRecordset* pRecordset);
  426. #endif
  427. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, double& value,
  428. CRecordset* pRecordset);
  429. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, float& value,
  430. CRecordset* pRecordset);
  431. #if _MFC_VER >= 0x0600
  432. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, CTime& value,
  433. CRecordset* pRecordset);
  434. #endif
  435. // special control types
  436. void AFXAPI DDX_FieldCheck(CDataExchange* pDX, int nIDC, int& value,
  437. CRecordset* pRecordset);
  438. void AFXAPI DDX_FieldRadio(CDataExchange* pDX, int nIDC, int& value,
  439. CRecordset* pRecordset);
  440. void AFXAPI DDX_FieldLBString(CDataExchange* pDX, int nIDC,
  441. CString& value,
  442. CRecordset* pRecordset);
  443. void AFXAPI DDX_FieldCBString(CDataExchange* pDX, int nIDC,
  444. CString& value,
  445. CRecordset* pRecordset);
  446. void AFXAPI DDX_FieldLBIndex(CDataExchange* pDX, int nIDC, int& index,
  447. CRecordset* pRecordset);
  448. void AFXAPI DDX_FieldCBIndex(CDataExchange* pDX, int nIDC, int& index,
  449. CRecordset* pRecordset);
  450. void AFXAPI DDX_FieldLBStringExact(CDataExchange* pDX, int nIDC,
  451. CString& value,
  452. CRecordset* pRecordset);
  453. void AFXAPI DDX_FieldCBStringExact(CDataExchange* pDX, int nIDC,
  454. CString& value,
  455. CRecordset* pRecordset);
  456. void AFXAPI DDX_FieldScroll(CDataExchange* pDX, int nIDC, int& value,
  457. CRecordset* pRecordset);
  458. //////////////////////////////////////////////////////////////////////////////
  459. // CRecordset - the result of a SQL Statement
  460. #define AFX_DB_USE_DEFAULT_TYPE (0xFFFFFFFF)
  461. // Most Move constants out of date
  462. // #define AFX_MOVE_FIRST 0x80000000L
  463. // #define AFX_MOVE_PREVIOUS (-1L)
  464. #define AFX_MOVE_REFRESH 0L
  465. // #define AFX_MOVE_NEXT (+1L)
  466. // #define AFX_MOVE_LAST 0x7fffffffL
  467. #define AFX_RECORDSET_STATUS_OPEN (+1L)
  468. #define AFX_RECORDSET_STATUS_CLOSED 0L
  469. #define AFX_RECORDSET_STATUS_UNKNOWN (-1L)
  470. class CRecordset : public CObject
  471. {
  472. DECLARE_DYNAMIC(CRecordset)
  473. // Constructor
  474. public:
  475. CRecordset(CDatabase* pDatabase = NULL);
  476. public:
  477. virtual ~CRecordset();
  478. enum OpenType
  479. {
  480. dynaset, // uses SQLExtendedFetch, keyset driven cursor
  481. snapshot, // uses SQLExtendedFetch, static cursor
  482. forwardOnly, // uses SQLFetch
  483. dynamic // uses SQLExtendedFetch, dynamic cursor
  484. };
  485. enum OpenOptions
  486. {
  487. none = 0x0,
  488. readOnly = 0x0004,
  489. appendOnly = 0x0008,
  490. skipDeletedRecords = 0x0010, // turn on skipping of deleted records, Will slow Move(n).
  491. noDirtyFieldCheck = 0x0020, // disable automatic dirty field checking
  492. useBookmarks = 0x0100, // turn on bookmark support
  493. useMultiRowFetch = 0x0200, // turn on multi-row fetch model
  494. userAllocMultiRowBuffers = 0x0400, // if multi-row fetch on, user will alloc memory for buffers
  495. useExtendedFetch = 0x0800, // use SQLExtendedFetch with forwardOnly type recordsets
  496. executeDirect = 0x2000, // Directly execute SQL rather than prepared execute
  497. optimizeBulkAdd = 0x4000, // Use prepared HSTMT for multiple AddNews, dirty fields must not change.
  498. firstBulkAdd = 0x8000, // INTERNAL to MFC, don't specify on Open.
  499. };
  500. virtual BOOL Open(UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE,
  501. LPCTSTR lpszSQL = NULL, DWORD dwOptions = none);
  502. virtual void Close();
  503. // Attributes
  504. public:
  505. HSTMT m_hstmt; // Source statement for this resultset
  506. CDatabase* m_pDatabase; // Source database for this resultset
  507. CString m_strFilter; // Where clause
  508. CString m_strSort; // Order By Clause
  509. BOOL CanAppend() const; // Can AddNew be called?
  510. BOOL CanRestart() const; // Can Requery be called to restart a query?
  511. BOOL CanScroll() const; // Can MovePrev and MoveFirst be called?
  512. BOOL CanTransact() const; // Are Transactions supported?
  513. BOOL CanUpdate() const; // Can Edit/AddNew/Delete be called?
  514. BOOL CanBookmark() const; // Can Get/SetBookmark be called?
  515. const CString& GetSQL() const; // SQL executed for this recordset
  516. const CString& GetTableName() const; // Table name
  517. BOOL IsOpen() const; // Recordset successfully opened?
  518. BOOL IsBOF() const; // Beginning Of File
  519. BOOL IsEOF() const; // End Of File
  520. BOOL IsDeleted() const; // On a deleted record
  521. BOOL IsFieldDirty(void *pv); // has field been updated?
  522. BOOL IsFieldNull(void *pv); // is field NULL valued?
  523. BOOL IsFieldNullable(void *pv); // can field be set to a NULL value
  524. long GetRecordCount() const; // Records seen so far or -1 if unknown
  525. void GetStatus(CRecordsetStatus& rStatus) const;
  526. // Operations
  527. public:
  528. // cursor operations
  529. void MoveNext();
  530. void MovePrev();
  531. void MoveFirst();
  532. void MoveLast();
  533. virtual void Move(long nRows, WORD wFetchType = SQL_FETCH_RELATIVE);
  534. void SetAbsolutePosition(long nRows);
  535. void GetBookmark(CDBVariant& varBookmark);
  536. void SetBookmark(const CDBVariant& varBookmark);
  537. virtual void SetRowsetSize(DWORD dwNewRowsetSize);
  538. DWORD GetRowsetSize() const;
  539. DWORD GetRowsFetched() const;
  540. virtual void CheckRowsetError(RETCODE nRetCode);
  541. void RefreshRowset(WORD wRow, WORD wLockType = SQL_LOCK_NO_CHANGE);
  542. void SetRowsetCursorPosition(WORD wRow, WORD wLockType = SQL_LOCK_NO_CHANGE);
  543. WORD GetRowStatus(WORD wRow) const;
  544. // edit buffer operations
  545. virtual void AddNew(); // add new record at the end
  546. virtual void Edit(); // start editing
  547. virtual BOOL Update(); // update it
  548. virtual void Delete(); // delete the current record
  549. void CancelUpdate(); // cancel pending Edit/AddNew
  550. BOOL FlushResultSet() const;
  551. // field operations
  552. short GetODBCFieldCount() const;
  553. void GetODBCFieldInfo(short nIndex, CODBCFieldInfo& fieldinfo);
  554. void GetODBCFieldInfo(LPCTSTR lpszName, CODBCFieldInfo& fieldinfo);
  555. void GetFieldValue(LPCTSTR lpszName, CDBVariant& varValue,
  556. short nFieldType = DEFAULT_FIELD_TYPE);
  557. void GetFieldValue(short nIndex, CDBVariant& varValue,
  558. short nFieldType = DEFAULT_FIELD_TYPE);
  559. void GetFieldValue(LPCTSTR lpszName, CString& strValue);
  560. void GetFieldValue(short nIndex, CString& strValue);
  561. void SetFieldDirty(void *pv, BOOL bDirty = TRUE);
  562. void SetFieldNull(void *pv, BOOL bNull = TRUE);
  563. void SetParamNull(int nIndex, BOOL bNull = TRUE);
  564. // locking control during Edit
  565. enum LockMode
  566. {
  567. optimistic,
  568. pessimistic,
  569. };
  570. void SetLockingMode(UINT nMode);
  571. // Recordset operations
  572. virtual BOOL Requery(); // Re-execute query based on new params
  573. // Cancel asynchronous operation
  574. void Cancel();
  575. // Overridables
  576. public:
  577. // Get default connect string
  578. virtual CString GetDefaultConnect();
  579. // Get SQL to execute
  580. virtual CString GetDefaultSQL();
  581. // set special options
  582. virtual void OnSetOptions(HSTMT hstmt);
  583. // for recordset field exchange
  584. virtual void DoFieldExchange(CFieldExchange* pFX);
  585. virtual void DoBulkFieldExchange(CFieldExchange* pFX);
  586. // Implementation
  587. public:
  588. #ifdef _DEBUG
  589. virtual void AssertValid() const;
  590. virtual void Dump(CDumpContext& dc) const;
  591. #endif //_DEBUG
  592. virtual BOOL Check(RETCODE nRetCode) const; // general error check
  593. void InitRecord();
  594. void ResetCursor();
  595. void CheckRowsetCurrencyStatus(UWORD wFetchType, long nRows);
  596. RETCODE FetchData(UWORD wFetchType, SDWORD nRow,
  597. DWORD* pdwRowsFetched);
  598. void SkipDeletedRecords(UWORD wFetchType, long nRows,
  599. DWORD* pdwRowsFetched, RETCODE* pnRetCode);
  600. virtual void SetRowsetCurrencyStatus(RETCODE nRetCode,
  601. UWORD wFetchType, long nRows, DWORD dwRowsFetched);
  602. virtual void PreBindFields(); // called before data fields are bound
  603. UINT m_nFields; // number of RFX fields
  604. UINT m_nParams; // number of RFX params
  605. BOOL m_bCheckCacheForDirtyFields; // switch for dirty field checking
  606. BOOL m_bRebindParams; // date or UNICODE text parameter existence flag
  607. BOOL m_bLongBinaryColumns; // long binary column existence flag
  608. BOOL m_bUseUpdateSQL; // uses SQL-based updates
  609. DWORD m_dwOptions; // archive dwOptions on Open
  610. SWORD m_nResultCols; // number of columns in result set
  611. BOOL m_bUseODBCCursorLib; // uses ODBC cursor lib if m_pDatabase not Open
  612. CODBCFieldInfo* m_rgODBCFieldInfos; // Array of field info structs with ODBC meta-data
  613. CFieldInfo* m_rgFieldInfos; // Array of field info structs with MFC specific field data
  614. CMapPtrToPtr m_mapFieldIndex; // Map of member address to field index
  615. CMapPtrToPtr m_mapParamIndex; // Map of member address to field index
  616. BOOL IsSQLUpdatable(LPCTSTR lpszSQL);
  617. BOOL IsSelectQueryUpdatable(LPCTSTR lpszSQL);
  618. static BOOL PASCAL IsJoin(LPCTSTR lpszJoinClause);
  619. static LPCTSTR PASCAL FindSQLToken(LPCTSTR lpszSQL, LPCTSTR lpszSQLToken);
  620. // RFX Operations on fields of CRecordset
  621. UINT BindParams(HSTMT hstmt);
  622. void RebindParams(HSTMT hstmt);
  623. UINT BindFieldsToColumns();
  624. void BindFieldsForUpdate();
  625. void UnbindFieldsForUpdate();
  626. void Fixups();
  627. UINT AppendNames(CString* pstr, LPCTSTR szSeparator);
  628. UINT AppendValues(HSTMT hstmt, CString* pstr, LPCTSTR szSeparator);
  629. UINT AppendNamesValues(HSTMT hstmt, CString* pstr, LPCTSTR szSeparator);
  630. void StoreFields();
  631. void LoadFields();
  632. void MarkForAddNew();
  633. void MarkForUpdate();
  634. void AllocDataCache();
  635. void FreeDataCache();
  636. #ifdef _DEBUG
  637. void DumpFields(CDumpContext& dc) const;
  638. #endif //_DEBUG
  639. // RFX operation helper functions
  640. virtual void ThrowDBException(RETCODE nRetCode, HSTMT hstmt = SQL_NULL_HSTMT);
  641. int GetBoundFieldIndex(void* pv);
  642. int GetBoundParamIndex(void* pv);
  643. short GetFieldIndexByName(LPCTSTR lpszFieldName);
  644. void AllocStatusArrays();
  645. long* GetFieldLengthBuffer(DWORD nField, int nFieldType); // for fields & params
  646. BYTE GetFieldStatus(DWORD nField);
  647. void SetFieldStatus(DWORD nField, BYTE bFlags);
  648. void ClearFieldStatus();
  649. BOOL IsFieldStatusDirty(DWORD nField) const;
  650. void SetDirtyFieldStatus(DWORD nField);
  651. void ClearDirtyFieldStatus(DWORD nField);
  652. BOOL IsFieldStatusNull(DWORD nField) const;
  653. void SetNullFieldStatus(DWORD nField);
  654. void ClearNullFieldStatus(DWORD nField);
  655. BOOL IsParamStatusNull(DWORD nField) const;
  656. void SetNullParamStatus(DWORD nField);
  657. void ClearNullParamStatus(DWORD nField);
  658. BOOL IsFieldNullable(DWORD nField) const;
  659. void** m_pvFieldProxy;
  660. void** m_pvParamProxy;
  661. UINT m_nProxyFields;
  662. UINT m_nProxyParams;
  663. // GetFieldValue helpers
  664. static short PASCAL GetDefaultFieldType(short nSQLType);
  665. static void* PASCAL GetDataBuffer(CDBVariant& varValue, short nFieldType,
  666. int* pnLen, short nSQLType, UDWORD nPrecision);
  667. static int PASCAL GetTextLen(short nSQLType, UDWORD nPrecision);
  668. static long PASCAL GetData(CDatabase* pdb, HSTMT hstmt, short nFieldIndex,
  669. short nFieldType, LPVOID pvData, int nLen, short nSQLType);
  670. static void PASCAL GetLongBinaryDataAndCleanup(CDatabase* pdb, HSTMT hstmt,
  671. short nFieldIndex, long nActualSize, LPVOID* ppvData, int nLen,
  672. CDBVariant& varValue, short nSQLType);
  673. static void PASCAL GetLongCharDataAndCleanup(CDatabase* pdb, HSTMT hstmt,
  674. short nFieldIndex, long nActualSize, LPVOID* ppvData, int nLen,
  675. CString& strValue, short nSQLType);
  676. protected:
  677. UINT m_nOpenType;
  678. UINT m_nDefaultType;
  679. enum EditMode
  680. {
  681. noMode,
  682. edit,
  683. addnew
  684. };
  685. long m_lOpen;
  686. UINT m_nEditMode;
  687. BOOL m_bEOFSeen;
  688. long m_lRecordCount;
  689. long m_lCurrentRecord;
  690. CString m_strCursorName;
  691. // Perform operation based on m_nEditMode
  692. BOOL UpdateInsertDelete();
  693. BOOL m_nLockMode; // Control concurrency for Edit()
  694. UDWORD m_dwDriverConcurrency; // driver supported concurrency types
  695. UDWORD m_dwConcurrency; // requested concurrency type
  696. UWORD* m_rgRowStatus; // row status used by SQLExtendedFetch and SQLSetPos
  697. DWORD m_dwRowsFetched; // number of rows fetched by SQLExtendedFetch
  698. HSTMT m_hstmtUpdate;
  699. BOOL m_bRecordsetDb;
  700. BOOL m_bBOF;
  701. BOOL m_bEOF;
  702. BOOL m_bUpdatable; // Is recordset updatable?
  703. BOOL m_bAppendable;
  704. CString m_strSQL; // SQL statement for recordset
  705. CString m_strUpdateSQL; // SQL statement for updates
  706. CString m_strTableName; // source table of recordset
  707. BOOL m_bScrollable; // supports MovePrev
  708. BOOL m_bDeleted;
  709. int m_nFieldsBound;
  710. BYTE* m_pbFieldFlags;
  711. BYTE* m_pbParamFlags;
  712. LONG* m_plParamLength;
  713. DWORD m_dwInitialGetDataLen; // Initial GetFieldValue alloc size for long data
  714. DWORD m_dwRowsetSize;
  715. DWORD m_dwAllocatedRowsetSize;
  716. protected:
  717. CString m_strRequerySQL; // archive SQL string for use in Requery()
  718. CString m_strRequeryFilter; // archive filter string for use in Requery()
  719. CString m_strRequerySort; // archive sort string for use in Requery()
  720. void SetState(int nOpenType, LPCTSTR lpszSQL, DWORD dwOptions);
  721. BOOL AllocHstmt();
  722. void BuildSQL(LPCTSTR lpszSQL);
  723. void PrepareAndExecute();
  724. void BuildSelectSQL();
  725. void AppendFilterAndSortSQL();
  726. BOOL IsRecordsetUpdatable();
  727. void VerifyDriverBehavior();
  728. DWORD VerifyCursorSupport();
  729. void EnableBookmarks();
  730. void SetUpdateMethod();
  731. void SetConcurrencyAndCursorType(HSTMT hstmt, DWORD dwScrollOptions);
  732. void AllocAndCacheFieldInfo();
  733. void AllocRowset();
  734. void FreeRowset();
  735. void ExecuteSetPosUpdate();
  736. void PrepareUpdateHstmt();
  737. void BuildUpdateSQL();
  738. void ExecuteUpdateSQL();
  739. void SendLongBinaryData(HSTMT hstmt);
  740. virtual long GetLBFetchSize(long lOldSize); // CLongBinary fetch chunking
  741. virtual long GetLBReallocSize(long lOldSize); // CLongBinary realloc chunking
  742. friend class CFieldExchange;
  743. friend class CRecordView;
  744. };
  745. /////////////////////////////////////////////////////////////////////////////
  746. // Info helper definitions
  747. #define AFX_CURRENT_RECORD_UNDEFINED (-2)
  748. #define AFX_CURRENT_RECORD_BOF (-1)
  749. // For returning status for a recordset
  750. struct CRecordsetStatus
  751. {
  752. long m_lCurrentRecord; // -2=Unknown,-1=BOF,0=1st record. . .
  753. BOOL m_bRecordCountFinal;// Have we counted all records?
  754. };
  755. // Must maintian data binding info
  756. struct CFieldInfo
  757. {
  758. // MFC specific info
  759. void* m_pvDataCache;
  760. long m_nLength;
  761. int m_nDataType;
  762. BYTE m_bStatus;
  763. #ifdef _DEBUG
  764. void* m_pvBindAddress;
  765. #endif
  766. };
  767. struct CODBCFieldInfo
  768. {
  769. // meta data from ODBC
  770. CString m_strName;
  771. SWORD m_nSQLType;
  772. UDWORD m_nPrecision;
  773. SWORD m_nScale;
  774. SWORD m_nNullability;
  775. };
  776. struct CODBCParamInfo
  777. {
  778. // meta data from ODBC
  779. SWORD m_nSQLType;
  780. UDWORD m_nPrecision;
  781. SWORD m_nScale;
  782. SWORD m_nNullability;
  783. };
  784. /////////////////////////////////////////////////////////////////////////////
  785. // CDBVariant
  786. #define DBVT_NULL 0
  787. #define DBVT_BOOL 1
  788. #define DBVT_UCHAR 2
  789. #define DBVT_SHORT 3
  790. #define DBVT_LONG 4
  791. #define DBVT_SINGLE 5
  792. #define DBVT_DOUBLE 6
  793. #define DBVT_DATE 7
  794. #define DBVT_STRING 8
  795. #define DBVT_BINARY 9
  796. class CDBVariant
  797. {
  798. // Constructor
  799. public:
  800. CDBVariant();
  801. // Attributes
  802. public:
  803. DWORD m_dwType;
  804. union
  805. {
  806. BOOL m_boolVal;
  807. unsigned char m_chVal;
  808. short m_iVal;
  809. long m_lVal;
  810. float m_fltVal;
  811. double m_dblVal;
  812. TIMESTAMP_STRUCT* m_pdate;
  813. CString* m_pstring;
  814. CLongBinary* m_pbinary;
  815. };
  816. // Operations
  817. void Clear();
  818. // Implementation
  819. public:
  820. virtual ~CDBVariant();
  821. };
  822. /////////////////////////////////////////////////////////////////////////////
  823. // CRecordView - form for viewing data records
  824. #ifdef _AFXDLL
  825. class CRecordView : public CFormView
  826. #else
  827. class AFX_NOVTABLE CRecordView : public CFormView
  828. #endif
  829. {
  830. DECLARE_DYNAMIC(CRecordView)
  831. // Construction
  832. protected: // must derive your own class
  833. CRecordView(LPCTSTR lpszTemplateName);
  834. CRecordView(UINT nIDTemplate);
  835. // Attributes
  836. public:
  837. virtual CRecordset* OnGetRecordset() = 0;
  838. BOOL IsOnLastRecord();
  839. BOOL IsOnFirstRecord();
  840. // Operations
  841. public:
  842. virtual BOOL OnMove(UINT nIDMoveCommand);
  843. // Implementation
  844. public:
  845. virtual ~CRecordView();
  846. #ifdef _DEBUG
  847. virtual void AssertValid() const;
  848. virtual void Dump(CDumpContext& dc) const;
  849. #endif
  850. virtual void OnInitialUpdate();
  851. protected:
  852. BOOL m_bOnFirstRecord;
  853. BOOL m_bOnLastRecord;
  854. //{{AFX_MSG(CRecordView)
  855. afx_msg void OnUpdateRecordFirst(CCmdUI* pCmdUI);
  856. afx_msg void OnUpdateRecordPrev(CCmdUI* pCmdUI);
  857. afx_msg void OnUpdateRecordNext(CCmdUI* pCmdUI);
  858. afx_msg void OnUpdateRecordLast(CCmdUI* pCmdUI);
  859. //}}AFX_MSG
  860. afx_msg void OnMove(int cx, int cy);
  861. DECLARE_MESSAGE_MAP()
  862. };
  863. /////////////////////////////////////////////////////////////////////////////
  864. // Inline function declarations
  865. #ifdef _AFX_PACKING
  866. #pragma pack(pop)
  867. #endif
  868. #ifdef _AFX_ENABLE_INLINES
  869. #define _AFXDBCORE_INLINE AFX_INLINE
  870. #define _AFXDBRFX_INLINE AFX_INLINE
  871. #define _AFXDBVIEW_INLINE AFX_INLINE
  872. #include <afxdb.inl>
  873. #undef _AFXDBVIEW_INLINE
  874. #undef _AFXDBCORE_INLINE
  875. #undef _AFXDBRFX_INLINE
  876. #endif
  877. #undef AFX_DATA
  878. #define AFX_DATA
  879. #ifdef _AFX_MINREBUILD
  880. #pragma component(minrebuild, on)
  881. #endif
  882. #ifndef _AFX_FULLTYPEINFO
  883. #pragma component(mintypeinfo, off)
  884. #endif
  885. #endif //__AFXDB_H__
  886. /////////////////////////////////////////////////////////////////////////////