afxdb.h 34 KB

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