Decode persist looked brands up with a case-sensitive eq(), so an
uppercase decode string ("FORD") missed canonical "Ford" → brand_id
NULL + raw uppercase stored as brand_name, splitting one brand across
casing variants in analytics/catalog. Now matches brands
case-insensitively and stores the canonical name. Migration
0013_fix_brand_casing backfills existing rows (60 on prod, 1 on dev).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
29 lines
1.4 KiB
SQL
29 lines
1.4 KiB
SQL
-- Canonicalise vehicle brand casing + backfill missing brand_id.
|
|
--
|
|
-- Root cause: the decode persist (vehicles.service.ts) looked brands up with a
|
|
-- case-SENSITIVE `eq(brands.name, brandName)`. A decode source that yields an
|
|
-- uppercase brand string (e.g. "FORD", "MERCEDES-BENZ") missed the canonical
|
|
-- "Ford" / "Mercedes-Benz" row → brand_id stayed NULL and the raw uppercase
|
|
-- string was stored as brand_name. That split the same brand across casing
|
|
-- variants in analytics + the catalog ("Ford" vs "FORD"). The companion code
|
|
-- fix makes the lookup case-insensitive and stores the canonical name; this
|
|
-- migration repairs the rows already written.
|
|
--
|
|
-- Backfill every vehicle whose brand_name matches a canonical brand
|
|
-- case-insensitively: set the FK and the canonical-cased name. (catalog_vehicles
|
|
-- is intentionally untouched — its brand_name namespace does not match the
|
|
-- brands table, so 0 rows would qualify.)
|
|
UPDATE "vehicles" v
|
|
SET brand_id = b.id, brand_name = b.name
|
|
FROM "brands" b
|
|
WHERE v.brand_id IS NULL AND lower(v.brand_name) = lower(b.name);
|
|
--> statement-breakpoint
|
|
|
|
-- Defensive: realign any vehicle whose brand_id is set but whose denormalised
|
|
-- brand_name has drifted from the canonical brands.name (none today, but keeps
|
|
-- the FK and the denormalised name consistent going forward).
|
|
UPDATE "vehicles" v
|
|
SET brand_name = b.name
|
|
FROM "brands" b
|
|
WHERE v.brand_id = b.id AND v.brand_name <> b.name;
|