Skip to content

Commit 10e6c71

Browse files
committed
Fix upgrade from 1.4 to 1.5.
This upgrade drops a column from pg_config. This is problematic, because pg_attribute entry is never actually removed in Postgres and fresh install and upgraded one had different number of attrs. To avoid bothering with this, recreate pg_config during upgrade from scratch. To test this, rewrite check_update.py which was outright broken; now it runs large part of regression tests. Also, test script revealed that update script hasn't included dd71813 fix for replace_hash_partition.
1 parent 6499232 commit 10e6c71

File tree

3 files changed

+287
-91
lines changed

3 files changed

+287
-91
lines changed

Diff for: pg_pathman--1.4--1.5.sql

+129
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,41 @@ RETURNS BOOL AS 'pg_pathman', 'validate_interval_value'
1111
LANGUAGE C;
1212

1313
ALTER TABLE @[email protected]_config DROP COLUMN cooked_expr;
14+
/*
15+
* Dropped columns are never actually purged, entry in pg_attribute remains.
16+
* Since dealing with different number of attrs in C code is cumbersome,
17+
* let's recreate table instead.
18+
*/
19+
CREATE TABLE @[email protected]_config_tmp (LIKE @[email protected]_config INCLUDING ALL);
20+
INSERT INTO @[email protected]_config_tmp SELECT * FROM @[email protected]_config;
21+
ALTER EVENT TRIGGER pathman_ddl_trigger DISABLE;
22+
DROP TABLE @[email protected]_config;
23+
ALTER TABLE @[email protected]_config_tmp RENAME TO pathman_config;
24+
ALTER EVENT TRIGGER pathman_ddl_trigger ENABLE;
25+
26+
/*
27+
* Get back stuff not preserved by CREATE TABLE LIKE: ACL, RLS and
28+
* pg_extension_config_dump mark.
29+
*/
30+
31+
GRANT SELECT, INSERT, UPDATE, DELETE
32+
33+
TO public;
34+
35+
/*
36+
* Row security policy to restrict partitioning operations to owner and superusers only
37+
*/
38+
CREATE POLICY deny_modification ON @[email protected]_config
39+
FOR ALL USING (check_security_policy(partrel));
40+
CREATE POLICY allow_select ON @[email protected]_config FOR SELECT USING (true);
41+
ALTER TABLE @[email protected]_config ENABLE ROW LEVEL SECURITY;
42+
43+
/*
44+
* Enable dump of config tables with pg_dump.
45+
*/
46+
SELECT pg_catalog.pg_extension_config_dump('@[email protected]_config', '');
47+
48+
1449
ALTER TABLE @[email protected]_config ADD CONSTRAINT pathman_config_interval_check
1550
CHECK (@[email protected]_interval_value(partrel,
1651
expr,
@@ -505,6 +540,100 @@ BEGIN
505540
END
506541
$$ LANGUAGE plpgsql;
507542

543+
/*
544+
* Replace hash partition with another one. It could be useful in case when
545+
* someone wants to attach foreign table as a partition.
546+
*
547+
* lock_parent - should we take an exclusive lock?
548+
*/
549+
CREATE OR REPLACE FUNCTION @[email protected]_hash_partition(
550+
old_partition REGCLASS,
551+
new_partition REGCLASS,
552+
lock_parent BOOL DEFAULT TRUE)
553+
RETURNS REGCLASS AS $$
554+
DECLARE
555+
parent_relid REGCLASS;
556+
old_constr_name TEXT; /* name of old_partition's constraint */
557+
old_constr_def TEXT; /* definition of old_partition's constraint */
558+
rel_persistence CHAR;
559+
p_init_callback REGPROCEDURE;
560+
561+
BEGIN
562+
PERFORM @[email protected]_relname(old_partition);
563+
PERFORM @[email protected]_relname(new_partition);
564+
565+
/* Parent relation */
566+
parent_relid := @[email protected]_parent_of_partition(old_partition);
567+
568+
IF lock_parent THEN
569+
/* Acquire data modification lock (prevent further modifications) */
570+
PERFORM @[email protected]_data_modification(parent_relid);
571+
ELSE
572+
/* Acquire lock on parent */
573+
PERFORM @[email protected]_part_modification(parent_relid);
574+
END IF;
575+
576+
/* Acquire data modification lock (prevent further modifications) */
577+
PERFORM @[email protected]_data_modification(old_partition);
578+
PERFORM @[email protected]_data_modification(new_partition);
579+
580+
/* Ignore temporary tables */
581+
SELECT relpersistence FROM pg_catalog.pg_class
582+
WHERE oid = new_partition INTO rel_persistence;
583+
584+
IF rel_persistence = 't'::CHAR THEN
585+
RAISE EXCEPTION 'temporary table "%" cannot be used as a partition',
586+
new_partition::TEXT;
587+
END IF;
588+
589+
/* Check that new partition has an equal structure as parent does */
590+
IF NOT @[email protected]_tuple_convertible(parent_relid, new_partition) THEN
591+
RAISE EXCEPTION 'partition must have a compatible tuple format';
592+
END IF;
593+
594+
/* Check that table is partitioned */
595+
IF @[email protected]_partition_key(parent_relid) IS NULL THEN
596+
RAISE EXCEPTION 'table "%" is not partitioned', parent_relid::TEXT;
597+
END IF;
598+
599+
/* Fetch name of old_partition's HASH constraint */
600+
old_constr_name = @[email protected]_check_constraint_name(old_partition::REGCLASS);
601+
602+
/* Fetch definition of old_partition's HASH constraint */
603+
SELECT pg_catalog.pg_get_constraintdef(oid) FROM pg_catalog.pg_constraint
604+
WHERE conrelid = old_partition AND quote_ident(conname) = old_constr_name
605+
INTO old_constr_def;
606+
607+
/* Detach old partition */
608+
EXECUTE format('ALTER TABLE %s NO INHERIT %s', old_partition, parent_relid);
609+
EXECUTE format('ALTER TABLE %s DROP CONSTRAINT %s',
610+
old_partition,
611+
old_constr_name);
612+
613+
/* Attach the new one */
614+
EXECUTE format('ALTER TABLE %s INHERIT %s', new_partition, parent_relid);
615+
EXECUTE format('ALTER TABLE %s ADD CONSTRAINT %s %s',
616+
new_partition,
617+
@[email protected]_check_constraint_name(new_partition::REGCLASS),
618+
old_constr_def);
619+
620+
/* Fetch init_callback from 'params' table */
621+
WITH stub_callback(stub) as (values (0))
622+
SELECT init_callback
623+
FROM stub_callback
624+
LEFT JOIN @[email protected]_config_params AS params
625+
ON params.partrel = parent_relid
626+
INTO p_init_callback;
627+
628+
/* Finally invoke init_callback */
629+
PERFORM @[email protected]_on_partition_created_callback(parent_relid,
630+
new_partition,
631+
p_init_callback);
632+
633+
RETURN new_partition;
634+
END
635+
$$ LANGUAGE plpgsql;
636+
508637
/*
509638
* Disable pathman partitioning for specified relation.
510639
*/

Diff for: tests/update/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,9 @@ PG_CONFIG=... ./dump_pathman_objects %DBNAME%
99

1010
diff file_1 file_2
1111
```
12+
13+
check_update.py script tries to verify that update is ok automatically. For
14+
instance,
15+
```bash
16+
tests/update/check_update.py d34a77e worktree
17+
```

0 commit comments

Comments
 (0)