Gráfico de llaves foráneas
Ayer, uno de los sistemas de monitorización de red que utilizamos en la universidad NAV - Network Administration Visualized tuvo problemas con una de las consultas DELETE que mandaba a la base de datos PostgreSQL que utiliza.
La base de datos que utiliza NAV es un poco complicada, con muchas claves foráneas, triggers y rules para garantizar la integridad de los datos. En el proceso de busqueda del fallo, una de las cosas que queria tener era una relación de todas las tablas y sus claves foráneas para hacerme una idea de como las diferentes tablas estaban relacionadas entre si. En una base de datos pequeña y sin muchas relaciones esto no seria un problema pero a medida que la cosa crece, se va complicando rápidamente.
Necesitaba algo rápido y fácil que me diera esta información sin tener que instalar ningún programa adicional, además solamente me interesaba la relación de claves foráneas y no una representación completa de la base de datos.
Y como no hay nada más rápido que una consola con psql y una consulta SQL apropiada, me puse manos a la obra para generar una consulta SQL que me generase una salida que pudiese utilizar con Graphviz, para crear un gráfico con las relaciones. En debian/ubuntu, Graphviz se puede instalar con: sudo apt-get install graphviz
La consulta que se me ocurrio es la siguiente:
SELECT DISTINCT ON ('"' || fkey_table || '" -> "' || pkey_table || '(' || pkey_column || ')";')
'"' || fkey_table || '" -> "' || pkey_table || '(' || pkey_column || ')";'
FROM
(
SELECT a.constraint_name,
b.column_name AS fkey_column,
b.table_name AS fkey_table
FROM information_schema.referential_constraints a
INNER JOIN information_schema.key_column_usage b ON a.constraint_name = b.constraint_name
) AS fkey_constraints
INNER JOIN
(
SELECT a.unique_constraint_name,
b.column_name AS pkey_column,
b.table_name AS pkey_table,
a.constraint_name
FROM information_schema.referential_constraints a
INNER JOIN information_schema.constraint_column_usage b ON a.unique_constraint_name = b.constraint_name
) AS pkey_constraints
ON fkey_constraints.constraint_name = pkey_constraints.constraint_name;
Esta consulta te devuelve una lista con lineas del tipo:
"accountalertqueue" -> "account(id)";
"accountalertqueue" -> "account(id)";
"accountalertqueue" -> "alertq(alertqid)";
"accountalertqueue" -> "alertsubscription(id)";
"accountgroup_accounts" -> "account(id)";
"accountgroup_accounts" -> "accountgroup(id)";
...........
"type" -> "vendor(vendorid)";
"vlan" -> "nettype(nettypeid)";
"vlan" -> "org(orgid)";
"vlan" -> "usage(usageid)";
En donde el primer termino antes del simbolo “->” es el nombre de una tabla en vuestra base de datos y el segundo una clave foránea (tabla(columna)) definida en esta tabla.
Ahora lo único que nos queda es copiar y pegar el resultado en un editor de texto, añadirle un par de lineas extras, grabarlo en un fichero y ejecutar Graphviz sobre el mismo. Podemos grabar un fichero llamado claves_foraneas.dot con estos datos:
digraph fkey_pkey_relacion{
K=1;
Aqui vendria la salida de ejecutar
el comando SQL en vustro sistema
}
y ejecutar este comando para generar un fichero PNG:
fdp -Tpng -o claves_foraneas.png claves_foraneas.dot
El resultado que conseguí lo podeis ver a continuación: