Teradata Tools and Utilities (TTU’s) para Ubuntu

10 julio \10\UTC 2017

Hasta ahora las Teradata Teradata Tools and Utilities (TTU’s) para linux sólo se podían instalar “oficialmente” en distribuciones Redhat (y sus respectivas Fedora, CentOS, etc…) o en SuSE (también OpenSuSE). Este paquete de instalación está basado en paquetes “.rpm”.

A partir de la versión 16.10 aparece un nuevo paquete de instalación apto para Ubuntu (basado en paquetes “.deb”), con lo que las TTU’s pueden ser instaladas fácilmente en Ubuntu y, en teoría, en cualquier distribución basada en Debian.

Nota: De momento no pienso instalarlas en mi eee PC con Lubuntu. (Aunque, ¿quién sabe?…)

Saludos.

Carlos.

 

 

Anuncios

Lubuntu 16.04 en eee PC

3 julio \03\UTC 2017

El viejo eee PC que tenía La Parte Contraria andaba arrinconado por casa. El Windows 7 que traía como sistema operativo se había ido degradando hasta el punto de convertirlo prácticamente en inutilizable. El cacharro literalmente se arrastraba. Además, había sido olvidado tras la llegada de un nuevo chico más guapo: el iPad.

Así que, ¿qué se me ocurrió un domingo por la mañana? pues instalarle un Linux. Estuve mirando opciones, y tras descartar alternativas, me decidí por Lubuntu (y eso que no soy yo muy de Debian/Ubuntu…), pero tras investigar un poco, me pareció la mejor opción de entre todos los linux ligeros.

Primer asunto: el eee PC no tiene CD, por lo que hay que crear un USB ‘bootable‘. Y entrar en la BIOS para alterar el orden de arranque y que reconozca el USB como primera unidad. También necesité el ISO de Lubuntu 16.04, que me bajé de su “site“.

Para crear el USB ‘bootable‘ utilicé rufus, aunque no todo salió a la primera: los primeros intentos acabaron con repetidos “NO DEFAULT or UI configuration directive found.”. Aquí fue ensayo y error: diferentes versiones de rufus, cambios de USB y diferentes formateos (a mí me funcionó formatear con FAT16).

Tras por fin conseguir arrancar desde el USB comencé con la instalación. Pero todo fueron problemas (arrancar sin entorno gráfico, por ejemplo) que me hicieron tener que repetirla hasta tener éxito únicamente cuando hice la instalación con una conexión a internet abierta.

En esta instalación se accedía a los repositorios y se bajaban e instalaban versiones de los programas y librerías más actualizadas de las de la propia ISO.

Aunque, tras terminar por fin la descarga e instalación, al ir a hacer el primer “login” en la ventana de conexión, ésta volvía a aparecer una y otra vez sin que me dejara acceder al escritorio. Tras la consiguiente investigación (en init 3), descubrí que en el directorio “home” de mi usuario el fichero .Xauthority pertenecía a “root” y no a mí. “chown” al canto y a otra cosa.

Finalmente:

He de decir que estoy sorprendidísimo con el rendimiento. El cacharrín (un Atom con 1GB de RAM) va estupendamente bien. Nada que ver con la desesperante lentitud del Windows 7.

La navegación por internet va estupendamente (siempre y cuando no haya demasiado javascript) y en general el uso es magnífico (de hecho, estoy escribiendo esto con él). Incluso me atrevo con ‘pelis’ con el vlc que ni soñaría poder ver en el Windows.

Además, dispone de 250GB de disco duro y lector de tarjetas SD, y puede funcionar horas sólo con la batería. Creo que va a ser el accesorio ideal para las actividades fotográficas de las vacaciones de este verano, que me huelo yo que van a ser unas pocas…

En resumen: tengo juguete para una temporada…

Saludos.

Carlos.


zypper y la actualización obstinada.

12 enero \12\UTC 2017

Software Updates” en mi openSuSE 42.1 Leap me avisaba de una actualización pendiente:

“openSuSE-2016-1453 Security update for Chromium”

Pero cada vez que intentaba la actualización se producía un fallo y me indicaba que los detalles del problema estaban en el “detailed report“. Report que, por otra parte, fui incapaz de encontrar. Y así una y otra vez.

Así que, harto del dichoso mensajito de error, me fui a la documentación: zypper.

Gestión de actualizaciones:
...
patch                   Instalar los parches necesarios.

Con esto:

carlos@OpenSuSE42:~> sudo zypper patch
root's password:
Cargando datos del repositorio...
Leyendo los paquetes instalados...
Resolviendo dependencias de paquete...

Problema: patch:openSUSE-2016-1453-1.noarch está en conflicto con chromium.x86_64 < 55.0.2883.75-99.2 
          proporcionado por chromium-54.0.2840.100-91.1.x86_64 
 Solución 1: instalar chromium-55.0.2883.75-99.2.x86_64 (con cambio de proveedor) http://packman.links2linux.de -->  openSUSE
 Solución 2: no instalar patch:openSUSE-2016-1453-1.noarch

Choose from above solutions by number or cancel [1/2/c] (c): 1
Resolviendo dependencias...
Resolviendo dependencias de paquete...

The following application is going to be installed:
  Chromium

The following 3 NEW packages are going to be installed:
  libre2-0 libsnappy1 libwebpdemux1

The following NEW patch is going to be installed:
  openSUSE-2016-1453

The following package is going to be REMOVED:
  chromium-ffmpeg

The following package is going to be upgraded:
  chromium

1 package to upgrade, 3 new, 1 to remove.
Tamaño total de descarga: 50,3 MiB. Ya en caché: 0 B. Después de la operación, se liberarán 900,2 KiB.
¿Desea continuar? [s/n/? mostrar todas las opciones] (s): s
Recuperando package libsnappy1-1.1.3-1.1.x86_64            (1/4),  19,8 KiB ( 33,0 KiB desempaquetado)
Recuperando: libsnappy1-1.1.3-1.1.x86_64.rpm ..................................[TERMINADO (1,9 KiB/s)]
Recuperando package libre2-0-20161101-2.1.x86_64           (2/4), 143,4 KiB (411,9 KiB desempaquetado)
Recuperando: libre2-0-20161101-2.1.x86_64.rpm ...............................[TERMINADO (286,7 KiB/s)]
Recuperando package libwebpdemux1-0.4.3-7.1.x86_64         (3/4),  13,8 KiB ( 14,1 KiB desempaquetado)
Recuperando: libwebpdemux1-0.4.3-7.1.x86_64.rpm ...........................................[TERMINADO]
Recuperando package chromium-55.0.2883.75-99.2.x86_64      (4/4),  50,1 MiB (193,3 MiB desempaquetado)
Recuperando: chromium-55.0.2883.75-99.2.x86_64.rpm ..........................[TERMINADO (610,3 KiB/s)]
Buscando conflictos de archivos: ..........................................................[TERMINADO]
(1/4) Instalando: libsnappy1-1.1.3-1.1.x86_64 .............................................[TERMINADO]
(2/4) Instalando: libre2-0-20161101-2.1.x86_64 ............................................[TERMINADO]
(3/4) Instalando: libwebpdemux1-0.4.3-7.1.x86_64 ..........................................[TERMINADO]
(4/4) Instalando: chromium-55.0.2883.75-99.2.x86_64 .......................................[TERMINADO]
carlos@OpenSuSE42:~> 

Una vez hecho esto, la famosa actualización “openSuSE-2016-1453 Security update for Chromium” no me ha vuelto a molestar…

He aquí una pequeña magia de zypper: te detecta los problemas, te indica las soluciones a elegir y ejecuta la que tú le digas.

Saludos.

Carlos.


CentOS 6.8

2 diciembre \02\UTC 2016

Tenía el servidor CentOS un poco descuidado, así que he hecho la actualización a 6.8 (nada de 7, ni ahora ni en un futuro cercano).

CentOS 6.8

Y, por supuesto, seguimos con gnome 2.

Saludos.

Carlos.


OpenSuSE 42.2

24 noviembre \24\UTC 2016

Desde hace un tiempo vengo utilizando openSuSE 42.1 como mi distribución Linux “personal” (en el trabajo uso otras, empezando por SLES y siguiendo con inevitables Windows). Además, estoy usando kde. Yo, que siempre he sido un fan de gnome… (pero es que el gnome 3 no me entra).

Encuentro la distribución muy elegante y bastante fácil de usar, aunque al principio me costó un poco configurar el ‘desktop‘, los paneles y demás…

openSuSE 42.1

El caso es que acaba de liberarse la versión 42.2 así que habrá que ponerse a actualizar…

Saludos.

Carlos.


Cargar campos “COBOL Comp-3 (Packed Decimals)” con Multiload.

6 octubre \06\UTC 2016

Teradata permite conexión directa entre entornos “mainframe” y sistemas Teradata mediante conexiones FICON. Esto significa que se pueden instalar las TTU’s en dichos “mainframes” y cargar directamente datos desde ficheros que existan allí sin necesidad de hacer ftp’s a entornos UNIX, Linux o Windows, con lo engorroso que puede ser el ftp en sí, por no hablar de las conversiones EBCDIC / ASCII…

El problema viene cuando los ficheros en cuestión contienen campos “Comp-3” (Computational-3), también llamados “packed decimals“.

Pero ¿qué son exactamente estos “Comp-3”?

“Comp-3” es una forma de almacenamiento de datos numéricos en COBOL en formato BCD (binary coded decimal). El BCD almacena numeros en formato DECIMAL y,como los números decimales van de 0 a 9, caben en cuatro bits (es lo que se llama un ‘nibble‘) con lo que en un byte caben dos números (ej.: byte 11, en bin 00010001 => almacena el 11 decimal). Esto hace que los datos ocupen la mitad de lo que ocuparían como caracteres (un byte por cada dígito).

A esto hay que sumarle que el último nibble (el menos significativo) se guarda para el signo, y se notan como “C” hex para positivos, “D” hex para negativos y “F” hex para “unsigned“. Así el número 1000 se guardará en tres bytes como 01 00 0C.

Para calcular lo que ocupará un número en Comp-3 bastará con contar sus dígitos, sumarle uno para el signo y dividir por dos. En caso de que el resultado no sea entero se redondea hacia arriba. En nuestro ejemplo anterior: 1000 => (4+1)/2 = 2,5 y se redondea a 3.

OK, pero ¿cómo se guardan los decimales? pues NO se guardan, sino que se resuelven con los ‘PICTURES’ (PIC). Siguiendo con nuestro ejemplo, si el campo es definido como ‘PIC S9(4)’, será 1000, pero si lo definimos como PIC S9(2)V99 se convertirá en 10.00.

Vale. Ahora ya sabemos lo que son pero ¿cómo los cargamos con Multiload?

Un poco de calma. Antes vamos ver cómo nosotros linuxeros y windowseros hemos adquirido vicios a la hora de cargar ficheros, en este caso con multiload, y más tarde nos daremos cuenta de que las cosas son más fáciles de lo que parecen…

¿Qué hacemos normalmente para cargar ficheros? Pues normalmente elegimos entre ficheros “TEXT” (de registros de longitud fija) y ficheros “VARTEXT” (registros de longitud variable con separadores de campo). Y a la hora de definir el LAYOUT definimos generalmente campos CHAR() o VARCHAR() donde colocar la información de los campos del fichero, que suelen llegar en forma de texto (ASCII, o UTF8, o lo que sea…). El objeto de esto es que el LAYOUT guarde la información en texto y que los cambios de tipo (CASTs) se resuelvan a la hora de la inserción final en las tablas.

Esto funciona generalmente muy bien, pero hace que olvidemos cómo funciona el multiload (en realidad el dataconector o “PIOM” para los más viejos).

Vamos a ver un ejemplo:

Tenemos un fichero Prueba.txt de longitud fija (4 bytes por registro) que tiene:

1UNO
2DOS

Tenemos una tabla para cargar dicho fichero:

 BTEQ -- Enter your SQL request or BTEQ command: 
DROP TABLE CARLOS.PRUEBA_TEXT;
CREATE MULTISET TABLE CARLOS.PRUEBA_TEXT
   (
      ID_N  INTEGER NOT NULL,
      C_TXT CHAR(3)
   )
;

 *** Failure 3807 Object 'CARLOS.PRUEBA_TEXT' does not exist.
                Statement# 1, Info =0 
 *** Total elapsed time was 1 second.


 BTEQ -- Enter your SQL request or BTEQ command: 


 *** Table has been created. 
 *** Total elapsed time was 1 second.

Creamos el script de multiload:

.LOGTABLE CARLOS.PRUEBA_TEXT_LOG;

.LOGON MyTdpId/carlos,MyPassword;

.BEGIN IMPORT MLOAD TABLES CARLOS.PRUEBA_TEXT;

.DML LABEL INSERTAR_PRUEBA_TEXT;
INSERT INTO CARLOS.PRUEBA_TEXT VALUES(
	:id_n,
	:c_txt)
;

.LAYOUT INSERTAR;
	.FIELD id_n    1 CHAR(1);
	.FIELD c_txt   * CHAR(3);

.IMPORT INFILE Prueba.txt FORMAT TEXT
 LAYOUT INSERTAR
  APPLY INSERTAR_PRUEBA_TEXT;

.END MLOAD;

.LOGOFF;

Y lo ejecutamos. Acaba (sin errores):

...
     Target table 1: CARLOS.PRUEBA_TEXT
     Number of Rows        Error Table Name
     ====================  ==================================================
                        0  CARLOS.ET_PRUEBA_TEXT
                        0  CARLOS.UV_PRUEBA_TEXT

**** 19:19:13 UTY0817 MultiLoad submitting the following request:
     BEGIN TRANSACTION;
**** 19:19:13 UTY0817 MultiLoad submitting the following request:
     USING Ckpt(VARBYTE(1024)) INS CARLOS.PRUEBA_TEXT_LOG (LogType, Seq,
     MLoadCkpt)VALUES(140, 1, :Ckpt);
**** 19:19:13 UTY0817 MultiLoad submitting the following request:
     INS CARLOS.PRUEBA_TEXT_LOG (LogType, Seq) VALUES (125, 1)
**** 19:19:13 UTY0817 MultiLoad submitting the following request:
     END TRANSACTION;
**** 19:19:13 UTY0822 MultiLoad processing complete for this MultiLoad import
     task.
     ========================================================================
     =                                                                      =
     =          MultiLoad Task Complete                                     =
     =                                                                      =
     ========================================================================
**** 19:19:13 UTY1024 Session modal request, 'SET
     QUERY_BAND='UTILITYNAME=MULTLOAD;' UPDATE FOR SESSION;', re-executed.
     ========================================================================
     =                                                                      =
     =          Processing Control Statements                               =
     =                                                                      =
     ========================================================================

0011 .LOGOFF;
     ========================================================================
     =                                                                      =
     =          Logoff/Disconnect                                           =
     =                                                                      =
     ========================================================================
**** 19:19:14 UTY6216 The restart log table has been dropped.
**** 19:19:14 UTY6212 A successful disconnect was made from the RDBMS.
**** 19:19:14 UTY2410 Total processor time used = '0.265202 Seconds'
     .       Start : 19:19:04 - THU OCT 06, 2016
     .       End   : 19:19:14 - THU OCT 06, 2016
     .       Highest return code encountered = '0'.

Si vemos lo que hemos cargado:

 BTEQ -- Enter your SQL request or BTEQ command: 
SELECT * FROM CARLOS.PRUEBA_TEXT ORDER BY 1;


 *** Query completed. 2 rows found. 2 columns returned. 
 *** Total elapsed time was 1 second.

       ID_N  C_TXT
-----------  -----
          1  UNO
          2  DOS

Todo correcto, pues. Pero vamos a cambiar un poco el script de multiload. Vamos a cambiar en el LAYOUT el campo id_n de CHAR(1) a DECIMAL(1) (que también ocupa 1 byte):

.LOGTABLE CARLOS.PRUEBA_TEXT_LOG;

.LOGON MyTdpId/carlos,MyPassword;

.BEGIN IMPORT MLOAD TABLES CARLOS.PRUEBA_TEXT;

.DML LABEL INSERTAR_PRUEBA_TEXT;
INSERT INTO CARLOS.PRUEBA_TEXT VALUES(
	:id_n,
	:c_txt)
;

.LAYOUT INSERTAR;
	.FIELD id_n    1 DECIMAL(1);
	.FIELD c_txt   * CHAR(3);

.IMPORT INFILE Prueba.txt FORMAT TEXT
 LAYOUT INSERTAR
  APPLY INSERTAR_PRUEBA_TEXT;

.END MLOAD;

.LOGOFF;

Una nueva ejecución (otra vez sin errores):

     Target table 1: CARLOS.PRUEBA_TEXT
     Number of Rows        Error Table Name
     ====================  ==================================================
                        0  CARLOS.ET_PRUEBA_TEXT
                        0  CARLOS.UV_PRUEBA_TEXT

**** 19:22:08 UTY0817 MultiLoad submitting the following request:
     BEGIN TRANSACTION;
**** 19:22:08 UTY0817 MultiLoad submitting the following request:
     USING Ckpt(VARBYTE(1024)) INS CARLOS.PRUEBA_TEXT_LOG (LogType, Seq,
     MLoadCkpt)VALUES(140, 1, :Ckpt);
**** 19:22:08 UTY0817 MultiLoad submitting the following request:
     INS CARLOS.PRUEBA_TEXT_LOG (LogType, Seq) VALUES (125, 1)
**** 19:22:08 UTY0817 MultiLoad submitting the following request:
     END TRANSACTION;
**** 19:22:08 UTY0822 MultiLoad processing complete for this MultiLoad import
     task.
     ========================================================================
     =                                                                      =
     =          MultiLoad Task Complete                                     =
     =                                                                      =
     ========================================================================
**** 19:22:08 UTY1024 Session modal request, 'SET
     QUERY_BAND='UTILITYNAME=MULTLOAD;' UPDATE FOR SESSION;', re-executed.
     ========================================================================
     =                                                                      =
     =          Processing Control Statements                               =
     =                                                                      =
     ========================================================================

0011 .LOGOFF;
     ========================================================================
     =                                                                      =
     =          Logoff/Disconnect                                           =
     =                                                                      =
     ========================================================================
**** 19:22:09 UTY6216 The restart log table has been dropped.
**** 19:22:09 UTY6212 A successful disconnect was made from the RDBMS.
**** 19:22:09 UTY2410 Total processor time used = '0.296402 Seconds'
     .       Start : 19:22:00 - THU OCT 06, 2016
     .       End   : 19:22:09 - THU OCT 06, 2016
     .       Highest return code encountered = '0'.

Verificamos los datos en la tabla:

 BTEQ -- Enter your SQL request or BTEQ command: 
SELECT * FROM CARLOS.PRUEBA_TEXT ORDER BY 1;


 *** Query completed. 4 rows found. 2 columns returned. 
 *** Total elapsed time was 1 second.

       ID_N  C_TXT
-----------  -----
          1  UNO
          2  DOS
         49  UNO
         50  DOS

¡Hey! ¿Qué son ese 49 y ese 50? Pues ni más ni menos que los códigos decimales ASCII correspondientes a los dígitos ‘1’ y ‘2’. Al definir el campo (.FIELD) como DECIMAL(1) le hemos dicho que el dato que viene en el campo no es texto, sino un número, y multiload así lo hace: lee los BYTES como números y los carga en la tabla tal cual, sin interpretar el dato como la representación “en texto” de un número.

Pues sabiendo esto, y aunque no nos demos cuenta todavía, ahí está la clave para cargar los Comp-3 (Packed Decimals) en “mainframes“. La receta es fácil: si el dato numérico viene como texto (que será EBCDIC), bastará definir el .FIELD como CHAR(n) y multiload se encargará del CAST a numérico. Si por el contrario viene como “packed decimal” necesitaremos saber cuánto ocupa el campo en BYTES. En este caso también es necesario conocer el ‘PIC’ original. Así, por ejemplo:

PIC S9(4) COMP-3 => Byte size = (4 + 1) / 2 = 2.5 -> 3 bytes => .FIELD fld1 * DECIMAL(4)
PIC S9(5)V99 COMP-3 => Byte size = (5 + 2 + 1) / 2 = 4 bytes => .FIELD fld2 * DECIMAL(7,2)

Como se ve, el ‘PIC’ funciona de distinta manera que la definición de numéricos SQL: la parte entera se suma a la parte fraccionaria, mientras que en SQL la ESCALA supone el número total de dígitos, mientras que la PRECISIÓN dice cuántos de ellos son decimales.

Saludos.

Carlos.


Historial de comandos en bteq (y sql*plus) con las flechas del teclado en Linux.

8 junio \08\UTC 2016

La funcionalidad de utilizar las flechas del teclado para navegar por la historia de las sentencias ejecutadas en bteq (y en sql*plus) cuando trabajamos en entornos Windows hace que cuando nos pasamos a entornos Linux nos pase siempre esto:

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT DATE;

 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

    Date
--------
16/06/08

 BTEQ -- Enter your SQL request or BTEQ command:
^[[A

¡Arrrggg! Y siempre nos pasa. Una y otra vez.

Pero hay una solución: utilizar rlwrap, que es un ‘readline wrapper‘. Basta con buscarlo (por ejemplo aquí) e instalarlo.

La instalación es simple: descomprimir el ‘tarball‘ (.tar.gz) en un directorio de trabajo y ejecutar:

./configure 
make install

Yo lo hago como ‘root’ para evitar problemas (“no se puede crear el directorio /usr/local/share/man”).

¡Ojo! Hay que tener instaladas las librerías GNU readline y readline-devel para que el instalador no termine con error.

Una vez hecho esto, lo que suelo hacer es modificar los lanzadores de bteq y sql*plus que tengo en el escritorio sustituyendo las llamadas simples “bteq” y “sqlplus /nolog” por “rlwrap bteq” y “rlwrap sqlplus /nolog”.

A partir de ese momento tengo mis utilidades SQL de línea de comando favoritas funcionando exactamente igual que en Windows y puedo navegar por la historia de los comandos ejecutados con “flecha arriba” y “flecha abajo”.

Saludos.

Carlos.