miércoles, marzo 31, 2010

Mi blog y el lucro

Yo no lucro con este blog (aún), de hecho el índice de visitas no es ni siquiera considerable, y debo conformarme con los escasos 3 o 4 lectores habituales que pasan por aquí.

Si usted busca lucrar usando mi blog como trampolín, ya sea respondiendo un artículo promocionando sus servicios, o simplemente poniendo un enlace a su sitio Web, por lo menos tenga la decencia de solicitar mi autorización. Es más, incluso puede que les otorgue un espacio exclusivo.

Cualquier publicidad no solicitada ni autorizada será eliminada. Fácil y bonito, para bien o para mal, este es MI blog, por lo tanto se juega con MIS reglas.

Y si no le gusta tomo mi pelota y me la llevo a mi casa :-)

jueves, marzo 25, 2010

Construcción masiva de consultas SQL desde una consulta SQL

Nota: Como ha sido habitual desde mis últimos artículos, y para que los que misteriosamente me leen sigan creyendo que trabajo en mis horas laborales comprendan lo difícil de las labores que desempeño, he aquí otro problema técnico y su correspondiente solución.
Nuevamente, si no le interesa el tema, simplemente pase a saludar, y será retribuido con mi eterno agradecimiento temporal.

Supuesto a priori: El lector tienen mediano entendimiento y nociones de SQL.

Problema: Se tiene cierta información distribuida en 2 tablas distintas dentro de una base de datos y se desea hacer un cruce de esta, actualizando los datos de la tabla 1 con ciertos datos de la tabla 2.
En el caso particular de la problemática enfrentada, se tiene la codificación estándar de enfermedades y se desea agregar una sup-clasificación que permita agruparlas según ciertos criterios, también estandarizados.

Solución: Lo más lógico sería hacer un update utilizando los datos de un select. El problema es que la consulta arroja más de un resultado.
Por ello se debe recurrir a la segunda opción, que es construir los updates necesarios a partir de los resultados del select que entrega la información que se va a actualizar.

Para ello:
  1. Rescatar la información desde las tablas correspondientes hacia un archivo, ejecutando:
    psql -h servidorbasedatos -U usuariobasedatos basedatos -c 'select tipodiagnostico.idtipodiagnostico, care_icd10_bg.diagnosis_code from care_icd10_bg, tipodiagnostico where substring(care_icd10_bg.diagnosis_code, 1, 3) between tipodiagnostico.rangoini and tipodiagnostico.rangofin' -t > archivo_resultados.txt
    Notar la sutilezas:
    • -c indica al comando psql que ejecute la consulta SQL escrita entre las comillas simples.
    • -t indica que el resultado de la ejecución sea presentado sin las cabeceras que indican los nombres de las columnas involucradas.
    • Dentro de la consulta la llamada a la función substring se asegura que los códigos de diagnóstico se encuentren dentro de los rangos expresados en la tabla tipodiagnostico. Al respecto, los códigos de diagnóstico se representan con 3 caracteres . Hay casos particulares en que este código va precedido por un punto y otro código numérico, o un signo de suma, o un asterisco. dado que los rangos están expresados sólo en 3 caracteres, es necesario usar la función substring.
  2. Construir los updates que sea necesario ejecutar. Para ello se debe ejecutar el toxi-comando:
    cat archivo_resultados.txt | awk -v q="'" -F'|' '{ gsub(/[[:space:]]*/,"",$1); gsub(/[[:space:]]*/,"",$2); print "update care_icd10_bg set type =", q $1 q, " where diagnosis_code=", q $2 q, "\;" }' > archivo_consultas.sql
    Las sutilezas de esta maravilla de la concatenación y del copiar-pegar:
    • -v q="'" le indica al comando awk que el caracter comilla simple (que tantos dolores de cabeza nos da cuando lo queremos usar dentro del awk), sea representado por una q. La otra solución es usar \x27 como caracter al escribirla, pero al menos a mi me resulta más clara la q.
    • -F'|' le indica al comando awk que el caracter pipe (|) es el separador de campos, para cada línea a procesar. Esto es debido a que la salida del comando psql entrega resultados como:
      207 | A01
      207 | A01.0
      207 | A01.1
    • Dentro de la secuencia de instrucciones awk, la función gsub(/[[:space:]]*/,"",$1); aplicada sobre $1 y $2 se encargará de eliminar los espacios sobrantes en $1 y $2 (207 y A01 en el ejemplo).
    El resultado de la ejecución de este comando es algo como:
    update care_icd10_bg set type = '207' where diagnosis_code= 'A01' ;
    update care_icd10_bg set type = '207' where diagnosis_code= 'A01.0' ;
    update care_icd10_bg set type = '207' where diagnosis_code= 'A01.1' ;
  3. Ejecutar la consultas recién creadas, ejecutando:
    psql -h servidorbasedatos -U usuariobasedatos basedatos -f archivo_consultas.sql
  4. Y esperar. Utilizando la base de datos de códigos de diagnósticos de http://www.care2x.com/ , se deben actualizar del orden de 13 mil registros lo que en una máquina medianamente actualizada (Athlon x64, 4GB de RAM) se demora alrededor de 2 minutos.

Y eso sería. Que les vaya bonito.

martes, marzo 23, 2010

No funciona el ssh -Y (X11 forwarding)

Nota al lector casual: Si su interés no es netamente técnico o si no entiende el título del artículo, se le recomienda pasar a saludar.

Problema: Le dieron acceso a un servidor vía SSH y necesita abrir un programa, digamos el navegador Firefox para configurar algo de manera local (a ese servidor). Por mucho que lo intente y que setee las variables de ambiente (emulando las de otras máquinas donde si funciona) sigue sin funcionar:
[root@localhost ~]# firefox
Error: no display specified
[root@localhost ~]# export DISPLAY=localhost:10.0
[root@localhost ~]# firefox
Error: cannot open display: localhost:10.0
[root@localhost ~]# firefox --no-remote
Error: cannot open display: localhost:10.0

Solución: Ejecutar la conexion ssh de la siguiente manera
ssh -XYv root@ip.servidor.ajeno
y analizar la salida
... muchas líneas ...
debug1: Requesting X11 forwarding with authentication spoofing.
debug1: Sending environment.
debug1: Sending env LANG = es_CL.ISO-8859-1
debug1: Remote: No xauth program; cannot forward with spoofing.

Interesante: Parece que falta algo.
Así que procedemos a conectarnos nuevamente y a instalar el paquete xauth.

Nos desconectamos y tratamos nuevamente.
Debiera funcionar.

lunes, marzo 22, 2010

Haciendo un respaldo total de las bases de datos PostgreSQL

Nota para el lector casual: Si su interés no es técnico o si el título de este artículo le resulta familiar al arameo antiguo entonces le recomiendo solamente pasar a saludar :-)

Problema: Es necesario realizar un respaldo total de todas las bases de datos que existen en una máquina. Estas bases de datos están sostenidas sobre PostgreSQL.

Solución:
  1. Acceder como root
  2. Habilitar el acceso en modo confianza (trust) para las conexiones locales. Para ello bastará editar el archivo pg_hba.conf , buscar la línea que se refiere a 127.0.0.1 y editarla para que quede como:
    host all all 127.0.0.1/32 trust
    Si no sabemos donde puede estar este archivo, lo podemos encontrar ejecutando:
    find / | grep pg_hba.conf
    lo que nos entregará la ruta completa hacia el archivo.
  3. Reiniciar el servicio de PostgreSQL. Normalmente esto resulta con alguno de estos comandos:
    service postgresql restart
    o bién
    /etc/init.d/postgresql restart
    Eventualmente, dependiendo de la distribución de Linux usada, y del PostgreSQL instalado, el nombre del servicio puede variar. Ante la duda vayan a /etc/init.d y ejecuten un:
    ls p*
    lo que listará todas las opciones de servicios que empiecen con p.
  4. Crear una ruta donde guardar los respaldos, por ejemplo una carpeta sql
    mkdir sql
  5. Cambiar a la carpeta recien creada
    cd sql
  6. Ejecutar el toxi-comando (en una sola línea):
    psql -lt -U postgres | awk '{ print $1 }' | xargs -i pg_dump -h localhost -U postgres -cO -Ft -f `date +%Y%m%d%H%M%S`_{}.tar -d {}
    Esto creará un archivo de extensión .tar con prefijo fecha_actual_ seguidi por el nombre de la base de datos.

Es recomendable que trás hacer el respaldo de la base de datos, restauren la línea del archivo pg_hba.conf que cambiaron a su estado anterior (posiblemente en vez de trust sea md5 o sameuser) y reinicien PostgreSQL (ver paso 3).

La restauración de estos archivos se hace con pg_restore, pero eso lo dejamos para otro día. Si su urgencia es mayor ejecuten el comando:
man pg_restore
o bién
pg_restore --help

Eso sería por el día de hoy. Que les vaya bonito.

martes, marzo 02, 2010

Como resetear un Califont Junkers

Con el terremoto uno de los damnificados fue mi califont que debido a su encendido electrónico, derechamente dejó de encender.

En un comienzo lo atribuímos a que por un tema de seguridad cortamos el suministro de gas hacia el califont. De todas formas llamamos a Junkers para consultar cual podía ser el problema. La amable señorita que atendió la llamada me explicoó que con el corte de luz los califont Junkers de encendido electrónico se bloquean.

Para desbloquearlo hay que seguir los siguiente pasos:
  1. Poner el interruptor del califont en su posición de apagado (normalmente presionando un botón blanco al lado de la perilla giratoria).
  2. Desenchufar el califont de la toma de electricidad.
  3. Esperar 10 minutos
  4. Enchufar el califont a la toma de electricidad.
  5. Encender el califont.
  6. Dar el agua 3 segundos (no más que eso)
  7. Repetir el paso anterior 2 veces (total 3 veces)
Eso debiera resetear el califont, y este debiera volver a encender.

Personalmente hubiera preferido un botón de reseteo (pequeñito oculto debajo de la carcaza), o una combinación de teclas tipo Control+Alt+Suprimir .

Si el califont siguiera sin encender, como me sucedió a mi, la salida es llamar a un técnico de Junkers y coordinar una visita. Debo que decirlo, no me salió barata la gracia, pero aparte de restaurarlo aprovecharon de hacerle la muy necesaria limpieza que correspondía después de 2 años de uso.