Skip to content

Force CREATE EXTENSION through the upgrade chain + fix CI + add PG17 - #13

Merged
utkarash2991 merged 3 commits into
supabase:mainfrom
utkarash2991:utkarashsingh/psqlext-1773-force-upgrade-chain
Oct 6, 2026
Merged

utkarash2991 merged 3 commits into
supabase:mainfrom
utkarash2991:utkarashsingh/psqlext-1773-force-upgrade-chain

Conversation

@utkarash2991

@utkarash2991 utkarash2991 commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Two things, both prerequisites for cutting a 0.2.1 release with the fix in PSQLEXT-1773:

  1. Force CREATE EXTENSION through the full upgrade chain, per the suggestion in Schema-qualify hypopg_reset() and hypopg_get_indexdef() calls #12. Previously a fresh CREATE EXTENSION installed straight from a standalone "latest version" script, while ALTER EXTENSION UPDATE on an existing install walked a separate chain of incremental scripts - the two paths were only kept in sync by hand.

Now only 0.1.0 is a standalone base script; every later version (0.1.1, 0.1.2, 0.2.0) is reachable only via incremental upgrade scripts . CREATE EXTENSION with no version and ALTER EXTENSION UPDATE on an existing install both resolve through the same chain now - one code path, not two.

0.1.2->0.2.0 needs an explicit DROP FUNCTION first since the return signature changed (added the errors column) - confirmed this is actually required via the real Postgres error it produces without it: cannot change return type of existing function, HINT: Use DROP FUNCTION index_advisor(text) first.

  1. Fixed CI entirely

Test plan

Added two tests:

  • create_extension_default_version: unversioned CREATE EXTENSION resolves through the full chain to default_version.
  • upgrade_from_oldest_version: a real ALTER EXTENSION UPDATE from 0.1.0 walks the whole chain and the function works correctly afterward - not just a version-pinned fresh install.

Tracked in https://linear.app/supabase/issue/PSQLEXT-1773

Previously, a fresh CREATE EXTENSION installed straight from a standalone
"latest version" script, while ALTER EXTENSION UPDATE on an existing
install walked a separate chain of incremental scripts. These two paths
were only kept in sync by hand, with nothing enforcing they actually
produced the same end state.

0.1.1 and 0.1.2 only ever existed as standalone full scripts, with no
update path connecting them - meaning a project already installed at
0.1.1 or 0.1.2 had no way to self-upgrade via ALTER EXTENSION UPDATE at
all.

This removes the standalone 0.1.1/0.1.2/0.2.0 scripts, keeping only 0.1.0
as the base install, with every later version reachable only via
incremental upgrade scripts (adding the two that were missing:
0.1.1->0.1.2, 0.1.2->0.2.0). CREATE EXTENSION with no version, and
ALTER EXTENSION UPDATE on an existing install, now both resolve through
the same chain - so there's only one code path to keep correct, and it's
exercised by every test that installs the extension at all, not just a
dedicated upgrade test.

0.1.2->0.2.0 needs an explicit DROP FUNCTION first since the return
signature changed (added the errors column) - confirmed via the actual
Postgres error this produces without it ("cannot change return type of
existing function").

Added two tests:
- create_extension_default_version: unversioned CREATE EXTENSION resolves
  through the full chain to default_version.
- upgrade_from_oldest_version: a real ALTER EXTENSION UPDATE from 0.1.0
  walks the whole chain and the function works correctly afterward, not
  just a version-pinned fresh install.

All 9 tests pass, including the 7 pre-existing ones unchanged.
actions/upload-artifact@v3 is deprecated and GitHub now hard-fails any
run that uses it, which is why CI never actually executed on this repo
(confirmed: zero runs ever, including on the historical merged PRs).
Bumped it and actions/checkout to v4.

Added PG17 to the matrix. This needed bumping the pinned hypopg version
too - debian/1.3.1-2 doesn't compile against PG17 headers
(tuplestore_donestoring no longer exists, a Datum/pointer type mismatch
in hypopg_index.c). Verified 1.4.3 builds cleanly and passes the full
suite on both PG15 and PG17.
with:
repository: 'HypoPG/hypopg'
ref: 'debian/1.3.1-2'
ref: '1.4.3'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to keep these in a different PR as they are totally independent.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah ideally it should be in different PRs. Will be keeping in mind next time

@AndrewJackson2020

Copy link
Copy Markdown

did you create a branch both in this repo and your fork? looks like this one is only pointing at the fork. Not sure what the difference is between them but please make sure the fork in this repo is removed after this PR.

aj@Andrews-MacBook-Pro:~/Repos/mono/external/repos/supabase/index_advisor/main/ > git branch -vr | grep upg
rade-chain
  origin/utkarashsingh/psqlext-1773-force-upgrade-chain                   0bc39fe Fix CI and add PG17 to the test matrix
  utkarash_fork/utkarashsingh/psqlext-1773-force-upgrade-chain            0bc39fe Fix CI and add PG17 to the test matrix

@AndrewJackson2020

Copy link
Copy Markdown

Went ahead and tested the upgrade paths.

create chained upgraded extension

PGOPTIONS='--search_path=test' psql -h localhost -d postgres -f ./index_advisor--0.1.0.sql -f index_advisor--0.1.0--0.1.1.sql -f index_advisor--0.1.1--0.1.2.sql -f ./index_advisor--0.1.2--0.2.0.sql

create snapshot upgraded extension

PGOPTIONS='--search_path=test' psql -h localhost -d postgres -f ./index_advisor--0.2.0.sql

did not realize when I initiated the ask that this extension consists of one function. a bit overkill imo as extensions are designed to package and version objects that belong together but that is okay.

\df test.*
                                                                                             List of functions
 Schema |     Name      |                                                                  Result data type                                                                   | Argument data types | Type
--------+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+------
 test   | index_advisor | TABLE(startup_cost_before jsonb, startup_cost_after jsonb, total_cost_before jsonb, total_cost_after jsonb, index_statements text[], errors text[]) | query text          | func
(1 row)

Either way took the pg_dumps and the end result is that they are the same.

aj@Andrews-MacBook-Pro:~/Repos/mono/external/repos/supabase/index_advisor/v0.2.0/ > diff ./master.sql ../main/chained_upgrade.sql
5c5
< \restrict CO7C6JhNnwyFR93BUbstmEnmOWSIlIZ0JrAiWGuzBJFgIhni92mo1mKVgGWBwIK
---
> \restrict d6Go0Hy35JMAEMkpyOHIPtAxhIcUl3vDK8QxfSzQM7l12K9SpUnFG4W0eHLGgB5
222c222
< \unrestrict CO7C6JhNnwyFR93BUbstmEnmOWSIlIZ0JrAiWGuzBJFgIhni92mo1mKVgGWBwIK
---
> \unrestrict d6Go0Hy35JMAEMkpyOHIPtAxhIcUl3vDK8QxfSzQM7l12K9SpUnFG4W0eHLGgB5j

also some diff output between the relevant files

aj@Andrews-MacBook-Pro:~/Repos/mono/external/repos/supabase/index_advisor/v0.2.0/ > diff index_advisor--0.1.0--0.1.1.sql ../main/index_advisor--0.1.0--0.1.1.sql
diff index_advisor--0.1.0.sql ../main/index_advisor--0.1.0.sql
diff index_advisor--0.1.2.sql ../main/index_advisor--0.1.1--0.1.2.sql
diff index_advisor--0.2.0.sql ../main/index_advisor--0.1.2--0.2.0.sql

0a1,2
> drop function index_advisor(text);
>
aj@Andrews-MacBook-Pro:~/Repos/mono/external/repos/supabase/index_advisor/v0.2.0/ >

Comment thread index_advisor--0.1.2--0.2.0.sql Resolved
Comment thread index_advisor--0.1.2--0.2.0.sql Resolved
@AndrewJackson2020

Copy link
Copy Markdown

Most of these comments are nits. Im satisfied that the new migration path is functionally correct. Good to merge.

Per Andrew's review comment - nothing exists to replace once the
preceding drop function has run, so plain CREATE FUNCTION is clearer.
@utkarash2991
utkarash2991 deleted the utkarashsingh/psqlext-1773-force-upgrade-chain branch October 6, 2026 10:42
@utkarash2991 utkarash2991 reopened this Oct 6, 2026
@utkarash2991
utkarash2991 merged commit 8aa7ece into supabase:main Oct 6, 2026
3 checks passed
utkarash2991 added a commit that referenced this pull request Oct 6, 2026
Per hanefi's review comment on #13 - 0.2.1 hasn't been released
anywhere yet, so there's no reason to burn a second version number
(0.2.2) for more fixes found before the first real release. These two
bugs (greedy block-comment regex deleting code between separate
comments, and bare "deallocate all" wiping every prepared statement in
the session) were originally a separate stacked PR on top of this one -
folding them in here instead, so 0.2.1 ships as the one complete fix.
@utkarash2991

Copy link
Copy Markdown
Contributor Author

Good point - 0.2.1 hasn't shipped anywhere yet. Folded the two additional fixes that were in a separate stacked PR (#15, now closed) directly into #14's 0.2.1 script instead of bumping to 0.2.2. One version, ships once.

utkarash2991 added a commit that referenced this pull request Oct 8, 2026
…a-qualify-hypopg-calls-v2

Schema-qualify hypopg_reset() and hypopg_get_indexdef() calls (stacked on #13)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants