|
| 1 | +CREATE TABLE "auction_relationships" ( |
| 2 | + "left_platform" text NOT NULL, |
| 3 | + "left_external_id" text NOT NULL, |
| 4 | + "right_platform" text NOT NULL, |
| 5 | + "right_external_id" text NOT NULL, |
| 6 | + "kind" text NOT NULL, |
| 7 | + "confidence" text NOT NULL, |
| 8 | + "source" text DEFAULT 'auto' NOT NULL, |
| 9 | + "evidence" jsonb DEFAULT '{}'::jsonb NOT NULL, |
| 10 | + "created_at" timestamp with time zone DEFAULT now() NOT NULL, |
| 11 | + "updated_at" timestamp with time zone DEFAULT now() NOT NULL, |
| 12 | + CONSTRAINT "auction_relationships_left_platform_left_external_id_right_platform_right_external_id_pk" PRIMARY KEY("left_platform","left_external_id","right_platform","right_external_id") |
| 13 | +); |
| 14 | +--> statement-breakpoint |
| 15 | +ALTER TABLE "auction_relationships" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint |
| 16 | +ALTER TABLE "auction_relationships" ADD CONSTRAINT "fk_auction_relationships_left_auction" FOREIGN KEY ("left_platform","left_external_id") REFERENCES "public"."auctions"("platform","external_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint |
| 17 | +ALTER TABLE "auction_relationships" ADD CONSTRAINT "fk_auction_relationships_right_auction" FOREIGN KEY ("right_platform","right_external_id") REFERENCES "public"."auctions"("platform","external_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint |
| 18 | +CREATE INDEX "idx_auction_relationships_left" ON "auction_relationships" USING btree ("left_platform","left_external_id");--> statement-breakpoint |
| 19 | +CREATE INDEX "idx_auction_relationships_right" ON "auction_relationships" USING btree ("right_platform","right_external_id");--> statement-breakpoint |
| 20 | +ALTER TABLE "auction_relationships" ADD CONSTRAINT "auction_relationships_canonical_pair" CHECK (("left_platform", "left_external_id") < ("right_platform", "right_external_id"));--> statement-breakpoint |
| 21 | +WITH current_details AS ( |
| 22 | + SELECT platform, external_id, address |
| 23 | + FROM auction_details |
| 24 | + WHERE is_latest = true |
| 25 | +), candidates AS ( |
| 26 | + SELECT a.platform, a.external_id, a.country, lower(trim(a.authority)) AS authority_key, |
| 27 | + lower(trim(regexp_replace(a.case_number, E'\\s+', ' ', 'g'))) AS case_raw, |
| 28 | + a.auction_date_iso, |
| 29 | + regexp_replace(replace(translate(lower(coalesce(d.address, '')), 'äöü', 'aou'), 'ß', 'ss'), '[^[:alnum:]]', '', 'g') AS address_key |
| 30 | + FROM auctions a |
| 31 | + LEFT JOIN current_details d ON d.platform = a.platform AND d.external_id = a.external_id |
| 32 | +), normalized AS ( |
| 33 | + SELECT *, regexp_match(case_raw, E'^0*([0-9]+)\\s*k\\s*0*([0-9]+)\\s*/\\s*0*([0-9]{2,4})$') AS case_parts |
| 34 | + FROM candidates |
| 35 | +), keyed AS ( |
| 36 | + SELECT *, CASE WHEN case_parts IS NULL THEN NULL ELSE |
| 37 | + (case_parts[1]::integer)::text || ' k ' || (case_parts[2]::integer)::text || '/' || right(case_parts[3], 2) |
| 38 | + END AS case_key |
| 39 | + FROM normalized |
| 40 | +), edges AS ( |
| 41 | + SELECT l.platform AS left_platform, l.external_id AS left_external_id, |
| 42 | + r.platform AS right_platform, r.external_id AS right_external_id, |
| 43 | + 'same_proceeding'::text AS kind, 'high'::text AS confidence, |
| 44 | + jsonb_build_object('migrationBackfill', true, 'sameAuthority', true, 'sameCaseNumber', true, 'sameAuctionDate', true) AS evidence, |
| 45 | + 0 AS priority |
| 46 | + FROM keyed l |
| 47 | + JOIN keyed r ON l.country = r.country AND l.authority_key = r.authority_key |
| 48 | + AND l.case_key IS NOT NULL AND l.case_key = r.case_key |
| 49 | + AND l.auction_date_iso IS NOT DISTINCT FROM r.auction_date_iso |
| 50 | + AND (l.platform, l.external_id) < (r.platform, r.external_id) |
| 51 | + UNION ALL |
| 52 | + SELECT l.platform, l.external_id, r.platform, r.external_id, |
| 53 | + 'same_address'::text, 'medium'::text, |
| 54 | + jsonb_build_object('migrationBackfill', true, 'sameAddress', true), 1 |
| 55 | + FROM keyed l |
| 56 | + JOIN keyed r ON l.country = r.country AND l.address_key = r.address_key |
| 57 | + AND length(l.address_key) >= 8 AND l.address_key ~ '[0-9]' |
| 58 | + AND (l.platform, l.external_id) < (r.platform, r.external_id) |
| 59 | +), deduplicated AS ( |
| 60 | + SELECT DISTINCT ON (left_platform, left_external_id, right_platform, right_external_id) |
| 61 | + left_platform, left_external_id, right_platform, right_external_id, kind, confidence, evidence |
| 62 | + FROM edges |
| 63 | + ORDER BY left_platform, left_external_id, right_platform, right_external_id, priority |
| 64 | +) |
| 65 | +INSERT INTO auction_relationships ( |
| 66 | + left_platform, left_external_id, right_platform, right_external_id, kind, confidence, source, evidence |
| 67 | +) |
| 68 | +SELECT left_platform, left_external_id, right_platform, right_external_id, kind, confidence, 'auto', evidence |
| 69 | +FROM deduplicated; |
0 commit comments