diff --git a/src/backend/distributed/sql/citus--12.1-1--13.0-1.sql b/src/backend/distributed/sql/citus--12.1-1--13.0-1.sql index 216171664..b19ddfb75 100644 --- a/src/backend/distributed/sql/citus--12.1-1--13.0-1.sql +++ b/src/backend/distributed/sql/citus--12.1-1--13.0-1.sql @@ -2,3 +2,4 @@ -- bump version to 13.0-1 #include "udfs/citus_prepare_pg_upgrade/13.0-1.sql" +#include "udfs/create_time_partitions/13.0-1.sql" diff --git a/src/backend/distributed/sql/downgrades/citus--13.0-1--12.1-1.sql b/src/backend/distributed/sql/downgrades/citus--13.0-1--12.1-1.sql index 006349990..681ec6e82 100644 --- a/src/backend/distributed/sql/downgrades/citus--13.0-1--12.1-1.sql +++ b/src/backend/distributed/sql/downgrades/citus--13.0-1--12.1-1.sql @@ -1,2 +1,4 @@ -- citus--13.0-1--12.1-1 -- this is an empty downgrade path since citus--12.1-1--13.0-1.sql is empty + +#include "../udfs/create_time_partitions/10.2-1.sql" diff --git a/src/backend/distributed/sql/udfs/create_time_partitions/13.0-1.sql b/src/backend/distributed/sql/udfs/create_time_partitions/13.0-1.sql new file mode 100644 index 000000000..566ba7163 --- /dev/null +++ b/src/backend/distributed/sql/udfs/create_time_partitions/13.0-1.sql @@ -0,0 +1,58 @@ +CREATE OR REPLACE FUNCTION pg_catalog.create_time_partitions( + table_name regclass, + partition_interval INTERVAL, + end_at timestamptz, + start_from timestamptz DEFAULT now()) +returns boolean +LANGUAGE plpgsql +AS $$ +DECLARE + -- partitioned table name + schema_name_text name; + table_name_text name; + + -- record for to-be-created partition + missing_partition_record record; + + -- result indiciates whether any partitions were created + partition_created bool := false; +BEGIN + IF start_from >= end_at THEN + RAISE 'start_from (%) must be older than end_at (%)', start_from, end_at; + END IF; + + IF NOT isfinite(partition_interval) THEN + RAISE 'Partition interval must be a finite value'; + END IF; + + SELECT nspname, relname + INTO schema_name_text, table_name_text + FROM pg_class JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid + WHERE pg_class.oid = table_name::oid; + + -- Get missing partition range info using the get_missing_partition_ranges + -- and create partitions using that info. + FOR missing_partition_record IN + SELECT * + FROM get_missing_time_partition_ranges(table_name, partition_interval, end_at, start_from) + LOOP + EXECUTE format('CREATE TABLE %I.%I PARTITION OF %I.%I FOR VALUES FROM (%L) TO (%L)', + schema_name_text, + missing_partition_record.partition_name, + schema_name_text, + table_name_text, + missing_partition_record.range_from_value, + missing_partition_record.range_to_value); + + partition_created := true; + END LOOP; + + RETURN partition_created; +END; +$$; +COMMENT ON FUNCTION pg_catalog.create_time_partitions( + table_name regclass, + partition_interval INTERVAL, + end_at timestamptz, + start_from timestamptz) +IS 'create time partitions for the given range'; diff --git a/src/backend/distributed/sql/udfs/create_time_partitions/latest.sql b/src/backend/distributed/sql/udfs/create_time_partitions/latest.sql index 11edcc5ac..566ba7163 100644 --- a/src/backend/distributed/sql/udfs/create_time_partitions/latest.sql +++ b/src/backend/distributed/sql/udfs/create_time_partitions/latest.sql @@ -21,6 +21,10 @@ BEGIN RAISE 'start_from (%) must be older than end_at (%)', start_from, end_at; END IF; + IF NOT isfinite(partition_interval) THEN + RAISE 'Partition interval must be a finite value'; + END IF; + SELECT nspname, relname INTO schema_name_text, table_name_text FROM pg_class JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid diff --git a/src/test/regress/expected/pg17.out b/src/test/regress/expected/pg17.out index ff1e57d74..1141efef0 100644 --- a/src/test/regress/expected/pg17.out +++ b/src/test/regress/expected/pg17.out @@ -1453,6 +1453,21 @@ ROLLBACK; NOTICE: issuing ROLLBACK DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -- End of Testing AT LOCAL option +-- interval can have infinite values +-- Relevant PG17 commit: https://github.com/postgres/postgres/commit/519fc1bd9 +-- disallow those in create_time_partitions +-- test create_time_partitions with infinity values +CREATE TABLE date_partitioned_table( + measureid integer, + eventdate date, + measure_data jsonb) PARTITION BY RANGE(eventdate); +SELECT create_time_partitions('date_partitioned_table', INTERVAL 'infinity', '2022-01-01', '2021-01-01'); +ERROR: Partition interval must be a finite value +CONTEXT: PL/pgSQL function create_time_partitions(regclass,interval,timestamp with time zone,timestamp with time zone) line XX at RAISE +SELECT create_time_partitions('date_partitioned_table', INTERVAL '-infinity', '2022-01-01', '2021-01-01'); +ERROR: Partition interval must be a finite value +CONTEXT: PL/pgSQL function create_time_partitions(regclass,interval,timestamp with time zone,timestamp with time zone) line XX at RAISE +-- end of testing interval with infinite values \set VERBOSITY terse SET client_min_messages TO WARNING; DROP SCHEMA pg17 CASCADE; diff --git a/src/test/regress/sql/pg17.sql b/src/test/regress/sql/pg17.sql index fd3a6ddfd..888a0463c 100644 --- a/src/test/regress/sql/pg17.sql +++ b/src/test/regress/sql/pg17.sql @@ -797,6 +797,21 @@ ROLLBACK; -- End of Testing AT LOCAL option +-- interval can have infinite values +-- Relevant PG17 commit: https://github.com/postgres/postgres/commit/519fc1bd9 +-- disallow those in create_time_partitions + +-- test create_time_partitions with infinity values +CREATE TABLE date_partitioned_table( + measureid integer, + eventdate date, + measure_data jsonb) PARTITION BY RANGE(eventdate); + +SELECT create_time_partitions('date_partitioned_table', INTERVAL 'infinity', '2022-01-01', '2021-01-01'); +SELECT create_time_partitions('date_partitioned_table', INTERVAL '-infinity', '2022-01-01', '2021-01-01'); + +-- end of testing interval with infinite values + \set VERBOSITY terse SET client_min_messages TO WARNING; DROP SCHEMA pg17 CASCADE;