Environment
- Connector:
source-redshift
- Stack: Legacy JDBC CDK (
AbstractJdbcSource / JdbcSourceOperations)
Current Behavior
Given a Redshift table:
CREATE TABLE invoices (
invoice_date DATE,
due_date DATE,
created_at TIMESTAMP,
amount NUMERIC,
invoice_id INTEGER,
....
);
Schema discovery produces:
| Column |
Discovered Airbyte type |
invoice_date |
String |
due_date |
String |
created_at |
String |
amount |
Number |
invoice_id |
Integer |
Catalog JSON Schema for the date/timestamp columns is effectively {"type":"string"} with no format (date / date-time).
Downstream, destinations that honor semantic types (e.g. destination-postgres) therefore create VARCHAR columns instead of DATE / TIMESTAMP.
Redshift metadata itself is correct (DATE / TIMESTAMP). The destination mapping is also correct when given format-aware schema types. The loss happens during source discovery.
Expected Behavior
Discovery should emit semantic Airbyte temporal types, e.g.:
| Column |
Expected type |
invoice_date |
Date (JsonSchemaType.STRING_DATE, format=date) |
due_date |
Date |
created_at |
Timestamp without timezone (STRING_TIMESTAMP_WITHOUT_TIMEZONE, format=date-time) |
So destinations can create native temporal columns.
Root Cause
RedshiftSourceOperations extends JdbcSourceOperations but does not override getAirbyteType.
The legacy JDBC CDK default maps temporal JDBC types to plain string:
// airbyte-cdk/.../JdbcSourceOperations.kt
JDBCType.DATE -> JsonSchemaType.STRING
JDBCType.TIME -> JsonSchemaType.STRING
JDBCType.TIMESTAMP -> JsonSchemaType.STRING
Discovery path:
RedshiftSource → AbstractJdbcSource / AbstractDbSource.discover
→ discoverInternal (JDBC metadata → JDBCType on CommonField) // still correct
→ DbSourceDiscoverUtil.convertTableInfosToAirbyteCatalog
→ sourceOperations.getAirbyteType(JDBCType) // ★ semantic info lost here
→ AirbyteCatalog
RedshiftSourceOperations only customizes value serialization (putTimestamp, copyToJsonField, etc.), not catalog type mapping. Git history under source-redshift has no prior getAirbyteType / STRING_DATE mapping — this appears to be an omission.
Comparison with other connectors
| Connector |
Temporal discover mapping |
| ClickHouse |
Overrides getAirbyteType → STRING_DATE / STRING_TIMESTAMP_* (fixed in #72484 / #72483) |
| DB2 / SingleStore |
Same override pattern |
| MySQL / Postgres |
Bulk CDK FieldType mappers → DATE / TIMESTAMP_* |
| Redshift |
Inherits CDK default → plain STRING |
Note: changing the CDK default was briefly tried historically and reverted (#7859 / #7969), so a connector-local override is the established fix pattern.
Environment
source-redshiftAbstractJdbcSource/JdbcSourceOperations)Current Behavior
Given a Redshift table:
Schema discovery produces:
invoice_datedue_datecreated_atamountinvoice_idCatalog JSON Schema for the date/timestamp columns is effectively
{"type":"string"}with noformat(date/date-time).Downstream, destinations that honor semantic types (e.g.
destination-postgres) therefore createVARCHARcolumns instead ofDATE/TIMESTAMP.Redshift metadata itself is correct (
DATE/TIMESTAMP). The destination mapping is also correct when given format-aware schema types. The loss happens during source discovery.Expected Behavior
Discovery should emit semantic Airbyte temporal types, e.g.:
invoice_dateJsonSchemaType.STRING_DATE,format=date)due_datecreated_atSTRING_TIMESTAMP_WITHOUT_TIMEZONE,format=date-time)So destinations can create native temporal columns.
Root Cause
RedshiftSourceOperationsextendsJdbcSourceOperationsbut does not overridegetAirbyteType.The legacy JDBC CDK default maps temporal JDBC types to plain string:
Discovery path:
RedshiftSourceOperationsonly customizes value serialization (putTimestamp,copyToJsonField, etc.), not catalog type mapping. Git history undersource-redshifthas no priorgetAirbyteType/STRING_DATEmapping — this appears to be an omission.Comparison with other connectors
getAirbyteType→STRING_DATE/STRING_TIMESTAMP_*(fixed in #72484 / #72483)DATE/TIMESTAMP_*STRINGNote: changing the CDK default was briefly tried historically and reverted (#7859 / #7969), so a connector-local override is the established fix pattern.