0

I'm trying to build a messaging feature with the following tables: Users, Conversations, Inbox, and Messages. What I'm having an issue with is checking if a bidirectional conversation record exist between users in the conversation table :

id | user_id1 | user_id2 |
 1 |    1     |    2     |
 2 |    2     |    1     |
 3 |    1     |    3     |

and if a record exists, select that record on conversations and update it or create a new record of conversation and insert into messages inbox etc

My Tables

create table users(
  user_id serial primary key not null,
  first_name varchar(20),
  last_name varchar(20),
  email text,
  password varchar(100),
  dob varchar(10),
  city varchar(50),
  state varchar(50),
  profile_img text,
  about_me text,
  date timestamptz
);

create table conversations (
  conversation_id serial primary key not null
  user_id1 integer,
  user_id2 integer,
  date timestamptz
);

create table inbox (
  user_id2 integer,
  last_message_user_id integer,
  last_subject text,
  last_message text,
  date timestamptz
);

create table messages(
  message_id serial primary key not null,
  conversation_id integer,
  user_id_sender integer,
  subject varchar(100),
  message text,
  seen boolean default false,
  date timestamptz
);

I have tried using a trigger like so:

CREATE OR REPLACE FUNCTION check_conversation_exists() RETURNS trigger AS $$
BEGIN
  IF ((${user_id_sender} = conversations.user_id1 AND ${user_id_receiver} = conversations.user_id2) OR (${user_id_receiver} = conversations.user_id1 AND user_id_sender = conversations.user_id2))
    THEN UPDATE inbox
      SET 
        user_id2 = ${user_id_receiver},
        last_message_user_id = ${user_id_sender},
        last_subject = ${subject},
        last_message = ${message},
        date = now()
      WHERE (${user_id_sender} = conversations.user_id1 AND ${user_id_receiver} = conversations.user_id2) OR (${user_id_receiver} = conversations.user_id1 AND ${user_id_sender} = conversations.user_id2);
      INSERT INTO messages(conversation_id, user_id_sender, subject, message, date)
      VALUES(lastval(), ${user_id_sender}, ${subject}, ${message}, now());
  ELSE
    INSERT INTO conversations(user_id1, user_id2, date)
    VALUES(${user_id_sender}, ${user_id_receiver}, now());
    INSERT INTO messages(conversation_id, user_id_sender, subject, message, date)
    VALUES(lastval(), ${user_id_sender}, ${subject}, ${message}, now());
    INSERT INTO inbox(user_id2, last_message_user_id, last_subject, last_message, date)
    VALUES(${user_id_receiver}, ${user_id_sender}, ${subject}, ${message}, now());
  END IF;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER check_conversation 
BEFORE INSERT on conversations FOR EACH STATEMENT EXECUTE FUNCTION check_conversation_exists();

The issue with the above executes, but there are no records being created. Is there a better way to achieve what I'm trying to do, or am I overcomplicating this. All I want is to have a list of conversations the main user has with other users removing duplicates (like an inbox) and when a user selects on the inbox retrieves all messages associated with that conversation id.

Expecting records to update if exists, if not exists create new record

Ken White
  • 123,280
  • 14
  • 225
  • 444
Randall H
  • 64
  • 5
  • 1
    Have you considered using `MERGE` instead? – Dai Nov 14 '22 at 22:06
  • I haven't heard of MERGE because i'm fairly beginner with SQL. But i'm interested is there a conditional way to do what I'm trying to achieve? – Randall H Nov 14 '22 at 22:12
  • See https://www.postgresql.org/docs/current/sql-merge.html and https://stackoverflow.com/questions/17267417/how-to-upsert-merge-insert-on-duplicate-update-in-postgresql – Stefan Wuebbe Nov 15 '22 at 00:17

0 Answers0