Finalidad
Define una subrutina que Net.Data invoca desde la macro. Las sentencias ejecutables de un bloque FUNCTION pueden ser sentencias incorporadas que un entorno de lenguaje interpreta directamente o bien pueden indicar una llamada a un programa externo.
Si utiliza el bloque EXEC en el bloque FUNCTION, debe ser la única sentencia ejecutable del bloque FUNCTION. Antes de transmitir la sentencia ejecutable al entorno de lenguaje, Net.Data agrega el nombre de archivo del programa del bloque EXEC a un nombre de vía de acceso determinado por medio de la sentencia de configuración de vía de acceso EXEC_PATH en el archivo de inicialización. La serie resultante se transmite al entorno de lenguaje que ha de ejecutarse.
El método que utiliza el entorno de lenguaje para procesar el bloque EXEC depende del entorno de lenguaje en concreto; los entornos de lenguaje REXX, Sistema y Perl que facilita Net.Data dan soporte al bloque EXEC.
Cuando se utilizan caracteres que coinciden con construcciones de lenguaje de Net.Data en la sección de sentencias de lenguaje de un bloque de función como parte del código de programa intercalado válido sintácticamente (por ejemplo, REXX o Perl), pueden interpretarse erróneamente como construcciones de lenguaje de Net.Data, ocasionando errores o un resultado imprevisible en una macro.
Por ejemplo, es posible que una función Perl utilice los caracteres de delimitador de bloque de COMMENT, %{. Cuando se ejecute la macro, los caracteres %{ se interpretan como el principio de un bloque COMMENT. A continuación, Net.Data busca el final del bloque COMMENT, que piensa que ha encontrado cuando lee el final del bloque de función. Después Net.Data sigue buscando el final del bloque de función y cuando no lo encuentra emite un error.
Utilice uno de los métodos siguientes para utilizar caracteres especiales de Net.Data como parte del código de programa intercalado, sin que Net.Data los interprete como caracteres especiales:
Por ejemplo, la función Perl siguiente contiene caracteres que representan a un delimitador de bloque COMMENT, %{, como parte de sus sentencias de lenguaje de Perl:
%function(DTW_PERL) func() { ... for $num_words (sort bynumber keys %{ $Rtitles{$num} }) { &make_links($Rtitles{$num}{$num_words}); } ... %}
Para asegurarse de que Net.Data interpreta los caracteres %{ como código fuente Perl en vez de como delimitador de bloque COMMENT de Net.Data, vuelva a escribir la función en cualquiera de las formas siguientes:
%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}); } ... %}
Sintaxis
>>-%FUNCTION--(--ent_leng--)--nombre_función--| espec transm param |--> .-;-----------------------------------------------. >----+-| espec retorno |--{--| cuerpo función |----%}--+------->< espec transm param |---(--+------------------------------------------------+---)---| | .-,----------------------------------------. | | | (1) | | | V .-IN-------. | | '----+----------+---+------------+---nombre---+--' +-OUT------+ '-tipodatos--' '-INOUT----' espec retorno |---+------------------------+----------------------------------| '-RETURNS--(--nombre--)--' cuerpo función |---+--------------------------------+--------------------------> | .---------------------------. | | V | | +----bloque inline statement---+-+ '-bloque exec--------------------' >-----+-------------------------------------------------+-------| | .----------------------. | | V (2) | | +----bloque report--------+---+-----------------+-+ | '-bloque message--' | | .---------------------------. | | V | | '-bloque message-----+---------------------+--+---' | (2) | '-bloque report-------'
Notas:
Valores
Contexto
El bloque FUNCTION puede encontrarse en estos contextos:
Restricciones
DB2 tiene las restricciones siguientes:
Ejemplos
Los ejemplos siguientes son genéricos y no tratan sobre todos los entornos de lenguaje. Consulte la publicación Net.Data Language Environment Reference para obtener más información sobre la utilización de bloques FUNCTION con un entorno de lenguaje específico.
Ejemplo 1: Una función de subserie REXX
%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 %}
Cuando se evalúa a, se busca la llamada de función @substring y se ejecuta el bloque FUNCTION de subserie. Las variables se sustituyen en las sentencias ejecutables en el bloque FUNCTION, a continuación, la serie de texto s = substr("longstring", 1, 4) se transmite al intérprete REXX para su ejecución. Puesto que se especifica la cláusula RETURNS, el valor de la llamada de función @substring en la evaluación de a se sustituye por "long", el valor de s.
Ejemplo 2: Invocación de un programa REXX externo
%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> <p> @my_rexx_pgm(w, x, y, z) </p> <p> Modified variable values: $(w) $(x) $(z) </p> %}
Las variables w y x se corresponden con los parámetros de INOUT a y b de la función. Sus valores y el valor de y, que se corresponde con el parámetro IN c, ya deberían haberse definido desde la entrada del formato HTML o desde una sentencia DEFINE. A las variables a y b se les asignan valores nuevos cuando los parámetros a y b devuelven valores. La variable z se define cuando el parámetro OUT d devuelve un valor.
/* 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"
La sentencia EXEC indica al entorno de lenguaje de REXX que indique al intérprete de REXX que ejecute el programa de REXX externo mypgm.cmd. Puesto que el entorno de lenguaje de REXX puede compartir directamente variables de Net.Data con el programa REXX, asigna a las variables de REXX a, b y c los valores de las variables de Net.Data w, x e y antes de ejecutar mypgm.cmd. mypgm.cmd puede utilizar directamente las variables a, b y c en sentencias REXX. Cuando finaliza el programa, las variables de REXX a, b y d se recuperan del programa REXX y sus valores se asignan a las variables de Net.Data w, x y z. Puesto que la cláusula RETURNS no se utiliza en la definición del bloque FUNCTION my_rexx_pgm, el valor de la llamada de función @my_rexx_pgm es la serie nula, "", (si el código de retorno es 0) o el valor del código de retorno del programa REXX (si el código de retorno es diferente a cero).
Ejemplo 3: Informe y consulta de SQL
%DEFINE customer_name="IBM" %DEFINE customer_order="12345" %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> <p>$(NLIST) </p> <ul> %ROW{ <li>$(V1) $(V2) $(V3) $(V4) </li> %} </ul> %} %} %HTML(REPORT) { @query_1(customer_name, customer_order) %}
La llamada de función @query_1 sustituye IBM por $(x) y 12345 por $(y) en la sentencia SELECT. Puesto que la definición de la función de SQL query_1 no identifica una variable de tabla de salida, se utiliza la tabla por omisión (consulte el bloque de variables de TABLE para obtener más detalles). Las variables NLIST y Vn a las que se hace referencia en el bloque REPORT se definen por medio de la definición de tabla por omisión. El informe que se produce por medio del bloque REPORT se coloca en el HTML de salida en el que se invoca la función query_1.
Ejemplo 4: Una llamada de sistema para ejecutar un script de Perl
%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";
Cuando se encuentra la llamada de función @today, Net.Data efectúa la sustitución de variables en las sentencias ejecutables. En este ejemplo, no hay variables de Net.Data en las sentencias ejecutables, por lo que no se efectúa ninguna sustitución de variables. Los parámetros y sentencias ejecutables se transmiten al entorno de lenguaje de Sistema, que crea un área de interconexión de memoria definida y establece la variable de entorno DTWPIPE en el nombre del área de interconexión de memoria.
A continuación, el programa externo se invoca con la llamada de función system() de C. El programa externo abre el área de interconexión de memoria como sólo de grabación y graba los valores de los parámetros de salida en el área de interconexión de memoria como si fuera un archivo continuo estándar. El programa externo genera la salida grabando en STDOUT. En este ejemplo, la salida del programa de fecha del sistema se ha asignado al resultado de la variable, que es la variable identificada en la cláusula RETURNS del bloque FUNCTION. Este valor de la variable de resultado sustituye la llamada de función @today() en el bloque HTML.
Ejemplo 5: Entorno de lenguaje Perl
%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 este ejemplo con el Ejemplo 4 para ver cómo se utiliza el bloque EXEC. En el Ejemplo 4, el entorno de lenguaje del Sistema no sabe cómo en que ha de interpretar programas Perl, pero el entorno de lenguaje sí sabe cómo llamar a programas externos. El bloque EXEC le indica que invoque un programa denominado perl como programa externo. El programa Perl externo interpreta las sentencias de lenguaje Perl reales. El ejemplo 5 no tiene un bloque EXEC, ya que el entorno de lenguaje Perl puede interpretar las sentencias de lenguaje Perl directamente.