HOTFIX: add #18/#13 schema to Postgres (chat history returned empty)

Production runs DB_BACKEND=pg, but the message_hidden table (#18) and
pinned_at/pinned_by columns (#13) were only added to the SQLite migrations in
db.js — never to schema.pg.sql. So thread/conversations/pinned queries hit a
missing relation/column and 500'd, which surfaced as "chat history removed"
(no data was ever deleted — the reads just errored).

pg.js init() runs schema.pg.sql on every boot. Added the message_hidden table
and, because CREATE TABLE IF NOT EXISTS can't add columns to the existing
messages table, idempotent ALTER TABLE ... ADD COLUMN IF NOT EXISTS for
pinned_at/pinned_by. Restores all chat history and re-enables pin + delete-for-me.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-12 07:53:13 +05:30
parent d0863351d2
commit f3b6e67c19
+18 -1
View File
@@ -129,7 +129,9 @@ CREATE TABLE IF NOT EXISTS messages (
msg_type TEXT,
deleted SMALLINT NOT NULL DEFAULT 0,
edited_at BIGINT,
fwd_from TEXT
fwd_from TEXT,
pinned_at BIGINT, -- #13 pin a message
pinned_by TEXT -- #13
);
CREATE INDEX IF NOT EXISTS idx_messages_pair ON messages(team_id, sender_id, recipient_id, created_at);
CREATE INDEX IF NOT EXISTS idx_messages_unread ON messages(team_id, recipient_id, sender_id, read_at);
@@ -137,6 +139,21 @@ CREATE INDEX IF NOT EXISTS idx_messages_conv ON messages(conversation_id, crea
-- New: attachment lookups drove the /files auth scan (see static.js authAttachment). Index it so the
-- per-Range playback auth is a keyed lookup, not a table scan (the auth cache stays as a second line).
CREATE INDEX IF NOT EXISTS idx_messages_attachment ON messages(attachment_id);
-- Columns/tables added AFTER the initial PG cutover. The CREATE TABLE above only applies to a FRESH
-- database (IF NOT EXISTS is a no-op once the table exists), so add these idempotently for the existing
-- production table too. Safe to run on every boot. (Unlike the up-front rule at the top of this file, a
-- post-cutover column MUST also be ALTER-ed in — otherwise it silently never lands on the live DB.)
ALTER TABLE messages ADD COLUMN IF NOT EXISTS pinned_at BIGINT; -- #13
ALTER TABLE messages ADD COLUMN IF NOT EXISTS pinned_by TEXT; -- #13
-- #18 "Delete for me": a per-user hide. The message row is untouched (everyone else still sees it); this
-- records that THIS user removed it from their own threads + sidebar.
CREATE TABLE IF NOT EXISTS message_hidden (
message_id TEXT NOT NULL,
user_id TEXT NOT NULL,
hidden_at BIGINT,
PRIMARY KEY (message_id, user_id)
);
CREATE TABLE IF NOT EXISTS message_reactions (
message_id TEXT NOT NULL,