diff options
author | Claire Villard <60586848+claire-villard-sonarsource@users.noreply.github.com> | 2024-09-27 09:57:19 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2024-10-09 20:02:47 +0000 |
commit | e8ef7e9b39e0ea580d82df8b7b4fabbcc6e41f01 (patch) | |
tree | d5a488342abfecf96e914f18cf735c769901b9eb /server/sonar-db-migration | |
parent | a79666b02068f247ea26944d3ea0d0181365c3b7 (diff) | |
download | sonarqube-e8ef7e9b39e0ea580d82df8b7b4fabbcc6e41f01.tar.gz sonarqube-e8ef7e9b39e0ea580d82df8b7b4fabbcc6e41f01.zip |
SONAR-22880 Migrate 'live_measures' to 'measures'
Diffstat (limited to 'server/sonar-db-migration')
17 files changed, 1082 insertions, 5 deletions
diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToPortfoliosTableIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToPortfoliosTableIT.java new file mode 100644 index 00000000000..000681ae3b6 --- /dev/null +++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToPortfoliosTableIT.java @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import java.sql.SQLException; +import java.sql.Types; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.db.MigrationDbTester; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; +import static org.sonar.server.platform.db.migration.version.v107.AddMeasuresMigratedColumnToPortfoliosTable.MIGRATION_FLAG_COLUMN_NAME; +import static org.sonar.server.platform.db.migration.version.v107.AddMeasuresMigratedColumnToPortfoliosTable.PORTFOLIOS_TABLE_NAME; + +class AddMeasuresMigratedColumnToPortfoliosTableIT { + + @RegisterExtension + public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(AddMeasuresMigratedColumnToPortfoliosTable.class); + private final AddMeasuresMigratedColumnToPortfoliosTable underTest = new AddMeasuresMigratedColumnToPortfoliosTable(db.database()); + + @Test + void execute_whenColumnDoesNotExist_shouldCreateColumn() throws SQLException { + db.assertColumnDoesNotExist(PORTFOLIOS_TABLE_NAME, MIGRATION_FLAG_COLUMN_NAME); + underTest.execute(); + db.assertColumnDefinition(PORTFOLIOS_TABLE_NAME, MIGRATION_FLAG_COLUMN_NAME, Types.BOOLEAN, null, false); + } + + @Test + void execute_whenColumnAlreadyExists_shouldNotFail() throws SQLException { + underTest.execute(); + assertThatCode(underTest::execute).doesNotThrowAnyException(); + } +} diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToProjectBranchesTableIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToProjectBranchesTableIT.java new file mode 100644 index 00000000000..8971111f7ee --- /dev/null +++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToProjectBranchesTableIT.java @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import java.sql.SQLException; +import java.sql.Types; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.db.MigrationDbTester; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; +import static org.sonar.server.platform.db.migration.version.v107.AddMeasuresMigratedColumnToProjectBranchesTable.MIGRATION_FLAG_COLUMN_NAME; +import static org.sonar.server.platform.db.migration.version.v107.AddMeasuresMigratedColumnToProjectBranchesTable.PROJECT_BRANCHES_TABLE_NAME; + +class AddMeasuresMigratedColumnToProjectBranchesTableIT { + + @RegisterExtension + public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(AddMeasuresMigratedColumnToProjectBranchesTable.class); + private final AddMeasuresMigratedColumnToProjectBranchesTable underTest = new AddMeasuresMigratedColumnToProjectBranchesTable(db.database()); + + @Test + void execute_whenColumnDoesNotExist_shouldCreateColumn() throws SQLException { + db.assertColumnDoesNotExist(PROJECT_BRANCHES_TABLE_NAME, MIGRATION_FLAG_COLUMN_NAME); + underTest.execute(); + db.assertColumnDefinition(PROJECT_BRANCHES_TABLE_NAME, MIGRATION_FLAG_COLUMN_NAME, Types.BOOLEAN, null, false); + } + + @Test + void execute_whenColumnAlreadyExists_shouldNotFail() throws SQLException { + underTest.execute(); + assertThatCode(underTest::execute).doesNotThrowAnyException(); + } +} diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnPortfoliosMeasuresMigratedIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnPortfoliosMeasuresMigratedIT.java new file mode 100644 index 00000000000..691c105d8ff --- /dev/null +++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnPortfoliosMeasuresMigratedIT.java @@ -0,0 +1,53 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import java.sql.SQLException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.db.MigrationDbTester; + +import static org.sonar.server.platform.db.migration.version.v107.CreateIndexOnPortfoliosMeasuresMigrated.COLUMN_NAME; +import static org.sonar.server.platform.db.migration.version.v107.CreateIndexOnPortfoliosMeasuresMigrated.TABLE_NAME; + +class CreateIndexOnPortfoliosMeasuresMigratedIT { + + private static final String INDEX_NAME = "portfolios_measures_migrated"; + @RegisterExtension + public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(CreateIndexOnPortfoliosMeasuresMigrated.class); + private final CreateIndexOnPortfoliosMeasuresMigrated underTest = new CreateIndexOnPortfoliosMeasuresMigrated(db.database()); + + @Test + void migration_should_create_index() throws SQLException { + db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME); + + underTest.execute(); + + db.assertIndex(TABLE_NAME, INDEX_NAME, COLUMN_NAME); + } + + @Test + void migration_should_be_reentrant() throws SQLException { + underTest.execute(); + underTest.execute(); + + db.assertIndex(TABLE_NAME, INDEX_NAME, COLUMN_NAME); + } +} diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnProjectBranchesMeasuresMigratedIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnProjectBranchesMeasuresMigratedIT.java new file mode 100644 index 00000000000..3e95ed5611d --- /dev/null +++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnProjectBranchesMeasuresMigratedIT.java @@ -0,0 +1,54 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import java.sql.SQLException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.db.MigrationDbTester; + +import static org.sonar.server.platform.db.migration.version.v107.CreateIndexOnProjectBranchesMeasuresMigrated.COLUMN_NAME; +import static org.sonar.server.platform.db.migration.version.v107.CreateIndexOnProjectBranchesMeasuresMigrated.TABLE_NAME; + +class CreateIndexOnProjectBranchesMeasuresMigratedIT { + + private static final String INDEX_NAME = "pb_measures_migrated"; + + @RegisterExtension + public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(CreateIndexOnProjectBranchesMeasuresMigrated.class); + private final CreateIndexOnProjectBranchesMeasuresMigrated underTest = new CreateIndexOnProjectBranchesMeasuresMigrated(db.database()); + + @Test + void migration_should_create_index() throws SQLException { + db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME); + + underTest.execute(); + + db.assertIndex(TABLE_NAME, INDEX_NAME, COLUMN_NAME); + } + + @Test + void migration_should_be_reentrant() throws SQLException { + underTest.execute(); + underTest.execute(); + + db.assertIndex(TABLE_NAME, INDEX_NAME, COLUMN_NAME); + } +} diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/MigrateBranchesLiveMeasuresToMeasuresIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/MigrateBranchesLiveMeasuresToMeasuresIT.java new file mode 100644 index 00000000000..fda3df82af9 --- /dev/null +++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/MigrateBranchesLiveMeasuresToMeasuresIT.java @@ -0,0 +1,184 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import java.nio.charset.StandardCharsets; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.api.utils.System2; +import org.sonar.core.util.SequenceUuidFactory; +import org.sonar.db.MigrationDbTester; +import org.sonar.server.platform.db.migration.step.DataChange; + +import static java.lang.String.format; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.Mockito.mock; + +class MigrateBranchesLiveMeasuresToMeasuresIT { + + private static final String MEASURES_MIGRATED_COLUMN = "measures_migrated"; + public static final String SELECT_MEASURE = "select component_uuid, branch_uuid, json_value, json_value_hash, created_at, updated_at " + + "from measures where component_uuid = '%s'"; + + @RegisterExtension + public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(MigrateBranchesLiveMeasuresToMeasures.class); + + private final SequenceUuidFactory uuidFactory = new SequenceUuidFactory(); + private final System2 system2 = mock(); + private final DataChange underTest = new MigrateBranchesLiveMeasuresToMeasures(db.database(), system2); + + @Test + void shall_complete_when_tables_are_empty() throws SQLException { + underTest.execute(); + + assertThat(db.countRowsOfTable("measures")).isZero(); + } + + @Test + void shall_not_migrate_when_branch_is_already_flagged() throws SQLException { + String nclocMetricUuid = insertMetric("ncloc", "INT"); + String qgStatusMetricUuid = insertMetric("quality_gate_status", "STRING"); + String metricWithDataUuid = insertMetric("metric_with_data", "DATA"); + String branch1 = "branch_1"; + insertMigratedBranch(branch1); + insertMeasure(branch1, nclocMetricUuid, Map.of("value", 120)); + insertMeasure(branch1, qgStatusMetricUuid, Map.of("text_value", "ok")); + insertMeasure(branch1, metricWithDataUuid, Map.of("measure_data", "some data".getBytes(StandardCharsets.UTF_8))); + + insertMigratedBranch("branch_2"); + insertMeasure("branch_2", nclocMetricUuid, Map.of("value", 14220)); + + underTest.execute(); + + assertThat(db.countRowsOfTable("measures")).isZero(); + } + + @Test + void should_flag_branch_with_no_measures() throws SQLException { + String branch = "branch_3"; + insertNotMigratedBranch(branch); + + underTest.execute(); + + assertBranchMigrated(branch); + assertThat(db.countRowsOfTable("measures")).isZero(); + } + + @Test + void should_migrate_branch_with_measures() throws SQLException { + String nclocMetricUuid = insertMetric("ncloc", "INT"); + String qgStatusMetricUuid = insertMetric("quality_gate_status", "STRING"); + String metricWithDataUuid = insertMetric("metric_with_data", "DATA"); + + String branch1 = "branch_4"; + insertNotMigratedBranch(branch1); + String component1 = uuidFactory.create(); + String component2 = uuidFactory.create(); + insertMeasure(branch1, component1, nclocMetricUuid, Map.of("value", 120)); + insertMeasure(branch1, component1, qgStatusMetricUuid, Map.of("text_value", "ok")); + insertMeasure(branch1, component2, metricWithDataUuid, Map.of("measure_data", "some data".getBytes(StandardCharsets.UTF_8))); + + String branch2 = "branch_5"; + insertNotMigratedBranch(branch2); + insertMeasure(branch2, nclocMetricUuid, Map.of("value", 64)); + + String migratedBranch = "branch_6"; + insertMigratedBranch(migratedBranch); + insertMeasure(migratedBranch, nclocMetricUuid, Map.of("value", 3684)); + + underTest.execute(); + + assertBranchMigrated(branch1); + assertBranchMigrated(branch2); + assertThat(db.countRowsOfTable("measures")).isEqualTo(3); + + assertThat(db.select(format(SELECT_MEASURE, component1))) + .hasSize(1) + .extracting(t -> t.get("component_uuid"), t -> t.get("branch_uuid"), t -> t.get("json_value"), t -> t.get("json_value_hash")) + .containsOnly(tuple(component1, branch1, "{\"ncloc\":120.0,\"quality_gate_status\":\"ok\"}", 6033012287291512746L)); + + assertThat(db.select(format(SELECT_MEASURE, component2))) + .hasSize(1) + .extracting(t -> t.get("component_uuid"), t -> t.get("branch_uuid"), t -> t.get("json_value"), t -> t.get("json_value_hash")) + .containsOnly(tuple(component2, branch1, "{\"metric_with_data\":\"some data\"}", -4524184678167636687L)); + } + + private void assertBranchMigrated(String branch) { + List<Map<String, Object>> result = db.select(format("select %s as \"MIGRATED\" from project_branches where uuid = '%s'", MEASURES_MIGRATED_COLUMN, branch)); + assertThat(result) + .hasSize(1) + .extracting(t -> t.get("MIGRATED")) + .containsOnly(true); + } + + private String insertMetric(String metricName, String valueType) { + String metricUuid = uuidFactory.create(); + db.executeInsert("metrics", + "uuid", metricUuid, + "name", metricName, + "val_type", valueType); + return metricUuid; + } + + private void insertMeasure(String branchUuid, String metricUuid, Map<String, Object> data) { + insertMeasure(branchUuid, uuidFactory.create(), metricUuid, data); + } + + private void insertMeasure(String branchUuid, String componentUuid, String metricUuid, Map<String, Object> data) { + Map<String, Object> dataMap = new HashMap<>(data); + dataMap.put("uuid", uuidFactory.create()); + dataMap.put("component_uuid", componentUuid); + dataMap.put("project_uuid", branchUuid); + dataMap.put("metric_uuid", metricUuid); + dataMap.put("created_at", 12L); + dataMap.put("updated_at", 12L); + + db.executeInsert("live_measures", dataMap); + } + + private void insertNotMigratedBranch(String branchUuid) { + insertBranch(branchUuid, false); + } + + private void insertMigratedBranch(String branchUuid) { + insertBranch(branchUuid, true); + } + + private void insertBranch(String branchUuid, boolean migrated) { + db.executeInsert("project_branches", + "uuid", branchUuid, + "kee", branchUuid, + "branch_type", "LONG", + "project_uuid", uuidFactory.create(), + MEASURES_MIGRATED_COLUMN, migrated, + "need_issue_sync", false, + "is_main", true, + "created_at", 12L, + "updated_at", 12L + ); + } + + +} diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/MigratePortfoliosLiveMeasuresToMeasuresIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/MigratePortfoliosLiveMeasuresToMeasuresIT.java new file mode 100644 index 00000000000..50519cde383 --- /dev/null +++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v107/MigratePortfoliosLiveMeasuresToMeasuresIT.java @@ -0,0 +1,182 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import java.nio.charset.StandardCharsets; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.api.utils.System2; +import org.sonar.core.util.SequenceUuidFactory; +import org.sonar.db.MigrationDbTester; +import org.sonar.server.platform.db.migration.step.DataChange; + +import static java.lang.String.format; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.Mockito.mock; + +class MigratePortfoliosLiveMeasuresToMeasuresIT { + + private static final String MEASURES_MIGRATED_COLUMN = "measures_migrated"; + public static final String SELECT_MEASURE = "select component_uuid, branch_uuid, json_value, json_value_hash, created_at, updated_at " + + "from measures where component_uuid = '%s'"; + + @RegisterExtension + public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(MigratePortfoliosLiveMeasuresToMeasures.class); + + private final SequenceUuidFactory uuidFactory = new SequenceUuidFactory(); + private final System2 system2 = mock(); + private final DataChange underTest = new MigratePortfoliosLiveMeasuresToMeasures(db.database(), system2); + + @Test + void shall_complete_when_tables_are_empty() throws SQLException { + underTest.execute(); + + assertThat(db.countRowsOfTable("measures")).isZero(); + } + + @Test + void shall_not_migrate_when_portfolio_is_already_flagged() throws SQLException { + String nclocMetricUuid = insertMetric("ncloc", "INT"); + String qgStatusMetricUuid = insertMetric("quality_gate_status", "STRING"); + String metricWithDataUuid = insertMetric("metric_with_data", "DATA"); + String portfolio1 = "portfolio_1"; + insertMigratedPortfolio(portfolio1); + insertMeasure(portfolio1, nclocMetricUuid, Map.of("value", 120)); + insertMeasure(portfolio1, qgStatusMetricUuid, Map.of("text_value", "ok")); + insertMeasure(portfolio1, metricWithDataUuid, Map.of("measure_data", "some data".getBytes(StandardCharsets.UTF_8))); + + insertMigratedPortfolio("portfolio_2"); + insertMeasure("portfolio_2", nclocMetricUuid, Map.of("value", 14220)); + + underTest.execute(); + + assertThat(db.countRowsOfTable("measures")).isZero(); + } + + @Test + void should_flag_portfolio_with_no_measures() throws SQLException { + String portfolio = "portfolio_3"; + insertNotMigratedPortfolio(portfolio); + + underTest.execute(); + + assertPortfolioMigrated(portfolio); + assertThat(db.countRowsOfTable("measures")).isZero(); + } + + @Test + void should_migrate_portfolio_with_measures() throws SQLException { + String nclocMetricUuid = insertMetric("ncloc", "INT"); + String qgStatusMetricUuid = insertMetric("quality_gate_status", "STRING"); + String metricWithDataUuid = insertMetric("metric_with_data", "DATA"); + + String portfolio1 = "portfolio_4"; + insertNotMigratedPortfolio(portfolio1); + String component1 = uuidFactory.create(); + String component2 = uuidFactory.create(); + insertMeasure(portfolio1, component1, nclocMetricUuid, Map.of("value", 120)); + insertMeasure(portfolio1, component1, qgStatusMetricUuid, Map.of("text_value", "ok")); + insertMeasure(portfolio1, component2, metricWithDataUuid, Map.of("measure_data", "some data".getBytes(StandardCharsets.UTF_8))); + + String portfolio2 = "portfolio_5"; + insertNotMigratedPortfolio(portfolio2); + insertMeasure(portfolio2, nclocMetricUuid, Map.of("value", 64)); + + String migratedPortfolio = "portfolio_6"; + insertMigratedPortfolio(migratedPortfolio); + insertMeasure(migratedPortfolio, nclocMetricUuid, Map.of("value", 3684)); + + underTest.execute(); + + assertPortfolioMigrated(portfolio1); + assertPortfolioMigrated(portfolio2); + assertThat(db.countRowsOfTable("measures")).isEqualTo(3); + + assertThat(db.select(format(SELECT_MEASURE, component1))) + .hasSize(1) + .extracting(t -> t.get("component_uuid"), t -> t.get("branch_uuid"), t -> t.get("json_value"), t -> t.get("json_value_hash")) + .containsOnly(tuple(component1, portfolio1, "{\"ncloc\":120.0,\"quality_gate_status\":\"ok\"}", 6033012287291512746L)); + + assertThat(db.select(format(SELECT_MEASURE, component2))) + .hasSize(1) + .extracting(t -> t.get("component_uuid"), t -> t.get("branch_uuid"), t -> t.get("json_value"), t -> t.get("json_value_hash")) + .containsOnly(tuple(component2, portfolio1, "{\"metric_with_data\":\"some data\"}", -4524184678167636687L)); + } + + private void assertPortfolioMigrated(String portfolio) { + List<Map<String, Object>> result = db.select(format("select %s as \"MIGRATED\" from portfolios where uuid = '%s'", MEASURES_MIGRATED_COLUMN, portfolio)); + assertThat(result) + .hasSize(1) + .extracting(t -> t.get("MIGRATED")) + .containsOnly(true); + } + + private String insertMetric(String metricName, String valueType) { + String metricUuid = uuidFactory.create(); + db.executeInsert("metrics", + "uuid", metricUuid, + "name", metricName, + "val_type", valueType); + return metricUuid; + } + + private void insertMeasure(String portfolioUuid, String metricUuid, Map<String, Object> data) { + insertMeasure(portfolioUuid, uuidFactory.create(), metricUuid, data); + } + + private void insertMeasure(String portfolioUuid, String componentUuid, String metricUuid, Map<String, Object> data) { + Map<String, Object> dataMap = new HashMap<>(data); + dataMap.put("uuid", uuidFactory.create()); + dataMap.put("component_uuid", componentUuid); + dataMap.put("project_uuid", portfolioUuid); + dataMap.put("metric_uuid", metricUuid); + dataMap.put("created_at", 12L); + dataMap.put("updated_at", 12L); + + db.executeInsert("live_measures", dataMap); + } + + private void insertNotMigratedPortfolio(String portfolioUuid) { + insertPortfolio(portfolioUuid, false); + } + + private void insertMigratedPortfolio(String portfolioUuid) { + insertPortfolio(portfolioUuid, true); + } + + private void insertPortfolio(String portfolioUuid, boolean migrated) { + db.executeInsert("portfolios", + "uuid", portfolioUuid, + "kee", portfolioUuid, + "name", portfolioUuid, + "private", true, + "root_uuid", portfolioUuid, + "selection_mode", "MANUAL", + MEASURES_MIGRATED_COLUMN, migrated, + "created_at", 12L, + "updated_at", 12L + ); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/MassUpdate.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/MassUpdate.java index 428c641d98a..a6b25e68a36 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/MassUpdate.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/MassUpdate.java @@ -38,7 +38,7 @@ public class MassUpdate { * * @return true if the row must be updated, else false. If false, then the update parameter must not be touched. */ - boolean handle(Select.Row row, SqlStatement update) throws SQLException; + boolean handle(Select.Row row, Upsert update) throws SQLException; } @FunctionalInterface @@ -49,7 +49,7 @@ public class MassUpdate { * @param updateIndex 0-based * @return true if the row must be updated, else false. If false, then the update parameter must not be touched. */ - boolean handle(Select.Row row, SqlStatement update, int updateIndex) throws SQLException; + boolean handle(Select.Row row, Upsert update, int updateIndex) throws SQLException; } private final Database db; diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AbstractAddMeasuresMigratedColumnToTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AbstractAddMeasuresMigratedColumnToTable.java new file mode 100644 index 00000000000..0c3ed45418c --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AbstractAddMeasuresMigratedColumnToTable.java @@ -0,0 +1,56 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import java.sql.Connection; +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.db.DatabaseUtils; +import org.sonar.server.platform.db.migration.def.BooleanColumnDef; +import org.sonar.server.platform.db.migration.def.ColumnDef; +import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +public class AbstractAddMeasuresMigratedColumnToTable extends DdlChange { + + public static final String MIGRATION_FLAG_COLUMN_NAME = "measures_migrated"; + private final String tableName; + + public AbstractAddMeasuresMigratedColumnToTable(Database db, String tableName) { + super(db); + this.tableName = tableName; + } + + @Override + public void execute(Context context) throws SQLException { + try (Connection connection = getDatabase().getDataSource().getConnection()) { + if (!DatabaseUtils.tableColumnExists(connection, tableName, MIGRATION_FLAG_COLUMN_NAME)) { + ColumnDef columnDef = BooleanColumnDef.newBooleanColumnDefBuilder() + .setColumnName(MIGRATION_FLAG_COLUMN_NAME) + .setIsNullable(false) + .setDefaultValue(false) + .build(); + context.execute(new AddColumnsBuilder(getDialect(), tableName) + .addColumn(columnDef) + .build()); + } + } + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AbstractCreateIndexOnMeasuresMigrated.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AbstractCreateIndexOnMeasuresMigrated.java new file mode 100644 index 00000000000..120e395ce8c --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AbstractCreateIndexOnMeasuresMigrated.java @@ -0,0 +1,53 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import java.sql.Connection; +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.db.DatabaseUtils; +import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +public class AbstractCreateIndexOnMeasuresMigrated extends DdlChange { + + static final String COLUMN_NAME = "measures_migrated"; + private final String tableName; + private final String indexName; + + public AbstractCreateIndexOnMeasuresMigrated(Database db, String tableName, String indexName) { + super(db); + this.tableName = tableName; + this.indexName = indexName; + } + + @Override + public void execute(Context context) throws SQLException { + try (Connection connection = getDatabase().getDataSource().getConnection()) { + if (!DatabaseUtils.indexExistsIgnoreCase(tableName, indexName, connection)) { + context.execute(new CreateIndexBuilder(getDialect()) + .setTable(tableName) + .setName(indexName) + .addColumn(COLUMN_NAME, false) + .build()); + } + } + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AbstractMigrateLiveMeasuresToMeasures.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AbstractMigrateLiveMeasuresToMeasures.java new file mode 100644 index 00000000000..cdb53badd79 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AbstractMigrateLiveMeasuresToMeasures.java @@ -0,0 +1,204 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import com.google.gson.Gson; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import javax.annotation.Nullable; +import org.apache.commons.codec.digest.MurmurHash3; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.utils.System2; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.step.DataChange; +import org.sonar.server.platform.db.migration.step.MassUpdate; +import org.sonar.server.platform.db.migration.step.Select; +import org.sonar.server.platform.db.migration.step.Upsert; + +import static java.lang.String.format; +import static java.nio.charset.StandardCharsets.UTF_8; + +public abstract class AbstractMigrateLiveMeasuresToMeasures extends DataChange { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractMigrateLiveMeasuresToMeasures.class); + + private static final Set<String> TEXT_VALUE_TYPES = Set.of("STRING", "LEVEL", "DATA", "DISTRIB"); + private static final Gson GSON = new Gson(); + + private static final String SELECT_QUERY = """ + SELECT lm.component_uuid, + m.name, + m.val_type, + lm.value, + lm.text_value, + lm.measure_data + FROM live_measures lm + INNER JOIN metrics m ON m.uuid = lm.metric_uuid + WHERE lm.project_uuid = ? + ORDER BY lm.component_uuid + """; + + private static final String INSERT_QUERY = """ + insert into measures (component_uuid, branch_uuid, json_value, json_value_hash, created_at, updated_at) + values ( ?, ?, ?, ?, ?, ?) + """; + + private final String tableName; + private final String item; + private final System2 system2; + + protected AbstractMigrateLiveMeasuresToMeasures(Database db, System2 system2, String tableName, String item) { + super(db); + this.system2 = system2; + this.tableName = tableName; + this.item = item; + } + + private String getSelectUuidQuery() { + return format(""" + SELECT uuid + FROM %s + WHERE measures_migrated = ? + """, tableName); + } + + private String getCountQuery() { + return format(""" + SELECT count(uuid) + FROM %s + """, tableName); + } + + private String getUpdateFlagQuery() { + return format(""" + UPDATE %s + SET measures_migrated = ? + WHERE uuid = ? + """, tableName); + } + + @Override + protected void execute(Context context) throws SQLException { + List<String> uuids = context.prepareSelect(getSelectUuidQuery()) + .setBoolean(1, false) + .list(row -> row.getString(1)); + + Long total = context.prepareSelect(getCountQuery()) + .get(row -> row.getLong(1)); + + LOGGER.info("Starting the migration of {} {}s (total number of {}s: {})", uuids.size(), item, item, total); + int migrated = 0; + + for (String uuid : uuids) { + migrateItem(uuid, context); + + migrated++; + if (migrated % 100 == 0) { + LOGGER.info("{} {}s migrated", migrated, item); + } + } + } + + private void migrateItem(String uuid, Context context) throws SQLException { + LOGGER.debug("Migrating {} {}...", item, uuid); + + Map<String, Object> measureValues = new HashMap<>(); + AtomicReference<String> componentUuid = new AtomicReference<>(null); + + MassUpdate massUpdate = context.prepareMassUpdate(); + massUpdate.select(SELECT_QUERY).setString(1, uuid); + massUpdate.update(INSERT_QUERY); + massUpdate.execute((row, update) -> { + boolean shouldUpdate = false; + String rowComponentUuid = row.getString(1); + if (componentUuid.get() == null || !rowComponentUuid.equals(componentUuid.get())) { + if (!measureValues.isEmpty()) { + preparePersistMeasure(uuid, update, componentUuid, measureValues); + shouldUpdate = true; + } + + LOGGER.debug("Starting processing of component {}...", rowComponentUuid); + componentUuid.set(rowComponentUuid); + measureValues.clear(); + readMeasureValue(row, measureValues); + } else { + readMeasureValue(row, measureValues); + } + return shouldUpdate; + }); + // insert the last component + if (!measureValues.isEmpty()) { + Upsert measureInsert = context.prepareUpsert(INSERT_QUERY); + preparePersistMeasure(uuid, measureInsert, componentUuid, measureValues); + measureInsert + .execute() + .commit(); + } + + LOGGER.debug("Flagging migration done for {} {}...", item, uuid); + + context.prepareUpsert(getUpdateFlagQuery()) + .setBoolean(1, true) + .setString(2, uuid) + .execute() + .commit(); + + LOGGER.debug("Migration finished for {} {}", item, uuid); + } + + private void preparePersistMeasure(String uuid, Upsert update, AtomicReference<String> componentUuid, Map<String, Object> measureValues) throws SQLException { + LOGGER.debug("Persisting measures for component {}...", componentUuid.get()); + String jsonValue = GSON.toJson(measureValues); + + long jsonHash = MurmurHash3.hash128(jsonValue.getBytes(UTF_8))[0]; + + update.setString(1, componentUuid.get()); + update.setString(2, uuid); + update.setString(3, jsonValue); + update.setLong(4, jsonHash); + update.setLong(5, system2.now()); + update.setLong(6, system2.now()); + } + + private static void readMeasureValue(Select.Row row, Map<String, Object> measureValues) throws SQLException { + String metricName = row.getString(2); + String valueType = row.getString(3); + Double numericValue = row.getDouble(4); + String textValue = row.getString(5); + byte[] data = row.getBytes(6); + + Object metricValue = getMetricValue(data, textValue, valueType, numericValue); + if (metricValue != null) { + measureValues.put(metricName, metricValue); + } + } + + private static Object getMetricValue(@Nullable byte[] data, @Nullable String textValue, String valueType, Double numericValue) { + return TEXT_VALUE_TYPES.contains(valueType) ? getTextValue(data, textValue) : numericValue; + } + + private static String getTextValue(@Nullable byte[] data, @Nullable String textValue) { + return data != null ? new String(data, UTF_8) : textValue; + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToPortfoliosTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToPortfoliosTable.java new file mode 100644 index 00000000000..7a16c70a198 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToPortfoliosTable.java @@ -0,0 +1,31 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import org.sonar.db.Database; + +public class AddMeasuresMigratedColumnToPortfoliosTable extends AbstractAddMeasuresMigratedColumnToTable { + + static final String PORTFOLIOS_TABLE_NAME = "portfolios"; + + public AddMeasuresMigratedColumnToPortfoliosTable(Database db) { + super(db, PORTFOLIOS_TABLE_NAME); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToProjectBranchesTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToProjectBranchesTable.java new file mode 100644 index 00000000000..fa77640db0e --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/AddMeasuresMigratedColumnToProjectBranchesTable.java @@ -0,0 +1,31 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import org.sonar.db.Database; + +public class AddMeasuresMigratedColumnToProjectBranchesTable extends AbstractAddMeasuresMigratedColumnToTable { + + public static final String PROJECT_BRANCHES_TABLE_NAME = "project_branches"; + + public AddMeasuresMigratedColumnToProjectBranchesTable(Database db) { + super(db, PROJECT_BRANCHES_TABLE_NAME); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnPortfoliosMeasuresMigrated.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnPortfoliosMeasuresMigrated.java new file mode 100644 index 00000000000..639c121d131 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnPortfoliosMeasuresMigrated.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import org.sonar.db.Database; + +public class CreateIndexOnPortfoliosMeasuresMigrated extends AbstractCreateIndexOnMeasuresMigrated { + + static final String TABLE_NAME = "portfolios"; + static final String INDEX_NAME = "portfolios_measures_migrated"; + + public CreateIndexOnPortfoliosMeasuresMigrated(Database db) { + super(db, TABLE_NAME, INDEX_NAME); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnProjectBranchesMeasuresMigrated.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnProjectBranchesMeasuresMigrated.java new file mode 100644 index 00000000000..d1a805ab3a5 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/CreateIndexOnProjectBranchesMeasuresMigrated.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import org.sonar.db.Database; + +public class CreateIndexOnProjectBranchesMeasuresMigrated extends AbstractCreateIndexOnMeasuresMigrated { + + static final String TABLE_NAME = "project_branches"; + static final String INDEX_NAME = "pb_measures_migrated"; + + public CreateIndexOnProjectBranchesMeasuresMigrated(Database db) { + super(db, TABLE_NAME, INDEX_NAME); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/DbVersion107.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/DbVersion107.java index 1c6bbd95afa..742ecd58643 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/DbVersion107.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/DbVersion107.java @@ -58,9 +58,14 @@ public class DbVersion107 implements DbVersion { .add(10_7_014, "Create 'issues_dependency' table", CreateIssuesDependencyTable.class) .add(10_7_015, "Add 'ai_code_assurance' column to 'projects' table", AddAiCodeAssuranceColumnInProjectsTable.class) .add(10_7_016, "Create 'measures' table", CreateMeasuresTable.class) - // TODO data migration - .add(10_7_018, "Create primary key on 'measures' table", CreatePrimaryKeyOnMeasuresTable.class) - .add(10_7_019, "Create index on column 'branch_uuid' in 'measures' table", CreateIndexOnMeasuresTable.class); + .add(10_7_017, "Add 'measures_migrated' column on 'project_branches' table", AddMeasuresMigratedColumnToProjectBranchesTable.class) + .add(10_7_018, "Create index on 'project_branches.measures_migrated'", CreateIndexOnProjectBranchesMeasuresMigrated.class) + .add(10_7_019, "Migrate the content of 'live_measures' to 'measures' for branches", MigrateBranchesLiveMeasuresToMeasures.class) + .add(10_7_020, "Add 'measures_migrated' column on 'portfolios' table", AddMeasuresMigratedColumnToPortfoliosTable.class) + .add(10_7_021, "Create index on 'portfolios.measures_migrated'", CreateIndexOnPortfoliosMeasuresMigrated.class) + .add(10_7_022, "Migrate the content of 'live_measures' to 'measures' for portfolios", MigratePortfoliosLiveMeasuresToMeasures.class) + .add(10_7_023, "Create primary key on 'measures' table", CreatePrimaryKeyOnMeasuresTable.class) + .add(10_7_024, "Create index on column 'branch_uuid' in 'measures' table", CreateIndexOnMeasuresTable.class); } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/MigrateBranchesLiveMeasuresToMeasures.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/MigrateBranchesLiveMeasuresToMeasures.java new file mode 100644 index 00000000000..135f887ebc9 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/MigrateBranchesLiveMeasuresToMeasures.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import org.sonar.api.utils.System2; +import org.sonar.db.Database; + +public class MigrateBranchesLiveMeasuresToMeasures extends AbstractMigrateLiveMeasuresToMeasures { + + public MigrateBranchesLiveMeasuresToMeasures(Database db, System2 system2) { + super(db, system2, "project_branches", "branch"); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/MigratePortfoliosLiveMeasuresToMeasures.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/MigratePortfoliosLiveMeasuresToMeasures.java new file mode 100644 index 00000000000..9ea66fd6382 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v107/MigratePortfoliosLiveMeasuresToMeasures.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.v107; + +import org.sonar.api.utils.System2; +import org.sonar.db.Database; + +public class MigratePortfoliosLiveMeasuresToMeasures extends AbstractMigrateLiveMeasuresToMeasures { + + protected MigratePortfoliosLiveMeasuresToMeasures(Database db, System2 system2) { + super(db, system2, "portfolios", "portfolio"); + } +} |