How to make an item list
BTPFIND and BTPSEQ allow all or just a range of item identifiers to be extracted from a B-tree in a pre-defined order, so that a program doesn't have to wait for a SSELECT to finish before output can be generated. For example, here's a program to output a selected range of items in our NAMES file:
LIST.NAMES.RANGE001 OPEN "B-TREE" TO BFILE ELSE STOP002 OPEN "NAMES" TO NFILE ELSE STOP003 CRT ; CRT "Ready to output sorted mailing labels."004 CRT "C (by company) or N (by name) or Z (by zip)":005 INPUT ROOT006 BEGIN CASE007 CASE ROOT = "C"008 ROOT = "COMP" ; FRAG = "company" ; AMC = 3009 CASE ROOT = "N"010 ROOT = "LNAME" ; FRAG = "last name" ; AMC = 2011 CASE 1012 ROOT = "ZIP" ; FRAG = "zip code" ; AMC = 6013 END CASE014 CRT "Beginning ":FRAG015 CRT "(or just RETURN for very first)": ; INPUT FIRST016 CRT "Ending ":FRAG017 CRT "(or just RETURN for very last)": ; INPUT LAST018 CRT019 ID = "" ; ITEM = "" ; ITEM<AMC> = FIRST020 CALL BTPFIND(ROOT,BFILE,NFILE,ID,ITEM,NODE,POS)021 LOOP022 IF ID = "" THEN STOP023 READ NAMES FROM NFILE, ID ELSE NAMES = ""024 UNTIL (NAMES<AMC> > LAST) AND (LAST # "") DO025 PRINT NAMES<1>:" ":NAMES<2>:" ":ID026 PRINT NAMES<3> ; PRINT NAMES<4>027 PRINT NAMES<5>:" ":NAMES<6> ; PRINT028 CALL BTPSEQ(BFILE, NODE, POS, "NEXT", ID)029 REPEAT030 STOP031 ENDAlthough the above code can immediately output any range of names, companies, or ZIP codes without delay, the output is generated with BASIC. Often, it would be more convenient to just extract identifiers from a B-tree as an item list, and then let the SORT or LIST verb generate the output. Unfortunately, Pick does not offer a "writenext" capability to allow a program to write an item list, to complement the way a program can read an item list with READNEXT. That leaves two choices for a program that extracts item identifiers from a B-tree, but doesn't want to generate its own output. If the identifier list is small, the program can save the list as a single item which can then be retrieved with QSELECT or FORM-LIST before using the LIST verb. If the item list is large, the program can save the identifiers in a scratch file, which can then be retrieved with a SSELECT.
For example, here is a program that saves a list of all NAMES items in ZIP code order:
MAKE.LIST.ITEM001 OPEN "B-TREE" TO BFILE ELSE STOP002 OPEN "NAMES" TO NFILE ELSE STOP003 OPEN "MD" TO MFILE ELSE STOP004 ID = "" ; ITEM = "" ; ITEM.LIST = ""005 CALL BTPFIND("ZIP",BFILE,NFILE,ID,ITEM,NODE,POS)006 LOOP UNTIL ID = "" DO007 ITEM.LIST<-1> = ID008 CALL BTPSEQ(BFILE, NODE, POS, "NEXT", ID)009 REPEAT010 WRITE ITEM.LIST ON MFILE, "ZLIST"011 STOP012 ENDExecute MAKE.LIST.ITEM, then give the command QSELECT MD 'ZLIST', and you can then use the command LIST NAMES to output all items in ZIP code order without having to use SORT... BY... commands.
MAKE.LIST.ITEM will bog down if the number of items is large. In that case, save the item identifiers in a scratch file with a program like:
MAKE.LIST.FILE001 OPEN "B-TREE" TO BFILE ELSE STOP002 OPEN "NAMES" TO NFILE ELSE STOP003 OPEN "SCRATCH" TO SFILE ELSE STOP004 ID = "" ; ITEM = "" ; NEXT.ID = 1005 CALL BTPFIND("ZIP",BFILE,NFILE,ID,ITEM,NODE,POS)006 LOOP UNTIL ID = "" DO007 WRITE ID ON SFILE, NEXT.ID ; NEXT.ID = NEXT.ID+1008 CALL BTPSEQ(BFILE, NODE, POS, "NEXT", ID)009 REPEAT010 STOP011 ENDExecute MAKE.LIST.FILE, then SSELECT SCRATCH (using right justification), then QSELECT SCRATCH, then LIST NAMES to avoid sorting the NAMES file itself.
MAKE.LIST.ITEM and MAKE.LIST.FILE are only advantageous if their execution times plus the time necessary for subsequent SELECTs is less than the time needed to SSELECT the NAMES file itself. If MAKE.LIST.ITEM and MAKE.LIST.FILE output a range of items (like LIST.NAMES.RANGE does), then they can be very powerful tools that extract a sorted list of items much faster than a SELECT command.