summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2023-03-11 18:15:37 +0100
committerJörg Frings-Fürst <debian@jff-webhosting.net>2023-03-11 18:15:37 +0100
commitdd70ff8bf32c2d7ed365004b1770058265db1978 (patch)
tree084788d142d86c4dc38f5c48606523b4040596e6 /src
parent517ad9d4b6eae320b708d03a9340a22893b0cab7 (diff)
New upstream version 4.1.0upstream/4.1.0
Diffstat (limited to 'src')
-rwxr-xr-xsrc/core/xbbcd.cpp5
-rwxr-xr-xsrc/core/xbblockread.cpp271
-rwxr-xr-xsrc/core/xbdbf.cpp154
-rwxr-xr-xsrc/core/xbdbf3.cpp8
-rwxr-xr-xsrc/core/xbdbf4.cpp19
-rwxr-xr-xsrc/core/xbexp.cpp31
-rwxr-xr-xsrc/core/xbfile.cpp286
-rwxr-xr-xsrc/core/xbfilter.cpp50
-rwxr-xr-xsrc/core/xbixmdx.cpp50
-rwxr-xr-xsrc/core/xbixndx.cpp3
-rwxr-xr-xsrc/core/xblog.cpp4
-rwxr-xr-xsrc/core/xbssv.cpp111
-rwxr-xr-xsrc/core/xbstring.cpp71
-rwxr-xr-xsrc/core/xbtblmgr.cpp85
-rwxr-xr-xsrc/core/xbxbase.cpp54
-rwxr-xr-xsrc/examples/xb_ex_expression.cpp4
-rwxr-xr-xsrc/examples/xb_ex_ssv.cpp134
-rwxr-xr-xsrc/examples/xb_ex_v4_upd_dbf.cpp6
-rwxr-xr-xsrc/include/xbase.h7
-rwxr-xr-xsrc/include/xbblkread.h70
-rwxr-xr-xsrc/include/xbconfig.h.in2
-rwxr-xr-xsrc/include/xbdate.h1
-rwxr-xr-xsrc/include/xbdbf.h37
-rwxr-xr-xsrc/include/xbfile.h4
-rwxr-xr-xsrc/include/xbfilter.h6
-rwxr-xr-xsrc/include/xbretcod.h5
-rwxr-xr-xsrc/include/xbsql.h78
-rwxr-xr-xsrc/include/xbssv.h31
-rwxr-xr-xsrc/include/xbstring.h2
-rwxr-xr-xsrc/include/xbtblmgr.h9
-rwxr-xr-xsrc/include/xbuda.h6
-rwxr-xr-xsrc/include/xbxbase.h10
-rwxr-xr-xsrc/sql/xbalttbl.cpp7
-rwxr-xr-xsrc/sql/xbcrix.cpp16
-rwxr-xr-xsrc/sql/xbcrtbl.cpp49
-rwxr-xr-xsrc/sql/xbcrtbl.save.cpp256
-rwxr-xr-xsrc/sql/xbdelete.cpp2
-rwxr-xr-xsrc/sql/xbdrptbl.cpp9
-rwxr-xr-xsrc/sql/xbselect.cpp17
-rwxr-xr-xsrc/sql/xbset.cpp5
-rwxr-xr-xsrc/sql/xbsql.cpp3
-rwxr-xr-xsrc/sql/xbstmt.cpp679
-rwxr-xr-xsrc/tests/xb_test_bcd.cpp5
-rwxr-xr-xsrc/tests/xb_test_blockread.cpp168
-rwxr-xr-xsrc/tests/xb_test_date.cpp7
-rwxr-xr-xsrc/tests/xb_test_dbf_v3_memos.cpp4
-rwxr-xr-xsrc/tests/xb_test_dbf_v3_nomemos.cpp10
-rwxr-xr-xsrc/tests/xb_test_dbf_v4_memos.cpp10
-rwxr-xr-xsrc/tests/xb_test_dbf_v4_nomemos.cpp29
-rwxr-xr-xsrc/tests/xb_test_expnode.cpp4
-rwxr-xr-xsrc/tests/xb_test_expression.cpp7
-rwxr-xr-xsrc/tests/xb_test_file.cpp3
-rwxr-xr-xsrc/tests/xb_test_filter.cpp8
-rwxr-xr-xsrc/tests/xb_test_funcs.cpp3
-rwxr-xr-xsrc/tests/xb_test_linklist.cpp8
-rwxr-xr-xsrc/tests/xb_test_lock.cpp4
-rwxr-xr-xsrc/tests/xb_test_lock2.cpp5
-rwxr-xr-xsrc/tests/xb_test_log.cpp15
-rwxr-xr-xsrc/tests/xb_test_mdx.cpp70
-rwxr-xr-xsrc/tests/xb_test_ndx.cpp15
-rwxr-xr-xsrc/tests/xb_test_sql.cpp151
-rwxr-xr-xsrc/tests/xb_test_string.cpp11
-rwxr-xr-xsrc/tests/xb_test_tblmgr.cpp81
-rwxr-xr-xsrc/tests/xb_test_uda.cpp9
-rwxr-xr-xsrc/tests/xb_test_xbase.cpp44
-rwxr-xr-xsrc/utils/xb_cfg_check.cpp84
-rwxr-xr-xsrc/utils/xb_copydbf.cpp78
-rwxr-xr-xsrc/utils/xb_dbfutil.cpp453
-rwxr-xr-xsrc/utils/xb_deletall.cpp54
-rwxr-xr-xsrc/utils/xb_dumpdbt.cpp54
-rwxr-xr-xsrc/utils/xb_dumphdr.cpp45
-rwxr-xr-xsrc/utils/xb_dumpix.cpp56
-rwxr-xr-xsrc/utils/xb_dumprecs.cpp60
-rwxr-xr-xsrc/utils/xb_execsql.cpp2
-rwxr-xr-xsrc/utils/xb_pack.cpp54
-rwxr-xr-xsrc/utils/xb_tblinfo.cpp105
-rwxr-xr-xsrc/utils/xb_undelall.cpp53
-rwxr-xr-xsrc/utils/xb_zap.cpp52
78 files changed, 3476 insertions, 1002 deletions
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.<br>
+
+ \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.<br><br>
+ For performance reasons, this method assumes a valid record number has been
+ passed.<br><br>
+
+ \param ulRecNo - Record number to retrieve.
+ \returns <a href="xbretcod_8h.html">Return Codes</a>
+*/
+
+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.<br><br>
+
+ \param ulRecNo - Record number to retrieve.
+ \returns <a href="xbretcod_8h.html">Return Codes</a>
+*/
+
+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.<br><br>
+
+ \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.<br><br>
+
+ \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.<br>
+ 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 <a href="xbretcod_8h.html">Return Codes</a>
+*/
+
+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.<br>.
+
+ \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();
}
/************************************************************************/
@@ -1952,6 +1968,18 @@ xbInt16 xbDbf::GetFirstKey(){
}
/************************************************************************/
+//! @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.
/*!
@@ -2054,6 +2082,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.
/*!
\returns Returns 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<xbString> * 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.
@@ -49,6 +49,119 @@ xbFile::~xbFile(){
}
/************************************************************************/
+//! @brief Create Home Folders.
+/*!
+ Create xbase64 log and data folders in the home directory for current usre.
+
+ \returns <a href="xbretcod_8h.html">Return Codes</a>
+*/
+
+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.
/*!
Given a directory and file extension as inputs, 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 <a href="xbretcod_8h.html">Return Codes</a>
*/
@@ -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 <a href="xbretcod_8h.html">Return Codes</a>
*/
-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 <a href="xbretcod_8h.html">Return Codes</a>
+*/
+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
@@ -63,6 +62,12 @@ void xbFilter::ResetQryCnt(){
}
/************************************************************************/
+xbInt16 xbFilter::Set( const char *sFilter ) {
+ xbString sFilt( sFilter );
+ return Set( sFilt );
+}
+
+/************************************************************************/
xbInt16 xbFilter::Set( xbString &sFilter ) {
xbInt16 iRc = XB_NO_ERROR;
@@ -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 <a href="xbretcod_8h.html">Return Codes</a>
*/
-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<br>
- 4 - Dbase IV file format<br>
-*/
-
-/*
-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
@@ -1267,6 +1267,45 @@ xbString &xbString::PadRight( char c, xbUInt32 ulNewLen ){
//! @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
+/*!
+ \param c Seek character
\returns Position within string. Returns 0 if not found.
*/
xbUInt32 xbString::Pos(char c) const {
@@ -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<br> 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<br> 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 <ctype.h>
#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
@@ -89,6 +93,7 @@ Email Contact:
#include <xbexp.h>
#include <xbtag.h>
+#include <xbblkread.h>
#include <xbdbf.h> /* dbf base class */
#include <xbindex.h> /* index base class */
#include <xbfilter.h>
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.<br>
+
+*/
+
+
+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<xbUInt32> 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<xbTag *> llTags; // linked list of open tags
+ #endif // XB_INDEX_SUPPORT
-#endif // XB_INDEX_SUPPORT
+ #ifdef XB_INF_SUPPORT
+ xbLinkList<xbString> 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<xbString> 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<xbTblJoin *> 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<xbString> 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<xbString> 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<xbString> 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<xbString> * 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<xbString> 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 <stdio.h>
#include <stdlib.h>
@@ -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 <xbase.h>
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 <xbase.h>
-
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 <xbase.h>
-
-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 <xbase.h>
-
-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 <xbase.h>
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 <xbase.h>
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 <xbase.h>
-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;
-}