Files
harbour-core/harbour/source/rdd/dbcmd.c
2000-01-17 15:06:29 +00:00

7624 lines
218 KiB
C
Raw Blame History

/*
* $Id$
*/
/*
* Harbour Project source code:
* Base RDD module
*
* Copyright 1999 Bruno Cantero <bruno@issnet.net>
* 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 of the License, or
* (at your option) any later version, with one exception:
*
* The exception is that if you link the Harbour Runtime Library (HRL)
* and/or the Harbour Virtual Machine (HVM) 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 HRL
* and/or HVM code into it.
*
* 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 program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit
* their web site at http://www.gnu.org/).
*
*/
/*
* The following parts are Copyright of the individual authors.
* www - http://www.harbour-project.org
*
* Copyright 1999 Luiz Rafael Culik <culik@sl.conex.net>
* DB* () documentation
* ORD*() documentation
* RDD*() documentation
* See doc/license.txt for licensing terms.
*
*/
#include <ctype.h>
#include "extend.h"
#include "itemapi.h"
#include "errorapi.h"
#include "rddapi.h"
#include "set.h"
#include "ctoharb.h"
#include "rddsys.ch"
#include "set.ch"
#include "langapi.h"
#define HARBOUR_MAX_RDD_DRIVERNAME_LENGTH 32
#define HARBOUR_MAX_RDD_ALIAS_LENGTH 32
#define HARBOUR_MAX_RDD_FIELDNAME_LENGTH 32
typedef struct _RDDNODE
{
char szName[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH + 1 ];
USHORT uiType; /* Type of RDD */
RDDFUNCS pTable; /* Table of functions */
USHORT uiAreaSize; /* Size of the WorkArea */
struct _RDDNODE * pNext; /* Next RDD in the list */
} RDDNODE;
typedef RDDNODE * LPRDDNODE;
typedef struct _AREANODE
{
void * pArea; /* WorkAreas with different sizes */
struct _AREANODE * pPrev; /* Prev WorkArea in the list */
struct _AREANODE * pNext; /* Next WorkArea in the list */
} AREANODE;
typedef AREANODE * LPAREANODE;
extern HARBOUR HB__DBF( void );
extern HARBOUR HB__SDF( void );
extern HARBOUR HB__DELIM( void );
extern HARBOUR HB_RDDSYS( void );
HARBOUR HB_AFIELDS( void );
HARBOUR HB_ALIAS( void );
HARBOUR HB_BOF( void );
HARBOUR HB_DBAPPEND( void );
HARBOUR HB_DBCLEARFILTER( void );
HARBOUR HB_DBCLOSEALL( void );
HARBOUR HB_DBCLOSEAREA( void );
HARBOUR HB_DBCOMMIT( void );
HARBOUR HB_DBCOMMITALL( void );
HARBOUR HB___DBCONTINUE( void );
HARBOUR HB_DBCREATE( void );
HARBOUR HB_DBDELETE( void );
HARBOUR HB_DBEVAL( void );
HARBOUR HB_DBF( void );
HARBOUR HB_DBFILTER( void );
HARBOUR HB_DBGOBOTTOM( void );
HARBOUR HB_DBGOTO( void );
HARBOUR HB_DBGOTOP( void );
HARBOUR HB___DBLOCATE( void );
HARBOUR HB___DBPACK( void );
HARBOUR HB_DBRECALL( void );
HARBOUR HB_DBRLOCK( void );
HARBOUR HB_DBRLOCKLIST( void );
HARBOUR HB_DBRUNLOCK( void );
HARBOUR HB_DBSEEK( void );
HARBOUR HB_DBSELECTAREA( void );
HARBOUR HB_DBSETDRIVER( void );
HARBOUR HB_DBSETFILTER( void );
HARBOUR HB___DBSETFOUND( void );
HARBOUR HB___DBSETLOCATE( void );
HARBOUR HB_DBSKIP( void );
HARBOUR HB_DBSTRUCT( void );
HARBOUR HB_DBTABLEEXT( void );
HARBOUR HB_DBUNLOCK( void );
HARBOUR HB_DBUNLOCKALL( void );
HARBOUR HB_DBUSEAREA( void );
HARBOUR HB___DBZAP( void );
HARBOUR HB_DELETED( void );
HARBOUR HB_EOF( void );
HARBOUR HB_FCOUNT( void );
HARBOUR HB_FIELDGET( void );
HARBOUR HB_FIELDNAME( void );
HARBOUR HB_FIELDPOS( void );
HARBOUR HB_FIELDPUT( void );
HARBOUR HB_FLOCK( void );
HARBOUR HB_FOUND( void );
HARBOUR HB_HEADER( void );
HARBOUR HB_INDEXORD( void );
HARBOUR HB_LASTREC( void );
HARBOUR HB_LOCK( void );
HARBOUR HB_LUPDATE( void );
HARBOUR HB_NETERR( void );
HARBOUR HB_ORDBAGEXT( void );
HARBOUR HB_ORDBAGNAME( void );
HARBOUR HB_ORDCONDSET( void );
HARBOUR HB_ORDCREATE( void );
HARBOUR HB_ORDDESTROY( void );
HARBOUR HB_ORDFOR( void );
HARBOUR HB_ORDKEY( void );
HARBOUR HB_ORDLISTADD( void );
HARBOUR HB_ORDLISTCLEAR( void );
HARBOUR HB_ORDLISTREBUILD( void );
HARBOUR HB_ORDNAME( void );
HARBOUR HB_ORDNUMBER( void );
HARBOUR HB_ORDSETFOCUS( void );
HARBOUR HB_RDDLIST( void );
HARBOUR HB_RDDNAME( void );
HARBOUR HB_RDDREGISTER( void );
HARBOUR HB_RDDSETDEFAULT( void );
HARBOUR HB_RECCOUNT( void );
HARBOUR HB_RECNO( void );
HARBOUR HB_RECSIZE( void );
HARBOUR HB_RLOCK( void );
HARBOUR HB_SELECT( void );
HARBOUR HB_USED( void );
HARBOUR HB___RDDSETDEFAULT( void );
static char * szDefDriver = NULL; /* Default RDD name */
static USHORT uiCurrArea = 1; /* Selectd area */
static LPRDDNODE pRddList = NULL; /* Registered RDD's */
static BOOL bNetError = FALSE; /* Error on Networked environments */
static LPAREANODE pWorkAreas = NULL; /* WorkAreas */
static LPAREANODE pCurrArea = NULL; /* Pointer to a selectd and valid area */
/*
* -- BASIC RDD METHODS --
*/
static ERRCODE defAddField( AREAP pArea, LPDBFIELDINFO pFieldInfo )
{
LPFIELD pField;
ULONG ulLen;
HB_TRACE(HB_TR_DEBUG, ("defAddField(%p, %p)", pArea, pFieldInfo));
/* Validate the name of field */
ulLen = strlen( ( char * ) pFieldInfo->atomName );
hb_strLTrim( ( char * ) pFieldInfo->atomName, &ulLen );
if( !ulLen )
return FAILURE;
pField = pArea->lpFields + pArea->uiFieldCount;
if( pArea->uiFieldCount > 0 )
{
( ( LPFIELD ) ( pField - 1 ) )->lpfNext = pField;
if( ( ( LPFIELD ) ( pField - 1 ) )->uiType == 'C' )
pField->uiOffset = ( ( LPFIELD ) ( pField - 1 ) )->uiOffset +
( ( LPFIELD ) ( pField - 1 ) )->uiLen +
( ( USHORT ) ( ( LPFIELD ) ( pField - 1 ) )->uiDec << 8 );
else
pField->uiOffset = ( ( LPFIELD ) ( pField - 1 ) )->uiOffset +
( ( LPFIELD ) ( pField - 1 ) )->uiLen;
}
else
pField->uiOffset = 1;
pField->sym = ( void * ) hb_dynsymGet( ( char * ) pFieldInfo->atomName );
pField->uiType = pFieldInfo->uiType;
pField->uiTypeExtended = pFieldInfo->typeExtended;
pField->uiLen = pFieldInfo->uiLen;
pField->uiDec = pFieldInfo->uiDec;
pField->uiArea = pArea->uiArea;
pArea->uiFieldCount++;
return SUCCESS;
}
static ERRCODE defAlias( AREAP pArea, BYTE * szAlias )
{
HB_TRACE(HB_TR_DEBUG, ("defAlias(%p, %p)", pArea, szAlias));
strncpy( ( char * ) szAlias,
( ( PHB_DYNS ) pArea->atomAlias )->pSymbol->szName,
HARBOUR_MAX_RDD_ALIAS_LENGTH );
return SUCCESS;
}
static ERRCODE defBof( AREAP pArea, BOOL * pBof )
{
HB_TRACE(HB_TR_DEBUG, ("defBof(%p, %p)", pArea, pBof));
* pBof = pArea->fBof;
return SUCCESS;
}
static ERRCODE defClearFilter( AREAP pArea )
{
HB_TRACE(HB_TR_DEBUG, ("defClearFilter(%p)", pArea));
if( pArea->dbfi.fFilter )
{
hb_itemRelease( pArea->dbfi.itmCobExpr );
hb_itemRelease( pArea->dbfi.abFilterText );
pArea->dbfi.fFilter = FALSE;
}
return SUCCESS;
}
static ERRCODE defClearLocate( AREAP pArea )
{
HB_TRACE(HB_TR_DEBUG, ("defClearLocate(%p)", pArea));
if( pArea->dbsi.itmCobFor )
{
hb_itemRelease( pArea->dbsi.itmCobFor );
pArea->dbsi.itmCobFor = NULL;
}
if( pArea->dbsi.lpstrFor )
{
hb_itemRelease( pArea->dbsi.lpstrFor );
pArea->dbsi.lpstrFor = NULL;
}
if( pArea->dbsi.itmCobWhile )
{
hb_itemRelease( pArea->dbsi.itmCobWhile );
pArea->dbsi.itmCobWhile = NULL;
}
if( pArea->dbsi.lpstrWhile )
{
hb_itemRelease( pArea->dbsi.lpstrWhile );
pArea->dbsi.lpstrWhile = NULL;
}
if( pArea->dbsi.lNext )
{
hb_itemRelease( pArea->dbsi.lNext );
pArea->dbsi.lNext = NULL;
}
if( pArea->dbsi.itmRecID )
{
hb_itemRelease( pArea->dbsi.itmRecID );
pArea->dbsi.itmRecID = NULL;
}
if( pArea->dbsi.fRest )
{
hb_itemRelease( pArea->dbsi.fRest );
pArea->dbsi.fRest = NULL;
}
return SUCCESS;
}
static ERRCODE defClose( AREAP pArea )
{
HB_TRACE(HB_TR_DEBUG, ("defClose(%p)", pArea));
SELF_CLEARFILTER( pArea );
SELF_CLEARLOCATE( pArea );
( ( PHB_DYNS ) pArea->atomAlias )->hArea = 0;
return SUCCESS;
}
static ERRCODE defCompile( AREAP pArea, BYTE * szExpr )
{
HB_MACRO_PTR pMacro;
HB_TRACE(HB_TR_DEBUG, ("defCompile(%p, %p)", pArea, szExpr));
pMacro = hb_macroCompile( ( char * ) szExpr );
if( pMacro )
{
pArea->valResult = hb_itemPutPtr( pArea->valResult, ( void * ) pMacro );
return SUCCESS;
}
else
return FAILURE;
}
static ERRCODE defCreateFields( AREAP pArea, PHB_ITEM pStruct )
{
USHORT uiCount, uiItems;
PHB_ITEM pFieldDesc;
DBFIELDINFO pFieldInfo;
long lLong;
HB_TRACE(HB_TR_DEBUG, ("defCreateFields(%p, %p)", pArea, pStruct));
uiItems = hb_arrayLen( pStruct );
SELF_SETFIELDEXTENT( pArea, uiItems );
pFieldInfo.typeExtended = 0;
for( uiCount = 0; uiCount < uiItems; uiCount++ )
{
pFieldDesc = hb_arrayGetItemPtr( pStruct, uiCount + 1 );
pFieldInfo.uiType = toupper( hb_arrayGetCPtr( pFieldDesc, 2 )[ 0 ] );
pFieldInfo.atomName = ( BYTE * ) hb_arrayGetCPtr( pFieldDesc, 1 );
lLong = hb_arrayGetNL( pFieldDesc, 3 );
if( lLong < 0 )
lLong = 0;
pFieldInfo.uiLen = ( USHORT ) lLong;
lLong = hb_arrayGetNL( pFieldDesc, 4 );
if( lLong < 0 )
lLong = 0;
pFieldInfo.uiDec = ( USHORT ) lLong;
if( SELF_ADDFIELD( pArea, &pFieldInfo ) == FAILURE )
return FAILURE;
}
return SUCCESS;
}
static ERRCODE defEof( AREAP pArea, BOOL * pEof )
{
HB_TRACE(HB_TR_DEBUG, ("defEof(%p, %p)", pArea, pEof));
* pEof = pArea->fEof;
return SUCCESS;
}
static ERRCODE defError( AREAP pArea, PHB_ITEM pError )
{
char * szRddName;
HB_TRACE(HB_TR_DEBUG, ("defError(%p, %p)", pArea, pError));
szRddName = ( char * ) hb_xgrab( HARBOUR_MAX_RDD_DRIVERNAME_LENGTH + 1 );
SELF_SYSNAME( pArea, ( BYTE * ) szRddName );
hb_errPutSeverity( pError, ES_ERROR );
hb_errPutSubSystem( pError, szRddName );
hb_xfree( szRddName );
return hb_errLaunch( pError );
}
static ERRCODE defEval( AREAP pArea, LPDBEVALINFO pEvalInfo )
{
BOOL bEof, bFor, bWhile;
ULONG ulNext;
HB_TRACE(HB_TR_DEBUG, ("defEval(%p, %p)", pArea, pEvalInfo));
if( pEvalInfo->dbsci.itmRecID )
{
SELF_GOTOID( pArea, pEvalInfo->dbsci.itmRecID );
SELF_EOF( pArea, &bEof );
if( !bEof )
{
if( pEvalInfo->dbsci.itmCobWhile )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pEvalInfo->dbsci.itmCobWhile );
hb_vmDo( 0 );
bWhile = hb_itemGetL( &hb_stack.Return );
}
else
bWhile = TRUE;
if( pEvalInfo->dbsci.itmCobFor )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pEvalInfo->dbsci.itmCobFor );
hb_vmDo( 0 );
bFor = hb_itemGetL( &hb_stack.Return );
}
else
bFor = TRUE;
if( bWhile && bFor )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pEvalInfo->itmBlock );
hb_vmDo( 0 );
}
}
return SUCCESS;
}
if( !pEvalInfo->dbsci.fRest || !hb_itemGetL( pEvalInfo->dbsci.fRest ) )
SELF_GOTOP( pArea );
if( pEvalInfo->dbsci.lNext )
ulNext = hb_itemGetNL( pEvalInfo->dbsci.lNext );
SELF_EOF( pArea, &bEof );
while( !bEof )
{
if( pEvalInfo->dbsci.lNext && ulNext-- < 1 )
break;
if( pEvalInfo->dbsci.itmCobWhile )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pEvalInfo->dbsci.itmCobWhile );
hb_vmDo( 0 );
bWhile = hb_itemGetL( &hb_stack.Return );
if( !bWhile )
break;
}
else
bWhile = TRUE;
if( pEvalInfo->dbsci.itmCobFor )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pEvalInfo->dbsci.itmCobFor );
hb_vmDo( 0 );
bFor = hb_itemGetL( &hb_stack.Return );
}
else
bFor = TRUE;
if( bFor && bWhile )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pEvalInfo->itmBlock );
hb_vmDo( 0 );
}
SELF_SKIP( pArea, 1 );
SELF_EOF( pArea, &bEof );
}
return SUCCESS;
}
static ERRCODE defEvalBlock( AREAP pArea, PHB_ITEM pBlock )
{
PHB_ITEM pError;
HB_TRACE(HB_TR_DEBUG, ("defEvalBlock(%p, %p)", pArea, pBlock));
if( !pBlock && !IS_BLOCK( pBlock ) )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_NOMETHOD );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_NOMETHOD ) );
SELF_ERROR( pArea, pError );
hb_errRelease( pError );
return FAILURE;
}
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pBlock );
hb_vmDo( 0 );
if( !pArea->valResult )
pArea->valResult = hb_itemNew( NULL );
hb_itemCopy( pArea->valResult, &hb_stack.Return );
return SUCCESS;
}
static ERRCODE defFieldCount( AREAP pArea, USHORT * uiFields )
{
HB_TRACE(HB_TR_DEBUG, ("defFieldCount(%p, %p)", pArea, uiFields));
* uiFields = pArea->uiFieldCount;
return SUCCESS;
}
static ERRCODE defFieldInfo( AREAP pArea, USHORT uiIndex, USHORT uiType, PHB_ITEM pItem )
{
LPFIELD pField;
char szType[ 2 ];
HB_TRACE(HB_TR_DEBUG, ("defFieldInfo(%p, %hu, %hu, %p)", pArea, uiIndex, uiType, pItem));
if( uiIndex > pArea->uiFieldCount )
return FAILURE;
pField = pArea->lpFields + uiIndex - 1;
switch( uiType )
{
case DBS_NAME:
hb_itemPutC( pItem, ( ( PHB_DYNS ) pField->sym )->pSymbol->szName );
break;
case DBS_TYPE:
szType[ 0 ] = pField->uiType;
szType[ 1 ] = '\0';
hb_itemPutC( pItem, szType );
break;
case DBS_LEN:
hb_itemPutNL( pItem, pField->uiLen );
break;
case DBS_DEC:
hb_itemPutNL( pItem, pField->uiDec );
break;
default:
return FAILURE;
}
return SUCCESS;
}
static ERRCODE defFieldName( AREAP pArea, USHORT uiIndex, void * szName )
{
LPFIELD pField;
HB_TRACE(HB_TR_DEBUG, ("defFieldName(%p, %hu, %p)", pArea, uiIndex, szName));
if( uiIndex > pArea->uiFieldCount )
return FAILURE;
pField = pArea->lpFields + uiIndex - 1;
strncpy( ( char * ) szName, ( ( PHB_DYNS ) pField->sym )->pSymbol->szName,
HARBOUR_MAX_RDD_FIELDNAME_LENGTH );
return SUCCESS;
}
static ERRCODE defFilterText( AREAP pArea, PHB_ITEM pFilter )
{
HB_TRACE(HB_TR_DEBUG, ("defFilterText(%p, %p)", pArea, pFilter));
if( pArea->dbfi.fFilter )
hb_itemCopy( pFilter, pArea->dbfi.abFilterText );
return SUCCESS;
}
static ERRCODE defFound( AREAP pArea, BOOL * pFound )
{
HB_TRACE(HB_TR_DEBUG, ("defFound(%p, %p)", pArea, pFound));
* pFound = pArea->fFound;
return SUCCESS;
}
static ERRCODE defNewArea( AREAP pArea )
{
HB_TRACE(HB_TR_DEBUG, ("defNewArea(%p)", pArea));
pArea->lpDataInfo = ( LPFILEINFO ) hb_xgrab( sizeof( FILEINFO ) );
memset( pArea->lpDataInfo, 0, sizeof( FILEINFO ) );
pArea->lpDataInfo->hFile = FS_ERROR;
pArea->lpExtendInfo = ( LPDBEXTENDINFO ) hb_xgrab( sizeof( DBEXTENDINFO ) );
memset( pArea->lpExtendInfo, 0, sizeof( DBEXTENDINFO ) );
return SUCCESS;
}
static ERRCODE defOpen( AREAP pArea, LPDBOPENINFO pOpenInfo )
{
HB_TRACE(HB_TR_DEBUG, ("defOpen(%p, %p)", pArea, pOpenInfo));
pArea->atomAlias = hb_dynsymGet( ( char * ) pOpenInfo->atomAlias );
if( ( ( PHB_DYNS ) pArea->atomAlias )->hArea )
{
hb_errRT_DBCMD( EG_DUPALIAS, 1011, NULL, ( char * ) pOpenInfo->atomAlias );
return FAILURE;
}
( ( PHB_DYNS ) pArea->atomAlias )->hArea = pOpenInfo->uiArea;
pArea->lpExtendInfo->fExclusive = !pOpenInfo->fShared;
pArea->lpExtendInfo->fReadOnly = pOpenInfo->fReadonly;
return SUCCESS;
}
static ERRCODE defOrderCondition( AREAP pArea, LPDBORDERCONDINFO pOrderInfo )
{
if( pArea->lpdbOrdCondInfo )
{
if( pArea->lpdbOrdCondInfo->abFor )
hb_xfree( pArea->lpdbOrdCondInfo->abFor );
if( pArea->lpdbOrdCondInfo->itmCobFor )
hb_itemRelease( pArea->lpdbOrdCondInfo->itmCobFor );
if( pArea->lpdbOrdCondInfo->itmCobWhile )
hb_itemRelease( pArea->lpdbOrdCondInfo->itmCobWhile );
if( pArea->lpdbOrdCondInfo->itmCobEval )
hb_itemRelease( pArea->lpdbOrdCondInfo->itmCobEval );
hb_xfree( pArea->lpdbOrdCondInfo );
}
pArea->lpdbOrdCondInfo = pOrderInfo;
return SUCCESS;
}
static ERRCODE defRelease( AREAP pArea )
{
LPFILEINFO pFileInfo;
HB_TRACE(HB_TR_DEBUG, ("defRelease(%p)", pArea));
SELF_ORDSETCOND( pArea, NULL );
if( pArea->valResult )
hb_itemRelease( pArea->valResult );
if( pArea->lpFields )
{
hb_xfree( pArea->lpFields );
pArea->uiFieldCount = 0;
}
while( pArea->lpDataInfo )
{
pFileInfo = pArea->lpDataInfo;
pArea->lpDataInfo = pArea->lpDataInfo->pNext;
if( pFileInfo->szFileName )
hb_xfree( pFileInfo->szFileName );
hb_xfree( pFileInfo );
}
if( pArea->lpExtendInfo )
{
if( pArea->lpExtendInfo->bRecord )
hb_xfree( pArea->lpExtendInfo->bRecord );
hb_xfree( pArea->lpExtendInfo );
}
return SUCCESS;
}
static ERRCODE defSetFieldExtent( AREAP pArea, USHORT uiFieldExtent )
{
HB_TRACE(HB_TR_DEBUG, ("defSetFieldExtent(%p, %hu)", pArea, uiFieldExtent));
pArea->uiFieldExtent = uiFieldExtent;
pArea->lpFields = ( LPFIELD ) hb_xgrab( uiFieldExtent * sizeof( FIELD ) );
memset( pArea->lpFields, 0, uiFieldExtent * sizeof( FIELD ) );
return SUCCESS;
}
static ERRCODE defSetFilter( AREAP pArea, LPDBFILTERINFO pFilterInfo )
{
HB_TRACE(HB_TR_DEBUG, ("defSetFilter(%p, %p)", pArea, pFilterInfo));
if( pArea->dbfi.fFilter )
{
hb_itemCopy( pArea->dbfi.itmCobExpr, pFilterInfo->itmCobExpr );
hb_itemCopy( pArea->dbfi.abFilterText, pFilterInfo->abFilterText );
}
else
{
pArea->dbfi.itmCobExpr = hb_itemNew( NULL );
hb_itemCopy( pArea->dbfi.itmCobExpr, pFilterInfo->itmCobExpr );
pArea->dbfi.abFilterText = hb_itemNew( NULL );
hb_itemCopy( pArea->dbfi.abFilterText, pFilterInfo->abFilterText );
pArea->dbfi.fFilter = TRUE;
}
return SUCCESS;
}
static ERRCODE defSetLocate( AREAP pArea, LPDBSCOPEINFO pScopeInfo )
{
HB_TRACE(HB_TR_DEBUG, ("defSetLocate(%p, %p)", pArea, pScopeInfo));
if( pArea->dbsi.itmCobFor )
hb_itemRelease( pArea->dbsi.itmCobFor );
pArea->dbsi.itmCobFor = pScopeInfo->itmCobFor;
if( pArea->dbsi.itmCobWhile )
hb_itemRelease( pArea->dbsi.itmCobWhile );
pArea->dbsi.itmCobWhile = pScopeInfo->itmCobWhile;
if( pArea->dbsi.lNext )
hb_itemRelease( pArea->dbsi.lNext );
pArea->dbsi.lNext = pScopeInfo->lNext;
if( pArea->dbsi.itmRecID )
hb_itemRelease( pArea->dbsi.itmRecID );
pArea->dbsi.itmRecID = pScopeInfo->itmRecID;
if( pArea->dbsi.fRest )
hb_itemRelease( pArea->dbsi.fRest );
pArea->dbsi.fRest = pScopeInfo->fRest;
return SUCCESS;
}
static ERRCODE defSkip( AREAP pArea, LONG lToSkip )
{
BOOL bExit;
HB_TRACE(HB_TR_DEBUG, ("defSkip(%p, %ld)", pArea, lToSkip));
if( pArea->dbfi.fFilter || hb_set.HB_SET_DELETED )
{
if( lToSkip > 0 )
{
while( lToSkip > 0 )
{
SELF_SKIPRAW( pArea, 1 );
SELF_SKIPFILTER( pArea, 1 );
SELF_EOF( pArea, &bExit );
if( bExit )
return SUCCESS;
lToSkip--;
}
}
else if( lToSkip < 0 )
{
while( lToSkip < 0 )
{
SELF_SKIPRAW( pArea, -1 );
SELF_SKIPFILTER( pArea, -1 );
SELF_BOF( pArea, &bExit );
if( bExit )
return SELF_SKIPFILTER( pArea, 1 );
lToSkip++;
}
}
else
{
SELF_SKIPRAW( pArea, 0 );
SELF_SKIPFILTER( pArea, 1 );
SELF_EOF( pArea, &bExit );
if( bExit )
return SUCCESS;
}
}
return SELF_SKIPRAW( pArea, lToSkip );
}
static ERRCODE defSkipFilter( AREAP pArea, LONG lUpDown )
{
BOOL bExit, bDeleted;
HB_TRACE(HB_TR_DEBUG, ("defSkipFilter(%p, %ld)", pArea, lUpDown));
if( lUpDown > 0 )
{
while( 1 )
{
SELF_EOF( pArea, &bExit );
if( bExit )
return SUCCESS;
/* SET DELETED */
if( hb_set.HB_SET_DELETED )
{
SELF_DELETED( pArea, &bDeleted );
if( bDeleted )
{
SELF_SKIPRAW( pArea, 1 );
continue;
}
}
/* SET FILTER TO */
if( pArea->dbfi.fFilter )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pArea->dbfi.itmCobExpr );
hb_vmDo( 0 );
if( IS_LOGICAL( &hb_stack.Return ) &&
!hb_stack.Return.item.asLogical.value )
{
SELF_SKIPRAW( pArea, 1 );
continue;
}
}
return SUCCESS;
}
}
else if( lUpDown < 0 )
{
while( 1 )
{
SELF_BOF( pArea, &bExit );
if( bExit )
return SELF_SKIPFILTER( pArea, 1 );
/* SET DELETED */
if( hb_set.HB_SET_DELETED )
{
SELF_DELETED( pArea, &bDeleted );
if( bDeleted )
{
SELF_SKIPRAW( pArea, -1 );
continue;
}
}
/* SET FILTER TO */
if( pArea->dbfi.fFilter )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pArea->dbfi.itmCobExpr );
hb_vmDo( 0 );
if( IS_LOGICAL( &hb_stack.Return ) &&
!hb_stack.Return.item.asLogical.value )
{
SELF_SKIPRAW( pArea, 1 );
continue;
}
}
return SUCCESS;
}
}
return SUCCESS;
}
static ERRCODE defSkipRaw( AREAP pArea, LONG lToSkip )
{
HB_TRACE(HB_TR_DEBUG, ("defSkipRaw(%p, %ld)", pArea, lToSkip));
return SELF_GOTO( pArea, pArea->lpExtendInfo->ulRecNo + lToSkip );
}
static ERRCODE defStructSize( AREAP pArea, USHORT * uiSize )
{
HB_TRACE(HB_TR_DEBUG, ("defStrucSize(%p, %p)", pArea, uiSize));
HB_SYMBOL_UNUSED( pArea );
HB_SYMBOL_UNUSED( uiSize );
return SUCCESS;
}
static ERRCODE defSysName( AREAP pArea, BYTE * pBuffer )
{
USHORT uiCount;
LPRDDNODE pRddNode;
HB_TRACE(HB_TR_DEBUG, ("defSysName(%p, %p)", pArea, pBuffer));
pRddNode = pRddList;
for( uiCount = 0; uiCount < pArea->rddID; uiCount++ )
pRddNode = pRddNode->pNext;
strncpy( ( char * ) pBuffer, pRddNode->szName, HARBOUR_MAX_RDD_DRIVERNAME_LENGTH );
return SUCCESS;
}
static ERRCODE defUnSupported( AREAP pArea )
{
PHB_ITEM pError;
HB_TRACE(HB_TR_DEBUG, ("defUnSupported(%p)", pArea));
HB_SYMBOL_UNUSED( pArea );
pError = hb_errNew();
hb_errPutGenCode( pError, EG_UNSUPPORTED );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_UNSUPPORTED ) );
SELF_ERROR( pArea, pError );
hb_errRelease( pError );
return FAILURE;
}
static RDDFUNCS defTable = { defBof,
defEof,
defFound,
defUnSupported,
( DBENTRYP_UL ) defUnSupported,
( DBENTRYP_I ) defUnSupported,
defUnSupported,
( DBENTRYP_BIB ) defUnSupported,
defSkip,
defSkipFilter,
defSkipRaw,
defAddField,
( DBENTRYP_B ) defUnSupported,
defCreateFields,
defUnSupported,
( DBENTRYP_BP ) defUnSupported,
defFieldCount,
( DBENTRYP_VF ) defUnSupported,
defFieldInfo,
defFieldName,
defUnSupported,
( DBENTRYP_PP ) defUnSupported,
( DBENTRYP_SI ) defUnSupported,
( DBENTRYP_SVL ) defUnSupported,
defUnSupported,
defUnSupported,
( DBENTRYP_P ) defUnSupported,
( DBENTRYP_SI ) defUnSupported,
defUnSupported,
( DBENTRYP_ULP ) defUnSupported,
( DBENTRYP_ISI ) defUnSupported,
( DBENTRYP_I ) defUnSupported,
defSetFieldExtent,
defAlias,
defClose,
( DBENTRYP_VP ) defUnSupported,
( DBENTRYP_SI ) defUnSupported,
defNewArea,
defOpen,
defRelease,
defStructSize,
defSysName,
defEval,
defUnSupported,
defUnSupported,
( DBENTRYP_OI ) defUnSupported,
defUnSupported,
( DBENTRYP_OI ) defUnSupported,
defUnSupported,
defOrderCondition,
( DBENTRYP_VOC ) defUnSupported,
( DBENTRYP_OI ) defUnSupported,
( DBENTRYP_OII ) defUnSupported,
defClearFilter,
defClearLocate,
defFilterText,
defSetFilter,
defSetLocate,
defCompile,
defError,
defEvalBlock,
( DBENTRYP_VSP ) defUnSupported,
( DBENTRYP_VL ) defUnSupported,
( DBENTRYP_UL ) defUnSupported,
defUnSupported,
( DBENTRYP_VP ) defUnSupported,
( DBENTRYP_SVP ) defUnSupported,
( DBENTRYP_VP ) defUnSupported,
( DBENTRYP_SVP ) defUnSupported,
defUnSupported,
defUnSupported,
( DBENTRYP_SVP ) defUnSupported
};
static void hb_rddCheck( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_rddCheck()"));
if( !szDefDriver )
{
szDefDriver = ( char * ) hb_xgrab( 1 );
szDefDriver[ 0 ] = '\0';
/* Force link the built-in RDD's */
HB__DBF();
HB__SDF();
HB__DELIM();
HB_RDDSYS();
}
}
static void hb_rddCloseAll( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_rddCloseAll()"));
pCurrArea = pWorkAreas;
while( pWorkAreas )
{
pCurrArea = pWorkAreas;
pWorkAreas = pWorkAreas->pNext;
SELF_CLOSE( ( AREAP ) pCurrArea->pArea );
SELF_RELEASE( ( AREAP ) pCurrArea->pArea );
hb_xfree( pCurrArea->pArea );
hb_xfree( pCurrArea );
}
uiCurrArea = 1;
pCurrArea = NULL;
pWorkAreas = NULL;
}
static LPRDDNODE hb_rddFindNode( char * szDriver, USHORT * uiIndex )
{
LPRDDNODE pRddNode;
USHORT uiCount;
HB_TRACE(HB_TR_DEBUG, ("hb_rddFindNode(%s, %p)", szDriver, uiIndex));
uiCount = 0;
pRddNode = pRddList;
while( pRddNode )
{
if( strcmp( pRddNode->szName, szDriver ) == 0 ) /* Matched RDD */
{
if( uiIndex )
* uiIndex = uiCount;
return pRddNode;
}
pRddNode = pRddNode->pNext;
uiCount++;
}
if( uiIndex )
* uiIndex = 0;
return NULL;
}
static int hb_rddRegister( char * szDriver, USHORT uiType )
{
LPRDDNODE pRddNode, pRddNewNode;
PHB_DYNS pGetFuncTable;
char * szGetFuncTable;
USHORT uiFunctions;
HB_TRACE(HB_TR_DEBUG, ("hb_rddRegister(%s, %hu)", szDriver, uiType));
if( hb_rddFindNode( szDriver, 0 ) ) /* Duplicated RDD */
return 1;
szGetFuncTable = ( char * ) hb_xgrab( strlen( szDriver ) + 14 );
strcpy( szGetFuncTable, szDriver );
strcat( szGetFuncTable, "_GETFUNCTABLE" );
pGetFuncTable = hb_dynsymFindName( szGetFuncTable );
hb_xfree( szGetFuncTable );
if( !pGetFuncTable )
return 2; /* Not valid RDD */
/* Create a new RDD node */
pRddNewNode = ( LPRDDNODE ) hb_xgrab( sizeof( RDDNODE ) );
memset( pRddNewNode, 0, sizeof( RDDNODE ) );
/* Fill the new RDD node */
strncpy( pRddNewNode->szName, szDriver, HARBOUR_MAX_RDD_DRIVERNAME_LENGTH );
pRddNewNode->uiType = uiType;
/* Call <szDriver>_GETFUNCTABLE() */
hb_vmPushSymbol( pGetFuncTable->pSymbol );
hb_vmPushNil();
hb_vmPushLong( ( long ) &uiFunctions );
hb_vmPushLong( ( long ) &pRddNewNode->pTable );
hb_vmDo( 2 );
if ( hb_parni( -1 ) != SUCCESS )
{
hb_xfree( pRddNewNode ); /* Delete de new RDD node */
return 3; /* Invalid FUNCTABLE */
}
if( !pRddList ) /* First RDD node */
pRddList = pRddNewNode;
else
{
pRddNode = pRddList;
while( pRddNode->pNext )
pRddNode = pRddNode->pNext; /* Locate the last RDD node */
pRddNode->pNext = pRddNewNode; /* Add the new RDD node */
}
return 0; /* Ok */
}
static USHORT hb_rddSelect( char * szAlias )
{
PHB_DYNS pSymAlias;
HB_TRACE(HB_TR_DEBUG, ("hb_rddSelect(%s)", szAlias));
pSymAlias = hb_dynsymFindName( szAlias );
if( pSymAlias && pSymAlias->hArea )
return pSymAlias->hArea;
else
return 0;
}
static void hb_rddSelectFirstAvailable( void )
{
LPAREANODE pAreaNode;
HB_TRACE(HB_TR_DEBUG, ("hb_rddSelectFirstAvailable()"));
uiCurrArea = 1;
pAreaNode = pWorkAreas;
while( pAreaNode )
{
if( ( ( AREAP ) pAreaNode->pArea )->uiArea > uiCurrArea )
break;
else if( ( ( AREAP ) pAreaNode->pArea )->uiArea == uiCurrArea )
uiCurrArea++;
pAreaNode = pAreaNode->pNext;
}
pCurrArea = NULL; /* Selected WorkArea must be created */
}
ERRCODE hb_rddInherit( PRDDFUNCS pTable, PRDDFUNCS pSubTable, PRDDFUNCS pSuperTable, BYTE * szDrvName )
{
char * szSuperName;
LPRDDNODE pRddNode;
USHORT uiCount;
DBENTRYP_V * pFunction, * pSubFunction;
HB_TRACE(HB_TR_DEBUG, ("hb_rddInherit(%p, %p, %p, %s)", pTable, pSubTable, pSuperTable, szDrvName));
if( !pTable )
return FAILURE;
/* Copy the pSuperTable into pTable */
if( !szDrvName || !( uiCount = strlen( ( const char * ) szDrvName ) ) )
{
memcpy( pTable, &defTable, sizeof( RDDFUNCS ) );
memcpy( pSuperTable, &defTable, sizeof( RDDFUNCS ) );
}
else
{
szSuperName = ( char * ) hb_xgrab( uiCount + 1 );
hb_strncpyUpper( szSuperName, ( char * ) szDrvName, uiCount );
pRddNode = hb_rddFindNode( szSuperName, 0 );
hb_xfree( szSuperName );
if( !pRddNode )
{
return FAILURE;
}
memcpy( pTable, &pRddNode->pTable, sizeof( RDDFUNCS ) );
memcpy( pSuperTable, &pRddNode->pTable, sizeof( RDDFUNCS ) );
}
/* Copy the non NULL entries from pSubTable into pTable */
pFunction = ( DBENTRYP_V * ) pTable;
pSubFunction = ( DBENTRYP_V * ) pSubTable;
for( uiCount = 0; uiCount < RDDFUNCSCOUNT; uiCount++ )
{
if( * pSubFunction )
* pFunction = * pSubFunction;
pFunction += 1;
pSubFunction += 1;
}
return SUCCESS;
}
/*
* -- FUNCTIONS ACCESSED FROM VIRTUAL MACHINE --
*/
int hb_rddGetCurrentWorkAreaNumber( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_rddGetCurrentWorkAreaNumber()"));
return uiCurrArea;
}
ERRCODE hb_rddSelectWorkAreaNumber( int iArea )
{
LPAREANODE pAreaNode;
HB_TRACE(HB_TR_DEBUG, ("hb_rddSelectWorkAreaNumber(%d)", iArea));
uiCurrArea = iArea;
pAreaNode = pWorkAreas;
while( pAreaNode )
{
if( ( ( AREAP ) pAreaNode->pArea )->uiArea == uiCurrArea )
{
pCurrArea = pAreaNode; /* Select a valid WorkArea */
return SUCCESS;
}
pAreaNode = pAreaNode->pNext;
}
pCurrArea = NULL; /* Selected WorkArea is closed */
return FAILURE;
}
ERRCODE hb_rddSelectWorkAreaSymbol( PHB_SYMB pSymAlias )
{
ERRCODE bResult;
HB_TRACE(HB_TR_DEBUG, ("hb_rddSelectWorkAreaSymbol(%p)", pSymAlias));
if( pSymAlias->pDynSym->hArea )
bResult = hb_rddSelectWorkAreaNumber( pSymAlias->pDynSym->hArea );
else
{
char * szName = pSymAlias->pDynSym->pSymbol->szName;
if( strlen( szName ) == 1 && toupper( szName[ 0 ] ) >= 'A' && toupper( szName[ 0 ] ) <= 'K' )
bResult = hb_rddSelectWorkAreaNumber( toupper( szName[ 0 ] ) - 'A' + 1 );
else
{
/* generate an error with retry possibility
* (user created error handler can open a missing database)
*/
USHORT uiAction = E_RETRY;
HB_ITEM_PTR pError;
pError = hb_errRT_New( ES_ERROR, NULL, EG_NOALIAS, 1002,
NULL, pSymAlias->szName, 0, EF_CANRETRY );
bResult = FAILURE;
while( uiAction == E_RETRY )
{
uiAction = hb_errLaunch( pError );
if( uiAction == E_RETRY )
if( pSymAlias->pDynSym->hArea )
{
bResult = hb_rddSelectWorkAreaNumber( pSymAlias->pDynSym->hArea );
uiAction = E_DEFAULT;
}
}
hb_errRelease( pError );
}
}
return bResult;
}
ERRCODE hb_rddSelectWorkAreaAlias( char * szName )
{
ERRCODE bResult;
ULONG ulLen;
HB_TRACE(HB_TR_DEBUG, ("hb_rddSelectWorkAreaAlias(%s)", szName));
ulLen = strlen( szName );
if( ulLen >= 1 && toupper( szName[ 0 ] ) > '0' && toupper( szName[ 0 ] ) <= '9' )
bResult = hb_rddSelectWorkAreaNumber( atoi( szName ) );
else if( ulLen == 1 && toupper( szName[ 0 ] ) >= 'A' && toupper( szName[ 0 ] ) <= 'K' )
bResult = hb_rddSelectWorkAreaNumber( toupper( szName[ 0 ] ) - 'A' + 1 );
else
{
PHB_DYNS pSymArea;
pSymArea = hb_dynsymFindName( szName );
if( pSymArea && pSymArea->hArea )
bResult = hb_rddSelectWorkAreaNumber( pSymArea->hArea );
else
{
/* generate an error with retry possibility
* (user created error handler can open a missing database)
*/
USHORT uiAction = E_RETRY;
HB_ITEM_PTR pError;
pError = hb_errRT_New( ES_ERROR, NULL, EG_NOALIAS, 1002,
NULL, szName, 0, EF_CANRETRY );
bResult = FAILURE;
while( uiAction == E_RETRY )
{
uiAction = hb_errLaunch( pError );
if( uiAction == E_RETRY )
{
pSymArea = hb_dynsymFindName( szName );
if( pSymArea && pSymArea->hArea )
{
bResult = hb_rddSelectWorkAreaNumber( pSymArea->hArea );
uiAction = E_DEFAULT;
}
}
}
hb_errRelease( pError );
}
}
return bResult;
}
ERRCODE hb_rddGetFieldValue( HB_ITEM_PTR pItem, PHB_SYMB pFieldSymbol )
{
ERRCODE bSuccess;
HB_TRACE(HB_TR_DEBUG, ("hb_rddGetFieldValue(%p, %p)", pItem, pFieldSymbol));
bSuccess = hb_rddFieldGet( pItem, pFieldSymbol );
if( bSuccess == FAILURE )
{
/* generate an error with retry possibility
* (user created error handler can make this field accessible)
*/
USHORT uiAction = E_RETRY;
HB_ITEM_PTR pError;
pError = hb_errRT_New( ES_ERROR, NULL, EG_NOVAR, 1003,
NULL, pFieldSymbol->szName, 0, EF_CANRETRY );
while( uiAction == E_RETRY )
{
uiAction = hb_errLaunch( pError );
if( uiAction == E_RETRY )
{
bSuccess = hb_rddFieldGet( pItem, pFieldSymbol );
if( bSuccess == SUCCESS )
uiAction = E_DEFAULT;
}
}
hb_errRelease( pError );
}
return bSuccess;
}
ERRCODE hb_rddPutFieldValue( HB_ITEM_PTR pItem, PHB_SYMB pFieldSymbol )
{
ERRCODE bSuccess;
HB_TRACE(HB_TR_DEBUG, ("hb_rddPutFieldValue(%p, %p)", pItem, pFieldSymbol));
bSuccess = hb_rddFieldPut( pItem, pFieldSymbol );
if( bSuccess == FAILURE )
{
/* generate an error with retry possibility
* (user created error handler can make this field accessible)
*/
USHORT uiAction = E_RETRY;
HB_ITEM_PTR pError;
pError = hb_errRT_New( ES_ERROR, NULL, EG_NOVAR, 1003,
NULL, pFieldSymbol->szName, 0, EF_CANRETRY );
while( uiAction == E_RETRY )
{
uiAction = hb_errLaunch( pError );
if( uiAction == E_RETRY )
{
bSuccess = hb_rddFieldPut( pItem, pFieldSymbol );
if( bSuccess == SUCCESS )
uiAction = E_DEFAULT;
}
}
hb_errRelease( pError );
}
return bSuccess;
}
ERRCODE hb_rddFieldPut( HB_ITEM_PTR pItem, PHB_SYMB pFieldSymbol )
{
LPFIELD pField;
USHORT uiField;
HB_TRACE(HB_TR_DEBUG, ("hb_rddFieldPut(%p, %p)", pItem, pFieldSymbol));
if( pCurrArea )
{
uiField = 1;
pField = ( ( AREAP ) pCurrArea->pArea )->lpFields;
while( pField )
{
if( ( PHB_DYNS ) pField->sym == pFieldSymbol->pDynSym )
{
SELF_PUTVALUE( ( AREAP ) pCurrArea->pArea, uiField, pItem );
return SUCCESS;
}
pField = pField->lpfNext;
uiField++;
}
}
return FAILURE;
}
ERRCODE hb_rddFieldGet( HB_ITEM_PTR pItem, PHB_SYMB pFieldSymbol )
{
LPFIELD pField;
USHORT uiField;
HB_TRACE(HB_TR_DEBUG, ("hb_rddFieldGet(%p, %p)", pItem, pFieldSymbol));
if( pCurrArea )
{
uiField = 1;
pField = ( ( AREAP ) pCurrArea->pArea )->lpFields;
while( pField )
{
if( ( PHB_DYNS ) pField->sym == pFieldSymbol->pDynSym )
{
SELF_GETVALUE( ( AREAP ) pCurrArea->pArea, uiField, pItem );
return SUCCESS;
}
pField = pField->lpfNext;
uiField++;
}
}
return FAILURE;
}
void hb_rddShutDown( void )
{
LPRDDNODE pRddNode;
HB_TRACE(HB_TR_DEBUG, ("hb_rddShutDown()"));
hb_rddCloseAll();
if( szDefDriver )
hb_xfree( szDefDriver );
while( pRddList )
{
pRddNode = pRddList;
pRddList = pRddList->pNext;
hb_xfree( pRddNode );
}
}
/*
* -- HARBOUR FUNCTIONS --
*/
/* $DOC$
* $FUNCNAME$
* AFIELDS()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Fills referenced arrays with database field information
* $SYNTAX$
* AFields(<aNames>[,<aTypes>][,<aLen>][,<aDecs>]) --> <nFields>
* $ARGUMENTS$
* <aNames> Array of field names
* <aTypes> Array of field names
* <aLens> Array of field names
* <aDecs> Array of field names
* $RETURNS$
* <nFields> Number od fields in a database or work area
* $DESCRIPTION$
* This function will fill a series of arrays with field
* names,field types,field lenghts, and number of field
* decimal positions for the currently selected or designed
* database. Each array parallels the different descriptors
* of a file's structure.The first array will consist of the
* names of the fields in the current work area.All other arrays
* are optional and will be filled with the corrensponding data.
* This function will return zero if no parameters are specified
* or if no database is avaliable in the current work area.Otherwise,
* the number of fields or the lenght of the shortest array argument,
* witchever is smaller, will be returned.
* $EXAMPLES$
* FUNCTION Main()
* LOCAL aNames:={},aTypes:={},aLens:={},aDecs:={},nFields:=0
*
* USE Test
*
* dbGoTop()
* nFields:=aFields(aNames,aTypes,aLens,aDecs)
*
* ? "Number of fields", nFields
*
* RETURN NIL
* $TESTS$
* $STATUS$
* R
* $COMPLIANCE$
* AFIELDS() is fully CA-Clipper compliant.
* $SEEALSO$
* $END$
*/
HARBOUR HB_AFIELDS( void )
{
PHB_ITEM pName, pType, pLen, pDec, pItem;
USHORT uiFields, uiArrayLen, uiCount;
if( !pCurrArea )
{
hb_retni( 0 );
return;
}
pName = hb_param( 1, IT_ARRAY );
pType = hb_param( 2, IT_ARRAY );
pLen = hb_param( 3, IT_ARRAY );
pDec = hb_param( 4, IT_ARRAY );
if( !pName && !pType && !pLen && !pDec )
{
hb_retni( 0 );
return;
}
pItem = hb_itemNew( NULL );
SELF_FIELDCOUNT( ( AREAP ) pCurrArea->pArea, &uiFields );
if( pName )
{
uiArrayLen = hb_arrayLen( pName );
if( uiArrayLen > uiFields )
uiArrayLen = uiFields;
for( uiCount = 1; uiCount <= uiArrayLen; uiCount++ )
{
SELF_FIELDINFO( ( AREAP ) pCurrArea->pArea, uiCount, DBS_NAME, pItem );
hb_arraySet( pName, uiCount, pItem );
}
}
if( pType )
{
uiArrayLen = hb_arrayLen( pType );
if( uiArrayLen > uiFields )
uiArrayLen = uiFields;
for( uiCount = 1; uiCount <= uiArrayLen; uiCount++ )
{
SELF_FIELDINFO( ( AREAP ) pCurrArea->pArea, uiCount, DBS_TYPE, pItem );
hb_arraySet( pType, uiCount, pItem );
}
}
if( pLen )
{
uiArrayLen = hb_arrayLen( pLen );
if( uiArrayLen > uiFields )
uiArrayLen = uiFields;
for( uiCount = 1; uiCount <= uiArrayLen; uiCount++ )
{
SELF_FIELDINFO( ( AREAP ) pCurrArea->pArea, uiCount, DBS_LEN, pItem );
hb_arraySet( pLen, uiCount, pItem );
}
}
if( pDec )
{
uiArrayLen = hb_arrayLen( pDec );
if( uiArrayLen > uiFields )
uiArrayLen = uiFields;
for( uiCount = 1; uiCount <= uiArrayLen; uiCount++ )
{
SELF_FIELDINFO( ( AREAP ) pCurrArea->pArea, uiCount, DBS_DEC, pItem );
hb_arraySet( pDec, uiCount, pItem );
}
}
hb_itemRelease( pItem );
hb_retni( uiArrayLen );
}
/* $DOC$
* $FUNCNAME$
* ALIAS()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Returns the alias name of a work area
* $SYNTAX$
* Alias([<nWorkArea>]) --> <cWorkArea>
* $ARGUMENTS$
* <nWorkArea> Number of a work area
* $RETURNS$
* <cWorkArea> Name of alias
* $DESCRIPTION$
* This function returns the alias of the work area
* indicated by <nWorkArea>. If <nWorkArea> is not
* provided, the alias of the current work area is
* returned.This function does not differ from the Clipper
* function DBF(), with is a strictly a compatibility function
* $EXAMPLES$
* FUNCTION Main()
*
* USE Test
*
* select 0
* qOut( IF(Alias()=="","No Name",Alias()))
* Test->(qOut(Alias())
* qOut(Alias(1))
*
* RETURN NIL
* $TESTS$
* $STATUS$
* R
* $COMPLIANCE$
* ALIAS() is fully CA-Clipper compliant.
* $SEEALSO$
* $END$
*/
HARBOUR HB_ALIAS( void )
{
USHORT uiArea;
LPAREANODE pAreaNode;
char * szAlias;
uiArea = hb_parni( 1 );
uiArea = uiArea ? uiArea : uiCurrArea;
pAreaNode = pWorkAreas;
while( pAreaNode )
{
if( ( ( AREAP ) pAreaNode->pArea )->uiArea == uiArea )
{
if( ( ( AREAP ) pAreaNode->pArea )->atomAlias &&
( ( PHB_DYNS ) ( ( AREAP ) pAreaNode->pArea )->atomAlias )->hArea )
{
szAlias = ( char * ) hb_xgrab( HARBOUR_MAX_RDD_ALIAS_LENGTH + 1 );
SELF_ALIAS( ( AREAP ) pAreaNode->pArea, ( BYTE * ) szAlias );
hb_retc( szAlias );
hb_xfree( szAlias );
return;
}
break;
}
pAreaNode = pAreaNode->pNext;
}
hb_retc( "" );
}
/* $DOC$
* $FUNCNAME$
* DBEVAL()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Performs a code block operation on the current DATA BASE
* $SYNTAX$
* DBEVAL( <bBlock>,
* [<bFor>], [<bWhile>],
* [<nNext>], [<nRecord>],
* [<lRest>] ) --> NIL
* $ARGUMENTS$
* <bBlock> Operation that is to be performed
* <bFor> Code block for the For condition
* <bWhile> Code block for the WHILE condition
* <nNext> Number of NEXT records to process
* <nRecord> Record number to work on exactly
* <lRest> Toggle to rewind record pointer
* $RETURNS$
* NIL
* $DESCRIPTION$
* Performs a code block operation on the current DATA BASE
* $EXAMPLES$
* FUNCTION Main()
* LOCAL nCount
*
* USE Test
*
* dbGoto( 4 )
* ? RecNo()
* COUNT TO nCount
* ? RecNo(), nCount
* COUNT TO nCount NEXT 10
* ? RecNo(), nCount
*
* RETURN NIL
* $TESTS$
* $STATUS$
* S
* $COMPLIANCE$
* DBEVAL is fully CA-Clipper compliant.
* $SEEALSO$
* $END$
*/
HARBOUR HB_DBEVAL( void )
{
if( pCurrArea )
{
DBEVALINFO pEvalInfo;
pEvalInfo.itmBlock = hb_param( 1, IT_BLOCK );
if( !pEvalInfo.itmBlock )
{
hb_errRT_DBCMD( EG_ARG, 2019, NULL, "DBEVAL" );
return;
}
pEvalInfo.dbsci.itmCobFor = hb_param( 2, IT_BLOCK );
if( !pEvalInfo.dbsci.itmCobFor )
{
if( !ISNIL( 2 ) )
{
hb_errRT_DBCMD( EG_ARG, 2019, NULL, "DBEVAL" );
return;
}
}
pEvalInfo.dbsci.itmCobWhile = hb_param( 3, IT_BLOCK );
if( !pEvalInfo.dbsci.itmCobWhile )
{
if( !ISNIL( 3 ) )
{
hb_errRT_DBCMD( EG_ARG, 2019, NULL, "DBEVAL" );
return;
}
}
pEvalInfo.dbsci.lNext = hb_param( 4, IT_NUMERIC );
if( !pEvalInfo.dbsci.lNext )
{
if( !ISNIL( 4 ) )
{
hb_errRT_DBCMD( EG_ARG, 2019, NULL, "DBEVAL" );
return;
}
}
pEvalInfo.dbsci.itmRecID = hb_param( 5, IT_NUMERIC );
if( !pEvalInfo.dbsci.itmRecID )
{
if( !ISNIL( 5 ) )
{
hb_errRT_DBCMD( EG_ARG, 2019, NULL, "DBEVAL" );
return;
}
}
pEvalInfo.dbsci.fRest = hb_param( 6, IT_LOGICAL );
if( !pEvalInfo.dbsci.fRest )
{
if( !ISNIL( 6 ) )
{
hb_errRT_DBCMD( EG_ARG, 2019, NULL, "DBEVAL" );
return;
}
}
SELF_DBEVAL( ( AREAP ) pCurrArea->pArea, &pEvalInfo );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBEVAL" );
}
/* $DOC$
* $FUNCNAME$
* DBF()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Returns the alias name of a work area
* $SYNTAX$
* Dbf() --> <cWorkArea>
* $ARGUMENTS$
*
* $RETURNS$
* <cWorkArea> Name of alias
* $DESCRIPTION$
* This function returns the same alias name of
* the currently selected work area.
* This function is the same as Alias()
* $EXAMPLES$
* FUNCTION Main()
*
* USE Test
*
* select 0
* qOut( IF(DBF()=="","No Name",DBF()))
* Test->(qOut(DBF())
* qOut(Alias(1))
*
* RETURN NIL
* $TESTS$
* $STATUS$
* R
* $COMPLIANCE$
* ALIAS() is fully CA-Clipper compliant.
* $SEEALSO$
* $END$
*/
HARBOUR HB_DBF( void )
{
LPAREANODE pAreaNode = pWorkAreas;
while( pAreaNode )
{
if( ( ( AREAP ) pAreaNode->pArea )->uiArea == uiCurrArea )
{
if( ( ( AREAP ) pAreaNode->pArea )->atomAlias &&
( ( PHB_DYNS ) ( ( AREAP ) pAreaNode->pArea )->atomAlias )->hArea )
{
char * szAlias = ( char * ) hb_xgrab( HARBOUR_MAX_RDD_ALIAS_LENGTH + 1 );
SELF_ALIAS( ( AREAP ) pAreaNode->pArea, ( BYTE * ) szAlias );
hb_retc( szAlias );
hb_xfree( szAlias );
return;
}
break;
}
pAreaNode = pAreaNode->pNext;
}
hb_retc( "" );
}
/* $DOC$
* $FUNCNAME$
* BOF()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Test for the beggining-of-file condition
* $SYNTAX$
* BOF() --> <lBegin>
* $ARGUMENTS$
*
* $RETURNS$
* <lBegin> Logical true (.T.) or false (.F.)
* $DESCRIPTION$
* This function determines if the beggining of the file
* marker has been reached. If so, the function will return
* a logical true (.T.); otherwise, a logical false(.F.) will
* be returned.
* By default, BOF() will apply to the currently selected
* database unless the function is preceded by an alias
* $EXAMPLES$
* FUNCTION Main()
*
* USE Test
*
* qOut( BOF(),Recno())
* qOut(Test->(BOF()),Test->(Recno()))
* skip -1
* qOut( BOF(),Recno())
* qOut(Test->(BOF()),Test->(Recno()))
* dbGoBottom()
* qOut( EOF(),Recno())
* qOut(Test->(BOF()),Test->(Recno()),Test->(BOF()))
* skip
* Test->(dbGoBottom(),LastRec())
* qOut( EOF(),Recno())
* Test->(qOut(BOF(),Recno(),BOF()))
*
* RETURN NIL
* $TESTS$
* $STATUS$
* R
* $COMPLIANCE$
* BOF() is fully CA-Clipper compliant.
* $SEEALSO$
* EOF(),FOUND(),LASTREC()
* $END$
*/
HARBOUR HB_BOF( void )
{
BOOL bBof = TRUE;
if( pCurrArea )
SELF_BOF( ( AREAP ) pCurrArea->pArea, &bBof );
hb_retl( bBof );
}
/* $DOC$
* $FUNCNAME$
* DBAPPEND()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Appends a new record to a database file.
* $SYNTAX$
* DbAppend(<<lLock>]) --> NIL
* $ARGUMENTS$
* <lLock> Toggle to release record locks
* $RETURNS$
* $DESCRIPTION$
* This function add a new record to the end of the database
* in the selected or aliased work area. All fields in that
* database will be given empty data values - character fields
* will be filled with blank spaces,date fields with CTOD('//'),
* numeric fields with 0,logical fields with .F., and memo fields
* with NULL bytes.The header of the database is not updated until
* the record is flushed from the buffer and the contents are
* written to the disk.
* Under a networking enviroment, DBAPPEND() performs an addi-
* tional operation: It attrmps to lock the newly added record. If
* the database file is currently locked or if a locking assignment
* if made to LASTREC()+1,NETERR() will return a logical true (.T.)
* immediately after the DBAPPEND() function. This function does
* not unlock the locked records.
* If <lLock> is passed a logical true (.T.) value, it will
* release the record locks, which allows the application to main-
* tain multiple record locks during an appending operation. The
* default for this parameter is a logical false (.F.).
* $EXAMPLES$
* FUNCTION Main()
*
* USE Test
* local cName="HARBOUR",nId=10
* Test->(DbAppend())
* Replace Test->Name wit cName,Id with nId
* Use
* RETURN NIL
* $TESTS$
* $STATUS$
* R
* $COMPLIANCE$
* DBAPPEND() is fully CA-Clipper compliant.
* $SEEALSO$
* $END$
*/
HARBOUR HB_DBAPPEND( void )
{
BOOL bUnLockAll = TRUE;
if( pCurrArea )
{
bNetError = FALSE;
if( ISLOG( 1 ) )
bUnLockAll = hb_parl( 1 );
bNetError = ( SELF_APPEND( ( AREAP ) pCurrArea->pArea, bUnLockAll ) == FAILURE );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBAPPEND" );
}
/* $DOC$
* $FUNCNAME$
* DBCLEARFILTER()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Clears the current filter condiction in a work area
* $SYNTAX$
* DbClearFilTer() -> NIL
* $ARGUMENTS$
*
* $RETURNS$
*
* $DESCRIPTION$
* This function clears any active filter condiction
* for the current or selected work area.
* $EXAMPLES$
* Function Main()
*
* Use Test
*
* Set Filter to Left(Test->Name,2) == "An"
*
* Dbedit()
*
* Test->(DbClearFilter())
*
* USE
*
* Return Nil
* $TESTS$
* $STATUS$
* R
* $COMPLIANCE$
* DBCLEARFILTER() is fully CA-Clipper compliant.
* $SEEALSO$
* $END$
*/
HARBOUR HB_DBCLEARFILTER( void )
{
if( pCurrArea )
SELF_CLEARFILTER( ( AREAP ) pCurrArea->pArea );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBCLEARFILTER" );
}
/* $DOC$
* $FUNCNAME$
* DBCLOSEALL()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Close all open files in all work areas.
* $SYNTAX$
* DbCloseAll() -> NIL
* $ARGUMENTS$
*
* $RETURNS$
* DBCLOSEALL always return NIL
* $DESCRIPTION$
* This function close all open databases and all associated
* indexes.In addition, it closes all format files and moves
* the work area pointer to the first position
* $EXAMPLES$
* Function Main()
*
* Use Test New
*
* DbEdit()
*
* Use Test1 New
*
* DbEdit()
*
* DbCloseAll()
*
* USE
*
* Return Nil
* $TESTS$
* $STATUS$
* R
* $COMPLIANCE$
* DBCLOSEALL() is fully CA-Clipper compliant.
* $SEEALSO$
* $END$
*/
HARBOUR HB_DBCLOSEALL( void )
{
hb_rddCloseAll();
}
/* $DOC$
* $FUNCNAME$
* DBCLOSEAREA()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Close a database file in a work area.
* $SYNTAX$
* DbCloseArea() -> NIL
* $ARGUMENTS$
*
* $RETURNS$
*
* $DESCRIPTION$
* This function will close any database open in the selected
* or aliased work area.
* $EXAMPLES$
* Function Main()
*
* Use Test
*
* Dbedit()
*
* Test->(DbCloseArea())
*
* USE
*
* Return Nil
* $TESTS$
* $STATUS$
* R
* $COMPLIANCE$
* DBCLOSEAREA() is fully CA-Clipper compliant.
* $SEEALSO$
* $END$
*/
HARBOUR HB_DBCLOSEAREA( void )
{
if( !pCurrArea )
return;
SELF_CLOSE( ( AREAP ) pCurrArea->pArea );
SELF_RELEASE( ( AREAP ) pCurrArea->pArea );
if( pWorkAreas == pCurrArea )
{
pWorkAreas = pCurrArea->pNext;
if( pWorkAreas )
pWorkAreas->pPrev = NULL;
}
else
{
if( pCurrArea->pPrev )
pCurrArea->pPrev->pNext = pCurrArea->pNext;
if( pCurrArea->pNext )
pCurrArea->pNext->pPrev = pCurrArea->pPrev;
}
hb_xfree( pCurrArea->pArea );
hb_xfree( pCurrArea );
pCurrArea = NULL;
}
/* $DOC$
* $FUNCNAME$
* DBCOMMIT()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Flush pending updates
* $SYNTAX$
* DBCOMMIT() --> NIL
* $ARGUMENTS$
*
* $RETURNS$
* DBCOMMIT() always returns NIL.
* $DESCRIPTION$
* DBCOMMIT() causes all updates to the current work area to be written to
* disk. All updated database and index buffers are written to DOS and a
* DOS COMMIT request is issued for the database (.dbf) file and any index
* files associated with the work area.
*
* DBCOMMIT() performs the same function as the standard COMMIT command
* except that it operates only on the current work area. For more
* information, refer to the COMMIT command.
*
* Notes
*
* Network environment: DBCOMMIT() makes database updates visible
* to other processes. To insure data integrity, issue DBCOMMIT()
* before an UNLOCK operation. For more information, refer to the
* Network Programming chapter in the Programming and Utilities guide.
*
* DBCOMMIT() uses DOS interrupt 21h function 68h to perform the
* solid-disk write. It is up to the network operating system to
* properly implement this request. Check with the network vendor to
* see if this is supported.
*
* $EXAMPLES$
* In this example, COMMIT is used to force a write to disk after
* a series of memory variables are assigned to field variables:
*
* USE Sales EXCLUSIVE NEW
* MEMVAR->Name := Sales->Name
* MEMVAR->Amount := Sales->Amount
* //
* @ 10, 10 GET MEMVAR->Name
* @ 11, 10 GET MEMVAR->Amount
* READ
* //
* IF UPDATED()
* APPEND BLANK
* REPLACE Sales->Name WITH MEMVAR->Name
* REPLACE Sales->Amount WITH MEMVAR->Amount
* Sales->( DBCOMMIT() )
* ENDIF
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
*
* $SEEALSO$
* DBCLOSEALL(),DBCOMMITALL(),DBUNLOCK()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBCOMMIT( void )
{
if( pCurrArea )
SELF_FLUSH( ( AREAP ) pCurrArea->pArea );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBCOMMIT" );
}
/* $DOC$
* $FUNCNAME$
* DBCOMMITALL()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Flush pending updates in all work areas
* $SYNTAX$
* DBCOMMIT() --> NIL
* $ARGUMENTS$
*
* $RETURNS$
* DBCOMMIT() always returns NIL.
* $DESCRIPTION$
* DBCOMMITALL() causes all pending updates to all work areas to be written
* to disk. It is equivalent to calling DBCOMMIT() for every occupied work
* area.
* For more information, refer to DBCOMMIT().
* Notes
* DBCOMMITALL() uses DOS interrupt 21h function 68h to perform
* the solid-disk write. It is up to the network operating system to
* properly implement this request. Check with the network vendor to
* see if this is supported.
*
* $EXAMPLES$
* The following example writes all pending updates to disk:
* cLast := "Winston"
* //
* DBUSEAREA( .T., "DBFNTX", "Sales", "Sales", .T. )
* DBSETINDEX( "SALEFNAM" )
* DBSETINDEX( "SALELNAM" )
* //
* DBUSEAREA( .T., "DBFNTX", "Colls", "Colls", .T. )
* DBSETINDEX( "COLLFNAM" )
* DBSETINDEX( "COLLLNAM" )
* DBSELECTAREA( "Sales" ) // select "Sales" work area
* IF ( Sales->(DBSEEK(cLast)) )
* IF Sales->( DELETED() ) .AND. Sales( RLOCK() )
* Sales->( DBRECALL() )
* ? "Deleted record has been recalled."
* ENDIF
* ELSE
* ? "Not found"
* ENDIF
* //
* // processing done, write updates to disk and close
* DBCOMMITALL()
* DBCLOSEALL()
* QUIT
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBCLOSEALL(),DBCOMMIT(),DBUNLOCK()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBCOMMITALL( void )
{
LPAREANODE pAreaNode;
pAreaNode = pWorkAreas;
while( pAreaNode )
{
SELF_FLUSH( ( AREAP ) pAreaNode->pArea );
pAreaNode = pAreaNode->pNext;
}
}
/* $DOC$
* $FUNCNAME$
* __DBCONTINUE
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Resume a pending LOCATE
* $SYNTAX$
* __DbCONTINUE() -> NIL
* $ARGUMENTS$
*
* $RETURNS$
* __DbCONTINUE() Always return nil
* $DESCRIPTION$
* __DBCONTINUE is a database command that searches from the current record
* position for the next record meeting the most recent LOCATE condition
* executed in the current work area. It terminates when a match is found
* or end of file is encountered. If __DBCONTINUE is successful, the matching
* record becomes the current record and FOUND() returns true (.T.); if
* unsuccessful, FOUND() returns false (.F.).
* Each work area may have an active LOCATE condition. In CA-Clipper, a
* LOCATE condition remains pending until a new LOCATE condition is
* specified. No other commands release the condition.
Notes
* Scope and WHILE condition: Note that the scope and WHILE
* condition of the initial LOCATE are ignored; only the FOR condition
* is used with CONTINUE. If you are using a LOCATE with a WHILE
* condition and want to continue the search for a matching record, use
* SKIP and then repeat the original LOCATE statement adding REST as the
* scope.
*
* $EXAMPLES$
* This example scans records in Sales.dbf for a particular
* salesman and displays a running total sales amounts:
* LOCAL nRunTotal := 0
* USE Sales NEW
* LOCATE FOR Sales->Salesman = "1002"
* DO WHILE FOUND()
* ? Sales->Salesname, nRunTotal += Sales->Amount
* __DBCONTINUE()
* ENDDO
* This example demonstrates how to continue if the pending
* LOCATE scope contains a WHILE condition:
* LOCAL nRunTotal := 0
* USE Sales INDEX Salesman NEW
* SEEK "1002"
* LOCATE REST WHILE Sales->Salesman = "1002";
* FOR Sales->Amount > 5000
* DO WHILE FOUND()
* ? Sales->Salesname, nRunTotal += Sales->Amount
* SKIP
* LOCATE REST WHILE Sales->Salesman = "1002";
* FOR Sales->Amount > 5000
* ENDDO
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* EOF(),FOUND()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB___DBCONTINUE()
{
BOOL bEof;
if( !pCurrArea )
{
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBCONTINUE" );
return;
}
if( !( ( AREAP ) pCurrArea->pArea )->dbsi.itmCobFor )
return;
( ( AREAP ) pCurrArea->pArea )->fFound = FALSE;
SELF_SKIP( ( AREAP ) pCurrArea->pArea, 1 );
SELF_EOF( ( AREAP ) pCurrArea->pArea, &bEof );
if( bEof )
return;
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( ( ( AREAP ) pCurrArea->pArea )->dbsi.itmCobFor );
hb_vmDo( 0 );
( ( AREAP ) pCurrArea->pArea )->fFound = hb_itemGetL( &hb_stack.Return );
while( !bEof && !( ( AREAP ) pCurrArea->pArea )->fFound )
{
SELF_SKIP( ( AREAP ) pCurrArea->pArea, 1 );
SELF_EOF( ( AREAP ) pCurrArea->pArea, &bEof );
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( ( ( AREAP ) pCurrArea->pArea )->dbsi.itmCobFor );
hb_vmDo( 0 );
( ( AREAP ) pCurrArea->pArea )->fFound = hb_itemGetL( &hb_stack.Return );
}
}
/* $DOC$
* $FUNCNAME$
* DBCREATE()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Create a database file from a database structure array
* $SYNTAX$
* DBCREATE(<cDatabase>, <aStruct>,[<cDriver>]) --> NIL
*
* $ARGUMENTS$
* <cDatabase> is the name of the new database file, with an optional
* drive and directory, specified as a character string. If specified
* without an extension (.dbf) is assumed.
* <aStruct> is an array that contains the structure of <cDatabase> as
* a series of subarrays, one per field. Each subarray contains the
* definition of each field's attributes and has the following structure:
* Field Definition Subarray
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* Position Metasymbol Dbstruct.ch
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 1 cName DBS_NAME
* 2 cType DBS_TYPE
* 3 nLength DBS_LEN
* 4 nDecimals DBS_DEC
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <cDriver> specifies the replaceable database driver (RDD) to use to
* process the current work area. <cDriver> is name of the RDD specified
* as a character expression. If you specify <cDriver> as a literal value,
* you must enclose it in quotes.
*
* $RETURNS$
* DBCREATE() always returns NIL.
* $DESCRIPTION$
DBCREATE() is a database function that creates a database file from an
* array containing the structure of the file. You may create the array
* programmatically or by using DBSTRUCT(). DBCREATE() is similar to the
* CREATE FROM command which creates a new database file structure from a
* structure extended file. Use CREATE or COPY STRUCTURE EXTENDED commands
* to create a structure extended file.
* Before using DBCREATE(), you must first create the <aStruct> array and
* fill it with the field definition arrays according to the structure in
* Field Definition Subarray table (above). There are some specific rules
* for creating a field definition array, including:
* Specify all field attributes with a value of the proper data
* type for the attribute. The decimals attribute must be
* specified--even for non-numeric fields. If the field does not have a
* decimals attribute, specify zero.
* Specify the type attribute using the first letter of the data
* type as a minimum. Use longer and more descriptive terms for
* readability. For example, both "C" and "Character" can be specified
* as the type attribute for character fields.
* In CA-Clipper, character fields contain up to 64,000
* characters. Unlike the CREATE FROM command, DBCREATE() does not use
* the decimals attribute to specify the high-order part of the field
* length. Specify the field length directly, regardless of its
* magnitude.
* To make references to the various elements of the field definition
* subarray more readable, the header file called Dbstruct.ch is supplied
* which contains the #defines to assign a name to the array position for
* each field attribute. It is located in \CLIPPER5\INCLUDE.
*
* $EXAMPLES$
* This example creates an empty array and then adds field
* definition subarrays using the AADD() function before creating
* People.dbf. You might use this technique to add field definitions to
* your structure array dynamically:
* aDbf := {}
* AADD(aDbf, { "Name", "C", 25, 0 })
* AADD(aDbf, { "Address", "C", 1024, 0 })
* AADD(aDbf, { "Phone", "N", 13, 0 })
* //
* DBCREATE("People", aDbf)
* This example performs the same types of actions but declares
* the structure array as a two-dimensional array, and then uses
* subscript addressing to specify the field definitions. It will be
* created using the DBFMDX RDD:
* #include "Dbstruct.ch"
* //
* LOCAL aDbf[1][4]
* aDbf[1][ DBS_NAME ] := "Name"
* aDbf[1][ DBS_TYPE ] := "Character"
* aDbf[1][ DBS_LEN ] := 25
* aDbf[1][ DBS_DEC ] := 0
* //
* DBCREATE("Name", aDbf, "DBFMDX")
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* AFIELDS(),DBSTRUCT()
* $INCLUDE$
* "Dbstruct.ch"
* $END$
*/
HARBOUR HB_DBCREATE( void )
{
char * szDriver, * szFileName;
USHORT uiSize, uiLen, uiRddID;
ULONG ulRecCount;
LPRDDNODE pRddNode;
LPAREANODE pAreaNode;
DBOPENINFO pInfo;
PHB_FNAME pFileName;
PHB_ITEM pStruct, pFieldDesc, pFileExt;
char cDriverBuffer[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ];
BOOL bError = FALSE;
szFileName = hb_parc( 1 );
pStruct = hb_param( 2 , IT_ARRAY );
uiLen = hb_arrayLen( pStruct );
if( ( strlen( szFileName ) == 0 ) || !pStruct || uiLen == 0 )
{
hb_errRT_DBCMD( EG_ARG, 1014, NULL, "DBCREATE" );
return;
}
for( uiSize = 0; uiSize < uiLen; uiSize++ )
{
pFieldDesc = hb_arrayGetItemPtr( pStruct, uiSize + 1 );
if( hb_arrayLen( pFieldDesc ) < 4 )
{
hb_errRT_DBCMD( EG_ARG, 1014, NULL, "DBCREATE" );
return;
}
/* Validate items type, name, size and decimals of field */
if( !( hb_arrayGetType( pFieldDesc, 1 ) & IT_STRING ) ||
!( hb_arrayGetType( pFieldDesc, 2 ) & IT_STRING ) ||
!( hb_arrayGetType( pFieldDesc, 3 ) & IT_NUMERIC ) ||
!( hb_arrayGetType( pFieldDesc, 4 ) & IT_NUMERIC ) )
{
hb_errRT_DBCMD( EG_ARG, 1014, NULL, "DBCREATE" );
return;
}
}
hb_rddCheck();
uiLen = hb_parclen( 3 );
if( uiLen > 0 )
{
hb_strncpyUpper( cDriverBuffer, hb_parc( 3 ), uiLen );
szDriver = cDriverBuffer;
}
else
szDriver = szDefDriver;
uiRddID = 0;
pRddNode = hb_rddFindNode( szDriver, &uiRddID ) ;
if( !pRddNode )
{
hb_errRT_DBCMD( EG_ARG, 1015, NULL, "DBCREATE" );
return;
}
if( !ISLOG( 4 ) )
hb_rddSelectFirstAvailable();
else
{
if( hb_parl( 4 ) )
hb_rddSelectFirstAvailable();
else if( pCurrArea ) /* If current WorkArea is in use then close it */
{
SELF_CLOSE( ( AREAP ) pCurrArea->pArea );
SELF_RELEASE( ( AREAP ) pCurrArea->pArea );
if( pWorkAreas == pCurrArea )
{
pWorkAreas = pCurrArea->pNext;
if( pWorkAreas )
pWorkAreas->pPrev = NULL;
}
else
{
if( pCurrArea->pPrev )
pCurrArea->pPrev->pNext = pCurrArea->pNext;
if( pCurrArea->pNext )
pCurrArea->pNext->pPrev = pCurrArea->pPrev;
}
hb_xfree( pCurrArea->pArea );
hb_xfree( pCurrArea );
pCurrArea = NULL;
}
}
/* Create a new WorkArea node */
pCurrArea = ( LPAREANODE ) hb_xgrab( sizeof( AREANODE ) );
if( pRddNode->uiAreaSize == 0 ) /* Calculate the size of WorkArea */
{
uiSize = sizeof( AREA ); /* Default Size Area */
pCurrArea->pArea = ( AREAP ) hb_xgrab( uiSize );
memset( pCurrArea->pArea, 0, uiSize );
( ( AREAP ) pCurrArea->pArea )->lprfsHost = &pRddNode->pTable;
/* Need more space? */
SELF_STRUCTSIZE( ( AREAP ) pCurrArea->pArea, &uiSize );
if( uiSize > sizeof( AREA ) ) /* Size of Area changed */
pCurrArea->pArea = ( AREAP ) hb_xrealloc( pCurrArea->pArea, uiSize );
pRddNode->uiAreaSize = uiSize; /* Update the size of WorkArea */
}
else
{
pCurrArea->pArea = ( AREAP ) hb_xgrab( pRddNode->uiAreaSize );
memset( pCurrArea->pArea, 0, pRddNode->uiAreaSize );
( ( AREAP ) pCurrArea->pArea )->lprfsHost = &pRddNode->pTable;
}
( ( AREAP ) pCurrArea->pArea )->rddID = uiRddID;
pCurrArea->pPrev = NULL;
pCurrArea->pNext = NULL;
SELF_NEW( ( AREAP ) pCurrArea->pArea );
if( SELF_CREATEFIELDS( ( AREAP ) pCurrArea->pArea, pStruct ) == FAILURE )
{
SELF_RELEASE( ( AREAP ) pCurrArea->pArea );
hb_xfree( pCurrArea->pArea );
hb_xfree( pCurrArea );
pCurrArea = NULL;
hb_errRT_DBCMD( EG_ARG, 1014, NULL, "DBCREATE" );
return;
}
pFileName = hb_fsFNameSplit( szFileName );
szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 );
strcpy( szFileName, hb_parc( 1 ) );
if( !pFileName->szExtension )
{
pFileExt = hb_itemPutC( NULL, "" );
SELF_INFO( ( AREAP ) pCurrArea->pArea, DBI_TABLEEXT, pFileExt );
strcat( szFileName, pFileExt->item.asString.value );
hb_itemRelease( pFileExt );
}
hb_xfree( pFileName );
pInfo.abName = ( BYTE * ) szFileName;
pInfo.atomAlias = ( BYTE * ) hb_parc( 5 );
pInfo.uiArea = uiCurrArea;
( ( AREAP ) pCurrArea->pArea )->uiArea = uiCurrArea;
/* Insert the new WorkArea node */
if( !pWorkAreas )
pWorkAreas = pCurrArea; /* The new WorkArea node is the first */
else
{
pAreaNode = pWorkAreas;
while( pAreaNode )
{
if( ( ( AREAP ) pAreaNode->pArea )->uiArea > uiCurrArea )
{
/* Insert the new WorkArea node */
pCurrArea->pPrev = pAreaNode->pPrev;
pCurrArea->pNext = pAreaNode;
pAreaNode->pPrev = pCurrArea;
if( pCurrArea->pPrev )
pCurrArea->pPrev->pNext = pCurrArea;
else
pWorkAreas = pCurrArea;
break;
}
if( pAreaNode->pNext )
pAreaNode = pAreaNode->pNext;
else
{
/* Append the new WorkArea node */
pAreaNode->pNext = pCurrArea;
pCurrArea->pPrev = pAreaNode;
break;
}
}
}
( ( AREAP ) pCurrArea->pArea )->lpDataInfo->szFileName = szFileName;
( ( AREAP ) pCurrArea->pArea )->atomAlias = hb_dynsymGet( ( char * ) pInfo.atomAlias );
if( ( ( PHB_DYNS ) ( ( AREAP ) pCurrArea->pArea )->atomAlias )->hArea )
{
hb_errRT_DBCMD( EG_DUPALIAS, 1011, NULL, ( char * ) pInfo.atomAlias );
bError = TRUE;
}
if( !bError )
bError = ( SELF_CREATE( ( AREAP ) pCurrArea->pArea, &pInfo ) == FAILURE );
if( !bError )
( ( PHB_DYNS ) ( ( AREAP ) pCurrArea->pArea )->atomAlias )->hArea = pInfo.uiArea;
if( !bError && ( ( AREAP ) pCurrArea->pArea )->lpExtendInfo->fHasMemo )
{
pFileExt = hb_itemPutC( NULL, "" );
SELF_INFO( ( AREAP ) pCurrArea->pArea, DBI_MEMOEXT, pFileExt );
pFileName = hb_fsFNameSplit( ( char * ) pInfo.abName );
szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 );
szFileName[ 0 ] = '\0';
if( pFileName->szDrive )
strcat( szFileName, pFileName->szDrive );
if( pFileName->szPath )
strcat( szFileName, pFileName->szPath );
strcat( szFileName, pFileName->szName );
strcat( szFileName, pFileExt->item.asString.value );
pInfo.abName = ( BYTE * ) szFileName;
hb_xfree( pFileName );
hb_itemRelease( pFileExt );
( ( AREAP ) pCurrArea->pArea )->lpDataInfo->pNext =
( LPFILEINFO ) hb_xgrab( sizeof( FILEINFO ) );
memset( ( ( AREAP ) pCurrArea->pArea )->lpDataInfo->pNext, 0,
sizeof( FILEINFO ) );
( ( AREAP ) pCurrArea->pArea )->lpDataInfo->pNext->hFile = FS_ERROR;
( ( AREAP ) pCurrArea->pArea )->lpDataInfo->pNext->szFileName = szFileName;
bError = ( SELF_CREATEMEMFILE( ( AREAP ) pCurrArea->pArea, &pInfo ) == FAILURE );
}
( ( PHB_DYNS ) ( ( AREAP ) pCurrArea->pArea )->atomAlias )->hArea = 0;
SELF_RELEASE( ( AREAP ) pCurrArea->pArea );
if( !ISLOG( 4 ) || bError )
{
if( pWorkAreas == pCurrArea )
{
pWorkAreas = pCurrArea->pNext;
if( pWorkAreas )
pWorkAreas->pPrev = NULL;
}
else
{
if( pCurrArea->pPrev )
pCurrArea->pPrev->pNext = pCurrArea->pNext;
if( pCurrArea->pNext )
pCurrArea->pNext->pPrev = pCurrArea->pPrev;
}
hb_xfree( pCurrArea->pArea );
hb_xfree( pCurrArea );
pCurrArea = NULL;
}
else
{
SELF_NEW( ( AREAP ) pCurrArea->pArea );
szFileName = hb_parc( 1 );
pFileName = hb_fsFNameSplit( szFileName );
szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 );
strcpy( szFileName, hb_parc( 1 ) );
if( !pFileName->szExtension )
{
pFileExt = hb_itemPutC( NULL, "" );
SELF_INFO( ( AREAP ) pCurrArea->pArea, DBI_TABLEEXT, pFileExt );
strcat( szFileName, pFileExt->item.asString.value );
hb_itemRelease( pFileExt );
}
hb_xfree( pFileName );
pInfo.abName = ( BYTE * ) szFileName;
pInfo.fShared = !hb_set.HB_SET_EXCLUSIVE;
pInfo.fReadonly = FALSE;
( ( AREAP ) pCurrArea->pArea )->uiArea = uiCurrArea;
( ( AREAP ) pCurrArea->pArea )->lpDataInfo->szFileName = szFileName;
if( SELF_OPEN( ( AREAP ) pCurrArea->pArea, &pInfo ) == FAILURE )
{
SELF_RELEASE( ( AREAP ) pCurrArea->pArea );
hb_xfree( pCurrArea->pArea );
hb_xfree( pCurrArea );
pCurrArea = NULL;
}
SELF_RECCOUNT( ( AREAP ) pCurrArea->pArea, &ulRecCount );
( ( AREAP ) pCurrArea->pArea )->lpExtendInfo->ulRecCount = ulRecCount;
}
}
/* $DOC$
* $FUNCNAME$
* DBDELETE()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Mark a record for deletion
* $SYNTAX$
* DBDELETE() --> NIL
* $ARGUMENTS$
*
* $RETURNS$
* DBDELETE() always returns NIL.
* $DESCRIPTION$
DBDELETE() marks the current record as deleted. Records marked for
deletion can be filtered using SET DELETED or removed from the file
using the PACK command.
DBDELETE() performs the same function as the standard DELETE command
with a scope of the current record. For more information, refer to the
DELETE command.
Notes
Logical records: If the global _SET_DELETED status is true
(.T.), deleted records are not logically visible. That is, database
operations which operate on logical records will not consider records
marked for deletion. Note, however, that if _SET_DELETED is true
(.T.) when the current record is marked for deletion, the record
remains visible until it is no longer the current record.
Network environment: For a shared database on a network,
DBDELETE() requires the current record to be locked. For more
information, refer to the Network Programming chapter of the
Programming and Utilities guide.
*
* $EXAMPLES$
The following example deletes a record after a successful
record lock:
cLast := "Winston"
DBUSEAREA( .T., "DBFNTX", "Sales", "Sales", .T. )
DBSETINDEX( "LASTNAME" )
//
IF ( Sales->(DBSEEK(cLast)) )
IF Sales->( RLOCK() )
Sales->( DBDELETE() )
? "Record deleted: ", Sales( DELETED() )
ELSE
? "Unable to lock record..."
ENDIF
ELSE
? "Not found"
ENDIF
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBRECALL()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBDELETE( void )
{
if( pCurrArea )
SELF_DELETE( ( AREAP ) pCurrArea->pArea );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBDELETE" );
}
/* $DOC$
* $FUNCNAME$
* DBFILTER()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the current filter expression as a character string
* $SYNTAX$
* DBFILTER() --> cFilter
* $ARGUMENTS$
*
* $RETURNS$
* DBFILTER() returns the filter condition defined in the current work area
* as a character string. If no FILTER has been SET, DBFILTER() returns a
* null string ("").
*
* $DESCRIPTION$
* DBFILTER() is a database function used to save and reexecute an active
* filter by returning the filter expression as a character string that can
* be later recompiled and executed using the macro operator (&). This
* function operates like the DBRELATION() and DBRSELECT() functions which
* save and reexecute the linking expression of a relation within a work
* area.
*
* Since each work area can have an active filter, DBFILTER() can return
* the filter expression of any work area. This is done by referring to
* DBFILTER() within an aliased expression as demonstrated below.
*
* Notes
*
* Declared variables: A character string returned by DBFILTER()
* may not operate correctly when recompiled and executed using the
* macro operator (&) if the original filter expression contained
* references to local or static variables, or otherwise depended on
* compile-time declarations.
*
* $EXAMPLES$
* This example opens two database files, sets two filters, then
* displays the filter expressions for both work areas:
*
* USE Customer INDEX Customer NEW
* SET FILTER TO Last = "Smith"
* USE Invoices INDEX Invoices NEW
* SET FILTER TO CustId = "Smi001"
* SELECT Customer
* //
* ? DBFILTER() // Result: Last = "Smith"
* ? Invoices->(DBFILTER()) // Result: Custid = "Smi001"
*
* This user-defined function, CreateQry(), uses DBFILTER() to
* create a memory file containing the current filter expression in the
* private variable cFilter:
*
* FUNCTION CreateQry( cQryName )
*
* PRIVATE cFilter := DBFILTER()
* SAVE ALL LIKE cFilter TO (cQryName + ".qwy")
* RETURN NIL
*
* You can later RESTORE a query file with this user-defined
* function, SetFilter():
*
* FUNCTION SetFilter()
* PARAMETER cQryName
* RESTORE FROM &cQryName..qwy ADDITIVE
* SET FILTER TO &cFilter.
* RETURN NIL
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBRELATION(),DBRSELECT()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBFILTER( void )
{
PHB_ITEM pFilter;
if( pCurrArea )
{
pFilter = hb_itemPutC( NULL, "" );
SELF_FILTERTEXT( ( AREAP ) pCurrArea->pArea, pFilter );
hb_retc( pFilter->item.asString.value );
hb_itemRelease( pFilter );
}
else
hb_retc( "" );
}
/* $DOC$
* $FUNCNAME$
* DBGOBOTTOM()
* $CATEGORY$
* Data Base
* $ONELINER$
* Move to the last logical record
* $SYNTAX$
* DBGOBOTTOM() --> NIL
* $ARGUMENTS$
*
* $RETURNS$
* DBGOBOTTOM() always returns NIL.
* $DESCRIPTION$
* DBGOBOTTOM() moves to last logical record in the current work area.
*
* DBGOBOTTOM() performs the same function as the standard GO BOTTOM
* command. For more information, refer to the GO command.
*
* Notes
*
* Logical records: DBGOBOTTOM() operates on logical records. If
* there is an active index, DBGOBOTTOM() moves to the last record in
* indexed order. If a filter is set, only records which meet the
* filter condition are considered.
*
* Controlling order: If more than one index is active in the
* work area, the operation is performed using the controlling order as
* set by DBSETORDER() or the SET ORDER command. For more information,
* refer to the SET ORDER command.
*
* Network environment: For a shared file on a network, moving to
* a different record may cause updates to the current record to become
* visible to other processes.
*
* $EXAMPLES$
* The following example uses DBGOBOTTOM() to position the record
* pointer on the last logical record:
*
* cLast := "Winston"
* DBUSEAREA( .T., "DBFNTX", "Sales", "Sales", .T. )
* DBSETINDEX( "LASTNAME" )
* //
* Sales->( DBGOBOTTOM() )
* IF ( Sales->Last == "Winston" )
* IF RLOCK()
* Sales->( DBDELETE() )
* ? "Record deleted: ", Sales( DELETED() )
* ELSE
* ? "Unable to lock record..."
* ENDIF
* END
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* BOF(),EOF(),DBSKIP(),DBSEEK(),DBGOTOP()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBGOBOTTOM( void )
{
if( pCurrArea )
SELF_GOBOTTOM( ( AREAP ) pCurrArea->pArea );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBGOBOTTOM" );
}
/* $DOC$
* $FUNCNAME$
* DBGOTO()
* $CATEGORY$
* Data Base
* $ONELINER$
* Move to the record having the specified record number
* $SYNTAX$
* DBGOTO(<nRecordNumber>) --> NIL
* $ARGUMENTS$
* <nRecordNumber> is a numeric value that specifies the record number
* of the desired record.
*
* $RETURNS$
* DBGOTO() always returns NIL.
* $DESCRIPTION$
* DBGOTO() moves to the record whose record number is equal to
* <nRecordNumber>. If no such record exists, the work area is positioned
* to LASTREC() + 1 and both EOF() and BOF() return true (.T.).
*
* DBGOTO() performs the same function as the standard GO command. For
* more information, refer to the GO command.
*
* Notes
*
* Logical records: DBGOTO() does not respect logical visibility.
* That is, if the specified record exists, it will become the current
* record regardless of any index or filter condition.
*
* Network environment: For a shared file on a network, moving to
* a different record may cause updates to the current record to become
* visible to other processes.
*
* $EXAMPLES$
*
* The following example uses DBGOTO() to iteratively process
* every fourth record:
*
* DBUSEAREA( .T., "DBFNTX", "Sales", "Sales", .T. )
* //
* // toggle every fourth record
* DO WHILE !EOF()
* DBGOTO( RECNO() + 4 )
* Sales->Group := "Bear"
* ENDDO
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* BOF(),EOF(),DBGOTOP(),DBGOBOTTOM(),DBSEEK(),DBSKIP()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBGOTO( void )
{
PHB_ITEM pItem;
if( !pCurrArea )
{
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBGOTO" );
return;
}
pItem = hb_param( 1, IT_ANY );
if( !pItem )
hb_errRT_DBCMD( EG_ARG, 1003, NULL, "DBGOTO" );
else
SELF_GOTOID( ( AREAP ) pCurrArea->pArea, pItem );
}
/* $DOC$
* $FUNCNAME$
* DBGOTOP()
* $CATEGORY$
* Data Base
* $ONELINER$
* Move to the first logical record
* $SYNTAX$
* DBGOTOP() --> NIL
* $ARGUMENTS$
*
* $RETURNS$
* DBGOTOP() always returns NIL.
* $DESCRIPTION$
* DBGOTOP() moves to last logical record in the current work area.
*
* DBGOTOP() performs the same function as the standard GO TOP
* command. For more information, refer to the GO command.
*
* Notes
*
* Logical records: DBGOTOP() operates on logical records. If
* there is an active index, DBGOTOP() moves to the last record in
* indexed order. If a filter is set, only records which meet the
* filter condition are considered.
*
* Controlling order: If more than one index is active in the
* work area, the operation is performed using the controlling order as
* set by DBSETORDER() or the SET ORDER command. For more information,
* refer to the SET ORDER command.
*
* Network environment: For a shared file on a network, moving to
* a different record may cause updates to the current record to become
* visible to other processes.
*
* $EXAMPLES$
*
* This example demonstrates the typical use of DBGOTOP():
*
* DBGOTOP()
* WHILE ( !EOF() )
* ? FIELD->Name
* DBSKIP()
* END
*
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* BOF(),EOF(),DBSKIP(),DBSEEK(),DBGOBOTTOM()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBGOTOP( void )
{
if( pCurrArea )
SELF_GOTOP( ( AREAP ) pCurrArea->pArea );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBGOTOP" );
}
HARBOUR HB___DBLOCATE()
{
PHB_ITEM pFor, pFor2, pWhile, pNext, pRecord, pRest;
DBSCOPEINFO pScopeInfo;
ULONG lNext;
BOOL bEof, bFor, bWhile;
if( !pCurrArea )
{
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBSETFILTER" );
return;
}
memset( &pScopeInfo, 0, sizeof( DBSCOPEINFO ) );
pFor2 = hb_param( 1, IT_BLOCK );
pWhile = hb_param( 2, IT_BLOCK );
pNext = hb_param( 3, IT_NUMERIC );
pRecord = hb_param( 4, IT_NUMERIC );
pRest = hb_param( 5, IT_LOGICAL );
if( !pWhile )
{
pWhile = hb_itemPutL( NULL, TRUE );
pScopeInfo.itmCobWhile = pWhile;
}
else
{
pRest = hb_itemPutL( NULL, TRUE );
pScopeInfo.fRest = pRest;
}
if( !pFor2 )
pFor = hb_itemPutL( NULL, TRUE );
else
{
pFor = hb_itemNew( NULL );
hb_itemCopy( pFor, pFor2 );
}
if( !pRest )
{
pRest = hb_itemPutL( NULL, FALSE );
pScopeInfo.fRest = pRest;
}
pScopeInfo.itmCobFor = pFor;
SELF_SETLOCATE( ( AREAP ) pCurrArea->pArea, &pScopeInfo );
( ( AREAP ) pCurrArea->pArea )->fFound = FALSE;
if( pRecord )
{
SELF_GOTOID( ( AREAP ) pCurrArea->pArea, pRecord );
SELF_EOF( ( AREAP ) pCurrArea->pArea, &bEof );
if( bEof )
return;
if( hb_itemType( pWhile ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pWhile );
hb_vmDo( 0 );
bWhile = hb_itemGetL( &hb_stack.Return );
}
else
bWhile = hb_itemGetL( pWhile );
if( hb_itemType( pFor ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pFor );
hb_vmDo( 0 );
bFor = hb_itemGetL( &hb_stack.Return );
( ( AREAP ) pCurrArea->pArea )->fFound = ( bWhile && bFor );
}
else
( ( AREAP ) pCurrArea->pArea )->fFound = ( bWhile && hb_itemGetL( pFor ) );
}
else if( pNext )
{
SELF_EOF( ( AREAP ) pCurrArea->pArea, &bEof );
lNext = hb_parnl( 3 );
if( bEof || lNext <= 0 )
return;
if( hb_itemType( pWhile ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pWhile );
hb_vmDo( 0 );
bWhile = hb_itemGetL( &hb_stack.Return );
}
else
bWhile = hb_itemGetL( pWhile );
if( hb_itemType( pFor ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pFor );
hb_vmDo( 0 );
bFor = hb_itemGetL( &hb_stack.Return );
}
else
bFor = hb_itemGetL( pFor );
while( !bEof && lNext-- > 0 && bWhile && !bFor )
{
SELF_SKIP( ( AREAP ) pCurrArea->pArea, 1 );
SELF_EOF( ( AREAP ) pCurrArea->pArea, &bEof );
if( hb_itemType( pWhile ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pWhile );
hb_vmDo( 0 );
bWhile = hb_itemGetL( &hb_stack.Return );
}
else
bWhile = hb_itemGetL( pWhile );
if( hb_itemType( pFor ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pFor );
hb_vmDo( 0 );
bFor = hb_itemGetL( &hb_stack.Return );
}
else
bFor = hb_itemGetL( pFor );
}
( ( AREAP ) pCurrArea->pArea )->fFound = bFor;
}
else if( hb_itemGetL( pRest ) )
{
SELF_EOF( ( AREAP ) pCurrArea->pArea, &bEof );
if( bEof )
return;
if( hb_itemType( pWhile ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pWhile );
hb_vmDo( 0 );
bWhile = hb_itemGetL( &hb_stack.Return );
}
else
bWhile = hb_itemGetL( pWhile );
if( hb_itemType( pFor ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pFor );
hb_vmDo( 0 );
bFor = hb_itemGetL( &hb_stack.Return );
}
else
bFor = hb_itemGetL( pFor );
while( !bEof && bWhile && !bFor )
{
SELF_SKIP( ( AREAP ) pCurrArea->pArea, 1 );
SELF_EOF( ( AREAP ) pCurrArea->pArea, &bEof );
if( hb_itemType( pWhile ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pWhile );
hb_vmDo( 0 );
bWhile = hb_itemGetL( &hb_stack.Return );
}
else
bWhile = hb_itemGetL( pWhile );
if( hb_itemType( pFor ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pFor );
hb_vmDo( 0 );
bFor = hb_itemGetL( &hb_stack.Return );
}
else
bFor = hb_itemGetL( pFor );
}
( ( AREAP ) pCurrArea->pArea )->fFound = bFor;
}
else
{
SELF_GOTOP( ( AREAP ) pCurrArea->pArea );
SELF_EOF( ( AREAP ) pCurrArea->pArea, &bEof );
if( bEof )
return;
if( hb_itemType( pFor ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pFor );
hb_vmDo( 0 );
bFor = hb_itemGetL( &hb_stack.Return );
}
else
bFor = hb_itemGetL( pFor );
while( !bEof && !bFor )
{
SELF_SKIP( ( AREAP ) pCurrArea->pArea, 1 );
SELF_EOF( ( AREAP ) pCurrArea->pArea, &bEof );
if( hb_itemType( pFor ) == IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pFor );
hb_vmDo( 0 );
bFor = hb_itemGetL( &hb_stack.Return );
}
else
bFor = hb_itemGetL( pFor );
}
( ( AREAP ) pCurrArea->pArea )->fFound = bFor;
}
}
HARBOUR HB___DBSETLOCATE( void )
{
PHB_ITEM pLocate, pFor;
DBSCOPEINFO pScopeInfo;
if( pCurrArea )
{
pLocate = hb_param( 1, IT_BLOCK );
if( pLocate )
{
pFor = hb_itemNew( NULL );
hb_itemCopy( pFor, pLocate );
memset( &pScopeInfo, 0, sizeof( DBSCOPEINFO ) );
pScopeInfo.itmCobFor = pFor;
SELF_SETLOCATE( ( AREAP ) pCurrArea->pArea, &pScopeInfo );
}
}
}
HARBOUR HB___DBPACK( void )
{
if( pCurrArea )
{
/* Additional feature: __dbPack( [<bBlock>, [<nEvery>] )
Code Block to execute for every record. */
( ( AREAP ) pCurrArea->pArea )->lpExtendInfo->itmEval = hb_param( 1, IT_BLOCK );
( ( AREAP ) pCurrArea->pArea )->lpExtendInfo->ulEvery = hb_parnl( 2 );
if( !( ( AREAP ) pCurrArea->pArea )->lpExtendInfo->ulEvery )
( ( AREAP ) pCurrArea->pArea )->lpExtendInfo->ulEvery = 1;
SELF_PACK( ( AREAP ) pCurrArea->pArea );
( ( AREAP ) pCurrArea->pArea )->lpExtendInfo->itmEval = NULL;
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "__DBPACK" );
}
/* $DOC$
* $FUNCNAME$
* DBRECALL()
* $CATEGORY$
* Data Base
* $ONELINER$
* Reinstate a record marked for deletion
* $SYNTAX$
* DBRECALL() --> NIL
* $ARGUMENTS$
*
* $RETURNS$
* DBRECALL() always returns NIL.
* $DESCRIPTION$
* DBRECALL() causes the current record to be reinstated if it is marked
* for deletion.
*
* DBRECALL() performs the same function as the RECALL command. For more
* information, refer to the DELETE and RECALL commands.
*
* Notes
*
* Logical records: Reinstating a deleted record affects the
* record's logical visibility if the global _SET_DELETED status is true
* (.T.). For more information, refer to the DBDELETE() function and
* the DELETE and RECALL commands.
*
* Network environment: For a shared database on a network,
* DBRECALL() requires the current record to be locked.
*
* $EXAMPLES$
*
* The following example recalls a record if it is deleted and
* attempts to lock the record if successful:
*
* cLast := "Winston"
* DBUSEAREA( .T., "DBFNTX", "Sales", "Sales", .T. )
* DBSETINDEX( "LASTNAME" )
* //
* IF ( Sales->(DBSEEK(cLast)) )
* IF Sales->( DELETED() )
*
* IF Sales( RLOCK() )
* Sales( DBRECALL() )
* ? "Record recalled"
* ELSE
* ? "Unable to lock record..."
* ENDIF
* ENDIF
* ELSE
* ? "Not found"
* ENDIF
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBDELETE()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBRECALL( void )
{
if( pCurrArea )
SELF_RECALL( ( AREAP ) pCurrArea->pArea );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBRECALL" );
}
/* $DOC$
* $FUNCNAME$
* DBRLOCK()
* $CATEGORY$
* Data Base
* $ONELINER$
* Lock the record at the current or specified identity
* $SYNTAX$
* DBRLOCK([<xIdentity>]) --> lSuccess
* $ARGUMENTS$
* <xIdentity> is a unique value guaranteed by the structure of the
* data file to reference a specific item in a data source (database). In
* a (.dbf) <xIdentity> is the record number. In other data formats,
* <xIdentity> is the unique primary key value.
*
* $RETURNS$
*
* DBRLOCK() returns lSuccess, a logical data type that is true (.T.) if
* successful, false (.F.) if unsuccessful.
*
* $DESCRIPTION$
* DBRLOCK() is a database function that locks the record identified by the
* value <xIdentity>. In Xbase, <xIdentity> is the record number.
*
* If you do not specify <xIdentity>, all record locks are released and the
* current record is locked. If you specify <xIdentity>, DBRLOCK()
* attempts to lock it and, if successful, adds it to the locked record
* list.
*
* $EXAMPLES$
* This example shows two different methods for locking multiple
* records:
*
* FUNCTION dbRLockRange( nLo, nHi )
*
* LOCAL nRec
* FOR nRec := nLo TO nHi
* IF ! DBRLOCK( nRec )
* DBRUNLOCK() // Failed - unlock everything
* ENDIF
* NEXT
* RETURN DBRLOCKLIST() // Return array of actual locks
*
* FUNCTION dbRLockArray( aList )
*
* LOCAL nElement, nLen, lRet
* lRet := .T.
* nLen := LEN( aList )
* FOR nElement := 1 TO nLen
* IF ! DBRLOCK( aList[ nElement ] )
* DBRUNLOCK() // Failed - unlock everything
* lRet := .F.
* ENDIF
* NEXT
* RETURN DBRLOCKLIST()
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBUNLOCK(),DBUNLOCKALL(),FLOCK(),RLOCK()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBRLOCK( void )
{
DBLOCKINFO pLockInfo;
pLockInfo.fResult = FALSE;
if( pCurrArea )
{
pLockInfo.itmRecID = hb_parnl( 1 );
pLockInfo.uiMethod = REC_LOCK;
SELF_LOCK( ( AREAP ) pCurrArea->pArea, &pLockInfo );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBRLOCK" );
hb_retl( pLockInfo.fResult );
}
/* $DOC$
* $FUNCNAME$
* DBRLOCKLIST()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return an array of the current Lock List
* $SYNTAX$
* DBRLOCKLIST() --> aRecordLocks
* $ARGUMENTS$
*
* $RETURNS$
* Returns an array of the locked records in the current or aliased work
* area.
* $DESCRIPTION$
* DBRLOCKLIST() is a database function that returns a one-dimensional
* array that contains the identities of record locks active in the
* selected work area.
*
* $EXAMPLES$
* PROCEDURE PrintCurLocks()
*
* LOCAL aList
* LOCAL nSize
* LOCAL nCount
*
* aList := DBRLOCKLIST()
* nSize := LEN( aList )
*
* ? "Currently locked records: "
* FOR nCount := 1 TO nSize
* ?? aList[ nCount ]
* ?? SPACE( 1 )
* NEXT
* ?
*
* RETURN
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* RLOCK(),DBRLOCK(),DBRUNLOCK()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBRLOCKLIST( void )
{
PHB_ITEM pList;
pList = hb_itemArrayNew( 0 );
if( pCurrArea )
SELF_INFO( ( AREAP ) pCurrArea->pArea, DBI_GETLOCKARRAY, pList );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBRLOCKLIST" );
hb_itemReturn( pList );
hb_itemRelease( pList );
}
/* $DOC$
* $FUNCNAME$
* DBRUNLOCK()
* $CATEGORY$
* Data Base
* $ONELINER$
* Release all or specified record locks
* $SYNTAX$
* DBRUNLOCK([<xIdentity>]) --> NIL
* $ARGUMENTS$
* <xIdentity> is a unique value guaranteed by the structure of the
* data file to reference a specific item in a data source (database). In
* a (.dbf) <xIdentity> is the record number. In other data formats,
* <xIdentity> is the unique primary key value.
* $RETURNS$
* DBRUNLOCK() always returns NIL.
* $DESCRIPTION$
* DBRUNLOCK() is a database function that releases the lock on <xIdentity>
* and removes it from the Lock List. If <xIdentity> is not specified, all
* record locks are released.
*
* $EXAMPLES$
* PROCEDURE dbRUnlockRange( nLo, nHi )
*
* LOCAL nCounter
*
* // Unlock the records in the range from nLo to nHi
* FOR nCounter := nLo TO nHi
* DBRUNLOCK( nCounter )
* NEXT
*
* RETURN
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* RLOCK(),DBRLOCK(),DBRLOCKLIST()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBRUNLOCK( void )
{
if( pCurrArea )
SELF_UNLOCK( ( AREAP ) pCurrArea->pArea, hb_parnl( 1 ) );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBRUNLOCK" );
}
/* $DOC$
* $FUNCNAME$
* DBSEEK()
* $CATEGORY$
* Data Base
* $ONELINER$
* Move to the record having the specified key value
* $SYNTAX$
* DBSEEK(<expKey>, [<lSoftSeek>],[<lFindLast>]) --> lFound
* $ARGUMENTS$
* <expKey> is a value of any type that specifies the key value
* associated with the desired record.
*
* <lSoftSeek> is an optional logical value that specifies whether a
* soft seek is to be performed. This determines how the work area is
* positioned if the specified key value is not found (see below). If
* <lSoftSeek> is omitted, the current global _SET_SOFTSEEK setting is
* used.
* <lFindLast> is an optional logical value that set the current
* record position to the last record if successful
* $RETURNS$
* DBSEEK() returns true (.T.) if the specified key value was found;
* otherwise, it returns false (.F.).
* $DESCRIPTION$
* DBSEEK() moves to the first logical record whose key value is equal to
* <expKey>. If such a record is found, it becomes the current record and
* DBSEEK() returns true (.T.). Otherwise, DBSEEK() returns false (.F.)
* and the positioning of the work area is as follows: for a normal (not
* soft) seek, the work area is positioned to LASTREC() + 1 and EOF()
* returns true (.T.); for a soft seek, the work area is positioned to the
* first record whose key value is greater than the specified key value.
* If no such record exists, the work area is positioned to LASTREC() + 1
* and EOF() returns true (.T.).
*
* For a work area with no active indexes, DBSEEK() has no effect.
*
* DBSEEK() performs the same function as the standard SEEK command. For
* more information, refer to the SEEK command.
*
* Notes
*
* Logical records: DBSEEK() operates on logical records.
* Records are considered in indexed order. If a filter is set, only
* records which meet the filter condition are considered.
*
* Controlling order: If the work area has more than one active
* index, the operation is performed using the controlling order as set
* by DBSETORDER() or the SET ORDER command. For more information,
* refer to the SET ORDER command.
*
* Network environment: For a shared file on a network, moving to
* a different record may cause updates to the current record to become
* visible to other processes.
*
*
* $EXAMPLES$
* In this example, DBSEEK() moves the pointer to the record in
* the database, Employee, in which the value in FIELD <20>cName<6D> matches
* the entered value of cName:
*
* ACCEPT "Employee name: " TO cName
* IF ( Employee->(DBSEEK(cName)) )
* Employee->(ViewRecord())
* ELSE
* ? "Not found"
* END
*
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
* DBSEEK() is Compatible with CA-Clipper 5.3
* $SEEALSO$
* DBGOBOTTOM(),DBGOTOP(),DBSKIP(),EOF(),BOF(),FOUND()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBSEEK( void )
{
PHB_ITEM pKey;
BOOL bSoftSeek, bFindLast;
if( pCurrArea )
{
if( !ISNIL( 1 ) )
{
pKey = hb_param( 1, IT_ANY );
bSoftSeek = ISLOG( 2 ) ? hb_parl( 2 ) : hb_set.HB_SET_SOFTSEEK;
bFindLast = ISLOG( 3 ) ? hb_parl( 3 ) : FALSE;
if( SELF_SEEK( ( AREAP ) pCurrArea->pArea, bSoftSeek, pKey, bFindLast ) == SUCCESS )
{
hb_retl( ( ( AREAP ) pCurrArea->pArea )->fFound );
return;
}
}
else
hb_errRT_DBCMD( EG_ARG, 1001, NULL, "DBSEEK" );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBSEEK" );
hb_retl( FALSE );
}
/* $DOC$
* $FUNCNAME$
* DBSELECTAREA()
* $CATEGORY$
* Data Base
* $ONELINER$
* Change the current work area
* $SYNTAX$
* DBSELECTAREA(<nArea> | <cAlias>) --> NIL
* $ARGUMENTS$
* <nArea> is a numeric value between zero and 250, inclusive, that
* specifies the work area being selected.
*
* <cAlias> is a character value that specifies the alias of a
* currently occupied work area being selected.
*
* $RETURNS$
* DBSELECTAREA() always returns NIL.
* $DESCRIPTION$
*
* DBSELECTAREA() causes the specified work area to become the current work
* area. All subsequent database operations will apply to this work area
* unless another work area is explicitly specified for an operation.
* DBSELECTAREA() performs the same function as the standard SELECT
* command. For more information, refer to the SELECT command.
*
* Notes
*
* Selecting zero: Selecting work area zero causes the lowest
* numbered unoccupied work area to become the current work area.
*
* Aliased expressions: The alias operator (->) can temporarily
* select a work area while an expression is evaluated and automatically
* restore the previously selected work area afterward. For more
* information, refer to the alias operator (->).
*
* $EXAMPLES$
* The following example selects a work area via the alias name:
*
* cLast := "Winston"
* DBUSEAREA( .T., "DBFNTX", "Sales", "Sales", .T. )
* DBSETINDEX( "SALEFNAM" )
* DBSETINDEX( "SALELNAM" )
* //
* DBUSEAREA( .T., "DBFNTX", "Colls", "Colls", .T. )
* DBSETINDEX( "COLLFNAM" )
* DBSETINDEX( "COLLLNAM" )
* //
* DBSELECTAREA( "Sales" ) // select "Sales" work area
* //
* IF ( Sales->(DBSEEK(cLast)) )
* IF Sales->( DELETED() ) .AND. Sales->( RLOCK() )
* Sales->( DBRECALL() )
* ? "Deleted record has been recalled."
* ENDIF
* ELSE
* ? "Not found"
* ENDIF
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBUSEAREA(),SELECT()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBSELECTAREA( void )
{
USHORT uiNewArea;
char * szAlias;
LPAREANODE pAreaNode;
if( ISCHAR( 1 ) )
{
ULONG ulLen;
szAlias = hb_parc( 1 );
ulLen = strlen( szAlias );
if( ulLen >= 1 && szAlias[ 0 ] >= '0' && szAlias[ 0 ] <= '9' )
uiNewArea = atoi( szAlias );
else if( ulLen == 1 && toupper( szAlias[ 0 ] ) >= 'A' && toupper( szAlias[ 0 ] ) <= 'K' )
uiNewArea = toupper( szAlias[ 0 ] ) - 'A' + 1;
else
{
if( ( uiNewArea = hb_rddSelect( szAlias ) ) == 0 )
{
hb_errRT_BASE( EG_NOALIAS, 1002, NULL, szAlias );
return;
}
}
}
else
uiNewArea = hb_parni( 1 );
if( uiNewArea == 0 )
hb_rddSelectFirstAvailable();
else
uiCurrArea = uiNewArea;
pAreaNode = pWorkAreas;
while( pAreaNode )
{
if( ( ( AREAP ) pAreaNode->pArea )->uiArea == uiCurrArea )
{
pCurrArea = pAreaNode; /* Select a valid WorkArea */
return;
}
pAreaNode = pAreaNode->pNext;
}
pCurrArea = NULL; /* Selected WorkArea is closed */
}
/* $DOC$
* $FUNCNAME$
* DBSETDRIVER()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the default database driver and optionally set a new driver
* $SYNTAX$
* DBSETDRIVER([<cDriver>]) --> cCurrentDriver
* $ARGUMENTS$
* <cDriver> is an optional character value that specifies the name of
* the database driver that should be used to activate and manage new work
* areas when no driver is explicitly specified.
* $RETURNS$
* DBSETDRIVER() returns the name of the current default driver.
* $DESCRIPTION$
* DBSETDRIVER() sets the database driver to be used when activating new
* work areas without specifying a driver. If the specified driver is not
* available to the application, the call has no effect. DBSETDRIVER()
* returns the name of the current default driver, if any.
*
* $EXAMPLES$
* This example makes the "DBFNDX" driver the default driver. If
* the driver is unavailable, a message is issued:
* DBSETDRIVER("DBFNDX")
* IF ( DBSETDRIVER() <> "DBFNDX" )
* * ? "DBFNDX driver not available"
* ENDIF
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBUSEAREA()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBSETDRIVER( void )
{
char * szNewDriver;
USHORT uiLen;
hb_rddCheck();
hb_retc( szDefDriver );
szNewDriver = hb_parc( 1 );
if( ( uiLen = strlen( szNewDriver ) ) > 0 )
{
hb_strUpper( szNewDriver, uiLen ); /* TOFIX: Direct access to hb_parc() buffer ! */
if( !hb_rddFindNode( szNewDriver, NULL ) )
{
hb_errRT_DBCMD( EG_ARG, 1015, NULL, "DBSETDRIVER" );
return;
}
szDefDriver = ( char * ) hb_xrealloc( szDefDriver, uiLen + 1 );
strcpy( szDefDriver, szNewDriver );
}
}
HARBOUR HB___DBSETFOUND( void )
{
PHB_ITEM pFound;
if( pCurrArea )
{
pFound = hb_param( 1, IT_LOGICAL );
if( pFound )
( ( AREAP ) pCurrArea->pArea )->fFound = hb_itemGetL( pFound );
}
}
/* $DOC$
* $FUNCNAME$
* DBSKIP()
* $CATEGORY$
* Data Base
* $ONELINER$
* Move relative to the current record
* $SYNTAX$
* DBSKIP([<nRecords>]) --> NIL
* $ARGUMENTS$
* <nRecords> is the number of logical records to move, relative to the
* current record. A positive value means to skip forward, and a negative
* value means to skip backward. If <nRecords> is omitted, a value of 1 is
* assumed.
* $RETURNS$
* DBSKIP() always returns NIL.
* $DESCRIPTION$
* DBSKIP() moves either forward or backward relative to the current
* record. Attempting to skip forward beyond the last record positions the
* work area to LASTREC() + 1 and EOF() returns true (.T.). Attempting to
* skip backward beyond the first record positions the work area to the
* first record and BOF() returns true (.T.).
* DBSKIP() performs the same function as the standard SKIP command. For
* more information, refer to the SKIP command.
*
* Notes
*
* Logical records: DBSKIP() operates on logical records. If
* there is an active index, records are considered in indexed order.
* If a filter is set, only records which meet the filter condition are
* considered.
*
* Controlling order: If the work area has more than one active
* index, the skip operation is performed using the controlling order as
* set by DBSETORDER() or the SET ORDER command. For more information,
* refer to the SET ORDER command.
*
* Network environment: For a shared file on a network, moving to
* a different record may cause updates to the current record to become
* visible to other processes.
*
* $EXAMPLES$
* This example demonstrates a typical use of the DBSKIP()
* function:
*
* DBGOTOP()
* DO WHILE ( !EOF() )
* ? FIELD->Name
* DBSKIP()
* ENDDO
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* BOF(),DBGOBOTTOM(),DBGOTOP(),DBSEEK(),EOF()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBSKIP( void )
{
LONG lToSkip = 1;
if( pCurrArea )
{
if( ISNUM( 1 ) )
lToSkip = hb_parnl( 1 );
SELF_SKIP( ( AREAP ) pCurrArea->pArea, lToSkip );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBSKIP" );
}
/* $DOC$
* $FUNCNAME$
* DBSETFILTER()
* $CATEGORY$
* Data Base
* $ONELINER$
* Set a filter condition
* $SYNTAX$
* DBSETFILTER(<bCondition>, [<cCondition>]) --> NIL
* $ARGUMENTS$
* <bCondition> is a code block that expresses the filter condition in
* executable form.
* <cCondition> is an optional character value that expresses the
* filter condition in textual form. If <cCondition> is omitted, the
* DBSETFILTER() function will return an empty string for the work area.
*
* $RETURNS$
* DBSETFILTER() always returns NIL.
* $DESCRIPTION$
* DBSETFILTER() sets a logical filter condition for the current work area.
* When a filter is set, records which do not meet the filter condition are
* not logically visible. That is, database operations which act on
* logical records will not consider these records.
* The filter expression supplied to DBSETFILTER() evaluates to true (.T.)
* if the current record meets the filter condition; otherwise, it should
* evaluate to false (.F.).
* The filter expression may be a code block (<bCondition>) or both a code
* block and equivalent text (<cCondition>). If both versions are
* supplied, they must express the same condition. If the text version is
* omitted, DBFILTER() will return an empty string for the work area.
* DBSETFILTER() performs the same function as the standard SET FILTER
* command. For more information, refer to the SET FILTER command.
*
* Notes
*
* Logical records: DBSETFILTER() affects the logical visibility
* of records (see above).
*
* Side effects: Setting a filter condition is only guaranteed to
* restrict visibility of certain records as described above. The
* filter expression is not necessarily evaluated at any particular
* time, by any particular means, or on any particular record or series
* of records. If the filter expression relies on information external
* to the database file or work area, the effect is unpredictable. If
* the filter expression changes the state of the work area (e.g., by
* moving to a different record or changing the contents of a record),
* the effect is unpredictable.
*
* Evaluation context: When the filter expression is evaluated,
* the associated work area is automatically selected as the current
* work area before the evaluation; the previously selected work area is
* automatically restored afterward.
* $EXAMPLES$
* This example limits data access to records in which the Age
* field value is less than 40:
*
* USE Employee NEW
* DBSETFILTER( {|| Age < 40}, "Age < 40" )
* DBGOTOP()
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBFILTER(),DBCLEARFILTER()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBSETFILTER( void )
{
PHB_ITEM pBlock, pText;
DBFILTERINFO pFilterInfo;
if( pCurrArea )
{
pBlock = hb_param( 1, IT_BLOCK );
if( pBlock )
{
pText = hb_param( 2, IT_STRING );
pFilterInfo.itmCobExpr = pBlock;
if( pText )
pFilterInfo.abFilterText = pText;
else
pFilterInfo.abFilterText = hb_itemPutC( NULL, "" );
SELF_SETFILTER( ( AREAP ) pCurrArea->pArea, &pFilterInfo );
if( !pText )
hb_itemRelease( pFilterInfo.abFilterText );
}
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBSETFILTER" );
}
/* $DOC$
* $FUNCNAME$
* DBSTRUCT()
* $CATEGORY$
* Data Base
* $ONELINER$
* Create an array containing the structure of a database file
* $SYNTAX$
* DBSTRUCT() --> aStruct
* $ARGUMENTS$
*
* $RETURNS$
* DBSTRUCT() returns the structure of the current database file in an
* array whose length is equal to the number of fields in the database
* file. Each element of the array is a subarray containing information
* for one field. The subarrays have the following format:
* DBSTRUCT() Return Array
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* Position * Metasymbol * Dbstruct.ch
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 1 * * cName * * DBS_NAME
* 2 * * cType * * DBS_TYPE
* 3 * * nLength * DBS_LEN
* 4 * * nDecimals * DBS_DEC
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* If there is no database file in USE in the current work area, DBSTRUCT()
* returns an empty array ({}).
*
* $DESCRIPTION$
* DBSTRUCT() is a database function that operates like COPY STRUCTURE
* EXTENDED by creating an array of structure information rather than a
* database file of structure information. There is another function,
* DBCREATE(), that can create a database file from the structure array.
* By default, DBSTRUCT() operates on the currently selected work area. It
* will operate on an unselected work area if you specify it as part of an
* aliased expression as shown below.
* Note, a header file, Dbstruct.ch, located in \HARBOUR\INCLUDE contains
* a series of manifest constants for each field attribute.
*
* $EXAMPLES$
* This example opens two database files then creates an array
* containing the database structure using DBSTRUCT() within an aliased
* expression. The field names are then listed using AEVAL():
* #include "Dbstruct.ch"
* //
* LOCAL aStruct
* USE Customer NEW
* USE Invoices NEW
* //
* aStruct := Customer->(DBSTRUCT())
* AEVAL( aStruct, {|aField| QOUT(aField[DBS_NAME])} )
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* AFIELDS()
* $INCLUDE$
* DbStruct.ch
* $END$
*/
HARBOUR HB_DBSTRUCT( void )
{
PHB_ITEM pItem, pData;
USHORT uiFields, uiCount;
hb_arrayNew( &hb_stack.Return, 0 );
if( pCurrArea )
{
SELF_FIELDCOUNT( ( AREAP ) pCurrArea->pArea, &uiFields );
pData = hb_itemNew( NULL );
pItem = hb_itemNew( NULL );
for( uiCount = 1; uiCount <= uiFields; uiCount++ )
{
hb_arrayNew( pItem, 4 );
SELF_FIELDINFO( ( AREAP ) pCurrArea->pArea, uiCount, DBS_NAME, pData );
hb_arraySet( pItem, 1, pData );
SELF_FIELDINFO( ( AREAP ) pCurrArea->pArea, uiCount, DBS_TYPE, pData );
hb_arraySet( pItem, 2, pData );
SELF_FIELDINFO( ( AREAP ) pCurrArea->pArea, uiCount, DBS_LEN, pData );
hb_arraySet( pItem, 3, pData );
SELF_FIELDINFO( ( AREAP ) pCurrArea->pArea, uiCount, DBS_DEC, pData );
hb_arraySet( pItem, 4, pData );
hb_arrayAdd( &hb_stack.Return, pItem );
}
hb_itemRelease( pItem );
hb_itemRelease( pData );
}
}
HARBOUR HB_DBTABLEEXT( void )
{
LPRDDNODE pRddNode;
AREAP pTempArea;
USHORT uiSize, uiRddID;
PHB_ITEM pItem;
if( !pCurrArea )
{
hb_rddCheck();
uiRddID = 0;
pRddNode = hb_rddFindNode( szDefDriver, &uiRddID );
if( !pRddNode )
{
hb_retc( "" );
return;
}
uiSize = sizeof( AREA ); /* Default Size Area */
pTempArea = ( AREAP ) hb_xgrab( uiSize );
memset( pTempArea, 0, uiSize );
pTempArea->lprfsHost = &pRddNode->pTable;
/* Need more space? */
SELF_STRUCTSIZE( ( AREAP ) pTempArea, &uiSize );
if( uiSize > sizeof( AREA ) ) /* Size of Area changed */
pTempArea = ( AREAP ) hb_xrealloc( pTempArea, uiSize );
pRddNode->uiAreaSize = uiSize; /* Update the size of WorkArea */
pTempArea->rddID = uiRddID;
if( SELF_NEW( ( AREAP ) pTempArea ) == FAILURE )
hb_retc( "" );
else
{
pItem = hb_itemPutC( NULL, "" );
SELF_INFO( ( AREAP ) pTempArea, DBI_TABLEEXT, pItem );
hb_retc( pItem->item.asString.value );
hb_itemRelease( pItem );
SELF_RELEASE( ( AREAP ) pTempArea );
}
hb_xfree( pTempArea );
}
else
{
pItem = hb_itemPutC( NULL, "" );
SELF_INFO( ( AREAP ) pCurrArea->pArea, DBI_TABLEEXT, pItem );
hb_retc( pItem->item.asString.value );
hb_itemRelease( pItem );
}
}
/* $DOC$
* $FUNCNAME$
* DBUNLOCK()
* $CATEGORY$
* Data Base
* $ONELINER$
* Release all locks for the current work area
* $SYNTAX$
* DBUNLOCK() --> NIL
* $ARGUMENTS$
*
* $RETURNS$
* DBUNLOCK() always returns NIL.
* $DESCRIPTION$
* DBUNLOCK() releases any record or file locks obtained by the current
* process for the current work area. DBUNLOCK() is only meaningful on a
* shared database in a network environment.
* DBUNLOCK() performs the same function as the standard UNLOCK command.
* For more information, refer to the UNLOCK command.
* Notes
* Network environment: Releasing locks may cause updates to the
* database to become visible to other processes.
*
* $EXAMPLES$
* The following example illustrates a basic use of the
* DBUNLOCK() function:
* cLast := "Winston"
* USE Sales SHARED NEW VIA "DBFNTX"
* DBSETINDEX( "LASTNAME" )
* //
* IF ( Sales->(DBSEEK(cLast)) )
* IF Sales->( RLOCK() )
* Sales->( DBDELETE() )
* ? "Record deleted: ", Sales( DELETED() )
* Sales->( DBUNLOCK() )
* ELSE
* ? "Unable to lock record..."
* ENDIF
* ELSE
* ? "Not found"
* ENDIF
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBUNLOCKALL(),FLOCK(),RLOCK()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBUNLOCK( void )
{
if( pCurrArea )
SELF_RAWLOCK( ( AREAP ) pCurrArea->pArea, FILE_UNLOCK, 0 );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "DBUNLOCK" );
}
/* $DOC$
* $FUNCNAME$
* DBUNLOCKALL()
* $CATEGORY$
* Data Base
* $ONELINER$
* Release all locks for all work areas
* $SYNTAX$
* DBUNLOCKALL() --> NIL
* $ARGUMENTS$
*
* $RETURNS$
* DBUNLOCKALL() always returns NIL.
* $DESCRIPTION$
* DBUNLOCKALL() releases any record or file locks obtained by the current
* process for any work area. DBUNLOCKALL() is only meaningful on a shared
* database in a network environment. It is equivalent to calling
* DBUNLOCK() on every occupied work area.
* DBUNLOCKALL() performs the same function as the UNLOCK ALL command. For
* more information, refer to the UNLOCK ALL command.
*
* $EXAMPLES$
* The following example marks a record for deletion if an
* RLOCK() attempt is successful, then clears all locks in all work
* areas:
* cLast := "Winston"
* USE Sales SHARED NEW VIA "DBFNTX"
* DBSETINDEX( "SALEFNAM" )
* DBSETINDEX( "SALELNAM" )
* //
* USE Colls SHARED NEW VIA "DBFNTX"
* DBSETINDEX( "COLLFNAM" )
* DBSETINDEX( "COLLLNAM" )
* //
* DBSELECTAREA( "Sales" ) * // select "Sales" work area
* //
* IF ( Colls->(DBSEEK(cLast)) )
* IF Colls->( DELETED() )
* ? "Record deleted: ", Colls->( DELETED() )
* IF Colls->( RLOCK() )
* Colls->( DBRECALL() )
* ? "Record recalled..."
* ENDIF
* ENDIF
* ELSE
* ? "Not found"
* DBUNLOCKALL() // remove all locks in
* ENDIF // all work areas
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBUNLOCK(),FLOCK(),RLOCK()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBUNLOCKALL( void )
{
LPAREANODE pTempArea;
pTempArea = pWorkAreas;
while( pTempArea )
{
SELF_RAWLOCK( ( AREAP ) pTempArea->pArea, FILE_UNLOCK, 0 );
pTempArea = pTempArea->pNext;
}
}
/* $DOC$
* $FUNCNAME$
* DBUSEAREA()
* $CATEGORY$
* Data Base
* $ONELINER$
* Use a database file in a work area
* $SYNTAX$
* DBUSEAREA( [<lNewArea>], [<cDriver>], <cName>, [<xcAlias>],
* [<lShared>], [<lReadonly>]) --> NIL
* $ARGUMENTS$
* <lNewArea> is an optional logical value. A value of true (.T.)
* selects the lowest numbered unoccupied work area as the current work
* area before the use operation. If <lNewArea> is false (.F.) or omitted,
* the current work area is used; if the work area is occupied, it is
* closed first.
* <cDriver> is an optional character value. If present, it specifies
* the name of the database driver which will service the work area. If
* <cDriver> is omitted, the current default driver is used (see note
* below).
* <cName> specifies the name of the database (.dbf) file to be opened.
* <xcAlias> is an optional character value. If present, it specifies
* the alias to be associated with the work area. The alias must
* constitute a valid HARBOUR identifier. A valid <xcAlias> may be any
* legal identifier (i.e., it must begin with an alphabetic character and
* may contain numeric or alphabetic characters and the underscore).
* Within a single application, HARBOUR will not accept duplicate
* aliases. If <xcAlias> is omitted, a default alias is constructed from
* <cName>.
* <lShared> is an optional logical value. If present, it specifies
* whether the database (.dbf) file should be accessible to other processes
* on a network. A value of true (.T.) specifies that other processes
* should be allowed access; a value of false (.F.) specifies that the
* current process is to have exclusive access. If <lShared> is omitted,
* the current global _SET_EXCLUSIVE setting determines whether shared
* access is allowed.
* <lReadonly> is an optional logical value that specifies whether
* updates to the work area are prohibited. A value of true (.T.)
* prohibits updates; a value of false (.F.) permits updates. A value of
* true (.T.) also permits read-only access to the specified database
* (.dbf) file. If <lReadonly> is omitted, the default value is false
* (.F.).
* $RETURNS$
* DBUSEAREA() always returns NIL.
* $DESCRIPTION$
* DBUSEAREA() associates the specified database (.dbf) file with the
* current work area.
* DBUSEAREA() performs the same function as the standard USE command. For
* more information, refer to the USE command.
* Notes
* Current driver: If no driver is specified in the call to
* DBUSEAREA() the default driver is used. If more than one driver is
* available to the application, the default driver is the driver
* specified in the most recent call to DBSETDRIVER(). If DBSETDRIVER()
* has not been called, the name of the default driver is undetermined.
*
* $EXAMPLES$
* This example is a typical use of the DBUSEAREA() function:
* DBUSEAREA(.T., "DBFNDX", "Employees")
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBCLOSEAREA(),DBSETDRIVER(),SELECT(),SET()
*
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DBUSEAREA( void )
{
char * szDriver, * szFileName;
LPRDDNODE pRddNode;
LPAREANODE pAreaNode;
USHORT uiSize, uiRddID, uiLen;
ULONG ulLen;
DBOPENINFO pInfo;
PHB_FNAME pFileName;
PHB_ITEM pFileExt;
char szDriverBuffer[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH + 1 ];
char szAlias[ HARBOUR_MAX_RDD_ALIAS_LENGTH + 1 ];
bNetError = FALSE;
if( hb_parl( 1 ) )
hb_rddSelectFirstAvailable();
else if( pCurrArea ) /* If current WorkArea is in use then close it */
{
SELF_CLOSE( ( AREAP ) pCurrArea->pArea );
SELF_RELEASE( ( AREAP ) pCurrArea->pArea );
if( pWorkAreas == pCurrArea )
{
pWorkAreas = pCurrArea->pNext;
if( pWorkAreas )
pWorkAreas->pPrev = NULL;
}
else
{
if( pCurrArea->pPrev )
pCurrArea->pPrev->pNext = pCurrArea->pNext;
if( pCurrArea->pNext )
pCurrArea->pNext->pPrev = pCurrArea->pPrev;
}
hb_xfree( pCurrArea->pArea );
hb_xfree( pCurrArea );
pCurrArea = NULL;
}
hb_rddCheck();
uiLen = hb_parclen( 2 );
if( uiLen > 0 )
{
if( uiLen > HARBOUR_MAX_RDD_DRIVERNAME_LENGTH )
uiLen = HARBOUR_MAX_RDD_DRIVERNAME_LENGTH;
hb_strncpyUpper( szDriverBuffer, hb_parc( 2 ), uiLen );
szDriver = szDriverBuffer;
}
else
szDriver = szDefDriver;
uiRddID = 0;
pRddNode = hb_rddFindNode( szDriver, &uiRddID );
if( !pRddNode )
{
hb_errRT_DBCMD( EG_ARG, 1015, NULL, "DBUSEAREA" );
return;
}
szFileName = hb_parc( 3 );
if( strlen( szFileName ) == 0 )
{
hb_errRT_DBCMD( EG_ARG, 1005, NULL, "DBUSEAREA" );
return;
}
pFileName = hb_fsFNameSplit( szFileName );
strncpy( szAlias, hb_parc( 4 ), HARBOUR_MAX_RDD_ALIAS_LENGTH );
ulLen = strlen( szAlias );
if( ulLen == 0 )
strncpy( szAlias, pFileName->szName, HARBOUR_MAX_RDD_ALIAS_LENGTH );
else if( ulLen == 1 )
{
/* Alias with a single letter. Only are valid 'L' and > 'M' */
if( toupper( szAlias[ 0 ] ) < 'N' && toupper( szAlias[ 0 ] ) != 'L' )
{
hb_xfree( pFileName );
hb_errRT_DBCMD( EG_DUPALIAS, 1011, NULL, "DBUSEAREA" );
return;
}
}
/* Create a new WorkArea node */
pCurrArea = ( LPAREANODE ) hb_xgrab( sizeof( AREANODE ) );
if( pRddNode->uiAreaSize == 0 ) /* Calculate the size of WorkArea */
{
uiSize = sizeof( AREA ); /* Default Size Area */
pCurrArea->pArea = ( AREAP ) hb_xgrab( uiSize );
memset( pCurrArea->pArea, 0, uiSize );
( ( AREAP ) pCurrArea->pArea )->lprfsHost = &pRddNode->pTable;
/* Need more space? */
SELF_STRUCTSIZE( ( AREAP ) pCurrArea->pArea, &uiSize );
if( uiSize > sizeof( AREA ) ) /* Size of Area changed */
pCurrArea->pArea = ( AREAP ) hb_xrealloc( pCurrArea->pArea, uiSize );
pRddNode->uiAreaSize = uiSize; /* Update the size of WorkArea */
}
else
{
pCurrArea->pArea = ( AREAP ) hb_xgrab( pRddNode->uiAreaSize );
memset( pCurrArea->pArea, 0, pRddNode->uiAreaSize );
( ( AREAP ) pCurrArea->pArea )->lprfsHost = &pRddNode->pTable;
}
( ( AREAP ) pCurrArea->pArea )->rddID = uiRddID;
pCurrArea->pPrev = NULL;
pCurrArea->pNext = NULL;
SELF_NEW( ( AREAP ) pCurrArea->pArea );
szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 );
strcpy( szFileName, hb_parc( 3 ) );
if( !pFileName->szExtension )
{
pFileExt = hb_itemPutC( NULL, "" );
SELF_INFO( ( AREAP ) pCurrArea->pArea, DBI_TABLEEXT, pFileExt );
strcat( szFileName, pFileExt->item.asString.value );
hb_itemRelease( pFileExt );
}
hb_xfree( pFileName );
pInfo.uiArea = uiCurrArea;
pInfo.abName = ( BYTE * ) szFileName;
pInfo.atomAlias = ( BYTE * ) szAlias;
pInfo.fShared = ISLOG( 5 ) ? hb_parl( 5 ) : !hb_set.HB_SET_EXCLUSIVE;
pInfo.fReadonly = ISLOG( 6 ) ? hb_parl( 6 ) : FALSE;
( ( AREAP ) pCurrArea->pArea )->uiArea = uiCurrArea;
/* Insert the new WorkArea node */
if( !pWorkAreas )
pWorkAreas = pCurrArea; /* The new WorkArea node is the first */
else
{
pAreaNode = pWorkAreas;
while( pAreaNode )
{
if( ( ( AREAP ) pAreaNode->pArea )->uiArea > uiCurrArea )
{
/* Insert the new WorkArea node */
pCurrArea->pPrev = pAreaNode->pPrev;
pCurrArea->pNext = pAreaNode;
pAreaNode->pPrev = pCurrArea;
if( pCurrArea->pPrev )
pCurrArea->pPrev->pNext = pCurrArea;
else
pWorkAreas = pCurrArea;
break;
}
if( pAreaNode->pNext )
pAreaNode = pAreaNode->pNext;
else
{
/* Append the new WorkArea node */
pAreaNode->pNext = pCurrArea;
pCurrArea->pPrev = pAreaNode;
break;
}
}
}
( ( AREAP ) pCurrArea->pArea )->lpDataInfo->szFileName = szFileName;
if( SELF_OPEN( ( AREAP ) pCurrArea->pArea, &pInfo ) == FAILURE )
{
SELF_RELEASE( ( AREAP ) pCurrArea->pArea );
if( pWorkAreas == pCurrArea )
{
pWorkAreas = pCurrArea->pNext;
if( pWorkAreas )
pWorkAreas->pPrev = NULL;
}
else
{
if( pCurrArea->pPrev )
pCurrArea->pPrev->pNext = pCurrArea->pNext;
if( pCurrArea->pNext )
pCurrArea->pNext->pPrev = pCurrArea->pPrev;
}
hb_xfree( pCurrArea->pArea );
hb_xfree( pCurrArea );
pCurrArea = NULL;
return;
}
SELF_RECCOUNT( ( AREAP ) pCurrArea->pArea, &ulLen );
( ( AREAP ) pCurrArea->pArea )->lpExtendInfo->ulRecCount = ulLen;
}
/* $DOC$
* $FUNCNAME$
* __DBZAP()
* $CATEGORY$
* Data Base
* $ONELINER$
* Remove all records from the current database file
* $SYNTAX$
* __DbZap() -> NIL
* $ARGUMENTS$
*
* $RETURNS$
* __DbZap() will always return nil
* $DESCRIPTION$
* __DbZap*( is a database command that permanently removes all records from
* files open in the current work area. This includes the current database
* file, index files, and associated memo file. Disk space previously
* occupied by the ZAPped files is released to the operating system.
* __DbZap() performs the same operation as DELETE ALL followed by PACK but is
* almost instantaneous.
*
* To ZAP in a network environment, the current database file must be USEd
* EXCLUSIVEly.
*
* $EXAMPLES$
* This example demonstrates a typical ZAP operation in a network
* environment:
*
* USE Sales EXCLUSIVE NEW
* IF !NETERR()
* SET INDEX TO Sales, Branch, Salesman
* __dbZAP()
* CLOSE Sales
* ELSE
* ? "Zap operation failed"
* BREAK
* ENDIF
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
*
* $INCLUDE$
*
* $END$
*/
/* $DOC$
* $COMMANDNAME$
* ZAP
* $CATEGORY$
* Command
* $ONELINER$
* Remove all records from the current database file
* $SYNTAX$
* ZAP
* $ARGUMENTS$
*
* $RETURNS$
*
* $DESCRIPTION$
* ZAP is a database command that permanently removes all records from
* files open in the current work area. This includes the current database
* file, index files, and associated memo file. Disk space previously
* occupied by the ZAPped files is released to the operating system. ZAP
* performs the same operation as DELETE ALL followed by PACK but is almost
* instantaneous.
*
* To ZAP in a network environment, the current database file must be USEd
* EXCLUSIVEly.
*
* $EXAMPLES$
* This example demonstrates a typical ZAP operation in a network
* environment:
*
* USE Sales EXCLUSIVE NEW
* IF !NETERR()
* SET INDEX TO Sales, Branch, Salesman
* ZAP
* CLOSE Sales
* ELSE
* ? "Zap operation failed"
* BREAK
* ENDIF
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
*
* $INCLUDE$
*
* $END$
*/
HARBOUR HB___DBZAP( void )
{
if( pCurrArea )
SELF_ZAP( ( AREAP ) pCurrArea->pArea );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "__DBZAP" );
}
/* $DOC$
* $FUNCNAME$
* DELETED()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the deleted status of the current record
* $SYNTAX$
* DELETED() --> lDeleted
* $ARGUMENTS$
*
* $RETURNS$
* DELETED() returns true (.T.) if the current record is marked for
* deletion; otherwise, it returns false (.F.). If there is no database
* file in USE in the current work area, DELETED() returns false (.F.).
* $DESCRIPTION$
* DELETED() is a database function that determines if the current record
* in the active work area is marked for deletion. Since each work area
* with an open database file can have a current record, each work area has
* its own DELETED() value.
* By default, DELETED() operates on the currently selected work area. It
* will operate on an unselected work area if you specify it as part of an
* aliased expression (see example below).
* In applications, DELETED() is generally used to query the deleted status
* as a part of record processing conditions, or to display the deleted
* status as a part of screens and reports.
* $EXAMPLES$
* This example uses DELETED() in the current and in an
* unselected work area:
* USE Customer NEW
* USE Sales NEW
* ? DELETED() // Result: .F.
* DELETE
* ? DELETED() // Result: .T.
* ? Customer->(DELETED()) // Result: .F.
* This example uses DELETED() to display a record's deleted
* status in screens and reports:
* @ 1, 65 SAY IF(DELETED(), "Inactive", "Active")
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
*
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_DELETED( void )
{
BOOL bDeleted = FALSE;
if( pCurrArea )
SELF_DELETED( ( AREAP ) pCurrArea->pArea, &bDeleted );
hb_retl( bDeleted );
}
/* $DOC$
* $FUNCNAME$
* EOF()
* $CATEGORY$
* DATA BASE
* $ONELINER$
* Determine when end of file is encountered
* $SYNTAX$
* EOF() --> <lEnd>
* $ARGUMENTS$
*
* $RETURNS$
*
* EOF() returns true (.T.) when an attempt is made to move the record
* pointer beyond the last logical record in a database file; otherwise, it
* returns false (.F.). If there is no database file open in the current
* work area, EOF() returns false (.F.). If the current database file
* contains no records, EOF() returns true (.T.).
* $DESCRIPTION$
* EOF() is a database function used to test for an end of file boundary
* condition when the record pointer is moving forward through a database
* file. Any command that can move the record pointer can set EOF().
* The most typical application is as a part of the <lCondition> argument
* of a DO WHILE construct that sequentially processes records in a
* database file. Here <lCondition> would include a test for .NOT. EOF(),
* forcing the DO WHILE loop to terminate when EOF() returns true (.T.).
* EOF() and FOUND() are often used interchangeably to test whether a SEEK,
* FIND, or LOCATE command failed. With these commands, however, FOUND()
* is preferred.
* When EOF() returns true (.T.), the record pointer is positioned at
* LASTREC() + 1 regardless of whether there is an active SET FILTER or SET
* DELETED is ON. Further attempts to move the record pointer forward
* return the same result without error. Once EOF() is set to true (.T.),
* it retains its value until there is another attempt to move the record
* pointer.
* By default, EOF() operates on the currently selected work area. It can
* be made to operate on an unselected work area by specifying it within an
* aliased expression (see example below).
* $EXAMPLES$
* This example demonstrates EOF() by deliberately moving the
* record pointer beyond the last record:
* USE Sales
* GO BOTTOM
* ? EOF() // Result: .F.
* SKIP
* ? EOF() // Result: .T.
* This example uses aliased expressions to query the value of
* EOF() in unselected work areas:
* USE Sales NEW
* USE Customer NEW
* ? Sales->(EOF())
* ? Customer->(EOF())
* This example illustrates how EOF() can be used as part of a
* condition for sequential database file operations:
* USE Sales INDEX CustNum NEW
* DO WHILE !EOF()
* nOldCust := Sales->CustNum
* nTotalAmount := 0
* DO WHILE nOldCust = Sales->CustNum .AND. (!EOF())
* ? Sales->CustNum, Sales->Description, ;
* Sales->SaleAmount
* nTotalAmount += Sales->SaleAmount
* SKIP
* ENDDO
* ? "Total amount: ", nTotalAmount
* ENDDO
* $TESTS$
* $STATUS$
* R
* $COMPLIANCE$
* EOF() is fully CA-Clipper compliant.
* $SEEALSO$
* BOF(),FOUND(),LASTREC()
* $END$
*/
HARBOUR HB_EOF( void )
{
BOOL bEof = TRUE;
if( pCurrArea )
SELF_EOF( ( AREAP ) pCurrArea->pArea, &bEof );
hb_retl( bEof );
}
/* $DOC$
* $FUNCNAME$
* FCOUNT()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the number of fields in the current (.dbf) file
* $SYNTAX$
* FCOUNT() --> nFields
* $ARGUMENTS$
*
* $RETURNS$
* FCOUNT() returns the number of fields in the database file in the
* current work area as an integer numeric value. If there is no database
* file open, FCOUNT() returns zero.
* $DESCRIPTION$
* FCOUNT() is a database function. It is useful in applications
* containing data-independent programs that can operate on any database
* file. These include generalized import/export and reporting programs.
* Typically, you use FCOUNT() to establish the upper limit of a FOR...NEXT
* or DO WHILE loop that processes a single field at a time.
* By default, FCOUNT() operates on the currently selected work area.
* $EXAMPLES$
* This example illustrates FCOUNT(), returning the number of
* fields in the current and an unselected work area:
* USE Sales NEW
* USE Customer NEW
* ? FCOUNT() // Result: 5
* ? Sales->(FCOUNT()) // Result: 8
* This example uses FCOUNT() to DECLARE an array with field
* information:
* LOCAL aFields := ARRAY(FCOUNT())
* AFIELDS(aFields)
* This example uses FCOUNT() as the upper boundary of a FOR loop
* that processes the list of current work area fields:
* LOCAL nField
* USE Sales NEW
* FOR nField := 1 TO FCOUNT()
* ? FIELD(nField)
* NEXT
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* FIELDNAME(),TYPE()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_FCOUNT( void )
{
USHORT uiFields = 0;
if( pCurrArea )
SELF_FIELDCOUNT( ( AREAP ) pCurrArea->pArea, &uiFields );
hb_retni( uiFields );
}
/* $DOC$
* $FUNCNAME$
* FIELDGET()
* $CATEGORY$
* Data Base
* $ONELINER$
* Retrieve the value of a field variable
* $SYNTAX$
* FIELDGET(<nField>) --> ValueField
* $ARGUMENTS$
* <nField> is the ordinal position of the field in the record
* structure for the current work area.
* $RETURNS$
* FIELDGET() returns the value of the specified field. If <nField> does
* not correspond to the position of any field in the current database
* file, FIELDGET() returns NIL.
* $DESCRIPTION$
* FIELDGET() is a database function that retrieves the value of a field
* using its position within the database file structure rather than its
* field name. Within generic database service functions this allows,
* among other things, the retrieval of field values without use of the
* macro operator.
* $EXAMPLES$
* This example compares FIELDGET() to functionally equivalent
* code that uses the macro operator to retrieve the value of a field:
* LOCAL nField := 1, FName, FVal
* USE Customer NEW
* //
* // Using macro operator
* FName := FIELD( nField ) // Get field name
* FVal := &FName // Get field value
* // Using FIELDGET()
* FVal := FIELDGET( nField ) // Get field value
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* FIELDPUT()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_FIELDGET( void )
{
PHB_ITEM pItem;
USHORT uiField;
pItem = hb_itemNew( NULL );
uiField = hb_parni( 1 );
if( pCurrArea && uiField )
SELF_GETVALUE( ( AREAP ) pCurrArea->pArea, uiField, pItem );
hb_itemReturn( pItem );
hb_itemRelease( pItem );
}
/* $DOC$
* $FUNCNAME$
* FIELDNAME()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return a field name from the current (.dbf) file
* $SYNTAX$
* FIELDNAME/FIELD(<nPosition>) --> cFieldName
* $ARGUMENTS$
* <nPosition> is the position of a field in the database file
* structure.
* $RETURNS$
* FIELDNAME() returns the name of the specified field as a character
* string. If <nPosition> does not correspond to an existing field in the
* current database file or if no database file is open in the current work
* area, FIELDNAME() returns a null string ("").
* $DESCRIPTION$
* FIELDNAME() is a database function that returns a field name using an
* index to the position of the field name in the database structure. Use
* it in data-independent applications where the field name is unknown. If
* information for more than one field is required, use AFIELDS() to create
* an array of field information or COPY STRUCTURE EXTENDED to create a
* database of field information.
* If you need additional database file structure information, use TYPE()
* and LEN(). To obtain the number of decimal places for a numeric field,
* use the following expression:
* LEN(SUBSTR(STR(<idField>), RAT(".", ;
* STR(<idField>)) + 1))
* By default, FIELDNAME() operates on the currently selected work area as
* shown in the example below.
*
* $EXAMPLES$
* These examples illustrate FIELDNAME() used with several other
* functions:
* USE Sales
* ? FIELDNAME(1) // Result: BRANCH
* ? FCOUNT() // Result: 5
* ? LEN(FIELDNAME(0)) // Result: 0
* ? LEN(FIELDNAME(40)) // Result: 0
* This example uses FIELDNAME() to list the name and type of
* each field in Customer.dbf:
* USE Customer NEW
* FOR nField := 1 TO FCOUNT()
* ? PADR(FIELDNAME(nField), 10),;
* VALTYPE(&(FIELDNAME(nField)))
* NEXT
* This example accesses fields in unselected work areas using
* aliased expressions:
* USE Sales NEW
* USE Customer NEW
* USE Invoices NEW
* //
* ? Sales->(FIELDNAME(1)) // Result: SALENUM
* ? Customer->(FIELDNAME(1)) // Result: CUSTNUM
*
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBSTRUCT() FCOUNT() LEN() misc.ngo:VALTYPE()
*
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_FIELDNAME( void )
{
USHORT uiFields, uiIndex;
char * szName;
if( pCurrArea )
{
uiIndex = hb_parni( 1 );
if( SELF_FIELDCOUNT( ( AREAP ) pCurrArea->pArea, &uiFields ) == SUCCESS )
{
if( uiIndex > 0 && uiIndex <= uiFields )
{
szName = ( char * ) hb_xgrab( HARBOUR_MAX_RDD_FIELDNAME_LENGTH + 1 );
SELF_FIELDNAME( ( AREAP ) pCurrArea->pArea, hb_parni( 1 ), szName );
hb_retc( szName );
hb_xfree( szName );
return;
}
hb_errRT_DBCMD( EG_ARG, 1009, NULL, "FIELDNAME" );
}
}
hb_retc( "" );
}
/* $DOC$
* $FUNCNAME$
* FIELDPOS()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the position of a field in a work area
* $SYNTAX$
* FIELDPOS(<cFieldName>) --> nFieldPos
* $ARGUMENTS$
* <cFieldName> is the name of a field in the current or specified work
* area.
* $RETURNS$
* FIELDPOS() returns the position of the specified field within the list
* of fields associated with the current or specified work area. If the
* current work area has no field with the specified name, FIELDPOS()
* returns zero.
* $DESCRIPTION$
* FIELDPOS() is a database function that is the inverse of the FIELDNAME()
* function. FIELDPOS() is most often used with the FIELDPUT() and
* FIELDGET() functions.
* FIELDPOS() return the names of fields in any unselected work area by
* referring to the function using an aliased expression. See the example
* below.
* $EXAMPLES$
* This example demonstrates a typical specification of the
* FIELDPOS() function:
* USE Customer NEW
* ? FIELDPOS("Name") * * * * // Result: 1
* ? FIELDGET(FIELDPOS("Name")) * * // Result: Kate
* This example uses FIELDPOS() to return the position of a
* specified field in a unselected work area:
* USE Customer NEW
* USE Invoices NEW
* ? Customer->(FIELDPOS("Name")) * // Result: 1
* ? Customer->(FIELDGET(FIELDPOS("Name"))) // Result: Kate
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* FIELDGET(),FIELDPUT()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_FIELDPOS( void )
{
USHORT uiCount;
LPFIELD pField;
if( pCurrArea )
{
char szName[ HARBOUR_MAX_RDD_FIELDNAME_LENGTH ];
hb_strncpyUpper( szName, hb_parc( 1 ), hb_parclen( 1 ) );
uiCount = 0;
pField = ( ( AREAP ) pCurrArea->pArea )->lpFields;
while( pField )
{
++uiCount;
if( strcmp( szName, ( ( PHB_DYNS ) pField->sym )->pSymbol->szName ) == 0 )
{
hb_retni( uiCount );
return;
}
pField = pField->lpfNext;
}
}
hb_retni( 0 );
}
/* $DOC$
* $FUNCNAME$
* FIELDPUT()
* $CATEGORY$
* Data Base
* $ONELINER$
* Set the value of a field variable
* $SYNTAX$
* FIELDPUT(<nField>, <expAssign>) --> ValueAssigned
* $ARGUMENTS$
* <nField> is the ordinal position of the field in the current
* database file.
* <expAssign> is the value to assign to the given field. The data
* type of this expression must match the data type of the designated field
* variable.
* $RETURNS$
* FIELDPUT() returns the value assigned to the designated field. If
* <nField> does not correspond to the position of any field in the current
* database file, FIELDPUT() returns NIL.
* $DESCRIPTION$
* FIELDPUT() is a database function that assigns <expAssign> to the field
* at ordinal position <nField> in the current work area. This function
* allows you to set the value of a field using its position within the
* database file structure rather than its field name. Within generic
* database service functions this allows, among other things, the setting
* of field values without use of the macro operator.
* $EXAMPLES$
* This example compares FIELDPUT() to functionally equivalent
* code that uses the macro operator to set the value of a field:
* // Using macro operator
* FName := FIELD(nField) // Get field name
* FIELD->&FName := FVal // Set field value
* // Using FIELDPUT()
* FIELDPUT(nField, FVal) // Set field value
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* FIELDGET()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_FIELDPUT( void )
{
USHORT uiIndex;
PHB_ITEM pItem;
uiIndex = hb_parni( 1 );
if( pCurrArea && uiIndex )
{
pItem = hb_param( 2, IT_ANY );
if( SELF_PUTVALUE( ( AREAP ) pCurrArea->pArea, uiIndex, pItem ) == SUCCESS )
{
hb_itemReturn( pItem );
return;
}
}
hb_ret();
}
/* $DOC$
* $FUNCNAME$
* FLOCK()
* $CATEGORY$
* Data Base
* $ONELINER$
* Lock an open and shared database file
* $SYNTAX$
* FLOCK() --> lSuccess
* $ARGUMENTS$
*
* $RETURNS$
* FLOCK() returns true (.T.) if an attempt to lock a database file in USE
* in the current work area succeeds; otherwise, it returns false (.F.).
* For more information on file locking, refer to the Network Programming
* chapter in the Programming and Utilities guide.
*
* $DESCRIPTION$
* FLOCK() is a database function used in network environments to lock an
* open and shared database file, preventing other users from updating the
* file until the lock is released. Records in the locked file are
* accessible for read-only operations.
*
* FLOCK() is related to USE...EXCLUSIVE and RLOCK(). USE...EXCLUSIVE
* opens a database file so that no other user can open the same file at
* the same time and is the most restrictive locking mechanism in
* HARBOUR. RLOCK() is the least restrictive and attempts to place an
* update lock on a shared record, precluding other users from updating the
* current record. FLOCK() falls in the middle.
*
* FLOCK() is used for operations that access the entire database file.
* Typically, these are commands that update the file with a scope or a
* condition such as DELETE or REPLACE ALL. The following is a list of
* such commands:
*
* Commands that require an FLOCK()
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* Command Mode
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* APPEND FROM FLOCK() or USE...EXCLUSIVE
* DELETE (multiple records) FLOCK() or USE...EXCLUSIVE
* RECALL (multiple records) FLOCK() or USE...EXCLUSIVE
* REPLACE (multiple records) FLOCK() or USE...EXCLUSIVE
* UPDATE ON FLOCK() or USE...EXCLUSIVE
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* For each invocation of FLOCK(), there is one attempt to lock the
* database file, and the result is returned as a logical value. A file
* lock fails if another user currently has a file or record lock for the
* same database file or EXCLUSIVE USE of the database file. If FLOCK() is
* successful, the file lock remains in place until you UNLOCK, CLOSE the
* DATABASE, or RLOCK().
*
* By default, FLOCK() operates on the currently selected work area as
* shown in the example below.
*
* Notes
*
* SET RELATION: HARBOUR does not automatically lock all work
* areas in the relation chain when you lock the current work area, and
* an UNLOCK has no effect on related work areas.
* $EXAMPLES$
* This example uses FLOCK() for a batch update of prices in
* Inventory.dbf:
*
* USE Inventory NEW
* IF FLOCK()
* REPLACE ALL Inventory->Price WITH ;
* Inventory->Price * 1.1
* ELSE
* ? "File not available"
* ENDIF
*
* This example uses an aliased expression to attempt a file lock
* in an unselected work area:
*
* USE Sales NEW
* USE Customer NEW
* //
* IF !Sales->(FLOCK())
* ? "Sales is in use by another"
* ENDIF
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* RLOCK()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_FLOCK( void )
{
DBLOCKINFO pLockInfo;
pLockInfo.fResult = FALSE;
if( pCurrArea )
{
pLockInfo.itmRecID = 0;
pLockInfo.uiMethod = FILE_LOCK;
SELF_LOCK( ( AREAP ) pCurrArea->pArea, &pLockInfo );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "FLOCK" );
hb_retl( pLockInfo.fResult );
}
/* $DOC$
* $FUNCNAME$
* FOUND()
* $CATEGORY$
* Data Base
* $ONELINER$
* Determine if the previous search operation succeeded
* $SYNTAX$
* FOUND() --> lSuccess
* $ARGUMENTS$
*
* $RETURNS$
* FOUND() returns true (.T.) if the last search command was successful;
* otherwise, it returns false (.F.).
*
* $DESCRIPTION$
* FOUND() is a database function that determines whether a search
* operation (i.e., FIND, LOCATE, CONTINUE, SEEK, or SET RELATION)
* succeeded. When any of these commands are executed, FOUND() is set to
* true (.T.) if there is a match; otherwise, it is set to false (.F.).
*
* If the search command is LOCATE or CONTINUE, a match is the next record
* meeting the scope and condition. If the search command is FIND, SEEK or
* SET RELATION, a match is the first key in the controlling index that
* equals the search argument. If the key value equals the search
* argument, FOUND() is true (.T.); otherwise, it is false (.F.).
*
* The value of FOUND() is retained until another record movement command
* is executed. Unless the command is another search command, FOUND() is
* automatically set to false (.F.).
*
* Each work area has a FOUND() value. This means that if one work area
* has a RELATION set to a child work area, querying FOUND() in the child
* returns true (.T.) if there is a match.
*
* By default, FOUND() operates on the currently selected work area. It
* can be made to operate on an unselected work area by specifying it
* within an aliased expression (see example below).
*
* FOUND() will return false (.F.) if there is no database open in the
* current work area.
* $EXAMPLES$
* This example illustrates the behavior of FOUND() after a
* record movement command:
*
* USE Sales INDEX Sales
* ? INDEXKEY(0) // Result: SALESMAN
* SEEK "1000"
* ? FOUND() // Result: .F.
* SEEK "100"
* ? FOUND() // Result: .T.
* SKIP
* ? FOUND() // Result: .F.
*
* This example tests a FOUND() value in an unselected work area
* using an aliased expression:
*
* USE Sales INDEX Sales NEW
* USE Customer INDEX Customer NEW
* SET RELATION TO CustNum INTO Sales
* //
* SEEK "Smith"
* ? FOUND(), Sales->(FOUND())
*
* This code fragment processes all Customer records with the key
* value "Smith" using FOUND() to determine when the key value changes:
*
* USE Customer INDEX Customer NEW
* SEEK "Smith"
* DO WHILE FOUND()
* .
* . <statements>
* .
* SKIP
* LOCATE REST WHILE Name == "Smith"
* ENDDO
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* EOF()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_FOUND( void )
{
BOOL bFound = FALSE;
if( pCurrArea )
SELF_FOUND( ( AREAP ) pCurrArea->pArea, &bFound );
hb_retl( bFound );
}
/* $DOC$
* $FUNCNAME$
* HEADER()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the current database file header length
* $SYNTAX$
* HEADER() --> nBytes
* $ARGUMENTS$
*
* $RETURNS$
HEADER() returns the number of bytes in the header of the current
database file as an integer numeric value. If no database file is in
use, HEADER() returns a zero (0).
* $DESCRIPTION$
HEADER() is a database function that is used with LASTREC(), RECSIZE(),
and DISKSPACE() to create procedures for backing up files.
By default, HEADER() operates on the currently selected work area. It
will operate on an unselected work area if you specify it as part of an
aliased expression (see example below).
* $EXAMPLES$
This example determines the header size of the Sales.dbf:
USE Sales NEW
? HEADER() // Result: 258
This example defines a pseudofunction, DbfSize(), that uses
HEADER() with RECSIZE() and LASTREC() to calculate the size of the
current database file in bytes:
#define DbfSize() ((RECSIZE() * LASTREC()) + ;
HEADER() + 1)
Later you can use DbfSize() as you would any function:
USE Sales NEW
USE Customer NEW
? DbfSize()
? Sales->(DbfSize())
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DISKSPACE(),LASTREC(),RECSIZE()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_HEADER( void )
{
PHB_ITEM pRecSize;
if( !pCurrArea )
hb_retni( 0 );
else
{
pRecSize = hb_itemNew( NULL );
SELF_INFO( ( AREAP ) pCurrArea->pArea, DBI_GETHEADERSIZE, pRecSize );
hb_itemReturn( pRecSize );
hb_itemRelease( pRecSize );
}
}
/* $DOC$
* $FUNCNAME$
* INDEXORD()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the order position of the controlling index
* $SYNTAX$
* INDEXORD() --> nOrder
* $ARGUMENTS$
*
* $RETURNS$
INDEXORD() returns an integer numeric value. The value returned is
equal to the position of the controlling index in the list of open
indexes for the current work area. A value of zero indicates that there
is no controlling index and records are being accessed in natural order.
If no database file is open, INDEXORD() will also return a zero.
* $DESCRIPTION$
INDEXORD() is a database function that determines the position of the
controlling index in the list of index files opened by the last
USE...INDEX or SET INDEX TO in the current work area. It is often
useful to save the last controlling index so it can be restored later.
By default, INDEXORD() operates on the currently selected work area. It
will operate on an unselected work area if you specify it as part of an
aliased expression (see example below).
* $EXAMPLES$
This example uses INDEXORD() to save the current order. After
changing to a new order, it uses the saved value to restore the
original order:
USE Customer INDEX Name, Serial NEW
nOrder := INDEXORD() // Result: 1
SET ORDER TO 2
? INDEXORD() // Result: 2
SET ORDER TO nOrder
? INDEXORD() // Result: 1
This example uses an aliased expression to determine the order
number of the controlling index in an unselected work area:
USE Sales INDEX Salesman, CustNum NEW
USE Customer INDEX Name, Serial NEW
? Sales->(INDEXORD()) // Result: 1
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* INDEXKEY()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_INDEXORD( void )
{
DBORDERINFO pInfo;
if( pCurrArea )
{
pInfo.itmResult = hb_itemPutNI( NULL, 0 );
SELF_ORDINFO( ( AREAP ) pCurrArea->pArea, DBOI_NUMBER, &pInfo );
hb_retni( hb_itemGetNI( pInfo.itmResult ) );
hb_itemRelease( pInfo.itmResult );
}
else
hb_retni( 0 );
}
/* $DOC$
* $FUNCNAME$
* LASTREC()
* $CATEGORY$
* Data Base
* $ONELINER$
* Determine the number of records in the current (.dbf) file
* $SYNTAX$
* LASTREC() | RECCOUNT()* --> nRecords
* $ARGUMENTS$
*
* $RETURNS$
LASTREC() returns the number of physical records in the current database
file as an integer numeric value. Filtering commands such as SET FILTER
or SET DELETED have no effect on the return value. LASTREC() returns
zero if there is no database file in USE in the current work area.
* $DESCRIPTION$
LASTREC() is a database function that determines the number of physical
records in the current database file. LASTREC() is identical to
RECCOUNT() which is supplied as a compatibility function.
By default, LASTREC() operates on the currently selected work area. It
will operate on an unselected work area if you specify it as part of an
aliased expression (see example below).
* $EXAMPLES$
This example illustrates the relationship between LASTREC(),
RECCOUNT(), and COUNT:
USE Sales NEW
? LASTREC(), RECCOUNT() // Result: 84 84
//
SET FILTER TO Salesman = "1001"
COUNT TO nRecords
? nRecords, LASTREC() // Result: 14 84
This example uses an aliased expression to access the number
of records in a open database file in an unselected work area:
USE Sales NEW
USE Customer NEW
? LASTREC(), Sales->(LASTREC())
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* EOF()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_LASTREC( void )
{
HB_RECCOUNT();
}
HARBOUR HB_LOCK( void )
{
DBLOCKINFO pLockInfo;
pLockInfo.fResult = FALSE;
if( pCurrArea )
{
pLockInfo.itmRecID = 0;
pLockInfo.uiMethod = FILE_LOCK;
SELF_LOCK( ( AREAP ) pCurrArea->pArea, &pLockInfo );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "LOCK" );
hb_retl( pLockInfo.fResult );
}
/* $DOC$
* $FUNCNAME$
* LUPDATE()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the last modification date of a (.dbf) file
* $SYNTAX$
* LUPDATE() --> dModification
* $ARGUMENTS$
*
* $RETURNS$
LUPDATE() returns the date of last change to the open database file in
the current work area. If there is no database file in USE, LUPDATE()
returns a blank date.
*
* $DESCRIPTION$
LUPDATE() is a database function that determines the date the database
file in the current work area was last modified and CLOSEd. By default,
LUPDATE() operates on the currently selected work area. It will operate
on an unselected work area if you specify it as part of an aliased
expression as shown in the example below.
* $EXAMPLES$
This example demonstrates that the modification date of
database file is not changed until the database file is closed:
? DATE() // Result: 09/01/90
USE Sales NEW
? LUPDATE() // Result: 08/31/90
//
APPEND BLANK
? LUPDATE() // Result: 08/31/90
CLOSE DATABASES
//
USE Sales NEW
? LUPDATE() // Result: 09/01/90
This example uses an aliased expression to access LUPDATE()
for a database file open in an unselected work area:
USE Sales NEW
USE Customer NEW
? LUPDATE(), Sales->(LUPDATE())
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* FIELDNAME(),LASTREC(),RECSIZE()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_LUPDATE( void )
{
if( !pCurrArea )
hb_itemPutDS( &hb_stack.Return, "" );
else
SELF_INFO( ( AREAP ) pCurrArea->pArea, DBI_LASTUPDATE, &hb_stack.Return );
}
/* $DOC$
* $FUNCNAME$
* NETERR()
* $CATEGORY$
* Data Base
* $ONELINER$
* Determine if a network command has failed
* $SYNTAX$
* NETERR([<lNewError>]) --> lError
* $ARGUMENTS$
<lNewError> if specified sets the value returned by NETERR() to the
specified status. <lNewError> can be either true (.T.) or false (.F.).
Setting NETERR() to a specified value allows the runtime error handler
to control the way certain file errors are handled. For more
information, refer to Errorsys.prg.
*
* $RETURNS$
NETERR() returns true (.T.) if a USE or APPEND BLANK fails. The initial
value of NETERR() is false (.F.). If the current process is not running
under a network operating system, NETERR() always returns false (.F.).
* $DESCRIPTION$
NETERR() is a network function. It is a global flag set by USE,
USE...EXCLUSIVE, and APPEND BLANK in a network environment. It is used
to test whether any of these commands have failed by returning true
(.T.) in the following situations:
NETERR() Causes
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Command Cause
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
USE USE EXCLUSIVE by another process
USE...EXCLUSIVE USE EXCLUSIVE or USE by another process
APPEND BLANK FLOCK() or RLOCK() of LASTREC() + 1 by another user
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
NETERR() is generally applied in a program by testing it following a USE
or APPEND BLANK command. If it returns false (.F.), you can perform the
next operation. If the command is USE, you can open index files. If it
is APPEND BLANK, you can assign values to the new record with a REPLACE
or @...GET command. Otherwise, you must handle the error by either
retrying the USE or APPEND BLANK, or terminating the current operation
with a BREAK or RETURN.
* $EXAMPLES$
This example demonstrates typical usage of NETERR(). If the
USE succeeds, the index files are opened and processing continues.
If the USE fails, a message displays and control returns to the
nearest BEGIN SEQUENCE construct:
USE Customer SHARED NEW
IF !NETERR()
SET INDEX TO CustNum, CustOrders, CustZip
ELSE
? "File is in use by another"
BREAK
ENDIF
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* FLOCK(),RLOCK()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_NETERR( void )
{
if( ISLOG( 1 ) )
bNetError = hb_parl( 1 );
hb_retl( bNetError );
}
/* $DOC$
* $FUNCNAME$
* ORDBAGEXT()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the default Order Bag RDD extension
* $SYNTAX$
* ORDBAGEXT() --> cBagExt
* $ARGUMENTS$
*
* $RETURNS$
* ORDBAGEXT() returns a character expression.
* $DESCRIPTION$
ORDBAGEXT() is an Order management function that returns a character
expression that is the default Order Bag extension of the current or
aliased work area. cBagExt is determined by the RDD active in the
current work area.
ORDBAGEXT() supersedes the INDEXEXT() and is not recommended.
*
* $EXAMPLES$
USE sample VIA "DBFNTX"
? ORDBAGEXT() // Returns .ntx
*
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* INDEXEXT(),ORDBAGNAME()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDBAGEXT( void )
{
LPRDDNODE pRddNode;
AREAP pTempArea;
USHORT uiSize, uiRddID;
DBORDERINFO pInfo;
if( !pCurrArea )
{
hb_rddCheck();
uiRddID = 0;
pRddNode = hb_rddFindNode( szDefDriver, &uiRddID );
if( !pRddNode )
{
hb_retc( "" );
return;
}
uiSize = sizeof( AREA ); /* Default Size Area */
pTempArea = ( AREAP ) hb_xgrab( uiSize );
memset( pTempArea, 0, uiSize );
pTempArea->lprfsHost = &pRddNode->pTable;
/* Need more space? */
SELF_STRUCTSIZE( ( AREAP ) pTempArea, &uiSize );
if( uiSize > sizeof( AREA ) ) /* Size of Area changed */
pTempArea = ( AREAP ) hb_xrealloc( pTempArea, uiSize );
pRddNode->uiAreaSize = uiSize; /* Update the size of WorkArea */
pTempArea->rddID = uiRddID;
if( SELF_NEW( ( AREAP ) pTempArea ) == FAILURE )
hb_retc( "" );
else
{
pInfo.itmResult = hb_itemPutC( NULL, "" );
SELF_ORDINFO( pTempArea, DBOI_BAGEXT, &pInfo );
hb_retc( pInfo.itmResult->item.asString.value );
hb_itemRelease( pInfo.itmResult );
SELF_RELEASE( ( AREAP ) pTempArea );
}
hb_xfree( pTempArea );
}
else
{
pInfo.itmResult = hb_itemPutC( NULL, "" );
SELF_ORDINFO( ( AREAP ) pCurrArea->pArea, DBOI_BAGEXT, &pInfo );
hb_retc( pInfo.itmResult->item.asString.value );
hb_itemRelease( pInfo.itmResult );
}
}
/* $DOC$
* $FUNCNAME$
* ORDBAGNAME()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the Order Bag name of a specific Order
* $SYNTAX$
* ORDBAGNAME(<nOrder> | <cOrderName>) --> cOrderBagName
* $ARGUMENTS$
<nOrder> is an integer that identifies the position in the Order
List of the target Order whose Order Bag name is sought.
<cOrderName> is a character string that represents the name of the
target Order whose Order Bag name is sought.
*
* $RETURNS$
ORDBAGNAME() returns a character string, the Order Bag name of the
specific Order.
* $DESCRIPTION$
ORDBAGNAME() is an Order management function that lets you access the
name of the Order Bag in which <cOrderName> resides. You may identify
the Order as a character string or with an integer that represents its
position in the Order List. In case of duplicate names, ORDBAGNAME()
only recognizes the first matching name.
* $EXAMPLES$
The following example uses ORDBAGNAME() with the default
DBFNTX driver:
USE Customer VIA "DBFNTX" NEW
SET INDEX TO CuAcct, CuName, CuZip
ORDBAGNAME( 2 ) // Returns: CuName
ORDBAGNAME( 1 ) // Returns: CuAcct
ORDBAGNAME( 3 ) // Returns: CuZip
In this example, Customer.cdx contains three orders named
CuAcct, CuName, CuZip:
USE Customer VIA "DBFCDX" NEW
SET INDEX TO Customer
ORDBAGNAME( "CuAcct" ) // Returns: Customer
ORDBAGNAME( "CuName" ) // Returns: Customer
ORDBAGNAME( "CuZip" ) // Returns: Customer
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* ORDBAGEXT()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDBAGNAME( void )
{
DBORDERINFO pOrderInfo;
if( pCurrArea )
{
pOrderInfo.itmOrder = hb_param( 1, IT_STRING );
if( !pOrderInfo.itmOrder )
pOrderInfo.itmOrder = hb_param( 1, IT_NUMERIC );
if( !pOrderInfo.itmOrder )
{
hb_errRT_DBCMD( EG_ARG, 1006, NULL, "ORDBAGNAME" );
return;
}
pOrderInfo.itmResult = hb_itemPutC( NULL, "" );
SELF_ORDINFO( ( AREAP ) pCurrArea->pArea, DBOI_BAGNAME, &pOrderInfo );
hb_retc( pOrderInfo.itmResult->item.asString.value );
hb_itemRelease( pOrderInfo.itmResult );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "ORDBAGNAME" );
}
/* $DOC$
* $FUNCNAME$
* ORDCONDSET()
* $CATEGORY$
* Data Base
* $ONELINER$
* Set the Condition and scope for an order
* $SYNTAX$
* ORDCONSET([<cForCondition>],
[<bForCondition>],
[<lAll>],
[<bWhileCondition>],
[<bEval>],
[<nInterval>],
[<nStart>],
[<nNext>],
[<nRecord>],
[<lRest>],
[<lDescend>],
[<lAdditive>],
[<lCurrent>],
[<lCustom>],
[<lNoOptimize>])
* $ARGUMENTS$
* <cForCondition> is a string that specifies the FOR condition for the
order.
<bForCondition> is a code block that defines a FOR condition that
each record within the scope must meet in order to be processed. If
a record does not meet the specified condition,it is ignored and the
next record is processed.Duplicate keys values are not added to the
index file when a FOR condition is Used.
* $RETURNS$
*
* $DESCRIPTION$
*
* $EXAMPLES$
*
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
* ORDCONDSET() is CA-CLIPPER 5.3 Compilant
* $SEEALSO$
*
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDCONDSET( void )
{
LPDBORDERCONDINFO pOrderCondInfo;
char * szFor;
ULONG ulLen;
PHB_ITEM pItem;
if( pCurrArea )
{
pOrderCondInfo = ( LPDBORDERCONDINFO ) hb_xgrab( sizeof( DBORDERCONDINFO ) );
szFor = hb_parc( 1 );
ulLen = strlen( szFor );
if( ulLen )
{
pOrderCondInfo->abFor = ( BYTE * ) hb_xgrab( ulLen + 1 );
strcpy( ( char * ) pOrderCondInfo->abFor, szFor );
}
else
pOrderCondInfo->abFor = NULL;
pItem = hb_param( 2, IT_BLOCK );
if( pItem )
{
pOrderCondInfo->itmCobFor = hb_itemNew( NULL );
hb_itemCopy( pOrderCondInfo->itmCobFor, pItem );
}
else
pOrderCondInfo->itmCobFor = NULL;
if( ISLOG( 3 ) )
pOrderCondInfo->fAll = hb_parl( 3 );
else
pOrderCondInfo->fAll = TRUE;
pItem = hb_param( 4, IT_BLOCK );
if( pItem )
{
pOrderCondInfo->itmCobWhile = hb_itemNew( NULL );
hb_itemCopy( pOrderCondInfo->itmCobWhile, pItem );
}
else
pOrderCondInfo->itmCobWhile = NULL;
pItem = hb_param( 5, IT_BLOCK );
if( pItem )
{
pOrderCondInfo->itmCobEval = hb_itemNew( NULL );
hb_itemCopy( pOrderCondInfo->itmCobEval, pItem );
}
else
pOrderCondInfo->itmCobEval = NULL;
pOrderCondInfo->lStep = hb_parnl( 6 );
pOrderCondInfo->lStartRecno = hb_parnl( 7 );
pOrderCondInfo->lNextCount = hb_parnl( 8 );
pOrderCondInfo->lRecno = hb_parnl( 9 );
pOrderCondInfo->fRest = hb_parl( 10 );
pOrderCondInfo->fDescending = hb_parl( 11 );
pOrderCondInfo->fAdditive = hb_parl( 12 );
pOrderCondInfo->fScoped = hb_parl( 13 );
pOrderCondInfo->fCustom = hb_parl( 14 );
pOrderCondInfo->fNoOptimize = hb_parl( 15 );
if( !pOrderCondInfo->itmCobWhile )
pOrderCondInfo->fRest = TRUE;
if( pOrderCondInfo->lNextCount || pOrderCondInfo->lRecno || pOrderCondInfo->fRest )
pOrderCondInfo->fAll = FALSE;
hb_retl( SELF_ORDSETCOND( ( AREAP ) pCurrArea->pArea, pOrderCondInfo ) == SUCCESS );
}
else
hb_retl( FALSE );
}
/* $DOC$
* $FUNCNAME$
* ORDCREATE()
* $CATEGORY$
* Data Base
* $ONELINER$
* Create an Order in an Order Bag
* $SYNTAX$
ORDCREATE(<cOrderBagName>,[<cOrderName>], <cExpKey>,
[<bExpKey>], [<lUnique>]) --> NIL
* $ARGUMENTS$
<cOrderBagName> is the name of a disk file containing one or more
Orders. You may specify <cOrderBagName> as the filename with or without
the pathname or extension. If you do not include the extension as part
of <cOrderBagName> HARBOUR uses the default extension of the current
RDD.
<cOrderName> is the name of the Order to be created.
Note: Although both <cOrderBagName> and <cOrderName> are both
optional, at least one of them must be specified.
<cExpKey> is an expression that returns the key value to place in
the Order for each record in the current work area. <cExpKey> can
represent a character, date, logical, or numeric data type. The maximum
length of the index key expression is determined by the database driver.
<bExpKey> is a code block that evaluates to a key value that is
placed in the Order for each record in the current work area. If you do
not supply <bExpKey>, it is macro-compiled from <cExpKey>.
<lUnique> is an optional logical value that specifies whether a
unique Order is to be created. If <lUnique> is omitted, the current
global _SET_UNIQUE setting is used.
* $RETURNS$
* ORDCREATE() always returns NIL.
* $DESCRIPTION$
ORDCREATE() is an Order management function that creates an Order in the
current work area. It works like DBCREATEINDEX() except that it lets
you create Orders in RDDs that recognize multiple-Order Bags.
ORDCREATE() supersedes the DBCREATEINDEX() function because of this
capability, and is the preferred function.
The active RDD determines the Order capacity of an Order Bag. The
default DBFNTX and the DBFNDX drivers only support single-Order Bags,
while other RDDs may support multiple-Order Bags (e.g., the DBFCDX and
DBFMDX drivers).
In RDDs that support production or structural indexes (e.g., DBFCDX,
DBFMDX), if you specify a Tag but do not specify an Order Bag, the Tag is
created and added to the index. If no production or structural index
exists, it will be created and the Tag will be added to it. When using
RDDs that support multiple Order Bags, you must explicitly SET ORDER (or
ORDSETFOCUS()) to the desired controlling Order. If you do not specify
a controlling Order, the data file will be viewed in natural Order.
If <cOrderBagName> does not exist, it is created in accordance with the
RDD in the current or specified work area.
If <cOrderBagName> exists and the RDD specifies that Order Bags can only
contain a single Order, <cOrderBagName> is erased and the new Order is
added to the Order List in the current or specified work area.
If <cOrderBagName> exists and the RDD specifies that Order Bags can
contain multiple Tags, <cOrderName> is created if it does not already
exist, otherwise <cOrderName> is replaced in <cOrderBagName> and the
Order is added to the Order List in the current or specified work area.
* $EXAMPLES$
The following example demonstrates ORDCREATE() with the DBFNDX
driver:
USE Customer VIA "DBFNDX" NEW
ORDCREATE( "CuAcct",, "Customer->Acct" )
The following example demonstrates ORDCREATE() with the
default DBFNTX driver:
USE Customer VIA "DBFNTX" NEW
ORDCREATE( "CuAcct", "CuAcct", "Customer->Acct", ;
{|| Customer->Acct } )
The following example demonstrates ORDCREATE() with the FoxPro
driver, DBFCDX:
USE Customer VIA "DBFCDX" NEW
ORDCREATE( "Customer", "CuAcct", "Customer->Acct" )
This example creates the Order "CuAcct" and adds it to the
production index (Order Bag) "Customer". The production index , will
be created if it doesn't exist:
USE Customer VIA "DBFMDX" NEW
ORDCREATE( , "CuAcct", "Customer->Acct" )
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* DBCREATEINDEX()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDCREATE( void )
{
DBORDERCREATEINFO pOrderInfo;
if( pCurrArea )
{
pOrderInfo.abBagName = ( BYTE * ) hb_parc( 1 );
pOrderInfo.atomBagName = ( BYTE * ) hb_parc( 2 );
pOrderInfo.abExpr = hb_param( 3, IT_STRING );
if( ( ( strlen( ( char * ) pOrderInfo.abBagName ) == 0 ) &&
( strlen( ( char * ) pOrderInfo.atomBagName ) == 0 ) ) ||
!pOrderInfo.abExpr )
{
hb_errRT_DBCMD( EG_ARG, 1006, NULL, "ORDCREATE" );
return;
}
pOrderInfo.itmCobExpr = hb_param( 4, IT_BLOCK );
if( ISLOG( 5 ) )
pOrderInfo.fUnique = hb_parl( 5 );
else
pOrderInfo.fUnique = hb_set.HB_SET_UNIQUE;
SELF_ORDCREATE( ( AREAP ) pCurrArea->pArea, &pOrderInfo );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "ORDCREATE" );
}
/* $DOC$
* $FUNCNAME$
* ORDDESTROY()
* $CATEGORY$
* Data Base
* $ONELINER$
* Remove a specified Order from an Order Bag
* $SYNTAX$
* ORDDESTROY(<cOrderName> [, <cOrderBagName> ]) --> NIL
* $ARGUMENTS$
<cOrderName> is the name of the Order to be removed from the current
or specified work area.
<cOrderBagName> is the name of a disk file containing one or more
Orders. You may specify <cOrderBagName> as the filename with or without
the pathname or appropriate extension. If you do not include the
extension as part of <cOrderBagName> HARBOUR uses the default
extension of the current RDD.
* $RETURNS$
* ORDDESTROY() always returns NIL.
* $DESCRIPTION$
ORDDESTROY() is an Order management function that removes a specified
Order from multiple-Order Bags.
The active RDD determines the Order capacity of an Order Bag. The
default DBFNTX and the DBFNDX drivers only support single-Order Bags,
while other RDDs may support multiple-Order Bags (e.g., the DBFCDX and
DBPX drivers).
Note: RDD suppliers may define specific behaviors for this command.
Warning! ORDDESTROY() is not supported for DBFNDX and DBFNTX.
* $EXAMPLES$
This example demonstrates ORDDESTROY() with the FoxPro driver,
DBFCDX:
USE Customer VIA "DBFCDX" NEW
SET INDEX TO Customer, CustTemp
ORDDESTROY( "CuAcct", "Customer" )
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* ORDCREATE()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDDESTROY( void )
{
DBORDERINFO pOrderInfo;
if( pCurrArea )
{
pOrderInfo.itmOrder = hb_param( 1, IT_STRING );
if( !pOrderInfo.itmOrder )
pOrderInfo.itmOrder = hb_param( 1, IT_NUMERIC );
pOrderInfo.atomBagName = hb_param( 2, IT_STRING );
SELF_ORDDESTROY( ( AREAP ) pCurrArea->pArea, &pOrderInfo );
}
}
/* $DOC$
* $FUNCNAME$
* ORDFOR()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the FOR expression of an Order
* $SYNTAX$
ORDFOR(<cOrderName> | <nOrder>
[, <cOrderBagName>]) --> cForExp
*
* $ARGUMENTS$
<cOrderName> is the name of the target Order, whose cForExp is
sought.
<nOrder> is an integer that identifies the position in the Order
List of the target Order whose cForExp is sought.
<cOrderBagName> is the name of an Order Bag containing one or more
Orders. You may specify <cOrderBagName> as the filename with or without
the pathname or appropriate extension. If you do not include the
extension as part of <cOrderBagName> HARBOUR uses the default
extension of the current RDD.
* $RETURNS$
ORDFOR() returns a character expression, cForExp, that represents the
FOR condition of the specified Order. If the Order was not created
using the FOR clause the return value will be an empty string (""). If
the database driver does not support the FOR condition, it may either
return an empty string ("") or raise an "unsupported function" error,
depending on the driver.
* $DESCRIPTION$
ORDFOR() is an Order management function that returns the character
string, cForExp, that represents the logical FOR condition of the Order,
<cOrderName> or <nOrder>.
* $EXAMPLES$
This example retrieves the FOR condition from an Order:
USE Customer NEW
INDEX ON Customer->Acct ;
TO Customer ;
FOR Customer->Acct > "AZZZZZ"
ORDFOR( "Customer" ) // Returns: Customer->Acct > "AZZZZZ"
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* ORDKEY(),ORDCREATE(),ORDNAME(),ORDNUMBER()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDFOR( void )
{
DBORDERINFO pOrderInfo;
if( pCurrArea )
{
pOrderInfo.itmOrder = hb_param( 1, IT_STRING );
if( !pOrderInfo.itmOrder )
pOrderInfo.itmOrder = hb_param( 1, IT_NUMERIC );
pOrderInfo.atomBagName = hb_param( 2, IT_STRING );
if( !pOrderInfo.itmOrder )
{
hb_errRT_DBCMD( EG_ARG, 1006, NULL, "ORDFOR" );
return;
}
pOrderInfo.itmResult = hb_itemPutC( NULL, "" );
SELF_ORDINFO( ( AREAP ) pCurrArea->pArea, DBOI_CONDITION, &pOrderInfo );
hb_retc( pOrderInfo.itmResult->item.asString.value );
hb_itemRelease( pOrderInfo.itmResult );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "ORDFOR" );
}
/* $DOC$
* $FUNCNAME$
* ORDKEY()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the key expression of an Order
* $SYNTAX$
ORDKEY(<cOrderName> | <nOrder>
[, <cOrderBagName>]) --> cExpKey
* $ARGUMENTS$
<cOrderName> is the name of an Order, a logical ordering of a
database.
<nOrder> is an integer that identifies the position in the Order
List of the target Order whose cExpKey is sought.
<cOrderBagName> is the name of a disk file containing one or more
Orders. You may specify <cOrderBagName> as the filename with or without
the pathname or appropriate extension. If you do not include the
extension as part of <cOrderBagName> HARBOUR uses the default
extension of the current RDD.
* $RETURNS$
* Returns a character string, cExpKey.
* $DESCRIPTION$
ORDKEY() is an Order management function that returns a character
expression, cExpKey, that represents the key expression of the specified
Order.
You may specify the Order by name or with a number that represents its
position in the Order List. Using the Order name is the preferred
method.
The active RDD determines the Order capacity of an Order Bag. The
default DBFNTX and the DBFNDX drivers only support single-Order Bags,
while other RDDs may support multiple-Order Bags (e.g., the DBFCDX and
DBFMDX drivers).
* $EXAMPLES$
This example retrieves the index expression from an Order:
USE Customer NEW
INDEX ON Customer->Acct ;
TO Customer ;
FOR Customer->Acct > "AZZZZZ"
ORDKEY( "Customer" ) // Returns: Customer->Acct
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* ORDFOR(),ORDNAME(),ORDNUMBER()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDKEY( void )
{
DBORDERINFO pOrderInfo;
if( pCurrArea )
{
pOrderInfo.itmOrder = hb_param( 1, IT_STRING );
if( !pOrderInfo.itmOrder )
pOrderInfo.itmOrder = hb_param( 1, IT_NUMERIC );
pOrderInfo.atomBagName = hb_param( 2, IT_STRING );
if( !pOrderInfo.itmOrder )
{
hb_errRT_DBCMD( EG_ARG, 1006, NULL, "ORDKEY" );
return;
}
pOrderInfo.itmResult = hb_itemPutC( NULL, "" );
SELF_ORDINFO( ( AREAP ) pCurrArea->pArea, DBOI_EXPRESSION, &pOrderInfo );
hb_retc( pOrderInfo.itmResult->item.asString.value );
hb_itemRelease( pOrderInfo.itmResult );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "ORDKEY" );
}
/* $DOC$
* $FUNCNAME$
* ORDLISTADD()
* $CATEGORY$
* Data Base
* $ONELINER$
* Add Orders to the Order List
* $SYNTAX$
ORDLISTADD(<cOrderBagName>
[, <cOrderName>]) --> NIL
* $ARGUMENTS$
<cOrderBagName> is the name of a disk file containing one or more
Orders. You may specify <cOrderBagName> as the filename with or without
the pathname or appropriate extension. If you do not include the
extension as part of <cOrderBagName> HARBOUR uses the default
extension of the current RDD.
<cOrderName> the name of the specific Order from the Order Bag to be
added to the Order List of the current work area. If you do not specify
<cOrderName>, all orders in the Order Bag are added to the Order List of
the current work area.
* $RETURNS$
* ORDLISTADD() always returns NIL.
* $DESCRIPTION$
ORDLISTADD() is an Order management function that adds the contents of
an Order Bag , or a single Order in an Order Bag, to the Order List.
This function lets you extend the Order List without issuing a SET INDEX
command that, first, clears all the active Orders from the Order List.
Any Orders already associated with the work area continue to be active.
If the newly opened Order Bag contains the only Order associated with
the work area, it becomes the controlling Order; otherwise, the
controlling Order remains unchanged.
After the new Orders are opened, the work area is positioned to the
first logical record in the controlling Order.
ORDLISTADD() is similar to the SET INDEX command or the INDEX clause of
the USE command, except that it does not clear the Order List prior to
adding the new order(s).
ORDLISTADD() supersedes the DBSETINDEX() function.
The active RDD determines the Order capacity of an Order Bag. The
default DBFNTX and the DBFNDX drivers only support single-Order Bags,
while other RDDs may support multiple-Order Bags (e.g., the DBFCDX and
DBPX drivers). When using RDDs that support multiple Order Bags, you
must explicitly SET ORDER (or ORDSETFOCUS()) to the desired controlling
Order. If you do not specify a controlling Order, the data file will be
viewed in natural Order.
* $EXAMPLES$
In this example Customer.cdx contains three orders, CuAcct,
CuName, and CuZip. ORDLISTADD() opens Customer.cdx but only uses the
order named CuAcct:
USE Customer VIA "DBFCDX" NEW
ORDLISTADD( "Customer", "CuAcct" )
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* DBSETINDEX()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDLISTADD( void )
{
DBORDERINFO pOrderInfo;
if( pCurrArea )
{
pOrderInfo.atomBagName = hb_param( 1, IT_STRING );
pOrderInfo.itmOrder = hb_param( 2, IT_STRING );
if( !pOrderInfo.atomBagName )
{
hb_errRT_DBCMD( EG_ARG, 1006, NULL, "ORDLISTADD" );
return;
}
SELF_ORDLSTADD( ( AREAP ) pCurrArea->pArea, &pOrderInfo );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "ORDLISTADD" );
}
/* $DOC$
* $FUNCNAME$
* ORDLISTCLEAR()
* $CATEGORY$
* Data Base
* $ONELINER$
* Clear the current Order List
* $SYNTAX$
* ORDLISTCLEAR() --> NIL
* $ARGUMENTS$
*
* $RETURNS$
* ORDLISTCLEAR() always returns NIL.
* $DESCRIPTION$
ORDLISTCLEAR() is an Order management function that removes all Orders
from the Order List for the current or aliased work area. When you are
done, the Order List is empty.
This function supersedes the function DBCLEARINDEX().
*
* $EXAMPLES$
USE Sales NEW
SET INDEX TO SaRegion, SaRep, SaCode
.
. < statements >
.
ORDLISTCLEAR() // Closes all the current indexes
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* DBCLEARINDEX()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDLISTCLEAR( void )
{
if( pCurrArea )
SELF_ORDLSTCLEAR( ( AREAP ) pCurrArea->pArea );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "ORDLISTCLEAR" );
}
/* $DOC$
* $FUNCNAME$
* ORDLISTREBUILD()
* $CATEGORY$
* Data Base
* $ONELINER$
* Rebuild all Orders in the Order List of the current work area
* $SYNTAX$
* ORDLISTREBUILD() --> NIL
* $ARGUMENTS$
*
* $RETURNS$
* ORDLISTREBUILD() always returns NIL.
* $DESCRIPTION$
ORDLISTREBUILD() is an Order management function that rebuilds all the
orders in the current or aliased Order List.
To only rebuild a single Order use the function ORDCREATE().
Unlike ORDCREATE(), this function rebuilds all Orders in the Order List.
It is equivalent to REINDEX.
*
* $EXAMPLES$
USE Customer NEW
SET INDEX TO CuAcct, CuName, CuZip
ORDLISTREBUILD() // Causes CuAcct, CuName, CuZip to
// be rebuilt
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* ORDCREATE()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDLISTREBUILD( void )
{
if( pCurrArea )
SELF_ORDLSTREBUILD( ( AREAP ) pCurrArea->pArea );
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "ORDLISTCLEAR" );
}
/* $DOC$
* $FUNCNAME$
* ORDNAME()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the name of an Order in the Order List
* $SYNTAX$
* ORDNAME(<nOrder>[,<cOrderBagName>])
--> cOrderName
* $ARGUMENTS$
<nOrder> is an integer that identifies the position in the Order
List of the target Order whose database name is sought.
<cOrderBagName> is the name of a disk file containing one or more
Orders. You may specify <cOrderBagName> as the filename with or without
the pathname or appropriate extension. If you do not include the
extension as part of <xcOrderBagName> HARBOUR uses the default
extension of the current RDD.
* $RETURNS$
ORDNAME() returns the name of the specified Order in the current Order
List or the specified Order Bag if opened in the Current Order list.
* $DESCRIPTION$
ORDNAME() is an Order management function that returns the name of the
specified Order in the current Order List.
If <cOrderBagName> is an Order Bag that has been emptied into the
current Order List, only those Orders in the Order List that correspond
to <cOrderBagName> Order Bag are searched.
The active RDD determines the Order capacity of an Order Bag. The
default DBFNTX and the DBFNDX drivers only support single-Order Bags,
while other RDDs may support multiple-Order Bags (e.g., the DBFCDX and
DBPX drivers).
* $EXAMPLES$
This example retrieves the name of an Order using its position
in the order list:
USE Customer NEW
SET INDEX TO CuAcct, CuName, CuZip
ORDNAME( 2 ) // Returns: CuName
This example retrieves the name of an Order given its position
within a specific Order Bag in the Order List:
USE Customer NEW
SET INDEX TO Temp, Customer
// Assume Customer contains CuAcct, CuName, CuZip
ORDNAME( 2, "Customer" ) // Returns: CuName
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* ORDFOR(),ORDKEY(),ORDNUMBER()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDNAME( void )
{
DBORDERINFO pOrderInfo;
if( pCurrArea )
{
pOrderInfo.itmOrder = hb_param( 1, IT_NUMERIC );
pOrderInfo.atomBagName = hb_param( 2, IT_STRING );
if( !pOrderInfo.itmOrder )
{
hb_errRT_DBCMD( EG_ARG, 1006, NULL, "ORDNAME" );
return;
}
pOrderInfo.itmResult = hb_itemPutC( NULL, "" );
SELF_ORDINFO( ( AREAP ) pCurrArea->pArea, DBOI_NAME, &pOrderInfo );
hb_retc( pOrderInfo.itmResult->item.asString.value );
hb_itemRelease( pOrderInfo.itmResult );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "ORDNAME" );
}
/* $DOC$
* $FUNCNAME$
* ORDNUMBER()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the position of an Order in the current Order List
* $SYNTAX$
ORDNUMBER(<cOrderName>
[, <cOrderBagName>]) --> nOrderNo
* $ARGUMENTS$
<cOrderName> the name of the specific Order whose position in the
Order List is sought.
<cOrderBagName> is the name of a disk file containing one or more
Orders. You may specify <cOrderBagName> as the filename with or without
the pathname or appropriate extension. If you do not include the
extension as part of <cOrderBagName> HARBOUR uses the default
extension of the current RDD.
* $RETURNS$
Returns nOrderNo, an integer that represents the position of the
specified Order in the Order List.
* $DESCRIPTION$
ORDNUMBER() is an Order management function that lets you determine the
position in the current Order List of the specified Order. ORDNUMBER()
searches the Order List in the current work area and returns the
position of the first Order that matches <cOrderName>. If
<cOrderBagName> is the name of an Order Bag newly emptied into the
current Order List, only those orders in the Order List that have been
emptied from <cOrderBagName> are searched.
If <cOrderName> is not found ORDNUMBER() raises a recoverable runtime
error.
The active RDD determines the Order capacity of an Order Bag. The
default DBFNTX driver only supports single-Order Bags, while other RDDs
may support multiple-Order Bags (e.g., the DBFCDX and DBPX drivers).
* $EXAMPLES$
USE Customer VIA "DBFNTX" NEW
SET INDEX TO CuAcct, CuName, CuZip
ORDNUMBER( "CuName" ) // Returns: 2
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
* INDEXORD()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDNUMBER( void )
{
DBORDERINFO pOrderInfo;
if( pCurrArea )
{
pOrderInfo.itmOrder = hb_param( 1, IT_STRING );
pOrderInfo.atomBagName = hb_param( 2, IT_STRING );
if( !pOrderInfo.itmOrder )
{
hb_errRT_DBCMD( EG_ARG, 1006, NULL, "ORDNUMBER" );
return;
}
pOrderInfo.itmResult = hb_itemPutNI( NULL, 0 );
SELF_ORDINFO( ( AREAP ) pCurrArea->pArea, DBOI_NUMBER, &pOrderInfo );
hb_retni( hb_itemGetNI( pOrderInfo.itmResult ) );
hb_itemRelease( pOrderInfo.itmResult );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "ORDNUMBER" );
}
/* $DOC$
* $FUNCNAME$
* ORDSETFOCUS()
* $CATEGORY$
* Data Base
* $ONELINER$
* Set focus to an Order in an Order List
* $SYNTAX$
ORDSETFOCUS([<cOrderName> | <nOrder>]
[,<cOrderBagName>]) --> cPrevOrderNameInFocus
*
* $ARGUMENTS$
<cOrderName> is the name of the selected Order, a logical ordering
of a database. ORDSETFOCUS() ignores any invalid values of
<cOrderName>.
<nOrder> is a number representing the position in the Order List of
the selected Order.
<cOrderBagName> is the name of a disk file containing one or more
Orders. You may specify <cOrderBagName> as the filename with or without
the pathname or appropriate extension. If you do not include the
extension as part of <cOrderBagName> HARBOUR uses the default
extension of the current RDD.
* $RETURNS$
* ORDSETFOCUS() returns the Order Name of the previous controlling Order.
* $DESCRIPTION$
ORDSETFOCUS() is an Order management function that returns the Order
Name of the previous controlling Order and optionally sets the focus to
an new Order.
If you do not specify <cOrderName> or <nOrder>, the name of the
currently controlling order is returned and the controlling order
remains unchanged.
All Orders in an Order List are properly updated no matter what
<cOrderName> is the controlling Order. After a change of controlling
Orders, the record pointer still points to the same record.
The active RDD determines the Order capacity of an Order Bag. The
default DBFNTX driver only supports single-Order Bags, while other RDDs
may support multiple-Order Bags (e.g., the DBFCDX and DBPX drivers).
ORDSETFOCUS() supersedes INDEXORD().
* $EXAMPLES$
USE Customer VIA "DBFNTX" NEW
SET INDEX TO CuAcct, CuName, CuZip
? ORDSETFOCUS( "CuName" ) // Displays: "CuAcct"
? ORDSETFOCUS() // Displays: "CuName"
* $TESTS$
*
* $STATUS$
* S
* $COMPLIANCE$
*
* $SEEALSO$
*
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_ORDSETFOCUS( void )
{
DBORDERINFO pInfo;
if( pCurrArea )
{
pInfo.itmOrder = hb_param( 1, IT_STRING );
if( !pInfo.itmOrder )
pInfo.itmOrder = hb_param( 1, IT_NUMERIC );
pInfo.atomBagName = hb_param( 2, IT_STRING );
pInfo.itmResult = hb_itemPutC( NULL, "" );
SELF_ORDLSTFOCUS( ( AREAP ) pCurrArea->pArea, &pInfo );
hb_retc( pInfo.itmResult->item.asString.value );
hb_itemRelease( pInfo.itmResult );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "ORDSETFOCUS" );
}
/* $DOC$
* $FUNCNAME$
* RDDLIST()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return an array of the available Replaceable Database Drivers
* $SYNTAX$
* RDDLIST([<nRDDType>]) --> aRDDList
* $ARGUMENTS$
<nRDDType> is an integer that represents the type of the RDD you
wish to list. The constants RDT_FULL and RDT_TRANSFER represent the two
types of RDDs currently available.
RDDType Summary
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Constant Value Meaning
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RDT_FULL 1 Full RDD implementation
RDT_TRANSFER 2 Import/Export only driver
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RDT_FULL identifies full-featured RDDs that have all the capabilities
associated with an RDD.
RDT_TRANSFER identifies RDDs of limited capability. They can only
transfer records between files. You cannot use these limited RDD
drivers to open a file in a work area. The SDF and DELIM drivers are
examples of this type of RDD. They are only used in the implementation
of APPEND FROM and COPY TO with SDF or DELIMITED files.
* $RETURNS$
RDDLIST() returns a one-dimensional array of the RDD names registered
with the application as <nRDDType>.
* $DESCRIPTION$
RDDLIST() is an RDD function that returns a one-dimensional array that
lists the available RDDs.
If you do not supply <nRDDType>, all available RDDs, regardless of type,
are returned.
* $EXAMPLES$
In this example RDDLIST() returns an array containing the
character strings, "DBF", "SDF", "DELIM", "DBFCDX", and "DBFNTX":
REQUEST DBFCDX
.
. < statements >
.
aRDDs := RDDLIST()
// Returns {"DBF", SDF", "DELIM", "DBFCDX", "DBFNTX" }
In this example, RDDLIST() returns an array containing the
character strings, "SDF" and "DELIM":
#include "rddsys.ch"
.
. < statements >
.
aImpExp := RDDLIST( RDT TRANSFER )
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
*
* $INCLUDE$
* RDDSYS.CH
* $END$
*/
HARBOUR HB_RDDLIST( void )
{
USHORT uiType;
PHB_ITEM pName;
LPRDDNODE pRddNode;
hb_rddCheck();
hb_arrayNew( &hb_stack.Return, 0 );
pName = hb_itemNew( NULL );
pRddNode = pRddList;
uiType = hb_parni( 1 ); /* 0 all types of RDD's */
while( pRddNode )
{
if( ( uiType == 0 ) || ( pRddNode->uiType == uiType ) )
hb_arrayAdd( &hb_stack.Return, hb_itemPutC( pName, pRddNode->szName ) );
pRddNode = pRddNode->pNext;
}
hb_itemRelease( pName );
}
/* $DOC$
* $FUNCNAME$
* RDDNAME()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the name of the currently active RDD
* $SYNTAX$
* RDDNAME() --> cRDDName
* $ARGUMENTS$
*
* $RETURNS$
* Returns a character string, cRDDName, the registered name of the active
* RDD in the current or specified work area.
* $DESCRIPTION$
* RDDNAME() is an RDD function that returns a character string, cRDDName,
* the name of the active RDD in the current or specified work area.
*
* You can specify a work area other than the currently active work area by
* aliasing the function.
* $EXAMPLES$
* USE Customer VIA "DBFNTX" NEW
* USE Sales VIA "DBFCDX" NEW
*
* ? RDDNAME() // Returns: DBFCDX
* ? Customer->( RDDNAME() ) // Returns: DBFNTX
* ? Sales->( RDDNAME() ) // Returns: DBFCDX
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* RDDLIST()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_RDDNAME( void )
{
char * pBuffer;
if( pCurrArea )
{
pBuffer = ( char * ) hb_xgrab( HARBOUR_MAX_RDD_DRIVERNAME_LENGTH + 1 );
pBuffer[ 0 ] = '\0';
SELF_SYSNAME( ( AREAP ) pCurrArea->pArea, ( BYTE * ) pBuffer );
hb_retc( pBuffer );
hb_xfree( pBuffer );
}
else
{
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "RDDNAME" );
hb_retc( "" );
}
}
HARBOUR HB_RDDREGISTER( void )
{
char szDriver[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ];
USHORT uiLen;
hb_rddCheck();
uiLen = hb_parclen( 1 );
if( uiLen > 0 )
{
hb_strncpyUpper( szDriver, hb_parc( 1 ), uiLen );
/*
* hb_rddRegister returns:
*
* 0: Ok, RDD registered
* 1: RDD already registerd
* > 1: error
*/
if( hb_rddRegister( szDriver, hb_parni( 2 ) ) <= 1 )
return;
hb_errInternal( 9002, "", "", "" );
}
}
/* $DOC$
* $FUNCNAME$
* RDDSETDEFAULT()
* $CATEGORY$
* Data Base
* $ONELINER$
* Set or return the default RDD for the application
* $SYNTAX$
* RDDSETDEFAULT([<cNewDefaultRDD>])
* --> cPreviousDefaultRDD
*
* $ARGUMENTS$
* <cNewDefaultRDD> is a character string, the name of the RDD that is
* to be made the new default RDD in the application.
* $RETURNS$
* RDDSETDEFAULT() returns a character string, cPreviousDefaultRDD, the
* name of the previous default driver. The default driver is the driver
* that HARBOUR uses if you do not explicitly specify an RDD with the
* VIA clause of the USE command.
* $DESCRIPTION$
* RDDSETDEFAULT() is an RDD function that sets or returns the name of the
* previous default RDD driver and, optionally, sets the current driver to
* the new RDD driver specified by cNewDefaultRDD. If <cNewDefaultDriver>
* is not specified, the current default driver name is returned and
* continues to be the current default driver.
*
* This function replaces the DBSETDRIVER() function.
* $EXAMPLES$
* // If the default driver is not DBFNTX, make it the default
*
* IF ( RDDSETDEFAULT() != "DBFNTX" )
* cOldRdd := RDDSETDEFAULT( "DBFNTX" )
* ENDIF
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBSETDRIVER()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_RDDSETDEFAULT( void )
{
char szNewDriver[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ];
USHORT uiLen;
hb_rddCheck();
hb_retc( szDefDriver );
uiLen = hb_parclen( 1 );
if( uiLen > 0 )
{
hb_strncpyUpper( szNewDriver, hb_parc( 1 ), uiLen );
if( !hb_rddFindNode( szNewDriver, NULL ) )
{
hb_errRT_DBCMD( EG_ARG, 1015, NULL, "RDDSETDEFAULT" );
return;
}
szDefDriver = ( char * ) hb_xrealloc( szDefDriver, uiLen + 1 );
strcpy( szDefDriver, szNewDriver );
}
}
/* $DOC$
* $FUNCNAME$
* RECCOUNT()
* $CATEGORY$
* Data Base
* $ONELINER$
* Determine the number of records in the current (.dbf) file
* $SYNTAX$
* RECCOUNT()* | LASTREC() --> nRecords
* $ARGUMENTS$
*
* $RETURNS$
RECCOUNT() returns the number of physical records in the current
database file as an integer numeric value. Filtering commands such as
SET FILTER or SET DELETED have no effect on the return value.
RECCOUNT() returns zero if there is no database file open in the current
work area.
*
* $DESCRIPTION$*
RECCOUNT() is a database function that is a synonym for LASTREC(). By
default, RECCOUNT() operates on the currently selected work area. It
will operate on an unselected work area if you specify it as part of an
aliased expression (see example below).
* $EXAMPLES$
This example illustrates the relationship between COUNT and
RECCOUNT():
USE Sales NEW
? RECCOUNT() // Result: 84
//
SET FILTER TO Salesman = "1001"
COUNT TO nRecords
? nRecords // Result: 14
? RECCOUNT() // Result: 84
This example uses an aliased expression to access the number
of records in an unselected work area:
USE Sales NEW
USE Customer NEW
? RECCOUNT(), Sales->(RECCOUNT())
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* EOF(),LASTREC()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_RECCOUNT( void )
{
ULONG ulRecCount = 0;
if( pCurrArea )
{
SELF_RECCOUNT( ( AREAP ) pCurrArea->pArea, &ulRecCount );
( ( AREAP ) pCurrArea->pArea )->lpExtendInfo->ulRecCount = ulRecCount;
}
hb_retnl( ulRecCount );
}
/* $DOC$
* $FUNCNAME$
* RECNO()
* $CATEGORY$
* Data Base
* $ONELINER$
* Return the identity at the position of the record pointer
* $SYNTAX$
* RECNO() --> Identity
* $ARGUMENTS$
*
* $RETURNS$
RECNO() returns the identity found at the position of the record
pointer.
* $DESCRIPTION$
RECNO() is a database function that returns the identity found at the
current position of the record pointer. Identity is a unique value
guaranteed by the structure of the data file to reference a specific
record of data file. The data file need not be a traditional Xbase
file. Therefore, unlike earlier versions of HARBOUR, the value
returned need not be a numeric data type.
Under all RDDs, RECNO() returns the value at the position of the record
pointer; the data type and other characteristics of this value are
determined by the content of the accessed data and the RDD active in the
current work area. In an Xbase database this value is the record
number.
* $EXAMPLES$
USE Sales VIA "DBFNTX"
.
. < statements >
.
DBGOTOP()
RECNO() // Returns 1
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBGOTO()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_RECNO( void )
{
PHB_ITEM pRecNo;
pRecNo = hb_itemPutNL( NULL, 0 );
if( pCurrArea )
SELF_RECNO( ( AREAP ) pCurrArea->pArea, pRecNo );
hb_itemReturn( pRecNo );
hb_itemRelease( pRecNo );
}
/* $DOC$
* $FUNCNAME$
* RECSIZE()
* $CATEGORY$
* Data Base
* $ONELINER$
* Determine the record length of a database (.dbf) file
* $SYNTAX$
* RECSIZE() --> nBytes
* $ARGUMENTS$
*
* $RETURNS$
RECSIZE() returns, as a numeric value, the record length, in bytes, of
the database file open in the current work area. RECSIZE() returns zero
if no database file is open.
* $DESCRIPTION$
RECSIZE() is a database function that determines the length of a record
by summing the lengths of each field then adding one for the DELETED()
status flag. When this value is multiplied by LASTREC(), the product is
the amount of space occupied by the file's records.
RECSIZE() is useful in programs that perform automatic file backup.
When used in conjunction with DISKSPACE(), the RECSIZE() function can
assist in ensuring that sufficient free space exists on the disk before a
file is stored.
By default, RECSIZE() operates on the currently selected work area. It
will operate on an unselected work area if you specify it as part of an
aliased expression (see example below).
* $EXAMPLES$
The following user-defined function, DbfSize(), uses RECSIZE()
to calculate the size of the current database file:
FUNCTION DbfSize
RETURN ((RECSIZE() * LASTREC()) + HEADER() + 1)
This example illustrates the use of RECSIZE() to determine the
record length of database files open in unselected work areas:
USE Customer NEW
USE Sales NEW
//
? RECSIZE(), Customer->(RECSIZE())
? DbfSize(), Customer->(DbfSize())
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DISKSPACE(),FIELDNAME(),HEADER(),LASTREC()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_RECSIZE( void )
{
PHB_ITEM pRecSize;
if( !pCurrArea )
hb_retni( 0 );
else
{
pRecSize = hb_itemNew( NULL );
SELF_INFO( ( AREAP ) pCurrArea->pArea, DBI_GETRECSIZE, pRecSize );
hb_itemReturn( pRecSize );
hb_itemRelease( pRecSize );
}
}
/* $DOC$
* $FUNCNAME$
* RLOCK()
* $CATEGORY$
* Data Base
* $ONELINER$
* Lock the current record in the active work area
* $SYNTAX$
* RLOCK() --> lSuccess
* $ARGUMENTS$
*
* $RETURNS$
RLOCK() returns true (.T.) if the record lock is obtained; otherwise, it
returns false (.F.).
* $DESCRIPTION$
RLOCK() is a network function that locks the current record, preventing
other users from updating the record until the lock is released.
RLOCK() provides a shared lock, allowing other users read-only access to
the locked record while allowing only the current user to modify it. A
record lock remains until another record is locked, an UNLOCK is
executed, the current database file is closed, or an FLOCK() is obtained
on the current database file.
For each invocation of RLOCK(), there is one attempt to lock the current
record, and the result is returned as a logical value. An attempt to
obtain a record lock fails if another user currently has a file or
record lock, or EXCLUSIVE USE of the database file. An attempt to
RLOCK() in an empty database returns true (.T.).
By default, RLOCK() operates on the currently selected work area. It
will operate on an unselected work area if you specify it as part of an
aliased expression (see example below). This feature is useful since
RLOCK() does not automatically attempt a record lock for related files.
As a general rule, RLOCK() operates solely on the current record. This
includes the following commands:
@...GET
DELETE (single record)
RECALL (single record)
REPLACE (single record)
Refer to the Network Programming chapter in the Programming and
Utilities guide for more information.
Notes
SET RELATION: HARBOUR does not automatically lock all
records in the relation chain when you lock the current work area
record. Also, an UNLOCK has no effect on related work areas.
* $EXAMPLES$
This example deletes a record in a network environment, using
RLOCK():
USE Customer INDEX CustName SHARED NEW
SEEK "Smith"
IF FOUND()
IF RLOCK()
DELETE
? "Smith deleted"
ELSE
? "Record in use by another"
ENDIF
ELSE
? "Smith not in Customer file"
ENDIF
CLOSE
This example specifies RLOCK() as an aliased expression to
lock a record in an unselected work area:
USE Sales SHARED NEW
USE Customer SHARED NEW
//
IF !Sales->(RLOCK())
? "The current Sales record is in use by another"
ENDIF
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* FLOCK()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_RLOCK( void )
{
DBLOCKINFO pLockInfo;
PHB_ITEM pRecNo;
pLockInfo.fResult = FALSE;
if( pCurrArea )
{
pRecNo = hb_itemPutNL( NULL, 0 );
SELF_RECNO( ( AREAP ) pCurrArea->pArea, pRecNo );
pLockInfo.itmRecID = pRecNo->item.asLong.value;
pLockInfo.uiMethod = REC_LOCK;
SELF_LOCK( ( AREAP ) pCurrArea->pArea, &pLockInfo );
hb_itemRelease( pRecNo );
}
else
hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "RLOCK" );
hb_retl( pLockInfo.fResult );
}
/* $DOC$
* $FUNCNAME$
* SELECT()
* $CATEGORY$
* Data Base
* $ONELINER$
* Determine the work area number of a specified alias
* $SYNTAX$
* SELECT([<cAlias>]) --> nWorkArea
* $ARGUMENTS$
* <cAlias> is the target work area alias name.
* $RETURNS$
SELECT() returns the work area of the specified alias as a integer
numeric value.
* $DESCRIPTION$
SELECT() is a database function that determines the work area number of
an alias. The number returned can range from zero to 250. If <cAlias>
is not specified, the current work area number is returned. If <cAlias>
is specified and the alias does not exist, SELECT() returns zero.
Note: The SELECT() function and SELECT command specified with an
extended expression argument look somewhat alike. This shouldn't be a
problem since the SELECT() function is not very useful on a line by
itself
* $EXAMPLES$
This example uses SELECT() to determine which work area
USE...NEW selected:
USE Sales NEW
SELECT 1
? SELECT("Sales") // Result: 4
To reselect the value returned from the SELECT() function, use
the SELECT command with the syntax, SELECT (<idMemvar>), like this:
USE Sales NEW
nWorkArea:= SELECT()
USE Customer NEW
SELECT (nWorkArea)
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* ALIAS(),USED()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_SELECT( void )
{
char * szAlias;
ULONG ulLen;
szAlias = hb_parc( 1 );
ulLen = strlen( szAlias );
if( ulLen == 1 && toupper( szAlias[ 0 ] ) >= 'A' && toupper( szAlias[ 0 ] ) <= 'K' )
hb_retni( toupper( szAlias[ 0 ] ) - 'A' + 1 );
else if( ulLen > 0 )
hb_retni( hb_rddSelect( szAlias ) );
else
hb_retni( uiCurrArea );
}
/* $DOC$
* $FUNCNAME$
* USED()
* $CATEGORY$
* Data Base
* $ONELINER$
* Determine whether a database file is in USE
* $SYNTAX$
* USED() --> lDbfOpen
* $ARGUMENTS$
*
* $RETURNS$
USED() returns true (.T.) if there is a database file in USE; otherwise,
it returns false (.F.).
* $DESCRIPTION$
USED() is a database function that determines whether there is a
database file in USE in a particular work area. By default, USED()
operates on the currently selected work area. It will operate on an
unselected work area if you specify it as part of an aliased expression.
* $EXAMPLES$
This example determines whether a database file is in USE in
the current work area:
USE Customer NEW
? USED() // Result: .T.
CLOSE
? USED() // Result: .F.
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* ALIAS(),SELECT()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB_USED( void )
{
hb_retl( pCurrArea != NULL );
}
/* NOTE: Same as dbSetDriver() and rddSetDefault(), but doesn't
throw any error if the driver doesn't exist, this is
required in the RDDSYS INIT function, since it's not guaranteed
that the RDD is already registered at that point. */
/* $DOC$
* $FUNCNAME$
* __RDDSETDEFAULT()
* $CATEGORY$
* Data Base
* $ONELINER$
* Set or return the default RDD for the application
* $SYNTAX$
__RDDSETDEFAULT([<cNewDefaultRDD>])
--> cPreviousDefaultRDD
*
* $ARGUMENTS$
<cNewDefaultRDD> is a character string, the name of the RDD that is
to be made the new default RDD in the application.
* $RETURNS$
__RDDSETDEFAULT() returns a character string, cPreviousDefaultRDD, the
name of the previous default driver. The default driver is the driver
that HARBOUR uses if you do not explicitly specify an RDD with the
VIA clause of the USE command.
* $DESCRIPTION$
RDDSETDEFAULT() is an RDD function that sets or returns the name of the
previous default RDD driver and, optionally, sets the current driver to
the new RDD driver specified by cNewDefaultRDD. If <cNewDefaultDriver>
is not specified, the current default driver name is returned and
continues to be the current default driver.
This function replaces the DBSETDRIVER() function.
* $EXAMPLES$
// If the default driver is not DBFNTX, make it the default
IF ( __RDDSETDEFAULT() != "DBFNTX" )
cOldRdd := __RDDSETDEFAULT( "DBFNTX" )
ENDIF
* $TESTS$
*
* $STATUS$
* R
* $COMPLIANCE$
*
* $SEEALSO$
* DBSETDRIVER()
* $INCLUDE$
*
* $END$
*/
HARBOUR HB___RDDSETDEFAULT( void )
{
char * szNewDriver;
USHORT uiLen;
char cDriverBuffer[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ];
hb_rddCheck();
hb_retc( szDefDriver );
szNewDriver = hb_parc( 1 );
if( ( uiLen = strlen( szNewDriver ) ) > 0 )
{
hb_strncpyUpper( cDriverBuffer, szNewDriver, uiLen );
szDefDriver = ( char * ) hb_xrealloc( szDefDriver, uiLen + 1 );
strcpy( szDefDriver, cDriverBuffer );
}
}