Added .cpp and .h files under the sql/src subdirectory
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@469 0109f412-320b-0410-ab79-c3e0c5ffbbe6
This commit is contained in:
783
sql/src/fsdatacu.cpp
Normal file
783
sql/src/fsdatacu.cpp
Normal file
@@ -0,0 +1,783 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Desc: Cursor routines to get the complexity of the file system out
|
||||
// of the search code.
|
||||
//
|
||||
// Tabs: 3
|
||||
//
|
||||
// Copyright (c) 2000-2006 Novell, Inc. All Rights Reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of version 2 of the GNU General Public
|
||||
// License as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, contact Novell, Inc.
|
||||
//
|
||||
// To contact Novell about this file by physical or electronic mail,
|
||||
// you may find current contact information at www.novell.com
|
||||
//
|
||||
// $Id$
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "flaimsys.h"
|
||||
#include "fscursor.h"
|
||||
|
||||
/****************************************************************************
|
||||
Desc:
|
||||
****************************************************************************/
|
||||
FSTableCursor::FSTableCursor()
|
||||
{
|
||||
m_pbTree = NULL;
|
||||
m_bTreeOpen = FALSE;
|
||||
m_pTable = NULL;
|
||||
m_pLFile = NULL;
|
||||
m_pDb = NULL;
|
||||
m_eTransType = SFLM_NO_TRANS;
|
||||
resetCursor();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc:
|
||||
****************************************************************************/
|
||||
FSTableCursor::~FSTableCursor()
|
||||
{
|
||||
closeBTree();
|
||||
if (m_pbTree)
|
||||
{
|
||||
gv_SFlmSysData.pBtPool->btpReturnBtree( &m_pbTree);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Resets any allocations, keys, state, etc.
|
||||
****************************************************************************/
|
||||
void FSTableCursor::resetCursor( void)
|
||||
{
|
||||
closeBTree();
|
||||
m_uiTableNum = 0;
|
||||
m_uiBlkChangeCnt = 0;
|
||||
m_ui64CurrTransId = 0;
|
||||
m_ui64CurRowId = 0;
|
||||
m_bAtBOF = TRUE;
|
||||
m_bAtEOF = FALSE;
|
||||
m_bSetup = FALSE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Resets to a new transaction that may change the read consistency of
|
||||
the query.
|
||||
****************************************************************************/
|
||||
RCODE FSTableCursor::resetTransaction(
|
||||
F_Db * pDb)
|
||||
{
|
||||
RCODE rc = NE_SFLM_OK;
|
||||
F_TABLE * pTable;
|
||||
|
||||
if ((pTable = pDb->m_pDict->getTable( m_uiTableNum)) == NULL)
|
||||
{
|
||||
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_TABLE_NUM);
|
||||
goto Exit;
|
||||
}
|
||||
if (pTable != m_pTable)
|
||||
{
|
||||
m_pTable = pTable;
|
||||
m_pLFile = &pTable->lfInfo;
|
||||
if (m_bTreeOpen)
|
||||
{
|
||||
closeBTree();
|
||||
}
|
||||
m_pDb = pDb;
|
||||
m_eTransType = pDb->m_eTransType;
|
||||
}
|
||||
m_ui64CurrTransId = pDb->m_ui64CurrTransID;
|
||||
m_uiBlkChangeCnt = pDb->m_uiBlkChangeCnt;
|
||||
|
||||
Exit:
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Open the F_Btree object if not already open.
|
||||
****************************************************************************/
|
||||
RCODE FSTableCursor::openBTree(
|
||||
F_Db * pDb
|
||||
)
|
||||
{
|
||||
RCODE rc = NE_SFLM_OK;
|
||||
|
||||
if (!m_bTreeOpen)
|
||||
{
|
||||
if (!m_pbTree)
|
||||
{
|
||||
if (RC_BAD( rc = gv_SFlmSysData.pBtPool->btpReserveBtree( &m_pbTree)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
Open_Btree:
|
||||
if (RC_BAD( rc = m_pbTree->btOpen( pDb, m_pLFile, FALSE, FALSE)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
m_bTreeOpen = TRUE;
|
||||
m_pDb = pDb;
|
||||
m_eTransType = pDb->m_eTransType;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pDb != m_pDb || pDb->m_eTransType != m_eTransType)
|
||||
{
|
||||
closeBTree();
|
||||
goto Open_Btree;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Set the row position.
|
||||
****************************************************************************/
|
||||
RCODE FSTableCursor::setRowPosition(
|
||||
F_Db * pDb,
|
||||
FLMBOOL bGoingForward,
|
||||
FLMUINT64 ui64RowId,
|
||||
FLMBOOL bPopulateCurRowId,
|
||||
F_Btree * pBTree // BTree to use. NULL means use our
|
||||
// internal one.
|
||||
)
|
||||
{
|
||||
RCODE rc = NE_SFLM_OK;
|
||||
FLMBOOL bNeg;
|
||||
FLMBYTE ucRowKey [FLM_MAX_NUM_BUF_SIZE];
|
||||
FLMUINT uiRowKeyLen;
|
||||
FLMBYTE * pucRowKey;
|
||||
FLMUINT * puiRowKeyLen;
|
||||
FLMUINT uiKeyBufSize;
|
||||
FLMUINT uiBytesProcessed;
|
||||
FLMUINT64 ui64TmpRowId;
|
||||
|
||||
// if pBTree is NULL, we are to use m_pbTree. Otherwise, we
|
||||
// need to open the pBTree and use it.
|
||||
|
||||
if (!pBTree)
|
||||
{
|
||||
if (RC_BAD( rc = openBTree( pDb)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
pBTree = m_pbTree;
|
||||
}
|
||||
|
||||
if (bPopulateCurRowId)
|
||||
{
|
||||
pucRowKey = &m_ucCurRowKey [0];
|
||||
puiRowKeyLen = &m_uiCurRowKeyLen;
|
||||
uiKeyBufSize = sizeof( m_ucCurRowKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
pucRowKey = &ucRowKey [0];
|
||||
puiRowKeyLen = &uiRowKeyLen;
|
||||
uiKeyBufSize = sizeof( ucRowKey);
|
||||
}
|
||||
|
||||
*puiRowKeyLen = uiKeyBufSize;
|
||||
if (RC_BAD( rc = flmNumber64ToStorage( ui64RowId, puiRowKeyLen,
|
||||
pucRowKey, FALSE, TRUE)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (RC_BAD( rc = pBTree->btLocateEntry( pucRowKey, uiKeyBufSize,
|
||||
puiRowKeyLen, FLM_INCL)))
|
||||
{
|
||||
if (rc != NE_SFLM_EOF_HIT)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (bGoingForward)
|
||||
{
|
||||
if (rc == NE_SFLM_EOF_HIT)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Going backwards or to last. See if we positioned too far.
|
||||
|
||||
if (rc == NE_SFLM_BOF_HIT || rc == NE_SFLM_EOF_HIT)
|
||||
{
|
||||
|
||||
// Position to last key in tree.
|
||||
|
||||
if (RC_BAD( rc = pBTree->btLastEntry( pucRowKey, uiKeyBufSize,
|
||||
puiRowKeyLen,
|
||||
NULL, NULL, NULL)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RC_BAD( rc = flmCollation2Number( *puiRowKeyLen, pucRowKey,
|
||||
&ui64TmpRowId, &bNeg, &uiBytesProcessed)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
if (ui64TmpRowId > ui64RowId)
|
||||
{
|
||||
|
||||
// Position to the previous key.
|
||||
|
||||
if (RC_BAD( rc = pBTree->btPrevEntry( pucRowKey, uiKeyBufSize,
|
||||
puiRowKeyLen, NULL, NULL, NULL)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bPopulateCurRowId)
|
||||
{
|
||||
if (RC_BAD( rc = flmCollation2Number( *puiRowKeyLen, pucRowKey,
|
||||
&m_ui64CurRowId, &bNeg, &uiBytesProcessed)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
if (RC_BAD( rc))
|
||||
{
|
||||
if (pBTree == m_pbTree)
|
||||
{
|
||||
closeBTree();
|
||||
}
|
||||
}
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Setup the from and until keys in the cursor. Return counts
|
||||
after positioning to the from and until key in the table.
|
||||
****************************************************************************/
|
||||
RCODE FSTableCursor::setupRange(
|
||||
F_Db * pDb,
|
||||
FLMUINT uiTableNum,
|
||||
FLMUINT64 ui64LowRowId,
|
||||
FLMUINT64 ui64HighRowId,
|
||||
FLMUINT64 * pui64LeafBlocksBetween, // [out] blocks between the stacks
|
||||
FLMUINT64 * pui64TotalRows, // [out]
|
||||
FLMBOOL * pbTotalsEstimated) // [out] set to TRUE when estimating.
|
||||
{
|
||||
RCODE rc = NE_SFLM_OK;
|
||||
F_Btree * pUntilBTree = NULL;
|
||||
|
||||
m_bAtBOF = TRUE;
|
||||
m_bAtEOF = FALSE;
|
||||
m_uiTableNum = uiTableNum;
|
||||
if (RC_BAD( rc = checkTransaction( pDb)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
m_ui64FromRowId = ui64LowRowId;
|
||||
m_ui64UntilRowId = ui64HighRowId;
|
||||
m_bSetup = TRUE;
|
||||
m_ui64CurRowId = 0;
|
||||
|
||||
// Want any of the counts back?
|
||||
|
||||
if (pui64LeafBlocksBetween || pui64TotalRows)
|
||||
{
|
||||
if (pui64LeafBlocksBetween)
|
||||
{
|
||||
*pui64LeafBlocksBetween = 0;
|
||||
}
|
||||
if (pui64TotalRows)
|
||||
{
|
||||
*pui64TotalRows = 0;
|
||||
}
|
||||
if (pbTotalsEstimated)
|
||||
{
|
||||
*pbTotalsEstimated = FALSE;
|
||||
}
|
||||
|
||||
// Position to the FROM and UNTIL key so we can get the stats.
|
||||
|
||||
if (RC_BAD( rc = setRowPosition( pDb, TRUE,
|
||||
m_ui64FromRowId, TRUE, NULL)))
|
||||
{
|
||||
if (rc == NE_SFLM_EOF_HIT)
|
||||
{
|
||||
rc = NE_SFLM_OK;
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// All nodes between FROM and UNTIL may be gone.
|
||||
|
||||
if (m_ui64CurRowId < m_ui64UntilRowId)
|
||||
{
|
||||
|
||||
// Get a btree object
|
||||
|
||||
if (RC_BAD( rc = gv_SFlmSysData.pBtPool->btpReserveBtree(
|
||||
&pUntilBTree)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
if (RC_BAD( rc = pUntilBTree->btOpen( pDb, m_pLFile,
|
||||
FALSE, FALSE)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// We better be able to at least find m_ui64CurRowId going
|
||||
// backward from m_ui64UntilRowId.
|
||||
|
||||
if (RC_BAD( rc = setRowPosition( pDb, FALSE,
|
||||
m_ui64UntilRowId, FALSE, pUntilBTree)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
if (RC_BAD( rc = m_pbTree->btComputeCounts( pUntilBTree,
|
||||
pui64LeafBlocksBetween, pui64TotalRows,
|
||||
pbTotalsEstimated,
|
||||
(pDb->m_pDatabase->m_uiBlockSize * 3) / 4)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
if (pUntilBTree)
|
||||
{
|
||||
gv_SFlmSysData.pBtPool->btpReturnBtree( &pUntilBTree);
|
||||
}
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Return the current row.
|
||||
****************************************************************************/
|
||||
RCODE FSTableCursor::currentRow(
|
||||
F_Db * pDb,
|
||||
F_Row ** ppRow,
|
||||
FLMUINT64 * pui64RowId
|
||||
)
|
||||
{
|
||||
RCODE rc = NE_SFLM_OK;
|
||||
|
||||
if (RC_BAD( rc = checkTransaction( pDb)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
if (m_bAtBOF)
|
||||
{
|
||||
rc = RC_SET( NE_SFLM_BOF_HIT);
|
||||
goto Exit;
|
||||
}
|
||||
if (m_bAtEOF)
|
||||
{
|
||||
rc = RC_SET( NE_SFLM_EOF_HIT);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
flmAssert( m_ui64CurRowId);
|
||||
|
||||
if (RC_BAD( rc = populateRow( pDb, ppRow, pui64RowId)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Fetch the current row. B-tree object is assumed to be positioned on
|
||||
the row.
|
||||
****************************************************************************/
|
||||
RCODE FSTableCursor::populateRow(
|
||||
F_Db * pDb,
|
||||
F_Row ** ppRow,
|
||||
FLMUINT64 * pui64RowId)
|
||||
{
|
||||
if (pui64RowId)
|
||||
{
|
||||
*pui64RowId = m_ui64CurRowId;
|
||||
}
|
||||
if (ppRow)
|
||||
{
|
||||
return( gv_SFlmSysData.pRowCacheMgr->retrieveRow( pDb, m_uiTableNum,
|
||||
m_ui64CurRowId, ppRow));
|
||||
}
|
||||
return( NE_SFLM_OK);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Make sure the current node is positioned in the range for the cursor.
|
||||
****************************************************************************/
|
||||
RCODE FSTableCursor::checkIfRowInRange(
|
||||
FLMBOOL bPositionForward)
|
||||
{
|
||||
RCODE rc = NE_SFLM_OK;
|
||||
|
||||
if (bPositionForward)
|
||||
{
|
||||
if (m_ui64CurRowId > m_ui64UntilRowId)
|
||||
{
|
||||
m_bAtEOF = TRUE;
|
||||
rc = RC_SET( NE_SFLM_EOF_HIT);
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_ui64CurRowId < m_ui64FromRowId)
|
||||
{
|
||||
m_bAtBOF = TRUE;
|
||||
rc = RC_SET( NE_SFLM_BOF_HIT);
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Position to and return the first row.
|
||||
****************************************************************************/
|
||||
RCODE FSTableCursor::firstRow(
|
||||
F_Db * pDb,
|
||||
F_Row ** ppRow,
|
||||
FLMUINT64 * pui64RowId)
|
||||
{
|
||||
RCODE rc = NE_SFLM_OK;
|
||||
|
||||
if( RC_BAD( rc = checkTransaction( pDb)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
flmAssert( m_bSetup);
|
||||
|
||||
// If at BOF and we have a node, then we are positioned on the first
|
||||
// node already - this would have happened if we had positioned to
|
||||
// calculate a cost. Rather than do the positioning again, we simply
|
||||
// set m_bAtBOF to FALSE.
|
||||
|
||||
if (m_bAtBOF && m_ui64CurRowId)
|
||||
{
|
||||
m_bAtBOF = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bAtBOF = m_bAtEOF = FALSE;
|
||||
if (RC_BAD( rc = setRowPosition( pDb, TRUE, m_ui64FromRowId,
|
||||
TRUE, NULL)))
|
||||
{
|
||||
if (rc == NE_SFLM_EOF_HIT)
|
||||
{
|
||||
m_bAtEOF = TRUE;
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the current row ID is within the FROM/UNTIL range.
|
||||
|
||||
if (RC_BAD( rc = checkIfRowInRange( TRUE)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
if (RC_BAD( rc = populateRow( pDb, ppRow, pui64RowId)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
if (RC_BAD( rc))
|
||||
{
|
||||
m_ui64CurRowId = 0;
|
||||
}
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Position to the next row.
|
||||
****************************************************************************/
|
||||
RCODE FSTableCursor::nextRow(
|
||||
F_Db * pDb,
|
||||
F_Row ** ppRow,
|
||||
FLMUINT64 * pui64RowId)
|
||||
{
|
||||
RCODE rc = NE_SFLM_OK;
|
||||
|
||||
if (RC_BAD( rc = checkTransaction( pDb)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
flmAssert( m_bSetup);
|
||||
if (m_bAtEOF)
|
||||
{
|
||||
rc = RC_SET( NE_SFLM_EOF_HIT);
|
||||
goto Exit;
|
||||
}
|
||||
if (m_bAtBOF || !m_ui64CurRowId)
|
||||
{
|
||||
rc = firstRow( pDb, ppRow, pui64RowId);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// Get the next row, if any
|
||||
|
||||
if (m_ui64CurRowId == FLM_MAX_UINT64)
|
||||
{
|
||||
rc = RC_SET( NE_SFLM_EOF_HIT);
|
||||
m_bAtEOF = TRUE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// See if we need to reset the b-tree object we are using
|
||||
|
||||
if (m_bTreeOpen &&
|
||||
(pDb != m_pDb || pDb->m_eTransType != m_eTransType))
|
||||
{
|
||||
closeBTree();
|
||||
}
|
||||
|
||||
// checkTransaction may have closed the B-tree, in which case we
|
||||
// need to reopen the b-tree and position to the next row.
|
||||
|
||||
if (!m_bTreeOpen)
|
||||
{
|
||||
if (RC_BAD( rc = setRowPosition( pDb, TRUE,
|
||||
m_ui64CurRowId + 1, TRUE, NULL)))
|
||||
{
|
||||
if (rc == NE_SFLM_EOF_HIT)
|
||||
{
|
||||
m_bAtEOF = TRUE;
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FLMBOOL bNeg;
|
||||
FLMUINT uiBytesProcessed;
|
||||
|
||||
// If we have a b-tree open, it is more efficient to call btNextEntry
|
||||
// directly. This may allow us to avoid repositioning down the b-tree.
|
||||
|
||||
if (RC_BAD( rc = m_pbTree->btNextEntry( m_ucCurRowKey,
|
||||
sizeof( m_ucCurRowKey),
|
||||
&m_uiCurRowKeyLen, NULL, NULL, NULL)))
|
||||
{
|
||||
if (rc == NE_SFLM_EOF_HIT)
|
||||
{
|
||||
m_bAtEOF = TRUE;
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
if (RC_BAD( rc = flmCollation2Number( m_uiCurRowKeyLen, m_ucCurRowKey,
|
||||
&m_ui64CurRowId, &bNeg, &uiBytesProcessed)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the current row ID is within the FROM/UNTIL range.
|
||||
|
||||
if (RC_BAD( rc = checkIfRowInRange( TRUE)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
if (RC_BAD( rc = populateRow( pDb, ppRow, pui64RowId)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
if (RC_BAD( rc))
|
||||
{
|
||||
m_ui64CurRowId = 0;
|
||||
}
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Position to and return the last row.
|
||||
****************************************************************************/
|
||||
RCODE FSTableCursor::lastRow(
|
||||
F_Db * pDb,
|
||||
F_Row ** ppRow,
|
||||
FLMUINT64 * pui64RowId)
|
||||
{
|
||||
RCODE rc = NE_SFLM_OK;
|
||||
|
||||
if( RC_BAD( rc = checkTransaction( pDb)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
flmAssert( m_bSetup);
|
||||
|
||||
// Position to the until node
|
||||
|
||||
m_bAtBOF = m_bAtEOF = FALSE;
|
||||
if (RC_BAD( rc = setRowPosition( pDb, FALSE, m_ui64UntilRowId,
|
||||
TRUE, NULL)))
|
||||
{
|
||||
if (rc == NE_SFLM_BOF_HIT)
|
||||
{
|
||||
m_bAtBOF = TRUE;
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// Make sure the current row ID is within the FROM/UNTIL range.
|
||||
|
||||
if (RC_BAD( rc = checkIfRowInRange( FALSE)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
if (RC_BAD( rc = populateRow( pDb, ppRow, pui64RowId)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
if (RC_BAD( rc))
|
||||
{
|
||||
m_ui64CurRowId = 0;
|
||||
}
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Position to the previous row.
|
||||
****************************************************************************/
|
||||
RCODE FSTableCursor::prevRow(
|
||||
F_Db * pDb,
|
||||
F_Row ** ppRow,
|
||||
FLMUINT64 * pui64RowId)
|
||||
{
|
||||
RCODE rc = NE_SFLM_OK;
|
||||
|
||||
if (RC_BAD( rc = checkTransaction( pDb)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
flmAssert( m_bSetup);
|
||||
if (m_bAtBOF)
|
||||
{
|
||||
rc = RC_SET( NE_SFLM_BOF_HIT);
|
||||
goto Exit;
|
||||
}
|
||||
if (m_bAtEOF || !m_ui64CurRowId)
|
||||
{
|
||||
rc = lastRow( pDb, ppRow, pui64RowId);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// Get the previous row, if any
|
||||
|
||||
if (m_ui64CurRowId == 1)
|
||||
{
|
||||
rc = RC_SET( NE_SFLM_BOF_HIT);
|
||||
m_bAtBOF = TRUE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// See if we need to reset the b-tree object we are using
|
||||
|
||||
if (m_bTreeOpen &&
|
||||
(pDb != m_pDb || pDb->m_eTransType != m_eTransType))
|
||||
{
|
||||
closeBTree();
|
||||
}
|
||||
|
||||
// checkTransaction may have closed the B-tree, in which case we
|
||||
// need to reopen the b-tree and position to the previous row.
|
||||
|
||||
if (!m_bTreeOpen)
|
||||
{
|
||||
if (RC_BAD( rc = setRowPosition( pDb, TRUE,
|
||||
m_ui64CurRowId - 1, TRUE, NULL)))
|
||||
{
|
||||
if (rc == NE_SFLM_BOF_HIT)
|
||||
{
|
||||
m_bAtBOF = TRUE;
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FLMBOOL bNeg;
|
||||
FLMUINT uiBytesProcessed;
|
||||
|
||||
// If we have a b-tree open, it is more efficient to call btPrevEntry
|
||||
// directly. This may allow us to avoid repositioning down the b-tree.
|
||||
|
||||
if (RC_BAD( rc = m_pbTree->btPrevEntry( m_ucCurRowKey,
|
||||
sizeof( m_ucCurRowKey),
|
||||
&m_uiCurRowKeyLen, NULL, NULL, NULL)))
|
||||
{
|
||||
if (rc == NE_SFLM_EOF_HIT)
|
||||
{
|
||||
m_bAtEOF = TRUE;
|
||||
}
|
||||
goto Exit;
|
||||
}
|
||||
if (RC_BAD( rc = flmCollation2Number( m_uiCurRowKeyLen, m_ucCurRowKey,
|
||||
&m_ui64CurRowId, &bNeg, &uiBytesProcessed)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the current row ID is within the FROM/UNTIL range.
|
||||
|
||||
if (RC_BAD( rc = checkIfRowInRange( FALSE)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
if (RC_BAD( rc = populateRow( pDb, ppRow, pui64RowId)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
||||
if (RC_BAD( rc))
|
||||
{
|
||||
m_ui64CurRowId = 0;
|
||||
}
|
||||
return( rc);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user