Editing with CRUD
CRUD commands treat a GTFS feed like a small relational database. This guide walks through a realistic scenario: renaming a stop, fixing a mis-classified route, and retiring a line — all while keeping the feed valid at every step.
The running example uses a feed called gtfs.zip in the current directory. Swap in your own path as you follow along.
Scenario
Section titled “Scenario”You maintain a transit feed with tens of thousands of stops. A recent audit flagged three issues to fix:
- Stop
S01should be renamed from “Place” to “Gare Centrale”. - A bus route is mis-encoded as
route_type=700(cable tram) and needs to be3(bus). - An old line
OLD_LINEis being retired — every trip, and the rows that reference them, should be removed.
1. Inspect before you edit
Section titled “1. Inspect before you edit”Never update what you have not verified first. The read command is read-only and takes the same --where clause as update and delete.
gapline read stops -f gtfs.zip --where "stop_id=S01"Output confirms exactly one row, with the fields you expect:
stop_id | stop_name | stop_lat | stop_lon | ...S01 | Place | 45.5017 | -73.5673 | ...If the match set is larger than you think, tighten the filter:
gapline read stops -f gtfs.zip --where "stop_name LIKE Place%" | wc -l2. Rename the stop
Section titled “2. Rename the stop”A straight field rewrite — stop_name is not a primary key, so no cascade is needed.
gapline update stops -f gtfs.zip \ --where "stop_id=S01" \ --set stop_name="Gare Centrale" \ --confirmRe-read to confirm:
gapline read stops -f gtfs.zip --where "stop_id=S01"3. Fix the route classification
Section titled “3. Fix the route classification”Same shape — single-field, non-PK update. The --where matches any route with the wrong type, which may be one or several.
gapline update routes -f gtfs.zip \ --where "route_type=700" \ --set route_type=3 \ --confirmIf the run reported “NO_CHANGES” (exit code 4), nothing matched — the audit’s fix list was already applied in a previous pass.
4. Retire the old line
Section titled “4. Retire the old line”This is the risky step. Removing a route_id means every trip tied to it has to go, and every stop_times row that references those trips has to go. gapline computes this chain automatically.
-
Preview the blast radius first — read-only, no surprises:
Terminal window gapline read trips -f gtfs.zip --where "route_id=OLD_LINE" | wc -l -
Delete the trips — the cascade preview lists every dependent file that will lose rows:
Terminal window gapline delete trips -f gtfs.zip --where "route_id=OLD_LINE"Records to delete from trips.txt:OLD_LINE-T01OLD_LINE-T02... and 47 moreDeleting would also delete:- 1 243 records in stop_times.txt- 12 records in frequencies.txtProceed with cascade delete? [y/N] y -
Remove the route itself — it no longer has trips referencing it, so there is no cascade:
Terminal window gapline delete routes -f gtfs.zip --where "route_id=OLD_LINE" --confirm
5. Validate the result
Section titled “5. Validate the result”Before shipping the modified feed, run the full validation suite to confirm nothing has slipped:
gapline validate -f gtfs.zip --min-severity warningIf the goal is a separate output file, add --output gtfs-patched.zip to the final update/delete or pass it to a .gl script. See writing .gl scripts for a version of this whole walkthrough as a single batch file that keeps the source feed intact until the save directive succeeds.
Quick reference
Section titled “Quick reference”| Intent | Command |
|---|---|
| See what will be affected. | gapline read <target> --where "…" |
| Edit a field (non-PK). | gapline update <target> --where "…" --set field=value --confirm |
| Rename a primary key across the whole feed. | gapline update <target> --where "…" --set id=new_id --cascade --confirm |
| Remove records and their dependents. | gapline delete <target> --where "…" (preview) or … --confirm (auto-yes) |
| Write to a new file instead of in place. | Add -o newfeed.zip to any of the above. |
See also
Section titled “See also”gapline read,gapline update,gapline delete— command references.- Concepts / Query language — what
--wherecan express. - Concepts / Referential integrity — how the cascade is computed.
- Guides / Writing
.glscripts — same workflow, repeatable.