create or replace
function partition_insert_trigger() returns trigger
language 'plpgsql' as $$
declare
    column_name text := TG_ARGV[0];
    columnt_format text := TG_ARGV[1];
    column_value timestamp;
    table_name text;
    insert_stmt_tpl text := 'insert into %I select ($1).*';
    insert_stmt text;
    create_table_tpl text := '
create table {table_name} (
    like {base_table_name} including all
);
alter table {table_name} inherit {base_table_name};
';
begin
    execute format('select $1.%s', column_name) using NEW into column_value;
    -- TODO: move
    table_name := format('%s_%s', TG_TABLE_NAME, to_char(column_value, columnt_format));
    insert_stmt = format(insert_stmt_tpl, table_name);
    begin
        execute format(insert_stmt_tpl, table_name) using new;
    exception
        when undefined_table then
            begin
                execute replace(replace(create_table_tpl,
                    '{table_name}', table_name),
                    '{base_table_name}', TG_TABLE_NAME);
            exception
                when duplicate_table then -- ignore
            end;
            execute insert_stmt using new;
    end;
    return NEW;
end;
$$;


create or replace
function init_partition(table_name text, column_name text, partition_interval text) returns void
language 'plpgsql' as $$
declare
    columnt_format text;
    query_tpl text := '
create trigger on_inserted_{table_name}
before insert on {table_name}
for each row
    execute procedure partition_insert_trigger(''{column_name}'', ''{columnt_format}'');';
begin
    CASE
        WHEN partition_interval = 'monthly' THEN
            columnt_format = '"y"yy_"m"mm';
        WHEN partition_interval = 'weekly' THEN
            columnt_format = '"y"yy_"m"mm_"w"w';
        WHEN partition_interval = 'daily' THEN
            columnt_format = '"y"yy_"m"mm_"d"dd';
        WHEN partition_interval = 'hourly' THEN
            columnt_format = '"y"yy_"m"mm_"d"dd_"h"hh24';
        ELSE
            RAISE EXCEPTION 'Must use a predefined time interval: monthly, weekly, daily, hourly.';
    END CASE;

    execute replace(replace(replace(query_tpl,
            '{table_name}', table_name),
            '{column_name}', column_name),
            '{columnt_format}', columnt_format);
end;
$$;
