add stops.stop_access field#504
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds support for the proposed GTFS stops.stop_access field to Transitland’s GTFS ingestion pipeline so it can be parsed/validated and persisted to storage (Postgres + SQLite schemas), without exposing it via APIs yet.
Changes:
- Adds
StopAccessto the GTFSStopentity with enum validation (0,1) and conditional validation rules inConditionalErrors(). - Adds
stop_accesscolumn togtfs_stopsin the SQLite schema. - Adds a Postgres migration to add nullable
gtfs_stops.stop_access.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
gtfs/stop.go |
Adds StopAccess field and conditional validation rules for allowed usage. |
schema/sqlite/sqlite.sql |
Adds stop_access column to gtfs_stops for SQLite-backed workflows. |
schema/postgres/migrations/20260617000002_add_stop_access.up.pgsql |
Adds migration to add nullable stop_access column to Postgres gtfs_stops. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the
stops.stop_accessfield (GTFS proposal google/transit#515, closing tlv2#204) end-to-end: parsing and validation on theStopentity, storage in both the raw and materialized stop tables (Postgres and SQLite), the materialization projection, the read path, GraphQL (both theStoptype and the stop edit mutation), and REST, with unit and mutation tests. This supersedes the original scope of this PR, which only parsed/validated/stored the field without exposing it.transitland-lib#504 — spec: google/transit#515
Field and validation (gtfs/stop.go)
Adds
StopAccess tt.Intwithenum:"0,1"to theStopstruct. With no explicitcsv:/db:tag it maps to thestop_accessCSV and DB column by the standard snake_case reflection, same as the adjacentLevelID/level_id, so the import write path persists it with no extra wiring.Per the spec,
0means the platform must be reached via a station entrance/pathways,1means directions may route directly to the stop, and empty means undefined.ConditionalErrors()enforces thatstop_accessis only valid on a platform (location_type0) that has aparent_station: it flags anInvalidFieldErrorwhenlocation_type != 0, or (else) whenparent_stationis empty. Theelse ifreports a single error rather than two when both conditions hold (e.g. a station). Theenum:"0,1"tag independently rejects out-of-range values.Both the enum and conditional rules run on every write path, including the GraphQL mutation:
createUpdateEntcallstt.CheckErrorsbefore insert/update, so an invalidstop_accesscannot be persisted.Storage and schema
New Postgres migration
20260617000002_add_stop_access.up.pgsqladds a nullablestop_access integercolumn to bothgtfs_stopsand the materializedtl_materialized_active_stops. Up-only, additive, backward compatible, consistent with the repo's migration convention (no.downfiles exist). It is numbered000002so it orders after20260617000001_trip_safe_duration, which arrived on this branch via the merge frommain.schema/sqlite/sqlite.sql(hand-maintained) adds the matchingstop_access integercolumn to bothgtfs_stopsandtl_materialized_active_stops.internal/feedstate/manager.goaddsstop_accessto the stop projection map so the value propagates fromgtfs_stopsintotl_materialized_active_stopsduring materialization.Read path and API exposure
server/finders/dbfinder/stop.goaddsgtfs_stops.stop_accessto thestopSelectcolumn list, which reads from eithergtfs_stopsor the aliasedtl_materialized_active_stops.schema/graphql/schema.graphqlsaddsstop_access: Inttotype Stop. It autobinds to the embeddedgtfs.Stop.StopAccess(no resolver needed); the generated gqlgen runtime is regenerated.REST exposes the field via the
stop_request.gqlandstop_departure_request.gqlselection sets;doc/openapi/rest.jsonis regenerated (the large diff is the deterministicx-orderrenumbering plus the new field — no other changes).Mutations
stop_access: Intis added toinput StopSetInput, andcreateUpdateStopscans it into the entity, so the field is settable through thestop_create/stop_updatemutations alongside the other editable platform attributes. The generated input model is regenerated.Tests
gtfs/stop_test.goadds validation cases: validstop_access0/1 on a platform with a parent, forbidden on an entrance and on a parentless platform, and a station case asserting a single error (which guards theelse if).server/gql/entity_mutation_resolver_test.goextendsTestStopCreateto create a parent station, setstop_accessthrough the stop mutation, and assert the value round-trips back from the database.Migration
Required. Deploying this runs
dbmigrate upto addgtfs_stops.stop_accessandtl_materialized_active_stops.stop_access(andtlv2 dbmigrate upwhen this pin is later picked up by tlv2). Additive and backward compatible; existing materialized rows pick up the value on the next materialization.Test plan
go build ./... and go test ./... (CI).
Import a feed whose
stops.txtsetsstop_accessto 0/1 on platforms with aparent_station; confirm the values land ingtfs_stops.stop_accessand surface via the GraphQLStop.stop_accessfield and the REST stop and stop-departures endpoints.Set
stop_accessvia thestop_create/stop_updateGraphQL mutation on a platform with a parent and confirm it persists.Confirm validation rejects
stop_accesson a station, on a parentless stop, and any value outside {0,1}, on both import and the mutation path.