Per-backend column type overrides, e.g. json on mysql / jsonb on postgres
Motivation
Column types are not portable across databases, and today SeaORM/sea-query can only express a single fixed column type per column. Two concrete consequences:
- The common "JSON" column needs
jsonon mysql andjsonbon postgres. There is no single column definition that produces the native right type on both; you either pick one or work around it outside the entity. - Types that only some databases have (
tinyint,longblob, postgresinterval, ...) force either a customColumnType::Custom("...")string that is wrong on every other backend, or a bigger portable type. Long-standing issues #426 (interval), #631 (longblob), #213 (DATE) and the newer composite/domain type requests (#2895, #2863) all sit around this gap.
Proposed Solutions
I'd like to start a discussion on a per-backend column type override, roughly:
ColumnDef::new(Column::Payload)
.string() // abstract fallback for backends without an override
.per_backend(|backend| match backend {
Backend::MySql => ColumnType::Json,
Backend::Postgres => ColumnType::JsonB,
_ => ColumnType::String(None),
})(or any equivalent shape — a map from backend to ColumnType, an extension of ColumnType::Custom, or derivable helpers; the ergonomics are for maintainers to steer).
The semantics that have proven themselves in other ORMs: the backend-specific type wins on that backend, other backends fall back to the abstract type, and columns without overrides render exactly as today.
- ent (Go) has
field.String("s").SchemaType(map[string]string{dialect.MySQL: "varchar(255)", dialect.Postgres: "text"})as a built-in - SQLAlchemy has
String(255).with_variant(VARCHAR(255, charset="utf8"), "mysql") - gorm recently merged dialect-qualified type tags (go-gorm/gorm#7867)
Happy to collaborate on a design and implementation if maintainers think this fits sea-query/SeaORM's direction.
Additional Information
The same need shows up across ecosystems; the ent and SQLAlchemy links above are the closest prior art. No behavior would change for existing entities — the fallback path is the current rendering.
Source: SeaQL/sea-orm