QueryDef.h
资源名称:querydef.zip [点击查看]
上传用户:yunnanyeer
上传日期:2007-01-03
资源大小:86k
文件大小:18k
源码类别:
数据库编程
开发平台:
Visual C++
- // QueryDef.h: interface for the CQueryDef class.
- // See accompanying document QueryDef - a complete implementation of a dynamic recordset.doc
- // Eugen Paval (C) 1998, 1999
- // Revision History:
- // 01/17/1998 - V1.0 - Retrieving data only thru GetSQLData
- // 02/23/1998 - V1.5 - Support for positioned updates and dynamic binding thru RFX_ functions
- // 03/14/1998 - V2.0 - Support for notifications and column descriptors
- // 08/25/1998 - V2.01- Bugs fixed in changing the datatype
- // 01/18/1999 - V2.02- Revision and fixups for known issues
- //
- // To compile the library define the symbol _QUERYDEFCOMPILE
- //////////////////////////////////////////////////////////////////////
- #if !defined(AFX_QUERYDEF_H__A94B98EA_5F3C_11D1_898E_0080C83612CB__INCLUDED_)
- #define AFX_QUERYDEF_H__A94B98EA_5F3C_11D1_898E_0080C83612CB__INCLUDED_
- #if defined(_QUERYDEFCOMPILE) // compile the library
- #if !defined(_AFXEXT)
- #define _AFXEXT // export AFX_EXT_CLASS
- #endif // _AFXEXT
- #else
- #if defined(_AFXEXT)
- #undef _AFXEXT // import AFX_EXT_CLASS
- #define _GUARDIAN_ANGEL // see the end of this file
- #endif // _AFXEXT
- #endif // _QUERYDEFCOMPILE
- #if _MSC_VER >= 1000
- #pragma once
- #endif // _MSC_VER >= 1000
- #if !defined(__AFXDB_H__)
- #define __AFXDB_H__
- #include <afxdb.h>
- #endif
- #include <afxdisp.h>
- #include <afxtempl.h>
- #include <Recordset2.h> // fixes a bug in CRecordset &
- // adds fixups to output params
- #define MAX_SHORT 32767
- #define USE_QUERYDEF using namespace QueryDef; // shortcut to namespace
- namespace QueryDef // use namespace required
- {
- class CQueryDefException;
- class CQueryVar;
- class CQueryVariant;
- class CQueryDef;
- class CQueryCol;
- class CQueryDefDefaultSink;
- class CTabbedString;
- class CSQLNull;
- class CQueryDefException : public CDBException // not yet implemented
- {
- };
- class AFX_EXT_CLASS CQueryVar : public CDBVariant
- {
- short m_decPlaces; // decimal places for float,double->string conversions
- CString m_dateFormat; // the implicit format for date & time values
- CString m_convert; // placeholder for conversion operators
- BYTE m_allocFlags; // shows the alloc status of the m_pxxx pointers
- // 0 = nothing allocated, 1 = m_pstring, 2 = m_pdate, 4 = m_pbinary
- void ConstructObject();
- LPCTSTR ToString(); // convert this object to string
- enum AllocFlags {
- eAllocNothing = 0,
- eAllocString = 1,
- eAllocDate = 2,
- eAllocBinary=4
- }; // alloc flags
- void ChangeDataType(int allocFlags); // changes the data type
- public:
- CQueryVar();
- CQueryVar(LPCTSTR str);
- CQueryVar(int i);
- CQueryVar(long l);
- CQueryVar(short s);
- CQueryVar(float f);
- CQueryVar(double d);
- CQueryVar(COleDateTime& t);
- CQueryVar(CLongBinary& lB);
- virtual ~CQueryVar();
- operator LPCTSTR();
- operator int();
- operator BYTE();
- operator long();
- operator short();
- operator float();
- operator double();
- operator void*();
- operator COleDateTime&();
- operator CLongBinary&();
- operator CStringArray&();
- CQueryVar& operator=(UCHAR ch);
- CQueryVar& operator=(long l);
- CQueryVar& operator=(int l);
- CQueryVar& operator=(short s);
- CQueryVar& operator=(float f);
- CQueryVar& operator=(double d);
- CQueryVar& operator=(LPCTSTR str);
- CQueryVar& operator=(COleDateTime& date);
- CQueryVar& operator=(CLongBinary& lB);
- CQueryVar& operator=(CQueryVar& v);
- CQueryVar& operator=(CSQLNull& sqlNull) { SetNull(); return *this; };
- BOOL operator==(CSQLNull& sqlNull);
- BOOL operator!=(CSQLNull& sqlNull);
- void SetNull(void) { m_dwType = DBVT_NULL; }; // sets this object to NULL (SQL Server view)
- BOOL IsNull(void) { return m_dwType == DBVT_NULL; };
- short SetDecimalDigits(short d);
- short GetDecimalDigits() { return m_decPlaces; };
- LPCSTR SetDateFormat(LPCSTR strDateFormat);
- LPCTSTR GetDateFormat() const { return m_dateFormat; };
- public:
- enum eException {
- eConversionError = 1, // conversion not supported
- eMemoryLimit, // CString may not exceed 32K
- eBoundary
- };
- friend class CQueryVariant;
- friend class CQueryDef;
- };
- typedef CArray<CQueryVar,CQueryVar&> CQueryVarArray; // metaclass for an array of CQueryVar
- // template <CQueryVar> void AFXAPI ConstructElements(CQueryVar* pNewQueryVar,int nCount);
- class AFX_EXT_CLASS CQueryVariant
- {
- CQueryVarArray m_varDB; // holds the columns
- short m_decPlaces; // decimal places for float,double->string conversions
- CString m_dateFormat; // the implicit format for date & time values
- void ConstructObject();
- void SetSize(int nNewSize); // shrink or grow the array m_varDB
- public:
- CQueryVariant();
- CQueryVariant(LPCTSTR str);
- CQueryVariant(int i);
- CQueryVariant(long l);
- CQueryVariant(short s);
- CQueryVariant(float f);
- CQueryVariant(double d);
- CQueryVariant(COleDateTime& t);
- CQueryVariant(CLongBinary& lB);
- virtual ~CQueryVariant();
- operator CString();
- operator int();
- operator BYTE();
- operator long();
- operator short();
- operator float();
- operator double();
- operator COleDateTime&();
- operator CLongBinary&();
- operator LPCTSTR();
- CQueryVar& operator[](int i);
- CQueryVariant& operator=(CQueryVariant& v);
- CQueryVariant& operator=(CStringArray& srcArray); // to transfer all columns to strings
- public:
- enum eException {
- eConversionError = 1, // conversion not supported
- eMemoryLimit, // CString may not exceed 32K
- eBoundary
- };
- short SetDecimalDigits(short d); // format float and double values with this digits
- LPCSTR SetDateFormat(LPCSTR strFormat); // format date-time values with this format
- WORD Columns() { return m_varDB.GetSize(); };
- friend class CQueryDef;
- friend class CTabbedString;
- };
- // V2.0 SQL columns descriptors
- class AFX_EXT_CLASS CQueryCol // describe an SQL column
- {
- CQueryVar* m_pValue;
- CODBCFieldInfo* m_pfldInfo;
- public:
- CQueryCol();
- CQueryCol(CQueryVar& qv,CODBCFieldInfo& fi);
- ~CQueryCol();
- CQueryVar& Value() { return *m_pValue; };
- LPCTSTR Name() const { return m_pfldInfo->m_strName; };
- SWORD SQLType() const { return m_pfldInfo->m_nSQLType; };
- DWORD Type() const { return m_pValue->m_dwType; };
- UDWORD Precision() const { return m_pfldInfo->m_nPrecision; };
- SWORD Scale() const { return m_pfldInfo->m_nScale; };
- SWORD IsNullable() const { return m_pfldInfo->m_nNullability; };
- };
- // V2.0 notification events
- typedef POSITION EVNHANDLE;
- struct IQueryDefEventSink // CQueryDef event sink
- {
- // possible notifications - returning 0 means proceed with the next notification otherwise stop
- virtual LPARAM RSNotifyOpen(EVNHANDLE) = 0; // the recordset has been opened
- virtual LPARAM RSNotifyClose(EVNHANDLE) = 0; // the recordset has been closed
- virtual LPARAM RSNotifyMove(EVNHANDLE) = 0; // the recordset has modified the current position
- virtual LPARAM RSNotifyAddNew(EVNHANDLE) = 0; // recordset is about to insert a new record (called after CQueryDef::AddNew)
- virtual LPARAM RSNotifyEdit(EVNHANDLE) = 0; // the current record will be modified to be updated (called after CQueryDef::Edit)
- virtual LPARAM RSNotifyUpdate(EVNHANDLE) = 0; // the current record will be updated (called after CQueryDef::Update)
- virtual LPARAM RSNotifyDelete(EVNHANDLE) = 0; // the current record was deleted
- virtual LPARAM RSNotifyCancelUpdate(EVNHANDLE) = 0; // the update of the current record was canceled (called after CQueryDef::CancelUpdate)
- virtual LPARAM RSNotifyRequery(EVNHANDLE) = 0; // the recordset was refreshed
- virtual LPARAM RSNotifyFormatChanged(EVNHANDLE,BYTE nFormat) = 0; // number of decimal digits or date format has been changed
- };
- // the default implementation of a sink which does nothing
- // derive from it and implement only the notification wanted
- class AFX_EXT_CLASS CQueryDefDefaultSink : public IQueryDefEventSink
- {
- public:
- LPARAM RSNotifyOpen(EVNHANDLE) {return 0;}; // the recordset has been opened
- LPARAM RSNotifyClose(EVNHANDLE) {return 0;}; // the recordset has been closed
- LPARAM RSNotifyMove(EVNHANDLE) {return 0;}; // the recordset has modified the current position
- LPARAM RSNotifyAddNew(EVNHANDLE) {return 0;}; // recordset is about to insert a new record (called after CQueryDef::AddNew)
- LPARAM RSNotifyEdit(EVNHANDLE) {return 0;}; // the current record will be modified to be updated (called after CQueryDef::Edit)
- LPARAM RSNotifyUpdate(EVNHANDLE) {return 0;}; // the current record will be updated (called after CQueryDef::Update)
- LPARAM RSNotifyDelete(EVNHANDLE) {return 0;}; // the current record was deleted
- LPARAM RSNotifyCancelUpdate(EVNHANDLE) {return 0;}; // the update of the current record was canceled (called after CQueryDef::CancelUpdate)
- LPARAM RSNotifyRequery(EVNHANDLE) {return 0;}; // the recordset was refreshed
- LPARAM RSNotifyFormatChanged(EVNHANDLE,BYTE nFormat){return 0;}; // number of decimal digits or date format has been changed
- };
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // QueryDefinition class used for retrieving (V1.0) & updating data (V1.5) from SQL Server
- // It may be used with stored procedures as well
- // Great use in dynamic recordsets in conjunction with the CQueryVariant datatype
- // Usage:
- // select * from T where ... group by ... having ... order by ...
- // {?=CALL stored_procedure(input_param1,input_param2,...,?,...,?'type-letter')}
- // where
- // ? is a placeholder for parameters (? input param, ?'type-letter' output param)
- //
- // where type-letter:
- // L = long, F = float, D = double, I = int, Y = byte, C = char, X = binary, T = date-time, B = bool
- //
- // Due to different behaviour of various ODBC drivers, CQueryDef cannot be used to return output parameters
- // altogether with rows. There is also a limitation in returning rows and the use of SQL Server based cursors.
- // Rules of thumb:
- // 1. return rows w/o output parameters
- // 2. don't return rows if you're using SQL based cursors (output params are legal)
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////
- struct SQueryDefEventSink
- {
- SQueryDefEventSink(IQueryDefEventSink* pSink,BOOL bFreeze)
- {
- m_pSink = pSink;
- m_frozen = bFreeze;
- };
- IQueryDefEventSink* m_pSink;
- BOOL m_frozen;
- };
- typedef CArray<CQueryCol,CQueryCol&> CQueryColArray; // an array of SQL column descriptors
- typedef CList<SQueryDefEventSink*,SQueryDefEventSink*> CSinkList; // the list of event sinks for notification
- class AFX_EXT_CLASS CQueryDef : public CRecordset2
- {
- DECLARE_DYNAMIC(CQueryDef);
- CQueryVariant m_cLine; // current line
- CQueryVariant m_cParam; // input & output parameters
- char m_ioParam[256]; // a maximum of 256 Params are allowed
- // 0 = input, 'type-letter' = output
- CString m_originalQuery; // the query as given by the user
- CArray<CODBCFieldInfo,int> m_ODBCFieldInfo; // columns information
- enum { eModeNoMode,eModeAddNew,eModeEdit }; // the edit modes (see below)
- int m_nMode; // signal AddNew is in progress
- // changed from V1.0 to RFX_xxx bindings in later versions
- // void GetSQLData(); // fills in the current line
- // see ReOpen()
- UINT m_nOpenType; // for implementation of ReOpen()
- CString m_strSQL;
- DWORD m_dwOptions;
- public:
- CQueryDef(CDatabase* pDB = NULL);
- CQueryDef(CDatabase* pConn,LPCSTR strSQL); // support for ad-hoc queries
- virtual ~CQueryDef();
- operator CQueryVariant&() { return m_cLine; }; // for direct access from this object
- CQueryVariant& Fields() { return m_cLine; }; // access to fields
- CQueryVar& Field(int i); // access to fields
- CQueryVar& Field(LPCTSTR fldName); // access to fields
- CQueryVariant& Params() { return m_cParam; }; // access to stored procedure's parameters
- CQueryVar& Param(int i); // access to stored procedure's parameters
- // conversion operators to use directly
- operator int() { return (int)m_cLine; }; // this class object when a single column
- operator BYTE() { return (BYTE)m_cLine; }; // or the first column are to be retrieved
- operator long() { return (long)m_cLine; };
- operator short() { return (short)m_cLine; };
- operator float() { return (float)m_cLine; };
- operator double() { return (double)m_cLine; };
- operator COleDateTime&() { return m_cLine.operator COleDateTime&(); };
- operator CLongBinary&() { return (CLongBinary&)m_cLine; };
- operator CStringArray&() { return (CStringArray&)m_cLine; };
- operator LPCTSTR() { return (LPCTSTR)m_cLine; };
- CQueryVar& operator[](int i); // access to fields by index
- CQueryVar& operator[](LPCTSTR lpszColumnName); // access to fields by column name
- CQueryVariant& operator=(CQueryVariant& v); // transfer the current line to a CQueryVariant
- virtual BOOL Open(UINT nOpenType=forwardOnly,
- LPCTSTR lpszSQL = NULL,
- DWORD dwOptions = readOnly|noDirtyFieldCheck|executeDirect);
- virtual void Close();
- // ReOpen() makes it possible to open again the querydef in case the database connection was broken
- virtual BOOL ReOpen(CDatabase* pDB); // connection broken & remade
- virtual void Move(long nRows,WORD wFetchType = SQL_FETCH_RELATIVE);
- virtual void PreBindFields(); // undocumented - called before first Move
- virtual void AddNew(); // needed for fixup the buffer adress change assert
- virtual void Edit();
- virtual BOOL Update();
- virtual void Delete();
- virtual BOOL Requery();
- void CancelUpdate(); // since this is not virtual must be explicitly called
- void SetFieldNull(void* pv,BOOL bNull = TRUE); // not implemented to generate a link error
- void SetParamNull(int nIndex,BOOL bNull = TRUE);
- short SetDecimalDigits(short d);
- LPCSTR SetDateFormat(LPCSTR strFormat);
- protected:
- virtual void DoFieldExchange(CFieldExchange* pFX);
- void BindParams(CFieldExchange* pFX);
- void BindFields(CFieldExchange* pFX);
- friend class CTabbedString;
- // V2.0
- private:
- CQueryColArray m_columns; // SQL column descriptors (V2.0)
- CSinkList m_evSink; // the notification sinks
- enum ENOTIFICATION // notification type
- {
- eNotifyOpen,
- eNotifyClose,
- eNotifyMove,
- eNotifyAddNew,
- eNotifyEdit,
- eNotifyUpdate,
- eNotifyDelete,
- eNotifyCancelUpdate,
- eNotifyRequery,
- eNotifyFormatChanged
- };
- enum // format changed enumerators
- {
- eFormatChangedDecimalDigits = 0xFF,
- eFormatChangedDate = 0xFE
- };
- void FreezeAllEvents(BOOL bFreeze=TRUE); // internal freeze
- void ClearEventSinkList(); // remove event sinks & cleanup
- public:
- // V2.0 notifications
- EVNHANDLE Advise(IQueryDefEventSink* pSink); // connects the notification sink
- void Unadvise(EVNHANDLE evnHandle);
- void FreezeEvents(EVNHANDLE evnHandle,BOOL bFreeze=TRUE); // temporarily start or stop notifications
- void NotifySink(ENOTIFICATION nNotify,LPARAM lp = 0); // notify all sinks
- // V2.0 SQL column descriptors
- CQueryColArray& Columns() { return m_columns; };
- CQueryCol& Column(int i);
- CQueryCol& Column(LPCTSTR colName);
- };
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Helper classes to be used with CQueryDef and CQueryVariant
- //
- // CTabbedString - a string with <TAB> between columns
- //
- // NULL columns are represented with value <NULL> (as it is written i.e. with angle brackets)
- class AFX_EXT_CLASS CTabbedString : public CString
- {
- public:
- CTabbedString() : CString() {};
- CTabbedString(const CString& stringSrc) : CString(stringSrc) {};
- CTabbedString(TCHAR ch,int nRepeat = 1) : CString(ch,nRepeat) {};
- CTabbedString(LPCTSTR lpch,int nLength) : CString(lpch,nLength) {};
- CTabbedString(const unsigned char* psz) : CString(psz) {};
- CTabbedString(LPCWSTR lpsz) : CString(lpsz) {};
- CTabbedString(LPCSTR lpsz) : CString(lpsz) {};
- virtual ~CTabbedString() {};
- CTabbedString& operator=(CQueryDef& qDef); // get the current row from this qDef
- CTabbedString& operator=(CQueryVariant& qV); // get the values from this qV
- CTabbedString operator[](int i); // access to individual elements
- BOOL operator==(CSQLNull& sqlNull);
- BOOL operator!=(CSQLNull& sqlNull);
- BOOL IsNull(int i); // test the ith element for NULL value
- };
- // CSQLNull - helper class to test the above classes for SQL NULL value
- //
- class CSQLNull
- {
- public:
- static const int SqlNull;
- public:
- BOOL operator==(CQueryVar& qVar);
- BOOL operator!=(CQueryVar& qVar);
- BOOL operator==(CTabbedString& qVar);
- BOOL operator!=(CTabbedString& qVar);
- };
- inline CQueryVar& CQueryDef::Field(int i)
- {
- return operator[](i);
- };
- inline CQueryVar& CQueryDef::Field(LPCTSTR fldName)
- {
- return operator[](fldName);
- };
- inline CQueryVar& CQueryDef::Param(int i)
- {
- return m_cParam.operator[](i);
- };
- inline CQueryCol& CQueryDef::Column(int i)
- {
- if (i >= m_columns.GetSize())
- throw CQueryVar::eBoundary;
- return m_columns[i];
- };
- // global functions
- const char chHexDigits[] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
- CString ConvertToHex(void* pbinary,int length); // converts a binary stream to hex representation
- }; // namespace QueryDef
- #if !defined(_QUERYDEFCOMPILE)
- __declspec(dllimport) QueryDef::CSQLNull SQL_NULL; // use this value to test for SQL NULL
- #if defined(_DEBUG)
- #pragma comment(lib,"QueryDefD")
- #else
- #pragma comment(lib,"QueryDef")
- #endif // defined(_DEBUG)
- #endif // defined(_AFXEXT)
- #if defined(_GUARDIAN_ANGEL)
- #define _AFXEXT
- #endif
- #endif // !defined(AFX_QUERYDEF_H__A94B98EA_5F3C_11D1_898E_0080C83612CB__INCLUDED_)