Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
81bdb18
Squashed 'pgxntool/' changes from c0af00f..bed3604
jnasbyupgrade Nov 6, 2024
5a01ec5
Pull pgxntool from git@github.com:decibel/pgxntool.git stable
jnasbyupgrade Nov 6, 2024
cb9b8a4
Add cat_tools 0.2.2: fix PG11+ and PG12+ compatibility via dynamic views
jnasbyupgrade Apr 8, 2026
3290094
Use block comment format for pg_class_v upgrade warning
jnasbyupgrade Apr 14, 2026
bdb5068
Fix attmissingval: consistent view schema across PG versions
jnasbyupgrade Apr 14, 2026
9ae32d8
Add pgxn-tools CI
jnasbyupgrade Nov 7, 2024
18b8ee5
Fix CI version matrix
jnasbyupgrade Nov 7, 2024
5b4b027
Add automated test workflow
jnasbyupgrade Nov 11, 2025
48a9e69
Install rsync in CI before running tests
jnasbyupgrade Apr 7, 2026
35be60b
Remove .travis.yml
jnasbyupgrade Nov 11, 2024
f691b98
Fix test failures on PG11+/PG12+/PG15+; add CLAUDE.md coding standards
jnasbyupgrade Apr 14, 2026
e4cdd3f
Makefile: drop .in pipeline; use wildcard for historical install scripts
jnasbyupgrade Apr 15, 2026
bac7018
Merge master into v0.2.2: extend CI matrix to PG 9.2-18
jnasbyupgrade Apr 17, 2026
ea08b38
Avoid DROP CASCADE in upgrade script; move attmissingval to end of view
jnasbyupgrade Apr 17, 2026
943c8ac
Merge pgext/master into v0.2.2: resolve .gitignore and Makefile confl…
jnasbyupgrade Apr 17, 2026
73f4066
Merge CLAUDE.md: combine git and code style sections
jnasbyupgrade Apr 17, 2026
3c45da2
Remove redundant include control.mk; base.mk already includes it
jnasbyupgrade Apr 17, 2026
ec3f771
Fix upgrade script: runtime detection for extschema on PG < 9.5
jnasbyupgrade Apr 17, 2026
3363ffe
Convert upgrade script to .sql.in with SED markers for extschema
jnasbyupgrade Apr 17, 2026
af7170a
Replace runtime attmissingval detection with SED markers
jnasbyupgrade Apr 17, 2026
1d58ff6
Fix pre-processed SED marker in cat_tools.sql.in
jnasbyupgrade Apr 17, 2026
4ca6ab6
Fix install script filename: cat_tools--0.2.1.sql → cat_tools--0.2.2.sql
jnasbyupgrade Apr 20, 2026
9f497d8
Fix pg_attribute_v: omit oid+attmissingval; note attmissingval in cat…
jnasbyupgrade Apr 20, 2026
15d8d30
Sync upgrade script pg_attribute_v section with cat_tools.sql.in
jnasbyupgrade Apr 20, 2026
6140a5b
Merge pgext/master into v0.2.2
jnasbyupgrade Apr 20, 2026
2f5c995
test/attribute: cast attmissingval::text[] instead of excluding it
jnasbyupgrade Apr 20, 2026
0afa86a
HISTORY.asc: document 0.2.2 as compatibility/stepping-stone release
jnasbyupgrade Apr 20, 2026
46c3231
Fix upgrade: append attmissingval at end of _cat_tools.column
jnasbyupgrade Apr 20, 2026
7f32617
HISTORY.asc: remove premature 0.3.0 reference from 0.2.2 entry
jnasbyupgrade Apr 20, 2026
7e08795
CI: add pg_upgrade and extension update test jobs
jnasbyupgrade Apr 20, 2026
665a5f0
CI: use pg_upgradecluster instead of raw pg_upgrade
jnasbyupgrade Apr 20, 2026
e027a3f
Fix two CI failures
jnasbyupgrade Apr 20, 2026
7cec4cb
Revert "Fix two CI failures"
jnasbyupgrade Apr 20, 2026
dc3f19d
ci: add postgresql-server-dev-N when installing new PG for pg_upgrade…
jnasbyupgrade Apr 20, 2026
4b63157
Fix omit_column bug, attmissingval cast, and CI workflow issues
jnasbyupgrade Apr 20, 2026
609a79e
omit_column: use != ALL(omit) instead of NOT (= ANY(omit))
jnasbyupgrade Apr 20, 2026
c18e1e9
ci: restrict extension-update-test to PG 10-11; add install step for …
jnasbyupgrade Apr 20, 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
75 changes: 73 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ jobs:
test:
strategy:
matrix:
pg: [17, 16, 15, 14, 13, 12, 11, 10, 9.6, 9.5, 9.4, 9.3, 9.2]
pg: [18, 17, 16, 15, 14, 13, 12, 11, 10]
name: 🐘 PostgreSQL ${{ matrix.pg }}
runs-on: ubuntu-latest
container: pgxn/pgxn-tools
Expand All @@ -13,5 +13,76 @@ jobs:
run: pg-start ${{ matrix.pg }}
- name: Check out the repo
uses: actions/checkout@v4
- name: Install rsync
run: apt-get install -y rsync
- name: Test on PostgreSQL ${{ matrix.pg }}
run: pg-build-test
run: make test PGUSER=postgres

pg-upgrade-test:
strategy:
matrix:
include:
- old_pg: "10"
new_pg: "11"
- old_pg: "10"
new_pg: "18"
- old_pg: "11"
new_pg: "12"
- old_pg: "11"
new_pg: "18"
- old_pg: "12"
new_pg: "13"
- old_pg: "12"
new_pg: "18"
name: 🔄 pg_upgrade ${{ matrix.old_pg }} → ${{ matrix.new_pg }}
runs-on: ubuntu-latest
container: pgxn/pgxn-tools
steps:
- name: Start PostgreSQL ${{ matrix.old_pg }}
run: pg-start ${{ matrix.old_pg }}
- name: Check out the repo
uses: actions/checkout@v4
- name: Install rsync
run: apt-get install -y rsync
- name: Install cat_tools into old cluster
run: make install PGUSER=postgres
- name: Test cat_tools on old cluster
run: make test PGUSER=postgres
- 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
run: make install PGUSER=postgres PG_CONFIG=/usr/lib/postgresql/${{ matrix.new_pg }}/bin/pg_config
- name: Upgrade cluster to PostgreSQL ${{ matrix.new_pg }}
run: pg_upgradecluster -v ${{ matrix.new_pg }} ${{ matrix.old_pg }} test
- name: Verify extension version after upgrade
run: |
DB=$(psql -U postgres -tAc "SELECT datname FROM pg_database WHERE datname ~ '^cat_tools'" | head -1)
psql -U postgres -d "$DB" -c "SELECT extversion FROM pg_extension WHERE extname = 'cat_tools'" | grep -q "0.2.2"
- name: Run test suite on new cluster
run: make test PGUSER=postgres

extension-update-test:
strategy:
matrix:
pg: [11, 10]
name: ⬆️ Extension update test on PostgreSQL ${{ matrix.pg }}
runs-on: ubuntu-latest
container: pgxn/pgxn-tools
steps:
- name: Start PostgreSQL ${{ matrix.pg }}
run: pg-start ${{ matrix.pg }}
- name: Check out the repo
uses: actions/checkout@v4
- name: Install rsync
run: apt-get install -y rsync
- name: Install cat_tools (all versions)
run: make install PGUSER=postgres
- name: Install cat_tools from version 0.2.0
run: psql -U postgres -c "CREATE EXTENSION cat_tools VERSION '0.2.0'"
- name: Update cat_tools to current version
run: psql -U postgres -c "ALTER EXTENSION cat_tools UPDATE"
- name: Verify extension version after update
run: |
psql -U postgres -c "SELECT extversion FROM pg_extension WHERE extname = 'cat_tools'" | grep -q "0.2.2"
- name: Run test suite on updated extension
run: make test PGUSER=postgres
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ test/install/schedule
# Misc
tmp/
.DS_Store
.claude/worktrees/

# pg_tle generated files
/pg_tle/
25 changes: 25 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,28 @@
**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.

## CI: extension-update-test matrix

The `extension-update-test` job in `.github/workflows/ci.yml` is currently restricted to
`pg: [11, 10]` because those are the only PostgreSQL versions where a pre-0.2.2 install
script (`cat_tools--0.2.0.sql`) installs cleanly. PG 12+ exposed the `oid` system column
in `SELECT *`, breaking `0.2.0` and `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.

## Code Style

### Comments
Always use block comment format for multi-line comments in SQL files:

```sql
/*
* First line of comment.
* Second line of comment.
*/
```

Never use `--` line comments for multi-line explanations.
38 changes: 38 additions & 0 deletions HISTORY.asc
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
0.2.2
-----
Compatibility release: fixes broken installs on PostgreSQL 11 and 12+, and
provides an upgrade path from 0.2.1.

### PostgreSQL Version Support

cat_tools 0.2.1 (and earlier) only installs correctly on **PostgreSQL 9.2 – 10**.
It fails on newer versions due to catalog schema changes:

* **PG 11+**: `pg_attribute` gained the `attmissingval` column (pseudo-type `anyarray`),
which cannot be used as a view column. The 0.2.1 install script's `SELECT a.*` from
`pg_attribute` picks this column up and fails.
* **PG 12+**: System catalog `oid` columns became visible as regular columns. Views
using `SELECT c.*` alongside an explicit `c.oid` alias produce duplicate column names.

cat_tools 0.2.2 installs and upgrades correctly on **PostgreSQL 9.2 through 18+**
(all currently supported versions).

### Upgrade Path

0.2.2 provides the stepping stone for future upgrades. Users on 0.2.1 can upgrade to
0.2.2 via `ALTER EXTENSION cat_tools UPDATE`. If upgrading PostgreSQL to version 11 or
later, upgrade cat_tools to 0.2.2 first (or run `ALTER EXTENSION cat_tools UPDATE`
immediately after the PostgreSQL upgrade).

### Changes

* `_cat_tools.pg_attribute_v`, `_cat_tools.column`, and `cat_tools.column` now expose
`attmissingval` as `text[]` (cast from `anyarray` on PG 11+, or `NULL::text[]` on
older versions). Any `SELECT *` on `cat_tools.column` or `_cat_tools.column` will now
include this column.
* Views rebuilt using `omit_column()` to enumerate columns explicitly, avoiding both the
`anyarray` and duplicate-`oid` problems.
* Upgrade script uses `CREATE OR REPLACE VIEW` throughout — no `DROP CASCADE` — so
user-defined views built on `cat_tools.column` or `cat_tools.pg_class_v` are not
dropped during the upgrade.

0.2.1
-----
Fix significant problems with a previous upgrade script.
Expand Down
4 changes: 2 additions & 2 deletions META.in.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"name": "cat_tools",

"X_comment": "REQUIRED. Version of the distribution. http://pgxn.org/spec/#version",
"version": "0.2.1",
"version": "0.2.2",

"X_comment": "REQUIRED. Short description of distribution.",
"abstract": "Tools for interfacing with the Postgres catalog",
Expand All @@ -37,7 +37,7 @@
"file": "sql/cat_tools.sql",

"X_comment": "REQUIRED. Version the extension is at.",
"version": "0.2.1",
"version": "0.2.2",

"X_comment": "Optional: \"abstract\": Description of the extension.",
"abstract": "Tools for interfacing with the catalog",
Expand Down
4 changes: 2 additions & 2 deletions META.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"name": "cat_tools",

"X_comment": "REQUIRED. Version of the distribution. http://pgxn.org/spec/#version",
"version": "0.2.1",
"version": "0.2.2",

"X_comment": "REQUIRED. Short description of distribution.",
"abstract": "Tools for interfacing with the Postgres catalog",
Expand All @@ -37,7 +37,7 @@
"file": "sql/cat_tools.sql",

"X_comment": "REQUIRED. Version the extension is at.",
"version": "0.2.1",
"version": "0.2.2",

"X_comment": "Optional: \"abstract\": Description of the extension.",
"abstract": "Tools for interfacing with the catalog",
Expand Down
2 changes: 1 addition & 1 deletion cat_tools.control
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
comment = 'Tools for intorfacing with the catalog'
default_version = '0.2.1'
default_version = '0.2.2'
relocatable = false
schema = 'cat_tools'
5 changes: 5 additions & 0 deletions control.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
EXTENSION_cat_tools_VERSION := 0.2.2
$(EXTENSION_cat_tools_VERSION_FILE): sql/cat_tools.sql cat_tools.control
@echo '/* DO NOT EDIT - AUTO-GENERATED FILE */' > $(EXTENSION_cat_tools_VERSION_FILE)
@cat sql/cat_tools.sql >> $(EXTENSION_cat_tools_VERSION_FILE)

2 changes: 2 additions & 0 deletions sql/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ cat_tools--*.sql
# Historical exceptions — no .sql.in source; must be tracked directly.
!cat_tools--0.1.*.sql
!cat_tools--0.2.0--0.2.1.sql
# v0.2.2 install script — committed directly on this branch.
!cat_tools--0.2.2.sql
163 changes: 163 additions & 0 deletions sql/cat_tools--0.2.1--0.2.2.sql.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
CREATE SCHEMA __cat_tools;

CREATE FUNCTION __cat_tools.exec(
sql text
) RETURNS void LANGUAGE plpgsql AS $body$
BEGIN
RAISE DEBUG 'sql = %', sql;
EXECUTE sql;
END
$body$;

CREATE FUNCTION __cat_tools.omit_column(
rel text
, omit name[] DEFAULT array['oid']
) RETURNS text LANGUAGE sql IMMUTABLE AS $body$
SELECT array_to_string(array(
SELECT attname
FROM pg_attribute a
WHERE attrelid = rel::regclass
AND NOT attisdropped
AND attnum >= 0
AND attname != ANY( omit )
ORDER BY attnum
)
, ', '
)
$body$;

ALTER DEFAULT PRIVILEGES IN SCHEMA cat_tools GRANT USAGE ON TYPES TO cat_tools__usage;

/*
* Recreate _cat_tools.pg_class_v with dynamic column list to handle PG12+ oid visibility.
* On PG < 12, oid was already hidden so the effective column list is unchanged;
* CREATE OR REPLACE VIEW works without disturbing dependent views.
*/
SELECT __cat_tools.exec(format($fmt$
CREATE OR REPLACE VIEW _cat_tools.pg_class_v AS
SELECT c.oid AS reloid
, %s
, n.nspname AS relschema
FROM pg_class c
LEFT JOIN pg_namespace n ON( n.oid = c.relnamespace )
;
$fmt$
, __cat_tools.omit_column('pg_catalog.pg_class')
));
REVOKE ALL ON _cat_tools.pg_class_v FROM public;

CREATE OR REPLACE VIEW cat_tools.pg_class_v AS
SELECT *
FROM _cat_tools.pg_class_v
WHERE NOT pg_is_other_temp_schema(relnamespace)
AND relkind IN( 'r', 'v', 'f' )
;
GRANT SELECT ON cat_tools.pg_class_v TO cat_tools__usage;

/*
* On PG11+, pg_attribute gained attmissingval (pseudo-type anyarray, not usable in views).
* Include it cast to text[] on PG11+; expose as NULL::text[] on older versions.
*/
SELECT __cat_tools.exec(format($fmt$
CREATE OR REPLACE VIEW _cat_tools.pg_attribute_v AS
SELECT %s
, c.*
, t.oid AS typoid
, %s
, a.attmissingval::text::text[] AS attmissingval -- SED: REQUIRES 11!
, NULL::text[] AS attmissingval -- SED: PRIOR TO 11!
FROM pg_attribute a
LEFT JOIN _cat_tools.pg_class_v c ON ( c.reloid = a.attrelid )
LEFT JOIN pg_type t ON ( t.oid = a.atttypid )
;
$fmt$
/*
* attmissingval is explicitly included above (cast to text[] via SED markers).
* Omit it here so it doesn't appear twice, and omit oid to avoid conflicts on PG12+.
*/
, __cat_tools.omit_column('pg_catalog.pg_attribute', array['oid', 'attmissingval'])
, __cat_tools.omit_column('pg_catalog.pg_type')
));
REVOKE ALL ON _cat_tools.pg_attribute_v FROM public;

/*
* Rebuild _cat_tools.column using omit_column() on _cat_tools.pg_attribute_v so that
* attmissingval is appended AFTER the pre-existing computed columns. This is required
* for CREATE OR REPLACE VIEW to succeed: PostgreSQL only allows adding new columns at
* the end. The plain SELECT * approach would insert attmissingval before column_type,
* shifting existing column positions and causing "cannot change name of view column".
*/
SELECT __cat_tools.exec(format($fmt$
CREATE OR REPLACE VIEW _cat_tools.column AS
SELECT %s
, pg_catalog.format_type(typoid, atttypmod) AS column_type
, CASE typtype
WHEN 'd' THEN pg_catalog.format_type(typbasetype, typtypmod)
WHEN 'e' THEN 'text'
ELSE pg_catalog.format_type(typoid, atttypmod)
END AS base_type
, pk.conkey AS pk_columns
, ARRAY[attnum] <@ pk.conkey AS is_pk_member
, (SELECT pg_catalog.pg_get_expr(d.adbin, d.adrelid)
FROM pg_catalog.pg_attrdef d
WHERE d.adrelid = a.attrelid
AND d.adnum = a.attnum
AND a.atthasdef
) AS column_default
, a.attmissingval
FROM _cat_tools.pg_attribute_v a
LEFT JOIN pg_constraint pk
ON ( reloid = pk.conrelid )
AND pk.contype = 'p'
;
$fmt$
, __cat_tools.omit_column('_cat_tools.pg_attribute_v', array['attmissingval'])
));
REVOKE ALL ON _cat_tools.column FROM public;

CREATE OR REPLACE VIEW cat_tools.column AS
SELECT *
FROM _cat_tools.column
WHERE NOT pg_is_other_temp_schema(relnamespace)
AND attnum > 0
AND NOT attisdropped
AND relkind IN( 'r', 'v', 'f' )
AND (
pg_has_role(SESSION_USER, relowner, 'USAGE'::text)
OR has_column_privilege(SESSION_USER, reloid, attnum, 'SELECT, INSERT, UPDATE, REFERENCES'::text)
)
ORDER BY relschema, relname, attnum
;
GRANT SELECT ON cat_tools.column TO cat_tools__usage;

/*
* Fix cat_tools.pg_extension_v for PG12+ oid visibility.
* On PG < 12, oid was already hidden so the effective column list is unchanged;
* CREATE OR REPLACE VIEW works without disturbing pg_extension__get or other dependents.
*/
SELECT __cat_tools.exec(format($fmt$
CREATE OR REPLACE VIEW cat_tools.pg_extension_v AS
SELECT e.oid
, %s

, extnamespace::regnamespace AS extschema -- SED: REQUIRES 9.5!
, nspname AS extschema -- SED: PRIOR TO 9.5!

, extconfig::pg_catalog.regclass[] AS ext_config_tables
FROM pg_catalog.pg_extension e
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace
;
$fmt$
, __cat_tools.omit_column('pg_catalog.pg_extension')
));
GRANT SELECT ON cat_tools.pg_extension_v TO cat_tools__usage;

-- Drop temporary helper objects
DROP FUNCTION __cat_tools.omit_column(
rel text
, omit name[]
);
DROP FUNCTION __cat_tools.exec(
sql text
);
DROP SCHEMA __cat_tools;
Loading
Loading