From c894a7cdd8686ea695602a23a511a3f1b0d047be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 14 Aug 2023 21:07:46 +0200 Subject: New upstream version 4.1.4 --- src/include/xbcrix.cpp | 292 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100755 src/include/xbcrix.cpp (limited to 'src/include/xbcrix.cpp') diff --git a/src/include/xbcrix.cpp b/src/include/xbcrix.cpp new file mode 100755 index 0000000..b89baaa --- /dev/null +++ b/src/include/xbcrix.cpp @@ -0,0 +1,292 @@ +/* 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 + 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 = 160; + throw iRc; + } + } + } + } + #endif // XB_NDX_SUPPORT + + if(( iRc = pIx->Reindex( &vpTag )) != XB_NO_ERROR ){ + +// if(( iRc = dbf->Reindex( 2, &vpTag )) != XB_NO_ERROR ){ + iErrorStop = 170; + throw iRc; + } + + + //std::cout << "Tag count = " << pIx->GetTagCount() << "\n"; + // s = pIx->GetTagName( &vpTag ); + // std::cout << "tagname = [" << s.Str() << "]\n"; + + + #ifdef XB_LOCKING_SUPPORT + if( bTableLocked ){ + if(( iRc = dbf->LockTable( XB_UNLOCK )) != XB_NO_ERROR ){ + iErrorStop = 180; + 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 */ + -- cgit v1.2.3