Catalog System Architecture in pgrust: A Three-Layer Rust Implementation of PostgreSQL System Tables
The pgrust catalog system replicates PostgreSQL's internal system tables through a modular three-layer architecture that combines compile-time generated Rust structs, MVCC-consistent snapshot management, and seam-based APIs for extension integration.
The catalog system architecture in pgrust serves as the backbone for type resolution, function dispatch, and schema metadata management in this Rust-based PostgreSQL implementation. Developed in the malisper/pgrust repository, the system translates PostgreSQL's C header definitions into idiomatic Rust while preserving full compatibility with upstream OID conventions and system table layouts.
Catalog Definition Layer: Static System Table Representations
At the foundation of the architecture lies the catalog definition layer, which declares Rust equivalents of PostgreSQL's system catalogs including pg_type, pg_proc, and pg_class. These definitions mirror the C structs and constants found in PostgreSQL's catalog/pg_*.h header files, providing type-safe access to built-in OIDs and catalog schemas.
Core Catalog Files
The primary definitions reside in the types_core crate under the _support directory:
crates/_support/types/types_core/src/catalog/pg_type.rs– Containspg_typedefinitions includingINT4_OIDand other built-in type constantscrates/_support/types/types_core/src/catalog/pg_proc.rs– Defines procedure catalog entries and built-in function OIDscrates/_support/types/types_core/src/catalog/pg_class.rs– Represents relation metadata and table structure definitions
These files are generated from PostgreSQL header files, ensuring that OIDs and catalog layouts remain synchronized with upstream PostgreSQL versions.
Syscache and Snapshot Seams: Dynamic Catalog Access
The second layer provides runtime catalog visibility through snapshot management and seam interfaces. Unlike the static definitions, this layer handles MVCC-consistent views of the catalog during query execution, managing cache invalidation and snapshot lifecycles.
MVCC Snapshot Management
The snapshot manager, implemented in crates/backend/utils/time/snapmgr_seams/src/lib.rs, provides functions for obtaining catalog snapshots:
get_catalog_snapshot()– Returns an MVCC-consistent view of the catalog for the current transactioninvalidate_catalog_snapshot()– Clears cached snapshots after schema modifications
Catalog-Driven Utility Seams
Additional seam modules provide catalog-aware functionality throughout the backend:
crates/backend/utils/time/snapmgr_seams/src/lib.rs– Manages MVCC snapshots for catalog consistencycrates/backend/utils/sort/tuplesort/src/lib.rs– Implements catalog-driven comparators for sorting tuples based on catalog type definitions
These seams abstract whether the catalog data resides in memory caches, on-disk structures, or temporary snapshot buffers, presenting a uniform API to upper layers.
Execution and Extension Integration
The third layer enables extension integration and runtime catalog consumption. Extensions like pgcrypto and pg_trgm use the seam APIs to register custom catalog objects while leveraging the same infrastructure as built-in types.
Extension Registration Points
Extension modules demonstrate practical catalog usage:
crates/contrib/pgcrypto/src/lib.rs– Creates catalog objects for cryptographic functions, inserting entries into thepg_procseamcrates/contrib/pg_trgm/src/trgm_gist.rs– Implements GiST opclass support using catalog-driven dispatch to resolve operator OIDscrates/pl/plpgsql/src/handler/src/lib.rs– Resolves type and function OIDs during stored procedure execution
Working with the Catalog System
Working with the catalog system involves combining static OID constants with dynamic snapshot acquisition. The following example demonstrates resolving type and function OIDs with proper snapshot management:
use pgrust::types_core::catalog::{pg_type, pg_proc};
use pgrust::backend::utils::time::snapmgr_seams::{get_catalog_snapshot, invalidate_catalog_snapshot};
fn resolve_catalog_objects() -> Result<(), Box<dyn std::error::Error>> {
// Obtain a fresh catalog snapshot (MVCC-consistent)
let snap = get_catalog_snapshot(0)?; // 0 = InvalidRelationId = whole-catalog view
// Resolve a built-in type OID using static constants
let int_oid = pg_type::INT4_OID;
println!("OID for int4 = {}", int_oid);
// Resolve a function OID (e.g., length(text))
let len_oid = pg_proc::PG_PROC_OID.get("length")?;
println!("OID for length(text) = {}", len_oid);
// After schema changes, invalidate the snapshot so the next call sees the new catalog
invalidate_catalog_snapshot();
Ok(())
}
This pattern ensures that catalog lookups respect transaction isolation levels while providing the performance benefits of syscache lookups.
Summary
- Three-layer architecture separates static definitions (mirror PostgreSQL headers), dynamic snapshots (MVCC consistency), and consumption APIs (seam interfaces)
- Type-safe catalog definitions in
crates/_support/types/types_core/src/catalog/prevent OID mismatches through compile-time generated Rust code - Snapshot management via
snapmgr_seamsprovides MVCC-consistent catalog views without exposing underlying storage implementation details - Extension integration allows contrib modules like
pgcryptoto register catalog objects using the same APIs as core system components - Seam-based design abstracts catalog storage, enabling optimizations like in-memory syscaching without changing consumer code
Frequently Asked Questions
How does pgrust maintain compatibility with PostgreSQL's catalog OID assignments?
pgrust generates Rust catalog definitions directly from PostgreSQL's catalog/pg_*.h header files, ensuring that built-in type OIDs (like INT4_OID in pg_type.rs) and function OIDs match the upstream C constants exactly. This compile-time generation prevents drift between the Rust implementation and PostgreSQL's system catalogs.
What is the difference between catalog definitions and snapshot seams in pgrust?
Catalog definitions (in types_core) provide compile-time constants and struct layouts for system tables, while snapshot seams (in snapmgr_seams) provide runtime MVCC-consistent views of these catalogs during query execution. The definitions are static metadata; the seams manage dynamic visibility and cache invalidation.
Where are extension-specific catalog objects registered in pgrust?
Extension modules register catalog objects in their respective src/lib.rs files within the crates/contrib/ directory. For example, crates/contrib/pgcrypto/src/lib.rs inserts cryptographic function entries into the pg_proc catalog through the seam API, while pg_trgm registers GiST opclass information in trgm_gist.rs.
How does the catalog snapshot system handle schema changes during transactions?
The snapshot manager in crates/backend/utils/time/snapmgr_seams/src/lib.rs tracks catalog modifications and provides invalidate_catalog_snapshot() to clear stale caches. When DDL statements modify system tables, calling this function ensures subsequent catalog lookups see the updated schema while maintaining MVCC consistency for existing snapshots.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →