Skip to content

Commit c24588c

Browse files
committed
incorporate issue 660. remove superuser requirement
1 parent 98c57d2 commit c24588c

File tree

4 files changed

+61
-13
lines changed

4 files changed

+61
-13
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
=====
44
NEW FEATURES
55
------------
6-
- Add support for microsecond precisions in epoch partitioning (Github PR #659)
6+
- 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)
8+
- 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
79

810

911
5.1.0

pg_partman.control

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

sql/functions/run_maintenance.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ ex_message text;
1616
v_adv_lock boolean;
1717
v_analyze boolean := FALSE;
1818
v_check_subpart int;
19+
v_child_timestamp timestamptz;
1920
v_control_type text;
2021
v_create_count int := 0;
2122
v_current_partition_id bigint;
@@ -33,7 +34,6 @@ v_last_partition_timestamp timestamptz;
3334
v_max_id bigint;
3435
v_max_id_default bigint;
3536
v_max_time_default timestamptz;
36-
v_child_timestamp timestamptz;
3737
v_new_search_path text;
3838
v_next_partition_id bigint;
3939
v_next_partition_timestamp timestamptz;

updates/pg_partman--5.1.0--5.2.0.sql

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,7 +1459,6 @@ END
14591459
$$;
14601460

14611461

1462-
14631462
CREATE OR REPLACE FUNCTION @[email protected]_maintenance(
14641463
p_parent_table text DEFAULT NULL
14651464
-- If these defaults change reflect them in `run_maintenance_proc`!
@@ -1478,6 +1477,7 @@ ex_message text;
14781477
v_adv_lock boolean;
14791478
v_analyze boolean := FALSE;
14801479
v_check_subpart int;
1480+
v_child_timestamp timestamptz;
14811481
v_control_type text;
14821482
v_create_count int := 0;
14831483
v_current_partition_id bigint;
@@ -1495,7 +1495,6 @@ v_last_partition_timestamp timestamptz;
14951495
v_max_id bigint;
14961496
v_max_id_default bigint;
14971497
v_max_time_default timestamptz;
1498-
v_max_timestamp timestamptz;
14991498
v_new_search_path text;
15001499
v_next_partition_id bigint;
15011500
v_next_partition_timestamp timestamptz;
@@ -1681,31 +1680,31 @@ LOOP
16811680
-- Must be reset to null otherwise if the next partition set in the loop is empty, the previous partition set's value could be used
16821681
v_current_partition_timestamp := NULL;
16831682

1684-
-- Loop through child tables starting from highest to get current max value in partition set
1683+
-- Loop through child tables starting from highest to get a timestamp from the highest non-empty partition in the set
16851684
-- Avoids doing a scan on entire partition set and/or getting any values accidentally in default.
16861685
FOR v_row_max_time IN
16871686
SELECT partition_schemaname, partition_tablename FROM @[email protected]_partitions(v_row.parent_table, 'DESC', false)
16881687
LOOP
1689-
EXECUTE format('SELECT max(%s)::text FROM %I.%I'
1688+
EXECUTE format('SELECT %s::text FROM %I.%I LIMIT 1'
16901689
, v_partition_expression
16911690
, v_row_max_time.partition_schemaname
16921691
, v_row_max_time.partition_tablename
1693-
) INTO v_max_timestamp;
1692+
) INTO v_child_timestamp;
16941693

1695-
IF v_row.infinite_time_partitions AND v_max_timestamp < CURRENT_TIMESTAMP THEN
1694+
IF v_row.infinite_time_partitions AND v_child_timestamp < CURRENT_TIMESTAMP THEN
16961695
-- No new data has been inserted relative to "now", but keep making child tables anyway
16971696
v_current_partition_timestamp = CURRENT_TIMESTAMP;
16981697
-- Nothing else to do in this case so just end early
16991698
EXIT;
17001699
END IF;
1701-
IF v_max_timestamp IS NOT NULL THEN
1702-
SELECT suffix_timestamp INTO v_current_partition_timestamp FROM @[email protected]_partition_name(v_row.parent_table, v_max_timestamp::text);
1700+
IF v_child_timestamp IS NOT NULL THEN
1701+
SELECT suffix_timestamp INTO v_current_partition_timestamp FROM @[email protected]_partition_name(v_row.parent_table, v_child_timestamp::text);
17031702
EXIT;
17041703
END IF;
17051704
END LOOP;
1706-
IF v_row.infinite_time_partitions AND v_max_timestamp IS NULL THEN
1705+
IF v_row.infinite_time_partitions AND v_child_timestamp IS NULL THEN
17071706
-- If partition set is completely empty, still keep making child tables anyway
1708-
-- Has to be separate check outside above loop since "future" tables are likely going to be empty and make max value in that loop NULL
1707+
-- Has to be separate check outside above loop since "future" tables are likely going to be empty, hence ignored in that loop
17091708
v_current_partition_timestamp = CURRENT_TIMESTAMP;
17101709
END IF;
17111710

@@ -1725,7 +1724,7 @@ LOOP
17251724
UPDATE @[email protected]_config SET maintenance_last_run = clock_timestamp() WHERE parent_table = v_row.parent_table;
17261725
CONTINUE;
17271726
END IF;
1728-
RAISE DEBUG 'run_maint: v_max_timestamp: %, v_current_partition_timestamp: %, v_max_time_default: %', v_max_timestamp, v_current_partition_timestamp, v_max_time_default;
1727+
RAISE DEBUG 'run_maint: v_child_timestamp: %, v_current_partition_timestamp: %, v_max_time_default: %', v_child_timestamp, v_current_partition_timestamp, v_max_time_default;
17291728
IF v_current_partition_timestamp IS NULL OR (v_max_time_default > v_current_partition_timestamp) THEN
17301729
SELECT suffix_timestamp INTO v_current_partition_timestamp FROM @[email protected]_partition_name(v_row.parent_table, v_max_time_default::text);
17311730
END IF;
@@ -1915,3 +1914,49 @@ DETAIL: %
19151914
HINT: %', ex_message, ex_context, ex_detail, ex_hint;
19161915
END
19171916
$$;
1917+
1918+
1919+
CREATE OR REPLACE FUNCTION @[email protected]_name_length (
1920+
p_object_name text
1921+
, p_suffix text DEFAULT NULL
1922+
, p_table_partition boolean DEFAULT FALSE
1923+
)
1924+
RETURNS text
1925+
LANGUAGE plpgsql IMMUTABLE
1926+
SET search_path TO pg_catalog, pg_temp
1927+
AS $$
1928+
DECLARE
1929+
v_new_name text;
1930+
v_suffix text;
1931+
BEGIN
1932+
/*
1933+
* Truncate the name of the given object if it is greater than the postgres default max (63 bytes).
1934+
* Also appends given suffix and schema if given and truncates the name so that the entire suffix will fit.
1935+
* Returns original name (with suffix if given) if it doesn't require truncation
1936+
*/
1937+
1938+
IF p_table_partition IS TRUE AND (NULLIF(p_suffix, '') IS NULL) THEN
1939+
RAISE EXCEPTION 'Table partition name requires a suffix value';
1940+
END IF;
1941+
1942+
1943+
v_suffix := format('%s%s', CASE WHEN p_table_partition THEN '_p' END, p_suffix);
1944+
-- Use optimistic behavior: in almost all cases `v_new_name` will be less than allowed maximum.
1945+
-- Do "heavy" work only in rare cases.
1946+
v_new_name := p_object_name || v_suffix;
1947+
1948+
-- Postgres' relation name limit is in bytes, not characters; also it can be compiled with bigger allowed length.
1949+
-- Use its internals to detect where to cut new object name.
1950+
IF v_new_name::name != v_new_name THEN
1951+
-- Here we need to detect how many chars (not bytes) we need to get from the `p_object_name`.
1952+
-- Use suffix as prefix and get the rest of `p_object_name`.
1953+
v_new_name := (v_suffix || p_object_name)::name;
1954+
-- `substr` starts from 1, that is why we need to add 1 below.
1955+
-- Edge case: `v_suffix` is empty, length is 0, but need to start from 1.
1956+
v_new_name := substr(v_new_name, length(v_suffix) + 1) || v_suffix;
1957+
END IF;
1958+
1959+
RETURN v_new_name;
1960+
1961+
END
1962+
$$;

0 commit comments

Comments
 (0)