Desarrollando en Cobol y Natural sobre Plataforma Mainframe

lunes, 14 de septiembre de 2015

ICETOOL: Como cruzar Ficheros con SPLICE (1)

Una de las funcionalidades más apreciadas de ICETOOL es la que nos permite cruzar varios ficheros y realizar comparaciones entre los registros contenidos en ellos. Estas acciones se realizan mediante el comando SPLICE, que puede ser considerado como uno de los operadores más útiles de la herramienta.

Cruzar ficheros mediante SPLICE de ICETOOL


En muchas ocasiones nos podemos encontrar con la necesidad de comparar los registros de dos ficheros distintos con el objetivo de determinar si son iguales en función de una clave determinada o no. Esto, que en principio parece una operativa compleja, puede ser realizado de forma bastante ágil mediante el operador SPLICE de la utilidad ICETOOL.

Tal y como se especifica en la documentación de la herramienta, la función SPLICE sirve para realizar un cruce de ficheros, comparar los registros contenidos en ellos, extraer la información seleccionada y enviarla a un fichero de salida.



Una vez comentado de forma teórica, lo mejor es que veamos cómo funciona el proceso de cruce de ficheros mediante un ejemplo. Para ello, vamos a partir de dos ficheros de diferente longitud de registro. En ambos datasets se va a encontrar la misma clave Población, así que vamos a ejecutar la comparación mediante este campo.

Comparar registros de ficheros mediante SPLICE


En nuestro ejemplo, vamos a usar como entrada un fichero de claves (KEYS) y un fichero maestro (MASTER). En el KEYS tendremos la relación entre los códigos de Población actuales (antiguos) y los códigos de Población nuevos. En el MASTER tendremos los registros de Población con toda su información asociada (uno de esos campos será la clave Población, que figurará inicialmente con el código actual).

En este caso, nos piden que sustituyamos en el MASTER los códigos actuales de las Poblaciones por los códigos nuevos (recordemos que la relación entre ambos figura en el fichero KEYS). Aquí es donde va a entrar en escena el empleo del SPLICE de la utilidad ICETOOL.
El contenido del fichero de relaciones entre claves, denominado SIST.UNLOAD.X0005X.POBL.KEYS, es el siguiente (en primer lugar figura la clave actual y, a continuación, la clave nueva sustituta):

----+----1---
*************
000010-100010
000002-100002
000004-100004
000005-100005
000006-100006
000007-100007
000008-100008
*************




Por otra parte, los registros que tenemos cargados en el fichero de Poblaciones, denominado SIST.UNLOAD.X0005X.POBL.MASTER, son los siguientes:

----+----1----+----2----+----3----+----4
***************************** Top of Data *****
A-000020-MADRID.................MAD00100    
B-000019-CIUDAD REAL............CRE00200    
A-000018-BARCELONA..............BAR00300    
A-000017-VALENCIA...............VAL00400    
A-000015-ZARAGOZA...............ZAR00600    
B-000014-CASTELLON..............CAS00700    
B-000012-GRANADA................GRA00900    
B-000011-TOLEDO.................TOL01000    
B-000010-SEGOVIA................SEG01100    
B-000002-ALMERIA................ALM01300    
B-000004-SANTANDER..............SAN01500    
B-000005-TARRAGONA..............TAR01600    
B-000006-BADAJOZ................BAD01700    
B-000007-SALAMANCA..............SAL01800    
B-000008-BURGOS.................BUR01900    
**************************** Bottom of Data ***


La idea es que, tras lanzar nuestro proceso de conversión, la población Madrid del MASTER, por ejemplo, ya no esté asociada al código antiguo 000020 sino al código nuevo 100020. El resto de campos de los registros del fichero maestro tienen que quedar exactamente igual que ahora.

A continuación, mostramos el código necesario para realizar el cambio comentado.

//*            *******************************************
//*            * PASO ICETOOL PARA REFORMATEAR ENTRADAS      //*            *                                          //*            *******************************************
//JJ0105   EXEC PGM=ICETOOL                                          //TOOLMSG  DD  SYSOUT=*                                             
//DFSMSG   DD  SYSOUT=*                                             
//* KEYS  : FICHERO DE RELACIONES ENTRE CLAVES                   
//KEYS     DD  DSN= SIST.UNLOAD.X0005X.POBL.KEYS,    
//             DISP=SHR                                             
//* MASTER: FICHEROS DE POBLACIONES
//MASTER   DD  DSN= SIST.UNLOAD.X0005X.POBL.MASTER,
//             DISP=SHR                                              //* TEMP1 : FICHERO KEYS FORMATEADO Y ORDENADO PARA CRUCE
//TEMP1    DD  DSN=SIST.JJ0105T1.X0060X.DDD.POBL.T1,
//             DISP=(NEW,CATLG,DELETE),                              //             SPACE=(CYL,(00100,00100),RLSE),                     
//             UNIT=DISCO                                          
//* TEMP2 : F. POBLACIONES FORMATEADO Y ORDENADO PARA CRUCE
//TEMP2    DD  DSN=SIST.JJ0105T2. X0060X.DDD.POBL.T2,
//             DISP=(NEW,CATLG,DELETE),                              //             SPACE=(CYL,(00100,00100),RLSE),                     
//             UNIT=DISCO                                          
//TOOLIN   DD  DSN=SIST.SYSIN(JJRS1A03),                      
//             DISP=SHR                                            
//CTL1CNTL DD  DSN=SIST.SYSIN(JJRS1A04),                     
//             DISP=SHR                                            
//CTL2CNTL DD  DSN=SIST.SYSIN(JJRS1A05),                     
//             DISP=SHR                                            
//JJ0105A  EXEC PGM=ABEN3333,                                      
//             COND=(4,GE,JJ0105)                                  
//CTRNORST DD  DUMMY                                               
//*                                                                
//*            *******************************************
//*            * PASO ICETOOL PARA GENERAR SALIDAS
//*            *                                            
//*            *******************************************
//JJ0107   EXEC PGM=ICETOOL                                         
//TOOLMSG  DD  SYSOUT=*                                             
//DFSMSG   DD  SYSOUT=*                                             
//* CONCAT: FICHERO UNIFICADO PARA REALIZAR EL ICETOOL       
//CONCAT   DD  DSN=SIST.JJ0105T1.X0060X.DDD.POBL.T1,
//             DISP=SHR                                              //         DD  DSN=SIST.JJ0105T2.X0060X.DDD.POBL.T2,
//             DISP=SHR                                             
//* OUT   : FICHERO DE SALIDA CON LOS REGISTROS MODIFICADOS         
//OUT      DD  DSN=SIST.JJ0107S1.X0060X.DDD.POBL.MD,
//             DISP=(NEW,CATLG,DELETE),                              //             SPACE=(CYL,(00100,00100),RLSE),                      
//             UNIT=DISCO                                           
//* OUT1  : F. DE SALIDA CON LOS REGISTROS NO MODIFICADOS      
//OUT1     DD  DSN=SIST.JJ0107S2.X0060X.DDD.POBL.RS,
//             DISP=(NEW,CATLG,DELETE),                              //             SPACE=(CYL,(00100,00100),RLSE),                    
//             UNIT=DISCO                                         
//TOOLIN   DD  DSN=SIST.SYSIN(JJRS1A06),                    
//             DISP=SHR                                           
//CTL3CNTL DD  DSN=SIST.SYSIN(JJRS1A07),
//             DISP=SHR                                           
//CTL4CNTL DD  DSN=SIST.SYSIN(JJRS1A08),                    
//             DISP=SHR                                           
//JJ0107A  EXEC PGM=ABEN3333,                                      
//             COND=(4,GE,JJ0107)                                 
//CTRNORST DD  DUMMY                                              
//*

   
Y las fichas asociadas al código anterior son las siguientes:

*--------------------------------------------------------*
* <<< FICHA JJRS1A03 >>>
* COPIA KEYS A FICHERO TEMP1 PARA PERMITIR SPLICE
* COPIA MASTER A TEMP Y AÑADE LOS REGISTROS A COMBINAR
*--------------------------------------------------------*
  COPY FROM(KEYS) TO(TEMP1) USING(CTL1)          

  COPY FROM(MASTER) TO(TEMP2) USING(CTL2)

*--------------------------------------------------------*
* <<< FICHA JJRS1A04 >>>  
* REFORMATEAMOS EL KEYS - LA CLAVE ES LA POBLACION
*--------------------------------------------------------*
  SORT FIELDS=(1,6,CH,A)                                  
  OUTREC FIELDS=(1,13,33X,47:C'D',8,6)

*--------------------------------------------------------*
* <<< FICHA JJRS1A05 >>>
* REFORMATEAMOS EL MASTER - LA CLAVE ES LA POBLACION
*--------------------------------------------------------*
  INREC FIELDS=(3,6,1,40)     
  SORT FIELDS=(1,6,CH,A)      
  OUTREC FIELDS=(1,46,47:C' ',6X)

*--------------------------------------------------------*
* <<< FICHA JJRS1A06 >>>
* OUT: REGISTROS QUE COINCIDEN                           *
* INCLUIMOS TODO DEL MASTER MAS POBLACION NUEVA DE KEY   *
* MAS UN INDICADOR NUEVO DE MODIFICADO
* OUT1: RESTO DE REGISTROS QUE NO COINCIDEN              *
*--------------------------------------------------------*
  SPLICE FROM(CONCAT) TO(OUT) ON(1,6,CH) WITHALL  -
  WITH(7,40) USING(CTL3)                         
  SPLICE FROM(CONCAT) TO(OUT1) ON(1,6,CH) WITHALL  -
  WITH(7,40) USING(CTL4) KEEPNODUPS KEEPBASE     

*--------------------------------------------------------*
* <<< FICHA JJRS1A07 >>>
* SUSTITUIMOS POBL ENCONTRADOS POR POBL NUEVAS
* SE INCLUYE INDICADOR DE MODIFICADO
*--------------------------------------------------------*
  OUTFIL FNAMES=OUT,
  INCLUDE=(47,1,CH,EQ,C'D'),
  OUTREC=(7,2,48,6,15,32)                  

*--------------------------------------------------------*
* <<< FICHA JJRS1A08 >>>
* SACAMOS REGISTROS NO ENCONTRADOS PARA CUADRAR ENTRADA
*--------------------------------------------------------*
  OUTFIL FNAMES=OUT1,
  INCLUDE=(47,1,CH,EQ,C' '),
  OUTREC=(7,40)       
                       


Como vemos, el código anterior se compone de dos pasos JCL, que son los que vamos a necesitar para, en primer lugar, reformatear e igualar la longitud de los dos ficheros de entrada y, posteriormente, generar un fichero de salida con los registros modificados y otro con los registros no modificados.



Detalle de las fichas requeridas para realizar un SPLICE


A continuación, una vez mostrado el código anterior, vamos a ir revisando con un poco de detalle en qué consisten cada una de las fichas que hemos tenido que crear en los dos pasos del JCL. Como veremos, muchas de ellas son bastante genéricas.

PASO 1: PASO ICETOOL PARA REFORMATEAR ENTRADAS


1º) Invocación a ICETOOL: El primer paso es, como siempre, la invocación a la herramienta ICETOOL mediante el comando EXEC PGM.

//JJ0105   EXEC PGM=ICETOOL                                           

2º) Especificación de los ficheros de entrada: A continuación, indicamos los nombres de los dos ficheros de entrada que vamos a emplear en el ICETOOL. Se trata del fichero de relaciones entre claves (SIST.UNLOAD.X0005X.POBL.KEYS) a emplear y del fichero maestro con los datos de poblaciones (SIST.UNLOAD.X0005X.POBL.MASTER).

//* KEYS  : FICHERO DE RELACIONES ENTRE CLAVES                    
//KEYS     DD  DSN= SIST.UNLOAD.X0005X.POBL.KEYS,    
//             DISP=SHR
//* MASTER: FICHEROS DE POBLACIONES
//MASTER   DD  DSN= SIST.UNLOAD.X0005X.POBL.MASTER,
//             DISP=SHR


3º) Especificación de los ficheros de salida: Del mismo modo, también indicamos los nombres de los ficheros que van a contener la información reformateada de KEYS y MASTER. Estos datsets intermedios se denominarán SIST.JJ0105T1.X0060X.DDD.POBL.T1 y SIST.JJ0105T2.X0060X.DDD.POBL.T2.

//* TEMP1 : FICHERO KEYS FORMATEADO Y ORDENADO PARA CRUCE
//TEMP1    DD  DSN=SIST.JJ0105T1.X0060X.DDD.POBL.T1,
//             DISP=(NEW,CATLG,DELETE),               

//             SPACE=(CYL,(00100,00100),RLSE), 
//             UNIT=DISCO  
//* TEMP2 : F. POBLACIONES FORMATEADO Y ORDENADO PARA CRUCE
//TEMP2    DD  DSN=SIST.JJ0105T2. X0060X.DDD.POBL.T2,
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(00100,00100),RLSE),
//             UNIT=DISCO



4º) Ficha TOOLIN: Aquí es donde vamos a indicarle a ICETOOL que tiene que proceder a ejecutar el operador COPY en dos ocasiones. La primera de ellas para pasar de KEYS a TEMP1 y la segunda para pasar de MASTER a TEMP2.

*--------------------------------------------------------*
* <<< FICHA JJRS1A03 >>>                                
* COPIA KEYS A FICHERO TEMP1 PARA PERMITIR SPLICE
* COPIA MASTER A TEMP2 Y AÑADE LOS REGISTROS A COMBINAR
*--------------------------------------------------------*
  COPY FROM(KEYS) TO(TEMP1) USING(CTL1)

  COPY FROM(MASTER) TO(TEMP2) USING(CTL2)
                                     
5º) Fichas de Control: Aquí es donde tenemos que indicar al SPLICE la forma en la que queremos que se ejecuten los operadores COPYS del TOOLIN anterior. En nuestro ejemplo, aquí están incluidas las fichas CTL1 y CTL2.

*--------------------------------------------------------*
* <<< FICHA JJRS1A04 >>>                            

* REFORMATEAMOS EL KEYS - LA CLAVE ES LA POBLACION
*--------------------------------------------------------*
  SORT FIELDS=(1,6,CH,A)                                  
  OUTREC FIELDS=(1,13,33X,47:C'D',8,6)





La primera ficha de control (CTL1CNTL) hace referencia al COPY de KEYS a TEMP1. Como podemos ver en la codificación de la ficha anterior, en ella se realizan dos cosas con los datos de entrada.

-          Lo primero que hace es ordenar el fichero KEYS en función del campo de longitud 6 situado en la posición 1 (se trata del campo código de Población).

-          A continuación, transfiere del KEYS al TEMP1 la siguiente información de los registros: el campo de longitud 13 que empieza en la posición 1 (1,13), 33 espacios en blanco (33X), un carácter ‘D’ en la posición 47 (47:C’D’) y el campo de longitud 6 que empieza en la posición 8 (8,6).

*--------------------------------------------------------*
* <<< FICHA JJRS1A05 >>>
* REFORMATEAMOS EL MASTER - LA CLAVE ES LA POBLACION
*--------------------------------------------------------*
  INREC FIELDS=(3,6,1,40)     
  SORT FIELDS=(1,6,CH,A)      
  OUTREC FIELDS=(1,46,47:C' ',6X)




La segunda ficha de control (CTL2CNTL) hace referencia al COPY de MASTER a TEMP2. Del mismo modo que en la anterior, en esta segunda ficha vemos que también se realizan varias acciones con los datos de entrada.

-          INREC: En primer lugar, a los registros de entrada le insertamos por delante el campo de longitud 6 que está en la posición 3 (3,6), que es la Población. A continuación, se incluyen las 40 posiciones de los registros sin realizar ningún cambio sobre ellas (1,40).

-          SORT: Se ordena el fichero en función del campo de longitud 6 situado en la posición 1 (se trata del campo código de Población que acabamos de insertar en la sentencia anterior).

-          OUTREC: Se transfiere del MASTER al TEMP2 la siguiente información de los registros: el campo de longitud 46 situado en la posición 1 (1,46), un carácter en blanco (47:C’ ‘) y 6 espacios en blanco (6X).


El próximo día, en un nuevo post, terminaremos de ver las fichas necesarias para implementar un SPLICE en un JCL. La idea será examinar en detalle para qué sirve cada una de las sentencias incluidas en el paso 2. De ese modo, completaremos la visión global del proceso y, a partir de ese momento, ya no deberíais tener problemas a la hora de codificar vuestro propio job.

Pues nada, eso es todo por hoy. Como ya sabéis, quedáis invitados a la segunda parte del artículo. De todas formas, si no podéis esperar hasta entonces, aquí abajo podéis ir dejándome las dudas que os surjan en relación con este tema.

Saludos.

No hay comentarios:

Publicar un comentario

Related Posts Plugin for WordPress, Blogger...