Bienvenidos a Iseries Venezuela

Las mejores prácticas, recursos, tips, enlaces, videos y artículos para informáticos relacionados con el Iseries y el As/400 lenguajes de programación RPG, ILE RPG y SQL.

The best practices, resources, tips, links, videoes and articles for computer related to the Iseries and the As/400 languages of programming RPG, ILE RPG and SQL.

sábado, 21 de marzo de 2009

Pregunta- STRISDB










Pregunta:

Hola te saluda Jaime Maza desde Quito-Ecuador, tuvieras la gentileza de indicarme con un ejemplo como se debe pasar parámetros de variables tipo caracter, numérica y lógica utilizando la herramienta de depuración STRIDB, en ambiente de programación RPG400.

De antemano gracias por tu ayuda.

Saludos

Respuesta:

El comando STRISDB, se utiliza en un ambiente interactivo y es activado desde la línea de comando del Iseries.

AL colocar STRISDB y luego F4, aparecen una series de parámetros en los cuales debes especificar el nombre del programa que deseas invocar, si deseas invocarlo inmediatamente o no y si deseas incorporarles parámetros en la llamada o no.

Primera Opción:

Los parámetros en cualquiera de sus modalidades son “valores”, no permite variables sino literales por ejemplo:


STRISDB PGM(TUPROGRAMA) INVPGM(*YES) PARM(‘Hola Mundo’ X'11' ‘1’)

En esta primera opción, con el parámetro INVPGM = *yes el programa se llama inmediatamente al terminar de activar el comando.

Para valores alfabéticos: EL valor entre comillas simples: ‘Hola Mundo’

Para valores numéricos: El valor como se especifica en el ejemplo:

-Para el caso X’11’ se trata de un numérico empaquetado (número 11)
-Cuando es un numérico con signo (declarado ‘S’ en la hoja ‘D’):
Sería X’011F’ si es un numérico positivo y si es negativo X'011D’

En todos los casos:
la longitud del valor (la parte entre apóstrofos)
siempre debe ser par (rellenar con 0 a la izquierda de ser necesario)
incluyendo el último caracter, que indica el signo (F=Positivo y D=Negativo)

(En lo particular prefiero trabajar con parámetros alfabéticos porque en versiones de Rpg-Ile avanzadas los parámetros de entrada numéricos son un dolor de cabeza)

-Para valores lógicos (Indicadores o variables booleanas) se pasa lo siguiente:

‘0’ = indicador apagado
‘1’ = indicador encendido

En el ejemplo se inicializa encendido el parámetro lógico = ‘1’


Segunda Opción:

Con el parámetro INVPGM = *NO el sistema operativo presenta ante ti la línea de comandos para que realices los comandos previos que necesites a la ejecución del programa sobre el cual estas haciendo el STRISDB

Te expongo este caso por si tu dilema se trata de “pasar variables” que tu necesitas pasar en el strisdb. Como no es posible pasar variables sino valores literales, puedes llamar en la línea de comandos a un programa RPG o a un programa CLP que a su vez, llame al programa sobre el cual estas haciendo debug y cuando el strisdb entra a tu programa recibe, del programa previo, los valores que deben ejecutarse.

Tercera Opción:

Puedes realizar STRISDB a varios programas a la vez, es decir al programa previo que llama (call) al programa que te interesa y además al programa que en realidad te interesa controlar.

¿Cómo se hace eso?

Primero realizas un STRISDB sobre el primer programa puedes colocar INVPGM = *YES, cuando el sistema operativo esté suspendido en este primer debug, aplicas F14 y te presenta una opción para añadir otro programa que debe ser incluido en STRISDB, allí colocas el nombre del segundo programa (para los fines de este ejemplo es el que realmente te interesa controlar) y continuas haciendo debug paso a paso con el primer programa. Antes de que se invoque el segundo programa puedes cambiar los valores de los parámetros de entrada y luego proseguir con el debug.

Para realizar STRISDB sobre varios programas a la vez, los programas deben ser de tipo: RPG, CLP.

Para realizar debug simultáneos entre programas RPG y CLP, que ejecutan programas RPGLE, y CLLE hay que realizar un procedimiento especial. (Me parece que este tema en particular está fuera del alcance de tu pregunta).

Espero esto resuelva tu inquietud,
A tu orden para cualquier duda o aclaratoria.

Saludos desde Venezuela!

Para nuestros lectores:
Envíanos tus preguntas a rpg.iseries@gmail.com y las compartimos para que todos
podamos aprender de nuestras experiencias.



Si te pareció interesante, reenvialo a un amigo haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo.


Autor:  Ing. Liliana Suárez

miércoles, 18 de marzo de 2009

SENTENCIAS DEL FLUJO DE CONTROL EN LOS CLP











Antes del Release V5R3 del Iseries, era imprescindible el uso del GOTO para generar lazos iterativos, bucles o ciclos de repetición. A partir del la versión V5R3 se introducen sentencias que permiten eliminar el uso del GOTO y desarrollar una programación con el uso de sentencias asociadas al concepto de Programación Estructurada. A continuación los nuevos comandos que permiten el Flujo de control en los CLP

Nuevos Comandos CLP


----------------------

DOUNTIL

• Evalúa la condición al final del lazo

Ejemplo:

DOUNTIL (&NUM *EQ 20)

CHGVAR var(&NUM) Value(&NUM + 1)

END


------------------------------------

DOWHILE

• Evalúa la condición al principio del lazo

Ejemplo:

DOWHILE (&NUM *LT 20)

Chgvar var(&Num) Value(&Num + 1)

ENDDO


------------------------------

DOFOR

• Evalúa la condición al principio del lazo
• Var(&num) debe ser tipo *Int (integer)
• From/To pueden ser Integer, expresiones o variables.
• By() debe ser constante integer.


CHGVAR var(&NUMB) Value(0)

DOFOR VAR(&NUM) FROM(9) TO(13) BY(1)

CHGVAR var(&NUMB) Value(&NUMB + &NUM)

ENDDO
/* &NUMB = 55 después de ejecutar el DOFOR cuatro veces.


-------------------


SELECT (with WHEN and OTHERWISE)

• La Sentencia SELECT Inicia un grupo de comandos
• ENDSELECT Finaliza el grupo de comandos
• El grupo debe tener al menos una sentencia WHEN
• La sentencia OTHERWISE es opcional


SELECT

WHEN (&LogicaL)

WHEN (&NUM *GT 0) THEN (CHGVAR
&NUM 0)

WHEN (&NUM *GT 10) (DOUNTIL (&NUM
*EQ 0))

CHGVAR &NUM (&NUM - 1)
ENDDO

OTHERWISE (CHGVAR &LogicaL ’0’)

ENDSELECT


----------------------------------

ITERATE


• A través de etiquetas, permite saltar hacia otros lazos de iteración
• Por omisión permanece en el lazo donde se encuentra
• Pasa el control al final del lazo y verifica la condición.

Se permite dentro de un ciclo de iteración
– DOWHILE
– DOUNTIL
– DOFOR

CICLO1:
CICLO2: DOWHILE &LGL
CICLO3: DOFOR &INT FROM(0) TO(99)

IF (&NUMA *EQ 500) THEN (ITERATE CICLO1)
/* No procesa si NUMA=500 */

IF (&NUMA *GT 500) ITERATE
/* No procesa si NUMA>500 por omisión va a CICLO3*/
ENDDO

IF (&NUMA *LT 500) (ITERATE CICLO1)
/* No procesa si NUMA < 500 */ ENDDO


---------------------------

LEAVE


• A través de etiquetas, permite saltar hacia otros lazos de iteración
• Por omisión permanece en el lazo donde se encuentra
• Pasa el control a la instrucción que esté después del final del lazo

Se permite dentro de un ciclo de iteración
– DOWHILE
– DOUNTIL
– DOFOR

CICLO1:
CICLO2: DOWHILE &LGL
CICLO3: DOFOR &INT FROM(0) TO(99)

IF (&NUMA *EQ 500) THEN (LEAVE CICLO1)
/* No procesa si NUMA=500 */

IF (&NUMA *GT 500) LEAVE
/* No procesa si NUMA>500 salta a: IF Numa *Lt 500*/
ENDDO

IF (&NUMA *LT 500) (LEAVE CICLO1)
/* No procesa si NUMA < 500 */ ENDDO




Si te pareció interesante, reenvialo a un amigo haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo.


Autor:  Ing. Liliana Suárez

domingo, 15 de marzo de 2009

¿Es posible Hacer un Chain en un programa CL?












Cuando estamos programando un CLP, a veces nos encontramos en la necesidad de detectar si un registro con determinados valores en su clave, existe en la base de datos y dependiendo del resultado de la búsqueda tomamos una acción u otra.

Hay varias opciones para obtener un resultado, algunas son más felices que otras en términos de eficiencia y programación:

1.-Leer todo el archivo y preguntar si el valor de un campo corresponde al valor que estamos buscando en el archivo.
Esto consume mucho tiempo de respuesta.


2.-Llamar a un programa en RPG pasándole el valor como parámetro para que el Programa RPG realice el chain y nos devuelva en otro parámetro la respuesta de si existe o no existe el registro en el archivo. Esto implica un call cada vez que se entra al programa CLP

3.-Utilizar Opnqryf y leer los resultados que arroja. Es mas lento por la generación de una tabla de lectura intermedia.

4.-Realizar un ovrdbf especificando la clave de búsqueda y monitoreando el mensaje de excepción. Esta es la opción más eficiente. A continuación un ejemplo:

PGM
DCL VAR(&USER) TYPE(*CHAR) LEN(10)
DCLF FILE(TABLAUSER)
/* Obtiene el usuario actual */
RTVSYSVAL SYSVAL(QUSER) RTNVAR(&USER)

OVRDBF FILE(TABLAUSER) POSITION(*KEY 1 FMT1 &USER)
RCVF

/* SI ES FIN DE ARCHIVO O NO ENCUENTRA LA CLAVE DE BUSQUEDA */
/* Finaliza el programa*/
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(FINPGM))
/* Si el Usuario está en el archivo */

IF (&USER *EQ &NOMBRE) +
THEN(DO) /* USUARIO SI ESTA EN LA TABLA*/
GOTO CMDLBL(PROCESAR)
ENDDO


PROCESAR: CALL PGM(PROCUSER)
FINPGM: ENDPGM


Esta última opción es la mas eficiente ya que consume menos tiempo de procesamiento y el código es mas directo y fácil de seguir para cualquier programador.

Se explica el comando Ovrdbf con estos nuevos parámetros:

OVRDBF FILE(TABLAUSER) POSITION(*KEY 1 FMT1 &USER)

Los valores del parámetro POSITION se interpretan de la siguiente manera:

Posicionarse en:

A) *KEY = el primer registro del archivo TABLAUSER
B) FMT1 = con formato de registro FMT1
C) 1 = cuyo valor en el primer campo clave (1) sea igual al
valor de la variable &USER.

Al momento de ejecutar el RCVF, si no consigue ningún registro en el archivo que cumpla con esta condición entonces va a Fin de programa. Esta verificación se realiza utilizando el comando MONMSG para detectar si hay algún status de excepción.

1.- Además del valor *KEY existen otros valores que podemos emplear si necesitamos una búsqueda mas avanzada:


*KEYBE (key-before or equal): Si no hay registro en el archivo que haga match con el valor especificado en el ovrdbf, se selecciona el registro anterior con valor menor al especificado.
Esto es la combinación de dos comandos SETLL y READ

*KEY (key-equal): The registro identificado por los valores de búsqueda especificados en el programa es el registro que será retribuido en la lectura.
Esto es la combinación de SETLL y READE

*KEYAE (key-after or equal):
Si no hay registro en el archivo que haga match con el valor especificado en el ovrdbf, se selecciona el siguiente registro con valor mayor al especificado.
Esto es la combinación de dos comandos READE y SETGT

*KEYA (key-after):
El primer registro con un valor mayor al valor especificado en el programa será el registro retribuido en la lectura.
Esto es la combinación de dos comandos SETGT y READ

2.-Número de Campos clave en la búsqueda.

En el ejemplo colocamos un 1, pero podemos colocar otros valores de acuerdo a lo que necesitemos buscar en el archivo.

Si POSITION(*KEY 1 FMT1 A) es especificada, el primer registro en el archivo con formato de registro FMT1 que tiene su primer campo clave con valor ‘A’ es retribuido en la lectura. Si se especifica un valor cero (0) la búsqueda del valor ‘A’ se realizará en todos los campos clave del archivo.

Si especificamos un valor 2, por ejemplo estamos diciendo que busque el primer registro del archivo con valor ‘A’ en el segundo campo que constituye la clave del archivo.

El nombre del formato de registro puede ser omitido y podemos colocar *N para decirle que tome todos los formatos de registro del archivo

Tomando en cuenta estos últimos tips, el parámetro POSITION quedaría asi:

POSITION(*KEY 2 *N A)



Si te pareció interesante, reenvialo a un amigo haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo.


Autor:  Ing. Liliana Suárez

miércoles, 11 de marzo de 2009

Integridad de la base de datos.











En la imagen asociada a este artículo se observa un relación 1:N, en una base de datos hipotética de cualquier institución comercial. Tenemos un encabezado de Factura en el nivel mas alto de la jerarquía del modelo y los detalles de los artículos en el siguiente nivel. (Haz Click sobre la imagen si la quieres ver ampliada)

Un buen contingente de programadores hace esto al grabar, en los archivos, la información incluida por el usuario:

C Lee artículo
C*
C Dow Not (*in99)
C |
C | Monto Total Factura = Monto Total Factura + Monto Artículo
C |
C | Write artículo
C |
C | Lee artículo
C |
C | Enddo

C Write Encabezado de Factura


La idea de este algoritmo, es ir acumulando los montos parciales facturados para luego grabar el monto total en el encabezado de la factura.

Esta secuencia de pasos mostrado en este pseudocódigo puede poner en peligro la integridad de la base de datos. Si hay una caída del sistema, antes de que se grabe el encabezado de factura, quedaran los artículos grabados sin tener su respectivo encabezado asociado y recuperar la información que quedó incompleta será más difícil:


1.- Si el sistema genera los códigos de factura con un consecutivo en forma automática y hay varios usuarios cargando factura en el mismo momento en que el sistema cae podrían mezclarse artículos de distintas facturas, dependiendo del algoritmo que se utilice para generar las facturas.

2.-Los reportes y consultas que totalizan por artículo vendido en un rango de fecha no podrían reflejar estos artículos que quedaron sin encabezado.

3.-Probablemente, el cruce de información entre los reportes consolidados y los reportes detallados no reflejarán el descuadre porque tanto en los reportes de totales facturados como en los detallados en un período de tiempo, posiblemente, omiten las facturas que quedaron incompletas. Esto dificulta al analista de sistemas como al analista de negocio localizar los errores con prontitud.




Haciendo algunos cambios en el algoritmo presentado, se reduce el riesgo de atentar en contra de la integridad de la base de datos:

C Write Encabezado de Factura /* con monto total en cero, */
C*
C Lee artículo
C*
C Dow Not (*in99)
C |
C | Monto Total Factura = Monto Total Factura + Monto Artículo
C |
C | Write artículo
C |
C | Lee artículo
C |
C | Enddo

C Update Encabezado de Factura


Si hay una caída del sistema, puede detectarse con facilidad las facturas que quedaron inconclusas en información puesto que el monto del encabezado quedó grabado en cero.
Por otra parte, el cruce de reportes consolidados y detallados reflejaría inmediatamente un descuadre que sería rápidamente detectado por cualquier analista del negocio aunque no pertenezca al área de sistemas.


Si te pareció interesante, reenvialo a un amigo haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo.


Autor:  Ing. Liliana Suárez