jeudi 21 mai 2015

shebang postgresql (suite)

Dans le billet précédent nous avions écarté l'usage du shebang
#/usr/bin/psql -f
car cette ligne n'est pas  un commentaire pour psql. Elle est envoyée vers le serveur pour traitement, ce qui provoque une erreur.
Tout un coup: une illumination! Et si on commençait par vider le tampon des requêtes ?
Et ça fonctionne!
Modifions le script sbpsql1x du billet précédent et sauvegardons le sous le nom sbpsql4x:

#!/usr/bin/psql -f
\set QUIET
\r
select now()
\echo
\echo 'Sera envoyé au serveur:'
\echo
\p
\echo
\echo 'Procédons:'
\echo
;

Avant de vider le tampon des requêtes (\r), nous avons défini la variable QUIET afin d'éviter le message:

Query buffer reset (cleared).

Vérifions:



Nous pouvons donc utiliser ce shebang. Le problème est que les paramètres passés au script (comme bdtest) sont en fait des arguments pour la ligne de commande psql.

Pour pouvoir passer de vrais paramètres , il est donc préférable d'utiliser exec psql comme dans le script sbpsql5x (obtenu en modifiant le script sbpsql2x):

#!/bin/bash
exec psql bdtest -f "$0"
\set QUIET 
\echo
\echo 'Tampon initial:'
\echo
\p
\echo
\r
select now()
\echo
\echo 'Sera envoyé au serveur:'
\echo
\p
\echo
\echo 'Procédons:'
\echo
;

Nous avons ajouté l'en-tête 
#!/bin/bash
Et comme de toute façon nous allons vider le tampon, la fonction
--() { :; }
est passée à la trappe car il n'est plus besoin que la ligne avec exec soit un commentaire.

Essayons le script:



Adaptons le script dépensepx du billet script psql. Appelons la nouvelle version dépensenpx:

#!/bin/bash
exec psql bdtest -v signification="$1" -f "$0"
\set QUIET
\r
\pset numericlocale
\pset border 2
\pset linestyle u
\pset footer
\set titre 'Dépenses ':signification
\pset title :titre'\n'
\set code_u
\echo
SELECT code_u
FROM utilisations
WHERE signification = :'signification'
\gset
SELECT référence, date_exec::text as date, détails, montant
FROM dépenses
WHERE code_u = :'code_u'
UNION
SELECT 'TOTAL', '', '', sum(montant)
FROM dépenses
WHERE code_u = :'code_u'
order by 1

Ce script fonctionne très bien:



Cependant ce script se termine en même temps que la commande psql.
Si nous voulons apporter certaines améliorations (utilisation de awk,envoi des messages d'erreur vers /dev/null), nous devons l'appeler à partir de dépensenp0x:

fichier=$(mktemp)
exec 7>&1
exec 1>$fichier
exec 6>&2
exec 2>/dev/null
./dépensenpx "$1"
exec 1>&7 7>&-
awk 'NR==6 {y=$0};/TOTAL/ {print y};1' $fichier
exec 2>&6 6>&-

(Toutes les explications se trouvent dans ce billet)

Ce qui donne ceci:



Avant de terminer, précisons que les tables utilisées ici ont déjà été présentées dans ce blog.
Nous avons rappelé les instructions de créations de ces tables dans le billet script psql