fix: Replace COUNT(*) with SELECT id in FOR UPDATE query (refs #23)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 2m18s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 29s
Deploy to Staging / Verify Staging (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 6s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped

PostgreSQL error 0A000 (feature_not_supported) occurs when using
FOR UPDATE with aggregate functions like COUNT(*). Row-level locking
requires actual rows to lock.

Changes:
- Select id column instead of COUNT(*) aggregate
- Count rows in application using .length
- Maintains transaction isolation and race condition prevention

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Eric Gullickson
2026-01-11 18:08:49 -06:00
parent 20189a1d37
commit 8703e7758a

View File

@@ -86,11 +86,12 @@ export class VehiclesService {
await client.query('BEGIN'); await client.query('BEGIN');
// Lock user's vehicle rows and get count // Lock user's vehicle rows and get count
const countResult = await client.query( // Note: Cannot use COUNT(*) with FOR UPDATE, so we select IDs and count in app
'SELECT COUNT(*) as count FROM vehicles WHERE user_id = $1 AND is_active = true FOR UPDATE', const lockResult = await client.query(
'SELECT id FROM vehicles WHERE user_id = $1 AND is_active = true FOR UPDATE',
[userId] [userId]
); );
const currentCount = parseInt(countResult.rows[0].count, 10); const currentCount = lockResult.rows.length;
// Check if user can add another vehicle // Check if user can add another vehicle
if (!canAddVehicle(userTier, currentCount)) { if (!canAddVehicle(userTier, currentCount)) {