-
Notifications
You must be signed in to change notification settings - Fork 47
spoc-504: 5.x -> 6.x upgrade path and version safety nets #421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
64e8b07
0d1fb65
5d61e46
985156a
c5aef49
6810add
a8828dd
ee0f4ef
240458c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| Spock core-patchset: export patchset version via miscadmin.h and globals.c. | ||
|
|
||
| Adds SPOCK_CORE_PATCHSET_VERSION (compile-time constant) and | ||
| SpockCorePatchsetVersion (runtime global) to the standard places | ||
| PostgreSQL already uses for server-wide state. No new files. | ||
|
|
||
| --- a/src/include/miscadmin.h | ||
| +++ b/src/include/miscadmin.h | ||
| @@ -498,4 +498,11 @@ | ||
| /* in executor/nodeHash.c */ | ||
| extern size_t get_hash_memory_limit(void); | ||
|
|
||
| +/* | ||
| + * Spock core-patchset identity. Bump the version when the patchset | ||
| + * changes in a way visible to the extension binary. | ||
| + */ | ||
| +#define SPOCK_CORE_PATCHSET_VERSION 1 | ||
| +extern PGDLLIMPORT int SpockCorePatchsetVersion; | ||
| + | ||
| #endif /* MISCADMIN_H */ | ||
| --- a/src/backend/utils/init/globals.c | ||
| +++ b/src/backend/utils/init/globals.c | ||
| @@ -114,6 +114,9 @@ | ||
| bool IsBinaryUpgrade = false; | ||
| bool IsBackgroundWorker = false; | ||
|
|
||
| +/* Spock core-patchset identity. */ | ||
| +int SpockCorePatchsetVersion = SPOCK_CORE_PATCHSET_VERSION; | ||
| + | ||
| bool ExitOnAnyError = false; | ||
|
|
||
| int DateStyle = USE_ISO_DATES; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| Spock core-patchset: export patchset version via miscadmin.h and globals.c. | ||
|
|
||
| Adds SPOCK_CORE_PATCHSET_VERSION (compile-time constant) and | ||
| SpockCorePatchsetVersion (runtime global) to the standard places | ||
| PostgreSQL already uses for server-wide state. No new files. | ||
|
|
||
| --- a/src/include/miscadmin.h | ||
| +++ b/src/include/miscadmin.h | ||
| @@ -510,4 +510,11 @@ | ||
| /* in executor/nodeHash.c */ | ||
| extern size_t get_hash_memory_limit(void); | ||
|
|
||
| +/* | ||
| + * Spock core-patchset identity. Bump the version when the patchset | ||
| + * changes in a way visible to the extension binary. | ||
| + */ | ||
| +#define SPOCK_CORE_PATCHSET_VERSION 1 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is smart idea in general. It does replace one patch with another though (but smaller). I am thinking one day we could have a spock-lite with reduced functionality that would work with plain Postgres. I will think about this some more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mason-sharp , |
||
| +extern PGDLLIMPORT int SpockCorePatchsetVersion; | ||
| + | ||
| #endif /* MISCADMIN_H */ | ||
| --- a/src/backend/utils/init/globals.c | ||
| +++ b/src/backend/utils/init/globals.c | ||
| @@ -114,6 +114,9 @@ | ||
| bool IsBinaryUpgrade = false; | ||
| bool IsBackgroundWorker = false; | ||
|
|
||
| +/* Spock core-patchset identity. */ | ||
| +int SpockCorePatchsetVersion = SPOCK_CORE_PATCHSET_VERSION; | ||
| + | ||
| bool ExitOnAnyError = false; | ||
|
|
||
| int DateStyle = USE_ISO_DATES; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| Spock core-patchset: export patchset version via miscadmin.h and globals.c. | ||
|
|
||
| Adds SPOCK_CORE_PATCHSET_VERSION (compile-time constant) and | ||
| SpockCorePatchsetVersion (runtime global) to the standard places | ||
| PostgreSQL already uses for server-wide state. No new files. | ||
|
|
||
| --- a/src/include/miscadmin.h | ||
| +++ b/src/include/miscadmin.h | ||
| @@ -525,4 +525,11 @@ | ||
| /* in executor/nodeHash.c */ | ||
| extern size_t get_hash_memory_limit(void); | ||
|
|
||
| +/* | ||
| + * Spock core-patchset identity. Bump the version when the patchset | ||
| + * changes in a way visible to the extension binary. | ||
| + */ | ||
| +#define SPOCK_CORE_PATCHSET_VERSION 1 | ||
| +extern PGDLLIMPORT int SpockCorePatchsetVersion; | ||
| + | ||
| #endif /* MISCADMIN_H */ | ||
| --- a/src/backend/utils/init/globals.c | ||
| +++ b/src/backend/utils/init/globals.c | ||
| @@ -117,6 +117,9 @@ | ||
| bool IsUnderPostmaster = false; | ||
| bool IsBinaryUpgrade = false; | ||
|
|
||
| +/* Spock core-patchset identity. */ | ||
| +int SpockCorePatchsetVersion = SPOCK_CORE_PATCHSET_VERSION; | ||
| + | ||
| bool ExitOnAnyError = false; | ||
|
|
||
| int DateStyle = USE_ISO_DATES; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| Spock core-patchset: export patchset version via miscadmin.h and globals.c. | ||
|
|
||
| Adds SPOCK_CORE_PATCHSET_VERSION (compile-time constant) and | ||
| SpockCorePatchsetVersion (runtime global) to the standard places | ||
| PostgreSQL already uses for server-wide state. No new files. | ||
|
|
||
| --- a/src/include/miscadmin.h | ||
| +++ b/src/include/miscadmin.h | ||
| @@ -540,4 +540,11 @@ | ||
| /* in executor/nodeHash.c */ | ||
| extern size_t get_hash_memory_limit(void); | ||
|
|
||
| +/* | ||
| + * Spock core-patchset identity. Bump the version when the patchset | ||
| + * changes in a way visible to the extension binary. | ||
| + */ | ||
| +#define SPOCK_CORE_PATCHSET_VERSION 1 | ||
| +extern PGDLLIMPORT int SpockCorePatchsetVersion; | ||
| + | ||
| #endif /* MISCADMIN_H */ | ||
| --- a/src/backend/utils/init/globals.c | ||
| +++ b/src/backend/utils/init/globals.c | ||
| @@ -120,6 +120,9 @@ | ||
| bool IsUnderPostmaster = false; | ||
| bool IsBinaryUpgrade = false; | ||
|
|
||
| +/* Spock core-patchset identity. */ | ||
| +int SpockCorePatchsetVersion = SPOCK_CORE_PATCHSET_VERSION; | ||
| + | ||
| bool ExitOnAnyError = false; | ||
|
|
||
| int DateStyle = USE_ISO_DATES; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,163 @@ | ||
|
|
||
| /* spock--5.0.6--5.0.7.sql */ | ||
|
|
||
| -- complain if script is sourced in psql, rather than via ALTER EXTENSION | ||
| \echo Use "ALTER EXTENSION spock UPDATE TO '5.0.7'" to load this file. \quit | ||
|
|
||
| CREATE FUNCTION spock.pause_apply_workers() | ||
| RETURNS void VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'spock_pause_apply_workers'; | ||
|
|
||
| CREATE FUNCTION spock.resume_apply_workers() | ||
| RETURNS void VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'spock_resume_apply_workers'; | ||
|
|
||
| REVOKE EXECUTE ON FUNCTION spock.pause_apply_workers() FROM PUBLIC; | ||
| REVOKE EXECUTE ON FUNCTION spock.resume_apply_workers() FROM PUBLIC; | ||
|
|
||
| DROP PROCEDURE IF EXISTS spock.wait_for_sync_event(OUT bool, oid, pg_lsn, int); | ||
| DROP PROCEDURE IF EXISTS spock.wait_for_sync_event(OUT bool, oid, pg_lsn, int, bool); | ||
| DROP PROCEDURE IF EXISTS spock.wait_for_sync_event(OUT bool, name, pg_lsn, int); | ||
| DROP PROCEDURE IF EXISTS spock.wait_for_sync_event(OUT bool, name, pg_lsn, int, bool); | ||
| CREATE PROCEDURE spock.wait_for_sync_event( | ||
| OUT result bool, | ||
| origin_id oid, | ||
| lsn pg_lsn, | ||
| timeout int DEFAULT 0, | ||
| wait_if_disabled bool DEFAULT false | ||
| ) AS $$ | ||
| DECLARE | ||
| target_id oid; | ||
| start_time timestamptz := clock_timestamp(); | ||
| progress_lsn pg_lsn; | ||
| sub_is_enabled bool; | ||
| sub_slot name; | ||
| BEGIN | ||
| IF origin_id IS NULL THEN | ||
| RAISE EXCEPTION 'Invalid NULL origin_id'; | ||
| END IF; | ||
| target_id := node_id FROM spock.node_info(); | ||
|
|
||
| -- Upfront existence check is skipped when wait_if_disabled is true because | ||
| -- the subscription may not yet exist (e.g. a newly added node whose | ||
| -- subscriptions are still initializing). The loop below handles both the | ||
| -- not-found and disabled cases gracefully in that mode. | ||
| IF NOT wait_if_disabled THEN | ||
| SELECT sub_enabled, sub_slot_name INTO sub_is_enabled, sub_slot | ||
| FROM spock.subscription | ||
| WHERE sub_origin = origin_id AND sub_target = target_id; | ||
|
|
||
| IF NOT FOUND THEN | ||
| RAISE EXCEPTION 'No subscription found for replication % => %', | ||
| origin_id, target_id; | ||
| END IF; | ||
| END IF; | ||
|
|
||
| WHILE true LOOP | ||
| -- Re-check subscription state each iteration. Also re-fetches | ||
| -- sub_slot_name so the loop is self-contained when wait_if_disabled | ||
| -- is true and the pre-loop check was skipped. | ||
| SELECT sub_enabled, sub_slot_name INTO sub_is_enabled, sub_slot | ||
| FROM spock.subscription | ||
| WHERE sub_origin = origin_id AND sub_target = target_id; | ||
|
|
||
| IF NOT FOUND THEN | ||
| IF NOT wait_if_disabled THEN | ||
| RAISE EXCEPTION 'No subscription found for replication % => %', | ||
| origin_id, target_id; | ||
| END IF; | ||
| -- Subscription not yet created; fall through to sleep. | ||
| ELSIF NOT sub_is_enabled THEN | ||
| IF NOT wait_if_disabled THEN | ||
| RAISE EXCEPTION 'Subscription % => % has been disabled', | ||
| origin_id, target_id; | ||
| END IF; | ||
| -- Subscription still initializing; fall through to sleep. | ||
| ELSE | ||
| -- Subscription is enabled; check LSN progress. | ||
| -- Uses PostgreSQL's native origin tracking rather than spock.progress | ||
| SELECT remote_lsn INTO progress_lsn | ||
| FROM pg_replication_origin_status | ||
| WHERE external_id = sub_slot; | ||
|
|
||
| IF progress_lsn IS NOT NULL AND progress_lsn >= lsn THEN | ||
| result = true; | ||
| RETURN; | ||
| END IF; | ||
| END IF; | ||
|
|
||
| IF timeout <> 0 AND | ||
| EXTRACT(EPOCH FROM (clock_timestamp() - start_time)) >= timeout THEN | ||
| result := false; | ||
| RETURN; | ||
| END IF; | ||
|
|
||
| ROLLBACK; | ||
| PERFORM pg_sleep(0.2); | ||
| END LOOP; | ||
| END; | ||
| $$ LANGUAGE plpgsql; | ||
|
|
||
| CREATE PROCEDURE spock.wait_for_sync_event( | ||
| OUT result bool, | ||
| origin name, | ||
| lsn pg_lsn, | ||
| timeout int DEFAULT 0, | ||
| wait_if_disabled bool DEFAULT false | ||
| ) AS $$ | ||
| DECLARE | ||
| origin_id oid; | ||
| BEGIN | ||
| origin_id := node_id FROM spock.node WHERE node_name = origin; | ||
| IF origin_id IS NULL THEN | ||
| RAISE EXCEPTION 'Origin node ''%'' not found', origin; | ||
| END IF; | ||
| CALL spock.wait_for_sync_event(result, origin_id, lsn, timeout, wait_if_disabled); | ||
| END; | ||
| $$ LANGUAGE plpgsql; | ||
|
|
||
| -- spock.sync_event() gained an optional 'transactional' boolean argument | ||
| -- (default false). Drop the old zero-arg signature first so the upgrade | ||
| -- doesn't leave behind two overloads with overlapping zero-arg resolution. | ||
| DROP FUNCTION IF EXISTS spock.sync_event(); | ||
| CREATE FUNCTION spock.sync_event(transactional boolean DEFAULT false) | ||
| RETURNS pg_lsn RETURNS NULL ON NULL INPUT | ||
| AS 'MODULE_PATHNAME', 'spock_create_sync_event' | ||
| LANGUAGE C VOLATILE; | ||
|
|
||
| /* | ||
| * Correct the declared type of spock.subscription.sub_skip_schema. | ||
| * | ||
| * The column was added as text in the 5.0.1--5.0.2 upgrade, but the C code | ||
| * has always treated it as text[] on both read and write paths | ||
| * (strlist_to_textarray on write, DatumGetArrayTypeP on read). The bytes | ||
| * already on disk are therefore a valid ArrayType; only the catalog's type | ||
| * label is wrong. ALTER TABLE ... ALTER COLUMN TYPE text[] USING ... is | ||
| * not viable here: there is no SQL expression that converts "varlena bytes | ||
| * the planner believes are text but are in fact ArrayType internal format" | ||
| * back into an ArrayType Datum. Relabel the column in place so SQL-level | ||
| * access (SELECT, unnest, etc.) works as users expect, without rewriting | ||
| * data. | ||
| */ | ||
| LOCK TABLE spock.subscription IN ACCESS EXCLUSIVE MODE; | ||
|
|
||
| UPDATE pg_catalog.pg_attribute | ||
| SET atttypid = 'text[]'::regtype, | ||
| attndims = 1 | ||
| WHERE attrelid = 'spock.subscription'::regclass | ||
| AND attname = 'sub_skip_schema' | ||
| AND atttypid = 'text'::regtype; | ||
|
|
||
| /* | ||
| * Drop any pg_statistic rows for the column. Stats sampled when the | ||
| * column was labelled text encode varlena bytes with text semantics; | ||
| * after the relabel the planner would interpret the same stavalues | ||
| * arrays as text[], producing nonsense selectivities (and possibly | ||
| * crashing on operators that validate ArrayType structure). ANALYZE | ||
| * will repopulate as needed. | ||
| */ | ||
| DELETE FROM pg_catalog.pg_statistic | ||
| WHERE starelid = 'spock.subscription'::regclass | ||
| AND staattnum = ( | ||
| SELECT attnum | ||
| FROM pg_catalog.pg_attribute | ||
| WHERE attrelid = 'spock.subscription'::regclass | ||
| AND attname = 'sub_skip_schema'); | ||
|
danolivo marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| /* spock--5.0.7--5.0.8.sql */ | ||
|
|
||
| -- complain if script is sourced in psql, rather than via ALTER EXTENSION | ||
| \echo Use "ALTER EXTENSION spock UPDATE TO '5.0.8'" to load this file. \quit | ||
|
|
||
| -- No schema changes in 5.0.8. |
Uh oh!
There was an error while loading. Please reload this page.