Purpose
Defines a subroutine that Net.Data invokes from the macro. The executable statements in a FUNCTION block can be inline statements directly interpreted by a language environment, or they can be a call to an external program.
If you use the EXEC block within the FUNCTION block, it must be the only executable statement in the FUNCTION block. Before passing the executable statement to the language environment, Net.Data appends the file name of the program in the EXEC block to a path name determined by the EXEC_PATH path configuration statement in the initialization file. The resulting string is passed to the language environment to be executed.
The method that the language environment uses to process the EXEC block depends on the particular language environment; the REXX, System, and Perl Net.Data-provided language environments support the EXEC block.
When characters that match Net.Data language constructs syntax are used in the language statements section of a function block as part of syntactically valid embedded program code (such as REXX or Perl), they can be misinterpreted as Net.Data language constructs, causing errors or unpredictable results in a macro.
For example, a Perl function might use the COMMENT block delimiter characters, %{. When the macro is run, the %{ characters are interpreted as the beginning of a COMMENT block. Net.Data then looks for the end of the COMMENT block, which it thinks it finds when it reads the end of the function block. Net.Data then proceeds to look for the end of the function block, and when it can't be found, issues an error.
Use one of the following methods to use Net.Data special characters as part of your embedded program code, without having them interpreted by Net.Data as special characters:
For example, the following Perl function contains characters representing a COMMENT block delimiter, %{, as part of its Perl language statements:
%function(DTW_PERL) func() { ... for $num_words (sort bynumber keys %{ $Rtitles{$num} }) { &make_links($Rtitles{$num}{$num_words}); } ... %}
To ensure that Net.Data interprets the %{ characters as Perl source code rather than as a Net.Data COMMENT block delimiter, rewrite the function in either of the following ways:
%function(DTW_PERL) func() { %EXEC{ func.prl %} %}
%define percent_openbrace = "%{" %function(DTW_PERL) func() { ... for $num_words (sort bynumber keys $(percent_openbrace) $Rtitles{$num} }) { &make_links($Rtitles{$num}{$num_words}); } ... %}
Syntax
>>-%FUNCTION--(--lang_env--)--function_name--| parm passing spec |--> .-;---------------------------------------------. >----+-| returns spec |--{--| function body |----%}--+--------->< parm passing spec |---(--+---------------------------------------------+---)------| | .-,-------------------------------------. | | | (1) | | | V .-IN-------. | | '----+----------+---+-----------+---name---+--' +-OUT------+ '-datatype--' '-INOUT----' returns spec |---+----------------------+------------------------------------| '-RETURNS--(--name--)--' function body |---+-------------------------------+---------------------------> | .--------------------------. | | V | | +----inline statement block---+-+ '-exec block--------------------' >-----+-----------------------------------------------+---------| | .---------------------. | | V (2) | | +----report block--------+---+----------------+-+ | '-message block--' | | .--------------------------. | | V | | '-message block-----+--------------------+--+---' | (2) | '-report block-------'
Notes:
Values
Context
The FUNCTION block can be found in these contexts:
Restrictions
DB2 has the following restrictions:
Examples
The following examples are general and do not cover all language environments. See Net.Data Language Environment Reference for more information about using FUNCTION blocks with a specific language environment.
Example 1: A REXX substring function
%DEFINE lstring = "longstring" %FUNCTION(DTW_REXX) substring(IN x, y, z) RETURNS(s) { s = substr("$(x)", $(y), $(z)); %} %DEFINE a = {@substring(lstring, "1", "4")%} %{ assigns "long" to a %}
When a is evaluated, the @substring function call is found and the substring FUNCTION block is executed. Variables are substituted in the executable statements in the FUNCTION block, then the text string s = substr("longstring", 1, 4) is passed to the REXX interpreter to execute. Because the RETURNS clause is specified, the value of the @substring function call in the evaluation of a is replaced with "long", the value of s.
Example 2: Invoking an external REXX program
%FUNCTION(DTW_REXX) my_rexx_pgm(INOUT a, b, IN c, OUT d) { %EXEC{ mypgm.cmd this is a test %} %} %HTML(INPUT) { <p> Original variable values: $(w) $(x) $(z) <p> @my_rexx_pgm(w, x, y, z) <p> Modified variable values: $(w) $(x) $(z) %}
Variables w and x correspond to the INOUT parameters a and b in the function. Their values and the value of y, which corresponds to the IN parameter c, should already be defined from HTML form input or from a DEFINE statement. Variables a and b are assigned new values when parameters a and b return values. The variable z is defined when the OUT parameter d returns a value.
/* Sample REXX Program for Example 2 */ /* Test arguments */ num_args = arg(); say 'There are' num_args 'arguments'; do i = 1 to num_args; say 'arg' i 'is "'arg(i)'"' end; /* Set variables passed from Net.Data */ d = a || b || c; /* concatenate a, b, and c forming d */ a = ''; /* reset a to null string */ b = ''; /* reset b to null string */ return;
There are 1 arguments arg 1 is "this is a test"
The EXEC statement tells the REXX language environment to tell the REXX interpreter to execute the external REXX program mypgm.cmd. Because the REXX language environment can directly share Net.Data variables with the REXX program, it assigns the REXX variables a, b, and c the values of the Net.Data variables w, x and y before executing mypgm.cmd. mypgm.cmd can directly use the variables a, b, and c in REXX statements. When the program ends, the REXX variables a, b, and d are retrieved from the REXX program, and their values are assigned to the Net.Data variables w, x, and z. Because the RETURNS clause is not used in the definition of the my_rexx_pgm FUNCTION block, the value of the @my_rexx_pgm function call is the null string, "", (if the return code is 0) or the value of the REXX program return code (if the return code is nonzero).
Example 3: An SQL query and report
%FUNCTION(DTW_SQL) query_1(IN x, IN y) { SELECT customer.num, order.num, part.num, status FROM customer, order, shippingpart WHERE customer.num = '$(x)' AND customer.ordernumber = order.num AND order.num = '$(y)' AND order.partnumber = part.num %REPORT{ <p>Here is the status of your order: <p>$(NLIST) <ul> %ROW{ <li>$(V1) $(V2) $(V3) $(V4) %} </ul> %} %} %DEFINE customer_name="IBM" %DEFINE customer_order="12345" %HTML(REPORT) { @query_1(customer_name, customer_order) %}
The @query_1 function call substitutes IBM for $(x) and 12345 for $(y) in the SELECT statement. Because the definition of the SQL function query_1 does not identify an output table variable, the default table is used (see the TABLE variables block for details). The NLIST and Vi variables referenced in the REPORT block are defined by the default table definition. The report produced by the REPORT block is placed in the output HTML where the query_1 function is invoked.
Example 4: A system call to execute a Perl script
%FUNCTION(DTW_SYSTEM) today() RETURNS(result) { %exec{ perl "today.prl" %} %} %HTML(INPUT) { @today() %}
$date = `date`; chop $date; open(DTW, "> $ENV{DTWPIPE}") || die "Could not open: $!"; print DTW "result = \"$date\"\n";
When the @today function call is encountered, Net.Data performs variable substitution on the executable statements. In this example, there are no Net.Data variables in the executable statements, so no variable substitution is performed. The executable statements and parameters are passed to the System language environment, which creates a named pipe and sets the environment variable DTWPIPE to the name of the pipe.
Then the external program is called with the C system() function call. The external program opens the pipe as write-only and writes the values of output parameters to the pipe as if it were a standard stream file. The external program generates HTML output by writing to STDOUT. In this example, the output of the system date program is assigned to the variable result, which is the variable identified in the RETURNS clause of the FUNCTION block. This value of the result variable replaces the @today() function call in the HTML block.
Example 5: Perl language environment
%FUNCTION(DTW_PERL) today() RETURNS(result) { $date = `date`; chop $date; open(DTW, "> $ENV{DTWPIPE}") || die "Could not open: $!"; print DTW "result = \"$date\"\n"; %} %HTML(INPUT) { @today() %}
Compare this example with Example 4 to see how the EXEC block is used. In Example 4, the System language environment does not understand how to interpret Perl programs, but the language environment does know how to call external programs. The EXEC block tells it to call a program called perl as an external program. The actual Perl language statements are interpreted by the external Perl program. Example 5 has no EXEC block, because the Perl language environment is able to directly interpret Perl language statements.