Skip to content

Commit b968372

Browse files
committed
features and bug fixes for 5.2.0
1 parent df602e8 commit b968372

19 files changed

+3784
-1562
lines changed

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,18 @@
44
NEW FEATURES
55
------------
66
- Add support for microsecond precisions in epoch partitioning. (Github PR #659)
7-
- Improve partition maintenance performance when determining next partition to created. (Github Issue #660)
7+
- Improve partition maintenance performance when determining next partition to be created. (Github Issue #660)
88
- Removed requirement for pg_partman to be installed as a superuser. See "superuser" parameter in control file documentation for more details - https://www.postgresql.org/docs/current/extend-extensions.html#EXTEND-EXTENSIONS-FILES
99
- Do not create partitions during a maintenance run that aren't going to be kept as part of retention anyway. (Github Issue #649)
10+
- Removed `default_table` column from `part_config` table. It's only necessary in `part_config_sub` to determine whether future sub-partition parents should have defaults made. Adjusted other code to look up whether a default table actually exists to determine its behavior. (Github Issue #637)
11+
- Allow the control column to be NULL. This is not advised without very careful review and an explicit use-case defined as it can cause unexpected behavior or excessive data in the DEFAULT child partition. A new flag `p_control_not_null` has been added to the `create_parent()` and `create_sub_parent()` functions.
1012

13+
BUG FIXES
14+
---------
15+
- Enforcement of the control column being NOT NULL was not being done as intended. This has been fixed. If you'd like to allow the control column to be NULL, see the new feature flag in 5.2.0
16+
- Fixed `reapply_constraint_proc()` to work properly when there are no relevant child tables to place additional constraints. In the process reworked the logic to determine the target child tables for both that procedure and the apply_constraints() function. The determining factor is now always the newest child table that contains data (other than the default). Updated documentation to clarify how the optimize_constraint flag works. (Github Issue #694)
17+
- Properly handle partial indexes that are inherited from the template table. (Github Issue #657)
18+
- Move the retention logic for dropping tables later in the maintenance process to help avoid longer running heavy locks on partition sets. (Github Issue #678)
1119

1220

1321
5.1.0

doc/pg_partman.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,7 @@ Stores all configuration data for partition sets managed by the extension.
787787
- `constraint_cols`
788788
- Array column that lists columns to have additional constraints applied. See **About** section for more information on how this feature works.
789789
- `optimize_constraint`
790-
- Manages which old tables get additional constraints set if configured to do so. See **About** section for more info. Default 30.
790+
- Manages which old tables get additional constraints set if configured to do so. This value is a count on the number of child tables backwards from the newest child table that contains data. The default value of 30 means that the constraints will be created on the the child table that is 30 behind the newest child table that contains data. See **About** section for more info.
791791
- `infinite_time_partitions`
792792
- By default, new partitions in a time-based set will not be created if new data is not inserted to keep an infinite amount of empty tables from being created.
793793
- If you'd still like new partitions to be made despite there being no new data, set this to TRUE.

pg_partman.control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
default_version = '5.1.0'
1+
default_version = '5.2.0'
22
comment = 'Extension to manage partitioned tables by time or ID'
33
relocatable = false
44
superuser = false

sql/functions/apply_constraints.sql

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ ex_hint text;
1515
ex_message text;
1616
v_child_exists text;
1717
v_child_tablename text;
18+
v_child_value text;
1819
v_col text;
1920
v_constraint_cols text[];
2021
v_constraint_name text;
@@ -34,6 +35,8 @@ v_last_partition_timestamp timestamptz;
3435
v_new_search_path text;
3536
v_old_search_path text;
3637
v_optimize_constraint int;
38+
v_optimize_counter int := 0;
39+
v_row_max_value record;
3740
v_parent_schema text;
3841
v_parent_table text;
3942
v_parent_tablename text;
@@ -114,20 +117,29 @@ IF p_child_table IS NULL THEN
114117
v_step_id := add_step(v_job_id, 'Applying additional constraints: Automatically determining most recent child on which to apply constraints');
115118
END IF;
116119

117-
SELECT partition_tablename INTO v_last_partition FROM @[email protected]_partitions(v_parent_table, 'DESC') LIMIT 1;
120+
-- Loop through child tables starting from highest to get a value from the highest non-empty partition in the set
121+
-- Once a child table with a value is found, go back <optimize_constraint> children to make the constraint on that child
122+
FOR v_row_max_value IN
123+
SELECT partition_schemaname, partition_tablename FROM @[email protected]_partitions(p_parent_table, 'DESC', false)
124+
LOOP
125+
IF v_child_value IS NULL THEN
126+
EXECUTE format('SELECT %L::text FROM %I.%I LIMIT 1'
127+
, v_control
128+
, v_row_max_value.partition_schemaname
129+
, v_row_max_value.partition_tablename
130+
) INTO v_child_value;
118131

119-
IF v_control_type = 'time' OR (v_control_type = 'id' AND v_epoch <> 'none') THEN
120-
SELECT child_start_time INTO v_last_partition_timestamp FROM @[email protected]_partition_info(v_parent_schema||'.'||v_last_partition, v_partition_interval, v_parent_table);
121-
v_partition_suffix := to_char(v_last_partition_timestamp - (v_partition_interval::interval * (v_optimize_constraint + v_premake + 1) ), v_datetime_string);
122-
ELSIF v_control_type = 'id' THEN
123-
SELECT child_start_id INTO v_last_partition_id FROM @[email protected]_partition_info(v_parent_schema||'.'||v_last_partition, v_partition_interval, v_parent_table);
124-
v_partition_suffix := (v_last_partition_id - (v_partition_interval::bigint * (v_optimize_constraint + v_premake + 1) ))::text;
125-
END IF;
126-
127-
RAISE DEBUG 'apply_constraint: v_parent_tablename: %, v_last_partition: %, v_last_partition_timestamp: %, v_partition_suffix: %'
128-
, v_parent_tablename, v_last_partition, v_last_partition_timestamp, v_partition_suffix;
132+
ELSE
133+
v_optimize_counter := v_optimize_counter + 1;
134+
IF v_optimize_counter = v_optimize_constraint THEN
135+
v_child_tablename = v_row_max_value.partition_tablename;
136+
EXIT;
137+
END IF;
138+
END IF;
139+
END LOOP;
129140

130-
v_child_tablename := @[email protected]_name_length(v_parent_tablename, v_partition_suffix, TRUE);
141+
RAISE DEBUG 'apply_constraint: v_parent_tablename: %, v_last_partition: %, v_child_tablename: %, v_optimize_counter: %'
142+
, v_parent_tablename, v_last_partition, v_child_tablename, v_optimize_counter;
131143

132144
IF v_jobmon_schema IS NOT NULL THEN
133145
PERFORM update_step(v_step_id, 'OK', format('Target child table: %s.%s', v_parent_schema, v_child_tablename));

sql/functions/check_name_length.sql

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,17 @@ CREATE FUNCTION @[email protected]_name_length (
44
, p_table_partition boolean DEFAULT FALSE
55
)
66
RETURNS text
7-
LANGUAGE plpgsql IMMUTABLE SECURITY DEFINER
7+
LANGUAGE plpgsql IMMUTABLE
88
SET search_path TO pg_catalog, pg_temp
99
AS $$
1010
DECLARE
1111
v_new_name text;
1212
v_suffix text;
1313
BEGIN
1414
/*
15-
* Truncate the name of the given object if it is greater than the postgres default max (63 characters).
15+
* Truncate the name of the given object if it is greater than the postgres default max (63 bytes).
1616
* Also appends given suffix and schema if given and truncates the name so that the entire suffix will fit.
1717
* Returns original name (with suffix if given) if it doesn't require truncation
18-
* Retains SECURITY DEFINER since it is called by trigger functions and did not want to break installations prior to 4.0.0
1918
*/
2019

2120
IF p_table_partition IS TRUE AND (NULLIF(p_suffix, '') IS NULL) THEN

sql/functions/check_subpart_sameconfig.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ CREATE FUNCTION @[email protected]_subpart_sameconfig(p_parent_table text)
2222
, sub_default_table boolean
2323
, sub_maintenance_order int
2424
, sub_retention_keep_publication boolean
25+
, sub_control_not_null boolean
2526
)
2627
LANGUAGE sql STABLE
2728
SET search_path = @extschema@,pg_temp
@@ -74,6 +75,7 @@ AS $$
7475
, a.sub_default_table
7576
, a.sub_maintenance_order
7677
, a.sub_retention_keep_publication
78+
, a.sub_control_not_null
7779
FROM @[email protected]_config_sub a
7880
JOIN child_tables b on a.sub_parent = b.tablename;
7981
$$;

sql/functions/create_parent.sql

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ CREATE FUNCTION @[email protected]_parent(
1212
, p_template_table text DEFAULT NULL
1313
, p_jobmon boolean DEFAULT true
1414
, p_date_trunc_interval text DEFAULT NULL
15+
, p_control_not_null boolean DEFAULT true
1516
)
1617
RETURNS boolean
1718
LANGUAGE plpgsql
@@ -116,8 +117,10 @@ JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
116117
WHERE c.relname = v_parent_tablename::name
117118
AND n.nspname = v_parent_schema::name
118119
AND a.attname = p_control::name;
119-
IF (v_notnull = false OR v_notnull IS NULL) THEN
120-
RAISE EXCEPTION 'Control column given (%) for parent table (%) does not exist or must be set to NOT NULL', p_control, p_parent_table;
120+
IF (v_notnull IS NULL) THEN
121+
RAISE EXCEPTION 'Control column given (%) for parent table (%) does not exist', p_control, p_parent_table;
122+
ELSIF (v_notnull = false and p_control_not_null = true) THEN
123+
RAISE EXCEPTION 'Control column given (%) for parent table (%) must be set to NOT NULL', p_control, p_parent_table;
121124
END IF;
122125

123126
SELECT general_type, exact_type INTO v_control_type, v_control_exact_type
@@ -372,7 +375,6 @@ IF v_control_type = 'time' OR (v_control_type = 'id' AND p_epoch <> 'none') THEN
372375
, jobmon
373376
, template_table
374377
, inherit_privileges
375-
, default_table
376378
, date_trunc_interval)
377379
VALUES (
378380
p_parent_table
@@ -387,7 +389,6 @@ IF v_control_type = 'time' OR (v_control_type = 'id' AND p_epoch <> 'none') THEN
387389
, p_jobmon
388390
, v_template_schema||'.'||v_template_tablename
389391
, v_inherit_privileges
390-
, p_default_table
391392
, p_date_trunc_interval);
392393

393394
RAISE DEBUG 'create_parent: v_partition_time_array: %', v_partition_time_array;
@@ -524,7 +525,6 @@ IF v_control_type = 'id' AND p_epoch = 'none' THEN
524525
, jobmon
525526
, template_table
526527
, inherit_privileges
527-
, default_table
528528
, date_trunc_interval)
529529
VALUES (
530530
p_parent_table
@@ -537,7 +537,6 @@ IF v_control_type = 'id' AND p_epoch = 'none' THEN
537537
, p_jobmon
538538
, v_template_schema||'.'||v_template_tablename
539539
, v_inherit_privileges
540-
, p_default_table
541540
, p_date_trunc_interval);
542541

543542
v_last_partition_created := @[email protected]_partition_id(p_parent_table, v_partition_id_array);

sql/functions/create_partition_id.sql

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ FOREACH v_id IN ARRAY p_partition_ids LOOP
211211
, sub_default_table
212212
, sub_maintenance_order
213213
, sub_retention_keep_publication
214+
, sub_control_not_null
214215
FROM @[email protected]_config_sub
215216
WHERE sub_parent = p_parent_table
216217
LOOP
@@ -230,7 +231,8 @@ FOREACH v_id IN ARRAY p_partition_ids LOOP
230231
, p_template_table := %L
231232
, p_jobmon := %L
232233
, p_start_partition := %L
233-
, p_date_trunc_interval := %L )'
234+
, p_date_trunc_interval := %L
235+
, p_control_not_null := %L )'
234236
, v_parent_schema||'.'||v_partition_name
235237
, v_row.sub_control
236238
, v_row.sub_partition_type
@@ -243,7 +245,8 @@ FOREACH v_id IN ARRAY p_partition_ids LOOP
243245
, v_row.sub_template_table
244246
, v_row.sub_jobmon
245247
, p_start_partition
246-
, v_row.sub_date_trunc_interval);
248+
, v_row.sub_date_trunc_interval
249+
, v_row.sub_control_not_null);
247250
RAISE DEBUG 'create_partition_id (create_parent loop): %', v_sql;
248251
EXECUTE v_sql;
249252

sql/functions/create_partition_time.sql

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ FOREACH v_time IN ARRAY p_partition_times LOOP
302302
, sub_default_table
303303
, sub_maintenance_order
304304
, sub_retention_keep_publication
305+
, sub_control_not_null
305306
FROM @[email protected]_config_sub
306307
WHERE sub_parent = p_parent_table
307308
LOOP
@@ -321,7 +322,8 @@ FOREACH v_time IN ARRAY p_partition_times LOOP
321322
, p_template_table := %L
322323
, p_jobmon := %L
323324
, p_start_partition := %L
324-
, p_date_trunc_interval := %L )'
325+
, p_date_trunc_interval := %L
326+
, p_control_not_null := %L )'
325327
, v_parent_schema||'.'||v_partition_name
326328
, v_row.sub_control
327329
, v_row.sub_partition_interval
@@ -334,7 +336,8 @@ FOREACH v_time IN ARRAY p_partition_times LOOP
334336
, v_row.sub_template_table
335337
, v_row.sub_jobmon
336338
, p_start_partition
337-
, v_row.sub_date_trunc_interval);
339+
, v_row.sub_date_trunc_interval
340+
, v_row.sub_control_not_null);
338341

339342
RAISE DEBUG 'create_partition_time (create_parent loop): %', v_sql;
340343
EXECUTE v_sql;

sql/functions/create_sub_parent.sql

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ CREATE FUNCTION @[email protected]_sub_parent(
1111
, p_epoch text DEFAULT 'none'
1212
, p_jobmon boolean DEFAULT true
1313
, p_date_trunc_interval text DEFAULT NULL
14+
, p_control_not_null boolean DEFAULT true
1415
)
1516
RETURNS boolean
1617
LANGUAGE plpgsql
@@ -86,7 +87,8 @@ INSERT INTO @[email protected]_config_sub (
8687
, sub_epoch
8788
, sub_jobmon
8889
, sub_template_table
89-
, sub_date_trunc_interval)
90+
, sub_date_trunc_interval
91+
, sub_control_not_null)
9092
VALUES (
9193
p_top_parent
9294
, p_control
@@ -99,7 +101,8 @@ VALUES (
99101
, p_epoch
100102
, p_jobmon
101103
, v_template_table
102-
, p_date_trunc_interval);
104+
, p_date_trunc_interval
105+
, p_control_not_null);
103106

104107
FOR v_row IN
105108
-- Loop through all current children to turn them into partitioned tables
@@ -190,7 +193,8 @@ IF v_recreate_child = false THEN
190193
, p_epoch := %L
191194
, p_template_table := %L
192195
, p_jobmon := %L
193-
, p_date_trunc_interval := %L)'
196+
, p_date_trunc_interval := %L
197+
, p_control_not_null := %L)'
194198
, v_row.child_schema||'.'||v_row.child_tablename
195199
, p_control
196200
, p_interval
@@ -203,7 +207,8 @@ IF v_recreate_child = false THEN
203207
, p_epoch
204208
, v_template_table
205209
, p_jobmon
206-
, p_date_trunc_interval);
210+
, p_date_trunc_interval
211+
, p_control_not_null);
207212
RAISE DEBUG 'create_sub_parent: create parent v_sql: %', v_sql;
208213
EXECUTE v_sql;
209214
END IF; -- end recreate check

0 commit comments

Comments
 (0)