# Catalog System Architecture in pgrust: A Three-Layer Rust Implementation of PostgreSQL System Tables

> Explore the pgrust catalog system architecture A three-layer Rust implementation of PostgreSQL system tables Learn about its modular design snapshot management and extension APIs

- Repository: [Michael Malis/pgrust](https://github.com/malisper/pgrust)
- Tags: architecture
- Published: 2026-07-13

---

**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`](https://github.com/malisper/pgrust/blob/main/crates/_support/types/types_core/src/catalog/pg_type.rs) – Contains `pg_type` definitions including `INT4_OID` and other built-in type constants
- [`crates/_support/types/types_core/src/catalog/pg_proc.rs`](https://github.com/malisper/pgrust/blob/main/crates/_support/types/types_core/src/catalog/pg_proc.rs) – Defines procedure catalog entries and built-in function OIDs  
- [`crates/_support/types/types_core/src/catalog/pg_class.rs`](https://github.com/malisper/pgrust/blob/main/crates/_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`](https://github.com/malisper/pgrust/blob/main/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 transaction
- `invalidate_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`](https://github.com/malisper/pgrust/blob/main/crates/backend/utils/time/snapmgr_seams/src/lib.rs) – Manages MVCC snapshots for catalog consistency
- [`crates/backend/utils/sort/tuplesort/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/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`](https://github.com/malisper/pgrust/blob/main/crates/contrib/pgcrypto/src/lib.rs) – Creates catalog objects for cryptographic functions, inserting entries into the `pg_proc` seam
- [`crates/contrib/pg_trgm/src/trgm_gist.rs`](https://github.com/malisper/pgrust/blob/main/crates/contrib/pg_trgm/src/trgm_gist.rs) – Implements GiST opclass support using catalog-driven dispatch to resolve operator OIDs
- [`crates/pl/plpgsql/src/handler/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/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:

```rust
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_seams` provides MVCC-consistent catalog views without exposing underlying storage implementation details
- **Extension integration** allows contrib modules like `pgcrypto` to 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`](https://github.com/malisper/pgrust/blob/main/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`](https://github.com/malisper/pgrust/blob/main/src/lib.rs) files within the `crates/contrib/` directory. For example, [`crates/contrib/pgcrypto/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/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`](https://github.com/malisper/pgrust/blob/main/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`](https://github.com/malisper/pgrust/blob/main/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.