@@ -77,9 +77,11 @@ public JdbcTableWriter (
77
77
78
78
// TODO: verify specTable.name is ok to use for constructing dynamic sql statements
79
79
this .specTable = specTable ;
80
+ // Below is a bit messy because the connection field on this class is set to final and we cannot set this to
81
+ // the optionally passed-in connection with the ternary statement unless connection1 already exists.
80
82
Connection connection1 ;
81
83
try {
82
- connection1 = dataSource .getConnection ();
84
+ connection1 = this . dataSource .getConnection ();
83
85
} catch (SQLException e ) {
84
86
e .printStackTrace ();
85
87
connection1 = null ;
@@ -170,11 +172,34 @@ public String update(Integer id, String json, boolean autoCommit) throws SQLExce
170
172
updateChildTable (childEntitiesArray , entityId , isCreating , referencingTable , connection );
171
173
}
172
174
}
173
- // Iterate over table's fields and apply linked values to any tables
174
- if ("routes" .equals (specTable .name )) {
175
- updateLinkedFields (specTable , jsonObject , "trips" , "route_id" , "wheelchair_accessible" );
176
- } else if ("patterns" .equals (specTable .name )) {
177
- updateLinkedFields (specTable , jsonObject , "trips" , "pattern_id" , "direction_id" );
175
+ // Iterate over table's fields and apply linked values to any tables. This is to account for "exemplar"
176
+ // fields that exist in one place in our tables, but are duplicated in GTFS. For example, we have a
177
+ // Route#wheelchair_accessible field, which is used to set the Trip#wheelchair_accessible values for all
178
+ // trips on a route.
179
+ // NOTE: pattern_stops linked fields are updated in the updateChildTable method.
180
+ switch (specTable .name ) {
181
+ case "routes" :
182
+ updateLinkedFields (
183
+ specTable ,
184
+ jsonObject ,
185
+ "trips" ,
186
+ "route_id" ,
187
+ "wheelchair_accessible"
188
+ );
189
+ break ;
190
+ case "patterns" :
191
+ updateLinkedFields (
192
+ specTable ,
193
+ jsonObject ,
194
+ "trips" ,
195
+ "pattern_id" ,
196
+ "direction_id" , "shape_id"
197
+ );
198
+ break ;
199
+ default :
200
+ LOG .debug ("No linked fields to update." );
201
+ // Do nothing.
202
+ break ;
178
203
}
179
204
if (autoCommit ) {
180
205
// If nothing failed up to this point, it is safe to assume there were no problems updating/creating the
@@ -205,6 +230,7 @@ public String update(Integer id, String json, boolean autoCommit) throws SQLExce
205
230
* the related table (e.g., pattern_stop#timepoint should update all of its related stop_times).
206
231
*/
207
232
private void updateLinkedFields (Table referenceTable , ObjectNode jsonObject , String tableName , String keyField , String ...fieldNames ) throws SQLException {
233
+ boolean updatingStopTimes = "stop_times" .equals (tableName );
208
234
// Collect fields, the JSON values for these fields, and the strings to add to the prepared statement into Lists.
209
235
List <Field > fields = new ArrayList <>();
210
236
List <JsonNode > values = new ArrayList <>();
@@ -216,12 +242,17 @@ private void updateLinkedFields(Table referenceTable, ObjectNode jsonObject, Str
216
242
}
217
243
String setFields = String .join (", " , fieldStrings );
218
244
// If updating stop_times, use a more complex query that joins trips to stop_times in order to match on pattern_id
219
- boolean updatingStopTimes = "stop_times" .equals (tableName );
220
245
Field orderField = updatingStopTimes ? referenceTable .getFieldForName (referenceTable .getOrderFieldName ()) : null ;
221
246
String sql = updatingStopTimes
222
- ? String .format ("update %s.stop_times st set %s from %s.trips t " +
223
- "where st.trip_id = t.trip_id AND t.%s = ? AND st.%s = ?" ,
224
- tablePrefix , setFields , tablePrefix , keyField , orderField .name )
247
+ ? String .format (
248
+ "update %s.stop_times st set %s from %s.trips t " +
249
+ "where st.trip_id = t.trip_id AND t.%s = ? AND st.%s = ?" ,
250
+ tablePrefix ,
251
+ setFields ,
252
+ tablePrefix ,
253
+ keyField ,
254
+ orderField .name
255
+ )
225
256
: String .format ("update %s.%s set %s where %s = ?" , tablePrefix , tableName , setFields , keyField );
226
257
// Prepare the statement and set statement parameters
227
258
PreparedStatement statement = connection .prepareStatement (sql );
@@ -371,8 +402,6 @@ private void updateChildTable(ArrayNode subEntities, Integer id, boolean isCreat
371
402
// Get parent entity's key value
372
403
keyValue = getValueForId (id , keyField .name , tablePrefix , specTable , connection );
373
404
String childTableName = String .join ("." , tablePrefix , subTable .name );
374
- // FIXME: add check for pattern stop consistency.
375
- // FIXME: re-order stop times if pattern stop order changes.
376
405
// Reconciling pattern stops MUST happen before original pattern stops are deleted in below block (with
377
406
// getUpdateReferencesSql)
378
407
if ("pattern_stops" .equals (subTable .name )) {
@@ -390,15 +419,14 @@ private void updateChildTable(ArrayNode subEntities, Integer id, boolean isCreat
390
419
}
391
420
reconcilePatternStops (keyValue , newPatternStops , connection );
392
421
}
393
- // FIXME: allow shapes to be updated on pattern geometry change.
394
422
if (!isCreatingNewEntity ) {
395
423
// Delete existing sub-entities for given entity ID if the parent entity is not being newly created.
396
424
String deleteSql = getUpdateReferencesSql (SqlMethod .DELETE , childTableName , keyField , keyValue , null );
397
425
LOG .info (deleteSql );
398
426
Statement statement = connection .createStatement ();
399
427
// FIXME: Use copy on update for a pattern's shape instead of deleting the previous shape and replacing it.
400
- // This would better account for GTFS data loaded from a file where multiple patterns reference a single
401
- // shape.
428
+ // This would better account for GTFS data loaded from a file where multiple patterns reference a single
429
+ // shape.
402
430
int result = statement .executeUpdate (deleteSql );
403
431
LOG .info ("Deleted {} {}" , result , subTable .name );
404
432
// FIXME: are there cases when an update should not return zero?
@@ -436,7 +464,7 @@ private void updateChildTable(ArrayNode subEntities, Integer id, boolean isCreat
436
464
// If handling first iteration, create the prepared statement (later iterations will add to batch).
437
465
insertStatement = createPreparedUpdate (id , true , subEntity , subTable , connection , true );
438
466
}
439
- // Update linked stop times fields for updated pattern stop (e.g., timepoint, pickup/drop off type).
467
+ // Update linked stop times fields for each updated pattern stop (e.g., timepoint, pickup/drop off type).
440
468
if ("pattern_stops" .equals (subTable .name )) {
441
469
updateLinkedFields (
442
470
subTable ,
@@ -610,8 +638,13 @@ else if (i == newStops.size() - 1 || !originalStopIds.get(i).equals(newStops.get
610
638
}
611
639
// Increment sequences for stops that follow the inserted location (including the stop at the changed index).
612
640
// NOTE: This should happen before the blank stop time insertion for logical consistency.
613
- String updateSql = String .format ("update %s.stop_times set stop_sequence = stop_sequence + 1 from %s.trips where stop_sequence >= %d AND %s" ,
614
- tablePrefix , tablePrefix , differenceLocation , joinToTrips );
641
+ String updateSql = String .format (
642
+ "update %s.stop_times set stop_sequence = stop_sequence + 1 from %s.trips where stop_sequence >= %d AND %s" ,
643
+ tablePrefix ,
644
+ tablePrefix ,
645
+ differenceLocation ,
646
+ joinToTrips
647
+ );
615
648
LOG .info (updateSql );
616
649
PreparedStatement updateStatement = connection .prepareStatement (updateSql );
617
650
int updated = updateStatement .executeUpdate ();
@@ -638,13 +671,23 @@ else if (originalStopIds.size() == newStops.size() + 1) {
638
671
}
639
672
}
640
673
// Delete stop at difference location
641
- String deleteSql = String .format ("delete from %s.stop_times using %s.trips where stop_sequence = %d AND %s" ,
642
- tablePrefix , tablePrefix , differenceLocation , joinToTrips );
674
+ String deleteSql = String .format (
675
+ "delete from %s.stop_times using %s.trips where stop_sequence = %d AND %s" ,
676
+ tablePrefix ,
677
+ tablePrefix ,
678
+ differenceLocation ,
679
+ joinToTrips
680
+ );
643
681
LOG .info (deleteSql );
644
682
PreparedStatement deleteStatement = connection .prepareStatement (deleteSql );
645
683
// Decrement all stops with sequence greater than difference location
646
- String updateSql = String .format ("update %s.stop_times set stop_sequence = stop_sequence - 1 from %s.trips where stop_sequence > %d AND %s" ,
647
- tablePrefix , tablePrefix , differenceLocation , joinToTrips );
684
+ String updateSql = String .format (
685
+ "update %s.stop_times set stop_sequence = stop_sequence - 1 from %s.trips where stop_sequence > %d AND %s" ,
686
+ tablePrefix ,
687
+ tablePrefix ,
688
+ differenceLocation ,
689
+ joinToTrips
690
+ );
648
691
LOG .info (updateSql );
649
692
PreparedStatement updateStatement = connection .prepareStatement (updateSql );
650
693
int deleted = deleteStatement .executeUpdate ();
@@ -764,9 +807,7 @@ else if (originalStopIds.size() < newStops.size()) {
764
807
insertBlankStopTimes (tripsForPattern , newStops , firstDifferentIndex , stopsToInsert , connection );
765
808
}
766
809
// ANY OTHER TYPE OF MODIFICATION IS NOT SUPPORTED
767
- else {
768
- throw new IllegalStateException (RECONCILE_STOPS_ERROR_MSG );
769
- }
810
+ else throw new IllegalStateException (RECONCILE_STOPS_ERROR_MSG );
770
811
}
771
812
772
813
/**
0 commit comments