diff options
Diffstat (limited to 'src/sql')
-rwxr-xr-x | src/sql/xbcrix.cpp | 279 | ||||
-rwxr-xr-x | src/sql/xbcrtbl.cpp | 256 | ||||
-rwxr-xr-x | src/sql/xbdrpix.cpp | 143 | ||||
-rwxr-xr-x | src/sql/xbdrptbl.cpp | 125 | ||||
-rwxr-xr-x | src/sql/xbinsert.cpp | 190 | ||||
-rwxr-xr-x | src/sql/xbset.cpp | 91 | ||||
-rwxr-xr-x | src/sql/xbsql.cpp | 143 |
7 files changed, 1227 insertions, 0 deletions
diff --git a/src/sql/xbcrix.cpp b/src/sql/xbcrix.cpp new file mode 100755 index 0000000..b24782e --- /dev/null +++ b/src/sql/xbcrix.cpp @@ -0,0 +1,279 @@ +/* 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{ + + +/***********************************************************************/ +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; + + try{ + + // std::cout << "xbSql::CreateIx()\n" ; + + // 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 = 20; + throw iRc; + } + } + + #ifdef XB_NDX_SUPPORT + if( sIxType == "NDX" ){ + xbFile f( xbase ); + f.SetFileName( sIxName ); + if( f.FileExists()){ + iErrorStop = 30; + 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 = 40; + throw iRc; + } + } + if( dbf == NULL ){ + iErrorStop = 50; + iRc = XB_FILE_NOT_FOUND; + throw iRc; + } + sCmd.Ltrunc( ulPos ); + + // std::cout << "cp1 ulPos = " << ulPos << " scmd = " << sCmd << "\n"; + + //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] == ',' ){ + 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 + 7 ); + sFilter.Trim(); + } + } +// std::cout << "sCmd - FILTER = [" << sFilter << "]\n"; + + #ifdef XB_LOCKING_SUPPORT + if(( iRc = dbf->LockTable( XB_LOCK )) != XB_NO_ERROR ){ + iErrorStop = 60; + throw iRc; + } + #endif // XB_LOCKING_SUPPORT + +// std::cout << "SqlCreateIndex() - ixtype = " << sIxType << "\n"; + + xbIx *pIx; + void *vpTag; + + if(( iRc = dbf->CreateTag( sIxType, sIxName, sKeyExpression, sFilter, bDesc, bUnique, xbFalse, &pIx, &vpTag )) != XB_NO_ERROR ){ + iErrorStop = 70; + throw iRc; + } +// std::cout << "SqlCreateIndex() - back from tag create\n"; + #ifdef XB_NDX_SUPPORT + if( sIxType == "NDX"){ + sCmd.Ltrunc( ulPos ); + sCmd.Trim(); + if( sCmd.Len() > 0 ){ + sCmd.ToUpperCase(); + if( sCmd.Pos( "ASSOCIATE" )){ + if(( iRc = dbf->AssociateIndex( "NDX", sIxName, 0 )) != XB_NO_ERROR ){ + iErrorStop = 80; + throw iRc; + } + } + } + } + if( sIxType == "NDX"){ + if(( iRc = pIx->Reindex( &vpTag )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } + #endif // XB_NDX_SUPPORT + + #ifdef XB_LOCKING_SUPPORT + if(( iRc = dbf->LockTable( XB_UNLOCK )) != XB_NO_ERROR ){ + iErrorStop = 140; + throw iRc; + } + #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 + dbf->LockTable( XB_UNLOCK ); + #endif // XB_LOCKING_SUPPORT + + return iRc; +} + +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/sql/xbcrtbl.cpp b/src/sql/xbcrtbl.cpp new file mode 100755 index 0000000..4193d01 --- /dev/null +++ b/src/sql/xbcrtbl.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 fields 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 = 10; + 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 = 20; + 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 = 30; + 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 XB_DBF3_SUPPORT + dbf = new xbDbf3( xbase ); + #endif + if(( iRc = dbf->CreateTable( sTableName, "", schema, 0, XB_MULTI_USER )) != XB_NO_ERROR ){ + iErrorStop = 50; + 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/xbdrpix.cpp b/src/sql/xbdrpix.cpp new file mode 100755 index 0000000..9e3bc3b --- /dev/null +++ b/src/sql/xbdrpix.cpp @@ -0,0 +1,143 @@ +/* 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{ + + +/***********************************************************************/ +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 = 10; + 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 = 20; + throw iRc; + } + } + if( dbf == NULL ){ + iErrorStop = 40; + iRc = XB_FILE_NOT_FOUND; + throw iRc; + } + + #ifdef XB_LOCKING_SUPPORT + if(( iRc = dbf->LockTable( XB_LOCK )) != XB_NO_ERROR ){ + iErrorStop = 50; + throw iRc; + } + #endif // XB_LOCKING_SUPPORT + + iRc = dbf->DeleteTag( "NDX", sIxName ); + if( iRc == XB_FILE_NOT_FOUND && !bIfExists ){ + iErrorStop = 60; + throw( iRc ); + } else if( iRc != XB_NO_ERROR ){ + iErrorStop = 70; + 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; +} + +/***********************************************************************/ +} /* namespace */ +#endif /* XB_SQL_SUPPORT */ + diff --git a/src/sql/xbdrptbl.cpp b/src/sql/xbdrptbl.cpp new file mode 100755 index 0000000..e2cfa9d --- /dev/null +++ b/src/sql/xbdrptbl.cpp @@ -0,0 +1,125 @@ +/* xbdrptbl.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::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 = 10; + 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 ); + if( iRc != XB_NO_ERROR ){ + if( iRc == XB_FILE_NOT_FOUND && bIfExists ){ + return XB_NO_ERROR; + } else { + iErrorStop = 20; + throw iRc; + } + } + } + if( dbf == NULL ){ + iErrorStop = 40; + iRc = XB_OPEN_ERROR; + throw iRc; + } + + if(( dbf->DeleteTable()) != XB_NO_ERROR ){ + iErrorStop = 50; + throw iRc; + } + + } + + 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..1095202 --- /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 = 10; + throw iRc; + } + } + + if( !dbf ){ + iErrorStop = 20; + 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 = 30; + 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 = 40; + throw iRc; + } + if(( iRc = dbf->GetFieldType( iFldNo, cFldType )) != XB_NO_ERROR ){ + iErrorStop = 50; + 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 = 100; + throw iRc; + } + break; + + case 'D': + // assumes input date format of yyyy-mm-dd + if( sFieldData.Len() != 10 || sFieldData[5] != '-' || sFieldData[8] != '-' ){ + iErrorStop = 110; + 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 = 120; + throw iRc; + } + break; + + case 'M': + llMemoFieldNos.InsertAtFront( iFldNo ); + llMemoFieldData.InsertAtFront( sFieldData ); + break; + + default: + iErrorStop= 150; + iRc = XB_INVALID_FIELD_TYPE; + throw iRc; + } + } + + if(( iRc = dbf->AppendRecord()) != XB_NO_ERROR ){ + iErrorStop = 300; + 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 = 400; + throw iRc; + } + llN = llN->GetNextNode(); + llD = llD->GetNextNode(); + } + + if(( iRc == dbf->Commit()) != XB_NO_ERROR ){ + iErrorStop = 500; + 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/xbset.cpp b/src/sql/xbset.cpp new file mode 100755 index 0000000..98de309 --- /dev/null +++ b/src/sql/xbset.cpp @@ -0,0 +1,91 @@ +/* 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 = 10; + throw iRc; + } + } else { + if(( iRc = uda.UpdTokenForKey( sKey, sToken )) != XB_NO_ERROR ){ + iErrorStop = 10; + 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..25cd2c8 --- /dev/null +++ b/src/sql/xbsql.cpp @@ -0,0 +1,143 @@ +/* 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 == "CREATE" ){ + + xbString sNode2; + sNode2.ExtractElement( sCmd.Str(), ' ', 2, 0 ); + sNode2.ToUpperCase(); + sNode2.Trim(); + if( sNode2 == "TABLE" ) + iRc = SqlCreateTable( sCmd ); + else if( sNode2 == "INDEX" || sNode2 == "UNIQUE" ) + iRc = SqlCreateIndex( sCmd ); + + 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 ); + + else if( sNode2 == "INDEX" ) + iRc = SqlDropIndex( 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 << "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 */ |