diff options
Diffstat (limited to 'src/sql')
-rwxr-xr-x | src/sql/xbalttbl.cpp | 120 | ||||
-rwxr-xr-x | src/sql/xbcrix.cpp | 301 | ||||
-rwxr-xr-x | src/sql/xbcrtbl.cpp | 274 | ||||
-rwxr-xr-x | src/sql/xbdelete.cpp | 148 | ||||
-rwxr-xr-x | src/sql/xbdrpix.cpp | 155 | ||||
-rwxr-xr-x | src/sql/xbdrptbl.cpp | 129 | ||||
-rwxr-xr-x | src/sql/xbinsert.cpp | 190 | ||||
-rwxr-xr-x | src/sql/xbselect.cpp | 97 | ||||
-rwxr-xr-x | src/sql/xbset.cpp | 90 | ||||
-rwxr-xr-x | src/sql/xbsql.cpp | 176 | ||||
-rwxr-xr-x | src/sql/xbstmt.cpp | 679 |
11 files changed, 2359 insertions, 0 deletions
diff --git a/src/sql/xbalttbl.cpp b/src/sql/xbalttbl.cpp new file mode 100755 index 0000000..8a36b46 --- /dev/null +++ b/src/sql/xbalttbl.cpp @@ -0,0 +1,120 @@ +/* xbslttbl.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{ + + +/***********************************************************************/ +xbInt16 xbSql::SqlAlterTable( const xbString &sCmdLine ){ + + // expected format: + // ALTER TABLE tablename.DBF RENAME TO newtablename.DBF + + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbString sTableName = ""; + xbUInt32 ulPos = 0; + xbString sCmd = sCmdLine; + xbString sNode = ""; + + xbString sSrcTbl; + xbString sTrgTbl; + xbDbf * dbf = NULL; + + try{ + +// std::cout << "xbSql::SqlAlterTable( " << sCmdLine.Str() << " )\n"; + + // drop off the first node "DROP" + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + // drop off the second node "TABLE" + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + // pull off the source table + sSrcTbl.ExtractElement( sCmd, ' ', 1, 0 ); + sSrcTbl.Trim(); + + // pull off the action + sNode.ExtractElement( sCmd, ' ', 2, 0 ); + sNode.Trim(); + sNode.ToUpperCase(); + if( sNode != "RENAME" ){ + iErrorStop = 100; + iRc = XB_SYNTAX_ERROR; + throw iRc; + } + + // pull off "TO" + sNode.ExtractElement( sCmd, ' ', 3, 0 ); + sNode.Trim(); + sNode.ToUpperCase(); + if( sNode != "TO" ){ + iErrorStop = 110; + iRc = XB_SYNTAX_ERROR; + throw iRc; + } + + sTrgTbl.ExtractElement( sCmd, ' ', 4, 0 ); + sTrgTbl.Trim(); + +// 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 ){ + if(( iRc = xbase->OpenHighestVersion( sSrcTbl, "", &dbf )) != XB_NO_ERROR ){ + iErrorStop = 120; + throw iRc; + } + } + if( !dbf ){ + iErrorStop = 130; + iRc = XB_DBF_FILE_NOT_OPEN; + throw iRc; + } + + if(( iRc = dbf->Rename( sTrgTbl )) != XB_NO_ERROR ){ + iErrorStop = 140; + throw iRc; + } + + } + + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbSql::SqlAlterTable() Exception Caught. Error Stop = [%d] rc = [%d] table = [%s]", iErrorStop, iRc, sTableName.Str() ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + + return iRc; +} + +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/sql/xbcrix.cpp b/src/sql/xbcrix.cpp new file mode 100755 index 0000000..8efdc39 --- /dev/null +++ b/src/sql/xbcrix.cpp @@ -0,0 +1,301 @@ +/* xbcrix.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{ + + +/***********************************************************************/ +#ifdef XB_INDEX_SUPPORT +xbInt16 xbSql::SqlCreateIndex( const xbString &sCmdLine ){ + + // std::cout << "CREATE INDEX " << sCmdLine << std::endl; + + // expected format to create an Dbase 3, NDX index: + // CREATE INDEX ixname.ndx ON tablename.dbf ( EXPRESSION ) [ASSOCIATE] + + // expected format to create an Dbase 4, tag on an MDX index: + // CREATE [UNIQUE] INDEX tagname ON tablename.dbf ( EXPRESSION ) [DESC] [FILTER .NOT. DELETED()] + + // The ASSOCIATE parameter is specific to Xbase64 library, it is used to associate + // a non production (NDX) index file to a dbf file so it will be automatically + // opened with the dbf file whenever the dbf file is opened by the xbase64 routines. + + // The [ASSOCIATE] parameter is not used with MDX production indices + + // This method first looks for ".NDX" in the file name to determine if an NDX + // index should be created. + // if .NDX is not in the filename, it looks in the uda for "IXTYPE" for either + // NDX or MDX to detmermine the index type to create + // if IXTYPE not found, create an MDX tag + + // The optional DESC parameter defines an entire index key as descending. This is + // different than other SQL implementations where specific fields can be descending. + + // The optional FILTER parameter is specific to the XBASE64 library, is it used to + // assign a filter to a tag in an MDX style index. Everything to the right of + // the keyword FILTER is considered part of the filter. + + // The original DBASE indices used to '+' to create an index on more than one field + // ie: FIELD1+FIELD2+FIELD3 + // SQL uses commas: ie: FIELD1, FIELD2, FIELD3 + // The Xbase library supports either '+' or ',' when creating mutli field indices. + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbString sTableName; + xbString sIxName; + xbString sIxType; + xbUInt32 ulPos; + xbString sCmd = sCmdLine; + xbString sNode; + xbBool bUnique = xbFalse; + xbDbf * dbf = NULL; + xbBool bTableLocked = xbFalse; + + try{ + + // drop off the first node + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + sNode.ExtractElement( sCmd, ' ', 1, 0 ); + sNode.ToUpperCase(); + + if( sNode == "UNIQUE" ){ + //std::cout << "unique ix\n"; + bUnique = xbTrue; + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + } + + // go past the index keyword + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + // pull the index name off the cmd line + sIxName.ExtractElement( sCmd, ' ', 1, 0 ); + + #ifdef XB_NDX_SUPPORT + xbString sTemp = sIxName; + sTemp.ToUpperCase(); + ulPos = sTemp.Pos( ".NDX" ); + if(ulPos == (sTemp.Len() - 3) ) + sIxType = "NDX"; + #endif // XB_NDX_SUPPORT + + if( sIxType == "" ){ + if(( iRc = uda.GetTokenForKey( "IXTYPE", sIxType )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } + + #ifdef XB_NDX_SUPPORT + if( sIxType == "NDX" ){ + xbFile f( xbase ); + f.SetFileName( sIxName ); + if( f.FileExists()){ + + iErrorStop = 110; + iRc = XB_FILE_EXISTS; + throw iRc; + } + } + #endif // XB_NDX_SUPPORT + + // skip past index name + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + // skip past "ON" + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + // get the table name + ulPos = sCmd.Pos( '(' ); + sTableName.ExtractElement( sCmd, '(', 1, 0 ); + sTableName.Trim(); + + xbFile fDbf( xbase ); + fDbf.SetFileName( sTableName ); + + // if not open, attempt to open it + dbf = xbase->GetDbfPtr( fDbf.GetFqFileName()); + + if( !dbf ){ + if(( iRc = xbase->OpenHighestVersion( sTableName, "", &dbf )) != XB_NO_ERROR ){ + iErrorStop = 120; + throw iRc; + } + } + + if( dbf == NULL ){ + iErrorStop = 130; + iRc = XB_FILE_NOT_FOUND; + throw iRc; + } + sCmd.Ltrunc( ulPos ); + + //ulPos = sCmd.GetLastPos( ')' ); + xbString sKeyExpression; + xbBool bDone = xbFalse; + xbUInt32 lPos = 1; + xbInt16 iParenCtr = 0; + + while( !bDone && lPos < sCmd.Len()){ + if( sCmd[lPos] == '(' ){ + iParenCtr++; + sKeyExpression.Append( sCmd[lPos] ); + } else if( sCmd[lPos] == ')' ){ + if( iParenCtr > 0 ){ + iParenCtr--; + sKeyExpression.Append( sCmd[lPos] ); + } else { + bDone = xbTrue; + } + } else if( sCmd[lPos] == ',' && iParenCtr == 0 ){ + sKeyExpression.Append( '+' ); + } else if( sCmd[lPos] != ' ' ){ + sKeyExpression.Append( sCmd[lPos] ); + } + lPos++; + } + + // std::cout << "Key Expression =[" << sKeyExpression << "]\n"; + sCmd.Ltrunc( lPos ); + sCmd.Trim(); + + xbBool bDesc = xbFalse; + // std::cout << "sCmd - looking for DESC [" << sCmd << "]\n"; + if( sCmd.Len() > 4 ){ + sNode = sCmd; + sNode.ToUpperCase(); + ulPos = sNode.Pos( "DESC" ); + if( ulPos > 0 ){ + bDesc = xbTrue; + sCmd.Ltrunc( 4 ); + sCmd.Trim(); + std::cout << "Descending\n"; + } + } + + // std::cout << "sCmd - looking for FILTER stuff [" << sCmd << "]\n"; + xbString sFilter; + if( sCmd.Len() > 6 ){ + sNode = sCmd; + sNode.ToUpperCase(); + ulPos = sNode.Pos( "FILTER" ); + if( ulPos > 0 ){ + sFilter = sCmd; + sFilter.Ltrunc( ulPos + 6 ); + sFilter.Trim(); + } + } + // std::cout << "sCmd - FILTER = [" << sFilter << "]\n"; + + #ifdef XB_LOCKING_SUPPORT + if(( iRc = dbf->LockTable( XB_LOCK )) != XB_NO_ERROR ){ + iErrorStop = 140; + throw iRc; + } else { + bTableLocked = xbTrue; + } + #endif // XB_LOCKING_SUPPORT + + xbIx *pIx; + void *vpTag; + + if(( iRc = dbf->CreateTag( sIxType, sIxName, sKeyExpression, sFilter, bDesc, bUnique, xbFalse, &pIx, &vpTag )) != XB_NO_ERROR ){ + iErrorStop = 150; + throw iRc; + } + + #ifdef XB_NDX_SUPPORT + xbBool bAssociate = xbFalse; + if( sIxType == "NDX"){ + sCmd.Ltrunc( ulPos ); + sCmd.Trim(); + if( sCmd.Len() > 0 ){ + sCmd.ToUpperCase(); + if( sCmd.Pos( "ASSOCIATE" )){ + bAssociate = xbTrue; + if(( iRc = dbf->AssociateIndex( "NDX", sIxName, 0 )) != XB_NO_ERROR ){ + iErrorStop = 160; + throw iRc; + } + } + } + } + #endif // XB_NDX_SUPPORT + + iRc = dbf->Reindex( 2, 1, &pIx, &vpTag ); + + #ifdef XB_NDX_SUPPORT + if( iRc != XB_NO_ERROR && sIxType == "NDX" && bAssociate ){ + xbInt16 iRc2; + if(( iRc2 = dbf->AssociateIndex( "NDX", sIxName, 1 )) != XB_NO_ERROR ){ + iErrorStop = 180; + throw iRc2; + } + iErrorStop = 190; + throw iRc; + } + #endif // XB_NDX_SUPPORT + + if( iRc != XB_NO_ERROR ){ + iErrorStop = 200; + throw iRc; + } + + + #ifdef XB_LOCKING_SUPPORT + if( bTableLocked ){ + if(( iRc = dbf->LockTable( XB_UNLOCK )) != XB_NO_ERROR ){ + iErrorStop = 210; + throw iRc; + } else { + bTableLocked = xbFalse; + } + } + #endif // XB_LOCKING_SUPPORT + + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbSql::SqlCreateIndex() Exception Caught. Error Stop = [%d] rc = [%d] table = [%s]", iErrorStop, iRc, sTableName.Str() ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + #ifdef XB_LOCKING_SUPPORT + if( bTableLocked && dbf ) + dbf->LockTable( XB_UNLOCK ); + #endif // XB_LOCKING_SUPPORT + + return iRc; +} +#endif // XB_INDEX_SUPPORT +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/sql/xbcrtbl.cpp b/src/sql/xbcrtbl.cpp new file mode 100755 index 0000000..e22b0b5 --- /dev/null +++ b/src/sql/xbcrtbl.cpp @@ -0,0 +1,274 @@ +/* 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; + xbString sWork; + + try{ + // retrieve table name + s.ExtractElement( sCmdLine, '(', 1, 0 ); + sTableName.ExtractElement( s, ' ', 3, 0 ); + sTableName.Trim(); + +// std::cout << "Create table - Tablename = [" << sTableName.Str() << "]\n"; +// std::cout << "Cm line = [" << sCmdLine.Str() << "]\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(); + + 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 = 120; + iRc = XB_INVALID_FIELD_LEN; + throw iRc; + } + 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(); + 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 = 150; + 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 new file mode 100755 index 0000000..9bd4279 --- /dev/null +++ b/src/sql/xbdelete.cpp @@ -0,0 +1,148 @@ +/* xbdelete.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{ + + +/***********************************************************************/ +xbInt16 xbSql::SqlDelete( const xbString &sCmdLine ){ + + // expected format: + // DELETE FROM tablename.DBF [WHERE expression] + + + xbInt16 iRc = 0; + xbInt16 iRc2 = 0; + xbInt16 iErrorStop = 0; + xbString sTableName = ""; + xbUInt32 ulPos = 0; + xbString sCmd = sCmdLine; + xbString sNode = ""; + xbString sFilter; + xbInt16 iDelOpt = 0; + + xbString sTable; + xbDbf * dbf = NULL; + + try{ + +// std::cout << "xbSql::SqlDelete( " << sCmdLine.Str() << " )\n"; + + sNode.ExtractElement( sCmd, ' ', 1, 0 ); + sNode.Trim(); + sNode.ToUpperCase(); + if( sNode == "UNDELETE" ) + iDelOpt = 1; + + // pull off the action + sNode.ExtractElement( sCmd, ' ', 2, 0 ); + sNode.Trim(); + sNode.ToUpperCase(); + if( sNode != "FROM" ){ + iErrorStop = 100; + iRc = XB_SYNTAX_ERROR; + throw iRc; + } + + // pull off the table name + sTable.ExtractElement( sCmd, ' ', 3, 0 ); + sTable.Trim(); + + // pull off the "WHERE" statement if it exists + sNode.ExtractElement( sCmd, ' ', 4, 0 ); + sNode.Trim(); + sNode.ToUpperCase(); + if( sNode == "WHERE" ){ + ulPos = sCmd.Pos( "WHERE" ); + sFilter = sCmd; + sFilter.Ltrunc( ulPos + 5 ); + } + + // if not open, attempt to open it + dbf = xbase->GetDbfPtr( sTable ); + if( !dbf ){ + if(( iRc = xbase->OpenHighestVersion( sTable, "", &dbf )) != XB_NO_ERROR ){ + iErrorStop = 110; + throw iRc; + } + } + if( !dbf ){ + iErrorStop = 120; + iRc = XB_DBF_FILE_NOT_OPEN; + throw iRc; + } + + if( sFilter == "" ){ + if(( iRc = dbf->DeleteAll( iDelOpt )) != XB_NO_ERROR ){ + iErrorStop = 130; + throw iRc; + } + } else { + + xbFilter f( dbf ); + if(( iRc = f.Set( sFilter )) != XB_NO_ERROR ){ + iErrorStop = 150; + throw iRc; + } + + iRc2 = f.GetFirstRecord( XB_ALL_RECS ); + while( iRc2 == XB_NO_ERROR ){ + if( iDelOpt == 0 ){ + if( !dbf->RecordDeleted()){ + if(( iRc = dbf->DeleteRecord()) != XB_NO_ERROR ){ + iErrorStop = 160; + throw iRc; + } + if(( iRc = dbf->Commit()) != XB_NO_ERROR ){ + iErrorStop = 170; + throw iRc; + } + } + + } else { // undelete + if( dbf->RecordDeleted()){ + if(( iRc = dbf->UndeleteRecord()) != XB_NO_ERROR ){ + iErrorStop = 180; + throw iRc; + } + if(( iRc = dbf->Commit()) != XB_NO_ERROR ){ + iErrorStop = 190; + throw iRc; + } + } + } + iRc2 = f.GetNextRecord(); + } + } + } + + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbSql::SqlDelete() Exception Caught. Error Stop = [%d] rc = [%d] table = [%s]", iErrorStop, iRc, sTableName.Str() ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + + return iRc; +} + +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/sql/xbdrpix.cpp b/src/sql/xbdrpix.cpp new file mode 100755 index 0000000..2815264 --- /dev/null +++ b/src/sql/xbdrpix.cpp @@ -0,0 +1,155 @@ +/* xbdrpix.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{ + +#ifdef XB_INDEX_SUPPORT +/***********************************************************************/ +xbInt16 xbSql::SqlDropIndex( const xbString &sCmdLine ){ + + // std::cout << "DROP INDEX [" << sCmdLine << "]\n"; + + // expected format: + // DROP INDEX [IF EXISTS] ixname.ndx ON tablename.dbf + + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbString sTableName; + xbString sIxName; + xbUInt32 ulPos; + xbString sCmd = sCmdLine; + xbString sNode; + xbBool bIfExists = xbFalse; + xbDbf * dbf = NULL; + + try{ + + // drop off the first node "DROP" + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + // drop off the second node "INDEX" + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + sNode.ExtractElement( sCmd, ' ', 1, 0 ); + sNode.Trim(); + sNode.ToUpperCase(); + + if( sNode == "IF" ){ + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + sNode.ExtractElement( sCmd, ' ', 1, 0 ); + sNode.Trim(); + sNode.ToUpperCase(); + if( sNode != "EXISTS" ){ + iErrorStop = 100; + iRc = XB_SYNTAX_ERROR; + throw iRc; + } else { + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + bIfExists = xbTrue; + } + } + + // get the index name + sIxName.ExtractElement( sCmd, ' ', 1, 0 ); + sIxName.Trim(); + + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + // go past "ON" + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + sTableName = sCmd; + sTableName.Trim(); + + xbFile fDbf( xbase ); + fDbf.SetFileName( sTableName ); + + // if not open, attempt to open it + dbf = xbase->GetDbfPtr( fDbf.GetFqFileName()); + if( !dbf ){ + if(( iRc = xbase->OpenHighestVersion( sTableName, "", &dbf )) != XB_NO_ERROR ){ + iErrorStop = 110; + throw iRc; + } + } + if( dbf == NULL ){ + iErrorStop = 120; + iRc = XB_FILE_NOT_FOUND; + throw iRc; + } + + #ifdef XB_LOCKING_SUPPORT + if(( iRc = dbf->LockTable( XB_LOCK )) != XB_NO_ERROR ){ + iErrorStop = 130; + throw iRc; + } + #endif // XB_LOCKING_SUPPORT + + ulPos = sIxName.Pos( ".NDX" ); + if( ulPos > 0 ){ + iRc = dbf->DeleteTag( "NDX", sIxName ); + if( iRc == XB_FILE_NOT_FOUND && !bIfExists ){ + iErrorStop = 140; + throw( iRc ); + } else if( iRc != XB_NO_ERROR ){ + iErrorStop = 150; + throw iRc; + } + } else { // assuming MDX tag + iRc = dbf->DeleteTag( "MDX", sIxName ); + if( iRc == XB_FILE_NOT_FOUND && !bIfExists ){ + iErrorStop = 160; + throw( iRc ); + } else if( iRc != XB_NO_ERROR ){ + iErrorStop = 170; + throw iRc; + } + } + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbSql::SqlDropIndex() Exception Caught. Error Stop = [%d] rc = [%d] table = [%s]", iErrorStop, iRc, sTableName.Str() ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + + #ifdef XB_LOCKING_SUPPORT + dbf->LockTable( XB_UNLOCK ); + #endif // XB_LOCKING_SUPPORT + + return iRc; +} +#endif // XB_INDEX_SUPPORT +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/sql/xbdrptbl.cpp b/src/sql/xbdrptbl.cpp new file mode 100755 index 0000000..ee3e325 --- /dev/null +++ b/src/sql/xbdrptbl.cpp @@ -0,0 +1,129 @@ +/* xbdrptbl.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 + +*/ + +#include "xbase.h" + +#ifdef XB_SQL_SUPPORT + +namespace xb{ + + +/***********************************************************************/ +xbInt16 xbSql::SqlDropTable( const xbString &sCmdLine ){ + + // std::cout << "DROP TABLE [" << sCmdLine << "]\n"; + // expected format: + // DROP TABLE [IF EXISTS] tablename.dbf + + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbString sTableName = ""; + xbUInt32 ulPos = 0; + xbString sCmd = sCmdLine; + xbString sNode = ""; + xbBool bIfExists = xbFalse; + xbDbf * dbf = NULL; + + try{ + + // drop off the first node "DROP" + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + // drop off the second node "TABLE" + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + sNode.ExtractElement( sCmd, ' ', 1, 0 ); + sNode.Trim(); + sNode.ToUpperCase(); + + if( sNode == "IF" ){ + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + sNode.ExtractElement( sCmd, ' ', 1, 0 ); + sNode.Trim(); + sNode.ToUpperCase(); + if( sNode != "EXISTS" ){ + iErrorStop = 100; + iRc = XB_SYNTAX_ERROR; + throw iRc; + } else { + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + bIfExists = xbTrue; + } + } + + // get the table name + sTableName.ExtractElement( sCmd, ' ', 1, 0 ); + sTableName.Trim(); + + xbFile fDbf( xbase ); + fDbf.SetFileName( sTableName ); + + if( bIfExists && ! fDbf.FileExists()) + return XB_NO_ERROR; + + // if not open, attempt to open it + dbf = xbase->GetDbfPtr( fDbf.GetFqFileName()); + + if( !dbf ){ + + //dbf = xbase->Open( sTableName, iRc ); + iRc = xbase->OpenHighestVersion( sTableName, "", &dbf ); + if( iRc != XB_NO_ERROR ){ + if( iRc == XB_FILE_NOT_FOUND && bIfExists ){ + return XB_NO_ERROR; + } else { + iErrorStop = 110; + throw iRc; + } + } + } + if( dbf == NULL ){ + iErrorStop = 120; + iRc = XB_OPEN_ERROR; + throw iRc; + } + + if(( dbf->DeleteTable()) != XB_NO_ERROR ){ + iErrorStop = 130; + throw iRc; + } + + delete dbf; + // dbf = NULL; + } + + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbSql::SqlDropTable() Exception Caught. Error Stop = [%d] rc = [%d] table = [%s]", iErrorStop, iRc, sTableName.Str() ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + + return iRc; +} + +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/sql/xbinsert.cpp b/src/sql/xbinsert.cpp new file mode 100755 index 0000000..835f9e6 --- /dev/null +++ b/src/sql/xbinsert.cpp @@ -0,0 +1,190 @@ +/* xbinsert.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{ + + +/***********************************************************************/ +xbInt16 xbSql::SqlInsert( const xbString &sCmdLine ){ + + // expected format: + // INSERT INTO tablename (field1, field2, field3,...) VALUES ( 'charval', numval, 'what is the correct odbc date format to use? CCYYMMDD'); + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbString sTableName; + xbDbf * dbf = NULL; + + xbString sWork1; + xbString sFieldList; + xbString sDataList; + xbString sFieldName; + xbString sFieldData; + + // queue the memo data to post after the append occurs + // dbase does not support usage of memo fields with insert commands + xbLinkList <xbInt16> llMemoFieldNos; + xbLinkList <xbString> llMemoFieldData; + + try{ + // retrieve table name + sTableName.ExtractElement( sCmdLine, ' ', 3, 0 ); + sTableName.Trim(); + + // if not open, attempt to open it + dbf = xbase->GetDbfPtr( sTableName ); + + if( !dbf ){ + if(( iRc = xbase->OpenHighestVersion( sTableName, "", &dbf )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } + + if( !dbf ){ + iErrorStop = 110; + iRc = XB_FILE_NOT_FOUND; + throw iRc; + } + + // blank the record buffer + dbf->BlankRecord(); + + sWork1.ExtractElement( sCmdLine, ')', 1, 0 ); + sFieldList.ExtractElement( sWork1, '(', 2, 0 ); + + sDataList.ExtractElement( sCmdLine, '(', 3, 0 ); + sDataList.Trim(); + sDataList.ZapTrailingChar( ')' ); + + xbUInt32 iFldCnt = sFieldList.CountChar( ',' ); + xbUInt32 iDataCnt = sDataList.CountChar( ',', 1 ); + + // verify there are the same count in the field list and values list + if( iFldCnt != iDataCnt ){ + iErrorStop = 120; + iRc = XB_SYNTAX_ERROR; + throw iRc; + } + + iFldCnt++; + xbInt16 iFldNo = -1; + char cFldType = 0x00; + for( xbUInt32 i = 1; i <= iFldCnt; i++ ){ + sFieldName.ExtractElement( sFieldList, ',', i, 0 ); + sFieldName.Trim(); + if(( iRc = dbf->GetFieldNo( sFieldName, iFldNo )) != XB_NO_ERROR ){ + iErrorStop = 130; + throw iRc; + } + if(( iRc = dbf->GetFieldType( iFldNo, cFldType )) != XB_NO_ERROR ){ + iErrorStop = 140; + throw iRc; + } + + // get the field data here + sFieldData.ExtractElement( sDataList, ',', i, 1 ); + sFieldData.Trim(); + + // remove beginning and ending quotes + if(( sFieldData[1] == '\'' && sFieldData[sFieldData.Len()] == '\'') || (sFieldData[1] == '"' && sFieldData[sFieldData.Len()] == '"' )){ + sFieldData.Remove( sFieldData.Len(), 1 ); + sFieldData.Remove( 1, 1 ); + } + + switch( cFldType ){ + case 'C': + case 'N': + case 'L': + if(( iRc = dbf->PutField( iFldNo, sFieldData )) != XB_NO_ERROR ){ + iErrorStop = 150; + throw iRc; + } + break; + + case 'D': + // assumes input date format of yyyy-mm-dd + if( sFieldData.Len() != 10 || sFieldData[5] != '-' || sFieldData[8] != '-' ){ + iErrorStop = 160; + iRc = XB_INVALID_DATA; + throw iRc; + } + sWork1 = sFieldData; + sWork1.Remove( 8, 1 ); + sWork1.Remove( 5, 1 ); + if(( iRc = dbf->PutField( iFldNo, sWork1 )) != XB_NO_ERROR ){ + iErrorStop = 170; + throw iRc; + } + break; + + case 'M': + llMemoFieldNos.InsertAtFront( iFldNo ); + llMemoFieldData.InsertAtFront( sFieldData ); + break; + + default: + iErrorStop= 180; + iRc = XB_INVALID_FIELD_TYPE; + throw iRc; + } + } + + if(( iRc = dbf->AppendRecord()) != XB_NO_ERROR ){ + iErrorStop = 190; + throw iRc; + } + + // Add any memo fields + xbLinkListNode<xbInt16> * llN = llMemoFieldNos.GetHeadNode(); + xbLinkListNode<xbString> * llD = llMemoFieldData.GetHeadNode(); + xbUInt32 ulCnt = llMemoFieldNos.GetNodeCnt(); + for( xbUInt32 i = 0; i < ulCnt; i++ ){ + iFldNo = llN->GetKey(); + sFieldData = llD->GetKey(); + if(( iRc = dbf->UpdateMemoField( iFldNo, sFieldData )) != XB_NO_ERROR ){ + iErrorStop = 200; + throw iRc; + } + llN = llN->GetNextNode(); + llD = llD->GetNextNode(); + } + + if(( iRc = dbf->Commit()) != XB_NO_ERROR ){ + iErrorStop = 210; + throw iRc; + } + } + catch (xbInt16 iRc ){ + xbString sMsg; + xbase->WriteLogMessage( sCmdLine ); + sMsg.Sprintf( "xbSql::SqlInsert() Exception Caught. Error Stop = [%d] rc = [%d] table = [%s] field = [%s] data = [%s]", iErrorStop, iRc, sTableName.Str(), sFieldName.Str(), sFieldData.Str() ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + if( dbf ) + dbf->Abort(); + } + return iRc; + +} + +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/sql/xbselect.cpp b/src/sql/xbselect.cpp new file mode 100755 index 0000000..7f12e99 --- /dev/null +++ b/src/sql/xbselect.cpp @@ -0,0 +1,97 @@ +/* xbset.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{ + + +/***********************************************************************/ +xbInt16 xbStmt::ExecuteQuery( const xbString &sCmdLine ){ + + std::cout << "xbStmt::ExecuteQuery() - SELECT [" << sCmdLine << "]\n"; + // expected format: + // SELECT + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + // xbUInt32 ulPos; + + try{ + + if(( iRc = ParseStmt( sCmdLine )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + +/* + xbString sCmd = sCmdLine; + sCmd.Trim(); + sCmd.ZapTrailingChar( ';' ); + sCmd.Trim(); + + // drop off the first node "SET" + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + xbString sNode1 = sCmd; + sNode1.ToUpperCase(); + + if( sNode1 == "SET" ) { + uda.DumpUda(); + + } else { + + xbString sKey; + sKey.ExtractElement( sCmd, '=', 1, 0 ); + sKey.Trim(); + + xbString sToken; + sToken.ExtractElement( sCmd, '=', 2, 0 ); + sToken.Trim(); + + + if( sToken == '^' ){ + if(( iRc = uda.DelTokenForKey( sKey )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } else { + if(( iRc = uda.UpdTokenForKey( sKey, sToken )) != XB_NO_ERROR ){ + iErrorStop = 110; + throw iRc; + } + } + } +*/ + + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbStmt::ExecuteQuery() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + + return iRc; +} + +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/sql/xbset.cpp b/src/sql/xbset.cpp new file mode 100755 index 0000000..d0e8821 --- /dev/null +++ b/src/sql/xbset.cpp @@ -0,0 +1,90 @@ +/* xbset.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{ + + +/***********************************************************************/ +xbInt16 xbSql::SqlSet( const xbString &sCmdLine ){ + + // std::cout << "SET [" << sCmdLine << "]\n"; + // expected format: + // SET ATTRIBUTE = DATAVALUE + // SET ATTRIBUTE = ^ (to delete an entry) + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbUInt32 ulPos; + + try{ + + xbString sCmd = sCmdLine; + sCmd.Trim(); + sCmd.ZapTrailingChar( ';' ); + sCmd.Trim(); + + // drop off the first node "SET" + ulPos = sCmd.Pos( ' ' ); + sCmd.Ltrunc( ulPos ); + sCmd.Ltrim(); + + xbString sNode1 = sCmd; + sNode1.ToUpperCase(); + + if( sNode1 == "SET" ) { + uda.DumpUda(); + + } else { + + xbString sKey; + sKey.ExtractElement( sCmd, '=', 1, 0 ); + sKey.Trim(); + + xbString sToken; + sToken.ExtractElement( sCmd, '=', 2, 0 ); + sToken.Trim(); + + + if( sToken == '^' ){ + if(( iRc = uda.DelTokenForKey( sKey )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } else { + if(( iRc = uda.UpdTokenForKey( sKey, sToken )) != XB_NO_ERROR ){ + iErrorStop = 110; + throw iRc; + } + } + } + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbSql::SqlSet() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + + return iRc; +} + +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/sql/xbsql.cpp b/src/sql/xbsql.cpp new file mode 100755 index 0000000..12d3379 --- /dev/null +++ b/src/sql/xbsql.cpp @@ -0,0 +1,176 @@ +/* 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{ + +/***********************************************************************/ +xbSql::xbSql( xbXBase *x ){ + xbase = x; + xbString sIxType; + + #ifdef XB_MDX_SUPPORT + sIxType = "MDX"; + #endif + + #ifdef XB_NDX_SUPPORT + if( sIxType == "" ) + sIxType = "NDX"; + #endif + + if( sIxType != "" ) + uda.AddTokenForKey( "IXTYPE", sIxType ); + +} +/***********************************************************************/ +xbSql::~xbSql(){ +} + +/***********************************************************************/ +xbInt16 xbSql::ExecuteNonQuery( const xbString &sCmdLine ) { + +// std::cout << "\n\n\nExecute() " << sCmdLine.Str() << "\n"; + + xbInt16 iRc = XB_NO_ERROR; + xbString sCmd = sCmdLine; + + sCmd.Trim(); + xbString sNode1; + sNode1.ExtractElement( sCmd.Str(), ' ', 1, 0 ); + sNode1.ToUpperCase(); + sNode1.Trim(); + +// std::cout << "node 1 = " << sNode1.Str() << std::endl; + + if( sNode1 == "ALTER" ){ + xbString sNode2; + sNode2.ExtractElement( sCmd.Str(), ' ', 2, 0 ); + sNode2.ToUpperCase(); + sNode2.Trim(); + + if( sNode2 == "TABLE" ) + iRc = SqlAlterTable( sCmd ); + else + iRc = XB_INVALID_FUNCTION; + + + + } else if( sNode1 == "CREATE" ){ + + xbString sNode2; + sNode2.ExtractElement( sCmd.Str(), ' ', 2, 0 ); + sNode2.ToUpperCase(); + sNode2.Trim(); + if( sNode2 == "TABLE" ) + iRc = SqlCreateTable( sCmd ); + + #ifdef XB_INDEX_SUPPORT + else if( sNode2 == "INDEX" || sNode2 == "UNIQUE" ) + iRc = SqlCreateIndex( sCmd ); + #endif // XB_INDEX_SUPPORT + + else + iRc = XB_INVALID_FUNCTION; + + } else if( sNode1 == "DROP" ){ + + xbString sNode2; + sNode2.ExtractElement( sCmd.Str(), ' ', 2, 0 ); + sNode2.ToUpperCase(); + sNode2.Trim(); + + if( sNode2 == "TABLE" ) + iRc = SqlDropTable( sCmd ); + + #ifdef XB_INDEX_SUPPORT + else if( sNode2 == "INDEX" ) + iRc = SqlDropIndex( sCmd ); + #endif // XB_INDEX_SUPPORT + + else + iRc = XB_INVALID_FUNCTION; + + } else if( sNode1 == "DELETE" || sNode1 == "UNDELETE" ){ + + iRc = SqlDelete( sCmd ); + + + } else if( sNode1 == "HELP" ) + SqlHelp(); + + else if( sNode1 == "INSERT" ){ + iRc = SqlInsert( sCmd ); + + // else if( sNode1 == "UPDATE" ) + // iRc = SqlUpdate( sCmd ); + } + + else if( sNode1 == "USE" ) + iRc = SqlUse( sCmd ); + + else if( sNode1 == "SET" ) + iRc = SqlSet( sCmd ); + + else + return XB_INVALID_FUNCTION; + + return iRc; +} + +/***********************************************************************/ +xbXBase *xbSql::GetXbasePtr() const { + return xbase; +} + + +/***********************************************************************/ +void xbSql::SqlHelp() const { + std::cout << "************************" << std::endl; + std::cout << "Valid XBase SQL commands" << std::endl << std::endl; + std::cout << "HELP" << std::endl; + + std::cout << "ALTER TABLE tablename.DBF RENAME TO newtablename.DBF" << std::endl; + std::cout << "CREATE INDEX ixname.NDX ON tablename.dbf ( EXPRESSION ) [ASSOCIATE]" << std::endl; + std::cout << "CREATE [UNIQUE] INDEX tagname ON tablename.dbf ( EXPRESSION ) [DESC] [FILTER .NOT. DELETED()]" << std::endl; + std::cout << "CREATE TABLE tablename.DBF (Field1 CHAR(10), INTFLD1 INTEGER, ... )" << std::endl; + std::cout << "DELETE FROM tablename.DBF [WHERE expression]" << std::endl; + std::cout << "DROP INDEX [IF EXISTS] ixname.NDX ON tablename.DBF" << std::endl; + std::cout << "DROP TABLE [IF EXISTS] tablename.DBF" << std::endl; + std::cout << "INSERT INTO tablename (field1, field2, field3,...) VALUES ( 'charval', numval, {MM/DD/YY})" << std::endl; + std::cout << "SELECT FIELD1,FIELD2... FROM TABLE.DBF [WHERE expression] [ORDER BY TAG TAGNAME" << std::endl; + std::cout << "SET ATTRIBUTE = DATAVALUE" << std::endl; + std::cout << "SET ATTRIBUTE = ^ (to delete an entry)" << std::endl; + std::cout << "USE /dir/to/dbf/tables" << std::endl; + std::cout << "CREATE TABLE" << std::endl << std::endl << std::endl; +} + +/***********************************************************************/ +xbInt16 xbSql::SqlUse( const xbString &sCmdLine ){ + + xbString sNode2; + sNode2.ExtractElement( sCmdLine.Str(), ' ', 2, 0 ); + sNode2.Trim(); + xbase->SetDataDirectory( sNode2 ); +// std::cout << "USE " << sNode2 << std::endl; + return XB_NO_ERROR; +} + +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + 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 */ + |