git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@491 0109f412-320b-0410-ab79-c3e0c5ffbbe6
3780 lines
88 KiB
C++
3780 lines
88 KiB
C++
//------------------------------------------------------------------------------
|
|
// Desc: Routines to access anything in the dictionary
|
|
//
|
|
// Tabs: 3
|
|
//
|
|
// Copyright (c) 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"
|
|
|
|
// Local function prototypes
|
|
|
|
FSTATIC FLMBOOL validBooleanValue(
|
|
const char * pszValue,
|
|
FLMBOOL * pbTrue);
|
|
|
|
FSTATIC FLMBOOL validDataType(
|
|
const char * pszDataType,
|
|
eDataType * peDataTyp);
|
|
|
|
FSTATIC FLMBOOL validEncAlgorithm(
|
|
const char * pszEncAlgorithm,
|
|
eEncAlgorithm * peEncAlg);
|
|
|
|
FSTATIC FLMBOOL validEncKeySize(
|
|
eEncAlgorithm eEncAlg,
|
|
FLMUINT uiKeySize);
|
|
|
|
FSTATIC void sortNameTbl(
|
|
NAME_INFO * pNameInfoTbl,
|
|
FLMUINT uiLowerBounds,
|
|
FLMUINT uiUpperBounds,
|
|
FLMBOOL * pbDuplicateNames);
|
|
|
|
FSTATIC FLMBOOL validIndexState(
|
|
const char * pszIndexState,
|
|
FLMUINT * puiFlags);
|
|
|
|
FSTATIC FLMBOOL validIndexOnValue(
|
|
const char * pszIndexOn,
|
|
FLMUINT * puiFlags);
|
|
|
|
FSTATIC FLMBOOL validCompareRulesValue(
|
|
char * pszCompareRules,
|
|
FLMUINT * puiCompareRules);
|
|
|
|
/***************************************************************************
|
|
Desc: Constructor
|
|
***************************************************************************/
|
|
F_Dict::F_Dict()
|
|
{
|
|
m_pNext = NULL;
|
|
m_pPrev = NULL;
|
|
m_pDatabase = NULL;
|
|
m_uiDictSeq = 0;
|
|
m_dictPool.poolInit( 1024);
|
|
|
|
m_pTableTbl = NULL;
|
|
m_uiTableTblSize = 0;
|
|
m_uiHighestTableNum = 0;
|
|
m_pTableNames = NULL;
|
|
|
|
m_pIndexTbl = NULL;
|
|
m_uiIndexTblSize = 0;
|
|
m_uiHighestIndexNum = 0;
|
|
m_pIndexNames = NULL;
|
|
|
|
m_pEncDefTbl = NULL;
|
|
m_uiEncDefTblSize = 0;
|
|
m_uiHighestEncDefNum = 0;
|
|
m_pEncDefNames = NULL;
|
|
|
|
// Whenever an F_Dict is allocated, it is always immediately
|
|
// used by an F_Db.
|
|
|
|
m_uiUseCount = 1;
|
|
}
|
|
|
|
/***************************************************************************
|
|
Desc: Destructor
|
|
***************************************************************************/
|
|
F_Dict::~F_Dict()
|
|
{
|
|
resetDict();
|
|
}
|
|
|
|
/***************************************************************************
|
|
Desc: Clear the dictionary object so it can be reused. NOTE: This function
|
|
also needs to do all the freeing up that the destructor would do
|
|
because it is called by the destructor.
|
|
***************************************************************************/
|
|
void F_Dict::resetDict( void)
|
|
{
|
|
FLMUINT uiLoop;
|
|
|
|
for (uiLoop = 0; uiLoop < m_uiHighestTableNum; uiLoop++)
|
|
{
|
|
if (m_pTableTbl [uiLoop].uiTableNum &&
|
|
m_pTableTbl [uiLoop].pColumnNames)
|
|
{
|
|
m_pTableTbl [uiLoop].pColumnNames->Release();
|
|
}
|
|
}
|
|
|
|
f_free( &m_pTableTbl);
|
|
m_uiTableTblSize = 0;
|
|
m_uiHighestTableNum = 0;
|
|
if (m_pTableNames)
|
|
{
|
|
m_pTableNames->Release();
|
|
m_pTableNames = NULL;
|
|
}
|
|
|
|
f_free( &m_pIndexTbl);
|
|
m_uiIndexTblSize = 0;
|
|
m_uiHighestIndexNum = 0;
|
|
if (m_pIndexNames)
|
|
{
|
|
m_pIndexNames->Release();
|
|
m_pIndexNames = NULL;
|
|
}
|
|
|
|
for (uiLoop = 0; uiLoop < m_uiHighestEncDefNum; uiLoop++)
|
|
{
|
|
if (m_pEncDefTbl [uiLoop].uiEncDefNum &&
|
|
m_pEncDefTbl [uiLoop].pCcs)
|
|
{
|
|
m_pEncDefTbl[ uiLoop].pCcs->Release();
|
|
}
|
|
}
|
|
f_free( &m_pEncDefTbl);
|
|
m_uiEncDefTblSize = 0;
|
|
m_uiHighestEncDefNum = 0;
|
|
if (m_pEncDefNames)
|
|
{
|
|
m_pEncDefNames->Release();
|
|
m_pEncDefNames = NULL;
|
|
}
|
|
|
|
m_dictPool.poolFree();
|
|
m_dictPool.poolInit( 1024);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Desc: Get the table given a table name.
|
|
***************************************************************************/
|
|
RCODE F_Dict::getTable(
|
|
const char * pszTableName,
|
|
F_TABLE ** ppTable,
|
|
FLMBOOL bOfflineOk)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_TABLE * pTable;
|
|
|
|
if ((pTable = findTable( pszTableName)) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_BAD_TABLE);
|
|
goto Exit;
|
|
}
|
|
|
|
// If the table is encrypted, and we are in limited mode, then we must
|
|
// treat is as an offline table.
|
|
|
|
if (pTable->lfInfo.uiEncDefNum && m_pDatabase &&
|
|
m_pDatabase->inLimitedMode() && !bOfflineOk)
|
|
{
|
|
rc = RC_SET( NE_SFLM_TABLE_OFFLINE);
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (ppTable)
|
|
{
|
|
*ppTable = pTable;
|
|
}
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Desc: Get the index given an index name.
|
|
***************************************************************************/
|
|
RCODE F_Dict::getIndex(
|
|
const char * pszIndexName,
|
|
F_INDEX ** ppIndex,
|
|
FLMBOOL bOfflineOk)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_INDEX * pIndex;
|
|
|
|
if ((pIndex = findIndex( pszIndexName)) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_BAD_IX);
|
|
goto Exit;
|
|
}
|
|
|
|
// If the index is suspended the IXD_OFFLINE flag
|
|
// will be set, so it is sufficient to just test
|
|
// the IXD_OFFLINE for both suspended and offline
|
|
// conditions.
|
|
|
|
if ((pIndex->uiFlags & IXD_OFFLINE) && !bOfflineOk)
|
|
{
|
|
rc = RC_SET( NE_SFLM_INDEX_OFFLINE);
|
|
goto Exit;
|
|
}
|
|
|
|
// An encrypted index is offline if we are in limited mode.
|
|
|
|
if (pIndex->lfInfo.uiEncDefNum && m_pDatabase &&
|
|
m_pDatabase->inLimitedMode() && !bOfflineOk)
|
|
{
|
|
rc = RC_SET( NE_SFLM_INDEX_OFFLINE);
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (ppIndex)
|
|
{
|
|
*ppIndex = pIndex;
|
|
}
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Link the dictionary to an F_Database object
|
|
NOTE: This routine assumes the global mutex is locked.
|
|
****************************************************************************/
|
|
void F_Dict::linkToDatabase(
|
|
F_Database * pDatabase)
|
|
{
|
|
if ((m_pNext = pDatabase->m_pDictList) != NULL)
|
|
{
|
|
m_uiDictSeq = m_pNext->m_uiDictSeq + 1;
|
|
m_pNext->m_pPrev = this;
|
|
}
|
|
else
|
|
{
|
|
m_uiDictSeq = 1;
|
|
}
|
|
pDatabase->m_pDictList = this;
|
|
m_pDatabase = pDatabase;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Unlink the dictionary from its F_Database object
|
|
NOTE: This routine assumes the database mutex is locked.
|
|
****************************************************************************/
|
|
void F_Dict::unlinkFromDatabase( void)
|
|
{
|
|
|
|
// Unlink the local dictionary from its database - if it is connected
|
|
// to one.
|
|
|
|
if (m_pDatabase)
|
|
{
|
|
if (m_pPrev)
|
|
{
|
|
m_pPrev->m_pNext = m_pNext;
|
|
}
|
|
else
|
|
{
|
|
m_pDatabase->m_pDictList = m_pNext;
|
|
}
|
|
if (m_pNext)
|
|
{
|
|
m_pNext->m_pPrev = m_pPrev;
|
|
}
|
|
}
|
|
|
|
// Free the local dictionary and its associated tables.
|
|
|
|
Release();
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Copies an encryption def (F_ENCDEF)
|
|
****************************************************************************/
|
|
RCODE F_Dict::copyEncDef(
|
|
F_ENCDEF * pDestEncDef,
|
|
F_ENCDEF * pSrcEncDef)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
|
|
f_memcpy( pDestEncDef, pSrcEncDef, sizeof( F_ENCDEF));
|
|
if (RC_BAD( rc = m_pEncDefNames->copyName( pSrcEncDef->pszEncDefName,
|
|
pDestEncDef->uiEncDefNum, &pDestEncDef->pszEncDefName,
|
|
&m_dictPool)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pDestEncDef->pCcs->AddRef();
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Copies a table column. NOTE: This routine assumes that
|
|
the encryption definitions have already been copied.
|
|
****************************************************************************/
|
|
RCODE F_Dict::copyColumn(
|
|
F_NameTable * pDestColumnNameTable,
|
|
F_COLUMN * pDestColumn,
|
|
F_COLUMN * pSrcColumn)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
|
|
f_memcpy( pDestColumn, pSrcColumn, sizeof( F_COLUMN));
|
|
if (RC_BAD( rc = pDestColumnNameTable->copyName( pSrcColumn->pszColumnName,
|
|
pDestColumn->uiColumnNum, &pDestColumn->pszColumnName,
|
|
&m_dictPool)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// ICDs will be fixed up and set when the indexes are copied later on.
|
|
|
|
pDestColumn->pFirstIcd = NULL;
|
|
pDestColumn->pFirstDataIcd = NULL;
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Copies a table and all of its columns. NOTE: This routine assumes that
|
|
the encryption definitions have already been copied.
|
|
****************************************************************************/
|
|
RCODE F_Dict::copyTable(
|
|
F_TABLE * pDestTable,
|
|
F_TABLE * pSrcTable)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
FLMUINT uiLoop;
|
|
F_COLUMN * pSrcColumn;
|
|
F_COLUMN * pDestColumn;
|
|
|
|
f_memcpy( pDestTable, pSrcTable, sizeof( F_TABLE));
|
|
|
|
// Add the table name to the table name table.
|
|
|
|
if (RC_BAD( rc = m_pTableNames->copyName( pSrcTable->pszTableName,
|
|
pDestTable->uiTableNum, &pDestTable->pszTableName,
|
|
&m_dictPool)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Allocate a name table for the column names.
|
|
|
|
if ((pDestTable->pColumnNames = f_new F_NameTable) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = f_alloc( sizeof( NAME_INFO) * pSrcTable->pColumnNames->m_uiNumNames,
|
|
&pDestTable->pColumnNames->m_pNames)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pDestTable->pColumnNames->m_uiTblSize = pSrcTable->pColumnNames->m_uiNumNames;
|
|
|
|
// Copy the columns. - There is always at least one column, so no
|
|
// need to check for a column count.
|
|
|
|
if (RC_BAD( rc = m_dictPool.poolAlloc( sizeof( F_COLUMN) * pSrcTable->uiNumColumns,
|
|
(void **)&pDestTable->pColumns)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
for (uiLoop = 0, pSrcColumn = pSrcTable->pColumns, pDestColumn = pDestTable->pColumns;
|
|
uiLoop < pSrcTable->uiNumColumns;
|
|
uiLoop++, pSrcColumn++, pDestColumn++)
|
|
{
|
|
if (RC_BAD( rc = copyColumn( pDestTable->pColumnNames, pDestColumn, pSrcColumn)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Copies an index and all of its ICDs. NOTE: This routine assumes that
|
|
the tables and columns have already been copied.
|
|
****************************************************************************/
|
|
RCODE F_Dict::copyIndex(
|
|
F_INDEX * pDestIndex,
|
|
F_INDEX * pSrcIndex)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
FLMUINT uiTotalIcds;
|
|
ICD * pIcd;
|
|
F_COLUMN * pColumn;
|
|
F_TABLE * pDestTable;
|
|
FLMUINT uiLoop;
|
|
|
|
f_memcpy( pDestIndex, pSrcIndex, sizeof( F_INDEX));
|
|
|
|
// Tables should already have been set up, and pSrcIndex->uiTableNum
|
|
// better be referencing a valid table!
|
|
|
|
pDestTable = getTable( pDestIndex->uiTableNum);
|
|
flmAssert( pDestTable);
|
|
|
|
// Add the index name to the index name table.
|
|
|
|
if (RC_BAD( rc = m_pIndexNames->copyName( pSrcIndex->pszIndexName,
|
|
pDestIndex->uiIndexNum, &pDestIndex->pszIndexName,
|
|
&m_dictPool)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Allocate space for the ICDs.
|
|
|
|
uiTotalIcds = pDestIndex->uiNumKeyComponents + pDestIndex->uiNumDataComponents;
|
|
if (RC_BAD( rc = m_dictPool.poolAlloc( sizeof( ICD) * uiTotalIcds,
|
|
(void **)&pDestIndex->pKeyIcds)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
f_memcpy( pDestIndex->pKeyIcds, pSrcIndex->pKeyIcds,
|
|
sizeof( ICD) * pDestIndex->uiNumKeyComponents);
|
|
if (pDestIndex->pDataIcds)
|
|
{
|
|
pDestIndex->pDataIcds = pDestIndex->pKeyIcds + pDestIndex->uiNumKeyComponents;
|
|
f_memcpy( pDestIndex->pDataIcds, pSrcIndex->pDataIcds,
|
|
sizeof( ICD) * pDestIndex->uiNumDataComponents);
|
|
}
|
|
|
|
// Fixup the index and column pointers in the destination ICD.
|
|
|
|
for (uiLoop = 0, pIcd = pDestIndex->pKeyIcds;
|
|
uiLoop < pDestIndex->uiNumKeyComponents;
|
|
uiLoop++, pIcd++)
|
|
{
|
|
|
|
// Columns should already be set up and column number better be
|
|
// referencing a valid column!
|
|
|
|
pColumn = getColumn( pDestTable, pIcd->uiColumnNum);
|
|
flmAssert( pColumn);
|
|
|
|
pIcd->pNextInChain = pColumn->pFirstIcd;
|
|
pColumn->pFirstIcd = pIcd->pNextInChain;
|
|
}
|
|
for (uiLoop = 0, pIcd = pDestIndex->pDataIcds;
|
|
uiLoop < pDestIndex->uiNumDataComponents;
|
|
uiLoop++, pIcd++)
|
|
{
|
|
|
|
// Columns should already be set up and column number better be
|
|
// referencing a valid column!
|
|
|
|
pColumn = getColumn( pDestTable, pIcd->uiColumnNum);
|
|
flmAssert( pColumn);
|
|
pIcd->pNextInDataChain = pColumn->pFirstDataIcd;
|
|
pColumn->pFirstDataIcd = pIcd->pNextInDataChain;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Clones a dictionary from another one.
|
|
****************************************************************************/
|
|
RCODE F_Dict::cloneDict(
|
|
F_Dict * pSrcDict)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_ENCDEF * pSrcEncDef;
|
|
F_ENCDEF * pDestEncDef;
|
|
F_TABLE * pSrcTable;
|
|
F_TABLE * pDestTable;
|
|
F_INDEX * pSrcIndex;
|
|
F_INDEX * pDestIndex;
|
|
FLMUINT uiLoop;
|
|
|
|
resetDict();
|
|
|
|
// Set up all of the name tables to be large enough to hold the
|
|
// names in the source dictionary.
|
|
|
|
if (pSrcDict->m_pTableNames)
|
|
{
|
|
if ((m_pTableNames = f_new F_NameTable) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = f_alloc( sizeof( NAME_INFO) * pSrcDict->m_pTableNames->m_uiNumNames,
|
|
&m_pTableNames->m_pNames)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
m_pTableNames->m_uiTblSize = pSrcDict->m_pTableNames->m_uiNumNames;
|
|
}
|
|
|
|
if (pSrcDict->m_pIndexNames)
|
|
{
|
|
if ((m_pIndexNames = f_new F_NameTable) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = f_alloc( sizeof( NAME_INFO) * pSrcDict->m_pIndexNames->m_uiNumNames,
|
|
&m_pIndexNames->m_pNames)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
m_pIndexNames->m_uiTblSize = pSrcDict->m_pIndexNames->m_uiNumNames;
|
|
}
|
|
|
|
if (pSrcDict->m_pEncDefNames)
|
|
{
|
|
if ((m_pEncDefNames = f_new F_NameTable) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = f_alloc( sizeof( NAME_INFO) * pSrcDict->m_pEncDefNames->m_uiNumNames,
|
|
&m_pEncDefNames->m_pNames)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
m_pEncDefNames->m_uiTblSize = pSrcDict->m_pEncDefNames->m_uiNumNames;
|
|
}
|
|
|
|
// Copy encryption definitions first.
|
|
|
|
if (pSrcDict->m_uiHighestEncDefNum)
|
|
{
|
|
if (RC_BAD( rc = f_alloc( sizeof( F_ENCDEF) * pSrcDict->m_uiHighestEncDefNum,
|
|
&m_pEncDefTbl)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
m_uiEncDefTblSize = m_uiHighestEncDefNum = pSrcDict->m_uiHighestEncDefNum;
|
|
|
|
for (uiLoop = 0, pSrcEncDef = pSrcDict->m_pEncDefTbl, pDestEncDef = m_pEncDefTbl;
|
|
uiLoop < m_uiHighestEncDefNum;
|
|
uiLoop++, pSrcEncDef++, pDestEncDef++)
|
|
{
|
|
if (RC_BAD( rc = copyEncDef( pDestEncDef, pSrcEncDef)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_uiEncDefTblSize = 0;
|
|
m_uiHighestEncDefNum = 0;
|
|
}
|
|
|
|
// Copy tables and columns. - There is always at least one table, so no
|
|
// need to check for a table count.
|
|
|
|
if (RC_BAD( rc = f_alloc( sizeof( F_TABLE) * pSrcDict->m_uiHighestTableNum,
|
|
&m_pTableTbl)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
m_uiTableTblSize = m_uiHighestTableNum = pSrcDict->m_uiHighestTableNum;
|
|
|
|
for (uiLoop = 0, pSrcTable = pSrcDict->m_pTableTbl, pDestTable = m_pTableTbl;
|
|
uiLoop < m_uiHighestTableNum;
|
|
uiLoop++, pSrcTable++, pDestTable++)
|
|
{
|
|
if (RC_BAD( rc = copyTable( pDestTable, pSrcTable)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Copy indexes. - there is always at least one index, because we have
|
|
// internal indexes - so no need to check for an index count.
|
|
|
|
if (RC_BAD( rc = f_alloc( sizeof( F_ENCDEF) * pSrcDict->m_uiHighestIndexNum,
|
|
&m_pIndexTbl)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
m_uiIndexTblSize = m_uiHighestIndexNum = pSrcDict->m_uiHighestIndexNum;
|
|
|
|
for (uiLoop = 0, pSrcIndex = pSrcDict->m_pIndexTbl, pDestIndex = m_pIndexTbl;
|
|
uiLoop < m_uiHighestIndexNum;
|
|
uiLoop++, pSrcIndex++, pDestIndex++)
|
|
{
|
|
if (RC_BAD( rc = copyIndex( pDestIndex, pSrcIndex)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: See if the read-only value is valid.
|
|
****************************************************************************/
|
|
FSTATIC FLMBOOL validBooleanValue(
|
|
const char * pszValue,
|
|
FLMBOOL * pbTrue)
|
|
{
|
|
if (f_stricmp( pszValue, "yes") == 0 ||
|
|
f_stricmp( pszValue, "1") == 0 ||
|
|
f_stricmp( pszValue, "enabled") == 0 ||
|
|
f_stricmp( pszValue, "on") == 0)
|
|
{
|
|
*pbTrue = TRUE;
|
|
return( TRUE);
|
|
}
|
|
else if (f_stricmp( pszValue, "no") == 0 ||
|
|
f_stricmp( pszValue, "0") == 0 ||
|
|
f_stricmp( pszValue, "disabled") == 0 ||
|
|
f_stricmp( pszValue, "off") == 0)
|
|
{
|
|
*pbTrue = FALSE;
|
|
return( TRUE);
|
|
}
|
|
return( FALSE);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Desc: Maps a string to an element or attribute data type.
|
|
***************************************************************************/
|
|
FSTATIC FLMBOOL validDataType(
|
|
const char * pszDataType,
|
|
eDataType * peDataTyp)
|
|
{
|
|
if (f_stricmp( pszDataType, SFLM_STRING_OPTION_STR) == 0)
|
|
{
|
|
*peDataTyp = SFLM_STRING_TYPE;
|
|
return( TRUE);
|
|
}
|
|
else if (f_stricmp( pszDataType, SFLM_INTEGER_OPTION_STR) == 0)
|
|
{
|
|
*peDataTyp = SFLM_NUMBER_TYPE;
|
|
return( TRUE);
|
|
}
|
|
else if (f_stricmp( pszDataType, SFLM_BINARY_OPTION_STR) == 0)
|
|
{
|
|
*peDataTyp = SFLM_BINARY_TYPE;
|
|
return( TRUE);
|
|
}
|
|
return( FALSE);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Desc: Determine if an encryption algorithm is valid.
|
|
***************************************************************************/
|
|
FSTATIC FLMBOOL validEncAlgorithm(
|
|
const char * pszEncAlgorithm,
|
|
eEncAlgorithm * peEncAlg)
|
|
{
|
|
if (f_stricmp( pszEncAlgorithm, SFLM_ENC_AES_OPTION_STR) == 0)
|
|
{
|
|
*peEncAlg = SFLM_AES_ENCRYPTION;
|
|
return( TRUE);
|
|
}
|
|
else if (f_stricmp( pszEncAlgorithm, SFLM_ENC_DES3_OPTION_STR))
|
|
{
|
|
*peEncAlg = SFLM_DES3_ENCRYPTION;
|
|
return( TRUE);
|
|
}
|
|
return( FALSE);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Desc: Determine if the key size for an encryption algorithm is valid.
|
|
***************************************************************************/
|
|
FSTATIC FLMBOOL validEncKeySize(
|
|
eEncAlgorithm eEncAlg,
|
|
FLMUINT uiKeySize)
|
|
{
|
|
switch (eEncAlg)
|
|
{
|
|
case SFLM_AES_ENCRYPTION:
|
|
if (uiKeySize == SFLM_AES128_KEY_SIZE ||
|
|
uiKeySize == SFLM_AES192_KEY_SIZE ||
|
|
uiKeySize == SFLM_AES256_KEY_SIZE)
|
|
{
|
|
return( TRUE);
|
|
}
|
|
break;
|
|
case SFLM_DES3_ENCRYPTION:
|
|
if (uiKeySize == SFLM_DES3_168_KEY_SIZE)
|
|
{
|
|
return( TRUE);
|
|
}
|
|
default:
|
|
// Should never hit this case.
|
|
flmAssert( 0);
|
|
break;
|
|
}
|
|
return( FALSE);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Add an encryption definition to the dictionary.
|
|
****************************************************************************/
|
|
RCODE F_Dict::addEncDef(
|
|
FLMUINT uiEncDefNum,
|
|
FLMUINT64 ui64DefRowId,
|
|
const char * pszEncDefName,
|
|
eEncAlgorithm eEncAlg,
|
|
FLMUINT uiEncKeySize,
|
|
FLMBYTE * pucEncKey,
|
|
FLMUINT uiEncKeyLen)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_ENCDEF * pEncDef;
|
|
F_CCS * pCcs = NULL;
|
|
|
|
if (!uiEncDefNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_ENCDEF_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Add a table entry to the array of tables.
|
|
// See if there is room in the table for another table.
|
|
|
|
if (uiEncDefNum >= m_uiEncDefTblSize)
|
|
{
|
|
FLMUINT uiNewTblSize = uiEncDefNum + 10;
|
|
|
|
if (RC_BAD( rc = f_realloc( sizeof( F_ENCDEF) * uiNewTblSize,
|
|
&m_pEncDefTbl)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Memset the new part of the table to all zeroes - so we can tell
|
|
// which slots are empty.
|
|
|
|
f_memset( &m_pEncDefTbl [m_uiEncDefTblSize], 0,
|
|
sizeof( F_ENCDEF) * (uiNewTblSize - m_uiEncDefTblSize));
|
|
m_uiEncDefTblSize = uiNewTblSize;
|
|
}
|
|
pEncDef = &m_pEncDefTbl [uiEncDefNum - 1];
|
|
|
|
// Make sure we have not already defined this slot.
|
|
|
|
if (pEncDef->uiEncDefNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DUPLICATE_ENCDEF_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Add the table name to the table name table.
|
|
|
|
if (RC_BAD( rc = m_pEncDefNames->copyName( pszEncDefName,
|
|
uiEncDefNum, &pEncDef->pszEncDefName, &m_dictPool)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pEncDef->eEncAlg = eEncAlg;
|
|
pEncDef->uiEncKeySize = uiEncKeySize;
|
|
|
|
// Create the CCS object
|
|
|
|
if ((pCcs = f_new( F_CCS)) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pCcs->init( FALSE, eEncAlg)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if( RC_BAD( rc = pCcs->setKeyFromStore(
|
|
pucEncKey, NULL, m_pDatabase->m_pWrappingKey)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pEncDef->pCcs = pCcs;
|
|
pEncDef->pCcs->AddRef();
|
|
|
|
pEncDef->uiEncDefNum = uiEncDefNum;
|
|
pEncDef->ui64DefRowId = ui64DefRowId;
|
|
if (uiEncDefNum > m_uiHighestEncDefNum)
|
|
{
|
|
m_uiHighestEncDefNum = uiEncDefNum;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Add a table to the dictionary, reserving room for its columns.
|
|
****************************************************************************/
|
|
RCODE F_Dict::addTable(
|
|
FLMUINT uiTableNum,
|
|
FLMUINT64 ui64DefRowId,
|
|
const char * pszTableName,
|
|
FLMBOOL bSystemTable,
|
|
FLMUINT uiNumColumns,
|
|
FLMUINT uiEncDefNum)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_TABLE * pTable;
|
|
|
|
if (!uiTableNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_TABLE_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Verify that the encryption definition is valid.
|
|
|
|
if (uiEncDefNum && getEncDef( uiEncDefNum) == NULL)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_ENCDEF_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Add a table entry to the array of tables.
|
|
// See if there is room in the table for another table.
|
|
|
|
if (uiTableNum >= m_uiTableTblSize)
|
|
{
|
|
FLMUINT uiNewTblSize = uiTableNum + 20;
|
|
|
|
if (RC_BAD( rc = f_realloc( sizeof( F_TABLE) * uiNewTblSize,
|
|
&m_pTableTbl)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Memset the new part of the table to all zeroes - so we can tell
|
|
// which slots are empty.
|
|
|
|
f_memset( &m_pTableTbl [m_uiTableTblSize], 0,
|
|
sizeof( F_TABLE) * (uiNewTblSize - m_uiTableTblSize));
|
|
m_uiTableTblSize = uiNewTblSize;
|
|
}
|
|
pTable = &m_pTableTbl [uiTableNum - 1];
|
|
|
|
// Make sure we have not already defined this slot.
|
|
|
|
if (pTable->uiTableNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DUPLICATE_TABLE_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Add the table name to the table name table.
|
|
|
|
if (RC_BAD( rc = m_pTableNames->copyName( pszTableName,
|
|
uiTableNum, &pTable->pszTableName, &m_dictPool)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Allocate a name table for the column names.
|
|
|
|
if ((pTable->pColumnNames = f_new F_NameTable) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = f_calloc( sizeof( NAME_INFO) * uiNumColumns,
|
|
&pTable->pColumnNames->m_pNames)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pTable->pColumnNames->m_uiTblSize = uiNumColumns;
|
|
|
|
// Make space for the columns.
|
|
|
|
if (RC_BAD( rc = m_dictPool.poolAlloc( sizeof( F_COLUMN) * uiNumColumns,
|
|
(void **)&pTable->pColumns)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pTable->uiNumColumns = uiNumColumns;
|
|
pTable->bSystemTable = bSystemTable;
|
|
f_memset( &pTable->lfInfo, 0, sizeof( LFILE));
|
|
pTable->lfInfo.uiLfNum = uiTableNum;
|
|
pTable->lfInfo.uiEncDefNum = uiEncDefNum;
|
|
pTable->uiTableNum = uiTableNum;
|
|
pTable->ui64DefRowId = ui64DefRowId;
|
|
pTable->uiFirstIndexNum = 0;
|
|
|
|
if (uiTableNum > m_uiHighestTableNum)
|
|
{
|
|
m_uiHighestTableNum = uiTableNum;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Add a column to a table in the dictionary.
|
|
****************************************************************************/
|
|
RCODE F_Dict::addColumn(
|
|
FLMUINT uiTableNum,
|
|
FLMUINT64 ui64DefRowId,
|
|
FLMUINT uiColumnNum,
|
|
const char * pszColumnName,
|
|
FLMUINT uiFlags,
|
|
eDataType eDataTyp,
|
|
FLMUINT uiEncDefNum)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_TABLE * pTable;
|
|
F_COLUMN * pColumn;
|
|
|
|
// Verify the table number
|
|
|
|
if ((pTable = getTable( uiTableNum)) == NULL)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_TABLE_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Verify that the encryption definition is valid.
|
|
|
|
if (uiEncDefNum && getEncDef( uiEncDefNum) == NULL)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_ENCDEF_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Make sure the column number is valid.
|
|
|
|
if (!uiColumnNum || uiColumnNum > pTable->uiNumColumns)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_COLUMN_NUM);
|
|
goto Exit;
|
|
}
|
|
pColumn = &pTable->pColumns [uiColumnNum - 1];
|
|
|
|
// Column number should not yet be set up.
|
|
|
|
if (pColumn->uiColumnNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DUPLICATE_COLUMN_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Add the column name to the table's column name table.
|
|
|
|
if (RC_BAD( rc = pTable->pColumnNames->copyName( pszColumnName,
|
|
uiColumnNum, &pColumn->pszColumnName, &m_dictPool)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pColumn->uiColumnNum = uiColumnNum;
|
|
pColumn->ui64DefRowId = ui64DefRowId;
|
|
pColumn->uiFlags = uiFlags;
|
|
pColumn->eDataTyp = eDataTyp;
|
|
pColumn->uiEncDefNum = uiEncDefNum;
|
|
pColumn->pFirstIcd = NULL;
|
|
pColumn->pFirstDataIcd = NULL;
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Add an index to the dictionary, reserving room for its key and data
|
|
components.
|
|
****************************************************************************/
|
|
RCODE F_Dict::addIndex(
|
|
FLMUINT uiIndexNum,
|
|
FLMUINT64 ui64DefRowId,
|
|
const char * pszIndexName,
|
|
FLMUINT uiTableNum,
|
|
FLMUINT uiEncDefNum,
|
|
FLMUINT uiFlags,
|
|
FLMUINT uiNumKeyComponents,
|
|
FLMUINT uiNumDataComponents,
|
|
FLMUINT uiLanguage,
|
|
FLMUINT64 ui64LastRowIndexed)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_INDEX * pIndex;
|
|
F_TABLE * pTable;
|
|
|
|
if (!uiIndexNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_INDEX_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Verify the table number
|
|
|
|
if ((pTable = getTable( uiTableNum)) == NULL)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_TABLE_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Verify that the encryption definition is valid.
|
|
|
|
if (uiEncDefNum && getEncDef( uiEncDefNum) == NULL)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_ENCDEF_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Add an index entry to the array of indexes.
|
|
// See if there is room in the table for another index.
|
|
|
|
if (uiIndexNum >= m_uiIndexTblSize)
|
|
{
|
|
FLMUINT uiNewTblSize = uiIndexNum + 20;
|
|
|
|
if (RC_BAD( rc = f_realloc( sizeof( F_INDEX) * uiNewTblSize,
|
|
&m_pIndexTbl)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Memset the new part of the table to all zeroes - so we can tell
|
|
// which slots are empty.
|
|
|
|
f_memset( &m_pIndexTbl [m_uiIndexTblSize], 0,
|
|
sizeof( F_INDEX) * (uiNewTblSize - m_uiIndexTblSize));
|
|
m_uiIndexTblSize = uiNewTblSize;
|
|
}
|
|
pIndex = &m_pIndexTbl [uiIndexNum - 1];
|
|
|
|
// Make sure we have not already defined this slot.
|
|
|
|
if (pIndex->uiIndexNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DUPLICATE_INDEX_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Add the index name to the index name table.
|
|
|
|
if (RC_BAD( rc = m_pIndexNames->copyName( pszIndexName,
|
|
uiIndexNum, &pIndex->pszIndexName, &m_dictPool)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Allocate space for the key components and data components
|
|
// Must be at least one key component.
|
|
|
|
flmAssert( uiNumKeyComponents);
|
|
if (RC_BAD( rc = m_dictPool.poolCalloc(
|
|
sizeof( ICD) * (uiNumKeyComponents + uiNumDataComponents),
|
|
(void **)&pIndex->pKeyIcds)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (uiNumDataComponents)
|
|
{
|
|
pIndex->pDataIcds = pIndex->pKeyIcds + uiNumKeyComponents;
|
|
}
|
|
else
|
|
{
|
|
pIndex->pDataIcds = NULL;
|
|
}
|
|
pIndex->uiNumKeyComponents = uiNumKeyComponents;
|
|
pIndex->uiNumDataComponents = uiNumDataComponents;
|
|
|
|
// Set other members of the index structure.
|
|
|
|
pIndex->uiTableNum = uiTableNum;
|
|
pIndex->uiFlags = uiFlags;
|
|
pIndex->uiLanguage = uiLanguage;
|
|
pIndex->ui64LastRowIndexed = ui64LastRowIndexed;
|
|
f_memset( &pIndex->lfInfo, 0, sizeof( LFILE));
|
|
pIndex->lfInfo.uiLfNum = uiIndexNum;
|
|
pIndex->lfInfo.uiEncDefNum = uiEncDefNum;
|
|
pIndex->uiIndexNum = uiIndexNum;
|
|
pIndex->ui64DefRowId = ui64DefRowId;
|
|
|
|
// Link the index into the list of indexes for the table
|
|
|
|
pIndex->uiNextIndexNum = pTable->uiFirstIndexNum;
|
|
pTable->uiFirstIndexNum = uiIndexNum;
|
|
|
|
if (uiIndexNum > m_uiHighestIndexNum)
|
|
{
|
|
m_uiHighestIndexNum = uiIndexNum;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Add an index column to an index's key component ICD array and/or to
|
|
the index's data component ICD array.
|
|
****************************************************************************/
|
|
RCODE F_Dict::addIndexComponent(
|
|
FLMUINT uiIndexNum,
|
|
FLMUINT64 ui64DefRowId,
|
|
FLMUINT uiColumnNum,
|
|
FLMUINT uiFlags,
|
|
FLMUINT uiCompareRules,
|
|
FLMUINT uiLimit,
|
|
FLMUINT uiKeyComponent,
|
|
FLMUINT uiDataComponent)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_INDEX * pIndex;
|
|
F_TABLE * pTable;
|
|
ICD * pIcd;
|
|
F_COLUMN * pColumn;
|
|
|
|
// Verify the index number
|
|
|
|
if ((pIndex = getIndex( uiIndexNum)) == NULL)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_INDEX_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// If we have a valid pIndex, it's table number should have already
|
|
// been validated.
|
|
|
|
pTable = getTable( pIndex->uiTableNum);
|
|
flmAssert( pTable);
|
|
|
|
// Verify the column number.
|
|
|
|
if ((pColumn = getColumn( pTable, uiColumnNum)) == NULL)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_COLUMN_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// See if it is a key component.
|
|
// NOTE: It is possible for the column to be both a key component and
|
|
// a data component.
|
|
|
|
if (uiKeyComponent)
|
|
{
|
|
if (uiKeyComponent > pIndex->uiNumKeyComponents)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_KEY_COMPONENT);
|
|
goto Exit;
|
|
}
|
|
pIcd = &pIndex->pKeyIcds [uiKeyComponent - 1];
|
|
|
|
// Make sure this component hasn't already been defined.
|
|
|
|
if (pIcd->uiIndexNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DUPLICATE_KEY_COMPONENT);
|
|
goto Exit;
|
|
}
|
|
|
|
pIcd->uiIndexNum = uiIndexNum;
|
|
pIcd->uiColumnNum = uiColumnNum;
|
|
pIcd->ui64DefRowId = ui64DefRowId;
|
|
pIcd->uiFlags = uiFlags;
|
|
pIcd->uiCompareRules = uiCompareRules;
|
|
pIcd->uiLimit = uiLimit;
|
|
pIcd->pNextInChain = pColumn->pFirstIcd;
|
|
pColumn->pFirstIcd = pIcd;
|
|
}
|
|
|
|
// See if it is a data component.
|
|
|
|
if (uiDataComponent)
|
|
{
|
|
if (uiDataComponent > pIndex->uiNumDataComponents)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_DATA_COMPONENT);
|
|
goto Exit;
|
|
}
|
|
|
|
pIcd = &pIndex->pDataIcds [uiDataComponent - 1];
|
|
|
|
// Make sure this component hasn't already been defined.
|
|
|
|
if (pIcd->uiIndexNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DUPLICATE_DATA_COMPONENT);
|
|
goto Exit;
|
|
}
|
|
|
|
pIcd->uiIndexNum = uiIndexNum;
|
|
pIcd->uiColumnNum = uiColumnNum;
|
|
pIcd->ui64DefRowId = ui64DefRowId;
|
|
pIcd->uiFlags = 0;
|
|
pIcd->uiCompareRules = 0;
|
|
pIcd->pNextInChain = NULL;
|
|
pIcd->uiLimit = 0;
|
|
pIcd->pNextInDataChain = pColumn->pFirstDataIcd;
|
|
pColumn->pFirstDataIcd = pIcd;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Setup the encryption definition table and its associated indexes.
|
|
****************************************************************************/
|
|
RCODE F_Dict::setupEncDefTable( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
|
|
// Create the table
|
|
|
|
if (RC_BAD( rc = addTable( SFLM_TBLNUM_ENCDEFS, 0,
|
|
SFLM_TBLNAM_ENCDEFS, TRUE,
|
|
SFLM_ENCDEFS_NUM_COLUMNS, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add Columns
|
|
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_ENCDEFS, 0,
|
|
SFLM_COLNUM_ENCDEFS_ENCDEF_NAME,
|
|
SFLM_COLNAM_ENCDEFS_ENCDEF_NAME,
|
|
0, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_ENCDEFS, 0,
|
|
SFLM_COLNUM_ENCDEFS_ENCDEF_NUM,
|
|
SFLM_COLNAM_ENCDEFS_ENCDEF_NUM,
|
|
COL_READ_ONLY, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_ENCDEFS, 0,
|
|
SFLM_COLNUM_ENCDEFS_ENC_ALGORITHM,
|
|
SFLM_COLNAM_ENCDEFS_ENC_ALGORITHM,
|
|
COL_READ_ONLY, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_ENCDEFS, 0,
|
|
SFLM_COLNUM_ENCDEFS_ENC_KEY_SIZE,
|
|
SFLM_COLNAM_ENCDEFS_ENC_KEY_SIZE,
|
|
COL_READ_ONLY, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_ENCDEFS, 0,
|
|
SFLM_COLNUM_ENCDEFS_ENC_KEY,
|
|
SFLM_COLNAM_ENCDEFS_ENC_KEY,
|
|
COL_READ_ONLY, SFLM_BINARY_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add an index on the encdef table, encdef name column
|
|
|
|
if (RC_BAD( rc = addIndex( SFLM_IXNUM_ENCDEF_NAME, 0,
|
|
SFLM_IXNAM_ENCDEF_NAME,
|
|
SFLM_TBLNUM_ENCDEFS, 0,
|
|
IXD_SYSTEM, 1, 0, FLM_US_LANG, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addIndexComponent( SFLM_IXNUM_ENCDEF_NAME, 0,
|
|
SFLM_COLNUM_ENCDEFS_ENCDEF_NAME,
|
|
ICD_VALUE, FLM_COMP_CASE_INSENSITIVE, 0,
|
|
1, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Setup the table table and its associated indexes.
|
|
****************************************************************************/
|
|
RCODE F_Dict::setupTableTable( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
|
|
// Create table
|
|
|
|
if (RC_BAD( rc = addTable( SFLM_TBLNUM_TABLES, 0,
|
|
SFLM_TBLNAM_TABLES, TRUE,
|
|
SFLM_TABLES_NUM_COLUMNS, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add Columns
|
|
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_TABLES, 0,
|
|
SFLM_COLNUM_TABLES_TABLE_NAME,
|
|
SFLM_COLNAM_TABLES_TABLE_NAME,
|
|
0, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_TABLES, 0,
|
|
SFLM_COLNUM_TABLES_TABLE_NUM,
|
|
SFLM_COLNAM_TABLES_TABLE_NUM,
|
|
COL_READ_ONLY, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_TABLES, 0,
|
|
SFLM_COLNUM_TABLES_ENCDEF_NUM,
|
|
SFLM_COLNAM_TABLES_ENCDEF_NUM,
|
|
0, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_TABLES, 0,
|
|
SFLM_COLNUM_TABLES_NUM_COLUMNS,
|
|
SFLM_COLNAM_TABLES_NUM_COLUMNS,
|
|
0, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add an index on the table name column
|
|
|
|
if (RC_BAD( rc = addIndex( SFLM_IXNUM_TABLE_NAME, 0,
|
|
SFLM_IXNAM_TABLE_NAME,
|
|
SFLM_TBLNUM_TABLES, 0,
|
|
IXD_SYSTEM, 1, 0, FLM_US_LANG, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addIndexComponent( SFLM_IXNUM_TABLE_NAME, 0,
|
|
SFLM_COLNUM_TABLES_TABLE_NAME,
|
|
ICD_VALUE, FLM_COMP_CASE_INSENSITIVE, 0,
|
|
1, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add an index on the encdef number column
|
|
|
|
if (RC_BAD( rc = addIndex( SFLM_IXNUM_TABLE_ENCDEF_NUM, 0,
|
|
SFLM_IXNAM_TABLE_ENCDEF_NUM,
|
|
SFLM_TBLNUM_TABLES, 0,
|
|
IXD_SYSTEM, 1, 0, FLM_US_LANG, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addIndexComponent( SFLM_IXNUM_TABLE_ENCDEF_NUM, 0,
|
|
SFLM_COLNUM_TABLES_ENCDEF_NUM,
|
|
ICD_VALUE, 0, 0,
|
|
1, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Setup the column table and its associated indexes.
|
|
****************************************************************************/
|
|
RCODE F_Dict::setupColumnTable( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
|
|
// Create table
|
|
|
|
if (RC_BAD( rc = addTable( SFLM_TBLNUM_COLUMNS, 0,
|
|
SFLM_TBLNAM_COLUMNS, TRUE,
|
|
SFLM_COLUMNS_NUM_COLUMNS, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add columns
|
|
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_COLUMNS, 0,
|
|
SFLM_COLNUM_COLUMNS_TABLE_NUM,
|
|
SFLM_COLNAM_COLUMNS_TABLE_NUM,
|
|
COL_READ_ONLY, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_COLUMNS, 0,
|
|
SFLM_COLNUM_COLUMNS_COLUMN_NAME,
|
|
SFLM_COLNAM_COLUMNS_COLUMN_NAME,
|
|
0, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_COLUMNS, 0,
|
|
SFLM_COLNUM_COLUMNS_COLUMN_NUM,
|
|
SFLM_COLNAM_COLUMNS_COLUMN_NUM,
|
|
COL_READ_ONLY, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_COLUMNS, 0,
|
|
SFLM_COLNUM_COLUMNS_DATA_TYPE,
|
|
SFLM_COLNAM_COLUMNS_DATA_TYPE,
|
|
COL_READ_ONLY, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_COLUMNS, 0,
|
|
SFLM_COLNUM_COLUMNS_ENCDEF_NUM,
|
|
SFLM_COLNAM_COLUMNS_ENCDEF_NUM,
|
|
COL_READ_ONLY | COL_NULL_ALLOWED, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_COLUMNS, 0,
|
|
SFLM_COLNUM_COLUMNS_READ_ONLY,
|
|
SFLM_COLNAM_COLUMNS_READ_ONLY,
|
|
COL_NULL_ALLOWED, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_COLUMNS, 0,
|
|
SFLM_COLNUM_COLUMNS_NULL_ALLOWED,
|
|
SFLM_COLNAM_COLUMNS_NULL_ALLOWED,
|
|
COL_NULL_ALLOWED, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add an index on the table number column
|
|
|
|
if (RC_BAD( rc = addIndex( SFLM_IXNUM_COLUMN_TABLE_NUM, 0,
|
|
SFLM_IXNAM_COLUMN_TABLE_NUM,
|
|
SFLM_TBLNUM_COLUMNS, 0,
|
|
IXD_SYSTEM, 1, 0, FLM_US_LANG, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addIndexComponent( SFLM_IXNUM_COLUMN_TABLE_NUM, 0,
|
|
SFLM_COLNUM_COLUMNS_TABLE_NUM,
|
|
ICD_VALUE, 0, 0,
|
|
1, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add an index on the encdef number column
|
|
|
|
if (RC_BAD( rc = addIndex( SFLM_IXNUM_COLUMN_ENCDEF_NUM, 0,
|
|
SFLM_IXNAM_COLUMN_ENCDEF_NUM,
|
|
SFLM_TBLNUM_COLUMNS, 0,
|
|
IXD_SYSTEM, 1, 0, FLM_US_LANG, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addIndexComponent( SFLM_IXNUM_COLUMN_ENCDEF_NUM, 0,
|
|
SFLM_COLNUM_COLUMNS_ENCDEF_NUM,
|
|
ICD_VALUE, 0, 0,
|
|
1, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Setup the index table and its associated indexes.
|
|
****************************************************************************/
|
|
RCODE F_Dict::setupIndexTable( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
|
|
// Create the table
|
|
|
|
if (RC_BAD( rc = addTable( SFLM_TBLNUM_INDEXES, 0,
|
|
SFLM_TBLNAM_INDEXES, TRUE,
|
|
SFLM_INDEXES_NUM_COLUMNS, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add columns
|
|
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEXES, 0,
|
|
SFLM_COLNUM_INDEXES_INDEX_NAME,
|
|
SFLM_COLNAM_INDEXES_INDEX_NAME,
|
|
0, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEXES, 0,
|
|
SFLM_COLNUM_INDEXES_INDEX_NUM,
|
|
SFLM_COLNAM_INDEXES_INDEX_NUM,
|
|
COL_READ_ONLY, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEXES, 0,
|
|
SFLM_COLNUM_INDEXES_TABLE_NUM,
|
|
SFLM_COLNAM_INDEXES_TABLE_NUM,
|
|
COL_READ_ONLY, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEXES, 0,
|
|
SFLM_COLNUM_INDEXES_ENCDEF_NUM,
|
|
SFLM_COLNAM_INDEXES_ENCDEF_NUM,
|
|
COL_READ_ONLY | COL_NULL_ALLOWED, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEXES, 0,
|
|
SFLM_COLNUM_INDEXES_LANGUAGE,
|
|
SFLM_COLNAM_INDEXES_LANGUAGE,
|
|
COL_NULL_ALLOWED, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEXES, 0,
|
|
SFLM_COLNUM_INDEXES_NUM_KEY_COMPONENTS,
|
|
SFLM_COLNAM_INDEXES_NUM_KEY_COMPONENTS,
|
|
COL_NULL_ALLOWED, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEXES, 0,
|
|
SFLM_COLNUM_INDEXES_NUM_DATA_COMPONENTS,
|
|
SFLM_COLNAM_INDEXES_NUM_DATA_COMPONENTS,
|
|
COL_NULL_ALLOWED, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEXES, 0,
|
|
SFLM_COLNUM_INDEXES_LAST_ROW_INDEXED,
|
|
SFLM_COLNAM_INDEXES_LAST_ROW_INDEXED,
|
|
COL_NULL_ALLOWED, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEXES, 0,
|
|
SFLM_COLNUM_INDEXES_INDEX_STATE,
|
|
SFLM_COLNAM_INDEXES_INDEX_STATE,
|
|
COL_NULL_ALLOWED, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add an index on the index name column
|
|
|
|
if (RC_BAD( rc = addIndex( SFLM_IXNUM_INDEX_NAME, 0,
|
|
SFLM_IXNAM_INDEX_NAME,
|
|
SFLM_TBLNUM_INDEXES, 0,
|
|
IXD_SYSTEM, 1, 0, FLM_US_LANG, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addIndexComponent( SFLM_IXNUM_INDEX_NAME, 0,
|
|
SFLM_COLNUM_INDEXES_INDEX_NAME,
|
|
ICD_VALUE, FLM_COMP_CASE_INSENSITIVE, 0,
|
|
1, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add an index on the table number column
|
|
|
|
if (RC_BAD( rc = addIndex( SFLM_IXNUM_INDEX_TABLE_NUM, 0,
|
|
SFLM_IXNAM_INDEX_TABLE_NUM,
|
|
SFLM_TBLNUM_INDEXES, 0,
|
|
IXD_SYSTEM, 1, 0, FLM_US_LANG, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addIndexComponent( SFLM_IXNUM_INDEX_TABLE_NUM, 0,
|
|
SFLM_COLNUM_INDEXES_TABLE_NUM,
|
|
ICD_VALUE, 0, 0,
|
|
1, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add an index on the encdef number column
|
|
|
|
if (RC_BAD( rc = addIndex( SFLM_IXNUM_INDEX_ENCDEF_NUM, 0,
|
|
SFLM_IXNAM_INDEX_ENCDEF_NUM,
|
|
SFLM_TBLNUM_INDEXES, 0,
|
|
IXD_SYSTEM, 1, 0, FLM_US_LANG, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addIndexComponent( SFLM_IXNUM_INDEX_ENCDEF_NUM, 0,
|
|
SFLM_COLNUM_INDEXES_ENCDEF_NUM,
|
|
ICD_VALUE, 0, 0,
|
|
1, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Setup the index component table and its associated indexes.
|
|
****************************************************************************/
|
|
RCODE F_Dict::setupIndexComponentTable( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
|
|
// Create the table
|
|
|
|
if (RC_BAD( rc = addTable( SFLM_TBLNUM_INDEX_COMPONENTS, 0,
|
|
SFLM_TBLNAM_INDEX_COMPONENTS, TRUE,
|
|
SFLM_INDEX_COMP_NUM_COLUMNS, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add Columns
|
|
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEX_COMPONENTS, 0,
|
|
SFLM_COLNUM_INDEX_COMP_INDEX_NUM,
|
|
SFLM_COLNAM_INDEX_COMP_INDEX_NUM,
|
|
COL_READ_ONLY, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEX_COMPONENTS, 0,
|
|
SFLM_COLNUM_INDEX_COMP_COLUMN_NUM,
|
|
SFLM_COLNAM_INDEX_COMP_COLUMN_NUM,
|
|
COL_READ_ONLY, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEX_COMPONENTS, 0,
|
|
SFLM_COLNUM_INDEX_COMP_KEY_COMPONENT,
|
|
SFLM_COLNAM_INDEX_COMP_KEY_COMPONENT,
|
|
COL_NULL_ALLOWED, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEX_COMPONENTS, 0,
|
|
SFLM_COLNUM_INDEX_COMP_DATA_COMPONENT,
|
|
SFLM_COLNAM_INDEX_COMP_DATA_COMPONENT,
|
|
COL_NULL_ALLOWED, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEX_COMPONENTS, 0,
|
|
SFLM_COLNUM_INDEX_COMP_INDEX_ON,
|
|
SFLM_COLNAM_INDEX_COMP_INDEX_ON,
|
|
COL_NULL_ALLOWED, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEX_COMPONENTS, 0,
|
|
SFLM_COLNUM_INDEX_COMP_COMPARE_RULES,
|
|
SFLM_COLNAM_INDEX_COMP_COMPARE_RULES,
|
|
COL_NULL_ALLOWED, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEX_COMPONENTS, 0,
|
|
SFLM_COLNUM_INDEX_COMP_SORT_DESCENDING,
|
|
SFLM_COLNAM_INDEX_COMP_SORT_DESCENDING,
|
|
COL_NULL_ALLOWED, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEX_COMPONENTS, 0,
|
|
SFLM_COLNUM_INDEX_COMP_SORT_MISSING_HIGH,
|
|
SFLM_COLNAM_INDEX_COMP_SORT_MISSING_HIGH,
|
|
COL_NULL_ALLOWED, SFLM_STRING_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_INDEX_COMPONENTS, 0,
|
|
SFLM_COLNUM_INDEX_COMP_LIMIT,
|
|
SFLM_COLNAM_INDEX_COMP_LIMIT,
|
|
COL_NULL_ALLOWED, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add an index on the index number column
|
|
|
|
if (RC_BAD( rc = addIndex( SFLM_IXNUM_INDEX_COMP_INDEX_NUM, 0,
|
|
SFLM_IXNAM_INDEX_COMP_INDEX_NUM,
|
|
SFLM_TBLNUM_INDEX_COMPONENTS, 0,
|
|
IXD_SYSTEM, 1, 0, FLM_US_LANG, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = addIndexComponent( SFLM_IXNUM_INDEX_COMP_INDEX_NUM, 0,
|
|
SFLM_COLNUM_INDEX_COMP_INDEX_NUM,
|
|
ICD_VALUE, 0, 0,
|
|
1, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Setup the block chain table.
|
|
****************************************************************************/
|
|
RCODE F_Dict::setupBlockChainTable( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
|
|
// Create the table
|
|
|
|
if (RC_BAD( rc = addTable( SFLM_TBLNUM_BLOCK_CHAINS, 0,
|
|
SFLM_TBLNAM_BLOCK_CHAINS, TRUE,
|
|
SFLM_BLOCK_CHAINS_NUM_COLUMNS, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add columns
|
|
|
|
if (RC_BAD( rc = addColumn( SFLM_TBLNUM_BLOCK_CHAINS, 0,
|
|
SFLM_COLNUM_BLOCK_CHAINS_BLOCK_ADDRESS,
|
|
SFLM_COLNAM_BLOCK_CHAINS_BLOCK_ADDRESS,
|
|
0, SFLM_NUMBER_TYPE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Setup the predefined tables and indexes.
|
|
****************************************************************************/
|
|
RCODE F_Dict::setupPredefined( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
|
|
// Set up the encryption definition table
|
|
|
|
if (RC_BAD( rc = setupEncDefTable()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Set up the table table
|
|
|
|
if (RC_BAD( rc = setupTableTable()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Set up the column table
|
|
|
|
if (RC_BAD( rc = setupColumnTable()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Set up the index table
|
|
|
|
if (RC_BAD( rc = setupIndexTable()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Set up the index component table
|
|
|
|
if (RC_BAD( rc = setupIndexComponentTable()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Set up the block chain deletion table
|
|
|
|
if (RC_BAD( rc= setupBlockChainTable()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Verify that a dictionary is good after having read it in. These are
|
|
things that didn't get verified as we were reading in.
|
|
****************************************************************************/
|
|
RCODE F_Dict::verifyDict( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
FLMUINT uiTableNum;
|
|
F_TABLE * pTable;
|
|
FLMUINT uiColumnNum;
|
|
F_COLUMN * pColumn;
|
|
FLMUINT uiIndexNum;
|
|
F_INDEX * pIndex;
|
|
ICD * pIcd;
|
|
FLMUINT uiKeyComponent;
|
|
FLMUINT uiDataComponent;
|
|
|
|
// Make sure we have no duplicate table names, index names, or encryption
|
|
// definition names.
|
|
|
|
if (m_pTableNames)
|
|
{
|
|
m_pTableNames->sortNames();
|
|
if (m_pTableNames->m_bDuplicateNames)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DUPLICATE_TABLE_NAME);
|
|
goto Exit;
|
|
}
|
|
}
|
|
if (m_pIndexNames)
|
|
{
|
|
m_pIndexNames->sortNames();
|
|
if (m_pTableNames->m_bDuplicateNames)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DUPLICATE_INDEX_NAME);
|
|
goto Exit;
|
|
}
|
|
}
|
|
if (m_pEncDefNames)
|
|
{
|
|
m_pEncDefNames->sortNames();
|
|
if (m_pTableNames->m_bDuplicateNames)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DUPLICATE_ENCDEF_NAME);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Loop through all of the tables. Verify that all of the column numbers
|
|
// are defined, and that for each column name table there are no duplicate
|
|
// column names.
|
|
|
|
for (uiTableNum = 0, pTable = m_pTableTbl;
|
|
uiTableNum < m_uiHighestTableNum;
|
|
uiTableNum++, pTable++)
|
|
{
|
|
if (!pTable->uiTableNum)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Sort the column names - make sure there are no duplicate column names.
|
|
|
|
pTable->pColumnNames->sortNames();
|
|
if (pTable->pColumnNames->m_bDuplicateNames)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DUPLICATE_COLUMN_NAME);
|
|
goto Exit;
|
|
}
|
|
|
|
// Make sure each column is defined.
|
|
|
|
for (uiColumnNum = 0, pColumn = pTable->pColumns;
|
|
uiColumnNum < pTable->uiNumColumns;
|
|
uiColumnNum++, pColumn++)
|
|
{
|
|
|
|
// uiColumnNum will be zero if it never got defined.
|
|
|
|
if (!pColumn->uiColumnNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_UNDEFINED_COLUMN_NUM);
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Verify that for each index all of the key components and data components
|
|
// are defined.
|
|
|
|
for (uiIndexNum = 0, pIndex = m_pIndexTbl;
|
|
uiIndexNum < m_uiHighestIndexNum;
|
|
uiIndexNum++, pIndex++)
|
|
{
|
|
if (!pIndex->uiIndexNum)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Make sure all key components are defined.
|
|
|
|
for (uiKeyComponent = 0, pIcd = pIndex->pKeyIcds;
|
|
uiKeyComponent < pIndex->uiNumKeyComponents;
|
|
uiKeyComponent++, pIcd++)
|
|
{
|
|
|
|
// If the ICD is not defined, the uiIndexNum field will be 0
|
|
|
|
if (!pIcd->uiIndexNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_UNDEFINED_KEY_COMPONENT);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Make sure all data components are defined.
|
|
|
|
for (uiDataComponent = 0, pIcd = pIndex->pDataIcds;
|
|
uiDataComponent < pIndex->uiNumDataComponents;
|
|
uiDataComponent++, pIcd++)
|
|
{
|
|
|
|
// If the ICD is not defined, the uiIndexNum field will be 0
|
|
|
|
if (!pIcd->uiIndexNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_UNDEFINED_DATA_COMPONENT);
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Read in LFH headers.
|
|
****************************************************************************/
|
|
RCODE F_Db::dictReadLFH( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_TABLE * pTable;
|
|
F_INDEX * pIndex;
|
|
F_CachedBlock * pSCache;
|
|
FLMBOOL bReleaseCache = FALSE;
|
|
F_BLK_HDR * pBlkHdr;
|
|
FLMUINT uiBlkAddress;
|
|
FLMUINT uiPos;
|
|
FLMUINT uiEndPos;
|
|
FLMUINT uiBlkSize = m_pDatabase->m_uiBlockSize;
|
|
LFILE TmpLFile;
|
|
|
|
f_memset( &TmpLFile, 0, sizeof( LFILE));
|
|
|
|
// Read through all of the LFILE blocks.
|
|
|
|
uiBlkAddress =
|
|
(FLMUINT)m_pDatabase->m_lastCommittedDbHdr.ui32FirstLFBlkAddr;
|
|
while (uiBlkAddress)
|
|
{
|
|
if (RC_BAD( rc = m_pDatabase->getBlock( this, NULL,
|
|
uiBlkAddress, NULL, &pSCache)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
bReleaseCache = TRUE;
|
|
|
|
pBlkHdr = pSCache->m_pBlkHdr;
|
|
uiPos = SIZEOF_STD_BLK_HDR;
|
|
uiEndPos = blkGetEnd( uiBlkSize, SIZEOF_STD_BLK_HDR, pBlkHdr);
|
|
|
|
// Read through all of the logical file definitions in the block
|
|
|
|
for( ; uiPos + sizeof( F_LF_HDR) <= uiEndPos; uiPos += sizeof( F_LF_HDR))
|
|
{
|
|
F_LF_HDR * pLfHdr = (F_LF_HDR *)((FLMBYTE *)(pBlkHdr) + uiPos);
|
|
eLFileType eLfType = (eLFileType)pLfHdr->ui32LfType;
|
|
|
|
// Have to fix up the offsets later when they are read in
|
|
|
|
if (eLfType == SFLM_LF_INVALID)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Populate the LFILE in the dictionary, if one has been set up.
|
|
|
|
if (eLfType == SFLM_LF_INDEX)
|
|
{
|
|
FSLFileIn( (FLMBYTE *)pLfHdr, &TmpLFile, uiBlkAddress, uiPos);
|
|
|
|
if ((pIndex = m_pDict->getIndex( TmpLFile.uiLfNum)) != NULL)
|
|
{
|
|
f_memcpy( &pIndex->lfInfo, &TmpLFile, sizeof( LFILE));
|
|
}
|
|
|
|
// LFILE better have a non-zero root block.
|
|
|
|
if (!TmpLFile.uiRootBlk)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DATA_ERROR);
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Better be a container
|
|
|
|
flmAssert( eLfType == SFLM_LF_TABLE);
|
|
|
|
FSLFileIn( (FLMBYTE *)pLfHdr, &TmpLFile, uiBlkAddress, uiPos);
|
|
|
|
if ((pTable = m_pDict->getTable( TmpLFile.uiLfNum)) != NULL)
|
|
{
|
|
f_memcpy( &pTable->lfInfo, &TmpLFile, sizeof( LFILE));
|
|
}
|
|
|
|
// LFILE better have a non-zero root block.
|
|
|
|
if (!TmpLFile.uiRootBlk)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_DATA_ERROR);
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get the next block in the chain
|
|
|
|
uiBlkAddress = (FLMUINT)pBlkHdr->ui32NextBlkInChain;
|
|
ScaReleaseCache( pSCache, FALSE);
|
|
bReleaseCache = FALSE;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (bReleaseCache)
|
|
{
|
|
ScaReleaseCache( pSCache, FALSE);
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Read in all rows from the encryption definition table.
|
|
Create the in-memory structures for each encryption definition.
|
|
****************************************************************************/
|
|
RCODE F_Db::dictReadEncDefs( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_Row * pRow = NULL;
|
|
FLMUINT64 ui64DefRowId;
|
|
FSTableCursor * pTableCursor = NULL;
|
|
char szEncDefName [MAX_ENCDEF_NAME_LEN + 1];
|
|
FLMUINT uiEncDefNameLen;
|
|
FLMUINT uiEncDefNum;
|
|
char szEncAlgorithm [20];
|
|
eEncAlgorithm eEncAlg;
|
|
FLMUINT uiEncKeySize;
|
|
FLMBYTE * pucEncKey = NULL;
|
|
FLMUINT uiEncKeyLen;
|
|
FLMBOOL bIsNull;
|
|
|
|
if ((pTableCursor = f_new FSTableCursor) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pTableCursor->setupRange( this, SFLM_TBLNUM_ENCDEFS,
|
|
1, FLM_MAX_UINT64, NULL, NULL, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Read through all rows in the table. Each row defines a table in
|
|
// the database, so we add it to the in-memory dictionary.
|
|
|
|
for (;;)
|
|
{
|
|
if (RC_BAD( rc = pTableCursor->nextRow( this, &pRow, &ui64DefRowId)))
|
|
{
|
|
if (rc == NE_SFLM_EOF_HIT)
|
|
{
|
|
rc = NE_SFLM_OK;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the encryption definition name - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_ENCDEFS_ENCDEF_NAME,
|
|
szEncDefName, sizeof( szEncDefName),
|
|
&bIsNull, &uiEncDefNameLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull || !uiEncDefNameLen)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_ENCDEF_NAME);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the encryption definition number - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_ENCDEFS_ENCDEF_NUM,
|
|
&uiEncDefNum, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_ENCDEF_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the encryption algorithm - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_ENCDEFS_ENC_ALGORITHM,
|
|
szEncAlgorithm, sizeof( szEncAlgorithm),
|
|
&bIsNull, NULL, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull || !szEncAlgorithm [0])
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_ENC_ALGORITHM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Make sure the encryption algorithm and key size are valid.
|
|
|
|
if (!validEncAlgorithm( szEncAlgorithm, &eEncAlg))
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_ENC_ALGORITHM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the encryption key size - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_ENCDEFS_ENC_KEY_SIZE,
|
|
&uiEncKeySize, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_ENC_KEY_SIZE);
|
|
goto Exit;
|
|
}
|
|
if (!validEncKeySize( eEncAlg, uiEncKeySize))
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_ENC_KEY_SIZE);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the encryption key. There better be one at this point.
|
|
|
|
pRow->getDataLen( this, SFLM_COLNUM_ENCDEFS_ENC_KEY,
|
|
&uiEncKeyLen, &bIsNull);
|
|
if (bIsNull || !uiEncKeyLen)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_ENC_KEY);
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = f_alloc( uiEncKeyLen, &pucEncKey)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = pRow->getBinary( this, SFLM_COLNUM_ENCDEFS_ENC_KEY,
|
|
pucEncKey, uiEncKeyLen, &uiEncKeyLen,
|
|
&bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
flmAssert( !bIsNull); // If encryption key length > 0, this better never be TRUE!
|
|
|
|
if (RC_BAD( rc = m_pDict->addEncDef( uiEncDefNum, ui64DefRowId,
|
|
szEncDefName, eEncAlg,
|
|
uiEncKeySize, pucEncKey, uiEncKeyLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (pRow)
|
|
{
|
|
pRow->ReleaseRow();
|
|
}
|
|
if (pucEncKey)
|
|
{
|
|
f_free( &pucEncKey);
|
|
}
|
|
if (pTableCursor)
|
|
{
|
|
pTableCursor->Release();
|
|
}
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Read in all rows from the table table. Create the in-memory structures
|
|
for each defined table.
|
|
****************************************************************************/
|
|
RCODE F_Db::dictReadTables( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_Row * pRow = NULL;
|
|
FLMUINT64 ui64DefRowId;
|
|
FSTableCursor * pTableCursor = NULL;
|
|
char szTableName [MAX_TABLE_NAME_LEN + 1];
|
|
FLMUINT uiTableNameLen;
|
|
FLMUINT uiTableNum;
|
|
FLMUINT uiEncDefNum;
|
|
FLMUINT uiNumColumns;
|
|
FLMBOOL bIsNull;
|
|
|
|
if ((pTableCursor = f_new FSTableCursor) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pTableCursor->setupRange( this, SFLM_TBLNUM_TABLES,
|
|
1, FLM_MAX_UINT64, NULL, NULL, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Read through all rows in the table. Each row defines a table in
|
|
// the database, so we add it to the in-memory dictionary.
|
|
|
|
for (;;)
|
|
{
|
|
if (RC_BAD( rc = pTableCursor->nextRow( this, &pRow, &ui64DefRowId)))
|
|
{
|
|
if (rc == NE_SFLM_EOF_HIT)
|
|
{
|
|
rc = NE_SFLM_OK;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the table name - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_TABLES_TABLE_NAME,
|
|
szTableName, sizeof( szTableName),
|
|
&bIsNull, &uiTableNameLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull || !uiTableNameLen)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_TABLE_NAME);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the table number - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_TABLES_TABLE_NUM,
|
|
&uiTableNum, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_TABLE_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the encryption name - optional. But if present, it must be
|
|
// defined in the dictionary already.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_TABLES_ENCDEF_NUM,
|
|
&uiEncDefNum, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
uiEncDefNum = 0;
|
|
}
|
|
|
|
// Get the number of columns. Must be non-zero.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_TABLES_NUM_COLUMNS,
|
|
&uiNumColumns, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_NUM_COLUMNS);
|
|
goto Exit;
|
|
}
|
|
if (!uiNumColumns)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_NUM_COLUMNS);
|
|
goto Exit;
|
|
}
|
|
|
|
// Add an entry to the in-memory dictionary for the table.
|
|
|
|
if (RC_BAD( rc = m_pDict->addTable( uiTableNum, ui64DefRowId,
|
|
szTableName, FALSE,
|
|
uiNumColumns, uiEncDefNum)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (pRow)
|
|
{
|
|
pRow->ReleaseRow();
|
|
}
|
|
|
|
if (pTableCursor)
|
|
{
|
|
pTableCursor->Release();
|
|
}
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Read in all rows from the column table. Create the in-memory structures
|
|
for each defined column.
|
|
****************************************************************************/
|
|
RCODE F_Db::dictReadColumns( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_Row * pRow = NULL;
|
|
FLMUINT64 ui64DefRowId;
|
|
FSTableCursor * pTableCursor = NULL;
|
|
FLMUINT uiEncDefNum;
|
|
FLMUINT uiTableNum;
|
|
char szColumnName [MAX_COLUMN_NAME_LEN + 1];
|
|
FLMUINT uiColumnNameLen;
|
|
FLMUINT uiColumnNum;
|
|
eDataType eDataTyp;
|
|
FLMUINT uiFlags;
|
|
char szTmp [100];
|
|
FLMUINT uiTmpLen;
|
|
FLMBOOL bTmp;
|
|
FLMBOOL bIsNull;
|
|
|
|
if ((pTableCursor = f_new FSTableCursor) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pTableCursor->setupRange( this, SFLM_TBLNUM_COLUMNS,
|
|
1, FLM_MAX_UINT64, NULL, NULL, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Read through all rows in the table. Each row defines a column in
|
|
// a table in the database, so we add it to the in-memory dictionary.
|
|
|
|
for (;;)
|
|
{
|
|
if (RC_BAD( rc = pTableCursor->nextRow( this, &pRow, &ui64DefRowId)))
|
|
{
|
|
if (rc == NE_SFLM_EOF_HIT)
|
|
{
|
|
rc = NE_SFLM_OK;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the table number - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_COLUMNS_TABLE_NUM,
|
|
&uiTableNum, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_TABLE_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the column name. There must be a column name.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_COLUMNS_COLUMN_NAME,
|
|
szColumnName, sizeof( szColumnName),
|
|
&bIsNull, &uiColumnNameLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull || !uiColumnNameLen)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_COLUMN_NAME);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get column number - must be non-zero.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_COLUMNS_COLUMN_NUM,
|
|
&uiColumnNum, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_COLUMN_NUM);
|
|
goto Exit;
|
|
}
|
|
flmAssert( uiColumnNum);
|
|
|
|
// Get the encryption definition number - optional.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_COLUMNS_ENCDEF_NUM,
|
|
&uiEncDefNum, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
uiEncDefNum = 0;
|
|
}
|
|
|
|
// Get the data type - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_COLUMNS_DATA_TYPE,
|
|
szTmp, sizeof( szTmp),
|
|
&bIsNull, &uiTmpLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull || !uiTmpLen)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_DATA_TYPE);
|
|
goto Exit;
|
|
}
|
|
if (!validDataType( szTmp, &eDataTyp))
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_ILLEGAL_DATA_TYPE);
|
|
goto Exit;
|
|
}
|
|
|
|
uiFlags = 0;
|
|
|
|
// Get the read-only flag - optional.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_COLUMNS_READ_ONLY,
|
|
szTmp, sizeof( szTmp),
|
|
&bIsNull, &uiTmpLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (!bIsNull && uiTmpLen)
|
|
{
|
|
if (!validBooleanValue( szTmp, &bTmp))
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_READ_ONLY_VALUE);
|
|
goto Exit;
|
|
}
|
|
if (bTmp)
|
|
{
|
|
uiFlags |= COL_READ_ONLY;
|
|
}
|
|
}
|
|
|
|
// Get the null-allowed flag
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_COLUMNS_NULL_ALLOWED,
|
|
szTmp, sizeof( szTmp),
|
|
&bIsNull, &uiTmpLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (!bIsNull && uiTmpLen)
|
|
{
|
|
if (!validBooleanValue( szTmp, &bTmp))
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_NULL_ALLOWED_VALUE);
|
|
goto Exit;
|
|
}
|
|
if (bTmp)
|
|
{
|
|
uiFlags |= COL_NULL_ALLOWED;
|
|
}
|
|
}
|
|
|
|
// Add the column to the table entry in the in-memory dictionary.
|
|
|
|
if (RC_BAD( rc = m_pDict->addColumn( uiTableNum, ui64DefRowId,
|
|
uiColumnNum, szColumnName, uiFlags,
|
|
eDataTyp, uiEncDefNum)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (pRow)
|
|
{
|
|
pRow->ReleaseRow();
|
|
}
|
|
|
|
if (pTableCursor)
|
|
{
|
|
pTableCursor->Release();
|
|
}
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Test the index state string to see if it is valid. Set index flags
|
|
accordingly.
|
|
****************************************************************************/
|
|
FSTATIC FLMBOOL validIndexState(
|
|
const char * pszIndexState,
|
|
FLMUINT * puiFlags)
|
|
{
|
|
if (f_stricmp( pszIndexState, SFLM_INDEX_SUSPENDED_STR) == 0)
|
|
{
|
|
(*puiFlags) |= IXD_SUSPENDED;
|
|
(*puiFlags) &= (~(IXD_OFFLINE));
|
|
return( TRUE);
|
|
}
|
|
else if (f_stricmp( pszIndexState, SFLM_INDEX_OFFLINE_STR) == 0)
|
|
{
|
|
(*puiFlags) |= IXD_OFFLINE;
|
|
(*puiFlags) &= (~(IXD_SUSPENDED));
|
|
return( TRUE);
|
|
}
|
|
else if (f_stricmp( pszIndexState, SFLM_INDEX_ONLINE_STR) == 0)
|
|
{
|
|
(*puiFlags) &= (~(IXD_SUSPENDED | IXD_OFFLINE));
|
|
return( TRUE);
|
|
}
|
|
return( FALSE);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Read in all rows from the index table. Create the in-memory structures
|
|
for each index.
|
|
****************************************************************************/
|
|
RCODE F_Db::dictReadIndexes( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_Row * pRow = NULL;
|
|
FLMUINT64 ui64DefRowId;
|
|
FSTableCursor * pTableCursor = NULL;
|
|
FLMUINT uiEncDefNum;
|
|
FLMUINT uiTableNum;
|
|
char szIndexName [MAX_INDEX_NAME_LEN + 1];
|
|
FLMUINT uiIndexNameLen;
|
|
FLMUINT uiIndexNum;
|
|
char szTmp [50];
|
|
FLMUINT uiTmpLen;
|
|
FLMUINT uiLanguage;
|
|
FLMUINT64 ui64LastRowIndexed;
|
|
FLMUINT uiNumKeyComponents;
|
|
FLMUINT uiNumDataComponents;
|
|
FLMUINT uiFlags;
|
|
FLMBOOL bIsNull;
|
|
|
|
if ((pTableCursor = f_new FSTableCursor) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pTableCursor->setupRange( this, SFLM_TBLNUM_INDEXES,
|
|
1, FLM_MAX_UINT64, NULL, NULL, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Read through all rows in the table. Each row defines an index on
|
|
// a table in the database, so we add it to the in-memory dictionary.
|
|
|
|
for (;;)
|
|
{
|
|
if (RC_BAD( rc = pTableCursor->nextRow( this, &pRow, &ui64DefRowId)))
|
|
{
|
|
if (rc == NE_SFLM_EOF_HIT)
|
|
{
|
|
rc = NE_SFLM_OK;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the index name - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_INDEXES_INDEX_NAME,
|
|
szIndexName, sizeof( szIndexName),
|
|
&bIsNull, &uiIndexNameLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull || !uiIndexNameLen)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_INDEX_NAME);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the index number - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_INDEXES_INDEX_NUM,
|
|
&uiIndexNum, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_INDEX_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the table number - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_INDEXES_TABLE_NUM,
|
|
&uiTableNum, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_TABLE_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the encryption definition number - optional.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_INDEXES_ENCDEF_NUM,
|
|
&uiEncDefNum, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
uiEncDefNum = 0;
|
|
}
|
|
|
|
// Get the number of key components - optional, defaults to zero.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_INDEXES_NUM_KEY_COMPONENTS,
|
|
&uiNumKeyComponents, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
uiNumKeyComponents = 0;
|
|
}
|
|
|
|
// Get the number of data components - optional, defaults to zero
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_INDEXES_NUM_DATA_COMPONENTS,
|
|
&uiNumDataComponents, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
uiNumDataComponents = 0;
|
|
}
|
|
|
|
// Get index language - optional.
|
|
|
|
uiLanguage = FLM_US_LANG;
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_INDEXES_LANGUAGE,
|
|
szTmp, sizeof( szTmp),
|
|
&bIsNull, &uiTmpLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (!bIsNull && uiTmpLen)
|
|
{
|
|
if (uiTmpLen != 2)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_ILLEGAL_LANGUAGE);
|
|
goto Exit;
|
|
}
|
|
|
|
uiLanguage = f_languageToNum( szTmp);
|
|
|
|
// f_languageToNum returns FLM_US_LANG for all strings it doesn't
|
|
// recognize. If that is what is returned make sure that the string
|
|
// is "US".
|
|
|
|
if (uiLanguage == FLM_US_LANG && f_stricmp( szTmp, "US") != 0)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_ILLEGAL_LANGUAGE);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Get the last row indexed, optional - defaults to zero.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT64( this, SFLM_COLNUM_INDEXES_LAST_ROW_INDEXED,
|
|
&ui64LastRowIndexed, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
ui64LastRowIndexed = 0;
|
|
}
|
|
|
|
// Get the index state - optional.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_INDEXES_INDEX_STATE,
|
|
szTmp, sizeof( szTmp), &bIsNull, &uiTmpLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiFlags = 0;
|
|
if (!bIsNull && uiTmpLen)
|
|
{
|
|
if (!validIndexState( szTmp, &uiFlags))
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_INDEX_STATE);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Add the index to the the in-memory dictionary.
|
|
|
|
if (RC_BAD( rc = m_pDict->addIndex( uiIndexNum, ui64DefRowId,
|
|
szIndexName, uiTableNum, uiEncDefNum,
|
|
uiFlags, uiNumKeyComponents,
|
|
uiNumDataComponents, uiLanguage,
|
|
ui64LastRowIndexed)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (pRow)
|
|
{
|
|
pRow->ReleaseRow();
|
|
}
|
|
|
|
if (pTableCursor)
|
|
{
|
|
pTableCursor->Release();
|
|
}
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Determine if the "index on" value for an index component is valid.
|
|
****************************************************************************/
|
|
FSTATIC FLMBOOL validIndexOnValue(
|
|
const char * pszIndexOn,
|
|
FLMUINT * puiFlags)
|
|
{
|
|
if (f_stricmp( pszIndexOn, SFLM_VALUE_OPTION_STR) == 0)
|
|
{
|
|
(*puiFlags) |= ICD_VALUE;
|
|
return( TRUE);
|
|
}
|
|
else if (f_stricmp( pszIndexOn, SFLM_PRESENCE_OPTION_STR) == 0)
|
|
{
|
|
(*puiFlags) |= ICD_PRESENCE;
|
|
return( TRUE);
|
|
}
|
|
else if (f_stricmp( pszIndexOn, SFLM_SUBSTRING_OPTION_STR) == 0)
|
|
{
|
|
(*puiFlags) |= ICD_SUBSTRING;
|
|
return( TRUE);
|
|
}
|
|
else if (f_stricmp( pszIndexOn, SFLM_EACHWORD_OPTION_STR) == 0)
|
|
{
|
|
(*puiFlags) |= ICD_EACHWORD;
|
|
return( TRUE);
|
|
}
|
|
else if (f_stricmp( pszIndexOn, SFLM_METAPHONE_OPTION_STR) == 0)
|
|
{
|
|
(*puiFlags) |= ICD_METAPHONE;
|
|
return( TRUE);
|
|
}
|
|
return( FALSE);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Determine if the "compare rules" value for an index component is valid.
|
|
NOTE: pszCompareRules will be modified, but it doesn't matter because
|
|
the caller should have passed a temporary buffer.
|
|
****************************************************************************/
|
|
FSTATIC FLMBOOL validCompareRulesValue(
|
|
char * pszCompareRules,
|
|
FLMUINT * puiCompareRules)
|
|
{
|
|
char * pszRuleStart;
|
|
char * pszRuleEnd;
|
|
|
|
pszRuleStart = pszCompareRules;
|
|
while (*pszRuleStart)
|
|
{
|
|
// Skip leading spaces, tabs, newlines, and commas.
|
|
|
|
while (*pszRuleStart == ' ' || *pszRuleStart == ',' ||
|
|
*pszRuleStart == '\t' || *pszRuleStart == '\n')
|
|
{
|
|
pszRuleStart++;
|
|
}
|
|
|
|
// If we are at the end, there are no more rules to look at.
|
|
|
|
if (*pszRuleStart == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Go until we hit a comma or whitespace.
|
|
|
|
pszRuleEnd = pszRuleStart;
|
|
while (*pszRuleEnd && *pszRuleEnd != ' ' && *pszRuleEnd != ',' &&
|
|
*pszRuleEnd != '\t' && *pszRuleEnd != '\n')
|
|
{
|
|
pszRuleEnd++;
|
|
}
|
|
if (*pszRuleEnd)
|
|
{
|
|
*pszRuleEnd = 0;
|
|
pszRuleEnd++;
|
|
}
|
|
|
|
// See if the rule is valid.
|
|
|
|
if (f_stricmp( SFLM_CASE_INSENSITIVE_OPTION_STR, pszRuleStart) == 0)
|
|
{
|
|
(*puiCompareRules) |= FLM_COMP_CASE_INSENSITIVE;
|
|
}
|
|
else if (f_stricmp( SFLM_MINSPACES_OPTION_STR, pszRuleStart) == 0)
|
|
{
|
|
(*puiCompareRules) |= FLM_COMP_COMPRESS_WHITESPACE;
|
|
}
|
|
else if (f_stricmp( SFLM_WHITESPACE_AS_SPACE_STR, pszRuleStart) == 0)
|
|
{
|
|
(*puiCompareRules) |= FLM_COMP_WHITESPACE_AS_SPACE;
|
|
}
|
|
else if (f_stricmp( SFLM_IGNORE_LEADINGSPACES_OPTION_STR, pszRuleStart) == 0)
|
|
{
|
|
(*puiCompareRules) |= FLM_COMP_IGNORE_LEADING_SPACE;
|
|
}
|
|
else if (f_stricmp( SFLM_IGNORE_TRAILINGSPACES_OPTION_STR, pszRuleStart) == 0)
|
|
{
|
|
(*puiCompareRules) |= FLM_COMP_IGNORE_TRAILING_SPACE;
|
|
}
|
|
else if (f_stricmp( SFLM_NOUNDERSCORE_OPTION_STR, pszRuleStart) == 0)
|
|
{
|
|
(*puiCompareRules) |= FLM_COMP_NO_UNDERSCORES;
|
|
}
|
|
else if (f_stricmp( SFLM_NOSPACE_OPTION_STR, pszRuleStart) == 0)
|
|
{
|
|
(*puiCompareRules) |= FLM_COMP_NO_WHITESPACE;
|
|
}
|
|
else if (f_stricmp( SFLM_NODASH_OPTION_STR, pszRuleStart) == 0)
|
|
{
|
|
(*puiCompareRules) |= FLM_COMP_NO_DASHES;
|
|
}
|
|
else
|
|
{
|
|
return( FALSE);
|
|
}
|
|
}
|
|
return( TRUE);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Read in all rows from the index component table. Create the in-memory
|
|
structure for each index component.
|
|
****************************************************************************/
|
|
RCODE F_Db::dictReadIndexComponents( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
F_Row * pRow = NULL;
|
|
FLMUINT64 ui64DefRowId;
|
|
FSTableCursor * pTableCursor = NULL;
|
|
FLMUINT uiColumnNum;
|
|
FLMUINT uiIndexNum;
|
|
char szTmp [200];
|
|
FLMUINT uiTmpLen;
|
|
FLMBOOL bTmp;
|
|
FLMUINT uiKeyComponent;
|
|
FLMUINT uiDataComponent;
|
|
FLMUINT uiFlags;
|
|
FLMUINT uiCompareRules;
|
|
FLMUINT uiLimit;
|
|
FLMBOOL bIsNull;
|
|
|
|
if ((pTableCursor = f_new FSTableCursor) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pTableCursor->setupRange( this, SFLM_TBLNUM_INDEX_COMPONENTS,
|
|
1, FLM_MAX_UINT64, NULL, NULL, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Read through all rows in the table. Each row defines an index component
|
|
// for an index in the database, so we add it to the in-memory dictionary.
|
|
|
|
for (;;)
|
|
{
|
|
if (RC_BAD( rc = pTableCursor->nextRow( this, &pRow, &ui64DefRowId)))
|
|
{
|
|
if (rc == NE_SFLM_EOF_HIT)
|
|
{
|
|
rc = NE_SFLM_OK;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the index number - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_INDEX_COMP_INDEX_NUM,
|
|
&uiIndexNum, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_INDEX_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the column number - required.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_INDEX_COMP_COLUMN_NUM,
|
|
&uiColumnNum, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NULL_COLUMN_NUM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the key component number - optional, defaults to zero.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_INDEX_COMP_KEY_COMPONENT,
|
|
&uiKeyComponent, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
uiKeyComponent = 0;
|
|
}
|
|
|
|
// Get the data component number - optional, defaults to zero.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_INDEX_COMP_DATA_COMPONENT,
|
|
&uiDataComponent, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
uiDataComponent = 0;
|
|
}
|
|
|
|
// We must have at least one of the components non-zero.
|
|
|
|
if (!uiKeyComponent && !uiDataComponent)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_NO_COMP_NUM_FOR_INDEX_COLUMN);
|
|
goto Exit;
|
|
}
|
|
|
|
uiFlags = 0;
|
|
uiCompareRules = 0;
|
|
uiLimit = 0;
|
|
|
|
// For data components we just ignore the index-on, compare-rules,
|
|
// sort-descending, sort-missing-high, and limit columns.
|
|
|
|
if (uiKeyComponent)
|
|
{
|
|
|
|
// Get what we are indexing on - optional, defaults to value.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_INDEX_COMP_INDEX_ON,
|
|
szTmp, sizeof( szTmp),
|
|
&bIsNull, &uiTmpLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull || !uiTmpLen)
|
|
{
|
|
uiFlags |= ICD_VALUE;
|
|
}
|
|
else
|
|
{
|
|
if (!validIndexOnValue( szTmp, &uiFlags))
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_INDEX_ON_VALUE);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Get compare rules - optional, defaults to none.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_INDEX_COMP_COMPARE_RULES,
|
|
szTmp, sizeof( szTmp), &bIsNull, &uiTmpLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (!bIsNull && uiTmpLen)
|
|
{
|
|
if (!validCompareRulesValue( szTmp, &uiCompareRules))
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_COMPARE_RULES_VALUE);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Get the sort-descending flag - optional, defaults to sort ascending.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_INDEX_COMP_SORT_DESCENDING,
|
|
szTmp, sizeof( szTmp), &bIsNull, &uiTmpLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (!bIsNull && uiTmpLen)
|
|
{
|
|
if (!validBooleanValue( szTmp, &bTmp))
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_SORT_DESCENDING_VALUE);
|
|
goto Exit;
|
|
}
|
|
if (bTmp)
|
|
{
|
|
uiFlags |= ICD_DESCENDING;
|
|
}
|
|
}
|
|
|
|
// Get the sort-missing-high flag - optional, defaults to sort missing low.
|
|
|
|
if (RC_BAD( rc = pRow->getUTF8( this, SFLM_COLNUM_INDEX_COMP_SORT_MISSING_HIGH,
|
|
szTmp, sizeof( szTmp), &bIsNull, &uiTmpLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (!bIsNull && uiTmpLen)
|
|
{
|
|
if (!validBooleanValue( szTmp, &bTmp))
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_SORT_MISSING_HIGH_VALUE);
|
|
goto Exit;
|
|
}
|
|
if (bTmp)
|
|
{
|
|
uiFlags |= ICD_MISSING_HIGH;
|
|
}
|
|
}
|
|
|
|
// Get the limit - defaults to different things depending on
|
|
// what we are indexing.
|
|
|
|
if (RC_BAD( rc = pRow->getUINT( this, SFLM_COLNUM_INDEX_COMP_LIMIT,
|
|
&uiLimit, &bIsNull)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bIsNull)
|
|
{
|
|
uiLimit = (FLMUINT)((uiFlags & ICD_SUBSTRING)
|
|
? (FLMUINT)ICD_DEFAULT_SUBSTRING_LIMIT
|
|
: (FLMUINT)ICD_DEFAULT_LIMIT);
|
|
}
|
|
}
|
|
|
|
// Add the index component to the the in-memory dictionary.
|
|
|
|
if (RC_BAD( rc = m_pDict->addIndexComponent( uiIndexNum, ui64DefRowId,
|
|
uiColumnNum,
|
|
uiFlags, uiCompareRules, uiLimit,
|
|
uiKeyComponent, uiDataComponent)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (pRow)
|
|
{
|
|
pRow->ReleaseRow();
|
|
}
|
|
|
|
if (pTableCursor)
|
|
{
|
|
pTableCursor->Release();
|
|
}
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Open a dictionary by reading in all of the dictionary tables
|
|
from the dictionaries.
|
|
****************************************************************************/
|
|
RCODE F_Db::dictOpen( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
|
|
// At this point, better not be pointing to a dictionary.
|
|
|
|
flmAssert( !m_pDict);
|
|
|
|
// Should never get here for a temporary database.
|
|
|
|
flmAssert( !m_pDatabase->m_bTempDb);
|
|
|
|
// Allocate a new F_Dict object for reading the dictionary
|
|
// into memory.
|
|
|
|
if ((m_pDict = f_new F_Dict) == NULL)
|
|
{
|
|
rc = RC_SET( NE_SFLM_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Allocate the fixed collections and indexes and set them up
|
|
|
|
if (RC_BAD( rc = m_pDict->setupPredefined()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Read in the LFH's for the predefined stuff.
|
|
|
|
if (RC_BAD( rc = dictReadLFH()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If dictionary tables are not yet set up, do nothing.
|
|
|
|
if (m_pDict->m_pTableTbl [SFLM_TBLNUM_TABLES - 1].lfInfo.uiBlkAddress)
|
|
{
|
|
|
|
// Read in definitions in the following order:
|
|
// 1) encryption definitions
|
|
// 2) table definitions
|
|
// 3) column definitions
|
|
// 4) index definitions
|
|
// 5) index components
|
|
// This guarantees that things will be defined by the
|
|
// time they are referenced.
|
|
|
|
if (RC_BAD( rc = dictReadEncDefs()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = dictReadTables()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = dictReadColumns()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = dictReadIndexes()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = dictReadIndexComponents()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Must read LFHs to get the LFILE information for the
|
|
// tables and indexes we have just added.
|
|
|
|
if (RC_BAD( rc = dictReadLFH()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Verify the dictionary after it is all read into memory.
|
|
|
|
if (RC_BAD( rc = m_pDict->verifyDict()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc) && m_pDict)
|
|
{
|
|
m_pDict->Release();
|
|
m_pDict = NULL;
|
|
}
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Creates a new dictionary for a database.
|
|
This occurs on database create and on a dictionary change.
|
|
****************************************************************************/
|
|
RCODE F_Db::createNewDict( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
|
|
// Unlink the DB from the current F_Dict object, if any.
|
|
|
|
if (m_pDict)
|
|
{
|
|
m_pDatabase->lockMutex();
|
|
unlinkFromDict();
|
|
m_pDatabase->unlockMutex();
|
|
}
|
|
|
|
// Allocate a new F_Dict object for the new dictionary we
|
|
// are going to create.
|
|
|
|
if (RC_BAD( rc = dictOpen()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Update the F_Db flags to indicate that the dictionary
|
|
// was updated.
|
|
|
|
m_uiFlags |= FDB_UPDATED_DICTIONARY;
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Create the tables and indexes needed for storing dictionary
|
|
definitions.
|
|
****************************************************************************/
|
|
RCODE F_Db::dictCreate( void)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
LFILE TempLFile;
|
|
|
|
// This should never be called for a temporary database.
|
|
|
|
flmAssert( !m_pDatabase->m_bTempDb);
|
|
|
|
// Create the dictionary tables
|
|
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_TBLNUM_ENCDEFS, SFLM_LF_TABLE, FALSE, TRUE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_TBLNUM_TABLES, SFLM_LF_TABLE, FALSE, TRUE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_TBLNUM_COLUMNS, SFLM_LF_TABLE, FALSE, TRUE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_TBLNUM_INDEXES, SFLM_LF_TABLE, FALSE, TRUE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_TBLNUM_INDEX_COMPONENTS, SFLM_LF_TABLE, FALSE, TRUE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_TBLNUM_BLOCK_CHAINS, SFLM_LF_TABLE, FALSE, TRUE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Create the dictionary indexes
|
|
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_IXNUM_ENCDEF_NAME, SFLM_LF_INDEX, FALSE, FALSE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_IXNUM_TABLE_NAME, SFLM_LF_INDEX, FALSE, FALSE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_IXNUM_TABLE_ENCDEF_NUM, SFLM_LF_INDEX, FALSE, FALSE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_IXNUM_COLUMN_TABLE_NUM, SFLM_LF_INDEX, FALSE, FALSE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_IXNUM_COLUMN_ENCDEF_NUM, SFLM_LF_INDEX, FALSE, FALSE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_IXNUM_INDEX_NAME, SFLM_LF_INDEX, FALSE, FALSE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_IXNUM_INDEX_TABLE_NUM, SFLM_LF_INDEX, FALSE, FALSE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_IXNUM_INDEX_ENCDEF_NUM, SFLM_LF_INDEX, FALSE, FALSE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD(rc = m_pDatabase->lFileCreate( this, &TempLFile,
|
|
SFLM_IXNUM_INDEX_COMP_INDEX_NUM, SFLM_LF_INDEX, FALSE, FALSE, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Create a new dictionary we can work with.
|
|
|
|
if (RC_BAD( rc = createNewDict()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Lookup a name in the name table
|
|
****************************************************************************/
|
|
NAME_INFO * F_NameTable::findName(
|
|
const char * pszName,
|
|
FLMUINT * puiInsertPos)
|
|
{
|
|
NAME_INFO * pNameInfo = NULL;
|
|
const char * pszTblName;
|
|
FLMUINT uiTblSize;
|
|
FLMUINT uiLow;
|
|
FLMUINT uiMid;
|
|
FLMUINT uiHigh;
|
|
FLMINT iCmp;
|
|
|
|
if (!m_bTableSorted)
|
|
{
|
|
sortNames();
|
|
}
|
|
|
|
// Do binary search in the table
|
|
|
|
if ((uiTblSize = m_uiNumNames) == 0)
|
|
{
|
|
if (puiInsertPos)
|
|
{
|
|
*puiInsertPos = 0;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
uiHigh = --uiTblSize;
|
|
uiLow = 0;
|
|
for (;;)
|
|
{
|
|
uiMid = (uiLow + uiHigh) / 2;
|
|
|
|
pszTblName = m_pNames [uiMid].pszName;
|
|
if ((iCmp = (FLMINT)f_strcmp( pszName, pszTblName)) == 0)
|
|
{
|
|
|
|
// Found Match
|
|
|
|
pNameInfo = &m_pNames [uiMid];
|
|
if (puiInsertPos)
|
|
{
|
|
*puiInsertPos = uiMid;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
// Check if we are done
|
|
|
|
if (uiLow >= uiHigh)
|
|
{
|
|
|
|
// Done, item not found
|
|
|
|
if (puiInsertPos)
|
|
{
|
|
*puiInsertPos = (iCmp < 0)
|
|
? uiMid
|
|
: uiMid + 1;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
if (iCmp < 0)
|
|
{
|
|
if (uiMid == 0)
|
|
{
|
|
if (puiInsertPos)
|
|
{
|
|
*puiInsertPos = 0;
|
|
}
|
|
goto Exit;
|
|
}
|
|
uiHigh = uiMid - 1;
|
|
}
|
|
else
|
|
{
|
|
if (uiMid == uiTblSize)
|
|
{
|
|
if (puiInsertPos)
|
|
{
|
|
*puiInsertPos = uiMid + 1;
|
|
}
|
|
goto Exit;
|
|
}
|
|
uiLow = uiMid + 1;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( pNameInfo);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Desc: Swap two entries in tag info table during sort.
|
|
*****************************************************************************/
|
|
FINLINE void nameInfoSwap(
|
|
NAME_INFO * pNameInfoTbl,
|
|
FLMUINT uiPos1,
|
|
FLMUINT uiPos2)
|
|
{
|
|
NAME_INFO tmpNameInfo;
|
|
|
|
tmpNameInfo.pszName = pNameInfoTbl [uiPos1].pszName;
|
|
tmpNameInfo.uiItemNum = pNameInfoTbl [uiPos1].uiItemNum;
|
|
pNameInfoTbl [uiPos1].pszName = pNameInfoTbl [uiPos2].pszName;
|
|
pNameInfoTbl [uiPos1].uiItemNum = pNameInfoTbl [uiPos2].uiItemNum;
|
|
pNameInfoTbl [uiPos2].pszName = tmpNameInfo.pszName;
|
|
pNameInfoTbl [uiPos2].uiItemNum = tmpNameInfo.uiItemNum;
|
|
}
|
|
|
|
/***************************************************************************
|
|
Desc: Comparison function for sorting name table
|
|
****************************************************************************/
|
|
FINLINE FLMINT compareNameInfo(
|
|
NAME_INFO * pNameInfo1,
|
|
NAME_INFO * pNameInfo2,
|
|
FLMBOOL * pbDuplicateNames)
|
|
{
|
|
FLMINT iCmp = (FLMINT)f_strcmp( pNameInfo1->pszName, pNameInfo2->pszName);
|
|
|
|
if (iCmp == 0)
|
|
{
|
|
*pbDuplicateNames = TRUE;
|
|
return( 0);
|
|
}
|
|
return( (iCmp < 0) ? -1 : 1);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Desc: Sort a name table.
|
|
****************************************************************************/
|
|
FSTATIC void sortNameTbl(
|
|
NAME_INFO * pNameInfoTbl,
|
|
FLMUINT uiLowerBounds,
|
|
FLMUINT uiUpperBounds,
|
|
FLMBOOL * pbDuplicateNames)
|
|
{
|
|
FLMUINT uiLBPos;
|
|
FLMUINT uiUBPos;
|
|
FLMUINT uiMIDPos;
|
|
FLMUINT uiLeftItems;
|
|
FLMUINT uiRightItems;
|
|
NAME_INFO * pCurNameInfo;
|
|
FLMINT iCompare;
|
|
|
|
Iterate_Larger_Half:
|
|
|
|
uiUBPos = uiUpperBounds;
|
|
uiLBPos = uiLowerBounds;
|
|
uiMIDPos = (uiUpperBounds + uiLowerBounds + 1) / 2;
|
|
pCurNameInfo = &pNameInfoTbl [uiMIDPos];
|
|
for (;;)
|
|
{
|
|
while (uiLBPos == uiMIDPos || // Don't compare with target
|
|
((iCompare =
|
|
compareNameInfo( &pNameInfoTbl [uiLBPos], pCurNameInfo,
|
|
pbDuplicateNames)) < 0))
|
|
{
|
|
if (uiLBPos >= uiUpperBounds)
|
|
{
|
|
break;
|
|
}
|
|
uiLBPos++;
|
|
}
|
|
|
|
while (uiUBPos == uiMIDPos || // Don't compare with target
|
|
(((iCompare =
|
|
compareNameInfo( pCurNameInfo, &pNameInfoTbl [uiUBPos],
|
|
pbDuplicateNames)) < 0)))
|
|
{
|
|
if (!uiUBPos)
|
|
{
|
|
break;
|
|
}
|
|
uiUBPos--;
|
|
}
|
|
|
|
if (uiLBPos < uiUBPos ) // Interchange and continue loop.
|
|
{
|
|
|
|
// Exchange [uiLBPos] with [uiUBPos].
|
|
|
|
nameInfoSwap( pNameInfoTbl, uiLBPos, uiUBPos);
|
|
uiLBPos++; // Scan from left to right.
|
|
uiUBPos--; // Scan from right to left.
|
|
}
|
|
else // Past each other - done
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Check for swap( LB, MID ) - cases 3 and 4
|
|
|
|
if( uiLBPos < uiMIDPos )
|
|
{
|
|
|
|
// Exchange [uiLBPos] with [uiMIDPos]
|
|
|
|
nameInfoSwap( pNameInfoTbl, uiMIDPos, uiLBPos);
|
|
uiMIDPos = uiLBPos;
|
|
}
|
|
else if( uiMIDPos < uiUBPos )
|
|
{
|
|
|
|
// Exchange [uUBPos] with [uiMIDPos]
|
|
|
|
nameInfoSwap( pNameInfoTbl, uiMIDPos, uiUBPos);
|
|
uiMIDPos = uiUBPos;
|
|
}
|
|
|
|
// Check the left piece.
|
|
|
|
uiLeftItems = (uiLowerBounds + 1 < uiMIDPos )
|
|
? uiMIDPos - uiLowerBounds // 2 or more
|
|
: 0;
|
|
uiRightItems = (uiMIDPos + 1 < uiUpperBounds )
|
|
? uiUpperBounds - uiMIDPos // 2 or more
|
|
: 0;
|
|
|
|
if( uiLeftItems < uiRightItems )
|
|
{
|
|
|
|
// Recurse on the LEFT side and goto the top on the RIGHT side.
|
|
|
|
if (uiLeftItems )
|
|
{
|
|
sortNameTbl( pNameInfoTbl, uiLowerBounds, uiMIDPos - 1, pbDuplicateNames);
|
|
}
|
|
uiLowerBounds = uiMIDPos + 1;
|
|
goto Iterate_Larger_Half;
|
|
}
|
|
else if (uiLeftItems ) // Compute a truth table to figure out this check.
|
|
{
|
|
|
|
// Recurse on the RIGHT side and goto the top for the LEFT side.
|
|
|
|
if (uiRightItems )
|
|
{
|
|
sortNameTbl( pNameInfoTbl, uiMIDPos + 1, uiUpperBounds, pbDuplicateNames);
|
|
}
|
|
uiUpperBounds = uiMIDPos - 1;
|
|
goto Iterate_Larger_Half;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Add a name to the table.
|
|
****************************************************************************/
|
|
RCODE F_NameTable::addName(
|
|
const char * pszName,
|
|
FLMUINT uiItemNum,
|
|
FLMBOOL bCheckDuplicates,
|
|
RCODE rcDuplicateError,
|
|
FLMUINT uiTableGrowSize)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
FLMUINT uiInsertPos;
|
|
|
|
if (!pszName || !uiItemNum)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( NE_SFLM_INVALID_PARM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (bCheckDuplicates)
|
|
{
|
|
|
|
// Make sure that the name is not already used.
|
|
|
|
if (findName( pszName, &uiInsertPos))
|
|
{
|
|
rc = RC_SET( rcDuplicateError);
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uiInsertPos = m_uiNumNames;
|
|
m_bTableSorted = FALSE;
|
|
}
|
|
|
|
// See if we need to grow the table.
|
|
|
|
if (m_uiNumNames == m_uiTblSize)
|
|
{
|
|
FLMUINT uiNewSize = m_uiTblSize + uiTableGrowSize;
|
|
|
|
if (RC_BAD( rc = f_realloc( sizeof( NAME_INFO) * uiNewSize,
|
|
&m_pNames)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
m_uiTblSize = uiNewSize;
|
|
}
|
|
|
|
// If necessary, move names up in the table to make room for the
|
|
// new name.
|
|
|
|
if (uiInsertPos < m_uiNumNames)
|
|
{
|
|
f_memmove( &m_pNames [uiInsertPos + 1],
|
|
&m_pNames [uiInsertPos],
|
|
sizeof( NAME_INFO) * (m_uiNumNames - uiInsertPos));
|
|
}
|
|
m_pNames [uiInsertPos].pszName = pszName;
|
|
m_pNames [uiInsertPos].uiItemNum = uiItemNum;
|
|
m_uiNumNames++;
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Copy a name into the name table.
|
|
****************************************************************************/
|
|
RCODE F_NameTable::copyName(
|
|
const char * pszName,
|
|
FLMUINT uiItemNum,
|
|
const char ** ppszDestName,
|
|
F_Pool * pPool)
|
|
{
|
|
RCODE rc = NE_SFLM_OK;
|
|
FLMUINT uiNameLen;
|
|
char * pszDestName;
|
|
|
|
uiNameLen = f_strlen( pszName) + 1;
|
|
if (RC_BAD( rc = pPool->poolAlloc( uiNameLen, (void **)&pszDestName)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
f_memcpy( pszDestName, pszName, uiNameLen);
|
|
*ppszDestName = pszDestName;
|
|
|
|
if (RC_BAD( rc = addName( pszDestName, uiItemNum,
|
|
FALSE, NE_SFLM_OK, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Sort the name table.
|
|
****************************************************************************/
|
|
void F_NameTable::sortNames( void)
|
|
{
|
|
if (!m_bTableSorted)
|
|
{
|
|
m_bDuplicateNames = FALSE;
|
|
if (m_uiNumNames > 1)
|
|
{
|
|
sortNameTbl( m_pNames, 0, m_uiNumNames - 1, &m_bDuplicateNames);
|
|
}
|
|
m_bTableSorted = TRUE;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Remove a name from the table
|
|
****************************************************************************/
|
|
void F_NameTable::removeName(
|
|
const char * pszName)
|
|
{
|
|
FLMUINT uiPos;
|
|
|
|
if (findName( pszName, &uiPos) != NULL)
|
|
{
|
|
if (uiPos < m_uiNumNames - 1)
|
|
{
|
|
f_memmove( &m_pNames [uiPos], &m_pNames [uiPos + 1],
|
|
sizeof( NAME_INFO) * (m_uiNumNames - uiPos - 1));
|
|
}
|
|
m_uiNumNames--;
|
|
}
|
|
}
|
|
|