@@ -11,6 +11,41 @@ RETURNS BOOL AS 'pg_pathman', 'validate_interval_value'
11
11
LANGUAGE C;
12
12
13
13
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
+
14
49
ALTER TABLE @
[email protected] _config ADD
CONSTRAINT pathman_config_interval_check
15
50
CHECK (@
[email protected] _interval_value(partrel,
16
51
expr,
@@ -505,6 +540,100 @@ BEGIN
505
540
END
506
541
$$ LANGUAGE plpgsql;
507
542
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
+
508
637
/*
509
638
* Disable pathman partitioning for specified relation.
510
639
*/
0 commit comments