fix(db): portable thread queries for Postgres (conditional cursor + subquery alias)
The DM/group thread queries used `(? IS NULL OR created_at < ?)` — an all-NULL
param Postgres can't type ('could not determine data type of parameter') — and an
unaliased FROM-subquery (Postgres requires an alias). Both rewritten to add the
`created_at < ?` clause only when a cursor is given, and alias the subquery `t`.
Portable; sqlite db-smoke still 22/22.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+16
-9
@@ -213,13 +213,17 @@ const messages = {
|
||||
// Full 1:1 (DM) thread between two users (both directions). Take the NEWEST `limit` messages
|
||||
// (inner DESC), then present them oldest-first. The old plain "ASC LIMIT" returned the OLDEST 300
|
||||
// and silently dropped everything newer once a thread passed 300 — so new messages "disappeared".
|
||||
thread: (teamId, a, b, limit = 500, before = null) =>
|
||||
db.prepare(`SELECT * FROM (
|
||||
// The `before` cursor is added CONDITIONALLY (not as `? IS NULL OR …`): an all-NULL param has no type
|
||||
// for Postgres to infer. The subquery also needs an alias (`t`) — Postgres requires it. Both portable.
|
||||
thread: (teamId, a, b, limit = 500, before = null) => {
|
||||
const cond = before != null ? ' AND created_at < ?' : '';
|
||||
const args = before != null ? [teamId, a, b, b, a, before, limit] : [teamId, a, b, b, a, limit];
|
||||
return db.prepare(`SELECT * FROM (
|
||||
SELECT * FROM messages WHERE team_id=? AND conversation_id IS NULL
|
||||
AND ((sender_id=? AND recipient_id=?) OR (sender_id=? AND recipient_id=?))
|
||||
AND (? IS NULL OR created_at < ?)
|
||||
AND ((sender_id=? AND recipient_id=?) OR (sender_id=? AND recipient_id=?))${cond}
|
||||
ORDER BY created_at DESC LIMIT ?
|
||||
) ORDER BY created_at ASC`).all(teamId, a, b, b, a, before, before, limit),
|
||||
) t ORDER BY created_at ASC`).all(...args);
|
||||
},
|
||||
// Full-thread search (ALL messages, not just the loaded window). `like` is the escaped LIKE pattern.
|
||||
searchThread: (teamId, a, b, like, limit = 300) =>
|
||||
db.prepare(`SELECT id, created_at, sender_id FROM messages WHERE team_id=? AND conversation_id IS NULL
|
||||
@@ -233,10 +237,13 @@ const messages = {
|
||||
db.prepare('SELECT * FROM messages WHERE team_id=? AND conversation_id IS NULL AND (sender_id=? OR recipient_id=?) ORDER BY created_at DESC LIMIT ?')
|
||||
.all(teamId, userId, userId, limit),
|
||||
// Group conversation helpers.
|
||||
threadByConversation: (conversationId, limit = 500, before = null) =>
|
||||
db.prepare(`SELECT * FROM (
|
||||
SELECT * FROM messages WHERE conversation_id=? AND (? IS NULL OR created_at < ?) ORDER BY created_at DESC LIMIT ?
|
||||
) ORDER BY created_at ASC`).all(conversationId, before, before, limit),
|
||||
threadByConversation: (conversationId, limit = 500, before = null) => {
|
||||
const cond = before != null ? ' AND created_at < ?' : '';
|
||||
const args = before != null ? [conversationId, before, limit] : [conversationId, limit];
|
||||
return db.prepare(`SELECT * FROM (
|
||||
SELECT * FROM messages WHERE conversation_id=?${cond} ORDER BY created_at DESC LIMIT ?
|
||||
) t ORDER BY created_at ASC`).all(...args);
|
||||
},
|
||||
searchConversation: (conversationId, like, limit = 300) =>
|
||||
db.prepare(`SELECT id, created_at, sender_id FROM messages WHERE conversation_id=? AND deleted=0
|
||||
AND body LIKE ? ESCAPE '\\' ORDER BY created_at ASC LIMIT ?`).all(conversationId, like, limit),
|
||||
|
||||
Reference in New Issue
Block a user