home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 25
/
CD_ASCQ_25_1095.iso
/
dos
/
prg
/
bltc125
/
bltxmpls
/
b2_xupd.c
< prev
next >
Wrap
Text File
|
1995-02-08
|
18KB
|
445 lines
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* if 16-bit program, use:
* #define __Bullet16
* #include "bullet2.h
* otherwise (32-bit), do as below
*/
#include "bullet2.h"
#define BULLET BULLET32 /* if 32-bit main(), go through BULLET32 */
/* b2_xupd.c showing:
* 1) DBF create
* 2) index create x 2
* 3) inserting into the database via InsertXB, updating entire database
* 4) accessing the database with either index via GetFirst/Next/EqualXB
* 5) updating the database via UpdateXB
*/
#pragma pack(1)
struct InitPack IP;
struct ExitPack EP;
struct FieldDescType fieldList[5]; /* 5 since 5 fields used in AnyRecType */
struct CreateDataPack CDP;
struct CreateKeyPack CKP;
struct OpenPack OP;
struct HandlePack HP;
struct AccessPack AP[2]; /* 2 since 2 "linked" index files used */
struct DosFilePack DFP;
struct AnyRecType {
char tag; /* tag not formal field but required */
char employeeNumber[6];
char lastName[20];
char firstName[20];
char SSN[10];
char andSoOn[7];
};
struct AnyRecType dataRec; /* 5 fields, 64-byte record */
#pragma pack()
int rez;
int rez2;
USHORT handleData;
USHORT handleIndex0;
USHORT handleIndex1;
char tmpStr[129];
char empData[] = "$EMPDATA.DBF";
char empIX0[] = "$EMPDATA.IX0";
char empIX1[] = "$EMPDATA.IX1";
char keyExpression0[] = "EMP_NO";
char keyExpression1[] = "SUBSTR(LNAME,1,5)+SUBSTR(FNAME,1,1)+SUBSTR(SSN,6,4)";
char keyBuffer[64];
int main()
{
setbuf(stdout,NULL);
/* this example presumes a known record layout -- also possible is
to create the record layout on-the-fly (see [TBD].C) */
/* build the field list of the data file -- it must match byte-for-byte
AnyRecType, but structure names do not need to match actual field names */
memset(fieldList,0,sizeof(fieldList)); /* clear out all fields */
strcpy(fieldList[0].fieldName, "EMP_NO");
fieldList[0].fieldType = 'N'; /* stored in DBF as ASCII numbers */
fieldList[0].fieldLen = 6; /* must match record structure */
fieldList[0].fieldDC = 0; /* no decimal point */
strcpy(fieldList[1].fieldName, "LNAME");
fieldList[1].fieldType = 'C';
fieldList[1].fieldLen = 20;
fieldList[1].fieldDC = 0;
strcpy(fieldList[2].fieldName, "FNAME");
fieldList[2].fieldType = 'C';
fieldList[2].fieldLen = 20;
fieldList[2].fieldDC = 0;
strcpy(fieldList[3].fieldName, "SSN");
fieldList[3].fieldType = 'C'; /* C so we can use SUBSTR() */
fieldList[3].fieldLen = 10; /* 9 +1 for \0 (see below) */
fieldList[3].fieldDC = 0;
strcpy(fieldList[4].fieldName, "ETC");
fieldList[4].fieldType = 'C';
fieldList[4].fieldLen = 7;
fieldList[4].fieldDC = 0;
/* must do InitXB before any other Bullet routine */
IP.func = INITXB;
IP.JFTmode = 1; /* allow up to 250 files open */
rez = BULLET(&IP);
if (rez==0) {
EP.func = ATEXITXB;
rez = BULLET(&EP);
if (rez!=0)
puts("bleep! DosExitList() must be full. Continuing.\n");
/* delete any current files used by this program --
Bullet won't create a file if it already exists
(DOS error 110 is returned on attempts to) */
DFP.func = DELETEFILEDOS;
DFP.filenamePtr = empData;
rez = BULLET(&DFP); /* ignore not found errors */
DFP.filenamePtr = empIX0;
rez = BULLET(&DFP);
DFP.filenamePtr = empIX1;
rez = BULLET(&DFP);
CDP.func = CREATEDXB;
CDP.filenamePtr = empData;
CDP.noFields = 5;
CDP.fieldListPtr = fieldList;
CDP.fileID = 3; /* standard DBF file ID byte */
rez = BULLET(&CDP);
if (rez==0) {
OP.func = OPENDXB;
OP.filenamePtr = empData;
OP.asMode = READWRITE | DENYNONE;
rez = BULLET(&OP);
if (rez==0) {
handleData = OP.handle;
CKP.func = CREATEKXB;
CKP.filenamePtr = empIX0;
CKP.keyExpPtr = keyExpression0;
CKP.xbLink = handleData;
CKP.keyFlags = cLONG | cUNIQUE; /* 32-bit binary key */
CKP.codePageID = -1; /* eventhough data field is ASCII */
CKP.countryCode = -1;
CKP.collatePtr = NULL;
rez = BULLET(&CKP);
if (rez==0) {
CKP.func = CREATEKXB;
CKP.filenamePtr = empIX1;
CKP.keyExpPtr = keyExpression1;
CKP.xbLink = handleData;
CKP.keyFlags = cCHAR | cUNIQUE; /* character key */
CKP.codePageID = -1;
CKP.countryCode = -1;
CKP.collatePtr = NULL;
rez = BULLET(&CKP);
if (rez==0) {
OP.func = OPENKXB;
OP.filenamePtr = empIX0;
OP.asMode = READWRITE | DENYNONE;
OP.xbLink = handleData;
rez = BULLET(&OP);
if (rez==0) {
handleIndex0 = OP.handle;
OP.func = OPENKXB;
OP.filenamePtr = empIX1;
OP.asMode = READWRITE | DENYNONE;
OP.xbLink = handleData;
rez = BULLET(&OP);
if (rez==0) {
handleIndex1 = OP.handle;
/* AT THIS POINT, we have created the single DBF data file and its two
related index files, and opened them, ready for work */
dataRec.tag = ' '; /* set to "not deleted" */
/* note the use of strncpy() -- we don't want \0 involved since this field is
of type N and so should be right-aligned, ASCII (for DBF compatibility) */
strncpy(dataRec.employeeNumber," 1",6);
/* since these fields are C type, they can be treated as regular strings with
\0 appended -- SSN is being used as a C type field, and so its size was made
to be 10 bytes; you could use strncpy() on SSN and change it to SSN[9]... */
strcpy(dataRec.lastName,"Huth");
strcpy(dataRec.firstName,"Cornel");
strcpy(dataRec.SSN,"123456789");
strcpy(dataRec.andSoOn,"abc21_");
/* record has been built, add it to DBF and insert its keys into index files */
AP[0].func = INSERTXB;
AP[0].handle = handleIndex0;
AP[0].recPtr = &dataRec;
AP[0].keyPtr = keyBuffer;
AP[0].nextPtr = &AP[1];
AP[1].func = INSERTXB;
AP[1].handle = handleIndex1;
AP[1].recPtr = &dataRec;
AP[1].keyPtr = keyBuffer;
AP[1].nextPtr = NULL;
rez = BULLET(&AP);
if (rez==0)
/* data record has just been added and each index file has had a key
inserted pointing to this data record -- logically, the following
exists now:
<tag> EMP_NO LNAME FNAME SSN ETC
in the DBF: ' ',' 1','Huth...','Cornel...','123456789\0','abc21_\0'
in index 0: 1 (as a binary, 32-bit value, pointing to DBF record)
in index 1: 'Huth C6789' (pointing to DBF record (no \0 in this case)
'...' signify NULL bytes to end of field (set to NULL by memset())
the comma logically demarks the fields (there is no physical separator)
index 0 has a binary 0x00000001 value in it and points to the record added
index 1 has the 'Huth<space>C6789' in it and points to the record added
*/
/* note that below we use AP[0] when accessing via the first index file, and
AP[1] when accessing via the second -- this is not actually required
since the GET...XB routines are not transactioned-based, but it can be
convenient since many of the AP[]. members will already be setup -- below
we setup all members, even if already set, just for show */
/* AT THIS POINT, we have a single data record in the DBF, and a single
key in each of the index files that points to that record -- the
following show several _different_ methods of accessing this database: */
/* GETFIRSTXB grabs the first key in the index file and locates the data
record it is assigned to, returning both in dataRec and keyBuffer: */
AP[0].func = GETFIRSTXB;
AP[0].handle = handleIndex0;
AP[0].recPtr = &dataRec;
AP[0].keyPtr = keyBuffer;
rez = BULLET(&AP[0]);
if (rez==0) {
puts("GetFirstXB, index 0:");
/* dataRec has DBF record data, keyBuffer has key of index file 1 */
printf("recNo: %uh tag: %c emp#: %.6s name: %s,%s SSN: %s misc: %s\n",
AP[0].recNo,
dataRec.tag,
dataRec.employeeNumber,
dataRec.lastName,dataRec.firstName,
dataRec.SSN,dataRec.andSoOn);
}
/* as above, but using index file 1 to access the data file */
AP[1].func = GETFIRSTXB;
AP[1].handle = handleIndex1;
AP[1].recPtr = &dataRec;
AP[1].keyPtr = keyBuffer;
rez = BULLET(&AP[1]);
if (rez==0) {
puts("GetFirstXB, index 1:");
/* dataRec has DBF record data, keyBuffer has key of index file 2 */
printf("recNo: %uh tag: %c emp#: %.6s name: %s,%s SSN: %s misc: %s\n",
AP[1].recNo,
dataRec.tag,
dataRec.employeeNumber,
dataRec.lastName,dataRec.firstName,
dataRec.SSN,dataRec.andSoOn);
}
/* GETEQUALXB grabs the key that _EXACTLY_ matches the key you have placed in
keyBuffer[] -- if an exact match is not found, you can do a GETNEXTXB or a
GETPREVXB to locate the next/prev logical in-order key and record */
/* note that since index 1 is using binary key values, set the key to a
binary value -- if this index file allowed duplicates, you would also
need to specify the enumerator word (see [TBD] in the manual) */
*((long *)keyBuffer) = 1L;
AP[0].func = GETEQUALXB;
AP[0].handle = handleIndex0;
AP[0].recPtr = &dataRec;
AP[0].keyPtr = keyBuffer;
rez = BULLET(&AP[0]);
if (rez==0) {
puts("GetEqualXB, key of (binary) 1, index 0:");
/* dataRec has DBF record data, keyBuffer has key of index file 2 */
printf("recNo: %uh tag: %c emp#: %.6s name: %s,%s SSN: %s misc: %s\n",
AP[1].recNo,
dataRec.tag,
dataRec.employeeNumber,
dataRec.lastName,dataRec.firstName,
dataRec.SSN,dataRec.andSoOn);
}
else if (rez==1200) { /* 1200 is "KEY NOT FOUND" */
puts("GetEqualXB, exact match not found, getting next...");
/* if no exact match, perform a GETNEXTXB
or GETPREVXB to find the logical next/prev key
that _would_have_ preceded/followed the key
you specified */
AP[0].func = GETNEXTXB;
rez = BULLET(&AP[0]);
if (rez==0) {
puts("GetEqualXB+GetNextXB, key of (binary) 1, index 0:");
/* dataRec has DBF record data, keyBuffer has key of index file 2 */
printf("recNo: %uh tag: %c emp#: %.6s name: %s,%s SSN: %s misc: %s\n",
AP[1].recNo,
dataRec.tag,
dataRec.employeeNumber,
dataRec.lastName,dataRec.firstName,
dataRec.SSN,dataRec.andSoOn);
}
}
else
puts("...other error");
/* as above, but using index file 2 to access the data file -- here we specify
that we want to locate to the first "H" in the index file (the two nulls
are added so that we are assured that we start at the very first "H", and
not "H<any-bytes>") -- there won't he an "H" only key, as expected, so we
do a GETNEXTXB to followup the request, thereby getting the first key that
starts with an H (so far, only "Huth C6789" exists anyway): */
strcpy(keyBuffer,"H\0\0");
AP[1].func = GETEQUALXB;
AP[1].handle = handleIndex1;
AP[1].recPtr = &dataRec;
AP[1].keyPtr = keyBuffer;
rez = BULLET(&AP[1]);
if (rez==1200) { /* as expected, KEY NOT FOUND */
AP[1].func = GETNEXTXB;
rez = BULLET(&AP[1]);
if (rez==0) {
puts("GetEqualXB/GetNextXB, ('H' or greater), index 1:");
/* dataRec has DBF record data, keyBuffer has key of index file 2 */
printf("recNo: %uh tag: %c emp#: %.6s name: %s,%s SSN: %s misc: %s\n",
AP[1].recNo,
dataRec.tag,
dataRec.employeeNumber,
dataRec.lastName,dataRec.firstName,
dataRec.SSN,dataRec.andSoOn);
}
}
/* AT THIS POINT, we can update the just gotten record and its related index
files, all with a single call, UpdateXB -- what we do here is change the
data record so that, in this example, both keys change, requiring Bullet
to update the index files and then update the data file -- all done
automatically -- EMP_NO is changed, as is SSN */
/* note that dataRec is already setup from previous work (the GETNEXTXB above)
and AP[1].recNo is also setup (see [TBD] in the manual) --
since AP[0].recNo is not necessarily set up, assign the known-to-be-it
record number in AP[1].recNo to AP[0].recNo */
strncpy(dataRec.employeeNumber," 2",6);
strcpy(dataRec.SSN,"123459876");
/* the above changes force both index files to update, as well as the DBF */
AP[0].func = UPDATEXB;
AP[0].handle = handleIndex0;
AP[0].recNo = AP[1].recNo; /* from above call */
AP[0].recPtr = &dataRec;
AP[0].keyPtr = keyBuffer;
AP[0].nextPtr = &AP[1];
AP[1].func = UPDATEXB;
AP[1].handle = handleIndex1;
/* AP[1].recNo already setup from above */
AP[1].recPtr = &dataRec;
AP[1].keyPtr = keyBuffer;
AP[1].nextPtr = NULL;
rez = BULLET(&AP);
if (rez==0) {
/* since a transaction routine, must check
first .stat for non-0 (error with data file) */
if (AP[0].stat!=0)
puts("UpdateXB failed at record update");
else
puts("UpdateXB completed okay");
}
else {
/* if non-0, rez is index of AP[] that failed
-- rez-1 since rez returned as 1-based index */
rez2 = AP[rez-1].stat;
printf("UpdateXB failed, index: %uh, error: %u\n",(rez-1),rez2);
}
/* Winding down this example... */
/* close up shop by closing files */
HP.func = CLOSEKXB;
HP.handle = handleIndex1;
rez = BULLET(&HP);
if (rez!=0)
printf("closeKXB, index 1 failed: %u\n",rez);
}
else /* open ix1 */
printf("openKXB failed, index 1, rez: %u\n",rez);
HP.func = CLOSEKXB;
HP.handle = handleIndex0;
rez = BULLET(&HP);
if (rez!=0)
printf("closeKXB, index 0 failed: %u\n",rez);
}
else /* open ix0 */
printf("openKXB failed, index 0, rez: %u\n",rez);
}
else /* create ix1 */
printf("createKXB failed, index 1, rez: %u\n",rez);
}
else /* create ix0 */
printf("createKXB failed, index 0, rez: %u\n",rez);
}
else /* open DBF */
printf("openDXB failed, rez: %u\n",rez);
}
else /* create DBF */
printf("createDXB failed, rez: %u\n",rez);
EP.func = EXITXB;
rez = BULLET(&EP);
}
else /* init */
printf("initXB failed, rez: %u\n",rez);
return(0);
}
/* program exit */