Pour dépister rapidement les tables qui ne balançaient pas, mon réflexe fût de bâtir une requête qui listerait toutes les tables d'un utilisateur propriétaire et pour chacune, de lancer une sous-requête qui obtiendrait le compte. Le problème, c'est qu'on ne peut pas le faire par un seul énoncé SQL. Bien que pg_tables retourne le schéma et le nom de la table, il faut contourner la limitation en écrivant une fonction utilitaire qui les concaténerait sous forme de texte pour être exécutée comme équivalent à la sous-requête qui retournerait le compte.
Sous cette forme :
SELECT schemaname, tablename, count_table_rows(schemaname, tablename) as nb_rows FROM pg_tables WHERE tableowner='code18' ORDER BY schemaname, tablename
La définition de la fonction PL/pgSQL de ma solution :
CREATE OR REPLACE FUNCTION count_table_rows (
"schema_name" name,
"table_name" name
)
RETURNS integer AS
$body$
DECLARE nb_rows INTEGER;
BEGIN
EXECUTE 'SELECT COUNT(*) FROM ' || schema_name || '.' || table_name INTO nb_rows;
RETURN nb_rows;
END;
$body$
LANGUAGE 'plpgsql'
Vous remarquerez que j'ai déclaré les paramètres en utilisant le type "name" plutôt que "text" ou "varchar". C'est qu'en testant la fonction sur deux serveurs qui faisaient tourner des versions différentes de Postgres, l'un procédait à un cast implicite à partir d'un varchar, l'autre d'un text. Pour que la fonction soit compatible dans les deux cas sans nécessiter de conversion, j'ai vérifié quels étaient les types des valeurs retournées par pg_tables et j'ai ajusté la fonction avec des paramètres de type name : SELECT column_name, data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'pg_tables'
Aucun commentaire:
Publier un commentaire