src/main/java/com/conveyal/gtfs/loader/JdbcGtfsLoader.java
public void setValueForField(Table table, int fieldIndex, int lineNumber, Field field, String string, boolean postgresText, String[] transformedStrings) {
        if (string.isEmpty()) {
            // CSV reader always returns empty strings, not nulls
            if (field.isRequired() && !field.isEmptyValuePermitted() && errorStorage != null) {
                errorStorage.storeError(NewGTFSError.forLine(table, lineNumber, MISSING_FIELD, field.name));
            }
            setFieldToNull(postgresText, transformedStrings, fieldIndex, field);
        } else {
            // Micro-benchmarks show it's only 4-5% faster to call typed parameter setter methods
            // rather than setObject with a type code. I think some databases don't have setObject though.
            // The Field objects throw exceptions to avoid passing the line number, table name etc. into them.
            try {
                // Here, we set the transformed string element even when an error occurs.
                // Ideally, no errors should be signaled with exceptions, but this happens in a try/catch in case
                // something goes wrong (we don't necessarily want to abort loading the feed altogether).
                // FIXME Also, we should probably not be converting any GTFS field values, but some of them are coerced
                //  to null if they are unparseable (e.g., DateField).
                //  We should be saving it as-is in the database and converting upon load into our model objects.
                Set<NewGTFSError> errors;
                if (postgresText) {
                    ValidateFieldResult<String> result = field.validateAndConvert(string);
                    // If the result is null, use the null-setting method.
                    if (result.clean == null) setFieldToNull(postgresText, transformedStrings, fieldIndex, field);
                    // Otherwise, set the cleaned field according to its index.
                    else transformedStrings[fieldIndex + 1] = result.clean;
                    errors = result.errors;
                } else {
                    errors = field.setParameter(insertStatement, fieldIndex + 2, string);
                }
                // Store any errors encountered after field value has been set.
                for (NewGTFSError error : errors) {
                    error.entityType = table.getEntityClass();
                    error.lineNumber = lineNumber;
                    if (errorStorage != null) errorStorage.storeError(error);
                }
            } catch (StorageException ex) {
                // FIXME many exceptions don't have an error type
                if (errorStorage != null) {
                    errorStorage.storeError(NewGTFSError.forLine(table, lineNumber, ex.errorType, ex.badValue));
                }
                // Set transformedStrings or prepared statement param to null
                setFieldToNull(postgresText, transformedStrings, fieldIndex, field);
            }
        }
    }
public void setValueForField(Table table, int fieldIndex, int lineNumber, Field field, String string, boolean postgresText, String[] transformedStrings) {
        if (string.isEmpty()) {
            // CSV reader always returns empty strings, not nulls
            if (field.isRequired() && !field.isEmptyValuePermitted() && errorStorage != null) {
                errorStorage.storeError(NewGTFSError.forLine(table, lineNumber, MISSING_FIELD, field.name));
            }
            setFieldToNull(postgresText, transformedStrings, fieldIndex, field);
        } else {
            // Micro-benchmarks show it's only 4-5% faster to call typed parameter setter methods
            // rather than setObject with a type code. I think some databases don't have setObject though.
            // The Field objects throw exceptions to avoid passing the line number, table name etc. into them.
            try {
                // Here, we set the transformed string element even when an error occurs.
                // Ideally, no errors should be signaled with exceptions, but this happens in a try/catch in case
                // something goes wrong (we don't necessarily want to abort loading the feed altogether).
                // FIXME Also, we should probably not be converting any GTFS field values, but some of them are coerced
                //  to null if they are unparseable (e.g., DateField).
                //  We should be saving it as-is in the database and converting upon load into our model objects.
                Set<NewGTFSError> errors;
                if (postgresText) {
                    ValidateFieldResult<String> result = field.validateAndConvert(string);
                    // If the result is null, use the null-setting method.
                    if (result.clean == null) setFieldToNull(postgresText, transformedStrings, fieldIndex, field);
                    // Otherwise, set the cleaned field according to its index.
                    else transformedStrings[fieldIndex + 1] = result.clean;
                    errors = result.errors;
                } else {
                    errors = field.setParameter(insertStatement, fieldIndex + 2, string);
                }
                // Store any errors encountered after field value has been set.
                for (NewGTFSError error : errors) {
                    error.entityType = table.getEntityClass();
                    error.lineNumber = lineNumber;
                    if (errorStorage != null) errorStorage.storeError(error);
                }
            } catch (StorageException ex) {
                // FIXME many exceptions don't have an error type
                if (errorStorage != null) {
                    errorStorage.storeError(NewGTFSError.forLine(table, lineNumber, ex.errorType, ex.badValue));
                }
                // Set transformedStrings or prepared statement param to null
                setFieldToNull(postgresText, transformedStrings, fieldIndex, field);
            }
        }
    }
Set value for a field either as a prepared statement parameter or (if using postgres text-loading) in the
transformed strings array provided. This also handles the case where the string is empty (i.e., field is null)
and when an exception is encountered while setting the field value (usually due to a bad data type), in which case
the field is set to null.