Simulate enums with SQLite `CHECK()`

Jjokull5/25/2023
I'm a heavy enum user in Postgres. Using SQLite now, wondering if anyone has come up with something clever to narrow a TEXT value to some values, perhaps based on CHECK() constraints, which kind of give you what ENUM does.
ASAndrii Sherman5/25/2023
2 options

Check only on type level
role: text('content').$type<'admin' | 'member'>().notNull(),


and to make runtime check available as well to can use custom types
https://orm.drizzle.team/docs/custom-types

const someSortOfEnum = customType<{
  data: string;
  driverData: string;
}>({
  dataType() {
    return "text";
  },
  toDriver(value: string): string {
    if (!["admin", "user"].includes(value)) throw Error("roles can be only admin or member");
    return value;
  },
});

export const table = sqliteTable("table", {
  role: someSortOfEnum("content").$type<"admin" | "member">().notNull(),
});
ASAndrii Sherman5/25/2023
In this case you'll have both types and runtime check without db constraints
ASAndrii Sherman5/25/2023
just tested, worked as expected
Jjokull5/25/2023
Awesome! I guess I could add the CHECK in the migration if I want, for DB consistency too
Jjokull5/25/2023
Or even dataType() { return "TEXT CHECK( role IN ('admin','user') )" } ?
ASAndrii Sherman5/25/2023
best way would be to add it manually in sql migration
ASAndrii Sherman5/25/2023
dataType() { return "TEXT CHECK( role IN ('admin','user') )" }

this approach won't be perfect
ASAndrii Sherman5/25/2023
it's better to have only type in dataType function
Jjokull5/25/2023
got it - thanks
Ssam694206/3/2023
sqlite has an enum option on the text type that does everything except adding the CHECK constraint. it's in the old docs just not the new ones
https://github.com/drizzle-team/drizzle-orm/blob/main/drizzle-orm/src/sqlite-core/README.md#column-types

but no runtime checks, but it plays nice with drizzle-zod