|
| 1 | +-- Migration to fix incorrectly formatted trusted domain entries in EnvironmentConfigOverride. |
| 2 | +-- |
| 3 | +-- A previous migration sometimes generated entries like: |
| 4 | +-- "domains.trustedDomains.<id>.<property1>": value1, |
| 5 | +-- "domains.trustedDomains.<id>.<property2>": value2 |
| 6 | +-- |
| 7 | +-- Without the parent key: |
| 8 | +-- "domains.trustedDomains.<id>": { ... } |
| 9 | +-- |
| 10 | +-- This migration adds an empty object at the <id> level for any missing parent keys: |
| 11 | +-- "domains.trustedDomains.<id>": {}, |
| 12 | +-- "domains.trustedDomains.<id>.<property1>": value1, |
| 13 | +-- "domains.trustedDomains.<id>.<property2>": value2 |
| 14 | + |
| 15 | +-- Add temporary column to track processed rows (outside transaction so it's visible immediately) |
| 16 | +-- SPLIT_STATEMENT_SENTINEL |
| 17 | +-- SINGLE_STATEMENT_SENTINEL |
| 18 | +-- RUN_OUTSIDE_TRANSACTION_SENTINEL |
| 19 | +ALTER TABLE /* SCHEMA_NAME_SENTINEL */."EnvironmentConfigOverride" ADD COLUMN IF NOT EXISTS "temp_trusted_domains_checked" BOOLEAN DEFAULT FALSE; |
| 20 | +-- SPLIT_STATEMENT_SENTINEL |
| 21 | + |
| 22 | +-- Create index on the temporary column for efficient querying |
| 23 | +-- SPLIT_STATEMENT_SENTINEL |
| 24 | +-- SINGLE_STATEMENT_SENTINEL |
| 25 | +-- RUN_OUTSIDE_TRANSACTION_SENTINEL |
| 26 | +CREATE INDEX CONCURRENTLY IF NOT EXISTS "temp_eco_trusted_domains_checked_idx" |
| 27 | +ON /* SCHEMA_NAME_SENTINEL */."EnvironmentConfigOverride" ("temp_trusted_domains_checked") |
| 28 | +WHERE "temp_trusted_domains_checked" IS NOT TRUE; |
| 29 | +-- SPLIT_STATEMENT_SENTINEL |
| 30 | + |
| 31 | +-- Process rows in batches (outside transaction so each batch commits independently) |
| 32 | +-- SPLIT_STATEMENT_SENTINEL |
| 33 | +-- SINGLE_STATEMENT_SENTINEL |
| 34 | +-- RUN_OUTSIDE_TRANSACTION_SENTINEL |
| 35 | +-- CONDITIONALLY_REPEAT_MIGRATION_SENTINEL |
| 36 | +WITH rows_to_check AS ( |
| 37 | + -- Get unchecked rows |
| 38 | + SELECT "projectId", "branchId", "config" |
| 39 | + FROM /* SCHEMA_NAME_SENTINEL */."EnvironmentConfigOverride" |
| 40 | + WHERE "temp_trusted_domains_checked" IS NOT TRUE |
| 41 | + -- Keep batch size small for consistent performance |
| 42 | + LIMIT 1000 |
| 43 | +), |
| 44 | +matching_keys AS ( |
| 45 | + -- Find all keys that look like "domains.trustedDomains.<id>.<property...>" |
| 46 | + -- (4 or more dot-separated parts starting with domains.trustedDomains) |
| 47 | + SELECT |
| 48 | + rtc."projectId", |
| 49 | + rtc."branchId", |
| 50 | + key, |
| 51 | + -- Extract the parent key: domains.trustedDomains.<id> |
| 52 | + (string_to_array(key, '.'))[1] || '.' || |
| 53 | + (string_to_array(key, '.'))[2] || '.' || |
| 54 | + (string_to_array(key, '.'))[3] AS parent_key |
| 55 | + FROM rows_to_check rtc, |
| 56 | + jsonb_object_keys(rtc."config") AS key |
| 57 | + WHERE key ~ '^domains\.trustedDomains\.[^.]+\..+' |
| 58 | + -- Pattern matches: domains.trustedDomains.<id>.<anything> |
| 59 | + -- e.g. "domains.trustedDomains.abc123.baseUrl" |
| 60 | +), |
| 61 | +missing_parents AS ( |
| 62 | + -- Find parent keys that don't exist in the config |
| 63 | + SELECT DISTINCT |
| 64 | + mk."projectId", |
| 65 | + mk."branchId", |
| 66 | + mk.parent_key |
| 67 | + FROM matching_keys mk |
| 68 | + JOIN rows_to_check rtc |
| 69 | + ON rtc."projectId" = mk."projectId" |
| 70 | + AND rtc."branchId" = mk."branchId" |
| 71 | + WHERE NOT (rtc."config" ? mk.parent_key) |
| 72 | +), |
| 73 | +parents_to_add AS ( |
| 74 | + -- Aggregate all missing parent keys per row into a single jsonb object |
| 75 | + SELECT |
| 76 | + mp."projectId", |
| 77 | + mp."branchId", |
| 78 | + jsonb_object_agg(mp.parent_key, '{}'::jsonb) AS new_keys |
| 79 | + FROM missing_parents mp |
| 80 | + GROUP BY mp."projectId", mp."branchId" |
| 81 | +), |
| 82 | +updated_with_keys AS ( |
| 83 | + -- Update rows that need new parent keys |
| 84 | + UPDATE /* SCHEMA_NAME_SENTINEL */."EnvironmentConfigOverride" eco |
| 85 | + SET |
| 86 | + "config" = eco."config" || pta.new_keys, |
| 87 | + "updatedAt" = NOW(), |
| 88 | + "temp_trusted_domains_checked" = TRUE |
| 89 | + FROM parents_to_add pta |
| 90 | + WHERE eco."projectId" = pta."projectId" |
| 91 | + AND eco."branchId" = pta."branchId" |
| 92 | + RETURNING eco."projectId", eco."branchId" |
| 93 | +), |
| 94 | +marked_as_checked AS ( |
| 95 | + -- Mark all checked rows (including ones that didn't need fixing) |
| 96 | + UPDATE /* SCHEMA_NAME_SENTINEL */."EnvironmentConfigOverride" eco |
| 97 | + SET "temp_trusted_domains_checked" = TRUE |
| 98 | + FROM rows_to_check rtc |
| 99 | + WHERE eco."projectId" = rtc."projectId" |
| 100 | + AND eco."branchId" = rtc."branchId" |
| 101 | + AND NOT EXISTS ( |
| 102 | + SELECT 1 FROM updated_with_keys uwk |
| 103 | + WHERE uwk."projectId" = eco."projectId" |
| 104 | + AND uwk."branchId" = eco."branchId" |
| 105 | + ) |
| 106 | + RETURNING eco."projectId" |
| 107 | +) |
| 108 | +SELECT COUNT(*) > 0 AS should_repeat_migration |
| 109 | +FROM rows_to_check; |
| 110 | +-- SPLIT_STATEMENT_SENTINEL |
| 111 | + |
| 112 | +-- Clean up: drop temporary index (outside transaction since CREATE was also outside) |
| 113 | +-- SPLIT_STATEMENT_SENTINEL |
| 114 | +-- SINGLE_STATEMENT_SENTINEL |
| 115 | +-- RUN_OUTSIDE_TRANSACTION_SENTINEL |
| 116 | +DROP INDEX IF EXISTS /* SCHEMA_NAME_SENTINEL */."temp_eco_trusted_domains_checked_idx"; |
| 117 | +-- SPLIT_STATEMENT_SENTINEL |
| 118 | + |
| 119 | +-- Clean up: drop temporary column (outside transaction) |
| 120 | +-- SPLIT_STATEMENT_SENTINEL |
| 121 | +-- SINGLE_STATEMENT_SENTINEL |
| 122 | +-- RUN_OUTSIDE_TRANSACTION_SENTINEL |
| 123 | +ALTER TABLE /* SCHEMA_NAME_SENTINEL */."EnvironmentConfigOverride" DROP COLUMN IF EXISTS "temp_trusted_domains_checked"; |
0 commit comments