I have a table ContentAddressedFiles
where the combination of the columns hash
, size
, and extension
are UNIQUE
. I want to create a stored procedure that when called, will insert a new record into the table with the given values. If a record for these values already exists, I want to just return that existing record. Here's my approach:
CREATE OR REPLACE FUNCTION INIT_CAF( id_in_case_of_new UUID, _hash VARCHAR(255), _size INTEGER, _extension VARCHAR(255), _mimeType VARCHAR(255))
RETURNS "ContentAddressedFiles"
AS $$
DECLARE
caf "ContentAddressedFiles"%ROWTYPE;
BEGIN
INSERT INTO "ContentAddressedFiles" (id, hash, size, extension, "mimeType", "createdAt", "updatedAt")
VALUES( id_in_case_of_new, _hash, _size, _extension, _mimeType, NOW(), NOW() ) RETURNING * INTO caf;
RETURN caf;
EXCEPTION WHEN unique_violation THEN
SELECT * FROM "ContentAddressedFiles" INTO caf WHERE "hash" = _hash AND "size" = _size AND "extension" = _extension;
IF NOT FOUND THEN
RAISE EXCEPTION 'This should never happen.';
END IF;
RETURN caf;
END;
$$ LANGUAGE plpgsql;
However, when I call the procedure from concurrent transactions, I consistently get the exception:
EXCEPTION: This should never happen.
How is this even possible? The procedure does not seem to be able to SELECT
the reason for the failing INSERT
before (it's not the id
that clashes, it's just the tuple of <hash, size, extension>
.