ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("UUID");
CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID");
CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES"("ANALYSIS_UUID", "METRIC_UUID");
+CREATE INDEX "PROJECT_MEASURES_METRIC" ON "PROJECT_MEASURES"("METRIC_UUID");
CREATE TABLE "PROJECT_QGATES"(
"PROJECT_UUID" VARCHAR(40) NOT NULL,
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2021 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.v82;
-
-import java.sql.SQLException;
-import javax.annotation.Nullable;
-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 DeleteSecurityReviewRatingProjectMeasures extends DataChange {
-
- private static final String SECURITY_REVIEW_RATING_METRIC_KEY = "security_review_rating";
- private static final String SECURITY_REVIEW_RATING_EFFORT_METRIC_KEY = "security_review_rating_effort";
- private static final String SELECT_COMPONENTS_STATEMENT = "select c.uuid from components c where c.scope in ('PRJ')";
-
- public DeleteSecurityReviewRatingProjectMeasures(Database db) {
- super(db);
- }
-
- @Override
- protected void execute(Context context) throws SQLException {
- Integer reviewRatingId = getMetricId(context, SECURITY_REVIEW_RATING_METRIC_KEY);
- Integer reviewRatingEffortId = getMetricId(context, SECURITY_REVIEW_RATING_EFFORT_METRIC_KEY);
- if (reviewRatingId != null) {
- deleteFromProjectMeasures(context, reviewRatingId, reviewRatingEffortId);
- }
- }
-
- @Nullable
- private static Integer getMetricId(Context context, String metricName) throws SQLException {
- return context.prepareSelect("select id from metrics where name = ?")
- .setString(1, metricName)
- .get(row -> row.getNullableInt(1));
- }
-
- private static void deleteFromProjectMeasures(Context context, Integer reviewRatingId, @Nullable Integer reviewRatingEffortId) throws SQLException {
- MassUpdate deleteFromProjectMeasures = context.prepareMassUpdate();
-
- deleteFromProjectMeasures.select(SELECT_COMPONENTS_STATEMENT);
- if (reviewRatingEffortId != null) {
- deleteFromProjectMeasures.update("delete from project_measures where component_uuid = ? and metric_id in (?, ?)");
- } else {
- deleteFromProjectMeasures.update("delete from project_measures where component_uuid = ? and metric_id = ?");
- }
-
- deleteFromProjectMeasures.execute((row, update) -> {
- String componentUuid = row.getString(1);
- update.setString(1, componentUuid)
- .setInt(2, reviewRatingId);
- if (reviewRatingEffortId != null) {
- update.setInt(3, reviewRatingEffortId);
- }
- return true;
- });
- }
-}
import org.sonar.server.platform.db.migration.version.v84.metrics.manualmeasures.DropMetricIdColumnOfManualMeasuresTable;
import org.sonar.server.platform.db.migration.version.v84.metrics.manualmeasures.MakeManualMeasuresMetricUuidNotNullable;
import org.sonar.server.platform.db.migration.version.v84.metrics.manualmeasures.PopulateManualMeasuresMetricUuid;
+import org.sonar.server.platform.db.migration.version.v84.metrics.projectmeasures.AddIndexOnMetricUuidAndAnalysisUuidOfProjectMeasuresTable;
import org.sonar.server.platform.db.migration.version.v84.metrics.projectmeasures.AddIndexOnMetricUuidOfProjectMeasuresTable;
import org.sonar.server.platform.db.migration.version.v84.metrics.projectmeasures.AddMetricUuidColumnToProjectMeasures;
+import org.sonar.server.platform.db.migration.version.v84.metrics.projectmeasures.DeleteSecurityReviewRatingProjectMeasures;
import org.sonar.server.platform.db.migration.version.v84.metrics.projectmeasures.DropIndexOnMetricIdOfProjectMeasuresTable;
import org.sonar.server.platform.db.migration.version.v84.metrics.projectmeasures.DropMetricIdColumnOfProjectMeasuresTable;
import org.sonar.server.platform.db.migration.version.v84.metrics.projectmeasures.MakeProjectMeasuresMetricUuidNotNullable;
.add(3533, "Populate 'metric_uuid' for 'PROJECT_MEASURES'", PopulateProjectMeasuresMetricUuid.class)
.add(3534, "Make 'metric_uuid' column not nullable for 'PROJECT_MEASURES'", MakeProjectMeasuresMetricUuidNotNullable.class)
.add(3535, "Drop index on 'metric_id' and 'analysis_uuid' columns of 'PROJECT_MEASURES' table", DropIndexOnMetricIdOfProjectMeasuresTable.class)
- .add(3536, "Add index on 'metric_uuid' and 'analysis_uuid' columns of 'PROJECT_MEASURES' table", AddIndexOnMetricUuidOfProjectMeasuresTable.class)
+ .add(3536, "Add index on 'metric_uuid' and 'analysis_uuid' columns of 'PROJECT_MEASURES' table", AddIndexOnMetricUuidAndAnalysisUuidOfProjectMeasuresTable.class)
// Migration of FK in QUALITY_GATE_CONDITIONS to METRICS
.add(3537, "Add 'metric_uuid' column on 'QUALITY_GATE_CONDITIONS' table", AddMetricUuidColumnToQualityGateConditions.class)
// Migration of ALM_SETTINGS table
.add(3807, "Add columns 'CLIENT_ID' and 'CLIENT_SECRET' to 'ALM_SETTINGS' table", AddClientIdAndClientSecretColumns.class)
+
+
+ // Removing old data from project_measures
+ .add(3808, "Add index on 'metric_uuid' column of 'PROJECT_MEASURES' table", AddIndexOnMetricUuidOfProjectMeasuresTable.class)
+ .add(3809, "Remove old Security Review Rating ProjectMeasures", DeleteSecurityReviewRatingProjectMeasures.class)
;
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.v84.metrics.projectmeasures;
+
+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.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class AddIndexOnMetricUuidAndAnalysisUuidOfProjectMeasuresTable extends DdlChange {
+ private static final String TABLE_NAME = "project_measures";
+ private static final String INDEX_NAME = "measures_analysis_metric";
+
+ public AddIndexOnMetricUuidAndAnalysisUuidOfProjectMeasuresTable(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ if (!indexExists()) {
+ context.execute(new CreateIndexBuilder()
+ .setUnique(false)
+ .setTable(TABLE_NAME)
+ .setName(INDEX_NAME)
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("analysis_uuid")
+ .setIsNullable(false)
+ .setLimit(VarcharColumnDef.UUID_SIZE)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("metric_uuid")
+ .setIsNullable(false)
+ .setLimit(VarcharColumnDef.UUID_SIZE)
+ .build())
+ .build());
+ }
+ }
+
+ private boolean indexExists() throws SQLException {
+ try (Connection connection = getDatabase().getDataSource().getConnection()) {
+ return DatabaseUtils.indexExistsIgnoreCase(TABLE_NAME, INDEX_NAME, connection);
+ }
+ }
+}
public class AddIndexOnMetricUuidOfProjectMeasuresTable extends DdlChange {
private static final String TABLE_NAME = "project_measures";
- private static final String INDEX_NAME = "measures_analysis_metric";
+ private static final String INDEX_NAME = "project_measures_metric";
public AddIndexOnMetricUuidOfProjectMeasuresTable(Database db) {
super(db);
.setUnique(false)
.setTable(TABLE_NAME)
.setName(INDEX_NAME)
- .addColumn(newVarcharColumnDefBuilder()
- .setColumnName("analysis_uuid")
- .setIsNullable(false)
- .setLimit(VarcharColumnDef.UUID_SIZE)
- .build())
.addColumn(newVarcharColumnDefBuilder()
.setColumnName("metric_uuid")
.setIsNullable(false)
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.v84.metrics.projectmeasures;
+
+import java.sql.SQLException;
+import javax.annotation.Nullable;
+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 DeleteSecurityReviewRatingProjectMeasures extends DataChange {
+
+ private static final String SECURITY_REVIEW_RATING_METRIC_KEY = "security_review_rating";
+ private static final String SECURITY_REVIEW_RATING_EFFORT_METRIC_KEY = "security_review_rating_effort";
+
+ public DeleteSecurityReviewRatingProjectMeasures(Database db) {
+ super(db);
+ }
+
+ @Override
+ protected void execute(Context context) throws SQLException {
+ String reviewRatingUuid = getMetricUuid(context, SECURITY_REVIEW_RATING_METRIC_KEY);
+ String reviewRatingEffortUuid = getMetricUuid(context, SECURITY_REVIEW_RATING_EFFORT_METRIC_KEY);
+ if (reviewRatingUuid != null) {
+ deleteFromProjectMeasures(context, reviewRatingUuid, reviewRatingEffortUuid);
+ }
+ }
+
+ @Nullable
+ private static String getMetricUuid(Context context, String metricName) throws SQLException {
+ return context.prepareSelect("select uuid from metrics where name = ?")
+ .setString(1, metricName)
+ .get(row -> row.getNullableString(1));
+ }
+
+ private static void deleteFromProjectMeasures(Context context, String reviewRatingUuid, @Nullable String reviewRatingEffortUuid) throws SQLException {
+ deleteFromProjectMeasures(context, reviewRatingUuid);
+
+ if (reviewRatingEffortUuid != null) {
+ deleteFromProjectMeasures(context, reviewRatingEffortUuid);
+ }
+ }
+
+ private static void deleteFromProjectMeasures(Context context, @Nullable String metricUuid) throws SQLException {
+ if (metricUuid == null) {
+ return;
+ }
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate.select("select uuid from project_measures where metric_uuid = ?")
+ .setString(1, metricUuid);
+ massUpdate.update("delete from project_measures where uuid = ?");
+ massUpdate.execute((row, update) -> {
+ update.setString(1, row.getString(1));
+ return true;
+ });
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.v84.metrics.projectmeasures;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.MigrationStep;
+
+public class AddIndexOnMetricUuidAndAnalysisUuidOfProjectMeasuresTableTest {
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(AddIndexOnMetricUuidAndAnalysisUuidOfProjectMeasuresTableTest.class, "schema.sql");
+
+ private MigrationStep underTest = new AddIndexOnMetricUuidAndAnalysisUuidOfProjectMeasuresTable(db.database());
+
+ @Test
+ public void execute() throws SQLException {
+ underTest.execute();
+
+ db.assertIndex("project_measures", "measures_analysis_metric", "analysis_uuid", "metric_uuid");
+ }
+
+ @Test
+ public void migration_is_re_entrant() throws SQLException {
+ underTest.execute();
+
+ // re-entrant
+ underTest.execute();
+
+ db.assertIndex("project_measures", "measures_analysis_metric", "analysis_uuid", "metric_uuid");
+ }
+}
public void execute() throws SQLException {
underTest.execute();
- db.assertIndex("project_measures", "measures_analysis_metric", "analysis_uuid", "metric_uuid");
+ db.assertIndex("project_measures", "project_measures_metric", "metric_uuid");
}
@Test
// re-entrant
underTest.execute();
- db.assertIndex("project_measures", "measures_analysis_metric", "analysis_uuid", "metric_uuid");
+ db.assertIndex("project_measures", "project_measures_metric", "metric_uuid");
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.v84.metrics.projectmeasures;
+
+import com.google.common.collect.ImmutableMap;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang.math.RandomUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+import static java.lang.String.format;
+import static java.util.Collections.singletonList;
+import static java.util.stream.Collectors.toList;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DeleteSecurityReviewRatingProjectMeasuresTest {
+ private static final String PROJECT_MEASURES_TABLE = "project_measures";
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(DeleteSecurityReviewRatingProjectMeasuresTest.class, "schema.sql");
+
+ private DataChange underTest = new DeleteSecurityReviewRatingProjectMeasures(db.database());
+
+ @Test
+ public void removes_project_measure_for_review_rating_and_review_rating_effort_metrics() throws SQLException {
+ String codeSmellMetric = insertMetric(1L, "security_review_rating");
+ insertProjectMeasure(codeSmellMetric);
+ String reviewRatingEffort = insertMetric(2L, "security_review_rating_effort");
+ insertProjectMeasure(reviewRatingEffort);
+ String anotherMetric = insertMetric(3L, "another_metric");
+ String anotherMetricProjectMeasure = insertProjectMeasure(anotherMetric);
+
+ underTest.execute();
+ verifyProjectMeasureIds(singletonList(anotherMetricProjectMeasure));
+ }
+
+
+ private String insertMetric(Long id, String key) {
+ db.executeInsert("metrics",
+ "id", id,
+ "uuid", id,
+ "name", key);
+
+ return (String) db.selectFirst(format("select uuid as \"uuid\" from metrics where name='%s'", key)).get("uuid");
+ }
+
+ private String insertProjectMeasure(String metricUuid) {
+ double projectMeasureUUid = RandomUtils.nextDouble();
+ Map<String, Object> values = new HashMap<>(ImmutableMap.of("uuid", projectMeasureUUid, "metric_uuid", metricUuid,
+ "analysis_uuid", "analysis_uuid", "component_uuid", "component_uuid"));
+ db.executeInsert(PROJECT_MEASURES_TABLE, values);
+ String sql = format("select uuid as \"uuid\" from %s where metric_uuid='%s'", PROJECT_MEASURES_TABLE, metricUuid);
+ return (String) db
+ .selectFirst(sql)
+ .get("uuid");
+ }
+
+ private void verifyProjectMeasureIds(List<String> expectedProjectMeasureIds) {
+ List<Map<String, Object>> results = db.select("select uuid from " + PROJECT_MEASURES_TABLE);
+ assertThat(results.stream()
+ .map(map -> (String) map.get("UUID"))
+ .collect(toList()))
+ .containsExactlyInAnyOrderElementsOf(expectedProjectMeasureIds);
+ }
+}
--- /dev/null
+CREATE TABLE "PROJECT_MEASURES"(
+ "VALUE" DOUBLE,
+ "METRIC_UUID" VARCHAR(40) NOT NULL,
+ "METRIC_ID" INTEGER NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "PERSON_ID" INTEGER,
+ "VARIATION_VALUE_1" DOUBLE,
+ "VARIATION_VALUE_2" DOUBLE,
+ "VARIATION_VALUE_3" DOUBLE,
+ "VARIATION_VALUE_4" DOUBLE,
+ "VARIATION_VALUE_5" DOUBLE,
+ "MEASURE_DATA" BLOB,
+ "UUID" VARCHAR(40) NOT NULL
+);
+ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("UUID");
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID");
--- /dev/null
+CREATE TABLE "METRICS"(
+ "ID" INTEGER NOT NULL AUTO_INCREMENT (1,1),
+ "UUID" VARCHAR(40) NOT NULL,
+ "NAME" VARCHAR(64) NOT NULL,
+ "DESCRIPTION" VARCHAR(255),
+ "DIRECTION" INTEGER DEFAULT 0 NOT NULL,
+ "DOMAIN" VARCHAR(64),
+ "SHORT_NAME" VARCHAR(64),
+ "QUALITATIVE" BOOLEAN DEFAULT FALSE NOT NULL,
+ "VAL_TYPE" VARCHAR(8),
+ "USER_MANAGED" BOOLEAN DEFAULT FALSE,
+ "ENABLED" BOOLEAN DEFAULT TRUE,
+ "WORST_VALUE" DOUBLE,
+ "BEST_VALUE" DOUBLE,
+ "OPTIMIZED_BEST_VALUE" BOOLEAN,
+ "HIDDEN" BOOLEAN,
+ "DELETE_HISTORICAL_DATA" BOOLEAN,
+ "DECIMAL_SCALE" INTEGER
+);
+ALTER TABLE "METRICS" ADD CONSTRAINT "PK_METRICS" PRIMARY KEY("ID");
+CREATE UNIQUE INDEX "METRICS_UNIQUE_NAME" ON "METRICS"("NAME");
+
+CREATE TABLE "PROJECT_MEASURES"(
+ "VALUE" DOUBLE,
+ "METRIC_UUID" VARCHAR(40) NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "PERSON_ID" INTEGER,
+ "VARIATION_VALUE_1" DOUBLE,
+ "VARIATION_VALUE_2" DOUBLE,
+ "VARIATION_VALUE_3" DOUBLE,
+ "VARIATION_VALUE_4" DOUBLE,
+ "VARIATION_VALUE_5" DOUBLE,
+ "MEASURE_DATA" BLOB,
+ "UUID" VARCHAR(40) NOT NULL
+);
+ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("UUID");
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID");