Partition trigger and serial column concurrence I'm using the following trigger to auto generate monthly partitions for a given table. It works fine.

create or replace function beat_insert_function()
returns trigger as $$

declare
  partition_date text;
  partition_name text;
  start_of_month text;
  end_of_next_month text;

begin
  partition_date := to_char(new.created_at, 'yyyy_mm');
  partition_name := 'beat_' || partition_date;
  start_of_month := to_char((new.created_at), 'yyyy-mm') || '-01';
  end_of_next_month := to_char((new.created_at + interval '1 month'), 'yyyy-mm') || '-01';

  if not exists (select 1 from information_schema.tables where table_name = partition_name) then
    raise notice 'A partition has been created %', partition_name;
    execute format(E'create table %I (check(date_trunc(''day'', created_at) &gt;= ''%s'' and date_trunc(''day'', created_at) &lt; ''%s'')) inherits (public.beat)', partition_name, start_of_month, end_of_next_month);
  end if;

  --- this generates only par keys
  execute format('insert into %I (something) values ($1)', partition_name) using new.something;

  return null;
end

$$
language plpgsql;


This trigger is configured to run before insert, like so:

create trigger beat_insert_trigger
before insert on beat
for each row execute procedure beat_insert_function();


Because the trigger intercepts each insert and the master table contains a id serial column primary key, I ended with only par keys (2, 4, 6, 8, etc), so I changed the insert to:

  execute format('insert into %I (id_beat, created_at) values (currval(''beat_id_beat_seq''), $1)', partition_name) using new.created_at;


Now, the primary key is correct (1, 2, 3, 4, etc)...

My question is: is it safe to use currval in the given scenario? Can the table receive another insert before the trigger finishes, thus creating an insert error, or will the session prevent this from happening?
Your code is safe, because according to the documentation:


  Because this is returning a session-local value, it gives a predictable answer whether or not other sessions have executed nextval since the current session did.


But why don't you do the natural thing and

EXECUTE format(
           'insert into %I (id_beat, created_at) values ($1, $2)',
           partition_name)
USING NEW.id_beat, NEW.created_at;