Rust in Everything
基于 sqlx 0.9.0

Postgres 驱动

这一部分是 sqlx-postgres crate:核心抽象里那些 trait 的 Postgres 实现,以及它和服务端之间的线协议。整个 crate 约 2 万行,types/ 占了 8.8k(每种 Rust 类型的编解码,只挑几个讲),connection/ 2.5k、message/ 2.3k、options/ 1.5k、type_info.rs 1.4k,再加上 listener.rs、copy.rs 等。

前三章是一条连接的生命周期,从下往上:连接怎么建起来,消息怎么收发,一次查询怎么用这些消息拼出来。后三章是建立在它们之上的专题。

  1. 连接选项与建立连接:PgConnectOptions 依次取环境变量、URL、passfile;establish 发 SSLRequest(看 sslmode)和 StartupMessage,走两个 SCRAM-SHA-256 来回,收到 ReadyForQuery 才交出连接;prefer 和 require 都不校验证书。
  2. 消息与读写缓冲:一条消息是类型字节加长度;write_msg 只写缓冲,flush 才发;recv_unchecked 靠 try_read 做到取消安全;recv 截走 NoticeResponse 和 ParameterStatus,把 ErrorResponse 变成 Error::Database,出错之后连接照常可用。
  3. 扩展查询协议与语句缓存:pending_ready_for_query_count 记着欠服务端几个 ReadyForQuery,没读完的结果由下一次查询读掉;StatementCache 是按 SQL 原文的 LRU,挤掉一条就发 Close;persistent(false) 用未命名语句,容量 0 在 0.9.0 里会泄漏。
  4. Postgres 类型:PgTypeInfo 和 OID;内建类型直接认 OID,自定义类型按名字解析,编码时先留「洞」、拿到 OID 再补;几个代表类型的二进制编码。
  5. describe 与可空性推断:编译期宏怎么拿到参数和列的类型,以及每一列可不可能是 NULL。
  6. LISTEN/NOTIFY 与 COPY:PgListener 怎么在一条连接上收通知,COPY 的进出两个方向。
flowchart TB
  opts[PgConnectOptions] --> est["establish 握手"]
  est --> stream["PgStream 收发消息"]
  stream --> run["run 扩展查询"]
  run --> cache[StatementCache]
  run --> types["PgTypeInfo 与 OID"]
  run --> desc["describe 给宏用"]
  stream --> listen["PgListener 与 COPY"]

Pool 怎么管理这些连接在 04 连接池;事务和迁移在 Postgres 上发什么语句在 05 事务与迁移。

💬 关联讨论

发起讨论
加载中...