794 lines
22 KiB
C++
794 lines
22 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Copyright (C) 1994-1997, Microsoft Corporation.
|
||
|
//
|
||
|
// File: rowseek.cxx
|
||
|
//
|
||
|
// Contents: Classes which encapsulate a positioning operation
|
||
|
// for a table.
|
||
|
//
|
||
|
// Classes: CRowSeekDescription
|
||
|
// CRowSeekNext
|
||
|
// CRowSeekAt
|
||
|
// CRowSeekAtRatio
|
||
|
// CRowSeekByBookmark
|
||
|
//
|
||
|
// History: 06 Apr 1995 AlanW Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#include <pch.cxx>
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <query.hxx>
|
||
|
#include <sizeser.hxx>
|
||
|
|
||
|
#include "tabledbg.hxx"
|
||
|
#include "rowseek.hxx"
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekDescription::MarshalledSize, public
|
||
|
//
|
||
|
// Synopsis: Return Serialized size of a CRowSeekDescription structure
|
||
|
//
|
||
|
// Arguments: - none -
|
||
|
//
|
||
|
// Returns: unsigned - size in bytes of serialized structure.
|
||
|
//
|
||
|
// Notes: The returned size should be the maximum of the serialized
|
||
|
// size on input and output. None of the seek descriptions
|
||
|
// grow on output, so the input size may be larger than the
|
||
|
// output size.
|
||
|
//
|
||
|
// History: 02 May 1995 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
unsigned
|
||
|
CRowSeekDescription::MarshalledSize(
|
||
|
) const {
|
||
|
//
|
||
|
// Determine the size of the serialized seek description
|
||
|
//
|
||
|
CSizeSerStream stmSize;
|
||
|
Marshall(stmSize);
|
||
|
|
||
|
return stmSize.Size();
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekDescription::MarshallBase, public
|
||
|
//
|
||
|
// Synopsis: Serialize the base CRowSeekDescription structure
|
||
|
//
|
||
|
// Arguments: [stm] -- stream structure is serialized into
|
||
|
// [eType] -- type descriminator for derived class
|
||
|
//
|
||
|
// Returns: nothing
|
||
|
//
|
||
|
// History: 29 Jan 1995 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void
|
||
|
CRowSeekDescription::MarshallBase(
|
||
|
PSerStream & stm,
|
||
|
DWORD eType
|
||
|
) const {
|
||
|
stm.PutULong(eType);
|
||
|
stm.PutULong(GetChapter());
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekNext::Marshall, public
|
||
|
//
|
||
|
// Synopsis: Serialize a CRowSeekNext structure
|
||
|
//
|
||
|
// Arguments: [stm] -- stream structure is serialized into
|
||
|
//
|
||
|
// Returns: nothing
|
||
|
//
|
||
|
// History: 29 Jan 1995 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void
|
||
|
CRowSeekNext::Marshall(
|
||
|
PSerStream & stm
|
||
|
) const {
|
||
|
CRowSeekDescription::MarshallBase( stm, eRowSeekCurrent );
|
||
|
stm.PutULong(GetSkip());
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekAt::Marshall, public
|
||
|
//
|
||
|
// Synopsis: Serialize a CRowSeekAt structure
|
||
|
//
|
||
|
// Arguments: [stm] -- stream structure is serialized into
|
||
|
//
|
||
|
// Returns: nothing
|
||
|
//
|
||
|
// History: 29 Jan 1995 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void
|
||
|
CRowSeekAt::Marshall(
|
||
|
PSerStream & stm
|
||
|
) const {
|
||
|
CRowSeekDescription::MarshallBase( stm, eRowSeekAt );
|
||
|
|
||
|
stm.PutULong(Bmk());
|
||
|
stm.PutLong(Offset());
|
||
|
stm.PutULong(ULONG(_hRegion));
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekAtRatio::Marshall, public
|
||
|
//
|
||
|
// Synopsis: Serialize a CRowSeekAtRatio structure
|
||
|
//
|
||
|
// Arguments: [stm] -- stream structure is serialized into
|
||
|
//
|
||
|
// Returns: nothing
|
||
|
//
|
||
|
// History: 29 Jan 1995 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CRowSeekAtRatio::Marshall( PSerStream & stm) const
|
||
|
{
|
||
|
CRowSeekDescription::MarshallBase( stm, eRowSeekAtRatio );
|
||
|
stm.PutULong(RatioNumerator());
|
||
|
stm.PutULong(RatioDenominator());
|
||
|
stm.PutULong(ULONG(_hRegion));
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekByBookmark::Marshall, public
|
||
|
//
|
||
|
// Synopsis: Serialize a CRowSeekByBookmark structure
|
||
|
//
|
||
|
// Arguments: [stm] -- stream structure is serialized into
|
||
|
//
|
||
|
// Returns: nothing
|
||
|
//
|
||
|
// Notes: When serializing ByBookmarks, we only do bookmarks
|
||
|
// or statuses, not both. Only one must exist in the structure.
|
||
|
//
|
||
|
// History: 29 Jan 1995 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CRowSeekByBookmark::Marshall(PSerStream & stm) const
|
||
|
{
|
||
|
Win4Assert(_cBookmarks == 0 || _cValidRet == 0);
|
||
|
|
||
|
CRowSeekDescription::MarshallBase( stm, eRowSeekByBookmark );
|
||
|
|
||
|
stm.PutULong(_cBookmarks);
|
||
|
for (unsigned i = 0; i < _cBookmarks; i++)
|
||
|
stm.PutULong(_aBookmarks[i]);
|
||
|
|
||
|
stm.PutULong(_cValidRet);
|
||
|
for (i = 0; i < _cValidRet; i++)
|
||
|
stm.PutULong(_ascRet[i]);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekNext::CRowSeekNext, public
|
||
|
//
|
||
|
// Synopsis: DeSerialize a CRowSeekNext structure
|
||
|
//
|
||
|
// Arguments: [stm] -- input stream structure is read from
|
||
|
// [iVersion] -- input stream version
|
||
|
//
|
||
|
// Returns: nothing
|
||
|
//
|
||
|
// History: 06 Apr 1995 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CRowSeekNext::CRowSeekNext( PDeSerStream & stm, int iVersion ) :
|
||
|
CRowSeekDescription( eRowSeekCurrent, 0 )
|
||
|
{
|
||
|
SetChapter( stm.GetULong() );
|
||
|
SetSkip( stm.GetULong() );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekAt::CRowSeekAt, public
|
||
|
//
|
||
|
// Synopsis: DeSerialize a CRowSeekAt structure
|
||
|
//
|
||
|
// Arguments: [stm] -- input stream structure is read from
|
||
|
//
|
||
|
// Returns: nothing
|
||
|
//
|
||
|
// History: 06 Apr 1995 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CRowSeekAt::CRowSeekAt( PDeSerStream & stm, int iVersion ) :
|
||
|
CRowSeekDescription( eRowSeekAt, 0 )
|
||
|
{
|
||
|
SetChapter( stm.GetULong() );
|
||
|
_bmkOffset = stm.GetULong();
|
||
|
_cRowsOffset = stm.GetLong();
|
||
|
_hRegion = (HWATCHREGION) stm.GetULong();
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekAtRatio::CRowSeekAtRatio, public
|
||
|
//
|
||
|
// Synopsis: DeSerialize a CRowSeekAtRatio structure
|
||
|
//
|
||
|
// Arguments: [stm] -- input stream structure is read from
|
||
|
//
|
||
|
// Returns: nothing
|
||
|
//
|
||
|
// History: 06 Apr 1995 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CRowSeekAtRatio::CRowSeekAtRatio( PDeSerStream & stm, int iVersion ) :
|
||
|
CRowSeekDescription( eRowSeekAtRatio, 0 )
|
||
|
{
|
||
|
SetChapter( stm.GetULong() );
|
||
|
_ulNumerator = stm.GetULong();
|
||
|
_ulDenominator = stm.GetULong();
|
||
|
_hRegion = (HWATCHREGION) stm.GetULong();
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekByBookmark::CRowSeekByBookmark, public
|
||
|
//
|
||
|
// Synopsis: DeSerialize a CRowSeekByBookmark structure
|
||
|
//
|
||
|
// Arguments: [stm] -- input stream structure is read from
|
||
|
//
|
||
|
// Returns: nothing
|
||
|
//
|
||
|
// History: 06 Apr 1995 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CRowSeekByBookmark::CRowSeekByBookmark( PDeSerStream & stm, int iVersion ) :
|
||
|
CRowSeekDescription( eRowSeekByBookmark, 0 ),
|
||
|
_aBookmarks( 0 ),
|
||
|
_ascRet( 0 )
|
||
|
{
|
||
|
SetChapter( stm.GetULong() );
|
||
|
|
||
|
_cBookmarks = stm.GetULong();
|
||
|
if (_cBookmarks)
|
||
|
{
|
||
|
// Protect agains unreasonable requests, which probably are attacks
|
||
|
|
||
|
if ( _cBookmarks >= 65536 )
|
||
|
THROW( CException( E_INVALIDARG ) );
|
||
|
|
||
|
_aBookmarks = new CI_TBL_BMK [ _cBookmarks ];
|
||
|
|
||
|
for (unsigned i = 0; i < _cBookmarks; i++)
|
||
|
_aBookmarks[i] = stm.GetULong();
|
||
|
}
|
||
|
|
||
|
_maxRet = _cValidRet = stm.GetULong();
|
||
|
|
||
|
if (_cValidRet)
|
||
|
{
|
||
|
// Protect against unreasonable requests, which probably are attacks
|
||
|
|
||
|
if ( _cValidRet >= 65536 )
|
||
|
THROW( CException( E_INVALIDARG ) );
|
||
|
|
||
|
_ascRet = new SCODE [ _cValidRet ];
|
||
|
|
||
|
for (unsigned i = 0; i < _cValidRet; i++)
|
||
|
_ascRet[i] = stm.GetULong();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We don't expect both bookmarks and statuses.
|
||
|
//
|
||
|
Win4Assert(_cBookmarks == 0 || _cValidRet == 0);
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekByBookmark::~CRowSeekByBookmark, public
|
||
|
//
|
||
|
// Synopsis: Destroy a CRowSeekByBookmark structure
|
||
|
//
|
||
|
// Returns: nothing
|
||
|
//
|
||
|
// History: 29 Jan 1995 AlanW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CRowSeekByBookmark::~CRowSeekByBookmark( )
|
||
|
{
|
||
|
delete _aBookmarks;
|
||
|
delete _ascRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekNext::GetRows, public
|
||
|
//
|
||
|
// Synopsis: Retrieve row data for a table cursor
|
||
|
//
|
||
|
// Arguments: [rCursor] - the cursor to fetch data for
|
||
|
// [rTable] - the table from which data is fetched
|
||
|
// [rFetchParams] - row fetch parameters and buffer pointers
|
||
|
// [pSeekDescOut] - pointer to seek description for restart
|
||
|
//
|
||
|
// Returns: SCODE - the status of the operation.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// History: 07 Apr 1995 Alanw Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
SCODE
|
||
|
CRowSeekNext::GetRows(
|
||
|
CTableCursor& rCursor,
|
||
|
CTableSource& rTable,
|
||
|
CGetRowsParams& rFetchParams,
|
||
|
XPtr<CRowSeekDescription>& pSeekDescOut) const
|
||
|
{
|
||
|
LONG cRowsToSkip = GetSkip();
|
||
|
|
||
|
if (cRowsToSkip)
|
||
|
{
|
||
|
tbDebugOut(( DEB_IWARN, "CRowSeekNext::GetRows - non-zero skip count %d\n",
|
||
|
cRowsToSkip ));
|
||
|
}
|
||
|
|
||
|
WORKID widStart;
|
||
|
if ( rTable.IsFirstGetNextRows() )
|
||
|
{
|
||
|
//
|
||
|
// For the first GetNextRows call, the start position is
|
||
|
// beginning of table if cRowsToSkip is positive, and end
|
||
|
// of table if its negative. For subsequent calls, the
|
||
|
// current position is the start position.
|
||
|
//
|
||
|
|
||
|
if ( cRowsToSkip >= 0 )
|
||
|
widStart = WORKID_TBLBEFOREFIRST;
|
||
|
else
|
||
|
widStart = WORKID_TBLAFTERLAST;
|
||
|
}
|
||
|
else
|
||
|
widStart = rTable.GetCurrentPosition( GetChapter() );
|
||
|
|
||
|
WORKID widEnd = widStart;
|
||
|
|
||
|
//
|
||
|
// OffsetSameDirFetch implements the skip of one row that
|
||
|
// Oledb::GetNextRows requires on the first fetch
|
||
|
// when scrolling and fetching are in the same direction,
|
||
|
// and for subsequent fetches when the fetch is in the
|
||
|
// same direction as previous fetch. When the direction is
|
||
|
// reversed the first wid fetched is same as the last wid
|
||
|
// returned from the previous call, and offsetSameDirFetch
|
||
|
// is 0 in this case.
|
||
|
//
|
||
|
LONG offsetSameDirFetch = 0;
|
||
|
if ( rTable.IsFirstGetNextRows() )
|
||
|
{
|
||
|
if ( cRowsToSkip >= 0 && rFetchParams.GetFwdFetch() )
|
||
|
offsetSameDirFetch = 1;
|
||
|
else if ( cRowsToSkip < 0 && !rFetchParams.GetFwdFetch() )
|
||
|
offsetSameDirFetch = -1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( rFetchParams.GetFwdFetch() == rTable.GetFwdFetchPrev() )
|
||
|
{
|
||
|
if ( rFetchParams.GetFwdFetch() )
|
||
|
offsetSameDirFetch = 1;
|
||
|
else
|
||
|
offsetSameDirFetch = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SCODE scRet = rTable.GetRowsAt( 0, // no watch region
|
||
|
widStart,
|
||
|
GetChapter(),
|
||
|
cRowsToSkip + offsetSameDirFetch,
|
||
|
rCursor.GetBindings(),
|
||
|
rFetchParams,
|
||
|
widEnd );
|
||
|
|
||
|
//
|
||
|
// Don't attempt to save the widEnd if the positioning
|
||
|
// operation got us past the end of the table. Storing
|
||
|
// widEnd in rCursor will cause us to be stuck at the
|
||
|
// end, with no way to get any more rows. In this situation,
|
||
|
// we don't expect to have successfully transferred any rows.
|
||
|
//
|
||
|
// NOTE: don't throw, the error may need to be seen by caller
|
||
|
// in CRowset::_FetchRows
|
||
|
//
|
||
|
if ( WORKID_TBLAFTERLAST == widEnd ||
|
||
|
WORKID_TBLBEFOREFIRST == widEnd ||
|
||
|
( scRet == DB_E_BADSTARTPOSITION && cRowsToSkip == 0 ) )
|
||
|
{
|
||
|
Win4Assert(rFetchParams.RowsTransferred() == 0);
|
||
|
return DB_S_ENDOFROWSET;
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(scRet))
|
||
|
{
|
||
|
rTable.SetCurrentPosition( GetChapter(), widEnd );
|
||
|
rTable.SetFwdFetchPrev( rFetchParams.GetFwdFetch() );
|
||
|
rTable.ResetFirstGetNextRows();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tbDebugOut(( DEB_WARN, "CRowSeekNext::GetRows failed, sc=%x\n",
|
||
|
scRet ));
|
||
|
}
|
||
|
|
||
|
|
||
|
if (DB_S_BLOCKLIMITEDROWS == scRet)
|
||
|
{
|
||
|
Win4Assert(rFetchParams.RowsTransferred() > 0);
|
||
|
pSeekDescOut.Set(new CRowSeekNext(GetChapter(), 0) );
|
||
|
}
|
||
|
|
||
|
return scRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekAt::GetRows, public
|
||
|
//
|
||
|
// Synopsis: Retrieve row data for a table cursor
|
||
|
//
|
||
|
// Arguments: [rCursor] - the cursor to fetch data for
|
||
|
// [rTable] - the table from which data is fetched
|
||
|
// [rFetchParams] - row fetch parameters and buffer pointers
|
||
|
// [pSeekDescOut] - pointer to seek description for restart
|
||
|
//
|
||
|
// Returns: SCODE - the status of the operation.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// History: 07 Apr 1995 Alanw Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
SCODE
|
||
|
CRowSeekAt::GetRows(
|
||
|
CTableCursor& rCursor,
|
||
|
CTableSource& rTable,
|
||
|
CGetRowsParams& rFetchParams,
|
||
|
XPtr<CRowSeekDescription>& pSeekDescOut) const
|
||
|
{
|
||
|
WORKID widStart = Bmk();
|
||
|
LONG iRowOffset = Offset();
|
||
|
|
||
|
SCODE scRet = rTable.GetRowsAt( _hRegion,
|
||
|
widStart,
|
||
|
GetChapter(),
|
||
|
iRowOffset,
|
||
|
rCursor.GetBindings(),
|
||
|
rFetchParams,
|
||
|
widStart );
|
||
|
|
||
|
// The first fetch took care of the hRegion manipulation
|
||
|
// set the new seek descriptor's hRegion to 0
|
||
|
if (DB_S_BLOCKLIMITEDROWS == scRet)
|
||
|
{
|
||
|
Win4Assert(rFetchParams.RowsTransferred() > 0);
|
||
|
pSeekDescOut.Set(new CRowSeekAt(0,
|
||
|
GetChapter(),
|
||
|
rFetchParams.GetFwdFetch() ? 1 : -1,
|
||
|
widStart) );
|
||
|
}
|
||
|
|
||
|
return scRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekAtRatio::GetRows, public
|
||
|
//
|
||
|
// Synopsis: Retrieve row data for a table cursor
|
||
|
//
|
||
|
// Arguments: [rCursor] - the cursor to fetch data for
|
||
|
// [rTable] - the table from which data is fetched
|
||
|
// [rFetchParams] - row fetch parameters and buffer pointers
|
||
|
// [pSeekDescOut] - pointer to seek description for restart
|
||
|
//
|
||
|
// Returns: SCODE - the status of the operation.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// History: 07 Apr 1995 Alanw Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
SCODE
|
||
|
CRowSeekAtRatio::GetRows(
|
||
|
CTableCursor& rCursor,
|
||
|
CTableSource& rTable,
|
||
|
CGetRowsParams& rFetchParams,
|
||
|
XPtr<CRowSeekDescription>& pSeekDescOut) const
|
||
|
{
|
||
|
WORKID widRestart = widInvalid;
|
||
|
SCODE scRet = rTable.GetRowsAtRatio( _hRegion,
|
||
|
RatioNumerator(),
|
||
|
RatioDenominator(),
|
||
|
GetChapter(),
|
||
|
rCursor.GetBindings(),
|
||
|
rFetchParams,
|
||
|
widRestart );
|
||
|
|
||
|
// The first fetch took care of the hRegion manipulation
|
||
|
// set the new seek descriptor's hRegion to 0
|
||
|
if (DB_S_BLOCKLIMITEDROWS == scRet)
|
||
|
{
|
||
|
Win4Assert(rFetchParams.RowsTransferred() > 0);
|
||
|
pSeekDescOut.Set(new CRowSeekAt(0, GetChapter(), 1, widRestart) );
|
||
|
}
|
||
|
|
||
|
return scRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekByBookmark::GetRows, public
|
||
|
//
|
||
|
// Synopsis: Retrieve row data for a table cursor
|
||
|
//
|
||
|
// Arguments: [rCursor] - the cursor to fetch data for
|
||
|
// [rTable] - the table from which data is fetched
|
||
|
// [rFetchParams] - row fetch parameters and buffer pointers
|
||
|
// [pSeekDescOut] - pointer to seek description for restart
|
||
|
//
|
||
|
// Returns: SCODE - the status of the operation.
|
||
|
//
|
||
|
//
|
||
|
// History: 07 Apr 1995 Alanw Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
SCODE
|
||
|
CRowSeekByBookmark::GetRows(
|
||
|
CTableCursor& rCursor,
|
||
|
CTableSource& rTable,
|
||
|
CGetRowsParams& rFetchParams,
|
||
|
XPtr<CRowSeekDescription>& pSeekDescOut) const
|
||
|
{
|
||
|
unsigned cFailed = 0;
|
||
|
ULONG cSavedRowsReq = rFetchParams.RowsToTransfer();
|
||
|
|
||
|
Win4Assert(_cBookmarks > 0);
|
||
|
Win4Assert(cSavedRowsReq <= _cBookmarks);
|
||
|
Win4Assert(0 == rFetchParams.RowsTransferred() && cSavedRowsReq > 0);
|
||
|
|
||
|
rFetchParams.SetRowsRequested(0);
|
||
|
|
||
|
SCODE scRet = S_OK;
|
||
|
|
||
|
TRY
|
||
|
{
|
||
|
XPtr<CRowSeekByBookmark> pSeekOut(
|
||
|
new CRowSeekByBookmark(GetChapter(), _cBookmarks) );
|
||
|
|
||
|
BOOL fFailed = FALSE;
|
||
|
// Iterate over bookmarks, calling rTable.GetRowsAt for each
|
||
|
for (unsigned i = 0; i < cSavedRowsReq; i++)
|
||
|
{
|
||
|
if (! fFailed)
|
||
|
rFetchParams.IncrementRowsRequested( );
|
||
|
|
||
|
WORKID widNext = _aBookmarks[i];
|
||
|
if (widNext == widInvalid)
|
||
|
{
|
||
|
scRet = DB_E_BADBOOKMARK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRY
|
||
|
{
|
||
|
scRet = rTable.GetRowsAt( 0, // no watch region
|
||
|
widNext,
|
||
|
GetChapter(),
|
||
|
0,
|
||
|
rCursor.GetBindings(),
|
||
|
rFetchParams,
|
||
|
widNext );
|
||
|
}
|
||
|
CATCH( CException, e )
|
||
|
{
|
||
|
scRet = e.GetErrorCode();
|
||
|
Win4Assert( scRet != STATUS_ACCESS_VIOLATION &&
|
||
|
scRet != STATUS_NO_MEMORY );
|
||
|
}
|
||
|
END_CATCH;
|
||
|
|
||
|
if (! SUCCEEDED(scRet) && scRet != STATUS_BUFFER_TOO_SMALL )
|
||
|
scRet = DB_E_BOOKMARKSKIPPED;
|
||
|
}
|
||
|
|
||
|
if (scRet == DB_S_ENDOFROWSET)
|
||
|
scRet = S_OK;
|
||
|
|
||
|
if ( STATUS_BUFFER_TOO_SMALL == scRet ||
|
||
|
DB_S_BLOCKLIMITEDROWS == scRet )
|
||
|
{
|
||
|
scRet = DB_S_BLOCKLIMITEDROWS;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// set per-row error status
|
||
|
//
|
||
|
pSeekOut->_SetStatus(i, scRet);
|
||
|
if (FAILED(scRet))
|
||
|
{
|
||
|
cFailed++;
|
||
|
fFailed = TRUE;
|
||
|
}
|
||
|
else
|
||
|
fFailed = FALSE;
|
||
|
}
|
||
|
pSeekDescOut.Set( pSeekOut.Acquire() );
|
||
|
}
|
||
|
CATCH( CException, e )
|
||
|
{
|
||
|
scRet = e.GetErrorCode();
|
||
|
}
|
||
|
END_CATCH;
|
||
|
|
||
|
if (cFailed)
|
||
|
return DB_S_ERRORSOCCURRED;
|
||
|
else if (0 == rFetchParams.RowsTransferred())
|
||
|
return STATUS_BUFFER_TOO_SMALL;
|
||
|
else
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekByBookmark::_SetStatus, private
|
||
|
//
|
||
|
// Synopsis: Set row status for a bookmark lookup
|
||
|
//
|
||
|
// Arguments: [iBmk] - index of bookmark to set status for
|
||
|
// [scRet] - the status to be saved
|
||
|
//
|
||
|
// Returns: Nothing
|
||
|
//
|
||
|
// History: 12 Apr 1995 Alanw Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
void
|
||
|
CRowSeekByBookmark::_SetStatus(
|
||
|
unsigned iBmk,
|
||
|
SCODE scRet
|
||
|
) {
|
||
|
Win4Assert( iBmk < _maxRet );
|
||
|
|
||
|
if (_ascRet == 0)
|
||
|
_ascRet = new SCODE[_maxRet];
|
||
|
|
||
|
_ascRet[iBmk] = scRet;
|
||
|
if (iBmk >= _cValidRet)
|
||
|
{
|
||
|
Win4Assert( iBmk == _cValidRet );
|
||
|
_cValidRet = iBmk + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekDescription::MergeResults, public
|
||
|
//
|
||
|
// Synopsis: Update seek description state after a transfer
|
||
|
//
|
||
|
// Arguments: [pRowSeek] - row seek description after transfer
|
||
|
//
|
||
|
// Returns: Nothing
|
||
|
//
|
||
|
// Notes: Used only in user mode. Does nothing for CRowSeekNext,
|
||
|
// CRowSeekAt and CRowSeekAtRatio.
|
||
|
//
|
||
|
// History: 02 May 1995 Alanw Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
void
|
||
|
CRowSeekDescription::MergeResults(
|
||
|
CRowSeekDescription * pRowSeek )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CRowSeekByBookmark::MergeResults, public
|
||
|
//
|
||
|
// Synopsis: Update seek description state after a transfer
|
||
|
//
|
||
|
// Arguments: [pRowSeek] - row seek description after transfer
|
||
|
//
|
||
|
// Returns: Nothing
|
||
|
//
|
||
|
// Notes: Used only in user mode. Transfers statuses into
|
||
|
// original rowseek and bookmarks from original to
|
||
|
// result rowseek.
|
||
|
//
|
||
|
// History: 02 May 1995 Alanw Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
void
|
||
|
CRowSeekByBookmark::MergeResults(
|
||
|
CRowSeekDescription * pRowSeekDesc)
|
||
|
{
|
||
|
Win4Assert(pRowSeekDesc->IsByBmkRowSeek());
|
||
|
|
||
|
CRowSeekByBookmark* pRowSeek = (CRowSeekByBookmark*) pRowSeekDesc;
|
||
|
|
||
|
Win4Assert(_cBookmarks > 0 &&
|
||
|
pRowSeek->_cValidRet > 0 && pRowSeek->_cBookmarks == 0);
|
||
|
|
||
|
//
|
||
|
// Transfer return statuses to this object from the other
|
||
|
//
|
||
|
unsigned iBaseRet = _cValidRet;
|
||
|
|
||
|
for (unsigned i=0; i < pRowSeek->_cValidRet; i++)
|
||
|
{
|
||
|
_SetStatus( i+iBaseRet, pRowSeek->_ascRet[i] );
|
||
|
}
|
||
|
|
||
|
delete [] pRowSeek->_ascRet;
|
||
|
pRowSeek->_ascRet = 0;
|
||
|
pRowSeek->_cValidRet = pRowSeek->_maxRet = 0;
|
||
|
|
||
|
//
|
||
|
// Transfer bookmarks from this object to the other.
|
||
|
//
|
||
|
if (_cBookmarks - _cValidRet > 0)
|
||
|
{
|
||
|
pRowSeek->_cBookmarks = _cBookmarks - _cValidRet;
|
||
|
pRowSeek->_aBookmarks = new CI_TBL_BMK[ pRowSeek->_cBookmarks ];
|
||
|
|
||
|
for (unsigned i=0; i<pRowSeek->_cBookmarks; i++)
|
||
|
{
|
||
|
pRowSeek->_aBookmarks[i] = _aBookmarks[ i+_cValidRet ];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|