跳到主要内容

在 Ent 模式中使用 Postgres 扩展

Postgres 扩展 是附加模块,通过提供新的数据类型、运算符、函数、过程语言等功能来扩展数据库的功能。

本指南说明如何使用 PostGIS 扩展提供的数据类型来定义模式字段,并配置模式迁移,以便使用 Atlas 将 Postgres 枚举和 Ent 模式作为单一迁移单元进行管理。

Atlas 只为专业用户提供 扩展支持,使用这些功能需运行:

atlas login

安装 Atlas

要安装Atlas的最新版本,只需在终端中运行以下任一命令,或访问Atlas 官方网站

curl -sSf https://atlasgo.sh | sh

登录 Atlas

$ atlas login a8m
You are now connected to "a8m" on Atlas Cloud.

复合模式

ent/schema 包主要用来定义 Ent 类型(对象),包括字段、边和逻辑等。 postgishstore 等扩展在 Ent 模式中不体现,Postgres 扩展在 Postgres 数据库中安装一次,并在不同的模式中可以使用多次。

为扩展 PostgreSQL 模式以包含自定义复合类型和 Ent 类型,可以配置 Atlas 来读取 复合模式 数据源的模式状态。 跟着以下步骤来配置你的项目:

1. 创建 schema.sql 来定义数据库中使用的必要扩展。同样你可以用 Atlas 模式 HCL 语言 来定义扩展:

schema.sql
-- Install PostGIS extension.
CREATE EXTENSION postgis;

2. 在 Ent 模式中定义扩展提供的数据类型。在本例中我们使用 postgis 扩展提供的 GEOMETRY(Point, 4326) 数据类型:

ent/schema/user.go
// Fields of the User.
func (User) Fields() []ent.Field {
return []ent.Field{
field.Bytes("location").
// Ideally, we would use a custom GoType
// to represent the "geometry" type.
SchemaType(map[string]string{
dialect.Postgres: "GEOMETRY(Point, 4326)",
}),
}
}

3. 使用包含在 schema.sql 和 Ent 模式中定义扩展的 composite_schema 来创建 atlas.hcl 配置文件:

atlas.hcl
data "composite_schema" "app" {
# Install extensions first (PostGIS).
schema "public" {
url = "file://schema.sql"
}
# Then, load the Ent schema.
schema "public" {
url = "ent://ent/schema"
}
}

env "local" {
src = data.composite_schema.app.url
dev = "docker://postgis/latest/dev"
format {
migrate {
diff = "{{ sql . \" \" }}"
}
}
}

使用

设置完复合模式后,我们可以使用 atlas schema inspect 命令来查看其表示、生成迁移或将它们应用到数据库等。以下是几个帮助你开始使用 Atlas 的几个命令:

检查模式

atlas schema inspect 命令通常用来检查数据库。然而我们也可以用它来检查 composite_schema 并打印其 SQL 表示形式:

atlas schema inspect \
--env local \
--url env://src \
--format '{{ sql . }}'

以上命令打印下述 SQL。

-- Add new schema named "public"
CREATE SCHEMA IF NOT EXISTS "public";
-- Set comment to schema: "public"
COMMENT ON SCHEMA "public" IS 'standard public schema';
-- Create extension "postgis"
CREATE EXTENSION "postgis" WITH SCHEMA "public" VERSION "3.4.2";
-- Create "users" table
CREATE TABLE "public"."users" ("id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "location" public.geometry(point,4326) NOT NULL, PRIMARY KEY ("id"));
扩展是数据库层面的对象

尽管 CREATE EXTENSION 命令支持 SCHEMA 参数,但该参数仅用于指定扩展对象的安装位置。扩展本身是在数据库层级安装的,无法被多次加载到不同的模式中。

因此,为避免与其他模式发生冲突,在处理扩展时,迁移范围应设置为数据库级别,其中对象需通过模式名称进行限定。据此,在 atlas.hcl 文件中开发数据库URL的 search_path 已被移除。

为模式生成迁移

运行以下命令为模式生成迁移:

atlas migrate diff \
--env local

注意可生成以下内容的新的迁移文件:

migrations/20240712090543.sql
-- Create extension "postgis"
CREATE EXTENSION "postgis" WITH SCHEMA "public" VERSION "3.4.2";
-- Create "users" table
CREATE TABLE "public"."users" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"location" public.geometry(point,4326) NOT NULL,
PRIMARY KEY ("id")
);

应用迁移

运行以下命令将生成的迁移应用到数据库:

atlas migrate apply \
--env local \
--url "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable"
将模式直接应用于数据库

有时需要在不生成迁移文件的时候将模式直接应用于数据库。例如,尝试模式变更、创建测试数据库等。这种情况下,可以使用下面的命令将模式直接应用于数据库:

atlas schema apply \
--env local \
--url "postgres://postgres:pass@localhost:5432/database?sslmode=disable"

或使用 Atlas Go SDK

ac, err := atlasexec.NewClient(".", "atlas")
if err != nil {
log.Fatalf("failed to initialize client: %w", err)
}
// Automatically update the database with the desired schema.
// Another option, is to use 'migrate apply' or 'schema apply' manually.
if _, err := ac.SchemaApply(ctx, &atlasexec.SchemaApplyParams{
Env: "local",
URL: "postgres://postgres:pass@localhost:5432/database?sslmode=disable",
AutoApprove: true,
}); err != nil {
log.Fatalf("failed to apply schema changes: %w", err)
}

本指南的代码参见 GitHub