From 25a8c76fc5e6e642887b10b325a41472a7b4d4a1 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Thu, 7 Dec 2017 14:09:56 +0100 Subject: [PATCH] SONAR-10166 Delete quality gates when deleting organization --- .../sonar/db/qualitygate/QualityGateDao.java | 9 ++++++++ .../db/qualitygate/QualityGateMapper.java | 5 ++++ .../db/qualitygate/QualityGateMapper.xml | 12 ++++++++++ .../db/qualitygate/QualityGateDaoTest.java | 23 +++++++++++++++++++ .../server/organization/ws/DeleteAction.java | 14 +++++++---- .../organization/ws/DeleteActionTest.java | 20 ++++++++++++++++ 6 files changed, 78 insertions(+), 5 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java index 5e226c64537..1529d4f7fa6 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java @@ -23,6 +23,7 @@ import java.util.Collection; import java.util.Date; import javax.annotation.CheckForNull; import org.sonar.db.Dao; +import org.sonar.db.DatabaseUtils; import org.sonar.db.DbSession; import org.sonar.db.organization.OrganizationDto; @@ -76,6 +77,14 @@ public class QualityGateDao implements Dao { mapper(session).deleteOrgQualityGatesByQualityGateUuid(qGate.getUuid()); } + public void deleteByUuids(DbSession session, Collection uuids) { + QualityGateMapper mapper = mapper(session); + DatabaseUtils.executeLargeUpdates(uuids, partitionUuids -> { + mapper.deleteByUuids(partitionUuids); + mapper.deleteOrgQualityGatesByQualityGateUuids(partitionUuids); + }); + } + public void update(QualityGateDto qGate, DbSession session) { mapper(session).update(qGate.setUpdatedAt(new Date())); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java index b804b904f0e..783d32bc650 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java @@ -19,6 +19,7 @@ */ package org.sonar.db.qualitygate; +import java.util.Collection; import java.util.List; import org.apache.ibatis.annotations.Param; @@ -46,8 +47,12 @@ public interface QualityGateMapper { void delete(String uuid); + void deleteByUuids(@Param("uuids") Collection uuids); + void deleteOrgQualityGatesByQualityGateUuid(String uuid); + void deleteOrgQualityGatesByQualityGateUuids(@Param("uuids") Collection uuids); + void update(QualityGateDto qGate); void ensureOneBuiltInQualityGate(String builtInQualityName); diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml index 89142897865..a235cefcf90 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml @@ -103,10 +103,22 @@ delete from quality_gates where uuid=#{uuid} + + delete from quality_gates + where uuid in + #{uuid, jdbcType=VARCHAR} + + delete from org_quality_gates where quality_gate_uuid=#{uuid} + + delete from org_quality_gates + where quality_gate_uuid in + #{uuid, jdbcType=VARCHAR} + + update quality_gates set name=#{name}, diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java index 03705830256..8c950112625 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java @@ -19,6 +19,7 @@ */ package org.sonar.db.qualitygate; +import java.util.Collections; import java.util.Date; import org.junit.Rule; import org.junit.Test; @@ -29,6 +30,7 @@ import org.sonar.db.DbTester; import org.sonar.db.organization.OrganizationDto; import static java.lang.String.format; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; public class QualityGateDaoTest { @@ -174,6 +176,27 @@ public class QualityGateDaoTest { assertThat(db.countSql(dbSession, format("select count(*) from org_quality_gates where quality_gate_uuid='%s'", otherQualityGate.getUuid()))).isEqualTo(1); } + @Test + public void delete_by_uuids() { + OrganizationDto organization = db.organizations().insert(); + QGateWithOrgDto qualityGate1 = qualityGateDbTester.insertQualityGate(organization); + QGateWithOrgDto qualityGate2 = qualityGateDbTester.insertQualityGate(organization); + + underTest.deleteByUuids(dbSession, asList(qualityGate1.getUuid(), qualityGate2.getUuid())); + dbSession.commit(); + + assertThat(db.countRowsOfTable(dbSession, "quality_gates")).isZero(); + assertThat(db.countRowsOfTable(dbSession, "org_quality_gates")).isZero(); + } + + @Test + public void delete_by_uuids_does_nothing_on_empty_list() { + underTest.deleteByUuids(dbSession, Collections.emptyList()); + dbSession.commit(); + + assertThat(db.countRowsOfTable(dbSession, "quality_gates")).isZero(); + } + @Test public void update() { OrganizationDto organization = db.organizations().insert(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/DeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/DeleteAction.java index f3c4f596446..6a50ee5ef12 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/DeleteAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/DeleteAction.java @@ -24,10 +24,12 @@ import java.util.List; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; +import org.sonar.core.util.stream.MoreCollectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.db.qualityprofile.QProfileDto; import org.sonar.server.component.ComponentCleanerService; import org.sonar.server.organization.DefaultOrganization; @@ -93,11 +95,7 @@ public class DeleteAction implements OrganizationsWsAction { String key = request.mandatoryParam(PARAM_ORGANIZATION); preventDeletionOfDefaultOrganization(key, defaultOrganizationProvider.get()); - OrganizationDto organization = checkFoundWithOptional( - dbClient.organizationDao().selectByKey(dbSession, key), - "Organization with key '%s' not found", - key); - + OrganizationDto organization = checkFoundWithOptional(dbClient.organizationDao().selectByKey(dbSession, key), "Organization with key '%s' not found", key); if (organization.isGuarded()) { userSession.checkIsSystemAdministrator(); } else { @@ -108,6 +106,7 @@ public class DeleteAction implements OrganizationsWsAction { deletePermissions(dbSession, organization); deleteGroups(dbSession, organization); deleteQualityProfiles(dbSession, organization); + deleteQualityGates(dbSession, organization); deleteOrganization(dbSession, organization); response.noContent(); @@ -138,6 +137,11 @@ public class DeleteAction implements OrganizationsWsAction { qProfileFactory.delete(dbSession, profiles); } + private void deleteQualityGates(DbSession dbSession, OrganizationDto organization) { + Collection qualityGates = dbClient.qualityGateDao().selectAll(dbSession, organization); + dbClient.qualityGateDao().deleteByUuids(dbSession, qualityGates.stream().map(QualityGateDto::getUuid).collect(MoreCollectors.toList())); + } + private void deleteOrganization(DbSession dbSession, OrganizationDto organization) { Collection logins = dbClient.organizationMemberDao().selectLoginsByOrganizationUuid(dbSession, organization.getUuid()); dbClient.organizationMemberDao().deleteByOrganizationUuid(dbSession, organization.getUuid()); diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java index 95b37cc554d..f6db373cd88 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java @@ -35,6 +35,7 @@ import org.sonar.db.component.ComponentTesting; import org.sonar.db.component.ResourceTypesRule; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.permission.template.PermissionTemplateDto; +import org.sonar.db.qualitygate.QGateWithOrgDto; import org.sonar.db.qualityprofile.QProfileDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; @@ -348,6 +349,25 @@ public class DeleteActionTest { .containsOnly(profileInOtherOrg.getKee()); } + @Test + public void delete_quality_gates() { + OrganizationDto org = db.organizations().insert(); + OrganizationDto otherOrg = db.organizations().insert(); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(org); + QGateWithOrgDto qualityGateInOtherOrg = db.qualityGates().insertQualityGate(otherOrg); + logInAsAdministrator(org); + + sendRequest(org); + + verifyOrganizationDoesNotExist(org); + assertThat(db.select("select uuid as \"uuid\" from quality_gates")) + .extracting(row -> (String) row.get("uuid")) + .containsOnly(qualityGateInOtherOrg.getUuid()); + assertThat(db.select("select organization_uuid as \"organizationUuid\" from org_quality_gates")) + .extracting(row -> (String) row.get("organizationUuid")) + .containsOnly(otherOrg.getUuid()); + } + private void verifyOrganizationDoesNotExist(OrganizationDto organization) { assertThat(db.getDbClient().organizationDao().selectByKey(session, organization.getKey())).isEmpty(); } -- 2.39.5