1043 lines
33 KiB
C
1043 lines
33 KiB
C
|
// This is a part of the Microsoft Foundation Classes C++ library.
|
||
|
// Copyright (C) 1992-1995 Microsoft Corporation
|
||
|
// All rights reserved.
|
||
|
//
|
||
|
// This source code is only intended as a supplement to the
|
||
|
// Microsoft Foundation Classes Reference and related
|
||
|
// electronic documentation provided with the library.
|
||
|
// See these sources for detailed information regarding the
|
||
|
// Microsoft Foundation Classes product.
|
||
|
|
||
|
#ifndef __AFXDB_H__
|
||
|
#define __AFXDB_H__
|
||
|
|
||
|
#ifdef _AFX_NO_DB_SUPPORT
|
||
|
#error Database classes not supported in this library variant.
|
||
|
#endif
|
||
|
|
||
|
#ifndef __AFXEXT_H__
|
||
|
#include <afxext.h>
|
||
|
#endif
|
||
|
|
||
|
#ifndef __AFXDB__H__
|
||
|
#include <afxdb_.h> // shared header DAO database classes
|
||
|
#endif
|
||
|
|
||
|
// include standard SQL/ODBC "C" APIs
|
||
|
#ifndef __SQL
|
||
|
#include <sql.h> // core
|
||
|
#endif
|
||
|
#ifndef __SQLEXT
|
||
|
#include <sqlext.h> // extensions
|
||
|
#endif
|
||
|
|
||
|
#ifdef _AFX_MINREBUILD
|
||
|
#pragma component(minrebuild, off)
|
||
|
#endif
|
||
|
#ifndef _AFX_FULLTYPEINFO
|
||
|
#pragma component(mintypeinfo, on)
|
||
|
#endif
|
||
|
|
||
|
#ifndef _AFX_NOFORCE_LIBS
|
||
|
#ifndef _MAC
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Win32 libraries
|
||
|
|
||
|
#ifdef _AFXDLL
|
||
|
#if defined(_DEBUG) && !defined(_AFX_MONOLITHIC)
|
||
|
#ifndef _UNICODE
|
||
|
#pragma comment(lib, "mfcd42d.lib")
|
||
|
#else
|
||
|
#pragma comment(lib, "mfcd42ud.lib")
|
||
|
#endif
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#pragma comment(lib, "odbc32.lib")
|
||
|
#pragma comment(lib, "odbccp32.lib")
|
||
|
|
||
|
#else //!_MAC
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Macintosh libraries
|
||
|
|
||
|
#ifdef _AFXDLL
|
||
|
#ifdef _DEBUG
|
||
|
#pragma comment(lib, "mfcd42pd.lib")
|
||
|
#else
|
||
|
#pragma comment(lib, "mfcd42p.lib")
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#ifdef _MPPC_
|
||
|
#pragma comment(lib, "odbccfgp.lib")
|
||
|
#pragma comment(lib, "odbcdrvp.lib")
|
||
|
#else
|
||
|
#pragma comment(lib, "odbccfgm.lib")
|
||
|
#pragma comment(lib, "odbcdrvm.lib")
|
||
|
#ifdef _DEBUG
|
||
|
#pragma comment (lib, "aslmd.lib")
|
||
|
#else
|
||
|
#pragma comment (lib, "aslm.lib")
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#endif //_MAC
|
||
|
#endif //!_AFX_NOFORCE_LIBS
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#ifdef _AFX_PACKING
|
||
|
#pragma pack(push, _AFX_PACKING)
|
||
|
#endif
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// AFXDB - MFC SQL/ODBC/Database support
|
||
|
|
||
|
// Classes declared in this file
|
||
|
|
||
|
//CException
|
||
|
class CDBException; // abnormal return value
|
||
|
|
||
|
//CFieldExchange
|
||
|
class CFieldExchange; // Recordset Field Exchange
|
||
|
|
||
|
//CObject
|
||
|
class CDatabase; // Connecting to databases
|
||
|
class CRecordset; // Data result sets
|
||
|
|
||
|
//CObject
|
||
|
//CCmdTarget;
|
||
|
//CWnd
|
||
|
//CView
|
||
|
//CScrollView
|
||
|
//CFormView
|
||
|
class CRecordView; // view records with a form
|
||
|
|
||
|
// Non CObject classes
|
||
|
class CDBVariant;
|
||
|
struct CRecordsetStatus;
|
||
|
struct CFieldInfo;
|
||
|
struct CODBCFieldInfo;
|
||
|
struct CODBCParamInfo;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// ODBC helpers
|
||
|
// return code left in 'nRetCode'
|
||
|
|
||
|
// This MACRO is now out-of-date (kept for backward compatibility)
|
||
|
#define AFX_ODBC_CALL(SQLFunc) \
|
||
|
do \
|
||
|
{ \
|
||
|
} while ((nRetCode = (SQLFunc)) == SQL_STILL_EXECUTING)
|
||
|
|
||
|
// Not really required, but kept for compatibilty
|
||
|
#define AFX_SQL_SYNC(SQLFunc) \
|
||
|
do \
|
||
|
{ \
|
||
|
nRetCode = SQLFunc; \
|
||
|
} while (0)
|
||
|
|
||
|
// Now out-of-date (prs not used) but kept for compatibility
|
||
|
#define AFX_SQL_ASYNC(prs, SQLFunc) AFX_ODBC_CALL(SQLFunc)
|
||
|
|
||
|
// Max display length in chars of timestamp (date & time) value
|
||
|
#define TIMESTAMP_PRECISION 23
|
||
|
|
||
|
// AFXDLL support
|
||
|
#undef AFX_DATA
|
||
|
#define AFX_DATA AFX_DB_DATA
|
||
|
|
||
|
// Miscellaneous sizing info
|
||
|
#define MAX_CURRENCY 30 // Max size of Currency($) string
|
||
|
#define MAX_TNAME_LEN 64 // Max size of table names
|
||
|
#define MAX_FNAME_LEN 64 // Max size of field names
|
||
|
#define MAX_DBNAME_LEN 32 // Max size of a database name
|
||
|
#define MAX_DNAME_LEN 256 // Max size of Recordset names
|
||
|
#define MAX_CONNECT_LEN 512 // Max size of Connect string
|
||
|
#define MAX_CURSOR_NAME 18 // Max size of a cursor name
|
||
|
#define DEFAULT_FIELD_TYPE SQL_TYPE_NULL // pick "C" data type to match SQL data type
|
||
|
|
||
|
// Timeout and net wait defaults
|
||
|
#define DEFAULT_LOGIN_TIMEOUT 15 // seconds to before fail on connect
|
||
|
#define DEFAULT_QUERY_TIMEOUT 15 // seconds to before fail waiting for results
|
||
|
|
||
|
// Field Flags, used to indicate status of fields
|
||
|
#define AFX_SQL_FIELD_FLAG_DIRTY 0x1
|
||
|
#define AFX_SQL_FIELD_FLAG_NULL 0x2
|
||
|
|
||
|
// Update options flags
|
||
|
#define AFX_SQL_SETPOSUPDATES 0x0001
|
||
|
#define AFX_SQL_POSITIONEDSQL 0x0002
|
||
|
#define AFX_SQL_GDBOUND 0x0004
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CDBException - something gone wrong
|
||
|
|
||
|
// Dbkit extended error codes
|
||
|
#define AFX_SQL_ERROR 1000
|
||
|
#define AFX_SQL_ERROR_CONNECT_FAIL AFX_SQL_ERROR+1
|
||
|
#define AFX_SQL_ERROR_RECORDSET_FORWARD_ONLY AFX_SQL_ERROR+2
|
||
|
#define AFX_SQL_ERROR_EMPTY_COLUMN_LIST AFX_SQL_ERROR+3
|
||
|
#define AFX_SQL_ERROR_FIELD_SCHEMA_MISMATCH AFX_SQL_ERROR+4
|
||
|
#define AFX_SQL_ERROR_ILLEGAL_MODE AFX_SQL_ERROR+5
|
||
|
#define AFX_SQL_ERROR_MULTIPLE_ROWS_AFFECTED AFX_SQL_ERROR+6
|
||
|
#define AFX_SQL_ERROR_NO_CURRENT_RECORD AFX_SQL_ERROR+7
|
||
|
#define AFX_SQL_ERROR_NO_ROWS_AFFECTED AFX_SQL_ERROR+8
|
||
|
#define AFX_SQL_ERROR_RECORDSET_READONLY AFX_SQL_ERROR+9
|
||
|
#define AFX_SQL_ERROR_SQL_NO_TOTAL AFX_SQL_ERROR+10
|
||
|
#define AFX_SQL_ERROR_ODBC_LOAD_FAILED AFX_SQL_ERROR+11
|
||
|
#define AFX_SQL_ERROR_DYNASET_NOT_SUPPORTED AFX_SQL_ERROR+12
|
||
|
#define AFX_SQL_ERROR_SNAPSHOT_NOT_SUPPORTED AFX_SQL_ERROR+13
|
||
|
#define AFX_SQL_ERROR_API_CONFORMANCE AFX_SQL_ERROR+14
|
||
|
#define AFX_SQL_ERROR_SQL_CONFORMANCE AFX_SQL_ERROR+15
|
||
|
#define AFX_SQL_ERROR_NO_DATA_FOUND AFX_SQL_ERROR+16
|
||
|
#define AFX_SQL_ERROR_ROW_UPDATE_NOT_SUPPORTED AFX_SQL_ERROR+17
|
||
|
#define AFX_SQL_ERROR_ODBC_V2_REQUIRED AFX_SQL_ERROR+18
|
||
|
#define AFX_SQL_ERROR_NO_POSITIONED_UPDATES AFX_SQL_ERROR+19
|
||
|
#define AFX_SQL_ERROR_LOCK_MODE_NOT_SUPPORTED AFX_SQL_ERROR+20
|
||
|
#define AFX_SQL_ERROR_DATA_TRUNCATED AFX_SQL_ERROR+21
|
||
|
#define AFX_SQL_ERROR_ROW_FETCH AFX_SQL_ERROR+22
|
||
|
#define AFX_SQL_ERROR_INCORRECT_ODBC AFX_SQL_ERROR+23
|
||
|
#define AFX_SQL_ERROR_UPDATE_DELETE_FAILED AFX_SQL_ERROR+24
|
||
|
#define AFX_SQL_ERROR_DYNAMIC_CURSOR_NOT_SUPPORTED AFX_SQL_ERROR+25
|
||
|
#define AFX_SQL_ERROR_FIELD_NOT_FOUND AFX_SQL_ERROR+26
|
||
|
#define AFX_SQL_ERROR_BOOKMARKS_NOT_SUPPORTED AFX_SQL_ERROR+27
|
||
|
#define AFX_SQL_ERROR_BOOKMARKS_NOT_ENABLED AFX_SQL_ERROR+28
|
||
|
#define AFX_SQL_ERROR_MAX AFX_SQL_ERROR+29
|
||
|
|
||
|
class CDBException : public CException
|
||
|
{
|
||
|
DECLARE_DYNAMIC(CDBException)
|
||
|
|
||
|
// Attributes
|
||
|
public:
|
||
|
RETCODE m_nRetCode;
|
||
|
CString m_strError;
|
||
|
CString m_strStateNativeOrigin;
|
||
|
|
||
|
// Implementation (use AfxThrowDBException to create)
|
||
|
public:
|
||
|
CDBException(RETCODE nRetCode = SQL_SUCCESS);
|
||
|
|
||
|
virtual void BuildErrorString(CDatabase* pdb, HSTMT hstmt,
|
||
|
BOOL bTrace = TRUE);
|
||
|
void Empty();
|
||
|
virtual ~CDBException();
|
||
|
|
||
|
virtual BOOL GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
|
||
|
PUINT pnHelpContext = NULL);
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
void TraceErrorMessage(LPCTSTR szTrace) const;
|
||
|
#endif // DEBUG
|
||
|
|
||
|
};
|
||
|
|
||
|
void AFXAPI AfxThrowDBException(RETCODE nRetCode, CDatabase* pdb, HSTMT hstmt);
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
// CDatabase - a SQL Database
|
||
|
|
||
|
class CDatabase : public CObject
|
||
|
{
|
||
|
DECLARE_DYNAMIC(CDatabase)
|
||
|
|
||
|
// Constructors
|
||
|
public:
|
||
|
CDatabase();
|
||
|
|
||
|
enum DbOpenOptions
|
||
|
{
|
||
|
openExclusive = 0x0001, // Not implemented
|
||
|
openReadOnly = 0x0002, // Open database read only
|
||
|
useCursorLib = 0x0004, // Use ODBC cursor lib
|
||
|
noOdbcDialog = 0x0008, // Don't display ODBC Connect dialog
|
||
|
forceOdbcDialog = 0x0010, // Always display ODBC connect dialog
|
||
|
};
|
||
|
|
||
|
virtual BOOL Open(LPCTSTR lpszDSN, BOOL bExclusive = FALSE,
|
||
|
BOOL bReadonly = FALSE, LPCTSTR lpszConnect = _T("ODBC;"),
|
||
|
BOOL bUseCursorLib = TRUE);
|
||
|
virtual BOOL OpenEx(LPCTSTR lpszConnectString, DWORD dwOptions = 0);
|
||
|
virtual void Close();
|
||
|
|
||
|
// Attributes
|
||
|
public:
|
||
|
HDBC m_hdbc;
|
||
|
|
||
|
BOOL IsOpen() const; // Database successfully opened?
|
||
|
BOOL CanUpdate() const;
|
||
|
BOOL CanTransact() const; // Are Transactions supported?
|
||
|
|
||
|
CString GetDatabaseName() const;
|
||
|
const CString& GetConnect() const;
|
||
|
|
||
|
DWORD GetBookmarkPersistence() const;
|
||
|
int GetCursorCommitBehavior() const;
|
||
|
int GetCursorRollbackBehavior() const;
|
||
|
|
||
|
// Operations
|
||
|
public:
|
||
|
void SetLoginTimeout(DWORD dwSeconds);
|
||
|
void SetQueryTimeout(DWORD dwSeconds);
|
||
|
|
||
|
// transaction control
|
||
|
BOOL BeginTrans();
|
||
|
BOOL CommitTrans();
|
||
|
BOOL Rollback();
|
||
|
|
||
|
void ExecuteSQL(LPCTSTR lpszSQL);
|
||
|
|
||
|
// Cancel asynchronous operation
|
||
|
void Cancel();
|
||
|
|
||
|
// Overridables
|
||
|
public:
|
||
|
// set special options
|
||
|
virtual void OnSetOptions(HSTMT hstmt);
|
||
|
|
||
|
// Implementation
|
||
|
public:
|
||
|
virtual ~CDatabase();
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
virtual void AssertValid() const;
|
||
|
virtual void Dump(CDumpContext& dc) const;
|
||
|
|
||
|
BOOL m_bTransactionPending;
|
||
|
#endif //_DEBUG
|
||
|
|
||
|
// general error check
|
||
|
virtual BOOL Check(RETCODE nRetCode) const;
|
||
|
|
||
|
virtual void BindParameters(HSTMT hstmt);
|
||
|
|
||
|
void ReplaceBrackets(LPTSTR lpchSQL);
|
||
|
BOOL m_bStripTrailingSpaces;
|
||
|
BOOL m_bIncRecordCountOnAdd;
|
||
|
BOOL m_bAddForUpdate;
|
||
|
char m_chIDQuoteChar;
|
||
|
char m_reserved1[3]; // pad to even 4 bytes
|
||
|
|
||
|
void SetSynchronousMode(BOOL bSynchronous); // Obsolete, doe nothing
|
||
|
|
||
|
protected:
|
||
|
CString m_strConnect;
|
||
|
|
||
|
CPtrList m_listRecordsets; // maintain list to ensure CRecordsets all closed
|
||
|
|
||
|
int nRefCount;
|
||
|
BOOL m_bUpdatable;
|
||
|
|
||
|
BOOL m_bTransactions;
|
||
|
SWORD m_nTransactionCapable;
|
||
|
SWORD m_nCursorCommitBehavior;
|
||
|
SWORD m_nCursorRollbackBehavior;
|
||
|
DWORD m_dwUpdateOptions;
|
||
|
DWORD m_dwBookmarkAttributes; // cache driver bookmark persistence
|
||
|
|
||
|
DWORD m_dwLoginTimeout;
|
||
|
HSTMT m_hstmt;
|
||
|
|
||
|
DWORD m_dwQueryTimeout;
|
||
|
|
||
|
virtual void ThrowDBException(RETCODE nRetCode);
|
||
|
void AllocConnect(DWORD dwOptions);
|
||
|
BOOL Connect(DWORD dwOptions);
|
||
|
void VerifyConnect();
|
||
|
void GetConnectInfo();
|
||
|
void Free();
|
||
|
|
||
|
// friend classes that call protected CDatabase overridables
|
||
|
friend class CRecordset;
|
||
|
friend class CFieldExchange;
|
||
|
friend class CDBException;
|
||
|
};
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
// CFieldExchange - for field exchange
|
||
|
class CFieldExchange
|
||
|
{
|
||
|
// Attributes
|
||
|
public:
|
||
|
enum RFX_Operation
|
||
|
{
|
||
|
BindParam, // register users parameters with ODBC SQLBindParameter
|
||
|
RebindParam, // migrate param values to proxy array before Requery
|
||
|
BindFieldToColumn, // register users fields with ODBC SQLBindCol
|
||
|
BindFieldForUpdate, // temporarily bind columns before update (via SQLSetPos)
|
||
|
UnbindFieldForUpdate, // unbind columns after update (via SQLSetPos)
|
||
|
Fixup, // Set string lengths, clear status bits
|
||
|
MarkForAddNew, // Prepare fields and flags for addnew operation
|
||
|
MarkForUpdate, // Prepare fields and flags for update operation
|
||
|
Name, // append dirty field name
|
||
|
NameValue, // append dirty name=value
|
||
|
Value, // append dirty value or parameter marker
|
||
|
SetFieldNull, // Set status bit for null value
|
||
|
StoreField, // archive values of current record
|
||
|
LoadField, // reload archived values into current record
|
||
|
AllocCache, // allocate cache used for dirty field check
|
||
|
AllocMultiRowBuffer, // allocate buffer holding multi rows of data
|
||
|
DeleteMultiRowBuffer, // delete buffer holding multi rows of data
|
||
|
#ifdef _DEBUG
|
||
|
DumpField, // dump bound field name and value
|
||
|
#endif
|
||
|
};
|
||
|
UINT m_nOperation; // Type of exchange operation
|
||
|
CRecordset* m_prs; // recordset handle
|
||
|
|
||
|
// Operations
|
||
|
enum FieldType
|
||
|
{
|
||
|
noFieldType = -1,
|
||
|
outputColumn = 0,
|
||
|
param = SQL_PARAM_INPUT,
|
||
|
inputParam = param,
|
||
|
outputParam = SQL_PARAM_OUTPUT,
|
||
|
inoutParam = SQL_PARAM_INPUT_OUTPUT,
|
||
|
};
|
||
|
|
||
|
// Operations (for implementors of RFX procs)
|
||
|
BOOL IsFieldType(UINT* pnField);
|
||
|
|
||
|
// Indicate purpose of subsequent RFX calls
|
||
|
void SetFieldType(UINT nFieldType);
|
||
|
|
||
|
// Implementation
|
||
|
CFieldExchange(UINT nOperation, CRecordset* prs, void* pvField = NULL);
|
||
|
|
||
|
void Default(LPCTSTR szName,
|
||
|
void* pv, LONG* plLength, int nCType, UINT cbValue, UINT cbPrecision);
|
||
|
|
||
|
// long binary helpers
|
||
|
long GetLongBinarySize(int nField);
|
||
|
void GetLongBinaryData(int nField, CLongBinary& lb, long* plSize);
|
||
|
BYTE* ReallocLongBinary(CLongBinary& lb, long lSizeRequired,
|
||
|
long lReallocSize);
|
||
|
|
||
|
// Current type of field
|
||
|
UINT m_nFieldType;
|
||
|
|
||
|
UINT m_nFieldFound;
|
||
|
|
||
|
CString* m_pstr; // Field name or destination for building various SQL clauses
|
||
|
BOOL m_bField; // Value to set for SetField operation
|
||
|
void* m_pvField; // For indicating an operation on a specific field
|
||
|
LPCTSTR m_lpszSeparator; // append after field names
|
||
|
UINT m_nFields; // count of fields for various operations
|
||
|
UINT m_nParams; // count of fields for various operations
|
||
|
UINT m_nParamFields; // count of fields for various operations
|
||
|
HSTMT m_hstmt; // For SQLBindParameter on update statement
|
||
|
long m_lDefaultLBFetchSize; // For fetching CLongBinary data of unknown len
|
||
|
long m_lDefaultLBReallocSize; // For fetching CLongBinary data of unknown len
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
CDumpContext* m_pdcDump;
|
||
|
#endif //_DEBUG
|
||
|
|
||
|
};
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Recordset Field Exchange helpers
|
||
|
void AFXAPI AfxStoreField(CRecordset& rs, UINT nField, void* pvField);
|
||
|
void AFXAPI AfxLoadField(CRecordset& rs, UINT nField,
|
||
|
void* pvField, long* plLength);
|
||
|
BOOL AFXAPI AfxCompareValueByRef(void* pvData, void* pvCache, int nDataType);
|
||
|
void AFXAPI AfxCopyValueByRef(void* pvCache, void* pvData,
|
||
|
long* plLength, int nDataType);
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Standard Recordset Field Exchange routines
|
||
|
|
||
|
// text data
|
||
|
void AFXAPI RFX_Text(CFieldExchange* pFX, LPCTSTR szName, CString& value,
|
||
|
// Default max length for char and varchar, default datasource type
|
||
|
int nMaxLength = 255, int nColumnType = SQL_VARCHAR, short nScale = 0);
|
||
|
|
||
|
// boolean data
|
||
|
void AFXAPI RFX_Bool(CFieldExchange* pFX, LPCTSTR szName, BOOL& value);
|
||
|
|
||
|
// integer data
|
||
|
void AFXAPI RFX_Long(CFieldExchange* pFX, LPCTSTR szName, long& value);
|
||
|
void AFXAPI RFX_Int(CFieldExchange* pFX, LPCTSTR szName, int& value);
|
||
|
void AFXAPI RFX_Single(CFieldExchange* pFX, LPCTSTR szName, float& value);
|
||
|
void AFXAPI RFX_Double(CFieldExchange* pFX, LPCTSTR szName, double& value);
|
||
|
|
||
|
// date and time
|
||
|
void AFXAPI RFX_Date(CFieldExchange* pFX, LPCTSTR szName, CTime& value);
|
||
|
void AFXAPI RFX_Date(CFieldExchange* pFX, LPCTSTR szName, TIMESTAMP_STRUCT& value);
|
||
|
|
||
|
// Binary data
|
||
|
void AFXAPI RFX_Binary(CFieldExchange* pFX, LPCTSTR szName, CByteArray& value,
|
||
|
// Default max length is for binary and varbinary
|
||
|
int nMaxLength = 255);
|
||
|
void AFXAPI RFX_Byte(CFieldExchange* pFX, LPCTSTR szName, BYTE& value);
|
||
|
void AFXAPI RFX_LongBinary(CFieldExchange* pFX, LPCTSTR szName, CLongBinary& value);
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Bulk Recordset Field Exchange helpers
|
||
|
void AFXAPI AfxRFXBulkDefault(CFieldExchange* pFX, LPCTSTR szName,
|
||
|
void* pv, long* rgLengths, int nCType, UINT cbValue);
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Bulk Recordset Field Exchange routines
|
||
|
|
||
|
void AFXAPI RFX_Text_Bulk(CFieldExchange* pFX, LPCTSTR szName,
|
||
|
LPSTR* prgStrVals, long** prgLengths, int nMaxLength);
|
||
|
|
||
|
void AFXAPI RFX_Bool_Bulk(CFieldExchange* pFX, LPCTSTR szName,
|
||
|
BOOL** prgBoolVals, long** prgLengths);
|
||
|
void AFXAPI RFX_Int_Bulk(CFieldExchange* pFX, LPCTSTR szName,
|
||
|
int** prgIntVals, long** prgLengths);
|
||
|
void AFXAPI RFX_Long_Bulk(CFieldExchange* pFX, LPCTSTR szName,
|
||
|
long** prgLongVals, long** prgLengths);
|
||
|
|
||
|
void AFXAPI RFX_Single_Bulk(CFieldExchange* pFX, LPCTSTR szName,
|
||
|
float** prgFltVals, long** prgLengths);
|
||
|
void AFXAPI RFX_Double_Bulk(CFieldExchange* pFX, LPCTSTR szName,
|
||
|
double** prgDblVals, long** prgLengths);
|
||
|
|
||
|
void AFXAPI RFX_Date_Bulk(CFieldExchange* pFX, LPCTSTR szName,
|
||
|
TIMESTAMP_STRUCT** prgTSVals, long** prgLengths);
|
||
|
|
||
|
void AFXAPI RFX_Byte_Bulk(CFieldExchange* pFX, LPCTSTR szName,
|
||
|
BYTE** prgByteVals, long** prgLengths);
|
||
|
void AFXAPI RFX_Binary_Bulk(CFieldExchange* pFX, LPCTSTR szName,
|
||
|
BYTE** prgByteVals, long** prgLengths, int nMaxLength);
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Database Dialog Data Exchange cover routines
|
||
|
// Cover routines provide database semantics on top of DDX routines
|
||
|
|
||
|
// simple text operations
|
||
|
void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, BYTE& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, int& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, UINT& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, long& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, DWORD& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, CString& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, double& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, float& value, CRecordset* pRecordset);
|
||
|
|
||
|
// special control types
|
||
|
void AFXAPI DDX_FieldCheck(CDataExchange* pDX, int nIDC, int& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldRadio(CDataExchange* pDX, int nIDC, int& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldLBString(CDataExchange* pDX, int nIDC, CString& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldCBString(CDataExchange* pDX, int nIDC, CString& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldLBIndex(CDataExchange* pDX, int nIDC, int& index, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldCBIndex(CDataExchange* pDX, int nIDC, int& index, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldLBStringExact(CDataExchange* pDX, int nIDC, CString& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldCBStringExact(CDataExchange* pDX, int nIDC, CString& value, CRecordset* pRecordset);
|
||
|
void AFXAPI DDX_FieldScroll(CDataExchange* pDX, int nIDC, int& value, CRecordset* pRecordset);
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
// CRecordset - the result of a SQL Statement
|
||
|
|
||
|
#define AFX_DB_USE_DEFAULT_TYPE (0xFFFFFFFF)
|
||
|
|
||
|
// Most Move constants out of date
|
||
|
// #define AFX_MOVE_FIRST 0x80000000L
|
||
|
// #define AFX_MOVE_PREVIOUS (-1L)
|
||
|
#define AFX_MOVE_REFRESH 0L
|
||
|
// #define AFX_MOVE_NEXT (+1L)
|
||
|
// #define AFX_MOVE_LAST 0x7fffffffL
|
||
|
|
||
|
#define AFX_RECORDSET_STATUS_OPEN (+1L)
|
||
|
#define AFX_RECORDSET_STATUS_CLOSED 0L
|
||
|
#define AFX_RECORDSET_STATUS_UNKNOWN (-1L)
|
||
|
|
||
|
class CRecordset : public CObject
|
||
|
{
|
||
|
DECLARE_DYNAMIC(CRecordset)
|
||
|
|
||
|
// Constructor
|
||
|
public:
|
||
|
CRecordset(CDatabase* pDatabase = NULL);
|
||
|
|
||
|
public:
|
||
|
virtual ~CRecordset();
|
||
|
|
||
|
enum OpenType
|
||
|
{
|
||
|
dynaset, // uses SQLExtendedFetch, keyset driven cursor
|
||
|
snapshot, // uses SQLExtendedFetch, static cursor
|
||
|
forwardOnly, // uses SQLFetch
|
||
|
dynamic // uses SQLExtendedFetch, dynamic cursor
|
||
|
};
|
||
|
|
||
|
enum OpenOptions
|
||
|
{
|
||
|
none = 0x0,
|
||
|
readOnly = 0x0004,
|
||
|
appendOnly = 0x0008,
|
||
|
skipDeletedRecords = 0x0010, // turn on skipping of deleted records, Will slow Move(n).
|
||
|
noDirtyFieldCheck = 0x0020, // disable automatic dirty field checking
|
||
|
useBookmarks = 0x0100, // turn on bookmark support
|
||
|
useMultiRowFetch = 0x0200, // turn on multi-row fetch model
|
||
|
userAllocMultiRowBuffers = 0x0400, // if multi-row fetch on, user will alloc memory for buffers
|
||
|
useExtendedFetch = 0x0800, // use SQLExtendedFetch with forwardOnly type recordsets
|
||
|
executeDirect = 0x2000, // Directly execute SQL rather than prepared execute
|
||
|
optimizeBulkAdd = 0x4000, // Use prepared HSTMT for multiple AddNews, dirty fields must not change.
|
||
|
firstBulkAdd = 0x8000, // INTERNAL to MFC, don't specify on Open.
|
||
|
};
|
||
|
virtual BOOL Open(UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE,
|
||
|
LPCTSTR lpszSQL = NULL, DWORD dwOptions = none);
|
||
|
virtual void Close();
|
||
|
|
||
|
// Attributes
|
||
|
public:
|
||
|
HSTMT m_hstmt; // Source statement for this resultset
|
||
|
CDatabase* m_pDatabase; // Source database for this resultset
|
||
|
|
||
|
CString m_strFilter; // Where clause
|
||
|
CString m_strSort; // Order By Clause
|
||
|
|
||
|
BOOL CanAppend() const; // Can AddNew be called?
|
||
|
BOOL CanRestart() const; // Can Requery be called to restart a query?
|
||
|
BOOL CanScroll() const; // Can MovePrev and MoveFirst be called?
|
||
|
BOOL CanTransact() const; // Are Transactions supported?
|
||
|
BOOL CanUpdate() const; // Can Edit/AddNew/Delete be called?
|
||
|
BOOL CanBookmark() const; // Can Get/SetBookmark be called?
|
||
|
|
||
|
const CString& GetSQL() const; // SQL executed for this recordset
|
||
|
const CString& GetTableName() const; // Table name
|
||
|
|
||
|
BOOL IsOpen() const; // Recordset successfully opened?
|
||
|
BOOL IsBOF() const; // Beginning Of File
|
||
|
BOOL IsEOF() const; // End Of File
|
||
|
BOOL IsDeleted() const; // On a deleted record
|
||
|
|
||
|
BOOL IsFieldDirty(void *pv); // has field been updated?
|
||
|
BOOL IsFieldNull(void *pv); // is field NULL valued?
|
||
|
BOOL IsFieldNullable(void *pv); // can field be set to a NULL value
|
||
|
|
||
|
long GetRecordCount() const; // Records seen so far or -1 if unknown
|
||
|
void GetStatus(CRecordsetStatus& rStatus) const;
|
||
|
|
||
|
// Operations
|
||
|
public:
|
||
|
// cursor operations
|
||
|
void MoveNext();
|
||
|
void MovePrev();
|
||
|
void MoveFirst();
|
||
|
void MoveLast();
|
||
|
virtual void Move(long nRows, WORD wFetchType = SQL_FETCH_RELATIVE);
|
||
|
|
||
|
void SetAbsolutePosition(long nRows);
|
||
|
|
||
|
void GetBookmark(CDBVariant& varBookmark);
|
||
|
void SetBookmark(const CDBVariant& varBookmark);
|
||
|
|
||
|
virtual void SetRowsetSize(DWORD dwNewRowsetSize);
|
||
|
DWORD GetRowsetSize() const;
|
||
|
DWORD GetRowsFetched() const;
|
||
|
virtual void CheckRowsetError(RETCODE nRetCode);
|
||
|
void RefreshRowset(WORD wRow, WORD wLockType = SQL_LOCK_NO_CHANGE);
|
||
|
void SetRowsetCursorPosition(WORD wRow, WORD wLockType = SQL_LOCK_NO_CHANGE);
|
||
|
WORD GetRowStatus(WORD wRow) const;
|
||
|
|
||
|
// edit buffer operations
|
||
|
virtual void AddNew(); // add new record at the end
|
||
|
virtual void Edit(); // start editing
|
||
|
virtual BOOL Update(); // update it
|
||
|
virtual void Delete(); // delete the current record
|
||
|
void CancelUpdate(); // cancel pending Edit/AddNew
|
||
|
|
||
|
BOOL FlushResultSet() const;
|
||
|
|
||
|
// field operations
|
||
|
short GetODBCFieldCount() const;
|
||
|
void GetODBCFieldInfo(short nIndex, CODBCFieldInfo& fieldinfo);
|
||
|
void GetODBCFieldInfo(LPCTSTR lpszName, CODBCFieldInfo& fieldinfo);
|
||
|
void GetFieldValue(LPCTSTR lpszName, CDBVariant& varValue,
|
||
|
short nFieldType = DEFAULT_FIELD_TYPE);
|
||
|
void GetFieldValue(short nIndex, CDBVariant& varValue,
|
||
|
short nFieldType = DEFAULT_FIELD_TYPE);
|
||
|
void GetFieldValue(LPCTSTR lpszName, CString& strValue);
|
||
|
void GetFieldValue(short nIndex, CString& strValue);
|
||
|
|
||
|
void SetFieldDirty(void *pv, BOOL bDirty = TRUE);
|
||
|
void SetFieldNull(void *pv, BOOL bNull = TRUE);
|
||
|
|
||
|
// locking control during Edit
|
||
|
enum LockMode
|
||
|
{
|
||
|
optimistic,
|
||
|
pessimistic,
|
||
|
};
|
||
|
void SetLockingMode(UINT nMode);
|
||
|
|
||
|
// Recordset operations
|
||
|
virtual BOOL Requery(); // Re-execute query based on new params
|
||
|
|
||
|
// Cancel asynchronous operation
|
||
|
void Cancel();
|
||
|
|
||
|
// Overridables
|
||
|
public:
|
||
|
// Get default connect string
|
||
|
virtual CString GetDefaultConnect();
|
||
|
|
||
|
// Get SQL to execute
|
||
|
virtual CString GetDefaultSQL();
|
||
|
|
||
|
// set special options
|
||
|
virtual void OnSetOptions(HSTMT hstmt);
|
||
|
|
||
|
// for recordset field exchange
|
||
|
virtual void DoFieldExchange(CFieldExchange* pFX);
|
||
|
virtual void DoBulkFieldExchange(CFieldExchange* pFX);
|
||
|
|
||
|
// Implementation
|
||
|
public:
|
||
|
#ifdef _DEBUG
|
||
|
virtual void AssertValid() const;
|
||
|
virtual void Dump(CDumpContext& dc) const;
|
||
|
#endif //_DEBUG
|
||
|
|
||
|
virtual BOOL Check(RETCODE nRetCode) const; // general error check
|
||
|
|
||
|
void InitRecord();
|
||
|
void ResetCursor();
|
||
|
void CheckRowsetCurrencyStatus(UWORD wFetchType, long nRows);
|
||
|
RETCODE FetchData(UWORD wFetchType, SDWORD nRow,
|
||
|
DWORD* pdwRowsFetched);
|
||
|
void SkipDeletedRecords(UWORD wFetchType, long nRows,
|
||
|
DWORD* pdwRowsFetched, RETCODE* pnRetCode);
|
||
|
virtual void SetRowsetCurrencyStatus(RETCODE nRetCode,
|
||
|
UWORD wFetchType, long nRows, DWORD dwRowsFetched);
|
||
|
|
||
|
virtual void PreBindFields(); // called before data fields are bound
|
||
|
UINT m_nFields; // number of RFX fields
|
||
|
UINT m_nParams; // number of RFX params
|
||
|
BOOL m_bCheckCacheForDirtyFields; // switch for dirty field checking
|
||
|
BOOL m_bRebindParams; // date or UNICODE text parameter existence flag
|
||
|
BOOL m_bLongBinaryColumns; // long binary column existence flag
|
||
|
BOOL m_bUseUpdateSQL; // uses SQL-based updates
|
||
|
DWORD m_dwOptions; // archive dwOptions on Open
|
||
|
SWORD m_nResultCols; // number of columns in result set
|
||
|
BOOL m_bUseODBCCursorLib; // uses ODBC cursor lib if m_pDatabase not Open
|
||
|
CODBCFieldInfo* m_rgODBCFieldInfos; // Array of field info structs with ODBC meta-data
|
||
|
CFieldInfo* m_rgFieldInfos; // Array of field info structs with MFC specific field data
|
||
|
CMapPtrToPtr m_mapFieldIndex; // Map of member address to field index
|
||
|
CMapPtrToPtr m_mapParamIndex; // Map of member address to field index
|
||
|
|
||
|
BOOL IsSQLUpdatable(LPCTSTR lpszSQL);
|
||
|
BOOL IsSelectQueryUpdatable(LPCTSTR lpszSQL);
|
||
|
static BOOL PASCAL IsJoin(LPCTSTR lpszJoinClause);
|
||
|
static LPCTSTR PASCAL FindSQLToken(LPCTSTR lpszSQL, LPCTSTR lpszSQLToken);
|
||
|
|
||
|
// RFX Operations on fields of CRecordset
|
||
|
UINT BindParams(HSTMT hstmt);
|
||
|
void RebindParams(HSTMT hstmt);
|
||
|
UINT BindFieldsToColumns();
|
||
|
void BindFieldsForUpdate();
|
||
|
void UnbindFieldsForUpdate();
|
||
|
void Fixups();
|
||
|
UINT AppendNames(CString* pstr, LPCTSTR szSeparator);
|
||
|
UINT AppendValues(HSTMT hstmt, CString* pstr, LPCTSTR szSeparator);
|
||
|
UINT AppendNamesValues(HSTMT hstmt, CString* pstr, LPCTSTR szSeparator);
|
||
|
void StoreFields();
|
||
|
void LoadFields();
|
||
|
void MarkForAddNew();
|
||
|
void MarkForUpdate();
|
||
|
void AllocDataCache();
|
||
|
void FreeDataCache();
|
||
|
#ifdef _DEBUG
|
||
|
void DumpFields(CDumpContext& dc) const;
|
||
|
#endif //_DEBUG
|
||
|
|
||
|
// RFX operation helper functions
|
||
|
virtual void ThrowDBException(RETCODE nRetCode, HSTMT hstmt = SQL_NULL_HSTMT);
|
||
|
|
||
|
int GetBoundFieldIndex(void* pv);
|
||
|
int GetBoundParamIndex(void* pv);
|
||
|
short GetFieldIndexByName(LPCTSTR lpszFieldName);
|
||
|
|
||
|
void AllocStatusArrays();
|
||
|
long* GetFieldLengthBuffer(DWORD nField, int nFieldType); // for fields & params
|
||
|
|
||
|
BYTE GetFieldStatus(DWORD nField);
|
||
|
void SetFieldStatus(DWORD nField, BYTE bFlags);
|
||
|
void ClearFieldStatus();
|
||
|
|
||
|
BOOL IsFieldStatusDirty(DWORD nField) const;
|
||
|
void SetDirtyFieldStatus(DWORD nField);
|
||
|
void ClearDirtyFieldStatus(DWORD nField);
|
||
|
|
||
|
BOOL IsFieldStatusNull(DWORD nField) const;
|
||
|
void SetNullFieldStatus(DWORD nField);
|
||
|
void ClearNullFieldStatus(DWORD nField);
|
||
|
|
||
|
BOOL IsParamStatusNull(DWORD nField) const;
|
||
|
void SetNullParamStatus(DWORD nField);
|
||
|
void ClearNullParamStatus(DWORD nField);
|
||
|
|
||
|
BOOL IsFieldNullable(DWORD nField) const;
|
||
|
|
||
|
void** m_pvFieldProxy;
|
||
|
void** m_pvParamProxy;
|
||
|
UINT m_nProxyFields;
|
||
|
UINT m_nProxyParams;
|
||
|
|
||
|
// GetFieldValue helpers
|
||
|
static short PASCAL GetDefaultFieldType(short nSQLType);
|
||
|
static void* PASCAL GetDataBuffer(CDBVariant& varValue, short nFieldType,
|
||
|
int* pnLen, short nSQLType, UDWORD nPrecision);
|
||
|
static int PASCAL GetTextLen(short nSQLType, UDWORD nPrecision);
|
||
|
static long PASCAL GetData(CDatabase* pdb, HSTMT hstmt, short nFieldIndex,
|
||
|
short nFieldType, LPVOID pvData, int nLen, short nSQLType);
|
||
|
static void PASCAL GetLongBinaryDataAndCleanup(CDatabase* pdb, HSTMT hstmt,
|
||
|
short nFieldIndex, long nActualSize, LPVOID* ppvData, int nLen,
|
||
|
CDBVariant& varValue, short nSQLType);
|
||
|
static void PASCAL GetLongCharDataAndCleanup(CDatabase* pdb, HSTMT hstmt,
|
||
|
short nFieldIndex, long nActualSize, LPVOID* ppvData, int nLen,
|
||
|
CString& strValue, short nSQLType);
|
||
|
|
||
|
protected:
|
||
|
UINT m_nOpenType;
|
||
|
UINT m_nDefaultType;
|
||
|
enum EditMode
|
||
|
{
|
||
|
noMode,
|
||
|
edit,
|
||
|
addnew
|
||
|
};
|
||
|
long m_lOpen;
|
||
|
UINT m_nEditMode;
|
||
|
BOOL m_bEOFSeen;
|
||
|
long m_lRecordCount;
|
||
|
long m_lCurrentRecord;
|
||
|
CString m_strCursorName;
|
||
|
// Perform operation based on m_nEditMode
|
||
|
BOOL UpdateInsertDelete();
|
||
|
BOOL m_nLockMode; // Control concurrency for Edit()
|
||
|
UDWORD m_dwDriverConcurrency; // driver supported concurrency types
|
||
|
UDWORD m_dwConcurrency; // requested concurrency type
|
||
|
UWORD* m_rgRowStatus; // row status used by SQLExtendedFetch and SQLSetPos
|
||
|
DWORD m_dwRowsFetched; // number of rows fetched by SQLExtendedFetch
|
||
|
HSTMT m_hstmtUpdate;
|
||
|
BOOL m_bRecordsetDb;
|
||
|
BOOL m_bBOF;
|
||
|
BOOL m_bEOF;
|
||
|
BOOL m_bUpdatable; // Is recordset updatable?
|
||
|
BOOL m_bAppendable;
|
||
|
CString m_strSQL; // SQL statement for recordset
|
||
|
CString m_strUpdateSQL; // SQL statement for updates
|
||
|
CString m_strTableName; // source table of recordset
|
||
|
BOOL m_bScrollable; // supports MovePrev
|
||
|
BOOL m_bDeleted;
|
||
|
int m_nFieldsBound;
|
||
|
BYTE* m_pbFieldFlags;
|
||
|
BYTE* m_pbParamFlags;
|
||
|
LONG* m_plParamLength;
|
||
|
DWORD m_dwInitialGetDataLen; // Initial GetFieldValue alloc size for long data
|
||
|
DWORD m_dwRowsetSize;
|
||
|
DWORD m_dwAllocatedRowsetSize;
|
||
|
|
||
|
protected:
|
||
|
CString m_strRequerySQL; // archive SQL string for use in Requery()
|
||
|
CString m_strRequeryFilter; // archive filter string for use in Requery()
|
||
|
CString m_strRequerySort; // archive sort string for use in Requery()
|
||
|
|
||
|
void SetState(int nOpenType, LPCTSTR lpszSQL, DWORD dwOptions);
|
||
|
BOOL AllocHstmt();
|
||
|
void BuildSQL(LPCTSTR lpszSQL);
|
||
|
void PrepareAndExecute();
|
||
|
|
||
|
void BuildSelectSQL();
|
||
|
void AppendFilterAndSortSQL();
|
||
|
BOOL IsRecordsetUpdatable();
|
||
|
|
||
|
void VerifyDriverBehavior();
|
||
|
DWORD VerifyCursorSupport();
|
||
|
void EnableBookmarks();
|
||
|
void SetUpdateMethod();
|
||
|
void SetConcurrencyAndCursorType(HSTMT hstmt, DWORD dwScrollOptions);
|
||
|
void AllocAndCacheFieldInfo();
|
||
|
void AllocRowset();
|
||
|
void FreeRowset();
|
||
|
|
||
|
void ExecuteSetPosUpdate();
|
||
|
void PrepareUpdateHstmt();
|
||
|
void BuildUpdateSQL();
|
||
|
void ExecuteUpdateSQL();
|
||
|
void SendLongBinaryData(HSTMT hstmt);
|
||
|
virtual long GetLBFetchSize(long lOldSize); // CLongBinary fetch chunking
|
||
|
virtual long GetLBReallocSize(long lOldSize); // CLongBinary realloc chunking
|
||
|
|
||
|
friend class CFieldExchange;
|
||
|
friend class CRecordView;
|
||
|
};
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Info helper definitions
|
||
|
#define AFX_CURRENT_RECORD_UNDEFINED (-2)
|
||
|
#define AFX_CURRENT_RECORD_BOF (-1)
|
||
|
|
||
|
// For returning status for a recordset
|
||
|
struct CRecordsetStatus
|
||
|
{
|
||
|
long m_lCurrentRecord; // -2=Unknown,-1=BOF,0=1st record. . .
|
||
|
BOOL m_bRecordCountFinal;// Have we counted all records?
|
||
|
};
|
||
|
|
||
|
// Must maintian data binding info
|
||
|
struct CFieldInfo
|
||
|
{
|
||
|
// MFC specific info
|
||
|
void* m_pvDataCache;
|
||
|
long m_nLength;
|
||
|
int m_nDataType;
|
||
|
BYTE m_bStatus;
|
||
|
#ifdef _DEBUG
|
||
|
void* m_pvBindAddress;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
struct CODBCFieldInfo
|
||
|
{
|
||
|
// meta data from ODBC
|
||
|
CString m_strName;
|
||
|
SWORD m_nSQLType;
|
||
|
UDWORD m_nPrecision;
|
||
|
SWORD m_nScale;
|
||
|
SWORD m_nNullability;
|
||
|
};
|
||
|
|
||
|
struct CODBCParamInfo
|
||
|
{
|
||
|
// meta data from ODBC
|
||
|
SWORD m_nSQLType;
|
||
|
UDWORD m_nPrecision;
|
||
|
SWORD m_nScale;
|
||
|
SWORD m_nNullability;
|
||
|
};
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CDBVariant
|
||
|
|
||
|
#define DBVT_NULL 0
|
||
|
#define DBVT_BOOL 1
|
||
|
#define DBVT_UCHAR 2
|
||
|
#define DBVT_SHORT 3
|
||
|
#define DBVT_LONG 4
|
||
|
#define DBVT_SINGLE 5
|
||
|
#define DBVT_DOUBLE 6
|
||
|
#define DBVT_DATE 7
|
||
|
#define DBVT_STRING 8
|
||
|
#define DBVT_BINARY 9
|
||
|
|
||
|
class CDBVariant
|
||
|
{
|
||
|
// Constructor
|
||
|
public:
|
||
|
CDBVariant();
|
||
|
|
||
|
// Attributes
|
||
|
public:
|
||
|
DWORD m_dwType;
|
||
|
|
||
|
union
|
||
|
{
|
||
|
BOOL m_boolVal;
|
||
|
unsigned char m_chVal;
|
||
|
short m_iVal;
|
||
|
long m_lVal;
|
||
|
float m_fltVal;
|
||
|
double m_dblVal;
|
||
|
TIMESTAMP_STRUCT* m_pdate;
|
||
|
CString* m_pstring;
|
||
|
CLongBinary* m_pbinary;
|
||
|
};
|
||
|
|
||
|
// Operations
|
||
|
void Clear();
|
||
|
|
||
|
// Implementation
|
||
|
public:
|
||
|
virtual ~CDBVariant();
|
||
|
};
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CRecordView - form for viewing data records
|
||
|
|
||
|
class CRecordView : public CFormView
|
||
|
{
|
||
|
DECLARE_DYNAMIC(CRecordView)
|
||
|
|
||
|
// Construction
|
||
|
protected: // must derive your own class
|
||
|
CRecordView(LPCTSTR lpszTemplateName);
|
||
|
CRecordView(UINT nIDTemplate);
|
||
|
|
||
|
// Attributes
|
||
|
public:
|
||
|
virtual CRecordset* OnGetRecordset() = 0;
|
||
|
|
||
|
BOOL IsOnLastRecord();
|
||
|
BOOL IsOnFirstRecord();
|
||
|
|
||
|
// Operations
|
||
|
public:
|
||
|
virtual BOOL OnMove(UINT nIDMoveCommand);
|
||
|
|
||
|
// Implementation
|
||
|
public:
|
||
|
virtual ~CRecordView();
|
||
|
#ifdef _DEBUG
|
||
|
virtual void AssertValid() const;
|
||
|
virtual void Dump(CDumpContext& dc) const;
|
||
|
#endif
|
||
|
virtual void OnInitialUpdate();
|
||
|
|
||
|
protected:
|
||
|
BOOL m_bOnFirstRecord;
|
||
|
BOOL m_bOnLastRecord;
|
||
|
|
||
|
//{{AFX_MSG(CRecordView)
|
||
|
afx_msg void OnUpdateRecordFirst(CCmdUI* pCmdUI);
|
||
|
afx_msg void OnUpdateRecordPrev(CCmdUI* pCmdUI);
|
||
|
afx_msg void OnUpdateRecordNext(CCmdUI* pCmdUI);
|
||
|
afx_msg void OnUpdateRecordLast(CCmdUI* pCmdUI);
|
||
|
//}}AFX_MSG
|
||
|
afx_msg void OnMove(int cx, int cy);
|
||
|
|
||
|
DECLARE_MESSAGE_MAP()
|
||
|
};
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Inline function declarations
|
||
|
|
||
|
#ifdef _AFX_PACKING
|
||
|
#pragma pack(pop)
|
||
|
#endif
|
||
|
|
||
|
#ifdef _AFX_ENABLE_INLINES
|
||
|
#define _AFXDBCORE_INLINE inline
|
||
|
#define _AFXDBRFX_INLINE inline
|
||
|
#define _AFXDBVIEW_INLINE inline
|
||
|
#include <afxdb.inl>
|
||
|
#undef _AFXDBVIEW_INLINE
|
||
|
#undef _AFXDBCORE_INLINE
|
||
|
#undef _AFXDBRFX_INLINE
|
||
|
#endif
|
||
|
|
||
|
#undef AFX_DATA
|
||
|
#define AFX_DATA
|
||
|
|
||
|
#ifdef _AFX_MINREBUILD
|
||
|
#pragma component(minrebuild, on)
|
||
|
#endif
|
||
|
#ifndef _AFX_FULLTYPEINFO
|
||
|
#pragma component(mintypeinfo, off)
|
||
|
#endif
|
||
|
|
||
|
#endif //__AFXDB_H__
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|