# 元数据只读连库查询与解析

> **真源（Agent 写码前）**：Agent **引导 LLM** 用**只读 SQL 直连业务库**查元数据，再由 **LLM 解析**结果（企业版抽三标识；苍穹/旗舰抽 field key / entityId / 库列）。  
> **不是 MCP 自动元数据服务**；不依赖元数据 MCP。  
> **业务运行时插件**禁止查 `t_meta_*` 做业务逻辑；本文仅约束 **Agent 取证**。

相关：企业版 [three-identifiers.md](three-identifiers.md) · 通用契约 [api-surface-contract.md](api-surface-contract.md) · [kd-domain-manual.md](kd-domain-manual.md)

---

## 0. Agent 强制流程（企业版与旗舰/苍穹相同）

```
需要字段 / FormId / entityId / 枚举 / 库列
  → 1. 解析产品线（enterprise | cosmic）
  → 2. 解析连接信息（见 §1）
        · 有连接 → 只读 SQL 查询（§2）→ LLM 解析（§3）→ 再写码
        · 无连接 → **先向用户索取连接信息**，不得假装已验证
  → 3. 用户明确「跳过查库 / 直接写」→ 允许写码，但字段必须标
        // 假设 Key=… PropertyName=… source=assumption 待库验证
```

| 场景 | 动作 |
|------|------|
| 写/改涉及字段 key、分录、枚举、FormId/实体、物理表列 | **先连库再写**（有连接时） |
| grill 已对齐单据但字段未证实 | 查库 → LLM 解析 |
| **连接信息缺失** | **询问用户**（主机、库名、认证方式等），禁止瞎连、禁止默认同形 |
| 用户拒绝提供连接 / 库不可达 | 显式假设；禁止写「已验证」 |
| 仅改注释/与元数据无关逻辑 | 可跳过 |

---

## 1. 连接信息：从哪来、缺了怎么办

### 1.1 查找顺序（Agent 自动）

1. 会话中用户刚提供的连接说明  
2. 项目内已有配置（勿把密钥提交仓库）：如 `.env` / `.env.local`（本地）、运维文档、团队约定的只读连接说明文件  
3. 本机常见工具是否可用：`sqlcmd`（企业版 SQL Server）、`psql`（苍穹 PostgreSQL）  

**禁止**把密码、完整连接串写入 git 跟踪文件或示例代码。

### 1.2 缺连接时必须向用户问清（最小集合）

| 产品线 | 最少问 |
|--------|--------|
| **企业版 / 标准版** | SQL Server 主机与端口、账套库名、认证方式（Windows 集成 / 只读账号）、是否仅允许 SELECT |
| **苍穹 / 星瀚 / 旗舰** | PostgreSQL 主机与端口、业务库名、schema（若非 public）、只读账号、是否仅允许 SELECT |

可选：CLI 是否已装（`sqlcmd` / `psql`）、FormId 或实体编号（已知则少搜一轮）。

**话术示例（可压缩为一问）：**

> 写字段相关代码前需要只读连业务库解析元数据（非 MCP）。请提供：产品线、数据库主机/端口、库名、只读认证方式。有 FormId/实体编号更好。

### 1.3 有连接后如何执行

- Agent 用 **bash / 终端** 执行只读 SQL（`sqlcmd`、`psql` 等），或用户指定的只读通道。  
- **仅 SELECT**。禁止 INSERT/UPDATE/DELETE/DDL。  
- 结果交给 **LLM 按 §3 解析**；不要依赖自动 MCP 解析扩展（`kingdee-metadata` 已为 no-op）。

---

## 2. 连哪、查哪

### 2.1 产品线 → 库

| 产品线 | 库 | 注意 |
|--------|-----|------|
| 苍穹 / 星瀚 / 旗舰 Cosmic | PostgreSQL **业务库** | 勿连维护库；entityId ≠ 物理表名 |
| 企业版 / 标准版 | SQL Server **账套库** | 单账套；只读 |
| Oracle 等 | 按现场 | 大小写以库为准 |

### 2.2 企业版（SQL Server）

| 目的 | 表/列（以现场为准） |
|------|---------------------|
| 按中文名找对象 | `T_META_OBJECTTYPE` + `T_META_OBJECTTYPE_L` |
| 取表单内核 | `T_META_OBJECTTYPE.FKERNELXML` |

```sql
SELECT TOP 50 a.FID, a.FBASEOBJECTID, b.FNAME
FROM T_META_OBJECTTYPE a
JOIN T_META_OBJECTTYPE_L b ON a.FID = b.FID AND b.FLOCALEID = 2052
WHERE b.FNAME LIKE N'%销售订单%';
```

```sql
SELECT CAST(a.FKERNELXML AS NVARCHAR(MAX)) AS FKERNELXML, a.FBASEOBJECTID, a.FID
FROM T_META_OBJECTTYPE a
WHERE a.FID = @P1;
```

CLI 示例（占位，勿写死密码）：

```text
sqlcmd -S <host,port> -E -d <账套库> -Q "SELECT CAST(FKERNELXML AS NVARCHAR(MAX)) FROM T_META_OBJECTTYPE WHERE FID=N'SAL_SaleOrder'" -h -1 -y 8000
# 或 -U <只读用户> -P ...
```

### 2.3 Cosmic（PostgreSQL）

| 目的 | 表/列（以现场为准） |
|------|---------------------|
| 实体/表单设计 | `t_meta_entitydesign`（常见 `fid`,`fnumber`,`fmodeltype`,`fparentid`,`fdata`） |

```sql
SELECT current_database(), current_schema();
SELECT fid, fnumber, fmodeltype, fparentid, fdata
FROM t_meta_entitydesign
WHERE fnumber ILIKE '%sal%order%'
LIMIT 50;
```

```text
psql "host=<host> port=<port> dbname=<业务库> user=<只读> sslmode=prefer" -c "SELECT ..."
```

### 2.4 查到后怎么写码

| 产品线 | 写码口径 |
|--------|----------|
| **企业版** | Key / PropertyName / FieldName 分层（three-identifiers.md） |
| **苍穹 / 星瀚 / 旗舰** | **不套**企业版三层；插件用 field key；SQL 用真实库列；entityId 用元数据标识 |

| 用途（企业版） | 层 |
|----------------|-----|
| GetValue/SetValue/FieldKey | Key |
| billObj / entry / entity 索引 | PropertyName |
| SQL/KSQL | FieldName |

---

## 3. LLM 如何解析结果

1. **解析主体是 LLM**：读 SQL 返回的 XML/文本，抽出本需求用到的字段。  
2. 禁止只看中文 caption；禁止脱离字段块乱匹配；禁止无证据口算。  
3. 企业版每个字段尽量抽出 **Key / PropertyName / FieldName**。  
4. Cosmic：抽出 **field key、entityId、枚举码、库列（若有）**；禁止把 `t_xxx` 当 entityId。

### 3.1 读 XML 启发式

1. 根：FormId / Name / BaseObject  
2. 实体：HeadEntity / EntryEntity → Key、TableName  
3. 字段：Key、PropertyName、FieldName（或等价属性）  
4. 枚举：Ext/Items 中 `A:已审核` 类映射  
5. **只取本需求字段**，按关键词在 XML 内搜索后回填

### 3.2 产出格式（注释或 grill 摘要）

```text
Product family: enterprise-csharp | cosmic-java
Form/entity: <id>  source: readonly-sql
Fields:
  数量: key=FQty  property=Qty  db=FQTY
  ...
Status: verified-by-sql | assumption
```

---

## 4. 与 kd-grill 的衔接

```
需求
  → kd-grill：产品线、生命周期、目标单据
  → 连接信息齐？否 → 问用户
  → 本文：只读 SQL → LLM 解析
  → 产品 skill 写码
```

| 阶段 | grill | 本文 |
|------|--------|------|
| 单据未定 | 确认业务单据 | 可按名称检索对象列表 |
| 单据已定 | 写入摘要 | 查 XML/fdata 并解析 |
| 无连接 | 提醒需库 | **向用户索取连接** |
| 用户要求跳过查库 | 记录风险 | 字段标 assumption |

---

## 5. 失败策略

| 情况 | 动作 |
|------|------|
| **无连接信息** | **询问用户**；不写「已验证」字段 |
| 连不上库 | 假设 + 风险；可要设计器导出三列 |
| 查无结果 | 换库/schema/单据名；请用户给 FormId |
| XML 过大 | 收窄 WHERE；只搜目标字段 |
| 与口头不一致 | **以库解析为准**，展示差异 |

---

## 6. 自检清单

- [ ] 产品线与库类型匹配  
- [ ] 连接信息已具备，或已向用户索取 / 用户明确跳过  
- [ ] 已只读 SQL 拿到 FKERNELXML/fdata（或明确 assumption）  
- [ ] LLM 已抽出所用字段（企业版三列 / Cosmic key+entityId）  
- [ ] 未把物理表名当 Cosmic entityId  
- [ ] 业务插件代码未把 Agent 查 meta 写成运行时逻辑  

---

## 7. 技能导航

| 角色 | 读 |
|------|-----|
| 澄清 | `kd-grill` → 本文 |
| 写码 | `ok-cosmic` / `kd-enterprise-csharp` + 本文 |
| KSQL | `kd-ksql` + 本文 |
| 审查 | `kd-cosmic-review` + 本文 |
