home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TBTREE.ZIP / SETOPS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-07-25  |  11.7 KB  |  308 lines

  1. (* TBTree13             Copyright (c)  1988            Dean H. Farwell II    *)
  2.  
  3. unit SetOps;
  4.  
  5. (*****************************************************************************)
  6. (*                                                                           *)
  7. (*                 S E T   O P E A T I O N   R O U T I N E S                 *)
  8. (*                                                                           *)
  9. (*****************************************************************************)
  10.  
  11. (* This unit contains procedures to perform the set operations Intersection,
  12.    Union, and Difference on a pair of logical record lists.  The two lists
  13.    passed into the routines (lrLst1 and lrLst2) contain zero or more logical
  14.    record numbers from the SAME (very important) data file.  A third logical
  15.    record list (lrLst3) will be produced.  The third list will contain the
  16.    resulting logical record numbers depending on the set operation performed.
  17.    Intersection produces a list that contains all record numbers which are in
  18.    both input lists.  Union produces a list containing all record numbers which
  19.    are in either or both lists.  Difference produces a list coantaining all
  20.    records in the first list but not in the second list.  Obviously, these are
  21.    extremely useful routines.  Queries using multiple selection criteria can
  22.    now be accomplished.  For example, you can now easily retrieve all records
  23.    for which filed1 <= 10 and field2 = 'MANAGER' by doing a query on field1
  24.    and a separate query on field2 and then taking the intersection of the two
  25.    resulting lists.  One note, theis is not the preferred method for doing
  26.    retrievals on range.  If a retrieval on range is desired, use
  27.    GetRangeFromBTree instead.  This will be significantly faster.            *)
  28.  
  29. (* Version Information
  30.  
  31.    Version 1.1 - Unit did not exist.
  32.  
  33.    Version 1.2 - Entire unit added.
  34.  
  35.    Version 1.3 - No Changes                                                  *)
  36.  
  37.  
  38. (*\*)
  39. (*////////////////////////// I N T E R F A C E //////////////////////////////*)
  40.  
  41. interface
  42.  
  43. uses
  44.     FileDecs,
  45.     Logical,
  46.     LRecList;
  47.  
  48.  
  49. (* This routine will take two logical record lists and create a new list
  50.    (lrLst3) which contains all logical record numbers which are in both
  51.    the first and second lists.  The original lists, lrLst1 and lrLst2, are
  52.    not affected at all.  The resulting list, lrLst3, will have the record
  53.    numbers in the same order as lrLst1.  Therefore, if lrLst1 was in some
  54.    special order, lrLst3 will also be in that order (except of course it won't
  55.    have all the entries that lrLst1 has unless lrLst2 is a superset of
  56.    LrLst1.                                                                   *)
  57.  
  58. procedure Intersection(lrLst1 : LrList;
  59.                        lrLst2 : LrList;
  60.                        var lrLst3 : LrList);
  61.  
  62.  
  63. (* This routine will take two logical record lists and create a new list
  64.    (lrLst3) which contains all logical record numbers which are in either
  65.    the first and second lists or both.  The original lists, lrLst1 and lrLst2,
  66.    are not affected at all.  The resulting list, lrLst3, will have the record
  67.    numbers in the same order as lrLst1.  Therefore, if lrLst1 was in some
  68.    special order, lrLst3 will also be in that order.  Any record numbers
  69.    which are in lrLst2 and not in lrLst1 will appear after all entries which
  70.    are in lrLst1.                                                            *)
  71.  
  72. procedure Union(lrLst1 : LrList;
  73.                 lrLst2 : LrList;
  74.                 var lrLst3 : LrList);
  75.  
  76.  
  77. (* This routine will take two logical record lists and create a new list
  78.    (lrLst3) which contains all logical record numbers which are in the first
  79.    list but not in the second list.  The original lists, lrLst1 and lrLst2,
  80.    are not affected at all.  The resulting list, lrLst3, will have the record
  81.    numbers in the same order as lrLst1.  Therefore, if lrLst1 was in some
  82.    special order, lrLst3 will also be in that order.  Any record numbers
  83.    which are in lrLst1 and lrLst2 will be missing from the resulting list.   *)
  84.  
  85. procedure Difference(lrLst1 : LrList;
  86.                      lrLst2 : LrList;
  87.                      var lrLst3 : LrList);
  88.  
  89. (*\*)
  90. (*///////////////////// I M P L E M E N T A T I O N /////////////////////////*)
  91.  
  92. implementation
  93.  
  94. type
  95.     EntryPointer = ^EntryArray;
  96.  
  97.     EntryArray = Array[DataSizeRange] of Boolean;
  98.  
  99. (*\*)
  100. (* This internal routine will build an array of Boolean (bitmap) which will be
  101.    used to keep track of record numbers which are in a logical record list.
  102.    The list is built in memory using the heap if there is enough room.
  103.    Keeping this list in memeory speeds up processing.  If the list is created
  104.    then inMemory is set to TRUE and FALSE otherwise.  If the list is not
  105.    built in memory then the calling routine will have to use a slower method
  106.    to process the lists.                                                     *)
  107.  
  108. procedure PutList2InBitMap(lrLst1 : LrList;
  109.                            lrLst2 : LrList;
  110.                            var entryPtr : EntryPointer;
  111.                            var entriesNeeded : LrNumber;
  112.                            var inMemory : Boolean);
  113.  
  114. var
  115.     lrNum,
  116.     largestLr1,
  117.     largestLr2 : LrNumber;
  118.  
  119.     begin
  120.     largestLr1 := FindLargestLr(lrLst1);
  121.     largestLr2 := FindLargestLr(lrLst2);
  122.     if largestLr1 > largestLr2 then
  123.         begin
  124.         entriesNeeded := largestLr1;
  125.         end
  126.     else
  127.         begin
  128.         entriesNeeded := largestLr2;
  129.         end;
  130.     if MaxAvail > entriesNeeded then
  131.         begin
  132.         GetMem(entryPtr,entriesNeeded);
  133.         FillChar(entryPtr^,entriesNeeded,0);
  134.         lrNum := GetFirstLr(lrLst2);
  135.         while lrNum <> 0 do
  136.             begin
  137.             entryPtr^[lrNum] := TRUE;
  138.             lrNum := GetNextLr(lrLst2);
  139.             end;
  140.         inMemory := TRUE;
  141.         end
  142.     else
  143.         begin
  144.         inMemory := FALSE;
  145.         end;
  146.     end;                                  (* end of PutList2InBitMap routine *)
  147.  
  148. (*\*)
  149. (* This routine will take two logical record lists and create a new list
  150.    (lrLst3) which contains all logical record numbers which are in both
  151.    the first and second lists.  The original lists, lrLst1 and lrLst2, are
  152.    not affected at all.  The resulting list, lrLst3, will have the record
  153.    numbers in the same order as lrLst1.  Therefore, if lrLst1 was in some
  154.    special order, lrLst3 will also be in that order (except of course it won't
  155.    have all the entries that lrLst1 has unless lrLst2 is a superset of
  156.    LrLst1.                                                                   *)
  157.  
  158. procedure Intersection(lrLst1 : LrList;
  159.                        lrLst2 : LrList;
  160.                        var lrLst3 : LrList);
  161.  
  162. var
  163.     lrNum,
  164.     entriesNeeded : LrNumber;
  165.     entryPtr : EntryPointer;
  166.     inMemory : Boolean;   (* set TRUE iff the intersection can be done using
  167.                              the heap as a bit map.  ie enough heap space
  168.                              exists                                          *)
  169.  
  170.     begin
  171.     CreateLrList(lrLst3);
  172.     PutList2InBitMap(lrLst1,lrLst2,entryPtr,entriesNeeded,inMemory);
  173.     lrNum := GetFirstLr(lrLst1);
  174.     while lrNum <> 0 do
  175.         begin
  176.         if inMemory then
  177.             begin
  178.             if entryPtr^[lrNum] then
  179.                 begin
  180.                 AddToLrList(lrNum,lrLst3);
  181.                 end;
  182.             end
  183.         else
  184.             begin
  185.             if FindLrInList(lrNum,lrLst2) then
  186.                 begin
  187.                 AddToLrList(lrNum,lrLst3);
  188.                 end;
  189.             end;
  190.         lrNum := GetNextLr(lrLst1);
  191.         end;
  192.     if inMemory then
  193.         begin
  194.         FreeMem(entryPtr,entriesNeeded);
  195.         end;
  196.     end;                                      (* end of Intersection routine *)
  197.  
  198. (*\*)
  199. (* This routine will take two logical record lists and create a new list
  200.    (lrLst3) which contains all logical record numbers which are in either
  201.    the first and second lists or both.  The original lists, lrLst1 and lrLst2,
  202.    are not affected at all.  The resulting list, lrLst3, will have the record
  203.    numbers in the same order as lrLst1.  Therefore, if lrLst1 was in some
  204.    special order, lrLst3 will also be in that order.  Any record numbers
  205.    which are in lrLst2 and not in lrLst1 will appear after all entries which
  206.    are in lrLst1.                                                            *)
  207.  
  208. procedure Union(lrLst1 : LrList;
  209.                 lrLst2 : LrList;
  210.                 var lrLst3 : LrList);
  211.  
  212. var
  213.     lrNum,
  214.     entriesNeeded : LrNumber;
  215.     entryPtr : EntryPointer;
  216.     inMemory : Boolean;   (* set TRUE iff the union can be done using
  217.                              the heap as a bit map.  ie enough heap space
  218.                              exists                                          *)
  219.  
  220.     begin
  221.     CreateLrList(lrLst3);
  222.     PutList2InBitMap(lrLst1,lrLst2,entryPtr,entriesNeeded,inMemory);
  223.     lrNum := GetFirstLr(lrLst1);
  224.     while lrNum <> 0 do
  225.         begin
  226.         AddToLrList(lrNum,lrLst3);
  227.         if inMemory then
  228.             begin
  229.             entryPtr^[lrNum] := FALSE;
  230.             end;
  231.         lrNum := GetNextLr(lrLst1);
  232.         end;
  233.     if inMemory then
  234.         begin
  235.         for lrNum := 1 to entriesNeeded do
  236.             begin
  237.             if entryPtr^[lrNum] then
  238.                 begin
  239.                 AddToLrList(lrNum,lrLst3);
  240.                 end;
  241.             end;
  242.         FreeMem(entryPtr,entriesNeeded);
  243.         end
  244.     else
  245.         begin
  246.         lrNum := GetFirstLr(lrLst2);
  247.         while lrNum <> 0 do
  248.             begin
  249.             if not FindLrInList(lrNum,lrLst3) then
  250.                 begin
  251.                 AddToLrList(lrNum,lrLst3);
  252.                 end;
  253.             lrNum := GetNextLr(lrLst2);
  254.             end;
  255.         end;
  256.     end;                                             (* end of Union routine *)
  257.  
  258. (*\*)
  259. (* This routine will take two logical record lists and create a new list
  260.    (lrLst3) which contains all logical record numbers which are in the first
  261.    list but not in the second list.  The original lists, lrLst1 and lrLst2,
  262.    are not affected at all.  The resulting list, lrLst3, will have the record
  263.    numbers in the same order as lrLst1.  Therefore, if lrLst1 was in some
  264.    special order, lrLst3 will also be in that order.  Any record numbers
  265.    which are in lrLst1 and lrLst2 will be missing from the resulting list.   *)
  266.  
  267. procedure Difference(lrLst1 : LrList;
  268.                      lrLst2 : LrList;
  269.                      var lrLst3 : LrList);
  270.  
  271. var
  272.     lrNum,
  273.     entriesNeeded : LrNumber;
  274.     entryPtr : EntryPointer;
  275.     inMemory : Boolean;   (* set TRUE iff the difference can be done using
  276.                              the heap as a bit map.  ie enough heap space
  277.                              exists                                          *)
  278.  
  279.     begin
  280.     CreateLrList(lrLst3);
  281.     PutList2InBitMap(lrLst1,lrLst2,entryPtr,entriesNeeded,inMemory);
  282.     lrNum := GetFirstLr(lrLst1);
  283.     while lrNum <> 0 do
  284.         begin
  285.         if inMemory then
  286.             begin
  287.             if not entryPtr^[lrNum] then
  288.                 begin
  289.                 AddToLrList(lrNum,lrLst3);
  290.                 end;
  291.             end
  292.         else
  293.             begin
  294.             if not FindLrInList(lrNum,lrLst2) then
  295.                 begin
  296.                 AddToLrList(lrNum,lrLst3);
  297.                 end;
  298.             end;
  299.         lrNum := GetNextLr(lrLst1);
  300.         end;
  301.     if inMemory then
  302.         begin
  303.         FreeMem(entryPtr,entriesNeeded);
  304.         end;
  305.     end;                                        (* end of Difference routine *)
  306.  
  307. end.                                                 (* end of Relation unit *)
  308.