Lukas Fittl:为 Postgres 16 推出 pg_query - 解析 SQL/JSON、支持 Windows、PL/pgSQL 解析模式及更多功能

Lukas Fittl:为 Postgres 16 推出 pg_query - 解析 SQL/JSON、支持 Windows、PL/pgSQL 解析模式及更多功能

💡 原文英文,约1900词,阅读约需7分钟。
📝

内容提要

pg_query发布了一个基于Postgres 16解析器的新版本,其中包括支持在Windows上运行和解析新的Postgres语法。该库可以解析SQL查询并返回Postgres解析树。它还引入了查询指纹以将查询分组在一起,并支持反解析以将查询升级到Postgres 16 SQL/JSON语法。新版本还包括对解析PL/pgSQL表达式的支持。社区在pg_query的发展中发挥了重要作用,团队正在考虑将pg_query的部分功能上游合并为Postgres的核心部分。

🔎

延伸解读

查询指纹:跨服务器识别相同查询

pg_query 的查询指纹功能通过使用表名和模式名(而非 Postgres 原生的关系 OID)来生成唯一标识,解决了 Postgres queryid 在不同服务器间不可移植的问题。指纹忽略常量值,因此相似查询(如 WHERE id = 1 和 id = 2)会得到相同指纹。这一特性可用于在应用端和数据库端关联同一查询,帮助定位慢查询的完整链路。

反解析助力 SQL 语法升级

新版本支持反解析(deparse),可将语法树转回 SQL 语句。文章示例展示了如何用 pg_query 将旧的 json_build_object 调用重写为 Postgres 16 的 SQL/JSON 语法 JSON_OBJECT。这种类似 codemod 的能力,有助于在代码库中批量迁移到新标准语法,且 pg_query 每个版本都用 Postgres 回归测试验证反解析的完整性。

PL/pgSQL 表达式解析的新支持

得益于社区贡献,pg_query 现在可以解析 PL/pgSQL 表达式。通过新增的 pg_query_parse_opts 函数并传入 PG_QUERY_PARSE_PLPGSQL_EXPR 模式,用户能将 PL/pgSQL 函数中的表达式文本转换为常规解析树。这为分析存储过程内部逻辑提供了可能,但目前语言绑定仍在更新中以支持该可选模式。

Windows 支持与社区协作

此版本增加了对 Windows 的编译支持(可使用 MSVC 或 MSYS2 工具链),回应了社区的频繁请求。pg_query 的发展离不开社区,团队特别感谢了贡献者,并正在与 Postgres 社区探讨将部分功能上游合并为核心部分,未来有望直接作为 Postgres 内置的查询解析库提供。

❓

Q&A

pg_query 是什么?它的核心功能是什么?

pg_query 是一个独立的 C 库,它将 Postgres 的“raw_parser”函数提取出来,用于解析 SQL 查询并返回 Postgres 解析树。它支持完整的 Postgres 语法,并提供了多种语言的绑定。

pg_query 新版本基于 Postgres 16 解析器,主要增加了哪些新特性?

新版本增加了对 Windows 的支持(可使用 MSVC 或 MSYS2 编译)、支持解析和反解析新的 Postgres 语法(如 SQL/JSON)、引入了查询指纹功能以将查询分组,并支持解析 PL/pgSQL 表达式。

pg_query 的查询指纹功能有什么作用?与 Postgres 自带的 queryid 有何不同?

查询指纹用于将相似查询分组,它基于表名和模式等生成唯一标识,忽略常量值,因此跨服务器可移植。而 Postgres 的 queryid 基于关系 OID,不同服务器上同一查询的 ID 可能不同,且分组效果有时不佳。

如何使用 pg_query 将旧的 JSON 构建语法升级为 Postgres 16 的 SQL/JSON 语法?

可以使用 pg_query 的反解析(deparse)功能。例如,解析包含 json_build_object 的查询,遍历解析树,将函数调用节点替换为 JsonObjectConstructor 节点,然后反解析生成新的 SQL 语句,从而将旧语法转换为标准的 SQL/JSON 语法。

pg_query 如何解析 PL/pgSQL 表达式?

从 Postgres 14 开始,PL/pgSQL 表达式可以通过传递特殊模式标志给 raw_parser 来解析。pg_query 新版本支持使用 pg_query_parse_opts 函数并指定 PG_QUERY_PARSE_PLPGSQL_EXPR 模式来直接解析 PL/pgSQL 表达式,返回常规的解析树。

pg_query 项目未来的发展方向是什么?

团队希望与 Postgres 社区继续讨论,将 pg_query 的部分功能上游合并为 Postgres 的核心部分,以便直接作为 Postgres 的一部分提供查询解析库。

🏷️

标签

➡️

继续阅读