home *** CD-ROM | disk | FTP | other *** search
/ Datatid 1999 #6 / Datatid_1999-06.iso / internet / Tango352Promo / P.SQL / PTKPKG.1 / BTRSAM32.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-11-07  |  18.4 KB  |  583 lines

  1. {****************************************************************************
  2. **
  3. **  Copyright 1982-1997 Pervasive Software Inc. All Rights Reserved
  4. **
  5. ****************************************************************************}
  6. {****************************************************************************
  7.    BTRSAM32.DPR
  8.       This is a simple sample designed to allow you to confirm your
  9.       ability to compile, link, and execute a Btrieve application for
  10.       your target 32-bit environment using your compiler tools.
  11.  
  12.       This program demonstrates the Delphi interface for Btrieve on 32-Bit
  13.       MS Windows NT and Windows 95, for Delphi 2.0 and 3.0.
  14.  
  15.     This program does the following operations on the sample file:
  16.     - gets the Microkernel Database Engine version using BTRVID
  17.     - opens sample.btr
  18.     - gets a record on a known value of Key 0
  19.     - displays the retrieved record
  20.     - performs a stat operation
  21.     - creates an empty 'clone' of sample.btr and opens it
  22.     - performs a 'Get Next Extended' operation to extract a subset
  23.       of the records in sample.btr
  24.     - inserts those records into the cloned file
  25.     - closes both files
  26.  
  27.       IMPORTANT:
  28.       You must specify the complete path to the directory that contains
  29.       the sample Btrieve data file, 'sample.btr'.  See IMPORTANT, below.
  30.  
  31.       Delphi 2.0/3.0 Btrieve projects must be compiled after selecting the
  32.       following from the Delphi project environment pull-down menus:
  33.  
  34.         PROJECT
  35.            OPTIONS...
  36.               COMPILER
  37.                  CODE GENERATION
  38.                     ALIGNED RECORD FIELDS ( de-select this )
  39.  
  40.         If you don't do this step, when the record is printed out, it will
  41.         seem 'jumbled' because the record structure is not byte-packed.
  42.  
  43.         You may, instead, use the (*A-*) compiler directive, or declare all
  44.         records as "packed," as shown below.  For more information, see the
  45.         Delphi documentation.
  46.  
  47.       PROJECT FILES:
  48.          - btr32.dpr       Borland project file
  49.          - btr32.dof       Borland project file
  50.          - btrsam32.dfm    Borland project file
  51.          - btrsam32.pas    Source code for the simple sample
  52.          - btrapi32.pas    Delphi interface to Btrieve
  53.          - btrconst.pas    Btrieve constants file
  54.  
  55. ****************************************************************************}
  56. unit btrsam32;
  57.  
  58. interface
  59.  
  60. uses
  61.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  62.   StdCtrls, BtrConst, BtrAPI32;
  63.  
  64. {*****************************************************************************
  65.    Program Constants
  66. *****************************************************************************}
  67. const
  68.   { program constants }
  69.   MY_THREAD_ID        = 50;
  70.   EXIT_WITH_ERROR     = 1;
  71.   VERSION_OFFSET      = 0;
  72.   REVISION_OFFSET     = 2;
  73.   PLATFORM_ID_OFFSET  = 4;
  74.  
  75.   {********************************************************************
  76.       IMPORTANT: You should modify the following to specify the
  77.                 complete path to 'sample.btr' for your environment.
  78.   ********************************************************************}
  79.   FILE_1              = 'c:\pvsw\samples\sample.btr';
  80.   FILE_2              = 'c:\pvsw\samples\sample2.btr';
  81.  
  82. {***************************************************************************
  83.   Record type definitions for Version operation
  84. ****************************************************************************}
  85. type
  86.   CLIENT_ID = packed record
  87.     networkandnode : array[1..12] of char;
  88.     applicationID  : array[1..3] of char;
  89.     threadID       : smallint;
  90.   end;
  91.  
  92.   VERSION_STRUCT = packed record
  93.     version   : smallint;
  94.     revision  : smallint;
  95.     MKDEId    : char;
  96.   end;
  97.  
  98. {***************************************************************************
  99.   Definition of record from 'sample.btr'
  100. ****************************************************************************}
  101.  
  102.   {* Use 'zero-based' arrays of char for writeln() compatibility *}
  103.   PERSON_STRUCT = packed record
  104.     ID          : longint;
  105.     FirstName   : array[0..15] of char;
  106.     LastName    : array[0..25] of char;
  107.     Street      : array[0..30] of char;
  108.     City        : array[0..30] of char;
  109.     State       : array[0..2]  of char;
  110.     Zip         : array[0..10] of char;
  111.     Country     : array[0..20] of char;
  112.     Phone       : array[0..13] of char;
  113.   end;
  114.  
  115. {***************************************************************************
  116.   Record type definitions for Stat and Create operations
  117. ****************************************************************************}
  118.   FILE_SPECS = packed record
  119.     recLength   : smallint;
  120.     pageSize    : smallint;
  121.     indexCount  : smallint;
  122.     reserved    : array[0..3] of char;
  123.     flags       : smallint;
  124.     dupPointers : byte;
  125.     notUsed     : byte;
  126.     allocations : smallint;
  127.   end;
  128.  
  129.   KEY_SPECS = packed record
  130.     position : smallint;
  131.     length : smallint;
  132.     flags : smallint;
  133.     reserved : array [0..3] of char;
  134.     keyType : char;
  135.     nullChar : char;
  136.     notUsed : array[0..1] of char;
  137.     manualKeyNumber : byte;
  138.     acsNumber : byte;
  139.   end;
  140.  
  141.   FILE_CREATE_BUF = packed record
  142.     fileSpecs : FILE_SPECS;
  143.     keySpecs  : array[0..4] of KEY_SPECS;
  144.   end;
  145.  
  146. {***************************************************************************
  147.   Record type definitions for Get Next Extended operation
  148. ****************************************************************************}
  149.  
  150.   GNE_HEADER = packed record
  151.     descriptionLen  : smallint;
  152.     currencyConst   : array[0..1] of char;
  153.     rejectCount     : smallint;
  154.     numberTerms     : smallint;
  155.   end;
  156.  
  157.   TERM_HEADER = packed record
  158.     fieldType       : byte;
  159.     fieldLen        : smallint;
  160.     fieldOffset     : smallint;
  161.     comparisonCode  : byte;
  162.     connector       : byte;
  163.     value           : array[0..2] of char;
  164.   end;
  165.  
  166.   RETRIEVAL_HEADER = packed record
  167.     maxRecsToRetrieve   : smallint;
  168.     noFieldsToRetrieve  : smallint;
  169.   end;
  170.  
  171.   FIELD_RETRIEVAL_HEADER = packed record
  172.     fieldLen    : smallint;
  173.     fieldOffset : smallint;
  174.   end;
  175.  
  176.   PRE_GNE_BUFFER = packed record
  177.     gneHeader : GNE_HEADER;
  178.     term1     : TERM_HEADER;
  179.     term2     : TERM_HEADER;
  180.     retrieval : RETRIEVAL_HEADER;
  181.     recordRet : FIELD_RETRIEVAL_HEADER;
  182.   end;
  183.  
  184.   RETURNED_REC = packed record
  185.     recLen        : smallint;
  186.     recPos        : longint;
  187.     personRecord  : PERSON_STRUCT;
  188.   end;
  189.  
  190.   POST_GNE_BUFFER = packed record
  191.     numReturned : smallint;
  192.     recs        : packed array[0..19] of RETURNED_REC;
  193.   end;
  194.  
  195.   GNE_BUFFER_PTR = ^GNE_BUFFER;
  196.   GNE_BUFFER = packed record
  197.   case byte of
  198.     1 : (preBuf  : PRE_GNE_BUFFER);
  199.     2 : (postBuf : POST_GNE_BUFFER);
  200.   end;
  201.  
  202. {***************************************************************************
  203.   Delphi-generated form definition
  204. ****************************************************************************}
  205.   TForm1 = class(TForm)
  206.     RunButton: TButton;
  207.     ExitButton: TButton;
  208.     ListBox1: TListBox;
  209.     procedure FormCreate(Sender: TObject);
  210.     procedure ExitButtonClick(Sender: TObject);
  211.     procedure RunButtonClick(Sender: TObject);
  212.   private
  213.   { Private declarations }
  214.     ArrowCursor,
  215.     WaitCursor:   HCursor;
  216.     status:       smallint;
  217.     bufferLength: smallint;
  218.     personRecord: PERSON_STRUCT;
  219.     recordsRead:  longint;
  220.     procedure RunTest;
  221.   public
  222.     { Public declarations }
  223.   end;
  224.  
  225. var
  226.   Form1: TForm1;
  227.  
  228. {***********************************************************************
  229.   Program starts here
  230. ************************************************************************}
  231. implementation
  232.  
  233. {$R *.DFM}
  234.  
  235. {***********************************************************************
  236.    Program Variables
  237. ************************************************************************}
  238. var
  239.   { Btrieve function parameters }
  240.   posBlock1     : string[128];
  241.   posBlock2     : string[128];
  242.   dataBuffer    : array[0..255] of char;
  243.   dataLen       : word;
  244.   keyBuf1       : string[255];
  245.   keyBuf2       : string[255];
  246.   keyNum        : smallint;
  247.  
  248.   btrieveLoaded : boolean;
  249.   personID      : longint;
  250.   file1Open     : boolean;
  251.   file2Open     : boolean;
  252.   status        : smallint;
  253.   getStatus     : smallint;
  254.   i             : smallint;
  255.   posCtr        : smallint;
  256.   client        : CLIENT_ID;
  257.   versionBuffer : array[1..3] of VERSION_STRUCT;
  258.   fileCreateBuf : FILE_CREATE_BUF;
  259.   gneBuffer     : GNE_BUFFER_PTR;
  260.   personRecord  : PERSON_STRUCT;
  261.  
  262. {***********************************************************************
  263.    A helper procedure to write to the ListBox
  264. ************************************************************************}
  265. procedure WritelnLB( LB: TListBox; Str: String);
  266. begin
  267.   LB.Items.Add(Str);
  268. end;
  269.  
  270. procedure TForm1.FormCreate(Sender: TObject);
  271. begin
  272.   ArrowCursor    :=  LoadCursor(0, IDC_ARROW);
  273.   WaitCursor     :=  LoadCursor(0, IDC_WAIT);
  274. end;
  275.  
  276. {***********************************************************************
  277.    This is the 'main' procedure of the sample
  278. ************************************************************************}
  279. procedure TForm1.RunTest;
  280. begin
  281.   ListBox1.Clear;
  282.   WritelnLB( ListBox1, 'Test started ...' );
  283.  
  284.   { initialize variables }
  285.   btrieveLoaded := FALSE;
  286.   file1Open := FALSE;
  287.   file2Open := FALSE;
  288.   keyNum := 0;
  289.   status := B_NO_ERROR;
  290.   getStatus := B_NO_ERROR;
  291.  
  292.   { set up the Client ID }
  293.   fillchar(client.networkAndNode, sizeof(client.networkAndNode), #0);
  294.   client.applicationID := 'MT' + #0;  { must be greater than "AA" }
  295.   client.threadID := MY_THREAD_ID;
  296.  
  297.   fillchar(versionBuffer, sizeof(versionBuffer), #0);
  298.   dataLen := sizeof(versionBuffer);
  299.  
  300.   status := BTRVID(
  301.               B_VERSION,
  302.               posBlock1,
  303.               versionBuffer,
  304.               dataLen,
  305.               keyBuf1[1],
  306.               keyNum,
  307.               client);
  308.  
  309.   if status = B_NO_ERROR then begin
  310.     writelnLB( ListBox1, 'Btrieve Versions returned are:' );
  311.     for i := 1 to 3 do begin
  312.       with versionBuffer[i] do begin
  313.         if (version > 0) then begin
  314.           writelnLB(ListBox1, intToStr(version) + '.' +
  315.                      intToStr(revision) + ' ' + MKDEId);
  316.         end
  317.       end
  318.     end;
  319.     btrieveLoaded := TRUE;
  320.   end else begin
  321.     writelnLB(ListBox1, 'Btrieve B_VERSION status = ' + intToStr(status));
  322.     if status <> B_RECORD_MANAGER_INACTIVE then begin
  323.       btrieveLoaded := TRUE;
  324.     end
  325.   end;
  326.  
  327.   { open sample.btr }
  328.   if status = B_NO_ERROR then begin
  329.     fillchar(dataBuffer, sizeof(dataBuffer), #0);
  330.     fillchar(keyBuf1, sizeof(keyBuf1), #0);
  331.     keyNum := 0;
  332.     dataLen := 0;
  333.  
  334.     keyBuf1 := FILE_1 + #0;
  335.     keyBuf2 := FILE_2 + #0;
  336.  
  337.     status := BTRVID(
  338.                   B_OPEN,
  339.                   posBlock1,
  340.                   dataBuffer,
  341.                   dataLen,
  342.                   keyBuf1[1],
  343.                   keyNum,
  344.                   client);
  345.  
  346.     writelnLB(ListBox1, 'Btrieve B_OPEN status = ' + intToStr(status));
  347.     if status = B_NO_ERROR then begin
  348.       file1Open := TRUE;
  349.     end
  350.   end;
  351.  
  352.   {* get the record using key 0 = a known value using B_GET_EQUAL *}
  353.   if status = B_NO_ERROR then begin
  354.     fillchar(personRecord, sizeof(personRecord), #0);
  355.     dataLen := sizeof(personRecord);
  356.     personID := 263512477;  {* this is really a social security number *}
  357.  
  358.     status := BTRVID(
  359.                 B_GET_EQUAL,
  360.                 posBlock1,
  361.                 personRecord,
  362.                 dataLen,
  363.                 personID,
  364.                 keyNum,
  365.                 client);
  366.  
  367.     writelnLB(ListBox1, 'Btrieve B_GET_EQUAL status = ' + intToStr(status));
  368.     if status = B_NO_ERROR then with personRecord do begin
  369.       writelnLB(ListBox1, '');
  370.       writelnLB(ListBox1, 'Selected fields from the retrieved record are:');
  371.       writelnLB(ListBox1, 'ID:      ' + intToStr(ID));
  372.       writelnLB(ListBox1, 'Name:    ' + FirstName + ' ' +
  373.                               LastName);
  374.       writelnLB(ListBox1, 'Street:  ' + Street);
  375.       writelnLB(ListBox1, 'City:    ' + City);
  376.       writelnLB(ListBox1, 'State:   ' + State);
  377.       writelnLB(ListBox1, 'Zip:     ' + Zip);
  378.       writelnLB(ListBox1, 'Country: ' + Country);
  379.       writelnLB(ListBox1, 'Phone:   ' + Phone);
  380.       writelnLB(ListBox1, '');
  381.     end;
  382.   end;
  383.  
  384.   { perform a stat operation to populate the create buffer }
  385.   fillchar(fileCreateBuf, sizeof(fileCreateBuf), #0);
  386.   dataLen := sizeof(fileCreateBuf);
  387.   keyNum  := -1;
  388.   status := BTRVID(B_STAT,
  389.                 posBlock1,
  390.                 fileCreateBuf,
  391.                 dataLen,
  392.                 keyBuf1[1],
  393.                 keyNum,
  394.                 client);
  395.  
  396.   if (status = B_NO_ERROR) then begin
  397.     { create and open sample2.btr }
  398.     keyNum := 0;
  399.     dataLen := sizeof(fileCreateBuf);
  400.     status := BTRVID(B_CREATE,
  401.                   posBlock2,
  402.                   fileCreateBuf,
  403.                   dataLen,
  404.                   keyBuf2[1],
  405.                   keyNum,
  406.                   client);
  407.  
  408.     writelnLB(ListBox1, 'Btrieve B_CREATE status = ' + intToStr(status));
  409.   end;
  410.  
  411.   if (status = B_NO_ERROR) then begin
  412.     keyNum  := 0;
  413.     dataLen := 0;
  414.  
  415.     status := BTRVID(
  416.                 B_OPEN,
  417.                 posBlock2,
  418.                 dataBuffer,
  419.                 dataLen,
  420.                 keyBuf2[1],
  421.                 keyNum,
  422.                 client);
  423.     writelnLB(ListBox1, 'Btrieve B_OPEN status = ' + intToStr(status));
  424.     if (status = B_NO_ERROR) then begin
  425.       file2Open := TRUE;
  426.     end;
  427.   end;
  428.  
  429.   { now extract data from the original file, insert into new one }
  430.   if (status = B_NO_ERROR) then begin
  431.     { getFirst to establish currency }
  432.     keyNum := 2; { STATE-CITY index }
  433.     fillchar(personRecord, sizeof(personRecord), #0);
  434.     fillchar(keyBuf1, sizeof(keyBuf1), #0);
  435.     dataLen := sizeof(personRecord);
  436.  
  437.     getStatus := BTRVID(
  438.                    B_GET_FIRST,
  439.                    posBlock1,
  440.                    personRecord,
  441.                    dataLen,
  442.                    keyBuf1[1],
  443.                    keyNum,
  444.                    client);
  445.  
  446.     writelnLB(ListBox1, 'Btrieve B_GET_FIRST status = ' + intToStr(GETstatus));
  447.     writelnLB(ListBox1, '');
  448.   end;
  449.  
  450.   { Allocate memory on heap }
  451.   gneBuffer := new(GNE_BUFFER_PTR);
  452.   fillchar(gneBuffer^, sizeof(GNE_BUFFER), #0);
  453.  
  454.   strPCopy(gneBuffer^.preBuf.gneHeader.currencyConst, 'UC');
  455.   while (getStatus = B_NO_ERROR) do begin
  456.     gneBuffer^.preBuf.gneHeader.rejectCount := 0;
  457.     gneBuffer^.preBuf.gneHeader.numberTerms := 2;
  458.     posCtr := sizeof(GNE_HEADER);
  459.  
  460.     { fill in the first condition }
  461.     gneBuffer^.preBuf.term1.fieldType := 11;
  462.     gneBuffer^.preBuf.term1.fieldLen := 3;
  463.     gneBuffer^.preBuf.term1.fieldOffset := 108;
  464.     gneBuffer^.preBuf.term1.comparisonCode := 1;
  465.     gneBuffer^.preBuf.term1.connector := 2;
  466.  
  467.     strPCopy(gneBuffer^.preBuf.term1.value, 'TX');
  468.     inc(posCtr, (sizeof(TERM_HEADER)));
  469.  
  470.     { fill in the second condition }
  471.     gneBuffer^.preBuf.term2.fieldType := 11;
  472.     gneBuffer^.preBuf.term2.fieldLen := 3;
  473.     gneBuffer^.preBuf.term2.fieldOffset := 108;
  474.     gneBuffer^.preBuf.term2.comparisonCode := 1;
  475.     gneBuffer^.preBuf.term2.connector := 0;
  476.     strPCopy(gneBuffer^.preBuf.term2.value, 'CA');
  477.     inc(posCtr, sizeof(TERM_HEADER));
  478.  
  479.     { fill in the projection header to retrieve whole record }
  480.     gneBuffer^.preBuf.retrieval.maxRecsToRetrieve := 20;
  481.     gneBuffer^.preBuf.retrieval.noFieldsToRetrieve := 1;
  482.     inc(posCtr, sizeof(RETRIEVAL_HEADER));
  483.     gneBuffer^.preBuf.recordRet.fieldLen := sizeof(PERSON_STRUCT);
  484.     gneBuffer^.preBuf.recordRet.fieldOffset := 0;
  485.     inc(posCtr, sizeof(FIELD_RETRIEVAL_HEADER));
  486.     gneBuffer^.preBuf.gneHeader.descriptionLen := posCtr;
  487.  
  488.     dataLen := sizeof(GNE_BUFFER);
  489.     getStatus := BTRVID(
  490.                    B_GET_NEXT_EXTENDED,
  491.                    posBlock1,
  492.                    gneBuffer^,
  493.                    dataLen,
  494.                    keyBuf1,
  495.                    keyNum,
  496.                    client);
  497.  
  498.     writelnLB(ListBox1, 'Btrieve B_GET_NEXT_EXTENDED status = ' + intToStr(getStatus));
  499.  
  500.     { Get Next Extended can reach end of file and still return some records }
  501.     if ((getStatus = B_NO_ERROR) or (getStatus = B_END_OF_FILE)) then begin
  502.       writelnLB(ListBox1, 'GetNextExtended returned ' +
  503.                 intToStr(gneBuffer^.postBuf.numReturned) + ' records.');
  504.       for i := 0 to gneBuffer^.postBuf.numReturned - 1 do begin
  505.         dataLen := sizeof(PERSON_STRUCT);
  506.         personRecord := gneBuffer^.postBuf.recs[i].personRecord;
  507.         status := BTRVID(
  508.                     B_INSERT,
  509.                     posBlock2,
  510.                     personRecord,
  511.                     dataLen,
  512.                     keyBuf2,
  513.                     -1,   { no currency change }
  514.                     client);
  515.         if (status <> B_NO_ERROR) then begin
  516.           writelnLB(ListBox1, 'Btrieve B_INSERT status = ' + intToStr(status));
  517.           break;
  518.         end;
  519.       end;
  520.  
  521.       writelnLB(ListBox1, 'Inserted ' + intToStr(gneBuffer^.postBuf.numReturned) +
  522.                 ' records in new file, status = ' + intToStr(status));
  523.       writelnLB(ListBox1, '');
  524.     end;
  525.     fillchar(gneBuffer^, sizeof(GNE_BUFFER), #0);
  526.     gneBuffer^.preBuf.gneHeader.currencyConst := 'EG';
  527.   end;
  528.   dispose(gneBuffer);
  529.  
  530.   { close open files }
  531.   keyNum := 0;
  532.   if file1Open = TRUE then begin
  533.     dataLen := 0;
  534.  
  535.     status := BTRVID(
  536.                 B_CLOSE,
  537.                 posBlock1,
  538.                 dataBuffer,
  539.                 dataLen,
  540.                 keyBuf1[1],
  541.                 keyNum,
  542.                 client);
  543.  
  544.     writelnLB(ListBox1, 'Btrieve B_CLOSE status (sample.btr) = ' + intToStr(status));
  545.   end;
  546.  
  547.   if file2Open = TRUE then begin
  548.     dataLen := 0;
  549.  
  550.     status := BTRVID(
  551.                 B_CLOSE,
  552.                 posBlock2,
  553.                 dataBuffer,
  554.                 dataLen,
  555.                 keyBuf2[1],
  556.                 keyNum,
  557.                 client);
  558.  
  559.     writelnLB(ListBox1, 'Btrieve B_CLOSE status (sample2.btr) = ' + intToStr(status));
  560.   end;
  561.  
  562.   { FREE RESOURCES }
  563.   dataLen := 0;
  564.   status := BTRVID( B_STOP, posBlock1, DataBuffer,
  565.                dataLen, keyBuf1[1], 0, client );
  566.   WritelnLB(ListBox1, 'Btrieve B_STOP status = ' + intToStr(status) );
  567.  
  568. end;
  569.  
  570. procedure TForm1.ExitButtonClick(Sender: TObject);
  571. begin
  572.   Close;
  573. end;
  574.  
  575. procedure TForm1.RunButtonClick(Sender: TObject);
  576. begin
  577.   SetCursor(WaitCursor);
  578.   RunTest;
  579.   SetCursor(ArrowCursor);
  580. end;
  581.  
  582. end.
  583.