Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
5a01ec5
Pull pgxntool from git@github.com:decibel/pgxntool.git stable
jnasbyupgrade Nov 6, 2024
81bdb18
Squashed 'pgxntool/' changes from c0af00f..bed3604
jnasbyupgrade Nov 6, 2024
d231a58
Add support for Postgres 13
jnasbyupgrade Nov 7, 2024
e8e2717
Add pgxn-tools CI
jnasbyupgrade Nov 7, 2024
0ff8a9a
Fix CI version matrix
jnasbyupgrade Nov 7, 2024
5c59f66
Remove .travis.yml
jnasbyupgrade Nov 11, 2024
ca7c8c1
Add new relkind entries
jnasbyupgrade Aug 28, 2025
700ac3b
Add relation__is_temp and relation__is_catalog functions
jnasbyupgrade Aug 29, 2025
4addd8c
Fix relation__column_names test to use temporary table instead of pg_…
jnasbyupgrade Sep 3, 2025
b1afca2
Fix missing commits
jnasbyupgrade Sep 3, 2025
3bde4a8
Add function__arg_names()
jnasbyupgrade Sep 23, 2025
c75eb40
Rename function__arg_* to routine__parse_arg_*
jnasbyupgrade Sep 23, 2025
262434f
Remove errant function from README
jnasbyupgrade Sep 23, 2025
6ad3efb
Refactor routine__arg_names() and reorganize file structure
jnasbyupgrade Sep 25, 2025
82be5ac
Add enum types for pg_proc fields and clean up permissions
jnasbyupgrade Sep 25, 2025
7a5fe71
Add missing test file
jnasbyupgrade Nov 11, 2025
21ec71b
Add automated test workflow
jnasbyupgrade Nov 11, 2025
55db3c7
Pull pgxntool from git@github.com:decibel/pgxntool.git release
jnasbyupgrade Jan 22, 2026
5332bc5
Squashed 'pgxntool/' changes from bed3604..54793a3
jnasbyupgrade Jan 22, 2026
4b86e4f
Update .gitignore from pgxntool template
jnasbyupgrade Jan 22, 2026
4c780b0
Update to new pgxntool standards
jnasbyupgrade Feb 4, 2026
65a998b
Pull pgxntool from git@github.com:decibel/pgxntool.git release
jnasbyupgrade Feb 19, 2026
5e73ee9
Squashed 'pgxntool/' changes from 54793a3..3b8cb2a
jnasbyupgrade Feb 19, 2026
5f7e573
Pull pgxntool from git@github.com:decibel/pgxntool.git release
jnasbyupgrade Feb 19, 2026
bb6146b
Squashed 'pgxntool/' changes from 3b8cb2a..639756c
jnasbyupgrade Feb 19, 2026
a4f0695
Add placeholder comment to empty upgrade file
jnasbyupgrade Feb 26, 2026
7473aa7
Fix compatibility with PostgreSQL 15+
jnasbyupgrade Apr 6, 2026
34d6fcf
Populate upgrade script from 0.2.1 to 0.3.0
jnasbyupgrade Apr 6, 2026
ab0306c
Merge origin/master into new_functions
jnasbyupgrade Apr 6, 2026
3028c8a
Squashed 'pgxntool/' changes from 639756c..121f0b3
jnasbyupgrade Apr 6, 2026
a4e8746
Pull pgxntool from git@github.com:decibel/pgxntool.git release
jnasbyupgrade Apr 6, 2026
9e73dfb
Update .gitignore after pgxntool-sync
jnasbyupgrade Apr 6, 2026
1763a93
Switch to pgxntool built-in test/build support
jnasbyupgrade Apr 6, 2026
d910a3c
Rename zzz_build.sql to build.sql
jnasbyupgrade Apr 7, 2026
3c33da3
Install rsync in CI before running tests
jnasbyupgrade Apr 7, 2026
cd75dc6
Add upgrade test and populate 0.2.1→0.3.0 upgrade script
jnasbyupgrade Apr 7, 2026
ab5f735
Fix 0.2.1 install script for PG12+ and run upgrade test unconditionally
jnasbyupgrade Apr 7, 2026
d9fd646
Revert 0.2.1.sql changes; fix upgrade test for PG12+ compatibility
jnasbyupgrade Apr 7, 2026
a3c7476
Use explicit version number in PG12+ upgrade test
jnasbyupgrade Apr 7, 2026
84e9a0d
Fix upgrade test threshold: 0.2.1 broken on PG11+ (attmissingval), no…
jnasbyupgrade Apr 7, 2026
11fcb95
Bridge 0.2.2→0.3.0 upgrade path; cast attmissingval to text::text[]
jnasbyupgrade Apr 8, 2026
4f45664
Fix upgrade test: use ERROR to suppress deprecation WARNINGs
jnasbyupgrade Apr 14, 2026
3e290be
Release cat_tools 0.2.2: fix PG11+ and PG12+ compatibility (#7)
jnasbyupgrade Apr 27, 2026
12c5596
Remove old travis file
jnasbyupgrade Apr 27, 2026
9af1f2e
Merge branch 'master' into new_functions
jnasbyupgrade Apr 27, 2026
4b18338
Fix sql/.gitignore violations: replace tracked .sql with .sql.in
jnasbyupgrade Apr 27, 2026
5366157
Update copyright to 2026
jnasbyupgrade Apr 27, 2026
e2525b0
Merge master into new_functions; resolve version/history conflicts
jnasbyupgrade Apr 27, 2026
5400e68
Consolidate permissions tests; fix pg_attribute_v format bug; expand CI
jnasbyupgrade Apr 27, 2026
f605bb4
test/upgrade-drift: add prompt files for upgrade-drift test planning
jnasbyupgrade Apr 27, 2026
f5a65d9
Drop PostgreSQL 10 support for 0.3.0
jnasbyupgrade Apr 28, 2026
3f9070d
Enforce update/upgrade terminology; add 0.3.0 history section
jnasbyupgrade Apr 28, 2026
2d5179e
Merge remote-tracking branch 'pgext/master' into new_functions
jnasbyupgrade Apr 28, 2026
752088f
Fix two CI failures introduced by merge into new_functions
jnasbyupgrade Apr 28, 2026
a1796d5
Remove dead /test/.build/ entry from .gitignore
jnasbyupgrade Apr 28, 2026
8146d5a
Fix stale build test expected output
jnasbyupgrade Apr 28, 2026
94a29b5
Fix PG11 ALTER TYPE restriction in upgrade test and CI matrix
jnasbyupgrade Apr 29, 2026
1b31c0d
Fix binary pg_upgrade compatibility: exclude relhasoids from pg_class_v
jnasbyupgrade Apr 30, 2026
7d3d367
Also omit relhaspkey from pg_class_v (removed in PG11)
jnasbyupgrade May 1, 2026
0c54003
Also omit attcacheoff from pg_attribute_v (removed in PG18)
jnasbyupgrade May 1, 2026
312a11c
Consolidate relation__ and routine__ test suites
jnasbyupgrade May 1, 2026
56b6667
Drop PG11 support: version that can't be updated to is not truly supp…
jnasbyupgrade May 1, 2026
15c6ad6
Remove accidental commits: upgrade-drift prompts and dead test/.gitig…
jnasbyupgrade May 1, 2026
124f5b0
Move function.sql tests into routine__.sql
jnasbyupgrade May 1, 2026
f3cf9a3
Move \set s to top of relation__ and routine__ test suites
jnasbyupgrade May 1, 2026
c61bc28
Restore function.sql; remove non-routine__ tests from routine__.sql
jnasbyupgrade May 1, 2026
8f6ea7b
Merge remote-tracking branch 'pgext/master' into new_functions
jnasbyupgrade May 1, 2026
c0b3eb1
Refactor test suite: helpers, dedup, consistency
jnasbyupgrade May 8, 2026
5be84a5
Address review feedback on test suite
jnasbyupgrade May 8, 2026
fcbb5b1
Further test suite refinements
jnasbyupgrade May 8, 2026
d28cf8b
Add REVOKE EXECUTE FROM PUBLIC for _cat_tools helper functions
jnasbyupgrade May 11, 2026
b4dd1a2
test/sql/routine__.sql: fix comma style, group CREATE FUNCTION with t…
jnasbyupgrade May 19, 2026
434ef45
test/sql/routine__.sql: move named_function creation to just before f…
jnasbyupgrade May 19, 2026
ec8d1e4
Address CodeRabbit review feedback for 0.3.0
jnasbyupgrade Jul 12, 2026
3d44705
Regenerate stale permissions/routine__ expected output
jnasbyupgrade Jul 12, 2026
e3db247
CI: harden version checks and fail the build on test regressions
jnasbyupgrade Jul 12, 2026
ae7c875
CI: run the extension update test on all supported versions (12–18)
jnasbyupgrade Jul 12, 2026
5ce80f9
Create _cat_tools helpers via create_function() instead of bare CREAT…
jnasbyupgrade Jul 12, 2026
3033548
test: detect when PostgreSQL adds a relkind cat_tools does not handle
jnasbyupgrade Jul 12, 2026
af30da3
CLAUDE.md: monitor CI after every push, not only PR-branch pushes
jnasbyupgrade Jul 13, 2026
b6fc753
Remove redundant client_min_messages handling from install script (fo…
jnasbyupgrade Jul 14, 2026
2417b66
test: use pgTAP set_has() for the relkind drift check
jnasbyupgrade Jul 15, 2026
a57f04c
test: share one temp table across the relation__ is_temp/is_catalog/c…
jnasbyupgrade Jul 15, 2026
eb658d1
CI: fail if the relkind drift source is empty (headers missing)
jnasbyupgrade Jul 15, 2026
271d2e5
Makefile: cache the relkind source instead of regenerating every run
jnasbyupgrade Jul 15, 2026
8347fe6
Restore upgrade-suite test capability (fresh-vs-upgrade equivalence, …
jnasbyupgrade Jul 15, 2026
e7a86d5
Makefile: quote "$@" in the relkind stamp/source recipes
jnasbyupgrade Jul 15, 2026
adb8648
Makefile: explain the order-only `| test/generated` prerequisite
jnasbyupgrade Jul 15, 2026
3510ae7
Makefile: reword relkind header-missing messages around the path, not…
jnasbyupgrade Jul 15, 2026
a1976e6
Makefile: drop stray blank line before the version-seds TODO
jnasbyupgrade Jul 15, 2026
7125b8b
test: install extension + roles once via test/install (fresh & upgrade)
jnasbyupgrade Jul 15, 2026
4e44aae
Makefile: rename test/generated -> test/.generated; define the dir re…
jnasbyupgrade Jul 15, 2026
e533923
test harness: require test_load_mode GUC; single-source, quote-forcin…
jnasbyupgrade Jul 15, 2026
831f7f9
Move versioned-SQL machinery into documented sql.mk; fix #28 DATA gap
jnasbyupgrade Jul 15, 2026
dfff40f
test harness: rename upgrade->update mode, add existing mode + update…
jnasbyupgrade Jul 16, 2026
01262b6
ci: guard existing-mode DBs against silent drop+reinstall; factor int…
jnasbyupgrade Jul 16, 2026
732d8de
ci: pg-upgrade PG10 leg validates the full bridge journey (0.2.0 → 0.…
jnasbyupgrade Jul 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 94 additions & 50 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
test:
strategy:
matrix:
pg: [18, 17, 16, 15, 14, 13, 12, 11, 10]
pg: [18, 17, 16, 15, 14, 13, 12]
name: 🐘 PostgreSQL ${{ matrix.pg }}
runs-on: ubuntu-latest
container: pgxn/pgxn-tools
Expand All @@ -25,27 +25,48 @@ jobs:
run: pg-start ${{ matrix.pg }}
- name: Check out the repo
uses: actions/checkout@v6
- name: Install rsync
run: apt-get install -y rsync
- name: Install rsync and server headers
# postgresql-server-dev-NN provides catalog/pg_class.h, which
# test/gen-relkinds.sh reads for the relkind drift check in
# test/sql/relation__.sql.
run: apt-get install -y rsync postgresql-server-dev-${{ matrix.pg }}
- name: Test on PostgreSQL ${{ matrix.pg }}
run: make test
run: |
# Fail if the relkind drift source is empty (headers missing): the
# drift check must actually run on every version, not pass silently.
make check-relkind-source
make test
# `make test` never exits non-zero on regressions (pgxntool marks
# installcheck `.IGNORE`), so gate the build explicitly on the
# pgtap/regression.diffs check or failures would pass silently.
make verify-results

pg-upgrade-test:
strategy:
matrix:
include:
- old_pg: "10"
new_pg: "11"
# old_pg=10: the FULL real-world journey for a user on old PostgreSQL +
# old cat_tools. 0.2.0 installs on PG10; the BRIDGE update to 0.2.2
# (run on PG10, before pg_upgrade) recreates the views with the
# pg_upgrade-safe omit_column fix so the binary pg_upgrade to a newer
# cluster succeeds; then update to current + run the suite. This proves
# a 0.2.2 reached via the bridge update (not a fresh install) survives
# pg_upgrade and updates to latest.
- old_pg: "10"
new_pg: "18"
- old_pg: "11"
new_pg: "12"
- old_pg: "11"
new_pg: "18"
old_install: "0.2.0"
bridge_to: "0.2.2"
# old_pg>=11: 0.2.0/0.2.1 do not install on PG11+, and such users are
# already on 0.2.2+. Install 0.2.2 directly (no bridge), pg_upgrade,
# then update to current.
- old_pg: "12"
new_pg: "13"
old_install: "0.2.2"
bridge_to: ""
- old_pg: "12"
new_pg: "18"
old_install: "0.2.2"
bridge_to: ""
name: 🔄 Binary pg_upgrade ${{ matrix.old_pg }} → ${{ matrix.new_pg }}
runs-on: ubuntu-latest
container: pgxn/pgxn-tools
Expand All @@ -72,8 +93,17 @@ jobs:
run: apt-get install -y rsync
- name: Install cat_tools into old cluster
run: make install
- name: Install cat_tools extension into upgrade test database
run: psql -c "CREATE EXTENSION cat_tools"
- name: Prepare the old cluster (install + bridge + dependency guard)
# prepare-old installs cat_tools at old_install and, when bridge_to is set
# (old_pg=10), ALTER EXTENSION UPDATEs to it BEFORE pg_upgrade -- the
# bridge that makes the views pg_upgrade-safe (see prepare-old in the
# script). It then plants + proves the dependency guard so the later
# existing-mode run cannot silently drop+reinstall and test a fresh
# install instead. The extension is always older than current, so the
# post-upgrade ALTER EXTENSION UPDATE has real work to do.
run: >-
test/ci/existing_mode.sh prepare-old cat_tools_upgrade
"${{ matrix.old_install }}" "${{ matrix.bridge_to }}"
- name: Install PostgreSQL ${{ matrix.new_pg }}
run: apt-get install -y postgresql-${{ matrix.new_pg }} postgresql-server-dev-${{ matrix.new_pg }}
- name: Install cat_tools into new cluster
Expand All @@ -100,32 +130,37 @@ jobs:
/var/lib/postgresql/${{ matrix.new_pg }}/test/pg_upgrade_output.d \
-name '*.log' 2>/dev/null | sort | xargs -r tail -n +1; exit 1; }
pg_ctlcluster ${{ matrix.new_pg }} test start
- name: Verify extension version after upgrade
run: |
VERSION=$(psql -tAc "SELECT extversion FROM pg_extension WHERE extname = 'cat_tools'")
echo "Extension version: ${VERSION:-<not found>}"
echo "$VERSION" | grep -q "0.2.2"
- name: Run test suite on upgraded cluster
run: make test
# TODO: also test ALTER EXTENSION cat_tools UPDATE here, once the
# pg_upgrade source versions (e.g. 0.2.0) can install on the new_pg
# version. Currently the pre-0.2.2 install scripts fail on PG11+ so
# we cannot pg_upgrade from a cluster that has them installed.
- name: Update the pg_upgraded extension to the current version
# Exercises ALTER EXTENSION UPDATE on genuinely pg_upgraded objects (the
# 0.2.2 extension binary pg_upgrade just migrated), running the
# version-to-version scripts up to the current version. The 0.2.2 -> 0.3.0
# script uses ALTER TYPE ... ADD VALUE, which is why new_pg must be >= 12.
run: test/ci/existing_mode.sh update cat_tools_upgrade
- name: Run the suite against the pg_upgraded database (existing mode)
# run-suite asserts the version, re-proves the dependency guard still
# blocks a non-CASCADE drop (i.e. it survived pg_upgrade), then runs the
# suite against the REAL pg_upgraded + updated database via --use-existing
# (so pg_regress does not drop/recreate it) -- a plain fresh `make test`
# would silently test a fresh install instead of the migrated objects.
run: test/ci/existing_mode.sh run-suite cat_tools_upgrade

extension-update-test:
strategy:
matrix:
# Restricted to PG10 only because the pre-0.2.2 install scripts use
# unqualified SELECT * in views over pg_attribute/pg_constraint:
# - PG11 added attmissingval (pseudo-type anyarray) to pg_attribute,
# so cat_tools--0.2.0.sql and cat_tools--0.2.1.sql fail on PG11+
# with "column attmissingval has pseudo-type anyarray".
# - PG12 made the `oid` system column visible in SELECT *, causing
# "column oid specified more than once" on PG12+.
# PG10 is the only version where both old scripts install cleanly.
# TODO: when a future version's install script works on PG11+, expand
# this matrix and add tests for the upgrade path from 0.2.2 onwards.
pg: [10]
# PG12+: exercise the WIDEST update path we support — CREATE EXTENSION at
# the 0.2.2 backward-compat floor, ALTER EXTENSION UPDATE to the CURRENT
# version, and run the full suite against the updated database. 0.2.2 is
# the floor because the 0.2.0/0.2.1 install scripts fail on PG11+/PG12+;
# PG12 is the PostgreSQL floor because the update runs
# `ALTER TYPE ... ADD VALUE`, which PG11 and below cannot run in an
# extension update script (lifted in PG12).
# PG10: the ONLY version where the pre-0.2.2 install scripts still load,
# so the only place the 0.2.0->0.2.2 and 0.2.1->0.2.2 update scripts can
# be exercised. They target 0.2.2 (not the current version) and use no
# ALTER TYPE ... ADD VALUE, so they run on PG10. The PG10 leg runs only
# those two checks — not the current-version suite (0.3.0 needs PG12+).
# See the per-step `if` guards.
pg: [18, 17, 16, 15, 14, 13, 12, 10]
name: ⬆️ Extension update test on PostgreSQL ${{ matrix.pg }}
runs-on: ubuntu-latest
container: pgxn/pgxn-tools
Expand All @@ -134,27 +169,36 @@ jobs:
run: pg-start ${{ matrix.pg }}
- name: Check out the repo
uses: actions/checkout@v6
- name: Install rsync and server headers
# server-dev provides catalog/pg_class.h for the relkind drift check
# (see the "test" job); required so check-relkind-source below passes.
# PG10 runs only the legacy-script checks (no suite), so it needs no headers.
if: matrix.pg != '10'
run: apt-get install -y rsync postgresql-server-dev-${{ matrix.pg }}
- name: Install rsync
if: matrix.pg == '10'
run: apt-get install -y rsync
- name: Install cat_tools (all versions)
run: make install
- name: Test upgrade from 0.2.0 (direct 0.2.0→0.2.2 path)
run: |
psql -c "CREATE EXTENSION cat_tools VERSION '0.2.0'"
psql -c "ALTER EXTENSION cat_tools UPDATE"
VERSION=$(psql -tAc "SELECT extversion FROM pg_extension WHERE extname = 'cat_tools'")
echo "Version after 0.2.0 upgrade: ${VERSION:-<not found>}"
echo "$VERSION" | grep -q "0.2.2"
- name: Test upgrade from 0.2.1 (0.2.1→0.2.2 path)
- name: Test pre-0.2.2 update scripts (0.2.0/0.2.1 → 0.2.2, PG10 only)
# 0.2.0/0.2.1 install only on PG10; their update scripts target 0.2.2 (not
# the current version) and are otherwise never exercised. PG takes the
# shortest path, so 0.2.0 → 0.2.2 uses the direct 0.2.0--0.2.2 script;
# starting at 0.2.1 exercises the 0.2.1--0.2.2 script directly. update-check
# asserts each lands on 0.2.2. No suite runs (0.3.0 needs PG12+).
if: matrix.pg == '10'
run: |
createdb cat_tools_from_021
psql -d cat_tools_from_021 -c "CREATE EXTENSION cat_tools VERSION '0.2.1'"
psql -d cat_tools_from_021 -c "ALTER EXTENSION cat_tools UPDATE"
VERSION=$(psql -d cat_tools_from_021 -tAc "SELECT extversion FROM pg_extension WHERE extname = 'cat_tools'")
echo "Version after 0.2.1 upgrade: ${VERSION:-<not found>}"
echo "$VERSION" | grep -q "0.2.2"
- name: Run test suite on updated extension
run: make test
test/ci/existing_mode.sh update-check cat_tools_from_020 0.2.0 0.2.2
test/ci/existing_mode.sh update-check cat_tools_from_021 0.2.1 0.2.2
- name: Update 0.2.2 → current and run the suite (existing mode, PG12+)
# update-scenario creates a real database at 0.2.2, plants + proves the
# dependency guard, ALTER EXTENSION UPDATEs to the current version, and
# runs the suite against that updated database in existing mode (asserting
# the version and that the guard still blocks a drop). Reusing the SAME
# suite and expected output asserts the updated database behaves
# identically to a fresh install.
if: matrix.pg != '10'
run: test/ci/existing_mode.sh update-scenario cat_tools_update 0.2.2

# A single stable check name for use as a required status check in branch
# protection rules. Matrix jobs produce check names like "🐘 PostgreSQL 14"
Expand Down
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ control.mk
# built targets
# Note: Version-specific files (sql/*--*.sql) are now tracked in git and should be committed

# test targets
/test/.build/

# Test artifacts
results/
regression.diffs
Expand Down
87 changes: 70 additions & 17 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,93 @@

## GitHub CI

After pushing to a branch with an open PR, monitor CI using `gh pr checks --watch` in a background subagent until all jobs pass or a failure is confirmed. Investigate and fix failures immediately rather than leaving them for the user to notice.
After **every** push, monitor GitHub CI in a background subagent until all jobs pass or a failure is confirmed. Use `gh pr checks <pr> --watch` when the branch has an open PR; otherwise (a branch with no PR yet, or a push to `master`) use `gh run watch` for the pushed commit. Investigate and fix failures immediately rather than leaving them for the user to notice.

(`paths-ignore` in `.github/workflows/ci.yml` skips CI only when the *entire* change set is docs-only — e.g. a docs-only push to `master`, or a PR whose whole diff is `**.md`/`**.asc`. A docs-only commit on a PR that also touches code still triggers CI on the full PR diff. When unsure, check `gh run list` for the pushed commit and monitor whatever run appears; if none does, there is nothing to watch.)

## Bug Fixes

When fixing a bug, add a comment at the fix site explaining what the bug was and why the fix works. The goal is to prevent re-introducing the bug later.
Comment the fix where it isn't self-evident, but keep it concise — no novels. Do NOT
recount the bug's history (what a past version got wrong) UNLESS the same mistake could
realistically be made again; if it could, briefly state the guard fact that prevents it.
Never repeat the same comment verbatim in adjacent code — write it once and reference it
("same as above").

## Git

**Never delete a branch without explicit user approval.** This includes `git push origin --delete`, `git branch -d`, and `git branch -D`. Always ask first.

**Always open PRs against the main repo** (`Postgres-Extensions/cat_tools`), not a fork.

## References to PRs and issues in committed files

Any reference to a GitHub PR or issue inside a **committed file** (SQL/code comments,
`.github/workflows/ci.yml` comments, `CLAUDE.md`, `test/install/load.sql`, docs) MUST be a
full URL, e.g. `https://github.com/Postgres-Extensions/cat_tools/issues/28` — never a bare
`#28` (a bare number is meaningless when the file is read outside GitHub). Referencing by
number is fine only in GitHub-native text (PR/issue titles and descriptions, review
comments).

## SQL file conventions

Rules for what to track in git:

0. If a `.sql.in` file exists, track the `.sql.in` and **not** the corresponding `.sql`.
1. If no `.sql.in` exists, track the `.sql` directly (e.g. historical pre-0.2.0 files).
2. Version-specific install scripts (e.g. `sql/cat_tools--0.2.2.sql.in`) MUST be tracked.
3. Upgrade scripts (e.g. `sql/cat_tools--0.2.1--0.2.2.sql.in`) MUST be tracked.
3. Update scripts (e.g. `sql/cat_tools--0.2.1--0.2.2.sql.in`) MUST be tracked.
4. The current version'''s install script (e.g. `sql/cat_tools--0.2.2.sql.in`) is generated
by `make` from `sql/cat_tools.sql.in`, but MUST still be tracked (rule 2 applies).
5. Version-specific files MUST NEVER be edited manually — always edit `sql/cat_tools.sql.in`
and regenerate.

## CI: extension-update-test matrix

The `extension-update-test` job in `.github/workflows/ci.yml` is currently restricted to
`pg: [10]` because that is the only PostgreSQL version where the pre-0.2.2 install scripts
install cleanly:
- PG 11 added `attmissingval` (pseudo-type `anyarray`) to `pg_attribute`; the old `SELECT *`
in `0.2.0`/`0.2.1` tries to include it directly, failing with "column attmissingval has
pseudo-type anyarray".
- PG 12+ exposed the `oid` system column in `SELECT *`, breaking `0.2.0`/`0.2.1` with
"column oid specified more than once".

**When working on a new version:** review and expand this matrix. The new version's install
script may support more PG versions, enabling testing of the upgrade path from older
cat_tools versions on newer PostgreSQL.
## CI: PostgreSQL version support

**Policy:** Never support a fresh install on any PostgreSQL version where the extension
update path is known to be broken — a version that cannot be updated to is not truly
supported.

Both PG10 and PG11 are dropped as of 0.3.0. The `ALTER TYPE ... ADD VALUE` statements in
the update script cannot run inside an extension update script on PG11 or earlier
(PROCESS_UTILITY_QUERY context); this restriction was lifted in PG12. Because a version
that cannot be updated to is not truly supported, PG10 and PG11 support is dropped
entirely. cat_tools 0.3.0 supports PG12+.

### Test-load modes (`TEST_LOAD_SOURCE`)

`test/install/load.sql` installs the suite's dependencies once, committed, before the pgTAP
suite. The Makefile exports the mode (and update range) as placeholder GUCs via `PGOPTIONS`;
`TEST_LOAD_SOURCE` must be `fresh`, `update`, or `existing` (anything else is a hard
parse-time error):

- **fresh** (default): `CREATE EXTENSION cat_tools` at the current version.
- **update**: `CREATE EXTENSION` at `TEST_UPDATE_FROM` (default `0.2.2`) then
`ALTER EXTENSION cat_tools UPDATE` — to `TEST_UPDATE_TO` if set, else to the current
version. Running the SAME suite/expected output asserts an updated database behaves
identically to a fresh install. `make test-update` is the shorthand.
- **existing**: the extension is ALREADY installed (by binary `pg_upgrade`, or an
`ALTER EXTENSION UPDATE` performed outside the suite). load.sql does not touch it; it only
asserts presence + current version and creates the test roles. Pair with
`CONTRIB_TESTDB=<db> EXTRA_REGRESS_OPTS=--use-existing` so `pg_regress` runs against that
database instead of dropping/recreating a throwaway one.

### CI jobs

- `extension-update-test` exercises the widest update path we support — `0.2.2` → current
in `update` mode — on `pg: [12..18]`, plus a PG10-only leg that exercises the pre-0.2.2
update scripts (`0.2.0`→`0.2.2` and `0.2.1`→`0.2.2`, which install only on PG10 and target
`0.2.2`, not the current version). `0.2.2` is the update-from floor only for backward-compat:
the 0.2.0/0.2.1 install scripts fail on PG11+/PG12+. PG12 is the PostgreSQL floor — PG11 and
earlier cannot run `ALTER TYPE ... ADD VALUE` in extension update scripts (lifted in PG12).
- `pg-upgrade-test` binary-`pg_upgrade`s a real database and then runs the suite against it
in `existing` mode (`0.2.2` is the oldest version that survives pg_upgrade — pre-0.2.2
views reference catalog columns removed in newer PostgreSQL). Two shapes:
- `old_pg>=11`: install `0.2.2` directly → plant guard → pg_upgrade → update to current.
- `old_pg=10`: the FULL real-world journey — install `0.2.0`, **bridge-update to `0.2.2` on
the old cluster** (the `0.2.0`→`0.2.2` script recreates the views with the pg_upgrade-safe
omit_column fix) → plant guard → pg_upgrade → update to current. This proves a `0.2.2`
reached via the bridge update (not a fresh install) survives pg_upgrade.
Both flows plant the dependency guard and run through `test/ci/existing_mode.sh`.

## Code Style

Expand All @@ -55,3 +103,8 @@ Always use block comment format for multi-line comments in SQL files:
```

Never use `--` line comments for multi-line explanations.

### Terminology
"upgrade" refers to a PostgreSQL cluster (`pg_upgrade`); "update" refers to an extension
(`ALTER EXTENSION ... UPDATE`). cat_tools' version-to-version scripts are "update scripts" —
never "upgrade scripts."
Loading
Loading