Welcome to jBASE's new documentation site! Many answers to your questions can be found by searching the Knowledgebase or viewing the jBASE Documentation. We also have a Google Group for peer discussion about jBASE. If you are unable to find the information you are looking for, jBASE Support will be glad to assist in resolving your technical problems. Enjoy and please provide comments and feedback .

How can we help you?

Calling a Subroutine from a Dictionary Item

Description

It is possible to have dictionary items call subroutines. This can be done as follows: 

B;{filename} subname

or

CALL {filename} subname

where :

  • 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, It is possible to 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.


Their 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(1) through newpick(11) are 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 D3, R83, AP or R91 emulations. In that case the passed parameter on the SUBROUTINE line would contain the value used by jQL.


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 that is required to persist throughout the jQL process. 

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

001     SUBROUTINE process_customers
002     COMMON /persist/ customer_file, static_time
003     INCLUDE qbasiccommonpick
004     EQU item_count TO access(4) ;* access(4) is initialized to 1 at the start of each jQL statement
005     EQU id TO access(10)
006     IF item_count = 1 THEN
007 *-- Initialize all persistent variables here...
008         OPEN "CUSTOMERS" TO customer_file ELSE ABORT
009         static_Time = TIME()
010     END
011     READ customer_record FROM customer_file, id THEN
012 *------ Process the customer here and return the result in newpick(12)
013     END
014     RETURN

Notice that the persistent variables (customer_file and static_time) 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. 

Example 1

This example illustrates how to get a running total of an attribute.

First, create this subroutine: 

001     SUBROUTINE running_total_sub
002     COMMON /running_total_common/ running_total
003     INCLUDE qbasiccommonpick
004     EQU item TO access(3)
005     EQU item_count TO access(4)
006     EQU attribute_number TO access(5)
007     IF item_count = 1 THEN running_total = 0
008     running_total += item<attribute_number>
009     newpick(12) = running_total
010     RETURN

Note that the program is using named-COMMON to allow the running_total variable to persist when the subroutine is CALL'd for each record being processed.

Line 5 is intialized to 1 at the start of a jQL query and is incremented for each record processed. 

Now, create a file called JQLDEMO with these records, where the AMT values are in attribute 6: 

JQLDEMO....... AMT

1               97
2               30
3               18
4               96
5                3
6               44
7               61
8               12
9               28
10              96

Create a dictionary item for attribute 6: 

ID: AMT
001 A
002 6
003
004
005
006
007
008
009 R
010 3

Create a dictionary item to call the subroutine to display a running total from attribute 6: 

ID: RUNNING.TOTAL
001 A
002 6
003 RUNNING]  TOTAL
004
005
006
007 MD0,
008 CALL running_total_sub
009 R
010 7

Now run this jQL statment: 

LIST JQLDEMO TOTAL AMT RUNNING.TOTAL HDR-SUPP

Results: 

JQLDEMO....... AMT RUNNING
                     TOTAL

1               97      97
2               30     127
3               18     145
4               96     241
5                3     244
6               44     288
7               61     349
8               12     361
9               28     389
10              96     485
               ===
***            485

 10 Records Listed

You will notice that each amount is added to the previous value in the RUNNING TOTAL column and that the total of AMT matches the final running total.


Example 2

This program illustrates how to obtain the last multi-value from an attribute: 

001     SUBROUTINE lastmv
002     INCLUDE qbasiccommonpick
003     newpick(12) = newpick(12)<1, DCOUNT(newpick(12), @VM)>
004     RETURN

For instance, this dictionary will display the last multi-value from attribute 1: 

ID:LASTVAL
001 A
002 1
...
008 CALL lastmv
009 L
010 10

 

 




Was this article helpful?