Files
doodle-store/apps/server/prisma/sql/README.md
T
2026-10-15 10:09:34 +08:00

183 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# v3.5 PostgreSQL 初始化 SQL
基于 [数据库设计](../../../../docs/v3.5/数据库设计文档.md),面向 PostgreSQL 18。缩进统一 4 个空格;文件是普通 PostgreSQL SQL,可使用 psql 或数据库客户端执行。
2026-10-12 已在本地 PostgreSQL 18.6 临时数据库执行 001/002/003,并重复执行 003 验证不覆盖 enabled=false;10 张表与 19 项关键约束检查通过,历史 NULL 事件、标识大小写及资产所有者删除行为符合设计。验证库已删除;随后已在用户授权下正式初始化 doodle_dev,10 张表与两条配置记录核对通过。
| 文件 | 作用 | 执行位置 |
| -------------------------------------------------------------------------------------------------- | ---------------------------------------------- | ---------------------------------------------------------- |
| [001-create-database.sql](./001-create-database.sql) | 创建 UTF-8 / C locale / UTC 的 doodle_dev | 连接 postgres 管理数据库,有 CREATEDB 权限;不能包在事务里 |
| [002-create-tables.sql](./002-create-tables.sql) | 创建 13 张表、约束、索引与注释 | 连接目标空数据库;单事务执行 |
| [003-initialize-settings.sql](./003-initialize-settings.sql) | 初始化 current 页面配置及 homeAutoRefresh 开关 | 连接已建表数据库;可重复执行且不覆盖旧值 |
| [004-remove-users-mini-app-id.sql](./004-remove-users-mini-app-id.sql) | 单小程序身份简化,OpenID 唯一 | 仅旧版基线库,成功后不重复执行 |
| [005-add-worksheet-resources.sql](./005-add-worksheet-resources.sql) | 增加绘制配置、多文件内容及下载内容标识 | 仅未执行此升级的既有库,单事务执行 |
| [006-add-worksheet-grades.sql](./006-add-worksheet-grades.sql) | 增加功能适用年级关系 | 已完成 004/005 的既有库;不自动回填旧 grade |
| [007-add-publication-and-resource-downloads.sql](./007-add-publication-and-resource-downloads.sql) | 功能/资源首次发布时间及资源下载量 | 已完成 004/005/006 的既有库;旧时间不推算、旧计数不分摊 |
| [008-add-resource-favorites.sql](./008-add-resource-favorites.sql) | 统一收藏功能与具体内容、两种部分唯一索引 | 已完成 004~007 的既有库,旧收藏保持功能目标 |
Docker 已在首次启动时创建 doodle_dev,**当前本地跳过 001**。其他环境显式修改 001 的数据库名并用对应角色执行;本次不自动创建云端数据库、生产账号或测试库,不在 SQL 中硬编码密码。生产角色和权限在部署时落实。
## 最新执行路径
当前本地 doodle_dev 已执行至 008,使用最新 13 张表;不重跑 002 或任何已成功的增量 SQL。
| 数据库当前状态 | 升级至最新的执行顺序 |
| ---------------------- | ------------------------------------------------------ |
| 空库 | 002 → 003;未建库时先执行 001,Docker 已建库则跳过 001 |
| 最初 10 张表的旧基线库 | 004 → 005 → 006 → 007 → 008 |
| 已执行部分增量的库 | 按编号顺序执行尚未应用的后续文件 |
| 已执行 008 的库 | 无需再次执行 DDL |
004~008 是历史结构的升级文件,不能用于已执行最新 002 的空库基线。下文各阶段记录解释该次变更,不表示只完成其中某一步就已到最新结构。Prisma 迁移历史尚未接入,执行前依据实际结构及执行记录确认当前版本。
## 空库初始化示例
从 `doodle-store` 根目录执行,以下仅适用于尚未建表的目标库。根 `.env` 当前指向已初始化的 doodle_dev,不在现有库再次运行 002。
```bash
pnpm infra:up
docker compose --env-file .env -f infra/compose.yaml exec -T postgres \
sh -c 'exec psql -X -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
< apps/server/prisma/sql/002-create-tables.sql
docker compose --env-file .env -f infra/compose.yaml exec -T postgres \
sh -c 'exec psql -X -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
< apps/server/prisma/sql/003-initialize-settings.sql
```
002 用显式 CREATE TABLE 而非 IF NOT EXISTS;已有同名表时返回错误并回滚,不覆盖已有结构或数据。它是空库基线,不是可反复执行的增量迁移;后续结构修改写新迁移文件。003 的重复执行不会覆盖导入内容、已递增版本或 enabled=false。
```sql
SELECT tablename FROM pg_tables WHERE schemaname = 'public' ORDER BY tablename;
SELECT id, version FROM public.page_configs;
SELECT id, value FROM public.settings;
```
最新基线预期业务表共 13 张,页面配置有 current,设置有 homeAutoRefresh。2026-10-12 已在本地 doodle_dev 执行 002/003 并核对通过,当时已有 10 张表;不要再次执行 002。独立临时库验证与正式本地初始化分别记录,未连接云服务器。
## 实施边界
- 字符串主键保留旧 ID,应用生成新 ID;所有身份/对象标识使用 C 排序规则。
- 收藏/下载的用户外键限制直接删除;注销需先清关系、处理计数,再删用户。题型仅逻辑关联,保留缺失题型历史。
- 资产 ready 必填元数据、avatar 必须 private;资产归属、用途匹配、签名地址、远程 URL 白名单和文件存在性仍由服务端校验。
- 下载 NULL exportId 只允许 import 来源;非空事件按 userId + exportId 去重。计数不会通过触发器自动更新,由后续业务事务实现。
- tags 元素类型、分类多层循环、任务租约/锁、JWT 失效与管理员权限由后续业务实现;SQL 不代表业务 API 已完成。
- updatedAt 和 contentUpdatedAt 由服务显式维护,不添加把两者混为一谈的更新时间触发器。
- Prisma 尚未安装,Schema 和迁移历史尚未接入。后续接入时将本 SQL 纳入正式基线;已有表的库须采用基线登记流程,不能直接再次执行同一 DDL。
## 单小程序身份简化(2026-10-14)
最新 002 已移除 users.mini_app_id,改为 users.openid 唯一,AppID 由服务端配置。
已执行旧版 002 的库使用 `004-remove-users-mini-app-id.sql` 增量升级;不要重跑 002。
新建库执行最新 002/003 即可,不执行 004。004 会先建立 OpenID 唯一约束,
如存在重复则全部回滚,不自动合并或删除用户;成功执行后不可重复执行。
2026-10-14 已在本地 doodle_dev 执行 004 并核对:mini_app_id 已移除,users_openid_key 为 UNIQUE (openid);执行时用户表为空。
## Worksheet 多资源扩展(2026-10-14)
设计原因见 [Worksheet 数据库设计说明](../../../../docs/v3.5/Worksheet数据库设计说明.md)。
最新 002 新建 13 张表;worksheet 增加 generation_mode、renderer_key、render_config,新增
worksheet_resources、worksheet_resource_assets,assets 支持 worksheet_source 用途,
download_logs 增加可空 worksheet_resource_id。文件关联首期只有 outline/reference,无文件级配置。
- 新空库:执行最新 002 → 003;不要执行 004/005/006/007/008,它们的结果已经包含在基线里。
- 2026-10-12 旧基线库:先执行 004(若尚未执行),再执行 005。
- 已执行 004 的本地库:只执行 005;不要重跑 002 或 004。
- 005 为单事务增量升级,成功后不可重复执行;不使用 IF NOT EXISTS 隐藏结构差异。
```bash
docker compose --env-file .env -f infra/compose.yaml exec -T postgres \
sh -c 'exec psql -X -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
< apps/server/prisma/sql/005-add-worksheet-resources.sql
```
旧 worksheet 的 ID/path、计数、预览及历史不变;新列默认 procedural、NULL renderer_key 和 {}。
导入时按实际功能核对,NULL renderer_key 仅供已登记的旧版映射兼容;新功能发布必须明确实现。
不把旧题型预览自动转为线框或参考资源,资源新表默认空。下载资源 ID 为逻辑关联,服务端需校验归属。
2026-10-14 验证记录:在两个隔离临时库分别执行最新 002/003 与旧版 002/003 + 005,
列定义、约束、索引及注释一致(忽略新增列的物理顺序)。两条路径均通过多线框、共享资产、
双用途引用、独立预览、JSON/状态/唯一性/外键/删除限制、旧数据保留与历史逻辑关联检查。
临时库均已删除;本地 doodle_dev 已执行 005,核对为 12 张表,current/homeAutoRefresh 保留,
两张资源新表为空,未导入测试内容或连接生产库。
## 多适用年级(2026-10-14)
categories 结构保持不变,新增 worksheet_grades(worksheet_id、grade),联合主键防重复,
反向索引供年级菜单筛选。固定编码 -4~6,0 为幼小衔接;不新增年级字典或菜单表。
旧 worksheets.grade 保留原值,关系表作为新适用年级筛选的唯一权威来源。
最新空库执行 002/003,跳过 004/005/006/007/008;已执行 005 的库仅执行 006。
更早的库先按版本补齐未执行的增量文件,不重复执行成功的 SQL。006 单事务、非重复执行脚本,
不自动从旧 grade 或年龄回填关系;经审核的 worksheetId → grades 映射另行导入。
无关系表示未配置,不表示全年级;年级筛选上线前完成对应题型的映射审核。
```bash
docker compose --env-file .env -f infra/compose.yaml exec -T postgres \
sh -c 'exec psql -X -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
< apps/server/prisma/sql/006-add-worksheet-grades.sql
```
2026-10-14 验证:最新 002/003 与旧版基线 + 006 在两个隔离库中生成相同的列、约束、
索引及注释;多/不连续年级、合法编码边界、联合主键、外键、删除限制、旧值保留、
不自动回填及分类/年级组合查询不重复检查通过。临时库已删除。
本地 doodle_dev 已执行 006,共 13 张表;worksheet_grades 为空,初始配置保留。
## 首次发布与资源下载统计(2026-10-14)
最新空库只执行 002/003;已执行 006 的既有库执行 007,不重跑旧迁移。
007 在功能及内容上增加可空 first_published_at(无默认值),内容增加非负 downloads(默认 0)。
旧 is_new 保留为兼容值,is_hot 保留为功能运营推荐;不新增资源新品/热门布尔值、收藏计数或 seed。
未知旧发布时间保持 NULL,首次发布/新品派生及下载幂等事务由后续服务端业务实现。
文件访问、日志数量、创建时间和升级时间都不能冒充真实历史依据。
```bash
docker compose --env-file .env -f infra/compose.yaml exec -T postgres \
sh -c 'exec psql -X -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
< apps/server/prisma/sql/007-add-publication-and-resource-downloads.sql
```
新结构仍为 13 张表。正常资源下载的日志及两层 downloads 由同一事务维护,不使用触发器自动加数。
功能原累计值不覆盖或分摊,资源默认 0;旧单独保存的 is_new 不变,不能据此伪造时间。
2026-10-14 验证:最新 002/003 与旧版基线 + 007 在两个临时库生成相同列、约束、索引及注释。
旧标记/计数/未知发布时间保留、资源默认 0、非负约束和独立发布时间检查通过;
SQL 事务示例通过重复事件不加数、任一步失败全回滚、删除日志不扣累计的验证。
这些验证不代表真实下载 API 已实现。临时库已清理;本地 doodle_dev 已执行 007,仍为 13 张表,
新时间列可空且无默认值,资源 downloads 默认 0、NOT NULL 且非负,原初始配置保留。
## 统一功能与内容收藏(2026-10-14)
最新空库执行 002/003,跳过 004~008;已执行 007 的既有库仅执行 008,不重复已成功 SQL。
008 新增 favorites.worksheet_resource_id,旧记录为 NULL;撤销旧全局唯一约束,
创建功能和内容两个部分唯一索引。不新增资源收藏表/type 字段或资源 likes,仍为 13 张表。
旧收藏 ID、时间、归属和功能 likes 不变。新内容 ID 为逻辑关联,归属由服务校验,缺失不 SET NULL。
```bash
docker compose --env-file .env -f infra/compose.yaml exec -T postgres \
sh -c 'exec psql -X -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
< apps/server/prisma/sql/008-add-resource-favorites.sql
```
后续收藏 INSERT 的 ON CONFLICT 需带对应部分索引谓词,Prisma 接入时保留原生索引。
旧查询/数量/取消加 IS NULL;新资源关系不增减功能 likes,注销清理两类但仅扣功能贡献。
本次仅修改数据库与接口契约,资源收藏 API 及小程序页面尚待实现。
2026-10-14 验证:最新基线与旧版基线 + 008 的列、约束、索引、注释一致;
旧收藏保留、功能和同功能多资源共存、两种部分唯一索引/ON CONFLICT、用户隔离、
旧功能取消范围、资源取消不扣 likes、下架/失联目标保留及注销 SQL 示例通过。
临时验证库已删除;本地 doodle_dev 已执行 008,仍为 13 张表,两种部分索引生效,
原配置保留,未导入测试收藏。验证不代表业务 API 或小程序资源收藏页面已经实现。
## 最终对齐核查(2026-10-14)
- 设计文档与最新 002 的 13 张表、135 个字段名称/类型/可空/默认值一致。
- 实测 001 建隔离库;最新 002/003、原始旧基线 + 004~008 全链路、本地 doodle_dev 的列、约束、索引和注释一致,忽略物理列顺序。
- 完整升级保留旧身份、功能、收藏、历史及计数;003 重复执行不覆盖关闭开关、页面内容及版本。
- 最新基线下的资源、年级、发布/下载、两种收藏约束与 SQL 事务示例回归通过,标识列 C 排序规则核对通过。
- 所有临时核查库已清理;开发库只读比对,无样本写入。本次只修正文档说明,无需新增 DDL 或再次升级开发库。
业务归属/权限、首次发布、计数和审计事务、任务调度等仍需服务端接入;SQL 验证不代替业务 API 验收。