Skip to content

Commit b1c67ae

Browse files
committed
add drop_range_partition_expand_next() function
1 parent cea6ea5 commit b1c67ae

File tree

4 files changed

+109
-67
lines changed

4 files changed

+109
-67
lines changed

expected/pathman_basic.out

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,35 @@ SELECT pathman.drop_range_partition('test.num_range_rel_7');
14091409
test.num_range_rel_7
14101410
(1 row)
14111411

1412+
SELECT pathman.drop_range_partition_expand_next('test.num_range_rel_4');
1413+
drop_range_partition_expand_next
1414+
----------------------------------
1415+
1416+
(1 row)
1417+
1418+
SELECT * FROM pathman.pathman_partition_list WHERE parent = 'test.num_range_rel'::regclass;
1419+
parent | partition | parttype | partattr | range_min | range_max
1420+
--------------------+----------------------+----------+----------+-----------+-----------
1421+
test.num_range_rel | test.num_range_rel_1 | 2 | id | 0 | 1000
1422+
test.num_range_rel | test.num_range_rel_2 | 2 | id | 1000 | 2000
1423+
test.num_range_rel | test.num_range_rel_3 | 2 | id | 2000 | 3000
1424+
test.num_range_rel | test.num_range_rel_6 | 2 | id | 3000 | 5000
1425+
(4 rows)
1426+
1427+
SELECT pathman.drop_range_partition_expand_next('test.num_range_rel_6');
1428+
drop_range_partition_expand_next
1429+
----------------------------------
1430+
1431+
(1 row)
1432+
1433+
SELECT * FROM pathman.pathman_partition_list WHERE parent = 'test.num_range_rel'::regclass;
1434+
parent | partition | parttype | partattr | range_min | range_max
1435+
--------------------+----------------------+----------+----------+-----------+-----------
1436+
test.num_range_rel | test.num_range_rel_1 | 2 | id | 0 | 1000
1437+
test.num_range_rel | test.num_range_rel_2 | 2 | id | 1000 | 2000
1438+
test.num_range_rel | test.num_range_rel_3 | 2 | id | 2000 | 3000
1439+
(3 rows)
1440+
14121441
SELECT pathman.append_range_partition('test.range_rel');
14131442
append_range_partition
14141443
------------------------
@@ -1711,15 +1740,13 @@ SELECT COUNT(*) FROM ONLY test.hash_rel;
17111740

17121741
DROP TABLE test.hash_rel CASCADE;
17131742
SELECT pathman.drop_partitions('test.num_range_rel');
1714-
NOTICE: drop cascades to 4 other objects
1743+
NOTICE: drop cascades to 3 other objects
17151744
NOTICE: 998 rows copied from test.num_range_rel_1
17161745
NOTICE: 1000 rows copied from test.num_range_rel_2
17171746
NOTICE: 1000 rows copied from test.num_range_rel_3
1718-
NOTICE: 2 rows copied from test.num_range_rel_4
1719-
NOTICE: 0 rows copied from test.num_range_rel_6
17201747
drop_partitions
17211748
-----------------
1722-
5
1749+
3
17231750
(1 row)
17241751

17251752
DROP TABLE test.num_range_rel CASCADE;

range.sql

Lines changed: 13 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -533,68 +533,6 @@ END
533533
$$
534534
LANGUAGE plpgsql;
535535

536-
537-
/*
538-
* Merge RANGE partitions
539-
*/
540-
CREATE OR REPLACE FUNCTION @extschema@.merge_range_partitions(
541-
partition1 REGCLASS,
542-
partition2 REGCLASS)
543-
RETURNS VOID AS
544-
$$
545-
DECLARE
546-
v_parent1 REGCLASS;
547-
v_parent2 REGCLASS;
548-
v_attname TEXT;
549-
v_part_type INTEGER;
550-
v_atttype REGTYPE;
551-
552-
BEGIN
553-
IF partition1 = partition2 THEN
554-
RAISE EXCEPTION 'cannot merge partition with itself';
555-
END IF;
556-
557-
v_parent1 := @extschema@.get_parent_of_partition(partition1);
558-
v_parent2 := @extschema@.get_parent_of_partition(partition2);
559-
560-
/* Acquire data modification locks (prevent further modifications) */
561-
PERFORM @extschema@.prevent_relation_modification(partition1);
562-
PERFORM @extschema@.prevent_relation_modification(partition2);
563-
564-
IF v_parent1 != v_parent2 THEN
565-
RAISE EXCEPTION 'cannot merge partitions with different parents';
566-
END IF;
567-
568-
/* Acquire lock on parent */
569-
PERFORM @extschema@.lock_partitioned_relation(v_parent1);
570-
571-
SELECT attname, parttype
572-
FROM @extschema@.pathman_config
573-
WHERE partrel = v_parent1
574-
INTO v_attname, v_part_type;
575-
576-
IF v_attname IS NULL THEN
577-
RAISE EXCEPTION 'table "%" is not partitioned', v_parent1::TEXT;
578-
END IF;
579-
580-
/* Check if this is a RANGE partition */
581-
IF v_part_type != 2 THEN
582-
RAISE EXCEPTION 'specified partitions are not RANGE partitions';
583-
END IF;
584-
585-
v_atttype := @extschema@.get_attribute_type(partition1, v_attname);
586-
587-
EXECUTE format('SELECT @extschema@.merge_range_partitions_internal($1, $2, $3, NULL::%s)',
588-
@extschema@.get_base_type(v_atttype)::TEXT)
589-
USING v_parent1, partition1, partition2;
590-
591-
/* Tell backend to reload configuration */
592-
PERFORM @extschema@.on_update_partitions(v_parent1);
593-
END
594-
$$
595-
LANGUAGE plpgsql;
596-
597-
598536
/*
599537
* Merge multiple partitions. All data will be copied to the first one. The rest
600538
* of partitions will be dropped
@@ -617,7 +555,6 @@ BEGIN
617555
END
618556
$$ LANGUAGE plpgsql;
619557

620-
621558
/*
622559
* Append new partition.
623560
*/
@@ -952,6 +889,19 @@ LANGUAGE plpgsql
952889
SET pg_pathman.enable_partitionfilter = off; /* ensures that PartitionFilter is OFF */
953890

954891

892+
/*
893+
* Drops partition and expands the next partition so that it cover dropped
894+
* one
895+
*
896+
* This function was written in order to support Oracle-like ALTER TABLE ...
897+
* DROP PARTITION. In Oracle partitions only have upper bound and when
898+
* partition is dropped the next one automatically covers freed range
899+
*/
900+
CREATE OR REPLACE FUNCTION @extschema@.drop_range_partition_expand_next(relid REGCLASS)
901+
RETURNS VOID AS 'pg_pathman', 'drop_range_partition_expand_next'
902+
LANGUAGE C STRICT;
903+
904+
955905
/*
956906
* Attach range partition
957907
*/

sql/pathman_basic.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,11 @@ SELECT pathman.prepend_range_partition('test.num_range_rel');
400400
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE id < 0;
401401
SELECT pathman.drop_range_partition('test.num_range_rel_7');
402402

403+
SELECT pathman.drop_range_partition_expand_next('test.num_range_rel_4');
404+
SELECT * FROM pathman.pathman_partition_list WHERE parent = 'test.num_range_rel'::regclass;
405+
SELECT pathman.drop_range_partition_expand_next('test.num_range_rel_6');
406+
SELECT * FROM pathman.pathman_partition_list WHERE parent = 'test.num_range_rel'::regclass;
407+
403408
SELECT pathman.append_range_partition('test.range_rel');
404409
SELECT pathman.prepend_range_partition('test.range_rel');
405410
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt BETWEEN '2014-12-15' AND '2015-01-15';

src/pl_range_funcs.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ PG_FUNCTION_INFO_V1( get_part_range_by_idx );
5959
PG_FUNCTION_INFO_V1( build_range_condition );
6060
PG_FUNCTION_INFO_V1( build_sequence_name );
6161
PG_FUNCTION_INFO_V1( merge_range_partitions );
62+
PG_FUNCTION_INFO_V1( drop_range_partition_expand_next );
6263

6364

6465
/*
@@ -690,3 +691,62 @@ drop_table(Oid relid)
690691

691692
RemoveRelations(n);
692693
}
694+
695+
/*
696+
* Drops partition and expands the next partition so that it cover dropped
697+
* one
698+
*
699+
* This function was written in order to support Oracle-like ALTER TABLE ...
700+
* DROP PARTITION. In Oracle partitions only have upper bound and when
701+
* partition is dropped the next one automatically covers freed range
702+
*/
703+
Datum
704+
drop_range_partition_expand_next(PG_FUNCTION_ARGS)
705+
{
706+
PartParentSearch parent_search;
707+
const PartRelationInfo *prel;
708+
RangeEntry *ranges;
709+
Oid relid = PG_GETARG_OID(0),
710+
parent;
711+
int i;
712+
713+
/* Get parent relid */
714+
parent = get_parent_of_partition(relid, &parent_search);
715+
if (parent_search != PPS_ENTRY_PART_PARENT)
716+
elog(ERROR, "relation \"%s\" is not a partition",
717+
get_rel_name_or_relid(relid));
718+
719+
prel = get_pathman_relation_info(parent);
720+
shout_if_prel_is_invalid(parent, prel, PT_RANGE);
721+
722+
ranges = PrelGetRangesArray(prel);
723+
724+
/* Looking for partition in child relations */
725+
for (i = 0; i < prel->children_count; i++)
726+
if (ranges[i].child_oid == relid)
727+
break;
728+
729+
/*
730+
* It must be in ranges array because we already know that table
731+
* is a partition
732+
*/
733+
Assert(i < prel->children_count);
734+
735+
/* If there is next partition then expand it */
736+
if (i < prel->children_count - 1)
737+
{
738+
RangeEntry *cur = &ranges[i],
739+
*next = &ranges[i+1];
740+
741+
recreate_range_constraint(next->child_oid,
742+
get_relid_attribute_name(prel->key, prel->attnum),
743+
prel->attnum,
744+
prel->atttype,
745+
&cur->min,
746+
&next->max);
747+
}
748+
749+
drop_table(relid);
750+
751+
PG_RETURN_VOID();
752+
}

0 commit comments

Comments
 (0)