FATS - Fast Access Tree System
Table of Contents
Programming Interfaces
Borland Delphi for Windows 95/NT


The  FATS matchcode commands create a full-text index with the content of your data tables or -files.
Every word and every number is incorporated into the index, an "inverted list" is generated.

This index enables FATS to find each data record by specification of any terms in fractions of a second.

The following Delphi example demonstrates the use of the FATS matchcode commands:

(*
   FATS 02.30
   (c) GCS Software, Udo Gertz 1993-1998

   Test program (Borland Delphi 32bit)

   This program needs the extended version of FATS (FATSXW32.DLL)
 
   Use the logical order of an FATS index file to build
   the matchcode index.

   19-03-2009      Udo Gertz
*) 

{$APPTYPE CONSOLE}


program MCSORT;

uses sysutils,
     windows;


type

{$IFOPT H+}
  FATScmndstr = string;
{$ELSE}
  FATScmndstr = string[255];
{$ENDIF}

  FATSkeystr = string[255];


     function FATSLibInit(nSize: integer; nSign: integer): Pointer;
              stdcall; external 'FATSXW32.DLL';

     function FATSLibExit(lpFATSdata: Pointer): Pointer;
              stdcall; external 'FATSXW32.DLL';
     function FATSLibCall(var szCmnd: FATScmndstr; var uErrorCode: integer;
              var szFATSkey: FATSkeystr; lpFATSdata: Pointer): longint;
              stdcall; external 'FATSXW32.DLL' name 'FATSLibCallA';


const

  fn_cust = 'CUSTOMER.DAT';

type

  custrec = record

    DELETEDMARK: char;
    ID: string[5];
    NAME: string[25];
    JOB: string[25];
    STREET: string[25];
    ZIP: string[5];
    CITY: string[20];

  end;


var

  szCmnd: FATScmndstr;
  szFATSkey: FATSkeystr;
  uFATSError: integer;
  dwFATSRecno: longint;
  lpFATSdata: pointer;

  hCustomer: file of custrec;
  cdata: custrec;
  dwCurRecno: longint;
  dwHitId: longint;
  szRecno: string[8];
  cChar: char;


  (*
     The "Build Matchcode" (MB) command demands an ascending number
     as a "RecNo" argument i.e. the matchcode can not usually be
     indexed in the logical order of an index-key.
   
     This example program uses the flag K#:# ("MC"-command)
     to create the matchcode index in sorted order.
  *) 


begin

  (*
     init FATS data area
  *) 

  {$IFOPT H+}
    lpFATSdata := FATSLibInit( 0, 4 );
  {$ELSE}
    lpFATSdata := FATSLibInit( 0, 1 );
  {$ENDIF}
  if lpFATSdata = nil then exit;


  writeln ('This Test Program was designed for Borland Delphi 32bit.');
  writeln;
  writeln ('You need the dynamic link library FATSXW32.DLL');
  writeln;
  writeln ('Please press the [ENTER] key ...');

  read (cChar);


  (*
     -------> Open data file
  *) 

  writeln ('Opening data file ...');

  assign (hCustomer, fn_cust);
  reset (hCustomer);


  (*
     -------> Opening key file
  *) 

  szCmnd:='O\CUSTOMER.KEY\2';
  dwFATSRecno:=FATSLibCall(szCmnd, uFATSError, szFATSkey, lpFATSdata);

  If uFATSError <> 0 Then Begin

    writeln;
    writeln( 'Error opening the file CUSTOMER.KEY' );
    writeln( 'Please create the file using the test program' );
    writeln( 'TST1_ENG.dpr' );
    exit;
  End;


  (*
     ========================================================================
               Creating Matchcode Index
     ========================================================================
  *) 


  (*
     -------> Creating Matchcode Index File
   
     With the command  "MC" Create Matchcode File, the most important
     query facilities are determined already while creating the
     matchcode index file. With the search-group flag ("I#"), several
     logically related data columns can be registered in a common index
     so that a query to this index resp. search group extends automatically
     over all these columns. A matchcode file manages up to 32 search
     groups that can be used for joined queries (using the "AND"-operator).
   
     In this example the following search groups are defined:
   
       Search Group    Fields
   
           I1          NAME
           I2          JOB
           I3          ZIP & CITY
   
     The syntax of the command string:
   
       szCmnd = "MC\{FileName}\{Flags}\{FileNo}\{Col1def}[\{Col2def}]"
   
         FileName   Filename, perhaps with an additional path
                    (i.e. C:/DATA/CUSTOMER.FMS or CUSTOMER.FMS)
   
         Flags      Reserved, not used at the moment
   
         FileNo     File number
   
         Col#def    Definition of data column # (flags, separated by comma).
                    The content of the corresponding data columns is transferred
                    the commands "MB", "MI" and "MD" later in the order determined
                    by this command.
   
                    I#  The content of the data column becomes part of search
                        group #. You can combine several columns into a logical
                        search group (e.g. first name, surname).
   
                    C   The content of the data column is edited for word overall
                        searching, i.e. a search for "motorca" e.g. finds
                        "motorcar" and "motor caravan".
   
                    N   Numbers are handled as words, i.e. during a search
                        according to "150", "12150" e.g. is also found.
   
                  K#:#  This switch activates the management of a primary key
                        for this matchcode index file. The first value after
                        the 'K' is the position of the data column within the
                        key (1 == first part), the second value specifies the
                        length of the data column valid as the key.
   
                    Further adjustments are possible and described in detail
                    in the user manual.

  *)  

  writeln;
  writeln ('Creating matchcode index file ...');

  szCmnd:='MC\CUSTSORT.FTS\\1\K1:5\I1\I2\I3';
  dwFATSRecno:=FATSLibCall(szCmnd, uFATSError, szFATSkey, lpFATSdata);

  (*
   
     "MC\{Filename}\\{FileNo}\K#:#\I1\I2\I3"
   
     The flag K#:# enables the management of a primary key within
     the matchcode file. FATS normaly only uses the record number
     during the generation of a result set. In specific situations,
     if e.g. the physical record number is not known, or does not
     correspond to the ID specified with the MB-command, the generation
     of a primary key becomes necessary. The browser commands then also
     make in addition to the record- or ID-number this key available via
     the FATSKEY-variable to the application.
   
     With the use of this flag, FATS generates a supplementary file with
     the file extension .FMK which is used for the sequential storage of
     the key.
  *) 

  If uFATSError <> 0 Then Begin

    writeln;
    write ('FATS Errorcode: '); write (uFATSError);
    writeln (' (Command: MC)');
    exit;

  End;


  (*
     -------> Insert text into the matchcode index
   
     After the matchcode file was generated, the content of the
     data columns may be with the command  "MB" Build Matchcode
     inserted into the matchcode index. The position of the
     data columns within the command string ("Col#data") corresponds
     to that with the call of command Create Matchcode File ("MC")
     determined definition.
   
     The syntax of the command string:
   
       szCmnd = "MB\{FileNo}\{RecNo}\{Col1data}[\{Col2data}[\{Col3data}]]"
   
         FileNo     File number
   
         RecNo      <> 0 Record- resp. id-number
                    == 0 Stop Build, no more records
   
         Col#data   Content of data column #
   
   
     The following sample program code indexes contents of the
     entire data file within a loop:

  *)  

  writeln;
  writeln ('Building matchcode index in sorted order');
  writeln;
  writeln ('Please press the [ENTER] key ...');
  writeln;

  read (cChar);


  dwCurRecno:=0;
  szCmnd:='F\2\2';

  (*
   
  *) 

  Repeat

    dwFATSRecno:=FATSLibCall(szCmnd, uFATSError, szFATSkey, lpFATSdata);

    If uFATSError = 0 Then Begin

      seek(hCustomer, dwFATSRecno - 1);
      read(hCustomer, cdata);

      dwCurRecno:=dwCurRecno + 1;

      str(dwCurRecno, szRecno);
      szCmnd:='MB\1\' + szRecno;

      (*
         Add the primary key to the command string
      *) 

      szCmnd:=szCmnd + '\' + cdata.ID;

        szCmnd:=szCmnd + '\' + cdata.NAME;
        szCmnd:=szCmnd + '\' + cdata.JOB;
        szCmnd:=szCmnd + '\' + cdata.ZIP + ' ' + cdata.CITY;

      dwFATSRecno:=FATSLibCall(szCmnd, uFATSError, szFATSkey, lpFATSdata);

      If uFATSError <> 0 Then Begin

        (*
           If an error occurred during the execution of the "MB" command,
           the matchcode index file is already closed by FATS.
        *) 

        write ('FATS Errorcode: '); write (uFATSError);
        writeln (' (Command: MB)');
        writeln;

      End Else begin

        writeln (cdata.NAME,' --> RecNo ', dwCurRecno:-8);

        szCmnd:='N\2';

      End;

    End Else Begin

      (*
         After the last record was inserted the creating process
         has to be terminated with the command "MB\{FileNo}\0".
         Because this command closes the matchcode index file you don't
         have to do a close command.
      *) 

      szCmnd:='MB\1\0';
      dwFATSRecno:=FATSLibCall(szCmnd, uFATSError, szFATSkey, lpFATSdata);
      break;

    End;

  Until uFATSError <> 0;


  (*
     ========================================================================
               Matchcode Search
     ========================================================================
  *) 


  (*
     -------> Open matchcode index file
   
     With the command  "O" Open Indexfile you open an existing
     matchcode index file with the opening flags defined with
     the command  "Y" Auto Refresh. After the file was opened
     it can be accessed under the file number you specified.

  *)  

  szCmnd:='O\CUSTSORT.FTS\1';
  dwFATSRecno:=FATSLibCall(szCmnd, uFATSError, szFATSkey, lpFATSdata);


  (*
     -------> Search in Search-Group 1 (NAME)
   
   
  *) 

  writeln;
  writeln ('We now search for all customers with the first name Michael.');
  writeln;
  writeln ('Please press the [ENTER] key ...');
  writeln;

  read (cChar);


  szCmnd:='MS\1\\0\michael';

  Repeat

    dwHitId:=FATSLibCall(szCmnd, uFATSError, szFATSkey, lpFATSdata);

    If uFATSError = 0 Then Begin

      (*
       
      *) 

      szCmnd:='S\1\2\' + szFATSkey;
      dwFATSRecno:=FATSLibCall(szCmnd, uFATSError, szFATSkey, lpFATSdata);

      seek(hCustomer, dwFATSRecno - 1);
      read(hCustomer, cdata);

      writeln(cdata.NAME, ' | ', cdata.JOB);
      writeln(cdata.ZIP, ' ', cdata.CITY, '(#', dwFATSRecno:-8, ')');
      writeln;

      str(dwHitId, szRecno);
      szCmnd:='MA\1\' + szRecno;

    End;

  Until uFATSError <> 0;


  (*
     --------> Close matchcode index file
  *) 

  szCmnd:='K';
  dwFATSRecno:=FATSLibCall(szCmnd, uFATSError, szFATSkey, lpFATSdata);

  close( hCustomer );


  (*
     free FATS data area
  *) 

  lpFATSdata := FATSLibExit( lpFATSdata );

End.

© 2008  GCS Software, Udo Gertz