#1881 - Update Postgres init helper procedures for DB table partitions

This commit is contained in:
rob bygrave
2019-12-04 22:07:05 +13:00
parent 4cc9278183
commit 89c05007c2
@@ -18,9 +18,7 @@ begin
period_end timestamptz,
period_name text,
base_name text,
part_name text,
unique_column text,
index_column text
part_name text
);
end if;
end$$;
@@ -28,38 +26,15 @@ end$$;
------------------------------------------------------------------------------------
-- Function: _partition_create
--
-- Internal helper method to create a partition given meta data and
-- optional extra function to call (typically to create additional indexes)
-- Internal helper method to create a partition given meta data
------------------------------------------------------------------------------------
create or replace function _partition_create(meta partition_meta, extra text)
create or replace function _partition_create(meta partition_meta)
returns text
language plpgsql
set timezone to 'UTC'
as $$
declare
idx_col text;
idx_name text;
begin
execute format('create table if not exists %I partition of %I for values from (''%s'') TO (''%s'')', meta.part_name, meta.base_name, meta.period_start, meta.period_end);
if (length(meta.unique_column) > 0) then
execute format('create unique index if not exists uq_%I ON %I (%I)', meta.part_name, meta.part_name, meta.unique_column);
end if;
if (length(meta.index_column) > 0) then
-- delimited for multiple indexes
foreach idx_col in array regexp_split_to_array(meta.index_column,';')
loop
idx_name = replace(idx_col, ',', '_');
execute format('create index if not exists ix_%I_%s ON %I (%s)', meta.part_name, idx_name, meta.part_name, idx_col);
end loop;
end if;
if (length(extra) > 0) then
execute 'select ' || extra || '($1)' using meta;
end if;
return meta.part_name;
end;
$$;
@@ -74,9 +49,7 @@ $$;
create or replace function _partition_meta(
mode text,
asOf date,
baseName text,
uniqueColumn text,
indexColumn text)
baseName text)
returns partition_meta
language plpgsql
set timezone to 'UTC'
@@ -108,29 +81,13 @@ begin
select asOfUtc, asOfUtc + interval '1 month' into meta.period_start, meta.period_end;
end if;
select partName, baseName, format('%s_%s', baseName, partName), uniqueColumn, indexColumn
into meta.period_name, meta.base_name, meta.part_name, meta.unique_column, meta.index_column;
select partName, baseName, format('%s_%s', baseName, partName)
into meta.period_name, meta.base_name, meta.part_name;
return meta;
end;
$$;
create or replace function _partition_meta_initdate(
meta partition_meta,
initDate date)
returns partition_meta
language plpgsql
set timezone to 'UTC'
as $$
begin
meta.period_start = initDate;
return meta;
end;
$$;
-- select _partition_over('week', current_date, 4);
------------------------------------------------------------------------------------
-- Function: _partition_over
--
@@ -180,24 +137,21 @@ $$;
--
-- Examples:
--
-- select partition('week', 'trip', 'id', 'when_started', 4);
-- select partition('month', 'event', 'id', 'event_timestamp', 1);
-- select partition('week', 'trip', 4);
-- select partition('month', 'event', 1);
--
------------------------------------------------------------------------------------
create or replace function partition(
mode text, -- one of 'day','week','month','year'
baseName text, -- base table name
uniqueColumn text, -- optional unique column
indexColumn text, -- optional column to index
partitionCount integer default 0, -- number of additional partitions
fromDate date default current_date, -- date to create first partition for
extra text default '') -- custom function to call per partition
fromDate date default current_date) -- date to create first partition for
returns text
language plpgsql
set timezone to 'UTC'
as $$
begin
perform _partition_create(_partition_meta(mode, poDate, baseName, uniqueColumn, indexColumn), extra)
perform _partition_create(_partition_meta(mode, poDate, baseName))
from _partition_over(mode, fromDate, partitionCount) poDate;
return 'done';
end;
@@ -212,18 +166,15 @@ $$;
--
-- Examples:
--
-- select partition_init(date '2001-01-01', 'week', 'event', 'id', 'event_timestamp', 4);
-- select partition_init(date '2001-01-01', 'week', 'event');
--
------------------------------------------------------------------------------------
create or replace function partition_init(
initDate date, -- first partition period start date
mode text, -- one of 'day','week','month','year'
baseName text, -- base table name
uniqueColumn text, -- optional unique column
indexColumn text, -- optional column to index
partitionCount integer default 0, -- number of additional partitions
fromDate date default current_date, -- date to create first partition for
extra text default '') -- custom function to call per partition
fromDate date default current_date) -- date to create first partition for
returns text
language plpgsql
set timezone to 'UTC'
@@ -232,13 +183,14 @@ declare
meta partition_meta;
begin
-- override the period start for the first partition
meta = _partition_meta(mode, fromDate, baseName, uniqueColumn, indexColumn);
meta = _partition_meta_initdate(meta, initDate);
perform _partition_create(meta, extra);
meta = _partition_meta(mode, fromDate, baseName);
meta.period_start = initDate;
perform _partition_create(meta);
if (partitionCount > 0) then
-- create additional migrations normally
perform _partition_create(_partition_meta(mode, poDate, baseName, uniqueColumn, indexColumn), extra)
-- create additional partitions normally
fromDate = fromDate + interval '1 day';
perform _partition_create(_partition_meta(mode, poDate, baseName))
from _partition_over(mode, fromDate, partitionCount) poDate;
end if;