Image de couverture : PostgreSQL : récupérer le DDL d'une base directement en SQL avec pg_get_database_ddl()
tech

PostgreSQL : récupérer le DDL d'une base directement en SQL avec pg_get_database_ddl()

03 May 2026
6 min de lecture
1 vues
Sébastien Muler

Enfin une API SQL pour obtenir le DDL d'une base — sans appeler pg_dump

Pendant trente ans, la réponse à la question «Comment obtenir le DDL d'un objet PostgreSQL ?» a toujours été la même : lancer pg_dump -s depuis un shell et passer le résultat à la moulinette. Outils de migration, utilitaires de diff de schéma, ORM qui introspectent une base live — tous ont soit invoqué pg_dump, soit réécrit leur propre logique de parcours des catalogues système. Souvent les deux.

C'est en train de changer. Un commit du 5 avril 2026 (patch principal d'Akshay Joshi, co-auteur Euler Taveira, intégré par Andrew Dunstan) introduit la première brique du programme «Retail DDL» : pg_get_database_ddl(). La promesse : obtenir les instructions DDL d'une base de données directement depuis SQL, sans quitter votre session psql ni votre application Symfony.

Source originale : Christophe Pettus — Retail DDL Arrives, One Function at a Time


Ce que fait pg_get_database_ddl()

La signature de la fonction est la suivante :

pg_get_database_ddl(regdatabase, VARIADIC text[])

Elle retourne un ensemble de lignes contenant les instructions nécessaires pour recréer une base de données :

  • Première ligne : le CREATE DATABASE avec ses paramètres.
  • Lignes suivantes : les éventuels ALTER DATABASE complémentaires.

Les options sont passées sous forme de paires nom/valeur en paramètres variadiques :

Option Type Effet
pretty boolean Indentation lisible du DDL
owner boolean Inclure la clause OWNER
tablespace boolean Inclure la clause TABLESPACE

Exemple d'appel

-- DDL complet de la base courante, avec owner et tablespace
SELECT *
FROM pg_get_database_ddl(
  current_database()::regdatabase,
  'pretty', 'true',
  'owner', 'true',
  'tablespace', 'true'
);

Permissions requises

L'appelant doit disposer du privilège CONNECT sur la base cible. Rien de plus — ce qui la rend utilisable depuis un rôle applicatif dédié sans droits superutilisateur.

-- Vérifier les permissions avant d'appeler
SELECT has_database_privilege(current_user, 'myapp_production', 'CONNECT');

Ce que cette fonction n'est PAS

Avant d'aller plus loin, soyons clairs sur les limites — et elles sont importantes.

pg_get_database_ddl() ne remplace pas pg_dump. Voici pourquoi :

  • pg_dump produit un fichier SQL complet et exécutable, gère les dépendances croisées entre objets, respecte la propriété des extensions, et traite des dizaines de cas limites accumulés en dix ans de production réelle.
  • pg_get_database_ddl() sérialise un seul objet — la base de données elle-même — avec des sémantiques claires pour owner et tablespace, et rien d'autre.

⚠️ Ne substituez pas cette fonction à pg_dump dans un pipeline de backup. Vous perdriez les données, les tables, les indexes, les fonctions, les extensions — tout.

L'idée du programme «Retail DDL» est différente : fournir des fonctions ciblées, objet par objet, pour les cas où appeler pg_dump a toujours été la mauvaise solution malgré l'absence d'alternative propre.


Cas d'usage concrets pour les projets Symfony / Laravel

1. Drift detection en CI/CD

Dans un pipeline GitHub Actions ou GitLab CI, vous pouvez désormais comparer le DDL courant d'une base de staging avec un snapshot de référence stocké dans le dépôt :

# Extraire le DDL courant et le comparer au snapshot
psql $DATABASE_URL -t -c "
  SELECT ddl FROM pg_get_database_ddl(
    current_database()::regdatabase,
    'pretty', 'true', 'owner', 'false', 'tablespace', 'false'
  )
" > current_db_ddl.sql

diff snapshots/db_reference.sql current_db_ddl.sql

Si le diff est non vide, le pipeline échoue et alerte l'équipe : la configuration de la base a dérivé par rapport à la référence.

2. Génération automatisée de snapshots de schéma

Dans une commande Symfony (ou une commande Artisan Laravel), vous pouvez générer périodiquement un snapshot de la configuration de chaque base :

// src/Command/DatabaseSnapshotCommand.php (Symfony)
protected function execute(InputInterface $input, OutputInterface $output): int
{
    $conn = $this->entityManager->getConnection();

    $rows = $conn->fetchAllAssociative("
        SELECT ddl
        FROM pg_get_database_ddl(
            current_database()::regdatabase,
            'pretty', 'true',
            'owner', 'true',
            'tablespace', 'true'
        )
    ");

    $ddl = implode("\n", array_column($rows, 'ddl'));
    file_put_contents(
        sprintf('var/snapshots/db_%s.sql', date('Ymd_His')),
        $ddl
    );

    $output->writeln('<info>Snapshot généré.</info>');
    return Command::SUCCESS;
}

3. Architecture multi-tenant

Si votre application gère plusieurs bases de données (un tenant = une base), pg_get_database_ddl() permet d'auditer la configuration de chaque base en une seule requête SQL, sans avoir à orchestrer N appels à pg_dump en shell :

-- Audit multi-tenant : DDL de toutes les bases applicatives
SELECT
  datname,
  (SELECT string_agg(ddl, E'\n')
   FROM pg_get_database_ddl(d.oid, 'owner', 'true')
  ) AS database_ddl
FROM pg_database d
WHERE datname LIKE 'tenant_%'
ORDER BY datname;

Pattern pratique : combiner Retail DDL et pg_dump

La vraie valeur de pg_get_database_ddl() n'est pas de remplacer pg_dump, mais de compléter les outils existants là où un appel shell était un hack déguisé.

Voici la règle de décision :

Besoin Outil recommandé
Backup complet avec données pg_dump
Diff de schéma complet (tables, index, fonctions…) pg_dump -s + diff
DDL de la configuration d'une base pg_get_database_ddl()
DDL d'une vue ou d'une fonction pg_get_viewdef() / pg_get_functiondef()
Introspection depuis une app sans accès shell Fonctions Retail DDL

La checklist permissions à vérifier avant d'intégrer la fonction :

  • Le rôle applicatif a CONNECT sur la base cible
  • La version PostgreSQL est ≥ 18 (la fonction est introduite dans PG18)
  • Le pipeline ne substitue pas cet appel à un vrai backup

Conclusion

Le programme «Retail DDL» de PostgreSQL est une évolution bienvenue pour tous ceux qui ont un jour écrit un wrapper autour de pg_dump pour extraire le DDL d'un seul objet. pg_get_database_ddl() n'est que la première brique : d'autres fonctions couvrant tables, indexes, séquences et contraintes sont attendues dans les versions suivantes.

Pour les projets Symfony et Laravel en architecture multi-tenant ou avec des pipelines CI/CD stricts sur la configuration PostgreSQL, c'est un outil à intégrer dès la sortie de PostgreSQL 18. Simple, sans dépendance shell, et avec des permissions explicites — exactement ce qu'on attendait.

Partager cet article