# knowhub_db — 数据库访问层

PostgreSQL 数据库的封装层。表结构和数据模型详见 [docs/schema.md](../docs/schema.md)。

> ⚠️ **动手前先读 [docs/db-operations.md](../docs/db-operations.md)**——DDL / migration / 排查卡死的操作规范，全是踩过的坑。

---

## 连接约定

所有 Store 使用 **`autocommit = True`**（每条语句独立事务）。原因：
- `autocommit = False` 时 SELECT 后连接停在 `idle in transaction`，永久持有 `AccessShareLock`，阻塞未来的 DDL（ALTER / CREATE INDEX 等）
- 我们的多语句写路径（`DELETE + INSERT ON CONFLICT DO NOTHING`）**幂等**，失去事务原子性影响可控——重试即可恢复

各 Store 内仍有 `self.conn.commit()` 调用，autocommit 模式下为 no-op，保留不删是为了最小侵入。

### AnalyticDB "beam" 表的 ON CONFLICT 限制

所有实体表在 AnalyticDB 上是 **beam storage（类似列存/append-optimized）**。一旦通过 `ALTER TABLE ADD COLUMN` 添加过新列（如 v5 加的 `version`、`images`），该表的 `ON CONFLICT DO UPDATE` 语句就会报错：

```
modification of part columns in OnConflictUpdate is not supported on beam relation
```

因此 5 张实体表（knowledge/resource/requirement/capability/strategy）的 `insert_or_update` 都改用 **DELETE + INSERT** 模式，而不是 ON CONFLICT DO UPDATE。junction 表仍可用 `ON CONFLICT DO NOTHING`（不涉及 UPDATE）。tool 表没加新列，ON CONFLICT 仍可用。

---

## 封装类

### `PostgreSQLStore` (`pg_store.py`)
knowledge 表的 CRUD + 向量检索：

| 方法 | 功能 |
|------|------|
| `insert(knowledge)` | 插入单条知识 |
| `insert_batch(list)` | 批量插入 |
| `search(embedding, filters, limit)` | 向量相似度检索 |
| `query(filters, limit)` | 纯标量过滤查询 |
| `get_by_id(id)` | 按 ID 查询 |
| `update(id, updates)` | 更新字段 |
| `delete(id)` | 删除 |
| `count()` | 统计总数 |

### `PostgreSQLResourceStore` (`pg_resource_store.py`)
resource 表的 CRUD + 层级导航：

| 方法 | 功能 |
|------|------|
| `insert_or_update(resource)` | 插入或更新 |
| `get_by_id(id)` | 按 ID 查询 |
| `list_resources(prefix, content_type, limit, offset)` | 列表查询 |
| `update(id, updates)` | 更新 |
| `delete(id)` | 删除 |
| `get_siblings(id)` | 获取前后同级节点 |

### `PostgreSQLToolStore` (`pg_tool_store.py`)
tool 表的 CRUD + 向量检索。关联表：capability_tool, tool_knowledge。

### `PostgreSQLCapabilityStore` (`pg_capability_store.py`)
capability 表的 CRUD + 向量检索。关联表：requirement_capability, capability_tool, capability_knowledge。

### `PostgreSQLRequirementStore` (`pg_requirement_store.py`)
requirement 表的 CRUD + 向量检索。关联表：requirement_capability, requirement_knowledge, requirement_resource, requirement_strategy。

| 方法 | 功能 |
|------|------|
| `insert_or_update(requirement)` | 插入或更新 |
| `get_by_id(id)` | 按 ID 查询 |
| `search(embedding, limit)` | 向量检索 |
| `list_all(limit)` | 列出所有需求 |
| `count()` | 统计总数 |
| `add_knowledge(req_id, kid, relation_type='related')` | 增量挂接知识 |
| `add_resource(req_id, resource_id)` | 增量挂接原始素材 |
| `add_strategy(req_id, strategy_id)` | 增量挂接 strategy |

### `PostgreSQLStrategyStore` (`pg_strategy_store.py`)
strategy 表（制作策略 = 原子能力的组合 + 可执行 body）。关联表：strategy_capability, strategy_knowledge, strategy_resource, requirement_strategy。

| 方法 | 功能 |
|------|------|
| `insert_or_update(strategy)` | 插入或更新 |
| `get_by_id(id)` | 按 ID 查询 |
| `search(embedding, limit)` | 向量检索 |
| `list_all(limit, status)` | 列表查询 |
| `update(id, updates)` | 更新 |
| `delete(id)` | 删除（含级联） |
| `count(status)` | 统计总数 |
| `add_capability(sid, cap_id, relation_type='compose')` | 增量组合能力 |
| `add_knowledge(sid, kid, relation_type='source')` | 增量挂接来源知识 |
| `add_resource(sid, resource_id)` | 增量挂接原始素材 |
| `add_requirement(sid, req_id)` | 增量挂接所满足的 requirement |

---

## 关联关系类型（relation_type）

`*_knowledge` 和 `strategy_*` 边携带 `relation_type VARCHAR(32)` 语义标签：

| 值 | 含义 | 使用场景 |
|----|------|---------|
| `source` | 构建该实体的知识/资料来源 | 研究产出的能力、策略的理论依据 |
| `case` | 该实体的应用实例 | 工具/能力/策略的使用案例 |
| `compose` | 组合关系 | 仅 strategy → capability |
| `related` | 默认/未分类 | 历史数据、弱关联 |

Store 读取时同时返回两种视图：
- `{entity}_ids: [id1, id2, ...]` —— 扁平 ID 列表（向后兼容）
- `{entity}_links: [{id, relation_type}, ...]` —— 含类型

写入时两种格式都接受：传扁平 ids 则默认 `'related'`，传 links 则使用指定 type。

---

## 目录结构

```
knowhub_db/
├── pg_store.py                # knowledge 表
├── pg_resource_store.py       # resource 表
├── pg_tool_store.py           # tool 表
├── pg_capability_store.py     # capability 表
├── pg_requirement_store.py    # requirement 表
├── pg_strategy_store.py       # strategy 表
├── cascade.py                 # 级联删除（应用层，替代 FK ON DELETE CASCADE）
├── README.md
├── migrations/                # 一次性迁移脚本（已执行，保留备查）
└── scripts/                   # 诊断和运维脚本
    ├── check_table_structure.py   # 查看表结构和行数
    ├── check_extensions.py        # 查看 PostgreSQL 扩展
    ├── clear_locks.py             # 清理数据库锁
    ├── kill_db_locks.py           # 清理数据库锁
    ├── clean_invalid_knowledge_refs.py  # 清理失效引用
    └── ...
```

---

## 环境变量

```bash
KNOWHUB_DB        # 数据库主机
KNOWHUB_PORT      # 端口（默认 5432）
KNOWHUB_USER      # 用户名
KNOWHUB_PASSWORD  # 密码
KNOWHUB_DB_NAME   # 数据库名
```
