Cargando ceros binarios en un campo “packed decimal” como nulos.

Siguiendo con los campos “COBOL Comp-3 (Packed Decimals)” y Multiload, se nos ha presentado un problema a la hora de cargar ficheros en un HOST IBM.

El asunto consistía en que había un campo “packed decimal” con tipo DECIMAL(9,0). Siguiendo lo visto aquí, hicimos un script:

.LAYOUT DATAIN;
  .FIELD field_1
  ...
  .FIELD field_n * DECIMAL(9,0);
  ...

Pero es que, además, nos dijeron que deberíamos cargar un NULL si el campo “llegaba a cero”.

OK. No problem. Hay dos alternativas. En la definición del “layout” haciendo:

.LAYOUT DATAIN;
  ...
  .FIELD field_n * DECIMAL(9,0) NULLIF field_n=0;
  ...
  
o, sin el NULLIF del LAYOUT, resolviendo en la parte del INSERT:

   INSERT INTO ...
   ...
   COLUMN_N,
   ...
   )VALUES(
   ...
   NULLIFZERO(:field_n),
   ...
   );

Los problemas se presentaron cuando comenzaron a aparecer errores en las ejecuciones de multiload.
Cuando se utilizaba la opción 1 (NULLIF en el LAYOUT) multiload se quejaba con:

"UTY2203 Unable to process input data: INVALID DECIMAL DATA DURING COMPARISON."

Y cuando se usaba la opción 2 (NULLIFZERO) las filas iban a la tabla de errores ET_ reportando errores:

2679 "The format or data contains a bad character."

Tras los lógicos primeros momentos de estupefacción, echamos un vistazo al fichero con un editor hexadecimal y vimos que en el campo problemático no estaba llegando un “packed decimal” cero, sino que estaban llegando cinco bytes ceros binarios.
Ahí está el problema. Según vimos aquí, el formato de un “packed decimal” incluye un último “nibble” para el signo (C, D, o F), y en nuestro caso el signo brilla por su ausencia… Multiload simplemente no puede hacer el CAST(), pues lo que le hemos dicho que es un “packed decimal” no lo es.

Así que nos pusimos a pensar y pensar, y finalmente dimos con una solución.

Si duplicamos el campo con dos tipos diferentes (el DECIMAL(9,0) y uno previo auxiliar como BYTE(5)), tratando el campo ‘bueno’ (DECIMAL(9,0)) con un NULLIF sobre el campo ‘BYTE(5)’ se evita el CAST problemático y el multiload funciona OK. Hay que tener en cuenta que en el LAYOUT necesitamos fijar explícitamente la posición del campo en el fichero (en el ejemplo, posición nnn).

En el .LAYOUT hacemos:

      .FIELD field_n_b nnn BYTE(5);
      .FIELD field_n   nnn DECIMAL(9,0) NULLIF field_n_b='0000000000'xB;

En el INSERT no hace falta el NULLIFZERO() porque el campo ya fue tratado en el LAYOUT:

Esto funciona también en entornos Linux/UNIX/Windows.

Si tenemos una tabla:

CREATE MULTISET TABLE CARLOS.PRUEBA_NULLIF_DATE
   (
      ID_N   INTEGER NOT NULL,
      D_DATE DATE
   )
;

Y un fichero en el el campo de fecha puede traer ceros binarios (10 bytes 0x00, representados por · ),

12016-11-07
22016-11-08
3··········          
42016-11-09

podemos cargarlo haciendo un script multiload:

.DATEFORM ANSIDATE; 

.LOGTABLE CARLOS.PRUEBA_NULLIF_DATE_LOG;

.LOGON MY_DB/carlos,**********;

.BEGIN IMPORT MLOAD TABLES CARLOS.PRUEBA_NULLIF_DATE;

.DML LABEL INSERTAR_PRUEBA_NULLIF_DATE;
INSERT INTO CARLOS.PRUEBA_NULLIF_DATE VALUES(
	:id_n,
	:d_date)
;

.LAYOUT INSERTAR;
	.FIELD id_n     1 CHAR(1);
        .FIELD d_date_b 2 BYTE(10);
	.FIELD d_date   2 DATE NULLIF d_date_b = '00000000000000000000'xB;

.IMPORT INFILE .\Ficheros\Prueba_NULLIF_DATE.txt FORMAT TEXT
 LAYOUT INSERTAR
  APPLY INSERTAR_PRUEBA_NULLIF_DATE;

.END MLOAD;

.LOGOFF;

Lo que subyace es el hecho de que el NULLIF se resuelve con el FIELD tipo BYTE anterior ANTES de hacer el CAST del campo sobre el que se actúa, con lo que ni siquiera se hace el CAST y no falla en la conversión de tipos.

Saludos.

Carlos.

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 )

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 )

Google+ photo

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

Conectando a %s

A %d blogueros les gusta esto: