diff --git a/internal/database/migrations/008_separate_official_metadata.sql b/internal/database/migrations/008_separate_official_metadata.sql index 767a7bb..a0b4af4 100644 --- a/internal/database/migrations/008_separate_official_metadata.sql +++ b/internal/database/migrations/008_separate_official_metadata.sql @@ -6,7 +6,7 @@ BEGIN; -- Add new columns for official metadata and core identifiers ALTER TABLE servers ADD COLUMN server_name VARCHAR(255); ALTER TABLE servers ADD COLUMN version VARCHAR(255); -ALTER TABLE servers ADD COLUMN status VARCHAR(50); +ALTER TABLE servers ADD COLUMN status VARCHAR(50) DEFAULT 'active'; ALTER TABLE servers ADD COLUMN published_at TIMESTAMP WITH TIME ZONE; ALTER TABLE servers ADD COLUMN updated_at TIMESTAMP WITH TIME ZONE; ALTER TABLE servers ADD COLUMN is_latest BOOLEAN; @@ -38,16 +38,16 @@ BEGIN -- Note: status is at top level in old format, not in official_meta UPDATE servers SET - status = COALESCE(NULLIF(rec.value->>'status', 'null'), 'active'), - published_at = (official_meta->>'publishedAt')::TIMESTAMP WITH TIME ZONE, - updated_at = (official_meta->>'updatedAt')::TIMESTAMP WITH TIME ZONE, - is_latest = (official_meta->>'isLatest')::BOOLEAN + status = rec.value->>'status', + published_at = COALESCE((official_meta->>'publishedAt')::TIMESTAMP WITH TIME ZONE, NOW()), + updated_at = COALESCE((official_meta->>'updatedAt')::TIMESTAMP WITH TIME ZONE, NOW()), + is_latest = COALESCE((official_meta->>'isLatest')::BOOLEAN, true) WHERE version_id = rec.version_id; ELSE -- Handle records without official metadata (set defaults) UPDATE servers SET - status = COALESCE(NULLIF(rec.value->>'status', 'null'), 'active'), + status = rec.value->>'status', published_at = NOW(), updated_at = NOW(), is_latest = true @@ -82,11 +82,53 @@ SELECT migrate_official_metadata(); -- Drop the migration function DROP FUNCTION migrate_official_metadata(); +-- Safety check: Normalize invalid status values before adding NOT NULL constraints +-- This handles: NULL (missing field), empty string, string "null", and any invalid values +UPDATE servers +SET status = 'active' +WHERE status IS NULL + OR status = '' + OR status = 'null' + OR status NOT IN ('active', 'deprecated', 'deleted'); + +UPDATE servers SET published_at = NOW() WHERE published_at IS NULL; + +-- Safety check: Ensure updated_at is never NULL +UPDATE servers SET updated_at = NOW() WHERE updated_at IS NULL; + +-- For is_latest: preserve existing true values, handle NULLs deterministically +-- First, for servers where NO version has is_latest=true, mark the most recent as latest +WITH servers_without_latest AS ( + SELECT DISTINCT s1.server_name + FROM servers s1 + WHERE NOT EXISTS ( + SELECT 1 FROM servers s2 + WHERE s2.server_name = s1.server_name + AND s2.is_latest = true + ) +), +latest_versions AS ( + SELECT s.server_name, MAX(s.published_at) as max_published + FROM servers s + INNER JOIN servers_without_latest swl ON s.server_name = swl.server_name + GROUP BY s.server_name +) +UPDATE servers s +SET is_latest = true +FROM latest_versions lv +WHERE s.server_name = lv.server_name + AND s.published_at = lv.max_published + AND s.is_latest IS NULL; + +-- Finally, set remaining NULLs to false +UPDATE servers SET is_latest = false WHERE is_latest IS NULL; + -- Make the new columns NOT NULL now that all records have values ALTER TABLE servers ALTER COLUMN server_name SET NOT NULL; ALTER TABLE servers ALTER COLUMN version SET NOT NULL; ALTER TABLE servers ALTER COLUMN status SET NOT NULL; ALTER TABLE servers ALTER COLUMN published_at SET NOT NULL; +ALTER TABLE servers ALTER COLUMN updated_at SET NOT NULL; ALTER TABLE servers ALTER COLUMN is_latest SET NOT NULL; -- Drop the old primary key constraint @@ -112,7 +154,7 @@ CREATE INDEX idx_servers_name_version ON servers (server_name, version); CREATE INDEX idx_servers_name_latest ON servers (server_name, is_latest) WHERE is_latest = true; CREATE INDEX idx_servers_status ON servers (status); CREATE INDEX idx_servers_published_at ON servers (published_at DESC); -CREATE INDEX idx_servers_updated_at ON servers (updated_at DESC) WHERE updated_at IS NOT NULL; +CREATE INDEX idx_servers_updated_at ON servers (updated_at DESC); -- Ensure only one version per server can be marked as latest CREATE UNIQUE INDEX idx_unique_latest_per_server