> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.alephant.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.alephant.io/_mcp/server.

# PostgreSQL

> 配置 PostgreSQL 连接器，从已批准数据库、schema、表和 SQL 查询中抽取结构化知识。

PostgreSQL 连接器用于把已批准的关系型数据行转成可检索文档。它支持两种索引模式：

* **自动发现**：读取可访问的基础表，由管理员选择 schema、表和列，再映射为文档。
* **自定义 SQL**：执行受控的 `SELECT` 或 `WITH` 查询，把返回列映射为文档 ID、标题、可检索正文、元数据和更新时间。

请使用专用只读账号，并只暴露经过整理的表或视图。不要把拥有广泛权限的生产账号连接到包含未审批个人数据、凭据、令牌或运营密钥的数据库。

## 需要准备什么

| 项目     | 要求                                                             |
| ------ | -------------------------------------------------------------- |
| 网络路径   | AIvis worker 必须能访问 PostgreSQL 主机和端口。使用私有网络、数据库代理或已加入白名单的出站 IP。 |
| 凭据     | 专用登录角色，仅具备 `CONNECT`、schema `USAGE` 和已批准表或视图的 `SELECT` 权限。     |
| 数据范围   | 对敏感 schema、join、聚合或字段重命名，优先使用脱敏视图。                             |
| 稳定身份   | 使用主键、非空唯一键，或在自定义 SQL 中返回稳定的 `id_column`。                       |
| 更新时间字段 | 优先使用 `timestamp` / `timestamptz` 字段，例如 `updated_at`，用于增量同步。    |
| SSL 模式 | 只有在网络路径已受信任时才使用较弱模式；外部或合规环境应使用证书校验。                            |

## 创建只读 PostgreSQL 角色

请用数据库管理员账号执行授权，并按实际环境调整数据库、schema、表和视图名称。

```sql
CREATE ROLE aivis_reader
  LOGIN
  PASSWORD '<generated-password>'
  NOSUPERUSER
  NOCREATEDB
  NOCREATEROLE
  NOREPLICATION
  NOBYPASSRLS
  CONNECTION LIMIT 3;

GRANT CONNECT ON DATABASE appdb TO aivis_reader;
GRANT USAGE ON SCHEMA knowledge TO aivis_reader;

GRANT SELECT ON TABLE
  knowledge.product_catalog_view,
  knowledge.faq_article_view
TO aivis_reader;
```

如果希望 AIvis 读取专用 schema 中的全部现有表，PostgreSQL 支持 `GRANT SELECT ON ALL TABLES IN SCHEMA ...`。仅在该 schema 已专门整理用于索引时使用。

```sql
GRANT USAGE ON SCHEMA aivis_public TO aivis_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA aivis_public TO aivis_reader;
```

当源表包含敏感列时，请先创建视图：

```sql
CREATE VIEW knowledge.product_catalog_view AS
SELECT
  id,
  name,
  status,
  public_summary,
  category,
  updated_at
FROM product_catalog
WHERE searchable = true;

GRANT SELECT ON TABLE knowledge.product_catalog_view TO aivis_reader;
```

## 创建凭据

| AIvis 字段 | 推荐填写                                                  | 说明                                |
| -------- | ----------------------------------------------------- | --------------------------------- |
| Host     | PostgreSQL 主机名或私有端点。                                  | 不要包含 `postgresql://` 这类协议前缀。      |
| Port     | 除非部署使用自定义端口，否则填 `5432`。                               | UI 默认值是 `5432`。                   |
| Database | 包含已批准 schema 或视图的数据库。                                 | 每个凭据连接一个数据库。                      |
| Username | 专用只读角色，例如 `aivis_reader`。                             | 避免使用超级用户、owner、migration 或应用写入账号。 |
| Password | 只读角色的生成密码。                                            | 通过常规凭据流程轮换。                       |
| SSL Mode | 外部可访问主机建议 `verify-full`；仅在获批时使用 `require` 或 `prefer`。 | UI 默认值是 `prefer`，可能根据服务器和客户端配置回退。 |

PostgreSQL 的 `sslmode` 遵循 libpq 行为。`verify-full` 会校验证书链和主机名；`verify-ca` 校验证书颁发机构；`require` 只要求 SSL，但不做完整主机名校验。

## 选择索引模式

| 模式      | 适用场景                                   | 边界                                                   |
| ------- | -------------------------------------- | ---------------------------------------------------- |
| 自动发现    | 希望 AIvis 发现可访问基础表，并让管理员选择 schema、表和字段。 | 自动发现读取基础表，不处理任意 join 或视图。视图、join、聚合或字段重命名请使用自定义 SQL。 |
| 自定义 SQL | 需要受控视图、join、筛选、投影或稳定行结构。               | 查询必须是单条 `SELECT` 或 `WITH`，并且每一行对应一个文档。               |

### 自动发现

自动发现会读取可访问的非系统基础表，并排除 `pg_catalog`、`information_schema`、`pg_toast` 等 PostgreSQL 系统 schema。

在 schema 树中：

* 只选择已批准索引的 schema、表和字段。
* 二进制列不会被索引。
* AIvis 优先使用主键，其次使用非空唯一索引；没有稳定键时使用行哈希。
* 没有稳定键的表在选中值变化后可能生成新的文档 ID；建议添加主键，或使用自定义 SQL 返回显式 ID。
* 标题字段会优先从 `title`、`name`、`subject`、`label` 等列推断；可在表设置中覆盖。
* 更新时间字段会从 `updated_at`、`updated`、`modified_at`、`modified`、`last_modified` 等 datetime 列推断；没有更新时间字段意味着该表需要全表扫描。

## 自定义 SQL 要求

连接器会把你的查询包装为子查询，并校验返回列。SQL 应保持只读、确定性和可复现。

| 字段                | 要求                                    |
| ----------------- | ------------------------------------- |
| SQL Query         | 单条 `SELECT` 或 `WITH` 查询。不要包含尾随分号或多语句。 |
| ID Column         | 每行非空唯一值。复合键可转换为文本。                    |
| Title Column      | 人类可读标题，用作文档名称。                        |
| Content Columns   | 一个或多个列，其值会成为可检索正文。                    |
| Metadata Columns  | 可选字段，用于筛选或排障。                         |
| Updated At Column | 可选 timestamp 字段，用于只同步每个窗口内更新的行。       |
| Batch Size        | 每批拉取的行数。UI 默认是 `16`；只有在测试查询成本后再提高。    |

示例：

```sql
SELECT
  p.id::text AS doc_id,
  p.name AS title,
  concat_ws(
    E'\n',
    'Status: ' || p.status,
    'Category: ' || p.category,
    'Summary: ' || p.public_summary
  ) AS body,
  p.category,
  p.updated_at
FROM knowledge.product_catalog_view AS p
WHERE p.searchable = true
```

对应字段：

| AIvis 字段          | 值            |
| ----------------- | ------------ |
| ID Column         | `doc_id`     |
| Title Column      | `title`      |
| Content Columns   | `body`       |
| Metadata Columns  | `category`   |
| Updated At Column | `updated_at` |

## 生产安全

连接器会以只读会话读取 PostgreSQL，并在读取时设置语句超时。这能避免 AIvis 写入数据，但不能替代数据库侧权限控制。

上线前：

* 尽量使用只读副本、分析库或受控视图层。
* 为自定义 SQL 的筛选条件和更新时间窗口添加索引。
* 自定义 SQL 避免 `SELECT *`；只返回已批准列。
* 避免在高负载 OLTP 表上运行长 join。
* 在测量查询计划和同步耗时前，保持较小批大小。
* 如果数据库使用 RLS，请用同一个只读角色验证行级安全行为。
* 确认查询计划不会产生重锁、大表顺序扫描或异常临时文件。

## 验证

1. 确认凭据能用只读角色连接。
2. 在自动发现中确认能看到预期 schema、表和字段。
3. 在自定义 SQL 中确认查询返回所有已配置列。
4. 执行首次同步，检查行数、已索引文档数和失败记录。
5. 按标题和正文搜索代表性记录。
6. 确认未选 schema、表、字段和敏感列不会出现在搜索中。
7. 修改一行测试数据，确认配置更新时间字段后会更新同一文档。
8. 使用连接器受众之外的用户测试，确认受限文档不可见。

## 常见问题排查

| 现象          | 可能原因                                            | 处理方式                                       |
| ----------- | ----------------------------------------------- | ------------------------------------------ |
| 认证失败        | 角色、密码、数据库、主机或端口错误。                              | 从部署网络用同一角色测试连接，必要时轮换密码。                    |
| 权限被拒绝       | 缺少 `CONNECT`、schema `USAGE` 或表/视图 `SELECT`。     | 给只读角色补充最小缺失权限。                             |
| 没有发现表       | 角色看不到任何基础表，或只授权了视图。                             | 自动发现请授权选定基础表；视图请使用自定义 SQL。                 |
| 自定义 SQL 被拒绝 | 查询为空、多语句、包含尾随分号后的额外内容，或不是 `SELECT` / `WITH` 开头。 | 使用单条只读查询，并为映射字段返回明确别名。                     |
| 缺少列         | 查询没有返回已配置的 ID、标题、正文、元数据或更新时间列。                  | 添加别名，或更新字段映射。                              |
| 更新时间字段无效    | 更新时间列不是 PostgreSQL datetime 值。                  | 使用 `timestamp` 或 `timestamptz`，或留空并接受全量扫描。 |
| 文档重复或 ID 变化 | 没有稳定身份，或配置的 ID 会变化。                             | 使用主键、非空唯一键，或稳定的 `id_column`。               |
| 同步超时        | 查询成本超过语句超时，或批大小过高。                              | 添加索引、缩小范围、降低批大小，或改用副本/视图。                  |
| SSL 连接失败    | `sslmode`、证书信任或主机名校验与服务器配置不匹配。                  | 使用正确 `sslmode` 和证书链；公网主机优先 `verify-full`。  |

## 相关官方文档

* [PostgreSQL `CREATE ROLE`](https://www.postgresql.org/docs/current/sql-createrole.html)
* [PostgreSQL `GRANT`](https://www.postgresql.org/docs/current/sql-grant.html)
* [PostgreSQL libpq 连接参数与 `sslmode`](https://www.postgresql.org/docs/current/libpq-connect.html)