Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Lenguaje RPG ILE para IBM (AS400) en Formato Free Con SQL
Lenguaje RPG ILE para IBM (AS400) en Formato Free Con SQL
Diseño estructurado
El diseño estructurado es una metodología de desarrollo ampliamente
aceptada que respalda el diseño de programas de calidad. Un aspecto
importante del diseño estructurado es limitar las estructuras de control dentro
de un programa a tres estructuras lógicas básicas:
Comparaciones relacionales
Las operaciones de decisión e iteración implican probar una condición para
determinar el curso de acción apropiado. Esta prueba implica una comparación
relacional entre dos valores. Para expresar la comparación, ILE RPG mantiene
seis símbolos relacionales que se utilizan con operaciones de decisión e
iteración:
· > (Mayor que)
· = (Igual a)
Dispositivo
La entrada que sigue al nombre del archivo indica el dispositivo asociado con el
archivo. Los tres tipos de dispositivo más utilizados son las siguientes:
Uso de archivos
Una vez que haya definido una constante con nombre, puede usarla con
cualquier procesamiento apropiado para su tipo. El valor de una constante
nombrada es fijo, no puede cambiarlo durante el curso de la ejecución del
programa. Las constantes con nombre facilitan la comprensión de los
programas al eliminar literales cuyo propósito no es evidente.
–999.20
0123
555
10
+5
–10
3500
.88888
Literales de caracteres
Con frecuencia, se necesitará trabajar con valores de caracteres. RPG permite
usar literales de caracteres para ese propósito. Los literales de caracteres son
cadenas de caracteres. Al igual que los literales numéricos, los literales de
caracter mantienen un valor constante durante la ejecución del programa. Para
indicar que un valor es un caracter literal (y no un nombre de variable),
simplemente enciérrelo entre apóstrofos. No se aplican restricciones sobre qué
caracteres pueden formar el literal. Cualquier caracter que se pueda
representar mediante el teclado, incluido un espacio en blanco, es aceptable. Si
el literal va a incluir un caracter apóstrofo, use dos apóstrofos para
representarlo. Los literales de caracteres pueden tener hasta 16,380 bytes. A
continuación se muestran algunos ejemplos de literales de caracteres :
'Juan Perez'
'Mno123 @15y'
'Valeria''s Pizza'
'12345'
'99%'
Literales tipificadas
Además de los literales numéricos y de caracteres, se pueden expresar otros
valores de datos, como fechas y horas, mediante el uso de literales tipificados.
Para codificar un literal tipificado, encierre el valor entre apóstrofos y precédalo
con un código de tipo de datos para indicar qué tipo de datos representa el
literal. Para hacer referencia a un valor del 28 de agosto de 1960, por ejemplo,
codificaría D’1960-08-28′ como el literal. Otros códigos de tipo de datos
comunes para literales son T (para horas), Z (para timestamps) y X (para
literales hexadecimales). A continuación, más ejemplos de este tipo de literales:
Tipo de dato
Literal tipificada
Date
D'2000-04-16'
Tipo de dato
Literal tipificada
Time
T'09.55.10'
Tipo de dato
Literal tipificada
Timestamp
Z'2005-04-10-07.46.21.000000'
Tipo de dato
Literal tipificada
Hexadecimal
X'F1F1F1'
Definición de constantes
Una constante nombrada asigna un nombre a un literal para que se pueda
hacer referencia al literal por su nombre en todo el programa. El valor de la
constante nombrada nunca cambia durante el procesamiento. La
instrucción Dcl-c (Declare Constant) define la constante nombrada, este es el
formato:
Dcl-c name value;
La instrucción Dcl-c requiere solo el nombre de la constante y su valor. La
constante se define sin una longitud o tipo específico; esos atributos están
implícitos en el valor. El nombre del elemento de datos debe comenzar con un
caracter alfabético, o los caracteres especiales $, # o @. Los caracteres
restantes pueden ser caracteres alfabéticos, números o cualquiera de los
cuatro caracteres especiales _, #, $ y @. El nombre de un elemento de datos
no puede contener espacios en blanco incrustados entre los caracteres
permitidos.
Se ingresa el valor literal de la constante después del nombre. Introduzca
valores constantes numéricos con un caracter base y un signo si corresponde,
pero nunca con miles como separadores. Incluya valores de constantes de
caracteres entre apóstrofos. Las constantes de otros tipos de datos deben
seguir las reglas indicadas anteriormente para literales tipificados. Estos son
algunos ejemplos de constantes válidas:
*Off
*On
*Hival
*Loval
*All
*Null
RPG permite asignar *Blank o *Blanks para hacer que una variable tipo
caracter se rellene con espacios en blanco. Asignar *Zero o * Zeros a variables
numéricas y de caracteres rellena las variables con ceros.
Las constantes figurativas *Off y *On representan valores de caracter "0" y "1".
*Off equivale a "0" y *On equivale a “1". Aunque puede utilizar *Off y *On con
cualquier variable de caracteres de cualquier longitud, los programadores
suelen utilizar *Off y *On para cambiar o comparar el valor de un indicador.
La asignación de *Hival rellena una variable con el valor más alto posible
apropiado para su tipo de datos. Asignarle a una variable tipo caracter *Hival
establece todos los bytes en FF hexadecimal. Para una variable numérica,
*Hival es el valor positivo máximo permitido para la representación de datos,
generalmente serán 9’s y un signo más (+). La asignación de *Loval rellena una
variable con el valor de clasificación más bajo posible apropiado para su tipo de
datos, por ejemplo, 00 hexadecimal para las variables tipo caracter y el valor
mínimo negativo para las variables numéricas. Los programadores a menudo
asignan *Hival o *Loval a una variable para asegurarse de que el valor de la
variable sea el máximo o el mínimo posible.
La constante *Null representa un valor nulo. Por lo general, se usa *Null para
representar la ausencia de cualquier valor, y esto no es lo mismo que usar
espacios en blanco o ceros. Por lo general, en ILE RPG se usa *Null solo en
situaciones inusuales.
Dcl-s VX Uns(5);
Dcl-s WHERESQL CHAR(256);
Dcl-s FLAG_CURSO INT(5);
Dcl-s FECFACTUR DATE;
Dcl-s DEUDA PACKED(7:2);
Tipo de datos
Los atributos de una variable se describen en una palabra clave de tipo de
datos, después del nombre de la variable. Las tres clases básicas de datos que
se utilizan en la mayoría de la programación empresarial son datos numéricos,
de caracteres y de fecha. RPG admite algunas variaciones de estas clases de
datos, junto con algunas otras que tienen usos especiales. Las siguientes son
las palabras clave de tipo de datos más utilizadas:
Pointer
Datos numéricos
Recordemos que las variables con zona (o con signo) almacenan datos
numéricos, donde cada dígito ocupa un byte, y que las variables empacadas
usan solo medio byte para cada dígito. RPG permite ambos tipos de datos
numéricos:
Los números con zona son equivalentes al tipo de datos NUMERIC de SQL, y
los números empacados son los mismos que el tipo de datos DECIMAL en
SQL.
Una variable numérica definida con INT es un entero con signo. Los enteros
son el medio más compacto de almacenar valores numéricos. La siguiente
declaración define un entero de cinco dígitos con signo, CONTROL:
La longitud entre paréntesis (que puede ser literal o constante) debe ser de 3,
5, 10 o 20 dígitos:
Dígito
Bytes
Valor Menor
Valor Mayor
3
-128
127
Dígito
Bytes
Valor Menor
Valor Mayor
5
-32,768
32,767
Dígito
Bytes
Valor Menor
Valor Mayor
10
-2,147,483,648
2,147,483,647
Dígito
Bytes
Valor Menor
Valor Mayor
20
-9,223,372,036,854,775,808
9,223,372,036,854,775,807
Los enteros no tienen decimales y tienen rangos limitados. Sin embargo, son
un tipo de datos eficiente y útil para datos numéricos. Un entero de cinco
dígitos en RPG es equivalente a SMALLINT de SQL, un entero de 10 dígitos en
RPG es equivalente a INT en SQL y un entero de 20 dígitos en RPG
corresponde a BIGINT.
Uns es una variación de los enteros con signo, Uns, define un entero sin signo.
Los enteros sin signo siguen los mismos principios que los enteros con signo,
excepto que sus valores son siempre positivos. La siguiente declaración define
CONTROL, un entero sin signo de cinco dígitos:
Los enteros sin signo tienen un rango de valores diferente de los enteros con
signo:
Dígito
Bytes
Valor Menor
Valor Mayor
3
255
Dígito
Bytes
Valor Menor
Valor Mayor
5
65,535
Dígito
Bytes
Valor Menor
Valor Mayor
10
4,294,967,295
Dígito
Bytes
Valor Menor
Valor Mayor
20
18,446,744,073,709,551,615
Para inicializar (es decir, asignar un valor inicial a) una variable, se especifica el
valor utilizando la palabra clave INZ (Inicializar) en la definición de la variable.
El valor inicial se indica mediante un literal, una constante o una constante
figurativa. En las siguientes definiciones se proporcionan valores iniciales a las
variables:
Dcl-s PRECIO PACKED(7:2) Inz(10500.50);
Dcl-s DIRECCION CHAR(200) Inz('SOLUCIONES DE SISTEMAS');
Dcl-s CONTROL CHAR(9) Inz(*Loval);
Dcl-s FECINIC DATE Inz(D'1899-12-30');
Otro valor de inicialización útil es *User, el cual se puede utilizar con campos de
caracteres si son al menos de 10 bytes de longitud. La codificación de Inz
(*User) para un campo de caracteres asigna el nombre del perfil de usuario
actual al campo de caracteres:
End-ds {ds-name};
DCL-DS CLIENTE;
id INT(10);
nombre CHAR(40);
fecInicio DATE(*ISO);
credito ZONED(11:2);
END-DS;
Las líneas para describir los subcampos que componen la estructura de datos
continúan después de la instrucción Dcl-ds. Definen cada entrada de subcampo
dándole un nombre. Es una práctica normal indentar la definición de
subcampos para mostrar una jerarquía de la estructura de datos fácilmente
visible. El orden de los subcampos debe representar sus posiciones relativas
en la estructura de datos. Después del nombre del subcampo, especifique una
palabra clave de tipo de datos. Cualquier tipo de datos permitido para variables
independientes también está permitido para subcampos de estructura de datos.
Una vez que haya definido los subcampos de la estructura de datos, puede
inicializarlos utilizando la palabra clave Inz. La palabra clave Inz inicializa
estructuras de datos completas o subcampos de la estructura de datos. Si
codifica Inz (sin ningún valor a continuación) en la instrucción Dcl-ds, el
programa inicializa todos los subcampos en la estructura de datos con valores
iniciales apropiados para los tipos de datos de los subcampos.
Sin la palabra clave Inz, todos los subcampos están inicialmente en blanco. El
programa finaliza de forma anormal si intenta realizar operaciones aritméticas
en CodArea, Central o NumeroLoc sin inicializarlas primero.
PIDPRODUCT = PRODUCTS.IDPRODUCT;
PDESCRIPT = PRODUCTS.descript;
PIDPRODTYP = PRODUCTS.idProdTyp;
PIDSUPPLR = PRODUCTS.idSupplr;
PUNITPRICE = PRODUCTS.UnitPrice;
PIDWREHOUS = PRODUCTS.idWrehous;
PIDBRAOFFI = PRODUCTS.idBraOffi;
PENTRYDTE = PRODUCTS.entrydte;
End-proc;
*La palabra clave Eval de asignación se puede omitir para este tipo de
asignación.
Evalr (evaluar expresión, ajuste a la derecha)
La operación Eval asigna valores transfiriendo el resultado de la expresión
caracter por caracter, comenzando con el caracter más a la izquierda,
rellenando el resultado con espacios en blanco a la derecha si es necesario.
Una operación relacionada, Evalr (Evaluar expresión, ajuste a la derecha),
funciona con la asignación de caracteres cuando se desea ajustar el resultado
a la derecha. Evalr asigna el valor del caracter comenzando con el caracter de
más a la derecha. Si la variable de resultado que recibe el valor se define más
larga que el valor a asignar, Evalr rellena la variable con espacios en blanco (es
decir, rellena las posiciones no utilizadas en el extremo izquierdo de la variable
con espacios en blanco). Evalr no funciona con expresiones numéricas y, a
diferencia de Eval, siempre debe estar codificado explícitamente en el
programa. Para ver cómo funciona Evalr, compare el siguiente código con los
ejemplos de asignación de caracteres anteriores:
Observe que la función %Trim elimina solo los espacios en blanco en los
extremos del valor tipo caracter, no los que están dentro del valor. Por lo tanto,
las funciones de %Trim anteriores retienen el espacio en blanco dentro de
‘MUY BIEN‘ al recortar los espacios en blanco de los bordes.
Como con todas las funciones, se usan separadores de dos puntos entre
argumentos. Puede representar la posición inicial y la longitud opcional
mediante el uso de variables numéricas, constantes o expresiones que
representen números enteros mayores a cero.
Los siguientes ejemplos ilustran cómo obtener una parte de una cadena de
caracteres:
El primer argumento (que puede ser una variable tipo caracter, literal o
expresión), proporciona la cadena de reemplazo para insertar en la cadena de
caracteres original, la cual es el segundo argumento que debe ser una variable
de tipo caracter.
Opcionalmente, puede especificar una posición inicial. Si omite este tercer
argumento, el reemplazo ocurre al principio de la variable original. El cuarto
argumento también es opcional, especifica cuántos caracteres se van a
reemplazar. Los argumentos opcionales tercero y cuarto pueden ser variables
numéricas, literales o expresiones. Omitir el cuarto argumento hace que el
número de caracteres sea el mismo que la longitud de la cadena de reemplazo.
Operaciones numéricas
Asignación numérica.
COMPRAS = *Zeros;
VALOR = *Loval;
Todos los valores de la expresión aritmética a la derecha del signo igual deben
ser, por supuesto, campos numéricos, literales o constantes. Otra restricción
surge cuando se utiliza la división en una expresión. un error de tiempo de
ejecución ocurre si en el momento de la división, el divisor (la parte de una
expresión inmediatamente a la derecha del signo de división) se evalúa como
cero.
Cuando la expresión aritmética contiene más de un operador, se usan las
reglas de precedencia de las matemáticas para determinar el orden en el cual
realizar las operaciones. La exponenciación tiene la precedencia más alta,
seguida de la multiplicación y la división, y luego la suma y la resta. Cuando
una expresión contiene operaciones de igual precedencia, el sistema las
ejecuta en orden de izquierda a derecha. Se pueden utilizar paréntesis para
cambiar el orden en el que el programa ejecuta las operaciones; las
operaciones entre paréntesis se realizan antes que las operaciones fuera de
los paréntesis.
Para los tipos de expresiones, que utilizan la variable de resultado como primer
operando de la expresión, RPG ofrece varios operadores compuestos: + =, - =,
* =, / = y ** =. Estos operadores le permiten codificar este tipo de expresión
común de manera más concisa. Realizan la función aritmética solicitada,
utilizando la variable de resultado como primer operando de la operación. Por
ejemplo, con + =, la expresión es agregada a la variable de resultado. Las
siguientes expresiones son equivalentes:
VALOR01 = VALOR01 + 1;
// EQUIVALE A
VALOR01 += 1;
Redondeo
Cuando se almacena un valor en una variable de resultado que tiene menos
posiciones decimales que la respuesta calculada, la práctica comercial común
dicta que siempre redondee su respuesta en lugar de permitir que el sistema la
trunque.
La sintaxis que usa ILE RPG para especificar que el redondeo toma lugar es
simple: solo ingrese una H entre paréntesis inmediatamente después del
código de operación Eval de la expresión cuyo resultado desea redondear. Los
siguientes ejemplos muestran el uso de la (H) con Eval:
Función numérica
%Rem(residuo)
La función incorporada %Rem (residuo) devuelve el residuo entero al dividir
dos números (literales, campos o expresiones). Los dos números se pasan
como dos argumentos, primero el dividendo y luego el divisor, inmediatamente
después de la notación %Rem. Aunque los programadores suelen utilizar
%Rem con la función %Div, no es necesario realizar la operación de división
para obtener el residuo, a continuación un ejemplo con la función %Rem:
A= 123;
B= 27;
Procesamiento de fechas
ILE RPG soporta tres tipos de datos que pueden almacenar y procesar valores
relacionados con fechas:
· Date
· Time
· Timestamp
La fecha y la hora son tipos de datos que se utilizan para almacenar valores
relacionados con un momento en el año (fecha) y un momento en el tiempo
(hora). Un timestamp es una combinación de una fecha y una hora.
Generalmente, ILE RPG aplica los mismos principios y reglas a los tres tipos de
datos.
Dcl-ds datosFact;
fechaVenta Date(*Iso);
a#no Zoned(4:0) Overlay(fechaVenta);
mes Zoned(2:0) Overlay(fechaVenta:6);
dia Zoned(2:0) Overlay(fechaVenta:9);
End-ds;
Cada uno de los tipos de datos relacionados con la fecha tiene un tamaño y
formato preestablecidos, y cada uno tiene un formato externo predeterminado
(*ISO), basado en los estándares de la Organización Internacional de
Normalización (ISO). El formato externo predeterminado para fechas es un
campo de 10 bytes con formato AAAA-MM-DD. La hora tienen una longitud
predeterminada de ocho bytes con formato hh.mm.ss. El formato externo
predeterminado para timestamp (Z) tiene una longitud de 26 bytes con formato
AAAA-MM-DD-hh.mm.ss.uuuuuu.
// myDate = '2004-05-01'
myDate = myDate + %days(3) ;
// myDate = '2004-05-04'
myDate = myDate + %months(1) ;
// myDate = '2004-06-04'
myDate = myDate - %years(2) ;
// myDate = '2002-06-04'
%Diff (diferencia)
La función %Diff (Diferencia) calcula la duración entre dos valores de fecha u
hora. Los dos primeros argumentos deben ser elementos de datos de tipos
compatibles, luego el tercer argumento representa el código de duración que
corresponde a la unidad de duración que desea determinar. El formato de la
función es el siguiente:
En este formato, la primera fecha debe ser más reciente que la segunda fecha
(u hora). El resultado es un número (no redondeado, hasta un límite de 15
dígitos) y se descarta el residuo. Puede utilizar la función% Diff para encontrar
la duración entre:
● Dos fechas
El tercer argumento debe ser un valor especial que corresponda a una de las
siete duraciones:
Operaciones de iteración
I=0;
dow i < 10;
I += 1;
dsply %CHAR(I);
enddo;
// ESTE CICLO DESPLIEGA LOS VALORES DESDE 1 HASTA 10
dcl-s I INT(3);
I = 0;
DOU I = 9;
dsply %CHAR(I);
I += 1;
ENDDO;
// ESTE CICLO DESPLIEGA LOS VALORES DESDE 0 HASTA 8
Ejemplo:
Dou %Eof;
Readc PGMSFL;
Select;
When %Eof; // SI HAY FIN DE ARCHIVO SE FINALIZA EL CICLO
Leave;
When Option = '1';
VACTION = 'C' ;
PROCHG_SQL(PIDPRODUCT:VACTION:VRESPONSE); // LLAMADA A
OTRO PROGRAMA
MSG = VRESPONSE;
When Option = '2';
VACTION = 'D' ;
PRODEL_SQL(PIDPRODUCT:VACTION:VRESPONSE); // LLAMADA A
OTRO PROGRAMA
MSG = VRESPONSE;
When Option = '3';
Iter; // OPCION EN DESARROLLO
OTHER;
ERROR = ERROR01; // ERROR01 = 'OPCION INVALIDA
Leave;
Endsl;
Enddo;
For
ILE RPG ofrece la operación For diseñada específicamente para ciclos
controlados por recuento (es decir, para ejecutar ciclos un número específico
de veces). Como Dow y Dou, un operador final (Endfor) señala el final de un
grupo For. A diferencia de las operaciones DOW y DOU, la operación For
incrementa automáticamente su contador para garantizar que la repetición se
produzca el número de veces deseado. El formato de la operación For es un
poco más largo que el de Dow o Dou porque For ofrece más opciones y valores
predeterminados. El diseño general de un ciclo For es el siguiente:
Select;
When Sqlstate = Success; // Success = '02000'
Rrn += 1;
Option = *BLANKS;
PDESCRIPT = VDESCRIPT;
PIDPRODUCT = VIDPRODUCT;
Write PGMSFL; // WRITE RECORD IN SUB FILE SCREEN
When Sqlstate = Endoffile; // Endoffile = '02000'
Sflend = *On;
Leave;
Endsl;
Endfor
Operaciones de selección
IF
El operador de decisión principal de RPG es IF. El formato general de la
operación IF es el siguiente:
If conditional_expression;
...
Endif;
La expresión condicional debe ser verdadera o falsa. Si la expresión
condicional es verdadera, todos los cálculos entre la instrucción If y su
correspondiente Endif se ejecutan. Si la relación no es verdadera, esas
declaraciones se omiten. El grupo If tiene un punto de entrada (la declaración
If) y un punto de salida (la declaración Endif).
If Not Exit;
Endif;
IF Sqlstate = Success;
PARM_MSG = SUCCESSOPE;
ELSE;
PARM_MSG = NOTSUCCOPE;
ENDIF
Anidamiento de grupos If
También se pueden anidar grupos If. Es decir, puede crear grupos If dentro de
otros grupos If, con o sin operaciones Else. Cada If requiere un Endif en el
lugar apropiado para indicar el punto final de la influencia de ese grupo de If. El
siguiente es un ejemplo con If anidados en ILE RPG:
IF PARM_ACT = 'A';
Addmode = *On; // WAY TO TURN ON AN INDICATOR
Chgmode = *Off;
Dltmode = *Off; // WAY TO TURN OFF AN INDICATOR
ELSE;
IF PARM_ACT = 'C';
Chgmode = *On;
Addmode = *Off;
Dltmode = *Off;
ELSE;
Dltmode = *On;
Chgmode = *Off;
Addmode = *Off;
ENDIF;
ENDIF;
Select;
When Exit;
Leave;
When AddProduct;
AddProd();
Clearsfl();
Loadsfl();
When Pagedown;
Loadsfl();
When Find <> *Blanks;
Clearsfl();
Loadsfl();
Other;
Readsfl();
Clearsfl();
Loadsfl();
Endsl;
LIKE
La palabra clave Like define una variable independiente o un subcampo de
estructura de datos que adopta la longitud y el tipo de datos de otro elemento
de datos. Cuando define un elemento de datos con la palabra clave Like, el tipo
de datos, las posiciones decimales y, por lo general, las longitudes se dejan en
blanco porque el compilador recupera esos atributos del ítem padre al que se
hace referencia. A continuación, se muestran algunos ejemplos del uso de
LIKE:
LIKEDS
Otra palabra clave, LIKEDS (como estructura de datos), define una estructura
de datos en base a otra estructura de datos, con los mismos subcampos:
Ejemplo:
Monitor;
// Code to monitor
On-Error statuscode1 : statuscode2 :statuscode3;
// Handle Error related to statuscode1 or statuscode2 or statuscode3
On-Error *FILE;
// Handles all file-error status codes, from 01000 to 09999
On-Error *PROGRAM;
// Handles all program-error status codes, from 00100 to 00999
On-Error *ALL;
// Handles both program-error and file-error codes, from 00100 to 09999.
This is the
default.
EndMon;
Monitor;
Eval(H) Resultado = Var01 / var02;
On-error 00102; // Divide by zero
Resultado = 0;
Endmon;
Llamada de programas
Programación modular
ILE RPG proporciona la operación Callp (llamar a un procedimiento/método o
llamar a un programa por medio de un prototipo) para facilitar un enfoque
modular al desarrollo de programas. Cuando la ejecución de un programa
alcanza una sentencia Callp, el control se pasa a otro programa (otro objeto
tipo *PGM). El programa llamado se ejecuta hasta que éste llegue a una
sentencia Return, entonces el control se devuelve al programa que hizo la
llamada (programa llamante) y éste continua con la línea siguiente a la que hizo
la llamada.
El flujo de control con una llamada es como el de una operación RPG Exsr
(ejecutar Subrutina), excepto que la llamada invoca un programa externo (o un
subprocedimiento) en lugar de una subrutina interna del programa. A la lista de
los programas activos en un trabajo se le llama pila de llamadas. Cada entrada
en la pila de programas (programa o procedimiento) tiene un nivel de llamada
que depende de su posición relativa con respecto a otras llamadas en la pila. El
primer programa tiene un nivel de llamada de 1, ese programa puede llamar a
otros programas los cuales estarán en un nivel de llamada de 2. Si alguna
entrada de nivel de llamada 2 realiza llamadas adicionales, esas llamadas
estarán en un nivel 3 y así sucesivamente. Cuando un programa de nivel de
llamada 3 termina, éste devuelve control al nivel de llamada 2. Similarmente,
cuando una entrada de nivel de llamada 2 termina regresa el control al nivel de
llamada 1.Y cuando un nivel de llamada 1 termina, el trabajo termina. El
sistema utiliza la pila de llamadas para monitorear el punto en el cual cada
programa debería regresar el control cuando cada uno termina.
Para definir esta interfaz se define una estructura especial llamada prototipo.
El compilador utiliza el prototipo para asegurar que el programa que llama pasa
los parámetros en forma correcta al programa llamado. El prototipo se codifica
en la sección de declaraciones del programa que hace la llamada. Si el
programa de llamada llama más de un programa, debe incluir un prototipo para
cada llamada.
Callp invoca al objeto del programa (tipo *PGM) asociado con el prototipo
declarado en el primer argumento requerido en la llamada y luego le pasa el
control. Enumere los parámetros entre paréntesis después del nombre del
prototipo:
Dcl-pr PRODEL_SQL Extpgm('PRODEL_SQL');
*N Char(5);
*N Char(1);
*N Char(40);
End-pr;
……………….
CALLP PRODEL_SQL(PIDPRODUCT:VACTION:VRESPONSE); // DELETE
A PRODUCT
Si los parámetros que pasa Callp no coinciden con el número, el orden y los
tipos de datos de los parámetros en la definición del prototipo, el programa no
se compilará. Si no hay parámetros, debe codificar paréntesis vacíos en su
lugar:
PRODEL_SQL(PIDPRODUCT:VACTION:VRESPONSE); // DELETE A
PRODUCT
sinParms ();
Este código llama a los programas asociados con sus respectivos prototipos, al
igual que en los ejemplos anteriores, la mayoría de los programadores
prefieren omitir la codificación explícita de la operación Callp, ya que esta
sintaxis coincide con operaciones de llamada similares a otros lenguajes
informáticos, como C o Java.
Return y *INLR
El sistema devuelve el control al programa de llamada cuando el programa
llamado encuentra una operación Return. Si el indicador LR esta también
encendido cuando se ejecuta el Return, el sistema libera los recursos
asignados al programa llamado. Una llamada subsecuente al programa causa
que comience de nuevo como si fuera la primera vez. Sin embargo, si el
indicador LR no está encendido dentro del programa llamado cuando éste
retorna control, el programa llamado continua activo, Como resultado una
llamada subsecuente a ese programa encuentra todas sus variables (excepto
las variables de los parámetros) e indicadores con los valores que tenían en el
momento del retorno anterior. Además, cualquier archivo que el programa
llamado utilizó permanece abierto, como resultado de la llamada anterior.
*Inlr = *On;
Return;
Por defecto, RPG pasa los argumentos de los parámetros pasando la dirección
de la ubicación en memoria representada por el parámetro, por lo que, de
hecho, estos parámetros correspondientes hacen referencia a la misma
ubicación de memoria dentro de la computadora. Los nombres de datos de
los parámetros que usa el programa llamante y el programa llamado no
necesitan ser los mismos. Para acceder a esas ubicaciones de memoria
pasadas por el programa llamante, el programa llamado debe incluir una
definición de interfaz de procedimiento (además del prototipo).
Al igual que el prototipo, la interfaz de procedimiento describe los parámetros
que el programa llamado debe compartir con el programa llamante. Sin
embargo, a diferencia del prototipo, la interfaz de procedimiento define los
nombres de las variables para almacenar los valores de los parámetros que el
programa llamado debe recibir, lo que le permite hacer referencia a esos
valores de los parámetros y manipularlos.
Dcl-pi MAIN;
PARM_TABLE Char(10); // TABLE NAME
PARM_CODVA Char(5); // CODE VALUE
PARM_RESUL CHAR(1); // RESPONSE
End-pi;
// PROGRAMA LLAMANTE
// ---- Prototypes
Dcl-pr PROVAL_SQL Extpgm('PROVAL_SQL');
*N Char(10);
*N Char(5);
*N Char(1);
End-pr;
......
VRESULT = *BLANKS;
PROVAL_SQL(VTABLE: PIDSUPPLR :VRESULT); // VALIDATE SUPPLIER
CODE
IF VRESULT = '1';
.....
Dcl-pi PROVAL_SQL;
PARM_TABLE Char(10); // TABLE NAME
PARM_CODVA Char(5); // CODE VALUE
PARM_RESUL CHAR(1); // RESPONSE
End-pi;
......
IF Sqlstate = SUCCESS;
PARM_RESUL = '1';
ELSE;
PARM_RESUL = '0';
ENDIF;
Después del retorno la variable VRESULT vale '1' o '0' y esto se debe a que
VRESULT y PARM_RESUL comparten la misma dirección en memoria.
Se debe asignar un tipo de datos a cada columna de una tabla. El tipo de datos
de la columna determina cómo se almacenan sus valores, cuánto
almacenamiento ocupa la columna y qué tipo de operaciones se pueden
realizar en la columna cuando se usa dentro de un programa. Los tipos de
datos de uso común se dividen en tres categorías generales:
· Carácter
· Numérico
· Fecha
Los datos tipo caracter pueden ser cualquier símbolo que el sistema soporte.
Las letras alfabéticas, los números y los caracteres especiales (por ejemplo,
signos de puntuación, símbolos de moneda) son todos datos de tipo caracter.
Una cadena de caracteres es una secuencia de caracteres. Un programa RPG
normalmente procesa datos de tipo caracter asignando valores de una variable
tipo caracter a otra, concatenando (uniendo) cadenas de caracteres o
convirtiendo datos tipo caracter en otro tipo de datos.
CHAR
Cuando SQL define una columna como CHAR (o CHARACTER), está
definiendo una cadena de caracteres de longitud fija. El atributo de longitud se
especifica entre paréntesis. Todos los valores de la columna tienen la misma
longitud en memoria. Los valores que no llenan toda la longitud se rellenan con
espacios en blanco.
VARCHAR
Especificar un tipo de datos de VARCHAR (o CHAR VARYING o CHARACTER
VARYING) define una columna como una cadena de caracteres de longitud
variable. El tamaño máximo se especifica (hasta 32.740) entre paréntesis.
Datos numéricos
NUMERIC
Especificar un tipo de datos NUMERIC (o NUM) define una columna como un
número decimal con zona (o con signo). Los números decimales con zona
toman un byte completo para almacenar cada dígito de un valor numérico. Por
tanto, un número de tres dígitos ocupa tres bytes. La zona del dígito más a la
derecha almacena el signo de los datos: 1111 (F) representa un valor positivo,
mientras que 1101 (D) representa un valor negativo. La representación por
zonas, entonces, es casi idéntica a la representación de caracteres, excepto
que el signo está incrustado en el byte del dígito más a la derecha.
F1 F5 F6
F1 F5 D6
DECIMAL
Especificar un tipo de datos DECIMAL (o DEC) define una columna como un
número decimal empacado. Los números empacados toman ventaja de la
redundancia que se crea en la representación de dígitos, en este caso no se
almacenan las zonas para los números. En formato empacado, solo el dígito, o
los bits de nivel inferior de un número se almacenan y el signo se representa
con 4 bits adicionales. Estos bits de signo siempre ocupan las últimas cuatro
posiciones de bits de un valor decimal empacado.
00010101 01101111
156F
00010101 01101101
156D
Un número de tres dígitos ocupa dos bytes. Puede que esto no parezca una
gran diferencia, pero números más grandes generan un mayor ahorro de
memoria: un número de 63 dígitos en formato empacado ocupa solo 32 bytes.
Tipo de Dato
Bytes
Digitos
Valor más bajo
Valor más alto
SMALLINT
2
-32,768
32,767
Tipo de Dato
Bytes
Digitos
Valor más bajo
Valor más alto
INT (o INTEGER)
4
10
-2,147,483,648
2,147,483,647
Tipo de Dato
Bytes
Digitos
Valor más bajo
Valor más alto
BIGINT
8
19
-9,223,372,036,854,775,808
9,223,372,036,854,775,807
DATE
Especificar un tipo de datos DATE define una columna como una fecha. Una
fecha es un valor de tres partes, que incorpora un mes, un día y año entre 0001
y 9999. Al definir una fecha, no es necesario especificar una longitud porque el
sistema la determina automáticamente.
(aaaa- mm-dd)
TIME
La especificación de un tipo de datos Time define una columna como una hora
del día, integrando horas, minutos y segundos. Los datos tipo Time siguen
muchos de los mismos principios que el tipo de datos Date. Al definir un dato
tipo Time, no es necesario especificar una longitud.
(hh.mm.ss)
· * JIS utiliza el formato de hora estándar industrial japonés (hh: mm: ss)
TIMESTAMP
Un timestamp es una combinación de fecha y hora en una sola variable. La
especificación de un tipo de datos timestamp define una columna tipo
timestamp (fecha y hora en una sola variable). Los tipos de datos timestamp
tienen seis o siete partes: año, mes, día, hora, minuto, segundo y,
opcionalmente, segundos fraccionarios.
Creación de tablas
Las declaraciones de lenguaje de definición de datos (DDL) se usan para crear
objetos nuevos, como tablas, y para alterar la estructura o propiedades de los
objetos de base de datos existentes.
Las tablas SQL contienen los datos de la base de datos. Cuando SQL crea una
tabla nueva, la base de datos crea un objeto de tipo archivo físico de un solo
miembro en una biblioteca. Las tablas están organizadas en filas (registros) y
columnas (campos). SQL usa la instrucción Create Table para crear una tabla:
Rcdfmt Prodrec
Nombre de tabla
La primera cláusula nombra la tabla a crear. El identificador de la tabla debe
comenzar con un carácter alfabético o uno de los caracteres especiales $, # o
@. Además de esos caracteres, los caracteres restantes pueden ser números o
un guión bajo (_). Un identificador de tabla no puede incluir espacios en blanco
incrustados. Los nombres de los objetos IBMi están limitados a 10
caracteres, por lo que se debe limitar el nombre de la tabla a 10
caracteres.
Definiciones de columna
La segunda cláusula de la declaración Create table enumera todas las
columnas que componen el diseño de la tabla. Las columnas se declaran
individualmente dentro de un único paréntesis. Cada definición de columna
incluye al menos el nombre de la columna y un tipo de datos. Si especifica un
nombre de columna de más de 10 caracteres o con caracteres no válidos, SQL
asigna un nombre generado por el sistema.
Los siguientes son los tipos de datos más comunes que se utilizan con IBMi:
· DATE
· TIME
· TIMESTAMP
Además del nombre y el tipo de datos, cada definición de columna puede incluir
cláusulas de restricción opcionales para definir mejor la columna. Una
restricción especifica una regla para los datos de una tabla. Dentro de las
cláusulas de restricción de uso común se incluyen las siguientes:
NOT NULL
DEFAULT
UNIQUE
PRIMARY KEY
La restricción UNIQUE garantiza que cada fila en las tablas tenga un valor
único para esa columna. Una regla relacionada, PRIMARY KEY (clave
principal), combina las restricciones NOT NULL y UNIQUE. PRIMARY KEY
asegura que una columna (o combinación de dos o más columnas) contiene un
valor único que identifica una fila específica en la tabla. Una tabla solo puede
tener una clave principal. Si la clave principal consta de una sola columna,
puede especificar la restricción de clave principal en la definición de columna:
……..
Rcdfmt Prodrec
Rcdfmt Prodrec3
…….
Rcdfmt Prodrec3
VALUES ('A001',3000,600,200)
Borrado de datos
Para eliminar una fila de una tabla, use la sentencia DELETE:
Nota: La consulta DELETE elimina datos de una tabla, pero no elimina la tabla
en sí. Para eliminar un objeto de base de datos y su contenido, se utiliza la
declaración DROP, por ejemplo, DROP TABLE PRODUCTS.
Actualización de datos
Hay casos en los que uno o más valores de columna necesitan ser
actualizados en un registro. Puede utilizar la sentencia UPDATE para modificar
los valores de los registros en una tabla:
Update INVENTORY
SET
QUANTITY = 5000
WHERE IDPROD = 'A001';
Este UPDATE establece el valor de 5000 para la columna QUANTITY solo para
la fila con un IDPROD cuyo contenido sea “A001". Si no se desea actualizar
todos los registros, asegúrese de incluir la cláusula WHERE. Pueden haber
situaciones en las que se desea actualizar cada registro de una tabla y, en
esos casos, no se necesitaría una cláusula WHERE.
Joins
Si necesita combinar o vincular datos de dos o más tablas diferentes en un solo
conjunto de resultados, puede usar JOIN para extraer datos de dos o más
tablas usando un campo común para vincularlos.
Hay múltiples tipos de JOIN disponibles. Un INNER JOIN devuelve todas las
filas de las tablas vinculadas donde se cumplen los criterios de coincidencia;
las filas que no coinciden no aparecen en el conjunto de resultados.
Supongamos que desea obtener el ID de Producto, la descripción del producto,
el precio unitario del producto y el nombre del proveedor que vende el
producto. En el siguiente ejemplo, los campos idSupplr y idSupp son campos
para relacionar las tablas PRODUCTS y SUPPLIERS (llave primaria y llave
foránea), y se puede usar JOIN para vincular las tablas. Esta sería la sintaxis
SQL:
ON A.idSupplr = B.idSupp ;
En la parte del SELECT para cada nombre de columna se tiene un prefijo. Esto
indica de qué tabla recuperar la columna. Por ejemplo, B.SUPPNAME indica
que se desea recuperar la columna SUPPNAME de la tabla SUPPLIERS en la
selección de columnas. Después de SELECT, viene la sintaxis JOIN, que dice:
Tomar la tabla PRODUCTS y unirla con la tabla SUPPLIERS. Las columnas
para hacer la coincidencia son idSupplr y idSupp para este caso y se usan en
la cláusula ON en donde se hace uso del prefijo para indicar la tabla a la que
pertenecen.
· RIGHT OUTER JOIN: incluye todas las filas de la tabla de la derecha y las
filas de la tabla de la izquierda que tengan coincidencia con filas de la tabla de
la derecha, si hay filas de la tabla de la derecha sin coincidencia con filas de la
tabla de la izquierda, las columnas de esa tabla (izquierda) vendrán con nulos.
· FULL OUTER JOIN: incluye filas coincidentes y no coincidentes de ambas
tablas.
AS
ON A.idSupplr = B.idSupp
INNER JOIN BRANCHES C
ON A.idBraOffi = C.idBraOffi
ON A.idWrehous = D.idWrehous
RCDFMT RECVIEW
Se elimina un constraint
Select
Insert
Update
Delete
Select
La instrucción Select es la instrucción de consulta principal de SQL, se puede
comparar con la operación de Read de RPG, pero con varias mejoras. Una
instrucción Select básica toma la siguiente forma:
Insert
La instrucción SQL Insert agrega un registro (fila) a una tabla o vista. Se
puede comparar a la operación RPG Write. Una declaración de inserción
simple tiene la siguiente forma:
La cláusula Insert Into nombra la tabla. Después del nombre de la tabla, una
lista de columnas entre paréntesis para las que se proporcionarán los valores.
La cláusula Values proporciona valores para cada una de las columnas de la
lista de columnas. Debe especificar los valores en el mismo orden que la lista
de columnas y debe tener el mismo número de valores que las columnas. La
lista de columnas es opcional. Si lo omite, la instrucción Insert asume que
todas las columnas en el diseño del registro tienen los valores
correspondientes especificados en la cláusula Values. Si una columna tiene
permite nulos o se crea con un valor predeterminado, puede omitirla de la
lista. En ese caso, se utiliza el valor predeterminado o un valor nulo.
Update
Delete
La instrucción SQL Delete elimina uno o más registros (filas) de una tabla, de
forma análoga corresponde a la operación Delete de RPG, esta declaración
sigue esta forma:
La directiva Exec SQL debe estar en una sola línea, pero la declaración SQL
en sí puede abarcar varias líneas. Al igual que con otras operaciones de RPG,
finaliza la instrucción SQL con un punto y coma (;):
UnitPrice = 999.99 ,
idWrehous = '002' ,
idBraOffi = '002' ,
entrydte = '2017-09-08'
WHERE idProduct = 'A001';
El nombre de la variable está precedido por dos puntos (:) y corresponde a una
variable de programa RPG. No es necesario definir la variable por separado
aparte de la variable RPG. Es el medio para permitir que la declaración SQL
se refiera a una variable RPG. Debe declarar la variable RPG con el mismo
tipo de datos y tamaño que la columna de base de datos asociada.
Las sentencias Insert y Delete también pueden usar variables Host para
sustituir valores de columnas:
Exec SQL Insert Into products
Values (:PIDPRODUCT, :PDESCRIPT, :PIDPRODTYP, :PIDSUPPLR,
:PUNITPRICE, :PIDWREHOUS, :PIDBRAOFFI, :PENTRYDTE);
Los nombres de variables Host no pueden comenzar con SQ, SQL, RDI o
DSN. Estos nombres están reservados para el uso de la base de datos.
Select Into
Si bien las sentencias Insert, Update y Delete se pueden insertar en un
programa RPG y pueden utilizar variables Host sin requerir grandes cambios,
el SQL incrustado requiere una modificación en la sentencia Select para
recuperar un conjunto de datos usando variables Host. La variación Select Into
recupera una sola fila y coloca el resultado en variables Host declaradas en el
programa:
Al igual que con las variables Host, debe existir una correspondencia uno a
uno entre las columnas de la consulta y los subcampos en la estructura Host.
Una estructura de datos Host es especialmente útil para recuperar todas las
columnas de un formato de registro. En este caso, es apropiada una estructura
de datos descrita externamente. Analice el siguiente ejemplo:
Cuando RPG ejecuta una declaración SQL, SQL devuelve al programa varias
herramientas de retroalimentación que se pueden utilizar para diagnosticar los
resultados de la ejecución de la sentencia. Si la instrucción SQL termina con
un error, el programa no se detiene sino que continúa ejecutándose con la
siguiente instrucción, por lo tanto, es importante verificar la respuesta de
diagnóstico antes de continuar con el programa RPG. El Área de
comunicación SQL (SQLCA) es una estructura de datos que contiene códigos
de retorno, subcampos con información valiosa de diagnósticos. No se debe
codificar explícitamente una estructura de datos SQLCA en el programa
porque el precompilador SQL la inserta automáticamente:
Dcl-ds Sqlca;
Sqlcaid Char(8); // (Nulo)
Sqlcabc Int(10); // Longitud de la estructura
Sqlcode Int(10); // Código retorno de SQL
Sqlerrml Int(5); // Longitud de Sqlerrmc
Sqlerrmc Char(70); // Texto de reemplazo del mensaje
Sqlerrp Char(8); // Identificador de producto
Sqlerrd Int(10) Dim(6); // información de diagnostico
Sqlwarn Char(1) Dim(11); // Banderas Warning
Sqlstate Char(5); // Código de retorno de SQL estándar
End-ds;
Sqlstate es similar a Sqlcode, pero mientras que los valores de Sqlcode pueden
ser exclusivos de IBMi, los valores de Sqlstate se establecen según los
estándares de la industria. Sqlstate tiene cinco caracteres; los dos primeros
caracteres indican una condición:
//----- CONSTANTS
Dcl-c SUCCESS '00000'; // SUCCESSFUL SQL OPER
Dcl-c EOF '02000'; // SQL RECORD NOT FOUND
Dcl-c NOT_FOUND 'PRODUCT NOT FOUND';
Dcl-c SUCCESSOPE 'OPERATION SUCCESSFUL';
Dcl-c NOTSUCCOPE 'OPERATION UNSUCCESSFUL';
Dcl-c INVSUPPLI 'INVALID SUPPLIER CODE';
IF Sqlstate = SUCCESS;
PARM_MSG = SUCCESSOPE;
ELSE;
PARM_MSG = NOTSUCCOPE;
ENDIF;
.....
1. Declarar el cursor.
2. Abrir el cursor.
3. Recuperar filas.
4. Cerrar el cursor.
Un cursor SQL siempre está asociado con una instrucción Select para
establecer las filas a recuperar. La instrucción Select no se ejecuta de
inmediato, sino hasta que se abre el cursor. La instrucción Select puede incluir
variables Host y variables tipo indicador, que se sustituyen cuando el
programa abre el cursor.
Cuando se abre un cursor insensitive, el sistema crea una copia temporal del
resultado de la consulta y el programa trabaja con esa copia. Un cursor
insensitive no reconoce las inserciones, actualizaciones o eliminaciones
posteriores de éste o cualquier otro programa. El uso de un cursor insensitive
puede mejorar el rendimiento, pero es posible que el programa no siempre lea
los datos más recientes.
Una vez que el programa ha procesado las filas en un cursor, debe cerrar
explícitamente el cursor. Cerrar un cursor descarta explícitamente el conjunto
de la consulta y libera bloqueos en tablas o vistas. Si el programa no cierra un
cursor, puede permanecer abierto para programas posteriores. Es necesario
cerrar y luego volver a abrir un cursor serial para volver a procesar el cursor.
Hasta ahora, todas las declaraciones de SQL incrustado que hemos discutido
han sido SQL estático. Con SQL estático, la estructura básica de cada
instrucción SQL se conoce en el momento de la compilación del programa. La
declaración SQL puede usar variables Host para sustituir valores en tiempo de
ejecución, pero su propósito general y construcción no cambian una vez que
se crea el programa.
Prepare
Los programadores suelen utilizar SQL dinámico junto con cursores SQL. En
el siguiente ejemplo, la instrucción Prepare traduce el contenido de la variable
SQLSTRING, creando SQLcursor, que luego se utiliza para proporcionar la
instrucción Select incrustada para el cursor PRODCURSOR:
ELSE;
Execute
Una vez que se ha preparado una sentencia, el programa puede ejecutar esa
sentencia muchas veces utilizando la instrucción SQL Execute. Si la
declaración incluye marcadores de parámetros, el programa puede sustituir un
valor diferente cada vez que se ejecuta la sentencia. La instrucción Execute
toma esta forma:
Alwcpydta
La opción Alwcpydta (Permitir copia de datos) indica si se puede utilizar una
copia de los datos con una instrucción Select para mejorar el rendimiento. El
uso de una copia temporal puede mejorar el rendimiento, pero el programa
puede correr el riesgo de usar un conjunto de resultados obsoleto si alguien
realizó cambios mientras el programa se está ejecutando.
Closqlcsr
Closqlcsr (Cerrar cursor de SQL) especifica cuándo cerrar los cursores de
SQL si el programa no los cierra explícitamente con una instrucción Close.
Esta opción también determina el alcance de las sentencias SQL preparadas y
los bloqueos de archivos. Estas son opciones comunes:
Closqlcsr (*Endjob) permite que los cursores permanezcan abiertos hasta que
finalice el trabajo en el IBMi (AS/400).
Commit
Hoy en día las DDS’s se continúan usando, pero con orientación a crear
archivos de dispositivos de pantalla o de impresión, siendo las pantallas las de
más uso.
Una pantalla en AS/400 está compuesta de tres tipos de definiciones, una
definición corresponde a nivel de archivo y sus definiciones aplican para
todos los formatos de pantalla dentro del archivo, es como el contenedor para
todo lo que se defina en relación a formatos de pantalla, otro tipo de
definición corresponde a formatos de pantalla y el termino formato lo
podemos asociar con una pantalla y la tercera definición corresponde a las
constantes y los campos que componen los formatos de pantalla.
Los formatos de pantalla establecen que campos serán leídos, que campos
serán para despliegue o que campos serán para ambos fines.
Para lograr la comunicación por medio de las teclas de función se hace uso de
INDICADORES, los indicadores fueron muy usados en versiones anteriores
del lenguaje RPG y los podemos comparar con el concepto de variable
booleana, en donde un indicador solo puede tener dos estados (encendido y
apagado), los indicadores son valores que están dentro del rango (01 - 99),
actualmente se siguen usando dentro de los archivos de pantalla, por ejemplo
la tecla de función F3 se puede asociar con el indicador 03, de tal forma que
cuando el usuario pulse F3 el indicador 03 pasara a un estado de
ENCENDIDO y este estado se usara en un programa para tomar una decisión.
A nivel de archivo de pantalla se puede declarar una palabra clave que permite
usar una estructura de datos de 99 bytes para organizar los 99 indicadores en
posiciones relativas y permite referirse a ellos por un nombre significativo en
lugar de usar un número.
Introducción a Procedimientos
Módulos NOMAIN
Ejemplo:
Dcl-proc MODVAL_SQL Export;
.
End-proc MODVAL_SQL;
Al igual que con los programas que hemos visto hasta ahora, los
procedimientos también requieren prototipos e interfaces para establecer
la comunicación.
Ejemplo:
ctl-opt Nomain ;
// --------------- PROTOTYPES ------------------------------------
/COPY EGO1L1/QSOURCES,PROTOTYPES
Dcl-pi MODVAL_SQL;
PARM_TABLE Char(10) VALUE; // TABLE NAME
PARM_CODVA Char(5) VALUE; // CODE VALUE
PARM_RESUL CHAR(1); // RESPONSE
End-pi;
.
.
End-proc MODVAL_SQL;
Los módulos Nomain también pueden ayudar a las empresas para centralizar
las funciones de la aplicación en una biblioteca común de módulos para su uso
y reutilización en toda la organización.
CRTPGM PGM(nombre-programa) +
BNDDIR(nombre-binder)
Ejemplo:
Dcl-pi MODVAL_SQL;
PARM_TABLE Char(10) VALUE; // TABLE NAME
PARM_CODVA Char(5) VALUE; // CODE VALUE
PARM_RESUL CHAR(1); // RESPONSE
End-pi;
Programas de servicio
El programa de servicio tiene solo una firma actual, pero puede conservar
muchas firmas anteriores, que representan muchas interfaces públicas
diferentes. Cuando se vincula un programa de servicio a un programa cliente,
el proceso de enlace asocia los dos objetos utilizando la firma actual. Pero si
existen programas cliente que identifican el programa de servicio por una
firma previa, esos programas pueden continuar usando el programa de
servicio sin volver a compilar o volver a enlazar. El comando DSPSRVPGM
muestra todas sus firmas válidas.
STRPGMEXP PGMLVL(*CURRENT)
EXPORT SYMBOL("MODVAL_SQL")
ENDPGMEXP
STRPGMEXP PGMLVL(*CURRENT)
EXPORT SYMBOL("MODVAL_SQL")
EXPORT SYMBOL("MODINC_SQL")
ENDPGMEXP
STRPGMEXP PGMLVL(*PRV)
EXPORT SYMBOL("MODVAL_SQL")
ENDPGMEXP
Grupos de activación
Un grupo de activación es una subdivisión de un trabajo que la arquitectura
ILE alista para realizar un seguimiento de los recursos que utiliza un
programa. Los recursos incluyen la memoria que utiliza un programa, ciertas
rutinas de manejo de errores y recursos de administración de datos temporales.
El sistema utiliza grupos de activación para permitirle a un trabajo crear
límites lógicos alrededor de sus aplicaciones.
Los programas ILE RPG (RPG IV), admiten todas las características ILE
modernas. Aunque los programas ILE RPG pueden ejecutarse en el grupo de
activación predeterminado DFTACTGRP(*YES), no deberían. Si se ejecutan
en el grupo de activación predeterminado DFTACTGRP(*YES), no se
admitirá módulos, procedimientos o programas de servicio, entre otras
restricciones.
El grupo de activación por defecto es el que usaban los programas RPG antes
de que se creara la arquitectura ILE.