SyncSort: Filtrar y ordenar un archivo por JCL

Comenzaré un conjunto de problemas que se pueden resolver en un entorno Mainframe directamente con herramientas Sort tipo SyncSort, en vez de usar problemas COBOL.

Esto nos servirá para revisar algunos conceptos de JCL y otros de COBOL. Algunos problemas serán muy sencillos y otros más complejos. Espero sean de utilidad.

Problema

Tengo un archivo de movimientos (operaciones, transacciones, etc.) Este archivo de movimientos tiene varios tipos de movimientos, además de los que necesito. Además, no está ordenado según mi conveniencia.

Digamos que tenemos esta estructura:

01 REGISTRO.
   05 CONTRATO PIC X(18). //POS 1..18*
 ...
   05 CANAL PIC X(04). //POS 58..4 
 ...
   05 FECHAPROC PIC X(10). //POS 78..10 
 ...
   05 TERMINAL PIC X(04). //POS 88..4 
 ...
   05 IMPORTE PIC S9(06)V9(02) COMP-3. //POS 116..5** 
 ...
   05 ESTADO PIC X(01). //POS 121..4 
 ...
   05 CODOPERAC PIC X(02). //POS 210..2
 ...

El archivo tiene en total 272 bytes de longitud fija, y queremos ordenar por CONTRATO, FECHAPROC, TERMINAL, IMPORTE y CODOPERAC.Además, queremos quedarnos solamente con las operaciones cuyo CANAL es ‘CAJE’, ‘TPV ‘ y ‘TERM’ y solo con movimientos activos, es decir, cuyo ESTADO sea ‘A’.

Notas

* Nota 1: Este comentario no es válido en un COPY real, es solo una referencia para indicar la posición del campo dentro del COPY real. He puesto solo los campos de interés para el problema.

** Nota 2: ¿Por qué ese COMP-3 ocupa 5 posiciones? Por la fórmula ((p+s)/2) +1. Estos campos son los llamados “empaquetados” y almacenan los números de manera distinta, optimizando espacio y tiempo de procesamiento. Más información, aquí.

Solución

¿Qué tenemos a disposición? Pues SyncSort.

Ya deberíamos pensar que como algoritmo tendríamos algo así:

ENTRADA SORT: FILE1.ENTRADA.D1%%ODATE
SALIDA SORT:  FILE1.SALIDA.D1%%ODATE     
ORDENAR POR: CONTRATO, FECHAPROC, TERMINAL, IMPORTE y CODOPERAC
FILTRAR POR: CANAL = 'CAJE', 'TPV ' o 'TERM' Y ESTADO = 'A'

Refinemos a colocar parámetros en el archivo de salida, y a convertir todos los nombres en posiciones, que es como funciona SyncSort (y utilitarios de ordenación en general), también usando ya la terminología SyncSort:

SORTIN=   FILE1.ENTRADA.D1%%ODATE
SORTOUT=  FILE1.SALIDA.D1%%ODATE          
          DISP=(NEW,CATLG,DELETE),
          DCB=(RECFM=FB,LRECL=272)   
SORT FIELDS=(1,18,CH,A,            
            78,10,CH,A,                                       
            88,4,CH,A, 
            116,5,PD,A,                                       
            210,2,CH,A) 
INCLUDE COND=((58,4,CH,EQ,C'CAJE',OR,
               58,4,CH,EQ,C'TPV ',OR,
               58,4,CH,EQ,C'TERM'),AND,
              121,1,CH,EQ,C'A')

Y listo. ¿Qué hemos escrito? Como secciones de SyncSort donde debemos colocar archivo de entrada, archivo de salida, condiciones de SORT y condiciones de INCLUSIÓN. Hay otras, estas nos sirven para este problema.

¿Qué más? Noten la estructura para la sección SORT: <pos>,<tamaño>,<formato>,<Asc|Desc> como en 88,4,CH,A, que quiere decir “posición 88, cuatro bytes, formato CHAR, de forma Ascendente o 116,5,PD,A, que quiere decir “posición 116, 5 bytes, formato decimal empaquetado (o packet decimal), ascendente.

Para la sección INCLUDE, tenemos un formato parecido, pero con EQ para hacer igualdades y una combinación tipica de OR y de AND, que es perfectamente posible, lo que hace de SynSort una herramienta muy poderosa. Este código en algún lenguaje de programación como COBOL se vería así:

IF  (CANAL EQUAL 'CAJE' OR 
     CANAL EQUAL 'TPV ' OR 
     CANAL EQUAL 'TERM') AND (ESTADO EQUAL 'A') 
...

En JCL

Entonces, el STEP en un JOB JCL correctamente formado se vería así:

//STEPNAME1 EXEC  PGM=ICEMAN,COND=(4,LT)                        
//SORTIN   DD DSN=FILE1.ENTRADA.D1%%ODATE,DISP=SHR
//SORTOUT  DD DSN=FILE1.SALIDA.D1%%ODATE,        
//            DISP=(NEW,CATLG,DELETE),UNIT=3390,               
//            SPACE=(CYL,(200,100),RLSE),                      
//            DCB=(RECFM=FB,LRECL=272,BLKSIZE=0,DSORG=PS)      
//SYSOUT   DD SYSOUT=*                                         
//SYSPRINT DD SYSOUT=*                                         
//SYSIN    DD                                                 
  SORT FIELDS=(1,18,CH,A,78,10,CH,A,
               88,4,CH,A,116,5,PD,A,
               210,2,CH,A)                                       
  INCLUDE COND=((58,4,CH,EQ,C'CAJE',OR,
                 58,4,CH,EQ,C'TPV ',OR,
                 58,4,CH,EQ,C'TERM'),AND,
                 121,1,CH,EQ,C'A')                               
  END  
//*

¡Solucionado!

Nótese que llamamos a ICEMAN quien en entornos Mainframe como en el que trabajo, resuelve contra el nombre del utilitario que esté realmente instalado. En mi caso, es el SyncSort el utilitario que se ejecutará.

19040-tongue
Lo intentaré.

Nos vemos en la red.

Anuncios

2 comentarios sobre “SyncSort: Filtrar y ordenar un archivo por JCL

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s