On 29/08/2025 09:02, Joel Jacobson wrote:
Ideas on possible solutions:

How about piggy-backing on the CREATE FUNCTION's existing ROWS
parameter, and reusing the [ ENFORCED | NOT ENFORCED ] terminology we
have for constraints? We would need to lift the current restriction that
it is only allowed when the function return a set.

CREATE FUNCTION test_update(_a int, _b int)
RETURNS BOOLEAN
ROWS 1 ENFORCED
BEGIN ATOMIC
     UPDATE foo SET a = _a WHERE b = _b RETURNING TRUE;
END;

CREATE FUNCTION test_select(_b int)
RETURNS INT
ROWS 1 ENFORCED
BEGIN ATOMIC
     SELECT a FROM foo WHERE b = _b;
END;

Alternatively, maybe we could set a per-function GUC,
e.g. SET assert_single_row = true?

CREATE FUNCTION test_update(_a int, _b int)
RETURNS BOOLEAN
SET assert_single_row = true
BEGIN ATOMIC
     UPDATE foo SET a = _a WHERE b = _b RETURNING TRUE;
END;

CREATE FUNCTION test_update(_a int, _b int)
RETURNS BOOLEAN
SET assert_single_row = true
BEGIN ATOMIC
     SELECT a FROM foo WHERE b = _b;
END;

INSERT and DELETE should be supported as well of course.

These were just the two first ideas on the top of my head, please share
yours if you see a better way.


The implementation is *supposed* to track several things for a query.  I am not sure PostgreSQL does this accurately or not.


The information is available through the GET DIAGNOSTICS command which postgres does not support (yet?).


So I might suggest something like:


    SELECT a
    FROM foo
    WHERE b = $1
    CHECK DIAGNOSTICS (ROW_COUNT = 1)


and


    UPDATE foo
    SET a = $1
    WHERE b = $2
    CHECK DIAGNOSTICS (ROW_COUNT = 1)


etc.


CHECK is already a reserved word in both postgres and the standard.

--

Vik Fearing



Reply via email to