Calling Subroutines from Dictionary Items

Back to Knowledge Base Back to How To

The syntax for calling a subroutine from a dictionary item is:

B; {filename} subname

or

CALL {filename} subname

SYNTAX ELEMENTS

filename is ignored but provided for compatibility with older systems
subname is the name of the called subroutine (or function).  This subroutine must reside in one of the libraries defined by the user and must be visible via JBCOBJECTLIST.

 

The subroutine can be called as a conversion (attribute 7 of the dictionary item) or as a correlative (attribute 8 of the dictionary item). Data is passed to and from the subroutine with named COMMON elements. In each subroutine the following line must be included:

INCLUDE qbasiccommonpick

For ex-Sequoia users, you may INCLUDE the file qbasiccommonseq, which provides compatibility with that platform.

The INCLUDE file defines the named common that is used by jQL. The named common consists of 2 arrays: access and newpick.

The usage of these arrays is:

access

access(1) Data file open variable
access(2) Dictionary file open variable
access(3) Data item currently being processed. If BY-EXP is used then only the current multi-value from each attribute is included in the item.
access(4) Item count  (Initialized to 1 at the start of each jQL statement)
access(5) Attribute being processed. This is the value in attribute 2 of the calling dictionary item.
access(6) Value mark counter
access(7) Sub value mark counter
access(8) reserved
access(9) reserved
access(10) Item id
access(11) Data file name
access(12) reserved
access(13) reserved
access(14) Multivalue number from an exploded select-list
access(15)  reserved
access(16) reserved
access(17) reserved

By default jBASE will only call a subroutine once per item. This is normally desirable, since value and sub value manipulation can be done within the subroutine. In addition, it is clearly more efficient to only call the subroutine once per item. However, for backward compatibility, jBASE can be configured to call the subroutine for every value and sub value processed. If this is required then set jql_mv_subcall = true in the '$JBCRELEASEDIR/config/Config_EMULATE' file under the appropriate emulation section. If this setting is in place, access(6) and access(7) are incremented appropriately as each value and sub value is processed. Otherwise the values in access(6) and access(7) have no meaning.

newpick

newpick(1) through newpick(11) reserved

newpick(12) - On entry to the subroutine this will contain the value of the data passed from jQL to the subroutine. By default, this will be all the data defined by the calling dictionary item (i.e. all values and sub values). However if "jql_mv_subcall = true" is set, then the subroutine is called for every value/sub value and newpick(12) contains just each value or sub value as it is processed.

It is worth noting that a subroutine can be called as part of a multi-valued correlative. For example, the calling dictionary item could look like:

<1>S
<2>17
<8>F;"ABCD"]CALL SUB1

In this instance, the data defined by the calling dictionary item is "ABCD". But if the calling dictionary item is:

<1>S
<2>17
<8>CALL SUB1

Then the data passed to the subroutine in newpick(12) is simply the contents of attribute 17 of the current item, which may be multi/sub valued.

On exit of the subroutine, newpick(12) contains the value used by jQL.

*Exception to this is if config_EMULATE has generic_pick=true as in R83, AP or R91 emulations. In that case the passed parameter on the SUBROUTINE line would contain the value used by jQL.

 

EXAMPLE

COMMENTS (in DICT of SALES file)
001 A
002 3
003 Comments
004
005
006
007
008 CALL comments
009 T
010 25

Subroutine code:

001 SUBROUTINE comments .... OR .... SUBROUTINE comments(Value) for generic_pick=true exception
002 INCLUDE qbasiccommonpick
003 * Interpret Comment code
004 IF newpick(12) = "A" THEN newpick(12) = "Grade 1"
005 IF newpick(12) = "B" THEN newpick(12) = "Grade 2"
005+ Value = newpick(12) ;* if generic_pick=true exception
006 RETURN

LIST SALES COMMENTS

SALES........ Comments.................
ABC           Grade 1
DEF           Grade 2

 

Persistent Variables

When calling subroutines from dictionary items it is sometimes advantageous for the values of variables to persist between CALLs for the duration of the jQL execution. An example of how persistent variables can be employed is when it is necessary to READ from a file in the subroutine. Rather than open the file every time the subroutine is called (i.e. for each record processed by jQL), it is more efficient to open the file when the first record is processed and keep the file variable available for subsequent records. Likewise, this technique is useful for initializing any other variable.

This can be achieved with the following code in the subroutine:

SUBROUTINE MYSUB
...
COMMON /PERSIST/ CustFileVar, StaticTime
INCLUDE qbasiccommonpick
EQU ItemCount TO access(4) ;* access(4) is initialized to 1 at the start of each jQL statement
IF ItemCount = 1 THEN
    * Initialize all persistent variables in this section
    OPEN "CUSTOMER" TO CustFileVar ELSE
        GOSUB FatalError
        ABORT
    END
    StaticTime = TIME()
END
...
RETURN

Notice that the persistent variables (CustFileVar and StaticTime) are treated as named COMMON variables. The one caveat is that they are initialized for each jQL command. If a subroutine is called from two or more dictionary items in the same jQL command then the variables will be shared in the same way that COMMON variables are. If the subroutine is called recursively, then the variables will be shared between each level of recursion, in the same way that COMMON variables are.


http://www.jbase.com/r5/knowledgebase/howto/general/common/DictSubroutines.htm last modified on 04/29/11 09:09 AM