# Installation
This extension is built from the `graph/` crate with `pgrx` 0.18.0. The crate
officially supports PostgreSQL 14 through 18 and defaults to `pg17`. A legacy
`pg13` pgrx feature remains available on a best-effort basis because pgrx 0.18
still exposes it, but PostgreSQL 13 has reached upstream EOL and is not part of
the release support matrix.
## Requirements
| Requirement | Version or note |
|---|---|
| Rust | `1.95`, pinned by `graph/rust-toolchain.toml` |
| PostgreSQL | 14, 15, 16, 17, or 18, with server development headers and `pg_config` |
| pgrx | `0.18.0` |
| Crate feature | One of `pg14`, `pg15`, `pg16`, `pg17`, `pg18` |
| Extension control | `graph/graph.control` |
Install with the PostgreSQL major that matches the target server. A `pg17`
build should not be installed into a PostgreSQL 16 server.
## Install pgrx
Install cargo-pgrx and register the PostgreSQL on your `PATH` with pgrx. The
major is detected from `pg_config`:
```bash
cargo install cargo-pgrx --version 0.18.0 --locked
PG_MAJOR=$(pg_config --version | sed -E 's/[^0-9]*([0-9]+).*/\1/')
cargo pgrx init --pg${PG_MAJOR}="$(which pg_config)"
```
To register a different installation, point the flag at that server's
`pg_config`. For example, a Debian or Ubuntu PostgreSQL 16 install:
```bash
cargo pgrx init --pg16=/usr/lib/postgresql/16/bin/pg_config
```
For PostgreSQL 13, use the legacy `pg13` pgrx feature only as best-effort
compatibility. It is not covered by release gates after PostgreSQL 13 upstream
EOL.
## PGXN Source Install
pgGraph is available on PGXN as a source distribution. Because pgGraph is a
Rust/pgrx extension, source installation requires Rust and `cargo-pgrx` before
running `pgxn install`.
```bash
cargo install cargo-pgrx --version 0.18.0 --locked
# Register the installed PostgreSQL with pgrx (auto-detects the major):
PG_MAJOR=$(pg_config --version | sed -E 's/[^0-9]*([0-9]+).*/\1/')
cargo pgrx init --pg${PG_MAJOR}="$(which pg_config)"
pgxn install pgGraph
```
## Manual Source Install
Compile and install the extension from source:
```bash
git clone https://github.com/evokoa/pggraph.git
cd pggraph
make install # may need sudo
```
If your machine has multiple PostgreSQL installations, set `PG_CONFIG` to the
target server's `pg_config`, then re-run the installation:
```bash
export PG_CONFIG=/usr/lib/postgresql/17/bin/pg_config
make install
```
If `sudo` is needed for `make install`, preserve `PG_CONFIG`:
```bash
sudo --preserve-env=PG_CONFIG make install
```
If compilation fails with `fatal error: postgres.h: No such file or directory`,
install the PostgreSQL server development package for the target PostgreSQL
major, such as `postgresql-server-dev-17` on Ubuntu or Debian.
## Build And Install With cargo-pgrx
`make install` wraps this flow. To run it directly, build with the feature that
matches your `pg_config` major and install into that server:
```bash
cd graph
PG_MAJOR=$(pg_config --version | sed -E 's/[^0-9]*([0-9]+).*/\1/')
cargo pgrx install --no-default-features --features pg${PG_MAJOR} --pg-config="$(which pg_config)"
```
To target a different installation, set its `pg_config` explicitly. For example,
a Debian or Ubuntu PostgreSQL 16 install:
```bash
cd graph
cargo pgrx install --no-default-features --features pg16 --pg-config=/usr/lib/postgresql/16/bin/pg_config
```
## Create The Extension
```sql
CREATE EXTENSION graph;
```
The bootstrap SQL creates:
| Object | Purpose |
|---|---|
| `graph.node_ref` | Composite start-node type for one traversal overload |
| `graph.node_ref(regclass, text)` | Constructor for `graph.node_ref` |
| `graph.traverse(graph.node_ref[], ...)` | SQL wrapper over the Rust multi-start traversal overload |
| `graph._registered_tables` | Durable registration catalog for node source tables |
| `graph._registered_edges` | Durable registration catalog for edge definitions |
| `graph._registered_filter_columns` | Durable registration catalog for traversal filter columns |
| `graph._build_jobs` | Durable asynchronous build job state |
| `graph._maintenance_jobs` | Durable maintenance job state |
| `graph._sync_log` | Durable trigger sync log |
| `graph._sync_buffer` | Legacy sync buffer compatibility table |
Internal catalog tables are extension-owned. They are readable by `PUBLIC` but
not directly writable by non-admin roles.
Pre-release catalog schema changes require recreating development and test
databases. Drop and recreate the extension with `DROP EXTENSION graph CASCADE;`
followed by `CREATE EXTENSION graph;` instead of relying on runtime migrations.
## Docker Install Options
pgGraph supports two Docker installation paths:
| Path | Use when |
|---|---|
| Build a PostgreSQL image with pgGraph already installed | You want a new container image for Evokoa or local evaluation |
| Install into an existing running PostgreSQL container | You already have a PostgreSQL container and want to add pgGraph to it |
### Build A PostgreSQL Image With pgGraph
From the repository root, build the root `Dockerfile` with the PostgreSQL major
that should be installed in the image:
```bash
docker build --build-arg PG_MAJOR=17 -t pggraph-postgres:17 .
```
Start the container:
```bash
docker run \
--name pggraph-postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=graph \
-p 5432:5432 \
pggraph-postgres:17
```
The root Docker image starts PostgreSQL with `pg_cron` and `graph` in
`shared_preload_libraries`, runs
`docker/init/01-create-extensions-and-schedule.sql` on first database
initialization, and creates:
| Object | Purpose |
|---|---|
| `pg_cron` extension | Enables cron-style scheduling inside the Docker database |
| `graph` extension | Installs pgGraph in the Docker database |
| `pggraph-maintenance` cron job | Runs `graph.run_scheduled_maintenance()` every five minutes |
The init SQL runs only when PostgreSQL initializes a new data directory. If you
reuse an existing Docker volume, recreate the volume before expecting init SQL
changes to apply.
For databases beyond the initial Docker database, create the extension
explicitly:
```sql
CREATE EXTENSION graph;
```
### Install Into An Existing PostgreSQL Container
Use the helper script from the repository root:
```bash
scripts/install_into_docker_postgres.sh CONTAINER [PG_MAJOR] [DB_NAME] [DB_USER]
```
For example, to install pgGraph built for PostgreSQL 17 into a running container
named `my-postgres` and create the extension in `appdb`:
```bash
scripts/install_into_docker_postgres.sh my-postgres 17 appdb postgres
```
The one-shot script builds the matching pgGraph package, copies the extension
control, SQL, and shared library files into the target container, and runs:
```sql
CREATE EXTENSION IF NOT EXISTS graph;
```
The lower-level steps are also available when you want to build once and install
the same package into one or more containers:
```bash
scripts/build_docker_pggraph_package.sh 17 target/docker-packages
scripts/copy_pggraph_package_to_docker_postgres.sh \
my-postgres target/docker-packages/graph-pg17 17 appdb postgres
```
To build packages for all supported PostgreSQL majors:
```bash
scripts/build_docker_pggraph_package.sh all target/docker-packages
```
Set `SKIP_CREATE_EXTENSION=1` to copy the files without creating the extension:
```bash
SKIP_CREATE_EXTENSION=1 scripts/install_into_docker_postgres.sh my-postgres 17
```
The PostgreSQL major must match the target container. A PostgreSQL 17 pgGraph
build should not be copied into a PostgreSQL 16 container. The target container
also needs compatible operating-system and CPU architecture assumptions for the
compiled extension.
## shared_preload_libraries
Most functionality works without `shared_preload_libraries`, but setting it lets
PostgreSQL call `_PG_init()` at server startup. `_PG_init()` registers the GUCs
and asks the operating system to pre-warm an existing `.pggraph` file.
```conf
shared_preload_libraries = 'graph'
```
Then restart PostgreSQL.
Pre-warming does not load the engine in every backend. Query backends still load
the graph lazily on first use when `graph.auto_load = true`.
## Verify Installation
```sql
SELECT graph.test_enabled();
SELECT * FROM graph.status();
```
Expected initial state before build:
| Column | Typical value |
|---|---|
| `node_count` | `0` |
| `edge_count` | `0` |
| `sync_mode` | `manual` unless configured |
| `schema_status` | `current` |
## Development Test Commands
```bash
cd graph
cargo fmt --check
cargo test --features pg17
cargo pgrx test pg17
```
SQLSTATE and ACL boundary tests intentionally run outside `cargo pgrx test`
because they need a normal client/server error boundary:
```bash
cd graph
PG_VERSION_FEATURE=pg17 DBNAME=pggraph_boundary ./tests/heavy/run_sqlstate_acl_boundary.sh
```
## Docker And Packaging Checks
The heavy test suite includes packaging, install smoke, function metadata audit,
backup/restore, Docker smoke, and PostgreSQL major matrix scripts:
```bash
cd graph
PG_VERSION_FEATURE=pg17 ./tests/heavy/package_validate.sh
PG_VERSION_FEATURE=pg17 DBNAME=pggraph_install ./tests/heavy/fresh_install_smoke.sh
PG_VERSION_FEATURE=pg17 DBNAME=pggraph_metadata ./tests/heavy/function_metadata_audit.sh
./tests/heavy/playground_release_gate.sh
./tests/heavy/docker_smoke.sh
```
For the full release gate:
```bash
cd graph
PG_VERSION_FEATURE=pg17 ./tests/heavy/run_release_gate.sh
```