upsert with trigger (or rule)

From: "Maeldron T(dot)" <maeldron(at)gmail(dot)com>
To: pgsql-general(at)postgresql(dot)org
Subject: upsert with trigger (or rule)
Date: 2016-07-19 18:56:46
Message-ID: d05720f4-2d44-e425-ebec-33020ce7f20e@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Hello,

I’m trying to rewrite inserts to upserts on a table when a certain
column has a certain value. Reason: the inserts are coming from an ORM.
It’s possible to send upsert from the ORM, however, in this case I find
it more elegant and future-proof to deal with it at the DB level.

First attempt:

create rule messages_insert_draft as on insert to messages where
new.is_draft do instead insert into messages values (new.*) on conflict
(sender_id, recipient_id) where is_draft do update set body =
excluded.body, updated_at = excluded.updated_at;

This has two disadvantages:

1. It doesnt work because of the endless recursion. Is there a way to
deal with the recursion without adding another column to the table?
2. Every time the table’s sctructure changes the rule has to be updated too.

With trigger:

create function trigger_messages_insert_draft() returns trigger as $$

begin

insert into messages values (new.*) on conflict (sender_id,
recipient_id) where is_draft do update set body = excluded.body,
updated_at = excluded.updated_at;

return null;

end;

$$ language plpgsql;


create trigger messages_before_insert_draft before insert on messages
for each row when ( new.is_draft and pg_trigger_depth() = 0 ) execute
procedure trigger_messages_insert_draft();

This works fine. As far as I see adding new columns to messages table
won’t require updating the procedure. Which is great.

There is one issue though. The orm sends 'insert into messages ....
returning id'. As the original insert is skipped, the id, which is a
serial, is not returned, so the orm can’t see the new/updated record's id.

Is there a way to make the 'returning id' part work?

M.

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Adrian Klaver 2016-07-19 19:27:10 Re: upsert with trigger (or rule)
Previous Message Tom Lane 2016-07-19 14:27:49 Re: Constraint using a SQL function executed during SELECT