Skip to content

Commit d4f4225

Browse files
committed
DuckDB [todo]
1 parent c5b28ec commit d4f4225

29 files changed

+1760
-2213
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ pnpm-debug.log
1515
/*.gtfs.zip
1616
/*.gtfs.tar.gz
1717
/*.gtfs.tar.zst
18+
19+
/*.duckdb

cli.js

Lines changed: 13 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ const {
4444
'lower-case-lang-codes': {
4545
type: 'boolean',
4646
},
47-
'stops-location-index': {
48-
type: 'boolean',
49-
},
5047
'stats-by-route-date': {
5148
type: 'string',
5249
},
@@ -59,21 +56,6 @@ const {
5956
'schema': {
6057
type: 'string',
6158
},
62-
'postgraphile': {
63-
type: 'boolean',
64-
},
65-
'postgraphile-password': {
66-
type: 'string',
67-
},
68-
'postgrest': {
69-
type: 'boolean',
70-
},
71-
'postgrest-password': {
72-
type: 'string',
73-
},
74-
'postgrest-query-cost-limit': {
75-
type: 'string',
76-
},
7759
'import-metadata': {
7860
type: 'boolean',
7961
}
@@ -84,7 +66,7 @@ const {
8466
if (flags.help) {
8567
process.stdout.write(`
8668
Usage:
87-
gtfs-to-sql [options] [--] <gtfs-file> ...
69+
import-gtfs-into-duckdb [options] [--] <path-to-duckdb> <gtfs-file> ...
8870
Options:
8971
--silent -s Don't show files being converted.
9072
--require-dependencies -d Require files that the specified GTFS files depend
@@ -101,8 +83,6 @@ Options:
10183
--routes-without-agency-id Don't require routes.txt items to have an agency_id.
10284
--stops-without-level-id Don't require stops.txt items to have a level_id.
10385
Default if levels.txt has not been provided.
104-
--stops-location-index Create a spatial index on stops.stop_loc for efficient
105-
queries by geolocation.
10686
--lower-case-lang-codes Accept Language Codes (e.g. in feed_info.feed_lang)
10787
with a different casing than the official BCP-47
10888
language tags (as specified by the GTFS spec),
@@ -123,34 +103,13 @@ Options:
123103
currently running trips over time, by hour.
124104
Like --stats-by-route-date, this flag accepts
125105
none, view & materialized-view.
126-
--schema The schema to use for the database. Default: public
127-
Even when importing into a schema other than \`public\`,
128-
a function \`public.gtfs_via_postgres_import_version()\`
129-
gets created, to ensure that multiple imports into the
130-
same database are all made using the same version. See
131-
also multiple-datasets.md in the docs.
132-
--postgraphile Tweak generated SQL for PostGraphile usage.
133-
https://www.graphile.org/postgraphile/
134-
--postgraphile-password Password for the PostGraphile PostgreSQL user.
135-
Default: $POSTGRAPHILE_PGPASSWORD, fallback random.
136-
--postgrest Tweak generated SQL for PostgREST usage.
137-
Please combine it with --schema.
138-
https://postgrest.org/
139-
--postgrest-password Password for the PostgREST PostgreSQL user \`web_anon\`.
140-
Default: $POSTGREST_PGPASSWORD, fallback random.
141-
--postgrest-query-cost-limit Define a cost limit [1] for queries executed by PostgREST
142-
on behalf of a user. It is only enforced if
143-
pg_plan_filter [2] is installed in the database!
144-
Must be a positive float. Default: none
145-
[1] https://www.postgresql.org/docs/14/using-explain.html
146-
[2] https://github.com/pgexperts/pg_plan_filter
106+
--schema The schema to use for the database. Default: main
147107
--import-metadata Create functions returning import metadata:
148108
- gtfs_data_imported_at (timestamp with time zone)
149109
- gtfs_via_postgres_version (text)
150110
- gtfs_via_postgres_options (jsonb)
151111
Examples:
152-
gtfs-to-sql some-gtfs/*.txt | sponge | psql -b # import into PostgreSQL
153-
gtfs-to-sql -u -- some-gtfs/*.txt | gzip >gtfs.sql.gz # generate a gzipped SQL dump
112+
import-gtfs-into-duckdb some-gtfs.duckdb some-gtfs/*.txt
154113
155114
[1] https://developers.google.com/transit/gtfs/reference/extended-route-types
156115
[2] https://groups.google.com/g/gtfs-changes/c/keT5rTPS7Y0/m/71uMz2l6ke0J
@@ -164,11 +123,11 @@ if (flags.version) {
164123
}
165124

166125
const {basename, extname} = require('path')
167-
const {pipeline} = require('stream')
168126
const convertGtfsToSql = require('./index')
169-
const DataError = require('./lib/data-error')
170127

171-
const files = args.map((file) => {
128+
const [pathToDb] = args
129+
130+
const files = args.slice(1).map((file) => {
172131
const name = basename(file, extname(file))
173132
return {name, file}
174133
})
@@ -184,9 +143,7 @@ const opt = {
184143
statsByRouteIdAndDate: flags['stats-by-route-date'] || 'none',
185144
statsByAgencyIdAndRouteIdAndStopAndHour: flags['stats-by-agency-route-stop-hour'] || 'none',
186145
statsActiveTripsByHour: flags['stats-active-trips-by-hour'] || 'none',
187-
schema: flags['schema'] || 'public',
188-
postgraphile: !!flags.postgraphile,
189-
postgrest: !!flags.postgrest,
146+
schema: flags['schema'] || 'main',
190147
importMetadata: !!flags['import-metadata'],
191148
}
192149
if ('stops-without-level-id' in flags) {
@@ -195,31 +152,11 @@ if ('stops-without-level-id' in flags) {
195152
if ('lower-case-lang-codes' in flags) {
196153
opt.lowerCaseLanguageCodes = flags['lower-case-lang-codes']
197154
}
198-
if ('postgraphile-password' in flags) {
199-
opt.postgraphilePassword = flags['postgraphile-password']
200-
}
201-
if ('postgrest-password' in flags) {
202-
opt.postgrestPassword = flags['postgrest-password']
203-
}
204-
if ('postgrest-query-cost-limit' in flags) {
205-
const limit = parseFloat(flags['postgrest-query-cost-limit'])
206-
if (!Number.isFinite(limit) || limit < 0) {
207-
console.error('Invalid --postgrest-query-cost-limit value.')
208-
process.exit(1)
209-
}
210-
opt.lowerCaseLanguageCodes = limit
211-
}
212155

213-
pipeline(
214-
convertGtfsToSql(files, opt),
215-
process.stdout,
216-
(err) => {
217-
if (!err) return;
218-
if (err instanceof DataError) {
219-
console.error(String(err))
220-
} else if (err.code !== 'EPIPE') {
221-
console.error(err)
222-
}
223-
process.exit(1)
156+
convertGtfsToSql(pathToDb, files, opt)
157+
.catch((err) => {
158+
if (err.code !== 'EPIPE') { // todo: check still necessary? we don't pipe anymore
159+
console.error(err)
224160
}
225-
)
161+
process.exit(1)
162+
})

0 commit comments

Comments
 (0)