@@ -50,6 +50,7 @@ public class DbVersion71 implements DbVersion { | |||
.add(2020, "Replace index in PROJECT_BRANCHES", ReplaceIndexInProjectBranches.class) | |||
.add(2021, "Add pull_request_data in PROJECT_BRANCHES", AddPullRequestBinaryInProjectBranches.class) | |||
.add(2022, "Clean broken project to QG references", CleanBrokenProjectToQGReferences.class) | |||
.add(2023, "Delete measures of project copies", DeleteMeasuresOfProjectCopies.class) | |||
; | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 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.v71; | |||
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 DeleteMeasuresOfProjectCopies extends DataChange { | |||
public DeleteMeasuresOfProjectCopies(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
protected void execute(DataChange.Context context) throws SQLException { | |||
MassUpdate massUpdate = context.prepareMassUpdate(); | |||
massUpdate.select("select distinct uuid from projects where copy_component_uuid is not null"); | |||
massUpdate.update("delete from project_measures where component_uuid=?"); | |||
massUpdate.execute((row, update) -> { | |||
update.setString(1, row.getString(1)); | |||
return true; | |||
}); | |||
} | |||
} |
@@ -17,7 +17,6 @@ | |||
* 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.v71; | |||
import org.junit.Test; | |||
@@ -36,7 +35,7 @@ public class DbVersion71Test { | |||
@Test | |||
public void verify_migration_count() { | |||
verifyMigrationCount(underTest, 23); | |||
verifyMigrationCount(underTest, 24); | |||
} | |||
} |
@@ -0,0 +1,104 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 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.v71; | |||
import java.sql.SQLException; | |||
import java.util.stream.IntStream; | |||
import javax.annotation.Nullable; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.core.util.SequenceUuidFactory; | |||
import org.sonar.core.util.UuidFactory; | |||
import org.sonar.db.CoreDbTester; | |||
import org.sonar.server.platform.db.migration.step.DataChange; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class DeleteMeasuresOfProjectCopiesTest { | |||
@Rule | |||
public final CoreDbTester db = CoreDbTester.createForSchema(DeleteMeasuresOfProjectCopiesTest.class, "initial.sql"); | |||
private UuidFactory uuidFactory = new SequenceUuidFactory(); | |||
private DataChange underTest = new DeleteMeasuresOfProjectCopies(db.database()); | |||
@Test | |||
public void has_no_effect_if_table_is_empty() throws SQLException { | |||
underTest.execute(); | |||
} | |||
@Test | |||
public void delete_measures_of_project_copies_only() throws SQLException { | |||
String project1 = insertComponent("PRJ", "TRK", null); | |||
String project1Copy = insertComponent("FIL", "TRK", project1); | |||
String fileInProject1 = insertComponent("FIL", "FIL", null); | |||
String project2 = insertComponent("PRJ", "TRK", null); | |||
String project2Copy = insertComponent("FIL", "TRK", project2); | |||
String project3 = insertComponent("PRJ", "TRK", null); | |||
insertMeasures(project1, 3); | |||
insertMeasures(project1Copy, 3); | |||
insertMeasures(project2, 5); | |||
insertMeasures(project2Copy, 5); | |||
insertMeasures(project3, 4); | |||
insertMeasures(fileInProject1, 3); | |||
underTest.execute(); | |||
verifyMeasures(project1, 3); | |||
verifyMeasures(project1Copy, 0); | |||
verifyMeasures(fileInProject1, 3); | |||
verifyMeasures(project2, 5); | |||
verifyMeasures(project2Copy, 0); | |||
verifyMeasures(project3, 4); | |||
} | |||
private String insertComponent(String scope, String qualifier, @Nullable String copyComponentUuid) { | |||
String uuid = uuidFactory.create(); | |||
db.executeInsert("PROJECTS", | |||
"ORGANIZATION_UUID", "O1", | |||
"KEE", uuid, | |||
"UUID", uuid, | |||
"PROJECT_UUID", uuid, | |||
"MAIN_BRANCH_PROJECT_UUID", uuid, | |||
"UUID_PATH", ".", | |||
"ROOT_UUID", uuid, | |||
"PRIVATE", "true", | |||
"QUALIFIER", qualifier, | |||
"SCOPE", scope, | |||
"COPY_COMPONENT_UUID", copyComponentUuid); | |||
return uuid; | |||
} | |||
private void insertMeasures(String componentUuid, int number) { | |||
IntStream.range(0, number).forEach(index -> db.executeInsert( | |||
"PROJECT_MEASURES", | |||
"COMPONENT_UUID", componentUuid, | |||
"ANALYSIS_UUID", uuidFactory.create(), | |||
"METRIC_ID", "111")); | |||
} | |||
private void verifyMeasures(String componentUuid, int expectedCount) { | |||
int count = db.countSql("select count(*) from project_measures where component_uuid='" + componentUuid + "'"); | |||
assertThat(expectedCount) | |||
.as("UUID " + componentUuid) | |||
.isEqualTo(count); | |||
} | |||
} |
@@ -0,0 +1,68 @@ | |||
CREATE TABLE "PROJECTS" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"ORGANIZATION_UUID" VARCHAR(40) NOT NULL, | |||
"KEE" VARCHAR(400), | |||
"UUID" VARCHAR(50) NOT NULL, | |||
"UUID_PATH" VARCHAR(1500) NOT NULL, | |||
"ROOT_UUID" VARCHAR(50) NOT NULL, | |||
"PROJECT_UUID" VARCHAR(50) NOT NULL, | |||
"MODULE_UUID" VARCHAR(50), | |||
"MODULE_UUID_PATH" VARCHAR(1500), | |||
"MAIN_BRANCH_PROJECT_UUID" VARCHAR(50), | |||
"NAME" VARCHAR(2000), | |||
"DESCRIPTION" VARCHAR(2000), | |||
"PRIVATE" BOOLEAN NOT NULL, | |||
"TAGS" VARCHAR(500), | |||
"ENABLED" BOOLEAN NOT NULL DEFAULT TRUE, | |||
"SCOPE" VARCHAR(3), | |||
"QUALIFIER" VARCHAR(10), | |||
"DEPRECATED_KEE" VARCHAR(400), | |||
"PATH" VARCHAR(2000), | |||
"LANGUAGE" VARCHAR(20), | |||
"COPY_COMPONENT_UUID" VARCHAR(50), | |||
"LONG_NAME" VARCHAR(2000), | |||
"DEVELOPER_UUID" VARCHAR(50), | |||
"CREATED_AT" TIMESTAMP, | |||
"AUTHORIZATION_UPDATED_AT" BIGINT, | |||
"B_CHANGED" BOOLEAN, | |||
"B_COPY_COMPONENT_UUID" VARCHAR(50), | |||
"B_DESCRIPTION" VARCHAR(2000), | |||
"B_ENABLED" BOOLEAN, | |||
"B_UUID_PATH" VARCHAR(1500), | |||
"B_LANGUAGE" VARCHAR(20), | |||
"B_LONG_NAME" VARCHAR(500), | |||
"B_MODULE_UUID" VARCHAR(50), | |||
"B_MODULE_UUID_PATH" VARCHAR(1500), | |||
"B_NAME" VARCHAR(500), | |||
"B_PATH" VARCHAR(2000), | |||
"B_QUALIFIER" VARCHAR(10) | |||
); | |||
CREATE INDEX "PROJECTS_ORGANIZATION" ON "PROJECTS" ("ORGANIZATION_UUID"); | |||
CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE"); | |||
CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID"); | |||
CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID"); | |||
CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID"); | |||
CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID"); | |||
CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER"); | |||
CREATE TABLE "PROJECT_MEASURES" ( | |||
"ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"VALUE" DOUBLE, | |||
"METRIC_ID" INTEGER NOT NULL, | |||
"COMPONENT_UUID" VARCHAR(50) NOT NULL, | |||
"ANALYSIS_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" BINARY | |||
); | |||
CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES" ("COMPONENT_UUID"); | |||
CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES" ("ANALYSIS_UUID", "METRIC_ID"); |