在 Ent Schema 中使用 Postgres 枚举类型
枚举类型是由预定义有序值集合组成的数据结构。默认情况下,在 Ent schema 中使用 field.Enum 时,Ent 会使用简单的字符串类型来表示 PostgreSQL 和 SQLite 中的枚举值。但在某些情况下,您可能需要使用数据库本身提供的原生枚举类型。
本指南将介绍如何定义使用原生 PostgreSQL 枚举类型的 schema 字段,并配置 schema 迁移,使用 Atlas 将 Postgres 枚举和 Ent schema 作为单一迁移单元进行管理。
本指南中使用的 Atlas 组合式 Schema 支持是 Pro 用户的专享功能。要使用此功能,请运行:
atlas login
安装 Atlas
To install the latest release of Atlas, simply run one of the following commands in your terminal, or check out the Atlas website:
- macOS + Linux
- Homebrew
- Docker
- Windows
curl -sSf https://atlasgo.sh | sh
brew install ariga/tap/atlas
docker pull arigaio/atlas
docker run --rm arigaio/atlas --help
If the container needs access to the host network or a local directory, use the --net=host flag and mount the desired
directory:
docker run --rm --net=host \
-v $(pwd)/migrations:/migrations \
arigaio/atlas migrate apply
--url "mysql://root:pass@:3306/test"
Download the latest release and move the atlas binary to a file location on your system PATH.
登录 Atlas
$ atlas login a8m
您现已连接至 Atlas Cloud 上的 "a8m" 账户。
组合式 Schema
ent/schema 包主要用于定义 Ent 类型(对象)、它们的字段、边和逻辑。外部枚举类型或任何其他数据库对象在 Ent 模型中没有表示形式——Postgres 枚举类型可以在 Postgres schema 中定义一次,并在不同字段和模型中多次使用。
为了扩展我们的 PostgreSQL schema 以包含自定义枚举类型和 Ent 类型,我们配置 Atlas 从组合式 Schema 数据源读取 schema 状态。请按照以下步骤为您的项目进行配置:
1. 创建一个 schema.sql 文件,在其中定义必要的枚举类型。同样地,您也可以用 Atlas Schema HCL 语言定义枚举类型:
- 使用 SQL
- 使用 HCL
CREATE TYPE status AS ENUM ('active', 'inactive', 'pending');
schema "public" {}
enum "status" {
schema = schema.public
values = ["active", "inactive", "pending"]
}
2. 在您的 Ent schema 中,定义一个使用底层 Postgres ENUM 类型的枚举字段:
// User 的字段。
func (User) Fields() []ent.Field {
return []ent.Field{
field.Enum("status").
Values("active", "inactive", "pending").
SchemaType(map[string]string{
dialect.Postgres: "status",
}),
}
}
如果使用了带有自定义驱动程序特定类型的 schema 与其他数据库一起使用,Ent 将回退到驱动程序使用的默认类型(例如,SQLite 中的 TEXT 以及 MariaDB 或 MySQL 中的 ENUM (...))。
3. 创建一个简单的 atlas.hcl 配置文件,其中包含一个 composite_schema,它同时包含了在 schema.sql 中定义的自定义枚举类型和您的 Ent schema:
data "composite_schema" "app" {
# 首先加载自定义类型。
schema "public" {
url = "file://schema.sql"
}
# 其次加载 Ent schema。
schema "public" {
url = "ent://ent/schema"
}
}
env "local" {
src = data.composite_schema.app.url
dev = "docker://postgres/15/dev?search_path=public"
}
使用方式
设置好组合式 schema 后,我们可以使用 atlas schema inspect 命令获取其表示形式,为其生成 schema 迁移,将其应用到数据库等。以下是一些让您开始使用 Atlas 的命令:
检查 Schema
atlas schema inspect 命令通常用于检查数据库。但我们也可以使用它来检查我们的 composite_schema 并打印其 SQL 表示形式:
atlas schema inspect \
--env local \
--url env://src \
--format '{{ sql . }}'
上述命令会打印以下 SQL。请注意,status 枚举类型在 users.status 列中使用之前已在 schema 中定义:
-- 创建枚举类型 "status"
CREATE TYPE "status" AS ENUM ('active', 'inactive', 'pending');
-- 创建 "users" 表
CREATE TABLE "users" ("id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "status" "status" NOT NULL, PRIMARY KEY ("id"));
为 Schema 生成迁移
要为 schema 生成迁移,请运行以下命令:
atlas migrate diff \
--env local
请注意,这会创建一个新的迁移文件,其内容如下:
-- 创建枚举类型 "status"
CREATE TYPE "status" AS ENUM ('active', 'inactive', 'pending');
-- 创建 "users" 表
CREATE TABLE "users" ("id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "status" "status" NOT NULL, PRIMARY KEY ("id"));
应用迁移
要将上面生成的迁移应用到数据库,请运行以下命令:
atlas migrate apply \
--env local \
--url "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable"
有时需要直接在数据库上应用 schema 而不生成迁移文件。例如,在试验 schema 更改、启动测试数据库等情况下。在这种情况下,您可以使用以下命令直接将 schema 应用到数据库:
atlas schema apply \
--env local \
--url "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable"
或者,使用 Atlas Go SDK:
ac, err := atlasexec.NewClient(".", "atlas")
if err != nil {
log.Fatalf("failed to initialize client: %w", err)
}
// 自动使用期望的 schema 更新数据库。
// 另一种选择是手动使用 'migrate apply' 或 'schema apply'。
if _, err := ac.SchemaApply(ctx, &atlasexec.SchemaApplyParams{
Env: "local",
URL: "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable",
AutoApprove: true,
}); err != nil {
log.Fatalf("failed to apply schema changes: %w", err)
}
本指南的代码可以在 GitHub 上找到。