[Back to MISC SWAG index]  [Back to Main SWAG index]  [Original]

unit DBaseDB;
{$V-,S-,R-}
{              ***************24/10/97*****************
               *This UNIT was created by DAVID HOOPER*
               *for general use, can use filelocking *
               *A record level locking version will  *
               *be available soon. Both going to SWAG*
               *          loki1@ihug.co.nz           *
               *  http://homepages.ihug.co.nz/~loki1 *
               ***************************************}

interface
uses Dos; {, MyDBase;}
type
    string30 = string[30];
{****NB:****  To use custom records:
     The Simple Way:- Do a SEARCh and REPLACE for DBase and replace it
       with your database name, (max 6 letters) eg. PLAYER or USERS
       also edit the DBaseRec (PLAYERRec) and put your own fields in.

     The other way :-
              make a simple unit that has just the record structure
              DBaseRec, and also the Vars
              DBase: DBaseRec;
              DBaseFile: File of DBaseRec;
              and include the USES Dos, MyDBase line (where MyDBase
              is the unit with your structures in it)
              then delete them from this unit

    An Example of using this DBase is at the end of this file}
    MemoType = Record
                 Memo_Date: string[15];
                 Memo_Line: string;
               End;
    DBaseRec = Record             {this is an example, make your own}
                 Deleted: boolean;{delete DBaseFINDDELD if u delete this}
                 Name: string30;  {delete DBaseFINDNAME if u delete this}
                 Age: byte;
                 Memo: array[1..10] of MemoType;
                End;
Var
  {GLOBAR VARIABLES}
   DBase : DBaseRec;
   DBaseFile : File of DBaseRec;
   OldFileMode : integer;
   RecFoundAT: word; {where was the searched for record found}

function FILEEXISTS(PathAndFile: string):Boolean;
function  DBaseOPEN(Path, FileName: string; fm: byte): Boolean;
procedure DBaseCLOSE;
procedure DBaseREAD(var DBase: DBaseRec);  {not normally used by user}
function  DBaseSEEK(Rec: word) : boolean;  {not normally used by user}
function  DBaseGET(var DBase: DBaseRec; Rec: word) :Boolean;{uses above 2}
procedure DBaseADD(var DBase: DBaseRec);
procedure DBaseEDIT(var DBase: DBaseRec);
function  DBaseCREATEFIRST(Path, FileName: string; fm: byte;
                               var DBase: DBaseRec): Boolean;
function  DBaseFINDNAME(var DBase: DBaseRec; InName: string30): Boolean;
function  DBaseFINDDEL(var DBase: DBaseRec): Boolean;
procedure DBaseSORT;

implementation


{***********************************
 *Opens the DBase file and returns *
 *TRUE if successful               *
 *fm= filemode:- 0=read, 2= write  *
 *64=read&share, 66=write&share    *
 ***********************************}
function FILEEXISTS(PathAndFile: string):Boolean;
var F: File;
begin
  assign(F,PathAndFile);
{$I-}
  reset(f);
{$I+}
  if ioresult = 0 then
  begin
    close(f);
    fileExists := true;
  end
  else
  fileExists := false;
end;

function DBaseOPEN(Path, FileName: string; fm: byte): Boolean;
var S: string;
 IsOK: Boolean;
begin
 S := FSearch(FileName,Path); {check it exists}
 IsOK := True;
 if ((fm = 0) or (fm = 64)) then IsOk := FILEEXISTS(Path+FileName);
 if IsOK then
 begin
  {$I-}
  OldFileMode := filemode;
  filemode := fm;
  Assign(DBaseFILE , Path+FileName);
  Reset(DBaseFILE);
  IsOK := (ioresult = 0);
  {$I+}
 end;
 if (not IsOK) then filemode := OldFileMode;
 DBaseOPEN := IsOK;
end;

{************************
 *Closes the DBase file *
 ************************}
procedure DBaseCLOSE;
begin
 CLOSE(DBaseFILE);
 filemode := OldFileMode;
end;

{***********************************
 *Seeks to a specific record number*
 *0 to end of file. Will return a  *
 *True if REC is within the range  *
 *Normally not used by user, but   *
 *here if needed                   *
 ***********************************}
function DBaseSEEK(Rec: word) : boolean;
begin
 if (((Rec+1) <= (FileSize(DBaseFILE))) and (Rec >=0)) then
 begin
  Seek(DBaseFILE, Rec);
  DBaseSEEK := True;
 end
 else DBaseSEEK := False;
end;

{**************************************
 *Simply Reads the next record.       *
 *Again, normally only used internally*
 *by other functions and procedures   *
 *such as DBaseGET, after range check *
 **************************************}
procedure DBaseREAD(var DBase: DBaseRec);
begin
 Read(DBaseFILE , DBase);
end;

{**************************************
 *Seeks to Rec with range checking    *
 *Reads in the record and returns and *
 *returns TRUE if successful or FALSE *
 *if Rec was out of range             *
 **************************************}
function DBaseGET(var DBase: DBaseRec;Rec: word) : boolean;
var IsOK: boolean;
begin
 IsOK := DBaseSEEK(Rec);
 if IsOK then DBaseREAD(DBase);
 DBaseGET := IsOK;
end;

{************************************************
 *Writes the DBase record to the current        *
 *Record number. This is usually called         *
 *like thius:-                                  *
 *If DBaseSeek(Rec_Number) then EDITDBase(DBase)*
 ************************************************}
procedure DBaseEDIT(var DBase: DBaseRec);
begin
 write(DBaseFILE, DBase);
end;

{************************************************
 *Writes a new record to the end of the database*
 ************************************************}
procedure DBaseADD(var DBase: DBaseRec);
begin
 RESET(DBaseFile);  {this line can be removed}
 SEEK(DBaseFILE, filesize(DBaseFile));
 DBaseEDIT(DBase);
end;

{*********************************************************
 *An alternate to automatically making a new file        *
 *If it does not exist.(eg. may just be a wrong          *
 *path. An example of calling this is :-                 *
 *if (NOT OPENDBase('C:\DATA\','MyDBase.DAT',2))         *
 *  then CREATEFIRSTDBase('C:\DATA\'MyDBase.Dat', DBase);*
 *the filemode that is passed, is used to reopen the file*
 *after it has been created. First record written assumes*
 *SharingWrite 66                                        *
 *********************************************************}
function DBaseCREATEFIRST(Path, FileName: string; fm: byte;
                               var DBase: DBaseRec):boolean;
begin
  {$I-}
  OldFileMode := filemode;
  filemode := 66;
  Assign(DBaseFILE , Path+FileName);
  Rewrite(DBaseFILE);
  {$I+}
 if ioresult <>0 then
 begin
   DBaseCREATEFIRST := False;
   exit;
 end;
 DBaseEDIT(DBase);
 close(DBaseFile);
 DBaseCREATEFIRST := DBaseOPEN(Path, FileName, fm);
end;

{*********************************************
 *Finds a name, and returns the record number*
 *in RecFoundAt, and a TRUE, else            *
 *RecFoundAt = 0, and function returns FALSE *
 *********************************************}
function  DBaseFINDNAME(var DBase: DBaseRec; InName: string30): Boolean;
var L1, UCLoop: word;
    found: boolean;
    TBName, TIName: string30;
begin
 L1 := 0;
 found := False;
 for UCLoop := 1 to length(InName) do InName[UCLoop] := upcase(InName[UCLoop]);
 while ((L1 < filesize(DBaseFile)) and (not found)) do
 begin
  if (DBaseGET(DBase, L1)) then
    TBName := DBase.Name;
    for UCLoop := 1 to length(TBName) do TBName[UCLoop] := upcase(TBName[UCLoop]);
     if ((TBName = InName) and (not DBase.deleted)) then found := true
     else found := false;
  if not found then inc(L1);
 end;

 if Found then
 begin
   RecFoundAt := L1;
   DBaseSEEK(L1);
   DBaseFINDNAME := TRUE;
 end
 else
 begin
   RecFoundAt := 0;
   DBaseFINDNAME := FALSE;
 end;
end;

{*********************************************
 *Finds the first Deleted (empty) record.    *
 *ie. DBase.Deleted := TRUE. returns record #*
 *in RecFoundAt, and a TRUE, else            *
 *RecFoundAt = 0, and function returns FALSE *
 *********************************************}
function  DBaseFINDDEL(var DBase: DBaseRec): Boolean;
var L1: word;
 found: boolean;
begin
 L1 := 0;
 found := False;
 while ((L1 < filesize(DBaseFile)) and (not found)) do
 begin
  if (DBaseGET(DBase, L1)) then found := (DBase.Deleted = True);
  if not found then inc(L1);
 end;
 if Found then
 begin
   RecFoundAt := L1;
   DBaseSEEK(L1);
   DBaseFINDDEL := TRUE;
 end
 else
 begin
   RecFoundAt := 0;
   DBaseFINDDEL := FALSE;
 end;
end;

PROCEDURE DBaseSORT;
var SORTLOOP: word;
    TempDBase: DBaseRec;
    DidSort: boolean;     {flag eg. why continue sorting when sorted?}
    count, endcount: integer;
begin
  count := 0;
  endcount := FileSize(DBaseFILE)-3;
  {-2(-3) because we do +1 in the search}
  DidSort := TRUE; {set true for first sort}
  while (DidSort AND (count <= endcount)) do
  begin
    DidSort := FALSE;
    for SortLoop := 0 to (FileSize(DBaseFILE)-(1+Count)) do
    begin
      DBaseGET(DBase, SortLoop);
      TempDBase := DBase;
      DBaseGET(DBase, SortLoop+1);
      if ((TempDBase.Name > DBase.Name) or (TempDBase.Deleted)) then
      {swap order, put deleted at end}
      begin
        DidSort := TRUE;                {Swapping part, uses a temp record}
        DBaseSEEK(SortLoop);
        write(DBaseFILE, DBase);
        DBaseSEEK(SortLoop+1);
        write(DBaseFILE, TempDBase);
      end;
    end; {of SortLoop}
    Count := Count + 1;
  end; {of while loop}
end;


begin
end.


(*  EXAMPLE OF USING THE DBASEDB UNIT
program TESTDB(input, output);
uses DBASEDB;
var
   Loop1: word; {only used for example}

begin
  if not FILEEXISTS('C:\TESTDB.DAT') then {no database made yet}
  begin
    DBase.Deleted := False;
    DBase.Name := 'First Person';
    DBase.Age := 27;
    DBase.Memo[1].Memo_Date := '27/10/97';
    DBase.Memo[1].Memo_Line := 'Meeting went well...';

    DBaseCREATEFIRST('C:\','TESTDB.DAT',66, DBase); {make the new database}
  end
  else {the database file DOES exist}
    DBaseOpen('C:\','TESTDB.DAT',66);{so open it}

    DBase.Deleted := False;
    DBase.Name := 'Joe Bloggs';
    DBase.Age := 23;
    DBase.Memo[1].Memo_Date := '23/10/97';
    DBase.Memo[1].Memo_Line := 'didn''t show for Meeting';
    DBaseADD(DBase); {ADD THIS RECORD}

    DBase.Deleted := False;
    DBase.Name := 'Fred Flintstone';
    DBase.Age := 47;
    DBase.Memo[1].Memo_Date := '29/11/97';
    DBase.Memo[1].Memo_Line := 'bought a new car';
    DBase.Memo[2].Memo_Date := '30/11/97';
    DBase.Memo[2].Memo_Line := 'crashed the new car';
    DBaseADD(DBase); {ADD THIS RECORD}

    writeln('There are ',filesize(DBaseFile),' records');
    for Loop1 := 0 to filesize(DBaseFile)-1 do  {-1 because first record}
    begin                                       {is record 0 (zero)     }
      DBaseGet(DBase, Loop1);
      with DBase do
      begin
        Writeln('Record: ',Loop1);
        Writeln(Name,'   ',Age);
      end;
    end;
   if DBaseFINDNAME(DBase, 'Fred Flintstone') then
   begin
     writeln('First name matching ''Fred Flintstone'' found at ',RecFoundAt);
     DBaseGet(DBase, RecFoundAt);        {or simply DBaseREAD(DBASE); since}
     Writeln(DBase.Name,'   ',DBase.Age);{FINDNAME Seeks to the start of it}
   end
   else writeln ('''Fred Flintstone'' not found');
   DBaseClose;
end.
*)

[Back to MISC SWAG index]  [Back to Main SWAG index]  [Original]