diff --git a/server/datastore/mysql/migrations/tables/20250922083056_AddTableMDMAndroidProfiles.go b/server/datastore/mysql/migrations/tables/20250922083056_AddTableMDMAndroidProfiles.go index bf1b328d18..b6bc9576c8 100644 --- a/server/datastore/mysql/migrations/tables/20250922083056_AddTableMDMAndroidProfiles.go +++ b/server/datastore/mysql/migrations/tables/20250922083056_AddTableMDMAndroidProfiles.go @@ -127,7 +127,6 @@ ALTER TABLE mdm_configuration_profile_labels ADD COLUMN android_profile_uuid VARCHAR(37) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, ADD FOREIGN KEY (android_profile_uuid) REFERENCES mdm_android_configuration_profiles(profile_uuid) ON DELETE CASCADE, ADD UNIQUE KEY idx_mdm_configuration_profile_labels_android_label_name (android_profile_uuid, label_name), - DROP CONSTRAINT ck_mdm_configuration_profile_labels_apple_or_windows, -- only one of apple, android or windows profile uuid must be set ADD CONSTRAINT ck_mdm_configuration_profile_labels_profile_uuid CHECK (IF(ISNULL(apple_profile_uuid), 0, 1) + IF(ISNULL(windows_profile_uuid), 0, 1) + IF(ISNULL(android_profile_uuid), 0, 1) = 1) @@ -136,6 +135,27 @@ ALTER TABLE mdm_configuration_profile_labels return fmt.Errorf("alter mdm_configuration_profile_labels table: %w", err) } + // our mysql version at the time this constraint was added did not support CHECK constraints so this may or may not exist for us + // to delete, so we create the new wider constraint above then, optionally, delete the older narrow one + checkIfOldConstraintExists := ` + SELECT COUNT(*) + FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS + WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_TYPE = 'CHECK' AND TABLE_NAME = 'mdm_configuration_profile_labels' + AND CONSTRAINT_NAME = 'ck_mdm_configuration_profile_labels_apple_or_windows'` + var constraintCount int + if err := tx.QueryRow(checkIfOldConstraintExists).Scan(&constraintCount); err != nil { + return fmt.Errorf("check for old CHECK constraint on mdm_configuration_profile_labels: %w", err) + } + if constraintCount > 0 { + dropOldConstraint := ` + ALTER TABLE mdm_configuration_profile_labels + DROP CONSTRAINT ck_mdm_configuration_profile_labels_apple_or_windows + ` + if _, err := tx.Exec(dropOldConstraint); err != nil { + return fmt.Errorf("drop old CHECK constraint on mdm_configuration_profile_labels: %w", err) + } + } + alterAndroidDevicesTable := ` ALTER TABLE android_devices ADD COLUMN applied_policy_id VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL, diff --git a/server/datastore/mysql/migrations/tables/20250922083056_AddTableMDMAndroidProfiles_test.go b/server/datastore/mysql/migrations/tables/20250922083056_AddTableMDMAndroidProfiles_test.go index 7ed3471c83..5cee33ad67 100644 --- a/server/datastore/mysql/migrations/tables/20250922083056_AddTableMDMAndroidProfiles_test.go +++ b/server/datastore/mysql/migrations/tables/20250922083056_AddTableMDMAndroidProfiles_test.go @@ -104,3 +104,11 @@ func TestUp_20250922083056(t *testing.T) { // empty android host got updated, non-empty stayed the same, mac host not updated require.Equal(t, []string{"from-enterprise", "got-one", ""}, got) } + +func TestUp_20250922083056_checkconstraint_missing(t *testing.T) { + // Create a DB without the old apple-or-windows constraint and verify the migration does not error + db := applyUpToPrev(t) + _, err := db.Exec(`ALTER TABLE mdm_configuration_profile_labels DROP CONSTRAINT ck_mdm_configuration_profile_labels_apple_or_windows`) + require.NoError(t, err) + applyNext(t, db) +}