
create table t (
  id numeric(10) primary key,
  dat varchar(100)
);

create language plpgsql;

create or replace function ins(
  a_id t.id%TYPE,
  a_dat t.dat%TYPE
) returns integer as
$$
declare
begin
  begin
    insert into t (id, dat) values (a_id, a_dat);
  exception
    when unique_violation then
      update t set dat = a_dat where id = a_id;
      return 0;
    when others then
      raise;
  end;

  return 1;
end;
$$ language plpgsql;

/* now do in separate sessions */

/* session 1 */
begin;
select ins(1, 'a');
commit;

begin;
select ins(2, 'a');
rollback;

/* session 2 */
begin;
select ins(1, 'b');
commit;

begin;
select ins(2, 'b');
commit;
