diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2017-06-12 22:57:00 +0200 |
---|---|---|
committer | Eric Hartmann <hartmann.eric@gmail.com> | 2017-06-14 15:43:13 +0200 |
commit | bce59a878501872b105e120bc0d8e13494f79aee (patch) | |
tree | 44862b1c6e1887eddd561223ed12b8ffefcd7044 /server/sonar-db-dao | |
parent | dd5713279b5b6beccdb5cc65681dbde25898f035 (diff) | |
download | sonarqube-bce59a878501872b105e120bc0d8e13494f79aee.tar.gz sonarqube-bce59a878501872b105e120bc0d8e13494f79aee.zip |
SONAR-9305 Built-in quality profiles should be updated automatically
Diffstat (limited to 'server/sonar-db-dao')
9 files changed, 180 insertions, 9 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java index 71002640fad..e62d881de6d 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java @@ -71,6 +71,10 @@ public class ActiveRuleDao implements Dao { return selectByProfileUuid(dbSession, profile.getKee()); } + public List<ActiveRuleDto> selectByRuleProfile(DbSession dbSession, RulesProfileDto ruleProfileDto) { + return mapper(dbSession).selectByRuleProfileUuid(ruleProfileDto.getKee()); + } + public ActiveRuleDto insert(DbSession dbSession, ActiveRuleDto item) { Preconditions.checkArgument(item.getProfileId() != null, QUALITY_PROFILE_IS_NOT_PERSISTED); Preconditions.checkArgument(item.getRuleId() != null, RULE_IS_NOT_PERSISTED); @@ -101,6 +105,11 @@ public class ActiveRuleDao implements Dao { DatabaseUtils.executeLargeUpdates(rulesProfileUuids, mapper::deleteByRuleProfileUuids); } + public void deleteByIds(DbSession dbSession, List<Integer> activeRuleIds) { + ActiveRuleMapper mapper = mapper(dbSession); + DatabaseUtils.executeLargeUpdates(activeRuleIds, mapper::deleteByIds); + } + public void deleteParametersByRuleProfileUuids(DbSession dbSession, Collection<String> rulesProfileUuids) { ActiveRuleMapper mapper = mapper(dbSession); DatabaseUtils.executeLargeUpdates(rulesProfileUuids, mapper::deleteParametersByRuleProfileUuids); @@ -152,6 +161,11 @@ public class ActiveRuleDao implements Dao { } } + public void deleteParamsByActiveRuleIds(DbSession dbSession, List<Integer> activeRuleIds) { + ActiveRuleMapper mapper = mapper(dbSession); + DatabaseUtils.executeLargeUpdates(activeRuleIds, mapper::deleteParamsByActiveRuleIds); + } + /** * Active rule on removed rule are NOT taken into account */ @@ -176,5 +190,4 @@ public class ActiveRuleDao implements Dao { private static ActiveRuleMapper mapper(DbSession dbSession) { return dbSession.getMapper(ActiveRuleMapper.class); } - } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java index 9e58d80c3d9..5c384a20ccd 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java @@ -36,6 +36,8 @@ public interface ActiveRuleMapper { void deleteByRuleProfileUuids(@Param("rulesProfileUuids") Collection<String> rulesProfileUuids); + void deleteByIds(@Param("ids") Collection<Integer> ids); + @CheckForNull ActiveRuleDto selectByKey(@Param("ruleProfileUuid") String ruleProfileUuid, @Param("repository") String repository, @Param("rule") String rule); @@ -49,6 +51,8 @@ public interface ActiveRuleMapper { List<OrgActiveRuleDto> selectByProfileUuid(String uuid); + List<ActiveRuleDto> selectByRuleProfileUuid(@Param("ruleProfileUuid") String uuid); + void insertParameter(ActiveRuleParamDto dto); void updateParameter(ActiveRuleParamDto dto); @@ -59,6 +63,8 @@ public interface ActiveRuleMapper { void deleteParameter(int activeRuleParamId); + void deleteParamsByActiveRuleIds(@Param("activeRuleIds") Collection<Integer> activeRuleIds); + List<ActiveRuleParamDto> selectParamsByActiveRuleId(int activeRuleId); List<ActiveRuleParamDto> selectParamsByActiveRuleIds(@Param("ids") List<Integer> ids); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java index 14b53010472..6f82c926bd1 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java @@ -109,9 +109,15 @@ public class QualityProfileDao implements Dao { } } + public void update(DbSession dbSession, RulesProfileDto rulesProfile) { + QualityProfileMapper mapper = mapper(dbSession); + long now = system.now(); + mapper.updateRuleProfile(rulesProfile, new Date(now)); + } + private void doUpdate(QualityProfileMapper mapper, QProfileDto profile, long now) { - mapper.updateRuleProfile(profile, new Date(now)); - mapper.updateOrgQProfile(profile, now); + mapper.updateRuleProfile(RulesProfileDto.from(profile), new Date(now)); + mapper.updateOrgQProfile(OrgQProfileDto.from(profile), now); } public List<QProfileDto> selectDefaultProfiles(DbSession dbSession, OrganizationDto organization, Collection<String> languages) { @@ -220,6 +226,10 @@ public class QualityProfileDao implements Dao { DatabaseUtils.executeLargeUpdates(rulesProfileUuids, mapper::deleteRuleProfilesByUuids); } + public List<QProfileDto> selectChildrenOfBuiltInRulesProfile(DbSession dbSession, RulesProfileDto rulesProfile) { + return mapper(dbSession).selectChildrenOfBuiltInRulesProfile(rulesProfile.getKee()); + } + private static String sqlQueryString(@Nullable String query) { if (query == null) { return "%"; diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java index 9121d9a40b4..758786dc15c 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java @@ -32,9 +32,9 @@ public interface QualityProfileMapper { void insertRuleProfile(@Param("dto") RulesProfileDto dto, @Param("now") Date now); - void updateRuleProfile(@Param("dto") QProfileDto dto, @Param("now") Date now); + void updateRuleProfile(@Param("dto") RulesProfileDto dto, @Param("now") Date now); - void updateOrgQProfile(@Param("dto") QProfileDto dto, @Param("now") long now); + void updateOrgQProfile(@Param("dto") OrgQProfileDto dto, @Param("now") long now); void deleteRuleProfilesByUuids(@Param("uuids") Collection<String> uuids); @@ -121,4 +121,6 @@ public interface QualityProfileMapper { List<String> selectUuidsOfCustomRuleProfiles(@Param("language") String language, @Param("name") String name); void renameRuleProfiles(@Param("newName") String newName, @Param("updatedAt") Date updatedAt, @Param("uuids") Collection<String> uuids); + + List<QProfileDto> selectChildrenOfBuiltInRulesProfile(@Param("rulesProfileUuid") String rulesProfileUuid); } diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml index 9948c028ebe..840467e7e8b 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml @@ -81,6 +81,13 @@ ) </delete> + <delete id="deleteByIds" parameterType="Integer"> + delete from active_rules + where + id in + <foreach collection="ids" open="(" close=")" item="id" separator=",">#{id, jdbcType=INTEGER}</foreach> + </delete> + <select id="selectByKey" parameterType="map" resultType="ActiveRule"> select <include refid="activeRuleColumns"/> @@ -116,6 +123,15 @@ where oqp.uuid = #{id, jdbcType=VARCHAR} </select> + <select id="selectByRuleProfileUuid" parameterType="string" resultType="org.sonar.db.qualityprofile.ActiveRuleDto"> + select + <include refid="activeRuleColumns"/> + from active_rules a + <include refid="activeRuleKeyJoin"/> + where + rp.kee = #{ruleProfileUuid, jdbcType=VARCHAR} + </select> + <select id="selectByRuleId" parameterType="map" resultType="org.sonar.db.qualityprofile.OrgActiveRuleDto"> select <include refid="orgActiveRuleColumns"/> @@ -203,6 +219,13 @@ DELETE FROM active_rule_parameters WHERE id=#{id, jdbcType=BIGINT} </delete> + <delete id="deleteParamsByActiveRuleIds" parameterType="Integer"> + delete from active_rule_parameters + where + active_rule_id in + <foreach collection="activeRuleIds" open="(" close=")" item="activeRuleId" separator=",">#{activeRuleId, jdbcType=INTEGER}</foreach> + </delete> + <select id="selectParamsByActiveRuleId" parameterType="Integer" resultType="ActiveRuleParam"> select <include refid="activeRuleParamColumns"/> diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml index 35b8cbdfcb0..1f8add3639b 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml @@ -77,18 +77,18 @@ rules_updated_at = #{dto.rulesUpdatedAt, jdbcType=VARCHAR}, is_built_in = #{dto.isBuiltIn, jdbcType=BOOLEAN} where - kee = #{dto.rulesProfileUuid, jdbcType=VARCHAR} + kee = #{dto.kee, jdbcType=VARCHAR} </update> <update id="updateOrgQProfile" parameterType="map"> update org_qprofiles set - parent_uuid = #{dto.parentKee, jdbcType=VARCHAR}, + parent_uuid = #{dto.parentUuid, jdbcType=VARCHAR}, last_used = #{dto.lastUsed, jdbcType=BIGINT}, user_updated_at = #{dto.userUpdatedAt, jdbcType=BIGINT}, updated_at = #{now, jdbcType=BIGINT} where - uuid = #{dto.kee, jdbcType=VARCHAR} + uuid = #{dto.uuid, jdbcType=VARCHAR} </update> <delete id="deleteRuleProfilesByUuids" parameterType="String"> @@ -335,5 +335,18 @@ where kee in <foreach collection="uuids" open="(" close=")" item="uuid" separator=",">#{uuid, jdbcType=VARCHAR}</foreach> </update> + + <select id="selectChildrenOfBuiltInRulesProfile" parameterType="string" resultType="org.sonar.db.qualityprofile.QProfileDto"> + select + <include refid="qProfileColumns"/> + from org_qprofiles oqp + inner join rules_profiles rp on oqp.rules_profile_uuid = rp.kee + inner join org_qprofiles parentoqp on parentoqp.uuid = oqp.parent_uuid + inner join rules_profiles parentrp on parentoqp.rules_profile_uuid = parentrp.kee + where + parentrp.kee = #{rulesProfileUuid, jdbcType=VARCHAR} + and parentrp.is_built_in = ${_true} + and oqp.parent_uuid is not null + </select> </mapper> diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java index fd293237cda..62c4c989d77 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java @@ -151,7 +151,7 @@ public class ActiveRuleDaoTest { } @Test - public void selectByProfileUuid_ignores_removed_rules() throws Exception { + public void selectByProfileUuid_ignores_removed_rules() { ActiveRuleDto activeRule = createFor(profile1, removedRule).setSeverity(BLOCKER); underTest.insert(dbSession, activeRule); @@ -159,6 +159,22 @@ public class ActiveRuleDaoTest { } @Test + public void selectByRuleProfileUuid() { + ActiveRuleDto activeRule1 = createFor(profile1, rule1).setSeverity(BLOCKER); + ActiveRuleDto activeRule2 = createFor(profile1, rule2).setSeverity(MAJOR); + underTest.insert(dbSession, activeRule1); + underTest.insert(dbSession, activeRule2); + + List<ActiveRuleDto> result = underTest.selectByRuleProfile(dbSession, RulesProfileDto.from(profile1)); + assertThat(result) + .hasSize(2) + .extracting(ActiveRuleDto::getProfileId, ActiveRuleDto::getRuleKey, ActiveRuleDto::getSeverityString) + .containsOnly(tuple(profile1.getId(), rule1.getKey(), BLOCKER), tuple(profile1.getId(), rule2.getKey(), MAJOR)); + + assertThat(underTest.selectByProfile(dbSession, profile2)).isEmpty(); + } + + @Test public void insert() { ActiveRuleDto activeRule = createFor(profile1, rule1) .setSeverity(BLOCKER) @@ -297,6 +313,29 @@ public class ActiveRuleDaoTest { assertThat(db.countRowsOfTable(dbSession, "active_rules")).isEqualTo(1); } + @Test + public void deleteByIds() { + ActiveRuleDto ar1 = underTest.insert(dbSession, newRow(profile1, rule1)); + ActiveRuleDto ar2 = underTest.insert(dbSession, newRow(profile1, rule2)); + ActiveRuleDto ar3 = underTest.insert(dbSession, newRow(profile2, rule1)); + + underTest.deleteByIds(dbSession, asList(ar1.getId(), ar3.getId())); + + assertThat(db.countRowsOfTable(dbSession, "active_rules")).isEqualTo(1); + assertThat(underTest.selectByProfile(dbSession, profile1)) + .extracting(ActiveRuleDto::getId) + .containsExactly(ar2.getId()); + } + + @Test + public void deleteByIds_does_nothing_if_empty_list_of_ids() { + underTest.insert(dbSession, newRow(profile1, rule1)); + + underTest.deleteByIds(dbSession, emptyList()); + + assertThat(db.countRowsOfTable(dbSession, "active_rules")).isEqualTo(1); + } + private static ActiveRuleDto newRow(QProfileDto profile, RuleDefinitionDto rule) { return createFor(profile, rule).setSeverity(BLOCKER); } @@ -461,6 +500,22 @@ public class ActiveRuleDaoTest { } @Test + public void deleteParamsByActiveRuleIds() { + ActiveRuleDto ar1 = underTest.insert(dbSession, newRow(profile1, rule1)); + ActiveRuleParamDto param = ActiveRuleParamDto.createFor(rule1Param1).setValue("foo"); + underTest.insertParam(dbSession, ar1, param); + + ActiveRuleDto ar2 = underTest.insert(dbSession, newRow(profile1, rule2)); + ActiveRuleParamDto param2 = ActiveRuleParamDto.createFor(rule2Param1).setValue("bar"); + underTest.insertParam(dbSession, ar2, param2); + + underTest.deleteParamsByActiveRuleIds(dbSession, asList(ar1.getId())); + + assertThat(underTest.selectParamsByActiveRuleId(dbSession, ar1.getId())).hasSize(0); + assertThat(underTest.selectParamsByActiveRuleId(dbSession, ar2.getId())).hasSize(1); + } + + @Test public void test_countActiveRulesByProfileKey_for_a_specified_organization() { db.qualityProfiles().activateRule(profile1, rule1); db.qualityProfiles().activateRule(profile1, rule2); diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java index 3fb9e58832a..48ae7bd63ef 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java @@ -49,7 +49,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.sonar.core.util.stream.MoreCollectors.toList; import static org.sonar.db.qualityprofile.QualityProfileTesting.newQualityProfileDto; +import static org.sonar.db.qualityprofile.RulesProfileDto.from; public class QualityProfileDaoTest { @@ -721,4 +723,35 @@ public class QualityProfileDaoTest { return Arrays.asList(dto1, dto2); } + @Test + public void selectChildrenOfBuiltInRulesProfile_must_return_only_inherited_profiles() { + OrganizationDto org1 = db.organizations().insert(); + OrganizationDto org2 = db.organizations().insert(); + OrganizationDto org3 = db.organizations().insert(); + + QProfileDto builtInProfile = db.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(true).setLanguage("java").setName("foo")); + QProfileDto javaProfileOrg2 = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); + QProfileDto inheritedJavaProfileOrg2 = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo").setParentKee(builtInProfile.getKee())); + QProfileDto differentLanguage = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("cobol").setName("foo")); + QProfileDto differentName = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("bar")); + QProfileDto javaProfileOrg3 = db.qualityProfiles().insert(org3, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); + QProfileDto inheritedJavaProfileOrg3 = db.qualityProfiles().insert(org3, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo").setParentKee(builtInProfile.getKee())); + + List<QProfileDto> children = db.getDbClient().qualityProfileDao().selectChildrenOfBuiltInRulesProfile(db.getSession(), from(builtInProfile)); + + assertThat(children.stream().map(qp -> qp.getId()).collect(toList())).containsExactlyInAnyOrder( + inheritedJavaProfileOrg2.getId(), inheritedJavaProfileOrg3.getId()); + } + + @Test + public void selectChildrenOfBuiltInRulesProfile_must_return_empty_list_if_not_built_in() { + OrganizationDto org = db.organizations().insert(); + + QProfileDto notBuiltInProfile = db.qualityProfiles().insert(org, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); + QProfileDto inheritedProfile = db.qualityProfiles().insert(org, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo").setParentKee(notBuiltInProfile.getKee())); + + List<QProfileDto> children = db.getDbClient().qualityProfileDao().selectChildrenOfBuiltInRulesProfile(db.getSession(), from(notBuiltInProfile)); + + assertThat(children).isEmpty(); + } } diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileTesting.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileTesting.java index 10958208dbc..fac9f8c8a33 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileTesting.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileTesting.java @@ -19,8 +19,11 @@ */ package org.sonar.db.qualityprofile; +import java.util.function.Consumer; import org.sonar.core.util.Uuids; +import static java.util.Arrays.stream; +import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.apache.commons.lang.math.RandomUtils.nextLong; @@ -56,4 +59,17 @@ public class QualityProfileTesting { .setChangeType("ACTIVATED") .setLogin(randomAlphanumeric(10)); } + + /** + * Create an instance of {@link RulesProfileDto} with most of random field values. + */ + public static RulesProfileDto newRuleProfileDto(Consumer<RulesProfileDto>... populators) { + RulesProfileDto dto = new RulesProfileDto() + .setKee("uuid" + randomAlphabetic(10)) + .setName("name" + randomAlphabetic(10)) + .setLanguage("lang" + randomAlphabetic(5)) + .setIsBuiltIn(false); + stream(populators).forEach(p -> p.accept(dto)); + return dto; + } } |