Rust in Everything
基于 sea-orm 2.0.4

迁移与 schema

前面几部分都假设表已经在那里。这一部分讲表从哪里来。sea-orm 给了两条路:手写迁移,由 sea-orm-migration(src/ 2 388 行)按顺序执行并记账;或者 2.0 新增的 schema sync,由 sea-orm 本体的 src/schema/(1 848 行)读出数据库现有的结构,按实体补齐。两条路共用同一套「实体 → DDL」的翻译:Schema::create_table_from_entity 和它的两个兄弟函数,生成的都是 sea-query 的 TableCreateStatement 这类语句树,最后经过 ConnectionTrait::execute 发出去。

  1. sea-orm-migration:MigrationTrait / MigratorTrait;seaql_migrations 只有 version 和 applied_at,改了已执行的迁移发现不了,改名会报 Migration file of version '...' is missing;2.0 在 Postgres 上每个迁移一个事务(use_transaction 可关),1.1.20 是整批一个;没有锁,两个实例同时迁移的三种报错;fresh 会删掉 schema 里所有的表;命令行的默认值。
  2. SchemaManager 与从实体建表:SchemaManager 只是把语句交给连接;create_table_from_entity 推得出列、主键、UNIQUE、默认值和外键,索引和 enum 类型要另外生成;2.0 的自增主键是 IDENTITY;为什么不该在迁移里用它。
  3. Entity First:schema sync:inventory 收集实体、按模块前缀挑选;按外键拓扑排序;逐项比较后加表、加列、改名、加外键、删多余的唯一键,改类型只警告,删字段什么也不做;2.0.4 上两种会卡住之后所有 sync 的情况。
flowchart TB
  ent["实体 DeriveEntityModel"] --> schema["Schema 实体到 DDL"]
  hand["手写迁移 MigrationTrait"] --> sm["SchemaManager"]
  schema -->|"可选"| sm
  sm --> migr["Migrator up / down"]
  migr --> rec["seaql_migrations 记账"]
  schema --> sb["SchemaBuilder"]
  sb -->|"apply"| ddl["CREATE 全部"]
  sb -->|"sync"| cmp["读现有结构再补齐"]
  migr --> conn["execute"]
  ddl --> conn
  cmp --> conn

sqlx 自带的迁移器(.sql 文件、校验和、advisory lock)在 sqlx 卷的迁移,第一页末尾有两者的对照。

💬 关联讨论

发起讨论
加载中...