io.ebeaninternal.dbmigration.builtin-extra-ddl-partitioning.xml Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ebean-ddlgen Show documentation
Show all versions of ebean-ddlgen Show documentation
DDL and DB Migration generation
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <extra-ddl xmlns="http://ebean-orm.github.io/xml/ns/extraddl"> <ddl-script name="partition help" init="true" platforms="postgres"> -- partitioning helper functions (UTC based) ------------------------------------------------------------------------------------ -- Type: partition_meta -- -- Type used to hold common partitioning parameters such as period start and end etc ------------------------------------------------------------------------------------ do $$ begin if not exists (select 1 from pg_type where typname = 'partition_meta') THEN create type partition_meta as ( period_start timestamptz, period_end timestamptz, period_name text, base_name text, part_name text ); end if; end$$; ------------------------------------------------------------------------------------ -- Function: _partition_create -- -- Internal helper method to create a partition given meta data ------------------------------------------------------------------------------------ create or replace function _partition_create(meta partition_meta) returns text language plpgsql set timezone to 'UTC' as $$ 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); return meta.part_name; end; $$; ------------------------------------------------------------------------------------ -- Function: _partition_meta -- -- Internal helper method to create and return meta data used to create a partition. -- Helps work out start and end periods for day, week, month and year partitions. ------------------------------------------------------------------------------------ create or replace function _partition_meta( mode text, asOf date, baseName text) returns partition_meta language plpgsql set timezone to 'UTC' as $$ declare partName text; meta partition_meta; asOfUtc timestamptz; begin asOfUtc = timezone('utc', asOf); if (mode = 'day') then asOfUtc = date_trunc('day', asOfUtc); partName = to_char(asOfUtc, 'YYYY_MM_DD'); select asOfUtc, asOfUtc + interval '1 days' into meta.period_start, meta.period_end; elseif (mode = 'week') then asOfUtc = date_trunc('week', asOfUtc); partName = format('%s_w%s', extract(ISOYEAR FROM asOfUtc), extract(WEEK FROM asOfUtc)); select asOfUtc, asOfUtc + interval '7 days' into meta.period_start, meta.period_end; elseif (mode = 'year') then asOfUtc = date_trunc('year', asOfUtc); partName = to_char(date_trunc('year', asOfUtc), 'YYYY'); select asOfUtc, asOfUtc + interval '1 year' into meta.period_start, meta.period_end; else asOfUtc = date_trunc('month', asOfUtc); partName = to_char(asOfUtc, 'YYYY_MM'); select asOfUtc, asOfUtc + interval '1 month' into meta.period_start, meta.period_end; end if; select partName, baseName, format('%s_%s', baseName, partName) into meta.period_name, meta.base_name, meta.part_name; return meta; end; $$; ------------------------------------------------------------------------------------ -- Function: _partition_over -- -- Internal helper method to return a set/table of dates to ensure partitions exists for. -- Typically we want to ensure some future partitions exist and this helps return dates -- for which we loop to create partitions. ------------------------------------------------------------------------------------ create or replace function _partition_over( mode text, fromDate date default current_date, _count integer default 0) returns TABLE(of_date date) language plpgsql as $$ declare endDate date; begin if (mode = 'day') then endDate = fromDate + (interval '1 day' * _count); fromDate = fromDate - interval '1 day'; -- allow for timezone return query select s::date from generate_series(fromDate, endDate, '1 day') s; elseif (mode = 'week') then fromDate = date_trunc('week', fromDate); endDate = fromDate + (interval '1 week' * _count); return query select s::date from generate_series(fromDate, endDate, '1 week') s; elseif (mode = 'year') then fromDate = date_trunc('year', fromDate); endDate = fromDate + (interval '1 year' * _count); return query select s::date from generate_series(fromDate, endDate, '1 year') s; else fromDate = date_trunc('month', fromDate); endDate = fromDate + (interval '1 month' * _count); return query select s::date from generate_series(fromDate, endDate, '1 month') s; end if; end; $$; ------------------------------------------------------------------------------------ -- Function: partition -- -- Helper to ensure we create partitions into the future as needed for day, week, month -- and year based partitioning. Typically we call this periodically (e.g. every day). -- -- Examples: -- -- 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 partitionCount integer default 0, -- number of additional partitions 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)) from _partition_over(mode, fromDate, partitionCount) poDate; return 'done'; end; $$; ------------------------------------------------------------------------------------ -- Function: partition_init -- -- Similar to partition but allows the first partition to be bigger with an explicit -- initDate typically to allow back dated rows to go into the initial partition. -- -- Examples: -- -- 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 partitionCount integer default 0, -- number of additional partitions fromDate date default current_date) -- date to create first partition for returns text language plpgsql set timezone to 'UTC' as $$ declare meta partition_meta; begin -- override the period start for the first partition meta = _partition_meta(mode, fromDate, baseName); meta.period_start = initDate; perform _partition_create(meta); if (partitionCount > 0) then -- 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; return 'done'; end; $$; </ddl-script> </extra-ddl>