Skip to main content

Open Enums

Open enums use lookup tables with foreign keys to encode enum values. This pattern works across all databases, making it a portable alternative to native enum types.

When to Use Open Enums​

  • Your database doesn't support native enums (Oracle, SQL Server)
  • You need to add new enum values without regenerating code
  • You want forwards compatibility with unknown values
  • You need referential integrity enforced by the database

Schema Pattern​

CREATE TABLE title (code TEXT PRIMARY KEY);
INSERT INTO title (code) VALUES ('mr'), ('ms'), ('dr'), ('phd');

CREATE TABLE titled_person (
title TEXT NOT NULL REFERENCES title,
name TEXT NOT NULL
);

Configuration​

Configure Typr to generate open enums:

val options = Options(
// ...
openEnums = Selector.relationNames("title")
)

Generated Code​

Typr generates an "open" enum type that accepts unknown values:

TitleId
public sealed interface TitleId permits TitleId.Unknown, TitleId.Known {
String value();

record Unknown(String value) implements TitleId {}

enum Known implements TitleId {
mr("mr"),
ms("ms"),
dr("dr"),
phd("phd");
final String value;

@Override
public String value() {
return value;
}

Known(String value) {
this.value = value;
}
}

java.util.Map<String, Known> ByName =
java.util.Arrays.stream(Known.values())
.collect(java.util.stream.Collectors.toMap(n -> n.value, n -> n));

static TitleId apply(String str) {
if (Known.ByName.containsKey(str)) {
return Known.ByName.get(str);
} else {
return new Unknown(str);
}
}

public static PgType<List<TitleId>> pgTypeArray =
PgTypes.text
.array()
.to(
Bijection.of(
xs -> xs.stream().map(TitleId::apply).toList(),
xs -> xs.stream().map(TitleId::value).toList()));
;
public static PgType<TitleId> pgType =
PgTypes.text.to(Bijection.of(TitleId::apply, TitleId::value));
;
}

The key difference from native enums: the Unknown case handles values not present at code generation time.

Supported Data Types​

Open enums support:

  • TEXT / VARCHAR columns
  • Domain types with TEXT as the base type