# Seams and builtin libraries

> Seam registration model, seams-init aggregation, and dfmgr builtin-library registration that replaces dlopen for ported contrib and regress helpers.

- Repository: malisper/pgrust
- GitHub: https://github.com/malisper/pgrust
- Human docs: https://grok-wiki.com/public/docs/malisper-pgrust-7e0c8e82bc21
- Complete Markdown: https://grok-wiki.com/public/docs/malisper-pgrust-7e0c8e82bc21/llms-full.txt

## Source Files

- `crates/_support/seam/seam_core/src/lib.rs`
- `crates/_support/seam/init/src/lib.rs`
- `crates/_support/seam/init/src/bin/postgres.rs`
- `crates/backend/utils/fmgr/dfmgr_seams/src/lib.rs`
- `crates/backend/test_regress/src/lib.rs`
- `crates/contrib/pg_stat_statements/src/lib.rs`

---

---
title: "Seams and builtin libraries"
description: "Seam registration model, seams-init aggregation, and dfmgr builtin-library registration that replaces dlopen for ported contrib and regress helpers."
---

pgrust links the server as one Rust `postgres` binary. Cross-crate calls that would form a Cargo dependency cycle go through **seams** (`OnceLock` function slots). Ported shared libraries (contrib modules, `regress`, PL/pgSQL, snowball, logical-decoding plugins) never `dlopen` a `.so`: they register into an in-process **builtin library** table that `dfmgr` consults before the OS loader.

## Architecture

```mermaid
flowchart TB
  subgraph bin["postgres binary"]
    main["init/src/bin/postgres.rs main()"]
    top["TopMemoryContext leak"]
    initall["init::init_all()"]
    pgmain["main_main::pg_main"]
    main --> top --> initall --> pgmain
  end

  subgraph seams["Seam layer"]
    core["seam_core::seam!"]
    xseams["X_seams crates<br/>declare slots"]
    owners["Owner crates<br/>init_seams() → slot::set"]
    core --> xseams
    owners --> xseams
    initall --> owners
  end

  subgraph builtins["Builtin library layer"]
    reg["dfmgr_seams BUILTIN_LIBRARIES"]
    regplugin["dfmgr_seams BUILTIN_OUTPUT_PLUGINS"]
    dfmgr["fmgr_dfmgr installers"]
    owners -->|"register_builtin_library"| reg
    owners -->|"register_builtin_output_plugin"| regplugin
    dfmgr -->|"builtin_library_present / resolve_*"| reg
    dfmgr -->|"resolve / invoke builtin plugin"| regplugin
  end

  subgraph sql["SQL / catalog path"]
    create["CREATE FUNCTION / CREATE EXTENSION<br/>LANGUAGE C AS '$libdir/…'"]
    load["LOAD 'module'"]
    create --> dfmgr
    load --> dfmgr
  end
```

| Layer | Crate / path | Role |
| --- | --- | --- |
| Macro | `seam_core` (`crates/_support/seam/seam_core`) | `seam!` → module with `set` / `call` / `is_installed` |
| Aggregator | `init` (`crates/_support/seam/init`) | `init_all()` calls every ported crate’s `init_seams()` |
| Binary | `postgres` bin in `init` | Leaks top memory context, runs `init_all()`, then `pg_main` |
| Declarations | `*_seams` crates (e.g. `heapam_seams`, `dfmgr_seams`) | Own the slot types; no implementations |
| Installers | Ported owner crates | `init_seams()` installs owned slots and/or registers builtins |
| Dynamic load | `fmgr_dfmgr` + `dfmgr_seams` | Registry-aware `load_file` / `load_external_function` / output plugins |

## Seam model

A seam exists only where a direct Cargo dependency would create a cycle. Declarations for crate X’s functions live in an `X_seams` crate; crate X installs them from `init_seams()`; `init::init_all()` invokes every such installer once at process start.

### `seam!` expansion

`seam_core::seam!(pub fn name(...) -> ...)` expands to a module `name` with:

| API | Behavior |
| --- | --- |
| `set(implementation)` | Installs into a process-global `OnceLock`. Second install panics: `seam installed twice: <module_path>` |
| `call(...)` | Invokes the installed body. Missing install panics: `seam not installed: <module_path>` |
| `is_installed()` | `true` after a successful `set` |
| `Signature` | `fn(...)` or higher-ranked `for<'a, ...> fn(...)` when lifetimes are declared |

There is no silent fallback. Optional feature `trace-seams` records hit/miss via `trace::Category::Seam`.

Lifetime:

```rust
// In an X_seams crate — declaration only
seam_core::seam!(
    pub fn vacuum_rel(relid: types_core::Oid) -> types_error::PgResult<()>
);

// In the owner crate's init_seams()
vacuum_rel_seams::vacuum_rel::set(my_vacuum_rel_impl);
```

Lifetime-generic form (allocator lifetimes, e.g. `Mcx<'mcx>`) is supported: the stored pointer is `for<'a> fn(...)`.

### Ownership rules

1. **Declare** in `*_seams` (depends on `seam_core` + shared types only).
2. **Install** from the owning unit’s `pub fn init_seams()` via `::set`.
3. **Call** from dependents via `::call` — dependents depend on `*_seams`, not on the owner (that is the cycle break).
4. Wire the owner into `init::init_all()` (and add a path dep in `crates/_support/seam/init/Cargo.toml`).

Uninstalled seams panic on first use. Double-install panics at boot when two crates both `set` the same slot.

## Startup aggregation (`init`)

The Cargo package is `init` at `crates/_support/seam/init` (repo comments often say “seams-init”). It holds **no** business logic and **no** `set()` calls of its own: one `crate::init_seams()` line per ported crate, kept sorted.

```rust
// crates/_support/seam/init/src/lib.rs (shape)
pub fn init_all() {
    // One line per ported crate…
    pg_stat_statements::init_seams();
    test_regress::init_seams();
    // …hundreds more backend / contrib / catalog units…
}
```

### Process entry

`crates/_support/seam/init/src/bin/postgres.rs` mirrors `src/backend/main/main.c`:

1. Build `argv`.
2. Leak `TopMemoryContext` and obtain a `'static` `mcx`.
3. **`init::init_all()`** — seam registry + builtin registrations must be complete before any cross-crate call.
4. `pg_main(mcx, &argv)` → postmaster / single-user / bootstrap / `--initdb` / print-and-exit paths.

```text
postgres main
  → MemoryContext "TopMemoryContext"
  → init::init_all()          # seams + builtin libraries
  → pg_main(mcx, argv)
```

### Guards and baseline

| Check | What it enforces |
| --- | --- |
| Integration tests under `init` | Every crate that defines `init_seams` is reachable from `init_all` (static wiring) |
| `tests/no_double_install.rs` | Full `init_all()` in a clean process completes without `seam installed twice` |
| `builtin_gap_baseline` | Live `missing_builtins()` after `init_all()` matches the checked-in OID/name gap set |

When porting a new unit: implement `init_seams()`, add dependency + call line in `init`, run the aggregator tests.

## Builtin libraries (dlopen replacement)

The Rust backend does not expose a C ABI suitable for loading stock `.so` modules. SQL that does `LANGUAGE C AS '$libdir/<name>', '<symbol>'` still works for **ported** modules because `dfmgr` resolves them in-process.

### Registry API (`dfmgr_seams`)

| Item | Purpose |
| --- | --- |
| `BuiltinLibraryEntry { name, lookup, pg_init }` | One ported shared library |
| `register_builtin_library(entry)` | Called from the module crate’s `init_seams()`; replace-on-same-name (idempotent re-init) |
| `registry_library_present(library)` | Name in table? |
| `registry_resolve(library, function)` | Symbol → `Option<LoadedExternalFunc>` |
| `registry_pg_init(library)` | Optional `_PG_init`-equivalent |

Seam consult surface (installed once by `fmgr_dfmgr::init_seams`):

- `builtin_library_present(library) -> bool`
- `resolve_builtin_library_function(library, function) -> PgResult<Option<LoadedExternalFunc>>`

Also declared on the same crate: `load_file`, `load_external_function`, and logical-decoding load/dispatch seams.

### Name keying

`fmgr_dfmgr::simple_library_name` reduces a `probin` / load path to a registry key:

- `$libdir/regress` → `regress`
- `/path/to/pg_stat_statements.so` → `pg_stat_statements`
- Strips known suffixes `.so` / `.dylib` / `.dll` (key is not opened as a file)

### Load and resolve path

**`load_external_function(probin, prosrc, …)`** (CREATE FUNCTION / fmgr resolve):

1. `simple_library_name(probin)` → key.
2. If `builtin_library_present(key)`:
   - Run `pg_init` once per backend (`run_builtin_pg_init_once`).
   - `resolve_builtin_library_function(key, prosrc)`.
   - Missing symbol → error: `could not find function "<prosrc>" in file "<probin>"` (`ERRCODE_UNDEFINED_FUNCTION`).
3. Else fall through to the OS dynamic loader path (fails in this build for unported C modules).

**`load_file` / `LOAD`** (utility):

1. Same present check.
2. On hit: `run_builtin_pg_init_once` then success (no OS open).
3. Else OS path.

`pg_init` must be **idempotent** at the registry level; the loader also de-duplicates with a per-backend “already inited” set so hooks/GUCs run once, matching C’s first-load `_PG_init`.

### Registered builtin libraries

| Registry `name` | Owner area | Typical `pg_init` |
| --- | --- | --- |
| `regress` | `backend/test_regress` | `None` |
| `citext` | `contrib/citext` | `None` |
| `hstore` | `contrib/hstore` | `None` |
| `ltree` | `contrib/ltree` | `None` |
| `pg_trgm` | `contrib/pg_trgm` | `Some` |
| `pgcrypto` | `contrib/pgcrypto` | `Some` |
| `pg_stat_statements` | `contrib/pg_stat_statements` | `Some` (hooks/GUCs when preload) |
| `uuid-ossp` | `contrib/uuid_ossp` | `None` |
| `pg_prewarm` | `contrib/pg_prewarm` | `None` |
| `injection_points` | `contrib/injection_points` | `None` (+ injection callbacks) |
| `plpgsql` | `pl/plpgsql` handler | `Some` (GUCs / reserved prefix) |
| `dict_snowball` | `backend/snowball/dict_snowball` | `None` |

### Output plugins (related registry)

Logical decoding plugins use a parallel table:

- `BuiltinOutputPlugin { name, init, invoke }`
- `register_builtin_output_plugin` / `resolve_builtin_output_plugin` / `registry_invoke_builtin_output_plugin`
- Ported example: `test_decoding` (`contrib/test_decoding`) as name `"test_decoding"`

`load_output_plugin` consults the builtin table **before** the OS loader; per-change dispatch can pass a live `LogicalDecodingContext` into the registered `invoke`.

## Port pattern (contrib / regress)

Each ported loadable module:

1. Defines `const LIBRARY: &str = "…"` (simple name matching `$libdir/…`).
2. Implements fmgr-1 bodies as `PGFunction` / `LoadedExternalFunc { user_fn, api_version: 1 }`.
3. Implements `fn lookup(function: &str) -> Option<LoadedExternalFunc>` (match on `prosrc` symbol).
4. Optionally implements `fn pg_init() -> PgResult<()>` (C `_PG_init`).
5. In `pub fn init_seams()`:

```rust
pub fn init_seams() {
    dfmgr_seams::register_builtin_library(dfmgr_seams::BuiltinLibraryEntry {
        name: LIBRARY,
        lookup,
        pg_init: Some(pg_init), // or None
    });
}
```

6. Ensures `init` depends on the crate and calls `that_crate::init_seams()` from `init_all()`.

SQL and control files still use vendored extension scripts (`MODULE_PATHNAME` / `$libdir/...`); only the **body** is in-process. Unported modules remain unusable: no C ABI, OS `dlopen` path does not load arbitrary Postgres extensions.

`regress` additionally registers planner-support symbols by `prosrc` for symbols that are not fixed builtin OIDs (e.g. `test_support_func`).

## Verification

```bash
# Aggregator + double-install / wiring guards
cargo test -p init

# Full crate gate that also exercises the aggregator when --full
scripts/gate-crate --full <your-crate>

# Single crate under change
scripts/check-crate <your-crate>
cargo test -p <your-crate>
```

Runtime signals of miswiring:

| Symptom | Likely cause |
| --- | --- |
| `seam not installed: …` panic | Owner’s `init_seams` missing, not called from `init_all`, or call order never reached |
| `seam installed twice: …` panic | Two installers of the same slot; fails clean-process boot / `no_double_install` |
| `could not find function "…" in file "…"` | Library registered but symbol missing from `lookup` |
| OS / dlopen-style failure for `$libdir/foo` | Library name not registered (unported extension) |
| Extension SQL OK but hooks/GUCs missing | `pg_init` not registered or never run (needs load / first resolve path) |

## Constraints

- Seams are **not** a general plugin API for third-party crates; they are an internal cycle-break and install registry for the monorepo port.
- Builtin registration only covers libraries **ported into this tree** and wired into `init_all`. Generic Postgres extensions still require C ABI / `.so` load, which this backend does not provide.
- `init_all()` is intended **once per process** (OnceLock slots). Do not call it twice in the same process expecting reinstall.
- `register_builtin_library` is replace-by-name; double registration of the same name is harmless, unlike seam `set`.

## Related pages

<CardGroup>
  <Card title="Compatibility and status" href="/compatibility">
    Extension and PL boundaries that block generic Postgres extensions.
  </Card>
  <Card title="Use contrib extensions" href="/contrib-extensions">
    Ported contrib modules, CREATE EXTENSION, and unported gaps.
  </Card>
  <Card title="Process modes and dispatch" href="/process-modes">
    How the postgres binary dispatches after seam init.
  </Card>
  <Card title="Workspace and crate checks" href="/workspace-workflow">
    check-crate, gate-crate, and validating a crate plus the init aggregator.
  </Card>
  <Card title="Run regression tests" href="/regression-tests">
    Regression harness that depends on the in-process regress builtin.
  </Card>
  <Card title="Troubleshooting" href="/troubleshooting">
    Boot and extension-load failure modes.
  </Card>
</CardGroup>
