nordabiz/database/migrations/091_messaging_redesign.sql
Maciej Pienczyn d4fd1f3b06 feat(messages): add unified conversation models and migration SQL
Add 5 new SQLAlchemy models (Conversation, ConversationMember, ConvMessage,
MessageReaction, MessagePin) and extend MessageAttachment with conv_message_id FK.
Migration 091 creates all tables with indexes, FKs, and grants.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:56:35 +01:00

97 lines
4.0 KiB
PL/PgSQL

-- 091_messaging_redesign.sql
-- Unified conversation model: replaces separate private_messages + message_group
-- Conversations (1:1 and group), messages, reactions, pins
BEGIN;
-- Unified conversations (1:1 or group)
CREATE TABLE conversations (
id SERIAL PRIMARY KEY,
name VARCHAR(255),
is_group BOOLEAN NOT NULL DEFAULT FALSE,
owner_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
last_message_id INTEGER -- FK added below after conv_messages exists
);
CREATE INDEX idx_conversations_owner ON conversations(owner_id);
CREATE INDEX idx_conversations_updated ON conversations(updated_at DESC);
-- Conversation membership
CREATE TABLE conversation_members (
conversation_id INTEGER NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
role VARCHAR(20) NOT NULL DEFAULT 'member',
last_read_at TIMESTAMP,
is_muted BOOLEAN NOT NULL DEFAULT FALSE,
is_archived BOOLEAN NOT NULL DEFAULT FALSE,
joined_at TIMESTAMP NOT NULL DEFAULT NOW(),
added_by_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
PRIMARY KEY (conversation_id, user_id)
);
CREATE INDEX idx_conversation_members_user ON conversation_members(user_id);
-- Messages within a conversation
CREATE TABLE conv_messages (
id SERIAL PRIMARY KEY,
conversation_id INTEGER NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
sender_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
content TEXT NOT NULL,
reply_to_id INTEGER REFERENCES conv_messages(id) ON DELETE SET NULL,
edited_at TIMESTAMP,
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
link_preview JSONB,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_conv_messages_conversation ON conv_messages(conversation_id);
CREATE INDEX idx_conv_messages_created ON conv_messages(created_at);
CREATE INDEX idx_conv_messages_conversation_created ON conv_messages(conversation_id, created_at);
-- Now add the deferred FK from conversations.last_message_id -> conv_messages.id
ALTER TABLE conversations
ADD CONSTRAINT fk_conversations_last_message
FOREIGN KEY (last_message_id) REFERENCES conv_messages(id) ON DELETE SET NULL;
-- Emoji reactions on messages
CREATE TABLE message_reactions (
id SERIAL PRIMARY KEY,
message_id INTEGER NOT NULL REFERENCES conv_messages(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
emoji VARCHAR(10) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
CONSTRAINT uq_message_reaction UNIQUE (message_id, user_id, emoji)
);
CREATE INDEX idx_message_reactions_message ON message_reactions(message_id);
-- Pinned messages
CREATE TABLE message_pins (
id SERIAL PRIMARY KEY,
conversation_id INTEGER NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
message_id INTEGER NOT NULL REFERENCES conv_messages(id) ON DELETE CASCADE,
pinned_by_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_message_pins_conversation ON message_pins(conversation_id);
-- Extend message_attachments to support conv_messages
ALTER TABLE message_attachments ADD COLUMN conv_message_id INTEGER REFERENCES conv_messages(id) ON DELETE CASCADE;
CREATE INDEX idx_message_attachments_conv ON message_attachments(conv_message_id) WHERE conv_message_id IS NOT NULL;
-- Grants
GRANT ALL ON TABLE conversations TO nordabiz_app;
GRANT ALL ON TABLE conversation_members TO nordabiz_app;
GRANT ALL ON TABLE conv_messages TO nordabiz_app;
GRANT ALL ON TABLE message_reactions TO nordabiz_app;
GRANT ALL ON TABLE message_pins TO nordabiz_app;
GRANT USAGE, SELECT ON SEQUENCE conversations_id_seq TO nordabiz_app;
GRANT USAGE, SELECT ON SEQUENCE conv_messages_id_seq TO nordabiz_app;
GRANT USAGE, SELECT ON SEQUENCE message_reactions_id_seq TO nordabiz_app;
GRANT USAGE, SELECT ON SEQUENCE message_pins_id_seq TO nordabiz_app;
COMMIT;