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:
dsandersoremutah
2006-05-26 23:17:49 +00:00
parent dc6cd8b9cb
commit 021073907f
82 changed files with 97516 additions and 0 deletions

887
sql/src/kybuild.cpp Normal file
View File

@@ -0,0 +1,887 @@
//------------------------------------------------------------------------------
// Desc: This file contains the main routines for building of index keys,
// and adding them to the database.
//
// Tabs: 3
//
// Copyright (c) 1990-1992, 1994-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"
#define STACK_DATA_BUF_SIZE 64
// Local function prototypes
FSTATIC RCODE kyAddRowIdToKey(
FLMUINT64 ui64RowId,
FLMBYTE * pucKeyBuf,
FLMUINT uiIDBufSize,
FLMUINT * puiIDLen);
/****************************************************************************
Desc: Append row ID to the key buffer.
****************************************************************************/
FSTATIC RCODE kyAddRowIdToKey(
FLMUINT64 ui64RowId,
FLMBYTE * pucKeyBuf,
FLMUINT uiIDBufSize,
FLMUINT * puiIDLen)
{
RCODE rc = NE_SFLM_OK;
FLMBYTE ucTmpSen [FLM_MAX_NUM_BUF_SIZE];
FLMBYTE * pucTmpSen;
// Put row ID into buffer. If there is room for at least nine
// bytes, we can encode the ID right into the buffer safely. Otherwise,
// we have to use a temporary buffer and see if there is room.
if (uiIDBufSize >= 9)
{
*puiIDLen = f_encodeSEN( ui64RowId, &pucKeyBuf);
}
else
{
pucTmpSen = &ucTmpSen [0];
*puiIDLen = f_encodeSEN( ui64RowId, &pucTmpSen);
if (*puiIDLen > uiIDBufSize)
{
rc = RC_SET( NE_SFLM_KEY_OVERFLOW);
goto Exit;
}
f_memcpy( pucKeyBuf, ucTmpSen, *puiIDLen);
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Add an index key to the buffers
****************************************************************************/
RCODE F_Db::addToKrefTbl(
FLMUINT uiKeyLen,
FLMUINT uiDataLen)
{
RCODE rc = NE_SFLM_OK;
KREF_ENTRY * pKref;
FLMUINT uiSizeNeeded;
FLMBYTE * pucDest;
// If the table is FULL, expand the table
if (m_uiKrefCount == m_uiKrefTblSize)
{
FLMUINT uiAllocSize;
FLMUINT uiOrigKrefTblSize = m_uiKrefTblSize;
if (m_uiKrefTblSize > 0x8000 / sizeof( KREF_ENTRY *))
{
m_uiKrefTblSize += 4096;
}
else
{
m_uiKrefTblSize *= 2;
}
uiAllocSize = m_uiKrefTblSize * sizeof( KREF_ENTRY *);
rc = f_realloc( uiAllocSize, &m_pKrefTbl);
if (RC_BAD(rc))
{
m_uiKrefTblSize = uiOrigKrefTblSize;
rc = RC_SET( NE_SFLM_MEM);
goto Exit;
}
}
// Allocate memory for the key's KREF and the key itself.
// We allocate one extra byte so we can zero terminate the key
// below. The extra zero character is to ensure that the compare
// in the qsort routine will work.
uiSizeNeeded = sizeof( KREF_ENTRY) + uiKeyLen + 1 + uiDataLen;
if (RC_BAD( rc = m_pKrefPool->poolAlloc( uiSizeNeeded,
(void **)&pKref)))
{
goto Exit;
}
m_pKrefTbl [ m_uiKrefCount++] = pKref;
m_uiTotalKrefBytes += uiSizeNeeded;
// Fill in all of the fields in the KREF structure.
pKref->ui16IxNum = (FLMUINT16)m_keyGenInfo.pIndex->uiIndexNum;
pKref->bDelete = m_keyGenInfo.bAddKeys ? FALSE : TRUE;
pKref->ui16KeyLen = (FLMUINT16)uiKeyLen;
pKref->uiSequence = m_uiKrefCount;
pKref->uiDataLen = uiDataLen;
pKref->pRow = m_keyGenInfo.pRow;
// Copy the key to just after the KREF structure.
pucDest = (FLMBYTE *)(&pKref [1]);
f_memcpy( pucDest, m_keyGenInfo.pucKeyBuf, uiKeyLen);
// Null terminate the key so compare in qsort will work.
pucDest [uiKeyLen] = 0;
if (uiDataLen)
{
f_memcpy( pucDest + uiKeyLen + 1, m_keyGenInfo.pucData, uiDataLen);
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Build the data part for a key.
Notes: This routine is recursive in nature. Will recurse the number of
data components defined in the index.
****************************************************************************/
RCODE F_Db::buildData(
ICD * pIcd,
FLMUINT uiDataComponent,
FLMUINT uiKeyLen,
FLMUINT uiDataLen)
{
RCODE rc = NE_SFLM_OK;
FLMUINT uiDataComponentLen;
FLMBYTE ucTmpSen [FLM_MAX_NUM_BUF_SIZE];
FLMBYTE * pucTmpSen;
FLMUINT uiSENLen;
FLMUINT uiIDLen;
F_COLUMN_ITEM * pColumnItem;
if ((pColumnItem = m_keyGenInfo.pRow->getColumn( pIcd->uiColumnNum)) != NULL)
{
uiDataComponentLen = pColumnItem->uiDataLen;
}
else
{
uiDataComponentLen = 0;
}
// Output the length of the data as a SEN value
pucTmpSen = &ucTmpSen [0];
uiSENLen = f_encodeSEN( uiDataComponentLen, &pucTmpSen);
if (uiDataComponentLen + uiSENLen + uiDataLen > m_keyGenInfo.uiDataBufSize)
{
FLMUINT uiNewSize = uiDataComponentLen + uiSENLen + uiDataLen + 512;
// Allocate the data buffer if it has not been allocated. Otherwise,
// realloc it.
if (!m_keyGenInfo.bDataBufAllocated)
{
FLMBYTE * pucNewData;
if (RC_BAD( rc = f_alloc( uiNewSize, &pucNewData)))
{
goto Exit;
}
if( uiDataLen)
{
f_memcpy( pucNewData, m_keyGenInfo.pucData, uiDataLen);
}
m_keyGenInfo.pucData = pucNewData;
m_keyGenInfo.bDataBufAllocated = TRUE;
}
else
{
// Reallocate the buffer.
if (RC_BAD( rc = f_realloc( uiNewSize, &m_keyGenInfo.pucData)))
{
goto Exit;
}
}
m_keyGenInfo.uiDataBufSize = uiNewSize;
}
f_memcpy( m_keyGenInfo.pucData + uiDataLen, ucTmpSen, uiSENLen);
if (uiDataComponentLen)
{
f_memcpy( m_keyGenInfo.pucData + uiDataLen + uiSENLen,
m_keyGenInfo.pRow->getColumnDataPtr( pIcd->uiColumnNum),
uiDataComponentLen);
}
// If this is the last data CDL, append IDs to the
// key and output the key and data to the KREF.
// Otherwise, recurse down.
if (uiDataComponent < m_keyGenInfo.pIndex->uiNumDataComponents)
{
if (RC_BAD( rc = buildData( pIcd + 1, uiDataComponent + 1, uiKeyLen,
uiDataLen + uiDataComponentLen + uiSENLen)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = kyAddRowIdToKey( m_keyGenInfo.pRow->m_ui64RowId,
&m_keyGenInfo.pucKeyBuf [uiKeyLen],
SFLM_MAX_KEY_SIZE - uiKeyLen, &uiIDLen)))
{
goto Exit;
}
if (RC_BAD( rc = addToKrefTbl( uiKeyLen + uiIDLen,
uiDataLen + uiDataComponentLen + uiSENLen)))
{
goto Exit;
}
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Finish the current key component. If there is a next one call
build keys. Otherwise, go on to doing data and context pieces.
****************************************************************************/
RCODE F_Db::finishKeyComponent(
ICD * pIcd,
FLMUINT uiKeyComponent,
FLMUINT uiKeyLen)
{
RCODE rc = NE_SFLM_OK;
FLMUINT uiIDLen;
if (uiKeyComponent < m_keyGenInfo.pIndex->uiNumKeyComponents)
{
flmAssert( m_keyGenInfo.bIsCompound);
if (RC_BAD( rc = buildKeys( pIcd + 1, uiKeyComponent + 1, uiKeyLen)))
{
goto Exit;
}
}
else
{
if (m_keyGenInfo.pIndex->pDataIcds)
{
if (RC_BAD( rc = buildData( m_keyGenInfo.pIndex->pDataIcds, 1, uiKeyLen, 0)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = kyAddRowIdToKey( m_keyGenInfo.pRow->m_ui64RowId,
&m_keyGenInfo.pucKeyBuf [uiKeyLen],
SFLM_MAX_KEY_SIZE - uiKeyLen, &uiIDLen)))
{
goto Exit;
}
if (RC_BAD( rc = addToKrefTbl( uiKeyLen + uiIDLen, 0)))
{
goto Exit;
}
}
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Generate the keys for a text component.
****************************************************************************/
RCODE F_Db::genTextKeyComponents(
F_COLUMN * pColumn,
ICD * pIcd,
FLMUINT uiKeyComponent,
FLMUINT uiKeyLen,
FLMBYTE ** ppucTmpBuf,
FLMUINT * puiTmpBufSize,
void ** ppvMark)
{
RCODE rc = NE_SFLM_OK;
FLMUINT uiNumChars;
FLMUINT uiStrBytes;
FLMUINT uiSubstrChars;
FLMUINT uiMeta;
FLMBOOL bEachWord = FALSE;
FLMBOOL bMetaphone = FALSE;
FLMBOOL bSubstring = FALSE;
FLMBOOL bWholeString = FALSE;
FLMBOOL bHadAtLeastOneString = FALSE;
FLMBOOL bDataTruncated;
FLMUINT uiSaveKeyLen;
FLMUINT uiElmLen;
FLMUINT uiKeyLenPos = uiKeyLen;
FLMUINT uiCompareRules = pIcd->uiCompareRules;
F_BufferIStream columnBufferIStream;
F_BufferIStream bufferIStream;
FLMBOOL bIsNull;
uiKeyLen += 2;
uiSaveKeyLen = uiKeyLen;
if (RC_BAD( rc = m_keyGenInfo.pRow->getTextIStream( this, pIcd->uiColumnNum,
&bIsNull, &columnBufferIStream, &uiNumChars)))
{
goto Exit;
}
if (bIsNull || !uiNumChars)
{
No_Strings:
// Save the key component length
UW2FBA( 0, &m_keyGenInfo.pucKeyBuf [uiKeyLenPos]);
rc = finishKeyComponent( pIcd, uiKeyComponent, uiKeyLen);
goto Exit;
}
if (pIcd->uiFlags & ICD_EACHWORD)
{
bEachWord = TRUE;
// OR in the compressing of spaces, because we only want to treat
// spaces as delimiters between words.
uiCompareRules |= FLM_COMP_COMPRESS_WHITESPACE;
}
else if (pIcd->uiFlags & ICD_METAPHONE)
{
bMetaphone = TRUE;
}
else if (pIcd->uiFlags & ICD_SUBSTRING)
{
bSubstring = TRUE;
}
else
{
bWholeString = TRUE;
}
// Loop on each word or substring in the value
for (;;)
{
uiKeyLen = uiSaveKeyLen;
bDataTruncated = FALSE;
if (bWholeString)
{
uiElmLen = SFLM_MAX_KEY_SIZE - uiKeyLen;
if( RC_BAD( rc = KYCollateValue( &m_keyGenInfo.pucKeyBuf [uiKeyLen],
&uiElmLen,
&columnBufferIStream, SFLM_STRING_TYPE,
pIcd->uiFlags, pIcd->uiCompareRules,
pIcd->uiLimit, NULL, NULL,
m_keyGenInfo.pIndex->uiLanguage,
FALSE, FALSE,
&bDataTruncated, NULL)))
{
goto Exit;
}
}
else if (bEachWord)
{
if (*ppucTmpBuf == NULL)
{
*ppvMark = m_tempPool.poolMark();
*puiTmpBufSize = (FLMUINT)SFLM_MAX_KEY_SIZE + 8;
if (RC_BAD( rc = m_tempPool.poolAlloc( *puiTmpBufSize,
(void **)ppucTmpBuf)))
{
goto Exit;
}
}
uiStrBytes = *puiTmpBufSize;
if( RC_BAD( rc = KYEachWordParse( &columnBufferIStream, &uiCompareRules,
pIcd->uiLimit, *ppucTmpBuf, &uiStrBytes)))
{
goto Exit;
}
if (!uiStrBytes)
{
if (!bHadAtLeastOneString)
{
goto No_Strings;
}
break;
}
if (RC_BAD( rc = bufferIStream.open(
(const char *)*ppucTmpBuf, uiStrBytes)))
{
goto Exit;
}
// Pass 0 for compare rules because KYEachWordParse will already
// have taken care of them - except for FLM_COMP_CASE_INSENSITIVE.
uiElmLen = SFLM_MAX_KEY_SIZE - uiKeyLen;
rc = KYCollateValue( &m_keyGenInfo.pucKeyBuf [uiKeyLen],
&uiElmLen,
&bufferIStream, SFLM_STRING_TYPE,
pIcd->uiFlags,
pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE,
pIcd->uiLimit,
NULL, NULL,
m_keyGenInfo.pIndex->uiLanguage,
FALSE, FALSE, &bDataTruncated, NULL);
bufferIStream.close();
if( RC_BAD( rc))
{
RC_UNEXPECTED_ASSERT( rc);
goto Exit;
}
bHadAtLeastOneString = TRUE;
}
else if (bMetaphone)
{
FLMBYTE ucStorageBuf[ FLM_MAX_NUM_BUF_SIZE];
FLMUINT uiStorageLen;
if( RC_BAD( rc = f_getNextMetaphone( &columnBufferIStream, &uiMeta)))
{
if( rc != NE_SFLM_EOF_HIT)
{
goto Exit;
}
rc = NE_SFLM_OK;
if (!bHadAtLeastOneString)
{
goto No_Strings;
}
break;
}
uiStorageLen = FLM_MAX_NUM_BUF_SIZE;
if( RC_BAD( rc = flmNumber64ToStorage( uiMeta,
&uiStorageLen, ucStorageBuf, FALSE, FALSE)))
{
goto Exit;
}
if (RC_BAD( rc = bufferIStream.open(
(const char *)ucStorageBuf, uiStorageLen)))
{
goto Exit;
}
// Pass 0 for compare rules - only applies to strings.
uiElmLen = SFLM_MAX_KEY_SIZE - uiKeyLen;
rc = KYCollateValue( &m_keyGenInfo.pucKeyBuf [uiKeyLen],
&uiElmLen,
&bufferIStream, SFLM_NUMBER_TYPE,
pIcd->uiFlags, 0,
pIcd->uiLimit,
NULL, NULL,
m_keyGenInfo.pIndex->uiLanguage,
FALSE, FALSE, NULL, NULL);
bufferIStream.close();
if( RC_BAD( rc))
{
RC_UNEXPECTED_ASSERT( rc);
goto Exit;
}
bHadAtLeastOneString = TRUE;
}
else
{
flmAssert( bSubstring);
if (*ppucTmpBuf == NULL)
{
*ppvMark = m_tempPool.poolMark();
*puiTmpBufSize = (FLMUINT)SFLM_MAX_KEY_SIZE + 8;
if (RC_BAD( rc = m_tempPool.poolAlloc( *puiTmpBufSize,
(void **)ppucTmpBuf)))
{
goto Exit;
}
}
uiStrBytes = *puiTmpBufSize;
if( RC_BAD( rc = KYSubstringParse( &columnBufferIStream, &uiCompareRules,
pIcd->uiLimit, *ppucTmpBuf, &uiStrBytes, &uiSubstrChars)))
{
goto Exit;
}
if (!uiStrBytes)
{
if (!bHadAtLeastOneString)
{
goto No_Strings;
}
break;
}
if (bHadAtLeastOneString && uiSubstrChars == 1 && !m_keyGenInfo.bIsAsia)
{
break;
}
if (RC_BAD( rc = bufferIStream.open(
(const char *)*ppucTmpBuf, uiStrBytes)))
{
goto Exit;
}
// Pass 0 for compare rules, because KYSubstringParse has already
// taken care of them, except for FLM_COMP_CASE_INSENSITIVE
uiElmLen = SFLM_MAX_KEY_SIZE - uiKeyLen;
rc = KYCollateValue( &m_keyGenInfo.pucKeyBuf [uiKeyLen],
&uiElmLen,
&bufferIStream, SFLM_STRING_TYPE,
pIcd->uiFlags,
pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE,
pIcd->uiLimit,
NULL, NULL,
m_keyGenInfo.pIndex->uiLanguage,
bHadAtLeastOneString ? FALSE : TRUE, FALSE,
&bDataTruncated, NULL);
bufferIStream.close();
if( RC_BAD( rc))
{
RC_UNEXPECTED_ASSERT( rc);
goto Exit;
}
bHadAtLeastOneString = TRUE;
}
uiKeyLen += uiElmLen;
// Save the key component length
if (!bDataTruncated)
{
UW2FBA( (FLMUINT16)(uiElmLen),
&m_keyGenInfo.pucKeyBuf [uiKeyLenPos]);
}
else
{
UW2FBA( (FLMUINT16)(uiElmLen | TRUNCATED_FLAG),
&m_keyGenInfo.pucKeyBuf [uiKeyLenPos]);
}
if (RC_BAD( rc = finishKeyComponent( pIcd, uiKeyComponent, uiKeyLen)))
{
goto Exit;
}
if (bWholeString)
{
break;
}
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Generate the keys for other data types besides text.
****************************************************************************/
RCODE F_Db::genOtherKeyComponent(
F_COLUMN * pColumn,
ICD * pIcd,
FLMUINT uiKeyComponent,
FLMUINT uiKeyLen)
{
RCODE rc = NE_SFLM_OK;
FLMUINT uiElmLen;
FLMUINT uiKeyLenPos = uiKeyLen;
FLMBOOL bDataTruncated;
FLMBOOL bIsNull;
F_BufferIStream columnBufferIStream;
eDataType eDataTyp;
FLMUINT uiDataLength;
uiKeyLen += 2;
if (pIcd->uiFlags & ICD_PRESENCE)
{
f_UINT32ToBigEndian( (FLMUINT32)pIcd->uiColumnNum, &m_keyGenInfo.pucKeyBuf [uiKeyLen]);
uiKeyLen += 4;
// Save the key component length.
UW2FBA( 4, &m_keyGenInfo.pucKeyBuf [uiKeyLenPos]);
}
else
{
if (RC_BAD( rc = m_keyGenInfo.pRow->getIStream( this,
pIcd->uiColumnNum,
&bIsNull, &columnBufferIStream,
&eDataTyp, &uiDataLength)))
{
goto Exit;
}
if (bIsNull || !columnBufferIStream.remainingSize())
{
// Save the key component length
UW2FBA( 0, &m_keyGenInfo.pucKeyBuf [uiKeyLenPos]);
rc = finishKeyComponent( pIcd, uiKeyComponent, uiKeyLen);
goto Exit;
}
// Compute number of bytes left
uiElmLen = SFLM_MAX_KEY_SIZE - uiKeyLen;
bDataTruncated = FALSE;
// Pass zero for compare rules - these are not strings.
if( RC_BAD( rc = KYCollateValue( &m_keyGenInfo.pucKeyBuf [uiKeyLen],
&uiElmLen, &columnBufferIStream,
eDataTyp, pIcd->uiFlags,
0, pIcd->uiLimit, NULL, NULL,
m_keyGenInfo.pIndex->uiLanguage,
FALSE, FALSE,
&bDataTruncated, NULL)))
{
goto Exit;
}
uiKeyLen += uiElmLen;
// Save the key component length.
if (!bDataTruncated)
{
UW2FBA( (FLMUINT16)(uiElmLen),
&m_keyGenInfo.pucKeyBuf [uiKeyLenPos]);
}
else
{
UW2FBA( (FLMUINT16)(uiElmLen | TRUNCATED_FLAG),
&m_keyGenInfo.pucKeyBuf [uiKeyLenPos]);
}
}
if (RC_BAD( rc = finishKeyComponent( pIcd, uiKeyComponent, uiKeyLen)))
{
goto Exit;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Build all compound keys from the CDL table.
Notes: This routine is recursive in nature. Will recurse the number of
key components defined in the index.
****************************************************************************/
RCODE F_Db::buildKeys(
ICD * pIcd,
FLMUINT uiKeyComponent,
FLMUINT uiKeyLen)
{
RCODE rc = NE_SFLM_OK;
FLMBYTE * pucTmpBuf = NULL;
void * pvMark = NULL;
FLMUINT uiTmpBufSize = 0;
F_COLUMN * pColumn = m_pDict->getColumn( m_keyGenInfo.pTable,
pIcd->uiColumnNum);
flmAssert( m_keyGenInfo.bIsCompound || uiKeyComponent == 1);
// Generate the key component
if (pColumn->eDataTyp == SFLM_STRING_TYPE && !(pIcd->uiFlags & ICD_PRESENCE))
{
if (RC_BAD( rc = genTextKeyComponents( pColumn, pIcd, uiKeyComponent, uiKeyLen,
&pucTmpBuf, &uiTmpBufSize, &pvMark)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = genOtherKeyComponent( pColumn, pIcd, uiKeyComponent, uiKeyLen)))
{
goto Exit;
}
}
Exit:
if (pvMark)
{
m_tempPool.poolReset( pvMark);
}
return( rc);
}
/****************************************************************************
Desc: Build all keys from combinations of CDLs. Add keys to KREF table.
****************************************************************************/
RCODE F_Db::buildKeys(
F_INDEX * pIndex,
F_TABLE * pTable,
F_Row * pOldRow,
F_Row * pNewRow)
{
RCODE rc = NE_SFLM_OK;
FLMBYTE ucDataBuf [STACK_DATA_BUF_SIZE];
if (RC_BAD( rc = krefCntrlCheck()))
{
goto Exit;
}
// Build all of the keys
m_keyGenInfo.pTable = pTable;
m_keyGenInfo.pIndex = pIndex;
m_keyGenInfo.bIsAsia = (FLMBOOL)(pIndex->uiLanguage >= FLM_FIRST_DBCS_LANG &&
pIndex->uiLanguage <= FLM_LAST_DBCS_LANG)
? TRUE
: FALSE;
m_keyGenInfo.bIsCompound = pIndex->uiNumKeyComponents > 1 ? TRUE : FALSE;
m_keyGenInfo.pucKeyBuf = m_pucKrefKeyBuf;
m_keyGenInfo.pucData = &ucDataBuf [0];
m_keyGenInfo.uiDataBufSize = sizeof( ucDataBuf);
m_keyGenInfo.bDataBufAllocated = FALSE;
// Build the keys for the old row.
if (pOldRow)
{
m_keyGenInfo.pRow = pOldRow;
m_keyGenInfo.bAddKeys = FALSE;
if (RC_BAD( rc = buildKeys( pIndex->pKeyIcds, 1, 0)))
{
goto Exit;
}
}
// Build all of the keys for the new row
if (pNewRow)
{
m_keyGenInfo.pRow = pNewRow;
m_keyGenInfo.bAddKeys = TRUE;
if (RC_BAD( rc = buildKeys( pIndex->pKeyIcds, 1, 0)))
{
goto Exit;
}
}
// Commit keys if we are over the limit.
if( isKrefOverThreshold())
{
processDupKeys( pIndex);
if (RC_BAD( rc = keysCommit( FALSE, FALSE)))
{
goto Exit;
}
}
Exit:
if (m_keyGenInfo.bDataBufAllocated)
{
f_free( &m_keyGenInfo.pucData);
m_keyGenInfo.bDataBufAllocated = FALSE;
}
return( rc);
}
/****************************************************************************
Desc: Routine that is called when inserting, modifying, or removing a row
from a table.
****************************************************************************/
RCODE F_Db::updateIndexKeys(
FLMUINT uiTableNum,
F_Row * pOldRow,
F_Row * pNewRow)
{
RCODE rc = NE_SFLM_OK;
F_TABLE * pTable = m_pDict->getTable( uiTableNum);
F_INDEX * pIndex;
FLMUINT uiIndexNum;
FLMUINT64 ui64RowId;
if (pOldRow)
{
ui64RowId = pOldRow->getRowId();
// New row, if any, should have same row ID as old row.
flmAssert( !pNewRow || pNewRow->getRowId() == ui64RowId);
}
else
{
flmAssert( pNewRow);
ui64RowId = pNewRow->getRowId();
}
//VISIT - Don't call this routine on a modify operation if none of the columns
//that were modified are indexed. The higher level routine can make this check.
// Go through each index on this table.
uiIndexNum = pTable->uiFirstIndexNum;
while (uiIndexNum)
{
pIndex = m_pDict->getIndex( uiIndexNum);
if (!(pIndex->uiFlags & (IXD_OFFLINE | IXD_SUSPENDED)) ||
ui64RowId <= pIndex->ui64LastRowIndexed)
{
if (RC_BAD( rc = buildKeys( pIndex, pTable, pOldRow, pNewRow)))
{
goto Exit;
}
}
uiIndexNum = pIndex->uiNextIndexNum;
}
Exit:
return( rc);
}