言库·象城:PostgreSQL 驱动
连接 PostgreSQL 14–18,使用 TLS、参数化查询、事务、连接池、反射、迁移与 JSONB 言据路径。
言库·象城(包名 言库象城,仓库 yanxu-postgres)是建立在言库 1.x 协议上的 PostgreSQL 原生驱动。它通过言序 ABI v2 直接连接数据库,覆盖 TLS、预编译、事务、连接池、取消、结构反射、迁移和 JSONB/言据集成。
| 项目 | 1.0 稳定边界 |
|---|---|
| 当前版本 | 1.0.0 |
| 最低言序 | 1.1.12 |
| PostgreSQL | 14、15、16、17、18 |
| 稳定依赖 | 言库 v1.0.0 / ^1.0 |
| 原生 ABI | v2 |
| 运行方式 | 字节码 VM、包运行或 YXB;树解释器不能载入 |
安装并固定公开标签
yanbao add postgres --package 言库象城 --version "^1.0"生产清单应固定公开附注标签,并把网络授权收紧到实际端点:
[依赖]
言库象城 = { git = "https://github.com/yanxulang/yanxu-postgres.git", 修订 = "v1.0.0", 版 = "^1.0" }
[权限]
网络 = ["db.example:5432"]
原生扩展 = true依赖不会扩大顶层应用权限。从文件读取自定义 CA 时,应用还需对该文件授予最小文件权限;驱动配置接收已经读取的 PEM 正文。
建立安全连接
引「包:言库象城」为 象城;
定 数据库 为 象城.打开配置({
「地址」:「postgresql://app@db.example/app」,
「密码」:安全配置【「数据库密码」】,
「应用名」:「account-service」,
「TLS」:「验证完整」,
「选项」:{
「连接超时毫秒」:5000
}
});也可分别传 主机、端口、数据库、用户 和 密码;分离字段优先于地址中的同类字段。打开(主机, 数据库, 用户, 密码) 默认启用完整 TLS,打开本地(...) 固定 127.0.0.1 并禁用 TLS,只适合隔离的本机测试服务。
| TLS 模式 | 行为 |
|---|---|
验证完整 | 默认;要求 TLS,验证证书链和连接主机名 |
要求 | 与 验证完整 使用相同的完整验证 |
优先 | 兼容模式;允许按服务端能力选择 TLS |
禁用 | 明文;仅限调用方明确接受的隔离环境 |
根证书PEM 可放在顶层或 选项 中。1.0 不支持客户端证书/私钥认证,也没有“加密但跳过主机名验证”的模式。连接地址、密码和 CA 正文不进入默认日志或公开错误。
参数化查询与预编译
PostgreSQL 值占位符从 $1 开始:
数据库.执行(
「CREATE TEMP TABLE users(id BIGSERIAL PRIMARY KEY, name TEXT NOT NULL, profile JSONB NOT NULL)」,
【】
);
定 插入 为 数据库.预编译(
「INSERT INTO users(name, profile) VALUES($1, $2) RETURNING id」
);
定 编号 为 插入.查询(【「子衿」,{「等级」:10}】).标量();
插入.关闭();
定 用户 为 数据库.查询(
「SELECT id, name, profile FROM users WHERE id = $1」,
【编号】
).首行();值参数由 PostgreSQL 协议绑定,不进入 SQL 模板。表名、列名、schema、排序方向和操作符不能参数化;动态标识符必须先经业务白名单,再用 数据库.方言().引名(名称) 引用。执行原始 / 查询原始 只用于受审计迁移或框架代码。
预编译 返回持有服务端/原生资源的 PostgreSQL原生预编译,支持 参数数()、绑定()、带选项执行与显式关闭。语句不能跨连接;连接关闭或池租约释放后,不得继续使用语句、绑定对象或事务。
查询结果拒绝重复列名,联表查询应给同名列唯一 AS 别名。这能避免行典静默覆盖,但也是从宽松客户端迁移时需要检查的兼容变化。
类型映射
| PostgreSQL 类型 | 言序读取值 | 1.0 写入边界 |
|---|---|---|
BOOL | 理 | 理 |
INT2/INT4/INT8/OID | 数;超安全整数为文 | 范围匹配整数;大值按驱动类型要求传十进制文 |
FLOAT4/FLOAT8 | 数;非有限值为文 | 有限数 |
NUMERIC | 保精度十进制文 | 数或十进制文 |
| 文字类型 | 文 | 文 |
BYTEA | 字节 | 字节 |
UUID | 规范文 | UUID 文 |
JSON/JSONB | 结构化言序值 | 空、理、数、文、列、典 |
| 日期时间类型 | ISO / RFC 3339 文 | 对应格式文 |
| ENUM | 文 | 文 |
| 支持类型的一维数组 | 列,元素可为空 | 列 |
多维数组、范围、网络地址、几何、复合类型和扩展自定义二进制类型不属于 1.0 稳定映射。驱动遇到无法安全解码的类型会报结构化类型错误,不做有损猜测。
事务、保存点、超时与取消
引「包:言库」为 言库;
法 转账(事务)则
事务.执行(
「UPDATE accounts SET balance = balance - $1 WHERE id = $2」,
【10,甲】
);
定 保存点 为 事务.保存点();
保存点.执行(
「UPDATE accounts SET balance = balance + $1 WHERE id = $2」,
【10,乙】
);
保存点.提交();
归 「已提交」;
终
定 结果 为 数据库.托管事务(
转账,
言库.事务选项()
.隔离(「可串行化」)
.只读(假)
.超时(5000)
);回调成功提交,抛错回滚;同一连接只允许一个顶层事务,嵌套工作使用保存点。手动事务必须在所有路径提交或回滚。超时覆盖开始、正文和提交阶段,不是自动重试策略。
单次操作可绑定请求标识:
定 选项 为 言库.执行选项()
.超时(2000)
.请求标识(「report-20260718」);
定 结果 为 数据库.查询带选项(SQL,参数,选项);另一执行上下文可调用 数据库.取消(同一标识)。驱动使用独立 PostgreSQL cancellation token,只取消当前匹配请求;空闲或不匹配调用不会污染下一次查询。若取消竞态后协议状态无法确认,连接会被丢弃。取消写请求不证明服务端未提交,应用必须使用事务、幂等键、唯一约束和业务对账。
连接池
定 池配置 为 言库.连接池配置()
.最小(2)
.最大(16)
.取得超时(2000)
.空闲超时(300000)
.最大生命周期(3600000)
.健康间隔(30000)
.等待上限(64);
定 连接池 为 象城.创建连接池(配置,池配置);
定 租约 为 连接池.取得();
试 则
言 租约.查询(「SELECT now() AS current_time」,【】).首行();
租约.释放();
救 所误 则
租约.释放();
抛 所误;
终
连接池.关闭平缓(10000);池会探活并剔除关闭、过期或协议状态不确定的连接,但不会自动重放可能已经提交的写操作。租约释放后不得继续使用其子资源。
结构反射
逐 模式 于 数据库.模式清单() 则
言 模式;
终
定 结构 为 数据库.公共表结构(「users」);
若 结构【「存在」】 则
言 结构【「列」】;
言 结构【「约束」】;
言 结构【「索引」】;
言 结构【「外键」】;
终反射覆盖用户 schema、表、分区表、视图、物化视图、外部表、列、主键、约束、复合索引和外键。schema 与关系名作为目录查询参数传入;缺失关系返回 存在 = 假 的稳定空结构。
版本化迁移
定 各迁移 为 【
象城.迁移(
1,
「创建用户」,
「CREATE TABLE users(id BIGINT PRIMARY KEY)」,
「DROP TABLE users」
),
象城.迁移(
2,
「增加姓名」,
「ALTER TABLE users ADD COLUMN name TEXT」,
「ALTER TABLE users DROP COLUMN name」
)
】;
定 迁移器 为 象城.默认迁移器(数据库);
言 迁移器.检查(各迁移);
言 迁移器.干运行升级(各迁移);
迁移器.升级(各迁移);默认登记表是 public._yanxu_migrations。迁移器在事务内取得 advisory transaction lock,锁内重读历史,再原子执行 DDL 与登记。版本严格递增,SHA-256 覆盖版本、名称和双向 SQL;缺失定义、名称/内容漂移、非前缀历史与不可逆回退都会拒绝。
锁只协调使用同一锁编号的迁移器。扩展函数或数据库外部副作用不一定可随事务回滚;生产迁移仍要先备份、干运行和恢复演练。旧空校验和只能在审计后显式 采用旧校验和。
言据与 JSONB
| 策略 | PostgreSQL 列 | 语义 |
|---|---|---|
规范文本 | TEXT | 规范 .yj 文本,适合跨方言保真 |
原生结构 | JSONB / JSON | 结构化值,适合路径条件与 GIN 索引 |
定 写入值 为 数据库.言据写入值(资料,「原生结构」);
数据库.执行(「INSERT INTO profiles(data) VALUES($1)」,【写入值】);
定 条件 为 数据库.言据路径(「data」,【「等级」】).至少(10);
定 各行 为 数据库.查询(
(「SELECT data FROM profiles WHERE 」 加 条件.SQL),
条件.参数()
).全部();路径数组、比较值和顶层键全部参数化,列名由方言引用。JSONB索引建议 只生成经引用的 DDL 建议,仍应进入受审计迁移。数据库 JSONB 不是规范言据文本;需要逐字稳定交换或跨数据库一致时使用 规范文本。
真实支持矩阵
PostgreSQL 服务
| 主版本 | 支持状态 | 1.0 发布证据边界 |
|---|---|---|
| 14 | 最低支持版本 | 发布 CI 真实服务生命周期门禁 |
| 15 | 支持 | 协议与类型兼容范围;本发布未单独列为完整真实服务门禁 |
| 16 | 支持 | 协议与类型兼容范围;本发布未单独列为完整真实服务门禁 |
| 17 | 支持 | 协议与类型兼容范围;本发布未单独列为完整真实服务门禁 |
| 18 | 最高已验证主版本 | 发布 CI 明文/TLS/取消/迁移;全生态在 18.4 完成源码与 YXB 集成 |
“支持”表示 1.0 公共协议与类型映射的承诺,不等于应用的精确补丁、扩展、排序规则和服务器参数已经替你验证。部署前应在实际补丁版本执行连接、类型往返、迁移、取消与故障恢复测试。
原生目标
| 操作系统 | x86-64 | ARM64 | 发布门禁 |
|---|---|---|---|
| macOS | 支持 | 支持 | Mach-O、ABI、安装名、签名与原生消费者 |
| Linux glibc 2.17+ | 支持 | 支持 | ELF、ABI、动态依赖与原生消费者 |
| Windows | 支持 | 支持 | PE、ABI、静态 CRT 与原生消费者 |
目标路径、大小和 SHA-256 以 v1.0.0 清单为准。未登记目标必须明确失败,不能加载其他架构或工作目录中的同名库。
权限、安全边界与明确限制
- 顶层应用必须授予精确数据库网络端点与原生扩展权限;象城不需要进程、环境、监听或 UDP 权限。
- SQL 最大 1 MiB、参数最多 65,535 个;单次结果最多 100,000 行、1,024 列和 16 MiB,返回前完整解码。
- 1.0 不提供异步逐行流、
COPY、LISTEN/NOTIFY、逻辑复制、流水线模式、客户端证书认证或自动断线重放。 - 只稳定映射支持类型的一维数组;复杂扩展类型需要上层明确适配。
- TLS、参数化和标识引用不能代替数据库账号最小权限、行级授权、迁移审核、备份和审计。
- 标准日志不记录参数值、密码、完整地址或 CA 正文;自定义日志器仍必须继续脱敏。
数据库错误归一为 YANKU_*,象城边界使用 POSTGRES_* / YANXIANG_* 稳定代码。仓库与 1.0.0 Release:yanxulang/yanxu-postgres。