527 lines
19 KiB
C++
527 lines
19 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1994 - 2000.
|
||
|
//
|
||
|
// File: rowset.hxx
|
||
|
//
|
||
|
// Contents: Declarations of classes which implement IRowset and
|
||
|
// related OLE DB interfaces over file stores.
|
||
|
//
|
||
|
// Classes: CRowset - cached table over file stores
|
||
|
//
|
||
|
// History: 05 Nov 94 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <coldesc.hxx>
|
||
|
#include <pidmap.hxx>
|
||
|
#include <rowseek.hxx>
|
||
|
|
||
|
#include <conpt.hxx>
|
||
|
#include <hraccess.hxx>
|
||
|
#include <rstprop.hxx>
|
||
|
#include <proprst.hxx>
|
||
|
#include <proputl.hxx>
|
||
|
|
||
|
#include <srvprvdr.h> // IServiceProperties
|
||
|
|
||
|
class PQuery;
|
||
|
class XRowsInfo;
|
||
|
|
||
|
class CRowBufferSet;
|
||
|
class CAccessor;
|
||
|
|
||
|
class CRowsetNotification;
|
||
|
class CRowsetAsynchNotification;
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Class: CRowset
|
||
|
//
|
||
|
// Purpose: Large table interface for file stores.
|
||
|
//
|
||
|
// Interface: IRowsetScroll and its superclasses.
|
||
|
//
|
||
|
// History: 05 Nov 94 AlanW Created
|
||
|
// 28 Mar 95 BartoszM Added IRowsetWatchRegion
|
||
|
// 03 Sep 99 KLam Reinstated _ConvertOffsetstoPointers
|
||
|
//
|
||
|
// Notes: Supports IRowset, IDBAsynchStatus, IRowsetInfo, IRowsetLocate,
|
||
|
// IRowsetScroll and IRowsetWatchRegion on
|
||
|
// cached data. Also supports IAccessor, IColumnsInfo and
|
||
|
// IConnectionPointContainer via embedded objects
|
||
|
// Executes in user mode from the client machine.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
class CRowset : public IRowsetExactScroll, public IAccessor,
|
||
|
public IRowsetInfo, public IRowsetIdentity,
|
||
|
public IDBAsynchStatus, public IConvertType,
|
||
|
public IRowsetWatchRegion, public IRowsetQueryStatus,
|
||
|
public IServiceProperties, public IChapteredRowset,
|
||
|
public IRowsetAsynch //(deprecated)
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
//
|
||
|
// IUnknown methods.
|
||
|
//
|
||
|
|
||
|
STDMETHOD(QueryInterface) ( THIS_ REFIID riid,
|
||
|
LPVOID *ppiuk )
|
||
|
{
|
||
|
return _pControllingUnknown->QueryInterface(riid,ppiuk);
|
||
|
}
|
||
|
|
||
|
STDMETHOD_(ULONG, AddRef) (THIS) { return _pControllingUnknown->AddRef();}
|
||
|
|
||
|
STDMETHOD_(ULONG, Release) (THIS) {return _pControllingUnknown->Release(); }
|
||
|
|
||
|
SCODE RealQueryInterface ( REFIID riid, LPVOID *ppiuk ); // used by _pControllingUnknown
|
||
|
// in aggregation - does QI without delegating to outer unknown
|
||
|
|
||
|
//
|
||
|
// IAccessor methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(AddRefAccessor) (HACCESSOR hAccessor,
|
||
|
ULONG * pcRefCount);
|
||
|
|
||
|
STDMETHOD(CreateAccessor) (DBACCESSORFLAGS dwBindIO,
|
||
|
DBCOUNTITEM cBindings,
|
||
|
const DBBINDING rgBindings[],
|
||
|
DBLENGTH cbRowSize,
|
||
|
HACCESSOR * phAccessor,
|
||
|
DBBINDSTATUS rgStatus[]);
|
||
|
|
||
|
STDMETHOD(GetBindings) (HACCESSOR hAccessor,
|
||
|
DBACCESSORFLAGS * pdwBindIO,
|
||
|
DBCOUNTITEM * pcBindings,
|
||
|
DBBINDING * * prgBindings) /*const*/;
|
||
|
|
||
|
STDMETHOD(ReleaseAccessor) (HACCESSOR hAccessor,
|
||
|
ULONG * pcRefCount);
|
||
|
|
||
|
//
|
||
|
// IRowset methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(AddRefRows) (DBCOUNTITEM cRows,
|
||
|
const HROW rghRows [],
|
||
|
DBREFCOUNT rgRefCounts[],
|
||
|
DBROWSTATUS rgRowStatus[]);
|
||
|
|
||
|
STDMETHOD(GetData) (HROW hRow,
|
||
|
HACCESSOR hAccessor,
|
||
|
void * pData) /*const*/;
|
||
|
|
||
|
STDMETHOD(GetNextRows) (HCHAPTER hChapter,
|
||
|
DBROWOFFSET cRowsToSkip,
|
||
|
DBROWCOUNT cRows,
|
||
|
DBCOUNTITEM * pcRowsObtained,
|
||
|
HROW * * prghRows);
|
||
|
|
||
|
STDMETHOD(GetReferencedRowset) (DBORDINAL iOrdinal,
|
||
|
REFIID riid,
|
||
|
IUnknown ** ppReferencedRowset) /*const*/;
|
||
|
|
||
|
STDMETHOD(GetProperties) (const ULONG cPropertyIDSets,
|
||
|
const DBPROPIDSET rgPropertyIDSets[],
|
||
|
ULONG * pcPropertySets,
|
||
|
DBPROPSET ** prgPropertySets);
|
||
|
|
||
|
STDMETHOD(GetSpecification) (REFIID riid,
|
||
|
IUnknown ** ppSpecification);
|
||
|
|
||
|
STDMETHOD(ReleaseRows) (DBCOUNTITEM cRows,
|
||
|
const HROW rghRows [],
|
||
|
DBROWOPTIONS rgRowOptions[],
|
||
|
DBREFCOUNT rgRefCounts[],
|
||
|
DBROWSTATUS rgRowStatus[]);
|
||
|
|
||
|
STDMETHOD(RestartPosition) (HCHAPTER hChapter);
|
||
|
|
||
|
#if 0
|
||
|
//
|
||
|
// IParentRowset methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(GetChildRowset) (IUnknown * pUnkOuter,
|
||
|
ULONG iOrdinal,
|
||
|
REFIID riid,
|
||
|
IUnknown ** ppRowset);
|
||
|
|
||
|
#endif // 0
|
||
|
|
||
|
//
|
||
|
// IChapteredRowset methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(AddRefChapter) (HCHAPTER hChapter,
|
||
|
ULONG * pcRefCount);
|
||
|
|
||
|
STDMETHOD(ReleaseChapter) (HCHAPTER hChapter,
|
||
|
ULONG * pcRefCount);
|
||
|
//
|
||
|
// IDBAsynchStatus methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(Abort) (HCHAPTER hChapter,
|
||
|
ULONG ulOpertation);
|
||
|
|
||
|
STDMETHOD(GetStatus) (HCHAPTER hChapter,
|
||
|
DBASYNCHOP ulOperation,
|
||
|
DBCOUNTITEM * pulProgress,
|
||
|
DBCOUNTITEM * pulProgressMax,
|
||
|
DBASYNCHPHASE * pulAsynchPhase,
|
||
|
LPOLESTR * ppwszStatusText) /*const*/;
|
||
|
|
||
|
//
|
||
|
// IRowsetAsynch methods
|
||
|
// deprecated
|
||
|
//
|
||
|
|
||
|
STDMETHOD(RatioFinished) (DBCOUNTITEM * pulDenominator,
|
||
|
DBCOUNTITEM * pulNumerator,
|
||
|
DBCOUNTITEM * pcRows,
|
||
|
BOOL * pfNewRows) /*const*/;
|
||
|
|
||
|
STDMETHOD(Stop) ( );
|
||
|
|
||
|
|
||
|
//
|
||
|
// IRowsetLocate methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(Compare) (HCHAPTER hChapter,
|
||
|
DBBKMARK cbBM1,
|
||
|
const BYTE * pBM1,
|
||
|
DBBKMARK cbBM2,
|
||
|
const BYTE * pBM2,
|
||
|
DBCOMPARE * pdwComparison) /*const*/;
|
||
|
|
||
|
STDMETHOD(GetRowsAt) (HWATCHREGION hRegion,
|
||
|
HCHAPTER hChapter,
|
||
|
DBBKMARK cbBookmark,
|
||
|
const BYTE * pBookmark,
|
||
|
DBROWOFFSET lRowsOffset,
|
||
|
DBROWCOUNT cRows,
|
||
|
DBCOUNTITEM * pcRowsObtained,
|
||
|
HROW * * prghRows);
|
||
|
|
||
|
STDMETHOD(GetRowsByBookmark) (HCHAPTER hChapter,
|
||
|
DBCOUNTITEM cRows,
|
||
|
const DBBKMARK rgcbBookmarks[],
|
||
|
const BYTE * rgpBookmarks[],
|
||
|
HROW rghRows[],
|
||
|
DBROWSTATUS rgRowStatus[]);
|
||
|
|
||
|
STDMETHOD(Hash) (HCHAPTER hChapter,
|
||
|
DBBKMARK cBookmarks,
|
||
|
const DBBKMARK rgcbBookmarks[],
|
||
|
const BYTE * rgpBookmarks[],
|
||
|
DBHASHVALUE rgHashedValues[],
|
||
|
DBROWSTATUS rgRowStatus[]);
|
||
|
|
||
|
//
|
||
|
// IRowsetScroll methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(GetApproximatePosition) (HCHAPTER hChapter,
|
||
|
DBBKMARK cbBookmark,
|
||
|
const BYTE * pBookmark,
|
||
|
DBCOUNTITEM * pulPosition,
|
||
|
DBCOUNTITEM * pcRows) /*const*/;
|
||
|
|
||
|
STDMETHOD(GetRowsAtRatio) (HWATCHREGION hRegion,
|
||
|
HCHAPTER hChapter,
|
||
|
DBCOUNTITEM ulNumerator,
|
||
|
DBCOUNTITEM ulDenominator,
|
||
|
DBROWCOUNT cRows,
|
||
|
DBCOUNTITEM * pcRowsObtained,
|
||
|
HROW * * prghRows);
|
||
|
|
||
|
//
|
||
|
// IRowsetExactScroll methods
|
||
|
// deprecated
|
||
|
//
|
||
|
|
||
|
STDMETHOD(GetExactPosition) (HCHAPTER hChapter,
|
||
|
DBBKMARK cbBookmark,
|
||
|
const BYTE * pBookmark,
|
||
|
DBCOUNTITEM * pulPosition,
|
||
|
DBCOUNTITEM * pcRows) /*const*/;
|
||
|
|
||
|
//
|
||
|
// IRowsetIdentity methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(IsSameRow) (HROW hThisRow,
|
||
|
HROW hThatRow);
|
||
|
|
||
|
//
|
||
|
// IRowsetWatchAll methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(Acknowledge) ( );
|
||
|
|
||
|
STDMETHOD(Start) ( );
|
||
|
|
||
|
STDMETHOD(StopWatching) ( );
|
||
|
|
||
|
//
|
||
|
// IRowsetWatchRegion methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(CreateWatchRegion) (
|
||
|
DBWATCHMODE mode,
|
||
|
HWATCHREGION* phRegion);
|
||
|
|
||
|
STDMETHOD(ChangeWatchMode) (
|
||
|
HWATCHREGION hRegion,
|
||
|
DBWATCHMODE mode);
|
||
|
|
||
|
STDMETHOD(DeleteWatchRegion) (
|
||
|
HWATCHREGION hRegion);
|
||
|
|
||
|
STDMETHOD(GetWatchRegionInfo) (
|
||
|
HWATCHREGION hRegion,
|
||
|
DBWATCHMODE * pMode,
|
||
|
HCHAPTER * phChapter,
|
||
|
DBBKMARK * pcbBookmark,
|
||
|
BYTE * * ppBookmark,
|
||
|
DBROWCOUNT * pcRows);
|
||
|
|
||
|
STDMETHOD(Refresh) (
|
||
|
DBCOUNTITEM* pChangesObtained,
|
||
|
DBROWWATCHCHANGE** prgChanges );
|
||
|
|
||
|
STDMETHOD(ShrinkWatchRegion) (
|
||
|
HWATCHREGION hRegion,
|
||
|
HCHAPTER hChapter,
|
||
|
DBBKMARK cbBookmark,
|
||
|
BYTE* pBookmark,
|
||
|
DBROWCOUNT cRows );
|
||
|
|
||
|
//
|
||
|
// IConvertType methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(CanConvert) (DBTYPE wFromType,
|
||
|
DBTYPE wToType,
|
||
|
DBCONVERTFLAGS dwConvertFlags );
|
||
|
|
||
|
//
|
||
|
// IRowsetQueryStatus methods
|
||
|
//
|
||
|
|
||
|
STDMETHOD(GetStatus) (DWORD * pStatus);
|
||
|
|
||
|
STDMETHOD(GetStatusEx) (DWORD * pStatus,
|
||
|
DWORD * pcFilteredDocuments,
|
||
|
DWORD * pcDocumentsToFilter,
|
||
|
DBCOUNTITEM * pdwRatioFinishedDenominator,
|
||
|
DBCOUNTITEM * pdwRatioFinishedNumerator,
|
||
|
DBBKMARK cbBmk,
|
||
|
const BYTE * pBmk,
|
||
|
DBCOUNTITEM * piRowCurrent,
|
||
|
DBCOUNTITEM * pcRowsTotal );
|
||
|
|
||
|
//
|
||
|
// IServiceProperties methods
|
||
|
//
|
||
|
#if 0
|
||
|
STDMETHOD(GetProperties) (
|
||
|
/* [in] */ ULONG cPropertyIDSets,
|
||
|
/* [size_is][in] */ const DBPROPIDSET rgPropertyIDSets[ ],
|
||
|
/* [out][in] */ ULONG *pcPropertySets,
|
||
|
/* [size_is][size_is][out] */ DBPROPSET **prgPropertySets);
|
||
|
#endif // 0
|
||
|
|
||
|
STDMETHOD(GetPropertyInfo) (
|
||
|
/* [in] */ ULONG cPropertyIDSets,
|
||
|
/* [size_is][in] */ const DBPROPIDSET rgPropertyIDSets[ ],
|
||
|
/* [out][in] */ ULONG *pcPropertyInfoSets,
|
||
|
/* [size_is][size_is][out] */ DBPROPINFOSET **prgPropertyInfoSets,
|
||
|
/* [out] */ OLECHAR **ppDescBuffer);
|
||
|
|
||
|
STDMETHOD(SetRequestedProperties) (
|
||
|
/* [in] */ ULONG cPropertySets,
|
||
|
/* [size_is][out][in] */ DBPROPSET rgPropertySets[ ]);
|
||
|
|
||
|
STDMETHOD(SetSuppliedProperties) (
|
||
|
/* [in] */ ULONG cPropertySets,
|
||
|
/* [size_is][out][in] */ DBPROPSET rgPropertySets[ ]);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Local methods.
|
||
|
//
|
||
|
|
||
|
CRowset( IUnknown * pUnkOuter,
|
||
|
IUnknown ** ppMyUnk,
|
||
|
CColumnSet const & cols,
|
||
|
CPidMapperWithNames const & pidmap,
|
||
|
PQuery & rQuery,
|
||
|
IUnknown & rControllingQuery,
|
||
|
BOOL fIsCategorized,
|
||
|
XPtr<CMRowsetProps> & xProps,
|
||
|
ULONG hCursor,
|
||
|
CAccessorBag & aAccessors,
|
||
|
IUnknown * pUnkCreator );
|
||
|
|
||
|
virtual ~CRowset();
|
||
|
|
||
|
|
||
|
void SetRelatedRowset( CRowset * pRowset ) {
|
||
|
_pRelatedRowset = pRowset;
|
||
|
pRowset->SetChapterRowbufs( _pRowBufs );
|
||
|
}
|
||
|
|
||
|
#ifdef CIEXTMODE
|
||
|
void CiExtDump(void *ciExtSelf);
|
||
|
#endif
|
||
|
|
||
|
private:
|
||
|
|
||
|
void SetChapterRowbufs( CRowBufferSet * pChapHelper ) {
|
||
|
Win4Assert( 0 == _pChapterRowbufs );
|
||
|
_pChapterRowbufs = pChapHelper;
|
||
|
}
|
||
|
|
||
|
// could use CImpIUnknown from impiunk.hxx except _rControllingQuery isn't
|
||
|
// used in general case.
|
||
|
|
||
|
class CImpIUnknown:public IUnknown
|
||
|
{
|
||
|
friend class CRowset;
|
||
|
public:
|
||
|
CImpIUnknown( IUnknown & rControllingQuery, CRowset * pRowset):
|
||
|
_ref(0), _rControllingQuery(rControllingQuery), _pRowset(pRowset)
|
||
|
{}
|
||
|
~CImpIUnknown() {};
|
||
|
|
||
|
//
|
||
|
// IUnknown methods.
|
||
|
//
|
||
|
|
||
|
STDMETHOD(QueryInterface) ( THIS_ REFIID riid,
|
||
|
LPVOID *ppiuk )
|
||
|
{ SCODE sc= S_OK;
|
||
|
if (IID_IUnknown == riid)
|
||
|
*ppiuk = this;
|
||
|
else
|
||
|
sc = _pRowset->RealQueryInterface(riid, ppiuk);
|
||
|
if ( SUCCEEDED( sc) )
|
||
|
((IUnknown *) *ppiuk)->AddRef();
|
||
|
return sc;
|
||
|
}
|
||
|
|
||
|
STDMETHOD_(ULONG, AddRef) (THIS);
|
||
|
|
||
|
STDMETHOD_(ULONG, Release) (THIS);
|
||
|
|
||
|
private:
|
||
|
long _ref; // OLE reference count
|
||
|
IUnknown & _rControllingQuery; // likely IQuery
|
||
|
CRowset * _pRowset;
|
||
|
};
|
||
|
|
||
|
void _ValidateColumnMappings();
|
||
|
|
||
|
#ifdef _WIN64
|
||
|
void _ConvertOffsetsToPointers( BYTE * pbRows,
|
||
|
BYTE * pbBias,
|
||
|
unsigned cRows,
|
||
|
CFixedVarAllocator *pArrayAlloc );
|
||
|
#endif
|
||
|
|
||
|
SCODE _FetchRows( CRowSeekDescription & rSeekDesc,
|
||
|
DBROWCOUNT cRows,
|
||
|
DBCOUNTITEM * pcRowsReturned,
|
||
|
HROW * * prghRows
|
||
|
);
|
||
|
|
||
|
DBROWSTATUS _MapBookmarkNoThrow( DBBKMARK cbBookmark,
|
||
|
const BYTE * pBookmark,
|
||
|
CI_TBL_BMK & rBmk) const;
|
||
|
|
||
|
CI_TBL_BMK _MapBookmark( DBBKMARK cbBmk,
|
||
|
const BYTE * pBmk ) const;
|
||
|
|
||
|
CI_TBL_CHAPT _MapChapter( HCHAPTER hChapter ) const;
|
||
|
|
||
|
PQuery & _rQuery; // The cached table/query (or proxy)
|
||
|
|
||
|
CMutexSem _mutex; // synchronizes access
|
||
|
|
||
|
XPtr<CMRowsetProps> _xProperties; // Rowset properties
|
||
|
|
||
|
ULONG _hCursor; // A handle to the table cursor
|
||
|
|
||
|
BOOL _fForwardOnly; // If TRUE, a forward-only Rowset
|
||
|
|
||
|
BOOL _fHoldRows; // if TRUE, forward-only Rowset can
|
||
|
// hold onto HROWs on GetNextRows
|
||
|
|
||
|
BOOL _fIsCategorized; // i.e. not a highest-level rowset,
|
||
|
// so chapter args must be non-zero
|
||
|
|
||
|
BOOL _fExtendedTypes; // if TRUE, okay to use PROPVARIANT
|
||
|
// instead of VARIANT
|
||
|
|
||
|
BOOL _fAsynchronous; // if TRUE, rowset is populated
|
||
|
// asynchronously
|
||
|
|
||
|
CRowBufferSet * _pRowBufs; // Buffered rows
|
||
|
|
||
|
BOOL _fPossibleOffsetConversions; // if TRUE, there could be offset
|
||
|
// conversion needed
|
||
|
|
||
|
//
|
||
|
// IConnectionPointContainer and notification support
|
||
|
//
|
||
|
CConnectionPointContainer * _pConnectionPointContainer;
|
||
|
XInterface<CRowsetNotification> _pRowsetNotification;
|
||
|
|
||
|
// Note: _pAsynchNotification is not owned by the recordset, it's an
|
||
|
// alias to _pRowsetNotification.
|
||
|
CRowsetAsynchNotification * _pAsynchNotification;
|
||
|
|
||
|
CColumnsInfo _ColumnsInfo; // Column information
|
||
|
CAccessorBag _aAccessors;
|
||
|
|
||
|
CMDSPropInfo _PropInfo; // IServiceProperties::GetPropertyInfo
|
||
|
|
||
|
IUnknown * _pControllingUnknown; // outer unknown
|
||
|
IRowset * _pRelatedRowset; // for GetRelatedRowset
|
||
|
CRowBufferSet * _pChapterRowbufs; // for IChapteredRowset
|
||
|
|
||
|
CImpIUnknown _impIUnknown;
|
||
|
|
||
|
//
|
||
|
// Support Ole DB error handling
|
||
|
//
|
||
|
|
||
|
CCIOleDBError _DBErrorObj;
|
||
|
|
||
|
// OLE DB Data Conversion Library Interface
|
||
|
// One IDataConvert interface is kept in each rowset object and is passed
|
||
|
// down in GetData function of the accessor. The IDataConvert interface is
|
||
|
// instantiated(by the lower lever conversion routine) only when needed for
|
||
|
// data conversion and then is kept in this smart interface pointer for
|
||
|
// the life of the rowset object.
|
||
|
XInterface<IDataConvert> _xDataConvert;
|
||
|
|
||
|
//
|
||
|
// Pointer to the command or session object which created this rowset.
|
||
|
// Used to implement IRowsetInfo::GetSpecification()
|
||
|
//
|
||
|
XInterface<IUnknown> _xUnkCreator;
|
||
|
};
|
||
|
|