Re: upsert with trigger (or rule)
От | Adrian Klaver |
---|---|
Тема | Re: upsert with trigger (or rule) |
Дата | |
Msg-id | 490dc766-b7fe-edf6-ec84-31bd8810b166@aklaver.com обсуждение исходный текст |
Ответ на | upsert with trigger (or rule) ("Maeldron T." <maeldron@gmail.com>) |
Ответы |
Re: upsert with trigger (or rule)
|
Список | pgsql-general |
On 07/19/2016 11:56 AM, Maeldron T. wrote: > 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(); By returning NULL in your function you are skipping the original INSERT. I am sure exactly what you are trying to achieve, but it would seem the thing to is check for the uniqueness of (sender_id, recipient_id) in your function and then modify the original INSERT row as needed and then RETURN it as NEW. > > 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? Not that I know of: https://www.postgresql.org/docs/9.5/static/plpgsql-trigger.html "A trigger function must return either NULL or a record/row value having exactly the structure of the table the trigger was fired for." > > M. > > > -- Adrian Klaver adrian.klaver@aklaver.com
В списке pgsql-general по дате отправления: