Le comportement par défaut de generate_schema_name dans dbt concatène target.schema avec tout schéma personnalisé spécifié dans dbt_project.yml ou la configuration du modèle. Un modèle configuré avec schema: marts dans une cible appelée dbt_adrienne atterrit dans dbt_adrienne_marts dans tous les environnements, y compris la production. Surcharger cette macro permet à la production d’utiliser des noms de schéma propres (marts) tandis que le développement obtient des schémas préfixés (dbt_adrienne_marts).
Comment fonctionne le nommage de schéma par défaut de dbt
Quand vous définissez un schéma personnalisé sur un modèle :
models: my_project: marts: +schema: martsdbt appelle generate_schema_name en interne pour décider du nom de schéma final. L’implémentation par défaut produit toujours {target.schema}_{custom_schema}. Il n’y a pas de distinction intégrée entre les environnements.
Cela signifie :
- En dev (schéma cible :
dbt_adrienne) : le modèle atterrit dansdbt_adrienne_marts - En prod (schéma cible :
analytics) : le modèle atterrit dansanalytics_marts
Aucun de ces résultats n’est ce que la plupart des équipes souhaitent. En production, le schéma devrait être marts. En développement, il devrait être dbt_adrienne_marts. Le comportement par défaut force les deux environnements à utiliser la même logique de concaténation, ce qui impose un choix gênant : soit accepter des noms de schéma désordonnés en production, soit accepter que les modèles de dev atterrissent dans des schémas identiques à ceux de la production.
La surcharge
La correction est une macro generate_schema_name dans le répertoire macros/ de votre projet. dbt appelle automatiquement cette macro à la place de celle intégrée quand elle existe — vous ne l’invoquez pas directement.
-- macros/generate_schema_name.sql{% macro generate_schema_name(custom_schema_name, node) %} {% if target.name == 'prod' and custom_schema_name is not none %} {{ custom_schema_name | trim }} {% else %} {{ target.schema }}{% if custom_schema_name is not none %}_{{ custom_schema_name | trim }}{% endif %} {% endif %}{% endmacro %}Avec cette macro en place, un modèle configuré avec schema: marts atterrit dans :
- Dev (
target.name == 'dev',target.schema == 'dbt_adrienne') :dbt_adrienne_marts - Prod (
target.name == 'prod') :marts
La logique est simple : en production, utilisez le schéma personnalisé directement tel quel. Dans tout autre environnement (dev, CI, staging), revenez au comportement de concaténation par défaut. Les modèles sans schéma personnalisé utilisent simplement target.schema dans tous les environnements, ce qui est déjà correct.
Sans la surcharge
Deux résultats courants sans la surcharge :
- Schémas de production concaténés (
analytics_marts,analytics_staging,analytics_finance). Les consommateurs en aval — outils BI, analystes, autres pipelines — sont couplés au préfixe. Quand le nom du projet ou le schéma cible change, les connexions se cassent. - Étapes de déploiement manuelles : les ingénieurs codent en dur les noms de schéma ou commentent/décommentent la configuration avant de déployer. Les étapes manuelles sont oubliées. Une exécution mal déployée place les modèles dans le mauvais schéma.
La surcharge détermine les noms de schéma au moment de la compilation en fonction de la cible de déploiement — sans intervention manuelle.
Gestion des environnements CI et staging
La séparation simple prod/non-prod couvre la plupart des projets, mais vous pourriez vouloir un contrôle plus granulaire. Une extension courante gère explicitement les environnements CI :
{% macro generate_schema_name(custom_schema_name, node) %} {% if target.name == 'prod' and custom_schema_name is not none %} {{ custom_schema_name | trim }} {% elif target.name == 'ci' %} ci_{{ target.schema }}{% if custom_schema_name is not none %}_{{ custom_schema_name | trim }}{% endif %} {% else %} {{ target.schema }}{% if custom_schema_name is not none %}_{{ custom_schema_name | trim }}{% endif %} {% endif %}{% endmacro %}Cela place les schémas CI dans un espace préfixé ci_ (ci_dbt_pr123_marts) afin que les exécutions CI ne polluent pas l’espace de dev. Sur la plupart des équipes, la version simple à deux branches suffit — mais si les schémas CI finissent par entrer en conflit avec les schémas dev, ajouter la branche CI résout le problème.
Emplacement et la règle une-macro-par-fichier
generate_schema_name est une macro de surcharge, pas une macro utilitaire. Elle appartient à la racine de votre répertoire macros/ aux côtés des autres surcharges dbt (generate_alias_name, generate_node_name), pas enfouie dans un sous-dossier utils/.
macros/├── _macros.yml├── generate_schema_name.sql # macros de surcharge à la racine├── generate_alias_name.sql # si vous en avez une└── utils/ ├── add_audit_columns.sql ├── cents_to_dollars.sql └── limit_data_in_dev.sqlCet emplacement signale à toute nouvelle personne dans le projet que ces macros ont un statut particulier — elles sont appelées automatiquement par dbt, pas explicitement par le SQL des modèles.
Puisque cette macro est appelée automatiquement, elle n’a pas besoin d’un bloc arguments dans _macros.yml de la même manière que les macros utilitaires. Mais il vaut la peine de documenter le comportement adapté à l’environnement dans la description, car la logique conditionnelle n’est pas évidente pour quelqu’un qui n’a jamais vu le pattern de surcharge auparavant.
Ce qui peut mal tourner
Mauvais target.name dans les profiles. La macro conditionne sur target.name. Si la cible de votre profil prod ne s’appelle pas vraiment prod, la condition ne s’active jamais. Vérifiez avec dbt debug que votre nom de cible correspond à ce que la macro attend. Utiliser une var pour le nom de cible de production (plutôt que de coder en dur 'prod') vous donne de la flexibilité :
{% if target.name == var('prod_target_name', 'prod') and custom_schema_name is not none %}Modèles sans schéma personnalisé en production. Les modèles qui ne définissent pas de schéma personnalisé utilisent target.schema dans tous les environnements, y compris en production. C’est généralement correct — vos modèles de staging peuvent intentionnellement atterrir dans le schéma par défaut. Mais vérifiez que le target.schema de production correspond à ce que vous souhaitez pour les modèles sans schéma.
Bases de données multiples. Si votre projet écrit dans plusieurs bases de données, le nommage des schémas peut également devoir en tenir compte. L’argument node vous donne accès à la configuration complète du modèle, y compris la base de données — vous pouvez conditionner sur node.database si nécessaire.
Le pattern plus large
generate_schema_name est l’une des plusieurs macros « hook » de dbt qui surchargent le comportement interne. Le pattern — surcharger une macro que dbt appelle automatiquement, conditionner sur target.name pour produire un comportement adapté à l’environnement — apparaît dans generate_alias_name (pour les alias de modèles personnalisés) et generate_node_name (pour le nommage personnalisé des nœuds).
La même logique adaptée à l’environnement qui fait fonctionner le nommage des schémas apparaît également dans [[fr/macros-dbt|le pattern limit_data_in_dev]] : utilisez target.name pour vérifier l’environnement et produire un comportement différent entre la production et le développement. La différence est que generate_schema_name est appelé par dbt, tandis que limit_data_in_dev est appelé explicitement dans le SQL de vos modèles.
Consultez Structure et nommage des projets dbt pour la façon dont l’organisation des schémas s’intègre dans la structure plus large du projet, et Macros dbt pour les fondamentaux Jinja qui expliquent comment cette macro produit sa sortie.