Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

779 lines
22 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 2000.
  5. //
  6. // File: tblwindo.hxx
  7. //
  8. // Contents: Declaration of the CTableWindow class, a component of
  9. // a large table.
  10. //
  11. // Classes: CTableWindow
  12. //
  13. // History: 14 Jun 1994 Alanw Created
  14. // 20 Jun 1995 BartoszM Added watch regions
  15. //
  16. //--------------------------------------------------------------------------
  17. #pragma once
  18. #include <tableseg.hxx>
  19. #include <shardbuf.hxx> // Shared buffer
  20. #include "tblvarnt.hxx" // for CTableVariant
  21. #include "rowcomp.hxx" // for CRowCompareXX
  22. #include "rowindex.hxx" // for CRowIndex
  23. #include "bmkmap.hxx" // for Book Mark Mapping
  24. #include "wnotifmg.hxx" // Watch region notifications manager
  25. class CTableWindowSplit;
  26. class CTableRowKey;
  27. class CPathStore;
  28. class CSingletonCursor;
  29. class CWindowWatch
  30. {
  31. public:
  32. HWATCHREGION _hRegion;
  33. long _iRowStart;
  34. long _cRowsHere; // rows watched in this window
  35. long _cRowsLeft; // rows watched here and in following segments
  36. };
  37. class CChangeScript; // NEWFEATURE - until we give change scripts.
  38. //+-------------------------------------------------------------------------
  39. //
  40. // Class: CTableWindow
  41. //
  42. // Purpose: A segment of a large table which is fully buffered in
  43. // memory.
  44. // It can be directly transferred to the user from the
  45. // cached rowdata.
  46. //
  47. // Interface:
  48. //
  49. //--------------------------------------------------------------------------
  50. class CTableWindow : public CTableSegment
  51. {
  52. INLINE_UNWIND( CTableWindow )
  53. friend CRowCompareVariant;
  54. friend class CTableWindowSplit;
  55. friend class CLargeTable;
  56. friend class CWindowRowIter;
  57. friend class CTableRowLocator;
  58. friend class CBucketizeWindows;
  59. public:
  60. //
  61. // Indicator values for data values.
  62. //
  63. // NOTE: These values need to be translated between these values
  64. // and the standard defines used by OLE DB. We define our
  65. // own values so we can store them in a byte (or smaller)
  66. // field in the row data.
  67. //
  68. enum TableIndicator
  69. {
  70. TBL_DATA_OKAY = 0, // data stored okay
  71. TBL_DATA_OUTOFRANGE, // range error, e.g., long into short
  72. TBL_DATA_CANTCOERCE, // type mismatch
  73. TBL_DATA_USEENTRYID, // entry too big, use entry ID
  74. TBL_DATA_OVERRUN, // value too big for data area
  75. TBL_DATA_EMPTY, // no value for this data point
  76. TBL_DATA_ROWADDED, // row status: added after cursor created
  77. TBL_DATA_BADBOOKMARK, // row status: bookmark for row was invalid
  78. TBL_DATA_PENDING_DELETE, // row status: pending delete
  79. TBL_DATA_HARD_DELETE // row status: hard deleted; not visible
  80. };
  81. CTableWindow(
  82. CSortSet const * pSortSet,
  83. CTableKeyCompare & comparator,
  84. CColumnMasterSet * pMasterColumns,
  85. ULONG segId,
  86. CCategorize *pCategorizer,
  87. CSharedBuffer & sharedBuf,
  88. CQAsyncExecute & QExecute
  89. );
  90. CTableWindow( CTableWindow & src,
  91. ULONG segId
  92. );
  93. ~CTableWindow();
  94. // Virtual methods inherited from CTableSink
  95. WORKID PathToWorkID( CRetriever& obj,
  96. CTableSink::ERowType eRowType );
  97. BOOL PutRow( CRetriever & obj, CTableSink::ERowType eRowType )
  98. {
  99. Win4Assert( !"Must not be called" );
  100. return FALSE;
  101. }
  102. BOOL RemoveRow( PROPVARIANT const & varUnique,
  103. WORKID & widNext,
  104. CI_TBL_CHAPT & chapt );
  105. CSortSet const & SortOrder();
  106. // Virtual methods inherited from CTableSegment
  107. BOOL PutRow( CRetriever & obj, CTableRowKey & currKey );
  108. DBCOUNTITEM RowCount()
  109. {
  110. return _visibleRowIndex.RowCount();
  111. }
  112. SCODE GetRows( HWATCHREGION hRegion,
  113. WORKID widStart,
  114. CI_TBL_CHAPT chapt,
  115. ULONG & cRowsToGet,
  116. CTableColumnSet const & rOutColumns,
  117. CGetRowsParams& rGetParams,
  118. WORKID& rwidNextRowToTransfer );
  119. void LokGetOneColumn( WORKID wid,
  120. CTableColumn const & rOutColumn,
  121. BYTE * pbOut,
  122. PVarAllocator & rVarAllocator );
  123. BOOL IsRowInSegment( WORKID wid );
  124. BOOL IsPendingDelete( WORKID wid );
  125. void CompareRange( CRetriever &obj, CCompareResult & rslt );
  126. SCODE GetNotifications( CNotificationParams &rParams );
  127. // Other public methods
  128. BOOL RowOffset(WORKID wid, ULONG & iRow)
  129. {
  130. if ( widInvalid == wid )
  131. return FALSE;
  132. TBL_OFF obRowOffset = 0;
  133. if ( FindBookMark( wid, obRowOffset, iRow ) )
  134. return TRUE;
  135. else return _FindWorkId(wid, obRowOffset, iRow);
  136. }
  137. BOOL FindBookMark( WORKID wid, TBL_OFF &obRow, ULONG & iRow );
  138. WORKID GetBookMarkAt( ULONG iRow );
  139. WORKID GetFirstBookMark();
  140. int CompressData(); // attempt to reduce data storage needs
  141. inline ULONG MemUsed( void ) {
  142. // PERFFIX - also need so sum all non-global, non-shared compressions
  143. return _cbHeapUsed + _DataAllocator.MemUsed();
  144. }
  145. BOOL IsSortedSplit( ULONG & riSplit )
  146. {
  147. return _GetInvisibleRowIndex().FindMidSplitPoint( riSplit );
  148. }
  149. BOOL IsEmptyForQuery();
  150. BOOL IsGettingFull();
  151. unsigned PercentFull();
  152. // Watch region manipulations
  153. long AddWatch (HWATCHREGION hRegion,
  154. LONG iStart,
  155. LONG cRows,
  156. BOOL isLast);
  157. long ModifyWatch (HWATCHREGION hRegion,
  158. LONG iStart,
  159. LONG cRows,
  160. BOOL isLast);
  161. long DeleteWatch (HWATCHREGION hRegion);
  162. long ShrinkWatch (HWATCHREGION hRegion,
  163. CI_TBL_BMK bookmark,
  164. LONG cRows);
  165. long ShrinkWatch (HWATCHREGION hRegion, LONG cRows);
  166. BOOL HasWatch (HWATCHREGION hRegion);
  167. BOOL IsWatched (HWATCHREGION hRegion, CI_TBL_BMK bookmark);
  168. BOOL IsWatched()
  169. {
  170. if ( _aWindowWatch.Count() > 0 )
  171. {
  172. if ( _xDeltaBookMarkMap.IsNull() )
  173. _xDeltaBookMarkMap.Set( new CBookMarkMap( _dynRowIndex ) );
  174. return TRUE;
  175. }
  176. return FALSE;
  177. }
  178. long RowsWatched (HWATCHREGION hRegion);
  179. WORKID RowWorkid(BYTE *pRow)
  180. { return *(WORKID *) (pRow + _iOffsetWid); }
  181. LONG RowRank(BYTE *pRow)
  182. {
  183. return ( ULONG_MAX == _iOffsetRank ) ?
  184. MAX_QUERY_RANK :
  185. *(LONG *) (pRow + _iOffsetRank);
  186. }
  187. LONG RowHitCount(BYTE *pRow)
  188. {
  189. return ( ULONG_MAX == _iOffsetHitCount ) ?
  190. 0 :
  191. *(LONG *) (pRow + _iOffsetHitCount);
  192. }
  193. long GetWatchStart( HWATCHREGION hRegion) const
  194. {
  195. unsigned i = FindRegion(hRegion);
  196. Win4Assert (i < _aWindowWatch.Count());
  197. return _aWindowWatch.Get(i)._iRowStart;
  198. }
  199. BOOL FindNearestDynamicBmk( CI_TBL_CHAPT chapter,
  200. CI_TBL_BMK & bookmark );
  201. BOOL FindFirstNonDeleteDynamicBmk( CI_TBL_BMK & bookmark );
  202. BOOL FindLastNonDeleteDynamicBmk( CI_TBL_BMK & bookmark );
  203. BOOL IsFirstRowFirstOfCategory();
  204. #ifdef CIEXTMODE
  205. void CiExtDump(void *ciExtSelf);
  206. #endif
  207. private:
  208. //
  209. // No Copy consructor allowed for this.
  210. //
  211. CTableWindow( CTableWindow & src );
  212. void _FinishInit( CTableRowAlloc & rowMap, unsigned &maxAlignment );
  213. CSharedBuffer & _GetSharedBuf() const { return _sharedBuf; }
  214. void _InitSortComparators();
  215. void _PopulateRow( CRetriever &obj, BYTE *pThisRow, WORKID wid );
  216. BOOL _FindWorkId( WORKID wid, TBL_OFF & obRow, ULONG & iRow );
  217. WORKID _GetWorkIdAt( ULONG iRow );
  218. WORKID _GetFirstWorkId();
  219. WORKID _GetLastWorkId();
  220. void _AddColumnDesc( CColumnMasterDesc& MasterCol,
  221. CTableRowAlloc& RowMap,
  222. unsigned& maxAlignment);
  223. void _AddColumnDesc( CTableColumn & src,
  224. CTableRowAlloc& RowMap,
  225. unsigned& maxAlignment);
  226. void _AddWatchItem (CWindowWatch& watch);
  227. void _RemoveWatchItem (unsigned i);
  228. CRowIndex & _GetInvisibleRowIndex()
  229. {
  230. return IsWatched() ? _dynRowIndex : _visibleRowIndex;
  231. }
  232. //
  233. // Methods used for window->bucket conversion
  234. //
  235. void GetSortKey( ULONG iRow, CTableRowKey & bktRow );
  236. unsigned FindRegion (HWATCHREGION hRegion) const;
  237. void _StartStaticDynamicSplit();
  238. void _EndStaticDynamicSplit();
  239. void _ReconcileRowIndexes( CRowIndex & dst , CRowIndex & src );
  240. void _CleanupAndReconcileRowIndexes( BOOL fCreatingWatch );
  241. void _Refresh();
  242. //
  243. // Storage for fixed length row data
  244. //
  245. unsigned _cbRowSize; // size in bytes of data for each row
  246. unsigned _iOffsetWid; // offset of WorkID in row data
  247. unsigned _iOffsetRank; // offset of rank in row data
  248. unsigned _iOffsetHitCount; // offset of hitcount in row data
  249. unsigned _iOffsetRowStatus; // offset of row status in row data
  250. unsigned _iOffsetChapter; // offset of chapter number (optional)
  251. CTableColumnSet _Columns; // column descriptions for this window
  252. //
  253. // Shared buffer for the whole table used as temporary memory.
  254. //
  255. CSharedBuffer & _sharedBuf;
  256. XPtr<CSingletonCursor> _xCursor; // singleton cursor used in GetRows
  257. //
  258. // Memory management related methods and variables.
  259. //
  260. BYTE * _RowAlloc( void )
  261. {
  262. _cRowsAllocated++;
  263. // Just get a new row from the allocator
  264. BYTE *pbRetBuf = (BYTE *) _DataAllocator.AllocFixed();
  265. Win4Assert(0 != pbRetBuf);
  266. return pbRetBuf;
  267. }
  268. //
  269. // Additional storage for variable length data which is not
  270. // stored as a compressed column. When first needed after a
  271. // window is created, this will begin at the end of the block of
  272. // data for row data, and grow downward toward it. When these
  273. // grow enough to meet, the row data will be moved out into
  274. // a separate block, allowing the variable data to expand into the
  275. // newly freed area.
  276. //
  277. // At the time this data is moved or grown, it may be a good time to
  278. // convert columns for compressions. All extra data for
  279. // compressed columns will be stored with the column descriptor.
  280. //
  281. CFixedVarTableWindowAllocator _DataAllocator; // Variable data allocator
  282. ULONG _cbHeapUsed; // total heap memory used by structure
  283. CPathStore * _pPathStore; // Store for paths.
  284. //
  285. // Row indirection object. This holds offsets in the heap where each
  286. // row resides. The row index is sorted by the current sort order.
  287. //
  288. CRowIndex _dynRowIndex;
  289. //
  290. // The "static" row index that will be used for giving rows to the
  291. // client (user).
  292. //
  293. CRowIndex _visibleRowIndex;
  294. //
  295. // BookMark mapping object. If there are no notifications, it is
  296. // associated with the _dynRowIndex; o/w it is associated with the
  297. // _visibleRowIndex.
  298. //
  299. CBookMarkMap _BookMarkMap;
  300. //
  301. // BookMark mapping object for the "deltas" or changes pending
  302. // notification to the user. It is always associated with the _dynRowIndex
  303. //
  304. XPtr<CBookMarkMap> _xDeltaBookMarkMap;
  305. //
  306. // Notification processing object
  307. //
  308. CDynArrayInPlace<CWindowWatch> _aWindowWatch;
  309. //
  310. // Row sorting objects.
  311. //
  312. XPtr<CRowCompareVariant> _RowCompare;
  313. XPtr<CRowCompare> _QuickRowCompare;
  314. CSortSet const * _pSortSet;
  315. ULONG _cPendingDeletes; // # of rows with pending deletes. These are
  316. // visible to retrievals.
  317. ULONG _cRowsHardDeleted; // # of rows "hard" deleted - not visible to
  318. // retrievals.
  319. ULONG _cRowsAllocated; // # of rows allocated in the table
  320. BOOL _fSplitInProgress; // Flag set to TRUE when a window split is
  321. // in progress.
  322. CQAsyncExecute & _QueryExecute; // The query object that will be used
  323. // when retrieving the partial deferred cols.
  324. BOOL _IsTableWatched() const;
  325. ULONG _AllocatedRowCount()
  326. {
  327. return _cRowsAllocated;
  328. }
  329. BOOL _fCanPartialDefer ; // Is set in constructor by taking value from the query session
  330. //
  331. // Functions to get at row metadata that always exists
  332. //
  333. void _SetRowWorkid(BYTE *pRow,WORKID wid)
  334. { *(WORKID *) (pRow + _iOffsetWid) = wid; }
  335. ULONG _RowStatus(BYTE *pRow)
  336. { return *(BYTE *) (pRow + _iOffsetRowStatus); }
  337. void _SetRowStatus(BYTE *pRow,BYTE status)
  338. { *(BYTE *) (pRow + _iOffsetRowStatus) = status; }
  339. ULONG _RowChapter(BYTE *pRow)
  340. { return *(unsigned *) (pRow + _iOffsetChapter); }
  341. void _SetChapter(BYTE *pRow,unsigned Chapter)
  342. { *(unsigned *) (pRow + _iOffsetChapter) = Chapter; }
  343. //
  344. // Methods to support window splitting. These will be used by the
  345. // CTableWindowSplit class.
  346. //
  347. CRowIndex & _GetVisibleRowIndex()
  348. {
  349. return _visibleRowIndex;
  350. }
  351. CRowIndex & _GetDynamicRowIndex()
  352. {
  353. return _dynRowIndex;
  354. }
  355. BYTE * _GetRow( TBL_OFF oTableRow )
  356. {
  357. return (BYTE *) _DataAllocator.FixedPointer( oTableRow );
  358. }
  359. void _PutRowToVisibleRowIndex( CTableWindow & srcWindow, TBL_OFF oSrcRow );
  360. void _PutRowToDynRowIndex( CTableWindow & srcWindow, TBL_OFF oSrcRow );
  361. TBL_OFF _CopyRow( CTableWindow & srcWindow, TBL_OFF oSrcRow );
  362. WORKID _GetWorkId( TBL_OFF oTableRow )
  363. {
  364. BYTE * pbRow = _GetRow( oTableRow );
  365. return RowWorkid( pbRow );
  366. }
  367. LONG _GetRank( TBL_OFF oTableRow )
  368. {
  369. BYTE * pbRow = _GetRow( oTableRow );
  370. return RowRank( pbRow );
  371. }
  372. LONG _GetHitCount( TBL_OFF oTableRow )
  373. {
  374. BYTE * pbRow = _GetRow( oTableRow );
  375. return RowHitCount( pbRow );
  376. }
  377. BOOL _IsRowDeleted( TBL_OFF oTableRow )
  378. {
  379. BYTE * pbRow = _GetRow( oTableRow );
  380. const ULONG rowStatus = _RowStatus( pbRow );
  381. return TBL_DATA_PENDING_DELETE == rowStatus ||
  382. TBL_DATA_HARD_DELETE == rowStatus ;
  383. }
  384. BOOL _IsWorkIdInVisRowIndex( WORKID wid )
  385. {
  386. return _BookMarkMap.IsBookMarkPresent(wid);
  387. }
  388. BOOL _IsRowInVisRowIndex( TBL_OFF oTableRow )
  389. {
  390. BYTE * pbRow = _GetRow(oTableRow);
  391. Win4Assert( pbRow );
  392. WORKID wid = RowWorkid(pbRow);
  393. TBL_OFF oRowFound;
  394. BOOL fFound = _BookMarkMap.FindBookMark( wid, oRowFound );
  395. return fFound && oRowFound == oTableRow;
  396. }
  397. int _CompareRows( TBL_OFF obRow1, TBL_OFF obRow2 )
  398. {
  399. if ( 0 != _QuickRowCompare.GetPointer() )
  400. return _QuickRowCompare->Compare( obRow1, obRow2 );
  401. else
  402. return _RowCompare->Compare( obRow1, obRow2 );
  403. }
  404. BYTE * _GetRowFromIndex( ULONG iRow, CRowIndex & rowIndex )
  405. {
  406. return _GetRow( rowIndex.GetRow( iRow ) );
  407. }
  408. void _SetSplitInProgress() { _fSplitInProgress = TRUE; }
  409. void _SetSplitDone() { _fSplitInProgress = FALSE; }
  410. void _CopyColumnData( BYTE* pbSrcRow, BYTE* pbOutRow,
  411. CTableColumn **pTableCols, CTableColumnSet const& rOutColumns,
  412. PVarAllocator& rDstPool, CRetriever* obj = NULL );
  413. inline BOOL _CanPartialDeferCol( XPtr<CTableColumn>& xTableCol ) const
  414. {
  415. Win4Assert( xTableCol.GetPointer() );
  416. Win4Assert( _pSortSet );
  417. return ( xTableCol->PropId != pidWorkId &&
  418. xTableCol->PropId != pidRank &&
  419. xTableCol->PropId != pidRankVector &&
  420. xTableCol->PropId != pidHitCount &&
  421. xTableCol->PropId != pidRowStatus &&
  422. xTableCol->PropId != pidChapter &&
  423. xTableCol->PropId != pidSelf &&
  424. !_pSortSet->Exists( xTableCol->PropId ) );
  425. }
  426. };
  427. //+-------------------------------------------------------------------------
  428. //
  429. // Member: CTableWindow::PathToWorkID, inline
  430. //
  431. // Synopsis: Path to WorkID conversion
  432. //
  433. // Arguments: [obj] -- positioned cursor to row
  434. //
  435. // Returns: WORKID - the WorkID assigned
  436. //
  437. // Notes: This method should be called only on CLargeTable.
  438. // CLEANCODE: for now it's convenient to have this as a
  439. // virtual method on CTableSink. It should become
  440. // an ordinary method on CLargeTable once the
  441. // ITable code is removed.
  442. //
  443. //--------------------------------------------------------------------------
  444. inline WORKID CTableWindow::PathToWorkID(
  445. CRetriever& obj,
  446. CTableSink::ERowType eRowType )
  447. {
  448. return 0;
  449. }
  450. //+---------------------------------------------------------------------------
  451. //
  452. // Member: CTableWindow::GetBookMarkAt
  453. //
  454. // Synopsis: Returns a bookmark at the specified offset.
  455. //
  456. // Arguments: [iRow] -
  457. //
  458. // History: 8-04-95 srikants Created
  459. //
  460. // Notes:
  461. //
  462. //----------------------------------------------------------------------------
  463. inline
  464. WORKID CTableWindow::GetBookMarkAt( ULONG iRow )
  465. {
  466. Win4Assert( iRow < _GetVisibleRowIndex().RowCount() );
  467. return RowWorkid( _GetRowFromIndex( iRow, _GetVisibleRowIndex() ) );
  468. }
  469. //+---------------------------------------------------------------------------
  470. //
  471. // Member: CTableWindow::GetFirstBookMark
  472. //
  473. // Synopsis: Returns the first BOOKMARK in the window. A BOOKMARK is one
  474. // which is visible to a client.
  475. //
  476. // History: 8-04-95 srikants Created
  477. //
  478. // Notes:
  479. //
  480. //----------------------------------------------------------------------------
  481. inline
  482. WORKID CTableWindow::GetFirstBookMark()
  483. {
  484. if ( 0 == RowCount() )
  485. return widInvalid;
  486. else
  487. return GetBookMarkAt(0);
  488. }
  489. //+---------------------------------------------------------------------------
  490. //
  491. // Member: CTableWindow::_GetWorkIdAt
  492. //
  493. // Synopsis: Returns the workid at the specified offset in the
  494. // "invisible" row index , ie, query row index.
  495. //
  496. // Arguments: [iRow] -
  497. //
  498. // History: 8-02-95 srikants Created
  499. //
  500. // Notes:
  501. //
  502. //----------------------------------------------------------------------------
  503. inline
  504. WORKID CTableWindow::_GetWorkIdAt( ULONG iRow )
  505. {
  506. Win4Assert( iRow < _GetInvisibleRowIndex().RowCount() );
  507. return RowWorkid( _GetRowFromIndex(iRow , _GetInvisibleRowIndex()) );
  508. }
  509. //+---------------------------------------------------------------------------
  510. //
  511. // Function: _GetFirstWorkId
  512. //
  513. // Synopsis: Returns the first WORKID visible to the QUERY only. Note that
  514. // this can be different from the first bookmark.
  515. //
  516. // History: 8-04-95 srikants Created
  517. //
  518. // Notes:
  519. //
  520. //----------------------------------------------------------------------------
  521. inline
  522. WORKID CTableWindow::_GetFirstWorkId()
  523. {
  524. if ( 0 == RowCount() )
  525. return widInvalid;
  526. else
  527. return _GetWorkIdAt(0);
  528. }
  529. //+---------------------------------------------------------------------------
  530. //
  531. // Function: _GetLastWorkId
  532. //
  533. // Synopsis: Returns the last WORKID visible to the QUERY only. Note that
  534. // this can be different from the first bookmark.
  535. //
  536. // History: 03-12-98 vikasman Created
  537. //
  538. // Notes:
  539. //
  540. //----------------------------------------------------------------------------
  541. inline
  542. WORKID CTableWindow::_GetLastWorkId()
  543. {
  544. if ( 0 == RowCount() )
  545. return widInvalid;
  546. else
  547. return _GetWorkIdAt( (ULONG) RowCount() - 1);
  548. }
  549. //+---------------------------------------------------------------------------
  550. //
  551. // Class: CWindowRowIter ()
  552. //
  553. // Purpose: An iterator to retrieve WORKIDs from the a window.
  554. //
  555. // History: 2-16-95 srikants Created
  556. //
  557. // Notes:
  558. //
  559. //----------------------------------------------------------------------------
  560. class CWindowRowIter
  561. {
  562. public:
  563. CWindowRowIter( CTableWindow & window )
  564. : _window(window), _rowIndex( window._GetInvisibleRowIndex() ),
  565. _curr(0),
  566. _cTotal( _rowIndex.RowCount() )
  567. {
  568. }
  569. BOOL AtEnd() const
  570. {
  571. Win4Assert( _curr <= _cTotal );
  572. return _curr == _cTotal;
  573. }
  574. BOOL AtEnd( ULONG iEnd ) const
  575. {
  576. Win4Assert( _curr <= _cTotal && iEnd <= _cTotal );
  577. return _curr == iEnd;
  578. }
  579. WORKID Get() const
  580. {
  581. Win4Assert( !AtEnd() );
  582. TBL_OFF oTableRow = _rowIndex.GetRow(_curr);
  583. return _window._GetWorkId( oTableRow );
  584. }
  585. LONG Rank() const
  586. {
  587. Win4Assert( !AtEnd() );
  588. TBL_OFF oTableRow = _rowIndex.GetRow(_curr);
  589. return _window._GetRank( oTableRow );
  590. }
  591. LONG HitCount() const
  592. {
  593. Win4Assert( !AtEnd() );
  594. TBL_OFF oTableRow = _rowIndex.GetRow(_curr);
  595. return _window._GetHitCount( oTableRow );
  596. }
  597. BOOL IsDeletedRow() const
  598. {
  599. Win4Assert( !AtEnd() );
  600. TBL_OFF oTableRow = _rowIndex.GetRow(_curr);
  601. return _window._IsRowDeleted( oTableRow );
  602. }
  603. ULONG GetCurrPos() const
  604. {
  605. return _curr;
  606. }
  607. void Next()
  608. {
  609. Win4Assert( !AtEnd() );
  610. _curr++;
  611. }
  612. ULONG TotalRows() const { return _cTotal; }
  613. private:
  614. CTableWindow & _window;
  615. CRowIndex & _rowIndex;
  616. ULONG _curr;
  617. const ULONG _cTotal;
  618. };