Re: INSERT ... ON CONFLICT {UPDATE | IGNORE}

From: Peter Geoghegan <pg(at)heroku(dot)com>
To: Simon Riggs <simon(at)2ndquadrant(dot)com>
Cc: Bruce Momjian <bruce(at)momjian(dot)us>, Josh Berkus <josh(at)agliodbs(dot)com>, Kevin Grittner <kgrittn(at)ymail(dot)com>, Andres Freund <andres(at)2ndquadrant(dot)com>, Heikki Linnakangas <hlinnakangas(at)vmware(dot)com>, Pg Hackers <pgsql-hackers(at)postgresql(dot)org>, Craig Ringer <craig(at)2ndquadrant(dot)com>
Subject: Re: INSERT ... ON CONFLICT {UPDATE | IGNORE}
Date: 2014-10-09 08:11:18
Message-ID: CAM3SWZS4RfZNCbG5DHZGqQxUcjazX+uWSnXsN1y9Xc_yzcmMGA@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Thu, Oct 9, 2014 at 12:38 AM, Simon Riggs <simon(at)2ndquadrant(dot)com> wrote:
> Do not use CONFLICTING() which looks like it is a function.

So is ROW(). Or COALESCE().

> Instead, use a row qualifier, such as NEW, OLD etc to reference values
> from the incoming data
> e.g. CONFLICTING.value rather than CONFLICTING(value)
>
> Do not use the word CONFLICTING since it isn't clear whether you are
> referring to the row in the table or the value in the incoming data.

If you don't have a word that you think would more clearly indicate
the intent of the expression, I'm happy to hear suggestions from
others.

> You may also wish to support the AS keyword, as MERGE does to make the
> above even more clear.
>
> e.g. SET col = EXISTING.col + NEW.col

That's less clear, IMV. EXISTING.col is col - the very same Var. So
why qualify that it's the existing value in one place but not the
other? In fact, you can't do that now with updates in general:

postgres=# update upsert u set u.val = 'foo';
ERROR: 42703: column "u" of relation "upsert" does not exist
LINE 1: update upsert u set u.val = 'foo';
^
LOCATION: transformUpdateStmt, analyze.c:2068

This does work, which is kind of what you outline:

postgres=# update upsert u set val = u.val;
UPDATE 3

But MERGE accepts the former in other systems (in general, and for
MERGE), where Postgres won't (for UPDATEs in general). Parse analysis
of UPDATE targetlists just rejects this outright.

FWIW, is any of the two tuples reference here "NEW", in any sense?
Informally, I'd say the new value is the resulting row - the final row
value after the UPDATE. We want to refer to the existing row, and the
row proposed for insertion (with all before trigger effects carried
forward).

Having the column reference go through an alias like this might be tricky.

--
Peter Geoghegan

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Marti Raudsepp 2014-10-09 08:33:04 Re: INSERT ... ON CONFLICT {UPDATE | IGNORE}
Previous Message Michael Paquier 2014-10-09 08:09:28 Re: BUG: *FF WALs under 9.2 (WAS: .ready files appearing on slaves)