Skip to content

Commit 8db4319

Browse files
committed
add pg_partman
1 parent f318389 commit 8db4319

File tree

7 files changed

+320
-6
lines changed

7 files changed

+320
-6
lines changed

flake.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
./nix/ext/pg_hashids.nix
112112
./nix/ext/pgsodium.nix
113113
./nix/ext/pg_graphql.nix
114+
./nix/ext/pg_partman.nix
114115
./nix/ext/pg_stat_monitor.nix
115116
./nix/ext/pg_jsonschema.nix
116117
./nix/ext/pgvector.nix

nix/ext/pg_partman.nix

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{ lib, stdenv, fetchFromGitHub, postgresql }:
2+
3+
stdenv.mkDerivation rec {
4+
pname = "pg_partman";
5+
version = "5.1.0";
6+
7+
buildInputs = [ postgresql ];
8+
9+
src = fetchFromGitHub {
10+
owner = "pgpartman";
11+
repo = pname;
12+
rev = "refs/tags/v${version}";
13+
sha256 = "sha256-GrVOJ5ywZMyqyDroYDLdKkXDdIJSDGhDfveO/ZvrmYs=";
14+
};
15+
16+
installPhase = ''
17+
mkdir -p $out/{lib,share/postgresql/extension}
18+
19+
cp src/*${postgresql.dlSuffix} $out/lib
20+
cp updates/* $out/share/postgresql/extension
21+
cp -r sql/* $out/share/postgresql/extension
22+
cp *.control $out/share/postgresql/extension
23+
'';
24+
25+
meta = with lib; {
26+
description = "Partition management extension for PostgreSQL";
27+
homepage = "https://github.com/pgpartman/pg_partman";
28+
changelog = "https://github.com/pgpartman/pg_partman/blob/v${version}/CHANGELOG.md";
29+
maintainers = with maintainers; [ samrose ];
30+
platforms = postgresql.meta.platforms;
31+
license = licenses.postgresql;
32+
broken = versionOlder postgresql.version "14";
33+
};
34+
}

nix/tests/expected/extensions_sql_interface.out

Lines changed: 100 additions & 5 deletions
Large diffs are not rendered by default.

nix/tests/expected/pg_partman.out

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
create schema if not exists partman_test;
2+
/*
3+
Simple Time Based: 1 Partition Per Day
4+
5+
For native partitioning, you must start with a parent table that has already been set up to be partitioned in the desired type. Currently pg_partman only supports the RANGE type of partitioning (both for time & id). You cannot turn a non-partitioned table into the parent table of a partitioned set, which can make migration a challenge. This document will show you some techniques for how to manage this later. For now, we will start with a brand new table in this example. Any non-unique indexes can also be added to the parent table in PG11+ and they will automatically be created on all child tables.
6+
*/
7+
create table partman_test.time_taptest_table(
8+
col1 int,
9+
col2 text default 'stuff',
10+
col3 timestamptz not null default now()
11+
)
12+
partition by range (col3);
13+
create index on partman_test.time_tap (col3);
14+
ERROR: relation "partman_test.time_tap" does not exist
15+
/*
16+
Unique indexes (including primary keys) cannot be created on a natively partitioned parent unless they include the partition key. For time-based partitioning that generally doesn't work out since that would limit only a single timestamp value in each child table. pg_partman helps to manage this by using a template table to manage properties that currently are not supported by native partitioning. Note that this does not solve the issue of the constraint not being enforced across the entire partition set. See the main documentation to see which properties are managed by the template.
17+
18+
Manually create the template table first so that when we run create_parent() the initial child tables that are created will have a primary key. If you do not supply a template table to pg_partman, it will create one for you in the schema that you installed the extension to. However properties you add to that template are only then applied to newly created child tables after that point. You will have to retroactively apply those properties manually to any child tables that already existed.
19+
*/
20+
create table partman_test.time_taptest_table_template (like partman_test.time_taptest_table);
21+
alter table partman_test.time_taptest_table_template add primary key (col1);
22+
/*
23+
Review tables in the partman_test schema
24+
*/
25+
select
26+
table_name,
27+
table_type
28+
from
29+
information_schema.tables
30+
where
31+
table_schema = 'partman_test';
32+
table_name | table_type
33+
-----------------------------+------------
34+
time_taptest_table | BASE TABLE
35+
time_taptest_table_template | BASE TABLE
36+
(2 rows)
37+
38+
select public.create_parent(
39+
p_parent_table := 'partman_test.time_taptest_table',
40+
p_control := 'col3',
41+
p_interval := '1 day',
42+
p_template_table := 'partman_test.time_taptest_table_template'
43+
);
44+
create_parent
45+
---------------
46+
t
47+
(1 row)
48+
49+
/*
50+
Review tables in the partman_test schema, which should now include daily partitions
51+
*/
52+
select
53+
-- dates in partition names are variable, so reduced to the prefix
54+
substring(table_name, 1, 21) as table_prefix,
55+
table_type
56+
from
57+
information_schema.tables
58+
where
59+
table_schema = 'partman_test'
60+
order by
61+
table_name;
62+
table_prefix | table_type
63+
-----------------------+------------
64+
time_taptest_table | BASE TABLE
65+
time_taptest_table_de | BASE TABLE
66+
time_taptest_table_p2 | BASE TABLE
67+
time_taptest_table_p2 | BASE TABLE
68+
time_taptest_table_p2 | BASE TABLE
69+
time_taptest_table_p2 | BASE TABLE
70+
time_taptest_table_p2 | BASE TABLE
71+
time_taptest_table_p2 | BASE TABLE
72+
time_taptest_table_p2 | BASE TABLE
73+
time_taptest_table_p2 | BASE TABLE
74+
time_taptest_table_p2 | BASE TABLE
75+
time_taptest_table_te | BASE TABLE
76+
(12 rows)
77+
78+
/*
79+
Confirm maintenance proc runs without issue
80+
*/
81+
call public.run_maintenance_proc();
82+
/*
83+
Make sure the background worker is NOT enabled.
84+
This is intentional. We document using pg_cron to schedule calls to
85+
public.run_maintenance_proc(). That is consistent with other providers.
86+
*/
87+
select
88+
application_name
89+
from
90+
pg_stat_activity
91+
where
92+
application_name = 'pg_partman_bgw';
93+
application_name
94+
------------------
95+
(0 rows)
96+
97+
-- Cleanup
98+
drop schema partman_test cascade;
99+
NOTICE: drop cascades to 2 other objects
100+
DETAIL: drop cascades to table partman_test.time_taptest_table
101+
drop cascades to table partman_test.time_taptest_table_template

nix/tests/postgresql.conf.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@ default_text_search_config = 'pg_catalog.english'
718718

719719
#local_preload_libraries = ''
720720
#session_preload_libraries = ''
721-
shared_preload_libraries = 'pg_stat_statements, pg_stat_monitor, pgaudit, plpgsql, plpgsql_check, pg_cron, pg_net, pgsodium, timescaledb, auto_explain, pg_tle, plan_filter, pg_backtrace' # (change requires restart)
721+
shared_preload_libraries = 'pg_stat_statements, pg_stat_monitor, pgaudit, plpgsql, plpgsql_check, pg_cron, pg_net, pgsodium, timescaledb, auto_explain, pg_tle, plan_filter, pg_backtrace, pg_partman_bgw' # (change requires restart)
722722
jit_provider = 'llvmjit' # JIT library to use
723723

724724

nix/tests/prime.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ create extension pg_net;
4242
create extension pg_graphql;
4343
create extension pg_freespacemap;
4444
create extension pg_hashids;
45+
create extension pg_partman;
4546
create extension pg_prewarm;
4647
create extension pg_jsonschema;
4748
create extension pg_repack;

nix/tests/sql/pg_partman.sql

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
create schema if not exists partman_test;
2+
3+
/*
4+
Simple Time Based: 1 Partition Per Day
5+
6+
For native partitioning, you must start with a parent table that has already been set up to be partitioned in the desired type. Currently pg_partman only supports the RANGE type of partitioning (both for time & id). You cannot turn a non-partitioned table into the parent table of a partitioned set, which can make migration a challenge. This document will show you some techniques for how to manage this later. For now, we will start with a brand new table in this example. Any non-unique indexes can also be added to the parent table in PG11+ and they will automatically be created on all child tables.
7+
*/
8+
9+
create table partman_test.time_taptest_table(
10+
col1 int,
11+
col2 text default 'stuff',
12+
col3 timestamptz not null default now()
13+
)
14+
partition by range (col3);
15+
16+
create index on partman_test.time_tap (col3);
17+
18+
/*
19+
Unique indexes (including primary keys) cannot be created on a natively partitioned parent unless they include the partition key. For time-based partitioning that generally doesn't work out since that would limit only a single timestamp value in each child table. pg_partman helps to manage this by using a template table to manage properties that currently are not supported by native partitioning. Note that this does not solve the issue of the constraint not being enforced across the entire partition set. See the main documentation to see which properties are managed by the template.
20+
21+
Manually create the template table first so that when we run create_parent() the initial child tables that are created will have a primary key. If you do not supply a template table to pg_partman, it will create one for you in the schema that you installed the extension to. However properties you add to that template are only then applied to newly created child tables after that point. You will have to retroactively apply those properties manually to any child tables that already existed.
22+
*/
23+
24+
create table partman_test.time_taptest_table_template (like partman_test.time_taptest_table);
25+
26+
alter table partman_test.time_taptest_table_template add primary key (col1);
27+
28+
/*
29+
Review tables in the partman_test schema
30+
*/
31+
32+
select
33+
table_name,
34+
table_type
35+
from
36+
information_schema.tables
37+
where
38+
table_schema = 'partman_test';
39+
40+
41+
select public.create_parent(
42+
p_parent_table := 'partman_test.time_taptest_table',
43+
p_control := 'col3',
44+
p_interval := '1 day',
45+
p_template_table := 'partman_test.time_taptest_table_template'
46+
);
47+
48+
/*
49+
Review tables in the partman_test schema, which should now include daily partitions
50+
*/
51+
52+
select
53+
-- dates in partition names are variable, so reduced to the prefix
54+
substring(table_name, 1, 21) as table_prefix,
55+
table_type
56+
from
57+
information_schema.tables
58+
where
59+
table_schema = 'partman_test'
60+
order by
61+
table_name;
62+
63+
64+
/*
65+
Confirm maintenance proc runs without issue
66+
*/
67+
call public.run_maintenance_proc();
68+
69+
/*
70+
Make sure the background worker is NOT enabled.
71+
This is intentional. We document using pg_cron to schedule calls to
72+
public.run_maintenance_proc(). That is consistent with other providers.
73+
*/
74+
select
75+
application_name
76+
from
77+
pg_stat_activity
78+
where
79+
application_name = 'pg_partman_bgw';
80+
81+
-- Cleanup
82+
drop schema partman_test cascade;

0 commit comments

Comments
 (0)