Skip to content

Commit cfef804

Browse files
committed
docs: creating pgrx extension
1 parent aa78cb3 commit cfef804

1 file changed

Lines changed: 238 additions & 0 deletions

File tree

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
# Creating a New pgrx Extension
2+
3+
This guide covers how to set up a new cargo pgrx PostgreSQL extension in this project.
4+
5+
## Template: New pgrx Extension
6+
7+
### 1. Directory Structure
8+
9+
Create your extension directory:
10+
11+
```
12+
nix/ext/my_extension/
13+
├── default.nix # Nix build configuration
14+
└── Cargo.lock.patch # (optional) if upstream lacks Cargo.lock
15+
```
16+
17+
### 2. Extension Nix File Template
18+
19+
Create `nix/ext/my_extension/default.nix`:
20+
21+
```nix
22+
{
23+
lib,
24+
stdenv,
25+
callPackages,
26+
fetchFromGitHub,
27+
postgresql,
28+
buildEnv,
29+
rust-bin,
30+
pkg-config,
31+
openssl,
32+
}:
33+
34+
let
35+
pname = "my_extension";
36+
37+
build =
38+
version: hash: rustVersion: pgrxVersion:
39+
let
40+
cargo = rust-bin.stable.${rustVersion}.default;
41+
mkPgrxExtension = callPackages ../../cargo-pgrx/mkPgrxExtension.nix {
42+
inherit rustVersion pgrxVersion;
43+
};
44+
in
45+
mkPgrxExtension rec {
46+
inherit pname version postgresql;
47+
48+
src = fetchFromGitHub {
49+
owner = "your-org";
50+
repo = pname;
51+
rev = "v${version}";
52+
inherit hash;
53+
};
54+
55+
nativeBuildInputs = [ pkg-config cargo ];
56+
buildInputs = [ openssl postgresql ];
57+
58+
CARGO = "${cargo}/bin/cargo";
59+
60+
cargoLock = {
61+
lockFile = "${src}/Cargo.lock";
62+
# Add outputHashes if you have git dependencies:
63+
# outputHashes = {
64+
# "some-crate-0.1.0" = "sha256-...";
65+
# };
66+
};
67+
68+
# Optional: if extension's Cargo.toml needs modification
69+
# preConfigure = ''
70+
# sed -i 's/pgrx = "0.12"/pgrx = "0.12.6"/' Cargo.toml
71+
# '';
72+
73+
meta = with lib; {
74+
description = "Description of your extension";
75+
homepage = "https://github.com/your-org/${pname}";
76+
license = licenses.mit; # adjust as needed
77+
};
78+
};
79+
80+
allVersions = (builtins.fromJSON (builtins.readFile ../versions.json)).${pname};
81+
82+
supportedVersions = lib.filterAttrs (
83+
_: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql
84+
) allVersions;
85+
86+
versions = lib.naturalSort (lib.attrNames supportedVersions);
87+
latestVersion = lib.last versions;
88+
89+
packages = map (
90+
version:
91+
let
92+
v = supportedVersions.${version};
93+
in
94+
build version v.hash v.rust v.pgrx
95+
) versions;
96+
in
97+
buildEnv {
98+
name = pname;
99+
paths = packages;
100+
pathsToLink = [
101+
"/lib"
102+
"/share/postgresql/extension"
103+
];
104+
105+
postBuild = ''
106+
# Create version-specific SQL symlinks for migrations
107+
${lib.concatMapStringsSep "\n" (version: ''
108+
if [ -f $out/share/postgresql/extension/${pname}--${version}.sql ]; then
109+
ln -sf ${pname}--${version}.sql $out/share/postgresql/extension/${pname}--${latestVersion}--${version}.sql 2>/dev/null || true
110+
fi
111+
'') versions}
112+
'';
113+
}
114+
```
115+
116+
### 3. Add to versions.json
117+
118+
Edit `nix/ext/versions.json` and add your extension:
119+
120+
```json
121+
{
122+
"my_extension": {
123+
"0.1.0": {
124+
"postgresql": ["15", "17"],
125+
"hash": "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
126+
"pgrx": "0.12.6",
127+
"rust": "1.80.0"
128+
}
129+
}
130+
}
131+
```
132+
133+
**To calculate the hash:** Use a dummy hash first, then run:
134+
```bash
135+
nix build .#psql_15/exts/my_extension -L
136+
```
137+
The error message will show the correct hash.
138+
139+
### 4. Register in postgres.nix
140+
141+
Edit `nix/packages/postgres.nix` and add to the `ourExtensions` list:
142+
143+
```nix
144+
ourExtensions = [
145+
# ... existing extensions ...
146+
../ext/my_extension/default.nix
147+
];
148+
```
149+
150+
## Files to Modify (Summary)
151+
152+
| File | Change |
153+
|------|--------|
154+
| `nix/ext/my_extension/default.nix` | Create new file |
155+
| `nix/ext/versions.json` | Add version entry |
156+
| `nix/packages/postgres.nix` | Add to `ourExtensions` list |
157+
| `nix/tests/sql/my_extension.sql` | (optional) Add test SQL |
158+
| `nix/tests/expected/my_extension.out` | (optional) Expected test output |
159+
160+
## Using nix develop for Extension Development
161+
162+
### Available Dev Shells
163+
164+
```bash
165+
# List all available dev shells
166+
nix flake show | grep devShells
167+
168+
# Enter pgrx 0.12.6 development environment (Rust 1.80.0)
169+
nix develop .#cargo-pgrx_0_12_6
170+
171+
# Enter pgrx 0.14.3 development environment (Rust 1.87.0)
172+
nix develop .#cargo-pgrx_0_14_3
173+
174+
# Default shell (general tooling, not pgrx-specific)
175+
nix develop
176+
```
177+
178+
### Inside the Dev Shell
179+
180+
Once inside `nix develop .#cargo-pgrx_0_12_6`:
181+
182+
```bash
183+
# Initialize pgrx (first time only)
184+
cargo pgrx init --pg15 $(which pg_config)
185+
186+
# Create a new extension from scratch
187+
cargo pgrx new my_extension
188+
cd my_extension
189+
190+
# Build and test your extension
191+
cargo pgrx run pg15
192+
193+
# Package for release
194+
cargo pgrx package
195+
```
196+
197+
### Dev Shell Contents
198+
199+
The pgrx dev shells provide:
200+
- Correct Rust toolchain version
201+
- `cargo-pgrx` CLI matching the pgrx version
202+
- PostgreSQL headers and pg_config
203+
- Required build tools (pkg-config, openssl, etc.)
204+
205+
## Build Commands
206+
207+
```bash
208+
# Build extension for PostgreSQL 15
209+
nix build .#psql_15/exts/my_extension -L
210+
211+
# Build extension for PostgreSQL 17
212+
nix build .#psql_17/exts/my_extension -L
213+
214+
# Build all extensions (full PostgreSQL package)
215+
nix build .#psql_15/bin -L
216+
217+
# Run tests
218+
nix flake check -L
219+
```
220+
221+
## Quick Reference: pgrx + Rust Version Combinations
222+
223+
From `nix/cargo-pgrx/versions.json`:
224+
225+
| pgrx Version | Rust Version |
226+
|--------------|--------------|
227+
| 0.12.6 | 1.80.0, 1.81.0 |
228+
| 0.14.3 | 1.87.0 |
229+
230+
Match your extension's pgrx dependency to a supported combination.
231+
232+
## Existing Examples to Reference
233+
234+
| Extension | Path | Notes |
235+
|-----------|------|-------|
236+
| pg_graphql | `nix/ext/pg_graphql/default.nix` | Clean pgrx example |
237+
| pg_jsonschema | `nix/ext/pg_jsonschema/default.nix` | Simple single-crate |
238+
| wrappers | `nix/ext/wrappers/default.nix` | Complex with git deps |

0 commit comments

Comments
 (0)