# Which Index Access Methods Are Supported by pgrust? B‑tree, Hash, GiST, and GIN

> Explore pgrust's support for PostgreSQL index access methods including B-tree, Hash, GiST, and GIN. Discover Rust-based equivalents for efficient indexing.

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

---

**pgrust implements all four core PostgreSQL index access methods—B‑tree, Hash, GiST, and GIN—providing complete Rust-based equivalents to PostgreSQL's `nbtree`, `hash`, `gist`, and `gin` access methods.**

The pgrust project reimplements PostgreSQL's storage engine in safe Rust, including full support for the standard index access methods defined by PostgreSQL's Access Method (AM) API. These implementations reside in dedicated crates under `crates/backend/access/`, offering memory-safe alternatives to PostgreSQL's C-based index handlers while maintaining compatibility with the `IndexAmRoutine` callback structure.

## B‑tree Index Implementation

The **B‑tree** access method in pgrust lives in `crates/backend/access/nbtree/nbtree_core/src/`. This crate contains the complete B‑tree logic including page layout management, tree traversal, and node splitting.

Key source files include:
- [`search.rs`](https://github.com/malisper/pgrust/blob/main/search.rs) – Implements tree traversal and key lookup algorithms
- [`insert.rs`](https://github.com/malisper/pgrust/blob/main/insert.rs) – Handles tuple insertion and page split operations

The module exposes standard PostgreSQL B‑tree callbacks through `IndexAmRoutine`, allowing the planner to create indexes via `CREATE INDEX` and execute scans using `nbtree_core::insert::btree_insert`.

## Hash Index Support

**Hash** indexes are implemented in [`crates/backend/access/hashfunc/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/backend/access/hashfunc/src/lib.rs) with validation routines in [`crates/backend/access/hashvalidate/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/backend/access/hashvalidate/src/lib.rs). This implementation provides bucket-based hash indexing with collision handling and consistency verification.

The hash function library computes bucket locations for heap TIDs, while `hashvalidate` ensures index consistency during operations. When executing `CREATE INDEX ... USING HASH`, pgrust routes calls through `hashfunc::hash_insert` to store entries in hash bucket pages.

## GiST (Generalized Search Tree) Access Method

pgrust implements **GiST** functionality in `crates/backend/access/spgist/spgist_core/src/`. This crate provides the generic index infrastructure required for extensible data types, including scan operations and handler routines.

Important files include:
- [`spgscan.rs`](https://github.com/malisper/pgrust/blob/main/spgscan.rs) – GiST scan implementation
- [`spgproc.rs`](https://github.com/malisper/pgrust/blob/main/spgproc.rs) – Procedural handlers for GiST operations

The GiST module supports extensible operator classes such as `ltree_gist_ops` (demonstrated in [`crates/contrib/ltree/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/contrib/ltree/src/lib.rs)), enabling spatial and custom data type indexing through the generic tree structure.

## GIN (Generalized Inverted Index) Implementation

The **GIN** access method resides in [`crates/backend/access/gin/ginutil/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/backend/access/gin/ginutil/src/lib.rs), providing utility routines for inverted index operations. GIN supports complex data types like arrays and full-text search documents through postings lists.

Concrete operator class implementations demonstrate GIN integration:
- [`crates/contrib/pg_trgm/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/contrib/pg_trgm/src/lib.rs) – Trigram matching with GIN opclass wiring
- [`crates/contrib/hstore/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/contrib/hstore/src/lib.rs) – Key-value GIN indexing

The generic GIN dispatcher routes opclass requests through `ginutil`, calling specific functions like `gin_consistent` and `gin_extract_value` during index maintenance and scanning.

## Practical Usage Examples

When creating indexes in pgrust, the planner selects the appropriate access method OID and routes to the corresponding Rust implementation.

### Creating a B‑tree Index

```sql
CREATE INDEX ON my_table (col1);

```

```rust
// The planner resolves `col1`’s OID, chooses the B‑tree AM (OID = BTREE_AM_OID),
// and builds an IndexInfo that is later passed to pgrust’s B‑tree inserter.
// Internally the B‑tree code in `nbtree_core` creates the root page and
// calls `nbtree_core::insert::btree_insert` for each tuple.

```

### Creating a GIN Index on tsvector

```sql
CREATE INDEX ON docs USING GIN (content);

```

```rust
// The planner selects the GIN access method (OID = GIN_AM_OID).
// pgrust routes the opclass `gin_tsvector_ops` through the generic GIN
// dispatcher (`crate::gin::extproc`) which ends up in `ginutil` and then
// calls the opclass’s `gin_consistent` / `gin_extract_value` functions.

```

### Creating a GiST Index on ltree

```sql
CREATE INDEX ON paths USING GiST (path);

```

```rust
// The GiST AM handler lives in `spgist_core`.  The planner builds a
// GiST `IndexInfo`, and the execution engine invokes `spgist_core::spg_insert`
// for each entry, using the ltree-specific GiST opclass (`ltree_gist_ops`).

```

### Creating a Hash Index

```sql
CREATE INDEX ON users USING HASH (email);

```

```rust
// The Hash AM is implemented in `hashfunc`.  During index creation the
// planner calls `hashfunc::hash_insert` for each row, which computes the
// hash and stores the heap TID in a hash bucket page.

```

## Key Source Files and Architecture

| Access Method | Primary Crate | Key Files |
|---------------|---------------|-----------|
| **B‑tree** | `nbtree_core` | [`crates/backend/access/nbtree/nbtree_core/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/backend/access/nbtree/nbtree_core/src/lib.rs) (entry point), [`search.rs`](https://github.com/malisper/pgrust/blob/main/search.rs), [`insert.rs`](https://github.com/malisper/pgrust/blob/main/insert.rs) |
| **Hash** | `hashfunc` | [`crates/backend/access/hashfunc/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/backend/access/hashfunc/src/lib.rs), [`crates/backend/access/hashvalidate/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/backend/access/hashvalidate/src/lib.rs) |
| **GiST** | `spgist_core` | [`crates/backend/access/spgist/spgist_core/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/backend/access/spgist/spgist_core/src/lib.rs), [`spgscan.rs`](https://github.com/malisper/pgrust/blob/main/spgscan.rs), [`spgproc.rs`](https://github.com/malisper/pgrust/blob/main/spgproc.rs) |
| **GIN** | `ginutil` | [`crates/backend/access/gin/ginutil/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/backend/access/gin/ginutil/src/lib.rs) |
| **Catalog** | `syscache_seams` | [`crates/backend/utils/cache/syscache_seams/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/backend/utils/cache/syscache_seams/src/lib.rs) (AM OID lookups) |
| **Opclass Examples** | `pg_trgm`, `hstore`, `ltree` | [`crates/contrib/pg_trgm/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/contrib/pg_trgm/src/lib.rs), [`crates/contrib/hstore/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/contrib/hstore/src/lib.rs), [`crates/contrib/ltree/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/contrib/ltree/src/lib.rs) |

## Summary

- **pgrust** provides Rust implementations for all four standard PostgreSQL index access methods: **B‑tree**, **Hash**, **GiST**, and **GIN**.
- Each method resides in a dedicated crate under `crates/backend/access/`, exposing `IndexAmRoutine` callbacks compatible with PostgreSQL's planner and executor.
- **B‑tree** logic handles page splits and searches in [`nbtree_core/src/search.rs`](https://github.com/malisper/pgrust/blob/main/nbtree_core/src/search.rs) and [`insert.rs`](https://github.com/malisper/pgrust/blob/main/insert.rs).
- **Hash** indexes use bucket-based storage via `hashfunc` and `hashvalidate` crates.
- **GiST** generic tree structures are implemented in `spgist_core` with support for custom operator classes.
- **GIN** inverted indexes utilize `ginutil` with concrete examples in `pg_trgm` and `hstore` contrib modules.

## Frequently Asked Questions

### Does pgrust support all standard PostgreSQL index types?

Yes, pgrust implements the four core index access methods defined by PostgreSQL: B‑tree, Hash, GiST, and GIN. These implementations provide the same `IndexAmRoutine` callbacks that PostgreSQL's planner expects, enabling transparent use with standard SQL `CREATE INDEX` commands.

### How does pgrust handle B‑tree page splits?

The B‑tree implementation in [`crates/backend/access/nbtree/nbtree_core/src/insert.rs`](https://github.com/malisper/pgrust/blob/main/crates/backend/access/nbtree/nbtree_core/src/insert.rs) manages page splits during tuple insertion. When a page exceeds capacity, the code allocates new pages and redistributes entries according to B‑tree balancing algorithms, maintaining the tree structure through the `btree_insert` function.

### What is the difference between GiST and GIN in pgrust's implementation?

GiST (Generalized Search Tree) in `spgist_core` provides a balanced tree structure framework suitable for geometric and custom data types with arbitrary splitting strategies. GIN (Generalized Inverted Index) in `ginutil` implements inverted indexes optimized for composite values containing multiple keys, such as arrays or full-text documents, with separate posting lists for each key.

### Where are the catalog lookups for index access methods handled?

Index access method metadata and OID lookups are managed by the system cache layer in [`crates/backend/utils/cache/syscache_seams/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/backend/utils/cache/syscache_seams/src/lib.rs). This module translates PostgreSQL catalog entries for `amopmethod` into the Rust structures used by pgrust's planner to select the appropriate index handler.