pgquery
libpg_query's parse tree as Lean 4, plus the C decoder that fills it — the READING side of the leangres AST split. Generated from pg_query.proto; nothing is proven about it by design.
| Latest | 17.6.0 |
|---|---|
| Versions | 1 |
| Category | Modules & tooling |
| Maintainers | Matt Marshall |
| Registry | https://registry.tbzl.dev/modules/pgquery/ |
| Source | github.com/leangres/pgquery |
bazel_dep(name = "pgquery", version = "17.6.0")
View source & releases on GitHub ↗
libpg_query’s parse tree, as Lean 4 — plus the C decoder that fills it.
Postgres’s own parse-node taxonomy, generated from pg_query.proto, with a
hand-curated typed layer over the statement shapes that downstream folds care
about.
Part of leangres.
Two AST layers, on purpose
leangres has two representations of a Postgres statement and conflating them would be a mistake.
This module is the reading side. Pg.Query.Generated mirrors libpg_query’s
protobuf faithfully — complete over Postgres’s grammar, machine-generated,
regenerated wholesale on a libpg_query bump. Nothing is proven about it. It
exists to get real SQL into Lean.
pgast is the writing side: small,
hand-curated, closed, every constructor carrying a printer and a place in an
exhaustiveness lock. Deliberately not complete, because completeness would mean
carrying grammar corners nobody can state a theorem about.
The bridge between them is where round-trip guarantees live — emit from the typed AST, parse with Postgres’s own parser, ingest here, compare.
Contents
| piece | what |
|---|---|
Pg.Query.Generated | proto-derived enums + messages: the full parse-node taxonomy |
Pg.Query.Top | hand-written typed dispatch — statement shapes with fields pre-decoded from protobuf bytes |
//tools/pgpb_to_lean_ast | the C decoder: .pgpb → Lean, with --typed emitting Top*Stmt values |
//tools/pgpb_codegen | regenerates Generated.lean from pg_query.proto |
Top.lean carries fields already decoded — a QualifiedName split into schema +
name, rather than a raw list of proto String message bytes. That pre-decoding
lives in the C tool deliberately, so the Lean side stays simple enough to reason
about.
The pipeline
SQL ──sql_to_protobuf──▶ .pgpb ──pgpb_to_lean_ast --typed──▶ Lean ──▶ a fold
sql_to_protobuf comes from
rules_postgres; it is the
ruleset’s tool, and this module is a consumer of it. CI exercises the whole chain
rather than just checking the C compiles.
Dependencies
pgcatalog—Top.leanimportsPg.Catalog.TablesforArgModealone, the proc-param direction enum. That single import is why pgquery sits above pgcatalog in the graph rather than beside it.rules_postgres(non-dev) — the C decoder is built against libpg_query’s protobuf-c bindings and is part of this module’s surface, so the libpg_query dependency is not gated dev-only.
Lean core otherwise. No mathlib, no batteries.
Consuming it
bazel_dep(name = "pgquery", version = "17.6.0")
lean_library(
name = "my_fold",
srcs = ["MyFold.lean"],
deps = ["@pgquery//lean:pgquery"],
)
Published as compiled oleans. .olean is a compacted heap image — neither
Lean-version- nor architecture-portable — so pin the same toolchain
(leanprover/lean4:v4.30.0-rc2) and select the artifact for your platform.
Versioning
<pg_major>.<pg_minor>.<patch>. This module mirrors pg_query.proto, and
libpg_query releases are themselves keyed to a Postgres major (17-6.2.2), so the
version tracks the Postgres release modelled.
⚠ A convention, not an enforced constraint. compatibility_level was the
mechanism that would have made bzlmod refuse a build mixing Postgres majors, and
Bazel 9 made it a no-op. See
pgcatalog’s MODULE.bazel for the two
candidate enforcement mechanisms, neither built yet.
Provenance
Carved from
tomato-bazel/rules_postgres
with git filter-repo, history preserved. Commit hashes quoted in those messages
may refer to commits that were filtered out.
License
MIT.
Conformance#
No gate findings. 8 contested atoms. See how gating works or the full report.
Contested atoms
Third-party modules where this module resolves a different version than others do. Not a violation of anything this module did — it is the actionable form of a registry-level convergence finding, and the sentence a maintainer can act on.
| Atom | Resolved here | Elsewhere |
|---|---|---|
apple_support | 1.24.2 | 2.2.0 ×1 |
bazel_skylib | 1.8.2 | 1.9.0 ×2 |
nlohmann_json | 3.6.1 | 3.12.0.bcr.1 ×1 |
protobuf | 33.4 | 34.0.bcr.1 ×2 |
rules_jvm_external | 6.7 | 6.8 ×4 |
rules_python | 1.7.0 | 2.0.1 ×1 |
rules_swift | 3.1.2 | 3.6.1 ×1 |
upb | 0.0.0-20220923-a547704 | 0.0.0-20230516-61a97ef ×1 |
Dependencies#
Depends on
Used by (1 in the registry)
Versions#
1 published version, newest first. Each resolves to an immutable, integrity-checked archive.
| Version | Integrity (sha256) | Source archive |
|---|---|---|
17.6.0 latest | Rbv0lKEoBDlyLcxo… | tag archive ↗ |
Changelog#
17.6.0 — carved out of rules_postgres
Pg.Query.* plus the two codegen/decode tools, extracted from
tomato-bazel/rules_postgres with git filter-repo, history preserved
(11 commits). 9 files, each verified byte-identical to source by sha256.
Its own module because it regenerates on a different clock.
Generated.lean is machine-generated from pg_query.proto and rewritten wholesale
when libpg_query bumps; the hand-curated AST above it is edited daily. rules_lean
compiles a whole library in one action, so sharing a module would recompile this on
every AST edit.
//tools:sql_to_protobuf repointed to @rules_postgres//tools:sql_to_protobuf.
The genrule that builds the decoder’s smoke fixture referenced an in-repo //tools
package that belongs to the ruleset, not to this module. It is rules_postgres’s
tool and pgquery is a consumer of it.
Depends on pgcatalog for one enum. Top.lean imports Pg.Catalog.Tables
solely for ArgMode. That single import is why pgquery sits above pgcatalog rather
than beside it.
Ships compiled, and CI exercises the decoder chain — SQL through
sql_to_protobuf, .pgpb through pgpb_to_lean_ast --typed, out as Lean — rather
than only checking that the C compiles.
Requires rules_lean 0.6.1: earlier releases’ lean_olean_archive fails on linux.