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

  1. {****************************************************************************
  2. **
  3. **  Copyright 1982-1997 Pervasive Software Inc. All Rights Reserved
  4. **
  5. ****************************************************************************}
  6. {****************************************************************************
  7.    BTRSAM16.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 16-bit environment using your compiler tools.
  11.  
  12.       This program demonstrates the Delphi interface for Btrieve on 16-Bit
  13.       MS Windows 3.1, for Delphi 1.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 1.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.             PROJECT
  37.               COMPILER
  38.                 CODE GENERATION
  39.                   WORD-ALIGNED DATA ( de-select this )
  40.  
  41.         If you don't do this step, when the record is printed out, it will
  42.         seem 'jumbled' because the record structure is not byte-packed.
  43.  
  44.         You may, instead, use the (*A-*) compiler directive, or declare all
  45.         records as "packed," as shown below. For more information, see the
  46.         Delphi documentation.
  47.  
  48.       PROJECT FILES:
  49.          - btr16.dpr       Borland project file
  50.          - btrsam16.dfm    Borland project file
  51.          - btrsam16.pas    Source code for the simple sample
  52.          - btrapi16.pas    Delphi interface to Btrieve
  53.          - btrconst.pas    Btrieve constants file
  54.  
  55. ****************************************************************************}
  56. unit btrsam16;
  57.  
  58. interface
  59.  
  60. uses
  61.   WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  62.   Dialogs, StdCtrls, BtrConst, BtrAPI16;
  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.   { open sample.btr }
  327.   if status = B_NO_ERROR then begin
  328.     fillchar(dataBuffer, sizeof(dataBuffer), #0);
  329.     fillchar(keyBuf1, sizeof(keyBuf1), #0);
  330.     keyNum := 0;
  331.     dataLen := 0;
  332.  
  333.     keyBuf1 := FILE_1 + #0;
  334.     keyBuf2 := FILE_2 + #0;
  335.  
  336.     status := BTRVID(
  337.                   B_OPEN,
  338.                   posBlock1,
  339.                   dataBuffer,
  340.                   dataLen,
  341.                   keyBuf1[1],
  342.                   keyNum,
  343.                   client);
  344.  
  345.     writelnLB(ListBox1, 'Btrieve B_OPEN status = ' + intToStr(status));
  346.     if status = B_NO_ERROR then begin
  347.       file1Open := TRUE;
  348.     end
  349.   end;
  350.  
  351.   {* get the record using key 0 = a known value using B_GET_EQUAL *}
  352.   if status = B_NO_ERROR then begin
  353.     fillchar(personRecord, sizeof(personRecord), #0);
  354.     dataLen := sizeof(personRecord);
  355.     personID := 263512477;  {* this is really a social security number *}
  356.  
  357.     status := BTRVID(
  358.                 B_GET_EQUAL,
  359.                 posBlock1,
  360.                 personRecord,
  361.                 dataLen,
  362.                 personID,
  363.                 keyNum,
  364.                 client);
  365.  
  366.     writelnLB(ListBox1, 'Btrieve B_GET_EQUAL status = ' + intToStr(status));
  367.     if status = B_NO_ERROR then with personRecord do begin
  368.       writelnLB(ListBox1, '');
  369.       writelnLB(ListBox1, 'Selected fields from the retrieved record are:');
  370.       writelnLB(ListBox1, 'ID:      ' + intToStr(ID));
  371.       writelnLB(ListBox1, 'Name:    ' + FirstName + ' ' +
  372.                               LastName);
  373.       writelnLB(ListBox1, 'Street:  ' + Street);
  374.       writelnLB(ListBox1, 'City:    ' + City);
  375.       writelnLB(ListBox1, 'State:   ' + State);
  376.       writelnLB(ListBox1, 'Zip:     ' + Zip);
  377.       writelnLB(ListBox1, 'Country: ' + Country);
  378.       writelnLB(ListBox1, 'Phone:   ' + Phone);
  379.       writelnLB(ListBox1, '');
  380.     end;
  381.   end;
  382.  
  383.   { perform a stat operation to populate the create buffer }
  384.   fillchar(fileCreateBuf, sizeof(fileCreateBuf), #0);
  385.   dataLen := sizeof(fileCreateBuf);
  386.   keyNum  := -1;
  387.   status := BTRVID(B_STAT,
  388.                 posBlock1,
  389.                 fileCreateBuf,
  390.                 dataLen,
  391.                 keyBuf1[1],
  392.                 keyNum,
  393.                 client);
  394.  
  395.   if (status = B_NO_ERROR) then begin
  396.     { create and open sample2.btr }
  397.     keyNum := 0;
  398.     dataLen := sizeof(fileCreateBuf);
  399.     status := BTRVID(B_CREATE,
  400.                   posBlock2,
  401.                   fileCreateBuf,
  402.                   dataLen,
  403.                   keyBuf2[1],
  404.                   keyNum,
  405.                   client);
  406.  
  407.     writelnLB(ListBox1, 'Btrieve B_CREATE status = ' + intToStr(status));
  408.   end;
  409.  
  410.   if (status = B_NO_ERROR) then begin
  411.     keyNum  := 0;
  412.     dataLen := 0;
  413.  
  414.     status := BTRVID(
  415.                 B_OPEN,
  416.                 posBlock2,
  417.                 dataBuffer,
  418.                 dataLen,
  419.                 keyBuf2[1],
  420.                 keyNum,
  421.                 client);
  422.     writelnLB(ListBox1, 'Btrieve B_OPEN status = ' + intToStr(status));
  423.     if (status = B_NO_ERROR) then begin
  424.       file2Open := TRUE;
  425.     end;
  426.   end;
  427.  
  428.   { now extract data from the original file, insert into new one }
  429.   if (status = B_NO_ERROR) then begin
  430.     { getFirst to establish currency }
  431.     keyNum := 2; { STATE-CITY index }
  432.     fillchar(personRecord, sizeof(personRecord), #0);
  433.     fillchar(keyBuf1, sizeof(keyBuf1), #0);
  434.     dataLen := sizeof(personRecord);
  435.  
  436.     getStatus := BTRVID(
  437.                    B_GET_FIRST,
  438.                    posBlock1,
  439.                    personRecord,
  440.                    dataLen,
  441.                    keyBuf1[1],
  442.                    keyNum,
  443.                    client);
  444.  
  445.     writelnLB(ListBox1, 'Btrieve B_GET_FIRST status = ' + intToStr(GETstatus));
  446.     writelnLB(ListBox1, '');
  447.   end;
  448.  
  449.   { Allocate memory on heap }
  450.   gneBuffer := new(GNE_BUFFER_PTR);
  451.   fillchar(gneBuffer^, sizeof(GNE_BUFFER), #0);
  452.  
  453.   strPCopy(gneBuffer^.preBuf.gneHeader.currencyConst, 'UC');
  454.   while (getStatus = B_NO_ERROR) do begin
  455.     gneBuffer^.preBuf.gneHeader.rejectCount := 0;
  456.     gneBuffer^.preBuf.gneHeader.numberTerms := 2;
  457.     posCtr := sizeof(GNE_HEADER);
  458.  
  459.     { fill in the first condition }
  460.     gneBuffer^.preBuf.term1.fieldType := 11;
  461.     gneBuffer^.preBuf.term1.fieldLen := 3;
  462.     gneBuffer^.preBuf.term1.fieldOffset := 108;
  463.     gneBuffer^.preBuf.term1.comparisonCode := 1;
  464.     gneBuffer^.preBuf.term1.connector := 2;
  465.  
  466.     strPCopy(gneBuffer^.preBuf.term1.value, 'TX');
  467.     inc(posCtr, (sizeof(TERM_HEADER)));
  468.  
  469.     { fill in the second condition }
  470.     gneBuffer^.preBuf.term2.fieldType := 11;
  471.     gneBuffer^.preBuf.term2.fieldLen := 3;
  472.     gneBuffer^.preBuf.term2.fieldOffset := 108;
  473.     gneBuffer^.preBuf.term2.comparisonCode := 1;
  474.     gneBuffer^.preBuf.term2.connector := 0;
  475.     strPCopy(gneBuffer^.preBuf.term2.value, 'CA');
  476.     inc(posCtr, sizeof(TERM_HEADER));
  477.  
  478.     { fill in the projection header to retrieve whole record }
  479.     gneBuffer^.preBuf.retrieval.maxRecsToRetrieve := 20;
  480.     gneBuffer^.preBuf.retrieval.noFieldsToRetrieve := 1;
  481.     inc(posCtr, sizeof(RETRIEVAL_HEADER));
  482.     gneBuffer^.preBuf.recordRet.fieldLen := sizeof(PERSON_STRUCT);
  483.     gneBuffer^.preBuf.recordRet.fieldOffset := 0;
  484.     inc(posCtr, sizeof(FIELD_RETRIEVAL_HEADER));
  485.     gneBuffer^.preBuf.gneHeader.descriptionLen := posCtr;
  486.  
  487.     dataLen := sizeof(GNE_BUFFER);
  488.     getStatus := BTRVID(
  489.                    B_GET_NEXT_EXTENDED,
  490.                    posBlock1,
  491.                    gneBuffer^,
  492.                    dataLen,
  493.                    keyBuf1,
  494.                    keyNum,
  495.                    client);
  496.  
  497.     writelnLB(ListBox1, 'Btrieve B_GET_NEXT_EXTENDED status = ' + intToStr(getStatus));
  498.  
  499.     { Get Next Extended can reach end of file and still return some records }
  500.     if ((getStatus = B_NO_ERROR) or (getStatus = B_END_OF_FILE)) then begin
  501.       writelnLB(ListBox1, 'GetNextExtended returned ' +
  502.                 intToStr(gneBuffer^.postBuf.numReturned) + ' records.');
  503.       for i := 0 to gneBuffer^.postBuf.numReturned - 1 do begin
  504.         dataLen := sizeof(PERSON_STRUCT);
  505.         personRecord := gneBuffer^.postBuf.recs[i].personRecord;
  506.         status := BTRVID(
  507.                     B_INSERT,
  508.                     posBlock2,
  509.                     personRecord,
  510.                     dataLen,
  511.                     keyBuf2,
  512.                     -1,   { no currency change }
  513.                     client);
  514.         if (status <> B_NO_ERROR) then begin
  515.           writelnLB(ListBox1, 'Btrieve B_INSERT status = ' + intToStr(status));
  516.           break;
  517.         end;
  518.       end;
  519.  
  520.       writelnLB(ListBox1, 'Inserted ' + intToStr(gneBuffer^.postBuf.numReturned) +
  521.                 ' records in new file, status = ' + intToStr(status));
  522.       writelnLB(ListBox1, '');
  523.     end;
  524.     fillchar(gneBuffer^, sizeof(GNE_BUFFER), #0);
  525.     gneBuffer^.preBuf.gneHeader.currencyConst := 'EG';
  526.   end;
  527.   dispose(gneBuffer);
  528.  
  529.   { close open files }
  530.   keyNum := 0;
  531.   if file1Open = TRUE then begin
  532.     dataLen := 0;
  533.  
  534.     status := BTRVID(
  535.                 B_CLOSE,
  536.                 posBlock1,
  537.                 dataBuffer,
  538.                 dataLen,
  539.                 keyBuf1[1],
  540.                 keyNum,
  541.                 client);
  542.  
  543.     writelnLB(ListBox1, 'Btrieve B_CLOSE status (sample.btr) = ' + intToStr(status));
  544.   end;
  545.  
  546.   if file2Open = TRUE then begin
  547.     dataLen := 0;
  548.  
  549.     status := BTRVID(
  550.                 B_CLOSE,
  551.                 posBlock2,
  552.                 dataBuffer,
  553.                 dataLen,
  554.                 keyBuf2[1],
  555.                 keyNum,
  556.                 client);
  557.  
  558.     writelnLB(ListBox1, 'Btrieve B_CLOSE status (sample2.btr) = ' + intToStr(status));
  559.   end;
  560.  
  561.   { FREE RESOURCES }
  562.   dataLen := 0;
  563.   status := BTRVID( B_STOP, posBlock1, DataBuffer,
  564.                dataLen, keyBuf1[1], 0, client );
  565.   WritelnLB(ListBox1, 'Btrieve B_STOP status = ' + intToStr(status) );
  566.  
  567. end;
  568.  
  569. procedure TForm1.ExitButtonClick(Sender: TObject);
  570. begin
  571.   Close;
  572. end;
  573.  
  574. procedure TForm1.RunButtonClick(Sender: TObject);
  575. begin
  576.   SetCursor(WaitCursor);
  577.   RunTest;
  578.   SetCursor(ArrowCursor);
  579. end;
  580.  
  581. end.
  582.