I am trying to toggle a relation in a single query where it deletes the relation if it already exists, otherwise it creates it. I could add a third column with a bool that toggles it but I would rather delete it.
Schema
CREATE TABLE IF NOT EXISTS thread_subscription (
profile_id INTEGER REFERENCES profile (id),
thread_id INTEGER REFERENCES thread (id),
UNIQUE(profile_id,thread_id)
)
Query
INSERT INTO thread_subscription (profile_id,thread_id)
VALUES ($1,$2) ON CONFLICT (profile_id,thead_id)
DO DELETE FROM thread_subscription
WHERE profile_id = $1 AND thread_id = $2;
So your intent is to run an INSERT order on a table, and you expect that on duplicate keys it will actually DELETE the related record. While technically feasible, I would not recommend this set up, because this is action at a distance, which is hard to debug.
The same type of functionnality however could be achieved with a Postgres function. This makes the intent explicit when it comes to toggling the subscription, and does not interfere with standard database statements (INSERT).
Here is the code for the function : it takes two parameters as input, verifies if a record is already there in the subscriptions table, and then performs the relevant operation ; it returns 0 on DELETE and 1 on INSERT. You can see this db fiddle for a full demo of how it works.
CREATE OR REPLACE FUNCTION toggle_subscription(
pid NUMERIC,
tid NUMERIC
)
RETURNS NUMERIC AS $$
DECLARE
row_exists NUMERIC;
BEGIN
SELECT 1
INTO row_exists
FROM thread_subscription
WHERE profile_id = pid and thread_id = tid;
IF (row_exists > 0) THEN
DELETE FROM thread_subscription WHERE profile_id = pid and thread_id = tid;
RETURN 0;
ELSE
INSERT INTO thread_subscription(profile_id, thread_id) VALUES(pid, tid);
RETURN 1;
END IF;
END;
$$
LANGUAGE plpgsql;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With