LSELECT - Create List Of Keys For Records Whose Field Definition Value Appears In A Defined List.

From Pickwiki
Jump to navigationJump to search

It is easy to select data from a file when a field equals a known value. e.g.

>LIST CUSTOMER WITH CUSTNO = "12345"

It is also easy to select data from a file when a field equals one of a number of known value. e.g.

>LIST CUSTOMER WITH CUSTNO = "12345""12346""12347""12348"

The query processor is very powerful and offers many ways to easily accommodate queries. Using selects before processing a query is a standard method to filter data. e.g.

>SELECT CUSTOMER WITH CUSTTYPE = "1"

14 items selected.

>>SELECT CUSTOMER WITH CUSTNO = "12345"

3 items selected.

>>LIST CUSTOMER

On occasion, we have a list of data we'd like to compare a select to to see if any data exists in the list. We might have a list of non-primary key values of colors and we want to select the items in a product file whose color matches one of the colors in this list.

It would be a very nice feature if we could do something like:

>LSELECT PRODUCTS WITH COLOR IN MYLIST

Somewhere we created MYLIST based on various colors with certain properties. e.g.

>SELECT COLORS WITH COLORTYPE = "POPULAR"

20 items selected.

>SAVE.LIST MYLIST Overwriting existing saved list. 20 key(s) saved to 1 record(s).

Now we want to use our fantasized query to select all our products that have this popular color.

>LSELECT PRODUCTS WITH COLOR IN MYLIST 750 items selected.

>>SORT PRODUCTS ....

Rocket Software, and IBM before this, had a tech tip that allowed us to create this new verb (LSELECT).

    <https://u2devzone.rocketsoftware.com/accelerate/articles/u2-select/u2-select>

The following is a basic program I created to use on UniData.


!
** Select file items using keys in select list
** (C) Copyright 1985-2012, Pacific Mgmt Software, Inc.  All Rights Reserved.
!
** Last Modified: 07 Aug 2012, wph
** First Created: 01 Oct 2009, wph
** Program Type-: Utility
!
** Notes:
**
** This process selects the items in [[FileName]] whose keys are in the
** defined select (saved) list.
**
**----------------------------------------------------------------------**
**                                                                      **
**                      I N I T I A L I Z A T I O N                     **
**                                                                      **
**----------------------------------------------------------------------**
*
** Initialization
NULL$ = ''
SP1   = ' '
*
* Initialize command variables
FILE.NAME   = NULL$
DICT.NAME   = NULL$
OPER        = NULL$
SOURCE.LIST = NULL$
TO.OP       = NULL$
DEST.LIST   = NULL$
*
** Initialize other variables
SOURCE.LIST.NAMED = 1
DEST.LIST.NAMED   = 1
DISPLAY.HELP      = 0
VERBOSE           = 0
*
**----------------------------------------------------------------------**
**                                                                      **
**               S T A R T   P R O C E S S I N G   D A T A              **
**                                                                      **
**----------------------------------------------------------------------**
*
** Run the command program
GOSUB GET.COMMAND
GOSUB GET.SOURCE.SELECT.LIST
GOSUB CREATE.TEMP.FILE
GOSUB LOAD.TEMP.FILE
GOSUB BUILD.LIST2
GOSUB FINISH.UP
GOTO END.OF.PROGRAM
*
**----------------------------------------------------------------------**
**                                                                      **
**                       S U B R O U T I N E ( S )                      **
**                                                                      **
**----------------------------------------------------------------------**
*
** Get the command and process
***************
GET.COMMAND:
***************
*
** Gather and parse input from command line
INPUT.PARAMS = TRIM(FIELD(@SENTENCE, " ", 2, 999))
SWAP ' ' WITH ';' IN INPUT.PARAMS
POS = 1
FILE.NAME = TRIM(FIELD(INPUT.PARAMS, ";", POS))
POS += 1
WITH.OP = UPCASE(TRIM(FIELD(INPUT.PARAMS, ";", POS)))
IF WITH.OP = "WITH" THEN POS += 1
DICT.NAME = TRIM(FIELD(INPUT.PARAMS, ";", POS))
POS += 1
OPER = UPCASE(TRIM(FIELD(INPUT.PARAMS, ";", POS)))
IF OPER = "IN" THEN
   POS += 1
   SOURCE.LIST= TRIM(FIELD(INPUT.PARAMS, ";", POS))
   POS += 1
   TO.OP = UPCASE(TRIM(FIELD(INPUT.PARAMS, ";", POS)))
   IF TO.OP = "TO" THEN POS += 1
   DEST.LIST = TRIM(FIELD(INPUT.PARAMS, ";", POS))
   IF DEST.LIST = "VERBOSE" OR DEST.LIST = "-V" THEN
      VERBOSE = 1
      DEST.LIST = NULL$
   END
END ELSE
   IF OPER = "TO" THEN
      POS += 1
      DEST.LIST = OCONV(TRIM(FIELD(INPUT.PARAMS, ";", POS)), 'MCU')
      IF DEST.LIST = "VERBOSE" OR DEST.LIST = "-V" THEN
         VERBOSE = 1
         DEST.LIST = NULL$
      END
   END ELSE
      IF OPER # NULL$ THEN
         ERROR.MSG =  'Expecting "IN" or "TO" clause. Found ':OPER
         GOSUB SHOW.MESSAGE
         DISPLAY.HELP = 1
      END
   END
END
*
LAST.COMMAND = UPCASE(FIELD(INPUT.PARAMS, ";", DCOUNT(INPUT.PARAMS, ";")))
IF (LAST.COMMAND = "VERBOSE") OR (LAST.COMMAND = "-V") THEN VERBOSE = 1
*
** Display Usage if parameters not supplied or help is requested
IF FILE.NAME = NULL$ OR FILE.NAME = "?" OR FILE.NAME = "HELP" OR DICT.NAME = NULL$ THEN DISPLAY.HELP = 1
IF DISPLAY.HELP THEN
   PRINT
   PRINT 'This will create a list of {[[FileName]]} keys for records whose'
   PRINT 'field definition value appears in a defined list.'
   PRINT
   PRINT 'Syntax:'
   PRINT '  LSELECT [[File_Name]] WITH [[Dict_Name]] IN LIST1 TO LIST2 [VERBOSE| -V]'
   PRINT
   PRINT 'Example: SELECT CUSTOMERS SAMPLE 500'
   PRINT ' SAVE.LIST MY.LIST'
   PRINT ' LSELECT SALES.ORDERS WITH CUST.NBR IN MY.LIST TO MY.LIST.2'
   PRINT
   PRINT 'Notes:'
   PRINT 'If a destination list is not supplied then keys will be left as the active'
   PRINT 'select list.  If a source list is not supplied then the current active select'
   PRINT 'list will be used.  Lists may be specified as select buffers (0-8) or as named'
   PRINT 'lists from SAVEDLISTS.'
   PRINT
   STOP
END
*
** Validate Dictionary
DR.REC = XLATE("DICT ":FILE.NAME, DICT.NAME, -1, "X")
IF DR.REC = NULL$ THEN
   ERROR.MSG = "Unable to read dictionary ":DICT.NAME:"  for file ":FILE.NAME
   GOSUB SHOW.MESSAGE
   STOP
END ELSE
   IF DR.REC<6> # "S" THEN
      ERROR.MSG = "Warning, ":DICT.NAME:" is not a single valued field. Results may be unexpected."
      GOSUB SHOW.MESSAGE
   END
END
*
** Complete defaulting behavior
IF SOURCE.LIST = NULL$ THEN
   SOURCE.LIST = 0
END
*
** Make sure the destination list has a value
IF DEST.LIST = NULL$ THEN DEST.LIST = 0
*
** Make sure source list name has a value (under misc circumstances)
IF NUM(SOURCE.LIST) AND LEN(SOURCE.LIST) = 1 AND (SOURCE.LIST NE 9) THEN SOURCE.LIST.NAMED = 0
*
** Make sure destination list name has a value (under misc circumstances)
IF NUM(DEST.LIST) AND LEN(DEST.LIST)=1 AND (DEST.LIST # 9) THEN DEST.LIST.NAMED = 0
*
** Display verbose information
IF VERBOSE THEN
   PRINT '(Parsed Command)'
   PRINT 'LSELECT ':FILE.NAME:' WITH ':DICT.NAME:' IN ':SOURCE.LIST:' TO ':DEST.LIST
   PRINT
END
RETURN
!
** Get the list of values to match
***************
GET.SOURCE.SELECT.LIST:
***************
*
SOURCE.ID.LIST = NULL$
*
** Process a named list
IF SOURCE.LIST.NAMED THEN
   EXECUTE \GET-LIST \ : SOURCE.LIST CAPTURING OUTPUT
   [[NoOfItems]] = SYSTEM(11)
   IF NOT([[NoOfItems]]) THEN
      ERROR.MSG = "Error reading saved list ":SOURCE.LIST : SP1 : OUTPUT
      GOSUB SHOW.MESSAGE
      STOP
   END
   READSELECT SOURCE.ID.LIST ELSE SOURCE.ID.LIST = NULL$
END ELSE
   READSELECT SOURCE.ID.LIST FROM SOURCE.LIST ELSE SOURCE.ID.LIST = NULL$
END
*
** Display verbose information
IF VERBOSE THEN
   PRINT '(Selected List)'
   PRINT 'List Source ':SOURCE.LIST:' found ':DCOUNT(SOURCE.ID.LIST, @AM):' items.'
   PRINT
END
RETURN
!
** Create temporary file to support TRANS selection
***************
CREATE.TEMP.FILE:
***************
*
** determine appropriate file size based on size of list of values to match
TBYTES   = SUM(LENS(SOURCE.ID.LIST))
TEMP.MOD = INT(TBYTES/1024)
IF TEMP.MOD < 1 THEN
   TEMP.MOD = 5
END
PROCESS.NBR = @UDTNO + 0
PROCESS.ID  = ('0000' : PROCESS.NBR : @LEVEL) "R#4"
TEMP.NAME   = 'LSELECT' : PROCESS.ID
UDT.COMMAND = 'CREATE.FILE ' : TEMP.NAME : SP1 : TEMP.MOD
PERFORM UDT.COMMAND CAPTURING UDT.RESPONSE
*
** Now open the temporary file
OPEN '', TEMP.NAME TO TEMP.HANDLE ELSE
   ERROR.MSG = "Error opening ":TEMP.NAME:" file"
   GOSUB SHOW.MESSAGE
   STOP
END
OPEN 'DICT', TEMP.NAME TO TEMP.DICT ELSE
   ERROR.MSG = "Error opening DICT ":TEMP.NAME:" file"
   GOSUB SHOW.MESSAGE
   STOP
END
*
** Display verbose information
IF VERBOSE THEN
   PRINT "(Create Temp File)"
   PRINT TEMP.NAME:' file created with MOD = ' : TEMP.MOD
   PRINT
END
RETURN
!
** Put selection values into temp file
***************
LOAD.TEMP.FILE:
***************
*
EMPTY.STRING = ''
MORE.IDS     = 1
[[LoadCnt]]      = 0
LOOP
   REMOVE ID FROM SOURCE.ID.LIST SETTING MORE.IDS
   WRITEVU EMPTY.STRING ON TEMP.HANDLE, ID, 0
   [[LoadCnt]] += 1
WHILE MORE.IDS DO
REPEAT
*
** Reset internal udt REMOVE pointer
SOURCE.ID.LIST = SOURCE.ID.LIST
*
** Display verbose information
IF VERBOSE THEN
   PRINT "(Loaded List to Temp File) - " : [[LoadCnt]] : " items."
   PRINT
END
RETURN
*
** Create the resulting list
***************
BUILD.LIST2:
***************
*
TRANS.STMT = "TRANS('" : TEMP.NAME : "'," : DICT.NAME : ",'@ID','X')"
IF DEST.LIST.NAMED THEN
   UDT.COMMAND = 'select ':FILE.NAME:' WITH EVAL "':TRANS.STMT:'" GT "" '
   PERFORM UDT.COMMAND CAPTURING UDT.RESPONSE
   PERFORM 'SAVE.LIST ':DEST.LIST
END ELSE
   UDT.COMMAND = 'select ':FILE.NAME:' WITH EVAL "':TRANS.STMT:'" GT "" TO ':DEST.LIST
   PERFORM UDT.COMMAND CAPTURING UDT.RESPONSE
   IF NOT(VERBOSE) THEN HUSH ON
   PERFORM 'SAVE.LIST ':TEMP.NAME
   IF NOT(VERBOSE) THEN HUSH OFF
END
*
** Display verbose information
IF VERBOSE THEN
   PRINT "(Selected Result List)"
   PRINT "UDT.COMMAND = ":UDT.COMMAND
   PRINT "UDT.RESPONSE = ":UDT.RESPONSE
   PRINT "Destination ":DEST.LIST
   PRINT "Named List ":DEST.LIST.NAMED
   PRINT
END
RETURN
!
** Remove temporary key list file
***************
FINISH.UP:
***************
*
** Close and delete the temporary file
CLOSE TEMP.HANDLE
CLOSE TEMP.DICT
UDT.COMMAND = 'DELETE.FILE ':TEMP.NAME
DATA 'Y'
PERFORM UDT.COMMAND CAPTURING UDT.RESPONSE
*
** Display verbose information
IF VERBOSE THEN
   PRINT "(Delete Temp File)"
   PRINT TEMP.NAME:' file deleted...'
   PRINT
END
*
** Create a currently active select list (if no to-list defined)
IF NOT(DEST.LIST.NAMED) THEN
   PERFORM 'GET.LIST ':TEMP.NAME CAPTURING UDT.RESPONSE
   READSELECT SOURCE.ID.LIST ELSE SOURCE.ID.LIST = NULL$
   PERFORM 'DELETE.LIST ':TEMP.NAME CAPTURING UDT.RESPONSE
   FORMLIST SOURCE.ID.LIST
END
RETURN
!
** Display error messages
***************
SHOW.MESSAGE:
***************
*
PRINT ERROR.MSG
PRINT "Press <cr> To Continue":
INPUT DUMMY
RETURN
*
**----------------------------------------------------------------------**
**                                                                      **
**                      E N D   O F   P R O G R A M                     **
**                                                                      **
**----------------------------------------------------------------------**
*
***************
END.OF.PROGRAM:
***************
*
END

A use of the program would look like:

2 Dev (0)-> SELECT MASTER WITH YREND NE "12"

4 records selected to list 0.

2 Dev (0)-> SAVE-LIST MY.LIST Overwriting existing saved list. 4 key(s) saved to 1 record(s). 2 Dev (0)-> LSELECT ARTMASTER WITH CLIENTNO IN MY.LIST VERBOSE (Parsed Command) LSELECT ARTMASTER WITH CLIENTNO IN MY.LIST TO 0

(Selected List) List Source MY.LIST found 4 items.

(Create Temp File) LSELECT0021 file created with MOD = 5

(Loaded List to Temp File) - 4 items.

235 key(s) saved to 1 record(s). (Selected Result List) UDT.COMMAND = select ARTMASTER WITH EVAL "TRANS('LSELECT0021',CLIENTNO,'@ID','X') " GT "" TO 0 UDT.RESPONSE = ■235 records selected to list 0.■■ Destination 0 Named List 0

(Delete Temp File) LSELECT0021 file deleted...

2 Dev (0)-> SSCROLL ARTMASTER


Command => SORT  ARTMASTER                                09:11:36 Oct 18 2012
ARTMASTER... CUSTOMER NAME (LFM)............ BT MOVE-IN. PRICHG$... BAL DUE...

120*1        ROBINSON, JAMES                    05-17-07     210.00       0.00
120*2        ROBINSON, KATHRYN J                06-18-08     210.00     210.00
120*3        GARCIA, SAMANTHA L                 08-13-09     210.00    -210.00
120*4        ROBINSON, CAROL A                  03-15-95     210.00     210.00
120*5        ROBINSON, AARON L                  09-19-06     210.00     210.00
  .
  .

I hope this is of some help.