summaryrefslogtreecommitdiff
path: root/src/core/xbdbf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/xbdbf.cpp')
-rwxr-xr-xsrc/core/xbdbf.cpp267
1 files changed, 231 insertions, 36 deletions
diff --git a/src/core/xbdbf.cpp b/src/core/xbdbf.cpp
index 4033ef9..8904a6d 100755
--- a/src/core/xbdbf.cpp
+++ b/src/core/xbdbf.cpp
@@ -159,12 +159,14 @@ xbInt16 xbDbf::Abort(){
//! @brief Add an index to the internal list of indices for this table.
/*!
The index list is used during any table update process to update any open
- index file. Index files can contain one or more tags.
+ index file. Index files can contain one or more tags. Temporary tags
+ are not included here because they are created after a table is open
+ and will be deleted when the table is closed.
\param ixIn Pointer to index object for a given index file.
- \param sFmt NDX or MDX.
+ \param sFmt NDX, MDX or TDX.
\returns <a href="xbretcod_8h.html">Return Codes</a>
-
+
*/
xbInt16 xbDbf::AddIndex( xbIx * ixIn, const xbString &sFmt ){
@@ -295,6 +297,7 @@ xbInt16 xbDbf::AppendRecord(){
// calculate the latest header information
xbDate d;
+ d.Sysdate();
cUpdateYY = (char) d.YearOf() - 1900;
cUpdateMM = (char) d.MonthOf();
cUpdateDD = (char) d.DayOf( XB_FMT_MONTH );
@@ -411,7 +414,7 @@ xbInt16 xbDbf::AppendRecord(){
\param sIxType Currently only NDX. Future versions will support additional non prod index types.
\param sIxName The index name.
\param iOpt 0 - Add index to .INF if not already there<br>
- 1 - Remove index from .INF if there
+ 1 - Remove index from .INF if exists
\returns <a href="xbretcod_8h.html">Return Codes</a>
@@ -534,7 +537,7 @@ xbInt16 xbDbf::BlankRecord()
This method is used to check an index tag's intgerity.
\param iTagOpt 0 - Check current tag<br>
- 1 - Check all tag<br>
+ 1 - Check all tags<br>
\param iOutputOpt Output message destination<br>
0 = stdout<br>
@@ -585,21 +588,41 @@ xbInt16 xbDbf::CheckTagIntegrity( xbInt16 iTagOpt, xbInt16 iOutputOpt ){
\param iTagOpt 0 - Reindex current tag<br>
1 - Reindex all tags<br>
+ 2 - Reindex for tag identified by vpTag
+ \param iErrorOpt 0 - Don't delete tag on reindex failure<br>
+ 1 - Delete tag on reindex failure
+ \param vpTag if option 2 used, pointer to tag to reindex
\returns <a href="xbretcod_8h.html">Return Codes</a>
*/
-xbInt16 xbDbf::Reindex( xbInt16 iTagOpt ){
+xbInt16 xbDbf::Reindex( xbInt16 iTagOpt, xbInt16 iErrorOpt, xbIx **ppIx, void **vppTag ){
xbInt16 iRc = XB_NO_ERROR;
xbInt16 iErrorStop = 0;
void *vp;
+ xbString sType;
+ xbString sTagName;
+
+ if( iTagOpt < 0 || iTagOpt > 2 || (iTagOpt == 2 && (!ppIx || !vppTag )))
+ return XB_INVALID_OPTION;
+
+
+ #ifdef XB_BLOCKREAD_SUPPORT
+ xbBool bOriginalBlockReadSts = GetBlockReadStatus();
+ #endif
+
try{
+
+ #ifdef XB_BLOCKREAD_SUPPORT
+ if( !bOriginalBlockReadSts )
+ EnableBlockReadProcessing();
+ #endif
+
if( iTagOpt == 0 ){
if( pCurIx ){
- iRc = pCurIx->Reindex( &vpCurIxTag );
- if( iRc != XB_NO_ERROR ){
+ if(( iRc = pCurIx->Reindex( &vpCurIxTag )) != XB_NO_ERROR ){
iErrorStop = 100;
throw iRc;
}
@@ -608,7 +631,7 @@ xbInt16 xbDbf::Reindex( xbInt16 iTagOpt ){
return XB_INVALID_TAG;
}
- } else {
+ } else if( iTagOpt == 1 ) {
xbLinkListNode<xbTag *> *llN = GetTagList();
xbTag *pTag;
@@ -622,6 +645,19 @@ xbInt16 xbDbf::Reindex( xbInt16 iTagOpt ){
}
llN = llN->GetNextNode();
}
+ } else if( iTagOpt == 2 ){
+
+ // xbIx *pIx;
+ // pIx = *ppIx;
+ xbIx *pIx = *ppIx;
+ // void *vpTag;
+ // vpTag = *vppTag;
+ void *vpTag = *vppTag;
+
+ if(( iRc = pIx->Reindex( &vpTag )) != XB_NO_ERROR ){
+ iErrorStop = 120;
+ throw iRc;
+ }
}
}
catch (xbInt16 iRc ){
@@ -630,6 +666,12 @@ xbInt16 xbDbf::Reindex( xbInt16 iTagOpt ){
xbase->WriteLogMessage( sMsg.Str() );
xbase->WriteLogMessage( GetErrorMessage( iRc ));
}
+
+ #ifdef XB_BLOCKREAD_SUPPORT
+ if( !bOriginalBlockReadSts )
+ DisableBlockReadProcessing();
+ #endif
+
return iRc;
}
@@ -939,10 +981,10 @@ xbInt16 xbDbf::CopyDbfStructure( xbDbf * dNewTable, const xbString &sNewTableNam
#ifdef XB_INDEX_SUPPORT
//! @brief Create a new tag (index) for this dbf file (table).
/*!
- This routine creates a new tag (index) on a dbf file. The library currently supports NDX and MDX
+ This routine creates a new tag (index) on a dbf file. The library currently supports NDX, MDX ans TDX.
indices. If you don't have a specific need for an NDX file, use MDX.
- \param sIxType "MDX" or "NDX".
+ \param sIxType "MDX", "NDX" or "NTX".
\param sName Index or tag name.
\param sKey Index key expression,
\param sFilter Filter expression. Not applicable for NDX indices.
@@ -1002,6 +1044,8 @@ xbInt16 xbDbf::CreateTag( const xbString &sIxType, const xbString &sName, const
}
*pIxOut = ixNdx;
+
+
// Set the current tag if one not already set
if( sCurIxType == "" ){
sCurIxType = "NDX";
@@ -1031,6 +1075,7 @@ xbInt16 xbDbf::CreateTag( const xbString &sIxType, const xbString &sName, const
ixMdx = (xbIxMdx *) ixList->ix;
bMdxFound = xbTrue;
}
+ ixList = ixList->next;
}
if( !bMdxFound )
@@ -1061,7 +1106,53 @@ xbInt16 xbDbf::CreateTag( const xbString &sIxType, const xbString &sName, const
pCurIx = ixMdx;
vpCurIxTag = ixMdx->GetTag(0);
}
+ #endif
+
+ #ifdef XB_TDX_SUPPORT
+ } else if( sIxType == "TDX" ){
+
+ if( GetVersion() == 3 ){ // TDX indexes were version 4 and higher
+ iErrorStop = 140;
+ iRc = XB_INVALID_INDEX;
+ throw iRc;
+ }
+ xbIxTdx *ixTdx;
+ xbString s;
+ // look through the index list and see if there is an mdx pointer we can grab
+ xbBool bTdxFound = xbFalse;
+ xbIxList *ixList = GetIxList();
+ while( ixList && !bTdxFound ){
+ s = ixList->sFmt->Str();
+ if( s == "TDX" ){
+ ixTdx = (xbIxTdx *) ixList->ix;
+ bTdxFound = xbTrue;
+ }
+ ixList = ixList->next;
+ }
+ if( !bTdxFound )
+ ixTdx = new xbIxTdx( this );
+
+ if(( iRc = ixTdx->CreateTag( sName, sKey, sFilter, iDescending, iUnique, iOverLay, vpTagOut )) != XB_NO_ERROR ){
+ iErrorStop = 150;
+ throw iRc;
+ }
+ if( !bTdxFound ){
+ if(( iRc = AddIndex( ixTdx, "TDX" )) != XB_NO_ERROR ){
+ iErrorStop = 160;
+ throw iRc;
+ }
+ }
+ *pIxOut = ixTdx;
+
+ // set the current tag if one not already set
+ if( sCurIxType == "" ){
+
+ sCurIxType = "TDX";
+ pCurIx = ixTdx;
+ vpCurIxTag = ixTdx->GetTag(0);
+ }
+
#endif
} else {
@@ -1192,17 +1283,23 @@ xbInt16 xbDbf::DeleteAllIndexFiles(){
// close any open index files, delete it, remove from the ix list
while( ixList ){
+
+ // next two lines for debugging
+ ixList->ix->GetFileNamePart( sIxName );
ixList->ix->Close();
- ixList->ix->xbRemove();
+ if(( iRc = ixList->ix->xbRemove()) != XB_NO_ERROR ){
+ iErrorStop = 110;
+ throw iRc;
+ }
#ifdef XB_INF_SUPPORT
// if XB_INF_SUPPORT is enabled, all open non prod indices should be in here
- if( *ixList->sFmt != "MDX" ){ // production indices not stored in .INF dataset
+ if( *ixList->sFmt != "MDX" && *ixList->sFmt != "TDX" ){ // production and temp indices not stored in .INF dataset
if(( iRc = ixList->ix->GetFileNamePart( sIxName )) != XB_NO_ERROR ){
- iErrorStop = 110;
+ iErrorStop = 120;
throw iRc;
}
if(( iRc = AssociateIndex( *ixList->sFmt, sIxName, 1 )) != XB_NO_ERROR ){
- iErrorStop = 120;
+ iErrorStop = 130;
throw iRc;
}
}
@@ -1391,7 +1488,7 @@ xbInt16 xbDbf::DeleteTable(){
/*!
This routine deletes an index tag
- \param sIxType Either "NDX" or "MDX".<br>
+ \param sIxType Either "NDX", "MDX" or "TDX".<br>
\param sName Tag name to delete.<br>
\returns <a href="xbretcod_8h.html">Return Codes</a>
*/
@@ -1452,7 +1549,7 @@ xbInt16 xbDbf::DeleteTag( const xbString &sIxType, const xbString &sName ){
throw iRc;
}
- if( ixl->ix == pCurIx )
+ if( !ixList || ixl->ix == pCurIx )
SetCurTag( "", NULL, NULL );
}
@@ -1500,7 +1597,64 @@ xbInt16 xbDbf::DeleteTag( const xbString &sIxType, const xbString &sName ){
iErrorStop = 170;
throw iRc;
}
- if( ixl->ix == pCurIx )
+ if( !ixList || ixl->ix == pCurIx )
+ SetCurTag( "", NULL, NULL );
+ }
+ }
+ ixlPrev = ixl;
+ ixl = ixlNext;
+ }
+
+ if( !bDone )
+ return XB_INVALID_TAG;
+ #endif
+
+ #ifdef XB_TDX_SUPPORT
+ } else if( sIxType == "TDX" ){
+ xbIxList *ixl = ixList;
+ xbIxList *ixlNext;
+ xbIxList *ixlPrev = NULL;
+ xbBool bDone = xbFalse;
+ xbIxTdx *pTdx;
+ xbMdxTag *pMdxTag;
+ xbInt16 iTagCnt = 0;
+
+ while( ixl && !bDone ){
+ ixlNext = ixl->next;
+ pTdx = (xbIxTdx *) ixl->ix;
+ iTagCnt = pTdx->GetTagCount();
+ for( xbInt16 i = 0; i < iTagCnt && !bDone; i++ ){
+ pMdxTag = (xbMdxTag *) pTdx->GetTag( i );
+ if( pTdx->GetTagName( pMdxTag ) == sName ){
+ bDone = xbTrue;
+ iRc = pTdx->DeleteTag( pMdxTag );
+ if( iRc > 0 ){
+ // Successful delete of only tag in production mdx file - need to remove it from the list, update the dbf header
+ cIndexFlag = 0x00;
+ if(( iRc = WriteHeader( 1, 0 )) != XB_NO_ERROR ){
+ iErrorStop = 150;
+ throw iRc;
+ }
+ if(( iRc = RemoveIndex( ixl->ix )) != XB_NO_ERROR ){
+ iErrorStop = 160;
+ throw iRc;
+ }
+ if( ixlPrev == NULL ){
+ // std::cout << "setting ixList to null or should be\n";
+ ixList = ixlNext;
+ } else {
+ ixlPrev = ixlNext;
+ }
+ } else if( iRc < 0 ){
+ iErrorStop = 170;
+ throw iRc;
+ }
+ if( ixList )
+ std::cout << "ixlist not null\n";
+ else
+ std::cout << "ixlist null\n";
+
+ if( !ixList || ixl->ix == pCurIx )
SetCurTag( "", NULL, NULL );
}
}
@@ -1513,6 +1667,8 @@ xbInt16 xbDbf::DeleteTag( const xbString &sIxType, const xbString &sName ){
#endif
+
+
} else {
iErrorStop = 180;
iRc = XB_INVALID_OPTION;
@@ -1562,15 +1718,19 @@ xbInt16 xbDbf::DeleteTag( const xbString &sIxType, const xbString &sName ){
\returns <a href="xbretcod_8h.html">Return Codes</a>
*/
-xbInt16 xbDbf::DumpHeader( xbInt16 iOption ) const {
+xbInt16 xbDbf::DumpHeader( xbInt16 iOption ){
int i;
int iMemoCtr = 0;
if( iOption < 1 || iOption > 4 )
return XB_INVALID_OPTION;
- if( iDbfStatus == XB_CLOSED )
- return XB_NOT_OPEN;
+ xbInt16 iRc = ReadHeader( xbTrue, 0 );
+ if( iRc != XB_NO_ERROR )
+ return iRc;
+
+// if( iDbfStatus == XB_CLOSED )
+// return XB_NOT_OPEN;
std::cout << "\nDatabase file " << GetFqFileName() << std::endl << std::endl;
@@ -1859,7 +2019,7 @@ xbUInt32 xbDbf::GetAppendLocked() const {
This routine returns the table setting if set, otherwise returns the system
level setting.
-
+
\returns Not 0 - Auto commit on for this table.<br>
0 - Auto commit off for this table.
*/
@@ -1920,8 +2080,10 @@ xbIx *xbDbf::GetCurIx() const {
/************************************************************************/
//! @brief Get pointer to current tag for the current index.
/*!
- An index file can have one or more tags. An NDX index has one tag.
- An MDX file can have up to 47 tags.
+ An index file can have one or more tags
+ NDX index files have one tag per file.
+ MDX index files can can have up to 47 tags per file.
+ TDX index files can can have up to 47 tags per file.
\returns Pointer to current tag.
*/
@@ -1932,7 +2094,8 @@ void *xbDbf::GetCurTag() const {
//! @brief Get the current index type.
/*!
\returns NDX for single tag index.<br>
- MDX for production multi tag index.
+ MDX for production multi tag index.<br>
+ TDX for temporary tag index.
*/
const xbString &xbDbf::GetCurIxType() const {
return sCurIxType;
@@ -2097,12 +2260,16 @@ xbBool xbDbf::GetBof() {
/************************************************************************/
//! @brief Return true if dbf file empty or positioned to the last record
/*!
- \returns Returns true if dbf file is empty or positioned on the last record.
+ \returns Returns true if error, dbf file is empty or positioned on the last record.
*/
xbBool xbDbf::GetEof() {
- xbUInt32 ulRecCnt = GetRecordCount();
+
+ // xbUInt32 ulRecCnt = GetRecordCount();
- if( ulRecCnt == 0 || GetCurRecNo() == ulRecCnt )
+ xbUInt32 ulRecCnt;
+ xbInt16 iRc = GetRecordCnt( ulRecCnt );
+
+ if( iRc != XB_NO_ERROR || ulRecCnt == 0 || GetCurRecNo() == ulRecCnt )
return xbTrue;
else
return xbFalse;
@@ -2542,6 +2709,7 @@ char * xbDbf::GetRecordBuf( xbInt16 iOpt ) const {
/*!
\returns Record count or <a href="xbretcod_8h.html">Return Codes</a>
*/
+/*
xbUInt32 xbDbf::GetRecordCount(){
xbUInt32 ulCnt;
@@ -2551,7 +2719,7 @@ xbUInt32 xbDbf::GetRecordCount(){
else
return ulCnt;
}
-
+*/
/************************************************************************/
//! @brief Get the current number of records in the dbf data file.
/*!
@@ -2626,8 +2794,8 @@ xbBool xbDbf::GetTableLocked() const {
This routine returns a list of tags for the file.<br>
The library is structured to support one or more files of the same or differing
- index types (NDX/MDX), with each file supporting one or more index tags.<br>
-
+ index types (NDX/MDX/TDX), with each file supporting one or more index tags.<br>
+
\returns Tag list for the file/table.
*/
xbLinkListNode<xbTag *> *xbDbf::GetTagList() const {
@@ -2944,6 +3112,19 @@ xbInt16 xbDbf::LockIndices( xbInt16 iLockFunction )
}
#endif
+ #ifdef XB_TDX_SUPPORT
+ if( *ixLI->sFmt == "TDX" ){
+ if( !ixLI->ix->GetLocked()){
+ if(( iRc = ixLI->ix->xbLock( XB_LOCK, LK4026531838, 1 )) != XB_NO_ERROR ){
+ ixLI->ix->xbLock( XB_UNLOCK, LK4026531838, 1 );
+ iErrorStop = 100;
+ throw iRc;
+ }
+ ixLI->ix->SetLocked( xbTrue );
+ }
+ }
+ #endif
+
} else if( iLockFunction == XB_UNLOCK ){
#ifdef XB_NDX_SUPPORT
@@ -2970,6 +3151,18 @@ xbInt16 xbDbf::LockIndices( xbInt16 iLockFunction )
}
#endif
+ #ifdef XB_TDX_SUPPORT
+ if( *ixLI->sFmt == "MDX" ){
+ if( ixLI->ix->GetLocked()){
+ if(( iRc = ixLI->ix->xbLock( XB_UNLOCK, LK4026531838, 1 )) != XB_NO_ERROR ){
+ iErrorStop = 100;
+ throw iRc;
+ }
+ ixLI->ix->SetLocked( xbFalse );
+ }
+ }
+ #endif
+
}
ixLI = ixLI->next;
}
@@ -3377,7 +3570,7 @@ xbInt16 xbDbf::OpenIndex( const xbString &sIxType, const xbString &sFileName ){
xbInt16 xbDbf::Pack()
{
xbUInt32 ulDeletedRecCnt;
- return Pack( ulDeletedRecCnt );
+ return Pack( ulDeletedRecCnt );
}
@@ -3484,6 +3677,7 @@ xbInt16 xbDbf::Pack( xbUInt32 &ulDeletedRecCnt )
// update header record count
xbDate d;
+ d.Sysdate();
cUpdateYY = (char) d.YearOf() - 1900;
cUpdateMM = (char) d.MonthOf();
cUpdateDD = (char) d.DayOf( XB_FMT_MONTH );
@@ -3520,7 +3714,6 @@ xbInt16 xbDbf::Pack( xbUInt32 &ulDeletedRecCnt )
}
}
#endif // XB_MEMO_SUPPORT
-
}
catch (xbInt16 iRc ){
if( iRc != XB_LOCK_FAILED ){
@@ -3665,6 +3858,7 @@ xbInt16 xbDbf::PutRecord(xbUInt32 ulRecNo)
// update latest header date if changed
xbDate d;
+ d.Sysdate();
if( (cUpdateYY != (char)(d.YearOf() - 1900)) || (cUpdateMM != (char) d.MonthOf()) || (cUpdateDD != (char)d.DayOf( XB_FMT_MONTH))){
cUpdateYY = (char) d.YearOf() - 1900;
cUpdateMM = (char) d.MonthOf();
@@ -3716,9 +3910,9 @@ xbInt16 xbDbf::PutRecord(xbUInt32 ulRecNo)
LockHeader( XB_UNLOCK );
LockAppend( XB_UNLOCK );
LockRecord( XB_UNLOCK, ulRecNo );
- #ifdef XB_INDEX_SUPPORT
+ #ifdef XB_INDEX_SUPPORT
LockIndices( XB_UNLOCK );
- #endif // XB_INDEX_SUPPORT
+ #endif // XB_INDEX_SUPPORT
}
#endif // XB_LOCKING_SUPPORT
@@ -3972,7 +4166,7 @@ xbInt16 xbDbf::SetCurTag( const xbString &sTagName ){
//! @brief Set the current tag for the dbf file.
/*!
- \param sIxType - One of "NDX" or MDX",
+ \param sIxType - One of "NDX", MDX or TDX",
\param pIx - Pointer to index object.
\param vpTag - Pointer to tag object.
\returns <a href="xbretcod_8h.html">Return Codes</a>
@@ -4206,6 +4400,7 @@ xbInt16 xbDbf::Zap(){
#endif
xbDate d;
+ d.Sysdate();
cUpdateYY = (char) d.YearOf() - 1900;
cUpdateMM = (char) d.MonthOf();
cUpdateDD = (char) d.DayOf( XB_FMT_MONTH );