546 lines
16 KiB
C++
546 lines
16 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1995 - 2000
|
|
//
|
|
// File: PosCache.cxx
|
|
//
|
|
// Contents: Positionable cache
|
|
//
|
|
// Classes: CMiniPositionableCache
|
|
//
|
|
// History: 05-Jun-95 KyleP Created
|
|
// 14-JAN-97 KrishnaN Undefined CI_INETSRV and related changes
|
|
// 29-Mar-2000 KLam Fixed Bookmarks
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include "poscache.hxx"
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMiniPositionableCache::CMiniPositionableCache, public
|
|
//
|
|
// Synopsis: Builds bindings to fetch bookmark.
|
|
//
|
|
// Arguments: [Index] -- Identifier. Not used internally.
|
|
// [pRowsetScroll] -- Rowset used to fill cache.
|
|
// [cBindings] -- Size of [pBindings].
|
|
// [pBindings] -- Default binding.
|
|
// [cbMaxLen] -- Max length of data fetched via [pBindings]
|
|
// [iColumnBookmark] -- Ordinal of column containing bookmark.
|
|
// [cbBookmark] -- Size of bookmark
|
|
//
|
|
// History: 05-Jun-95 KyleP Created.
|
|
// 06-Jan-2000 KLam Fixed bindings
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CMiniPositionableCache::CMiniPositionableCache( int Index,
|
|
IRowsetScroll * pRowsetScroll,
|
|
unsigned cBindings,
|
|
DBBINDING * pBindings,
|
|
unsigned cbMaxLen,
|
|
DBORDINAL iColumnBookmark,
|
|
DBBKMARK cbBookmark )
|
|
: PMiniRowCache( Index,
|
|
pRowsetScroll,
|
|
cBindings,
|
|
pBindings,
|
|
cbMaxLen ),
|
|
_pRowsetScroll( pRowsetScroll ),
|
|
_fUsingBookmark( FALSE ),
|
|
_haccBookmark( (HACCESSOR)0xFFFFFFFF ),
|
|
_pbBookmark( (unsigned) ( sizeof(DBBKMARK) + cbBookmark + 1 )),
|
|
_pbBookmarkSeek( (unsigned) (sizeof(DBBKMARK) + cbBookmark + 1 )),
|
|
_hrowPrev( DB_NULL_HROW )
|
|
{
|
|
if ( iColumnBookmark != -1 )
|
|
{
|
|
_fUsingBookmark = TRUE;
|
|
|
|
//
|
|
// Setup accessor for bookmark.
|
|
//
|
|
|
|
DBBINDING bindBmk;
|
|
RtlZeroMemory(&bindBmk, sizeof bindBmk);
|
|
|
|
bindBmk.iOrdinal = iColumnBookmark;
|
|
bindBmk.obValue = sizeof(DBLENGTH);
|
|
bindBmk.obLength = 0;
|
|
bindBmk.dwPart = DBPART_VALUE | DBPART_LENGTH;
|
|
bindBmk.cbMaxLen = _pbBookmark.Count() - sizeof(DBLENGTH);
|
|
bindBmk.wType = DBTYPE_BYTES;
|
|
|
|
IAccessor * pia = 0;
|
|
SCODE sc = _pRowsetScroll->QueryInterface( IID_IAccessor, (void **)&pia );
|
|
if (SUCCEEDED( sc ))
|
|
{
|
|
sc = pia->CreateAccessor( DBACCESSOR_ROWDATA,
|
|
1,
|
|
&bindBmk,
|
|
0,
|
|
&_haccBookmark,
|
|
0);
|
|
pia->Release();
|
|
}
|
|
|
|
if ( FAILED(sc) )
|
|
{
|
|
vqDebugOut(( DEB_ERROR,
|
|
"CMiniPositionableCache: CreateAccessor returned 0x%x\n",
|
|
sc ));
|
|
THROW( CException( sc ) );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Start with bookmark positioned at beginning of rowset (DBBMK_FIRST)
|
|
//
|
|
|
|
*(DBBKMARK *)_pbBookmark.GetPointer() = sizeof(BYTE);
|
|
_pbBookmark[sizeof(DBBKMARK)] = DBBMK_FIRST;
|
|
_oBookmark = 0;
|
|
|
|
*(DBBKMARK *)_pbBookmarkSeek.GetPointer() = sizeof(BYTE);
|
|
_pbBookmarkSeek[sizeof(DBBKMARK)] = DBBMK_FIRST;
|
|
|
|
_xpbPrevRow.Set( new BYTE [_cbRow] );
|
|
|
|
Next();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMiniPositionableCache::~CMiniPositionableCache, public
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
// History: 05-Jun-95 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CMiniPositionableCache::~CMiniPositionableCache()
|
|
{
|
|
if ( _haccBookmark != (HACCESSOR)0xFFFFFFFF )
|
|
{
|
|
IAccessor * pia = 0;
|
|
_pRowsetScroll->QueryInterface( IID_IAccessor, (void **)&pia );
|
|
Win4Assert(pia && "No Accessor!");
|
|
pia->ReleaseAccessor( _haccBookmark, 0 );
|
|
pia->Release();
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMiniPositionableCache::Next, public
|
|
//
|
|
// Synopsis: Moves to next row
|
|
//
|
|
// Returns: Move status
|
|
//
|
|
// History: 05-Jun-95 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
PMiniRowCache::ENext CMiniPositionableCache::Next( int iDir /* = 1 */ )
|
|
{
|
|
//
|
|
// If we had a row in cache, Just advance to it. Otherwise
|
|
// fetch more rows from table.
|
|
//
|
|
|
|
_ihrow++;
|
|
|
|
if ( _ihrow >= _chrow )
|
|
{
|
|
Win4Assert( iDir );
|
|
|
|
iDir = iDir > 0 ? 1 : -1 ;
|
|
|
|
//
|
|
// Fetch more rows from table.
|
|
//
|
|
|
|
HROW * phrow = _ahrow.GetPointer();
|
|
|
|
SCODE sc = _pRowsetScroll->GetRowsAt(
|
|
0, // Watch region handle
|
|
0, // Chapter
|
|
*(DBBKMARK *)_pbBookmark.GetPointer(), // cbBookmark
|
|
_pbBookmark.GetPointer() + sizeof(DBBKMARK), // pbBookmark
|
|
_oBookmark, // Offset from bookmark
|
|
_ahrow.Count() * iDir, // Rows requested
|
|
&_chrow, // Rows received
|
|
&phrow ); // HROWs stored here
|
|
|
|
Win4Assert( DB_E_BADSTARTPOSITION != sc );
|
|
|
|
vqDebugOut(( DEB_ITRACE, "Fetched %d from %d\n", _chrow, _Index ));
|
|
|
|
if ( FAILED(sc) )
|
|
{
|
|
vqDebugOut(( DEB_ERROR, "CMiniPositionableCache: Error 0x%x from GetRowsAt\n", sc ));
|
|
_chrow = 0;
|
|
|
|
THROW( CException( sc ) );
|
|
}
|
|
else if ( 0 == _chrow && sc != DB_S_ENDOFROWSET )
|
|
{
|
|
return( PMiniRowCache::NotNow );
|
|
}
|
|
|
|
if ( _fUsingBookmark && _chrow > 0 )
|
|
{
|
|
//
|
|
// Update current bookmark to last row fetched.
|
|
//
|
|
|
|
SCODE sc = _pRowsetScroll->GetData( _ahrow[(unsigned) (_chrow-1)],
|
|
_haccBookmark,
|
|
_pbBookmark.GetPointer() );
|
|
|
|
if ( FAILED(sc) )
|
|
{
|
|
vqDebugOut(( DEB_ERROR, "Error 0x%x fetching bookmark\n", sc ));
|
|
THROW( CException( sc ) );
|
|
}
|
|
|
|
_oBookmark = 1;
|
|
}
|
|
else
|
|
_oBookmark += _chrow;
|
|
|
|
_ihrow = 0;
|
|
}
|
|
|
|
if( IsAtEnd() )
|
|
{
|
|
*(DBBKMARK *)_pbBookmark.GetPointer() = sizeof(BYTE);
|
|
_pbBookmark[sizeof(DBBKMARK)] = DBBMK_LAST;
|
|
|
|
return CMiniPositionableCache::EndOfRows;
|
|
}
|
|
|
|
LoadData();
|
|
|
|
return CMiniPositionableCache::Ok;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMiniPositionableCache::LoadPrevRowData, public
|
|
//
|
|
// Synopsis: Load the previous row data from the current top
|
|
// position into _hrowPrev and _xpbPrevRow
|
|
//
|
|
// Returns: status
|
|
//
|
|
// History: 12-Sep-98 VikasMan Created
|
|
//
|
|
// Notes: The positioning of the cursor does not change in this call.
|
|
// _hrwoPrev is set to DB_NULL_HROW if there is no previous row
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
PMiniRowCache::ENext CMiniPositionableCache::LoadPrevRowData()
|
|
{
|
|
DBCOUNTITEM chrow = 0;
|
|
|
|
if ( _hrowPrev != DB_NULL_HROW )
|
|
{
|
|
_pRowsetScroll->ReleaseRows( 1, &_hrowPrev, 0, 0, 0 );
|
|
_hrowPrev = DB_NULL_HROW;
|
|
}
|
|
|
|
HROW * phrowPrev = &_hrowPrev;
|
|
|
|
SCODE sc = _pRowsetScroll->GetRowsAt(
|
|
0, // Watch region handle
|
|
0, // Chapter
|
|
*(DBBKMARK *)_pbBookmark.GetPointer(), // cbBookmark
|
|
_pbBookmark.GetPointer() + sizeof(DBBKMARK), // pbBookmark
|
|
0 - _chrow, // Offset from bookmark
|
|
1, // Rows requested
|
|
&chrow, // Rows received
|
|
&phrowPrev ); // HROWs stored here
|
|
|
|
Win4Assert( DB_E_BADSTARTPOSITION != sc );
|
|
|
|
vqDebugOut(( DEB_ITRACE, "Fetched %d from %d\n", chrow, _Index ));
|
|
|
|
if ( FAILED(sc) )
|
|
{
|
|
vqDebugOut(( DEB_ERROR, "CMiniPositionableCache: Error 0x%x from GetRowsAt\n", sc ));
|
|
_hrowPrev = DB_NULL_HROW;
|
|
|
|
THROW( CException( sc ) );
|
|
}
|
|
else if ( 0 == chrow )
|
|
{
|
|
return ( sc == DB_S_ENDOFROWSET ?
|
|
PMiniRowCache::EndOfRows : PMiniRowCache::NotNow );
|
|
}
|
|
|
|
if ( 1 == chrow )
|
|
{
|
|
Win4Assert( _hrowPrev != DB_NULL_HROW );
|
|
|
|
// Load Data
|
|
SCODE sc = _pRowset->GetData( _hrowPrev, _hacc, _xpbPrevRow.GetPointer() );
|
|
|
|
if ( FAILED(sc) )
|
|
{
|
|
vqDebugOut(( DEB_ERROR, "PMiniRowCache: GetData returned 0x%x\n", sc ));
|
|
THROW( CException( E_FAIL ) );
|
|
}
|
|
}
|
|
|
|
return CMiniPositionableCache::Ok;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMiniPositionableCache::MovePrev, public
|
|
//
|
|
// Synopsis: Move to the previous row
|
|
//
|
|
// Returns: status
|
|
//
|
|
// History: 12-Sep-98 VikasMan Created
|
|
//
|
|
// Notes: This function uses _hrowPrev to move to previous row. Use
|
|
// LoadPrevRowData to fill up _hrowPrev and then call this function.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
PMiniRowCache::ENext CMiniPositionableCache::MovePrev()
|
|
{
|
|
if ( _ihrow > 0 )
|
|
{
|
|
_ihrow--;
|
|
}
|
|
else if ( _hrowPrev != DB_NULL_HROW )
|
|
{
|
|
if ( _chrow > 0 )
|
|
{
|
|
_pRowsetScroll->ReleaseRows( 1, &_ahrow[(unsigned)(_chrow - 1)], 0, 0, 0 );
|
|
|
|
RtlMoveMemory( &_ahrow[1], &_ahrow[0], ( _chrow - 1 ) * sizeof( HROW ) );
|
|
}
|
|
else
|
|
{
|
|
SetCacheSize( _chrow = 1 );
|
|
}
|
|
|
|
_ahrow[0] = _hrowPrev;
|
|
_hrowPrev = DB_NULL_HROW;
|
|
|
|
RtlCopyMemory( _pbRow, _xpbPrevRow.GetPointer(), _cbRow );
|
|
|
|
if ( _fUsingBookmark )
|
|
{
|
|
//
|
|
// Update current bookmark to last row fetched.
|
|
//
|
|
|
|
SCODE sc = _pRowsetScroll->GetData( _ahrow[(unsigned)(_chrow-1)],
|
|
_haccBookmark,
|
|
_pbBookmark.GetPointer() );
|
|
|
|
if ( FAILED(sc) )
|
|
{
|
|
vqDebugOut(( DEB_ERROR, "Error 0x%x fetching bookmark\n", sc ));
|
|
THROW( CException( sc ) );
|
|
}
|
|
|
|
_oBookmark = 1;
|
|
}
|
|
}
|
|
|
|
return CMiniPositionableCache::Ok;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMiniPositionableCache::Seek, public
|
|
//
|
|
// Synopsis: Seek forward from current position.
|
|
//
|
|
// Arguments: [lRows] -- Rows to move from last seek position.
|
|
//
|
|
// Returns: Move status
|
|
//
|
|
// History: 05-Jun-95 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
PMiniRowCache::ENext CMiniPositionableCache::Seek( DBROWOFFSET lRows )
|
|
{
|
|
FlushCache();
|
|
|
|
memcpy( _pbBookmark.GetPointer(),
|
|
_pbBookmarkSeek.GetPointer(),
|
|
_pbBookmark.Count() );
|
|
|
|
_oBookmark = lRows;
|
|
|
|
vqDebugOut(( DEB_ITRACE, "%d: Seek %d\n", Index(), lRows ));
|
|
return Next();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMiniPositionableCache::Seek, public
|
|
//
|
|
// Synopsis: Seek to specified bookmark.
|
|
//
|
|
// Arguments: [cbBookmark] -- Size of [pbBookmark]
|
|
// [pbBookmark] -- Bookmark
|
|
//
|
|
// Returns: Move status
|
|
//
|
|
// History: 05-Jun-95 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
PMiniRowCache::ENext CMiniPositionableCache::Seek( DBBKMARK cbBookmark, BYTE const * pbBookmark )
|
|
{
|
|
Win4Assert( _fUsingBookmark ||
|
|
(cbBookmark == 1 && (*pbBookmark == DBBMK_FIRST || *pbBookmark == DBBMK_LAST) ) );
|
|
|
|
FlushCache();
|
|
|
|
#if CIDBG == 1
|
|
if ( cbBookmark == 4 )
|
|
vqDebugOut(( DEB_ITRACE, "%d: Seek 0x%x\n", Index(), *(ULONG UNALIGNED *)pbBookmark ));
|
|
#endif
|
|
|
|
//
|
|
// Set up bookmark.
|
|
//
|
|
|
|
*(DBBKMARK *)_pbBookmark.GetPointer() = cbBookmark;
|
|
memcpy( _pbBookmark.GetPointer() + sizeof(DBBKMARK),
|
|
pbBookmark,
|
|
(unsigned) cbBookmark );
|
|
|
|
*(DBBKMARK *)_pbBookmarkSeek.GetPointer() = cbBookmark;
|
|
memcpy( _pbBookmarkSeek.GetPointer() + sizeof(DBBKMARK),
|
|
pbBookmark,
|
|
(unsigned) cbBookmark );
|
|
|
|
_oBookmark = 0;
|
|
|
|
return Next();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMiniPositionableCache::Seek, public
|
|
//
|
|
// Synopsis: Seek to specified approximate position.
|
|
//
|
|
// Arguments: [ulNumerator] -- Numerator.
|
|
// [ulDenominator] -- Denominator.
|
|
//
|
|
// Returns: Move status
|
|
//
|
|
// History: 05-Jun-95 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
PMiniRowCache::ENext CMiniPositionableCache::Seek( DBCOUNTITEM ulNumerator, DBCOUNTITEM ulDenominator )
|
|
{
|
|
Win4Assert( _fUsingBookmark );
|
|
|
|
FlushCache();
|
|
|
|
vqDebugOut(( DEB_ITRACE, "%d: Seek %u/%u through.\n", Index(), ulNumerator, ulDenominator ));
|
|
|
|
HROW * phrow = _ahrow.GetPointer();
|
|
|
|
SCODE sc = _pRowsetScroll->GetRowsAtRatio( 0, // Watch region handle
|
|
0, // Chapter
|
|
ulNumerator,
|
|
ulDenominator,
|
|
_ahrow.Count(), // Rows requested
|
|
&_chrow, // Rows received
|
|
&phrow ); // HROWs stored here
|
|
|
|
vqDebugOut(( DEB_ITRACE, "Fetched %d from %d\n", _chrow, _Index ));
|
|
|
|
if ( FAILED(sc) )
|
|
{
|
|
vqDebugOut(( DEB_ERROR, "CMiniPositionableCache: Error 0x%x from GetRowsAtRatio\n", sc ));
|
|
_chrow = 0;
|
|
|
|
THROW( CException( sc ) );
|
|
}
|
|
else if ( 0 == _chrow && sc != DB_S_ENDOFROWSET )
|
|
{
|
|
return( PMiniRowCache::NotNow );
|
|
}
|
|
|
|
if ( _chrow > 0 )
|
|
{
|
|
//
|
|
// Update current bookmark to last row fetched.
|
|
//
|
|
|
|
SCODE sc = _pRowsetScroll->GetData( _ahrow[(unsigned)(_chrow-1)],
|
|
_haccBookmark,
|
|
_pbBookmark.GetPointer() );
|
|
|
|
if ( FAILED(sc) )
|
|
{
|
|
vqDebugOut(( DEB_ERROR, "Error 0x%x fetching bookmark\n", sc ));
|
|
THROW( CException( sc ) );
|
|
}
|
|
|
|
memcpy( _pbBookmarkSeek.GetPointer(),
|
|
_pbBookmark.GetPointer(),
|
|
_pbBookmark.Count() );
|
|
|
|
_oBookmark = 1;
|
|
}
|
|
|
|
_ihrow = 0;
|
|
|
|
if( IsAtEnd() )
|
|
{
|
|
return CMiniPositionableCache::EndOfRows;
|
|
}
|
|
|
|
LoadData();
|
|
|
|
return CMiniPositionableCache::Ok;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMiniPositionableCache::FlushCache, public
|
|
//
|
|
// Synopsis: Clear the cache.
|
|
//
|
|
// History: 12-Sep-98 VikasMan Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CMiniPositionableCache::FlushCache()
|
|
{
|
|
if ( _hrowPrev != DB_NULL_HROW )
|
|
{
|
|
_pRowsetScroll->ReleaseRows( 1, &_hrowPrev, 0, 0, 0 );
|
|
_hrowPrev = DB_NULL_HROW;
|
|
}
|
|
PMiniRowCache::FlushCache();
|
|
}
|
|
|