Skip to content

db.pg

since: std-0.5 stability: experimental

PostgreSQL 线协议 v3 核心(§12;P5-C;回放优先架构) ═══ 架构口径(控制器裁定;P5 计划 Task 3)═══ 协议核消费"注入源"帧:双薄源共驱一核—— ① pg_recv_frame_script(回放源):List[Str] 十六进制帧逐帧出(录制/手工 按协议文档构造;tests/db/replay_fixtures/.script + README)——CI 零真库; ② pg_recv_frame_fd(真源):fd 直读(db 自有垫片 db/c_src/ ctron_dbpg.c,镜像 ctron_net.c 约定;真 fd 冒烟 Task 6 nightly)。 Ctron 无可发射 trait ⇒ 既定双入口形态:两入口 fn 共享核心解析器 (pgx_),统一产出 PgRecv(帧面)/PgRows/PgSess(会话面)。 ═══ 依赖纪律 ═══ 单子扩展(P5-D 落定):唯一 std 依赖 = std.crypto(SCRAM 原语 sha256_bytes/hmac_sha256/pbkdf2_sha256;ws.ct→std.crypto 同款单子先例, E5020 树互斥)。base64 不取 std/enc——其 b64 面受 C8 printable-ASCII 约束,SCRAM 盐/证明/签名携任意字节(ws.ct lane-b64 同款先例),本文件 自出 pg_b64_encode/pg_b64_decode(List[I32] 字节容器,RFC 4648 标准 字母表 + '=' 填充)。不 use std.net(Global Constraints):真源经 PgCell64 标量胞(本文件自有声明;与 net bind.ct 的 Box64 同布局异名 ——同名 decl 二次合并 E5030,合并单命名空间纪律)传 fd,垫片符号 前缀 ctron_dbpg_。SCRAM 客户端 nonce 真熵经 ctron_dbpg_entropy (P5-D 新 extern;db 垫片别名转发 ctron_entropy_fill——pg.ct 直宣 ctron_entropy_fill 与 std/uuid.ct 同名 decl 合并即 E5030,探针实证, 故出 db 前缀别名;链接需并链 ctron_entropy.c)。 ═══ 发射面/解释面纪律(divergences (f)-(i) + P5 新证)═══ ① (h) 载荷通道:跨模块数值消费一律 struct 标量字段 + 自由 getter (client.ct HttpLoc/HttpResp 同款);Result 数值载荷禁跨模块。 ② (i) C10:长度/计数算术一律宽域播种(pgz)后乘法;帧长域门 [4, 1048576](2^20,远低 2^28 险带);BE 解析乘前高位预门; 装配侧全走 div/mod(乘法仅 256 阶梯,值域 ≤2^20)。 发射面 List[I64] struct 字段元素读坏(items 按 char 出)——探针 实证 P5-C 登记 divergences;本文件 struct 字段只用 List[Str]/ List[I32]。 ③ utf8_enc 解释口径坏(恒返 U+FFFD;自举 eval 值串未转 int——P5-C 登记 divergences):单元格 Str 解码走可打印 ASCII 表切片 (client.ct cx_slice_str 同款,双臂确定性;'{' 档 fail-closed); 任意字节精确面 = pg_hex_encode/pgr_cell_hex(List[I32] 字节容器, crypto 面纪律);非 ASCII 文本解码待解释器修复后收敛(登记口径)。 表切片内建收 I32 域标签:入参恒 I32,pgz 宽域值禁直入(解释口径 arity 拒;client.ct lane 值同域先例)。 ④ 无方法调用/无闭包/无 Tuple;while 体无 Drop 局部;状态随值携带 (message.ct ChunkSt 重入口径);List 经形参 push 跨函数传播 (parse_pkg.ct diags 同款已证形);"fn 内未用结果绑定"毒化纪律—— 绑定必消费,忽略返回值用裸语句形。 ⑤ inline test 不落本文件(C17 宿主敏感,P5-A 口径);声明冒烟 + 行为面全在 tests/db。 ═══ 线协议范围(本任务;P5-D 扩)═══ startup(3.0 + 参数面)/AuthenticationOk 检测/SCRAM-SHA-256 全流程 (RFC 5802/7677;gs2 'n' 档,channel-binding-plus 不支援即 clean Err; pg_scram_handshake 回放面 + pg_scram_ 纯核)/Query 简单查询/ 扩展查询装配(Parse/Bind/Describe/Execute/Close/Sync + 管线拼接; 收侧与简单查询共驱一核——1/t/2/n 帧入"其余跳过"前向兼容)/ 事务面(BEGIN/COMMIT/ROLLBACK Query 面 + ReadyForQuery 'T'/'I'/'E' 状态字节 + 取消传播:pg_conn_dirty 脏/排空分级 + 复位语义)/ RowDescription/DataRow(文本格式)/CommandComplete/ReadyForQuery/ ErrorResponse(全字段解析,暴露 severity+SQLSTATE+message)/ NoticeResponse 跳过/ParameterStatus 跳过/BackendKeyData 解析/ CancelRequest 装配(独立连startup 形)*/Terminate。大端长度前缀帧: server 帧 [type(1)|len(4,含自身)|payload];client 帧 startup/cancel 无 type 字节,其余有。 ═══ err 码(PgRecv.err/PgRows.err/PgSess.err)═══ 1 帧面坏(非十六进制/空行) 2 协议违例(长度域/字段越界/计数不符/ SCRAM 相位错) 3 源耗尽(脚本走完/fd 对端关) 4 认证败(SCRAM 签名 不符/nonce 前缀违例/盐·迭代·机制面坏;Cleartext/MD5 存根) 5 ErrorResponse 收到(SQLSTATE 在 ecode) 6 IO(fd 读写败;fd 源专面) rc 约定:0 成功 / <0 失败(net 门面同款)。

pub struct

struct PgCell64

fd 出参标量胞(与 net bind.ct Box64 同布局异名;见头注依赖纪律);
出参持态一律 BoxPgCell64

Field Type
var v I64

struct PgRecv

Field Type
var rc I64
var err I64
var next I64
var mtype I32
var body List[I32]

struct PgErrData

ErrorResponse/NoticeResponse 字段面:code(1B) + cstring 值,0x00 终。
S/V → severity,C → SQLSTATE,M → message,其余字段跳过(全字段扫描,
暴露面只取标准三槽)。无终止 NUL → ok=0。

Field Type
var ok I64
var sev Str
var code Str
var msg Str

struct PgRows

查询结果(struct 通道;头注①)——cells/nulls 行主序平铺;
cbytes/coffs 承载逐格原始字节(精确面;ASCII 面经 pgx_ascii_bytes;
List[I64] 字段发射面坏 ⇒ offsets 用 List[I32],帧长域 2^20 内恒安全)

Field Type
var rc I64
var err I64
var nrows I64
var ncols I64
var tag Str
var cols List[Str]
var oids List[I32]
var cells List[Str]
var nulls List[I32]
var cbytes List[I32]
var coffs List[I32]
var esev Str
var ecode Str
var emsg Str
var next I64
var status I64

struct PgSess

Field Type
var rc I64
var err I64
var next I64
var status I64
var pid I64
var key I64
var authkind I64
var esev Str
var ecode Str
var emsg Str
var mechs List[Str]
var cfirst Str
var sfirst Str
var cfinal Str
var sigok I64

pub fn

Signature Returns Description
pg_frame_max() I64 —
pg_err_frame() I64 —
pg_err_proto() I64 —
pg_err_eof() I64 —
pg_err_auth() I64 —
pg_err_response() I64 —
pg_err_io() I64 —
pg_hex_decode(s: Str) List[I32] 十六进制串 → 字节表(0..255);奇长/非法数位/空串 → 空表(fail-closed)
pg_hex_encode(b: List[I32]) Str 字节表 → 小写十六进制串(空表 → "")
pg_body_ascii(b: List[I32], a: I64, e: I64) Str ASCII 文本面 pub 形(P5-F:fd 真源消费方/nightly 需 body → 文本,如
SCRAM server-first 提取)。界外/非可打印 → ""(fail-closed 同上)。
pgv_rc(r: PgRecv) I64 —
pgv_err(r: PgRecv) I64 —
pgv_next(r: PgRecv) I64 —
pgv_type(r: PgRecv) I32 —
pgv_body_len(r: PgRecv) I64 —
pgv_body_at(r: PgRecv, i: I64) I32 —
pgv_body(r: PgRecv) List[I32] —
pg_recv_frame_script(frames: List[Str], cur: I64) PgRecv ① 回放源:十六进制帧脚本逐帧出(List[Str] 一帧一行;cur 越界 → eof)
pg_recv_frame_fd(fd: I64, rbuf: &[I64], fill: Box[PgCell64], scr: &[I64]) PgRecv ② 真源:fd 直读(阻塞;真 fd 冒烟 Task 6 nightly;x_ 夹具 emit 臂专面)。
rbuf = 持续读缓冲 lane(须 ≥ frame_max+1 lane;调用方持有;view .len =
字面量显式槽数——夹具逐槽写满字面量,tcp_echo 同款),fill = 缓冲填充位
标量胞(Box[PgCell64];net 出参 Box[Box64] 同款堆胞——struct 值语义下
裸形参写回是 callee 局部拷贝,跨调用持态必须经 Box),scr = 单读暂存
lane(垫片 CT_CHUNK=4096 口径)。声明长越域 → err 2;读败 → err 6;
对端关 → err 3;守卫计数防滞留(长度域已门,滞留面只剩对端慢滴,
nightly 面再演进)。mtype 在 leftover 前移前捕获(管线帧场景:一包
R+S+K+Z 到齐,shift 后 rbuf[0] 已是下一帧类型字节)。
pg_send_msg_fd(fd: I64, msg: List[I32], scr: &[I64]) I64 客户端帧发送(fd 源;List → lane 暂存后整发;rc 0 成/<0 败;超暂存 →
-1)。垫片 write 为 send-all 整长 chunk 循环(ctron_net.c ct_send_all
同口径,无静默截断),返回值语义 = 已发全长的确认。
pg_fd_close(fd: I64) I64 —
pg_fd_last_errno() I64 —
pg_startup_msg(user: Str, database: Str, app: Str) List[I32] startup 协议 3.0(版本 196608 = 3<<16):user 恒在;database/
application_name 非空才入参数面;尾 NUL 终止参数序列
pg_query_msg(sql: Str) List[I32] Query 简单查询帧('Q' + sql + NUL)
pg_password_msg(pw: Str) List[I32] CleartextPassword 应答帧('p' + 密码 + NUL;存根面,Task 4 SCRAM 接管)
pg_terminate_msg() List[I32] Terminate('X' + len 4)
pg_sasl_initial_msg(mech: Str, initial: List[I32]) List[I32] SASLInitialResponse('p'):机制名 + i32 初始响应长(-1 = 无)+ 初始响应
(gs2 头 + client-first-bare;'n' 档 = "n,," 前缀)
pg_sasl_response_msg(resp: List[I32]) List[I32] SASLResponse('p'):client-final-message("c=biws,r=...,p=<proof-b64>")
pg_parse_msg(stmt: Str, sql: Str, oids: List[I32]) List[I32] Parse('P'):语句名 + SQL + 参数 OID 表(0 = 未指定)
pg_bind_msg(portal: Str, stmt: Str, params: List[Str], nulls: List[I32]) List[I32] Bind('B'):portal + 语句 + 参数(format code 0 逐参;值文本格字节,
NULL = -1 长)+ result format 计数 0(全文本)。参数计数 i16 域门
(>65535 → 空表 fail-closed,(i) 族同门:计数先于 be16 装配)
pg_describe_msg(kind: I32, name: Str) List[I32] Describe('D'):kind 'S'(83)= 语句 / 'P'(80)= portal + 名
pg_close_msg(kind: I32, name: Str) List[I32] Close('C'):kind 同 Describe;语句清理(归池复位三件套之一,Task 5 消费)
pg_execute_msg(portal: Str, maxrows: I64) List[I32] Execute('E'):portal + max-rows(0 = 全行)
pg_sync_msg() List[I32] Sync('S'):扩展查询管线收口(事务边界由 ReadyForQuery 报)
pg_ext_pipeline(stmt: Str, sql: Str, oids: List[I32], portal: Str, params: List[Str], nulls: List[I32], maxrows: I64) List[I32] 参数化查询管线一发(stmt/portal 名显参 = 预编译句柄命名面):
Parse + Bind + Describe(portal) + Execute + Sync
pg_tx_begin_msg() List[I32] begin/commit/rollback = Query 简单查询(会话语义收 ReadyForQuery 状态
字节:'I'=73 idle / 'T'=84 in-tx / 'E'=69 failed-tx;pg_query_script
status 槽承接,tx 链 = 游标续跑)
pg_tx_commit_msg() List[I32] —
pg_tx_rollback_msg() List[I32] —
pg_cancel_msg(pid: I64, key: I64) List[I32] CancelRequest(独立连 startup 形:无 type 字节,len 16,code 80877102,
pid + key = BackendKeyData 回执面);收侧 Abort 面服务端自理
pg_conn_dirty(err: I64) I64 取消传播分级(池回池复位判定基面;Global Constraints:禁止跨取消复用
脏连接):
0 = clean(查询 rc 0,Z 已收,连接即复用)
2 = drain(E 已收口——含 57014 查询取消/25P02 事务内错——尾随 Z 在线,
复位 = 排空 Z(pgr_next 续跑)→ 事务内则 ROLLBACK → 见 Z('I') 复用)
1 = dirty(帧/协议/源耗尽/IO:流信任失,连接弃用,不复位不回池)
注:本分类只按 err 面;事务态 Z('T')(含 drain 排出 Z('T'))不在此
反映——池消费方回池前须另查 pgr_status,'T' 者先 ROLLBACK 见 'I' 再入池。
pg_dirty_clean(state: I64) I64 复用判定(1 = 可复用 / 0 = 需复位或弃用)
pg_auth_kind(body: List[I32]) I64 Authentication 消息体 → 认证方式(0 Ok/3 Cleartext/5 MD5/10 SASL/…;
越界/畸形 → -1)
pg_ready_status(body: List[I32]) I64 ReadyForQuery 体 → 事务状态字节('I'/'T'/'E';畸形 → -1)
pg_tag(body: List[I32]) Str CommandComplete 体 → tag 文本(可打印 ASCII;畸形/非打印 → "")
pge_ok(e: PgErrData) I64 —
pge_sev(e: PgErrData) Str —
pge_code(e: PgErrData) Str —
pge_msg(e: PgErrData) Str —
pg_err_data(body: List[I32]) PgErrData —
pgr_rc(r: PgRows) I64 —
pgr_err(r: PgRows) I64 —
pgr_rows(r: PgRows) I64 —
pgr_cols(r: PgRows) I64 —
pgr_tag(r: PgRows) Str —
pgr_colname(r: PgRows, i: I64) Str —
pgr_oid(r: PgRows, i: I64) I64 类型 OID(u32 档 ≥2^31 按 I32 符号化呈现,头注②;OOB → -1)
pgr_isnull(r: PgRows, row: I64, col: I64) I64 —
pgr_cell(r: PgRows, row: I64, col: I64) Str —
pgr_cell_hex(r: PgRows, row: I64, col: I64) Str 格精确字节面(十六进制;任意字节双臂可断言;OOB → "")
pgr_cell_bytes(r: PgRows, row: I64, col: I64) List[I32] —
pgr_esev(r: PgRows) Str —
pgr_ecode(r: PgRows) Str —
pgr_emsg(r: PgRows) Str —
pgr_next(r: PgRows) I64 会话游标(P5-D):next = 收侧消费停点(Z 之后 = 后续查询续跑位;E 之后 =
尾随 Z 待排空位——drain 面,自 next 续跑即排空);status = ReadyForQuery
状态字节('I'=73/'T'=84/'E'=69;未见 Z = 0)。事务链/取消复位面基石。
pgr_status(r: PgRows) I64 —
pg_query_script(frames: List[Str], cur: I64, sql: Str) PgRows 查询回放(脚本源;收侧核 = 简单查询与扩展查询响应流共驱——扩展查询的
ParseComplete('1')/BindComplete('2')/ParameterDescription('t')/NoData
('n')入"其余跳过"前向兼容,v0 不校验计数(登记口径)):发侧由调用方
构建/断言(回放源无下行信道;扩展查询装配 pg_ext_pipeline);收侧逐帧:
T→行描述,D→行(列数校验),C→tag,Z→收口(rc 0,next 推进 + status 记),
E→rc -1 err 5 + 字段面(next 停在尾随 Z 之前 = 排空位),N/S/K/其余→跳过
(前向兼容)。源耗尽未见 Z → err 3。无行集查询(BEGIN 等)rc 0 ncols 0。
next/status 语义见 pgr_next(pgr)。
pg_query_fd(fd: I64, rbuf: &[I64], fill: Box[PgCell64], scr: &[I64]) PgRows ② 真源查询收帧(P5-F nightly;pg_query_script 的 fd 薄源镜像——帧分派
核同构:R84 行描述/D68 数据行/C67 tag/Z90 收口/E69 错误,其余帧跳过
前向兼容;扩展查询响应面 1/2/t/n 同核)。发侧(Query/Sync/管线)由调用
方经 pg_send_msg_fd 装配;本入口自 fd 收帧至 Z/E/源尽。next 恒 0(fd 源
无脚本游标;留 fill/rbuf 持态续用)。阻塞 fd:pg_recv_frame_fd 循环至
整帧。守卫计数防滞留(对端慢滴/僵连面由调用方超时策略兜,v0 登记)。
pgs_rc(s: PgSess) I64 —
pgs_err(s: PgSess) I64 —
pgs_next(s: PgSess) I64 —
pgs_status(s: PgSess) I64 —
pgs_pid(s: PgSess) I64 —
pgs_key(s: PgSess) I64 —
pgs_authkind(s: PgSess) I64 —
pgs_esev(s: PgSess) Str —
pgs_ecode(s: PgSess) Str —
pgs_emsg(s: PgSess) Str —
pgs_nmech(s: PgSess) I64 SCRAM 面(P5-D):mechs = AuthenticationSASL 机制列表;cfirst/sfirst/
cfinal = client-first-bare / server-first-message / client-final-message
(含 ,p= 证明);sigok = server-final 签名校验(1 符 / 0 不符 / -1 未达)。
pgs_mech(s: PgSess, i: I64) Str —
pgs_cfirst(s: PgSess) Str —
pgs_sfirst(s: PgSess) Str —
pgs_cfinal(s: PgSess) Str —
pgs_sigok(s: PgSess) I64 —
pg_handshake_script(frames: List[Str], cur: I64) PgSess 握手回放:startup 发侧由调用方构建/断言(回放源无下行信道);收侧
R(AuthenticationOk=0 续;Cleartext=3/MD5=5 存根 err 4;SASL=10 → 本入口
不携凭据,err 4 指路 pg_scram_handshake),K 记 pid/key,E 记字段面,
Z 记 status 收口。源耗尽 → err 3。SCRAM 全流程 = pg_scram_handshake。
pg_b64_encode(b: List[I32]) Str 字节表 → base64 串(RFC 4648 标准字母表 + '=' 填充)
pg_b64_decode(s: Str) List[I32] base64 串 → 字节表;长度非 4 倍/非法数位/垫位错位(中段 '=')→ 空表
(fail-closed;空串 → 空表,调用方以盐长 0 拒)
pg_str_bytes(s: Str) List[I32] Str → 字节表(ASCII 域;byte_at 逐字节;AuthMessage/口令边)
pg_scram_first_bare(user: Str, nonce: Str) Str client-first-message-bare = "n=" + user(或 authzid)+ ",r=" + nonce
pg_scram_salted(pass: Str, salt: List[I32], iters: I32) List[I32] SaltedPassword = PBKDF2-HMAC-SHA256(口令字节, 盐, i;32B)
pg_scram_proof(salted: List[I32], authmsg: Str) List[I32] ClientProof = ClientKey XOR ClientSignature(= HMAC(StoredKey, AuthMessage);
authmsg 由调用方按上式拼)
pg_scram_server_sig(salted: List[I32], authmsg: Str) List[I32] ServerSignature = HMAC(HMAC(SaltedPassword,"Server Key"), AuthMessage)
pg_scram_nonce_from(rand: List[I32]) Str 18B 随机 → 24 字符 b64 nonce(RFC 5802 建议 nonce 熵 ≈ 18 字节档;
纯形:调用方供熵,双臂可测)
pg_scram_nonce() Str 真熵 nonce(发射臂面;interp 无 extern 运行时——uuid_v4 同款口径);
失败 → 空串(fail-closed,绝不回退伪熵)。lane 槽数 = 字面量显式
(P5-C 登记:lane .len = 字面量槽数)。
pg_scram_handshake(frames: List[Str], cur: I64, user: Str, pass: Str, nonce: Str) PgSess SCRAM-SHA-256 握手回放(frames[cur..];发侧 SASLInitialResponse/
SASLResponse 由调用方经 pg_sasl__msg 装配并断言,回放源无下行信道):
R kind 10(机制表;明档选择)→ kind 11(server-first:nonce 前缀校验/
盐 b64 解码/迭代 (i) 门 → PBKDF2 → client-final 计算面入 sess)→
kind 12(server-final v= 与本地 ServerSignature 比对,不符 → err 4
认证败)→ AuthOk/K/Z 收口(status 记;
Z 门 phase==3——未见 R12 校验
通过的收口一律 rc<0 err 4,信任面
。E → err 5 字段面。相序违例
(11/12 先于 10 / 12 先于 11)→ err 2。空 nonce → err 4(fail-closed:
前缀校验空洞)。sigok/pgs_
面 = 夹具逐字节锚定面。
pg_scram_handshake_fd(fd: I64, rbuf: &[I64], fill: Box[PgCell64], scr: &[I64], user: Str, pass: Str, nonce: Str) PgSess ② 真源 SCRAM-SHA-256 握手(fd 直读直发;pg_scram_handshake 的 fd 镜像
+ 下行信道):调用方先 pg_send_msg_fd 发 startup,再入本入口。相序门
(R10→R11→R12→AuthOk/K/S→Z)/ 机制明档选择 / nonce 前缀校验 / 盐-迭代
(i) 门 / server-final v= 校验 / Z 门 phase==3 信任面(P5-D 评审
必修同门:未见 R12 校验通过的收口一律 rc<0 err 4)/ kind 3/5 clean
Err 4 —— 全与脚本源逐条一致。fd 差分:R10 后发 SASLInitialResponse
("n,," + client-first-bare),R11 后发 SASLResponse(client-final);
发败 → err 6。kind 0 直达(trust 等)同脚本源口径:phase 门照收,不作
成功面(Z 门拦截)。next 恒 0(fd 源无脚本游标)。
sha256_hex(msg: Str) Str —
sha1_hex(msg: Str) Str —
sha256_bytes(msg: List[I32]) List[I32] —
hmac_sha256(key: List[I32], msg: List[I32]) List[I32] —
pbkdf2_sha256(pass: List[I32], salt: List[I32], iters: I32, dklen: I32) List[I32] —
bytes_to_hex(b: List[I32]) Str —
bytes_from_hex(s: Str) List[I32] —