home *** CD-ROM | disk | FTP | other *** search
- DECLARE SUB DoAssignFields (FLA() AS ANY, NoFields%, FieldData$())
- DECLARE SUB DoGetFieldDesc (FieldData$())
- DECLARE SUB DoGetKeyExpression (keyx$)
-
- REM $INCLUDE: 'QBXDBF.BI'
-
- DEFINT A-Z
-
- 'QBXDBF sample 1
- '-read data from an ASCII fixed-length record file
- '-create a .DBF data file and index it, incremental or mass reindex
- '-count all keys to measure key access time
- '-list all records just to look at them
-
- '31-Jul-91
- 'Cornel Huth
- '-----------
- '30-Sep-91-chh
- 'added /2:drivepath option to use second drive as XDATA1.DAT source
-
- '-------------
- 'C>bc XDBF1/o;
- 'C>link /noe XDBF1+nocom,XDBF1.EXE,nul,QBXDBF
- '
- 'C>XDBF1 [/I][/NL][/DP]
- '/I=do incremental indexing, /NL=no list all
- '/DP=delete every other record/pack+reindex
- '/2:d:\tmp\ =allow XDATA1.DAT to reside on other drivepath
- '
- 'common data structure in both the raw and the dbf file
- 'doing it this way makes it easier to assign one to the other
-
- TYPE CommonRecordTYPE
- partno AS STRING * 8
- desc AS STRING * 20
- cost AS STRING * 8
- pkgqty AS STRING * 2
- status AS STRING * 1
- END TYPE '39
-
- 'raw data file FIXED.DAT has this record layout
- 'raw data happens to be already sorted, matters not
-
- TYPE RawRecordTYPE
- info AS CommonRecordTYPE
- crlf AS STRING * 2
- END TYPE '41
- DIM RawRecord AS RawRecordTYPE
-
- 'DBF translation of FIXED.DAT record layout
-
- TYPE DBFRecordTYPE
- tag AS STRING * 1
- info AS CommonRecordTYPE
- END TYPE '40
- DIM DBFRecord AS DBFRecordTYPE
-
- cl$ = COMMAND$
-
- CLS
- nul = VersionDBF(version$)
- PRINT "WELCOME TO "; version$; " doing a little dBASE..."
-
- 'initialize QBXDBF to 1 key file, 1 data file, max of 5 fields per record
-
- NoFields = 5
- stat = InitDBF(1, 1, NoFields)
- IF stat THEN GOTO Abend
-
- 'example of how you could setup the field descriptions
- 'here we load the field descriptions into FieldData$() first
-
- REDIM FieldData$(1 TO NoFields)
- DoGetFieldDesc FieldData$()
-
- 'array FLA() is the data that determines how QBXDBF reads a DBF data file
- 'here we copy the field info just loaded into FieldData$() to FLA()
-
- REDIM FLA(1 TO NoFields) AS DBFFieldListTYPE
- DoAssignFields FLA(), NoFields, FieldData$()
-
- 'example of how you could get the key expression
-
- DoGetKeyExpression keyx$
-
- 'create the DBF data file (CATALOG.DBF) based on the field data in FLA()
- 'if it exists delete it
-
- dbfile$ = "catalog.dbf"
- PRINT ".create "; dbfile$
- IF FileExists(dbfile$ + CHR$(0)) = -1 THEN KILL dbfile$
- stat = CreateDataDBF(dbfile$, NoFields, FLA())
- IF stat THEN GOTO Abend
-
- 'open the DBF file using QBXDBF file handle dbfile
- 'open for compatible mode read/write access
-
- PRINT ".use "; dbfile$
- dbfile = FreeDataFileDBF: IF dbfile = -1 THEN GOTO Abend
- OpenMode = 2
- stat = OpenDataDBF(dbfile$, dbfile, OpenMode)
- IF stat THEN GOTO Abend
-
- 'create the key file (CATALOG.DEX) based on keyx$ and the open CATALOG.DBF
- 'if it exists delete it
-
- kyfile$ = "catalog.dex"
- PRINT ".index on "; keyx$; " to "; kyfile$
- IF FileExists(kyfile$ + CHR$(0)) = -1 THEN KILL kyfile$
- stat = CreateKeyDBF(kyfile$, keyx$, dbfile)
- IF stat THEN GOTO Abend
-
- 'open the key file using QBXDBF file handle kyfile
- 'open for compatible mode read/write access
-
- kyfile = FreeKeyFileDBF: IF kyfile = -1 THEN GOTO Abend
- OpenMode = 2
- stat = OpenKeyDBF(kyfile$, kyfile, dbfile, OpenMode)
- IF stat THEN GOTO Abend
-
- 'if you set IndexOn = -1 then indexing occurs concurrently when adding records
- 'that is not QBXDBF logic but rather just this program example
-
- IndexOn = 0
- IF INSTR(cl$, "/I") THEN IndexOn = -1
-
- IF IndexOn THEN
- PRINT ".set index to "; kyfile$
- ELSE
- PRINT ".set index to"
- END IF
-
- 'everything's setup to go
- 'we could use QBXDBF file I/O like ReadDevice(), DeleteFile(), etc., but
- 'for this example BASIC file I/O is used for simplicity
-
- drv1 = INSTR(cl$, "/2:")
- dpath$ = ""
- IF drv1 THEN
- dpath$ = MID$(cl$, drv1 + 3)
- FOR i = 1 TO LEN(dpath$)
- IF MID$(dpath$, i, 1) = " " THEN dpath$ = LEFT$(dpath$, i - 1): EXIT FOR
- NEXT
- IF RIGHT$(dpath$, 1) <> "\" THEN dpath$ = dpath$ + "\"
- END IF
- rawfile$ = dpath$ + "xdata1.dat"
- rawfile = FREEFILE
- OPEN rawfile$ FOR BINARY AS rawfile
-
- 'setup pointer to DBFRecord
-
- DBFRecord.tag = " " 'init deleted tag to 'not deleted' (deleted='*')
- vseg = VARSEG(DBFRecord)
- voff = VARPTR(DBFRecord)
-
- 'read a fixed-length record from raw file and add it to the dbfile
-
- PRINT ".append from "; rawfile$
- PRINT " Records added";
-
- 'preload first raw record
-
- s1! = TIMER
- GET rawfile, , RawRecord
- DO WHILE NOT EOF(rawfile)
-
- 'update DBFRecord only with the meaningful data in RawRecord
- 'write the DBF record
-
- DBFRecord.info = RawRecord.info
-
- stat = AddRecordDBF(dbfile, vseg, voff, recordno&)
- LOCATE , 15: PRINT recordno&;
- IF stat THEN EXIT DO
-
- 'add the key to the index file
- '--although QBXDBF is fast, indexing now would be slower
- '--than doing a ReindexDBF() all at once, as done below
-
- IF IndexOn THEN
- stat = AddKeyDBF(kyfile, recordno&, vseg, voff)
- IF stat THEN EXIT DO
- END IF
-
- 'load next raw record
-
- GET rawfile, , RawRecord
- LOOP
- e1! = TIMER
- CLOSE rawfile
- PRINT USING " (####.# secs)"; e1! - s1!
- IF stat THEN GOTO Abend
-
- 'do a fast reindex
- 'copy kyfile's structure to reindex$ (delete reindex$ first),
- 'reindex dbfile (in this case just index it), close kyfile, delete it,
- 'rename reindex$ to kyfile$, then open it as the new kyfile$
-
- IF IndexOn = 0 THEN
- PRINT ".set index to "; kyfile$
- PRINT ".reindex";
- reindex$ = "$reindex.$$$"
- IF FileExists(reindex$ + CHR$(0)) = -1 THEN KILL reindex$
- IF stat = 0 THEN stat = CopyKeyStrucDBF(kyfile, reindex$)
- s1! = TIMER
- IF stat = 0 THEN stat = ReIndexDBF(kyfile, dbfile, reindex$)
- e1! = TIMER
- PRINT USING " (####.# secs)"; e1! - s1!
- stat2 = CloseKeyDBF(kyfile)
- IF stat2 = 0 THEN KILL kyfile$
- IF stat2 = 0 THEN NAME reindex$ AS kyfile$
- kyfile = FreeKeyFileDBF: IF kyfile = -1 THEN GOTO Abend
- OpenMode = 2
- stat = OpenKeyDBF(kyfile$, kyfile, dbfile, OpenMode)
- IF stat THEN GOTO Abend
- END IF
-
- 'delete every other record, then pack+reindex
-
- IF INSTR(cl$, "/DP") THEN
- PRINT ".delete for mod(recno(),2)=0"
- PRINT " Records deleted";
- stat = GetFirstDBF(kyfile, dbfile, vseg, voff) 'leave odd records
- DO UNTIL stat
- stat = GetNextDBF(kyfile, dbfile, vseg, voff)
- IF stat = 0 THEN
- stat = GetPositionDBF(kyfile, recno&)
- IF stat = 0 THEN stat = DeleteRecordDBF(dbfile, recno&)
- cnt& = cnt& + 1
- LOCATE , 17: PRINT cnt&;
- IF stat = 0 THEN stat = GetNextDBF(kyfile, dbfile, vseg, voff)
- END IF
- LOOP
-
- 'stat=202 is normal in the case above, it means end of file reached
- IF stat = 202 THEN stat = 0
- PRINT
-
- IF stat = 0 THEN
- PRINT ".pack";
- packfile$ = "$datpack.$$$"
- IF FileExists(packfile$ + CHR$(0)) = -1 THEN KILL packfile$
- keyfile$ = "$keypack.$$$"
- IF FileExists(keyfile$ + CHR$(0)) = -1 THEN KILL keyfile$
- s1! = TIMER
- stat = PackDBF(dbfile, kyfile, packfile$, keyfile$)
- e1! = TIMER
- PRINT USING " (####.# secs, includes reindex)"; e1! - s1!
- IF stat = 0 THEN
- stat = CloseDataDBF(dbfile)
- IF stat = 0 THEN KILL dbfile$
- IF stat = 0 THEN NAME packfile$ AS dbfile$
-
- IF stat = 0 THEN stat = CloseKeyDBF(kyfile)
- IF stat = 0 THEN KILL kyfile$
- IF stat = 0 THEN NAME keyfile$ AS kyfile$
-
- IF stat = 0 THEN
- dbfile = FreeDataFileDBF: IF dbfile = -1 THEN GOTO Abend
- OpenMode = 2
- stat = OpenDataDBF(dbfile$, dbfile, OpenMode)
- IF stat THEN GOTO Abend
-
- kyfile = FreeKeyFileDBF: IF kyfile = -1 THEN GOTO Abend
- OpenMode = 2
- stat = OpenKeyDBF(kyfile$, kyfile, dbfile, OpenMode)
- IF stat THEN GOTO Abend
- END IF
- END IF
- END IF
- END IF
-
- IF stat THEN GOTO Abend
-
- 'count all keys of kyfile$
- 'this is a measure of index access speed only
-
- cnt& = 0&
- PRINT ".count"
- PRINT " Keys counted";
- s1! = TIMER
- stat = RetrieveFirst(kyfile, Qkey$, Qrecno&)
- DO UNTIL stat
- cnt& = cnt& + 1
- LOCATE , 14: PRINT cnt&;
- stat = RetrieveNext(kyfile, Qkey$, Qrecno&)
- LOOP
- e1! = TIMER
- PRINT USING " (####.# secs)"; e1! - s1!
-
- 'stat=202 is normal in the case above, it means end of file reached
- IF stat = 202 THEN stat = 0
- IF stat THEN GOTO Abend
-
- 'list all records of dbfile$ inorder by key
-
- IF INSTR(cl$, "/NL") = 0 THEN
- PRINT ".list all"
- PRINT "RECORD PARTNO-- DESC---------------- COST---- PKGQTY STATUS"
- use$ = " ##### &\ \ \ \ \ \ \\ \\"
- VIEW PRINT CSRLIN TO 24
-
- DIM check AS DBFRecordTYPE
- check.info.partno = STRING$(8, 0)
-
- stat = GetFirstDBF(kyfile, dbfile, vseg, voff)
- DO UNTIL stat
- nul = GetPositionDBF(kyfile, recno&)
- PRINT USING use$; recno&; DBFRecord.tag; DBFRecord.info.partno; DBFRecord.info.desc; DBFRecord.info.cost; DBFRecord.info.pkgqty; DBFRecord.info.status
-
- IF check.info.partno > DBFRecord.info.partno THEN BEEP: SLEEP
- check.info.partno = DBFRecord.info.partno
-
- stat = GetNextDBF(kyfile, dbfile, vseg, voff)
- LOOP
- VIEW PRINT
- LOCATE 24, 1
- PRINT ".quit";
-
- 'stat=202 is normal in the case above, it means end of file reached
- IF stat = 202 THEN stat = 0
- END IF
-
- Abend:
- IF stat THEN
- stat2 = GetXEInfo(class, action, locus)
- PRINT
- PRINT "I/O error"; stat; "occured ( extended info error:"; stat2;
- PRINT "class:"; class; "action:"; action; "locus:"; locus; ")"
- END IF
-
- 'no stat check on the DBF closes though it would be better to do so
-
- stat = CloseDataDBF(dbfile)
- stat = CloseKeyDBF(kyfile)
- SYSTEM
-
- SUB DoAssignFields (FLA() AS DBFFieldListTYPE, NoFields, FieldData$())
-
- 'assign the FieldData to FLA()
-
- FOR i = 1 TO NoFields
- FLA(i).FieldName = MID$(FieldData$(i), 1, 10)
- FLA(i).FieldType = MID$(FieldData$(i), 12, 1)
- FLA(i).FieldLen = VAL(MID$(FieldData$(i), 14, 2))
- FLA(i).FieldDC = VAL(MID$(FieldData$(i), 17, 1))
- NEXT
-
- END SUB
-
- SUB DoGetFieldDesc (FieldData$())
-
- 'in a SUB just for simplicity and clarity
- 'fixed-form for simplicity, whatever works for you
-
- FieldData$(1) = "PARTNO /C/08/0"
- FieldData$(2) = "DESC /C/20/0"
- FieldData$(3) = "COST /N/08/2"
- FieldData$(4) = "PKGQTY /N/02/0"
- FieldData$(5) = "STATUS /C/01/0"
-
- END SUB
-
- SUB DoGetKeyExpression (keyx$)
-
- 'just an example
-
- keyx$ = "upper(partno)"
-
- END SUB
-
-