diff options
author | Mike Young <mike.young@sonarsource.com> | 2025-07-02 15:46:56 -0400 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2025-07-02 20:04:24 +0000 |
commit | 99b6c70a7d74a92bf45e2c0a6af465c3937df549 (patch) | |
tree | 3faa024bb3629cf770b7d696157e9428ba384d8a /server/sonar-db-migration | |
parent | 5bec6b354f7e8e3af1181bebebf8a73c7b186bca (diff) | |
download | sonarqube-master.tar.gz sonarqube-master.zip |
Diffstat (limited to 'server/sonar-db-migration')
7 files changed, 388 insertions, 1 deletions
diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202504/AddOriginalAndManualSeverityToScaIssuesTest.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202504/AddOriginalAndManualSeverityToScaIssuesTest.java new file mode 100644 index 00000000000..0fdbda384a9 --- /dev/null +++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202504/AddOriginalAndManualSeverityToScaIssuesTest.java @@ -0,0 +1,63 @@ +/* + * SonarQube + * Copyright (C) 2009-2025 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform.db.migration.version.v202504; + +import java.sql.SQLException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.db.MigrationDbTester; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static java.sql.Types.VARCHAR; +import static org.sonar.db.MigrationDbTester.createForMigrationStep; +import static org.sonar.server.platform.db.migration.version.v202504.AddOriginalAndManualSeverityToScaIssues.MANUALLY_SET_COLUMN_NAME; +import static org.sonar.server.platform.db.migration.version.v202504.AddOriginalAndManualSeverityToScaIssues.ORIGINAL_VALUE_COLUMN_NAME; +import static org.sonar.server.platform.db.migration.version.v202504.AddOriginalAndManualSeverityToScaIssues.TABLE_NAME; + +class AddOriginalAndManualSeverityToScaIssuesTest { + + @RegisterExtension + public final MigrationDbTester db = createForMigrationStep(AddOriginalAndManualSeverityToScaIssues.class); + private final DdlChange underTest = new AddOriginalAndManualSeverityToScaIssues(db.database()); + + @Test + void execute_shouldAddCalculatedValueColumn() throws SQLException { + db.assertColumnDoesNotExist(TABLE_NAME, ORIGINAL_VALUE_COLUMN_NAME); + underTest.execute(); + db.assertColumnDefinition(TABLE_NAME, ORIGINAL_VALUE_COLUMN_NAME, VARCHAR, 15, true); + } + + @Test + void execute_shouldAddManuallySetColumn() throws SQLException { + db.assertColumnDoesNotExist(TABLE_NAME, MANUALLY_SET_COLUMN_NAME); + underTest.execute(); + db.assertColumnDefinition(TABLE_NAME, MANUALLY_SET_COLUMN_NAME, VARCHAR, 15, true); + } + + @Test + void execute_shouldBeReentrant() throws SQLException { + db.assertColumnDoesNotExist(TABLE_NAME, ORIGINAL_VALUE_COLUMN_NAME); + db.assertColumnDoesNotExist(TABLE_NAME, MANUALLY_SET_COLUMN_NAME); + underTest.execute(); + underTest.execute(); + db.assertColumnDefinition(TABLE_NAME, ORIGINAL_VALUE_COLUMN_NAME, VARCHAR, 15, true); + db.assertColumnDefinition(TABLE_NAME, MANUALLY_SET_COLUMN_NAME, VARCHAR, 15, true); + } +} diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202504/PopulateOriginalSeverityForScaIssuesReleasesTableIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202504/PopulateOriginalSeverityForScaIssuesReleasesTableIT.java new file mode 100644 index 00000000000..31091c17fc1 --- /dev/null +++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202504/PopulateOriginalSeverityForScaIssuesReleasesTableIT.java @@ -0,0 +1,80 @@ +/* + * SonarQube + * Copyright (C) 2009-2025 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform.db.migration.version.v202504; + +import java.sql.SQLException; +import java.util.Date; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.db.MigrationDbTester; + +import static org.assertj.core.api.Assertions.assertThat; + +class PopulateOriginalSeverityForScaIssuesReleasesTableIT { + @RegisterExtension + public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(PopulateOriginalSeverityForScaIssuesReleasesTable.class); + private final PopulateOriginalSeverityForScaIssuesReleasesTable underTest = new PopulateOriginalSeverityForScaIssuesReleasesTable(db.database()); + + @Test + void execute_shouldPopulateOriginaldSeverity() throws SQLException { + insertScaIssuesReleases(1, "HIGH", null); + insertScaIssuesReleases(2, "INFO", null); + + underTest.execute(); + + assertThatOriginalSeverityIs(1, "HIGH"); + assertThatOriginalSeverityIs(2, "INFO"); + } + + @Test + void execute_whenAlreadyExecuted_shouldBeIdempotent() throws SQLException { + insertScaIssuesReleases(1, "HIGH", "INFO"); + + underTest.execute(); + underTest.execute(); + + assertThatOriginalSeverityIs(1, "INFO"); + } + + private void insertScaIssuesReleases(Integer index, String severity, @Nullable String originalSeverity) { + db.executeInsert("sca_issues_releases", + "uuid", "uuid-" + index, + "sca_issue_uuid", "issue_id" + index, + "sca_release_uuid", "release_id", + "status", "TO_REVIEW", + "severity", severity, + "original_severity", originalSeverity, + "manual_severity", null, + "severity_sort_key", 1, + "created_at", new Date().getTime(), + "updated_at", new Date().getTime() + ); + } + + private void assertThatOriginalSeverityIs(Integer index, String expectedSeverity) { + String uuid = "uuid-" + index; + List<Map<String, Object>> rows = db.select("select original_severity from sca_issues_releases where uuid = '%s'".formatted(uuid)); + assertThat(rows).isNotEmpty() + .allSatisfy(row -> assertThat(row).containsEntry("original_severity", expectedSeverity)); + } +} diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202504/UpdateScaIssuesReleasesOriginalSeverityColumnNotNullableTestIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202504/UpdateScaIssuesReleasesOriginalSeverityColumnNotNullableTestIT.java new file mode 100644 index 00000000000..2e194f52ec6 --- /dev/null +++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202504/UpdateScaIssuesReleasesOriginalSeverityColumnNotNullableTestIT.java @@ -0,0 +1,68 @@ +/* + * SonarQube + * Copyright (C) 2009-2025 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform.db.migration.version.v202504; + +import java.sql.SQLException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.db.MigrationDbTester; +import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder; + +import static java.sql.Types.VARCHAR; +import static org.assertj.core.api.Assertions.assertThatCode; + +class UpdateScaIssuesReleasesOriginalSeverityColumnNotNullableTestIT { + static final String TABLE_NAME = "sca_issues_releases"; + static final String COLUMN_NAME = "original_severity"; + static final int COLUMN_SIZE = 15; + + @RegisterExtension + public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(UpdateScaIssuesReleasesOriginalSeverityColumnNotNullable.class); + + private final UpdateScaIssuesReleasesOriginalSeverityColumnNotNullable underTest = new UpdateScaIssuesReleasesOriginalSeverityColumnNotNullable(db.database()); + + @Test + void execute_whenColumnExists_shouldMakeColumnNotNull() throws SQLException { + // Verify column is nullable before update + db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, VARCHAR, COLUMN_SIZE, true); + + underTest.execute(); + + // Verify column is not nullable after update + db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, VARCHAR, COLUMN_SIZE, false); + } + + @Test + void execute_whenColumnDoesNotExist_shouldNotFail() throws SQLException { + // Ensure the column does not exist before executing the migration + DropColumnsBuilder dropColumnsBuilder = new DropColumnsBuilder(db.database().getDialect(), TABLE_NAME, COLUMN_NAME); + dropColumnsBuilder.build().forEach(db::executeDdl); + + db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME); + assertThatCode(underTest::execute).doesNotThrowAnyException(); + } + + @Test + void execute_whenExecutedTwice_shouldBeIdempotent() throws SQLException { + underTest.execute(); + assertThatCode(underTest::execute).doesNotThrowAnyException(); + db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, VARCHAR, COLUMN_SIZE, false); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/AddOriginalAndManualSeverityToScaIssues.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/AddOriginalAndManualSeverityToScaIssues.java new file mode 100644 index 00000000000..66c4c27254e --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/AddOriginalAndManualSeverityToScaIssues.java @@ -0,0 +1,67 @@ +/* + * SonarQube + * Copyright (C) 2009-2025 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform.db.migration.version.v202504; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.def.VarcharColumnDef; +import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.db.DatabaseUtils.tableColumnExists; + +public class AddOriginalAndManualSeverityToScaIssues extends DdlChange { + static final String TABLE_NAME = "sca_issues_releases"; + static final String ORIGINAL_VALUE_COLUMN_NAME = "original_severity"; + static final String MANUALLY_SET_COLUMN_NAME = "manual_severity"; + + public AddOriginalAndManualSeverityToScaIssues(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + try (var connection = getDatabase().getDataSource().getConnection()) { + if (!tableColumnExists(connection, TABLE_NAME, ORIGINAL_VALUE_COLUMN_NAME)) { + var columnDef = VarcharColumnDef.newVarcharColumnDefBuilder() + .setColumnName(ORIGINAL_VALUE_COLUMN_NAME) + .setLimit(15) + .setIsNullable(true) + .build(); + + context.execute(new AddColumnsBuilder(getDialect(), TABLE_NAME) + .addColumn(columnDef) + .build()); + } + + if (!tableColumnExists(connection, TABLE_NAME, MANUALLY_SET_COLUMN_NAME)) { + var columnDef = VarcharColumnDef.newVarcharColumnDefBuilder() + .setColumnName(MANUALLY_SET_COLUMN_NAME) + .setLimit(15) + .setIsNullable(true) + .build(); + + context.execute(new AddColumnsBuilder(getDialect(), TABLE_NAME) + .addColumn(columnDef) + .build()); + } + } + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/DbVersion202504.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/DbVersion202504.java index ac608e306a5..97a956b6ca7 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/DbVersion202504.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/DbVersion202504.java @@ -33,6 +33,11 @@ public class DbVersion202504 implements DbVersion { .add(2025_04_001, "Add 'organization_uuid' column to 'sca_license_profiles' table", AddOrganizationUuidToScaLicenseProfiles.class) .add(2025_04_002, "Drop unique index from 'sca_license_profiles'", DropUniqueIndexOnScaLicenseProfiles.class) .add(2025_04_003, "Create unique index from 'sca_license_profiles'", CreateUniqueIndexOnScaLicenseProfiles.class) - .add(2025_04_004, "Add index on 'alm_repo' column in 'project_alm_settings' table", AddIndexOnAlmRepoInProjectAlmSettings.class); + .add(2025_04_004, "Add index on 'alm_repo' column in 'project_alm_settings' table", AddIndexOnAlmRepoInProjectAlmSettings.class) + .add(2025_04_005, "Add 'original_severity' and 'manual_severity' columns to 'sca_issues_releases' table", AddOriginalAndManualSeverityToScaIssues.class) + .add(2025_04_006, "Populate 'original_severity' column for 'sca_issues_releases' table", PopulateOriginalSeverityForScaIssuesReleasesTable.class) + .add(2025_04_007, "Update 'original_severity' column to be not nullable in 'sca_issues_releases' table", UpdateScaIssuesReleasesOriginalSeverityColumnNotNullable.class) + + ; } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/PopulateOriginalSeverityForScaIssuesReleasesTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/PopulateOriginalSeverityForScaIssuesReleasesTable.java new file mode 100644 index 00000000000..bcee5bb0903 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/PopulateOriginalSeverityForScaIssuesReleasesTable.java @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2025 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform.db.migration.version.v202504; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.step.DataChange; +import org.sonar.server.platform.db.migration.step.MassUpdate; + +public class PopulateOriginalSeverityForScaIssuesReleasesTable extends DataChange { + private static final String SELECT_QUERY = "select severity, uuid from sca_issues_releases where original_severity is null"; + private static final String UPDATE_QUERY = "update sca_issues_releases set original_severity = ? where uuid = ?"; + + public PopulateOriginalSeverityForScaIssuesReleasesTable(Database db) { + super(db); + } + + @Override + protected void execute(Context context) throws SQLException { + MassUpdate massUpdate = context.prepareMassUpdate(); + massUpdate.select(SELECT_QUERY); + massUpdate.update(UPDATE_QUERY); + + massUpdate.execute((row, update, index) -> { + update + // Set original_severity from severity + .setString(1, row.getString(1)) + // Set uuid from uuid + .setString(2, row.getString(2)); + return true; + }); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/UpdateScaIssuesReleasesOriginalSeverityColumnNotNullable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/UpdateScaIssuesReleasesOriginalSeverityColumnNotNullable.java new file mode 100644 index 00000000000..4c842e81e1f --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202504/UpdateScaIssuesReleasesOriginalSeverityColumnNotNullable.java @@ -0,0 +1,54 @@ +/* + * SonarQube + * Copyright (C) 2009-2025 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform.db.migration.version.v202504; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.def.VarcharColumnDef; +import org.sonar.server.platform.db.migration.sql.AlterColumnsBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.db.DatabaseUtils.tableColumnExists; + +public class UpdateScaIssuesReleasesOriginalSeverityColumnNotNullable extends DdlChange { + static final String TABLE_NAME = "sca_issues_releases"; + static final String COLUMN_NAME = "original_severity"; + + public UpdateScaIssuesReleasesOriginalSeverityColumnNotNullable(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + try (var connection = getDatabase().getDataSource().getConnection()) { + if (tableColumnExists(connection, TABLE_NAME, COLUMN_NAME)) { + var columnDef = VarcharColumnDef.newVarcharColumnDefBuilder() + .setColumnName(COLUMN_NAME) + .setIsNullable(false) + .setLimit(15) + .build(); + + context.execute(new AlterColumnsBuilder(getDialect(), TABLE_NAME) + .updateColumn(columnDef) + .build()); + } + } + } +} |