From af39e95f8373964d9443938847b24e5fbfdbed75 Mon Sep 17 00:00:00 2001 From: lekss361 <47113017+lekss361@users.noreply.github.com> Date: Fri, 15 May 2026 08:12:18 +0300 Subject: [PATCH] =?UTF-8?q?fix(site-finder):=20SQLAlchemy=20syntax=20error?= =?UTF-8?q?=20:weights::jsonb=20=E2=86=92=20CAST(:weights=20AS=20jsonb)=20?= =?UTF-8?q?(#152)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Production POST /weight-profiles → 500 SyntaxError. ## Root cause SQLAlchemy text() parser трактует ':weights' followed by '::jsonb' двусмысленно: - ':weights' — named param binding (должен стать %(weights)s) - '::jsonb' — PG cast operator Parser НЕ распознаёт :weights как параметр когда сразу следует :: cast. Result: psycopg видит literal ':weights' в SQL → syntax error. ``` LINE 5: ($1, $2, :weights::jsonb, $3, $4) ^ parameters: {user_id, profile_name, is_default, description} ↑ note: 'weights' missing — SQLAlchemy skipped it ``` ## Fix Replace ambiguous :weights::jsonb с CAST(:weights AS jsonb): - _INSERT (line 102) - _UPDATE dynamic 'weights = :weights::jsonb' (line 273) CAST() syntax не имеет ambiguity, SQLAlchemy корректно bind'ит :weights. ## Affected endpoints - POST /api/v1/admin/site-finder/weight-profiles (create) - PUT /api/v1/admin/site-finder/weight-profiles/{id} (update with weights) Refs: user report 2026-05-15 Co-authored-by: lekss361 --- backend/app/services/site_finder/weight_profiles.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/app/services/site_finder/weight_profiles.py b/backend/app/services/site_finder/weight_profiles.py index 07dc2413..7f3f0ad2 100644 --- a/backend/app/services/site_finder/weight_profiles.py +++ b/backend/app/services/site_finder/weight_profiles.py @@ -99,7 +99,7 @@ _INSERT = """ INSERT INTO user_weight_profiles (user_id, profile_name, weights, is_default, description) VALUES - (:user_id, :profile_name, :weights::jsonb, :is_default, :description) + (:user_id, :profile_name, CAST(:weights AS jsonb), :is_default, :description) RETURNING id, created_at, updated_at """ @@ -270,7 +270,7 @@ def update_profile( params["profile_name"] = payload.profile_name if payload.weights is not None: - sets.append("weights = :weights::jsonb") + sets.append("weights = CAST(:weights AS jsonb)") params["weights"] = json.dumps(payload.weights, ensure_ascii=False) if payload.description is not None: