Help us shape the future of Go! Take the 2026 Go Developer Survey

schemamigrate

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 3, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package schemamigrate 封装 GORM AutoMigrate 和 SQL 种子校准,提供项目可复用的数据库初始化能力。 项目维护 Model 清单,在基础设施初始化后、业务服务启动前调用;不手工维护迁移版本。

以下示例需导入 context、gorm.io/gorm 和 github.com/bpcoder16/pixiu/infra/schemamigrate:

func migrate(ctx context.Context, masterDB func(context.Context) *gorm.DB) error {
	type Card struct {
		ID uint64 `gorm:"primaryKey"`
		Name string `gorm:"size:100;index:idx_card_name"`
	}
	_, err := schemamigrate.Apply(ctx, masterDB, []schemamigrate.Table{{
		Model: &Card{},
		Name: "cards",
		Comment: "卡片",
	}})
	return err
}

每次调用只按清单顺序对显式登记的表执行 AutoMigrate,由 GORM 处理列、索引及唯一/检查约束。 迁移会话统一忽略模型关联及其外键,不自动创建或更新关联表、多对多中间表,也不删除已有外键。 需要迁移的关联表和中间表须单独登记;关联外键由项目显式管理。 Model 可以保留关联字段,关联 ID 等普通列照常迁移;本包不修改调用方的 GORM 配置。 不计算 Model 哈希,不创建/读取迁移状态表,不提供迁移锁、Check/Verify 或自定义方言协议。 保留统一的 Table、Apply 和 bootstrap 接入,后续优化集中在 Pixiu,不要求项目直接调用 GORM。

Name 为空时沿用 GORM 命名;显式 Name 只接受字母、数字和下划线,用于物理分表。 登记表的最终表名均不得包含点号,例如 testdb.cards;即使前缀是当前库名也会在 DDL 前拒绝。 此限制覆盖显式 Name、Model 的 TableName 和 NamingStrategy;未登记的关联不作为迁移目标校验。 不支持库名或 schema 限定名,目标数据库由传入的连接选定,本包不解析库名或切库。 MySQL 建表使用 InnoDB;可指定 Charset/Collation,仅用于建表,不转换已有表。 每张登记表独立使用自己的建表选项,不展开关联,也不检查或调整关联依赖顺序。 非空 Comment 单独维护 MySQL 表注释,仅变化时执行 ALTER TABLE。 空 Comment 表示不管理注释,不会清空已有注释。其他方言设置这些 MySQL 选项会报错。 不带上述选项时直接使用连接现有的 GORM 方言;本包用 SQLite 验证通用流程、MySQL 验证专属行为。 不要把不归项目管理的表登记到迁移清单。

每次传入非 nil Context,主库提供函数返回无历史查询条件的会话;不接受外部事务或 DryRun。 空清单不获取数据库。本包不创建/关闭连接池,Apply 只执行表结构迁移。 错误保留底层错误链,Report 包含已处理表及首个失败表;applied 仅表示 AutoMigrate 成功, 不区分创建、更新或无变化。调用方处理失败,不应忽略错误后开放业务入口。

第一版接受每次启动检查所有登记表的成本。没有跨实例迁移锁,发布时避免多个实例同时迁移。 MySQL DDL 可能部分生效、持锁或超时,不能保证整批回滚;复杂数据修复留在项目显式执行。 旧试验版的 pixiu_schema_states 不再参与执行,组件不会自动删除已有表或记录。

SQL 种子由项目维护文件和 []Seed 声明,通过 ApplySeeds(ctx, masterDB, files, seeds) 显式执行。 files 接受 fs.FS(如 embed.FS);Model 只用于解析物理表名,Where 用于计数及删除范围。 每个有效行是一条以分号结束的 INSERT INTO,每条必须插入一行;空行与 -- 整行注释不计数。 关键字不区分大小写;不拆分 SQL 中的分号,不支持跨行 SQL、块注释或其他语句。 空文件报错,不能以空文件表达清空;文件来自可信部署代码,本包不解析 SQL 或隔离其写入权限。 调用方必须保证 SQL 的目标表和插入数据符合对应 Model/Where,数据库表须支持事务。

每项先比较有效 SQL 行数与 Where 范围内的物理记录数(包括软删除记录)。 相同则跳过写入,保留现有内容;不同则在事务内 DELETE 该范围并重新导入。 Where 为空时明确作用于整表;不使用 TRUNCATE,不重置自增序列。 计数和删除直接作用于物理表,不运行模型钩子或隐式附加 Model 的字段值、软删除条件。 每条 INSERT 检查 RowsAffected 为 1,完成后再次核对范围内数量;不满足约定则回滚本项。 错误包含文件路径及适用的行号,保留底层错误与 Context 取消/超时语义。 单项失败恢复其删除和插入并停止后续执行,之前成功的项已独立提交;不接受外部事务和 DryRun。 调用方提供带期限的 Context 限制整批执行;fs.FS 读取本身不可被 Context 中断,推荐本地内嵌文件。

种子按数量校准,不比较内容;同数量下修改 SQL 不会覆盖数据库。 数量变化会覆盖该范围的自定义内容,并可能改变自增 ID;只用于允许整体重建的受管数据。 没有跨实例锁,应由单个实例在业务流量进入前执行;复杂业务回填仍由项目显式管理。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ApplySeeds

func ApplySeeds(ctx context.Context, masterDB func(context.Context) *gorm.DB, files fs.FS, seeds []Seed) error

ApplySeeds 比较有效 SQL 行数与 Where 范围内的物理记录数,相同则保留现有数据。 不同则在单项事务内删除该范围并重新插入;失败回滚本项并停止,之前的项保持已提交。 空清单不获取数据库;调用方用 Context 限制整批期限,并负责单实例执行。 SQL 的实际写入范围由调用方保证,本包不解析 SQL 或提供权限隔离。

Types

type Report

type Report struct{ Tables []TableResult }

Report 保留按登记顺序完成的结果;失败时前面的 DDL 可能已经生效。

func Apply

func Apply(ctx context.Context, masterDB func(context.Context) *gorm.DB, tables []Table) (Report, error)

Apply 通过已有主库执行 GORM AutoMigrate,不创建连接池、状态表或迁移锁。 仅按清单顺序迁移登记表,忽略模型关联及其外键,不修改调用方的 GORM 配置。 空清单不调用 masterDB;错误保留底层错误链,调用方负责整体超时和启动失败处理。

type Seed

type Seed struct {
	// Model 仅用于解析物理表名,不使用其字段值、软删除过滤或模型钩子。
	Model any
	// Where 指定计数及物理删除的条件;为空时作用于整张表。
	Where map[string]any
	// File 为 fs.FS 内的文件路径;每个有效行是一条以分号结束、插入一行的 INSERT INTO。
	File string
}

Seed 声明一项按记录数校准的 SQL 种子,SQL 必须来自可信部署文件。

type Table

type Table struct {
	// Model 为必填的 GORM 模型,用于解析待迁移的表结构。
	Model any
	// Name 指定物理表名,仅允许字母、数字和下划线;为空时沿用 GORM 命名。
	Name string
	// Comment 指定 MySQL 表注释;为空时不管理或清空已有注释。
	Comment string
	// Charset 指定 MySQL 建表字符集,不转换已有表;为空时使用数据库默认值。
	Charset string
	// Collation 指定 MySQL 建表排序规则,需同时设置 Charset,不转换已有表。
	Collation string
}

Table 声明项目维护的表。Name 为空时沿用 GORM 命名;非空时用于指定物理分表。 只迁移显式登记的表;最终表名不得包含点号,不支持库名或 schema 限定名。 Comment、Charset、Collation 为可选 MySQL 设置;空 Comment 表示不管理表注释。 Charset/Collation 仅用于建表,不转换已有表。

type TableResult

type TableResult struct {
	Name   string
	Action string
}

TableResult 的 Action 为 applied 或 failed;applied 表示 AutoMigrate 成功,不保证实际执行了 DDL。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL