ajout de la syncho pour Enum.md avec init.sql
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
scripts/sync_enums.py
|
||||
|
||||
Génère une migration SQL non destructive pour ajouter les valeurs d'ENUM
|
||||
manquantes en se basant sur les CSV de `bdd/data_test`.
|
||||
|
||||
Usage:
|
||||
python3 scripts/sync_enums.py > migrations/00_sync_enums.sql
|
||||
|
||||
Relire le SQL généré avant application en production.
|
||||
"""
|
||||
from pathlib import Path
|
||||
import csv
|
||||
from collections import defaultdict
|
||||
import sys
|
||||
|
||||
# Mapping colonne CSV -> nom du type enum en base
|
||||
# NOTE: mapping is now based on filename (more precise)
|
||||
CSV_DIR = Path('bdd/data_test')
|
||||
|
||||
# Define per-file mappings: filename stem -> {column_name: enum_type}
|
||||
FILE_COLUMN_ENUM_MAP = {
|
||||
'utilisateurs': {
|
||||
'role': 'role_type',
|
||||
'genre': 'genre_type',
|
||||
'statut': 'statut_utilisateur_type',
|
||||
},
|
||||
'enfants': {
|
||||
'statut': 'statut_enfant_type',
|
||||
'genre': 'genre_type',
|
||||
},
|
||||
'contrats': {
|
||||
'statut': 'statut_contrat_type',
|
||||
},
|
||||
'dossiers': {
|
||||
'statut': 'statut_dossier_type',
|
||||
},
|
||||
'evenements': {
|
||||
'type': 'type_evenement_type',
|
||||
'statut': 'statut_evenement_type',
|
||||
},
|
||||
'validations': {
|
||||
'statut': 'statut_validation_type',
|
||||
}
|
||||
}
|
||||
|
||||
def quote_sql_literal(s: str) -> str:
|
||||
return "'" + s.replace("'", "''") + "'"
|
||||
|
||||
def discover_values():
|
||||
# heuristique : map common column names to enums
|
||||
enum_values = defaultdict(set)
|
||||
for p in sorted(CSV_DIR.glob('*.csv')):
|
||||
try:
|
||||
with p.open(newline='', encoding='utf-8') as fh:
|
||||
reader = csv.DictReader(fh)
|
||||
fname = p.stem
|
||||
per_file_map = FILE_COLUMN_ENUM_MAP.get(fname, {})
|
||||
for row in reader:
|
||||
for col, enum in per_file_map.items():
|
||||
if col in row and row[col] is not None:
|
||||
v = row[col].strip()
|
||||
if v != '':
|
||||
enum_values[enum].add(v)
|
||||
except Exception as e:
|
||||
print(f"-- Error reading {p}: {e}", file=sys.stderr)
|
||||
return enum_values
|
||||
|
||||
def emit_sql(enum_values):
|
||||
lines = []
|
||||
lines.append('-- Generated by scripts/sync_enums.py — review before applying')
|
||||
for enum_type, vals in enum_values.items():
|
||||
if not vals:
|
||||
continue
|
||||
for v in sorted(vals):
|
||||
lit = quote_sql_literal(v)
|
||||
block = f"""
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_enum e
|
||||
JOIN pg_type t ON e.enumtypid = t.oid
|
||||
WHERE t.typname = {quote_sql_literal(enum_type)}
|
||||
AND e.enumlabel = {lit}
|
||||
) THEN
|
||||
ALTER TYPE {enum_type} ADD VALUE {lit};
|
||||
END IF;
|
||||
END$$;
|
||||
"""
|
||||
lines.append(block)
|
||||
return '\n'.join(lines)
|
||||
|
||||
def main():
|
||||
enum_values = discover_values()
|
||||
sql = emit_sql(enum_values)
|
||||
print(sql)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user