# 设计文档:数据库文档整理与补全 ## 概述 本特性对 `docs/bd_manual/` 目录进行系统性整理和补全,涵盖四个核心工作流: 1. **目录结构规范化** — 统一各层目录布局,新增 `ETL_Admin/` 层和根目录 `README.md` 索引 2. **DDL 对比同步** — 编写 Python 脚本对比四个 schema 的 DDL 文件与数据库实际状态,以数据库为准修正 DDL 3. **ODS 表级文档补全** — 为 `billiards` schema 下所有 ODS 表生成 Markdown 表级文档 4. **API→ODS 字段映射文档** — 建立 API JSON 响应到 ODS 表字段的映射关系文档 本特性以文档和 DDL 维护为主,不涉及业务代码逻辑变更。DDL 修正属于 `database/` 高风险路径,完成后需触发 `/audit`。 ## 架构 ```mermaid graph TD subgraph 信息来源 DB[(PostgreSQL 数据库)] DDL[database/schema_*.sql] API_REF[docs/api-reference/] PARSERS[models/parsers.py] COMMENTS[DDL COMMENT ON 注释] end subgraph 对比脚本 COMPARE[scripts/compare_ddl_db.py] end subgraph 文档产出 README[docs/bd_manual/README.md] ODS_DOCS[docs/bd_manual/ODS/main/*.md] ODS_MAP[docs/bd_manual/ODS/mappings/*.md] ODS_DICT[docs/dictionary/ods_tables_dictionary.md] ETL_DOCS[docs/bd_manual/ETL_Admin/main/*.md] CHANGES[docs/bd_manual/*/changes/*.md] DDL_FIX[database/schema_*.sql 修正] end DB -->|information_schema 查询| COMPARE DDL -->|解析 CREATE TABLE| COMPARE COMPARE -->|差异报告| CHANGES COMPARE -->|修正| DDL_FIX DB -->|表结构 + COMMENT| ODS_DOCS COMMENTS -->|字段说明| ODS_DOCS API_REF -->|端点信息| ODS_MAP PARSERS -->|转换逻辑| ODS_MAP DB -->|表概览| ODS_DICT DB -->|表结构| ETL_DOCS ``` ## 组件与接口 ### 1. DDL 对比脚本 (`scripts/compare_ddl_db.py`) 一个独立的 Python 脚本,用于对比 DDL 文件与数据库实际状态。 **输入**: - DDL 文件路径(`database/schema_*.sql`) - 数据库连接(通过 `PG_DSN` 环境变量或 `--pg-dsn` 参数) **输出**: - 控制台差异报告(表级、字段级、类型级) - 可选:`--fix` 模式直接修正 DDL 文件 **对比逻辑**: - 从 `information_schema.columns` 查询数据库实际表结构 - 解析 DDL 文件中的 `CREATE TABLE` 语句提取表名和字段定义 - 逐表逐字段对比:表是否存在、字段是否存在、字段类型是否一致、约束是否一致 - 差异分类:`MISSING_TABLE`(DDL 缺表)、`EXTRA_TABLE`(DDL 多表)、`MISSING_COLUMN`、`EXTRA_COLUMN`、`TYPE_MISMATCH`、`NULLABLE_MISMATCH` **接口**: ```python def compare_schema(ddl_path: str, schema_name: str, pg_dsn: str) -> list[SchemaDiff] ``` ### 2. ODS 表级文档生成器 手动编写(非自动生成脚本),参考以下信息来源: - 数据库 `information_schema.columns` 获取字段名、类型、可空性 - DDL 文件中的 `COMMENT ON` 注释获取字段说明、示例值、JSON 字段映射 - 现有 DWD/DWS 表级文档格式作为模板 ### 3. API→ODS 映射文档 手动编写,参考以下信息来源: - `docs/api-reference/endpoints/*.md` — API 端点路径、请求参数、响应字段 - `docs/api-reference/samples/*.json` — JSON 响应样本 - `models/parsers.py` — `TypeParser` 类中的类型转换方法 - DDL 文件中的 `COMMENT ON` 注释中的 `【JSON字段】` 标注 ### 4. 目录结构与索引 **新增目录**: - `docs/bd_manual/ETL_Admin/main/` - `docs/bd_manual/ETL_Admin/changes/` - `docs/bd_manual/ODS/mappings/` **新增文件**: - `docs/bd_manual/README.md` — 根索引,列出目录结构和各层文档清单 ## 数据模型 本特性不引入新的数据模型。涉及的现有 schema 如下: | Schema | DDL 文件 | 用途 | 预估表数 | |--------|----------|------|----------| | `billiards_ods` | `database/schema_ODS_doc.sql` | 原始数据存储 | ~22 张 | | `billiards_dwd` | `database/schema_dwd_doc.sql` | 明细数据层 | ~22 张(含 Ex) | | `billiards_dws` | `database/schema_dws.sql` | 数据服务层 | ~30 张 | | `etl_admin` | `database/schema_etl_admin.sql` | ETL 管理元数据 | ~5 张 | ### 文档模板格式 **ODS 表级文档模板**(与 DWD/DWS 保持一致): ```markdown # {表名} {中文说明} > 生成时间:YYYY-MM-DD ## 表信息 | 属性 | 值 | |------|-----| | Schema | billiards | | 表名 | {表名} | | 主键 | {主键字段} | | 数据来源 | {API 端点 / JSON 文件} | | 说明 | {表说明} | ## 字段说明 | 序号 | 字段名 | 类型 | 可空 | 说明 | |------|--------|------|------|------| | 1 | ... | ... | ... | ... | ## 使用说明 {SQL 示例} ## 可回溯性 | 项目 | 说明 | |------|------| | 可回溯 | ✅ 完全可回溯(保留 payload 原始 JSON) | | 数据来源 | {API 端点路径} | ``` **API→ODS 映射文档模板**: ```markdown # {API端点名} → {ODS表名} 字段映射 > 生成时间:YYYY-MM-DD ## 端点信息 | 属性 | 值 | |------|-----| | 接口路径 | {路径} | | 请求方法 | POST | | ODS 对应表 | {表名} | | JSON 数据路径 | {如 data.tenantMemberInfos} | ## 字段映射 | JSON 字段 | ODS 列名 | 类型转换 | 说明 | |-----------|----------|----------|------| | id | id | int→BIGINT | 主键 | | ... | ... | ... | ... | ## ETL 补充字段 | ODS 列名 | 生成逻辑 | |-----------|----------| | content_hash | 对业务字段计算 SHA256 | | source_file | 固定值:{文件名}.json | | source_endpoint | API 端点路径 | | fetched_at | 入库时间戳 | | payload | 完整原始 JSON 记录 | ## 类型转换规则 - 时间戳:通过 `TypeParser.parse_timestamp()` 转换,支持字符串和 Unix 毫秒时间戳 - 金额:通过 `TypeParser.parse_decimal(value, scale=2)` 转换,ROUND_HALF_UP - 整数:通过 `TypeParser.parse_int()` 转换 ``` ## 正确性属性 *属性是系统在所有有效执行中都应保持为真的特征或行为——本质上是关于系统应该做什么的形式化陈述。属性是人类可读规格说明与机器可验证正确性保证之间的桥梁。* ### Property 1: 数据层目录结构一致性 *For any* 数据层目录(ODS、DWD、DWS、ETL_Admin),该目录下都应包含 `main/` 和 `changes/` 两个子目录。 **Validates: Requirements 1.2** ### Property 2: DDL 对比脚本差异检测完整性 *For any* schema 和对应的 DDL 文件,当数据库中存在 DDL 文件未定义的表或字段时,对比脚本应将其报告为 `MISSING_TABLE` 或 `MISSING_COLUMN`;当 DDL 文件中存在数据库没有的表或字段时,应报告为 `EXTRA_TABLE` 或 `EXTRA_COLUMN`;当字段类型不一致时,应报告为 `TYPE_MISMATCH`。 **Validates: Requirements 2.1, 2.2, 2.3, 2.4** ### Property 3: DDL 修正后零差异(不动点) *For any* schema,在以数据库实际状态修正 DDL 文件后,再次运行对比脚本,差异列表应为空。 **Validates: Requirements 2.5** ### Property 4: ODS 表级文档覆盖率 *For any* `billiards` schema 中的 ODS 表,在 `docs/bd_manual/ODS/main/` 目录下都应存在一份对应的 Markdown 文档。 **Validates: Requirements 3.1** ### Property 5: ODS 表级文档格式完整性 *For any* ODS 表级文档,都应包含以下章节:表信息(含 Schema、表名、主键、数据来源、说明)、字段说明表格、使用说明(含 SQL 示例)、可回溯性信息,以及 ETL 元数据字段(content_hash、source_file、source_endpoint、fetched_at、payload)的说明。 **Validates: Requirements 3.2, 3.4, 3.5** ### Property 6: ODS 表级文档命名规范 *For any* ODS 表级文档文件,其文件名应匹配 `BD_manual_{表名}.md` 格式。 **Validates: Requirements 3.6** ### Property 7: 映射文档覆盖率 *For any* 有对应 ODS 表的 API 端点,在 `docs/bd_manual/ODS/mappings/` 目录下都应存在一份对应的映射文档。 **Validates: Requirements 4.1** ### Property 8: 映射文档内容完整性 *For any* 映射文档,都应包含以下信息:API 端点路径、ODS 表名、JSON 数据路径、字段映射表格,以及 ETL 补充字段(content_hash、source_file、source_endpoint、fetched_at、payload)的生成逻辑。 **Validates: Requirements 4.2, 4.4** ### Property 9: 映射文档命名规范 *For any* 映射文档文件,其文件名应匹配 `mapping_{API端点名}_{ODS表名}.md` 格式。 **Validates: Requirements 4.6** ### Property 10: ODS 数据字典覆盖率 *For any* `billiards` schema 中的 ODS 表,ODS 数据字典中都应有对应的条目,包含表名、中文说明、主键、数据来源信息。 **Validates: Requirements 5.2** ## 错误处理 ### DDL 对比脚本 | 场景 | 处理方式 | |------|----------| | 数据库连接失败 | 输出错误信息并退出,返回非零退出码 | | DDL 文件不存在 | 输出错误信息并跳过该 schema | | DDL 文件解析失败 | 输出解析错误位置和原因,尽可能继续解析其余部分 | | schema 在数据库中不存在 | 输出警告并跳过 | ### 文档生成 | 场景 | 处理方式 | |------|----------| | 表无 COMMENT 注释 | 字段说明列填写"(待补充)" | | API 端点文档缺失 | 映射文档中标注"端点文档待补充",仅基于 DDL COMMENT 生成 | | 字段类型无法识别 | 保留数据库原始类型字符串 | ## 测试策略 ### 单元测试 针对 DDL 对比脚本的核心逻辑编写单元测试(`tests/unit/test_compare_ddl.py`): - 测试 DDL 解析器能正确提取表名、字段名、字段类型、约束 - 测试差异检测逻辑能识别各类差异(缺失表、多余表、字段差异、类型差异) - 测试边界情况:空 DDL 文件、无表的 schema、COMMENT 中含特殊字符 ### 属性测试 使用 `hypothesis` 库(Python 属性测试框架)。 - **Property 2 测试**:生成随机的"DDL 表定义"和"数据库表定义",注入已知差异,验证对比函数能检测到所有差异 - **Feature: bd-manual-docs-consolidation, Property 2: DDL 对比脚本差异检测完整性** - 最少 100 次迭代 - **Property 3 测试**:生成随机的数据库表定义,用其生成 DDL,再运行对比,验证差异为零 - **Feature: bd-manual-docs-consolidation, Property 3: DDL 修正后零差异(不动点)** - 最少 100 次迭代 ### 集成验证 文档覆盖率和格式验证通过 Python 脚本实现(`scripts/validate_bd_manual.py`),可在 CI 中运行: - 验证 Property 1(目录结构)、Property 4-10(文档覆盖率、格式、命名) - 输入:文件系统 + 数据库 `information_schema` 查询 - 输出:通过/失败报告,列出缺失或不合规的文档 ### 测试配置 - 属性测试库:`hypothesis`(需添加到开发依赖) - 单元测试:`pytest tests/unit/test_compare_ddl.py` - 集成验证:`python scripts/validate_bd_manual.py --pg-dsn "$PG_DSN"` - 每个属性测试最少 100 次迭代 - 每个测试需注释引用对应的设计属性编号