Files
harbour-core/harbour/source/rtl/dbsdf.prg
Przemyslaw Czerpak 268c9d28dc 2006-05-30 12:15 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbver.h
    * changed version number and ChangeLog entry

  * harbour/make_tgz.sh
    ! fixed creating PP in DJGPP builds

  * harbour/contrib/dot/pp.prg
    ! minor fix in parameter checking

  * harbour/contrib/libmisc/hb_f.c
    ! fixed bug in record numbering after reaching EOF position and
      backward skipping

  * harbour/include/hbrdddel.h
  * harbour/source/rdd/delim1.c
    + implemented DELIM RDD. It should be fully Clipper compatible
      in comma files parsing. If you will find any difference, please
      inform me and I'll update it. Unlike in Clipper in [x]Harbour
      these RDD can be used also in direct import operations with
      APPEND FROM ... VIA "DELIM"
      These RDD also support whole record transfering between RDDs
      if they support the same record format and field representation
      and can translate extended field types like "I", "B", "V3", "V4",
      etc.

  * harbour/source/rtl/dbdelim.prg
    * replaced old code of __dbDelim() function with simple calls to
      __dbCopy()/__dbApp() - it should fix most of the reported
      incompatibilities in DELIM import/export operations and
      increase their speed many times

  * harbour/include/hbrddsdf.h
  * harbour/source/rdd/sdf1.c
    + implemented SDF RDD. It should be fully Clipper compatible
      in SDF files parsing. If you will find any difference, please
      inform me and I'll update it. Unlike in Clipper in [x]Harbour
      these RDD can be used also in direct import operations with
      APPEND FROM ... VIA "SDF"
      These RDD also support whole record transfering between RDDs
      if they support the same record format and field representation
      and can translate extended field types like "I", "B", "V3", "V4",
      etc.

  * harbour/source/rtl/dbsdf.prg
    * replaced old code of __dbSDF() function with simple calls to
      __dbCopy()/__dbApp() - it should fix most of the reported
      incompatibilities in SDF import/export operations and
      increase their speed many times

  * harbour/source/rdd/dbcmd.c
    + added support for table structure inheriting in transfer RDDs.
    + added eleventh parameter with delimiter to __dbCopy()/__dbApp()

  * harbour/source/rdd/dbf1.c
    * force 10 bytes size for memo fields in DBF and SMT memos.
    * some minor clean-up.

  * harbour/source/rdd/workarea.c
    * added some dummy DBI_* actions in base RDD level
2006-05-30 10:28:42 +00:00

310 lines
9.7 KiB
Plaintext

/*
* $Id$
*/
/*
* Harbour Project source code:
* Copies the contents of a database to an SDF text file.
* Appends the contents of an SDF text file to a database.
*
* Copyright 2001-2002 David G. Holm <dholm@jsd-llc.com>
* www - http://www.harbour-project.org
*
* Copyright 2006 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
* function __dbSDF() replaced by the new one which uses
* SDF RDD I've just created
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#include "hbcommon.ch"
#include "fileio.ch"
#include "error.ch"
#include "set.ch"
HB_FILE_VER( "$Id$" )
REQUEST SDF
PROCEDURE __dbSDF( lExport, cFile, aFields, bFor, bWhile, nNext, nRecord, lRest )
IF lExport
__dbCopy( cFile, aFields, bFor, bWhile, nNext, nRecord, lRest, "SDF" )
ELSE
__dbApp( cFile, aFields, bFor, bWhile, nNext, nRecord, lRest, "SDF" )
ENDIF
RETURN
#ifdef __DBSDF_OLD_CODE__
#define SkipEOL( handle ) FSEEK( handle, nEOLSize, FS_RELATIVE )
#define AppendEOL( handle ) FWRITE( handle, HB_OSNewLine() )
#define AppendEOF( handle ) FWRITE( handle, CHR( 26 ) )
PROCEDURE __dbSDF( lExport, cFile, aFields, bFor, bWhile, nNext, nRecord, lRest )
LOCAL index, handle, cFileName := cFile, nStart, nCount, oErr, nFileLen, aStruct
LOCAL cFileEOL:=chr(13)+chr(10) // EOL defaults to windows
LOCAL nEOLSize:=2 // EOL size default to windows
// Process the file name argument.
index := RAT( ".", cFileName )
IF index > 0
// The file name might include a file extension.
IF RAT( "/", cFileName ) > index ;
.OR. RAT( "\", cFileName ) > index
// No, the file extension is in a directory name.
index := 0
END IF
END IF
IF index <= 0
// No file name extension, so provide the default.
cFileName += ".txt"
END IF
// Determine where to start and how many records to process.
IF nRecord != NIL
// The RECORD clause has the highest priority.
nStart := nRecord
nCount := 1
ELSEIF nNext != NIL
// The NEXT clause has the next highest priority.
nStart := -1
nCount := nNext
ELSEIF bWhile != NIL .OR. lRest
// The WHILE and REST clauses have equal priority.
nStart := -1
nCount := -1
ELSE
// Followed by the FOR clause or the ALL clause.
nStart := 0
nCount := -1
END IF
IF EMPTY( bFor )
// This simplifies the test that determines whether or not to
// use (i.e., import or export) any given processed record.
bFor := {||.T.}
END IF
IF lExport
// COPY TO SDF
handle := FCREATE( cFileName )
IF handle == -1
oErr := ErrorNew()
oErr:severity := ES_ERROR
oErr:genCode := EG_CREATE
oErr:subSystem := "SDF"
oErr:subCode := 1002
oErr:description := HB_LANGERRMSG( oErr:genCode )
oErr:canRetry := .T.
oErr:canDefault := .T.
oErr:fileName := cFileName
oErr:osCode := FERROR()
Eval(ErrorBlock(), oErr)
ELSE
IF nStart > -1
// Only reposition if a starting record was specified or implied.
IF nStart == 0
GO TOP
ELSE
GO (nStart)
END IF
END IF
IF EMPTY( bWhile )
// This simplifies the looping logic.
bWhile := {||.T.}
END IF
// Process the records to copy SDF.
WHILE EVAL( bWhile ) .AND. ( nCount == -1 .OR. nCount > 0 ) ;
.AND. !BOF() .AND. !EOF()
IF EVAL( bFor )
IF EMPTY( aFields )
// Process all fields.
FOR index := 1 TO FCOUNT()
ExportFixed( handle, FIELDGET( index ) )
NEXT index
ELSE
// Process the specified fields.
FOR index := 1 TO LEN( aFields )
ExportFixed( handle, FIELDGET( FIELDPOS( aFields[ index ] ) ) )
NEXT index
END IF
// Set up for the start of the next record.
AppendEOL( handle )
END IF
IF nCount != -1
nCount--
END IF
SKIP
END WHILE
IF SET(_SET_EOF)
AppendEOF( handle )
END IF
FCLOSE( handle )
END IF
ELSE
// APPEND FROM SDF
handle := FOPEN( cFileName )
IF handle == -1
oErr := ErrorNew()
oErr:severity := ES_ERROR
oErr:genCode := EG_OPEN
oErr:subSystem := "SDF"
oErr:subCode := 1001
oErr:description := HB_LANGERRMSG( oErr:genCode )
oErr:canRetry := .T.
oErr:canDefault := .T.
oErr:fileName := cFileName
oErr:osCode := FERROR()
Eval(ErrorBlock(), oErr)
ELSE
cFileEOL:=FindEOL(handle)
nEOLSize:=len(cFileEOL)
IF EMPTY( bWhile )
// This simplifies the looping logic.
bWhile := {||.T.}
END IF
nFileLen := FSEEK( handle,0,FS_END )
FSEEK( handle,0 )
aStruct := DBSTRUCT()
WHILE FSEEK( handle,0,FS_RELATIVE ) + 1 < nFileLen
APPEND BLANK
IF EMPTY( aFields )
// Process all fields.
FOR index := 1 TO FCOUNT()
IF !ImportFixed( handle,index,aStruct, cFileEOL )
EXIT
ENDIF
NEXT index
ELSE
// Process the specified fields.
FOR index := 1 TO LEN( aFields )
IF !ImportFixed( handle,FIELDPOS( aFields[ index ] ),aStruct, cFileEOL )
EXIT
ENDIF
NEXT index
END IF
// Set up for the start of the next record.
SkipEOL( handle )
END WHILE
FCLOSE( handle )
END IF
END IF
RETURN
STATIC FUNCTION ExportFixed( handle, xField )
DO CASE
CASE VALTYPE( xField ) == "C"
FWRITE( handle, xField )
CASE VALTYPE( xField ) == "D"
FWRITE( handle, DTOS( xField ) )
CASE VALTYPE( xField ) == "L"
FWRITE( handle, iif( xField, "T", "F" ) )
CASE VALTYPE( xField ) == "N"
FWRITE( handle, STR( xField ) )
OTHERWISE
RETURN .F.
END CASE
RETURN .T.
STATIC FUNCTION ImportFixed( handle, index, aStruct, cFileEOL )
LOCAL cBuffer := Space(aStruct[ index,3 ]), pos, res := .T., nRead
LOCAL vres
nRead := FREAD( handle, @cBuffer, aStruct[ index,3 ] )
IF ( pos := At( cFileEOL,cBuffer ) ) > 0 .AND. pos <= nRead
res := .F.
FSEEK( handle, -( nRead - pos + 1 ), FS_RELATIVE )
IF pos > 1
cBuffer := Left( cBuffer,pos-1 )
ELSE
RETURN res
ENDIF
ENDIF
DO CASE
CASE aStruct[ index,2 ] == "D"
vres := HB_STOD( cBuffer )
CASE aStruct[ index,2 ] == "L"
vres := iif( cBuffer == "T",.T.,.F. )
CASE aStruct[ index,2 ] == "N"
vres := VAL( cBuffer )
OTHERWISE
vres := cBuffer
END CASE
FIELDPUT( index, vres )
RETURN res
STATIC FUNCTION FindEOL(fh)
LOCAL nBufSize:=512
LOCAL cBuffer:=space(nBufSize)
LOCAL nF:=0,c:='',cResult:=''
fseek(fh,0,FS_SET)
do while fread(fh,@cBuffer,nBufSize) > 0
do while nF <= nBufSize
c:=substr(cBuffer,nF,1)
IF c==chr(10) // Unix type EOL
cResult := chr(10)
ELSEIF c==chr(13) // MSWIN or MAC
if substr(cBuffer,nF+1,1)==chr(10)
cResult := (chr(13)+chr(10))
else
cResult := chr(13)
endif
ENDIF
if len(cResult)>0
fseek(fh,0,FS_SET)
RETURN cResult
endif
++nF
enddo
enddo
fseek(fh,0,FS_SET)
if len(cResult)==0
// TODO: Report an error - can't find EOL
endif
RETURN cResult
#endif /* __DBSDF_OLD_CODE__ */