aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImplIT.java12
-rw-r--r--server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v108/EnableSpecificMqrModeIT.java117
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistory.java6
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java8
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v00/PopulateInitialSchema.java2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v108/DbVersion108.java3
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v108/EnableSpecificMqrMode.java78
7 files changed, 224 insertions, 2 deletions
diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImplIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImplIT.java
index 187222cfe57..5e14bdf0d7f 100644
--- a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImplIT.java
+++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImplIT.java
@@ -73,6 +73,18 @@ class MigrationHistoryImplIT {
assertThat(underTest.getLastMigrationNumber()).contains(12L);
}
+ @Test
+ void getInitialDbVersion_shouldReturnVersionAtStartUp() throws SQLException {
+ underTest.start();
+ assertThat(underTest.getInitialDbVersion()).isEqualTo(-1);
+
+ insert(12, 5, 30, 8);
+ underTest.start();
+ insert(35,37,42);
+
+ assertThat(underTest.getInitialDbVersion()).isEqualTo(30);
+ }
+
private void insert(int... versions) throws SQLException {
try (Connection connection = dbTester.database().getDataSource().getConnection()) {
Arrays.stream(versions).forEach(version -> insert(connection, version));
diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v108/EnableSpecificMqrModeIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v108/EnableSpecificMqrModeIT.java
new file mode 100644
index 00000000000..f51870d849f
--- /dev/null
+++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v108/EnableSpecificMqrModeIT.java
@@ -0,0 +1,117 @@
+/*
+ * 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.v108;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.sonar.api.impl.utils.TestSystem2;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.SequenceUuidFactory;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.MigrationDbTester;
+import org.sonar.server.platform.db.migration.history.MigrationHistory;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.core.config.MQRModeConstants.MULTI_QUALITY_MODE_ENABLED;
+
+class EnableSpecificMqrModeIT {
+
+ @RegisterExtension
+ public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(EnableSpecificMqrMode.class);
+
+ private final UuidFactory uuidFactory = new SequenceUuidFactory();
+ private final MigrationHistory migrationHistory = mock(MigrationHistory.class);
+ private final System2 system2 = new TestSystem2().setNow(2_000_000_000L);
+
+ private final DataChange underTest = new EnableSpecificMqrMode(db.database(), migrationHistory, uuidFactory, system2);
+
+ @ParameterizedTest
+ @MethodSource("versions")
+ void execute_correctlyInsertsProperty(long version, String expectedResult) throws SQLException {
+ when(migrationHistory.getInitialDbVersion()).thenReturn(version);
+ underTest.execute();
+
+ assertThat(getPropertyFromDB()).hasSize(1);
+ assertThat(getPropertyFromDB().get(0))
+ .containsEntry("text_value", expectedResult)
+ .containsEntry("is_empty", false)
+ .containsEntry("created_at", 2_000_000_000L)
+ .containsEntry("uuid", "00000000-0000-0000-0000-000000000001");
+ }
+
+ @ParameterizedTest
+ @MethodSource("versions")
+ void execute_doesNothingIfPropertyAlreadyExists(long version) throws SQLException {
+ when(migrationHistory.getInitialDbVersion()).thenReturn(version);
+
+ String uuid = uuidFactory.create();
+ db.executeInsert("properties",
+ "prop_key", MULTI_QUALITY_MODE_ENABLED,
+ "text_value", "false",
+ "is_empty", "false",
+ "created_at", 1_000_000_000L,
+ "uuid", uuid
+ );
+ underTest.execute();
+
+ assertThat(getPropertyFromDB()).hasSize(1);
+ assertThat(getPropertyFromDB().get(0))
+ .containsEntry("text_value", "false")
+ .containsEntry("is_empty", false)
+ .containsEntry("created_at", 1_000_000_000L)
+ .containsEntry("uuid", uuid);
+ }
+
+ @Test
+ void execute_shouldBeReentrant() throws SQLException {
+ when(migrationHistory.getInitialDbVersion()).thenReturn(102_000L);
+ underTest.execute();
+ underTest.execute();
+
+ assertThat(getPropertyFromDB()).hasSize(1);
+ assertThat(getPropertyFromDB().get(0))
+ .containsEntry("text_value", "true")
+ .containsEntry("is_empty", false)
+ .containsEntry("created_at", 2_000_000_000L)
+ .containsEntry("uuid", "00000000-0000-0000-0000-000000000001");
+ }
+
+ private List<Map<String, Object>> getPropertyFromDB() {
+ String sql = "SELECT text_value, is_empty, created_at, uuid FROM properties WHERE prop_key = '" + MULTI_QUALITY_MODE_ENABLED + "'";
+ return db.select(sql);
+ }
+
+ private static Stream<Arguments> versions() {
+ return Stream.of(
+ Arguments.of(102_000L, "true"),
+ Arguments.of(-1L, "true"),
+ Arguments.of(101_990L, "false"));
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistory.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistory.java
index c771c6c79d2..7e726181a8b 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistory.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistory.java
@@ -53,4 +53,10 @@ public interface MigrationHistory extends Startable {
*/
void done(RegisteredMigrationStep dbMigration);
+ /**
+ * Returns the initial version of the database.
+ *
+ * @return a long >= 0 or -1 if the migration history is empty.
+ */
+ long getInitialDbVersion();
}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java
index 49ebd5166ed..296a4f1da9e 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java
@@ -41,6 +41,8 @@ public class MigrationHistoryImpl implements MigrationHistory {
private final Database database;
private final MigrationHistoryMeddler migrationHistoryMeddler;
+ private long initialDbVersion;
+
public MigrationHistoryImpl(Database database, MigrationHistoryMeddler migrationHistoryMeddler) {
this.database = database;
this.migrationHistoryMeddler = migrationHistoryMeddler;
@@ -50,6 +52,7 @@ public class MigrationHistoryImpl implements MigrationHistory {
public void start() {
try (Connection connection = database.getDataSource().getConnection()) {
checkState(DatabaseUtils.tableExists(MigrationHistoryTable.NAME, connection), "Migration history table is missing");
+ this.initialDbVersion = getLastMigrationNumber().orElse(-1L);
migrationHistoryMeddler.meddle(this);
} catch (SQLException e) {
Throwables.propagate(e);
@@ -91,6 +94,11 @@ public class MigrationHistoryImpl implements MigrationHistory {
}
}
+ @Override
+ public long getInitialDbVersion() {
+ return initialDbVersion;
+ }
+
private static List<Long> selectVersions(Connection connection) throws SQLException {
try (Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select version from " + SCHEMA_MIGRATIONS_TABLE)) {
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v00/PopulateInitialSchema.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v00/PopulateInitialSchema.java
index 38b61ec6b3f..1cd9f0af8c8 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v00/PopulateInitialSchema.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v00/PopulateInitialSchema.java
@@ -256,7 +256,7 @@ public class PopulateInitialSchema extends DataChange {
context.prepareUpsert("truncate table " + table).execute().commit();
}
- private static String createInsertStatement(String tableName, String firstColumn, String... otherColumns) {
+ public static String createInsertStatement(String tableName, String firstColumn, String... otherColumns) {
return "insert into " + tableName + " " +
"(" + concat(of(firstColumn), stream(otherColumns)).collect(joining(",")) + ")" +
" values" +
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v108/DbVersion108.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v108/DbVersion108.java
index aab86608e2f..412306bceb7 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v108/DbVersion108.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v108/DbVersion108.java
@@ -56,7 +56,8 @@ public class DbVersion108 implements DbVersion {
.add(10_8_013, "Drop index on 'project_branches.measures_migrated'", DropIndexOnProjectBranchesMeasuresMigrated.class)
.add(10_8_014, "Drop 'measures_migrated' column on 'project_branches' table", DropMeasuresMigratedColumnInProjectBranchesTable.class)
.add(10_8_015, "Add column 'impacts' in 'active_rules' table", AddImpactsColumnInActiveRulesTable.class)
- .add(10_8_016, "Create 'project_dependencies' table", CreateProjectDependenciesTable.class);
+ .add(10_8_016, "Create 'project_dependencies' table", CreateProjectDependenciesTable.class)
+ .add(10_8_017, "Enable specific MQR mode", EnableSpecificMqrMode.class);
}
}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v108/EnableSpecificMqrMode.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v108/EnableSpecificMqrMode.java
new file mode 100644
index 00000000000..bdbcc0a43ea
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v108/EnableSpecificMqrMode.java
@@ -0,0 +1,78 @@
+/*
+ * 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.v108;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.history.MigrationHistory;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.Upsert;
+
+import static org.sonar.core.config.MQRModeConstants.MULTI_QUALITY_MODE_ENABLED;
+import static org.sonar.server.platform.db.migration.version.v00.PopulateInitialSchema.createInsertStatement;
+
+public class EnableSpecificMqrMode extends DataChange {
+ private final MigrationHistory migrationHistory;
+ private final UuidFactory uuidFactory;
+ private final System2 system2;
+
+ public EnableSpecificMqrMode(Database db, MigrationHistory migrationHistory, UuidFactory uuidFactory, System2 system2) {
+ super(db);
+ this.migrationHistory = migrationHistory;
+ this.uuidFactory = uuidFactory;
+ this.system2 = system2;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ try (Connection connection = getDatabase().getDataSource().getConnection()) {
+ if (!paramExists(connection)) {
+ long version = migrationHistory.getInitialDbVersion();
+ boolean mqrModeEnabled = version >= 102_000L || version == -1L;
+ Upsert upsert = context.prepareUpsert(
+ createInsertStatement("properties",
+ "uuid",
+ "prop_key",
+ "is_empty",
+ "text_value",
+ "created_at"));
+ upsert.setString(1, uuidFactory.create())
+ .setString(2, MULTI_QUALITY_MODE_ENABLED)
+ .setBoolean(3, false)
+ .setString(4, String.valueOf(mqrModeEnabled))
+ .setLong(5, system2.now());
+ upsert.execute().commit();
+ }
+ }
+ }
+
+ private static boolean paramExists(Connection connection) throws SQLException {
+ String sql = "SELECT count(1) FROM properties WHERE prop_key = '" + MULTI_QUALITY_MODE_ENABLED + "'";
+ try (PreparedStatement statement = connection.prepareStatement(sql)) {
+ ResultSet result = statement.executeQuery();
+ return result.next() && result.getInt(1) > 0;
+ }
+ }
+}