Intégrité référentielle
Un flux GTFS est une petite base relationnelle avec une vingtaine de relations FK. L’éditer naïvement — retirer un arrêt, renommer une ligne — est une voie rapide pour produire un flux qui valide structurellement mais échoue sur Google Maps parce que stop_times référence plus rien. L’intégrité référentielle est ce qui vous sauve de ce piège.
gapline applique l’intégrité à chaque écriture. Aucune édition n’atteint le disque avant que le modèle d’intégrité ait confirmé que le résultat est cohérent.
Le modèle
Section intitulée « Le modèle »En interne, gapline maintient un index inverse pour chaque clé primaire utilisée comme clé étrangère ailleurs. Au chargement du flux, l’index associe :
stops.stop_id → lignes de stop_times, transfers, pathways qui la référencentroutes.route_id → lignes de trips, fare_rules qui la référencenttrips.trip_id → lignes de stop_times, frequenciescalendar.service_id → lignes de trips, calendar_dates…Les requêtes sur l’index sont en O(1) par PK — construire le plan de cascade d’un delete sur un flux de taille moyenne se chiffre en millisecondes.
Délibérément, l’index n’est qu’une série de hash maps : pas de bibliothèque de graphes, pas de path-finding, pas de détection de cycles. Les chaînes de FK GTFS sont peu profondes (au plus 2–3 sauts), ce qui suffit amplement.
Delete : aperçu de cascade automatique
Section intitulée « Delete : aperçu de cascade automatique »delete ne peut pas orpheliner de dépendants. Quand vous lancez :
gapline delete stops --where "stop_id=S01"gapline :
- Calcule l’ensemble des
stop_id = S01dansstops.txt. - Pour chaque match, parcourt l’index inverse pour trouver toutes les lignes de tous les fichiers dépendants qui référencent le match transitivement.
- Affiche un aperçu :
Records to delete from stops.txt:S01Deleting would also delete:- 83 records in stop_times.txt- 2 records in transfers.txtProceed with cascade delete? [y/N]
- N’applique le plan qu’après votre confirmation (ou si vous avez passé
--confirm).
Il n’y a pas de flag --cascade sur delete parce que la cascade est le seul comportement par défaut sûr. Si la cible n’a pas de dépendants (par exemple calendar_dates.txt est une feuille), le prompt liste simplement les lignes matchées.
Update : les réécritures de PK demandent --cascade
Section intitulée « Update : les réécritures de PK demandent --cascade »Un update non-PK (par ex. changer un stop_name) ne touche que le fichier cible. Pas de cascade nécessaire, pas de cascade calculée.
Un update sur PK (par ex. renommer stop_id=S01 en stop_id=STOP_MAIN) est différent : toutes les lignes de tous les fichiers dépendants qui référencent l’ancienne PK doivent être réécrites pour pointer sur la nouvelle. --cascade active cette réécriture :
gapline update stops \ --where "stop_id=S01" \ --set stop_id=STOP_MAIN \ --cascade --confirmSans --cascade, la réécriture de PK est refusée avant même de commencer — sinon la commande orphelinerait toutes les lignes stop_times référençant S01.
Create : les FK doivent résoudre
Section intitulée « Create : les FK doivent résoudre »create refuse d’insérer un enregistrement dont les champs FK ne pointent pas sur des lignes existantes. Par exemple :
gapline create stop-times --set trip_id=UNKNOWN stop_id=S01 ...échoue immédiatement avec une erreur fk_violation — trip_id=UNKNOWN n’est pas dans trips.txt.
Pourquoi ça compte
Section intitulée « Pourquoi ça compte »Un flux qui passe la validation structurelle mais a des références orphelines est la pire classe de bug : ça passe un check rapide mais ça casse silencieusement en prod. Les consommateurs gèrent les orphelins de façons incohérentes — certains sautent les lignes concernées, d’autres rejettent le flux entier, d’autres rendent des données partielles sans jamais signaler l’erreur.
En appliquant l’intégrité au moment de l’écriture, gapline rend cette classe de bug impossible à produire depuis le CLI. Le compromis est que delete et update --cascade doivent planifier la cascade complète avant application — généralement quelques millisecondes, occasionnellement quelques secondes sur de très gros flux.
Voir aussi
Section intitulée « Voir aussi »gapline update— sémantique de--cascade.gapline delete— aperçu de cascade automatique.gapline create— résolution FK à l’insertion.- Guides / Éditer avec le CRUD — parcours avec un vrai flux.