Re: INSERT ... ON CONFLICT DO SELECT [FOR ...] take 2

From: "Joel Jacobson" <joel(at)compiler(dot)org>
To: "Andreas Karlsson" <andreas(at)proxel(dot)se>, pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>, "Marko Tiikkaja" <marko(at)joh(dot)to>
Subject: Re: INSERT ... ON CONFLICT DO SELECT [FOR ...] take 2
Date: 2024-12-03 10:24:26
Message-ID: 5e8b911c-c274-4dbb-a143-cd8a7e6a03b9@app.fastmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Tue, Dec 3, 2024, at 09:52, Andreas Karlsson wrote:
> Hi,
>
> Here is an updated version of the patch which fixes a few small bugs,
> including making sure it checks the update permission plus a bug found
> by Joel Jacobsson when it was called by SPI.

+1 for this feature.

This seems especially useful when designing idempotent APIs.
Neat to only need a single statement, for what we
currently need two separate statements for.

Here is an attempt of a realistic example:

CREATE OR REPLACE FUNCTION get_or_create_license_key(_user_id bigint, _product_id bigint)
RETURNS UUID BEGIN ATOMIC
INSERT INTO licenses (user_id, product_id)
VALUES (_user_id, _product_id)
ON CONFLICT (user_id, product_id) DO NOTHING;
SELECT license_key
FROM licenses
WHERE user_id = _user_id
AND product_id = _product_id;
END;

This can be simplified into:

CREATE OR REPLACE FUNCTION get_or_create_license_key(_user_id bigint, _product_id bigint)
RETURNS UUID BEGIN ATOMIC
INSERT INTO licenses (user_id, product_id)
VALUES (_user_id, _product_id)
ON CONFLICT (user_id, product_id) DO SELECT RETURNING license_key;
END;

I've tested the patch successfully and also looked at the code briefly
and at first glance think it looks nice and clean.

/Joel

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Kirill Reshke 2024-12-03 10:28:40 Re: on_error table, saving error info to a table
Previous Message Kirill Reshke 2024-12-03 09:43:31 Re: processes stuck in shutdown following OOM/recovery