home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TPTREE16.ZIP / BTREE2.INC < prev    next >
Encoding:
Text File  |  1989-04-01  |  20.0 KB  |  494 lines

  1. (******************************************************************************)
  2. (*                                                                           *)
  3. (*             B T R E E   R E T R I E V A L   R O U T I N E S               *)
  4. (*                                                                           *)
  5. (*****************************************************************************)
  6.  
  7. (* This routine locates all values within the index which meet a condition
  8.    (cond) and returns a list of logical record numbers corresponding to these
  9.    values.
  10.  
  11.    note - In the case of  cond = EX (exists) all entries in the index will be
  12.    returned.  paramValue is not really used in this case so anything (a dummy)
  13.    can be passed in as the parameter corresponding to paramValue.            *)
  14.  
  15. procedure GetValuesFromBTree(iFName : FnString;
  16.                              var paramValue;
  17.                              cond : Condition;
  18.                              var lrLst : LrList);
  19.  
  20. var
  21.     pRec : ParameterRecord;                    (* holds the index parameters *)
  22.     sNode : NodePtrType;         (* used as pointer to current sequence node *)
  23.     vCnt : Byte;                                (* count of values in a node *)
  24.     result : Comparison;
  25.     page : SinglePage;
  26.     finished,
  27.     done : Boolean;
  28.     cnt : Byte;               (* used to count number of values *)
  29.     lrNum : LrNumber;
  30.     bytePtr : PageRange;      (* used to keep track of current byte *)
  31.  
  32.     (* used to simplify the body of GetValuesFromBTree *)
  33.  
  34.     function Completed : Boolean;
  35.  
  36.     begin
  37.     if cnt > vCnt then
  38.         begin
  39.         Completed := TRUE;
  40.         end
  41.     else
  42.         begin
  43.         case cond of
  44.             GE : Completed := (CompareValues(page[bytePtr + RNSIZE],
  45.                                              paramValue,
  46.                                              pRec.vType) <> LESSTHAN);
  47.  
  48.             GT : Completed := (CompareValues(page[bytePtr + RNSIZE],
  49.                                              paramValue,
  50.                                              pRec.vType) = GREATERTHAN);
  51.             end;                                    (* end of case statement *)
  52.         end;
  53.     end;                                         (* end of Completed routine *)
  54.  
  55.     begin
  56.     CreateLrList(lrLst);
  57.     FetchFileParameters(iFName,pRec,SizeOf(pRec));
  58.     case cond of
  59.         EX,
  60.         NE,
  61.         LT,
  62.         LE,
  63.         GE,
  64.         GT : begin
  65.              bytePtr := 1;
  66.              cnt := 1;
  67.              case cond of
  68.                   EX,LT,LE,NE :
  69.                                 begin
  70.                                 sNode := pRec.fSNode;
  71.                                 FetchPage(iFName,sNode,page);
  72.                                 vCnt := page[VCNTLOC];
  73.                                 end;
  74.                   GE,GT :
  75.                                 begin
  76.                                 sNode := FindSNode(iFName,pRec.rNode,
  77.                                                    paramValue,pRec);
  78.                                 FetchPage(iFName,sNode,page);
  79.                                 vCnt := page[VCNTLOC];
  80.                                 while not Completed do
  81.                                     begin
  82.                                     bytePtr := bytePtr + pRec.vSize + RNSIZE;
  83.                                     Inc(cnt);
  84.                                     end;
  85.                                 end;
  86.                   end;                        (* end of inner case statement *)
  87.              done := FALSE;
  88.              while not done do
  89.                  begin
  90.                  if cnt <= vCnt then
  91.                      begin
  92.                      finished := FALSE;
  93.                      end
  94.                  else
  95.                      begin
  96.                      done := TRUE;
  97.                      finished := TRUE;
  98.                      end;
  99.                  while not finished do
  100.                      begin
  101.                      if cond <> EX then
  102.                          begin
  103.                          result := CompareValues(page[bytePtr + RNSIZE],
  104.                                                  paramValue,
  105.                                                  pRec.vType);
  106.                          end;
  107.                      if ((result = GREATERTHAN)
  108.                             and ((cond = LT) or (cond = LE))) or
  109.                         ((result = EQUALTO)
  110.                             and (cond = LT)) then
  111.                          begin
  112.                          finished := TRUE;
  113.                          done := TRUE;
  114.                          end
  115.                      else
  116.                          begin
  117.                          if (cond <> NE) or (result <> EQUALTO) then
  118.                              begin
  119.                              Move(page[bytePtr],lrNum,RNSIZE);
  120.                              AddToLrList(lrNum,lrLst);
  121.                              end;
  122.                          if cnt = vCnt then
  123.                              begin
  124.                              finished := TRUE;
  125.                              Move(page[NEXTLOC],sNode,RNSIZE);
  126.                              if sNode = NULL then
  127.                                  begin
  128.                                  done := TRUE;
  129.                                  end
  130.                              else
  131.                                  begin
  132.                                  FetchPage(iFName,sNode,page);
  133.                                  vCnt := page[VCNTLOC];
  134.                                  bytePtr := 1;
  135.                                  cnt := 1;
  136.                                  end;
  137.                              end
  138.                          else
  139.                              begin
  140.                              bytePtr := bytePtr + pRec.vSize + RNSIZE;
  141.                              Inc(cnt);
  142.                              end;
  143.                          end;
  144.                      end;
  145.                  end;
  146.              end;
  147.         EQ : begin
  148.              GetEqualsFromBTree(iFName,paramValue,lrLst,pRec);
  149.              end;
  150.         end;                                        (* end of case statement *)
  151.     end;                                (* end of GetValuesFromBTree routine *)
  152.  
  153. (*\*)
  154. (* This routine locates all values within the index within a given range and
  155.    returns a list of logical record numbers corresponding to values within
  156.    that range.  The range is determined by paramValue1 and paramValue2.
  157.    paramValue1 must be less than paramValue2.  cond1 and cond2 are used to
  158.    determine if the range is inclusive or exclusive.  cond1 must be either
  159.    GE or GT and cond2 must be either LE or LT for this to work.  If any of
  160.    the above conditions is not true then an empty list will be returned.     *)
  161.  
  162. procedure GetRangeFromBTree(iFName : FnString;
  163.                             var paramValue1;
  164.                             cond1 : Condition;
  165.                             var paramValue2;
  166.                             cond2 : Condition;
  167.                             var lrLst : LrList);
  168.  
  169. var
  170.     pRec : ParameterRecord;                    (* holds the index parameters *)
  171.     sNode : NodePtrType;         (* used as pointer to current sequence node *)
  172.     vCnt : Byte;                                (* count of values in a node *)
  173.     result : Comparison;
  174.     page : SinglePage;
  175.     finished,
  176.     done : Boolean;
  177.     cnt : Byte;               (* used to count number of values *)
  178.     lrNum : LrNumber;
  179.     bytePtr : PageRange;      (* used to keep track of current byte *)
  180.  
  181.     (* used to simplify the body of GetRangeFromBTree *)
  182.  
  183.     function Completed : Boolean;
  184.  
  185.     begin
  186.     if cnt > vCnt then
  187.         begin
  188.         Completed := TRUE;
  189.         end
  190.     else
  191.         begin
  192.         case cond1 of
  193.             GE : Completed := (CompareValues(page[bytePtr + RNSIZE],
  194.                                              paramValue1,
  195.                                              pRec.vType) <> LESSTHAN);
  196.  
  197.             GT : Completed := (CompareValues(page[bytePtr + RNSIZE],
  198.                                              paramValue1,
  199.                                              pRec.vType) = GREATERTHAN);
  200.             end;                                    (* end of case statement *)
  201.         end;
  202.     end;                                         (* end of Completed routine *)
  203.  
  204.     begin
  205.     CreateLrList(lrLst);
  206.     FetchFileParameters(iFName,pRec,SizeOf(pRec));
  207.     if (cond1 in [GT,GE]) and
  208.        (cond2 in [LT,LE]) and
  209.        (CompareValues(paramValue1,paramValue2,pRec.vType) <> GREATERTHAN) then
  210.         begin
  211.         bytePtr := 1;
  212.         cnt := 1;
  213.         sNode := FindSNode(iFName,pRec.rNode,paramValue1,pRec);
  214.         FetchPage(iFName,sNode,page);
  215.         vCnt := page[VCNTLOC];
  216.         while not Completed do
  217.             begin
  218.             bytePtr := bytePtr + pRec.vSize + RNSIZE;
  219.             Inc(cnt);
  220.             end;
  221.         done := FALSE;
  222.         while not done do
  223.             begin
  224.             if cnt <= vCnt then
  225.                 begin
  226.                 finished := FALSE;
  227.                 end
  228.             else
  229.                 begin
  230.                 done := TRUE;
  231.                 finished := TRUE;
  232.                 end;
  233.             while not finished do
  234.                 begin
  235.                 result := CompareValues(page[bytePtr + RNSIZE],
  236.                                              paramValue2,
  237.                                              pRec.vType);
  238.                 if (result = GREATERTHAN) or
  239.                    ((result = EQUALTO) and (cond2 = LT)) then
  240.                     begin
  241.                     finished := TRUE;
  242.                     done := TRUE;
  243.                     end
  244.                 else
  245.                     begin
  246.                     Move(page[bytePtr],lrNum,RNSIZE);
  247.                     AddToLrList(lrNum,lrLst);
  248.                     if cnt = vCnt then
  249.                         begin
  250.                         finished := TRUE;
  251.                         Move(page[NEXTLOC],sNode,RNSIZE);
  252.                         if sNode = NULL then
  253.                             begin
  254.                             done := TRUE;
  255.                             end
  256.                         else
  257.                             begin
  258.                             FetchPage(iFName,sNode,page);
  259.                             vCnt := page[VCNTLOC];
  260.                             bytePtr := 1;
  261.                             cnt := 1;
  262.                             end;
  263.                         end
  264.                     else
  265.                         begin
  266.                         bytePtr := bytePtr + pRec.vSize + RNSIZE;
  267.                         Inc(cnt);
  268.                         end;
  269.                     end;
  270.                 end;
  271.             end;
  272.         end;
  273.     end;                                 (* end of GetRangeFromBTree routine *)
  274.  
  275. (*\*)
  276. (* This routine is internal only and will search for a partial string match.
  277.    If position is not equal to 0 then cond must be CO and a list is returned
  278.    for all entries that contain a match anywhere in the string.  If position
  279.    is equal to 0 then position is ignored and a matches will be sought
  280.    according to the value of cond.  This routine is used by
  281.    GetSubstringFromBTree and GetSubstringAtPositionFromBTree                 *)
  282.  
  283. procedure InternalGetSubstring(iFName : FnString;
  284.                                var paramValue;       (* must be a string var *)
  285.                                cond : StringCondition;
  286.                                position : StringLengthRange;
  287.                                var lrLst : LrList);
  288.  
  289. var
  290.     pRec : ParameterRecord;                    (* holds the index parameters *)
  291.     sNode : NodePtrType;         (* used as pointer to current sequence node *)
  292.     vCnt : Byte;                                (* count of values in a node *)
  293.     result : Comparison;
  294.     page : SinglePage;
  295.     finished,
  296.     done : Boolean;
  297.     cnt : Byte;               (* used to count number of values *)
  298.     lrNum : LrNumber;
  299.     bytePtr : PageRange;      (* used to keep track of current byte *)
  300.  
  301.     (* used to simplify the body of InternalGetSubstring *)
  302.  
  303.     function Completed : Boolean;
  304.  
  305.     begin
  306.     if cnt > vCnt then
  307.         begin
  308.         Completed := TRUE;
  309.         end
  310.     else
  311.         begin
  312.         Completed := (SubstringCompare(page[bytePtr + RNSIZE],
  313.                       paramValue) <> LESSTHAN);
  314.         end;
  315.     end;                                         (* end of Completed routine *)
  316.  
  317.     begin
  318.     CreateLrList(lrLst);
  319.     FetchFileParameters(iFName,pRec,SizeOf(pRec));
  320.     bytePtr := 1;
  321.     cnt := 1;
  322.     case cond of
  323.         CO,EN :
  324.                       begin
  325.                       sNode := pRec.fSNode;
  326.                       FetchPage(iFName,sNode,page);
  327.                       vCnt := page[VCNTLOC];
  328.                       end;
  329.         ST :
  330.                       begin
  331.                       sNode := FindSNode(iFName,pRec.rNode,
  332.                                          paramValue,pRec);
  333.                       FetchPage(iFName,sNode,page);
  334.                       vCnt := page[VCNTLOC];
  335.                       while not Completed do
  336.                           begin
  337.                           bytePtr := bytePtr + pRec.vSize + RNSIZE;
  338.                           Inc(cnt);
  339.                           end;
  340.                       end;
  341.         end;                                  (* end of inner case statement *)
  342.     done := FALSE;
  343.     while not done do
  344.         begin
  345.         if cnt <= vCnt then
  346.             begin
  347.             finished := FALSE;
  348.             end
  349.         else
  350.             begin
  351.             done := TRUE;
  352.             finished := TRUE;
  353.             end;
  354.         while not finished do
  355.             begin
  356.             case cond of
  357.                 ST :
  358.                      begin
  359.                      if StartsWithSubstring(paramValue,
  360.                                             page[bytePtr + RNSIZE]) then
  361.                          begin
  362.                          Move(page[bytePtr],lrNum,RNSIZE);
  363.                          AddToLrList(lrNum,lrLst);
  364.                          end
  365.                      else
  366.                          begin
  367.                          finished := TRUE;
  368.                          done := TRUE;
  369.                          end;
  370.                      end;
  371.                 CO :
  372.                      begin
  373.                      if position = 0 then
  374.                          begin
  375.                          if ContainsSubstring(paramValue,
  376.                                               page[bytePtr + RNSIZE]) then
  377.                              begin
  378.                              Move(page[bytePtr],lrNum,RNSIZE);
  379.                              AddToLrList(lrNum,lrLst);
  380.                              end;
  381.                          end
  382.                      else
  383.                          begin
  384.                          if ContainsSubstringAtPosition(paramValue,
  385.                                                         page[bytePtr + RNSIZE],
  386.                                                         position) then
  387.                              begin
  388.                              Move(page[bytePtr],lrNum,RNSIZE);
  389.                              AddToLrList(lrNum,lrLst);
  390.                              end;
  391.                          end;
  392.                      end;
  393.                 EN :
  394.                      begin
  395.                      if EndsWithSubstring(paramValue,
  396.                                           page[bytePtr + RNSIZE]) then
  397.                          begin
  398.                          Move(page[bytePtr],lrNum,RNSIZE);
  399.                          AddToLrList(lrNum,lrLst);
  400.                          end;
  401.                      end;
  402.                 end;                                (* end of case statement *)
  403.             if not finished then
  404.                 begin
  405.                 if cnt = vCnt then
  406.                     begin
  407.                     finished := TRUE;
  408.                     Move(page[NEXTLOC],sNode,RNSIZE);
  409.                     if sNode = NULL then
  410.                         begin
  411.                         done := TRUE;
  412.                         end
  413.                     else
  414.                         begin
  415.                         FetchPage(iFName,sNode,page);
  416.                         vCnt := page[VCNTLOC];
  417.                         bytePtr := 1;
  418.                         cnt := 1;
  419.                         end;
  420.                     end
  421.                 else
  422.                     begin
  423.                     bytePtr := bytePtr + pRec.vSize + RNSIZE;
  424.                     Inc(cnt);
  425.                     end;
  426.                 end;
  427.             end;
  428.         end;
  429.     end;                              (* end of InternalGetSubstring routine *)
  430.  
  431. (*\*)
  432. (* This routine locates partial string matches in an index of type
  433.    STRINGVALUE.  A partial string match occurs when the string passed in as
  434.    paramValue is contained within a string entry in the index.  You must
  435.    specify where in the string the match must occur.  You accomplish this by
  436.    using cond.  cond can be CO which stands for contains.  In this case, a
  437.    match occurs if the string passed in as paramValue is anywhere in the
  438.    string in the index.  Another option for cond is ST which stands for
  439.    starts.  A match will occur in this instance if paramValue is located at
  440.    the start of the string in the index.  The last option for cond is EN which
  441.    stands for ends.  A match here occurs if paramValue matches the last
  442.    characters in the index string.  Be aware that if paramValue and the string
  443.    being checked are the same length and they match exactly, then a match
  444.    would occur if any of the three options were selected (not earth shattering
  445.    but true nonetheless).
  446.  
  447.    Otherwise, this works like any of the other retrieval routines.  A list of
  448.    logical record numbers will be returned.
  449.  
  450.    This is exceptionally useful for many applications.  For example, a field
  451.    might be a 7 digit code stored as a string (STRINGVALUE).  The last two
  452.    digits might mean something in particular (part category, state, or
  453.    whatever).  Using this you can look for all the matches on only the last
  454.    two digits.
  455.  
  456.    One reality note here!! - For cond <> ST I have to look at every entry in
  457.    the index for matches.  Why this is true should be reasonably obvious.
  458.    Anyway, for cond = EN or cond = CO it will be somewhat slower than for cond
  459.    = ST.  How much slower depends on the size of the index.  It boils down to
  460.    the difference between a O(LOG(n)) algorithm and a O(n) algorithm, the
  461.    former being much faster for n = a large number.  If any of the above is
  462.    confusing ignore it and experiment.  It is still better to use this routine
  463.    than to grovel through all of the data records yourself!!                 *)
  464.  
  465.  
  466. procedure GetSubstringFromBTree(iFName : FnString;
  467.                                 var paramValue;      (* must be a string var *)
  468.                                 cond : StringCondition;
  469.                                 var lrLst : LrList);
  470.  
  471.  
  472.     begin
  473.     InternalGetSubstring(iFName,paramValue,cond,0,lrLst);
  474.     end;                             (* end of GetSubstringFromBTree routine *)
  475.  
  476. (*\*)
  477. (* This routine is exactly like GetSubstringFromBTree except that matches only
  478.    occur if the substring passed in as paramValue is located at the exact
  479.    location specified by the position parameter.  Also, the cond parameter is
  480.    omitted since it only makes sense to look for a partial string match at a
  481.    particular position if cond is CO.  In other works, you will get a logical
  482.    record list with entries for all index values which contain paramValue at
  483.    the character position specified by position.                             *)
  484.  
  485. procedure GetSubstringAtPositionFromBTree(iFName : FnString;
  486.                                           var paramValue;   (* must be a string
  487.                                                                          var *)
  488.                                           position : StringLengthRange;
  489.                                           var lrLst : LrList);
  490.  
  491.     begin
  492.     InternalGetSubstring(iFName,paramValue,CO,position,lrLst);
  493.     end;                   (* end of GetSubstringAtPositionFromBTree routine *)
  494.