calculer le hash du résultat d'une requête

Avec un fichier de résultats en texte, il est trivial de calculer une empreinte (hash). Par contre, pour une requête SQL, c'est beaucoup plus compliqué : le langage est surtout conçu pour afficher des résultats ligne par ligne, et calculer un hash pour l'ensemble du résultat de la requête devient bien plus difficile.

Voici une méthode qui peut fonctionner.

La requête initiale est exécutée classiquement :

select poisson_id, poisson_statut_id, matricule from poisson  where categorie_id = 1;

Cette requête va être rejouée, en calculant maintenant un hash à partir de la concaténation de tous les champs (en md5, le risque de collision est suffisamment faible pour l'autoriser dans ce cas de figure).

Nous avons d'abord besoin d'une fonction de transformation du hash en bigint (source : http://stackoverflow.com/questions/9809381/hashing-a-string-to-a-numeric-value-in-postgressql) :

create function h_bigint(text) returns bigint as $$
 select ('x'||substr(md5($1),1,16))::bit(64)::bigint;
$$ language sql;

Nous pouvons maintenant exécuter la requête :

with req as (select poisson_id, poisson_statut_id, matricule from poisson  where categorie_id = 1 )
select '1' as keyhash, md5(sum(h_bigint(md5(concat (poisson_id::text||poisson_statut_id::text||matricule::text))))::text) as hash, current_timestamp as request_date from req group by 1, request_date;

keyhash

1

hash

37cd5bcbf426883de2961c2fc7f175d6

request_date

2017-03-06 09:33:44

Nous avons calculé le hash de chaque ligne. Le total de ce hash a été calculé, (group by keyhash, colonne fictive qui contient uniquement la valeur 1).

Ainsi, si la base de données évolue, le calcul effectué sera forcément différent.