From 3a282d8467bffab59da12af26b11fbd474ba95aa Mon Sep 17 00:00:00 2001 From: MythEclipse Date: Mon, 22 Jun 2026 17:54:09 +0700 Subject: [PATCH] =?UTF-8?q?fix:=20recordings=20endpoint=20500=20=E2=80=94?= =?UTF-8?q?=20broken=20SQL=20parameter=20binding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Hand-rolled , params with sql.raw() didn't actually bind values - Drizzle's sql.raw() just inserts literal text — no parameter binding - Replaced with proper sql`` tagged templates + sql.join() for conditions - Each filter now correctly binds via drizzle's parameterized query --- .../modules/recordings/recordings.service.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/services/backend/src/modules/recordings/recordings.service.ts b/services/backend/src/modules/recordings/recordings.service.ts index ae512da..c233a25 100644 --- a/services/backend/src/modules/recordings/recordings.service.ts +++ b/services/backend/src/modules/recordings/recordings.service.ts @@ -37,24 +37,22 @@ export class RecordingsService { logger.info({ limit }, "getRecent called"); const db = getDatabase(); - const conditions: string[] = []; - const params: unknown[] = []; + const conditions: ReturnType[] = []; if (filters?.cursor) { - params.push(filters.cursor); - conditions.push(`created_at < $${params.length}::numeric`); + conditions.push(sql`created_at < ${filters.cursor}::numeric`); } if (filters?.channelId) { - params.push(filters.channelId); - conditions.push(`channel_id = $${params.length}`); + conditions.push(sql`channel_id = ${filters.channelId}`); } if (filters?.userId) { - params.push(filters.userId); - conditions.push(`user_id = $${params.length}`); + conditions.push(sql`user_id = ${filters.userId}`); } const whereClause = - conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : ""; + conditions.length > 0 + ? sql`WHERE ${sql.join(conditions, sql` AND `)}` + : sql``; const { rows } = await db.execute(sql` SELECT @@ -63,7 +61,7 @@ export class RecordingsService { upload_status, upload_error, transcription, created_at, uploaded_at, COALESCE(size_bytes, 0) AS duration_bytes FROM voice_recordings - ${sql.raw(whereClause)} + ${whereClause} ORDER BY created_at DESC LIMIT ${limit + 1} `);