I had this:
CREATE FUNCTION upsert_user(u_name text, u_fullname text, u_email text, u_suffix text) RETURNS integer
LANGUAGE plpgsql
AS $$
DECLARE
userid users.id_user%TYPE;
BEGIN
LOOP
UPDATE users SET "fullname" = u_fullname, "email" = u_email, "suffix" = u_suffix WHERE "name" = u_name RETURNING "id_user" INTO userid;
IF FOUND THEN
RETURN userid;
END IF;
BEGIN
INSERT INTO users ("name", "fullname", "email", "suffix") VALUES (u_name, u_fullname, u_email, u_suffix) RETURNING "id_user" INTO userid;
RETURN userid;
EXCEPTION WHEN unique_violation THEN
END;
END LOOP;
END;
$$;
CREATE TRIGGER link_entity
BEFORE INSERT
ON public.users
FOR EACH ROW
EXECUTE PROCEDURE public.link_entity();
CREATE FUNCTION link_entity() RETURNS trigger
LANGUAGE plpgsql
AS $$ DECLARE
entityid integer;
BEGIN
INSERT INTO privileges_entities (name) VALUES (NEW.name) RETURNING privileges_entities.id_entity INTO entityid;
IF NOT FOUND THEN
RETURN NULL;
END IF;
NEW.ref_entity := entityid;
RETURN NEW;
END;
$$;
After updating postgresql to version 9.5, I modified the upsert_user function to use the new ON CONFLICT statement:
CREATE FUNCTION upsert_user(u_name text, u_fullname text, u_email text, u_suffix text) RETURNS integer
LANGUAGE sql
AS $$
INSERT INTO users (name, fullname, email, suffix)
VALUES (u_name, u_fullname, u_email, u_suffix)
ON CONFLICT (name) DO UPDATE SET name=EXCLUDED.name, fullname=EXCLUDED.fullname, email=EXCLUDED.email, suffix=EXCLUDED.suffix
RETURNING id_user;
$$;
The problem is that new rows are now inserted into the privileges_entities table, even if insertion into the users table is not performed. Is it possible to roll back a trigger if user insertion leads to a conflict?
source
share