* harbour/include/hbvm.h
* harbour/include/hbrdddbf.h
* harbour/include/hbapidbg.h
* harbour/include/hbset.h
* harbour/include/hbcomp.h
* harbour/include/hbapirdd.h
* harbour/include/hbstack.h
* harbour/include/hbsxfunc.h
* harbour/include/hbapilng.h
* harbour/include/hbgtcore.h
* harbour/include/hbapifs.h
* harbour/include/hbdbsort.h
* harbour/include/hbapigt.h
* harbour/include/hbapi.h
* harbour/include/hbapierr.h
* harbour/include/hbapiitm.h
* harbour/include/hbrddfpt.h
* harbour/contrib/hbmysql/mysql.c
* harbour/contrib/hbct/bitnum.c
* harbour/contrib/hbct/token2.c
* harbour/contrib/hbct/charsprd.c
* harbour/contrib/hbct/ctnet.c
* harbour/contrib/hbct/charonly.c
* harbour/contrib/hbct/atadjust.c
* harbour/contrib/hbct/ctwin.c
* harbour/contrib/hbct/charsort.c
* harbour/contrib/hbct/ctwin.h
* harbour/contrib/hbct/charmix.c
* harbour/contrib/hbct/charevod.c
* harbour/contrib/hbct/maxline.c
* harbour/contrib/hbct/wordrepl.c
* harbour/contrib/hbct/charrepl.c
* harbour/contrib/hbct/files.c
* harbour/contrib/hbct/video.c
* harbour/contrib/hbct/charswap.c
* harbour/contrib/hbct/dattime3.c
* harbour/contrib/hbct/charop.c
* harbour/contrib/hbct/misc2.c
* harbour/contrib/hbct/charone.c
* harbour/contrib/hbct/ctstr.c
* harbour/contrib/hbct/screen1.c
* harbour/contrib/hbct/token1.c
* harbour/contrib/hbct/ctstr.h
* harbour/contrib/hbct/charmirr.c
* harbour/contrib/hbct/relation.c
* harbour/contrib/hbct/atnum.c
* harbour/contrib/hbct/like.c
* harbour/contrib/hbct/count.c
* harbour/contrib/hbct/disk.c
* harbour/contrib/hbct/ctstrfil.c
* harbour/contrib/hbct/posdiff.c
* harbour/contrib/hbct/addascii.c
* harbour/contrib/hbct/tab.c
* harbour/contrib/hbct/numline.c
* harbour/contrib/hbct/dattime2.c
* harbour/contrib/hbct/asciisum.c
* harbour/contrib/hbct/expand.c
* harbour/contrib/hbct/pos2.c
* harbour/contrib/hbct/numat.c
* harbour/contrib/hbct/atrepl.c
* harbour/contrib/hbct/wordtoch.c
* harbour/contrib/hbct/print.c
* harbour/contrib/hbct/justify.c
* harbour/contrib/xhb/hbxml.c
* harbour/contrib/xhb/dbf2txt.c
* harbour/contrib/xhb/xhbis.c
* harbour/contrib/xhb/fparse.c
* harbour/contrib/xhb/xstrdel.c
* harbour/contrib/xhb/hbcomprs.c
* harbour/contrib/xhb/datesxhb.c
* harbour/contrib/xhb/xhbmsgs.c
* harbour/contrib/xhb/freadlin.c
* harbour/contrib/xhb/txtline.c
* harbour/contrib/xhb/xhbtrim.c
* harbour/contrib/xhb/xhbcopyf.c
* harbour/contrib/xhb/cstructc.c
* harbour/contrib/xhb/xhbfunc.c
* harbour/contrib/hbtpathy/tplinux.c
* harbour/contrib/hbgt/charmixg.c
* harbour/contrib/hbgt/strexpan.c
* harbour/contrib/hbgt/charodd.c
* harbour/contrib/hbgt/strright.c
* harbour/contrib/hbgt/asciisgt.c
* harbour/contrib/hbgt/strdiffg.c
* harbour/contrib/hbgt/chrtotal.c
* harbour/contrib/hbgt/strcount.c
* harbour/contrib/hbgt/strleft.c
* harbour/contrib/hbgt/ascposgt.c
* harbour/contrib/hbgt/chrfirst.c
* harbour/contrib/hbgt/chrcount.c
* harbour/contrib/hbgt/strpbrk.c
* harbour/contrib/hbgt/chareven.c
* harbour/contrib/hbgt/strcspn.c
* harbour/contrib/hbgt/atdiff.c
* harbour/contrib/hbsqlit3/hbsqlit3.c
* harbour/contrib/hbmzip/hbmzip.c
* harbour/contrib/hbnf/proper.c
* harbour/contrib/hbnf/fttext.c
* harbour/contrib/hbnf/chdir.c
* harbour/contrib/hbnf/getver.c
* harbour/contrib/hbnf/ftattr.c
* harbour/contrib/hbnf/mkdir.c
* harbour/contrib/hbnf/rmdir.c
* harbour/contrib/Makefile
* harbour/contrib/hbcurl/hbcurl.c
* harbour/contrib/rddsql/sddmy/mysqldd.c
* harbour/contrib/rddsql/sddpg/pgsqldd.c
* harbour/contrib/rddsql/sddfb/fbirddd.c
* harbour/contrib/rddsql/sddodbc/odbcdd.c
* harbour/contrib/rddsql/sqlmix.c
* harbour/contrib/hbhpdf/harupdf.c
* harbour/contrib/rddads/adsx.c
* harbour/contrib/rddads/adsfunc.c
* harbour/contrib/rddads/rddads.h
* harbour/contrib/rddads/ads1.c
* harbour/contrib/hbmisc/hb_f.c
* harbour/contrib/hbmisc/strfmt.c
* harbour/contrib/hbmisc/stringsx.c
* harbour/contrib/hbmisc/spd.c
* harbour/contrib/hbtip/utils.c
* harbour/contrib/hbwin/wapi_winbase.c
* harbour/contrib/hbwin/win_misc.c
* harbour/contrib/hbbtree/hb_btree.h
* harbour/contrib/hbbtree/hb_btree.c
* harbour/source/pp/hbpp.c
* harbour/source/vm/runner.c
* harbour/source/vm/estack.c
* harbour/source/vm/itemapi.c
* harbour/source/vm/hvm.c
* harbour/source/vm/cmdarg.c
* harbour/source/vm/memvars.c
* harbour/source/vm/dynlibhb.c
* harbour/source/vm/set.c
* harbour/source/main/harbour.c
* harbour/source/debug/dbgentry.c
* harbour/source/common/hbfsapi.c
* harbour/source/common/hbfopen.c
* harbour/source/rtl/gtdos/gtdos.c
* harbour/source/rtl/diskspac.c
* harbour/source/rtl/console.c
* harbour/source/rtl/chrasc.c
* harbour/source/rtl/fscopy.c
* harbour/source/rtl/run.c
* harbour/source/rtl/spfiles.c
* harbour/source/rtl/defpath.c
* harbour/source/rtl/philes.c
* harbour/source/rtl/oldbox.c
* harbour/source/rtl/math.c
* harbour/source/rtl/hbgtcore.c
* harbour/source/rtl/cdpapi.c
* harbour/source/rtl/gtcrs/gtcrs.c
* harbour/source/rtl/dirdrive.c
* harbour/source/rtl/hbi18n1.c
* harbour/source/rtl/trim.c
* harbour/source/rtl/hbzlibgz.c
* harbour/source/rtl/philesx.c
* harbour/source/rtl/mlcfunc.c
* harbour/source/rtl/filehb.c
* harbour/source/rtl/fstemp.c
* harbour/source/rtl/is.c
* harbour/source/rtl/hbrunfun.c
* harbour/source/rtl/ampm.c
* harbour/source/rtl/setcolor.c
* harbour/source/rtl/oemansi.c
* harbour/source/rtl/disksphb.c
* harbour/source/rtl/hbzlib.c
* harbour/source/rtl/strpeek.c
* harbour/source/rtl/replic.c
* harbour/source/rtl/stuff.c
* harbour/source/rtl/hbstrfmt.c
* harbour/source/rtl/transfrm.c
* harbour/source/rtl/hbhex.c
* harbour/source/rtl/trace.c
* harbour/source/rtl/hbadler.c
* harbour/source/rtl/samples.c
* harbour/source/rtl/filebuf.c
* harbour/source/rtl/hbcrc.c
* harbour/source/rtl/gete.c
* harbour/source/rtl/hbmd5.c
* harbour/source/rtl/langapi.c
* harbour/source/rtl/gtcgi/gtcgi.c
* harbour/source/rtl/errapi.c
* harbour/source/rtl/hbregexc.c
* harbour/source/rtl/natmsg.c
* harbour/source/rtl/fssize.c
* harbour/source/rtl/hbinet.c
* harbour/source/rtl/colorind.c
* harbour/source/rtl/copyfile.c
* harbour/source/rtl/mouseapi.c
* harbour/source/rtl/soundex.c
* harbour/source/rtl/memofile.c
* harbour/source/rtl/hbffind.c
* harbour/source/rtl/gtapi.c
* harbour/source/rtl/direct.c
* harbour/source/rtl/filesys.c
* harbour/source/rtl/file.c
* harbour/source/rtl/val.c
* harbour/source/rtl/hbregex.c
* harbour/source/rtl/rat.c
* harbour/source/rtl/isprint.c
* harbour/source/rdd/dbfntx/dbfntx1.c
* harbour/source/rdd/dbsql.c
* harbour/source/rdd/workarea.c
* harbour/source/rdd/wacore.c
* harbour/source/rdd/sdf1.c
* harbour/source/rdd/dbdetach.c
* harbour/source/rdd/dbcmdx.c
* harbour/source/rdd/dbfnsx/dbfnsx1.c
* harbour/source/rdd/dbcmd.c
* harbour/source/rdd/dbfcdx/dbfcdx1.c
* harbour/source/rdd/delim1.c
* harbour/source/rdd/dbf1.c
* harbour/source/rdd/hsx/hsx.c
* harbour/source/rdd/dbcmd53.c
* harbour/source/rdd/usrrdd/usrrdd.c
* harbour/source/rdd/wafunc.c
* harbour/source/rdd/dbffpt/dbffpt1.c
* harbour/source/rdd/hbsix/sxsem.c
* harbour/source/rdd/hbsix/sxord.c
* harbour/source/rdd/hbsix/sxfname.c
* harbour/source/rdd/hbsix/sxtable.c
* harbour/source/rdd/hbsix/sxdate.c
* harbour/source/rdd/hbsix/sxutil.c
* harbour/source/rdd/hbsix/sxcompr.c
* harbour/source/compiler/hbmain.c
* harbour/source/compiler/cmdcheck.c
* harbour/source/compiler/hbpcode.c
* harbour/source/compiler/genc.c
* harbour/source/compiler/gencc.c
* harbour/source/compiler/hbcmplib.c
* harbour/source/compiler/ppcomp.c
* changed 'char *' and changed 'BYTE *' to 'const char *' in
the following functions:
const char * hb_vmFindModuleSymbolName( PHB_SYMB pSym );
void hb_vmInitSymbolGroup( void * hNewDynLib, int argc,
const char * argv[] );
void hb_dbgEntry( int nMode, int nLine, const char *szName,
int nIndex, PHB_ITEM pFrame );
void hb_dbgAddBreak( void *handle, const char *cModule,
int nLine, const char *szFunction );
void hb_dbgAddWatch( void *handle, const char *szExpr, BOOL bTrace );
PHB_ITEM hb_dbgGetExpressionValue( void *handle,
const char *expression );
BOOL hb_dbgIsValidStopLine( void *handle, const char *szModule,
int nLine );
void hb_dbgSetToCursor( void *handle, const char *szModule,
int nLine );
void hb_dbgSetWatch( void *handle, int nWatch,
const char *szExpr, BOOL bTrace );
const char * hb_setGetCPtr( HB_set_enum set_specifier );
const char * hb_setGetAltFile( void );
const char * hb_setGetDateFormat( void );
const char * hb_setGetTimeFormat( void );
const char * hb_setGetDefault( void );
const char * hb_setGetDelimChars( void );
const char * hb_setGetDevice( void );
const char * hb_setGetExtraFile( void );
const char * hb_setGetPath( void );
const char * hb_setGetMFileExt( void );
const char * hb_setGetPrintFile( void );
const char * hb_setGetEOL( void );
const char * hb_setGetHBOUTLOG( void );
const char * hb_setGetHBOUTLOGINFO( void );
const char * hb_setGetOSCODEPAGE( void );
void hb_compInitPP( HB_COMP_DECL, int argc,
const char * const argv[] );
void hb_compGenPCodeN( const BYTE * pBuffer, ULONG ulSize,
HB_COMP_DECL );
int hb_compMain( int argc, const char * const argv[],
BYTE ** pBufPtr, ULONG * pulSize,
const char * szSource );
void hb_compChkCompilerSwitch( HB_COMP_DECL, int,
const char * const args[] );
void hb_compChkDefines( HB_COMP_DECL, int iArg,
const char * const args[] );
void hb_compGenCString( FILE * yyc, const BYTE * pText, ULONG ulLen );
AREAP hb_rddRequestArea( const char * szAlias, PHB_ITEM pCargo,
BOOL fNewArea, BOOL fWait );
char * hb_stackDirBuffer( void );
LONG hb_sxPtoD( const char * pDate );
const char * hb_langID( void );
const char * hb_langSelectID( const char * pszID );
const char * hb_langDGetItem( int iIndex );
const char * hb_langDGetErrorDesc( ULONG ulIndex );
BOOL hb_fsChDir( const char * pszDirName );
HB_FHANDLE hb_fsCreate( const char * pszFileName, ULONG ulAttr );
HB_FHANDLE hb_fsCreateEx( const char * pszFilename, ULONG ulAttr,
USHORT uiFlags );
HB_FHANDLE hb_fsCreateTemp( const char * pszDir,
const char * pszPrefix,
ULONG ulAttr, char * pszName );
HB_FHANDLE hb_fsCreateTempEx( char * pszName, const char * pszDir,
const char * pszPrefix,
const char * pszExt, ULONG ulAttr );
const char * hb_fsCurDir( USHORT uiDrive );
USHORT hb_fsCurDirBuff( USHORT uiDrive, char * pbyBuffer,
ULONG ulLen );
void hb_fsBaseDirBuff( char * pbyBuffer );
BOOL hb_fsDelete( const char * pszFileName );
BOOL hb_fsFile( const char * pszFileName );
BOOL hb_fsIsDirectory( const char * pszFilename );
HB_FOFFSET hb_fsFSize( const char * pszFileName, BOOL bUseDirEntry );
HB_FHANDLE hb_fsExtOpen( const char * pszFileName,
const char * pDefExt,
char * hb_fsExtName( const char * pFilename,
const char * pDefExt, USHORT uiExFlags,
const char * pPaths );
BOOL hb_fsMkDir( const char * pszDirName );
HB_FHANDLE hb_fsOpen( const char * pszFileName, USHORT uiFlags );
BOOL hb_fsRmDir( const char * pszDirName );
BOOL hb_fsRename( const char * pszOldName,
const char * pszNewName );
BOOL hb_fsGetFileTime( const char * pszFileName,
LONG * plJulian, LONG * plMillisec );
BOOL hb_fsSetFileTime( const char * pszFileName,
LONG lJulian, LONG lMillisec );
BOOL hb_fsGetAttr( const char * pszFileName, ULONG * pulAttr );
BOOL hb_fsSetAttr( const char * pszFileName, ULONG ulAttr );
HB_FHANDLE hb_fsPOpen( const char * pFilename, const char * pMode );
BOOL hb_fsCopy( const char * pSource, const char * pDest );
BOOL hb_spFile( const char * pFilename, char * pRetPath );
BOOL hb_spFileExists( const char * pFilename, char * pRetPath );
HB_FHANDLE hb_spOpen( const char * pFilename, USHORT uiFlags );
HB_FHANDLE hb_spCreate( const char * pFilename, ULONG ulAttr );
HB_FHANDLE hb_spCreateEx( const char * pFilename,
ULONG ulAttr, USHORT uiFlags );
PHB_FILE hb_fileExtOpen( const char * pFilename,
const char * pDefExt, USHORT uiExFlags,
const char * pPaths, PHB_ITEM pError );
PHB_FILE hb_fileCreateTemp( const char * pszDir,
const char * pszPrefix,
ULONG ulAttr, char * pszName );
PHB_FILE hb_fileCreateTempEx( char * pszName, const char * pszDir,
const char * pszPrefix,
const char * pszExt, ULONG ulAttr );
HB_ERRCODE hb_gtBox( SHORT uiTop, SHORT uiLeft, SHORT uiBottom,
SHORT uiRight, const BYTE * pbyFrame );
HB_ERRCODE hb_gtDrawBox( SHORT uiTop, SHORT uiLeft, SHORT uiBottom,
SHORT uiRight, const BYTE * pbyFrame,
int iColor );
HB_ERRCODE hb_gtWrite( const BYTE * pbyStr, ULONG ulLen );
HB_ERRCODE hb_gtWriteAt( USHORT uiRow, USHORT uiCol,
const BYTE * pbyStr, ULONG ulLen );
HB_ERRCODE hb_gtWriteCon( const BYTE * pbyStr, ULONG ulLen );
HB_ERRCODE hb_gtPutText( USHORT uiRow, USHORT uiCol,
const BYTE * pStr, ULONG ulLength,
int iColor );
HB_ERRCODE hb_gtOutStd( const BYTE * pbyStr, ULONG ulLen );
HB_ERRCODE hb_gtOutErr( const BYTE * pbyStr, ULONG ulLen );
HB_ERRCODE hb_gtBoxEx( int iTop, int iLeft, int iBottom, int iRight,
const BYTE * pbyFrame, int iColor );
void hb_mouseRestoreState( const BYTE * pBuffer );
const char * hb_strLTrim( const char * szText, ULONG * ulLen );
const char * hb_conNewLine( void );
const char * hb_conSetColor( const char * szColor );
const char * hb_errGetDescription( PHB_ITEM pError );
const char * hb_errGetFileName( PHB_ITEM pError );
const char * hb_errGetOperation( PHB_ITEM pError );
const char * hb_errGetSubSystem( PHB_ITEM pError );
int hb_ctwAddWindowBox( int iWindow, const BYTE * szBox, int iColor );
const char *ct_at_exact_forward
( const char *pcString, size_t sStrLen,
const char *pcMatch, size_t sMatchLen,
size_t *psMatchStrLen );
const char *ct_at_exact_backward
( const char *pcString, size_t sStrLen,
const char *pcMatch, size_t sMatchLen,
size_t *psMatchStrLen );
const char *ct_at_wildcard_forward
( const char *pcString, size_t sStrLen,
const char *pcMatch, size_t sMatchLen,
char cWildCard, size_t *psMatchStrLen );
const char *ct_at_wildcard_backward
( const char *pcString, size_t sStrLen,
const char *pcMatch, size_t sMatchLen,
char cWildCard, size_t *psMatchStrLen );
const char *ct_at_charset_forward
( const char *pcString, size_t sStrLen,
const char *pcCharSet, size_t sCharSetLen,
size_t *psMatchedCharPos );
const char *ct_at_charset_backward
( const char *pcString, size_t sStrLen,
const char *pcCharSet, size_t sCharSetLen,
size_t *psMatchedCharPos );
char * hb_adsOemToAnsi( const char * pcString, ULONG ulLen );
char * hb_adsAnsiToOem( const char * pcString, ULONG ulLen );
struct hb_BTree * hb_BTreeNew( const char *FileName,
USHORT usPageSize, USHORT usKeySize,
ULONG ulFlags, USHORT usBuffers );
struct hb_BTree * hb_BTreeOpen( const char *FileName, ULONG lFlags,
USHORT usBuffers );
BOOL hb_BTreeInsert( struct hb_BTree * pBTree, const char * szKey,
PHB_ITEM pData );
BOOL hb_BTreeDelete( struct hb_BTree * pBTree, const char * szKey,
LONG lData );
BOOL hb_BTreeSeek( struct hb_BTree * pBTree, const char * szKey,
LONG lData, BOOL bSoftSeek );
const char * hb_BTreeKey( struct hb_BTree * pBTree );
* modified RDD methods:
HB_ERRCODE PUTVALUEFILE( AREAP, USHORT, const char *, USHORT );
HB_ERRCODE GETVALUEFILE( AREAP, USHORT, const char *, USHORT );
* modified GT methods:
void REST( HB_GT_PTR, int, int, int, int, const BYTE * );
void PUTTEXT( HB_GT_PTR, int, int, BYTE, const BYTE *, ULONG );
void WRITEAT( HB_GT_PTR, int, int, const BYTE *, ULONG );
void WRITE( HB_GT_PTR, const BYTE *, ULONG );
void WRITECON( HB_GT_PTR, const BYTE *, ULONG );
void BOX( HB_GT_PTR, int, int, int, int, const BYTE *, BYTE );
void BOXD( HB_GT_PTR, int, int, int, int, const BYTE *, BYTE );
void BOXS( HB_GT_PTR, int, int, int, int, const BYTE *, BYTE );
void OUTSTD( HB_GT_PTR, BYTE *, ULONG );
void OUTERR( HB_GT_PTR, BYTE *, ULONG );
void MOUSERESTORESTATE( HB_GT_PTR, const BYTE * );
* modified RDD structers:
DBFIELDINFO, DBOPENINFO, DBORDERCONDINFO, DBCONSTRAINTINFO,
DBORDERCREATEINFO
+ modified parameters and behevior:
const char * hb_fsNameConv( const char * szFileName, char ** pszFree );
const char * hb_osEncode( const char * szFileName, char ** pszFree );
const char * hb_osDecode( const char * szFileName, char ** pszFree );
Please look at implementation and current usage of these functions.
+ added new function:
BOOL hb_itemGetWriteCL( PHB_ITEM pItem,
char ** pszValue, ULONG * pulLen );
which converts item string buffer to writable state to use with
functions like FREAD() instead of hb_itemUnShare*()
* updatd other code to respect above modifications
! fixed bugs (also GPF traps) located by above modifications
TODO: please make build tests. Especially in OS2 - not tested at all.
2336 lines
64 KiB
C
2336 lines
64 KiB
C
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* SQL MIX (Memory Index) Database Driver
|
|
*
|
|
* Copyright 2007 Mindaugas Kavaliauskas <dbtopas at dbtopas.lt>
|
|
* www - http://www.harbour-project.org
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this software; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
|
|
*
|
|
* As a special exception, the Harbour Project gives permission for
|
|
* additional uses of the text contained in its release of Harbour.
|
|
*
|
|
* The exception is that, if you link the Harbour libraries with other
|
|
* files to produce an executable, this does not by itself cause the
|
|
* resulting executable to be covered by the GNU General Public License.
|
|
* Your use of that executable is in no way restricted on account of
|
|
* linking the Harbour library code into it.
|
|
*
|
|
* This exception does not however invalidate any other reasons why
|
|
* the executable file might be covered by the GNU General Public License.
|
|
*
|
|
* This exception applies only to the code released by the Harbour
|
|
* Project under the name Harbour. If you copy code from other
|
|
* Harbour Project or Free Software Foundation releases into a copy of
|
|
* Harbour, as the General Public License permits, the exception does
|
|
* not apply to the code that you add in this way. To avoid misleading
|
|
* anyone as to the status of such modified files, you must delete
|
|
* this exception notice from them.
|
|
*
|
|
* If you write modifications of your own for Harbour, it is your choice
|
|
* whether to permit this exception to apply to your modifications.
|
|
* If you do not wish that, delete this exception notice.
|
|
*
|
|
*/
|
|
|
|
#include "hbapi.h"
|
|
#include "hbinit.h"
|
|
#include "hbapiitm.h"
|
|
#include "hbapirdd.h"
|
|
#include "hbapierr.h"
|
|
#include "hbdbferr.h"
|
|
#include "hbapilng.h"
|
|
#include "hbdate.h"
|
|
#include "hbset.h"
|
|
#include "hbvm.h"
|
|
#include "rddsys.ch"
|
|
|
|
#include "hbrddsql.h"
|
|
|
|
#define SUPERTABLE ( &sqlmixSuper )
|
|
|
|
|
|
|
|
#define MIX_KEY( tag, node, index ) \
|
|
( (PMIXKEY) & ( (BYTE*) (node) ) [ ( (node)->Leaf ? sizeof( MIXNODELEAF ) : sizeof( MIXNODE ) ) + (index) * (tag)->uiTotalLen ] )
|
|
|
|
#define MIX_COPY_KEYS_INTERNAL( tag, node, dst, src, count ) \
|
|
memmove( ( (BYTE*) (node) ) + ( (node)->Leaf ? sizeof( MIXNODELEAF ) : sizeof( MIXNODE ) ) + (dst) * (tag)->uiTotalLen, \
|
|
( (BYTE*) (node) ) + ( (node)->Leaf ? sizeof( MIXNODELEAF ) : sizeof( MIXNODE ) ) + (src) * (tag)->uiTotalLen, \
|
|
(count) * (tag)->uiTotalLen )
|
|
|
|
#define MIX_COPY_KEYS_EXTERNAL( tag, ndst, dst, nsrc, src, count ) \
|
|
memmove( ( (BYTE*) (ndst) ) + ( (ndst)->Leaf ? sizeof( MIXNODELEAF ) : sizeof( MIXNODE ) ) + (dst) * (tag)->uiTotalLen, \
|
|
( (BYTE*) (nsrc) ) + ( (nsrc)->Leaf ? sizeof( MIXNODELEAF ) : sizeof( MIXNODE ) ) + (src) * (tag)->uiTotalLen, \
|
|
(count) * (tag)->uiTotalLen )
|
|
|
|
#define MIX_ASSIGN_KEY( tag, node, dst, src ) \
|
|
memmove( ( (BYTE*) (node) ) + ( (node)->Leaf ? sizeof( MIXNODELEAF ) : sizeof( MIXNODE ) ) + (dst) * (tag)->uiTotalLen, \
|
|
(src), (tag)->uiTotalLen )
|
|
|
|
#define MIX_COPY_CHILDS_INTERNAL( tag, node, dst, src, count ) \
|
|
memmove( & ((node)->Child[ (dst) ]), & ((node)->Child[ (src) ]), (count) * sizeof( void* ) )
|
|
|
|
#define MIX_COPY_CHILDS_EXTERNAL( tag, ndst, dst, nsrc, src, count ) \
|
|
memmove( & ((ndst)->Child[ (dst) ]), & ((nsrc)->Child[ (src) ]), (count) * sizeof( void* ) )
|
|
|
|
|
|
|
|
static USHORT s_uiRddIdSQLMIX = ( USHORT ) -1;
|
|
|
|
static RDDFUNCS sqlmixSuper;
|
|
|
|
|
|
/*
|
|
=======================================================================
|
|
Misc functions
|
|
=======================================================================
|
|
*/
|
|
|
|
|
|
static HB_ERRCODE sqlmixErrorRT( SQLMIXAREAP pArea, USHORT uiGenCode, USHORT uiSubCode, char* filename, USHORT uiOsCode, USHORT uiFlags )
|
|
{
|
|
PHB_ITEM pError;
|
|
HB_ERRCODE iRet = HB_FAILURE;
|
|
|
|
if ( hb_vmRequestQuery() == 0 )
|
|
{
|
|
pError = hb_errNew();
|
|
hb_errPutGenCode( pError, uiGenCode );
|
|
hb_errPutSubCode( pError, uiSubCode );
|
|
hb_errPutOsCode( pError, uiOsCode );
|
|
hb_errPutDescription( pError, hb_langDGetErrorDesc( uiGenCode ) );
|
|
if ( filename )
|
|
hb_errPutFileName( pError, filename );
|
|
if ( uiFlags )
|
|
hb_errPutFlags( pError, uiFlags );
|
|
iRet = SELF_ERROR( (AREAP) pArea, pError );
|
|
hb_errRelease( pError );
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
|
|
/*
|
|
=======================================================================
|
|
Memory Index
|
|
=======================================================================
|
|
*/
|
|
|
|
/* -------------------------- Key management ---------------------------- */
|
|
/* hb_mixKey*() */
|
|
|
|
static PMIXKEY hb_mixKeyNew( PMIXTAG pTag )
|
|
{
|
|
return (PMIXKEY) hb_xgrab( pTag->uiTotalLen );
|
|
}
|
|
|
|
|
|
static PMIXKEY hb_mixKeyPutItem( PMIXKEY pKey, PHB_ITEM pItem, ULONG ulRecNo, PMIXTAG pTag )
|
|
{
|
|
ULONG ul;
|
|
double dbl;
|
|
BYTE buf[ 8 ];
|
|
|
|
if ( ! pKey )
|
|
pKey = hb_mixKeyNew( pTag );
|
|
|
|
pKey->rec = ulRecNo;
|
|
pKey->notnul = 1;
|
|
|
|
/* TODO: check valtype */
|
|
switch ( pTag->bType )
|
|
{
|
|
case 'C':
|
|
ul = hb_itemGetCLen( pItem );
|
|
|
|
if ( ul > (ULONG) pTag->uiKeyLen )
|
|
ul = pTag->uiKeyLen;
|
|
|
|
memcpy( pKey->val, hb_itemGetCPtr( pItem ), ul );
|
|
|
|
if ( ul < (ULONG) pTag->uiKeyLen )
|
|
memset( pKey->val + ul, ' ', (ULONG) pTag->uiKeyLen - ul );
|
|
|
|
break;
|
|
|
|
case 'N':
|
|
dbl = hb_itemGetND( pItem );
|
|
HB_DBL2ORD( &dbl, buf );
|
|
memcpy( pKey->val, buf, 8 );
|
|
break;
|
|
|
|
case 'D':
|
|
dbl = (double) hb_itemGetDL( pItem );
|
|
HB_DBL2ORD( &dbl, buf );
|
|
memcpy( pKey->val, buf, 8 );
|
|
break;
|
|
|
|
case 'L':
|
|
pKey->val[ 0 ] = (BYTE) (hb_itemGetL( pItem ) ? 'T' : 'F');
|
|
break;
|
|
|
|
default:
|
|
pKey->notnul = 0;
|
|
memset( pKey->val, ' ', pTag->uiKeyLen );
|
|
}
|
|
return pKey;
|
|
}
|
|
|
|
|
|
static PMIXKEY hb_mixKeyEval( PMIXKEY pKey, PMIXTAG pTag )
|
|
{
|
|
PHB_ITEM pItem;
|
|
SQLMIXAREAP pArea = pTag->pArea;
|
|
int iCurrArea = hb_rddGetCurrentWorkAreaNumber();
|
|
PHB_CODEPAGE pCodepage = hb_cdpSelect( pArea->cdPage );
|
|
|
|
if ( iCurrArea != pArea->uiArea )
|
|
hb_rddSelectWorkAreaNumber( pArea->uiArea );
|
|
else
|
|
iCurrArea = 0;
|
|
|
|
pItem = hb_vmEvalBlockOrMacro( pTag->pKeyItem );
|
|
|
|
pKey = hb_mixKeyPutItem( pKey, pItem, pArea->ulRecNo, pTag );
|
|
|
|
if ( iCurrArea )
|
|
hb_rddSelectWorkAreaNumber( iCurrArea );
|
|
|
|
hb_cdpSelect( pCodepage );
|
|
|
|
return pKey;
|
|
}
|
|
|
|
|
|
static BOOL hb_mixEvalCond( SQLMIXAREAP pArea, PHB_ITEM pCondItem )
|
|
{
|
|
int iCurrArea = 0;
|
|
BOOL fRet;
|
|
|
|
if ( pArea )
|
|
{
|
|
iCurrArea = hb_rddGetCurrentWorkAreaNumber();
|
|
|
|
if ( iCurrArea != pArea->uiArea )
|
|
hb_rddSelectWorkAreaNumber( pArea->uiArea );
|
|
else
|
|
iCurrArea = 0;
|
|
}
|
|
|
|
fRet = hb_itemGetL( hb_vmEvalBlockOrMacro( pCondItem ) );
|
|
|
|
if ( iCurrArea )
|
|
hb_rddSelectWorkAreaNumber( iCurrArea );
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
static void hb_mixKeyFree( PMIXKEY pKey )
|
|
{
|
|
hb_xfree( pKey );
|
|
}
|
|
|
|
|
|
#if 0
|
|
/* This function is unused */
|
|
static int hb_mixKeyCompareValue( PMIXTAG pTag, PMIXKEY pKey1, PMIXKEY pKey2, UINT uiLen )
|
|
{
|
|
BYTE* pSortTable = pTag->pSortTable;
|
|
UINT ui, uiSize;
|
|
int i;
|
|
|
|
if ( ! pKey1->notnul || ! pKey2->notnul )
|
|
{
|
|
return (int) pKey1->notnul - (int) pKey2->notnul;
|
|
}
|
|
|
|
i = 0;
|
|
uiSize = pTag->uiKeyLen > uiLen ? uiLen : pTag->uiKeyLen;
|
|
|
|
if ( pSortTable )
|
|
{
|
|
ui = 0;
|
|
while ( i == 0 && ui < uiSize )
|
|
{
|
|
i = pSortTable[ pKey1->val[ ui ] ] - pSortTable[ pKey2->val[ ui ] ];
|
|
ui++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( uiSize > 0 )
|
|
i = memcmp( pKey1->val, pKey2->val, uiSize );
|
|
}
|
|
|
|
if ( i == 0 )
|
|
{
|
|
/* This condition seems inverted, but it's ok for seek last */
|
|
if ( pTag->uiKeyLen > uiLen )
|
|
i = -1;
|
|
}
|
|
return i;
|
|
}
|
|
#endif
|
|
|
|
|
|
static int hb_mixKeyCompare( PMIXTAG pTag, PMIXKEY pKey1, PMIXKEY pKey2, UINT uiLen )
|
|
{
|
|
BYTE* pSortTable = pTag->pSortTable;
|
|
UINT ui, uiSize;
|
|
int i;
|
|
|
|
|
|
if ( ! pKey1->notnul || ! pKey2->notnul )
|
|
{
|
|
return (int) pKey1->notnul - (int) pKey2->notnul;
|
|
}
|
|
|
|
i = 0;
|
|
uiSize = pTag->uiKeyLen > uiLen ? uiLen : pTag->uiKeyLen;
|
|
|
|
if ( pSortTable )
|
|
{
|
|
ui = 0;
|
|
while ( i == 0 && ui < uiSize )
|
|
{
|
|
i = pSortTable[ pKey1->val[ ui ] ] - pSortTable[ pKey2->val[ ui ] ];
|
|
ui++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( uiSize > 0 )
|
|
i = memcmp( pKey1->val, pKey2->val, uiSize );
|
|
}
|
|
|
|
if ( i == 0 )
|
|
{
|
|
if ( pKey2->rec == (ULONG) -1 )
|
|
{
|
|
/* This condition seems inverted, but it's ok for seek last */
|
|
if ( pTag->uiKeyLen > uiLen )
|
|
i = -1;
|
|
}
|
|
else
|
|
{
|
|
if ( pTag->uiKeyLen > uiLen )
|
|
i = 1;
|
|
else if ( pTag->uiKeyLen < uiLen )
|
|
i = -1;
|
|
}
|
|
}
|
|
|
|
|
|
if ( i != 0 )
|
|
{
|
|
if ( i < 0 )
|
|
{
|
|
return -2;
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
if ( pKey1->rec < pKey2->rec )
|
|
{
|
|
return -1;
|
|
}
|
|
else if ( pKey1->rec > pKey2->rec )
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* -------------------------- Tag management ---------------------------- */
|
|
/* hb_mixTag*() */
|
|
|
|
/* This function is used for debugging purposes. Uncomment it, if you need it.
|
|
static void hb_mixTagPrintNode( PMIXTAG pTag, PMIXNODE pNode, int iLevel )
|
|
{
|
|
UINT i;
|
|
|
|
if ( !pNode )
|
|
return;
|
|
|
|
if ( pNode->KeyCount < MIX_NODE_ORDER / 2 && pNode->Parent )
|
|
{
|
|
printf("!!! Too few keys\n");
|
|
}
|
|
|
|
for ( i = 0; i < pNode->KeyCount; i++ )
|
|
{
|
|
if ( ! pNode->Leaf )
|
|
{
|
|
if ( pNode->Child[ i ]->Parent != pNode )
|
|
printf("!!! Invalid parent\n");
|
|
|
|
hb_mixTagPrintNode( pTag, pNode->Child[ i ], iLevel + 1 );
|
|
}
|
|
printf("%*ld %*s\n", iLevel * 10 + 5, MIX_KEY( pTag, pNode, i )->rec, pTag->uiKeyLen,
|
|
MIX_KEY( pTag, pNode, i )->notnul ? ( char * ) MIX_KEY( pTag, pNode, i )->val : "NULL" );
|
|
}
|
|
|
|
if ( ! pNode->Leaf )
|
|
{
|
|
if ( pNode->Child[ pNode->KeyCount ]->Parent != pNode )
|
|
printf("!!! Invalid parent\n");
|
|
|
|
hb_mixTagPrintNode( pTag, pNode->Child[ pNode->KeyCount ], iLevel + 1 );
|
|
}
|
|
}
|
|
*/
|
|
|
|
static PMIXNODE hb_mixTagCreateNode( PMIXTAG pTag, BOOL fLeaf )
|
|
{
|
|
PMIXNODE pNode;
|
|
ULONG ulSize;
|
|
|
|
ulSize = ( fLeaf ? sizeof( MIXNODELEAF ) : sizeof( MIXNODE ) ) + MIX_NODE_ORDER * pTag->uiTotalLen;
|
|
|
|
pNode = (PMIXNODE) hb_xgrab( ulSize );
|
|
memset( pNode, 0, ulSize );
|
|
pNode->Leaf = fLeaf ? 1 : 0;
|
|
return pNode;
|
|
}
|
|
|
|
|
|
static UINT hb_mixTagNodeParentIndex( PMIXNODE pNode )
|
|
{
|
|
PMIXNODE pParent = pNode->Parent;
|
|
UINT ui;
|
|
|
|
/* Find position in the parent node */
|
|
ui = pParent->KeyCount;
|
|
do {
|
|
if ( pParent->Child[ ui ] == pNode )
|
|
return ui;
|
|
} while ( ui-- );
|
|
|
|
return (UINT) -1;
|
|
}
|
|
|
|
|
|
static int hb_mixTagFindKey( PMIXTAG pTag, PMIXKEY pKey, UINT uiLen, PMIXNODE* ppNode, UINT* puiPos, BOOL fValidKey )
|
|
{
|
|
PMIXNODE pNode;
|
|
UINT ui;
|
|
int i;
|
|
|
|
pNode = pTag->Root;
|
|
|
|
while ( 1 )
|
|
{
|
|
i = -2;
|
|
|
|
/* TODO: binary search */
|
|
for ( ui = 0; ui < pNode->KeyCount; ui++ )
|
|
{
|
|
i = hb_mixKeyCompare( pTag, MIX_KEY( pTag, pNode, ui ), pKey, uiLen );
|
|
|
|
if ( i >= 0 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( i == 0 || pNode->Leaf )
|
|
break;
|
|
else
|
|
pNode = pNode->Child[ ui ];
|
|
}
|
|
|
|
if ( fValidKey && ui >= pNode->KeyCount )
|
|
{
|
|
/* unsuccessful find always finds position in leaf */
|
|
|
|
while ( pNode->Parent && pNode->Parent->Child[ pNode->Parent->KeyCount ] == pNode )
|
|
pNode = pNode->Parent;
|
|
|
|
if ( pNode->Parent )
|
|
{
|
|
for ( ui = 0; ui < pNode->Parent->KeyCount; ui++ )
|
|
{
|
|
if ( pNode->Parent->Child[ ui ] == pNode )
|
|
{
|
|
pNode = pNode->Parent;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ui = pNode->KeyCount + 1; /* EOF */
|
|
}
|
|
}
|
|
|
|
* ppNode = pNode;
|
|
* puiPos = ui;
|
|
return i;
|
|
}
|
|
|
|
|
|
static void hb_mixTagSetCurrent( PMIXTAG pTag, PMIXNODE pNode, UINT uiPos )
|
|
{
|
|
if ( uiPos < pNode->KeyCount )
|
|
{
|
|
pTag->CurNode = pNode;
|
|
pTag->CurPos = uiPos;
|
|
pTag->CurKey = MIX_KEY( pTag, pNode, uiPos );
|
|
pTag->fEof = FALSE;
|
|
}
|
|
else
|
|
{
|
|
pTag->fEof = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
static BOOL hb_mixTagRefreshKey( PMIXTAG pTag )
|
|
{
|
|
SQLMIXAREAP pArea;
|
|
|
|
pArea = pTag->pArea;
|
|
|
|
if ( pArea->lpdbPendingRel )
|
|
SELF_FORCEREL( ( AREAP ) pArea );
|
|
|
|
if ( ! pArea->fPositioned )
|
|
{
|
|
pTag->fEof = TRUE;
|
|
return FALSE;
|
|
}
|
|
else if ( pTag->fEof || pTag->CurKey->rec != pArea->ulRecNo )
|
|
{
|
|
PMIXKEY pKey;
|
|
PMIXNODE pNode;
|
|
UINT ui;
|
|
|
|
pKey = hb_mixKeyEval( NULL, pTag );
|
|
|
|
hb_mixTagFindKey( pTag, pKey, pTag->uiKeyLen, &pNode, &ui, FALSE );
|
|
hb_mixTagSetCurrent( pTag, pNode, ui );
|
|
|
|
hb_mixKeyFree( pKey );
|
|
return ! pTag->fEof && pTag->CurKey->rec == pArea->ulRecNo;
|
|
}
|
|
pTag->fBof = pTag->fEof = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static void hb_mixTagAddKeyNode( PMIXTAG pTag, PMIXNODE pNode, UINT uiPos, PMIXKEY pKey, PMIXNODE pChildLeft, PMIXNODE pChildRight )
|
|
{
|
|
MIX_COPY_KEYS_INTERNAL( pTag, pNode, uiPos + 1, uiPos, pNode->KeyCount - uiPos );
|
|
if ( ! pNode->Leaf )
|
|
{
|
|
MIX_COPY_CHILDS_INTERNAL( pTag, pNode, uiPos + 2, uiPos + 1, pNode->KeyCount - uiPos );
|
|
pNode->Child[ uiPos ] = pChildLeft;
|
|
pNode->Child[ uiPos + 1 ] = pChildRight;
|
|
pChildLeft->Parent = pNode;
|
|
pChildRight->Parent = pNode;
|
|
}
|
|
MIX_ASSIGN_KEY( pTag, pNode, uiPos, pKey );
|
|
pNode->KeyCount++;
|
|
}
|
|
|
|
|
|
static void hb_mixTagAddKeyPos( PMIXTAG pTag, PMIXNODE pNode, UINT uiPos, PMIXKEY pKey, PMIXNODE pChildLeft, PMIXNODE pChildRight )
|
|
{
|
|
PMIXNODE pNewNode;
|
|
UINT j, k;
|
|
|
|
if ( pNode->KeyCount < MIX_NODE_ORDER )
|
|
{
|
|
hb_mixTagAddKeyNode( pTag, pNode, uiPos, pKey, pChildLeft, pChildRight );
|
|
return;
|
|
}
|
|
|
|
#ifdef USE_SIBLINGS
|
|
/* Try use siblings, if leaf node is full */
|
|
|
|
if ( pNode->Leaf && pNode->Parent )
|
|
{
|
|
j = hb_mixTagNodeParentIndex( pNode );
|
|
|
|
if ( j > 0 && pNode->Parent->Child[ j - 1 ]->KeyCount < MIX_NODE_ORDER )
|
|
{
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pNode->Parent->Child[ j - 1 ], pNode->Parent->Child[ j - 1 ]->KeyCount, pNode->Parent, j - 1, 1 );
|
|
pNode->Parent->Child[ j - 1 ]->KeyCount++;
|
|
|
|
if ( uiPos == 0 )
|
|
{
|
|
MIX_ASSIGN_KEY( pTag, pNode->Parent, j - 1, pKey );
|
|
pNode->Parent->Key[ j - 1 ] = pKey;
|
|
}
|
|
else
|
|
{
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pNode->Parent, j - 1, pNode, 0 , 1 );
|
|
uiPos--;
|
|
MIX_COPY_KEYS_INTERNAL( pTag, pNode, 0, 1, uiPos );
|
|
MIX_ASSIGN_KEY( pTag, pNode, uiPos, pKey );
|
|
}
|
|
|
|
return;
|
|
}
|
|
else if ( j < pNode->Parent->KeyCount && pNode->Parent->Child[ j + 1 ]->KeyCount < MIX_NODE_ORDER )
|
|
{
|
|
MIX_COPY_KEYS_INTERNAL( pTag, pNode->Parent->Child[ j + 1 ], 1, 0, pNode->Parent->Child[ j + 1 ]->KeyCount );
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pNode->Parent->Child[ j + 1 ], 0, pNode->Parent, j, 1 );
|
|
pNode->Parent->Child[ j + 1 ]->KeyCount++;
|
|
|
|
if ( uiPos == MIX_NODE_ORDER )
|
|
{
|
|
MIX_ASSIGN_KEY( pTag, pNode->Parent, j, pKey );
|
|
}
|
|
else
|
|
{
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pNode->Parent, j, pNode, MIX_NODE_ORDER - 1, 1 );
|
|
MIX_COPY_KEYS_INTERNAL( pTag, pNode, uiPos + 1, uiPos, MIX_NODE_ORDER - uiPos - 1 );
|
|
MIX_ASSIGN_KEY( pTag, pNode, uiPos, pKey );
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
#endif /* USE_SIBLINGS */
|
|
|
|
|
|
/* Create new node */
|
|
pNewNode = hb_mixTagCreateNode( pTag, pNode->Leaf );
|
|
|
|
/* Move half of items to new node */
|
|
k = MIX_NODE_ORDER / 2 + ( ( uiPos <= MIX_NODE_ORDER / 2 ) ? 0 : 1 );
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pNewNode, 0, pNode, k, MIX_NODE_ORDER - k );
|
|
if ( ! pNode->Leaf )
|
|
{
|
|
MIX_COPY_CHILDS_EXTERNAL( pTag, pNewNode, 1, pNode, k + 1, MIX_NODE_ORDER - k );
|
|
for ( j = 1; j <= MIX_NODE_ORDER - k; j++ )
|
|
{
|
|
pNewNode->Child[ j ]->Parent = pNewNode; // Do NOT forget to re-parent
|
|
}
|
|
}
|
|
pNode->KeyCount = k;
|
|
pNewNode->KeyCount = MIX_NODE_ORDER - k;
|
|
|
|
|
|
/* Insert new item to the left node or right node */
|
|
if ( uiPos <= MIX_NODE_ORDER / 2 )
|
|
hb_mixTagAddKeyNode( pTag, pNode, uiPos, pKey, pChildLeft, pChildRight );
|
|
else
|
|
hb_mixTagAddKeyNode( pTag, pNewNode, uiPos - MIX_NODE_ORDER / 2 - 1, pKey, pChildLeft, pChildRight );
|
|
|
|
|
|
/* Assign the leftmost child of the new node */
|
|
if ( ! pNode->Leaf )
|
|
{
|
|
pNewNode->Child[ 0 ] = pNode->Child[ pNode->KeyCount ];
|
|
pNewNode->Child[ 0 ]->Parent = pNewNode;
|
|
}
|
|
|
|
pNode->KeyCount--;
|
|
|
|
/* Move middle (last+1 in first node) item up */
|
|
if ( pNode->Parent )
|
|
{
|
|
hb_mixTagAddKeyPos( pTag, pNode->Parent, hb_mixTagNodeParentIndex( pNode ),
|
|
MIX_KEY( pTag, pNode, pNode->KeyCount ), pNode, pNewNode );
|
|
}
|
|
else
|
|
{
|
|
pTag->Root = hb_mixTagCreateNode( pTag, 0 );
|
|
hb_mixTagAddKeyNode( pTag, pTag->Root, 0, MIX_KEY( pTag, pNode, pNode->KeyCount ), pNode, pNewNode );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static BOOL hb_mixTagAddKey( PMIXTAG pTag, PMIXKEY pKey )
|
|
{
|
|
PMIXNODE pNode;
|
|
UINT ui;
|
|
int i;
|
|
|
|
i = hb_mixTagFindKey( pTag, pKey, pTag->uiKeyLen, &pNode, &ui, FALSE );
|
|
|
|
/* Key can not be duplicated */
|
|
if ( ! i )
|
|
return FALSE;
|
|
|
|
hb_mixTagAddKeyPos( pTag, pNode, ui, pKey, NULL, NULL );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static void hb_mixTagDelKeyNode( PMIXTAG pTag, PMIXNODE pNode, UINT uiPos )
|
|
{
|
|
MIX_COPY_KEYS_INTERNAL( pTag, pNode, uiPos, uiPos + 1, pNode->KeyCount - uiPos - 1 );
|
|
if ( ! pNode->Leaf )
|
|
{
|
|
MIX_COPY_CHILDS_INTERNAL( pTag, pNode, uiPos, uiPos + 1, pNode->KeyCount - uiPos );
|
|
}
|
|
pNode->KeyCount--;
|
|
}
|
|
|
|
|
|
static void hb_mixTagNodeAdjust( PMIXTAG pTag, PMIXNODE pNode )
|
|
{
|
|
UINT i, j;
|
|
PMIXNODE pParent, pSibling;
|
|
|
|
|
|
while ( 1 )
|
|
{
|
|
if ( pNode->KeyCount >= MIX_NODE_ORDER / 2 )
|
|
return;
|
|
|
|
/* Check siblings */
|
|
|
|
if ( pNode->Parent )
|
|
{
|
|
pParent = pNode->Parent;
|
|
j = hb_mixTagNodeParentIndex( pNode );
|
|
|
|
if ( j > 0 && pParent->Child[ j - 1 ]->KeyCount > MIX_NODE_ORDER / 2 )
|
|
{
|
|
/* Borrow from left */
|
|
|
|
pSibling = pParent->Child[ j - 1 ];
|
|
|
|
/* It could not be pNode->Child[ 0 ] if it is not Leaf!!! */
|
|
hb_mixTagAddKeyNode( pTag, pNode, 0, MIX_KEY( pTag, pParent, j - 1 ), pSibling->Child[ pSibling->KeyCount ], pNode->Child[ 0 ] );
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pParent, j - 1, pSibling, pSibling->KeyCount - 1, 1 );
|
|
pSibling->KeyCount--;
|
|
return;
|
|
}
|
|
else if ( j < pParent->KeyCount && pParent->Child[ j + 1 ]->KeyCount > MIX_NODE_ORDER / 2 )
|
|
{
|
|
/* Borrow from right */
|
|
|
|
pSibling = pParent->Child[ j + 1 ];
|
|
hb_mixTagAddKeyNode( pTag, pNode, pNode->KeyCount, MIX_KEY( pTag, pParent, j ), pNode->Child[ pNode->KeyCount ], pSibling->Child[ 0 ] );
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pParent, j, pSibling, 0, 1 );
|
|
hb_mixTagDelKeyNode( pTag, pSibling, 0 );
|
|
return;
|
|
}
|
|
else if ( j > 0 )
|
|
{
|
|
/* Join with left */
|
|
|
|
pSibling = pParent->Child[ j - 1 ];
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pSibling, pSibling->KeyCount, pParent, j - 1, 1 );
|
|
pSibling->KeyCount++;
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pSibling, pSibling->KeyCount, pNode, 0, pNode->KeyCount );
|
|
|
|
if ( pNode->Leaf )
|
|
{
|
|
pSibling->KeyCount += pNode->KeyCount;
|
|
}
|
|
else
|
|
{
|
|
MIX_COPY_CHILDS_EXTERNAL( pTag, pSibling, pSibling->KeyCount, pNode, 0, pNode->KeyCount );
|
|
for ( i = 0; i < pNode->KeyCount; i++ )
|
|
{
|
|
pSibling->Child[ pSibling->KeyCount++ ]->Parent = pSibling;
|
|
}
|
|
pSibling->Child[ pSibling->KeyCount ] = pNode->Child[ i ];
|
|
pSibling->Child[ pSibling->KeyCount ]->Parent = pSibling;
|
|
}
|
|
hb_xfree( pNode );
|
|
pParent->Child[ j ] = pSibling;
|
|
hb_mixTagDelKeyNode( pTag, pParent, j - 1 );
|
|
pNode = pParent;
|
|
}
|
|
else if ( j < pParent->KeyCount )
|
|
{
|
|
/* Join with right */
|
|
|
|
pSibling = pParent->Child[ j + 1 ];
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pNode, pNode->KeyCount, pParent, j, 1 );
|
|
pNode->KeyCount++;
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pNode, pNode->KeyCount, pSibling, 0, pSibling->KeyCount );
|
|
if ( pNode->Leaf )
|
|
{
|
|
pNode->KeyCount += pSibling->KeyCount;
|
|
}
|
|
else
|
|
{
|
|
MIX_COPY_CHILDS_EXTERNAL( pTag, pNode, pNode->KeyCount, pSibling, 0, pSibling->KeyCount );
|
|
for ( i = 0; i < pSibling->KeyCount; i++ )
|
|
{
|
|
pNode->Child[ pNode->KeyCount++ ]->Parent = pNode;
|
|
}
|
|
pNode->Child[ pNode->KeyCount ] = pSibling->Child[ i ];
|
|
pNode->Child[ pNode->KeyCount ]->Parent = pNode;
|
|
}
|
|
hb_xfree( pSibling );
|
|
pParent->Child[ j + 1 ] = pNode;
|
|
hb_mixTagDelKeyNode( pTag, pParent, j );
|
|
pNode = pParent;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Adjust root */
|
|
|
|
if ( ! pNode->KeyCount && ! pNode->Leaf )
|
|
{
|
|
pTag->Root = pNode->Child[ 0 ];
|
|
pTag->Root->Parent = NULL;
|
|
hb_xfree( pNode );
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void hb_mixTagDelKeyPos( PMIXTAG pTag, PMIXNODE pNode, UINT uiPos )
|
|
{
|
|
if ( pNode->Leaf )
|
|
{
|
|
hb_mixTagDelKeyNode( pTag, pNode, uiPos );
|
|
hb_mixTagNodeAdjust( pTag, pNode );
|
|
}
|
|
else
|
|
{
|
|
PMIXNODE pLeaf;
|
|
|
|
pLeaf = pNode->Child[ uiPos + 1 ];
|
|
while ( ! pLeaf->Leaf )
|
|
{
|
|
pLeaf = pLeaf->Child[ 0 ];
|
|
}
|
|
MIX_COPY_KEYS_EXTERNAL( pTag, pNode, uiPos, pLeaf, 0, 1 );
|
|
hb_mixTagDelKeyNode( pTag, pLeaf, 0 );
|
|
hb_mixTagNodeAdjust( pTag, pLeaf );
|
|
}
|
|
}
|
|
|
|
|
|
static BOOL hb_mixTagDelKey( PMIXTAG pTag, PMIXKEY pKey )
|
|
{
|
|
PMIXNODE pNode;
|
|
UINT ui;
|
|
int i;
|
|
|
|
i = hb_mixTagFindKey( pTag, pKey, pTag->uiKeyLen, &pNode, &ui, FALSE );
|
|
|
|
if ( i )
|
|
return FALSE;
|
|
|
|
hb_mixTagDelKeyPos( pTag, pNode, ui );
|
|
return 1;
|
|
}
|
|
|
|
|
|
static BYTE* hb_mixBuildSortTable( PHB_CODEPAGE pCodepage )
|
|
{
|
|
BYTE* pSortTable;
|
|
BYTE* pChars;
|
|
int i, j;
|
|
BYTE c;
|
|
|
|
pSortTable = (BYTE*) hb_xalloc( 256 );
|
|
|
|
if ( pCodepage && pCodepage->s_chars )
|
|
{
|
|
pChars = pCodepage->s_chars;
|
|
|
|
c = 0;
|
|
for ( i = 0; i < 256; i++ )
|
|
{
|
|
for ( j = 0; j < 256; j++ )
|
|
{
|
|
if ( pChars[ j ] == (BYTE) i )
|
|
{
|
|
pSortTable[ j ] = c;
|
|
c++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( i = 0; i < 256; i++ )
|
|
pSortTable[ i ] = ( BYTE ) i;
|
|
}
|
|
return pSortTable;
|
|
}
|
|
|
|
|
|
static PMIXTAG hb_mixTagCreate( char* szTagName, PHB_ITEM pKeyExpr, PHB_ITEM pKeyItem, PHB_ITEM pForItem, PHB_ITEM pWhileItem, BYTE bType, UINT uiKeyLen, SQLMIXAREAP pArea )
|
|
{
|
|
PMIXTAG pTag;
|
|
PMIXKEY pKey = NULL;
|
|
LPDBORDERCONDINFO pOrdCondInfo = pArea->lpdbOrdCondInfo;
|
|
ULONG ulStartRec, ulNextCount = 0;
|
|
LONG lStep = 0;
|
|
PHB_ITEM pItem, pEvalItem = NULL;
|
|
|
|
pTag = ( PMIXTAG ) hb_xgrab( sizeof( MIXTAG ) );
|
|
memset( pTag, 0, sizeof( MIXTAG ) );
|
|
|
|
pTag->pArea = pArea;
|
|
|
|
pTag->szName = (char*) hb_xgrab( MIX_MAXTAGNAMELEN + 1 );
|
|
hb_strncpyUpperTrim( pTag->szName, szTagName, MIX_MAXTAGNAMELEN );
|
|
|
|
pTag->szKeyExpr = (char*) hb_xgrab( hb_itemGetCLen( pKeyExpr ) + 1 );
|
|
hb_strncpyTrim( pTag->szKeyExpr, hb_itemGetCPtr( pKeyExpr ), hb_itemGetCLen( pKeyExpr ) );
|
|
|
|
/* TODO: FOR expresion */
|
|
pTag->szForExpr = NULL;
|
|
|
|
pTag->pKeyItem = pKeyItem;
|
|
pTag->pForItem = pForItem;
|
|
pTag->bType = bType;
|
|
pTag->uiKeyLen = uiKeyLen;
|
|
|
|
pTag->uiTotalLen = sizeof( MIXKEY ) + pTag->uiKeyLen;
|
|
|
|
/* Use national support */
|
|
if ( bType == 'C' )
|
|
{
|
|
if( pArea->cdPage && pArea->cdPage->lSort && !pArea->pSortTable )
|
|
{
|
|
pArea->pSortTable = hb_mixBuildSortTable( pArea->cdPage );
|
|
}
|
|
pTag->pSortTable = pArea->pSortTable;
|
|
}
|
|
|
|
pTag->Root = hb_mixTagCreateNode( pTag, TRUE );
|
|
|
|
ulStartRec = 0;
|
|
|
|
if ( pOrdCondInfo )
|
|
{
|
|
pEvalItem = pOrdCondInfo->itmCobEval;
|
|
lStep = pOrdCondInfo->lStep;
|
|
}
|
|
|
|
if ( ! pOrdCondInfo || pOrdCondInfo->fAll )
|
|
{
|
|
pArea->pTag = NULL;
|
|
}
|
|
else
|
|
{
|
|
if ( pOrdCondInfo->itmRecID )
|
|
ulStartRec = hb_itemGetNL( pOrdCondInfo->itmRecID );
|
|
|
|
if ( ulStartRec )
|
|
{
|
|
ulNextCount = 1;
|
|
}
|
|
else if ( pOrdCondInfo->fRest || pOrdCondInfo->lNextCount > 0 )
|
|
{
|
|
if ( pOrdCondInfo->itmStartRecID )
|
|
ulStartRec = hb_itemGetNL( pOrdCondInfo->itmStartRecID );
|
|
|
|
if ( !ulStartRec )
|
|
ulStartRec = pArea->ulRecNo;
|
|
|
|
if ( pArea->lpdbOrdCondInfo->lNextCount > 0 )
|
|
ulNextCount = pOrdCondInfo->lNextCount;
|
|
}
|
|
else if ( ! pOrdCondInfo->fUseCurrent )
|
|
{
|
|
pArea->pTag = NULL;
|
|
}
|
|
}
|
|
|
|
if ( ulStartRec == 0 && pArea->pTag == NULL )
|
|
ulStartRec = 1;
|
|
|
|
if ( ulStartRec )
|
|
{
|
|
SELF_GOTO( (AREAP) pArea, ulStartRec );
|
|
}
|
|
else
|
|
{
|
|
SELF_GOTOP( (AREAP) pArea );
|
|
}
|
|
|
|
while ( ! pArea->fEof )
|
|
{
|
|
if ( pEvalItem )
|
|
{
|
|
if ( lStep >= pOrdCondInfo->lStep )
|
|
{
|
|
lStep = 0;
|
|
if ( ! hb_mixEvalCond( NULL, pEvalItem ) )
|
|
break;
|
|
}
|
|
++lStep;
|
|
}
|
|
|
|
if ( pWhileItem && ! hb_mixEvalCond( NULL, pWhileItem ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( pForItem == NULL || hb_mixEvalCond( NULL, pForItem ) )
|
|
{
|
|
pItem = hb_vmEvalBlockOrMacro( pKeyItem );
|
|
|
|
pKey = hb_mixKeyPutItem( pKey, pItem, pArea->ulRecNo, pTag );
|
|
hb_mixTagAddKey( pTag, pKey );
|
|
}
|
|
|
|
if ( ulNextCount )
|
|
{
|
|
ulNextCount--;
|
|
if ( !ulNextCount ) break;
|
|
}
|
|
if ( SELF_SKIPRAW( ( AREAP ) pArea, 1 ) == HB_FAILURE )
|
|
break;
|
|
}
|
|
if ( pKey )
|
|
hb_mixKeyFree( pKey );
|
|
|
|
return pTag;
|
|
}
|
|
|
|
|
|
static void hb_mixTagDestroyNode( PMIXNODE pNode )
|
|
{
|
|
if ( ! pNode->Leaf )
|
|
{
|
|
UINT ui;
|
|
|
|
for ( ui = 0; ui <= pNode->KeyCount; ui++ )
|
|
hb_mixTagDestroyNode( pNode->Child[ ui ] );
|
|
}
|
|
hb_xfree( pNode );
|
|
}
|
|
|
|
|
|
static void hb_mixTagDestroy( PMIXTAG pTag )
|
|
{
|
|
if ( pTag->szName )
|
|
hb_xfree( pTag->szName );
|
|
|
|
if ( pTag->szKeyExpr )
|
|
hb_xfree( pTag->szKeyExpr );
|
|
|
|
if ( pTag->szForExpr )
|
|
hb_xfree( pTag->szForExpr );
|
|
|
|
if ( pTag->pKeyItem )
|
|
hb_vmDestroyBlockOrMacro( pTag->pKeyItem );
|
|
|
|
if ( pTag->pForItem )
|
|
hb_vmDestroyBlockOrMacro( pTag->pForItem );
|
|
|
|
if ( pTag->Root )
|
|
{
|
|
hb_mixTagDestroyNode( pTag->Root );
|
|
}
|
|
|
|
hb_xfree( pTag );
|
|
}
|
|
|
|
|
|
static void hb_mixTagGoTop( PMIXTAG pTag )
|
|
{
|
|
PMIXNODE pNode;
|
|
|
|
pNode = pTag->Root;
|
|
while ( ! pNode->Leaf )
|
|
{
|
|
pNode = pNode->Child[ 0 ];
|
|
}
|
|
|
|
if ( ! pNode->KeyCount )
|
|
{
|
|
pTag->fEof = TRUE;
|
|
return;
|
|
}
|
|
pTag->fEof = FALSE;
|
|
pTag->CurNode = pNode;
|
|
pTag->CurPos = 0;
|
|
pTag->CurKey = MIX_KEY( pTag, pTag->CurNode, 0 );
|
|
}
|
|
|
|
|
|
static void hb_mixTagGoBottom( PMIXTAG pTag )
|
|
{
|
|
PMIXNODE pNode;
|
|
|
|
pNode = pTag->Root;
|
|
while ( ! pNode->Leaf )
|
|
{
|
|
pNode = pNode->Child[ pNode->KeyCount ];
|
|
}
|
|
|
|
if ( ! pNode->KeyCount )
|
|
{
|
|
pTag->fEof = TRUE;
|
|
return;
|
|
}
|
|
pTag->fEof = FALSE;
|
|
pTag->CurNode = pNode;
|
|
pTag->CurPos = pNode->KeyCount - 1;
|
|
pTag->CurKey = MIX_KEY( pTag, pTag->CurNode, pTag->CurPos );
|
|
}
|
|
|
|
|
|
static void hb_mixTagSkip( PMIXTAG pTag, LONG lSkip )
|
|
{
|
|
PMIXNODE pNode, pNode2;
|
|
UINT uiPos, uiPos2;
|
|
|
|
pNode = pTag->CurNode;
|
|
uiPos = pTag->CurPos;
|
|
|
|
/* printf("hb_mixTagSkip: CurNode=%p, CurPos=%d lSkip=%d\n", pNode, uiPos, lSkip ); */
|
|
|
|
if ( lSkip > 0 )
|
|
{
|
|
pTag->fBof = FALSE;
|
|
while ( ! pTag->fEof && lSkip > 0 )
|
|
{
|
|
if ( pNode->Leaf )
|
|
{
|
|
if ( (LONG) (pNode->KeyCount - 1 - uiPos) >= lSkip )
|
|
{
|
|
uiPos += lSkip;
|
|
lSkip = 0;
|
|
}
|
|
else if ( pNode->KeyCount - 1 > uiPos )
|
|
{
|
|
lSkip -= (LONG) (pNode->KeyCount - 1 - uiPos);
|
|
uiPos = pNode->KeyCount - 1;
|
|
}
|
|
if ( lSkip )
|
|
{
|
|
do {
|
|
if ( pNode->Parent )
|
|
uiPos = hb_mixTagNodeParentIndex( pNode );
|
|
pNode = pNode->Parent;
|
|
} while ( pNode && uiPos == pNode->KeyCount );
|
|
|
|
if ( pNode )
|
|
{
|
|
lSkip--;
|
|
}
|
|
else
|
|
{
|
|
pTag->fEof = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNode = pNode->Child[ uiPos + 1 ];
|
|
while ( ! pNode->Leaf )
|
|
{
|
|
pNode = pNode->Child[ 0 ];
|
|
}
|
|
uiPos = 0;
|
|
lSkip--;
|
|
}
|
|
}
|
|
}
|
|
else if ( lSkip < 0 )
|
|
{
|
|
lSkip = - lSkip;
|
|
|
|
/*
|
|
This is not needed. skip(-1) from Eof is processed inside sqlmixSkipRaw
|
|
if ( pTag->fEof )
|
|
{
|
|
hb_mixTagGoBottom( pTag );
|
|
lSkip--;
|
|
pTag->fBof = pTag->fEof;
|
|
}
|
|
*/
|
|
pTag->fBof = pTag->fEof;
|
|
|
|
while ( ! pTag->fBof && lSkip > 0 )
|
|
{
|
|
if ( pNode->Leaf )
|
|
{
|
|
if ( (LONG) uiPos >= lSkip )
|
|
{
|
|
uiPos -= lSkip;
|
|
lSkip = 0;
|
|
}
|
|
else if ( uiPos )
|
|
{
|
|
lSkip -= uiPos;
|
|
uiPos = 0;
|
|
}
|
|
if ( lSkip )
|
|
{
|
|
pNode2 = pNode;
|
|
uiPos2 = uiPos;
|
|
do {
|
|
if ( pNode->Parent )
|
|
uiPos = hb_mixTagNodeParentIndex( pNode );
|
|
pNode = pNode->Parent;
|
|
} while ( pNode && uiPos == 0 );
|
|
|
|
if ( pNode )
|
|
{
|
|
uiPos--;
|
|
lSkip--;
|
|
}
|
|
else
|
|
{
|
|
pNode = pNode2;
|
|
uiPos = uiPos2;
|
|
pTag->fBof = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
pNode = pNode->Child[ uiPos ];
|
|
uiPos = pNode->KeyCount;
|
|
}
|
|
while ( ! pNode->Leaf );
|
|
uiPos--;
|
|
lSkip--;
|
|
}
|
|
}
|
|
}
|
|
if ( ! pTag->fEof )
|
|
{
|
|
pTag->CurNode = pNode;
|
|
pTag->CurPos = uiPos;
|
|
pTag->CurKey = MIX_KEY( pTag, pNode, uiPos );
|
|
}
|
|
}
|
|
|
|
/* -------------------------- Misc functions ---------------------------- */
|
|
/* hb_mix*() */
|
|
|
|
static PMIXTAG hb_mixFindTag( SQLMIXAREAP pArea, PHB_ITEM pOrder )
|
|
{
|
|
PMIXTAG pTag;
|
|
|
|
if ( HB_IS_NUMBER( pOrder ) )
|
|
{
|
|
int iOrder, iCurr = 0;
|
|
|
|
iOrder = hb_itemGetNI( pOrder );
|
|
|
|
pTag = pArea->pTagList;
|
|
while ( pTag && iOrder != ++iCurr )
|
|
{
|
|
pTag = pTag->pNext;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
char szTag[ MIX_MAXTAGNAMELEN + 1 ];
|
|
|
|
hb_strncpyUpperTrim( szTag, hb_itemGetCPtr( pOrder ), MIX_MAXTAGNAMELEN );
|
|
pTag = pArea->pTagList;
|
|
while ( pTag && hb_stricmp( szTag, pTag->szName ) )
|
|
{
|
|
pTag = pTag->pNext;
|
|
}
|
|
}
|
|
return pTag;
|
|
}
|
|
|
|
|
|
/*=======================================================================*/
|
|
|
|
|
|
static ULONG hb_mixTagNodeKeyCount( PMIXNODE pNode )
|
|
{
|
|
ULONG ulKeyCount;
|
|
UINT ui;
|
|
|
|
ulKeyCount = pNode->KeyCount;
|
|
if ( ! pNode->Leaf )
|
|
{
|
|
for ( ui = 0; ui <= pNode->KeyCount; ui++ )
|
|
ulKeyCount += hb_mixTagNodeKeyCount( pNode->Child[ ui ] );
|
|
}
|
|
return ulKeyCount;
|
|
}
|
|
|
|
|
|
static BOOL hb_mixCheckRecordFilter( SQLMIXAREAP pArea, ULONG ulRecNo )
|
|
{
|
|
BOOL lResult = FALSE;
|
|
|
|
if ( pArea->dbfi.itmCobExpr || hb_setGetDeleted() )
|
|
{
|
|
if ( pArea->ulRecNo != ulRecNo || pArea->lpdbPendingRel )
|
|
SELF_GOTO( ( AREAP ) pArea, ulRecNo );
|
|
|
|
if ( hb_setGetDeleted() )
|
|
SUPER_DELETED( ( AREAP ) pArea, &lResult );
|
|
|
|
if ( !lResult && pArea->dbfi.itmCobExpr )
|
|
{
|
|
PHB_ITEM pResult = hb_vmEvalBlock( pArea->dbfi.itmCobExpr );
|
|
lResult = HB_IS_LOGICAL( pResult ) && !hb_itemGetL( pResult );
|
|
}
|
|
}
|
|
return !lResult;
|
|
}
|
|
|
|
|
|
static ULONG hb_mixDBOIKeyCount( PMIXTAG pTag, BOOL fFilter )
|
|
{
|
|
ULONG ulKeyCount;
|
|
|
|
if ( ! pTag )
|
|
return 0;
|
|
|
|
if ( fFilter && pTag->pArea->dbfi.fFilter )
|
|
{
|
|
PMIXNODE pNode = pTag->CurNode;
|
|
UINT uiPos = pTag->CurPos;
|
|
ULONG ulRecNo = pTag->pArea->ulRecNo;
|
|
|
|
ulKeyCount = 0;
|
|
|
|
hb_mixTagGoTop( pTag );
|
|
while ( ! pTag->fEof )
|
|
{
|
|
if ( hb_mixCheckRecordFilter( pTag->pArea, pTag->CurKey->rec ) )
|
|
ulKeyCount++;
|
|
hb_mixTagSkip( pTag, 1 );
|
|
}
|
|
hb_mixTagSetCurrent( pTag, pNode, uiPos );
|
|
SELF_GOTO( (AREAP) pTag->pArea, ulRecNo );
|
|
|
|
}
|
|
else
|
|
{
|
|
ulKeyCount = hb_mixTagNodeKeyCount( pTag->Root );
|
|
}
|
|
return ulKeyCount;
|
|
}
|
|
|
|
|
|
static ULONG hb_mixDBOIKeyNo( PMIXTAG pTag, BOOL fFilter )
|
|
{
|
|
ULONG ulKeyCount;
|
|
|
|
if ( ! pTag )
|
|
return 0;
|
|
|
|
if ( fFilter )
|
|
ulKeyCount = 0;
|
|
else
|
|
{
|
|
PMIXNODE pNode = pTag->CurNode;
|
|
UINT ui, uiPos = pTag->CurPos;
|
|
|
|
ulKeyCount = 1;
|
|
|
|
while ( pNode )
|
|
{
|
|
ulKeyCount += uiPos;
|
|
if ( ! pNode->Leaf )
|
|
{
|
|
for ( ui = 0; ui < uiPos; ui++ )
|
|
ulKeyCount += hb_mixTagNodeKeyCount( pNode->Child[ ui ] );
|
|
}
|
|
pNode = pNode->Parent;
|
|
if ( pNode )
|
|
uiPos = hb_mixTagNodeParentIndex( pNode );
|
|
}
|
|
}
|
|
return ulKeyCount;
|
|
}
|
|
|
|
|
|
/*
|
|
=======================================================================
|
|
SQLMIX RDD METHODS
|
|
=======================================================================
|
|
*/
|
|
|
|
static HB_ERRCODE sqlmixGoBottom( SQLMIXAREAP pArea )
|
|
{
|
|
HB_ERRCODE retval;
|
|
|
|
if ( SELF_GOCOLD( ( AREAP ) pArea ) == HB_FAILURE )
|
|
return HB_FAILURE;
|
|
|
|
if ( ! pArea->pTag )
|
|
return SUPER_GOBOTTOM( ( AREAP ) pArea );
|
|
|
|
if ( pArea->lpdbPendingRel && pArea->lpdbPendingRel->isScoped )
|
|
SELF_FORCEREL( ( AREAP ) pArea );
|
|
|
|
hb_mixTagGoBottom( pArea->pTag );
|
|
|
|
pArea->fTop = FALSE;
|
|
pArea->fBottom = TRUE;
|
|
|
|
retval = SELF_GOTO( ( AREAP ) pArea, pArea->pTag->CurKey ? pArea->pTag->CurKey->rec : 0 );
|
|
if ( retval != HB_FAILURE && pArea->fPositioned )
|
|
retval = SELF_SKIPFILTER( ( AREAP ) pArea, -1 );
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixGoTop( SQLMIXAREAP pArea )
|
|
{
|
|
HB_ERRCODE retval;
|
|
|
|
if ( SELF_GOCOLD( ( AREAP ) pArea ) == HB_FAILURE )
|
|
return HB_FAILURE;
|
|
|
|
if ( ! pArea->pTag )
|
|
return SUPER_GOTOP( ( AREAP ) pArea );
|
|
|
|
if ( pArea->lpdbPendingRel && pArea->lpdbPendingRel->isScoped )
|
|
SELF_FORCEREL( ( AREAP ) pArea );
|
|
|
|
hb_mixTagGoTop( pArea->pTag );
|
|
|
|
pArea->fTop = TRUE;
|
|
pArea->fBottom = FALSE;
|
|
|
|
retval = SELF_GOTO( ( AREAP ) pArea, pArea->pTag->CurKey ? pArea->pTag->CurKey->rec : 0 );
|
|
if ( retval != HB_FAILURE && pArea->fPositioned )
|
|
retval = SELF_SKIPFILTER( ( AREAP ) pArea, -1 );
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixSeek( SQLMIXAREAP pArea, BOOL fSoftSeek, PHB_ITEM pItem, BOOL fFindLast )
|
|
{
|
|
if ( SELF_GOCOLD( ( AREAP ) pArea ) == HB_FAILURE )
|
|
return HB_FAILURE;
|
|
|
|
if ( ! pArea->pTag )
|
|
{
|
|
sqlmixErrorRT( pArea, EG_NOORDER, 1201, NULL, 0, EF_CANDEFAULT );
|
|
return HB_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
PMIXKEY pKey;
|
|
HB_ERRCODE retval = HB_SUCCESS;
|
|
BOOL fEOF;
|
|
PMIXTAG pTag = pArea->pTag;
|
|
PMIXNODE pNode;
|
|
UINT uiKeyLen, ui;
|
|
|
|
if ( pArea->lpdbPendingRel && pArea->lpdbPendingRel->isScoped )
|
|
SELF_FORCEREL( ( AREAP ) pArea );
|
|
|
|
pArea->fTop = pArea->fBottom = FALSE;
|
|
pArea->fEof = FALSE;
|
|
|
|
pKey = hb_mixKeyPutItem( NULL, pItem, fFindLast ? (ULONG) -1 : 0, pTag );
|
|
|
|
uiKeyLen = pTag->uiKeyLen;
|
|
if ( pTag->bType == 'C' )
|
|
{
|
|
uiKeyLen = (UINT) hb_itemGetCLen( pItem );
|
|
if ( uiKeyLen > pTag->uiKeyLen )
|
|
uiKeyLen = pTag->uiKeyLen;
|
|
}
|
|
|
|
hb_mixTagFindKey( pTag, pKey, uiKeyLen, &pNode, &ui, TRUE );
|
|
hb_mixTagSetCurrent( pTag, pNode, ui );
|
|
|
|
if ( fFindLast )
|
|
{
|
|
if ( pTag->fEof )
|
|
hb_mixTagGoBottom( pTag );
|
|
else
|
|
hb_mixTagSkip( pTag, -1 );
|
|
|
|
pArea->fFound = ! pTag->fEof && ( uiKeyLen == 0 || memcmp( pTag->CurKey->val, pKey->val, (ULONG) uiKeyLen ) == 0 );
|
|
|
|
if ( ! pArea->fFound )
|
|
hb_mixTagSetCurrent( pTag, pNode, ui );
|
|
}
|
|
else
|
|
{
|
|
pArea->fFound = ! pTag->fEof && ( uiKeyLen == 0 || memcmp( pTag->CurKey->val, pKey->val, (ULONG) uiKeyLen ) == 0 );
|
|
}
|
|
|
|
fEOF = pTag->fEof;
|
|
|
|
if ( !fEOF )
|
|
{
|
|
retval = SELF_GOTO( ( AREAP ) pArea, pTag->CurKey->rec );
|
|
if ( retval != HB_FAILURE && pArea->fPositioned )
|
|
{
|
|
retval = SELF_SKIPFILTER( ( AREAP ) pArea, fFindLast ? -1 : 1 );
|
|
if ( retval != HB_FAILURE && pArea->fPositioned )
|
|
{
|
|
pArea->fFound = ( uiKeyLen == 0 || memcmp( pTag->CurKey->val, pKey->val, (ULONG) uiKeyLen ) == 0 );
|
|
if ( ! pArea->fFound && ! fSoftSeek )
|
|
fEOF = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if ( retval != HB_FAILURE && fEOF )
|
|
{
|
|
retval = SELF_GOTO( ( AREAP ) pArea, 0 );
|
|
}
|
|
pArea->fBof = FALSE;
|
|
|
|
hb_mixKeyFree( pKey );
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixSkipRaw( SQLMIXAREAP pArea, LONG lToSkip )
|
|
{
|
|
PMIXTAG pTag = pArea->pTag;
|
|
BOOL fOut = FALSE;
|
|
|
|
if ( SELF_GOCOLD( ( AREAP ) pArea ) == HB_FAILURE )
|
|
return HB_FAILURE;
|
|
|
|
if ( ! pTag || lToSkip == 0 )
|
|
return SUPER_SKIPRAW( ( AREAP ) pArea, lToSkip );
|
|
|
|
if ( pArea->lpdbPendingRel )
|
|
SELF_FORCEREL( ( AREAP ) pArea );
|
|
|
|
if ( ! hb_mixTagRefreshKey( pTag ) )
|
|
{
|
|
if ( lToSkip > 0 || pArea->fPositioned )
|
|
fOut = TRUE;
|
|
else
|
|
{
|
|
hb_mixTagGoBottom( pTag );
|
|
fOut = pTag->fEof;
|
|
lToSkip++;
|
|
}
|
|
}
|
|
|
|
if ( ! fOut )
|
|
hb_mixTagSkip( pTag, lToSkip );
|
|
|
|
if ( SELF_GOTO( ( AREAP ) pArea, ( pTag->fEof || fOut ) ? 0 : pTag->CurKey->rec ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
pArea->fEof = pTag->fEof;
|
|
pArea->fBof = pTag->fBof;
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixGoCold( SQLMIXAREAP pArea )
|
|
{
|
|
BOOL fRecordChanged = pArea->fRecordChanged;
|
|
BOOL fAppend = pArea->fAppend;
|
|
|
|
if ( SUPER_GOCOLD( ( AREAP ) pArea ) == HB_FAILURE )
|
|
return HB_FAILURE;
|
|
|
|
if ( fRecordChanged && pArea->pTagList )
|
|
{
|
|
PMIXTAG pTag;
|
|
PMIXKEY pKey = NULL;
|
|
BOOL fAdd, fDel;
|
|
LPDBRELINFO lpdbPendingRel;
|
|
|
|
lpdbPendingRel = pArea->lpdbPendingRel;
|
|
pArea->lpdbPendingRel = NULL;
|
|
|
|
pTag = pArea->pTagList;
|
|
while ( pTag )
|
|
{
|
|
|
|
if ( ! pTag->fCustom )
|
|
{
|
|
pKey = hb_mixKeyEval( pKey, pTag );
|
|
|
|
/* printf( "sqlmixGoCold NEWKEY:%s rec:%d\n", pKey->val, pKey->rec); */
|
|
|
|
if ( pTag->pForItem != NULL )
|
|
fAdd = hb_mixEvalCond( pArea, pTag->pForItem );
|
|
else
|
|
fAdd = TRUE;
|
|
|
|
if ( fAppend )
|
|
fDel = FALSE;
|
|
else
|
|
{
|
|
if ( hb_mixKeyCompare( pTag, pKey, pTag->HotKey, pTag->uiKeyLen ) == 0 )
|
|
{
|
|
fDel = !fAdd && pTag->HotFor;
|
|
fAdd = fAdd && !pTag->HotFor;
|
|
}
|
|
else
|
|
{
|
|
fDel = pTag->HotFor;
|
|
}
|
|
}
|
|
|
|
if ( fDel )
|
|
hb_mixTagDelKey( pTag, pTag->HotKey );
|
|
|
|
if ( fAdd )
|
|
hb_mixTagAddKey( pTag, pKey );
|
|
}
|
|
pTag = pTag->pNext;
|
|
}
|
|
|
|
if ( pKey )
|
|
hb_mixKeyFree( pKey );
|
|
|
|
pArea->lpdbPendingRel = lpdbPendingRel;
|
|
}
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixGoHot( SQLMIXAREAP pArea )
|
|
{
|
|
PMIXTAG pTag;
|
|
|
|
/*
|
|
if ( pArea->fRecordChanged )
|
|
printf( "sqlmixGoHot: multiple marking buffer as hot." );
|
|
*/
|
|
|
|
if ( SUPER_GOHOT( (AREAP) pArea ) == HB_FAILURE )
|
|
return HB_FAILURE;
|
|
|
|
pTag = pArea->pTagList;
|
|
while ( pTag )
|
|
{
|
|
if ( !pTag->fCustom )
|
|
{
|
|
pTag->HotKey = hb_mixKeyEval( pTag->HotKey, pTag );
|
|
pTag->HotFor = pTag->pForItem == NULL || hb_mixEvalCond( pArea, pTag->pForItem );
|
|
}
|
|
pTag = pTag->pNext;
|
|
}
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixClose( SQLMIXAREAP pArea )
|
|
{
|
|
if ( SELF_GOCOLD( (AREAP) pArea ) == HB_FAILURE )
|
|
return HB_FAILURE;
|
|
|
|
if ( SUPER_CLOSE( (AREAP) pArea ) == HB_FAILURE )
|
|
return HB_FAILURE;
|
|
|
|
if ( SELF_ORDLSTCLEAR( (AREAP) pArea ) == HB_FAILURE )
|
|
return HB_FAILURE;
|
|
|
|
if ( pArea->pSortTable )
|
|
hb_xfree( pArea->pSortTable );
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixStructSize( SQLMIXAREAP pArea, USHORT* StructSize )
|
|
{
|
|
HB_SYMBOL_UNUSED( pArea );
|
|
|
|
* StructSize = sizeof( SQLMIXAREA );
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixOrderListClear( SQLMIXAREAP pArea )
|
|
{
|
|
PMIXTAG pTag;
|
|
|
|
while ( pArea->pTagList )
|
|
{
|
|
pTag = pArea->pTagList;
|
|
pArea->pTagList = pTag->pNext;
|
|
hb_mixTagDestroy( pTag );
|
|
}
|
|
pArea->pTag = NULL;
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixOrderListFocus( SQLMIXAREAP pArea, LPDBORDERINFO pOrderInfo )
|
|
{
|
|
if ( pArea->pTag )
|
|
{
|
|
pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, pArea->pTag->szName );
|
|
}
|
|
|
|
if ( pOrderInfo->itmOrder )
|
|
{
|
|
pArea->pTag = hb_mixFindTag( pArea, pOrderInfo->itmOrder );
|
|
}
|
|
return pArea->pTag ? HB_SUCCESS : HB_FAILURE;
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixOrderCreate( SQLMIXAREAP pArea, LPDBORDERCREATEINFO pOrderInfo )
|
|
{
|
|
PMIXTAG pTagNew, pTag;
|
|
PHB_ITEM pKeyItem, pForItem = NULL, pWhileItem = NULL, pResult;
|
|
ULONG ulRecNo;
|
|
USHORT uiLen;
|
|
BYTE bType;
|
|
|
|
/* Obtain key codeblock */
|
|
if ( pOrderInfo->itmCobExpr )
|
|
{
|
|
pKeyItem = hb_itemNew( pOrderInfo->itmCobExpr );
|
|
}
|
|
else
|
|
{
|
|
if ( SELF_COMPILE( (AREAP) pArea, (BYTE*) hb_itemGetCPtr( pOrderInfo->abExpr ) ) == HB_FAILURE )
|
|
return HB_FAILURE;
|
|
pKeyItem = pArea->valResult;
|
|
pArea->valResult = NULL;
|
|
}
|
|
|
|
/* Test key codeblock on EOF */
|
|
ulRecNo = pArea->ulRecNo;
|
|
SELF_GOTO( (AREAP) pArea, 0 );
|
|
if ( SELF_EVALBLOCK( (AREAP) pArea, pKeyItem ) == HB_FAILURE )
|
|
{
|
|
hb_vmDestroyBlockOrMacro( pKeyItem );
|
|
SELF_GOTO( (AREAP) pArea, ulRecNo );
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
pResult = pArea->valResult;
|
|
pArea->valResult = NULL;
|
|
|
|
switch ( hb_itemType( pResult ) )
|
|
{
|
|
case HB_IT_STRING:
|
|
case HB_IT_STRING | HB_IT_MEMO:
|
|
bType = 'C';
|
|
uiLen = (USHORT) hb_itemGetCLen( pResult );
|
|
if ( uiLen > MIX_MAXKEYLEN ) uiLen = MIX_MAXKEYLEN;
|
|
break;
|
|
|
|
case HB_IT_INTEGER:
|
|
case HB_IT_LONG:
|
|
case HB_IT_DOUBLE:
|
|
bType = 'N';
|
|
uiLen = 8;
|
|
break;
|
|
|
|
case HB_IT_DATE:
|
|
bType = 'D';
|
|
uiLen = 8;
|
|
break;
|
|
|
|
case HB_IT_LOGICAL:
|
|
bType = 'L';
|
|
uiLen = 1;
|
|
break;
|
|
|
|
default:
|
|
bType = 'U';
|
|
uiLen = 0;
|
|
}
|
|
hb_itemRelease( pResult );
|
|
|
|
if ( bType == 'U' || uiLen == 0 )
|
|
{
|
|
hb_vmDestroyBlockOrMacro( pKeyItem );
|
|
SELF_GOTO( (AREAP) pArea, ulRecNo );
|
|
sqlmixErrorRT( pArea, bType == 'U' ? EG_DATATYPE : EG_DATAWIDTH, 1026, NULL, 0, 0 );
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
if ( pArea->lpdbOrdCondInfo )
|
|
{
|
|
/* Obtain FOR codeblock */
|
|
if ( pArea->lpdbOrdCondInfo->itmCobFor )
|
|
{
|
|
pForItem = hb_itemNew( pArea->lpdbOrdCondInfo->itmCobFor );
|
|
}
|
|
else if ( pArea->lpdbOrdCondInfo->abFor )
|
|
{
|
|
if ( SELF_COMPILE( (AREAP) pArea, ( BYTE * ) pArea->lpdbOrdCondInfo->abFor ) == HB_FAILURE )
|
|
{
|
|
hb_vmDestroyBlockOrMacro( pKeyItem );
|
|
SELF_GOTO( (AREAP) pArea, ulRecNo );
|
|
return HB_FAILURE;
|
|
}
|
|
pForItem = pArea->valResult;
|
|
pArea->valResult = NULL;
|
|
}
|
|
|
|
/* Obtain WHILE codeblock */
|
|
if ( pArea->lpdbOrdCondInfo->itmCobWhile )
|
|
{
|
|
pWhileItem = hb_itemNew( pArea->lpdbOrdCondInfo->itmCobWhile );
|
|
}
|
|
else if ( pArea->lpdbOrdCondInfo->abWhile )
|
|
{
|
|
if ( SELF_COMPILE( (AREAP) pArea, ( BYTE * ) pArea->lpdbOrdCondInfo->abWhile ) == HB_FAILURE )
|
|
{
|
|
hb_vmDestroyBlockOrMacro( pKeyItem );
|
|
if ( pForItem )
|
|
hb_vmDestroyBlockOrMacro( pForItem );
|
|
SELF_GOTO( (AREAP) pArea, ulRecNo );
|
|
return HB_FAILURE;
|
|
}
|
|
pWhileItem = pArea->valResult;
|
|
pArea->valResult = NULL;
|
|
}
|
|
}
|
|
|
|
/* Test FOR codeblock on EOF */
|
|
if ( pForItem )
|
|
{
|
|
if ( SELF_EVALBLOCK( (AREAP) pArea, pForItem ) == HB_FAILURE )
|
|
{
|
|
hb_vmDestroyBlockOrMacro( pKeyItem );
|
|
hb_vmDestroyBlockOrMacro( pForItem );
|
|
if ( pWhileItem )
|
|
hb_vmDestroyBlockOrMacro( pWhileItem );
|
|
SELF_GOTO( (AREAP) pArea, ulRecNo );
|
|
return HB_FAILURE;
|
|
}
|
|
if ( hb_itemType( pArea->valResult ) != HB_IT_LOGICAL )
|
|
{
|
|
hb_itemRelease( pArea->valResult );
|
|
pArea->valResult = 0;
|
|
hb_vmDestroyBlockOrMacro( pKeyItem );
|
|
hb_vmDestroyBlockOrMacro( pForItem );
|
|
if ( pWhileItem )
|
|
hb_vmDestroyBlockOrMacro( pWhileItem );
|
|
SELF_GOTO( (AREAP) pArea, ulRecNo );
|
|
sqlmixErrorRT( pArea, EG_DATATYPE, EDBF_INVALIDFOR, NULL, 0, 0 );
|
|
return HB_FAILURE;
|
|
}
|
|
hb_itemRelease( pArea->valResult );
|
|
pArea->valResult = 0;
|
|
}
|
|
|
|
/* TODO: WHILE condition is not tested, like in DBFCDX. Why? Compatibility with Clipper? */
|
|
|
|
SELF_GOTO( (AREAP) pArea, ulRecNo );
|
|
|
|
pTagNew = hb_mixTagCreate( ( char * ) pOrderInfo->atomBagName, pOrderInfo->abExpr, pKeyItem, pForItem, pWhileItem, bType, uiLen, pArea );
|
|
|
|
if ( pWhileItem )
|
|
hb_vmDestroyBlockOrMacro( pWhileItem );
|
|
|
|
/* Append the tag to the end of list */
|
|
if ( pArea->pTagList )
|
|
{
|
|
pTag = pArea->pTagList;
|
|
while ( pTag->pNext )
|
|
{
|
|
pTag = pTag->pNext;
|
|
}
|
|
pTag->pNext = pTagNew;
|
|
}
|
|
else
|
|
{
|
|
pArea->pTagList = pTagNew;
|
|
}
|
|
|
|
pArea->pTag = pTagNew;
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixOrderInfo( SQLMIXAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrderInfo )
|
|
{
|
|
PMIXTAG pTag;
|
|
USHORT uiTag = 0;
|
|
|
|
|
|
switch( uiIndex )
|
|
{
|
|
case DBOI_EVALSTEP:
|
|
pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult,
|
|
pArea->lpdbOrdCondInfo ? pArea->lpdbOrdCondInfo->lStep : 0 );
|
|
return HB_SUCCESS;
|
|
|
|
case DBOI_ORDERCOUNT:
|
|
pTag = pArea->pTagList;
|
|
while ( pTag )
|
|
{
|
|
pTag = pTag->pNext;
|
|
uiTag++;
|
|
}
|
|
pOrderInfo->itmResult = hb_itemPutNI( pOrderInfo->itmResult, uiTag );
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
|
|
if ( SELF_GOCOLD( ( AREAP ) pArea ) == HB_FAILURE )
|
|
return HB_FAILURE;
|
|
|
|
|
|
if ( pOrderInfo->itmOrder )
|
|
pTag = hb_mixFindTag( pArea, pOrderInfo->itmOrder );
|
|
else
|
|
pTag = pArea->pTag;
|
|
|
|
|
|
switch( uiIndex )
|
|
{
|
|
case DBOI_CONDITION:
|
|
pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, ( pTag ? pTag->szForExpr : NULL ) );
|
|
if ( pTag && pOrderInfo->itmNewVal && HB_IS_STRING( pOrderInfo->itmNewVal ) )
|
|
{
|
|
if ( pTag->szForExpr != NULL )
|
|
{
|
|
hb_xfree( pTag->szForExpr );
|
|
pTag->szForExpr = NULL;
|
|
}
|
|
if ( pTag->pForItem != NULL )
|
|
{
|
|
hb_vmDestroyBlockOrMacro( pTag->pForItem );
|
|
pTag->pForItem = NULL;
|
|
}
|
|
if ( hb_itemGetCLen( pOrderInfo->itmNewVal ) > 0 )
|
|
{
|
|
const char* pForExpr = hb_itemGetCPtr( pOrderInfo->itmNewVal );
|
|
|
|
if ( SELF_COMPILE( (AREAP) pArea, (BYTE*) pForExpr ) == HB_SUCCESS )
|
|
{
|
|
PHB_ITEM pForItem = pArea->valResult;
|
|
|
|
pArea->valResult = NULL;
|
|
if ( SELF_EVALBLOCK( (AREAP) pArea, pForItem ) == HB_SUCCESS )
|
|
{
|
|
if ( hb_itemType( pArea->valResult ) == HB_IT_LOGICAL )
|
|
{
|
|
pTag->szForExpr = hb_strdup( pForExpr );
|
|
pTag->pForItem = pForItem;
|
|
pForItem = NULL;
|
|
}
|
|
hb_itemRelease( pArea->valResult );
|
|
pArea->valResult = NULL;
|
|
}
|
|
if ( pForItem )
|
|
hb_vmDestroyBlockOrMacro( pForItem );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DBOI_EXPRESSION:
|
|
pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, pTag ? pTag->szKeyExpr : NULL );
|
|
break;
|
|
|
|
case DBOI_POSITION:
|
|
case DBOI_KEYNORAW:
|
|
if ( pOrderInfo->itmNewVal && HB_IS_NUMERIC( pOrderInfo->itmNewVal ) )
|
|
{
|
|
|
|
/* TODO:
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult,
|
|
hb_cdxDBOIKeyGoto( pArea, pTag,
|
|
hb_itemGetNL( pOrderInfo->itmNewVal ), uiIndex == DBOI_POSITION ) == HB_SUCCESS );
|
|
*/
|
|
}
|
|
else
|
|
pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult,
|
|
hb_mixDBOIKeyNo( pTag, uiIndex == DBOI_POSITION ) );
|
|
break;
|
|
|
|
case DBOI_KEYCOUNT:
|
|
case DBOI_KEYCOUNTRAW:
|
|
pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult,
|
|
hb_mixDBOIKeyCount( pTag, uiIndex == DBOI_KEYCOUNT ) );
|
|
break;
|
|
|
|
/* TODO:
|
|
case DBOI_FINDREC:
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult,
|
|
hb_cdxDBOIFindRec( pArea, pTag,
|
|
hb_itemGetNL( pOrderInfo->itmNewVal ), FALSE ) );
|
|
break;
|
|
|
|
case DBOI_FINDRECCONT:
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult,
|
|
hb_cdxDBOIFindRec( pArea, pTag,
|
|
hb_itemGetNL( pOrderInfo->itmNewVal ), TRUE ) );
|
|
break;
|
|
*/
|
|
case DBOI_NAME:
|
|
pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, pTag ? pTag->szName : NULL );
|
|
break;
|
|
|
|
case DBOI_NUMBER:
|
|
pOrderInfo->itmResult = hb_itemPutNI( pOrderInfo->itmResult, uiTag ); // kitaip
|
|
break;
|
|
|
|
case DBOI_ISCOND:
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, pTag && pTag->szForExpr != NULL );
|
|
break;
|
|
|
|
case DBOI_ISDESC:
|
|
case DBOI_UNIQUE:
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, FALSE );
|
|
break;
|
|
|
|
case DBOI_SCOPETOP:
|
|
case DBOI_SCOPEBOTTOM:
|
|
if ( pOrderInfo->itmResult )
|
|
hb_itemClear( pOrderInfo->itmResult );
|
|
break;
|
|
|
|
case DBOI_KEYTYPE:
|
|
if ( pTag )
|
|
{
|
|
char szType[ 2 ];
|
|
|
|
szType[ 0 ] = (char) pTag->bType;
|
|
szType[ 1 ] = 0;
|
|
pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, szType );
|
|
}
|
|
else
|
|
pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, NULL );
|
|
break;
|
|
|
|
case DBOI_KEYSIZE:
|
|
pOrderInfo->itmResult = hb_itemPutNI( pOrderInfo->itmResult, pTag ? pTag->uiKeyLen : 0 );
|
|
break;
|
|
|
|
case DBOI_KEYDEC:
|
|
pOrderInfo->itmResult = hb_itemPutNI( pOrderInfo->itmResult, 0 );
|
|
break;
|
|
|
|
/* TODO:
|
|
case DBOI_KEYVAL:
|
|
hb_itemClear( pOrderInfo->itmResult );
|
|
if ( pArea->lpdbPendingRel )
|
|
SELF_FORCEREL( ( AREAP ) pArea );
|
|
if ( pTag && pArea->fPositioned )
|
|
{
|
|
if ( pTag->CurKey->rec != pArea->ulRecNo )
|
|
{
|
|
hb_cdxIndexLockRead( pTag->pIndex );
|
|
hb_cdxCurKeyRefresh( pArea, pTag );
|
|
hb_cdxIndexUnLockRead( pTag->pIndex );
|
|
}
|
|
if ( pTag->CurKey->rec == pArea->ulRecNo )
|
|
pOrderInfo->itmResult = hb_cdxKeyGetItem( pTag->CurKey,
|
|
pOrderInfo->itmResult, pTag, TRUE );
|
|
}
|
|
break;
|
|
|
|
case DBOI_CUSTOM:
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, ( pTag ? pTag->fCustom : FALSE ) );
|
|
if ( pOrderInfo->itmNewVal && HB_IS_LOGICAL( pOrderInfo->itmNewVal )
|
|
&& hb_itemGetL( pOrderInfo->itmNewVal ) )
|
|
{
|
|
pTag->fCustom = TRUE;
|
|
}
|
|
break;
|
|
|
|
case DBOI_KEYADD:
|
|
if ( ! pTag )
|
|
{
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, FALSE );
|
|
}
|
|
else
|
|
{
|
|
if ( pTag->fCustom )
|
|
{
|
|
if ( pArea->lpdbPendingRel )
|
|
SELF_FORCEREL( ( AREAP ) pArea );
|
|
|
|
if ( ! pArea->fPositioned ||
|
|
( pTag->pForItem &&
|
|
! hb_cdxEvalCond( pArea, pTag->pForItem, TRUE ) ) )
|
|
{
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, FALSE );
|
|
}
|
|
else
|
|
{
|
|
LPCDXKEY pKey;
|
|
hb_cdxIndexLockWrite( pTag->pIndex );
|
|
if ( pOrderInfo->itmNewVal && ! HB_IS_NIL( pOrderInfo->itmNewVal ) )
|
|
pKey = hb_cdxKeyPutItem( NULL, pOrderInfo->itmNewVal, pArea->ulRecNo, pTag, TRUE, TRUE );
|
|
else
|
|
pKey = hb_cdxKeyEval( NULL, pTag );
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult,
|
|
hb_cdxTagKeyAdd( pTag, pKey ) );
|
|
hb_cdxIndexUnLockWrite( pTag->pIndex );
|
|
hb_cdxKeyFree( pKey );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sqlmixErrorRT( pArea, 0, 1052, NULL, 0, 0 );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DBOI_KEYDELETE:
|
|
if ( ! pTag )
|
|
{
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, FALSE );
|
|
}
|
|
else
|
|
{
|
|
if ( pTag->Custom )
|
|
{
|
|
if ( pArea->lpdbPendingRel )
|
|
SELF_FORCEREL( ( AREAP ) pArea );
|
|
|
|
if ( !pArea->fPositioned ||
|
|
( pTag->pForItem &&
|
|
!hb_cdxEvalCond( pArea, pTag->pForItem, TRUE ) ) )
|
|
{
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, FALSE );
|
|
}
|
|
else
|
|
{
|
|
LPCDXKEY pKey;
|
|
hb_cdxIndexLockWrite( pTag->pIndex );
|
|
if ( pOrderInfo->itmNewVal && !HB_IS_NIL( pOrderInfo->itmNewVal ) )
|
|
pKey = hb_cdxKeyPutItem( NULL, pOrderInfo->itmNewVal, pArea->ulRecNo, pTag, TRUE, TRUE );
|
|
else
|
|
pKey = hb_cdxKeyEval( NULL, pTag );
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult,
|
|
hb_cdxTagKeyDel( pTag, pKey ) );
|
|
hb_cdxIndexUnLockWrite( pTag->pIndex );
|
|
hb_cdxKeyFree( pKey );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sqlmixErrorRT( pArea, 0, 1052, NULL, 0, 0 );
|
|
}
|
|
}
|
|
break;
|
|
|
|
*/
|
|
case DBOI_SHARED:
|
|
case DBOI_ISREADONLY:
|
|
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, FALSE );
|
|
break;
|
|
|
|
default:
|
|
return SUPER_ORDINFO( ( AREAP ) pArea, uiIndex, pOrderInfo );
|
|
|
|
}
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
|
|
static HB_ERRCODE sqlmixExit( LPRDDNODE pRDD )
|
|
{
|
|
/* This empty method is used to avoid duplicated sqlbase exit call */
|
|
HB_SYMBOL_UNUSED( pRDD );
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
|
|
static RDDFUNCS sqlmixTable =
|
|
{( DBENTRYP_BP ) NULL, /* sqlmixBof */
|
|
( DBENTRYP_BP ) NULL, /* sqlmixEof */
|
|
( DBENTRYP_BP ) NULL, /* sqlmixFound */
|
|
( DBENTRYP_V ) sqlmixGoBottom,
|
|
( DBENTRYP_UL ) NULL, /* sqlmixGoTo */
|
|
( DBENTRYP_I ) NULL, /* sqlmixGoToId */
|
|
( DBENTRYP_V ) sqlmixGoTop,
|
|
( DBENTRYP_BIB ) sqlmixSeek,
|
|
( DBENTRYP_L ) NULL, /* sqlmixSkip */
|
|
( DBENTRYP_L ) NULL, /* sqlmixSkipFilter */
|
|
( DBENTRYP_L ) sqlmixSkipRaw,
|
|
( DBENTRYP_VF ) NULL, /* sqlmixAddField */
|
|
( DBENTRYP_B ) NULL, /* sqlmixAppend */
|
|
( DBENTRYP_I ) NULL, /* sqlmixCreateFields */
|
|
( DBENTRYP_V ) NULL, /* sqlmixDeleteRec */
|
|
( DBENTRYP_BP ) NULL, /* sqlmixDeleted */
|
|
( DBENTRYP_SP ) NULL, /* sqlmixFieldCount */
|
|
( DBENTRYP_VF ) NULL, /* sqlmixFieldDisplay */
|
|
( DBENTRYP_SSI ) NULL, /* sqlmixFieldInfo */
|
|
( DBENTRYP_SVP ) NULL, /* sqlmixFieldName */
|
|
( DBENTRYP_V ) NULL, /* sqlmixFlush */
|
|
( DBENTRYP_PP ) NULL, /* sqlmixGetRec */
|
|
( DBENTRYP_SI ) NULL, /* sqlmixGetValue */
|
|
( DBENTRYP_SVL ) NULL, /* sqlmixGetVarLen */
|
|
( DBENTRYP_V ) sqlmixGoCold,
|
|
( DBENTRYP_V ) sqlmixGoHot,
|
|
( DBENTRYP_P ) NULL, /* sqlmixPutRec */
|
|
( DBENTRYP_SI ) NULL, /* sqlmixPutValue */
|
|
( DBENTRYP_V ) NULL, /* sqlmixRecall */
|
|
( DBENTRYP_ULP ) NULL, /* sqlmixRecCount */
|
|
( DBENTRYP_ISI ) NULL, /* sqlmixRecInfo */
|
|
( DBENTRYP_ULP ) NULL, /* sqlmixRecNo */
|
|
( DBENTRYP_I ) NULL, /* sqlmixRecId */
|
|
( DBENTRYP_S ) NULL, /* sqlmixSetFieldExtent */
|
|
( DBENTRYP_P ) NULL, /* sqlmixAlias */
|
|
( DBENTRYP_V ) sqlmixClose,
|
|
( DBENTRYP_VP ) NULL, /* sqlmixCreate */
|
|
( DBENTRYP_SI ) NULL, /* sqlmixInfo */
|
|
( DBENTRYP_V ) NULL, /* sqlmixNewArea */
|
|
( DBENTRYP_VP ) NULL, /* sqlmixOpen */
|
|
( DBENTRYP_V ) NULL, /* sqlmixRelease */
|
|
( DBENTRYP_SP ) sqlmixStructSize,
|
|
( DBENTRYP_P ) NULL, /* sqlmixSysName */
|
|
( DBENTRYP_VEI ) NULL, /* sqlmixEval */
|
|
( DBENTRYP_V ) NULL, /* sqlmixPack */
|
|
( DBENTRYP_LSP ) NULL, /* sqlmixPackRec */
|
|
( DBENTRYP_VS ) NULL, /* sqlmixSort */
|
|
( DBENTRYP_VT ) NULL, /* sqlmixTrans */
|
|
( DBENTRYP_VT ) NULL, /* sqlmixTransRec */
|
|
( DBENTRYP_V ) NULL, /* sqlmixZap */
|
|
( DBENTRYP_VR ) NULL, /* sqlmixChildEnd */
|
|
( DBENTRYP_VR ) NULL, /* sqlmixChildStart */
|
|
( DBENTRYP_VR ) NULL, /* sqlmixChildSync */
|
|
( DBENTRYP_V ) NULL, /* sqlmixSyncChildren */
|
|
( DBENTRYP_V ) NULL, /* sqlmixClearRel */
|
|
( DBENTRYP_V ) NULL, /* sqlmixForceRel */
|
|
( DBENTRYP_SVP ) NULL, /* sqlmixRelArea */
|
|
( DBENTRYP_VR ) NULL, /* sqlmixRelEval */
|
|
( DBENTRYP_SVP ) NULL, /* sqlmixRelText */
|
|
( DBENTRYP_VR ) NULL, /* sqlmixSetRel */
|
|
( DBENTRYP_OI ) NULL, /* sqlmixOrderListAdd */
|
|
( DBENTRYP_V ) sqlmixOrderListClear,
|
|
( DBENTRYP_OI ) NULL, /* sqlmixOrderListDelete */
|
|
( DBENTRYP_OI ) sqlmixOrderListFocus,
|
|
( DBENTRYP_V ) NULL, /* sqlmixOrderListRebuild */
|
|
( DBENTRYP_VOI ) NULL, /* sqlmixOrderCondition */
|
|
( DBENTRYP_VOC ) sqlmixOrderCreate,
|
|
( DBENTRYP_OI ) NULL, /* sqlmixOrderDestroy */
|
|
( DBENTRYP_OII ) sqlmixOrderInfo,
|
|
( DBENTRYP_V ) NULL, /* sqlmixClearFilter */
|
|
( DBENTRYP_V ) NULL, /* sqlmixClearLocate */
|
|
( DBENTRYP_V ) NULL, /* sqlmixClearScope */
|
|
( DBENTRYP_VPLP ) NULL, /* sqlmixCountScope */
|
|
( DBENTRYP_I ) NULL, /* sqlmixFilterText */
|
|
( DBENTRYP_SI ) NULL, /* sqlmixScopeInfo */
|
|
( DBENTRYP_VFI ) NULL, /* sqlmixSetFilter */
|
|
( DBENTRYP_VLO ) NULL, /* sqlmixSetLocate */
|
|
( DBENTRYP_VOS ) NULL, /* sqlmixSetScope */
|
|
( DBENTRYP_VPL ) NULL, /* sqlmixSkipScope */
|
|
( DBENTRYP_B ) NULL, /* sqlmixLocate */
|
|
( DBENTRYP_P ) NULL, /* sqlmixCompile */
|
|
( DBENTRYP_I ) NULL, /* sqlmixError */
|
|
( DBENTRYP_I ) NULL, /* sqlmixEvalBlock */
|
|
( DBENTRYP_VSP ) NULL, /* sqlmixRawLock */
|
|
( DBENTRYP_VL ) NULL, /* sqlmixLock */
|
|
( DBENTRYP_I ) NULL, /* sqlmixUnLock */
|
|
( DBENTRYP_V ) NULL, /* sqlmixCloseMemFile */
|
|
( DBENTRYP_VP ) NULL, /* sqlmixCreateMemFile */
|
|
( DBENTRYP_SVPB ) NULL, /* sqlmixGetValueFile */
|
|
( DBENTRYP_VP ) NULL, /* sqlmixOpenMemFile */
|
|
( DBENTRYP_SVPB ) NULL, /* sqlmixPutValueFile */
|
|
( DBENTRYP_V ) NULL, /* sqlmixReadDBHeader */
|
|
( DBENTRYP_V ) NULL, /* sqlmixWriteDBHeader */
|
|
( DBENTRYP_R ) NULL, /* sqlmixInit */
|
|
( DBENTRYP_R ) sqlmixExit,
|
|
( DBENTRYP_RVVL) NULL, /* sqlmixDrop */
|
|
( DBENTRYP_RVVL) NULL, /* sqlmixExists */
|
|
( DBENTRYP_RSLV ) NULL, /* sqlmixRddInfo */
|
|
( DBENTRYP_SVP ) NULL, /* sqlmixWhoCares */
|
|
};
|
|
|
|
|
|
HB_FUNC( SQLMIX_GETFUNCTABLE )
|
|
{
|
|
RDDFUNCS * pTable;
|
|
USHORT * uiCount, uiRddId;
|
|
|
|
uiCount = ( USHORT * ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) );
|
|
* uiCount = RDDFUNCSCOUNT;
|
|
pTable = ( RDDFUNCS * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) );
|
|
uiRddId = ( USHORT ) hb_parni( 4 );
|
|
|
|
if ( pTable )
|
|
{
|
|
HB_ERRCODE errCode;
|
|
|
|
errCode = hb_rddInherit( pTable, &sqlmixTable, &sqlmixSuper, "SQLBASE" );
|
|
if ( errCode == HB_SUCCESS )
|
|
{
|
|
s_uiRddIdSQLMIX = uiRddId;
|
|
}
|
|
hb_retni( errCode );
|
|
}
|
|
else
|
|
{
|
|
hb_retni( HB_FAILURE );
|
|
}
|
|
}
|
|
|
|
|
|
HB_FUNC( SQLMIX ) { ; }
|
|
|
|
|
|
#define __PRG_SOURCE__ __FILE__
|
|
|
|
#ifdef HB_PCODE_VER
|
|
#undef HB_PRG_PCODE_VER
|
|
#define HB_PRG_PCODE_VER HB_PCODE_VER
|
|
#endif
|
|
|
|
|
|
HB_FUNC_EXTERN( SQLBASE );
|
|
|
|
|
|
static void hb_sqlmixRddInit( void * cargo )
|
|
{
|
|
HB_SYMBOL_UNUSED( cargo );
|
|
|
|
if ( hb_rddRegister( "SQLMIX", RDT_FULL ) > 1 )
|
|
{
|
|
/* try different RDD registrer order */
|
|
hb_rddRegister( "SQLBASE", RDT_FULL );
|
|
|
|
if ( hb_rddRegister( "SQLMIX", RDT_FULL ) > 1 )
|
|
{
|
|
hb_errInternal( HB_EI_RDDINVALID, NULL, NULL, NULL );
|
|
HB_FUNC_EXEC( SQLBASE ); /* force SQLBASE linking */
|
|
}
|
|
}
|
|
}
|
|
|
|
HB_INIT_SYMBOLS_BEGIN( sqlmix__InitSymbols )
|
|
{ "SQLMIX", {HB_FS_PUBLIC|HB_FS_LOCAL}, {HB_FUNCNAME( SQLMIX )}, NULL },
|
|
{ "SQLMIX_GETFUNCTABLE", {HB_FS_PUBLIC|HB_FS_LOCAL}, {HB_FUNCNAME( SQLMIX_GETFUNCTABLE )}, NULL }
|
|
HB_INIT_SYMBOLS_END( sqlmix__InitSymbols )
|
|
|
|
HB_CALL_ON_STARTUP_BEGIN( _hb_sqlmix_rdd_init_ )
|
|
hb_vmAtInit( hb_sqlmixRddInit, NULL );
|
|
HB_CALL_ON_STARTUP_END( _hb_sqlmix_rdd_init_ )
|
|
|
|
#if defined( HB_PRAGMA_STARTUP )
|
|
#pragma startup sqlmix__InitSymbols
|
|
#pragma startup _hb_sqlmix_rdd_init_
|
|
#elif defined( HB_MSC_STARTUP )
|
|
#if defined( HB_OS_WIN_64 )
|
|
#pragma section( HB_MSC_START_SEGMENT, long, read )
|
|
#endif
|
|
#pragma data_seg( HB_MSC_START_SEGMENT )
|
|
static HB_$INITSYM hb_vm_auto_sqlmix__InitSymbols = sqlmix__InitSymbols;
|
|
static HB_$INITSYM hb_vm_auto_sqlmix_rdd_init = _hb_sqlmix_rdd_init_;
|
|
#pragma data_seg()
|
|
#endif
|