Enums
Phi generates strongly-typed Go constants, validation routines, and dialect-specific database DDL for Prisma enum definitions. Enums provide compile-time type safety across your client builders, input structs, and query predicates while mapping cleanly to PostgreSQL and SQLite migrations.
Defining Enums in Prisma Schema
Define an enum in your schema.prisma:
enum UserRole {
ADMIN
STUDENT
TEACHER
}
model User {
id String @id @default(cuid())
email String @unique
role UserRole @default(STUDENT)
}Dialect Storage & DDL Generation
Phi's migration engine (phi migrate) tailors DDL generation based on the database provider:
1. PostgreSQL (Native DDL Enums)
PostgreSQL natively supports custom enum types. During migration generation, Phi generates a dedicated CREATE TYPE statement followed by an enum-typed column:
Generated DDL:
CREATE TYPE "UserRole" AS ENUM (
'ADMIN',
'STUDENT',
'TEACHER'
);
CREATE TABLE "User" (
"id" TEXT NOT NULL,
"email" TEXT NOT NULL,
"role" "UserRole" NOT NULL DEFAULT 'STUDENT',
PRIMARY KEY ("id")
);- Storage: Stored using PostgreSQL's internal 4-byte enum OID storage engine.
- Enforcement: Database engine strictly rejects non-enum string values at the SQL driver boundary.
2. SQLite (TEXT Storage + Inline CHECK Constraints)
SQLite does not have native enum types. Phi creates the column as TEXT and appends an inline SQL CHECK constraint:
Generated DDL:
CREATE TABLE "User" (
"id" TEXT NOT NULL,
"email" TEXT NOT NULL,
"role" TEXT NOT NULL DEFAULT 'STUDENT',
PRIMARY KEY ("id"),
CONSTRAINT "user_role_check" CHECK ("role" IN ('ADMIN', 'STUDENT', 'TEACHER'))
);- Storage: Stored as plain UTF-8
TEXT. - Enforcement:
- Database DDL: SQL
CHECKconstraint prevents invalid strings from being inserted directly via raw SQL. - Application Level: Phi generates
UserRoleTypeGo types with.IsValid()checks, guaranteeing strict type safety before queries hit SQLite.
- Database DDL: SQL
Default Value Formatting
When an @default(...) decorator is added to an enum field in your Prisma schema:
role UserRole @default(STUDENT)Phi's migration engine formats default values for the database DDL:
| Provider | Generated Default SQL | Behavior |
|---|---|---|
| PostgreSQL | DEFAULT 'STUDENT' |
Coerced to "UserRole" enum type by Postgres. |
| SQLite | DEFAULT 'STUDENT' |
Inserted as string default matching TEXT column. |
In Go client builders (Create()), if an optional or defaulted enum field is left unspecified (nil), Phi automatically applies the schema default value during record map computation.
Access Pattern & Naming Conventions
All enum types, constants, and validation methods live in the root generated package (phi):
Root Client Package (`phi`)
- Enum Type:
type UserRoleType string - Enum Values:
phi.UserRole_ADMIN,phi.UserRole_STUDENT,phi.UserRole_TEACHER - Validation Method:
(e UserRoleType).IsValid() bool
role := phi.UserRole_ADMIN
if role.IsValid() {
fmt.Println("Role is valid:", role)
}Model Package (`user`)
The model package (e.g. user) exports predicate builders typed against phi.UserRoleType:
- Field Predicates:
user.Role(typephi.Field[phi.User, phi.UserRoleType])
Usage Examples
1. Inserting Records (`Create` / `CreateMany`)
Pass root enum constants directly to builder Set* methods or struct fields:
u, err := db.User.Create().
SetEmail("student@example.com").
SetPhoneNum("+1001").
SetRole(phi.UserRole_STUDENT).
Exec(ctx)
u2, err := db.User.Create().
SetEmail("admin@example.com").
SetPhoneNum("+1002").
SetRole(phi.UserRole_ADMIN).
Exec(ctx)2. Querying with Enum Predicates
Filter records by enum values using EQ(), NEQ(), In(), and NotIn():
// Find all Teachers or Admins
users, err := db.User.FindMany(
user.Or(
user.Role.EQ(phi.UserRole_TEACHER),
user.Role.EQ(phi.UserRole_ADMIN),
),
).Exec(ctx)
// Using In operator
students, err := db.User.FindMany(
user.Role.In([]phi.UserRoleType{phi.UserRole_STUDENT}),
).Exec(ctx)3. Updating Enum Fields
Update enum values on existing records:
updatedUser, err := db.User.Update(user.Id.EQ("user-123")).
SetRole(phi.UserRole_ADMIN).
Exec(ctx)4. Conflict Updates in Upserts
Set or update enum values during OnConflict upsert execution:
affected, err := db.User.CreateMany(
db.User.Create().SetEmail("user@example.com").SetPhoneNum("+1000").SetRole(phi.UserRole_STUDENT),
).OnConflict(user.Email).Update(func(u *phi.UserUpsert) {
u.Role.Set(phi.UserRole_ADMIN)
}).Exec(ctx)