223 lines
9.4 KiB
SQL
223 lines
9.4 KiB
SQL
-- Hard-cut: central status/outcome taxonomy with deterministic cleanup and CHECK constraints.
|
|
|
|
-- Preflight: count invalid values per in-scope column before cleanup.
|
|
SELECT 'system_audit_log.outcome' AS field_name, COUNT(*) AS invalid_count
|
|
FROM system_audit_log
|
|
WHERE outcome IS NULL OR outcome NOT IN ('success', 'failed', 'denied');
|
|
|
|
SELECT 'system_audit_log.channel' AS field_name, COUNT(*) AS invalid_count
|
|
FROM system_audit_log
|
|
WHERE channel IS NULL OR channel NOT IN ('web', 'api', 'scheduler', 'cli');
|
|
|
|
SELECT 'user_lifecycle_audit_log.action' AS field_name, COUNT(*) AS invalid_count
|
|
FROM user_lifecycle_audit_log
|
|
WHERE action IS NULL OR action NOT IN ('deactivate', 'delete', 'restore');
|
|
|
|
SELECT 'user_lifecycle_audit_log.trigger_type' AS field_name, COUNT(*) AS invalid_count
|
|
FROM user_lifecycle_audit_log
|
|
WHERE trigger_type IS NULL OR trigger_type NOT IN ('manual', 'cron', 'system');
|
|
|
|
SELECT 'user_lifecycle_audit_log.status' AS field_name, COUNT(*) AS invalid_count
|
|
FROM user_lifecycle_audit_log
|
|
WHERE status IS NULL OR status NOT IN ('success', 'skipped', 'failed');
|
|
|
|
SELECT 'import_audit_runs.status' AS field_name, COUNT(*) AS invalid_count
|
|
FROM import_audit_runs
|
|
WHERE status IS NULL OR status NOT IN ('running', 'success', 'partial', 'failed');
|
|
|
|
SELECT 'scheduled_jobs.last_run_status' AS field_name, COUNT(*) AS invalid_count
|
|
FROM scheduled_jobs
|
|
WHERE last_run_status IS NOT NULL AND last_run_status NOT IN ('running', 'success', 'failed', 'skipped');
|
|
|
|
SELECT 'scheduled_job_runs.status' AS field_name, COUNT(*) AS invalid_count
|
|
FROM scheduled_job_runs
|
|
WHERE status IS NULL OR status NOT IN ('success', 'failed', 'skipped');
|
|
|
|
SELECT 'scheduled_job_runs.trigger_type' AS field_name, COUNT(*) AS invalid_count
|
|
FROM scheduled_job_runs
|
|
WHERE trigger_type IS NULL OR trigger_type NOT IN ('scheduler', 'manual');
|
|
|
|
SELECT 'mail_log.status' AS field_name, COUNT(*) AS invalid_count
|
|
FROM mail_log
|
|
WHERE status IS NULL OR status NOT IN ('queued', 'sent', 'failed');
|
|
|
|
SELECT 'tenants.status' AS field_name, COUNT(*) AS invalid_count
|
|
FROM tenants
|
|
WHERE status IS NULL OR status NOT IN ('active', 'inactive');
|
|
|
|
SELECT 'scheduler_runtime_status.last_result' AS field_name, COUNT(*) AS invalid_count
|
|
FROM scheduler_runtime_status
|
|
WHERE last_result IS NOT NULL AND last_result NOT IN ('ok', 'lock_not_acquired', 'unexpected_error');
|
|
|
|
-- Deterministic normalization before constraints.
|
|
UPDATE system_audit_log
|
|
SET outcome = 'success'
|
|
WHERE outcome IS NULL OR outcome NOT IN ('success', 'failed', 'denied');
|
|
|
|
UPDATE system_audit_log
|
|
SET channel = 'web'
|
|
WHERE channel IS NULL OR channel NOT IN ('web', 'api', 'scheduler', 'cli');
|
|
|
|
UPDATE user_lifecycle_audit_log
|
|
SET action = 'deactivate'
|
|
WHERE action IS NULL OR action NOT IN ('deactivate', 'delete', 'restore');
|
|
|
|
UPDATE user_lifecycle_audit_log
|
|
SET trigger_type = 'system'
|
|
WHERE trigger_type IS NULL OR trigger_type NOT IN ('manual', 'cron', 'system');
|
|
|
|
UPDATE user_lifecycle_audit_log
|
|
SET status = 'failed'
|
|
WHERE status IS NULL OR status NOT IN ('success', 'skipped', 'failed');
|
|
|
|
UPDATE import_audit_runs
|
|
SET status = 'failed'
|
|
WHERE status IS NULL OR status NOT IN ('running', 'success', 'partial', 'failed');
|
|
|
|
UPDATE scheduled_jobs
|
|
SET last_run_status = NULL
|
|
WHERE last_run_status IS NOT NULL AND last_run_status NOT IN ('running', 'success', 'failed', 'skipped');
|
|
|
|
UPDATE scheduled_job_runs
|
|
SET status = 'failed'
|
|
WHERE status IS NULL OR status NOT IN ('success', 'failed', 'skipped');
|
|
|
|
UPDATE scheduled_job_runs
|
|
SET trigger_type = 'scheduler'
|
|
WHERE trigger_type IS NULL OR trigger_type NOT IN ('scheduler', 'manual');
|
|
|
|
UPDATE mail_log
|
|
SET status = 'queued'
|
|
WHERE status IS NULL OR status NOT IN ('queued', 'sent', 'failed');
|
|
|
|
UPDATE tenants
|
|
SET status = 'active'
|
|
WHERE status IS NULL OR status NOT IN ('active', 'inactive');
|
|
|
|
UPDATE scheduler_runtime_status
|
|
SET last_result = NULL
|
|
WHERE last_result IS NOT NULL AND last_result NOT IN ('ok', 'lock_not_acquired', 'unexpected_error');
|
|
|
|
-- Add CHECK constraints once (idempotent via information_schema guard).
|
|
SET @schema_name := DATABASE();
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'system_audit_log'
|
|
AND constraint_name = 'chk_system_audit_log_outcome') = 0,
|
|
'ALTER TABLE system_audit_log ADD CONSTRAINT chk_system_audit_log_outcome CHECK (outcome IN (''success'', ''failed'', ''denied''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'system_audit_log'
|
|
AND constraint_name = 'chk_system_audit_log_channel') = 0,
|
|
'ALTER TABLE system_audit_log ADD CONSTRAINT chk_system_audit_log_channel CHECK (channel IN (''web'', ''api'', ''scheduler'', ''cli''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'user_lifecycle_audit_log'
|
|
AND constraint_name = 'chk_user_lifecycle_action') = 0,
|
|
'ALTER TABLE user_lifecycle_audit_log ADD CONSTRAINT chk_user_lifecycle_action CHECK (action IN (''deactivate'', ''delete'', ''restore''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'user_lifecycle_audit_log'
|
|
AND constraint_name = 'chk_user_lifecycle_trigger_type') = 0,
|
|
'ALTER TABLE user_lifecycle_audit_log ADD CONSTRAINT chk_user_lifecycle_trigger_type CHECK (trigger_type IN (''manual'', ''cron'', ''system''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'user_lifecycle_audit_log'
|
|
AND constraint_name = 'chk_user_lifecycle_status') = 0,
|
|
'ALTER TABLE user_lifecycle_audit_log ADD CONSTRAINT chk_user_lifecycle_status CHECK (status IN (''success'', ''skipped'', ''failed''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'import_audit_runs'
|
|
AND constraint_name = 'chk_import_audit_runs_status') = 0,
|
|
'ALTER TABLE import_audit_runs ADD CONSTRAINT chk_import_audit_runs_status CHECK (status IN (''running'', ''success'', ''partial'', ''failed''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'scheduled_jobs'
|
|
AND constraint_name = 'chk_scheduled_jobs_last_run_status') = 0,
|
|
'ALTER TABLE scheduled_jobs ADD CONSTRAINT chk_scheduled_jobs_last_run_status CHECK (last_run_status IS NULL OR last_run_status IN (''running'', ''success'', ''failed'', ''skipped''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'scheduled_job_runs'
|
|
AND constraint_name = 'chk_scheduled_job_runs_status') = 0,
|
|
'ALTER TABLE scheduled_job_runs ADD CONSTRAINT chk_scheduled_job_runs_status CHECK (status IN (''success'', ''failed'', ''skipped''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'scheduled_job_runs'
|
|
AND constraint_name = 'chk_scheduled_job_runs_trigger_type') = 0,
|
|
'ALTER TABLE scheduled_job_runs ADD CONSTRAINT chk_scheduled_job_runs_trigger_type CHECK (trigger_type IN (''scheduler'', ''manual''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'mail_log'
|
|
AND constraint_name = 'chk_mail_log_status') = 0,
|
|
'ALTER TABLE mail_log ADD CONSTRAINT chk_mail_log_status CHECK (status IN (''queued'', ''sent'', ''failed''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'tenants'
|
|
AND constraint_name = 'chk_tenants_status') = 0,
|
|
'ALTER TABLE tenants ADD CONSTRAINT chk_tenants_status CHECK (status IN (''active'', ''inactive''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @sql := IF(
|
|
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
WHERE constraint_schema = @schema_name
|
|
AND table_name = 'scheduler_runtime_status'
|
|
AND constraint_name = 'chk_scheduler_runtime_status_last_result') = 0,
|
|
'ALTER TABLE scheduler_runtime_status ADD CONSTRAINT chk_scheduler_runtime_status_last_result CHECK (last_result IS NULL OR last_result IN (''ok'', ''lock_not_acquired'', ''unexpected_error''))',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|