From dd70ff8bf32c2d7ed365004b1770058265db1978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sat, 11 Mar 2023 18:15:37 +0100 Subject: New upstream version 4.1.0 --- src/core/xbbcd.cpp | 5 +- src/core/xbblockread.cpp | 271 ++++++++++++++ src/core/xbdbf.cpp | 154 +++++++- src/core/xbdbf3.cpp | 8 +- src/core/xbdbf4.cpp | 19 +- src/core/xbexp.cpp | 31 +- src/core/xbfile.cpp | 286 ++++++++++++--- src/core/xbfilter.cpp | 50 +-- src/core/xbixmdx.cpp | 50 ++- src/core/xbixndx.cpp | 3 +- src/core/xblog.cpp | 4 +- src/core/xbssv.cpp | 111 +++--- src/core/xbstring.cpp | 71 +++- src/core/xbtblmgr.cpp | 85 +++-- src/core/xbxbase.cpp | 54 ++- src/examples/xb_ex_expression.cpp | 4 +- src/examples/xb_ex_ssv.cpp | 134 +++++++ src/examples/xb_ex_v4_upd_dbf.cpp | 6 +- src/include/xbase.h | 7 +- src/include/xbblkread.h | 70 ++++ src/include/xbconfig.h.in | 2 + src/include/xbdate.h | 1 - src/include/xbdbf.h | 37 +- src/include/xbfile.h | 4 + src/include/xbfilter.h | 6 +- src/include/xbretcod.h | 5 +- src/include/xbsql.h | 78 +++- src/include/xbssv.h | 31 +- src/include/xbstring.h | 2 + src/include/xbtblmgr.h | 9 +- src/include/xbuda.h | 6 +- src/include/xbxbase.h | 10 +- src/sql/xbalttbl.cpp | 7 +- src/sql/xbcrix.cpp | 16 +- src/sql/xbcrtbl.cpp | 49 ++- src/sql/xbcrtbl.save.cpp | 256 +++++++++++++ src/sql/xbdelete.cpp | 2 +- src/sql/xbdrptbl.cpp | 9 +- src/sql/xbselect.cpp | 17 +- src/sql/xbset.cpp | 5 +- src/sql/xbsql.cpp | 3 - src/sql/xbstmt.cpp | 679 +++++++++++++++++++++++++++++++++++ src/tests/xb_test_bcd.cpp | 5 +- src/tests/xb_test_blockread.cpp | 168 +++++++++ src/tests/xb_test_date.cpp | 7 +- src/tests/xb_test_dbf_v3_memos.cpp | 4 +- src/tests/xb_test_dbf_v3_nomemos.cpp | 10 +- src/tests/xb_test_dbf_v4_memos.cpp | 10 +- src/tests/xb_test_dbf_v4_nomemos.cpp | 29 +- src/tests/xb_test_expnode.cpp | 4 +- src/tests/xb_test_expression.cpp | 7 +- src/tests/xb_test_file.cpp | 3 +- src/tests/xb_test_filter.cpp | 8 +- src/tests/xb_test_funcs.cpp | 3 +- src/tests/xb_test_linklist.cpp | 8 +- src/tests/xb_test_lock.cpp | 4 +- src/tests/xb_test_lock2.cpp | 5 +- src/tests/xb_test_log.cpp | 15 +- src/tests/xb_test_mdx.cpp | 70 +++- src/tests/xb_test_ndx.cpp | 15 +- src/tests/xb_test_sql.cpp | 151 +++++--- src/tests/xb_test_string.cpp | 11 +- src/tests/xb_test_tblmgr.cpp | 81 ++--- src/tests/xb_test_uda.cpp | 9 +- src/tests/xb_test_xbase.cpp | 44 +-- src/utils/xb_cfg_check.cpp | 84 +++-- src/utils/xb_copydbf.cpp | 78 ++-- src/utils/xb_dbfutil.cpp | 453 +++++++++++++---------- src/utils/xb_deletall.cpp | 54 ++- src/utils/xb_dumpdbt.cpp | 54 ++- src/utils/xb_dumphdr.cpp | 45 --- src/utils/xb_dumpix.cpp | 56 --- src/utils/xb_dumprecs.cpp | 60 +++- src/utils/xb_execsql.cpp | 2 +- src/utils/xb_pack.cpp | 54 ++- src/utils/xb_tblinfo.cpp | 105 +++--- src/utils/xb_undelall.cpp | 53 ++- src/utils/xb_zap.cpp | 52 --- 78 files changed, 3476 insertions(+), 1002 deletions(-) create mode 100755 src/core/xbblockread.cpp create mode 100755 src/examples/xb_ex_ssv.cpp create mode 100755 src/include/xbblkread.h create mode 100755 src/sql/xbcrtbl.save.cpp create mode 100755 src/sql/xbstmt.cpp create mode 100755 src/tests/xb_test_blockread.cpp delete mode 100755 src/utils/xb_dumphdr.cpp delete mode 100755 src/utils/xb_dumpix.cpp delete mode 100755 src/utils/xb_zap.cpp (limited to 'src') diff --git a/src/core/xbbcd.cpp b/src/core/xbbcd.cpp index ff64110..f86e74f 100755 --- a/src/core/xbbcd.cpp +++ b/src/core/xbbcd.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -268,7 +268,6 @@ xbInt16 xbBcd::Compare( const xbBcd &bcdIn ){ return -1; } - /***********************************************************************/ unsigned char xbBcd::GetEncDigitsNoSign() const { unsigned char c = bcd.cEncDigits << 1; @@ -277,7 +276,7 @@ unsigned char xbBcd::GetEncDigitsNoSign() const { /***********************************************************************/ unsigned xbBcd::GetSign() const { //return bcd.Sign; - return bcd.cEncDigits >> 7; + return (unsigned) bcd.cEncDigits >> 7; } /***********************************************************************/ unsigned xbBcd::GetSigDigits() const { diff --git a/src/core/xbblockread.cpp b/src/core/xbblockread.cpp new file mode 100755 index 0000000..09076b1 --- /dev/null +++ b/src/core/xbblockread.cpp @@ -0,0 +1,271 @@ +/* xbblockread.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +This module handles block read methods. Block reading is used for performance improvement +during sequential access processing. + +*/ + +#include "xbase.h" + +#ifdef XB_BLOCKREAD_SUPPORT + +namespace xb{ + +/************************************************************************/ +xbBlockRead::xbBlockRead( xbDbf * d ) { + pBlock = NULL; + ulBlkSize = 0; + ulFirstBlkRec = 0; + ulRecCnt = 0; + ulMaxRecs = 0; + bEof = xbFalse; + this->dbf = d; + tFmTime = 0; +} +/************************************************************************/ +xbBlockRead::~xbBlockRead(){ + if( pBlock ){ + free( pBlock ); + pBlock = NULL; + } +} + +/************************************************************************/ +//! @brief Dump read block internals to stdout. +/*! + Dump the current read block internals to stdout. +*/ + + +#ifdef XB_DEBUG_SUPPORT +void xbBlockRead::DumpReadBlockInternals(){ + std::cout << "------- DumpBlockInternals ---------" << std::endl; + std::cout << "Dflt Blk Size = [" << dbf->GetXbasePtr()->GetDefaultBlockReadSize() + << "]" << std::endl; + std::cout << "Dbf Record Count = [" << dbf->GetRecordCount() << "]" << std::endl; + std::cout << "Dbf Record Len = [" << dbf->GetRecordLen() << "]" << std::endl; + std::cout << "ulBlkSize = [" << ulBlkSize << "]" << std::endl; + std::cout << "ulMaxRecs = [" << ulMaxRecs << "]" << std::endl; + std::cout << "ulFirstBlkRec = [" << ulFirstBlkRec << "]" << std::endl; + std::cout << "ulRecCnt = [" << ulRecCnt << "]" << std::endl; + std::cout << "bEof = [" << bEof << "]" << std::endl; +} +#endif // XB_DEBUG_SUPPORT +/************************************************************************/ +//! @brief Get the first record number in the current block. +/*! + Retrieve the first record numer in the current block.
+ + \returns First record number in the current block. +*/ + +xbUInt32 xbBlockRead::GetBlockFirstRecNo() const{ + return ulFirstBlkRec; +} +/************************************************************************/ +//! @brief Get record for specified record number. +/*! + Retrieve a record from read block buffer and copy it into the record buffer. + If the current record is not in the current block, the routine calls + GetBlockForRecNo to load the currect block from disk.

+ For performance reasons, this method assumes a valid record number has been + passed.

+ + \param ulRecNo - Record number to retrieve. + \returns Return Codes +*/ + +xbInt16 xbBlockRead::GetRecord( xbUInt32 ulRecNo ){ + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + // std::cout << "xbBlockRead::GetRecord( " << ulRecNo << ")\n"; + + try{ + if( !( ulRecNo >= ulFirstBlkRec && ulRecNo < (ulFirstBlkRec + ulRecCnt))){ + if(( iRc = GetBlockForRecNo( ulRecNo )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } + char *s = pBlock; + s += (ulRecNo - ulFirstBlkRec) * dbf->GetRecordLen(); + char *t = dbf->RecBuf; + xbUInt32 ulRecLen = dbf->GetRecordLen(); + for( xbUInt32 l = 0; l < ulRecLen; l++ ){ + *t = *s; + t++; + s++; + } + dbf->ulCurRec = ulRecNo; + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbBlockRead::GetBlockForRecNo() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); + } + return iRc; +} + +/************************************************************************/ +//! @brief Get record for specified record number. +/*! + Retrieve a block containing specified record. This routine calculates the + correct block in the DBF file, updates the internal block fields and retrieves + the block of records from disk and loads into the block buffer.

+ + \param ulRecNo - Record number to retrieve. + \returns Return Codes +*/ + +xbInt16 xbBlockRead::GetBlockForRecNo( xbUInt32 ulRecNo ){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + try{ + xbUInt32 ulDbfRecCnt = dbf->GetRecordCount(); + + // calc to determine block number for the requested record, 0 based offset + xbUInt32 ulBlockNo = (xbUInt32)(ulRecNo / ulMaxRecs); + if( ulRecNo % ulMaxRecs == 0 ) ulBlockNo--; + + // calc the first record + ulFirstBlkRec = (ulBlockNo * ulMaxRecs); + + // calc the record count + if(( ulFirstBlkRec + ulMaxRecs) > ulDbfRecCnt ){ + ulRecCnt = ulDbfRecCnt - ulFirstBlkRec; + bEof = xbTrue; + } else { + ulRecCnt = ulMaxRecs; + bEof = xbFalse; + } + + // position accordingly + xbInt64 ulStartPos = dbf->GetHeaderLen() + ((xbInt64) ulFirstBlkRec * dbf->GetRecordLen()); + if(( dbf->xbFseek( ulStartPos, SEEK_SET )) != XB_NO_ERROR ){ + iErrorStop = 110; + iRc = XB_SEEK_ERROR; + throw iRc; + } + + if(( dbf->GetFileMtime( tFmTime )) != XB_NO_ERROR ){ + iErrorStop = 120; + throw iRc; + } + // read it + if(( dbf->xbFread( (void *) pBlock, ulRecCnt * dbf->GetRecordLen(), 1 )) != XB_NO_ERROR ){ + iErrorStop = 130; + throw iRc; + } + + ulFirstBlkRec++; // zero offset in the routine, regular record number from ths point forward + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbBlockRead::GetBlockForRecNo() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); + } + return iRc; +} + + +/************************************************************************/ +//! @brief Get the current block size. +/*! + Retrieve the current block size.

+ + \returns Current Block Size. +*/ + +xbUInt32 xbBlockRead::GetBlockSize() const{ + return ulBlkSize; +} + +/************************************************************************/ +//! @brief Get the current block record count. +/*! + Retrieve the current number of records loaded in the block.

+ + \returns Current Block Size. +*/ + +xbUInt32 xbBlockRead::GetBlockRecCnt() const { + return ulRecCnt; +} + +/************************************************************************/ +//! @brief Init the block processing for a iven DBF file. +/*! + Initialize the settings for a given DBF file.
+ This routine may adjust the block size as needed to eliminate unused + memory or adjust it bigger if too small. + + \param ulRecNo - ulBlockSize - Block size to allocate. If 0 or missing, it uses default block size of 32K. + \returns Return Codes +*/ + +xbInt16 xbBlockRead::Init(xbUInt32 ulBlockSize ){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + try{ + + // calculate the block size + if( ulBlockSize == 0 ) + ulBlkSize = dbf->GetXbasePtr()->GetDefaultBlockReadSize(); + + // if not big enough to handle more than one record, bump it up to something meaningful + if( ulBlkSize < (xbUInt32)(dbf->GetRecordLen() * 2 )) + ulBlkSize = (xbUInt32) dbf->GetRecordLen() * 10; + + ulMaxRecs = (xbUInt32) ulBlkSize / dbf->GetRecordLen(); + ulBlkSize = ulMaxRecs * dbf->GetRecordLen(); + + // allocate memory for the block + if(( pBlock = (char *) calloc( 1, ulBlkSize )) == NULL ){ + iErrorStop = 100; + throw iRc; + } + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbBlockRead::Init() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); + } + return iRc; +} + +/************************************************************************/ +//! @brief Set the block size. +/*! + St block size for this DBF file.
. + + \param ulBlkSize - Block Size. + \returns XB_NO_ERROR +*/ + +xbInt16 xbBlockRead::SetBlockSize( xbUInt32 ulBlkSize ){ + this->ulBlkSize = ulBlkSize; + return XB_NO_ERROR; +} + +/************************************************************************/ +} /* namespace */ +#endif /* XB_BLOCKREAD_SUPPORT */ \ No newline at end of file diff --git a/src/core/xbdbf.cpp b/src/core/xbdbf.cpp index 3d13369..4033ef9 100755 --- a/src/core/xbdbf.cpp +++ b/src/core/xbdbf.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -24,10 +24,16 @@ namespace xb{ \param x Pointer to xbXbase */ xbDbf::xbDbf( xbXBase * x ) : xbFile( x ){ - xbase = x; - SchemaPtr = NULL; - RecBuf = NULL; - RecBuf2 = NULL; + xbase = x; + SchemaPtr = NULL; + RecBuf = NULL; + RecBuf2 = NULL; + + #ifdef XB_BLOCKREAD_SUPPORT + pRb = NULL; + bBlockReadEnabled = xbFalse; // batch read switch, if xbTrue, then ON + #endif // XB_BLOCKREAD_SUPPORT + InitVars(); } /************************************************************************/ @@ -77,7 +83,7 @@ void xbDbf::InitVars() #ifdef XB_INF_SUPPORT llInfData.Clear(); - #endif // XB_INF_SUPPORT + #endif // XB_INF_SUPPORT } /************************************************************************/ @@ -104,6 +110,16 @@ xbDbf::~xbDbf(){ free( RecBuf2 ); RecBuf2 = NULL; } + if( RecBuf ){ + free( RecBuf ); + RecBuf = NULL; + } + + #ifdef XB_BLOCKREAD_SUPPORT + if( bBlockReadEnabled ) + DisableBlockReadProcessing(); + #endif // XB_BLOCKREAD_SUPPORT + Close(); } /************************************************************************/ @@ -1951,6 +1967,18 @@ xbInt16 xbDbf::GetFirstKey(){ return XB_INVALID_TAG; } +/************************************************************************/ +//! @brief GetHeaderLen for dbf +/*! + + Returns the length of the header portion of the dbf file + \returns Length of header protion of dbf file + +*/ +xbUInt16 xbDbf::GetHeaderLen() const { + return uiHeaderLen; +} + /************************************************************************/ //! @brief GetLastKey for tag. /*! @@ -2053,6 +2081,32 @@ xbInt16 xbDbf::Find( xbDouble &dKey ){ #endif // XB_INDEX_SUPPORT +/************************************************************************/ +//! @brief Return true if dbf file empty or positioned to the first record +/*! + \returns Returns true if dbf file is empty or positioned on the first record. +*/ +xbBool xbDbf::GetBof() { +/* + if( GetRecordCount() == 0 || GetCurRecNo() == 1 ) + return xbTrue; + else + */ + return xbFalse; +} +/************************************************************************/ +//! @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. +*/ +xbBool xbDbf::GetEof() { + xbUInt32 ulRecCnt = GetRecordCount(); + + if( ulRecCnt == 0 || GetCurRecNo() == ulRecCnt ) + return xbTrue; + else + return xbFalse; +} /************************************************************************/ //! @brief Return the current record number. /*! @@ -2428,15 +2482,23 @@ xbInt16 xbDbf::GetRecord( xbUInt32 ulRecNo ){ iErrorStop = 120; throw iRc; } - } - } + } + } + + // std::cout << "xbdbf::GetRecord: " << ulRecNo << " " << ulNoOfRecs << "\n"; if( ulRecNo > ulNoOfRecs || ulRecNo == 0L ){ iErrorStop = 130; iRc = XB_INVALID_RECORD; throw iRc; } + #ifdef XB_BLOCKREAD_SUPPORT + if( bBlockReadEnabled ) + return pRb->GetRecord( ulRecNo ); + #endif // XB_BLOCK_READ_SUPPORT + + if(( xbFseek( (uiHeaderLen+(( (xbInt64) ulRecNo-1L ) * uiRecordLen )), SEEK_SET )) != XB_NO_ERROR ){ iErrorStop = 140; iRc = XB_SEEK_ERROR; @@ -2475,9 +2537,6 @@ char * xbDbf::GetRecordBuf( xbInt16 iOpt ) const { return RecBuf; } - - - /************************************************************************/ //! @brief Get the current number of records in the dbf data file. /*! @@ -3211,12 +3270,12 @@ xbInt16 xbDbf::Open( const xbString & sTableName, const xbString & sAlias ){ xbLinkListNode * llN = llInfData.GetHeadNode(); for( xbUInt32 i = 0; i < llNodeCnt; i++ ){ s2 = llN->GetKey(); - #ifdef XB_NDX_SUPPORT + #ifdef XB_NDX_SUPPORT if(( iRc = OpenIndex( "NDX", s2 )) != XB_NO_ERROR ){ iErrorStop = 120; throw iRc ; } - #endif // XB_NDX_SUPPORT + #endif // XB_NDX_SUPPORT llN = llN->GetNextNode(); } } @@ -3270,7 +3329,6 @@ xbInt16 xbDbf::OpenIndex( const xbString &sIxType, const xbString &sFileName ){ #ifdef XB_MDX_SUPPORT } else if( sType == "MDX" ){ - pIx = new xbIxMdx( this ); if(( iRc = pIx->Open( sFileName )) != XB_NO_ERROR ){ iErrorStop = 120; @@ -4209,4 +4267,72 @@ xbInt16 xbDbf::Zap(){ return iRc; } /************************************************************************/ +#ifdef XB_BLOCKREAD_SUPPORT +// block read processing is designed to provide a way to rapidly retrieve +// all the records from a .DBF file in sequential order. + +// It is not designed for doing any read/write processing or data retrieval based on a tag sort. +// It is designed for doing a fast sequentil block read out of a table + + +xbInt16 xbDbf::DisableBlockReadProcessing(){ + + if( bBlockReadEnabled ){ + bBlockReadEnabled = xbFalse; + delete pRb; + pRb = NULL; + } + return XB_NO_ERROR; +} + +xbBool xbDbf::GetBlockReadStatus() const { + return bBlockReadEnabled; +} + +xbInt16 xbDbf::EnableBlockReadProcessing(){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + try{ + + if( !bBlockReadEnabled ){ + if( iDbfStatus == XB_UPDATED ){ + if( GetAutoCommit() == 1 ){ + if(( iRc = Commit()) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } else { + if(( iRc = Abort()) != XB_NO_ERROR ){ + iErrorStop = 110; + throw iRc; + } + } + } + pRb = new xbBlockRead( this ); + if( !pRb ){ + iErrorStop = 120; + iRc = XB_NO_MEMORY; + throw iRc; + } + if(( iRc = pRb->Init()) != XB_NO_ERROR ){ + iErrorStop = 130; + throw iRc; + } + + bBlockReadEnabled = xbTrue; + } + + } catch( xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbdbf::EnableBlockReadProcessing() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return iRc; +} + +#endif // XB_BLOCKREAD_SUPPORT +/************************************************************************/ } /* namespace */ \ No newline at end of file diff --git a/src/core/xbdbf3.cpp b/src/core/xbdbf3.cpp index 504542f..d57be3c 100755 --- a/src/core/xbdbf3.cpp +++ b/src/core/xbdbf3.cpp @@ -261,7 +261,7 @@ xbInt16 xbDbf3::CreateTable( const xbString & sTableName, const xbString & sAlia catch( xbInt16 rc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf3::CreateTable() Exception Caught Error Stop = %d rc = %d", iErrorStop, rc ); + sMsg.Sprintf( "xbdbf3::CreateTable() Exception Caught Error Stop = [%d] rc = [%d]", iErrorStop, rc ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( rc )); @@ -453,7 +453,7 @@ xbInt16 xbDbf3::Open( const xbString & sTableName, const xbString & sAlias, catch ( xbInt16 iRc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf3::Open() Exception Caught Error Stop = %d iRc = %d ShareMode = %d OpenMode = %d", iErrorStop, iRc, iShareMode, iOpenMode ); + sMsg.Sprintf( "xbdbf3::Open() Exception Caught Error Stop = [%d] iRc = [%d] ShareMode = [%d] OpenMode = [%d]", iErrorStop, iRc, iShareMode, iOpenMode ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( iRc )); xbFclose(); @@ -623,14 +623,14 @@ xbInt16 xbDbf3::Rename( const xbString sNewName ){ xbTblList *tle = xbase->GetTblListEntry( this ); if( tle ){ // std::cout << "setting [" << GetFqFileName().Str() << "][" << sNewNameWoExt.Str() << "]\n"; - tle->psTblName->Set( GetFqFileName().Str()); + tle->psFqTblName->Set( GetFqFileName().Str()); tle->psTblAlias->Set( sNewNameWoExt.Str()); } } catch ( xbInt16 iRc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf3::Rename() Exception Caught Error Stop = %d iRc = %d", iErrorStop, iRc ); + sMsg.Sprintf( "xbdbf3::Rename() Exception Caught Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( iRc )); diff --git a/src/core/xbdbf4.cpp b/src/core/xbdbf4.cpp index 2b49be9..59ba39a 100755 --- a/src/core/xbdbf4.cpp +++ b/src/core/xbdbf4.cpp @@ -180,10 +180,10 @@ xbInt16 xbDbf4::CreateTable( const xbString &sTableName, const xbString &sAlias, ulCurRec = 0L; uiHeaderLen = 33 + iNoOfFields * 32; xbDate d; - 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(); + cUpdateDD = (char) d.DayOf( XB_FMT_MONTH ); + cIndexFlag = 0; // Default language driver to 0x1b cLangDriver = 0x1b; @@ -264,7 +264,7 @@ xbInt16 xbDbf4::CreateTable( const xbString &sTableName, const xbString &sAlias, catch( xbInt16 rc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf4::CreateTable() Exception Caught Error Stop = %d rc = %d", iErrorStop, rc ); + sMsg.Sprintf( "xbdbf4::CreateTable() Exception Caught Error Stop = [%d] rc = [%d]", iErrorStop, rc ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( rc )); @@ -452,6 +452,9 @@ xbInt16 xbDbf4::Open( const xbString & sTableName, const xbString & sAlias, #endif #ifdef XB_MDX_SUPPORT + +// printf( "cIndexFlag [%x]\n", cIndexFlag ); + if( cIndexFlag ){ // create the file name xbString sIxFileName = GetFqFileName(); @@ -471,7 +474,7 @@ xbInt16 xbDbf4::Open( const xbString & sTableName, const xbString & sAlias, catch ( xbInt16 iRc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf4::Open() Exception Caught Error Stop = %d iRc = %d ShareMode = %d OpenMode = %d", iErrorStop, iRc, iShareMode, iOpenMode ); + sMsg.Sprintf( "xbdbf4::Open() Exception Caught Error Stop = [%d] iRc = [%d] ShareMode = [%d] OpenMode = [%d]", iErrorStop, iRc, iShareMode, iOpenMode ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( iRc )); xbFclose(); @@ -726,7 +729,7 @@ xbInt16 xbDbf4::Rename( const xbString sNewName ){ // rename the table in the table list xbTblList *tle = xbase->GetTblListEntry( this ); if( tle ){ - tle->psTblName->Set( GetFqFileName().Str()); + tle->psFqTblName->Set( GetFqFileName().Str()); tle->psTblAlias->Set( sNewNameWoExt.Str()); } @@ -735,7 +738,7 @@ xbInt16 xbDbf4::Rename( const xbString sNewName ){ catch ( xbInt16 iRc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf4::Rename() Exception Caught Error Stop = %d iRc = %d", iErrorStop, iRc ); + sMsg.Sprintf( "xbdbf4::Rename() Exception Caught Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( iRc )); diff --git a/src/core/xbexp.cpp b/src/core/xbexp.cpp index 23bc7c6..deea53d 100755 --- a/src/core/xbexp.cpp +++ b/src/core/xbexp.cpp @@ -669,10 +669,22 @@ xbInt16 xbExp::GetTokenDatabaseField( xbExpToken &t ){ } // look for -> - // remove the field name from before the -> + // remove the table name from before the -> if( strncmp( s, "->", 2 ) == 0 ){ ulTokenLen2+=2; s+=2; + +/* + if( strncmp( s, "->", 2 ) == 0 || strncmp( s, ".", 1 ) == 0){ + if( *s == '.' ){ + ulTokenLen2+=1; + s+=1; + } else { + ulTokenLen2+=2; + s+=2; + } +*/ + // go past white space while( *s && !IsTokenSeparator( *s ) && IsWhiteSpace( *s )) { ulTokenLen2++; @@ -1489,6 +1501,7 @@ xbInt16 xbExp::ParseExpressionField( xbExpToken &t, xbExpNode *n ){ try{ xbUInt32 lPos; + if(( lPos = t.sToken.Pos( "->" )) > 0 ){ // table name is part of the token xbString sTableName = t.sToken; @@ -1496,6 +1509,22 @@ xbInt16 xbExp::ParseExpressionField( xbExpToken &t, xbExpNode *n ){ sFieldName = t.sToken; sFieldName.Mid( lPos + 2, t.sToken.Len() - lPos - 1 ); pDbf = (xbDbf *) xbase->GetDbfPtr( sTableName ); + + +/* + // updated 1/2/23 to support either table.field or table->field + if((( lPos = t.sToken.Pos( "->" )) > 0) || (( lPos = t.sToken.Pos( "." )) > 0) ){ + // table name is part of the token + xbString sTableName = t.sToken; + sTableName.Left( lPos-1 ); + sFieldName = t.sToken; + if( t.sToken[lPos] == '.' ) + sFieldName.Mid( lPos + 1, t.sToken.Len() - lPos ); + else // -> + sFieldName.Mid( lPos + 2, t.sToken.Len() - lPos - 1 ); + pDbf = (xbDbf *) xbase->GetDbfPtr( sTableName ); +*/ + } else { // table name is not part of the token pDbf = dbf; diff --git a/src/core/xbfile.cpp b/src/core/xbfile.cpp index 937c16f..3b798a2 100755 --- a/src/core/xbfile.cpp +++ b/src/core/xbfile.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -48,6 +48,119 @@ xbFile::~xbFile(){ xbFclose(); } +/************************************************************************/ +//! @brief Create Home Folders. +/*! + Create xbase64 log and data folders in the home directory for current usre. + + \returns Return Codes +*/ + +xbInt16 xbFile::SetHomeFolders(){ + + xbInt16 iErrorStop = 0; + xbInt16 iRc = XB_NO_ERROR; + xbString sHomeDir; + char cPathSeperator; + xbString sDflt; + + try{ + + GetHomeDir( sHomeDir ); + //std::cout << "CreateHomeFolders() home dir = [" << sHomeDir.Str() << "]\n"; + + if( FileExists( sHomeDir ) == xbFalse ){ + iErrorStop = 100; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + + #ifdef WIN32 + cPathSeperator = '\\'; + #else + cPathSeperator = '/'; + #endif + sDflt.Sprintf( ".%c", cPathSeperator ); + // set the default folders just in case later steps fail + xbase->SetDataDirectory( sDflt ); + #ifdef XB_LOGGING_SUPPORT + xbase->SetLogDirectory( sDflt ); + #endif + + if( sHomeDir[sHomeDir.Len()] != cPathSeperator ) + sHomeDir += cPathSeperator; + + xbString sWork( sHomeDir ); + sWork += "xbase64"; + + if( FileExists( sWork ) == xbFalse ){ + #ifdef WIN32 + if( CreateDirectory( sWork.Str(), NULL ) == 0 ){ + iErrorStop = 130; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #else + // 0777 mode is correct, the mode will be modified by the user's umask + if( mkdir( sWork.Str(), 0777 ) == -1 ){ + iErrorStop = 140; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #endif + } + + #ifdef XB_LOGGING_SUPPORT + sWork.Sprintf( "%sxbase64%clogs", sHomeDir.Str(), cPathSeperator ); + // std::cout << "logdir = " << sWork.Str() << "\n"; + + if( FileExists( sWork ) == xbFalse ){ + #ifdef WIN32 + if( CreateDirectory( sWork.Str(), NULL ) == 0 ){ + iErrorStop = 110; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #else + if( mkdir( sWork.Str(), 0777 ) == -1 ){ + iErrorStop = 120; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #endif + } + xbase->SetLogDirectory( sWork ); + #endif // XB_LOGGING_SUPPORT + + sWork.Sprintf( "%sxbase64%cdata", sHomeDir.Str(), cPathSeperator ); + // std::cout << "datadir = " << sWork.Str() << "\n"; + if( FileExists( sWork ) == xbFalse ){ + #ifdef WIN32 + if( CreateDirectory( sWork.Str(), NULL ) == 0 ){ + iErrorStop = 130; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #else + if( mkdir( sWork.Str(), 0777 ) == -1 ){ + iErrorStop = 140; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #endif + } + xbase->SetDataDirectory( sWork ); + + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbFile::CreateHomeFolders() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return iRc; +} + /************************************************************************/ //! @brief Create a unique file name. /*! @@ -1445,7 +1558,7 @@ xbInt16 xbFile::xbFputs( const xbString & s ){ /*! \param p Pointer to data to write \param size size of write - \param nmemb Number of times to write it + \param nmemb Number of times to read it \returns Return Codes */ @@ -1899,69 +2012,39 @@ void xbFile::SetLockRetryCount( xbInt16 iLockRetries ) { } #endif + + /***********************************************************************/ #ifdef XB_DEBUG_SUPPORT -//! @brief Debugging routine - dump a block to the log file. +//! @brief Debugging routine - dump mem to the log file. /*! - This routine dumps a block to a file in the log file. This is + This routine dumps data from meemory to the log file. This is primarily used for debugging and analysis purposes. - \param ulBlockNo Block number to write + \param p Pointer to data to write \param lBlxkSize Size of block \returns Return Codes */ -xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ +xbInt16 xbFile::DumpMemToDisk( char *p, size_t lSize ){ xbInt16 iRc = 0; xbInt16 iErrorStop = 0; - - xbUInt32 ulStartBlock; - xbUInt32 ulEndBlock; - - char *p = 0x00; - xbString sDir; xbString sFn; - char *buf = NULL; - FILE *fpd = NULL; - try{ - iErrorStop = 100; - if( ulBlockNo == 0 ){ - ulStartBlock = 0; - xbUInt64 ullFileSizeulBlockNo; - if(( iRc = GetFileSize( ullFileSizeulBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - ulEndBlock = (xbUInt32) (ullFileSizeulBlockNo / lBlkSize); - } else { - ulStartBlock = ulBlockNo; - ulEndBlock = ulBlockNo; - } - - if(( buf = (char *) malloc( lBlkSize )) == NULL ){ - iErrorStop = 120; - iRc = XB_NO_MEMORY; - throw iRc; - } - - sDir = GetDefaultLogDirectory(); - char cLastChar = sDir[sDir.Len()]; + FILE *fpd = NULL; - for( xbUInt32 l = ulStartBlock; l < ulEndBlock; l++ ){ + try{ - if(( iRc = ReadBlock( l, lBlkSize, buf )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } + sDir = GetLogDirectory(); + char cLastChar = sDir[sDir.Len()]; // build logfile name if( cLastChar != '/' && cLastChar != '\\' ) - sFn.Sprintf( "%s/Blockdump.B%ld", sDir.Str(), l); + sFn.Sprintf( "%s/MemDump.txt", sDir.Str()); else - sFn.Sprintf( "%sBlockDump.%ld", sDir.Str(), l); + sFn.Sprintf( "%sMemDump.txt", sDir.Str()); // open the dump file for append #ifdef HAVE__FSOPEN_F @@ -1969,17 +2052,17 @@ xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ #else if(( fpd = fopen( sFn.Str(), "w+b")) == NULL ){ #endif - iErrorStop = 140; + iErrorStop = 100; iRc = XB_OPEN_ERROR; throw iRc; } + int i; // dump the block to the file - p = buf; - for( size_t l = 0; l < lBlkSize; l++ ){ - //if( fputc( *p, fpd ) != *p ){ - if( fputc( *p, fpd ) == EOF ){ - iErrorStop = 150; + for( size_t l = 0; l < lSize; l++ ){ + i = *p; + if( fputc( i, fpd ) == EOF ){ + iErrorStop = 110; iRc = XB_WRITE_ERROR; throw iRc; } @@ -1988,6 +2071,103 @@ xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ // close the dump file fclose( fpd ); } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbFile::DumpBlockToDisk() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + if( fpd ) + fclose( fpd ); + } + return iRc; +} + +/***********************************************************************/ +//! @brief Debugging routine - dump a block to the log file. +/*! + This routine dumps a block to the log file. This is + primarily used for debugging and analysis purposes. + + \param ulBlockNo Block number to write + \param lBlxkSize Size of block + \returns Return Codes +*/ +xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + xbUInt32 ulStartBlock; + xbUInt32 ulEndBlock; + + char *p = 0x00; + + xbString sDir; + xbString sFn; + char *buf = NULL; + FILE *fpd = NULL; + try{ + + if( ulBlockNo == 0 ){ + ulStartBlock = 0; + xbUInt64 ullFileSizeulBlockNo; + if(( iRc = GetFileSize( ullFileSizeulBlockNo )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + ulEndBlock = (xbUInt32) (ullFileSizeulBlockNo / lBlkSize); + } else { + ulStartBlock = ulBlockNo; + ulEndBlock = ulBlockNo; + } + + if(( buf = (char *) malloc( lBlkSize )) == NULL ){ + iErrorStop = 110; + iRc = XB_NO_MEMORY; + throw iRc; + } + + sDir = GetLogDirectory(); + char cLastChar = sDir[sDir.Len()]; + + for( xbUInt32 l = ulStartBlock; l < ulEndBlock; l++ ){ + + if(( iRc = ReadBlock( l, lBlkSize, buf )) != XB_NO_ERROR ){ + iErrorStop = 120; + throw iRc; + } + + // build logfile name + if( cLastChar != '/' && cLastChar != '\\' ) + sFn.Sprintf( "%s/BlockDump.B%ld", sDir.Str(), l); + else + sFn.Sprintf( "%sBlockDump.%ld", sDir.Str(), l); + + // open the dump file for append + #ifdef HAVE__FSOPEN_F + if(( fpd = _fsopen( sFn.Str(), "w+b", 0x40 )) == NULL ){ + #else + if(( fpd = fopen( sFn.Str(), "w+b")) == NULL ){ + #endif + iErrorStop = 130; + iRc = XB_OPEN_ERROR; + throw iRc; + } + + // dump the block to the file + p = buf; + for( size_t l = 0; l < lBlkSize; l++ ){ + //if( fputc( *p, fpd ) != *p ){ + if( fputc( *p, fpd ) == EOF ){ + iErrorStop = 140; + iRc = XB_WRITE_ERROR; + throw iRc; + } + p++; + } + // close the dump file + fclose( fpd ); + } // free the buffer if( buf ) @@ -1995,10 +2175,7 @@ xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ } catch (xbInt16 iRc ){ xbString sMsg; - if( iErrorStop == 160 ) - sMsg.Sprintf( "xbFile::DumpBlockToDisk() Exception Caught. Error Stop = [%d] iRc = [%d] c=[%c][%x]", iErrorStop, iRc, *p, *p ); - else - sMsg.Sprintf( "xbFile::DumpBlockToDisk() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + sMsg.Sprintf( "xbFile::DumpBlockToDisk() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); xbase->WriteLogMessage( sMsg.Str() ); xbase->WriteLogMessage( GetErrorMessage( iRc )); if( buf ) @@ -2007,7 +2184,6 @@ xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ fclose( fpd ); } return iRc; - } #endif /***********************************************************************/ diff --git a/src/core/xbfilter.cpp b/src/core/xbfilter.cpp index 507a9e7..0fb643d 100755 --- a/src/core/xbfilter.cpp +++ b/src/core/xbfilter.cpp @@ -26,8 +26,7 @@ This module handles uda (user data area) methods namespace xb{ /************************************************************************/ -xbFilter::xbFilter( xbXBase *xbase, xbDbf *dbf ) { - this->xbase = xbase; +xbFilter::xbFilter( xbDbf *dbf ) { this->dbf = dbf; this->exp = NULL; lLimit = 0; // max number of responses @@ -62,6 +61,12 @@ void xbFilter::ResetQryCnt(){ this->lCurQryCnt = 0; } +/************************************************************************/ +xbInt16 xbFilter::Set( const char *sFilter ) { + xbString sFilt( sFilter ); + return Set( sFilt ); +} + /************************************************************************/ xbInt16 xbFilter::Set( xbString &sFilter ) { @@ -72,7 +77,7 @@ xbInt16 xbFilter::Set( xbString &sFilter ) { if( exp ) delete exp; - exp = new xbExp( xbase, dbf ); + exp = new xbExp( dbf->GetXbasePtr(), dbf ); if(( iRc = exp->ParseExpression( sFilter.Str() )) != XB_NO_ERROR ){ iErrorStop = 100; throw iRc; @@ -88,8 +93,8 @@ xbInt16 xbFilter::Set( xbString &sFilter ) { catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::SetExpression() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -141,8 +146,8 @@ xbInt16 xbFilter::GetFirstRecord( xbInt16 iOption ) { catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetFirstRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -196,8 +201,8 @@ xbInt16 xbFilter::GetNextRecord( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetNextRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -251,8 +256,8 @@ xbInt16 xbFilter::GetPrevRecord( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetPrevRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -304,8 +309,8 @@ xbInt16 xbFilter::GetLastRecord( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetLastRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -363,8 +368,8 @@ xbInt16 xbFilter::GetFirstRecordIx( xbInt16 iOption ) { catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetFirstRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -419,8 +424,8 @@ xbInt16 xbFilter::GetNextRecordIx( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetNextRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -475,8 +480,8 @@ xbInt16 xbFilter::GetPrevRecordIx( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetPrevRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -491,7 +496,6 @@ xbInt16 xbFilter::GetLastRecordIx( xbInt16 iOption ){ iErrorStop = 100; throw iRc; } - lCurQryCnt = 0; if(( iRc = dbf->GetCurIx()->GetLastKey( dbf->GetCurTag(), iOption )) != XB_NO_ERROR ){ if( iRc == XB_EOF ) @@ -501,7 +505,6 @@ xbInt16 xbFilter::GetLastRecordIx( xbInt16 iOption ){ throw iRc; } } - xbBool bFound = xbFalse; while( !bFound && iRc == XB_NO_ERROR ){ if(( iRc = exp->ProcessExpression()) != XB_NO_ERROR ){ @@ -528,12 +531,11 @@ xbInt16 xbFilter::GetLastRecordIx( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetLastRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } - #endif // XB_INDEX_SUPPORT diff --git a/src/core/xbixmdx.cpp b/src/core/xbixmdx.cpp index 95f342c..135cde8 100755 --- a/src/core/xbixmdx.cpp +++ b/src/core/xbixmdx.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -108,7 +108,7 @@ xbInt16 xbIxMdx::AddKey( void * vpTag, xbUInt32 ulRecNo ){ } else { // land here with a full leaf node - //std::cout << "Section B begin split leaf node\n"; + // std::cout << "Section B begin split leaf node\n"; iHeadNodeUpdateOpt = 1; npRightNode = AllocateIxNode( npTag, GetBlockSize() + (xbUInt32) npTag->iKeyItemLen, npTag->npCurNode->ulBlockNo * (xbUInt32) iBlockFactor ); @@ -122,7 +122,7 @@ xbInt16 xbIxMdx::AddKey( void * vpTag, xbUInt32 ulRecNo ){ ulNewRightChild = npRightNode->ulBlockNo * (xbUInt32) iBlockFactor; } - //std::cout << "ulNewRightChild = " << ulNewRightChild << "\n"; + // std::cout << "ulNewRightChild = " << ulNewRightChild << "\n"; if(( iRc = xbIxMdx::SplitNodeL( npTag, npTag->npCurNode, npRightNode, npTag->npCurNode->iCurKeyNo, npTag->cpKeyBuf, ulRecNo )) != XB_NO_ERROR ){ iErrorStop = 130; @@ -169,7 +169,8 @@ xbInt16 xbIxMdx::AddKey( void * vpTag, xbUInt32 ulRecNo ){ // section D - if cur node is split root, create new root if(( npTag->npCurNode->ulBlockNo * (xbUInt32) iBlockFactor ) == npTag->ulRootPage ){ - // std::cout << "Section D begin\n"; + + // std::cout << "Section D begin right node = " << npRightNode << "\n"; if(( iRc = AddKeyNewRoot( npTag, npTag->npCurNode, npRightNode )) != XB_NO_ERROR ){ iErrorStop = 160; @@ -179,9 +180,10 @@ xbInt16 xbIxMdx::AddKey( void * vpTag, xbUInt32 ulRecNo ){ if( npRightNode ) npRightNode = FreeNodeChain( npRightNode ); - //std::cout << "Section D end\n"; + // std::cout << "Section D end\n"; } else { + // std::cout << "Section E, put key in parent\n"; if(( iRc = InsertNodeI( (void *) vpTag, (xbIxNode *) npParent, (xbInt16) npParent->iCurKeyNo, BlockToPage( npRightNode->ulBlockNo ))) != XB_NO_ERROR ){ iErrorStop = 170; @@ -284,8 +286,8 @@ xbInt16 xbIxMdx::AddKeyNewRoot( xbMdxTag *npTag, xbIxNode *npLeft, xbIxNode *np // std::cout << "AddKeyNewRoot - LeftBlock = " << npLeft->ulBlockNo << "\n"; // std::cout << "AddKeyNewRoot - RightBlock = " << npRight->ulBlockNo << "\n"; - pLastKey = (char *) malloc( (size_t) npTag->iKeyLen ); + pLastKey = (char *) malloc( (size_t) npTag->iKeyLen ); if(( iRc = GetLastKeyForBlockNo( npTag, npLeft->ulBlockNo, pLastKey )) != XB_NO_ERROR ){ iErrorStop = 110; throw iRc; @@ -301,10 +303,17 @@ xbInt16 xbIxMdx::AddKeyNewRoot( xbMdxTag *npTag, xbIxNode *npLeft, xbIxNode *np // set the key pTrg+= 4; + // std::cout << "AddKeyNewRoot - key [" << pLastKey << "] len = [" << strlen( pLastKey) << "]\n"; memcpy( pTrg, pLastKey, (size_t) npTag->iKeyLen ); // set the right node number - pTrg+= (npTag->iKeyLen); + //pTrg+= (npTag->iKeyLen); + // pTrg+= (npTag->iKeyItemLen)-4; + + pTrg+= npTag->iKeyItemLen - 4; + + //pTrg-=4; + ePutUInt32( pTrg, npRight->ulBlockNo * (xbUInt32) iBlockFactor ); // write out the new block @@ -598,15 +607,17 @@ xbInt16 xbIxMdx::CheckTagIntegrity( void *vpTag, xbInt16 iOpt ){ iErrorStop = 100; throw iRc; } - bLocked = xbTrue; + bLocked = xbTrue; } #endif memset( npTag->cpKeyBuf2, 0x00, (size_t) npTag->iKeyLen ); + // memset( npTag->cpKeyBuf2, 0x00, (size_t) npTag->iKeyItemLen ); cKeyType = GetKeyType( vpTag ); pPrevKeyBuf = (char *) calloc( 1, (size_t) npTag->iKeyLen ); iRc = GetFirstKey( vpTag, 0 ); + memcpy( pPrevKeyBuf, GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->iKeyItemLen ), (size_t) npTag->iKeyLen ); // for each key in the index, make sure it is trending in the right direction @@ -719,7 +730,7 @@ xbInt16 xbIxMdx::CheckTagIntegrity( void *vpTag, xbInt16 iOpt ){ free( pPrevKeyBuf ); if( iErrorStop == 160 ){ - sMsg.Sprintf( "xbIxNdx::CheckTagIntegrity() Missing index entry for record [%d]", ulThisRecNo ); + sMsg.Sprintf( "xbIxMdx::CheckTagIntegrity() Missing index entry for record [%d]", ulThisRecNo ); xbase->WriteLogMessage( sMsg, iOpt ); } } @@ -1171,8 +1182,13 @@ xbInt16 xbIxMdx::CreateTag( const xbString &sName, const xbString &sKey, const tte->cKeyType2 = tte->cKeyType; tte->iKeyItemLen = tte->iKeyLen + 4; + while(( tte->iKeyItemLen % 4 ) != 0 ) tte->iKeyItemLen++; tte->iKeysPerBlock = (xbInt16) (GetBlockSize() - 12) / tte->iKeyItemLen; + + //std::cout << "-------------- create tag info\n"; + //std::cout << "keylen=" << tte->iKeyLen << " iKeyItemLen = " << tte->iKeyItemLen << " keys per block calc = " << tte->iKeysPerBlock << "\n"; + tte->cKeyFmt3 = CalcTagKeyFmt( *tte->exp ); // printf( "ulRootPage=[%d] cKeyFmt2=[%d] cKeyType2=[%d] iKeyLen=[%d]iKeysPerBlock=[%d]\n", tte->ulRootPage, tte->cKeyFmt2, tte->cKeyType2, tte->iKeyLen, tte->iKeysPerBlock ); @@ -2657,6 +2673,7 @@ xbInt16 xbIxMdx::GetFirstKey( void *vpTag, xbInt16 iRetrieveSw = 0 ){ // convert the tag pointer to mdx tag pointer xbMdxTag * mpTag = (xbMdxTag *) vpTag; + try{ // clear out any history if( mpTag->npNodeChain ){ @@ -2668,6 +2685,7 @@ xbInt16 xbIxMdx::GetFirstKey( void *vpTag, xbInt16 iRetrieveSw = 0 ){ iErrorStop = 100; throw iRc; } + // lRootPage is available if(( iRc = GetBlock( vpTag, (mpTag->ulRootPage / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ iErrorStop = 110; @@ -2683,8 +2701,7 @@ xbInt16 xbIxMdx::GetFirstKey( void *vpTag, xbInt16 iRetrieveSw = 0 ){ return iRc; } - while( !IsLeaf( vpTag, mpTag->npCurNode )) // go down the chain looking for a leaf node - { + while( !IsLeaf( vpTag, mpTag->npCurNode )){ // go down the chain looking for a leaf node if(( iRc = GetKeyPtr( vpTag, 0, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ iErrorStop = 120; throw iRc; @@ -2878,7 +2895,7 @@ xbInt16 xbIxMdx::GetLastKey( xbUInt32 ulBlockNo, void *vpTag, xbInt16 iRetrieveS } mpTag->npCurNode->iCurKeyNo = ulNoOfKeys; - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); + ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); xbUInt32 ulKeyPtr = 0; while( !IsLeaf( vpTag, mpTag->npCurNode )){ // go down the chain looking for a leaf node @@ -3559,6 +3576,11 @@ xbInt16 xbIxMdx::InsertNodeI( void *vpTag, xbIxNode *npNode, xbInt16 iSlotNo, xb pSrc = pLastKey; for( xbInt16 i = 0; i < npTag->iKeyLen; i++ ) *pTrg++ = *pSrc++; + + pTrg = pNewKeyPos; + //pTrg+= npTag->iKeyItemLen - 4; + pTrg+= npTag->iKeyItemLen; + ePutUInt32( pTrg, ulPtr); ePutInt32( npNode->cpBlockData, ++lKeyCnt ); @@ -4683,7 +4705,7 @@ xbInt16 xbIxMdx::SplitNodeI( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, } catch (xbInt16 iRc ){ xbString sMsg; - sMsg.Sprintf( "xbIxNdx::SplitNodeI() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + sMsg.Sprintf( "xbIxMdx::SplitNodeI() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( iRc )); } @@ -4712,7 +4734,7 @@ xbInt16 xbIxMdx::SplitNodeI( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, \returns Return Codes */ -xbInt16 xbIxMdx::SplitNodeL( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, +xbInt16 xbIxMdx::SplitNodeL( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, xbInt16 iSlotNo, char * cpKeyBuf, xbUInt32 ulPtr ){ xbInt16 iRc = XB_NO_ERROR; diff --git a/src/core/xbixndx.cpp b/src/core/xbixndx.cpp index dcec5f9..9d946dd 100755 --- a/src/core/xbixndx.cpp +++ b/src/core/xbixndx.cpp @@ -342,7 +342,7 @@ xbInt16 xbIxNdx::CheckTagIntegrity( void *vpTag, xbInt16 iOpt ){ iErrorStop = 100; throw iRc; } - bLocked = xbTrue; + bLocked = xbTrue; } #endif @@ -425,7 +425,6 @@ xbInt16 xbIxNdx::CheckTagIntegrity( void *vpTag, xbInt16 iOpt ){ sMsg.Sprintf( "CheckTagIntegrity() Index entry count [%ld] matches dbf record count [%ld]", ulIxCnt, ulDbfCnt ); xbase->WriteLogMessage( sMsg, iOpt ); } - if( pPrevKeyBuf ) free( pPrevKeyBuf ); diff --git a/src/core/xblog.cpp b/src/core/xblog.cpp index ea7c9d6..6031c9e 100755 --- a/src/core/xblog.cpp +++ b/src/core/xblog.cpp @@ -25,8 +25,8 @@ namespace xb{ //! @brief Constructor. xbLog::xbLog() : xbFile( NULL ){ - SetDirectory( GetDefaultLogDirectory()); - SetFileName ( GetDefaultLogFileName()); + SetDirectory( GetLogDirectory()); + SetFileName ( GetLogFileName()); bLoggingStatus = xbFalse; lLogSize = 50000; diff --git a/src/core/xbssv.cpp b/src/core/xbssv.cpp index 252daab..d3e1070 100755 --- a/src/core/xbssv.cpp +++ b/src/core/xbssv.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -15,8 +15,6 @@ Email Contact: #include "xbase.h" - - namespace xb{ const xbErrorMessage xbErrorMessages[] = { @@ -26,6 +24,7 @@ const xbErrorMessage xbErrorMessages[] = { { XB_DUP_TABLE_OR_ALIAS, "Duplicate Alias/Table Name" }, { XB_INVALID_NODELINK, "Invalid Node Link" }, { XB_KEY_NOT_UNIQUE, "Key Not Unique" }, + { XB_MEMCPY_ERROR, "Memory copy failure" }, { XB_FILE_EXISTS, "File Already Exists" }, { XB_ALREADY_OPEN, "Database already open" }, { XB_DBF_FILE_NOT_OPEN, "DBF File Not Open" }, @@ -49,6 +48,8 @@ const xbErrorMessage xbErrorMessages[] = { { XB_INVALID_TABLE_NAME, "Invalid Table Name" }, { XB_EMPTY, "Empty Table or Index" }, { XB_LIMIT_REACHED, "Limit Reached" }, + { XB_BLOCKREAD_NOT_ENABLED, "Block Read Mode is not enabled" }, + { XB_DIRECTORY_ERROR, "Directory Read/Write error" }, { XB_INVALID_FIELD_TYPE, "Unknown Field Type" }, { XB_INVALID_FIELD_NO, "Invalid Field Number" }, { XB_INVALID_DATA, "Invalid Data" }, @@ -89,12 +90,13 @@ xbBool xbSsv::bDefaultAutoCommit = xbTrue; xbString xbSsv::sDataDirectory = PROJECT_DATA_DIR; #else xbString xbSsv::sDataDirectory = PROJECT_DATA_DIR; -#endif +#endif // #ifdef XB_LOGGING_SUPPORT -xbString xbSsv::sDefaultLogDirectory = PROJECT_LOG_DIR; -xbString xbSsv::sDefaultLogFileName = PROJECT_DFLT_LOGFILE; -#endif +xbString xbSsv::sLogDirectory = PROJECT_LOG_DIR; +//xbString xbSsv::sLogDirectory = ""; +xbString xbSsv::sLogFileName = PROJECT_DFLT_LOGFILE; +#endif // XB_LOGGING_SUPPORT #ifdef XB_LOCKING_SUPPORT xbInt32 xbSsv::lDefaultLockWait = 100; @@ -104,18 +106,21 @@ xbInt16 xbSsv::iDefaultLockFlavor = 1; xbBool xbSsv::bMultiUser = xbTrue; #else xbBool xbSsv::bMultiUser = xbFalse; -#endif +#endif // XB_LOCKING_SUPPORT #if defined (XB_NDX_SUPPORT) || defined (XB_MDX_SUPPORT) xbInt16 xbSsv::iUniqueKeyOpt = XB_HALT_ON_DUPKEY; // is one of XB_HALT_ON_DUPKEY || XB_EMULATE_DBASE -#endif +#endif // defined (XB_NDX_SUPPORT) || defined (XB_MDX_SUPPORT) #ifdef XB_MDX_SUPPORT xbInt16 xbSsv::iCreateMdxBlockSize = 1024; // 1024 is DBase 7 default size for MDX index blocks -#endif +#endif // XB_MDX_SUPPORT +#ifdef XB_BLOCKREAD_SUPPORT +xbUInt32 xbSsv::ulDefaultBlockReadSize = 32768; // 32K buffer for block DBF datafile reads +#endif // XB_BLOCKREAD_SUPPORT /*************************************************************************/ //! @brief Class Constructor. @@ -139,7 +144,6 @@ void xbSsv::BitDump( char c ) const { xbBool xbSsv::BitSet( unsigned char c, xbInt16 iBitNo ) const { return c & 1 << iBitNo; } - /*************************************************************************/ //! @brief Display error message on console for a given error number. /*! @@ -164,7 +168,6 @@ void xbSsv::DisplayError( xbInt16 iErrorCode ) const { xbBool xbSsv::GetDefaultAutoCommit() const { return bDefaultAutoCommit; } - /*************************************************************************/ //! @brief Get the current data directory. /*! @@ -184,19 +187,6 @@ xbString &xbSsv::GetDataDirectory() const { xbString & xbSsv::GetDefaultDateFormat() const { return sDefaultDateFormat; } - -/*************************************************************************/ -// @brief Get the default file format version. -/* - \returns 3 - Dbase III file format
- 4 - Dbase IV file format
-*/ - -/* -xbInt16 xbSsv::GetDefaultFileVersion() const { - return iDefaultFileVersion; -} -*/ /*************************************************************************/ //! @brief Get the Endian type. /*! @@ -206,7 +196,6 @@ xbInt16 xbSsv::GetDefaultFileVersion() const { xbInt16 xbSsv::GetEndianType() const { return iEndianType; } - /*************************************************************************/ //! @brief Get an error message. /*! @@ -230,7 +219,25 @@ const char * xbSsv::GetErrorMessage( xbInt16 iErrorCode ) const{ } return ""; } +/*************************************************************************/ +//! @brief Get home directory. +/*! + \param sHomeDirOut - Output home directory for current user. + \returns void +*/ + +void xbSsv::GetHomeDir( xbString &sHomeDirOut ){ + #ifdef WIN32 + sHomeDirOut.Sprintf( "%s%s", getenv( "HOMEDRIVE" ), getenv( "HOMEPATH" )); + #else + sHomeDirOut.Sprintf( "%s", getenv( "HOME" )); + sHomeDirOut.Trim(); + if( sHomeDirOut == "" ) + sHomeDirOut.Sprintf( "%s", getpwuid( getuid())->pw_dir ); + #endif + sHomeDirOut.Trim(); +} /*************************************************************************/ //! @brief Set the data directory. /*! @@ -240,7 +247,6 @@ const char * xbSsv::GetErrorMessage( xbInt16 iErrorCode ) const{ void xbSsv::SetDataDirectory( const xbString &sDataDirectory ){ this->sDataDirectory = sDataDirectory; - #ifdef WIN32 this->sDataDirectory.SwapChars( '/', '\\' ); #else @@ -302,57 +308,53 @@ void xbSsv::SetEndianType() { /*! \returns Returns the log file name. */ -xbString & xbSsv::GetDefaultLogFileName() const { - return sDefaultLogFileName; +xbString & xbSsv::GetLogFileName() const { + return sLogFileName; } - /*************************************************************************/ //! @brief Get the default log directory. /*! \returns Returns the log directory. */ -xbString & xbSsv::GetDefaultLogDirectory() const { - return sDefaultLogDirectory; +xbString & xbSsv::GetLogDirectory() const { + return sLogDirectory; } /*************************************************************************/ //! @brief Set the default log directory name. /*! - \param sDefaultLogDirectory Name of desired log directory. + \param sLogDirectory Name of desired log directory. */ -void xbSsv::SetDefaultLogDirectory( const xbString &sDefaultLogDirectory ){ - - this->sDefaultLogDirectory = sDefaultLogDirectory; +void xbSsv::SetLogDirectory( const xbString &sLogDirectoryIn ){ + this->sLogDirectory = sLogDirectoryIn; #ifdef WIN32 - this->sDefaultLogDirectory.SwapChars( '/', '\\' ); + this->sLogDirectory.SwapChars( '/', '\\' ); #else - this->sDefaultLogDirectory.SwapChars( '\\', '/' ); + this->sLogDirectory.SwapChars( '\\', '/' ); #endif - } #else -xbString & xbSsv::GetDefaultLogFileName() const { +xbString & xbSsv::GetLogFileName() const { return sNullString; } -xbString & xbSsv::GetDefaultLogDirectory() const { +xbString & xbSsv::GetLogDirectory() const { return sNullString; } -void xbSsv::SetDefaultLogDirectory( const xbString &sDefaultLogDirectory ){ +void xbSsv::SetLogDirectory( const xbString &sLogDirectory ){ return; } #endif - /*************************************************************************/ #ifdef XB_LOCKING_SUPPORT @@ -541,6 +543,29 @@ xbInt16 xbSsv::SetUniqueKeyOpt( xbInt16 iOpt ){ } #endif /************************************************************************/ +#ifdef XB_BLOCKREAD_SUPPORT + +//! @brief Get Default Read Block Size +/*! + This routine returns the default read block size used when allocating + buffer space for block reads of table data. Initial setting is 32768 bytes. +*/ +xbUInt32 xbSsv::GetDefaultBlockReadSize() const { + return ulDefaultBlockReadSize; +} + + +//! @brief Set Default Read Block Size +/*! + This routine sets the default read block size used when allocating + buffer space for block reads of table data. Initial setting is 32768 bytes. +*/ +void xbSsv::SetDefaultBlockReadSize( xbUInt32 ulDfltBlockReadSize ){ + ulDefaultBlockReadSize = ulDfltBlockReadSize; +} + +#endif // XB_BLOCKREAD_SUPPORT +/************************************************************************/ diff --git a/src/core/xbstring.cpp b/src/core/xbstring.cpp index 81e67b8..701e50e 100755 --- a/src/core/xbstring.cpp +++ b/src/core/xbstring.cpp @@ -1263,6 +1263,45 @@ xbString &xbString::PadRight( char c, xbUInt32 ulNewLen ){ return *this; } +/************************************************************************/ +//! @brief Determine position of a given character +/*! + \param c Seek character + \param ulStartPos starting position for search, first position is 1 + \returns Position within string. Returns 0 if not found. +*/ +xbUInt32 xbString::Pos(char c, xbUInt32 ulStartPos ) const { + + if (data == NULL) + return 0; + char *p = data; + + if( ulStartPos >= size ) + return 0; + + xbUInt32 iPos = 0; + while( (iPos+1) < ulStartPos ){ + p++; + iPos++; + } + xbBool bFound = 0; + while( *p && !bFound && iPos < ( size - 1 )){ + if( *p == c ) + bFound = 1; + else { + iPos++; + p++; + } + } + + if( bFound ) + return iPos + 1; + else + return 0; +} + + + /************************************************************************/ //! @brief Determine position of a given character /*! @@ -1375,41 +1414,51 @@ xbString &xbString::Replace( const char *sReplace, const char *sReplaceWith, xbI xbBool bDone = xbFalse; xbUInt32 ulPos; - xbUInt32 ulNewSize; + xbUInt32 ulNewLen; + xbUInt32 ulReplaceWithLen; + xbUInt32 ulRsLen; // size of right side of string after replaced data xbUInt32 ulSp2; char *sBuf2; + const char *s; // source ptr + char *t; // target ptr + while( !bDone ){ ulPos = Pos( sReplace ); if( ulPos == 0 ){ bDone = xbTrue; } else { - ulNewSize = this->size + sizeof( sReplaceWith ) - sizeof( sReplace ); - sBuf2 = (char *) calloc( 1, ulNewSize ); + ulReplaceWithLen = (xbUInt32) strlen( sReplaceWith ); + ulNewLen = this->size + ulReplaceWithLen - (xbUInt32) strlen( sReplace ); + sBuf2 = (char *) calloc( 1, ulNewLen ); // copy part1 + t = sBuf2; + s = data; for( xbUInt32 ul = 0; ul < ulPos-1; ul++ ) - sBuf2[ul] = data[ul]; + *t++ = *s++; // copy part2 - strcat( sBuf2, sReplaceWith ); + s = sReplaceWith; + for( xbUInt32 ul = 0; ul < ulReplaceWithLen; ul++ ) + *t++ = *s++; // copy part3 - ulSp2 = ulPos + strlen( sReplace ); - char *p = data; - p+= (ulSp2 - 1); - strcat( sBuf2, p ); + ulSp2 = ulPos + (xbUInt32) strlen( sReplace ); + s = data; + s+= (ulSp2 - 1); + ulRsLen = (xbUInt32) strlen( s ); + for( xbUInt32 ul = 0; ul < ulRsLen; ul++ ) + *t++ = *s++; if( iOption ) bDone = xbTrue; free(data); data = sBuf2; - } } - return *this; } diff --git a/src/core/xbtblmgr.cpp b/src/core/xbtblmgr.cpp index f154dc6..2fe6a8c 100755 --- a/src/core/xbtblmgr.cpp +++ b/src/core/xbtblmgr.cpp @@ -22,20 +22,19 @@ Email Contact: namespace xb{ /*************************************************************************/ - xbTblMgr::xbTblMgr(){ TblList = NULL; iOpenTableCount = 0; } /*************************************************************************/ - xbTblMgr::~xbTblMgr(){ xbTblList *l; if( TblList ){ while( TblList ){ l = TblList; TblList = TblList->pNext; + delete l->psFqTblName; delete l->psTblName; delete l->psTblAlias; free( l ); @@ -44,47 +43,74 @@ xbTblMgr::~xbTblMgr(){ } /*************************************************************************/ - -xbInt16 xbTblMgr::AddTblToTblList( xbDbf *d, const xbString & sTblName ){ - return AddTblToTblList( d, sTblName, "" ); +xbInt16 xbTblMgr::AddTblToTblList( xbDbf *d, const xbString & sFqTblName ){ + return AddTblToTblList( d, sFqTblName, "" ); } /*************************************************************************/ +xbInt16 xbTblMgr::AddTblToTblList( xbDbf *d, const xbString & sFqTblName, const xbString & sTblAlias ) { + + // Set the Fq (fully qualified name) + // Pull the table name from the FQ name + // Set the Alias to the table name if the alias name is not provided -xbInt16 xbTblMgr::AddTblToTblList( xbDbf *d, const xbString & sTblName, const xbString & sTblAlias ) { xbTblList *i, *s, *t; xbInt16 iRc = 0; xbInt16 iErrorStop = 0; + xbString sTblName; xbString sAlias; + xbString sTemp; + xbString sFqTemp; + xbUInt32 iSlashPos; + + // std::cout << "AddTblToTblList fq in = [" << sFqTblName.Str() << "] alias in =[" << sTblAlias.Str() << "]\n"; try{ - if( sTblName.Len() == 0 ){ + if( sFqTblName.Len() == 0 ){ iErrorStop = 100; iRc = XB_INVALID_TABLE_NAME; throw iRc; } - if( sTblAlias.Len() == 0 ){ + sTblName = sFqTblName; + sTblName.SwapChars( '\\', '/' ); + iSlashPos = sTblName.GetLastPos( '/' ); + + // std::cout << "slashpos = " << iSlashPos << "\n"; + + + if( iSlashPos > 0 ){ + sTblName.Ltrunc( iSlashPos ); // remove the directory part from the table name + sFqTemp = sFqTblName; + } else{ + sFqTemp.Sprintf( "%s%s", GetDataDirectory().Str(), sFqTblName.Str()); // add the dir part to the FQ name + } + + xbUInt32 iDbfPos = sFqTemp.Pos( ".DBF" ); + if( iDbfPos == 0 ) + sFqTemp += ".DBF"; + else + sTblName.Resize( sTblName.Len() - 3 ); + + if( sTblAlias.Len() == 0 ) sAlias = sTblName; - sAlias.SwapChars( '\\', '/' ); - xbUInt32 iPos = sAlias.GetLastPos( '/' ); - if( iPos > 0 ) /* get rid of the directory part of the name */ - sAlias.Ltrunc( iPos ); - } else { + else sAlias = sTblAlias; - } + + //std::cout << "fq=[" << sFqTemp.Str() << "] tblname = [" << sTblName.Str() << "] alias = [" << sAlias.Str() << "]\n"; if((i = (xbTblList *) calloc(1, sizeof(xbTblList))) == NULL){ iErrorStop = 110; iRc = XB_NO_MEMORY; throw iRc; } - i->psTblName = new xbString( sTblName ); - i->psTblAlias = new xbString( sAlias ); - i->pDbf = d; - i->pNext = NULL; + i->psFqTblName = new xbString( sFqTemp ); + i->psTblName = new xbString( sTblName ); + i->psTblAlias = new xbString( sAlias ); + i->pDbf = d; + i->pNext = NULL; // insert new table into the list of open tables, sorted by table name s = NULL; @@ -97,7 +123,7 @@ xbInt16 xbTblMgr::AddTblToTblList( xbDbf *d, const xbString & sTblName, const xb if( t && (strcmp( t->psTblAlias->Str(), sAlias.Str()) == 0 )){ iErrorStop = 120; - delete i->psTblName; + delete i->psFqTblName; delete i->psTblAlias; free( i ); iRc = XB_DUP_TABLE_OR_ALIAS; @@ -131,7 +157,7 @@ xbInt16 xbTblMgr::DisplayTableList() const { else{ while( l ){ iTblCnt++; - std::cout << iTblCnt << " Table=[" << l->psTblName->Str() << "] Alias=[" << l->psTblAlias->Str() << "]" << std::endl; + std::cout << iTblCnt << " FqFileName=[" << l->psFqTblName->Str() << "] TableName=[" << l->psTblName->Str() << "] Alias=[" << l->psTblAlias->Str() << "]" << std::endl; l = l->pNext; } } @@ -149,6 +175,7 @@ xbInt16 xbTblMgr::DisplayTableList() const { xbDbf *xbTblMgr::GetDbfPtr(const xbString& sTblAlias) const { + xbTblList *t; t = TblList; xbString s; @@ -159,14 +186,26 @@ xbDbf *xbTblMgr::GetDbfPtr(const xbString& sTblAlias) const { s.Set( sTblAlias ); while( t ){ - if( s == t->psTblAlias->Str()) + if( s == t->psTblAlias->Str()){ + return t->pDbf; + } + t = t->pNext; + } + + t = TblList; + while( t ){ + std::cout << "s = [" << s.Str() << "] tbl name = [" << t->psTblName->Str() << "]\n"; + if( s == t->psTblName->Str()){ + std::cout << "found\n"; return t->pDbf; + } t = t->pNext; } + t = TblList; while( t ){ - if( sTblAlias == t->psTblName->Str()) + if( sTblAlias == t->psFqTblName->Str()) return t->pDbf; t = t->pNext; } @@ -227,6 +266,7 @@ xbInt16 xbTblMgr::RemoveTblFromTblList( const xbString & sTblAlias ) { else TblList = i->pNext; + delete i->psFqTblName; delete i->psTblName; delete i->psTblAlias; free( i ); @@ -254,6 +294,7 @@ xbInt16 xbTblMgr::RemoveTblFromTblList( xbDbf *pTbl ) { else TblList = i->pNext; + delete i->psFqTblName; delete i->psTblName; delete i->psTblAlias; free( i ); diff --git a/src/core/xbxbase.cpp b/src/core/xbxbase.cpp index 7443b26..20b7fcc 100755 --- a/src/core/xbxbase.cpp +++ b/src/core/xbxbase.cpp @@ -24,6 +24,10 @@ xbXBase::xbXBase() { #ifdef XB_LOGGING_SUPPORT xLog = new xbLog(); #endif + + xbFile f( this ); + f.SetHomeFolders(); + } /*************************************************************************/ //! @brief Class Deconstructor. @@ -69,6 +73,53 @@ xbInt16 xbXBase::CloseAllTables(){ } return iRc; } + + + +/*************************************************************************/ +//! @brief Parse commmand line options for a given parm request +/*! + \param lArgc Value passed from main( argc, argv[] ) + \param sArgv Valued passed from main + \param sOptRqst Option to search for in the arguments list + \param sParmOut String token immediately to the right of the the option request, if found + \returns 0 - paramater request not found
1 - Parameter found +*/ + +xbInt16 xbXBase::GetCmdLineOpt( xbInt32 lArgc, char **sArgv, const char *sOptRqst, xbString &sParmOut ){ + xbString sOpt( sOptRqst ); + return GetCmdLineOpt( lArgc, sArgv, sOpt, sParmOut ); +} + +/*************************************************************************/ +//! @brief Parse commmand line options for a given parm request +/*! + \param lArgc Value passed from main( argc, argv[] ) + \param sArgv Valued passed from main + \param sOptRqst Option to search for in the arguments list + \param sParmOut String token immediately to the right of the the option request, if found + \returns 0 - paramater request not found
1 - Parameter found +*/ + +xbInt16 xbXBase::GetCmdLineOpt( xbInt32 lArgc, char **sArgv, xbString &sOptRqst, xbString &sParmOut ){ + + xbInt16 iFound = 0; + sParmOut = ""; + if( lArgc < 2 ) // first string is the program name + return iFound; + + xbInt32 i = 1; + while( iFound == 0 && i < lArgc ){ + if( sOptRqst == sArgv[i] ){ + iFound = 1; + if( i < (lArgc-1)) + sParmOut = sArgv[i+1]; + } + i++; + } + return iFound; +} + /*************************************************************************/ #ifdef XB_LOGGING_SUPPORT //! @brief Get fully qualified log file name. @@ -109,6 +160,7 @@ xbBool xbXBase::GetLogStatus() const { \return void */ void xbXBase::SetLogFileName( const xbString & sLogFileName ){ + xLog->SetFileName( sLogFileName ); } @@ -550,7 +602,7 @@ xbDbf* xbXBase::Open( const xbString &sTableName, xbInt16 &iRc ){ \param iOpenMode - XB_READ_WRITE or XB_READ \param iShareMode - XB_SINGLE_USER or XB_MULTI_USER \param iRequestVersion 0 - Highest available - 4 - Version four dbf + 4 - Version four dbf 3 - Version three dbf \param iRc - Return code from open request \returns param dbf - Output pointer to dbf file opened or null if error diff --git a/src/examples/xb_ex_expression.cpp b/src/examples/xb_ex_expression.cpp index dc6d7e6..840e9c6 100755 --- a/src/examples/xb_ex_expression.cpp +++ b/src/examples/xb_ex_expression.cpp @@ -65,7 +65,9 @@ void PrintResult( xbString *sExpression, xbExp *exp ){ } //********************************************************************************************************************************* -int main( int ac, char ** av ){ +//int main( int ac, char ** av ){ + +int main(){ xbInt16 iRc = 0; xbInt16 iErrorStop = 0; diff --git a/src/examples/xb_ex_ssv.cpp b/src/examples/xb_ex_ssv.cpp new file mode 100755 index 0000000..a78345f --- /dev/null +++ b/src/examples/xb_ex_ssv.cpp @@ -0,0 +1,134 @@ +/* xb_ex_ssv.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2021,2022,2023 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +This program demonstrates using functionality of the xbSsv class (Shared system values) + +*/ + +#include "xbase.h" + +using namespace xb; + +int main( int ac, char ** av ){ + + xbXBase x; // set up xbase for business + xbString sMsg; // a message string + + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + std::cout << sMsg.Str() << std::endl; + + + // example code to set up log file usage + #ifdef XB_LOGGING_SUPPORT + char cSeperator; // is this a unix (/) or windows (\) file system + xbString sLog; // general string for log file activities + sLog = x.GetLogFqFileName().Str(); // get the system default log file name + std::cout << "System default logfile is [" << sLog.Str() << "]" << std::endl; + + cSeperator = sLog.GetPathSeparator(); // get the seperator from + std::cout << "Path seperator = [" << cSeperator << "]" << std::endl; + + sLog.Sprintf( "..%c", cSeperator ); + x.SetLogDirectory( sLog ); + std::cout << "sLog = [" << sLog.Str() << "]\n"; + + sLog = x.GetLogFqFileName().Str(); // get the system default log file name + std::cout << "New logfile is [" << sLog.Str() << "]" << std::endl; + + // turn on logging after file name set + x.EnableMsgLogging(); + #endif // XB_LOGGING_SUPPORT + + // const char *GetErrorMessage( xbInt16 ErrorCode ) const; + // void DisplayError( xbInt16 ErrorCode ) const; + std::cout << "DisplayError( -100 ) - "; + x.DisplayError( -100 ); + // << "]" << std::endl; + + // void SetDefaultDateFormat( const xbString &sDefaultDateFormat ); + // xbString& GetDefaultDateFormat() const; + std::cout << "GetDefaultDateFormat() - " << x.GetDefaultDateFormat().Str() << std::endl; + + + // void SetDataDirectory ( const xbString &sDataDirectory ); + // xbString& GetDataDirectory() const; + std::cout << "GetDataDirectory() - " << x.GetDataDirectory().Str() << std::endl; + + // xbInt16 GetEndianType() const; + if( x.GetEndianType() == 'L' ) + std::cout << "Little Endian Architecture." << std::endl; + else + std::cout << "Bid Endian Architecture." << std::endl; + + //xbBool GetDefaultAutoCommit() const; + //void SetDefaultAutoCommit( xbBool bDefaultAutoCommit ); + if( x.GetDefaultAutoCommit()) + std::cout << "AutoCommit is on." << std::endl; + else + std::cout << "AutoCommit is off." << std::endl; + + //xbBool GetMultiUser () const; + //void SetMultiUser ( xbBool bMultiUser ); + if( x.GetMultiUser()) + std::cout << "Multi user (locking) is enabled." << std::endl; + else + std::cout << "Multi user (locking) not enabled." << std::endl; + + #if defined (XB_NDX_SUPPORT) || defined (XB_MDX_SUPPORT) + // xbInt16 GetUniqueKeyOpt () const; + // xbInt16 SetUniqueKeyOpt ( xbInt16 iUniqueKeyOpt ); + // XB_HALT_ON_DUPKEY + // XB_EMULATE_DBASE + if( x.GetUniqueKeyOpt() == XB_HALT_ON_DUPKEY ) + std::cout << "UniqueKey option - XB_HALT_ON_DUPKEY" << std::endl; + else if( x.GetUniqueKeyOpt() == XB_EMULATE_DBASE ) + std::cout << "UniqueKey option - XB_EMULATE_DBASE" << std::endl; + #endif // (XB_NDX_SUPPORT) || defined (XB_MDX_SUPPORT) + + #ifdef XB_LOCKING_SUPPORT + //xbInt16 GetDefaultLockRetries () const; + //void SetDefaultLockRetries ( xbInt16 iRetryCount ); + //xbInt32 GetDefaultLockWait () const; + //void SetDefaultLockWait ( xbInt32 lRetryWait ); + //xbInt16 GetDefaultLockFlavor () const; + //void SetDefaultLockFlavor ( xbInt16 iLockFlavor ); + //xbBool GetDefaultAutoLock () const; + //void SetDefaultAutoLock ( xbBool bAutoLock ); + //void EnableDefaultAutoLock (); + //void DisableDefaultAutoLock (); + + std::cout << "GetDefaultLockRetries() - " << x.GetDefaultLockRetries() << std::endl; + std::cout << "GetDefaultLockWait() - " << x.GetDefaultLockWait() << std::endl; + std::cout << "GetDefaultAutoLock() - " << x.GetDefaultAutoLock() << std::endl; + #endif // XB_LOCKING_SUPPORT + + #ifdef XB_MDX_SUPPORT + // xbInt16 GetCreateMdxBlockSize() const; + // xbInt16 SetCreateMdxBlockSize( xbInt16 ulBlockSize ); + std::cout << "GetCreateMdxBlockSize() - " << x.GetCreateMdxBlockSize() << std::endl; + #endif // XB_MDX_SUPPORT + + #ifdef XB_BLOCKREAD_SUPPORT + // xbUInt32 GetDefaultBlockReadSize() const; + // void SetDefaultBlockReadSize( xbUInt32 ulDfltBlockReadSize ); + std::cout << "GetDefaultBlockReadSize() - " << x.GetDefaultBlockReadSize() << std::endl; + #endif // XB_BLOCKREAD_SUPPORT + + //xbBool BitSet ( unsigned char c, xbInt16 iBitNo ) const; + //void BitDump ( unsigned char c ) const; + //void BitDump ( char c ) const; + std::cout << "BitDump( 'A' ) - "; + x.BitDump( 'A' ); + + return 0; +} diff --git a/src/examples/xb_ex_v4_upd_dbf.cpp b/src/examples/xb_ex_v4_upd_dbf.cpp index 96b6bdf..75d0641 100755 --- a/src/examples/xb_ex_v4_upd_dbf.cpp +++ b/src/examples/xb_ex_v4_upd_dbf.cpp @@ -258,15 +258,15 @@ int main() throw iRc; } - // example code to loop through the table - for( xbUInt32 ulTuple = 1; ulTuple <= MyTable->GetRecordCount(); ulTuple++ ){ - if(( iRc = MyTable->GetRecord( ulTuple ) != XB_NO_ERROR )){ + for( xbUInt32 ul = 1; ul <= MyTable->GetRecordCount(); ul++ ){ + if(( iRc = MyTable->GetRecord( ul )) != XB_NO_ERROR ){ iErrorStop = 430; throw iRc; } // do something with the record here std::cout << "Tuple = " << MyTable->GetCurRecNo() << std::endl; + } /* Close database and associated indexes */ diff --git a/src/include/xbase.h b/src/include/xbase.h index 480d716..4ab8892 100755 --- a/src/include/xbase.h +++ b/src/include/xbase.h @@ -3,7 +3,7 @@ Xbase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license @@ -41,6 +41,10 @@ Email Contact: #include #endif +#ifdef HAVE_PWD_H +#include +#endif + #ifdef HAVE_STDARG_H #include #endif @@ -89,6 +93,7 @@ Email Contact: #include #include +#include #include /* dbf base class */ #include /* index base class */ #include diff --git a/src/include/xbblkread.h b/src/include/xbblkread.h new file mode 100755 index 0000000..353c618 --- /dev/null +++ b/src/include/xbblkread.h @@ -0,0 +1,70 @@ +/* xbblkread.h + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +#ifndef __XB_BLKREAD_H__ +#define __XB_BLKREAD_H__ + +namespace xb{ +#ifdef XB_BLOCKREAD_SUPPORT + + + +//! @brief xbBlockRead class. +/*! +The xbBlockRead class can be used to read blocks of records at one time +rather than one record at a time for perfomance improvements when reading a DBF file sequentially.
+ +*/ + + +class XBDLLEXPORT xbBlockRead { + + public: + xbBlockRead( xbDbf * d ); + ~xbBlockRead(); + + #ifdef XB_DEBUG_SUPPORT + void DumpReadBlockInternals(); + #endif + + xbInt16 Init( xbUInt32 ulBlkSize = 0 ); + + xbUInt32 GetBlockFirstRecNo() const; + xbUInt32 GetBlockRecCnt() const; + xbUInt32 GetBlockSize() const; + + xbInt16 GetRecord( xbUInt32 ulRecNo ); // retrieve a data record from a block to RecBuf + xbInt16 SetBlockSize( xbUInt32 ulBlkSize ); + + + private: + + xbInt16 GetBlockForRecNo( xbUInt32 ulRecNo ); // retrieve block from disk for a given record number + + char *pBlock; // block pointer + xbUInt32 ulBlkSize; // block size in bytes + xbUInt32 ulFirstBlkRec; // first recod number in the block + xbUInt32 ulRecCnt; // number of records in block + xbUInt32 ulMaxRecs; // max number of records block can handle + xbBool bEof; // EOF flag + xbDbf *dbf; // reference to associated dbf file +// xbXBase *xbase; // reference to main xbXBase structure + time_t tFmTime; // file modify time at time of block read + +}; + +#endif // XB_BLOCKREAD +} /* namespace */ +#endif /* __XB_BLOCKREAD_H__ */ diff --git a/src/include/xbconfig.h.in b/src/include/xbconfig.h.in index 969b761..f0d475a 100755 --- a/src/include/xbconfig.h.in +++ b/src/include/xbconfig.h.in @@ -51,6 +51,7 @@ #cmakedefine HAVE_DOS_H #cmakedefine HAVE_FCNTL_H #cmakedefine HAVE_INTTYPES_H +#cmakedefine HAVE_PWD_H #cmakedefine HAVE_STDARG_H #cmakedefine HAVE_STDARGS_H #cmakedefine HAVE_STRING_H @@ -100,6 +101,7 @@ #cmakedefine XB_SQL_SUPPORT #cmakedefine XB_INF_SUPPORT #cmakedefine XB_FILTER_SUPPORT +#cmakedefine XB_BLOCKREAD_SUPPORT #cmakedefine XB_UTILS_SUPPORT #cmakedefine XB_EXAMPLES_SUPPORT diff --git a/src/include/xbdate.h b/src/include/xbdate.h index 5406cbb..8dff463 100755 --- a/src/include/xbdate.h +++ b/src/include/xbdate.h @@ -92,7 +92,6 @@ class XBDLLEXPORT xbDate : public xbSsv { xbBool DateIsValid ( const xbString &sDate8 ) const; xbInt16 DayOf( xbInt16 iFormat ) const; xbInt16 CTOD( const xbString &sCtodInDate ); -// xbInt16 FormatDate( const char *sFmtIn, xbString &sFmtOut ); xbInt16 FormatDate( const xbString &sFmtIn, xbString &sFmtOut ); const char *Str() const; xbBool IsLeapYear( xbInt16 iYear ) const; diff --git a/src/include/xbdbf.h b/src/include/xbdbf.h index c0842cb..16799f2 100755 --- a/src/include/xbdbf.h +++ b/src/include/xbdbf.h @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -168,11 +168,14 @@ class XBDLLEXPORT xbDbf : public xbFile { virtual xbInt16 DumpRecord ( xbUInt32 ulRecNo, xbInt16 iOutputDest = 0, xbInt16 iOutputFmt = 0 ); virtual xbInt16 GetAutoCommit () const; virtual xbInt16 GetAutoCommit ( xbInt16 iOption ) const; + virtual xbBool GetBof (); virtual xbUInt32 GetCurRecNo () const; virtual xbInt16 GetDbfStatus () const; + virtual xbBool GetEof (); virtual xbInt32 GetFieldCnt () const; virtual xbInt16 GetFirstRecord (); virtual xbInt16 GetFirstRecord ( xbInt16 iOption ); + virtual xbUInt16 GetHeaderLen () const; virtual xbInt16 GetLastRecord (); virtual xbInt16 GetLastRecord ( xbInt16 iOption ); @@ -360,7 +363,11 @@ class XBDLLEXPORT xbDbf : public xbFile { //virtual xbInt16 SetCreateMdxBlockSize( xbInt16 ulBlockSize ); //#endif - + #ifdef XB_BLOCKREAD_SUPPORT + xbInt16 DisableBlockReadProcessing(); + xbInt16 EnableBlockReadProcessing(); + xbBool GetBlockReadStatus() const; + #endif // XB_BLOCKREAD_SUPPORT protected: #ifdef XB_INDEX_SUPPORT @@ -378,6 +385,10 @@ class XBDLLEXPORT xbDbf : public xbFile { virtual xbInt16 GetInfFileName( xbString &sNdxIdxFileName ); #endif // XB_INF_SUPPORT + #ifdef XB_BLOCKREAD_SUPPORT + friend class xbBlockRead; + #endif // XB_BLOCKREAD_SUPPORT + #ifdef XB_LOCKING_SUPPORT void SetHeaderLocked ( xbBool bTableLocked ); @@ -426,7 +437,7 @@ class XBDLLEXPORT xbDbf : public xbFile { xbSchemaRec *SchemaPtr; // Pointer to field data char *RecBuf; // Pointer to record buffer - char *RecBuf2; // Pointer to original rec buf + char *RecBuf2; // Pointer to original rec buf allocation /* Next several variables are database header fields, up through dbase V */ @@ -448,28 +459,32 @@ class XBDLLEXPORT xbDbf : public xbFile { void ResetNoOfRecords(); -#ifdef XB_LOCKING_SUPPORT + #ifdef XB_LOCKING_SUPPORT xbInt16 iAutoLock; // 0 - autolock off, 1 - autolock on xbInt16 iLockFlavor; xbBool bTableLocked; // is the table locked xbBool bHeaderLocked; // is the header locked xbUInt32 ulAppendLocked; // record number of the new record for the append lock operation xbLinkListOrd lloRecLocks; // ordered link list of locked records -#endif - + #endif -#ifdef XB_INDEX_SUPPORT + #ifdef XB_INDEX_SUPPORT xbIxList *ixList; // pointer to a list of indices associated with the table xbIx *pCurIx; // Pointer to current index class void *vpCurIxTag; // Pointer to current tag xbString sCurIxType; // Current index type xbLinkList llTags; // linked list of open tags + #endif // XB_INDEX_SUPPORT -#endif // XB_INDEX_SUPPORT + #ifdef XB_INF_SUPPORT + xbLinkList llInfData; // linked list of strings containing ndx file entries + #endif // XB_INF_SUPPORT + + #ifdef XB_BLOCKREAD_SUPPORT + xbBlockRead *pRb; + xbBool bBlockReadEnabled; // if true, then block read mode is on + #endif -#ifdef XB_INF_SUPPORT - xbLinkList llInfData; // linked list of strings containing ndx file entries -#endif // XB_INF_SUPPORT }; diff --git a/src/include/xbfile.h b/src/include/xbfile.h index ffbda06..af04e98 100755 --- a/src/include/xbfile.h +++ b/src/include/xbfile.h @@ -60,6 +60,9 @@ class XBDLLEXPORT xbFile : public xbSsv { xbFile( xbXBase * x ); ~xbFile(); + + xbInt16 SetHomeFolders(); + xbInt16 CreateUniqueFileName( const xbString &sDirIn, const xbString &sExtIn, xbString &sFqnOut ); xbInt16 CreateUniqueFileName( const xbString &sDirIn, const xbString &sExtIn, xbString &sFqnOut, xbInt16 iOption ); @@ -158,6 +161,7 @@ class XBDLLEXPORT xbFile : public xbSsv { #ifdef XB_DEBUG_SUPPORT xbInt16 DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlockSize ); + xbInt16 DumpMemToDisk ( char *p, size_t lBlockSize ); #endif diff --git a/src/include/xbfilter.h b/src/include/xbfilter.h index 8722256..635d117 100755 --- a/src/include/xbfilter.h +++ b/src/include/xbfilter.h @@ -37,9 +37,10 @@ namespace xb{ class XBDLLEXPORT xbFilter { public: - xbFilter( xbXBase *xbase, xbDbf *dbf ); + xbFilter( xbDbf *dbf ); ~xbFilter(); xbInt16 Set( xbString &sFilterExpression ); + xbInt16 Set( const char *sFilterExpression ); xbInt16 GetFirstRecord( xbInt16 iOpt = 1 ); xbInt16 GetNextRecord ( xbInt16 iOpt = 1 ); xbInt16 GetPrevRecord ( xbInt16 iOpt = 1 ); @@ -50,7 +51,6 @@ class XBDLLEXPORT xbFilter { xbInt32 GetQryCnt() const; #ifdef XB_INDEX_SUPPORT -// void Set( xbIx *pIx, void *vpTag ); xbInt16 GetFirstRecordIx( xbInt16 iOpt = 1 ); xbInt16 GetNextRecordIx ( xbInt16 iOpt = 1 ); xbInt16 GetPrevRecordIx ( xbInt16 iOpt = 1 ); @@ -59,7 +59,7 @@ class XBDLLEXPORT xbFilter { private: - xbXBase *xbase; +// xbXBase *xbase; xbDbf *dbf; xbExp *exp; diff --git a/src/include/xbretcod.h b/src/include/xbretcod.h index 6b73527..ec1f91b 100755 --- a/src/include/xbretcod.h +++ b/src/include/xbretcod.h @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -27,6 +27,7 @@ namespace xb{ #define XB_DUP_TABLE_OR_ALIAS -110 // table manager #define XB_INVALID_NODELINK -120 // linklist #define XB_KEY_NOT_UNIQUE -121 // linklist + #define XB_MEMCPY_ERROR -122 // memcpy failure #define XB_FILE_EXISTS -200 // file #define XB_ALREADY_OPEN -201 // file @@ -51,6 +52,8 @@ namespace xb{ #define XB_INVALID_TABLE_NAME -220 // file #define XB_EMPTY -221 // file #define XB_LIMIT_REACHED -222 // file + #define XB_BLOCKREAD_NOT_ENABLED -223 // file + #define XB_DIRECTORY_ERROR -224 // file #define XB_INVALID_FIELD_TYPE -300 // field #define XB_INVALID_FIELD_NO -301 // field diff --git a/src/include/xbsql.h b/src/include/xbsql.h index 653096c..07ffb70 100755 --- a/src/include/xbsql.h +++ b/src/include/xbsql.h @@ -39,7 +39,83 @@ struct XBDLLEXPORT xbSqlFld{ xbSqlFld * Next; // Next field in list }; +class xbStmt; + + +struct XBDLLEXPORT xbTblJoin { // structure for defining joined tables in the query + + xbString sTableName; + xbString sAlias; + xbString sJoinExp; // table join expression + xbDbf *pDbf; // pointer the the dbf structure for this table + xbTag *pTag; // pointer to relevant tag for this table, null for record order + xbExp *pLinkExp; // pointer to parsed linkage expression + char cJoinType; // M - Master + // L - Left or Full Left + // R - Right or Full Right + // I - Inner + // O - Outer or Full Outer Outer + + xbTblJoin *pMaster; // pointer to master table, null if this is the primary master + xbLinkList llSubList; // linked list of subordinate tables +// xbStmt *pSubQuery; // pointer to sub query + xbTblJoin *next; // next tbl +}; + + +class XBDLLEXPORT xbStmt : public xbSsv{ + + public: + xbStmt( xbXBase *x ); + ~xbStmt(); + + #ifdef XB_DEBUG_SUPPORT + xbInt16 DumpStmtInternals(); + xbInt16 Test(); + #endif + + xbInt16 ExecuteQuery( const xbString &sCmdLine ); + +// xbInt16 FetchFirst(); +// xbInt16 FetchNext(); +// xbInt16 FetchPrev(); +// xbInt16 FetchLast(); +// xbString &GetField( const xbString sFldName ); + protected: + + private: + + xbInt16 AddQryTbl( const xbString &sTable, const xbString &sAlias, const xbString &sExpression, const char cJoinType ); + xbInt16 CvtSqlExp2DbaseExp( const xbString &sExpIn, xbString &sExpOut ); + xbInt16 GetNextFromSeg( const xbString &sLineIn, xbString &sFromSegOut ); + xbUInt32 GetNextToken( const xbString &sCmdLineIn, xbString &sTokenOut, xbUInt32 ulStartPos ); + xbInt16 GetParenCnt( const xbString &sToken ); + xbInt16 ParseFromStmt( const xbString &sFromLine ); + xbInt16 ParseStmt( const xbString &sCmdLine ); + xbInt16 ProcessFromSeg( const xbString &sFromStmtSeg ); + xbInt16 UpdateJoinList( char cType, const xbString &sTableName, const xbString &sAlias, const xbString &sExp, xbDbf *d, xbExp *e ); //, xbTag *t); + + xbXBase *xbase; // pointer to xbase structure + + + xbTblJoin * pTblList; + xbSqlFld *fl; // field list in sql select statement + xbString sStmt; // complete query statment + xbString sFields; // list of fields + xbString sFrom; // from statment + xbString sWhere; // where clause + xbString sOrderBy; // sort order + xbString sGroupBy; // group by + xbString sHaving; // having + xbUInt32 ulFromPos; + xbUInt32 ulWherePos; + xbUInt32 ulOrderByPos; + xbUInt32 ulGroupByPos; + xbUInt32 ulHavingPos; + + +}; class XBDLLEXPORT xbSql : public xbSsv { @@ -68,7 +144,7 @@ class XBDLLEXPORT xbSql : public xbSsv { // xbInt16 SqlCreateView( const xbString &sCmdLine ); // xbInt16 SqlDropView( const xbString &sCmdLine ); // xbInt16 SqlUpdate( const xbString &sCmdLine ); - xbInt16 SqlSelect( const xbString &sCmdLine ); +// xbInt16 SqlSelect( const xbString &sCmdLine ); void SqlHelp() const; xbInt16 SqlInsert( const xbString &sCmLine ); diff --git a/src/include/xbssv.h b/src/include/xbssv.h index b9345fd..d050bcb 100755 --- a/src/include/xbssv.h +++ b/src/include/xbssv.h @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -77,9 +77,11 @@ class XBDLLEXPORT xbSsv{ xbBool GetDefaultAutoCommit () const; void SetDefaultAutoCommit ( xbBool bDefaultAutoCommit ); - xbString& GetDefaultLogDirectory () const; - xbString& GetDefaultLogFileName () const; - void SetDefaultLogDirectory ( const xbString &sDefaultLogDirectory ); + void GetHomeDir ( xbString &sHomeDirOut ); + + xbString& GetLogDirectory () const; + xbString& GetLogFileName () const; + void SetLogDirectory ( const xbString &sLogDirectory ); xbBool GetMultiUser () const; void SetMultiUser ( xbBool bMultiUser ); @@ -87,7 +89,7 @@ class XBDLLEXPORT xbSsv{ #if defined (XB_NDX_SUPPORT) || defined (XB_MDX_SUPPORT) xbInt16 GetUniqueKeyOpt () const; xbInt16 SetUniqueKeyOpt ( xbInt16 iUniqueKeyOpt ); - #endif + #endif // (XB_NDX_SUPPORT) || defined (XB_MDX_SUPPORT) #ifdef XB_LOCKING_SUPPORT xbInt16 GetDefaultLockRetries () const; @@ -100,12 +102,18 @@ class XBDLLEXPORT xbSsv{ void SetDefaultAutoLock ( xbBool bAutoLock ); void EnableDefaultAutoLock (); void DisableDefaultAutoLock (); - #endif + #endif // XB_LOCKING_SUPPORT #ifdef XB_MDX_SUPPORT xbInt16 GetCreateMdxBlockSize() const; xbInt16 SetCreateMdxBlockSize( xbInt16 ulBlockSize ); - #endif + #endif // XB_MDX_SUPPORT + + #ifdef XB_BLOCKREAD_SUPPORT + xbUInt32 GetDefaultBlockReadSize() const; + void SetDefaultBlockReadSize( xbUInt32 ulDfltBlockReadSize ); + #endif // XB_BLOCKREAD_SUPPORT + protected: @@ -121,8 +129,8 @@ class XBDLLEXPORT xbSsv{ static xbString sDataDirectory; //Data file directory #ifdef XB_LOGGING_SUPPORT - static xbString sDefaultLogDirectory; //Default location to store log files - static xbString sDefaultLogFileName; //Default LogFileName + static xbString sLogDirectory; //Default location to store log files + static xbString sLogFileName; //Default LogFileName #endif static xbInt16 iDefaultFileVersion; // 3 = DBase 3 @@ -150,7 +158,6 @@ class XBDLLEXPORT xbSsv{ #endif - #if defined (XB_NDX_SUPPORT) || defined (XB_MDX_SUPPORT) static xbInt16 iUniqueKeyOpt; @@ -167,6 +174,10 @@ class XBDLLEXPORT xbSsv{ #endif // XB_MDX_SUPPORT +#ifdef XB_BLOCKREAD_SUPPORT + static xbUInt32 ulDefaultBlockReadSize; +#endif // XB_BLOCKREAD_SUPPORT + }; diff --git a/src/include/xbstring.h b/src/include/xbstring.h index f5a22da..3e70acc 100755 --- a/src/include/xbstring.h +++ b/src/include/xbstring.h @@ -131,6 +131,8 @@ class XBDLLEXPORT xbString { xbString &Mid(xbUInt32 ulPos, xbUInt32 lLen ); xbString &PadLeft( char c, xbUInt32 ulLen ); xbString &PadRight( char c, xbUInt32 ulLen ); + + xbUInt32 Pos(char c, xbUInt32 ulStartPos ) const; xbUInt32 Pos(char c) const; xbUInt32 Pos(const char *s) const; xbString &PutAt(xbUInt32 ulPos, char c); diff --git a/src/include/xbtblmgr.h b/src/include/xbtblmgr.h index 150026b..2c31e45 100755 --- a/src/include/xbtblmgr.h +++ b/src/include/xbtblmgr.h @@ -30,8 +30,9 @@ class XBDLLEXPORT xbDbf; /* this structure is a linked list of open tables */ struct XBDLLEXPORT xbTblList{ xbTblList *pNext; - xbString *psTblName; /* Name of table - same table can be opened multiple times, but must have unique alias */ - xbString *psTblAlias; /* TblAliasName must be unique */ + xbString *psFqTblName; // Fully qualified name of table - same table can be opened multiple times, but must have unique alias + xbString *psTblName; // Table name without path, without extension + xbString *psTblAlias; // TblAliasName must be unique, same as TblNAme if Alias not provided xbDbf *pDbf; }; @@ -39,8 +40,8 @@ class XBDLLEXPORT xbTblMgr : public xbSsv { public: xbTblMgr(); ~xbTblMgr(); - xbInt16 AddTblToTblList ( xbDbf *d, const xbString &sTblName ); - xbInt16 AddTblToTblList ( xbDbf *d, const xbString &sTblName, const xbString &sTblAlias ); + xbInt16 AddTblToTblList ( xbDbf *d, const xbString &sFqTblName ); + xbInt16 AddTblToTblList ( xbDbf *d, const xbString &sFqTblName, const xbString &sTblAlias ); xbInt16 DisplayTableList () const; xbDbf * GetDbfPtr ( const xbString &sTblAlias ) const; xbDbf * GetDbfPtr ( xbInt16 sItemNo ) const; diff --git a/src/include/xbuda.h b/src/include/xbuda.h index 84eccee..e5c0e91 100755 --- a/src/include/xbuda.h +++ b/src/include/xbuda.h @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -34,7 +34,7 @@ class XBDLLEXPORT xbUda { public: xbUda(); ~xbUda(); - + xbInt16 AddTokenForKey( const xbString &sKey, const xbString &sToken ); void Clear(); xbInt16 DelTokenForKey( const xbString &sKey ); @@ -42,7 +42,7 @@ class XBDLLEXPORT xbUda { xbInt16 GetTokenForKey( const xbString &sKey, xbString &sData ); xbInt16 UpdTokenForKey( const xbString &sKey, const xbString &sToken ); void DumpUda() const; - + private: xbLinkListOrd llOrd; diff --git a/src/include/xbxbase.h b/src/include/xbxbase.h index 204e744..fe1f323 100755 --- a/src/include/xbxbase.h +++ b/src/include/xbxbase.h @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -148,6 +148,9 @@ class XBDLLEXPORT xbXBase : public xbTblMgr{ void xbSleep ( xbInt32 lMillisecs ); + xbInt16 GetCmdLineOpt ( xbInt32 lArgc, char **argv, const char *sOptRqst, xbString &sParmOut ); + xbInt16 GetCmdLineOpt ( xbInt32 lArgc, char **argv, xbString &sOptRqst, xbString &sParmOut ); + /* xbase functions */ #ifdef XB_FUNCTION_SUPPORT @@ -207,6 +210,11 @@ class XBDLLEXPORT xbXBase : public xbTblMgr{ friend class xbBcd; friend class xbExp; + #ifdef XB_BLOCKREAD_SUPPORT + friend class xbBlockRead; + #endif // XB_BLOCKREAD_SUPPORT + + xbInt16 GetFunctionInfo( const xbString &sExpLine, char &cReturnType, xbInt16 &iReturnLenCalc, xbInt32 &lReturnLenVal ) const; static xbInt16 xbMemcmp( const unsigned char *s1, const unsigned char *s2, size_t n ); diff --git a/src/sql/xbalttbl.cpp b/src/sql/xbalttbl.cpp index 576eab7..8a36b46 100755 --- a/src/sql/xbalttbl.cpp +++ b/src/sql/xbalttbl.cpp @@ -79,17 +79,12 @@ xbInt16 xbSql::SqlAlterTable( const xbString &sCmdLine ){ sTrgTbl.ExtractElement( sCmd, ' ', 4, 0 ); sTrgTbl.Trim(); - std::cout << "source table name = " << sSrcTbl.Str() << "\n"; +// std::cout << "source table name = " << sSrcTbl.Str() << "\n"; // std::cout << "target table name = " << sTrgTbl.Str() << "\n"; // if not open, attempt to open it dbf = xbase->GetDbfPtr( sSrcTbl ); - if( dbf ) - std::cout << "dbf valued\n"; - else - std::cout << "dbf not valued\n"; - if( !dbf ){ if(( iRc = xbase->OpenHighestVersion( sSrcTbl, "", &dbf )) != XB_NO_ERROR ){ iErrorStop = 120; diff --git a/src/sql/xbcrix.cpp b/src/sql/xbcrix.cpp index 8dc6f62..6a391f7 100755 --- a/src/sql/xbcrix.cpp +++ b/src/sql/xbcrix.cpp @@ -147,13 +147,13 @@ xbInt16 xbSql::SqlCreateIndex( const xbString &sCmdLine ){ } } if( dbf == NULL ){ - iErrorStop = 50; + iErrorStop = 130; iRc = XB_FILE_NOT_FOUND; throw iRc; } sCmd.Ltrunc( ulPos ); - std::cout << "cp1 ulPos = " << ulPos << " sCmd = [" << sCmd << "]\n"; + // std::cout << "cp1 ulPos = " << ulPos << " sCmd = [" << sCmd << "]\n"; //ulPos = sCmd.GetLastPos( ')' ); xbString sKeyExpression; @@ -180,7 +180,7 @@ xbInt16 xbSql::SqlCreateIndex( const xbString &sCmdLine ){ lPos++; } - std::cout << "Key Expression =[" << sKeyExpression << "]\n"; + // std::cout << "Key Expression =[" << sKeyExpression << "]\n"; sCmd.Ltrunc( lPos ); sCmd.Trim(); @@ -216,7 +216,7 @@ xbInt16 xbSql::SqlCreateIndex( const xbString &sCmdLine ){ #ifdef XB_LOCKING_SUPPORT if(( iRc = dbf->LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 130; + iErrorStop = 140; throw iRc; } #endif // XB_LOCKING_SUPPORT @@ -227,7 +227,7 @@ xbInt16 xbSql::SqlCreateIndex( const xbString &sCmdLine ){ void *vpTag; if(( iRc = dbf->CreateTag( sIxType, sIxName, sKeyExpression, sFilter, bDesc, bUnique, xbFalse, &pIx, &vpTag )) != XB_NO_ERROR ){ - iErrorStop = 140; + iErrorStop = 150; throw iRc; } // std::cout << "SqlCreateIndex() - back from tag create\n"; @@ -239,7 +239,7 @@ xbInt16 xbSql::SqlCreateIndex( const xbString &sCmdLine ){ sCmd.ToUpperCase(); if( sCmd.Pos( "ASSOCIATE" )){ if(( iRc = dbf->AssociateIndex( "NDX", sIxName, 0 )) != XB_NO_ERROR ){ - iErrorStop = 150; + iErrorStop = 160; throw iRc; } } @@ -255,14 +255,14 @@ xbInt16 xbSql::SqlCreateIndex( const xbString &sCmdLine ){ if(( iRc = pIx->Reindex( &vpTag )) != XB_NO_ERROR ){ - iErrorStop = 160; + iErrorStop = 170; throw iRc; } #ifdef XB_LOCKING_SUPPORT if(( iRc = dbf->LockTable( XB_UNLOCK )) != XB_NO_ERROR ){ - iErrorStop = 140; + iErrorStop = 180; throw iRc; } #endif // XB_LOCKING_SUPPORT diff --git a/src/sql/xbcrtbl.cpp b/src/sql/xbcrtbl.cpp index 7f6b8fa..dfb3403 100755 --- a/src/sql/xbcrtbl.cpp +++ b/src/sql/xbcrtbl.cpp @@ -29,7 +29,7 @@ xbInt16 xbSql::SqlCreateTable( const xbString &sCmdLine ){ // expected format: // CREATE TABLE tablename.dbf (Field1 CHAR(10), INTFLD1 INTEGER, ... ) - // supported fields types + // supported field types // // SQL TYPE XBASE Field Type // -------- ---------------- @@ -61,6 +61,7 @@ xbInt16 xbSql::SqlCreateTable( const xbString &sCmdLine ){ xbLinkList ll; xbSchema *schema = NULL; xbString sMsg; + xbString sWork; try{ // retrieve table name @@ -75,7 +76,7 @@ xbInt16 xbSql::SqlCreateTable( const xbString &sCmdLine ){ xbFile f( xbase ); f.SetFileName( sTableName ); if( f.FileExists() ){ - iErrorStop = 10; + iErrorStop = 100; iRc = XB_FILE_EXISTS; throw iRc; } @@ -90,8 +91,6 @@ xbInt16 xbSql::SqlCreateTable( const xbString &sCmdLine ){ s.Remove( s.Len(), 1 ); s.Trim(); - //std::cout << "s = [" << s << "]\n"; - xbBool bDone = xbFalse; xbInt16 iLoop = 0; @@ -129,7 +128,7 @@ xbInt16 xbSql::SqlCreateTable( const xbString &sCmdLine ){ else if( sDataType == "SMALLINT" || sDataType == "INTEGER" || sDataType == "DATE" || sDataType == "VARCHAR" || sDataType == "LOGICAL" ) iAttribCnt = 0; else{ - iErrorStop = 20; + iErrorStop = 110; iRc = XB_INVALID_FIELD_TYPE; throw iRc; } @@ -143,25 +142,37 @@ xbInt16 xbSql::SqlCreateTable( const xbString &sCmdLine ){ } else if( iAttribCnt > 0 ){ lPos = s.Pos( '(' ); if( lPos <= 0 ){ - iErrorStop = 30; + iErrorStop = 120; iRc = XB_INVALID_FIELD_LEN; throw iRc; } s.Ltrunc( lPos ); - if( iAttribCnt == 1 ) - lPos = s.Pos( ')' ); - else - lPos = s.Pos( ',' ); - - sAttrib1.Assign( s, 1, lPos-1 ); - sAttrib1.Trim(); - s.Ltrunc( lPos ); - if( iAttribCnt > 1 ){ - lPos = s.Pos( ')' ); - sAttrib2.Assign( s, 1, lPos-1 ); - s.Ltrunc( lPos ); + lPos = s.Pos( ')' ); + if( lPos <= 0 ){ + iErrorStop = 130; + iRc = XB_INVALID_FIELD_LEN; + throw iRc; } + sWork.Assign( s, 1, lPos - 1); + sWork.Trim(); + + if( iAttribCnt == 1 ){ + sAttrib1 = sWork; + } else { + lCmPos = sWork.Pos( ',' ); + if( lCmPos <= 0 ){ + iErrorStop = 140; + iRc = XB_INVALID_FIELD_LEN; + throw iRc; + } + sAttrib1.Assign( sWork, 1, lCmPos - 1); + sAttrib1.Trim(); + sWork.Ltrunc( lCmPos ); + sAttrib2 = sWork; + sAttrib2.Trim(); + } + s.Ltrunc( lPos ); } s.Ltrim(); @@ -229,7 +240,7 @@ xbInt16 xbSql::SqlCreateTable( const xbString &sCmdLine ){ dbf = new xbDbf3( xbase ); #endif if(( iRc = dbf->CreateTable( sTableName, "", schema, 0, XB_MULTI_USER )) != XB_NO_ERROR ){ - iErrorStop = 50; + iErrorStop = 150; throw iRc; } diff --git a/src/sql/xbcrtbl.save.cpp b/src/sql/xbcrtbl.save.cpp new file mode 100755 index 0000000..445ad56 --- /dev/null +++ b/src/sql/xbcrtbl.save.cpp @@ -0,0 +1,256 @@ +/* xbcrtbl.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2019,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +#include "xbase.h" + +#ifdef XB_SQL_SUPPORT + +namespace xb{ + + +/***********************************************************************/ +xbInt16 xbSql::SqlCreateTable( const xbString &sCmdLine ){ + + + // std::cout << "CREATE TABLE " << sCmdLine << std::endl; + + // expected format: + // CREATE TABLE tablename.dbf (Field1 CHAR(10), INTFLD1 INTEGER, ... ) + + // supported field types + // + // SQL TYPE XBASE Field Type + // -------- ---------------- + // SMALLINT NUMERIC(6,0) + // INTEGER NUMERIC(11,0) + // DECIMAL(x,y) NUMERIC(x+1,y) + // NUMERIC(x,y) NUMERIC(x,y) + // FLOAT(x,y) FLOAT(x,y) + // CHAR(n) CHARACTER(n) + // DATE DATE + // VARCHAR MEMO + // LOGICAL LOGICAL + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbString sTableName; + xbString sFieldName; + xbString sDataType; + xbString sAttrib1; + xbString sAttrib2; + xbString sLlEntry; + xbInt16 iType = 0; + xbInt16 iAttribCnt; // number of attributes for a given data type + xbString s; + xbUInt32 lPos = 0; + xbUInt32 lSpPos = 0; // space position + xbUInt32 lCmPos = 0; // comma position + xbUInt32 lLpPos = 0; // left paren position + xbLinkList ll; + xbSchema *schema = NULL; + xbString sMsg; + + try{ + // retrieve table name + s.ExtractElement( sCmdLine, '(', 1, 0 ); + sTableName.ExtractElement( s, ' ', 3, 0 ); + sTableName.Trim(); + + // std::cout << "Tablename = [" << sTableName << "]\n"; + + + // determine if it already exists + xbFile f( xbase ); + f.SetFileName( sTableName ); + if( f.FileExists() ){ + iErrorStop = 100; + iRc = XB_FILE_EXISTS; + throw iRc; + } + + // build out table structure with parms from the sql string + lPos = sCmdLine.Pos( '(' ); + s = sCmdLine; + s.Ltrunc( lPos ); + s.Trim(); + + // remove the last byte, should be a ) + s.Remove( s.Len(), 1 ); + + s.Trim(); + //std::cout << "s = [" << s << "]\n"; + + + xbBool bDone = xbFalse; + xbInt16 iLoop = 0; + while( !bDone && iLoop++ < 255 ){ + sFieldName.ExtractElement( s, ' ', 1 , 0 ); + lPos = sFieldName.Len(); + sFieldName.Trim(); + if( sFieldName.Len() > 10 ) + sFieldName.Mid( 1, 10 ); // shrink to 10 buytes if too big + + //std::cout << "field name=[" << sFieldName << "]\n"; + s.Ltrunc( lPos + 1 ); + s.Ltrim(); + //std::cout << "remainder after field name removed = [" << s << "]\n"; + + // Data type is delimited with either a space, comma or left paren + lPos = 9999999; + lSpPos = s.Pos( ' ' ); + lCmPos = s.Pos( ',' ); + lLpPos = s.Pos( '(' ); + if( lSpPos != 0 ) lPos = lSpPos; + if( lCmPos != 0 && lCmPos < lPos ) lPos = lCmPos; + if( lLpPos != 0 && lLpPos < lPos ) lPos = lLpPos; + + //sMsg.Sprintf( "SpPos=[%d] CmPos=[%d] LpPos=[%d] lPos=[%d]", lSpPos, lCmPos, lLpPos, lPos ); + //std::cout << sMsg << "\n"; + + sDataType.Assign( s, 1, lPos-1 ); + + //std::cout << "DataType=[" << sDataType << "]\n"; + if( sDataType == "CHAR" ) + iAttribCnt = 1; + else if( sDataType == "DECIMAL" || sDataType == "NUMERIC" || sDataType == "FLOAT" ) + iAttribCnt = 2; + else if( sDataType == "SMALLINT" || sDataType == "INTEGER" || sDataType == "DATE" || sDataType == "VARCHAR" || sDataType == "LOGICAL" ) + iAttribCnt = 0; + else{ + iErrorStop = 110; + iRc = XB_INVALID_FIELD_TYPE; + throw iRc; + } + + sAttrib1 = ""; + sAttrib2 = "0"; + + if( iAttribCnt == 0 ){ + s.Ltrunc( sDataType.Len()); + + } else if( iAttribCnt > 0 ){ + lPos = s.Pos( '(' ); + if( lPos <= 0 ){ + iErrorStop = 110; + iRc = XB_INVALID_FIELD_LEN; + throw iRc; + } + s.Ltrunc( lPos ); + if( iAttribCnt == 1 ) + lPos = s.Pos( ')' ); + else + lPos = s.Pos( ',' ); + + sAttrib1.Assign( s, 1, lPos-1 ); + sAttrib1.Trim(); + s.Ltrunc( lPos ); + + if( iAttribCnt > 1 ){ + lPos = s.Pos( ')' ); + sAttrib2.Assign( s, 1, lPos-1 ); + s.Ltrunc( lPos ); + } + } + + s.Ltrim(); + s.ZapLeadingChar( ',' ); + s.Ltrim(); + + if( sDataType == "CHAR" ){ + iType = XB_CHAR_FLD; + } else if( sDataType == "DECIMAL" ){ + xbInt32 lVal = atol( sAttrib1.Str()) + 1; + sAttrib1.Sprintf( "%d", lVal ); + iType = XB_NUMERIC_FLD; + } else if( sDataType == "SMALLINT" ){ + sAttrib1 = "6"; + iType = XB_NUMERIC_FLD; + } else if( sDataType == "INTEGER" ){ + sAttrib1 = "11"; + iType = XB_NUMERIC_FLD; + } else if( sDataType == "NUMERIC" ){ + iType = XB_NUMERIC_FLD; + } else if( sDataType == "FLOAT" ) { + iType = XB_FLOAT_FLD; + } else if( sDataType == "DATE" ){ + iType = XB_DATE_FLD; + sAttrib1 = "8"; + } else if( sDataType == "VARCHAR" ){ + iType = XB_MEMO_FLD; + sAttrib1 = "10"; + } else if( sDataType == "LOGICAL" ){ + iType = XB_LOGICAL_FLD; + sAttrib1 = "1"; + } + sLlEntry.Sprintf( "%s,%s,%c,%s,%s", sFieldName.Str(), sDataType.Str(), iType, sAttrib1.Str(), sAttrib2.Str()); + ll.InsertAtEnd( sLlEntry ); + + if( s.Len() == 0 ) + bDone = xbTrue; + } + + schema = (xbSchema *) calloc( ll.GetNodeCnt()+1, sizeof( xbSchema )); + xbLinkListNode * llN = ll.GetHeadNode(); + xbUInt32 ulCnt = ll.GetNodeCnt(); + + char *pTrg; + for( xbUInt32 i = 0; i < ulCnt; i++ ){ + s = llN->GetKey(); + sFieldName.ExtractElement( s, ',', 1 , 0 ); + pTrg = schema[i].cFieldName; + for( xbUInt32 j = 0; j < sFieldName.Len(); j++ ) + *pTrg++ = sFieldName[j+1]; + sDataType.ExtractElement( s, ',', 3, 0 ); + schema[i].cType = sDataType[1]; + sAttrib1.ExtractElement( s, ',', 4, 0 ); + schema[i].iFieldLen = atoi( sAttrib1.Str()); + sAttrib2.ExtractElement( s, ',', 5, 0 ); + schema[i].iNoOfDecs = atoi( sAttrib2.Str()); + llN = llN->GetNextNode(); + } + + // create the table + xbDbf * dbf = NULL; + #ifdef XB_DBF4_SUPPORT + dbf = new xbDbf4( xbase ); + #elif defined (XB_DBF3_SUPPORT) + dbf = new xbDbf3( xbase ); + #endif + if(( iRc = dbf->CreateTable( sTableName, "", schema, 0, XB_MULTI_USER )) != XB_NO_ERROR ){ + iErrorStop = 120; + throw iRc; + } + + free( schema ); + ll.Clear(); + } + catch (xbInt16 iRc ){ + xbString sMsg; + if( sFieldName.Len() > 0 ) + sMsg.Sprintf( "xbSql::SqlCreateTbl() Exception Caught. Error Stop = [%d] rc = [%d] table = [%s] field = [%s]", iErrorStop, iRc, sTableName.Str(), sFieldName.Str() ); + else + sMsg.Sprintf( "xbSql::SqlCreateTbl() Exception Caught. Error Stop = [%d] rc = [%d] table = [%s]", iErrorStop, iRc, sTableName.Str() ); + + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + if( schema ) free( schema ); + } + return iRc; +} + +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/sql/xbdelete.cpp b/src/sql/xbdelete.cpp index 157b281..82b4937 100755 --- a/src/sql/xbdelete.cpp +++ b/src/sql/xbdelete.cpp @@ -95,7 +95,7 @@ xbInt16 xbSql::SqlDelete( const xbString &sCmdLine ){ } } else { - xbFilter f( dbf->GetXbasePtr(), dbf ); + xbFilter f( dbf ); if(( iRc = f.Set( sFilter )) != XB_NO_ERROR ){ iErrorStop = 150; throw iRc; diff --git a/src/sql/xbdrptbl.cpp b/src/sql/xbdrptbl.cpp index e2cfa9d..b03ee8f 100755 --- a/src/sql/xbdrptbl.cpp +++ b/src/sql/xbdrptbl.cpp @@ -61,7 +61,7 @@ xbInt16 xbSql::SqlDropTable( const xbString &sCmdLine ){ sNode.Trim(); sNode.ToUpperCase(); if( sNode != "EXISTS" ){ - iErrorStop = 10; + iErrorStop = 100; iRc = XB_SYNTAX_ERROR; throw iRc; } else { @@ -91,22 +91,21 @@ xbInt16 xbSql::SqlDropTable( const xbString &sCmdLine ){ if( iRc == XB_FILE_NOT_FOUND && bIfExists ){ return XB_NO_ERROR; } else { - iErrorStop = 20; + iErrorStop = 110; throw iRc; } } } if( dbf == NULL ){ - iErrorStop = 40; + iErrorStop = 120; iRc = XB_OPEN_ERROR; throw iRc; } if(( dbf->DeleteTable()) != XB_NO_ERROR ){ - iErrorStop = 50; + iErrorStop = 130; throw iRc; } - } catch (xbInt16 iRc ){ diff --git a/src/sql/xbselect.cpp b/src/sql/xbselect.cpp index 91c0485..7f12e99 100755 --- a/src/sql/xbselect.cpp +++ b/src/sql/xbselect.cpp @@ -21,18 +21,23 @@ namespace xb{ /***********************************************************************/ -xbInt16 xbSql::SqlSelect( const xbString &sCmdLine ){ +xbInt16 xbStmt::ExecuteQuery( const xbString &sCmdLine ){ - std::cout << "SELECT [" << sCmdLine << "]\n"; + std::cout << "xbStmt::ExecuteQuery() - SELECT [" << sCmdLine << "]\n"; // expected format: // SELECT xbInt16 iRc = 0; xbInt16 iErrorStop = 0; - xbUInt32 ulPos; + // xbUInt32 ulPos; try{ + if(( iRc = ParseStmt( sCmdLine )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + /* xbString sCmd = sCmdLine; sCmd.Trim(); @@ -63,12 +68,12 @@ xbInt16 xbSql::SqlSelect( const xbString &sCmdLine ){ if( sToken == '^' ){ if(( iRc = uda.DelTokenForKey( sKey )) != XB_NO_ERROR ){ - iErrorStop = 10; + iErrorStop = 100; throw iRc; } } else { if(( iRc = uda.UpdTokenForKey( sKey, sToken )) != XB_NO_ERROR ){ - iErrorStop = 10; + iErrorStop = 110; throw iRc; } } @@ -78,7 +83,7 @@ xbInt16 xbSql::SqlSelect( const xbString &sCmdLine ){ } catch (xbInt16 iRc ){ xbString sMsg; - sMsg.Sprintf( "xbSql::SqlSelect() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); + sMsg.Sprintf( "xbStmt::ExecuteQuery() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); xbase->WriteLogMessage( sMsg.Str() ); xbase->WriteLogMessage( GetErrorMessage( iRc )); } diff --git a/src/sql/xbset.cpp b/src/sql/xbset.cpp index 98de309..d0e8821 100755 --- a/src/sql/xbset.cpp +++ b/src/sql/xbset.cpp @@ -63,17 +63,16 @@ xbInt16 xbSql::SqlSet( const xbString &sCmdLine ){ if( sToken == '^' ){ if(( iRc = uda.DelTokenForKey( sKey )) != XB_NO_ERROR ){ - iErrorStop = 10; + iErrorStop = 100; throw iRc; } } else { if(( iRc = uda.UpdTokenForKey( sKey, sToken )) != XB_NO_ERROR ){ - iErrorStop = 10; + iErrorStop = 110; throw iRc; } } } - } catch (xbInt16 iRc ){ xbString sMsg; diff --git a/src/sql/xbsql.cpp b/src/sql/xbsql.cpp index 5261b1a..12d3379 100755 --- a/src/sql/xbsql.cpp +++ b/src/sql/xbsql.cpp @@ -123,9 +123,6 @@ xbInt16 xbSql::ExecuteNonQuery( const xbString &sCmdLine ) { else if( sNode1 == "USE" ) iRc = SqlUse( sCmd ); - else if( sNode1 == "SELECT" ) - iRc = SqlSelect( sCmd ); - else if( sNode1 == "SET" ) iRc = SqlSet( sCmd ); diff --git a/src/sql/xbstmt.cpp b/src/sql/xbstmt.cpp new file mode 100755 index 0000000..61c84fd --- /dev/null +++ b/src/sql/xbstmt.cpp @@ -0,0 +1,679 @@ +/* xbsql.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +#include "xbase.h" + +#ifdef XB_SQL_SUPPORT + +namespace xb{ + +/***********************************************************************/ +xbStmt::xbStmt( xbXBase *x ){ + xbase = x; + pTblList = NULL; + fl = NULL; + ulFromPos = 0; + ulWherePos = 0; + ulOrderByPos = 0; + ulGroupByPos = 0; + ulHavingPos = 0; +} + +/***********************************************************************/ +xbStmt::~xbStmt(){ + + std::cout << "xbStmt::~xbStmt() - need to release all allocated structures and memory here\n"; + +} + +/***********************************************************************/ +xbInt16 xbStmt::CvtSqlExp2DbaseExp( const xbString &sExpIn, xbString &sExpOut ){ + + // convert Ansi SQL expression to a DBase compatible expression + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + try{ + + // convert tablename.fieldname to tablename->fieldname + sExpOut = sExpIn[1]; + xbUInt32 ulPos = 2; + while( ulPos < sExpIn.Len() ){ + if( sExpIn[ulPos] == '.' && sExpIn[ulPos-1] != ' ' && sExpIn[ulPos+1] != ' ' ) + sExpOut += "->"; + else + sExpOut += sExpIn[ulPos]; + ulPos++; + } + sExpOut += sExpIn[ulPos]; + + sExpOut.Replace( " AND ", " .AND. ", 0 ); + sExpOut.Replace( " and ", " .AND. ", 0 ); + sExpOut.Replace( " OR ", " .OR. ", 0 ); + sExpOut.Replace( " or ", " .OR. ", 0 ); + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbStmt::CvtSqlExp2DbaseExp() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return iRc; +} + + +/***********************************************************************/ +#ifdef XB_DEBUG_SUPPORT +xbInt16 xbStmt::DumpStmtInternals(){ + + std::cout << "************** Dump Statment Internals ***************" << std::endl; + std::cout << "Statement [" << sStmt << "]\n"; + std::cout << "Fields [" << sFields << "]\n"; + std::cout << "From [" << sFrom << "]\n"; + std::cout << "Where [" << sWhere << "]\n"; + std::cout << "Order By [" << sOrderBy << "]\n"; + std::cout << "Group By [" << sGroupBy << "]\n"; + std::cout << "Having [" << sHaving << "]\n"; + + xbTblJoin *p = pTblList; + if( p ){ + std::cout << "Tbl List\n"; + std::cout << "Type,Name,Alias,Exp\n"; + while( p ){ + std::cout << p->cJoinType << "," << p->sTableName.Str() << "," << p->sAlias.Str() << "," << p->sJoinExp.Str() << "\n"; + p = p->next; + } + } + std::cout << "*************** End of Internals ************" << std::endl; + return 0; +} + +xbInt16 xbStmt::Test(){ + xbString s; + + s = "(ABC)"; + std::cout << "[" << s.Str() << "][" << GetParenCnt( s ) << "]\n"; + s = "(ABC) )"; + std::cout << "[" << s.Str() << "][" << GetParenCnt( s ) << "]\n"; + s = "("; + std::cout << "[" << s.Str() << "][" << GetParenCnt( s ) << "]\n"; + s = "( ("; + std::cout << "[" << s.Str() << "][" << GetParenCnt( s ) << "]\n"; + s = "aaa)"; + std::cout << "[" << s.Str() << "][" << GetParenCnt( s ) << "]\n"; + s = "aaa"; + std::cout << "[" << s.Str() << "][" << GetParenCnt( s ) << "]\n"; + + return 0; + +} +#endif // XB_DEBUG_SUPPORT + + +/***********************************************************************/ +xbInt16 xbStmt::GetNextFromSeg( const xbString &sLineIn, xbString &sFromSegOut ){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbInt16 iParenCtr = 0; + xbUInt32 ulPos = 1; + xbUInt32 ulTsp = 0; // token start position + xbBool bDone = xbFalse; + xbString sToken; + + try{ + sFromSegOut = ""; + while( !bDone ){ + ulTsp = GetNextToken( sLineIn, sToken, ulPos ); + if( sToken == "" ){ + bDone = xbTrue; + + } else { + iParenCtr += GetParenCnt( sToken ); + if( iParenCtr == 0 && ulPos > 1 ){ + sToken.ToUpperCase(); + if( sToken == "LEFT" || sToken == "RIGHT" || sToken == "FULL" || + sToken == "INNER" || sToken == "OUTER" || sToken[1] == '(' ){ + bDone = xbTrue; + } + } + } + ulPos += (sToken.Len() + 1); + } + if( ulTsp > 1 ) + sFromSegOut.Assign( sLineIn, 1, ulTsp - 2 ); + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbStmt::GetNextFromSeg() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return iRc; +} + +/***********************************************************************/ + +xbUInt32 xbStmt::GetNextToken( const xbString &sCmdLineIn, xbString &sTokenOut, xbUInt32 ulStartPos ){ + + // input + // sCmdLine - Entire Command line + // ulStartPos - Where to start searching for the next token + // returns the position of the beginning of the token in the main command line + + xbUInt32 ul = ulStartPos; + xbUInt32 ulTokenStartPos = 0; + sTokenOut = ""; + + while( ul <= sCmdLineIn.Len() && sCmdLineIn[ul] == ' ' ) + ul++; + ulTokenStartPos = ul; + + while( ul <= sCmdLineIn.Len() && sCmdLineIn[ul] != ' ' ){ + sTokenOut += sCmdLineIn[ul]; + ul++; + } + + return ulTokenStartPos; +} +/***********************************************************************/ +xbInt16 xbStmt::GetParenCnt( const xbString &sToken ){ + + xbInt16 iParenCnt = 0; + + for( xbUInt32 i = 1; i <= sToken.Len(); i++ ){ + if( sToken[i] == '(' ) + iParenCnt++; + else if( sToken[i] == ')' ) + iParenCnt--; + } + return iParenCnt; +} + + +/***********************************************************************/ +xbInt16 xbStmt::ParseFromStmt( const xbString &sFromLine ){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbBool bDone = xbFalse; + xbString sFromSeg; + xbString sLine = sFromLine; + + try{ + std::cout << "ParseFromSeg [" << sFromLine.Str() << "]\n"; + + while( !bDone ){ + if(( iRc = GetNextFromSeg( sLine, sFromSeg)) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + if( sFromSeg.Len() == 0 ){ + bDone = xbTrue; + } else { + if(( iRc = ProcessFromSeg( sFromSeg )) != XB_NO_ERROR ){ + iErrorStop = 110; + throw iRc; + } + sLine.Ltrunc( sFromSeg.Len() ); + sLine.Ltrim(); + } + } + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbStmt::ParseFromSeg() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + + return iRc; +} +/***********************************************************************/ +xbInt16 xbStmt::ParseStmt( const xbString &sCmdLine ){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbInt16 iParenCnt = 0; + xbUInt32 ulStartPos = 7; + xbUInt32 ulLen = 0; + + + xbBool bFromFound = xbFalse; + xbBool bWhereFound = xbFalse; + xbBool bOrderByFound = xbFalse; + xbBool bGroupByFound = xbFalse; + xbBool bHavingFound = xbFalse; + xbBool bDone = xbFalse; + + xbString sToken; + + sStmt.Set( sCmdLine ); + sStmt.Trim(); + + try{ + + std::cout << "ParseStmt - [" << sStmt << "]\n"; + + xbUInt32 ulPos = ulStartPos; + + while( !bFromFound && !bDone ){ + ulPos = GetNextToken( sStmt, sToken, ulPos ); + if( sToken == "" ){ + bDone = xbTrue; + } else { + iParenCnt += GetParenCnt( sToken ); + if( iParenCnt == 0 ){ + sToken.ToUpperCase(); + if( sToken == "FROM" ){ + bFromFound = xbTrue; + ulFromPos = ulPos; + sFrom.Assign( sStmt, ulFromPos ); + } + } + ulPos += sToken.Len() + 1; + } + } + + // look for the where clause + if( bFromFound ) + ulPos = ulFromPos + 5; + else + ulPos = ulStartPos; + + bDone = xbFalse; + while( !bWhereFound && !bDone ){ + ulPos = GetNextToken( sStmt, sToken, ulPos ); + if( sToken == "" ){ + bDone = xbTrue; + } else { + iParenCnt += GetParenCnt( sToken ); + if( iParenCnt == 0 ){ + sToken.ToUpperCase(); + if( sToken == "WHERE" ){ + bWhereFound = xbTrue; + ulWherePos = ulPos; + sWhere.Assign( sStmt, ulWherePos+6 ); + } + } + ulPos += sToken.Len() + 1; + } + } + + + // look for the order clause + if( bWhereFound ) + ulPos = ulWherePos + 6; + else if( bFromFound ) + ulPos = ulFromPos + 5; + else + ulPos = ulStartPos; + + bDone = xbFalse; + while( !bOrderByFound && !bDone ){ + ulPos = GetNextToken( sStmt, sToken, ulPos ); + if( sToken == "" ){ + bDone = xbTrue; + } else { + iParenCnt += GetParenCnt( sToken ); + if( iParenCnt == 0 ){ + sToken.ToUpperCase(); + if( sToken == "ORDER" ){ + xbString sToken2; + xbUInt32 ulPos2 = GetNextToken( sStmt, sToken2, ulPos + 6 ); + if( sToken2 != "" ){ + sToken2.ToUpperCase(); + if( sToken2 == "BY" ){ + bOrderByFound = xbTrue; + ulOrderByPos = ulPos; + sOrderBy.Assign( sStmt, ulPos2 + 3 ); + } + } + } + } + ulPos += sToken.Len() + 1; + } + } + + + bDone = xbFalse; + while( !bGroupByFound && !bDone ){ + ulPos = GetNextToken( sStmt, sToken, ulPos ); + if( sToken == "" ){ + bDone = xbTrue; + } else { + iParenCnt += GetParenCnt( sToken ); + if( iParenCnt == 0 ){ + sToken.ToUpperCase(); + if( sToken == "GROUP" ){ + xbString sToken2; + xbUInt32 ulPos2 = GetNextToken( sStmt, sToken2, ulPos + 6 ); + if( sToken2 != "" ){ + sToken2.ToUpperCase(); + if( sToken2 == "BY" ){ + bGroupByFound = xbTrue; + ulGroupByPos = ulPos; + sGroupBy.Assign( sStmt, ulPos2 + 3 ); + } + } + } + } + ulPos += sToken.Len() + 1; + } + } + + bDone = xbFalse; + while( !bHavingFound && !bDone ){ + ulPos = GetNextToken( sStmt, sToken, ulPos ); + if( sToken == "" ){ + bDone = xbTrue; + } else { + iParenCnt += GetParenCnt( sToken ); + if( iParenCnt == 0 ){ + sToken.ToUpperCase(); + if( sToken == "HAVING" ){ + bHavingFound = xbTrue; + ulHavingPos = ulPos; + sHaving.Assign( sStmt, ulHavingPos + 7 ); + } + } + ulPos += sToken.Len() + 1; + } + } + + + // do the fields part + if( bFromFound ) + ulLen = ulFromPos - 7; + else if( bWhereFound ) + ulLen = ulWherePos - 7; + else if( bOrderByFound ) + ulLen = ulOrderByPos - 7; + else if( bGroupByFound ) + ulLen = ulGroupByPos - 7; + else if( bHavingFound ) + ulLen = ulHavingPos - 7; + else + ulLen = sStmt.Len() - 7; + sFields.Assign( sStmt, 7, ulLen ); + sFields.Trim(); + + // do the FROM part + if( bFromFound ){ + if( bWhereFound ) + ulLen = ulWherePos - ulFromPos; + else if( bOrderByFound ) + ulLen = ulOrderByPos - ulFromPos; + else if( bGroupByFound ) + ulLen = ulGroupByPos - ulFromPos; + else if( bHavingFound ) + ulLen = ulHavingPos - ulFromPos; + else + ulLen = sStmt.Len() - ulFromPos; + sFrom.Resize( ulLen ); + sFrom.Trim(); + + } + + + // do the WHERE part + if( bWhereFound ){ + ulLen = 0; + if( bOrderByFound ) + ulLen = ulOrderByPos - ulWherePos - 6; + else if( bGroupByFound ) + ulLen = ulGroupByPos - ulWherePos - 6; + else if( bHavingFound ) + ulLen = ulHavingPos - ulWherePos - 6; + + if( ulLen > 0 ) + sWhere.Resize( ulLen ); + sWhere.Trim(); + } + + // FIXME if there is more than one space between ORDER and BY then this doesn't work quite right + // do the ORDER BY part + if( bOrderByFound ){ + if( bGroupByFound ) + ulLen = ulGroupByPos - ulOrderByPos - 9; + else if( bHavingFound ) + ulLen = ulHavingPos - ulOrderByPos - 9; + else + ulLen = sStmt.Len() - ulOrderByPos - 9; + sOrderBy.Resize( ulLen ); + sOrderBy.Trim(); + } + + // FIXME if there is more than one space between ORDER and BY then this doesn't work quite right + // do the GROUP BY part + if( bGroupByFound ){ + if( bHavingFound ) + ulLen = ulHavingPos - ulGroupByPos - 9; + else + ulLen = sStmt.Len() - ulGroupByPos - 9; + sGroupBy.Resize( ulLen ); + sGroupBy.Trim(); + } + + if( bFromFound ){ + if(( iRc = ParseFromStmt( sFrom )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } + + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbStmt::ParseStmt() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + + return iRc; +} + +/***********************************************************************/ +xbInt16 xbStmt::ProcessFromSeg( const xbString &sFromSeg ){ + + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + char cType = ' '; + xbString sToken; + xbString sTable; + xbString sAlias; + xbString sWork; + xbString sExp; + xbUInt32 iPos; + xbBool bDone; + xbExp * pJoinExp = NULL; + + try{ + + std::cout << "ProcessFromSeg for segment [" << sFromSeg.Str() << "]\n"; + + GetNextToken( sFromSeg, sToken, 1 ); + sToken.ToUpperCase(); + + std::cout << "sToken1 = [" << sToken.Str() << "]\n"; + + if( sToken == "FROM" ){ + // FROM has to be the first statement, and exist only once + if( pTblList ){ + iErrorStop = 100; + iRc = XB_PARSE_ERROR; + throw iRc; + } + cType = 'M'; + } else if( sToken == "LEFT" ) + cType = 'L'; + else if( sToken == "RIGHT" ) + cType = 'R'; + else if( sToken == "RIGHT" ) + cType = 'R'; + else if( sToken == "INNER" ) + cType = 'I'; + else if( sToken == "OUTER" || sToken == "FULL" ) + cType = 'O'; + else if( sToken[1] == '(' ) + cType = 'Q'; + else{ + iErrorStop = 100; + iRc = XB_PARSE_ERROR; + throw iRc; + } + + + if( cType == 'M' ){ + // expecting "FROM table" or "FROM table alias" + iPos = GetNextToken( sFromSeg, sToken, 5 ); + sTable = sToken; + + iPos = GetNextToken( sFromSeg, sToken, iPos + sToken.Len() + 1 ); + if( sToken.Len() > 0 ) + sAlias = sToken; + else + sAlias = ""; + + sWork = sToken; + sWork.ToUpperCase(); + iPos = sWork.Pos( ".DBF" ); + if( iPos == 0 ) + sTable += ".DBF"; + + // std::cout << "table = [" << sTable.Str() << "] alias = [" << sAlias.Str() << "]\n"; + + } else if( cType != 'Q' ){ + sWork = sFromSeg; + sWork.ToUpperCase(); + iPos = sWork.Pos( " ON " ); + if( iPos == 0 ){ + iErrorStop = 110; + iRc = XB_PARSE_ERROR; + throw iRc; + } + bDone = xbFalse; + + sWork.Assign( sFromSeg, iPos + 4 ); + CvtSqlExp2DbaseExp( sWork, sExp ); + sExp.Trim(); + std::cout << "ON = [" << sExp.Str() << "]\n"; + + + // need to get past the keywords LEFT, FULL, OUTER, RIGHT, INNER and get the table name here + iPos = sToken.Len() + 1; + while( !bDone ){ + iPos = GetNextToken( sFromSeg, sToken, iPos ); + sWork = sToken; + sWork.ToUpperCase(); + if( sWork != "LEFT" && sWork != "RIGHT" && sWork != "INNER" && sWork != "OUTER" && sWork != "FULL" && sWork != "JOIN" ) + bDone = xbTrue; + else + iPos += (sWork.Len() + 1); + } + + sTable = sToken; + GetNextToken( sFromSeg, sAlias, iPos + sTable.Len() + 1 ); + sWork.ToUpperCase(); + iPos = sWork.Pos( ".DBF" ); + if( iPos == 0 ) + sTable += ".DBF"; + sWork = sAlias; + sWork.ToUpperCase(); + if( sWork == "ON" ) + sAlias = ""; + } + + + // open table + //std::cout << "attempting to open table " << sTable.Str() << "\n"; + xbDbf *d = NULL; + if(( iRc = xbase->OpenHighestVersion( sTable, sAlias, &d )) != XB_NO_ERROR ){ + iErrorStop = 120; + throw iRc; + } + + + + // build out table linkage expression + if( cType == 'M' ) + sExp = "MASTER"; + else if( cType == 'L' ){ + pJoinExp = new xbExp( xbase ); + + // std::cout << "Parsing expression [" << sExp.Str() << "]\n"; + if(( iRc = pJoinExp->ParseExpression( d, sExp )) != XB_NO_ERROR ){ + iErrorStop = 130; + throw iRc; + } + } + + + // attach to correct location in list + + + // update the UpdateJoinList routine as appropriate +// if(( iRc = UpdateJoinList( cType, sTable, sAlias, NULL, NULL, NULL, NULL )) != XB_NO_ERROR ){ + + if(( iRc = UpdateJoinList( cType, sTable, sAlias, sExp, d, pJoinExp )) != XB_NO_ERROR ){ + iErrorStop = 110; + throw iRc; + } + + + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbStmt::ProcessFromSeg() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return iRc; +} + +/***********************************************************************/ +xbInt16 xbStmt::UpdateJoinList( char cType, const xbString &sTableName, const xbString &sAlias, const xbString &sExp, xbDbf *d, xbExp *e ){ +// xbTag *t ){ + + + std::cout << "Update join list for table " << sTableName.Str() << "\n"; + + xbTblJoin *pTj; + if(( pTj = (xbTblJoin *) calloc( 1, sizeof( xbTblJoin ))) == NULL ) + return XB_NO_MEMORY; + + pTj->cJoinType = cType; + pTj->sTableName.Set( sTableName ); + pTj->sAlias.Set( sAlias ); + pTj->sJoinExp.Set( sExp ); + pTj->pDbf = d; + pTj->pLinkExp = e; + +/* + + pTj->pTag = t; +*/ + + if( cType == 'M' ) + pTblList = pTj; + + return 0; +} +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/tests/xb_test_bcd.cpp b/src/tests/xb_test_bcd.cpp index 1eab20f..f735935 100755 --- a/src/tests/xb_test_bcd.cpp +++ b/src/tests/xb_test_bcd.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2017,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2017,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -45,6 +45,7 @@ int main( int argCnt, char **av ) xbXBase x; #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( iPo ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -55,8 +56,6 @@ int main( int argCnt, char **av ) #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); - if( iPo > 0 ){ std::cout << "XBase bcd testing program.." << std::endl; diff --git a/src/tests/xb_test_blockread.cpp b/src/tests/xb_test_blockread.cpp new file mode 100755 index 0000000..ff55d23 --- /dev/null +++ b/src/tests/xb_test_blockread.cpp @@ -0,0 +1,168 @@ +/* xb_test_blockread.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the class xbBlockRead +// usage: xb_test_blockread QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + xbSchema MyDbfRec[] = + { + { "NFLD", XB_NUMERIC_FLD, 10, 0 }, + { "CFLD", XB_CHAR_FLD, 89, 0 }, + { "",0,0,0 } + }; + + +int main( int argCnt, char **av ) +{ + xbInt16 iRc = 0; + xbInt16 iRc2 = 0; + int iPo = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + iPo = 0; + else if( av[1][0] == 'V' ) + iPo = 2; + } + + xbXBase x; + x.SetDataDirectory( PROJECT_DATA_DIR ); + + xbDbf4 dbf( &x ); + + #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); + x.EnableMsgLogging(); + if( iPo ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + + InitTime(); + + + iRc2 = dbf.CreateTable( "BLOCKRD.DBF", "BlockRead", MyDbfRec, XB_OVERLAY, XB_MULTI_USER ); + iRc += TestMethod( iPo, "CreateTable()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + + // fill the file with several blocks of data + for( xbInt32 i = 0; i < 50; i++ ){ + iRc2 = dbf.BlankRecord(); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "BlankRecord()", (xbInt32) iRc2, XB_NO_ERROR ); + + iRc2 = dbf.PutLongField( 0, i+1 ); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "PutLongField()", (xbInt32) iRc2, XB_NO_ERROR ); + + iRc2 = dbf.AppendRecord(); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "AppendRecord()", (xbInt32) iRc2, XB_NO_ERROR ); + + iRc2 = dbf.Commit(); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "Commit()", (xbInt32) iRc2, XB_NO_ERROR ); + } + + + dbf.SetDefaultBlockReadSize( 2000 ); + + // enable block read for this table + iRc += TestMethod( iPo, "EnableBlockReadProcessing()", dbf.EnableBlockReadProcessing(), XB_NO_ERROR ); + + xbUInt32 ulFld = 0; + xbUInt32 ulCtr = 1; + + iRc2 = XB_NO_ERROR; + while( iRc2 == XB_NO_ERROR ){ + // std::cout << ulCtr << "\n"; + iRc2 += dbf.GetRecord( ulCtr ); + if( iRc2 != XB_NO_ERROR && iRc != XB_INVALID_RECORD ) + TestMethod( iPo, "GetRecord()", iRc, XB_NO_ERROR ); + + if( iRc2 == XB_NO_ERROR ){ + dbf.GetULongField( "NFLD", ulFld ); + if( ulFld != ulCtr ){ + std::cout << "ulFld = " << ulFld << " ulCtr = " << ulCtr << "\n"; + iRc += TestMethod( iPo, "Field Compare", (xbDouble) ulFld, (xbDouble) ulCtr ); + } + } + ulCtr++; + } + + // std::cout << "**********Delete every other record\n"; + iRc2 = dbf.GetFirstRecord(); + while( iRc2 == XB_NO_ERROR ){ + if( (dbf.GetCurRecNo() % 2) != 0 ){ + dbf.DeleteRecord(); + dbf.Commit(); + } + iRc2 = dbf.GetNextRecord(); + } + + + // test filter for deleted records + #ifdef XB_FILTER_SUPPORT + xbFilter f( &dbf ); + xbString sFilt = ".NOT. DELETED()"; + f.Set( sFilt ); + iRc2 = f.GetFirstRecord(); + while( iRc2 == XB_NO_ERROR ){ + dbf.GetULongField( "NFLD", ulFld ); + if( (ulFld % 2) != 0 ){ + iRc += TestMethod( iPo, "Filter GetNextRecord()", ulFld % 2, 0 ); + } + iRc2 = f.GetNextRecord(); + } + #endif // XB_FILTER_SUPPORT + + + iRc += TestMethod( iPo, "DisableBlockReadProcessing()", dbf.DisableBlockReadProcessing(), XB_NO_ERROR ); + //iRc2 = dbf.DeleteTable(); + + iRc2 = dbf.Close(); + iRc += TestMethod( iPo, "Close()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); + #endif + + + if( iPo > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + + return iRc; +} + diff --git a/src/tests/xb_test_date.cpp b/src/tests/xb_test_date.cpp index 1d9b523..7aee584 100755 --- a/src/tests/xb_test_date.cpp +++ b/src/tests/xb_test_date.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -40,8 +40,9 @@ int main( int argCnt, char **av ) po = 2; } -#ifdef XB_LOGGING_SUPPORT xbXBase x; + #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -49,7 +50,7 @@ int main( int argCnt, char **av ) xbString sMsg; sMsg.Sprintf( "Program [%s] initializing...", av[0] ); x.WriteLogMessage( sMsg ); -#endif + #endif InitTime(); xbDate d1; diff --git a/src/tests/xb_test_dbf_v3_memos.cpp b/src/tests/xb_test_dbf_v3_memos.cpp index ad3e8e0..e42edb1 100755 --- a/src/tests/xb_test_dbf_v3_memos.cpp +++ b/src/tests/xb_test_dbf_v3_memos.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -55,6 +55,7 @@ int main( int argCnt, char **av ) xbXBase x; #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -65,7 +66,6 @@ int main( int argCnt, char **av ) #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); #ifdef XB_LOCKING_SUPPORT x.DisableDefaultAutoLock(); diff --git a/src/tests/xb_test_dbf_v3_nomemos.cpp b/src/tests/xb_test_dbf_v3_nomemos.cpp index e5adc48..2dfeb7e 100755 --- a/src/tests/xb_test_dbf_v3_nomemos.cpp +++ b/src/tests/xb_test_dbf_v3_nomemos.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -59,7 +59,8 @@ int main( int argCnt, char **av ) xbXBase x; -#ifdef XB_LOGGING_SUPPORT + #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -67,10 +68,9 @@ int main( int argCnt, char **av ) xbString sMsg; sMsg.Sprintf( "Program [%s] initializing...", av[0] ); x.WriteLogMessage( sMsg ); -#endif + #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); #ifdef XB_LOCKING_SUPPORT x.DisableDefaultAutoLock(); @@ -97,7 +97,7 @@ int main( int argCnt, char **av ) xbDbf3 V3Dbf2( &x ); // next occurrence should error as a dup - x.WriteLogMessage( "Second create attempt" ); + x.WriteLogMessage( "Second create attempt, should generate an error." ); iRc2 = V3Dbf2.CreateTable( "TestV3.DBF", "TestV3", MyV3Record, XB_DONTOVERLAY, XB_MULTI_USER ); iRc += TestMethod( po, "CreateTable()", iRc2, XB_FILE_EXISTS ); if( iRc2 != XB_FILE_EXISTS ){ diff --git a/src/tests/xb_test_dbf_v4_memos.cpp b/src/tests/xb_test_dbf_v4_memos.cpp index 2b0e09c..47a9053 100755 --- a/src/tests/xb_test_dbf_v4_memos.cpp +++ b/src/tests/xb_test_dbf_v4_memos.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -47,8 +47,8 @@ int main( int argCnt, char **av ) xbXBase x; -#ifdef XB_LOGGING_SUPPORT - + #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -56,11 +56,9 @@ int main( int argCnt, char **av ) xbString sMsg; sMsg.Sprintf( "Program [%s] initializing...", av[0] ); x.WriteLogMessage( sMsg ); - -#endif + #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); #ifdef XB_LOCKING_SUPPORT x.DisableDefaultAutoLock(); diff --git a/src/tests/xb_test_dbf_v4_nomemos.cpp b/src/tests/xb_test_dbf_v4_nomemos.cpp index 4036588..984eb63 100755 --- a/src/tests/xb_test_dbf_v4_nomemos.cpp +++ b/src/tests/xb_test_dbf_v4_nomemos.cpp @@ -2,7 +2,7 @@ XBase Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -56,9 +56,19 @@ int main( int argCnt, char **av ) { "",0,0,0 } }; + xbSchema MyV4ZipRecord[] = + { + { "ZIPCODE", XB_NUMERIC_FLD, 5, 0 }, + { "CITY", XB_CHAR_FLD, 30, 0 }, + { "STATE", XB_CHAR_FLD, 2, 0 }, + { "",0,0,0 } + }; + + xbXBase x; #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -69,7 +79,6 @@ int main( int argCnt, char **av ) #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); #ifdef XB_LOCKING_SUPPORT x.DisableDefaultAutoLock(); @@ -318,10 +327,26 @@ int main( int argCnt, char **av ) rc += TestMethod( po, "GetField()", V4Dbf.GetField( fldAMT, sf ), XB_NO_ERROR ); rc += TestMethod( po, "GetField()", sf, " 432.55", 9 ); + + xbDbf4 V4DbfZ( &x ); // version 4 dbf file + rc2 = V4DbfZ.CreateTable( "TestV4Zip.DBF", "TestV4Zip", MyV4ZipRecord, XB_OVERLAY, XB_MULTI_USER ); + rc += TestMethod( po, "CreateTable()", (xbInt32) rc2, XB_NO_ERROR ); + if( rc2 ) + x.DisplayError( rc2 ); + + + rc += TestMethod( po, "Close()", V4Dbf.Close(), XB_NO_ERROR ); if( po == 2 ) x.DisplayTableList(); + + rc += TestMethod( po, "Close()", V4DbfZ.Close(), XB_NO_ERROR ); + if( po == 2 ) + x.DisplayTableList(); + + + if( po > 0 || rc < 0 ) fprintf( stdout, "Total Errors = %d\n", rc * -1 ); diff --git a/src/tests/xb_test_expnode.cpp b/src/tests/xb_test_expnode.cpp index 3fb716d..cbd79c9 100755 --- a/src/tests/xb_test_expnode.cpp +++ b/src/tests/xb_test_expnode.cpp @@ -2,7 +2,7 @@ XBase Software Library -Copyright (c) 1997,2003,2014,2017,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2017,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -42,6 +42,7 @@ int main( int argCnt, char **av ) xbXBase x; #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -52,7 +53,6 @@ int main( int argCnt, char **av ) #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); InitTime(); if( po > 0 ){ diff --git a/src/tests/xb_test_expression.cpp b/src/tests/xb_test_expression.cpp index 75ed3e5..ac1cde7 100755 --- a/src/tests/xb_test_expression.cpp +++ b/src/tests/xb_test_expression.cpp @@ -2,7 +2,7 @@ XBase Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -67,7 +67,7 @@ xbInt16 DevTester( xbXBase * xb, xbDbf * dbf, const char * sExpIn ){ if( iRc == XB_NO_ERROR ){ #ifdef XB_DEBUG_SUPPORT exp.DumpTree( xbTrue ); - #endif // XB_DEBUG_SUPPORT + #endif // XB_DEBUG_SUPPORT std::cout << "dump nodes\n"; n = exp.GetNextNodeTest( NULL ); if( !n ){ @@ -86,7 +86,6 @@ xbInt16 DevTester( xbXBase * xb, xbDbf * dbf, const char * sExpIn ){ std::cout << "Parse Error [" << iRc << "]\n"; return -1; } - return 0; } /**************************************************************************/ @@ -394,6 +393,7 @@ int main( int argCnt, char **av ) xbDate d; #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -404,7 +404,6 @@ int main( int argCnt, char **av ) #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); InitTime(); if( po > 0 ){ diff --git a/src/tests/xb_test_file.cpp b/src/tests/xb_test_file.cpp index 4614805..cf835c2 100755 --- a/src/tests/xb_test_file.cpp +++ b/src/tests/xb_test_file.cpp @@ -1,6 +1,6 @@ /* xb_test_file.cpp -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -42,6 +42,7 @@ int main( int argCnt, char **av ) xbXBase x; #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; diff --git a/src/tests/xb_test_filter.cpp b/src/tests/xb_test_filter.cpp index ac4b896..000e196 100755 --- a/src/tests/xb_test_filter.cpp +++ b/src/tests/xb_test_filter.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2020,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2020,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -41,7 +41,6 @@ int main( int argCnt, char **av ) iPo = 2; } - xbSchema MyV4Record[] = { { "CFLD", XB_CHAR_FLD, 6, 0 }, @@ -50,9 +49,9 @@ int main( int argCnt, char **av ) { "",0,0,0 } }; - xbXBase x; #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( iPo ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -64,7 +63,6 @@ int main( int argCnt, char **av ) #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); char c; xbString s; @@ -114,7 +112,7 @@ int main( int argCnt, char **av ) iRc += TestMethod( iPo, "SetCurTag()", MyFile->SetCurTag( "" ), XB_NO_ERROR ); #endif // XB_INDEX_SUPPORT - xbFilter f1( &x, MyFile ); + xbFilter f1( MyFile ); xbString sMyFilterExpression = "LEFT( CFLD, 2 ) = 'YY'"; iRc += TestMethod( iPo, "Set()", f1.Set( sMyFilterExpression ), XB_NO_ERROR ); diff --git a/src/tests/xb_test_funcs.cpp b/src/tests/xb_test_funcs.cpp index e8b73b0..c7bf0d3 100755 --- a/src/tests/xb_test_funcs.cpp +++ b/src/tests/xb_test_funcs.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -61,6 +61,7 @@ int main( int argCnt, char **av ) #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; diff --git a/src/tests/xb_test_linklist.cpp b/src/tests/xb_test_linklist.cpp index dc253af..288ee99 100755 --- a/src/tests/xb_test_linklist.cpp +++ b/src/tests/xb_test_linklist.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -42,7 +42,8 @@ int main( int argCnt, char **av ) } xbXBase x; -#ifdef XB_LOGGING_SUPPORT + #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -50,7 +51,8 @@ int main( int argCnt, char **av ) xbString sMsg; sMsg.Sprintf( "Program [%s] initializing...", av[0] ); x.WriteLogMessage( sMsg ); -#endif + #endif + InitTime(); xbLinkList ll; diff --git a/src/tests/xb_test_lock.cpp b/src/tests/xb_test_lock.cpp index 7e9865b..39332ad 100755 --- a/src/tests/xb_test_lock.cpp +++ b/src/tests/xb_test_lock.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -59,6 +59,7 @@ int main( int argCnt, char **av ) #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po > 0 ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -69,7 +70,6 @@ int main( int argCnt, char **av ) #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); InitTime(); #ifdef XB_DBF4_SUPPORT MyFile = new xbDbf4( &x ); /* version 4 dbf file */ diff --git a/src/tests/xb_test_lock2.cpp b/src/tests/xb_test_lock2.cpp index 3dd4b57..d5534ec 100755 --- a/src/tests/xb_test_lock2.cpp +++ b/src/tests/xb_test_lock2.cpp @@ -2,7 +2,7 @@ XBase Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -57,8 +57,8 @@ int main( int argCnt, char **av ) } #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); xbString sLogFileName = x.GetLogFqFileName().Str(); - sLogFileName.Resize( sLogFileName.Len() - 3 ); sLogFileName += "_l2.txt"; x.SetLogFileName( sLogFileName ); @@ -72,7 +72,6 @@ int main( int argCnt, char **av ) #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); InitTime(); #ifdef XB_DBF4_SUPPORT diff --git a/src/tests/xb_test_log.cpp b/src/tests/xb_test_log.cpp index 613b7dd..28ae552 100755 --- a/src/tests/xb_test_log.cpp +++ b/src/tests/xb_test_log.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -21,18 +21,13 @@ Email Contact: #include "xbase.h" using namespace xb; - #include "tstfuncs.cpp" - - int main( int argCnt, char **av ) { int rc = 0; -#ifdef XB_LOGGING_SUPPORT - - + #ifdef XB_LOGGING_SUPPORT int po = 1; /* print option */ /* 0 - QUIET */ /* 1 - NORMAL */ @@ -46,6 +41,7 @@ int main( int argCnt, char **av ) } xbXBase x; + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); InitTime(); if( po ){ @@ -55,21 +51,18 @@ int main( int argCnt, char **av ) sMsg.Sprintf( "Program [%s] initializing...", av[0] ); x.WriteLogMessage( sMsg ); - xbString sNewLogFileName = "Logfile2.txt"; sMsg.Sprintf( "Switching to logfile [%s]", sNewLogFileName.Str() ); x.WriteLogMessage( sMsg ); - x.DisableMsgLogging(); rc += TestMethod( po, "Set/Get Log Status()", x.GetLogStatus(), xbFalse ); x.SetLogFileName( sNewLogFileName ); - x.EnableMsgLogging(); + x.EnableMsgLogging(); rc += TestMethod( po, "Set/Get Log Status()", x.GetLogStatus(), 1 ); rc += TestMethod( po,"WriteLogMessage()", x.WriteLogMessage( "Test log message........" ), XB_NO_ERROR ); - sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], rc * -1 ); x.WriteLogMessage( sMsg ); diff --git a/src/tests/xb_test_mdx.cpp b/src/tests/xb_test_mdx.cpp index af191ad..2ef5ffb 100755 --- a/src/tests/xb_test_mdx.cpp +++ b/src/tests/xb_test_mdx.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -55,20 +55,28 @@ int main( int argCnt, char **av ) }; + xbSchema MyV4Record2[] = + { + { "CHAR1", XB_CHAR_FLD, 1, 0 }, + { "CHAR27", XB_CHAR_FLD, 27, 0 }, + { "",0,0,0 } + }; + + xbXBase x; -#ifdef XB_LOGGING_SUPPORT + #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( iPo ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; } sMsg.Sprintf( "Program [%s] initializing...", av[0] ); x.WriteLogMessage( sMsg ); -#endif + #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); - x.SetMultiUser( false ); + x.SetMultiUser( xbFalse ); InitTime(); if( iPo > 0 ) @@ -92,6 +100,7 @@ int main( int argCnt, char **av ) xbInt16 iDescending, xbInt16 iUnique, xbInt16 iOverLay, xbIx **xbIxOut, void **vpTagOut ); */ + iRc2 = V4DbfX1->CreateTag( "MDX", "CITY_TAGA", "CITY", "", 0, 0, XB_OVERLAY, &pIx, &pTag ); iRc += TestMethod( iPo, "CreateTag(1)", iRc2, 0 ); @@ -109,8 +118,6 @@ int main( int argCnt, char **av ) // std::cout << iRc2 << "\n"; -// something in th following block of code causing issues - xbInt32 uZip = 10000; for( xbUInt16 i = 0; i < 35; i++ ){ for( xbUInt16 j = 0; j < 14; j++ ){ @@ -147,7 +154,7 @@ int main( int argCnt, char **av ) } - iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "CheckTagIntegrity(1)", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); // attempt to add a dup key, should fail with XB_KEY_NOT_UNIQUE iRc2 = V4DbfX1->BlankRecord(); @@ -177,7 +184,7 @@ int main( int argCnt, char **av ) iRc += TestMethod( iPo, "Abort()", iRc2, XB_NO_ERROR ); iRc += TestMethod( iPo, "DeleteTag()", V4DbfX1->DeleteTag( "MDX", "CITY_TAGA" ), XB_NO_ERROR ); - iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "CheckTagIntegrity(2)", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); iRc2 = V4DbfX1->CreateTag( "MDX", "CITY_TAGF", "CITY", ".NOT. DELETED()", 0, 0, XB_OVERLAY, &pIx, &pTag ); iRc += TestMethod( iPo, "CreateTag(4)", iRc2, 0 ); @@ -186,27 +193,29 @@ int main( int argCnt, char **av ) iRc += TestMethod( iPo, "SetCurTag()", iRc2, XB_NO_ERROR ); iRc += TestMethod( iPo, "GetCurTagName()", V4DbfX1->GetCurTagName().Str(), "CITY_TAGF", 9 ); - iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_INVALID_INDEX ); + // next check throws an error message on the display, that is what it is testing, don't need to debug it + iRc += TestMethod( iPo, "CheckTagIntegrity(3)", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_INVALID_INDEX ); + iRc2 = V4DbfX1->Reindex( 0 ); iRc += TestMethod( iPo, "Reindex( 0 )", iRc2, XB_NO_ERROR ); - iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "CheckTagIntegrity(4)", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); iRc += TestMethod( iPo, "GetCurTagName()", V4DbfX1->GetCurTagName().Str(), "CITY_TAGF", 9 ); iRc2 = V4DbfX1->Reindex( 1 ); iRc += TestMethod( iPo, "Reindex( 1 )", iRc2, XB_NO_ERROR ); - iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "CheckTagIntegrity(5)", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); // delete everything, all keys should be removed from the filtered index iRc += TestMethod( iPo, "DeleteAll(0)", V4DbfX1->DeleteAll( 0 ), XB_NO_ERROR ); iRc += TestMethod( iPo, "Commit()", V4DbfX1->Commit(), XB_NO_ERROR ); - iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "CheckTagIntegrity(6)", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); // undelete everything, all keys should be added back into the filtered index iRc += TestMethod( iPo, "DeleteAll(1)", V4DbfX1->DeleteAll( 1 ), XB_NO_ERROR ); iRc += TestMethod( iPo, "Commit()", V4DbfX1->Commit(), XB_NO_ERROR ); - iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "CheckTagIntegrity(7)", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); // std::cout << "Cur Tag Name = " << V4DbfX1->GetCurTagName().Str() << "\n"; sKey = "abc"; @@ -239,8 +248,41 @@ int main( int argCnt, char **av ) iRc += TestMethod( iPo, "Rename()", V4DbfX1->Rename( "TestMdxR.DBF" ), XB_NO_ERROR ); + xbDbf *V4DbfX2 = new xbDbf4( &x ); + iRc2 = V4DbfX2->CreateTable( "TMDXDB02.DBF", "TestMdxX4", MyV4Record2, XB_OVERLAY, XB_MULTI_USER ); + iRc += TestMethod( iPo, "CreateTable(2)", iRc2, 0 ); + + + iRc2 = V4DbfX2->CreateTag( "MDX", "TAG1", "CHAR27", ".NOT. DELETED()", 0, 0, XB_OVERLAY, &pIx, &pTag ); +// iRc2 = V4DbfX2->CreateTag( "MDX", "TAG2", "CHAR1", "CHAR1 = 'O' .AND. .NOT. DELETED()", 0, 0, XB_OVERLAY, &pIx, &pTag ); + iRc += TestMethod( iPo, "CreateTag(4)", iRc2, 0 ); + + + + for( xbUInt32 ul = 0; ul < 500 && iRc2 == XB_NO_ERROR; ul++ ){ + c = 'O'; + V4DbfX2->BlankRecord(); + iRc2 = V4DbfX2->PutField( 1, c ); + if( iRc2 != XB_NO_ERROR ){ + iRc += TestMethod( iPo, "PutField()", iRc2, XB_NO_ERROR ); + } else { + iRc2 = V4DbfX2->AppendRecord(); + if( iRc2 != XB_NO_ERROR ){ + iRc += TestMethod( iPo, "AppendRecord()", iRc2, XB_NO_ERROR ); + } else { + iRc2 = V4DbfX2->Commit(); + if( iRc2 != XB_NO_ERROR ){ + iRc += TestMethod( iPo, "Commit()", iRc2, XB_NO_ERROR ); + } + } + } + } + + iRc += TestMethod( iPo, "CheckTagIntegrity(7)", V4DbfX2->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + x.CloseAllTables(); delete V4DbfX1; + delete V4DbfX2; if( iPo > 0 || iRc < 0 ) fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); diff --git a/src/tests/xb_test_ndx.cpp b/src/tests/xb_test_ndx.cpp index b8b97f6..34496b6 100755 --- a/src/tests/xb_test_ndx.cpp +++ b/src/tests/xb_test_ndx.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -57,6 +57,7 @@ int main( int argCnt, char **av ) xbString sMsg; #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( iPo ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -67,11 +68,7 @@ int main( int argCnt, char **av ) #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); - - #ifdef XB_LOCKING_SUPPORT - x.DisableDefaultAutoLock(); - #endif + x.SetMultiUser( xbFalse ); InitTime(); @@ -386,11 +383,13 @@ int main( int argCnt, char **av ) //ix->GetTagName( 0, sTagName ); sMsg.Sprintf( "CheckTagIntegrity() - [%s]", ix->GetTagName(ix->GetCurTag()).Str()); iRc += TestMethod( iPo, sMsg, ix->CheckTagIntegrity( ix->GetCurTag(), 2 ), XB_NO_ERROR ); - ixl = ixl->next; } + ixl = ixl->next; } - iRc += TestMethod( iPo, "DeleteTable()", V3Dbf->DeleteTable(), XB_NO_ERROR ); +// iRc += TestMethod( iPo, "DeleteTable()", V3Dbf->DeleteTable(), XB_NO_ERROR ); + + x.CloseAllTables(); if( iPo > 0 || iRc < 0 ) fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); diff --git a/src/tests/xb_test_sql.cpp b/src/tests/xb_test_sql.cpp index 20c8514..99a4f0b 100755 --- a/src/tests/xb_test_sql.cpp +++ b/src/tests/xb_test_sql.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel +Copyright (c) 1997,2003,2014, 2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -44,9 +44,10 @@ int main( int argCnt, char **av ) po = 2; } - - xbSchema MySqlRecord[] = +/* + xbSchema MyAddressRecord[] = { + { "ADDRESS", XB_CHAR_FLD, 30, 0 }, { "CITY", XB_CHAR_FLD, 30, 0 }, { "STATE", XB_CHAR_FLD, 2, 0 }, { "ZIPCODE", XB_NUMERIC_FLD, 9, 0 }, @@ -56,9 +57,23 @@ int main( int argCnt, char **av ) { "",0,0,0 } }; + above structure below, depending on how table is created + + sSql = "CREATE TABLE Address.DBF ( ADDRESS CHAR(30), CITY CHAR(30), STATE CHAR(2), ZIPCODE NUMERIC(9,0), NOTES VARCHAR, LASTUPDATE DATE, ACTIVE LOGICAL )"; +*/ + + xbSchema MyZipRecord[] = + { + { "ZIPCODE", XB_NUMERIC_FLD, 9, 0 }, + { "CITY", XB_CHAR_FLD, 30, 0 }, + { "STATE", XB_CHAR_FLD, 2, 0 }, + { "",0,0,0 } + }; + xbXBase x; #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -69,9 +84,7 @@ int main( int argCnt, char **av ) #endif - x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); InitTime(); xbSql sql( &x ); @@ -81,36 +94,48 @@ int main( int argCnt, char **av ) xbDbf4 SqlDbf( &x ); // version 4 dbf file + xbDbf4 SqlDbfZ( &x ); // version 4 dbf file + - // clean up any things possibly needing cleaned up - xbString sDir; - SqlDbf.GetFileDirPart( sDir ); - xbString sDbfName; - xbString sDbtName; - xbString sMdxName; - sDbfName.Sprintf( "%sTestSQL.DBF", sDir.Str()); - sDbtName.Sprintf( "%sTestSQL.DBR", sDir.Str()); - sMdxName.Sprintf( "%sTestSQL.MDX", sDir.Str()); - SqlDbf.xbRemove( sDbfName ); - SqlDbf.xbRemove( sDbtName ); - SqlDbf.xbRemove( sMdxName ); - sDbfName.Sprintf( "%sTestSqlR.DBF", sDir.Str()); - sDbtName.Sprintf( "%sTestSqlR.DBT", sDir.Str()); - sMdxName.Sprintf( "%sTestSqlR.MDX", sDir.Str()); - SqlDbf.xbRemove( sDbfName ); - SqlDbf.xbRemove( sDbtName ); - SqlDbf.xbRemove( sMdxName ); - - - iRc2 = SqlDbf.CreateTable( "TestSQL.DBF", "TestSQL", MySqlRecord, XB_OVERLAY, XB_MULTI_USER ); + + + sSql = "DROP TABLE IF EXISTS AddressR.DBF"; + iRc2 = sql.ExecuteNonQuery( sSql ); + iRc += TestMethod( po, "DropTable()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + + + sSql = "DROP TABLE IF EXISTS Address.DBF"; + iRc2 = sql.ExecuteNonQuery( sSql ); + iRc += TestMethod( po, "DropTable()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + + + sSql = "CREATE TABLE Address.DBF ( ADDRESS CHAR(30), CITY CHAR(30), STATE CHAR(2), ZIPCODE NUMERIC(9,0), NOTES VARCHAR, LASTUPDATE DATE, ACTIVE LOGICAL )"; + + iRc2 = sql.ExecuteNonQuery( sSql ); + iRc += TestMethod( po, "CreateTable()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + +/* + non sql way to create a table + iRc2 = SqlDbf.CreateTable( "Address.DBF", "Address", MyAddressRecord, XB_OVERLAY, XB_MULTI_USER ); iRc += TestMethod( po, "CreateTable()", (xbInt32) iRc2, XB_NO_ERROR ); if( iRc2 ) x.DisplayError( iRc2 ); +*/ + +// return 0; #ifdef XB_MDX_SUPPORT - sSql = "CREATE INDEX tag1 ON TestSQL.DBF( CITY, STATE, DTOS( LASTUPDATE )) FILTER .NOT. DELETED()"; - // xbString sSql = "CREATE INDEX tag1 ON TestSQL.DBF( CITY, STATE )"; + sSql = "CREATE INDEX tag1 ON Address.DBF( CITY, STATE, DTOS( LASTUPDATE )) FILTER .NOT. DELETED()"; + // xbString sSql = "CREATE INDEX tag1 ON Address.DBF( CITY, STATE )"; iRc2 = sql.ExecuteNonQuery( sSql ); iRc += TestMethod( po, "SqL CreateIndex()", (xbInt32) iRc2, XB_NO_ERROR ); @@ -118,65 +143,107 @@ int main( int argCnt, char **av ) x.DisplayError( iRc2 ); #endif // XB_MDX_SUPPORT - sSql = "INSERT INTO TestSQL (CITY, STATE, ZIPCODE, NOTES, LASTUPDATE, ACTIVE ) VALUES ( 'San Diego', 'CA', 92007, 'San Diego is a cool place', '1989-02-09', 'Y')"; + sSql = "INSERT INTO Address (CITY, STATE, ZIPCODE, NOTES, LASTUPDATE, ACTIVE ) VALUES ( 'San Diego', 'CA', 92007, 'San Diego is a cool place', '1989-02-09', 'Y')"; iRc2 = sql.ExecuteNonQuery( sSql ); iRc += TestMethod( po, "SqlInsert()", (xbInt32) iRc2, XB_NO_ERROR ); if( iRc2 ) x.DisplayError( iRc2 ); - sSql = "INSERT INTO TestSQL (CITY, STATE, ZIPCODE, NOTES, LASTUPDATE, ACTIVE ) VALUES ( 'Dallas', 'TX', 76248, 'Dallas is hot in the summer', '1989-02-09', 'N')"; + sSql = "INSERT INTO Address (CITY, STATE, ZIPCODE, NOTES, LASTUPDATE, ACTIVE ) VALUES ( 'Dallas', 'TX', 76248, 'Dallas is hot in the summer', '1989-02-09', 'N')"; iRc2 = sql.ExecuteNonQuery( sSql ); iRc += TestMethod( po, "SqlInsert()", (xbInt32) iRc2, XB_NO_ERROR ); if( iRc2 ) x.DisplayError( iRc2 ); - sSql = "ALTER TABLE TestSQL.DBF RENAME TO TestSqlR.DBF"; + sSql = "ALTER TABLE Address.DBF RENAME TO AddressR.DBF"; iRc2 = sql.ExecuteNonQuery( sSql ); iRc += TestMethod( po, "SqlAlterTable()", (xbInt32) iRc2, XB_NO_ERROR ); if( iRc2 ) x.DisplayError( iRc2 ); - x.DisplayTableList(); - - - sSql = "DELETE FROM TestSqlR.DBF WHERE CITY='San Diego'"; + sSql = "DELETE FROM AddressR.DBF WHERE CITY='San Diego'"; iRc2 = sql.ExecuteNonQuery( sSql ); iRc += TestMethod( po, "SqlDelete()", (xbInt32) iRc2, XB_NO_ERROR ); if( iRc2 ) x.DisplayError( iRc2 ); - sSql = "UNDELETE FROM TestSqlR.DBF WHERE CITY='San Diego'"; + sSql = "UNDELETE FROM AddressR.DBF WHERE CITY='San Diego'"; iRc2 = sql.ExecuteNonQuery( sSql ); iRc += TestMethod( po, "SqlUndelete()", (xbInt32) iRc2, XB_NO_ERROR ); if( iRc2 ) x.DisplayError( iRc2 ); - sSql = "DELETE FROM TestSqlR.DBF"; + sSql = "DELETE FROM AddressR.DBF"; iRc2 = sql.ExecuteNonQuery( sSql ); iRc += TestMethod( po, "SqlDelete()", (xbInt32) iRc2, XB_NO_ERROR ); if( iRc2 ) x.DisplayError( iRc2 ); - sSql = "UNDELETE FROM TestSqlR.DBF"; + sSql = "UNDELETE FROM AddressR.DBF"; iRc2 = sql.ExecuteNonQuery( sSql ); iRc += TestMethod( po, "SqlDelete()", (xbInt32) iRc2, XB_NO_ERROR ); if( iRc2 ) x.DisplayError( iRc2 ); - sSql = "DELETE FROM TestSqlR.DBF WHERE BAD='EXPRESSION'"; + iRc2 = SqlDbfZ.CreateTable( "ZipCode.DBF", "", MyZipRecord, XB_OVERLAY, XB_MULTI_USER ); + iRc += TestMethod( po, "CreateTable()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + +// sSql = "INSERT INTO ZipCode.DBF ( ZIPCODE, CITY, STATE ) VALUES ( 75087, 'Rockwall', 'TX' )"; + + +// std::cout << "---------------------------------------------------------\n"; +// std::cout << sSql.Str() << "\n"; + + sSql = "INSERT INTO ZipCode ( CITY ) VALUES ( 'city' )"; + iRc2 = sql.ExecuteNonQuery( sSql ); + + + iRc += TestMethod( po, "SqlInsert()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + + +//**************** work in progress + +/* + sSql = "DELETE FROM AddressR.DBF WHERE BAD='EXPRESSION'"; iRc2 = sql.ExecuteNonQuery( sSql ); iRc += TestMethod( po, "SqlDelete()", (xbInt32) iRc2, XB_INVALID_FIELD_NAME ); +*/ // if( iRc2 ) // x.DisplayError( iRc2 ); -// sSql = "SELECT CITY, STATE ZIPCODE FROM TestSQL.DBF WHERE CITY IS NOT NULL"; -// iRc += TestMethod( po, "Select()", SqlDbf.Select( sSql ), XB_NO_ERROR ); - iRc += TestMethod( po, "Close()", SqlDbf.Close(), XB_NO_ERROR ); + iRc += TestMethod( po, "Close()", SqlDbfZ.Close(), XB_NO_ERROR ); + + +// return 0; + +// std::cout << "---------------------------------------------------------\n"; + + xbStmt sqlQry1( &x ); +// sSql = "SELECT CITY, STATE, ZIPCODE FROM Address.DBF T LEFT JOIN LJ.DBF LJ WHERE CITY IS NOT NULL ORDER BY 2 GROUP BY STATE HAVING ZIPCODE .NOT. NULL"; +// sSql = "SELECT CITY, STATE, ZIPCODE FROM AddressR.DBF T WHERE CITY IS NOT NULL ORDER BY 2 GROUP BY STATE HAVING ZIPCODE .NOT. NULL"; + +// sSql = "SELECT CITY, STATE, ZIPCODE FROM AddressR A LEFT JOIN ZipCode Z ON A.ZIPCODE = Z.ZIPCODE WHERE CITY IS NOT NULL ORDER BY 2 GROUP BY STATE HAVING ZIPCODE .NOT. NULL"; +// sSql = "SELECT M.ID, M.LEFTFK0, L0.CFLD FROM MAIN0 M LEFT JOIN LEFT0 L0 ON M.LEFTFK0 = L0.LEFTFK0 WHERE M.ID IS NOT NULL"; + iRc += TestMethod( po, "Select()", sqlQry1.ExecuteQuery( sSql ), XB_NO_ERROR ); + + sqlQry1.DumpStmtInternals(); + + // sqlQry1.Test(); + + + x.DisplayTableList(); + if( po > 0 || iRc < 0 ) fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); diff --git a/src/tests/xb_test_string.cpp b/src/tests/xb_test_string.cpp index 9d730db..2f01e51 100755 --- a/src/tests/xb_test_string.cpp +++ b/src/tests/xb_test_string.cpp @@ -2,7 +2,7 @@ XBase63 Software Library -Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -46,6 +46,7 @@ int main( int argCnt, char **av = NULL ) xbString sMsg; #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -55,7 +56,6 @@ int main( int argCnt, char **av = NULL ) #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); InitTime(); @@ -260,6 +260,13 @@ int main( int argCnt, char **av = NULL ) rc += TestMethod( po, "Pos(\"000\") ", (xbInt32) s1.Pos( "000" ), 0 ); rc += TestMethod( po, "Pos(\"DEF\") ", (xbInt32) s1.Pos( "DEF" ), 1 ); + s1 = "ABC.123.abc"; + rc += TestMethod( po, "Pos( '.', 4 )", (xbInt32) s1.Pos( '.', 4 ), 4 ); + rc += TestMethod( po, "Pos( '.', 5 )", (xbInt32) s1.Pos( '.', 5 ), 8 ); + rc += TestMethod( po, "Pos( '.', 9 )", (xbInt32) s1.Pos( '.', 9 ), 0 ); + + + s1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; rc += TestMethod( po, "Remove(3,5) ", s1.Remove( 3, 5 ), "ABHIJKLMNOPQRSTUVWXYZ", 21 ); diff --git a/src/tests/xb_test_tblmgr.cpp b/src/tests/xb_test_tblmgr.cpp index 451432c..d048594 100755 --- a/src/tests/xb_test_tblmgr.cpp +++ b/src/tests/xb_test_tblmgr.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -13,7 +13,7 @@ Email Contact: */ -// This program tests the class xbXBase +// This program tests the table manager functions. // usage: xb_test_tblmgr QUITE|NORMAL|VERBOSE @@ -25,33 +25,35 @@ using namespace xb; int main( int argCnt, char **av ) { - int rc = 0; - int po = 1; /* print option */ + int iRc = 0; + int iPo = 1; /* print option */ /* 0 - QUIET */ /* 1 - NORMAL */ /* 2 - VERBOSE */ if( argCnt > 1 ) { if( av[1][0] == 'Q' ) - po = 0; + iPo = 0; else if( av[1][0] == 'V' ) - po = 2; + iPo = 2; } xbXBase x; -#ifdef XB_LOGGING_SUPPORT + #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); - if( po ){ + if( iPo ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; } xbString sMsg; sMsg.Sprintf( "Program [%s] initializing...", av[0] ); x.WriteLogMessage( sMsg ); -#endif + #endif + InitTime(); - if( po == 2 ){ + if( iPo == 2 ){ std::cout << "DisplayError Test ==> "; x.DisplayError( 0 ); #ifdef WIN32 @@ -73,14 +75,14 @@ int main( int argCnt, char **av ) return -1; #endif - rc += TestMethod( po, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableC" ), 0 ); - rc += TestMethod( po, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableA" ), 0 ); - rc += TestMethod( po, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableB" ), 0 ); - rc += TestMethod( po, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableD" ), 0 ); + iRc += TestMethod( iPo, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableC" ), 0 ); + iRc += TestMethod( iPo, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableA" ), 0 ); + iRc += TestMethod( iPo, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableB" ), 0 ); + iRc += TestMethod( iPo, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableD" ), 0 ); // Next line should generate an exception - rc += TestMethod( po, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableC" ), XB_DUP_TABLE_OR_ALIAS ); + iRc += TestMethod( iPo, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableC" ), XB_DUP_TABLE_OR_ALIAS ); std::cout << "**** Next list should have one each of TestTableA, B, C, D sorted in alpha order ****" << std::endl; x.DisplayTableList(); @@ -90,7 +92,7 @@ int main( int argCnt, char **av ) std::cout << "[PASS] GetDbfPtr()" << std::endl; else{ std::cout << "[FAIL] GetDbfPtr()" << std::endl; - rc--; + iRc--; } @@ -98,70 +100,59 @@ std::cout << "cp0\n"; x.SetDataDirectory( "/ABCDEFG/" ); #ifdef WIN32 - rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG\\", 9 ); + iRc += TestMethod( iPo, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG\\", 9 ); #else - rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG/", 9 ); + iRc += TestMethod( iPo, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG/", 9 ); #endif std::cout << "cp1\n"; x.SetDataDirectory( "/ABCDEFG" ); #ifdef WIN32 - rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG", 8 ); + iRc += TestMethod( iPo, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG", 8 ); #else - rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG", 8 ); + iRc += TestMethod( iPo, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG", 8 ); #endif - std::cout << "cp2\n"; - - x.SetDataDirectory( "\\ABCDEFG\\"); #ifdef WIN32 - rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG\\", 9 ); + iRc += TestMethod( iPo, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG\\", 9 ); #else - rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG/", 9 ); + iRc += TestMethod( iPo, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG/", 9 ); #endif - std::cout << "cp3\n"; - - x.SetDataDirectory( "\\ABCDEFG" ); #ifdef WIN32 - rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG", 8 ); + iRc += TestMethod( iPo, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG", 8 ); #else - rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG", 8 ); + iRc += TestMethod( iPo, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG", 8 ); #endif - - std::cout << "cp4\n"; - - x.SetDataDirectory( "ABCDEFG" ); - rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "ABCDEFG", 7 ); - + iRc += TestMethod( iPo, "Set/GetDataDirectory()", x.GetDataDirectory(), "ABCDEFG", 7 ); - rc += TestMethod( po, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableB" ), 0 ); - rc += TestMethod( po, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableB" ), XB_NOT_FOUND ); + iRc += TestMethod( iPo, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableB" ), 0 ); + iRc += TestMethod( iPo, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableB" ), XB_NOT_FOUND ); std::cout << "**** Next list should not have TestTableB in it ****" << std::endl; x.DisplayTableList(); - rc += TestMethod( po, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableA" ), 0 ); - rc += TestMethod( po, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableC" ), 0 ); - rc += TestMethod( po, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableD" ), 0 ); + iRc += TestMethod( iPo, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableA" ), 0 ); + iRc += TestMethod( iPo, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableC" ), 0 ); + iRc += TestMethod( iPo, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableD" ), 0 ); delete d1; - if( po > 0 || rc < 0 ) - fprintf( stdout, "Total Errors = %d\n", rc * -1 ); + if( iPo > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); #ifdef XB_LOGGING_SUPPORT - sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], rc * -1 ); + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); x.WriteLogMessage( sMsg ); #endif - return rc; + return iRc; } diff --git a/src/tests/xb_test_uda.cpp b/src/tests/xb_test_uda.cpp index dec41fa..18693b5 100755 --- a/src/tests/xb_test_uda.cpp +++ b/src/tests/xb_test_uda.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -45,7 +45,8 @@ int main( int argCnt, char **av ) xbXBase x; -#ifdef XB_LOGGING_SUPPORT + #ifdef XB_LOGGING_SUPPORT + x.SetLogDirectory( PROJECT_LOG_DIR ); x.EnableMsgLogging(); if( po ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; @@ -53,11 +54,9 @@ int main( int argCnt, char **av ) xbString sMsg; sMsg.Sprintf( "Program [%s] initializing...", av[0] ); x.WriteLogMessage( sMsg ); -#endif - + #endif x.SetDataDirectory( PROJECT_DATA_DIR ); - x.EnableMsgLogging(); xbUda uda; iRc += TestMethod( po, "GetTokencCnt()", uda.GetTokenCnt(), 0 ); diff --git a/src/tests/xb_test_xbase.cpp b/src/tests/xb_test_xbase.cpp index 9d523c5..4751c25 100755 --- a/src/tests/xb_test_xbase.cpp +++ b/src/tests/xb_test_xbase.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -27,26 +27,34 @@ using namespace xb; int main( int argCnt, char **av ) { int iRc = 0; - int po = 1; /* print option */ + int iPo = 1; /* print option */ /* 0 - QUIET */ /* 1 - NORMAL */ /* 2 - VERBOSE */ if( argCnt > 1 ) { if( av[1][0] == 'Q' ) - po = 0; + iPo = 0; else if( av[1][0] == 'V' ) - po = 2; + iPo = 2; } xbXBase x; xbString sMsg; #ifdef XB_LOGGING_SUPPORT + + + xbString sLogDir = PROJECT_LOG_DIR; +// x.SetLogDirectory( sLogDir ); + x.SetLogDirectory( PROJECT_LOG_DIR ); + + x.EnableMsgLogging(); - if( po ){ + if( iPo ){ std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; } + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); x.WriteLogMessage( sMsg ); #endif @@ -54,8 +62,8 @@ int main( int argCnt, char **av ) x.SetDefaultDateFormat( "YY-MM-DD" ); - iRc += TestMethod( po, "SetDefaultDateFormat", x.GetDefaultDateFormat(), "YY-MM-DD", 8 ); - if( po == 2 ){ + iRc += TestMethod( iPo, "SetDefaultDateFormat", x.GetDefaultDateFormat(), "YY-MM-DD", 8 ); + if( iPo == 2 ){ if( x.GetEndianType() == 'L' ) std::cout << "Little Endian Architecture" << std::endl; else if( x.GetEndianType() == 'B' ) @@ -64,38 +72,32 @@ int main( int argCnt, char **av ) std::cout << "Undefine Endian Architecture" << std::endl; } - iRc += TestMethod( po, "GetErrorMessage", x.GetErrorMessage( XB_DBF_FILE_NOT_OPEN ), "DBF File Not Open", 17 ); + iRc += TestMethod( iPo, "GetErrorMessage", x.GetErrorMessage( XB_DBF_FILE_NOT_OPEN ), "DBF File Not Open", 17 ); #ifdef XB_LOGGING_SUPPORT - xbString sLogDir = PROJECT_LOG_DIR; - iRc += TestMethod( po, "GetDefaultLogDirectory()", x.GetDefaultLogDirectory(), sLogDir, sLogDir.Len()); - + iRc += TestMethod( iPo, "GetLogDirectory()", x.GetLogDirectory(), sLogDir, sLogDir.Len()); xbString sLogName = CMAKE_SYSTEM_NAME; sLogName += "_"; sLogName += XB_PLATFORM; sLogName += ".xbLog.txt"; - iRc += TestMethod( po, "GetDefaultLogFileName()", x.GetDefaultLogFileName(), sLogName, sLogName.Len()); - - x.WriteLogMessage( "test" ); + iRc += TestMethod( iPo, "GetLogFileName()", x.GetLogFileName(), sLogName, sLogName.Len()); + x.WriteLogMessage( "Program xb_test_xbase - test logfile message" ); #endif x.xbSleep( 250 ); - - - if( po == 2 ){ + if( iPo == 2 ){ std::cout << "DisplayError Test ==> "; x.DisplayError( 0 ); } - - if( po > 0 || iRc < 0 ) + if( iPo > 0 || iRc < 0 ) fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); -#ifdef XB_LOGGING_SUPPORT + #ifdef XB_LOGGING_SUPPORT sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); x.WriteLogMessage( sMsg ); -#endif + #endif return iRc; } diff --git a/src/utils/xb_cfg_check.cpp b/src/utils/xb_cfg_check.cpp index 25ca46c..5489c51 100755 --- a/src/utils/xb_cfg_check.cpp +++ b/src/utils/xb_cfg_check.cpp @@ -1,3 +1,19 @@ +/* xb_cfg_check.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2019,2023 Gary A Kunkel + +The xb64 software library is covered under +the terms of the GPL Version 3, 2007 license. + +Email Contact: + + xb64-devel@lists.sourceforge.net + xb64-users@lists.sourceforge.net + +*/ + #include #include @@ -23,7 +39,7 @@ int main() fprintf( stdout, "CMAKE C FLAGS = [%s]\n", CMAKE_C_FLAGS ); fprintf( stdout, "CMAKE C FLAGS DEBUG = [%s]\n", CMAKE_C_FLAGS_DEBUG ); fprintf( stdout, "CMAKE C FLAGS RELEASE = [%s]\n", CMAKE_C_FLAGS_RELEASE ); - + #ifdef XB_PLATFORM_32 fprintf( stdout, "XB_PLATFORM_32 = [TRUE]\n" ); @@ -124,13 +140,13 @@ int main() fprintf( stdout, "XB_INDEX_SUPPORT = [OFF]\n" ); #endif - #ifdef XB_INDEX_SUPPORT + #ifdef XB_NDX_SUPPORT fprintf( stdout, "XB_NDX_SUPPORT = [ON]\n" ); #else fprintf( stdout, "XB_NDX_SUPPORT = [OFF]\n" ); #endif - #ifdef XB_INDEX_SUPPORT + #ifdef XB_MDX_SUPPORT fprintf( stdout, "XB_MDX_SUPPORT = [ON]\n" ); #else fprintf( stdout, "XB_MDX_SUPPORT = [OFF]\n" ); @@ -142,6 +158,24 @@ int main() fprintf( stdout, "XB_SQL_SUPPORT = [OFF]\n" ); #endif + #ifdef XB_INF_SUPPORT + fprintf( stdout, "XB_INF_SUPPORT = [ON]\n" ); + #else + fprintf( stdout, "XB_INF_SUPPORT = [OFF]\n" ); + #endif + + #ifdef XB_FILTER_SUPPORT + fprintf( stdout, "XB_FILTER_SUPPORT = [ON]\n" ); + #else + fprintf( stdout, "XB_FILTER_SUPPORT = [OFF]\n" ); + #endif + + #ifdef XB_BLOCKREAD_SUPPORT + fprintf( stdout, "XB_BLOCKREAD_SUPPORT = [ON]\n" ); + #else + fprintf( stdout, "XB_BLOCKREAD_SUPPORT = [OFF]\n" ); + #endif + fprintf( stdout, "\nDirectories:\n" ); fprintf( stdout, "HOME_DIRECTORY = [%s]\n", CMAKE_HOME_DIRECTORY ); @@ -159,32 +193,32 @@ int main() fprintf( stdout, "Field sizes:\n" ); fprintf( stdout, "SIZEOF_VOID_P = [%s]\n", CMAKE_SIZEOF_VOID_P ); - fprintf( stdout, "sizeof(char *) = [%ld]\n", sizeof( char *)); - fprintf( stdout, "sizeof(int) = [%ld]\n", sizeof( int )); - fprintf( stdout, "sizeof(long) = [%ld]\n", sizeof( long )); - fprintf( stdout, "sizeof(char) = [%ld]\n", sizeof( char )); + fprintf( stdout, "sizeof(char *) = [%zd]\n", sizeof( char *)); + fprintf( stdout, "sizeof(int) = [%zd]\n", sizeof( int )); + fprintf( stdout, "sizeof(long) = [%zd]\n", sizeof( long )); + fprintf( stdout, "sizeof(char) = [%zd]\n", sizeof( char )); #ifdef HAVE_WCHAR_H - fprintf( stdout, "sizeof(wchar_t) = [%ld]\n", sizeof( wchar_t )); + fprintf( stdout, "sizeof(wchar_t) = [%zd]\n", sizeof( wchar_t )); #endif #ifdef HAVE_WINDOWS_H - fprintf( stdout, "sizeof(DWORD) = [%ld]\n", sizeof( DWORD )); - #endif - - fprintf( stdout, "sizeof(double) = [%ld]\n", sizeof( double )); - fprintf( stdout, "sizeof(float) = [%ld]\n", sizeof( float )); - fprintf( stdout, "sizeof(size_t) = [%ld]\n", sizeof( size_t )); - fprintf( stdout, "sizeof(off_t) = [%ld]\n\n", sizeof( off_t )); - - fprintf( stdout, "sizeof(xbBool) = [%ld]\n", sizeof( xbBool )); - fprintf( stdout, "sizeof(xbInt16) = [%ld]\n", sizeof( xbInt16 )); - fprintf( stdout, "sizeof(xbUInt16) = [%ld]\n", sizeof( xbUInt16 )); - fprintf( stdout, "sizeof(xbInt32) = [%ld]\n", sizeof( xbInt32 )); - fprintf( stdout, "sizeof(xbUInt32) = [%ld]\n", sizeof( xbUInt32 )); - fprintf( stdout, "sizeof(xbInt64) = [%ld]\n", sizeof( xbInt64 )); - fprintf( stdout, "sizeof(xbUInt64) = [%ld]\n", sizeof( xbUInt64 )); - fprintf( stdout, "sizeof(xbFloat) = [%lu]\n", sizeof( xbFloat )); - fprintf( stdout, "sizeof(xbDouble) = [%lu]\n", sizeof( xbDouble )); + fprintf( stdout, "sizeof(DWORD) = [%zd]\n", sizeof( DWORD )); + #endif + + fprintf( stdout, "sizeof(double) = [%zd]\n", sizeof( double )); + fprintf( stdout, "sizeof(float) = [%zd]\n", sizeof( float )); + fprintf( stdout, "sizeof(size_t) = [%zd]\n", sizeof( size_t )); + fprintf( stdout, "sizeof(off_t) = [%zd]\n\n", sizeof( off_t )); + + fprintf( stdout, "sizeof(xbBool) = [%zd]\n", sizeof( xbBool )); + fprintf( stdout, "sizeof(xbInt16) = [%zd]\n", sizeof( xbInt16 )); + fprintf( stdout, "sizeof(xbUInt16) = [%zd]\n", sizeof( xbUInt16 )); + fprintf( stdout, "sizeof(xbInt32) = [%zd]\n", sizeof( xbInt32 )); + fprintf( stdout, "sizeof(xbUInt32) = [%zd]\n", sizeof( xbUInt32 )); + fprintf( stdout, "sizeof(xbInt64) = [%zd]\n", sizeof( xbInt64 )); + fprintf( stdout, "sizeof(xbUInt64) = [%zd]\n", sizeof( xbUInt64 )); + fprintf( stdout, "sizeof(xbFloat) = [%zu]\n", sizeof( xbFloat )); + fprintf( stdout, "sizeof(xbDouble) = [%zu]\n", sizeof( xbDouble )); fprintf( stdout, "\nHeader files:\n" ); diff --git a/src/utils/xb_copydbf.cpp b/src/utils/xb_copydbf.cpp index 1f88eb9..2466b1b 100755 --- a/src/utils/xb_copydbf.cpp +++ b/src/utils/xb_copydbf.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2019 Gary A Kunkel +Copyright (c) 1997,2003,2014,2019,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -17,42 +17,80 @@ Email Contact: #include using namespace xb; -int main(int ac,char** av) + +void PrintHelp(); +void PrintHelp(){ + std::cout << "Usage: xb_copydbf [-h] [-?] [--help] [-v] [--version] -s source.DBF -t target.DBF" << std::endl << std::endl; + std::cout << "This program copies the structure of a table defined in source.DBF to target.DBF. Data and indices are not included."; + std::cout << std::endl << std::endl; +} +void PrintVersion(); +void PrintVersion(){ + std::cout << "Xbase64 Version: " << xbase_VERSION_MAJOR << "." << xbase_VERSION_MINOR << "." << xbase_VERSION_PATCH << std::endl; +} + + +int main(int argc, char *argv[]) { - if (3 != ac) { - std::cout << - "\nUsage: xb_copydbf filename1 filename2\n" - "This program copies the structure of one dbf file to another\n"; + + xbXBase x; + xbInt16 iRc; + xbDbf *dSrc = NULL; + xbDbf *dTrg = NULL; + + xbString sParm; + xbString sSrcDbf; + xbString sTrgDbf; + + if (argc < 2 || x.GetCmdLineOpt( argc, argv, "-h", sParm ) || + x.GetCmdLineOpt( argc, argv, "-?", sParm ) || + x.GetCmdLineOpt( argc, argv, "--help", sParm )){ + PrintHelp(); + return 1; + } + + if ( x.GetCmdLineOpt( argc, argv, "-v", sParm ) || + x.GetCmdLineOpt( argc, argv, "--version", sParm )){ + PrintVersion(); return 1; } - char* sFileName = av[1]; - char* tFileName = av[2]; + if( !x.GetCmdLineOpt( argc, argv, "-s", sSrcDbf ) || sSrcDbf == "" ){ + PrintHelp(); + return 1; + } - xbXBase x; - xbInt16 iRc; - xbDbf *MyFile = NULL; - xbDbf *MyNewFile = NULL; + if( !x.GetCmdLineOpt( argc, argv, "-t", sTrgDbf ) || sTrgDbf == "" ){ + PrintHelp(); + return 1; + } #ifdef XB_LOGGING_SUPPORT x.EnableMsgLogging(); xbString sMsg; - sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + sMsg.Sprintf( "Program [%s] initializing...", argv[0] ); x.WriteLogMessage( sMsg ); #endif - if(( iRc = x.OpenHighestVersion( sFileName, "", &MyFile )) != XB_NO_ERROR ){ - std::cout << "Could not open file iRc = " << iRc << " file = " << sFileName << std::endl; + if(( iRc = x.OpenHighestVersion( sSrcDbf, "", &dSrc )) != XB_NO_ERROR ){ + std::cout << "Could not open file iRc = " << iRc << " file = " << sSrcDbf.Str() << std::endl; x.DisplayError( iRc ); - return 0; + return 1; } - if(( iRc = MyFile->CopyDbfStructure( MyNewFile, tFileName, tFileName, XB_DONTOVERLAY, XB_SINGLE_USER )) != XB_NO_ERROR ){ - std::cout << "Could not copy file " << tFileName << " Error = " << iRc << "\n"; - return 3; + #ifdef XB_DBF4_SUPPORT + dTrg = new xbDbf4( &x ); + #else + dTrg = new xbDbf3( &x ); + #endif + + if(( iRc = dSrc->CopyDbfStructure( dTrg, sTrgDbf, sTrgDbf, XB_DONTOVERLAY, XB_SINGLE_USER )) != XB_NO_ERROR ){ + std::cout << "Could not copy file " << sTrgDbf.Str() << " Error = " << iRc << "\n"; + x.DisplayError( iRc ); + return 1; } - MyFile->Close(); + x.CloseAllTables(); return 0; } diff --git a/src/utils/xb_dbfutil.cpp b/src/utils/xb_dbfutil.cpp index 9c04fe3..e50495e 100755 --- a/src/utils/xb_dbfutil.cpp +++ b/src/utils/xb_dbfutil.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2021 Gary A Kunkel +Copyright (c) 1997,2003,2014,2021,2022,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -29,11 +29,13 @@ using namespace xb; ///@cond DOXYOFF class xbUtil{ public: - xbUtil(); + xbUtil( xbXBase *x ); ~xbUtil(); xbDbf *GetTablePtr( const char * cTitle ); void DisplayActiveTable() const; + void Help(); + // menus xbInt16 GetOption(); xbInt32 GetLong(); @@ -215,8 +217,8 @@ class xbUtil{ private: - xbXBase x; - xbDbf * dActiveTable; + xbXBase *x; + xbDbf *dActiveTable; #ifdef XB_EXPRESSION_SUPPORT xbExp *exp; @@ -233,18 +235,19 @@ class xbUtil{ }; /*************************************************************************************/ -xbUtil::xbUtil() +xbUtil::xbUtil( xbXBase *x ) { + this->x = x; dActiveTable = NULL; - x.EnableMsgLogging(); - x.SetLogSize( 10000000L ); + x->EnableMsgLogging(); + x->SetLogSize( 10000000L ); #ifdef XB_EXPRESSION_SUPPORT exp = NULL; #endif #ifdef XB_SQL_SUPPORT - sql = new xbSql( &x ); + sql = new xbSql( x ); #endif // XB_SQL_SUPPORT #ifdef XB_FILTER_SUPPORT @@ -256,7 +259,7 @@ xbUtil::xbUtil() /*************************************************************************************/ xbUtil::~xbUtil(){ - x.CloseAllTables(); + x->CloseAllTables(); if( dActiveTable ) delete dActiveTable; @@ -272,6 +275,17 @@ xbUtil::~xbUtil(){ #endif // XB_FILTER_SUPPORT } + +/*************************************************************************************/ +void xbUtil::Help(){ + std::cout << "Program xb_dbfutil provides a menu driven application for accessing" << std::endl; + std::cout << "the xbase64 library functions." << std::endl << std::endl; + std::cout << "Menu choices can be selected directly with out accessing the given menus" << std::endl; + std::cout << "by entering a '=' followed by the menu choices. For example, entering '=3.4'" << std::endl; + std::cout << "would be the same as going to menu #3 and entering a 4, which is the sequence" << std::endl; + std::cout << "for opening a file." << std::endl; +} + /*************************************************************************************/ #ifdef XB_NDXINF_SUPPORT @@ -294,7 +308,7 @@ void xbUtil::AddInfFileData() std::cout << "Enter NDX index file name (FILENAME.NDX)" << std::endl; std::cin.getline( cBuf, 128 ); xbInt16 iRc = dActiveTable->AssociateIndex( "NDX", cBuf, 0 ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::DeleteInfFileData() @@ -303,7 +317,7 @@ void xbUtil::DeleteInfFileData() std::cout << "Enter NDX index file name (FILENAME.NDX)" << std::endl; std::cin.getline( cBuf, 128 ); xbInt16 iRc = dActiveTable->AssociateIndex( "NDX", cBuf, 1 ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::InfFileHelp() @@ -329,7 +343,7 @@ void xbUtil::LockIndices(){ return; } xbInt16 iRc = dActiveTable->LockIndices( XB_LOCK ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::UnlockIndices(){ @@ -343,7 +357,7 @@ void xbUtil::UnlockIndices(){ return; } xbInt16 iRc = dActiveTable->LockIndices( XB_UNLOCK ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } #endif // XB_LOCKING_SUPPORT @@ -381,11 +395,11 @@ void xbUtil::ParseExpression( xbInt16 iOption ){ exp = NULL; } - exp = new xbExp( &x, dActiveTable ); + exp = new xbExp( x, dActiveTable ); iRc = exp->ParseExpression( sExpression ); if( iOption == 0 ) - x.DisplayError( iRc ); + x->DisplayError( iRc ); } /*************************************************************************************/ @@ -404,7 +418,7 @@ void xbUtil::ProcessParsedExpression( xbInt16 iOption ){ xbInt16 iRc = exp->ProcessExpression(); if( iRc != XB_NO_ERROR ){ - x.DisplayError( iRc ); + x->DisplayError( iRc ); return; } @@ -496,7 +510,7 @@ void xbUtil::IsLeapYear(){ #ifdef XB_SQL_SUPPORT void xbUtil::ExecSqlNonQuery(){ - xbSql sql( &x ); + xbSql sql( x ); std::cout << "ExecSqlNonQuery\n"; char sSql[2048]; @@ -504,7 +518,7 @@ void xbUtil::ExecSqlNonQuery(){ std::cin.getline( sSql, 2048 ); xbInt16 iRc = sql.ExecuteNonQuery( sSql ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::ExecSqlQuery(){ @@ -681,7 +695,7 @@ void xbUtil::LockDbf(){ xbInt16 iRc; std::cout << std::endl << "Lock Table" << std::endl; iRc = dActiveTable->LockTable( XB_LOCK ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::LockAppend(){ @@ -696,7 +710,7 @@ void xbUtil::LockAppend(){ xbInt16 iRc; std::cout << std::endl << "Lock Append" << std::endl; iRc = dActiveTable->LockAppend( XB_LOCK ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::UnlockAppend(){ @@ -711,7 +725,7 @@ void xbUtil::UnlockAppend(){ xbInt16 iRc; std::cout << std::endl << "Unlock Append" << std::endl; iRc = dActiveTable->LockAppend( XB_UNLOCK ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } #ifdef XB_MEMO_SUPPORT void xbUtil::LockMemo(){ @@ -726,7 +740,7 @@ void xbUtil::LockMemo(){ xbInt16 iRc; std::cout << std::endl << "Lock Memo" << std::endl; iRc = dActiveTable->LockMemo( XB_LOCK ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::UnlockMemo(){ @@ -741,7 +755,7 @@ void xbUtil::UnlockMemo(){ xbInt16 iRc; std::cout << std::endl << "Unlock Memo" << std::endl; iRc = dActiveTable->LockMemo( XB_UNLOCK ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } #endif @@ -760,8 +774,10 @@ void xbUtil::LockRecord(){ char cBuf[15]; std::cin.getline( cBuf, 15 ); - iRc = dActiveTable->LockRecord( XB_LOCK, atol( cBuf )); - x.DisplayError( iRc ); + //iRc = dActiveTable->LockRecord( XB_LOCK, atol( cBuf )); + iRc = dActiveTable->LockRecord( XB_LOCK, strtoul( cBuf, NULL, 0 )); + + x->DisplayError( iRc ); } void xbUtil::UnlockRecord(){ @@ -779,8 +795,9 @@ void xbUtil::UnlockRecord(){ char cBuf[15]; std::cin.getline( cBuf, 15 ); - iRc = dActiveTable->LockRecord( XB_UNLOCK, atol( cBuf )); - x.DisplayError( iRc ); + //iRc = dActiveTable->LockRecord( XB_UNLOCK, atol( cBuf )); + iRc = dActiveTable->LockRecord( XB_UNLOCK, strtoul( cBuf, NULL, 0 )); + x->DisplayError( iRc ); } void xbUtil::UnlockDbf(){ @@ -796,7 +813,7 @@ void xbUtil::UnlockDbf(){ xbInt16 iRc; std::cout << std::endl << "Unlock Table" << std::endl; iRc = dActiveTable->LockTable( XB_UNLOCK ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::UnlockHeader(){ @@ -812,7 +829,7 @@ void xbUtil::UnlockHeader(){ xbInt16 iRc; std::cout << std::endl << "Unlock Table Header" << std::endl; iRc = dActiveTable->LockHeader( XB_UNLOCK ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::LockHeader(){ @@ -826,7 +843,7 @@ void xbUtil::LockHeader(){ xbInt16 iRc; std::cout << std::endl << "Lock Table Header" << std::endl; iRc = dActiveTable->LockHeader( XB_LOCK ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } #ifdef XB_DEBUG_SUPPORT @@ -860,7 +877,7 @@ void xbUtil::xbFileLock(){ s1 = cBufLen; s1.CvtLongLong( llLen ); xbInt16 iRc = dActiveTable->xbLock( XB_LOCK, llSpos, (size_t) llLen ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::xbFileUnlock(){ @@ -884,7 +901,7 @@ void xbUtil::xbFileUnlock(){ } xbInt16 iRc; iRc = dActiveTable->xbLock( XB_UNLOCK, atol( cBufOffset ), (size_t) atol( cBufLen )); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } #endif @@ -968,7 +985,7 @@ void xbUtil::UpdateFieldData(){ std::cin.getline( cFldData, 256 ); if(( rc = dActiveTable->PutField( cFldName, cFldData )) != XB_NO_ERROR ){ - x.DisplayError( rc ); + x->DisplayError( rc ); return; } std::cout << "Success" << std::endl; @@ -999,9 +1016,10 @@ void xbUtil::ShowMemoFieldData(){ std::cout << "Record number not entered" << std::endl; return; } - ulRecNo = atol( cBuf ); + //ulRecNo = atol( cBuf ); + ulRecNo = strtoul( cBuf, NULL, 0 ); if(( rc = dActiveTable->GetRecord( ulRecNo )) != XB_NO_ERROR ){ - x.DisplayError( rc ); + x->DisplayError( rc ); return; } } @@ -1009,12 +1027,12 @@ void xbUtil::ShowMemoFieldData(){ std::cin.getline( cFldName, 40 ); if(( rc = dActiveTable->GetMemoField( cFldName, sMemoData )) != XB_NO_ERROR ){ std::cout << "rc = " << rc << std::endl; - x.DisplayError( rc ); + x->DisplayError( rc ); return; } if(( rc = dActiveTable->GetMemoFieldLen( cFldName, ulFldLen )) != XB_NO_ERROR ){ std::cout << "rc = " << rc << std::endl; - x.DisplayError( rc ); + x->DisplayError( rc ); return; } std::cout << sMemoData.Str() << std::endl; @@ -1047,9 +1065,10 @@ void xbUtil::UpdateMemoFieldData(){ std::cout << "Record number not entered" << std::endl; return; } - ulRecNo = atol( cBuf ); + //ulRecNo = atol( cBuf ); + ulRecNo = strtoul( cBuf, NULL, 0 ); if(( rc = dActiveTable->GetRecord( ulRecNo )) != XB_NO_ERROR ){ - x.DisplayError( rc ); + x->DisplayError( rc ); return; } } @@ -1059,13 +1078,13 @@ void xbUtil::UpdateMemoFieldData(){ std::cin.getline( cMemoData, 2048 ); if(( rc = dActiveTable->UpdateMemoField( cFldName, cMemoData )) != XB_NO_ERROR ){ std::cout << "rc = " << rc << std::endl; - x.DisplayError( rc ); + x->DisplayError( rc ); return; } if(( rc = dActiveTable->PutRecord( dActiveTable->GetCurRecNo())) != XB_NO_ERROR ){ std::cout << "rc = " << rc << std::endl; - x.DisplayError( rc ); + x->DisplayError( rc ); return; } } @@ -1098,9 +1117,10 @@ void xbUtil::DeleteMemoField(){ std::cout << "Record number not entered" << std::endl; return; } - ulRecNo = atol( cBuf ); + //ulRecNo = atol( cBuf ); + ulRecNo = strtoul( cBuf, NULL, 0 ); if(( rc = dActiveTable->GetRecord( ulRecNo )) != XB_NO_ERROR ){ - x.DisplayError( rc ); + x->DisplayError( rc ); return; } } @@ -1108,12 +1128,12 @@ void xbUtil::DeleteMemoField(){ std::cin.getline( cFldName, 40 ); if(( rc = dActiveTable->UpdateMemoField( cFldName, "" )) != XB_NO_ERROR ){ std::cout << "rc = " << rc << std::endl; - x.DisplayError( rc ); + x->DisplayError( rc ); return; } if(( rc = dActiveTable->PutRecord( dActiveTable->GetCurRecNo())) != XB_NO_ERROR ){ std::cout << "rc = " << rc << std::endl; - x.DisplayError( rc ); + x->DisplayError( rc ); return; } } @@ -1123,13 +1143,13 @@ void xbUtil::SelectActiveTable(){ char cBuf[15]; xbInt16 iLineNo; - if( x.GetOpenTableCount() == 0 ){ + if( x->GetOpenTableCount() == 0 ){ std::cout << "No open tables" << std::endl; std::cout << "Use menu option =3.4 to open a table" << std::endl; return; } - x.DisplayTableList(); + x->DisplayTableList(); std::cout << std::endl << "Enter line number:" << std::endl; std::cin.getline( cBuf, 15 ); if( strlen( cBuf ) == 0 ){ @@ -1137,7 +1157,7 @@ void xbUtil::SelectActiveTable(){ return; } iLineNo = atoi( cBuf ); - dActiveTable = x.GetDbfPtr( iLineNo ); + dActiveTable = x->GetDbfPtr( iLineNo ); } /*************************************************************************************/ @@ -1157,7 +1177,7 @@ void xbUtil::CommitRecord(){ if(( rc = dActiveTable->Commit()) == XB_NO_ERROR ) std::cout << "Success" << std::endl; else - x.DisplayError( rc ); + x->DisplayError( rc ); } /*************************************************************************************/ void xbUtil::AbortRecord(){ @@ -1176,14 +1196,14 @@ void xbUtil::AbortRecord(){ if(( rc = dActiveTable->Abort()) == XB_NO_ERROR ) std::cout << "Success" << std::endl; else - x.DisplayError( rc ); + x->DisplayError( rc ); } /*************************************************************************************/ void xbUtil::DumpRecord(){ char cBuf[15]; xbInt16 rc; - xbUInt32 lRecNo; + xbUInt32 ulRecNo; if( !dActiveTable ) dActiveTable = GetTablePtr( " - select table" ); if( !dActiveTable ){ @@ -1199,9 +1219,10 @@ void xbUtil::DumpRecord(){ std::cout << "Record number not entered" << std::endl; return; } - lRecNo = atol( cBuf ); - if(( rc = dActiveTable->GetRecord( lRecNo )) != XB_NO_ERROR ){ - x.DisplayError( rc ); + //lRecNo = atol( cBuf ); + ulRecNo = strtoul( cBuf, NULL, 0 ); + if(( rc = dActiveTable->GetRecord( ulRecNo )) != XB_NO_ERROR ){ + x->DisplayError( rc ); return; } } @@ -1209,7 +1230,7 @@ void xbUtil::DumpRecord(){ if(( rc = dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2 )) == XB_NO_ERROR ) std::cout << "Success" << std::endl; else - x.DisplayError( rc ); + x->DisplayError( rc ); } /*************************************************************************************/ void xbUtil::GetFirstRecord(){ @@ -1227,7 +1248,7 @@ void xbUtil::GetFirstRecord(){ if(( iRc = dActiveTable->GetFirstRecord()) == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } /*************************************************************************************/ void xbUtil::GetNextRecord(){ @@ -1242,7 +1263,7 @@ void xbUtil::GetNextRecord(){ if(( iRc = dActiveTable->GetNextRecord()) == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } /*************************************************************************************/ void xbUtil::GetPrevRecord(){ @@ -1257,7 +1278,7 @@ void xbUtil::GetPrevRecord(){ if(( iRc = dActiveTable->GetPrevRecord()) == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } /*************************************************************************************/ void xbUtil::GetLastRecord(){ @@ -1274,15 +1295,15 @@ void xbUtil::GetLastRecord(){ if(( iRc = dActiveTable->GetLastRecord()) == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(),2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } /*************************************************************************************/ void xbUtil::UndeleteRecord(){ - char cBuf[15]; - xbInt16 rc; - xbUInt32 lRecNo; + char cBuf[15]; + xbInt16 rc; + xbUInt32 ulRecNo; if( !dActiveTable ) dActiveTable = GetTablePtr( " - select table" ); @@ -1292,7 +1313,6 @@ void xbUtil::UndeleteRecord(){ return; } DisplayActiveTable(); - if( dActiveTable->GetCurRecNo() == 0 ){ std::cout << "Enter Record number" << std::endl; std::cin.getline( cBuf, 15 ); @@ -1300,29 +1320,30 @@ void xbUtil::UndeleteRecord(){ std::cout << "Record number not entered" << std::endl; return; } - lRecNo = atol( cBuf ); - if(( rc = dActiveTable->GetRecord( lRecNo )) != XB_NO_ERROR ){ - x.DisplayError( rc ); + //lRecNo = atol( cBuf ); + ulRecNo = strtoul( cBuf, NULL, 0 ); + if(( rc = dActiveTable->GetRecord( ulRecNo )) != XB_NO_ERROR ){ + x->DisplayError( rc ); return; } } - if(( dActiveTable->RecordDeleted()) == xbFalse ) std::cout << "Record is not flagged for deletion" << std::endl; else{ if(( rc = dActiveTable->UndeleteRecord()) == XB_NO_ERROR ) std::cout << "Success" << std::endl; else - x.DisplayError( rc ); + x->DisplayError( rc ); } } /*************************************************************************************/ void xbUtil::DeleteRecord(){ - char cBuf[15]; - xbInt16 rc; - xbUInt32 lRecNo; + char cBuf[15]; + xbInt16 rc; + xbUInt32 ulRecNo; + if( !dActiveTable ) dActiveTable = GetTablePtr( " - select table" ); if( !dActiveTable ){ @@ -1337,9 +1358,11 @@ void xbUtil::DeleteRecord(){ std::cout << "Record number not entered" << std::endl; return; } - lRecNo = atol( cBuf ); - if(( rc = dActiveTable->GetRecord( lRecNo )) != XB_NO_ERROR ){ - x.DisplayError( rc ); + //ulRecNo = atol( cBuf ); + + ulRecNo = strtoul( cBuf, NULL, 0 ); + if(( rc = dActiveTable->GetRecord( ulRecNo )) != XB_NO_ERROR ){ + x->DisplayError( rc ); return; } } @@ -1350,16 +1373,16 @@ void xbUtil::DeleteRecord(){ if(( rc = dActiveTable->DeleteRecord()) == XB_NO_ERROR ) std::cout << "Success" << std::endl; else - x.DisplayError( rc ); + x->DisplayError( rc ); } } /*************************************************************************************/ void xbUtil::PutRecord(){ - char cBuf[15]; - xbInt16 rc; - xbUInt32 lRecNo; + char cBuf[15]; + xbInt16 rc; + xbUInt32 ulRecNo; if( !dActiveTable ) dActiveTable = GetTablePtr( " - select table" ); @@ -1376,11 +1399,12 @@ void xbUtil::PutRecord(){ std::cout << "Record number not entered" << std::endl; return; } - lRecNo = atol( cBuf ); - if(( rc = dActiveTable->PutRecord( lRecNo )) == XB_NO_ERROR ) + //lRecNo = atol( cBuf ); + ulRecNo = strtoul( cBuf, NULL, 0 ); + if(( rc = dActiveTable->PutRecord( ulRecNo )) == XB_NO_ERROR ) std::cout << "Success" << std::endl; else - x.DisplayError( rc ); + x->DisplayError( rc ); } /*************************************************************************************/ @@ -1396,7 +1420,7 @@ void xbUtil::AppendRecord(){ if(( rc = dActiveTable->AppendRecord()) == XB_NO_ERROR ) std::cout << "Success" << std::endl; else - x.DisplayError( rc ); + x->DisplayError( rc ); } /*************************************************************************************/ @@ -1412,7 +1436,7 @@ void xbUtil::BlankRecord(){ if(( rc = dActiveTable->BlankRecord()) == XB_NO_ERROR ) std::cout << "Success" << std::endl; else - x.DisplayError( rc ); + x->DisplayError( rc ); } /*************************************************************************************/ @@ -1449,16 +1473,14 @@ void xbUtil::RenameTable(){ dActiveTable = NULL; std::cout << "Table closed. Reopen if needed.\n"; } - - } /*************************************************************************************/ void xbUtil::GetRecord(){ - char cBuf[15]; - xbInt16 iRc; - xbUInt32 lRecNo; + char cBuf[15]; + xbInt16 iRc; + xbUInt32 ulRecNo; if( !dActiveTable ) dActiveTable = GetTablePtr( " - select table" ); @@ -1476,11 +1498,12 @@ void xbUtil::GetRecord(){ std::cout << "Record number not entered" << std::endl; return; } - lRecNo = atol( cBuf ); - if(( iRc = dActiveTable->GetRecord( lRecNo )) == XB_NO_ERROR ) + //lRecNo = atol( cBuf ); + ulRecNo = strtoul( cBuf, NULL, 0 ); + if(( iRc = dActiveTable->GetRecord( ulRecNo )) == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } /*************************************************************************************/ void xbUtil::DisplayActiveTable() const{ @@ -1513,7 +1536,7 @@ void xbUtil::DisplayActiveTable() const{ xbDbf * xbUtil::GetTablePtr( const char * cTitle ){ xbDbf *d; - xbInt16 iOpenTableCnt = x.GetOpenTableCount(); + xbInt16 iOpenTableCnt = x->GetOpenTableCount(); char cBuf[15]; xbInt16 iLineNo; @@ -1521,10 +1544,10 @@ xbDbf * xbUtil::GetTablePtr( const char * cTitle ){ std::cout << "No open tables" << std::endl; return NULL; } else if( iOpenTableCnt == 1 ){ - d = x.GetDbfPtr( 1 ); + d = x->GetDbfPtr( 1 ); } else { std::cout << "Select file/table " << cTitle << std::endl; - x.DisplayTableList(); + x->DisplayTableList(); std::cout << std::endl << "Enter line number:" << std::endl; memset( cBuf, 0x00, 15 ); std::cin.getline( cBuf, 15 ); @@ -1537,7 +1560,7 @@ xbDbf * xbUtil::GetTablePtr( const char * cTitle ){ std::cout << "Invalid selection. Valid line numbers are 1 through " << iOpenTableCnt << std::endl; return NULL; } - d = x.GetDbfPtr( iLineNo ); + d = x->GetDbfPtr( iLineNo ); } return d; } @@ -1551,7 +1574,7 @@ void xbUtil::UpdateTableAutoCommit(){ std::cout << " If unsure, leave the option turned on at the DBMS level (default)" << std::endl; std::cout << " and don't over ride the setting at the table level" << std::endl << std::endl; std::cout << " -1 ==> Use DBMS setting which is currently ["; - if( x.GetDefaultAutoCommit() ) + if( x->GetDefaultAutoCommit() ) std::cout << "ON]" << std::endl; else std::cout << "OFF]" << std::endl; @@ -1584,7 +1607,7 @@ void xbUtil::CopyDbfStructure(){ xbDbf *d; xbInt16 rc; char filename[128]; - xbFile f( &x ); + xbFile f( x ); xbDbf *dNewTable; d = GetTablePtr( "" ); @@ -1592,14 +1615,14 @@ void xbUtil::CopyDbfStructure(){ if( d->GetVersion() == 3 ){ #ifdef XB_DBF3_SUPPORT - dNewTable = new xbDbf3( &x ); + dNewTable = new xbDbf3( x ); #else std::cout << "Dbase III file support not build into library. See XB_DBF3_SUPPORT" << std::endl; return; #endif } else if( d->GetVersion() == 4 ){ #ifdef XB_DBF4_SUPPORT - dNewTable = new xbDbf4( &x ); + dNewTable = new xbDbf4( x ); #else std::cout << "Dbase IV file support not build into library. See XB_DBF4_SUPPORT" << std::endl; return; @@ -1622,13 +1645,13 @@ void xbUtil::CopyDbfStructure(){ } if(( rc = d->CopyDbfStructure( dNewTable, filename, filename, 0, XB_MULTI_USER )) != XB_NO_ERROR ){ std::cout << "Error " << rc << " creating new file" << std::endl; - x.DisplayError( rc ); + x->DisplayError( rc ); return; } std::cout << "Table " << f.GetFqFileName().Str() << " created" << std::endl; if(( rc = dNewTable->Close()) != XB_NO_ERROR ){ std::cout << "Error " << rc << " closing new file" << std::endl; - x.DisplayError( rc ); + x->DisplayError( rc ); return; } } @@ -1649,7 +1672,7 @@ void xbUtil::ZapTable(){ if( iRc == XB_NO_ERROR ) std::cout << "Table Zapped (all rows deleted)" << std::endl; else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } /*************************************************************************************/ void xbUtil::Pack(){ @@ -1666,7 +1689,7 @@ void xbUtil::Pack(){ if( iRc == XB_NO_ERROR ) std::cout << "Table Packed" << std::endl; else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } /*************************************************************************************/ void xbUtil::DisplayTableStats(){ @@ -1699,7 +1722,7 @@ void xbUtil::DisplayTableStats(){ // DBMS settings if( d->GetAutoCommit( 0 ) == -1 ){ std::cout << "Table Auto Commit = [Use DBMS Setting]" << std::endl; - if( x.GetDefaultAutoCommit() ) + if( x->GetDefaultAutoCommit() ) std::cout << "DBMS Auto Commit = [ON]" << std::endl; else std::cout << "DBMS Auto Commit = [OFF]" << std::endl; @@ -1714,24 +1737,24 @@ void xbUtil::DisplayTableStats(){ /*************************************************************************************/ void xbUtil::CloseAllTables(){ - xbInt16 sOpenTableCnt = x.GetOpenTableCount(); + xbInt16 sOpenTableCnt = x->GetOpenTableCount(); xbInt16 rc; if( sOpenTableCnt == 0 ){ std::cout << "No open tables" << std::endl; return; } - rc = x.CloseAllTables(); + rc = x->CloseAllTables(); if( rc == XB_NO_ERROR ) std::cout << "All open tables closed" << std::endl; else - x.DisplayError( rc ); + x->DisplayError( rc ); dActiveTable = NULL; } /*************************************************************************************/ void xbUtil::Close(){ xbDbf *d; -// xbInt16 sOpenTableCnt = x.GetOpenTableCount(); +// xbInt16 sOpenTableCnt = x->GetOpenTableCount(); d = GetTablePtr( "to close" ); if( d ){ @@ -1746,7 +1769,7 @@ void xbUtil::Close(){ /*************************************************************************************/ void xbUtil::Open(){ xbInt16 rc; - xbFile f( &x ); + xbFile f( x ); xbDbf *dTable; char filename[128]; unsigned char cFileTypeByte; @@ -1766,18 +1789,18 @@ void xbUtil::Open(){ } if(( rc = f.GetXbaseFileTypeByte( f.GetFqFileName(), cFileTypeByte )) != XB_NO_ERROR ){ std::cout << "Could not open file or determine file type rc = " << rc << " file = " << filename << std::endl; - x.DisplayError( rc ); + x->DisplayError( rc ); return; } std:: cout << "File Type Byte "; - x.BitDump( cFileTypeByte ); + x->BitDump( cFileTypeByte ); std::cout << "\n"; std::cout << "Table Type = [" << f.DetermineXbaseTableVersion( cFileTypeByte ) << "]\n"; std::cout << "Memo Type = [" << f.DetermineXbaseMemoVersion( cFileTypeByte ) << "]\n"; if( f.DetermineXbaseTableVersion( cFileTypeByte ) == 4 ){ #ifdef XB_DBF4_SUPPORT - dTable = new xbDbf4( &x ); + dTable = new xbDbf4( x ); #else std::cout << "Dbase IV file support not build into library. See XB_DBF4_SUPPORT" << std::endl; return; @@ -1785,21 +1808,21 @@ void xbUtil::Open(){ } else if( f.DetermineXbaseTableVersion( cFileTypeByte ) == 3 ){ #ifdef XB_DBF3_SUPPORT - dTable = new xbDbf3( &x ); + dTable = new xbDbf3( x ); #else std::cout << "Dbase III file support not build into library. See XB_DBF3_SUPPORT" << std::endl; return; #endif } else { std::cout << "Unsupported file type file = " << filename << " type = "; - x.BitDump( cFileTypeByte ); + x->BitDump( cFileTypeByte ); std::cout << std::endl; return; } if(( rc = dTable->Open( filename )) != 0 ){ std::cout << "Could not open file rc = " << rc << " file = " << filename << std::endl; - x.DisplayError( rc ); + x->DisplayError( rc ); return; } @@ -1821,9 +1844,9 @@ void xbUtil::UpdateDefaultLockRetries(){ std::cout << "Default Lock Retry Count not updated" << std::endl; return; } else { - x.SetDefaultLockRetries( atoi( cBuf )); + x->SetDefaultLockRetries( atoi( cBuf )); std::cout << "Default Lock Retry Count updated to [" - << x.GetDefaultLockRetries() << "]" << std::endl; + << x->GetDefaultLockRetries() << "]" << std::endl; } } @@ -1835,9 +1858,9 @@ void xbUtil::UpdateDefaultLockWait(){ std::cout << "Default Lock Wait Time not updated" << std::endl; return; } else { - x.SetDefaultLockWait( atoi( cBuf )); + x->SetDefaultLockWait( atoi( cBuf )); std::cout << "Default Lock Wait Time updated to [" - << x.GetDefaultLockWait() << "]" << std::endl; + << x->GetDefaultLockWait() << "]" << std::endl; } } @@ -1854,38 +1877,38 @@ void xbUtil::UpdateDefaultLockFlavor(){ std::cout << "Default Lock Flavor not updated" << std::endl; return; } else { - x.SetDefaultLockFlavor( atoi( cBuf )); + x->SetDefaultLockFlavor( atoi( cBuf )); std::cout << "Default Lock Flavor updated to [" - << x.GetDefaultLockFlavor() << "]" << std::endl; + << x->GetDefaultLockFlavor() << "]" << std::endl; } } void xbUtil::ToggleDefaultAutoLock(){ - if( x.GetDefaultAutoLock()){ - x.DisableDefaultAutoLock(); - x.WriteLogMessage( "xb_dbfutil - Default Auto Lock disabled" ); + if( x->GetDefaultAutoLock()){ + x->DisableDefaultAutoLock(); + x->WriteLogMessage( "xb_dbfutil - Default Auto Lock disabled" ); std::cout << "Default Auto Lock disabled" << std::endl; } else { - x.EnableDefaultAutoLock(); - x.WriteLogMessage( "xb_dbfutil - Default Auto Lock enabled" ); + x->EnableDefaultAutoLock(); + x->WriteLogMessage( "xb_dbfutil - Default Auto Lock enabled" ); std::cout << "Default Auto Lock enabled" << std::endl; } } void xbUtil::ToggleMultiUserMode(){ - if( x.GetMultiUser()){ - x.SetMultiUser( xbFalse ); - x.WriteLogMessage( "xb_dbfutil - Multi user mode disabled" ); + if( x->GetMultiUser()){ + x->SetMultiUser( xbFalse ); + x->WriteLogMessage( "xb_dbfutil - Multi user mode disabled" ); std::cout << "Multi user mode disabled" << std::endl; } else { - x.SetMultiUser( xbTrue ); - x.WriteLogMessage( "xb_dbfutil - Multu user mode enabled" ); + x->SetMultiUser( xbTrue ); + x->WriteLogMessage( "xb_dbfutil - Multu user mode enabled" ); std::cout << "Multi user mode enabled" << std::endl; } } #endif /*************************************************************************************/ void xbUtil::ListFilesInDataDirectory(){ - std::cout << "List files for [" << x.GetDataDirectory().Str() << "]" << std::endl << std::endl; + std::cout << "List files for [" << x->GetDataDirectory().Str() << "]" << std::endl << std::endl; xbString s1; xbInt16 iCnt = 0; @@ -1894,7 +1917,7 @@ void xbUtil::ListFilesInDataDirectory(){ WIN32_FIND_DATA fData; HANDLE hFile; - xbString sSearchPath = x.GetDataDirectory(); + xbString sSearchPath = x->GetDataDirectory(); xbUInt32 l = sSearchPath.Len(); char cPathSeperator = sSearchPath.GetPathSeparator(); char cLastChar = sSearchPath.GetCharacter( l ); @@ -1926,7 +1949,7 @@ void xbUtil::ListFilesInDataDirectory(){ DIR *dir; struct dirent *ent; - if(( dir = opendir( x.GetDataDirectory() )) != NULL ){ + if(( dir = opendir( x->GetDataDirectory() )) != NULL ){ while(( ent = readdir( dir )) != NULL ){ s1 = ent->d_name; if( s1 != "." && s1 != ".." ){ @@ -1947,20 +1970,20 @@ void xbUtil::UpdateLogDirectory(){ char cNewDir[256]; cNewDir[0] = 0x00; std::cout << std::endl << "Update Log Directory" << std::endl; - std::cout << "Current Log File Directory = [" << x.GetLogDirectory().Str() << "]" << std::endl; + std::cout << "Current Log File Directory = [" << x->GetLogDirectory().Str() << "]" << std::endl; std::cout << "Enter '1' to erase the Log File Directory" << std::endl; - std::cout << "Enter '2' to change Log File Directory to [" << x.GetDefaultLogDirectory().Str() << "]" << std::endl; + std::cout << "Enter '2' to change Log File Directory to [" << x->GetLogDirectory().Str() << "]" << std::endl; std::cout << "Enter new log directory. Enter for no updates." << std::endl; std::cin.getline( cNewDir, 256 ); if( strlen( cNewDir ) > 0 ){ if( cNewDir[0] == '1' ) - x.SetLogDirectory( "" ); + x->SetLogDirectory( "" ); else if( cNewDir[0] == '2' ) - x.SetLogDirectory( x.GetDefaultLogDirectory()); + x->SetLogDirectory( x->GetLogDirectory()); else - x.SetLogDirectory( cNewDir ); + x->SetLogDirectory( cNewDir ); - std::cout << "Log File Directory is [" << x.GetLogDirectory().Str() << "]" << std::endl; + std::cout << "Log File Directory is [" << x->GetLogDirectory().Str() << "]" << std::endl; } else std::cout << "Log Directory not updated" << std::endl; @@ -1971,51 +1994,51 @@ void xbUtil::UpdateLogFileName(){ cNewFile[0] = 0x00; std::cout << std::endl << "Update Log File Name" << std::endl; - std::cout << "Current Log File Name = [" << x.GetLogFileName().Str() << "]" << std::endl; - std::cout << "Enter '1' to change change Log File Name to default [" << x.GetDefaultLogFileName().Str() << "]" << std::endl; + std::cout << "Current Log File Name = [" << x->GetLogFileName().Str() << "]" << std::endl; + std::cout << "Enter '1' to change change Log File Name to default [" << x->GetLogFileName().Str() << "]" << std::endl; std::cout << "Enter new Log File Name" << std::endl; std::cin.getline( cNewFile, 256 ); if( strlen( cNewFile ) > 0 ){ if( cNewFile[0] == '1' ) - x.SetLogFileName( x.GetDefaultLogFileName()); + x->SetLogFileName( x->GetLogFileName()); else - x.SetLogFileName( cNewFile ); + x->SetLogFileName( cNewFile ); - std::cout << "Log File Name is [" << x.GetLogFileName().Str() << "]" << std::endl; + std::cout << "Log File Name is [" << x->GetLogFileName().Str() << "]" << std::endl; } else std::cout << "Log File Name not updated" << std::endl; } /*************************************************************************************/ void xbUtil::WriteLogMessage(){ - if( x.GetLogStatus()) { + if( x->GetLogStatus()) { char cMsg[256]; std::cout << "Enter a message to write to the log file (256 byte max)" << std::endl; std::cin.getline( cMsg, 256 ); - x.WriteLogMessage( cMsg ); + x->WriteLogMessage( cMsg ); } else std::cout << "Logging disabled" << std::endl; } /*************************************************************************************/ void xbUtil::ToggleLoggingStatus(){ - if( x.GetLogStatus()){ - x.DisableMsgLogging(); - x.WriteLogMessage( "xb_dbfutil - Logging disabled" ); + if( x->GetLogStatus()){ + x->DisableMsgLogging(); + x->WriteLogMessage( "xb_dbfutil - Logging disabled" ); std::cout << "Logging disabled" << std::endl; } else { - x.EnableMsgLogging(); - x.WriteLogMessage( "xb_dbfutil - Logging enabled" ); + x->EnableMsgLogging(); + x->WriteLogMessage( "xb_dbfutil - Logging enabled" ); std::cout << "Logging enabled" << std::endl; } } /*************************************************************************************/ void xbUtil::ToggleDefaultAutoCommit(){ - if( x.GetDefaultAutoCommit()){ - x.SetDefaultAutoCommit( xbFalse ); - x.WriteLogMessage( "xb_dbfutil - Default Auto Commit disabled" ); + if( x->GetDefaultAutoCommit()){ + x->SetDefaultAutoCommit( xbFalse ); + x->WriteLogMessage( "xb_dbfutil - Default Auto Commit disabled" ); std::cout << "Default Auto Commit disabled" << std::endl; } else { - x.SetDefaultAutoCommit( xbTrue ); - x.WriteLogMessage( "xb_dbfutil - Default Auto Commit enabled" ); + x->SetDefaultAutoCommit( xbTrue ); + x->WriteLogMessage( "xb_dbfutil - Default Auto Commit enabled" ); std::cout << "Default Auto Commit enabled" << std::endl; } } @@ -2024,19 +2047,19 @@ void xbUtil::UpdateDataDirectory(){ char cNewDir[256]; cNewDir[0] = 0x00; std::cout << std::endl << "Update Default Data Directory" << std::endl; - std::cout << "Current Default Data Directory = [" << x.GetDataDirectory().Str() << "]" << std::endl; + std::cout << "Current Default Data Directory = [" << x->GetDataDirectory().Str() << "]" << std::endl; std::cout << "Enter '1' to erase the Default Data Directory" << std::endl; std::cout << "Enter '2' to change Default Data Directory to [" << PROJECT_DATA_DIR << "]" << std::endl; std::cout << "Enter new directory" << std::endl; std::cin.getline( cNewDir, 256 ); if( strlen( cNewDir ) > 0 ){ if( cNewDir[0] == '1' ) - x.SetDataDirectory( "" ); + x->SetDataDirectory( "" ); else if( cNewDir[0] == '2' ) - x.SetDataDirectory( PROJECT_DATA_DIR ); + x->SetDataDirectory( PROJECT_DATA_DIR ); else - x.SetDataDirectory( cNewDir ); - std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + x->SetDataDirectory( cNewDir ); + std::cout << "Default Data Directory is [" << x->GetDataDirectory().Str() << "]" << std::endl; } else std::cout << "Default Data Directory not updated" << std::endl; @@ -2044,20 +2067,20 @@ void xbUtil::UpdateDataDirectory(){ /*************************************************************************************/ void xbUtil::ListSystemSettings(){ std::cout << std::endl << "List System Settings" << std::endl; - std::cout << "Default Data Directory = [" << x.GetDataDirectory().Str() << "]" << std::endl; -// std::cout << "Default File Version = [" << x.GetDefaultFileVersion() << "]" << std::endl; + std::cout << "Default Data Directory = [" << x->GetDataDirectory().Str() << "]" << std::endl; +// std::cout << "Default File Version = [" << x->GetDefaultFileVersion() << "]" << std::endl; #ifdef XB_LOCKING_SUPPORT std::cout << "Default Auto Locking = ["; - if( x.GetDefaultAutoLock()) + if( x->GetDefaultAutoLock()) std::cout << "ON]" << std::endl; else std::cout << "OFF]" << std::endl; - std::cout << "Default Lock Retries = [" << x.GetDefaultLockRetries() << "]" << std::endl; - std::cout << "Default Lock Wait Time = [" << x.GetDefaultLockWait() << "] (millisecs)" << std::endl; + std::cout << "Default Lock Retries = [" << x->GetDefaultLockRetries() << "]" << std::endl; + std::cout << "Default Lock Wait Time = [" << x->GetDefaultLockWait() << "] (millisecs)" << std::endl; std::cout << "Default Lock Flavor = ["; - switch (x.GetDefaultLockFlavor()){ + switch (x->GetDefaultLockFlavor()){ case 1: std::cout << "Dbase]" << std::endl; break; @@ -2075,26 +2098,26 @@ void xbUtil::ListSystemSettings(){ break; } #endif - std::cout << "Default Log Directory = [" << x.GetDefaultLogDirectory().Str() << "]" << std::endl; - std::cout << "Default Logfile Name = [" << x.GetDefaultLogFileName().Str() << "]" << std::endl; + std::cout << "Log Directory = [" << x->GetLogDirectory().Str() << "]" << std::endl; + std::cout << "Logfile Name = [" << x->GetLogFileName().Str() << "]" << std::endl; std::cout << "Default Auto Commit = ["; - if( x.GetDefaultAutoCommit()) + if( x->GetDefaultAutoCommit()) std::cout << "ON]" << std::endl; else std::cout << "OFF]" << std::endl; std::cout << "Logging Status = ["; - if( x.GetLogStatus()) + if( x->GetLogStatus()) std::cout << "ON]" << std::endl; else std::cout << "OFF]" << std::endl; std::cout << "Endian Type = ["; - if( x.GetEndianType() == 'L' ) + if( x->GetEndianType() == 'L' ) std::cout << "Little Endian]" << std::endl; else std::cout << "Big Endian]" << std::endl; - if( x.GetMultiUser()) + if( x->GetMultiUser()) std::cout << "Multi User Mode = [ON]"; else std::cout << "Multi User Mode = [OFF]"; @@ -2109,7 +2132,9 @@ void xbUtil::ProcessOption( const xbString &sOption ){ else if( sOption == "=0.99" ) // exit right now, now cleanup or termination of anything exit(0); - else if( sOption == "=2" ) + else if( sOption == "=1" ) + Help(); + else if( sOption == "=2" ) SystemMenu(); else if( sOption == "=2.1" ) ListSystemSettings(); @@ -2144,7 +2169,7 @@ void xbUtil::ProcessOption( const xbString &sOption ){ else if( sOption == "=3.2" ) UpdateDataDirectory(); else if( sOption == "=3.3" ) - x.DisplayTableList(); + x->DisplayTableList(); else if( sOption == "=3.4" ) Open(); else if( sOption == "=3.5" ) @@ -2808,7 +2833,7 @@ void xbUtil::FileMenu() case 0: break; case 1: ListFilesInDataDirectory(); break; case 2: UpdateDataDirectory(); break; - case 3: x.DisplayTableList(); break; + case 3: x->DisplayTableList(); break; case 4: Open(); break; case 5: Close(); break; case 6: CloseAllTables(); break; @@ -2963,6 +2988,7 @@ void xbUtil::MainMenu() option = GetOption(); switch( option ){ case 0: break; + case 1: Help(); break; case 2: SystemMenu(); break; case 3: FileMenu(); break; case 4: RecordMenu(); break; @@ -3114,7 +3140,7 @@ void xbUtil::OpenIndex(){ xbString sIxFileName = cBuf; iRc = dActiveTable->OpenIndex( sIxType, sIxFileName ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::CloseIndexFile(){ @@ -3141,7 +3167,7 @@ void xbUtil::CloseIndexFile(){ } xbInt16 iRc = dActiveTable->CloseIndexFile( pIx ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::CreateIndexTag(){ @@ -3227,7 +3253,7 @@ void xbUtil::CreateIndexTag(){ void *vpTag; xbInt16 iRc = dActiveTable->CreateTag( sIxType, sIxName, sKeyExpression, sFilter, iDescending, iUnique, 0, &pIx, &vpTag ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::GetFirstKey(){ @@ -3252,7 +3278,7 @@ void xbUtil::GetFirstKey(){ if( iRc == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::GetNextKey(){ @@ -3277,7 +3303,7 @@ void xbUtil::GetNextKey(){ if( iRc == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::GetPrevKey(){ @@ -3303,7 +3329,7 @@ void xbUtil::GetPrevKey(){ if( iRc == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::GetLastKey(){ @@ -3328,7 +3354,7 @@ void xbUtil::GetLastKey(){ if( iRc == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::FindKey(){ @@ -3387,7 +3413,7 @@ void xbUtil::FindKey(){ if( iRc == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::CheckIntegrity(){ @@ -3410,7 +3436,7 @@ void xbUtil::CheckIntegrity(){ void *vpCurTag = dActiveTable->GetCurTag(); xbInt16 iRc = pIx->CheckTagIntegrity( vpCurTag, 2 ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::Reindex(){ @@ -3433,7 +3459,7 @@ void xbUtil::Reindex(){ } void *vpCurTag = dActiveTable->GetCurTag(); xbInt16 iRc = pIx->Reindex( &vpCurTag ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::DeleteTag(){ @@ -3455,7 +3481,7 @@ void xbUtil::DeleteTag(){ } void *vpCurTag = dActiveTable->GetCurTag(); xbInt16 iRc = dActiveTable->DeleteTag( dActiveTable->GetCurIxType(), pIx->GetTagName( vpCurTag )); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::AssociateNonProdIx(){ @@ -3494,7 +3520,7 @@ void xbUtil::DumpRecsByIx( xbInt16 iOpt ){ std::cout << "1 - 1 line per record" << std::endl; xbInt16 iDispFmt = GetOption(); - x.WriteLogMessage( "--------- Dump Recs By Index -------------", iDispOpt ); + x->WriteLogMessage( "--------- Dump Recs By Index -------------", iDispOpt ); void *vpCurTag = dActiveTable->GetCurTag(); xbUInt32 lRecCnt = 0; xbInt16 iRc = 0; @@ -3509,7 +3535,7 @@ void xbUtil::DumpRecsByIx( xbInt16 iOpt ){ lRecCnt++; } } else { - x.DisplayError( iRc ); + x->DisplayError( iRc ); } } else if( iOpt == 1 ) { iRc = pIx->GetLastKey( vpCurTag, 1 ); @@ -3668,10 +3694,10 @@ void xbUtil::SetFilter() if( filt ) delete filt; - filt = new xbFilter( &x, dActiveTable ); + filt = new xbFilter( dActiveTable ); xbInt16 iRc = filt->Set( s ); - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::GetFirstFilterRec() @@ -3689,7 +3715,7 @@ void xbUtil::GetFirstFilterRec() if(( iRc = filt->GetFirstRecord()) == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::GetNextFilterRec() @@ -3706,7 +3732,7 @@ void xbUtil::GetNextFilterRec() if(( iRc = filt->GetNextRecord()) == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::GetPrevFilterRec() @@ -3723,7 +3749,7 @@ void xbUtil::GetPrevFilterRec() if(( iRc = filt->GetPrevRecord()) == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } void xbUtil::GetLastFilterRec() @@ -3740,17 +3766,46 @@ void xbUtil::GetLastFilterRec() if(( iRc = filt->GetLastRecord()) == XB_NO_ERROR ) dActiveTable->DumpRecord( dActiveTable->GetCurRecNo(), 2); else - x.DisplayError( iRc ); + x->DisplayError( iRc ); } #endif // XB_FILTER_SUPPORT ///@endcond DOXYOFF + +/*************************************************************************************/ +void PrintHelp(); +void PrintHelp(){ + std::cout << "Usage: xb_dbfutil [-h] [-?] [--help] [-v] [--version]" << std::endl << std::endl; + std::cout << "This program provides a menu driven tool for accissing the functionality og the xbase64 library" << std::endl; + std::cout << "and provides access to DBF, MDX, NDX and MDT xbase formatted data files." << std::endl << std::endl; +} +void PrintVersion(); +void PrintVersion(){ + std::cout << "Xbase64 Version: " << xbase_VERSION_MAJOR << "." << xbase_VERSION_MINOR << "." << xbase_VERSION_PATCH << std::endl; +} /*************************************************************************************/ -int main(int, char**) +int main(int argc, char *argv[] ) { - std::cout << "xb_dbfutil initializing" << std::endl; - xbUtil u; + + // std::cout << "xb_dbfutil initializing" << std::endl; + xbXBase x; + + xbString sParm; + if (x.GetCmdLineOpt( argc, argv, "-h", sParm ) || + x.GetCmdLineOpt( argc, argv, "-?", sParm ) || + x.GetCmdLineOpt( argc, argv, "--help", sParm )){ + PrintHelp(); + return 1; + } + + if ( x.GetCmdLineOpt( argc, argv, "-v", sParm ) || + x.GetCmdLineOpt( argc, argv, "--version", sParm )){ + PrintVersion(); + return 1; + } + + xbUtil u( &x ); u.MainMenu(); return 0; } diff --git a/src/utils/xb_deletall.cpp b/src/utils/xb_deletall.cpp index 720710f..3a8f6e4 100755 --- a/src/utils/xb_deletall.cpp +++ b/src/utils/xb_deletall.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2017,2019 Gary A Kunkel +Copyright (c) 1997,2003,2014,2017,2019,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -24,32 +24,62 @@ This program sets the delete flag on all records in a dbf file using namespace xb; -int main(int ac,char** av) + + +void PrintHelp(); +void PrintHelp(){ + std::cout << "Usage: xb_deleteall [-h] [-?] [--help] [-v] [--version] -i myfile" << std::endl << std::endl; + std::cout << "This program flags all the records in a DBF table for deletion. To physically remove the deleted records, see program xb_pack."; + std::cout << std::endl << std::endl; +} +void PrintVersion(); +void PrintVersion(){ + std::cout << "Xbase64 Version: " << xbase_VERSION_MAJOR << "." << xbase_VERSION_MINOR << "." << xbase_VERSION_PATCH << std::endl; +} + + +int main(int argc, char *argv[]) { + xbXBase x; xbDbf *MyFile = NULL; xbFile f( &x ); xbInt16 iRc = 0; - if (ac <= 1) { - std::cout << "\nUsage: xb_deletall filename...\n"; + xbString sParm; + + if (argc < 2 || x.GetCmdLineOpt( argc, argv, "-h", sParm ) || + x.GetCmdLineOpt( argc, argv, "-?", sParm ) || + x.GetCmdLineOpt( argc, argv, "--help", sParm )){ + PrintHelp(); + return 1; + } + + if ( x.GetCmdLineOpt( argc, argv, "-v", sParm ) || + x.GetCmdLineOpt( argc, argv, "--version", sParm )){ + PrintVersion(); + return 1; + } + + if( !x.GetCmdLineOpt( argc, argv, "-i", sParm ) || sParm == "" ){ + PrintHelp(); return 1; } - if(( iRc = x.OpenHighestVersion( av[1], "", &MyFile )) != XB_NO_ERROR ){ - std::cout << "Could not open file iRc = " << iRc << " file = " << av[1] << std::endl; + if(( iRc = x.OpenHighestVersion( sParm.Str(), "", &MyFile )) != XB_NO_ERROR ){ + std::cout << "Could not open file RC = " << iRc << " file = " << sParm.Str() << std::endl; x.DisplayError( iRc ); - return 0; + return 1; } iRc = MyFile->DeleteAllRecords(); if( iRc != XB_NO_ERROR ) { - std::cout << "Error Deleting all records - database ==> " << av[1] << "\n"; - std::cout << " Return Code = " << iRc; + std::cout << "Error Deleting all records - database ==> " << sParm.Str() << "\n"; + std::cout << "Return Code = " << iRc; + x.DisplayError( iRc ); + return 1; } MyFile->Close(); - std::cout << "\nDone...\n\n"; - + delete MyFile; return 0; - } \ No newline at end of file diff --git a/src/utils/xb_dumpdbt.cpp b/src/utils/xb_dumpdbt.cpp index bc95ab7..05b7209 100755 --- a/src/utils/xb_dumpdbt.cpp +++ b/src/utils/xb_dumpdbt.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2017 Gary A Kunkel +Copyright (c) 1997,2003,2014,2017,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -16,16 +16,25 @@ Email Contact: #include - using namespace xb; -int main( int ac, char **av ) -{ +void PrintHelp(); +void PrintHelp(){ + std::cout << "Usage: xb_dumpdbt [-h] [-?] [--help] [-v] [--version] -i filename.DBF" << std::endl << std::endl; + std::cout << "This program dumps memo record data from an xbase formatted DBT file to stdout." << std::endl << std::endl; +} +void PrintVersion(); +void PrintVersion(){ + std::cout << "Xbase64 Version: " << xbase_VERSION_MAJOR << "." << xbase_VERSION_MINOR << "." << xbase_VERSION_PATCH << std::endl; +} + +int main(int argc, char *argv[] ) +{ -#ifdef XB_MEMO_SUPPORT - xbXBase x; + #ifdef XB_MEMO_SUPPORT + xbXBase x; xbInt16 iRc; char cFieldType; xbDbf *MyFile = NULL; @@ -34,19 +43,33 @@ int main( int ac, char **av ) xbInt32 lBlockPtr; xbString sMemoFldData; - if( ac <= 1 ){ - std::cout << "\nUsage: dumpdbt filename...\n"; + xbString sParm; + if (argc < 2 || x.GetCmdLineOpt( argc, argv, "-h", sParm ) || + x.GetCmdLineOpt( argc, argv, "-?", sParm ) || + x.GetCmdLineOpt( argc, argv, "--help", sParm )){ + PrintHelp(); + return 1; + } + + if ( x.GetCmdLineOpt( argc, argv, "-v", sParm ) || + x.GetCmdLineOpt( argc, argv, "--version", sParm )){ + PrintVersion(); return 1; } - if(( iRc = x.OpenHighestVersion( av[1], "", &MyFile )) != XB_NO_ERROR ){ - std::cout << "Could not open file iRc = " << iRc << " file = " << av[1] << std::endl; + if( !x.GetCmdLineOpt( argc, argv, "-i", sParm ) || sParm == "" ){ + PrintHelp(); + return 1; + } + + if(( iRc = x.OpenHighestVersion( sParm.Str(), "", &MyFile )) != XB_NO_ERROR ){ + std::cout << "Could not open file iRc = " << iRc << " file = " << sParm.Str() << std::endl; x.DisplayError( iRc ); - return 0; + return 1; } if( MyFile->GetMemoFieldCnt() == 0 ) { - std::cout << "No memo fields exist in " << av[1] << std::endl; + std::cout << "No memo fields exist in " << sParm.Str() << std::endl; } else { xbUInt32 ulRecCnt = 0; @@ -78,10 +101,9 @@ int main( int ac, char **av ) MyFile->Close(); delete MyFile; } - -#else - std::cout << "\nXB_MEMO_SUPPORT is OFF\n"; -#endif + #else + std::cout << "\nXB_MEMO_SUPPORT is OFF\n"; + #endif return 0; } diff --git a/src/utils/xb_dumphdr.cpp b/src/utils/xb_dumphdr.cpp deleted file mode 100755 index 267f4c5..0000000 --- a/src/utils/xb_dumphdr.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* xb_dumphdr.cpp - -XBase64 Software Library - -Copyright (c) 1997,2003,2014 Gary A Kunkel - -The xb64 software library is covered under -the terms of the GPL Version 3, 2007 license. - -Email Contact: - - xb64-devel@lists.sourceforge.net - xb64-users@lists.sourceforge.net - -*/ - - -#include - -using namespace xb; - -int main( int ac, char ** av ){ - - - xbInt16 iRc; - xbXBase x; - xbDbf *MyFile = NULL; - - if( ac <= 1 ) { - std::cout << "\nUsage: xb_dumphdr filename...\n"; - return 1; - } - - if(( iRc = x.OpenHighestVersion( av[1], "", &MyFile )) != XB_NO_ERROR ){ - std::cout << "Could not open file iRc = " << iRc << " file = " << av[1] << std::endl; - x.DisplayError( iRc ); - return 0; - } - - MyFile->DumpHeader( 4 ); - MyFile->Close(); - delete MyFile; - - return 0; -} diff --git a/src/utils/xb_dumpix.cpp b/src/utils/xb_dumpix.cpp deleted file mode 100755 index afd8764..0000000 --- a/src/utils/xb_dumpix.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* xb_dumpix.cpp - -XBase64 Software Library - -Copyright (c) 1997,2003,2014 Gary A Kunkel - -The xb64 software library is covered under -the terms of the GPL Version 3, 2007 license. - -Email Contact: - - xb64-devel@lists.sourceforge.net - xb64-users@lists.sourceforge.net - -*/ - - -// This program dumps an index file's internal data blocks. -// This program is for index development and debugging purposes - - -#include - -using namespace xb; - -int main( int ac, char ** av ){ - - - xbInt16 iRc; - xbXBase x; - xbDbf *MyFile = NULL; - x.EnableMsgLogging(); - x.SetLogSize( 1000000L ); - - if( ac <= 1 ) { - std::cout << "\nUsage: xb_dumphdr filename...\n"; - return 1; - } - if(( iRc = x.OpenHighestVersion( av[1], "", &MyFile )) != XB_NO_ERROR ){ - std::cout << "Could not open file iRc = " << iRc << " file = " << av[1] << std::endl; - x.DisplayError( iRc ); - return 0; - } - xbIx *pIx = MyFile->GetCurIx(); - if( pIx ){ - // pIx->DumpHeader( 2, 3 ); - pIx->DumpTagBlocks( 2 ); - } else { - std::cout << av[1] << "No current index found" << std::endl; - } - - MyFile->Close(); - delete MyFile; - - return 0; -} diff --git a/src/utils/xb_dumprecs.cpp b/src/utils/xb_dumprecs.cpp index 0a85f45..cf6e33c 100755 --- a/src/utils/xb_dumprecs.cpp +++ b/src/utils/xb_dumprecs.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2019 Gary A Kunkel +Copyright (c) 1997,2003,2014,2019,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -17,27 +17,57 @@ Email Contact: #include using namespace xb; -int main(int ac,char** av) +void PrintHelp(); +void PrintHelp(){ + std::cout << "Usage: xb_dumprecs [-h] [-?] [--help] [-v] [--version] -i filename.DBF" << std::endl << std::endl; + std::cout << "This program dumps data records in an xbase formatted DBF file to stdout in csv format." << std::endl; + std::cout << "Memo data (variable length) is not included in this export. See program xb_dumpdpt for memo data." << std::endl << std::endl; +} +void PrintVersion(); +void PrintVersion(){ + std::cout << "Xbase64 Version: " << xbase_VERSION_MAJOR << "." << xbase_VERSION_MINOR << "." << xbase_VERSION_PATCH << std::endl; +} + +int main(int argc, char *argv[] ) { xbXBase x; + + xbInt16 iRc; x.EnableMsgLogging(); x.SetLogSize( 1000000L ); -// xbUInt32 ulRecCnt = 0; - if (ac <= 1) { - std::cout << "Usage: xb_dumprecs filename..." << std::endl; + xbString sParm; + if (argc < 2 || x.GetCmdLineOpt( argc, argv, "-h", sParm ) || + x.GetCmdLineOpt( argc, argv, "-?", sParm ) || + x.GetCmdLineOpt( argc, argv, "--help", sParm )){ + PrintHelp(); + return 1; + } + + if ( x.GetCmdLineOpt( argc, argv, "-v", sParm ) || + x.GetCmdLineOpt( argc, argv, "--version", sParm )){ + PrintVersion(); + return 1; + } + + if( !x.GetCmdLineOpt( argc, argv, "-i", sParm ) || sParm == "" ){ + PrintHelp(); return 1; } xbDbf *MyFile = NULL; - if(( iRc = x.OpenHighestVersion( av[1], "", &MyFile )) != XB_NO_ERROR ){ - std::cout << "Could not open file iRc = " << iRc << " file = " << av[1] << std::endl; + if(( iRc = x.OpenHighestVersion( sParm.Str(), "", &MyFile )) != XB_NO_ERROR ){ + std::cout << "Could not open file RC = " << iRc << " file = " << sParm.Str() << std::endl; x.DisplayError( iRc ); - return 0; + return 1; } -// std::cout << "Processing file sequentially from beginning..." << std::endl; + // std::cout << "Processing file sequentially from beginning..." << std::endl; + + #ifdef XB_BLOCKREAD_SUPPORT + MyFile->EnableBlockReadProcessing(); + #endif xbUInt32 j = 0; xbUInt32 ulRecCnt = 0; @@ -48,15 +78,21 @@ int main(int ac,char** av) return iRc; while( j < ulRecCnt ){ if( j == 0 ) - iRc = MyFile->DumpRecord(++j, 2, 2 ); + iRc = MyFile->DumpRecord(++j, 2, 2 ); // header + data else - iRc = MyFile->DumpRecord(++j, 2, 1 ); + iRc = MyFile->DumpRecord(++j, 2, 1 ); // data only if( iRc != XB_NO_ERROR ){ x.DisplayError( iRc ); return 1; } } -// std::cout << j << " Records written to logile" << std::endl; + std::cout << j << " Records processed." << std::endl; + + #ifdef XB_BLOCKREAD_SUPPORT + MyFile->DisableBlockReadProcessing(); + #endif + MyFile->Close(); + return 0; } diff --git a/src/utils/xb_execsql.cpp b/src/utils/xb_execsql.cpp index d474593..daa6b6e 100755 --- a/src/utils/xb_execsql.cpp +++ b/src/utils/xb_execsql.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014 Gary A Kunkel +Copyright (c) 1997,2003,2014,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. diff --git a/src/utils/xb_pack.cpp b/src/utils/xb_pack.cpp index ccec5a3..0cbba7e 100755 --- a/src/utils/xb_pack.cpp +++ b/src/utils/xb_pack.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2017 Gary A Kunkel +Copyright (c) 1997,2003,2014,2017,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -17,33 +17,59 @@ Email Contact: #include using namespace xb; -int main(int ac,char** av) -{ - if (ac <= 1) { - std::cout << - "\nUsage: xb_pack filename...\n" - "\nThis program does automatically reindexes any open NDX or MDX indexes."; - return 1; - } +void PrintHelp(); +void PrintHelp(){ + std::cout << "Usage: xb_pack [-h] [-?] [--help] [-v] [--version] -i filename.DBF" << std::endl << std::endl; + std::cout << "This program removes data records that are flagged for deletion in a DBF file and rebuilds indices." << std::endl << std::endl; +} +void PrintVersion(); +void PrintVersion(){ + std::cout << "Xbase64 Version: " << xbase_VERSION_MAJOR << "." << xbase_VERSION_MINOR << "." << xbase_VERSION_PATCH << std::endl; +} +int main(int argc, char *argv[] ) +{ xbXBase x; xbInt16 iRc; xbDbf * MyFile = NULL; - if(( iRc = x.OpenHighestVersion( av[1], "", &MyFile )) != XB_NO_ERROR ){ - std::cout << "Could not open file iRc = " << iRc << " file = " << av[1] << std::endl; + + xbString sParm; + if (argc < 2 || x.GetCmdLineOpt( argc, argv, "-h", sParm ) || + x.GetCmdLineOpt( argc, argv, "-?", sParm ) || + x.GetCmdLineOpt( argc, argv, "--help", sParm )){ + PrintHelp(); + return 1; + } + + if ( x.GetCmdLineOpt( argc, argv, "-v", sParm ) || + x.GetCmdLineOpt( argc, argv, "--version", sParm )){ + PrintVersion(); + return 1; + } + + if( !x.GetCmdLineOpt( argc, argv, "-i", sParm ) || sParm == "" ){ + PrintHelp(); + return 1; + } + + if(( iRc = x.OpenHighestVersion( sParm.Str(), "", &MyFile )) != XB_NO_ERROR ){ + std::cout << "Could not open file iRc = " << iRc << " file = " << sParm.Str() << std::endl; x.DisplayError( iRc ); - return 0; + return 1; } if(( iRc = MyFile->Pack()) != XB_NO_ERROR ) { - std::cout << "\nError packing DBF database ==> " << av[1] << std::endl; + std::cout << "\nError packing DBF database ==> " << sParm.Str() << std::endl; std::cout << " Return Code = " << iRc << std::endl; + return 1; } #ifdef XB_INDEX_SUPPORT if(( iRc = MyFile->Reindex( 1 )) != XB_NO_ERROR ) { - std::cout << "\nError reindexing DBF database ==> " << av[1] << std::endl; + std::cout << "\nError reindexing DBF database ==> " << sParm.Str() << std::endl; std::cout << " Return Code = " << iRc << std::endl; + x.DisplayError( iRc ); + return 1; } #endif // XB_INDEX_SUPPORT diff --git a/src/utils/xb_tblinfo.cpp b/src/utils/xb_tblinfo.cpp index 6b88403..241642a 100755 --- a/src/utils/xb_tblinfo.cpp +++ b/src/utils/xb_tblinfo.cpp @@ -1,8 +1,8 @@ -/* xb_dumpmdx.cpp +/* xb_tblinfo.cpp XBase64 Software Library -Copyright (c) 1997,2003,2014,2021 Gary A Kunkel +Copyright (c) 1997,2003,2014,2021,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -19,85 +19,86 @@ Email Contact: using namespace xb; -int main( int ac, char ** av ){ + +void PrintHelp(); +void PrintHelp(){ + std::cout << "Usage: xb_tblinfo [-h] [-?] [--help] [-v] [--version] -i filename.DBF" << std::endl << std::endl; + std::cout << "This program dumps table definition information from a DBF file and associated indices." << std::endl << std::endl; +} +void PrintVersion(); +void PrintVersion(){ + std::cout << "Xbase64 Version: " << xbase_VERSION_MAJOR << "." << xbase_VERSION_MINOR << "." << xbase_VERSION_PATCH << std::endl; +} + +int main(int argc, char *argv[] ){ xbXBase x; - xbBool bHdr = xbFalse; xbInt16 iRc; xbString sTagName; xbDbf *MyFile = NULL; - #ifdef XB_MDX_SUPPORT - #ifdef XB_DEBUG_SUPPORT - xbBool bMdxFound = xbFalse; - #endif // XB_DEBUG_SUPPORT - #endif // XB_MDX_SUPPORT - - x.EnableMsgLogging(); x.SetLogSize( 1000000L ); - - if( ac <= 1 ) { - std::cout << "\nUsage: xb_dumpmdx filename.DBF -h -tTAGNAME...\n"; - std::cout << "-h dump mdx file header (default)\n"; - std::cout << "-tTAGNAME where TAGNAME is the name of a tag for extract\n"; + xbString sParm; + if (argc < 2 || x.GetCmdLineOpt( argc, argv, "-h", sParm ) || + x.GetCmdLineOpt( argc, argv, "-?", sParm ) || + x.GetCmdLineOpt( argc, argv, "--help", sParm )){ + PrintHelp(); return 1; } - if( ac > 2 ){ - for( int i = 1; i< ac; i++ ){ - if( strstr( av[i], "-h" )) - bHdr = xbTrue; - else if( strstr( av[i], "-t" )) - sTagName.Set( av[i]+2 ); - } + if ( x.GetCmdLineOpt( argc, argv, "-v", sParm ) || + x.GetCmdLineOpt( argc, argv, "--version", sParm )){ + PrintVersion(); + return 1; } - if( bHdr == xbFalse && sTagName == "" ) - bHdr = xbTrue; - - - // std::cout << "Hdr = " << bHdr << std::endl; - if( sTagName != "" ) - std::cout << "Tag = " << sTagName.Str() << std::endl; + if( !x.GetCmdLineOpt( argc, argv, "-i", sParm ) || sParm == "" ){ + PrintHelp(); + return 1; + } - if(( iRc = x.OpenHighestVersion( av[1], "", &MyFile )) != XB_NO_ERROR ){ - std::cout << "Could not open file iRc = " << iRc << " file = " << av[1] << std::endl; + if(( iRc = x.OpenHighestVersion( sParm.Str(), "", &MyFile )) != XB_NO_ERROR ){ + std::cout << "Could not open file iRc = " << iRc << " file = " << sParm.Str() << std::endl; x.DisplayError( iRc ); - return 0; + return 1; } MyFile->DumpHeader( 4 ); - #ifdef XB_MDX_SUPPORT - // for each mdx file, dump the header - xbIxList *ixl = MyFile->GetIxList(); - xbIx *ixp; + + + #ifdef XB_INDEX_SUPPORT + xbIxList *ixl; + xbIx *ixp; xbString sFileType; + + #ifdef XB_MDX_SUPPORT + ixl = MyFile->GetIxList(); while( ixl ){ ixp = ixl->ix; ixp->GetFileType( sFileType ); - - #ifdef XB_DEBUG_SUPPORT - if( sFileType == "MDX" ){ - bMdxFound = xbTrue; - if( bHdr ){ - ixp->DumpHeader( 1, 3 ); - } - } - #endif // XB_DEBUG_SUPPORT + if( sFileType == "MDX" ) + ixp->DumpHeader( 1, 3 ); ixl = ixl->next; } - - #ifdef XB_DEBUG_SUPPORT - if( !bMdxFound ) - std::cout << "No MDX index for file." << std::endl; - #endif // XB_DEBUG_SUPPORT #endif // XB_MDX_SUPPORT + #ifdef XB_NDX_SUPPORT + ixl = MyFile->GetIxList(); + while( ixl ){ + ixp = ixl->ix; + ixp->GetFileType( sFileType ); + if( sFileType == "NDX" ) + ixp->DumpHeader( 1, 3 ); + ixl = ixl->next; + } + #endif // XB_NDX_SUPPORT + + #endif // XB_INDEX_SUPPORT + MyFile->Close(); delete MyFile; - return 0; } diff --git a/src/utils/xb_undelall.cpp b/src/utils/xb_undelall.cpp index 4f1af12..5fb1323 100755 --- a/src/utils/xb_undelall.cpp +++ b/src/utils/xb_undelall.cpp @@ -1,8 +1,8 @@ -/* xb_deletall.cpp +/* xb_undelall.cpp XBase64 Software Library -Copyright (c) 1997,2003,2014,2017 Gary A Kunkel +Copyright (c) 1997,2003,2014,2017,2023 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. @@ -13,8 +13,7 @@ Email Contact: xb64-users@lists.sourceforge.net - -This program sets the delete flag on all records in a dbf file +This program removes the delete flag on all records flagged for deletion in a DBF file */ @@ -24,32 +23,60 @@ This program sets the delete flag on all records in a dbf file using namespace xb; -int main(int ac,char** av) + + +void PrintHelp(); +void PrintHelp(){ + std::cout << "Usage: xb_undelall [-h] [-?] [--help] [-v] [--version] -i myfile" << std::endl << std::endl; + std::cout << "This program removes the deletion flags all the records in a DBF table that are flagged for deletion."; + std::cout << std::endl << std::endl; +} +void PrintVersion(); +void PrintVersion(){ + std::cout << "Xbase64 Version: " << xbase_VERSION_MAJOR << "." << xbase_VERSION_MINOR << "." << xbase_VERSION_PATCH << std::endl; +} + + +int main(int argc, char *argv[]) { xbXBase x; xbDbf *MyFile = NULL; xbInt16 iRc = 0; - if (ac <= 1) { - std::cout << "\nUsage: xb_deletall filename...\n"; + xbString sParm; + + if (argc < 2 || x.GetCmdLineOpt( argc, argv, "-h", sParm ) || + x.GetCmdLineOpt( argc, argv, "-?", sParm ) || + x.GetCmdLineOpt( argc, argv, "--help", sParm )){ + PrintHelp(); + return 1; + } + + if ( x.GetCmdLineOpt( argc, argv, "-v", sParm ) || + x.GetCmdLineOpt( argc, argv, "--version", sParm )){ + PrintVersion(); return 1; } - if(( iRc = x.OpenHighestVersion( av[1], "", &MyFile )) != XB_NO_ERROR ){ - std::cout << "Could not open file iRc = " << iRc << " file = " << av[1] << std::endl; + if( !x.GetCmdLineOpt( argc, argv, "-i", sParm ) || sParm == "" ){ + PrintHelp(); + return 1; + } + + if(( iRc = x.OpenHighestVersion( sParm.Str(), "", &MyFile )) != XB_NO_ERROR ){ + std::cout << "Could not open file RC = " << iRc << " file = " << sParm.Str() << std::endl; x.DisplayError( iRc ); - return 0; + return 1; } iRc = MyFile->UndeleteAllRecords(); if( iRc != XB_NO_ERROR ) { - std::cout << "Error Undeleting all records - database ==> " << av[1] << "\n"; + std::cout << "Error Undeleting all records - database ==> " << sParm.Str() << "\n"; std::cout << " Return Code = " << iRc; + return 1; } MyFile->Close(); delete MyFile; - std::cout << "\nDone...\n\n"; - return 0; } \ No newline at end of file diff --git a/src/utils/xb_zap.cpp b/src/utils/xb_zap.cpp deleted file mode 100755 index 4660cd8..0000000 --- a/src/utils/xb_zap.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* xb_zap.cpp - -XBase64 Software Library - -Copyright (c) 1997,2003,2014,2017 Gary A Kunkel - -The xb64 software library is covered under -the terms of the GPL Version 3, 2007 license. - -Email Contact: - - xb64-devel@lists.sourceforge.net - xb64-users@lists.sourceforge.net - -*/ - -#include -using namespace xb; - -int main(int ac,char** av) -{ - if (ac <= 1) { - std::cout << - "\nUsage: zap filename...\n" - "\nThis program does not automatically reindex any indices." - "\nUse the reindex program to reindex any indexes associated" - "\nwith the database, or build your own program which executes " - "\nthe PackDatabase() method after opening all the index files " - "\nassociated with the database.\n\n" - ; - return 1; - } - - xbXBase x; - xbInt16 iRc; - xbDbf *MyFile = NULL; - - if(( iRc = x.OpenHighestVersion( av[1], "", &MyFile )) != XB_NO_ERROR ){ - std::cout << "Could not open file " << av[1] << std::endl; - return iRc; - } - - if(( iRc = MyFile->Zap()) != XB_NO_ERROR ) { - std::cout << "\nError packing DBF database ==> " << av[1] << std::endl; - std::cout << " Return Code = " << iRc << std::endl; - } - MyFile->Close(); - delete MyFile; - - std::cout << "\nZap Database complete..." << std::endl; - return 0; -} -- cgit v1.2.3