@@ -29,6 +29,7 @@ import it.duplication.CrossProjectDuplicationsOnRemoveFileTest; | |||
import it.duplication.CrossProjectDuplicationsTest; | |||
import it.duplication.DuplicationsTest; | |||
import it.duplication.NewDuplicationsTest; | |||
import it.organization.RootUserTest; | |||
import it.projectEvent.EventTest; | |||
import it.projectEvent.ProjectActivityPageTest; | |||
import it.qualityProfile.QualityProfilesPageTest; | |||
@@ -57,6 +58,8 @@ import static util.ItUtils.xooPlugin; | |||
@RunWith(Suite.class) | |||
@Suite.SuiteClasses({ | |||
// organization | |||
RootUserTest.class, | |||
// server system | |||
ServerSystemTest.class, | |||
PingTest.class, |
@@ -19,7 +19,6 @@ | |||
*/ | |||
package it; | |||
import it.organization.RootTest; | |||
import it.serverSystem.ClusterTest; | |||
import it.serverSystem.RestartTest; | |||
import it.serverSystem.ServerSystemRestartingOrchestrator; | |||
@@ -46,8 +45,7 @@ import org.junit.runners.Suite; | |||
// update center | |||
UpdateCenterTest.class, | |||
RealmAuthenticationTest.class, | |||
SsoAuthenticationTest.class, | |||
RootTest.class | |||
SsoAuthenticationTest.class | |||
}) | |||
public class Category5Suite { | |||
@@ -20,6 +20,7 @@ | |||
package it; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import com.sonar.orchestrator.http.HttpMethod; | |||
import it.issue.IssueTagsTest; | |||
import it.issue.OrganizationIssueAssignTest; | |||
import it.organization.BillingTest; | |||
@@ -27,6 +28,7 @@ import it.organization.OrganizationMembershipTest; | |||
import it.organization.OrganizationTest; | |||
import it.projectSearch.LeakProjectsPageTest; | |||
import it.projectSearch.SearchProjectsTest; | |||
import it.organization.RootUserOnOrganizationTest; | |||
import it.qualityProfile.OrganizationQualityProfilesPageTest; | |||
import it.qualityProfile.QualityProfilesBuiltInTest; | |||
import it.uiExtension.OrganizationUiExtensionsTest; | |||
@@ -36,7 +38,6 @@ import org.junit.ClassRule; | |||
import org.junit.runner.RunWith; | |||
import org.junit.runners.Suite; | |||
import static java.util.Collections.emptyMap; | |||
import static util.ItUtils.pluginArtifact; | |||
import static util.ItUtils.xooPlugin; | |||
@@ -50,6 +51,7 @@ import static util.ItUtils.xooPlugin; | |||
OrganizationMembershipTest.class, | |||
OrganizationQualityProfilesPageTest.class, | |||
OrganizationTest.class, | |||
RootUserOnOrganizationTest.class, | |||
OrganizationUiExtensionsTest.class, | |||
QualityProfilesBuiltInTest.class, | |||
BillingTest.class, | |||
@@ -73,6 +75,10 @@ public class Category6Suite { | |||
} | |||
public static void enableOrganizationsSupport() { | |||
ORCHESTRATOR.getServer().post("api/organizations/enable_support", emptyMap()); | |||
ORCHESTRATOR.getServer() | |||
.newHttpCall("api/organizations/enable_support") | |||
.setMethod(HttpMethod.POST) | |||
.setAdminCredentials() | |||
.execute(); | |||
} | |||
} |
@@ -50,7 +50,7 @@ import static it.Category6Suite.enableOrganizationsSupport; | |||
import static java.lang.String.format; | |||
import static java.util.Collections.singletonList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static util.ItUtils.deleteOrganizationsIfExists; | |||
import static util.ItUtils.deleteOrganizations; | |||
import static util.ItUtils.newAdminWsClient; | |||
import static util.ItUtils.newOrganizationKey; | |||
import static util.ItUtils.restoreProfile; | |||
@@ -97,7 +97,7 @@ public class OrganizationIssueAssignTest { | |||
@After | |||
public void tearDown() throws Exception { | |||
userRule.deactivateUsers(ASSIGNEE_LOGIN, OTHER_LOGIN); | |||
deleteOrganizationsIfExists(orchestrator, ORGANIZATION_KEY, OTHER_ORGANIZATION_KEY); | |||
deleteOrganizations(orchestrator); | |||
} | |||
@Test |
@@ -44,7 +44,7 @@ import util.user.UserRule; | |||
import static it.Category6Suite.enableOrganizationsSupport; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static util.ItUtils.deleteOrganizationsIfExists; | |||
import static util.ItUtils.deleteOrganizations; | |||
import static util.ItUtils.newAdminWsClient; | |||
import static util.ItUtils.newOrganizationKey; | |||
import static util.ItUtils.newUserWsClient; | |||
@@ -73,12 +73,12 @@ public class OrganizationMembershipTest { | |||
adminClient = newAdminWsClient(orchestrator); | |||
enableOrganizationsSupport(); | |||
setServerProperty(orchestrator, "sonar.organizations.anyoneCanCreate", "true"); | |||
deleteOrganizationsIfExists(orchestrator, KEY); | |||
deleteOrganizations(orchestrator); | |||
} | |||
@After | |||
public void tearDown() throws Exception { | |||
deleteOrganizationsIfExists(orchestrator, KEY); | |||
deleteOrganizations(orchestrator); | |||
} | |||
@Test |
@@ -58,7 +58,7 @@ import static java.util.Collections.singletonList; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.junit.Assert.fail; | |||
import static util.ItUtils.deleteOrganizationsIfExists; | |||
import static util.ItUtils.deleteOrganizations; | |||
import static util.ItUtils.newAdminWsClient; | |||
import static util.ItUtils.newUserWsClient; | |||
import static util.ItUtils.newWsClient; | |||
@@ -95,13 +95,13 @@ public class OrganizationTest { | |||
@Before | |||
public void setUp() throws Exception { | |||
resetSettings(orchestrator, null, SETTING_ANYONE_CAN_CREATE_ORGANIZATIONS); | |||
deleteOrganizationsIfExists(orchestrator, KEY, "an-org"); | |||
deleteOrganizations(orchestrator); | |||
userRule.deactivateUsers(USER_LOGIN); | |||
} | |||
@After | |||
public void tearDown() throws Exception { | |||
deleteOrganizationsIfExists(orchestrator, KEY, "an-org"); | |||
deleteOrganizations(orchestrator); | |||
} | |||
@Test | |||
@@ -275,6 +275,7 @@ public class OrganizationTest { | |||
@Test | |||
public void an_organization_member_can_analyze_project() { | |||
assertThatOrganizationDoesNotExit(KEY); | |||
Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder() | |||
@@ -459,13 +460,14 @@ public class OrganizationTest { | |||
for (QualityProfiles.SearchWsResponse.QualityProfile profile : response.getProfilesList()) { | |||
assertThat(profile.getIsInherited()).isFalse(); | |||
assertThat(profile.getProjectCount()).isEqualTo(0); | |||
assertThat(profile.getIsBuiltIn()).isTrue(); | |||
if (profile.getName().toLowerCase(Locale.ENGLISH).contains("empty")) { | |||
assertThat(profile.getActiveRuleCount()).isEqualTo(0); | |||
} else { | |||
assertThat(profile.getActiveRuleCount()).isGreaterThan(0); | |||
// that allows to check the Elasticsearch index of active rules | |||
Rules.SearchResponse activeRulesResponse = adminClient.rules().search(new org.sonarqube.ws.client.rule.SearchWsRequest().setActivation(true).setQProfile(profile.getKey())); | |||
assertThat(activeRulesResponse.getTotal()).isEqualTo(profile.getActiveRuleCount()); | |||
assertThat(activeRulesResponse.getTotal()).as("profile " + profile.getName()).isEqualTo(profile.getActiveRuleCount()); | |||
assertThat(activeRulesResponse.getRulesCount()).isEqualTo((int)profile.getActiveRuleCount()); | |||
} | |||
} |
@@ -20,55 +20,56 @@ | |||
package it.organization; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import it.Category6Suite; | |||
import java.sql.SQLException; | |||
import java.util.Collections; | |||
import org.junit.After; | |||
import org.junit.Before; | |||
import org.junit.BeforeClass; | |||
import org.junit.ClassRule; | |||
import org.junit.Test; | |||
import org.sonarqube.ws.WsRoot; | |||
import org.sonarqube.ws.client.HttpException; | |||
import org.sonarqube.ws.client.WsClient; | |||
import org.sonarqube.ws.client.user.SearchRequest; | |||
import org.sonarqube.ws.client.user.UsersService; | |||
import util.user.UserRule; | |||
import static it.Category6Suite.enableOrganizationsSupport; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.fail; | |||
import static util.ItUtils.newAdminWsClient; | |||
import static util.ItUtils.newUserWsClient; | |||
import static util.ItUtils.newWsClient; | |||
public class RootTest { | |||
public class RootUserOnOrganizationTest { | |||
private static Orchestrator orchestrator; | |||
@ClassRule | |||
public static Orchestrator orchestrator = Category6Suite.ORCHESTRATOR; | |||
private static UserRule userRule; | |||
@Before | |||
public void start() { | |||
orchestrator = Orchestrator.builderEnv().build(); | |||
orchestrator.start(); | |||
userRule = UserRule.from(orchestrator); | |||
} | |||
@After | |||
public void stop() { | |||
if (orchestrator != null) { | |||
orchestrator.stop(); | |||
userRule = null; | |||
} | |||
public void tearDown() throws Exception { | |||
UsersService service = newAdminWsClient(orchestrator).users(); | |||
service.search(SearchRequest.builder().build()).getUsersList() | |||
.stream() | |||
.filter(u -> !u.getLogin().equals("admin")) | |||
.forEach(u -> { | |||
userRule.deactivateUsers(u.getLogin()); | |||
}); | |||
} | |||
@Test | |||
public void nobody_is_root_by_default() { | |||
// anonymous | |||
verifyHttpError(() -> newWsClient(orchestrator).rootService().search(), 403); | |||
// admin | |||
verifyHttpError(() -> newAdminWsClient(orchestrator).rootService().search(), 403); | |||
@BeforeClass | |||
public static void enableOrganizations() throws Exception { | |||
enableOrganizationsSupport(); | |||
} | |||
@Test | |||
public void system_administrator_is_flagged_as_root_when_he_enables_organization_support() { | |||
enableOrganizationSupport(); | |||
assertThat(newAdminWsClient(orchestrator).rootService().search().getRootsList()) | |||
.extracting(WsRoot.Root::getLogin) | |||
.containsOnly(UserRule.ADMIN_LOGIN); | |||
@@ -76,7 +77,6 @@ public class RootTest { | |||
@Test | |||
public void a_root_can_flag_other_user_as_root() { | |||
enableOrganizationSupport(); | |||
userRule.createUser("bar", "foo"); | |||
userRule.setRoot("bar"); | |||
@@ -87,13 +87,11 @@ public class RootTest { | |||
@Test | |||
public void last_root_can_not_be_unset_root() throws SQLException { | |||
enableOrganizationSupport(); | |||
verifyHttpError(() -> newAdminWsClient(orchestrator).rootService().unsetRoot(UserRule.ADMIN_LOGIN), 400); | |||
} | |||
@Test | |||
public void root_can_be_set_and_unset_via_web_services() { | |||
enableOrganizationSupport(); | |||
userRule.createUser("root1", "bar"); | |||
userRule.createUser("root2", "bar"); | |||
WsClient root1WsClient = newUserWsClient(orchestrator, "root1", "bar"); | |||
@@ -114,11 +112,7 @@ public class RootTest { | |||
// root2 can unset root itself as it's not the last root | |||
root2WsClient.rootService().unsetRoot("root2"); | |||
} | |||
private static void enableOrganizationSupport() { | |||
orchestrator.getServer().post("api/organizations/enable_support", Collections.emptyMap()); | |||
} | |||
private static void verifyHttpError(Runnable runnable, int expectedErrorCode) { | |||
try { | |||
runnable.run(); |
@@ -0,0 +1,55 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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 it.organization; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import it.Category4Suite; | |||
import org.junit.ClassRule; | |||
import org.junit.Test; | |||
import org.sonarqube.ws.client.HttpException; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.fail; | |||
import static util.ItUtils.newAdminWsClient; | |||
import static util.ItUtils.newWsClient; | |||
public class RootUserTest { | |||
@ClassRule | |||
public static Orchestrator orchestrator = Category4Suite.ORCHESTRATOR; | |||
@Test | |||
public void nobody_is_root_by_default() { | |||
// anonymous | |||
verifyHttpError(() -> newWsClient(orchestrator).rootService().search(), 403); | |||
// admin | |||
verifyHttpError(() -> newAdminWsClient(orchestrator).rootService().search(), 403); | |||
} | |||
private static void verifyHttpError(Runnable runnable, int expectedErrorCode) { | |||
try { | |||
runnable.run(); | |||
fail("Ws Call should have failed with http code " + expectedErrorCode); | |||
} catch (HttpException e) { | |||
assertThat(e.code()).isEqualTo(expectedErrorCode); | |||
} | |||
} | |||
} |
@@ -37,7 +37,7 @@ import pageobjects.Navigation; | |||
import static com.codeborne.selenide.Selenide.$; | |||
import static it.Category6Suite.enableOrganizationsSupport; | |||
import static util.ItUtils.deleteOrganizationsIfExists; | |||
import static util.ItUtils.deleteOrganizations; | |||
import static util.ItUtils.newAdminWsClient; | |||
import static util.ItUtils.projectDir; | |||
import static util.selenium.Selenese.runSelenese; | |||
@@ -59,7 +59,7 @@ public class OrganizationQualityProfilesPageTest { | |||
@AfterClass | |||
public static void tearDown() throws Exception { | |||
deleteOrganizationsIfExists(orchestrator, ORGANIZATION); | |||
deleteOrganizations(orchestrator); | |||
} | |||
@Before |
@@ -33,7 +33,7 @@ import util.ItUtils; | |||
import static it.Category6Suite.enableOrganizationsSupport; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static util.ItUtils.deleteOrganizationsIfExists; | |||
import static util.ItUtils.deleteOrganizations; | |||
import static util.ItUtils.newAdminWsClient; | |||
import static util.ItUtils.newWsClient; | |||
@@ -56,8 +56,7 @@ public class RulesPerOrganizationTest { | |||
@AfterClass | |||
public static void tearDown() throws Exception { | |||
deleteOrganizationsIfExists(orchestrator, ORGANIZATION_FOO); | |||
deleteOrganizationsIfExists(orchestrator, ORGANIZATION_BAR); | |||
deleteOrganizations(orchestrator); | |||
} | |||
private static void createOrganization(String organization) { |
@@ -372,10 +372,12 @@ public class ItUtils { | |||
return "key-" + randomAlphabetic(100); | |||
} | |||
public static void deleteOrganizationsIfExists(Orchestrator orchestrator, String... organizationKeys) { | |||
OrganizationService adminOrganizationService = newAdminWsClient(orchestrator).organizations(); | |||
adminOrganizationService.search(SearchWsRequest.builder().setOrganizations(organizationKeys).build()).getOrganizationsList() | |||
.forEach(organization -> adminOrganizationService.delete(organization.getKey())); | |||
public static void deleteOrganizations(Orchestrator orchestrator) { | |||
OrganizationService service = newAdminWsClient(orchestrator).organizations(); | |||
service.search(SearchWsRequest.builder().build()).getOrganizationsList() | |||
.stream() | |||
.filter(o -> !o.getGuarded()) | |||
.forEach(organization -> service.delete(organization.getKey())); | |||
} | |||
public static class ComponentNavigation { |
@@ -75,8 +75,8 @@ public class OrganizationDao implements Dao { | |||
return getMapper(dbSession).selectByPermission(userId, permission); | |||
} | |||
public List<OrganizationDto> selectWithoutQualityProfile(DbSession dbSession, String profileLanguage, String profileName) { | |||
return getMapper(dbSession).selectWithoutQualityProfile(profileLanguage, profileName); | |||
public List<String> selectAllUuids(DbSession dbSession) { | |||
return getMapper(dbSession).selectAllUuids(); | |||
} | |||
/** |
@@ -42,8 +42,7 @@ public interface OrganizationMapper { | |||
List<OrganizationDto> selectByPermission(@Param("userId") Integer userId, @Param("permission") String permission); | |||
List<OrganizationDto> selectWithoutQualityProfile(@Param("profileLanguage") String profileLanguage, | |||
@Param("profileName") String profileName); | |||
List<String> selectAllUuids(); | |||
DefaultTemplates selectDefaultTemplatesByUuid(@Param("uuid") String uuid); | |||
@@ -19,19 +19,18 @@ | |||
*/ | |||
package org.sonar.db.qualityprofile; | |||
import com.google.common.base.Optional; | |||
import com.google.common.base.Preconditions; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Map; | |||
import javax.annotation.CheckForNull; | |||
import java.util.Optional; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.db.Dao; | |||
import org.sonar.db.DatabaseUtils; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.KeyLongValue; | |||
import org.sonar.db.RowNotFoundException; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import static org.sonar.db.DatabaseUtils.executeLargeInputs; | |||
@@ -40,26 +39,16 @@ public class ActiveRuleDao implements Dao { | |||
private static final String QUALITY_PROFILE_IS_NOT_PERSISTED = "Quality profile is not persisted (missing id)"; | |||
private static final String RULE_IS_NOT_PERSISTED = "Rule is not persisted"; | |||
private static final String RULE_PARAM_IS_NOT_PERSISTED = "Rule param is not persisted"; | |||
private static final String ACTIVE_RULE_KEY_CANNOT_BE_NULL = "ActiveRuleKey cannot be null"; | |||
private static final String ACTIVE_RULE_IS_NOT_PERSISTED = "ActiveRule is not persisted"; | |||
private static final String ACTIVE_RULE_IS_ALREADY_PERSISTED = "ActiveRule is already persisted"; | |||
private static final String ACTIVE_RULE_PARAM_IS_NOT_PERSISTED = "ActiveRuleParam is not persisted"; | |||
private static final String ACTIVE_RULE_PARAM_IS_ALREADY_PERSISTED = "ActiveRuleParam is already persisted"; | |||
private static final String PARAMETER_NAME_CANNOT_BE_NULL = "ParameterName cannot be null"; | |||
public Optional<ActiveRuleDto> selectByKey(DbSession session, ActiveRuleKey key) { | |||
return Optional.fromNullable(mapper(session).selectByKey(key.qProfile(), key.ruleKey().repository(), key.ruleKey().rule())); | |||
public Optional<ActiveRuleDto> selectByKey(DbSession dbSession, ActiveRuleKey key) { | |||
return Optional.ofNullable(mapper(dbSession).selectByKey(key.getRuleProfileUuid(), key.getRuleKey().repository(), key.getRuleKey().rule())); | |||
} | |||
public ActiveRuleDto selectOrFailByKey(DbSession session, ActiveRuleKey key) { | |||
Optional<ActiveRuleDto> activeRule = selectByKey(session, key); | |||
if (activeRule.isPresent()) { | |||
return activeRule.get(); | |||
} | |||
throw new RowNotFoundException(String.format("Active rule with key '%s' does not exist", key)); | |||
} | |||
public List<ActiveRuleDto> selectByRuleId(DbSession dbSession, OrganizationDto organization, int ruleId) { | |||
public List<OrgActiveRuleDto> selectByRuleId(DbSession dbSession, OrganizationDto organization, int ruleId) { | |||
return mapper(dbSession).selectByRuleId(organization.getUuid(), ruleId); | |||
} | |||
@@ -67,49 +56,54 @@ public class ActiveRuleDao implements Dao { | |||
return mapper(dbSession).selectByRuleIdOfAllOrganizations(ruleId); | |||
} | |||
public List<ActiveRuleDto> selectByRuleIds(DbSession dbSession, String organizationUuid, List<Integer> ids) { | |||
return executeLargeInputs(ids, chunk -> mapper(dbSession).selectByRuleIds(organizationUuid, chunk)); | |||
public List<OrgActiveRuleDto> selectByRuleIds(DbSession dbSession, OrganizationDto organization, List<Integer> ids) { | |||
return executeLargeInputs(ids, chunk -> mapper(dbSession).selectByRuleIds(organization.getUuid(), chunk)); | |||
} | |||
/** | |||
* Active rule on removed rule are NOT returned | |||
*/ | |||
public List<ActiveRuleDto> selectByProfileKey(DbSession session, String profileKey) { | |||
return mapper(session).selectByProfileKey(profileKey); | |||
public List<OrgActiveRuleDto> selectByProfileUuid(DbSession dbSession, String uuid) { | |||
return mapper(dbSession).selectByProfileUuid(uuid); | |||
} | |||
public List<OrgActiveRuleDto> selectByProfile(DbSession dbSession, QProfileDto profile) { | |||
return selectByProfileUuid(dbSession, profile.getKee()); | |||
} | |||
public ActiveRuleDto insert(DbSession session, ActiveRuleDto item) { | |||
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); | |||
Preconditions.checkArgument(item.getId() == null, ACTIVE_RULE_IS_ALREADY_PERSISTED); | |||
mapper(session).insert(item); | |||
mapper(dbSession).insert(item); | |||
return item; | |||
} | |||
public ActiveRuleDto update(DbSession session, ActiveRuleDto item) { | |||
public ActiveRuleDto update(DbSession dbSession, ActiveRuleDto item) { | |||
Preconditions.checkArgument(item.getProfileId() != null, QUALITY_PROFILE_IS_NOT_PERSISTED); | |||
Preconditions.checkArgument(item.getRuleId() != null, ActiveRuleDao.RULE_IS_NOT_PERSISTED); | |||
Preconditions.checkArgument(item.getId() != null, ACTIVE_RULE_IS_NOT_PERSISTED); | |||
mapper(session).update(item); | |||
mapper(dbSession).update(item); | |||
return item; | |||
} | |||
public void delete(DbSession session, ActiveRuleKey key) { | |||
Optional<ActiveRuleDto> activeRule = selectByKey(session, key); | |||
public Optional<ActiveRuleDto> delete(DbSession dbSession, ActiveRuleKey key) { | |||
Optional<ActiveRuleDto> activeRule = selectByKey(dbSession, key); | |||
if (activeRule.isPresent()) { | |||
mapper(session).deleteParameters(activeRule.get().getId()); | |||
mapper(session).delete(activeRule.get().getId()); | |||
mapper(dbSession).deleteParameters(activeRule.get().getId()); | |||
mapper(dbSession).delete(activeRule.get().getId()); | |||
} | |||
return activeRule; | |||
} | |||
public void deleteByProfileKeys(DbSession dbSession, Collection<String> profileKeys) { | |||
public void deleteByRuleProfileUuids(DbSession dbSession, Collection<String> rulesProfileUuids) { | |||
ActiveRuleMapper mapper = mapper(dbSession); | |||
DatabaseUtils.executeLargeUpdates(profileKeys, mapper::deleteByProfileKeys); | |||
DatabaseUtils.executeLargeUpdates(rulesProfileUuids, mapper::deleteByRuleProfileUuids); | |||
} | |||
public void deleteParametersByProfileKeys(DbSession dbSession, Collection<String> profileKeys) { | |||
public void deleteParametersByRuleProfileUuids(DbSession dbSession, Collection<String> rulesProfileUuids) { | |||
ActiveRuleMapper mapper = mapper(dbSession); | |||
DatabaseUtils.executeLargeUpdates(profileKeys, mapper::deleteParametersByProfileKeys); | |||
DatabaseUtils.executeLargeUpdates(rulesProfileUuids, mapper::deleteParametersByRuleProfileUuids); | |||
} | |||
/** | |||
@@ -123,68 +117,36 @@ public class ActiveRuleDao implements Dao { | |||
return executeLargeInputs(activeRuleIds, mapper(dbSession)::selectParamsByActiveRuleIds); | |||
} | |||
@CheckForNull | |||
public ActiveRuleParamDto selectParamByKeyAndName(ActiveRuleKey key, String name, DbSession session) { | |||
Preconditions.checkNotNull(key, ACTIVE_RULE_KEY_CANNOT_BE_NULL); | |||
Preconditions.checkNotNull(name, PARAMETER_NAME_CANNOT_BE_NULL); | |||
Optional<ActiveRuleDto> activeRule = selectByKey(session, key); | |||
if (activeRule.isPresent()) { | |||
return mapper(session).selectParamByActiveRuleAndKey(activeRule.get().getId(), name); | |||
} | |||
return null; | |||
} | |||
/** | |||
* @deprecated currently used only by tests | |||
*/ | |||
@Deprecated | |||
public List<ActiveRuleParamDto> selectAllParams(DbSession dbSession) { | |||
return mapper(dbSession).selectAllParams(); | |||
} | |||
public ActiveRuleParamDto insertParam(DbSession session, ActiveRuleDto activeRule, ActiveRuleParamDto activeRuleParam) { | |||
public ActiveRuleParamDto insertParam(DbSession dbSession, ActiveRuleDto activeRule, ActiveRuleParamDto activeRuleParam) { | |||
Preconditions.checkArgument(activeRule.getId() != null, ACTIVE_RULE_IS_NOT_PERSISTED); | |||
Preconditions.checkArgument(activeRuleParam.getId() == null, ACTIVE_RULE_PARAM_IS_ALREADY_PERSISTED); | |||
Preconditions.checkNotNull(activeRuleParam.getRulesParameterId(), RULE_PARAM_IS_NOT_PERSISTED); | |||
activeRuleParam.setActiveRuleId(activeRule.getId()); | |||
mapper(session).insertParameter(activeRuleParam); | |||
mapper(dbSession).insertParameter(activeRuleParam); | |||
return activeRuleParam; | |||
} | |||
public void updateParam(DbSession session, ActiveRuleDto activeRule, ActiveRuleParamDto activeRuleParam) { | |||
Preconditions.checkNotNull(activeRule.getId(), ACTIVE_RULE_IS_NOT_PERSISTED); | |||
public void updateParam(DbSession dbSession, ActiveRuleParamDto activeRuleParam) { | |||
Preconditions.checkNotNull(activeRuleParam.getId(), ACTIVE_RULE_PARAM_IS_NOT_PERSISTED); | |||
mapper(session).updateParameter(activeRuleParam); | |||
mapper(dbSession).updateParameter(activeRuleParam); | |||
} | |||
public void deleteParam(DbSession session, ActiveRuleDto activeRule, ActiveRuleParamDto activeRuleParam) { | |||
Preconditions.checkNotNull(activeRule.getId(), ACTIVE_RULE_IS_NOT_PERSISTED); | |||
public void deleteParam(DbSession dbSession, ActiveRuleParamDto activeRuleParam) { | |||
Preconditions.checkNotNull(activeRuleParam.getId(), ACTIVE_RULE_PARAM_IS_NOT_PERSISTED); | |||
deleteParamById(session, activeRuleParam.getId()); | |||
deleteParamById(dbSession, activeRuleParam.getId()); | |||
} | |||
public void deleteParamById(DbSession session, int id) { | |||
mapper(session).deleteParameter(id); | |||
} | |||
public void deleteParamByKeyAndName(DbSession session, ActiveRuleKey key, String param) { | |||
// TODO SQL rewrite to delete by key | |||
Optional<ActiveRuleDto> activeRule = selectByKey(session, key); | |||
if (activeRule.isPresent()) { | |||
ActiveRuleParamDto activeRuleParam = mapper(session).selectParamByActiveRuleAndKey(activeRule.get().getId(), param); | |||
if (activeRuleParam != null) { | |||
mapper(session).deleteParameter(activeRuleParam.getId()); | |||
} | |||
} | |||
public void deleteParamById(DbSession dbSession, int id) { | |||
mapper(dbSession).deleteParameter(id); | |||
} | |||
public void deleteParamsByRuleParamOfAllOrganizations(DbSession dbSession, int ruleId, String paramKey) { | |||
List<ActiveRuleDto> activeRules = selectByRuleIdOfAllOrganizations(dbSession, ruleId); | |||
public void deleteParamsByRuleParamOfAllOrganizations(DbSession dbSession, RuleParamDto param) { | |||
List<ActiveRuleDto> activeRules = selectByRuleIdOfAllOrganizations(dbSession, param.getRuleId()); | |||
for (ActiveRuleDto activeRule : activeRules) { | |||
for (ActiveRuleParamDto activeParam : selectParamsByActiveRuleId(dbSession, activeRule.getId())) { | |||
if (activeParam.getKey().equals(paramKey)) { | |||
deleteParam(dbSession, activeRule, activeParam); | |||
if (activeParam.getKey().equals(param.getName())) { | |||
deleteParam(dbSession, activeParam); | |||
} | |||
} | |||
} | |||
@@ -193,26 +155,26 @@ public class ActiveRuleDao implements Dao { | |||
/** | |||
* Active rule on removed rule are NOT taken into account | |||
*/ | |||
public Map<String, Long> countActiveRulesByProfileKey(DbSession dbSession, OrganizationDto organization) { | |||
public Map<String, Long> countActiveRulesByProfileUuid(DbSession dbSession, OrganizationDto organization) { | |||
return KeyLongValue.toMap( | |||
mapper(dbSession).countActiveRulesByProfileKey(organization.getUuid())); | |||
mapper(dbSession).countActiveRulesByProfileUuid(organization.getUuid())); | |||
} | |||
public Map<String, Long> countActiveRulesForRuleStatusByProfileKey(DbSession dbSession, OrganizationDto organization, RuleStatus ruleStatus) { | |||
public Map<String, Long> countActiveRulesForRuleStatusByProfileUuid(DbSession dbSession, OrganizationDto organization, RuleStatus ruleStatus) { | |||
return KeyLongValue.toMap( | |||
mapper(dbSession).countActiveRulesForRuleStatusByProfileKey(organization.getUuid(), ruleStatus)); | |||
mapper(dbSession).countActiveRulesForRuleStatusByProfileUuid(organization.getUuid(), ruleStatus)); | |||
} | |||
/** | |||
* Active rule on removed rule are NOT taken into account | |||
*/ | |||
public Map<String, Long> countActiveRulesForInheritanceByProfileKey(DbSession dbSession, OrganizationDto organization, String inheritance) { | |||
public Map<String, Long> countActiveRulesForInheritanceByProfileUuid(DbSession dbSession, OrganizationDto organization, String inheritance) { | |||
return KeyLongValue.toMap( | |||
mapper(dbSession).countActiveRulesForInheritanceByProfileKey(organization.getUuid(), inheritance)); | |||
mapper(dbSession).countActiveRulesForInheritanceByProfileUuid(organization.getUuid(), inheritance)); | |||
} | |||
private static ActiveRuleMapper mapper(DbSession session) { | |||
return session.getMapper(ActiveRuleMapper.class); | |||
private static ActiveRuleMapper mapper(DbSession dbSession) { | |||
return dbSession.getMapper(ActiveRuleMapper.class); | |||
} | |||
} |
@@ -48,17 +48,21 @@ public class ActiveRuleDto { | |||
// These fields do not exists in db, it's only retrieve by joins | |||
private String repository; | |||
private String ruleField; | |||
private String profileKey; | |||
private String ruleProfileUuid; | |||
public ActiveRuleDto setKey(ActiveRuleKey key) { | |||
this.repository = key.ruleKey().repository(); | |||
this.ruleField = key.ruleKey().rule(); | |||
this.profileKey = key.qProfile(); | |||
this.repository = key.getRuleKey().repository(); | |||
this.ruleField = key.getRuleKey().rule(); | |||
this.ruleProfileUuid = key.getRuleProfileUuid(); | |||
return this; | |||
} | |||
public ActiveRuleKey getKey() { | |||
return ActiveRuleKey.of(profileKey, RuleKey.of(repository, ruleField)); | |||
return new ActiveRuleKey(ruleProfileUuid, RuleKey.of(repository, ruleField)); | |||
} | |||
public RuleKey getRuleKey() { | |||
return RuleKey.of(repository, ruleField); | |||
} | |||
public Integer getId() { | |||
@@ -142,13 +146,13 @@ public class ActiveRuleDto { | |||
return this; | |||
} | |||
public static ActiveRuleDto createFor(QProfileDto profileDto, RuleDefinitionDto ruleDto) { | |||
requireNonNull(profileDto.getId(), "Profile is not persisted"); | |||
public static ActiveRuleDto createFor(QProfileDto profile, RuleDefinitionDto ruleDto) { | |||
requireNonNull(profile.getId(), "Profile is not persisted"); | |||
requireNonNull(ruleDto.getId(), "Rule is not persisted"); | |||
ActiveRuleDto dto = new ActiveRuleDto(); | |||
dto.setProfileId(profileDto.getId()); | |||
dto.setProfileId(profile.getId()); | |||
dto.setRuleId(ruleDto.getId()); | |||
dto.setKey(ActiveRuleKey.of(profileDto.getKee(), ruleDto.getKey())); | |||
dto.setKey(ActiveRuleKey.of(profile, ruleDto.getKey())); | |||
return dto; | |||
} | |||
@@ -29,21 +29,23 @@ import org.sonar.api.rule.RuleKey; | |||
*/ | |||
public class ActiveRuleKey implements Serializable, Comparable<ActiveRuleKey> { | |||
private final String qualityProfileKey; | |||
private final String ruleProfileUuid; | |||
private final RuleKey ruleKey; | |||
protected ActiveRuleKey(String qualityProfileKey, RuleKey ruleKey) { | |||
this.qualityProfileKey = qualityProfileKey; | |||
protected ActiveRuleKey(String ruleProfileUuid, RuleKey ruleKey) { | |||
this.ruleProfileUuid = ruleProfileUuid; | |||
this.ruleKey = ruleKey; | |||
} | |||
/** | |||
* Create a key. Parameters are NOT null. | |||
*/ | |||
public static ActiveRuleKey of(String qualityProfileKey, RuleKey ruleKey) { | |||
Preconditions.checkNotNull(qualityProfileKey, "QProfile is missing"); | |||
Preconditions.checkNotNull(ruleKey, "RuleKey is missing"); | |||
return new ActiveRuleKey(qualityProfileKey, ruleKey); | |||
public static ActiveRuleKey of(QProfileDto profile, RuleKey ruleKey) { | |||
return new ActiveRuleKey(profile.getRulesProfileUuid(), ruleKey); | |||
} | |||
public static ActiveRuleKey of(RulesProfileDto rulesProfile, RuleKey ruleKey) { | |||
return new ActiveRuleKey(rulesProfile.getKee(), ruleKey); | |||
} | |||
/** | |||
@@ -53,23 +55,23 @@ public class ActiveRuleKey implements Serializable, Comparable<ActiveRuleKey> { | |||
public static ActiveRuleKey parse(String s) { | |||
Preconditions.checkArgument(s.split(":").length >= 3, "Bad format of activeRule key: " + s); | |||
int semiColonPos = s.indexOf(':'); | |||
String key = s.substring(0, semiColonPos); | |||
String ruleProfileUuid = s.substring(0, semiColonPos); | |||
String ruleKey = s.substring(semiColonPos + 1); | |||
return ActiveRuleKey.of(key, RuleKey.parse(ruleKey)); | |||
return new ActiveRuleKey(ruleProfileUuid, RuleKey.parse(ruleKey)); | |||
} | |||
/** | |||
* Never null | |||
*/ | |||
public RuleKey ruleKey() { | |||
public RuleKey getRuleKey() { | |||
return ruleKey; | |||
} | |||
/** | |||
* Never null | |||
*/ | |||
public String qProfile() { | |||
return qualityProfileKey; | |||
public String getRuleProfileUuid() { | |||
return ruleProfileUuid; | |||
} | |||
@Override | |||
@@ -81,7 +83,7 @@ public class ActiveRuleKey implements Serializable, Comparable<ActiveRuleKey> { | |||
return false; | |||
} | |||
ActiveRuleKey activeRuleKey = (ActiveRuleKey) o; | |||
if (!qualityProfileKey.equals(activeRuleKey.qualityProfileKey)) { | |||
if (!ruleProfileUuid.equals(activeRuleKey.ruleProfileUuid)) { | |||
return false; | |||
} | |||
return ruleKey.equals(activeRuleKey.ruleKey); | |||
@@ -89,7 +91,7 @@ public class ActiveRuleKey implements Serializable, Comparable<ActiveRuleKey> { | |||
@Override | |||
public int hashCode() { | |||
int result = qualityProfileKey.hashCode(); | |||
int result = ruleProfileUuid.hashCode(); | |||
result = 31 * result + ruleKey.hashCode(); | |||
return result; | |||
} | |||
@@ -99,12 +101,12 @@ public class ActiveRuleKey implements Serializable, Comparable<ActiveRuleKey> { | |||
*/ | |||
@Override | |||
public String toString() { | |||
return String.format("%s:%s", qualityProfileKey, ruleKey.toString()); | |||
return String.format("%s:%s", ruleProfileUuid, ruleKey.toString()); | |||
} | |||
@Override | |||
public int compareTo(ActiveRuleKey o) { | |||
int compareQualityProfileKey = this.qualityProfileKey.compareTo(o.qualityProfileKey); | |||
int compareQualityProfileKey = this.ruleProfileUuid.compareTo(o.ruleProfileUuid); | |||
if (compareQualityProfileKey == 0) { | |||
return this.ruleKey.compareTo(o.ruleKey); | |||
} |
@@ -34,19 +34,20 @@ public interface ActiveRuleMapper { | |||
void delete(int activeRuleId); | |||
void deleteByProfileKeys(@Param("profileKeys") Collection<String> profileKeys); | |||
void deleteByRuleProfileUuids(@Param("rulesProfileUuids") Collection<String> rulesProfileUuids); | |||
ActiveRuleDto selectByKey(@Param("profileKey") String profileKey, @Param("repository") String repository, @Param("rule") String rule); | |||
@CheckForNull | |||
ActiveRuleDto selectByKey(@Param("ruleProfileUuid") String ruleProfileUuid, @Param("repository") String repository, @Param("rule") String rule); | |||
List<ActiveRuleDto> selectByKeys(@Param("keys") List<ActiveRuleKey> keys); | |||
List<ActiveRuleDto> selectByRuleId(@Param("organizationUuid") String organizationUuid, @Param("ruleId") int ruleId); | |||
List<OrgActiveRuleDto> selectByRuleId(@Param("organizationUuid") String organizationUuid, @Param("ruleId") int ruleId); | |||
List<ActiveRuleDto> selectByRuleIdOfAllOrganizations(int ruleId); | |||
List<ActiveRuleDto> selectByRuleIds(@Param("organizationUuid") String organizationUuid, @Param("ruleIds") List<Integer> partitionOfRuleIds); | |||
List<OrgActiveRuleDto> selectByRuleIds(@Param("organizationUuid") String organizationUuid, @Param("ruleIds") List<Integer> partitionOfRuleIds); | |||
List<ActiveRuleDto> selectByProfileKey(String key); | |||
List<OrgActiveRuleDto> selectByProfileUuid(String uuid); | |||
void insertParameter(ActiveRuleParamDto dto); | |||
@@ -54,22 +55,17 @@ public interface ActiveRuleMapper { | |||
void deleteParameters(int activeRuleId); | |||
void deleteParametersByProfileKeys(@Param("profileKeys") Collection<String> profileKeys); | |||
void deleteParametersByRuleProfileUuids(@Param("rulesProfileUuids") Collection<String> rulesProfileUuids); | |||
void deleteParameter(int activeRuleParamId); | |||
@CheckForNull | |||
ActiveRuleParamDto selectParamByActiveRuleAndKey(@Param("activeRuleId") int activeRuleId, @Param("key") String key); | |||
List<ActiveRuleParamDto> selectParamsByActiveRuleId(int activeRuleId); | |||
List<ActiveRuleParamDto> selectParamsByActiveRuleIds(@Param("ids") List<Integer> ids); | |||
List<ActiveRuleParamDto> selectAllParams(); | |||
List<KeyLongValue> countActiveRulesByProfileKey(@Param("organizationUuid") String organizationUuid); | |||
List<KeyLongValue> countActiveRulesByProfileUuid(@Param("organizationUuid") String organizationUuid); | |||
List<KeyLongValue> countActiveRulesForRuleStatusByProfileKey(@Param("organizationUuid") String organizationUuid, @Param("ruleStatus") RuleStatus ruleStatus); | |||
List<KeyLongValue> countActiveRulesForRuleStatusByProfileUuid(@Param("organizationUuid") String organizationUuid, @Param("ruleStatus") RuleStatus ruleStatus); | |||
List<KeyLongValue> countActiveRulesForInheritanceByProfileKey(@Param("organizationUuid") String organizationUuid, @Param("inheritance") String inheritance); | |||
List<KeyLongValue> countActiveRulesForInheritanceByProfileUuid(@Param("organizationUuid") String organizationUuid, @Param("inheritance") String inheritance); | |||
} |
@@ -0,0 +1,44 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.db.qualityprofile; | |||
public class OrgActiveRuleDto extends ActiveRuleDto { | |||
private String organizationUuid; | |||
private String profileUuid; | |||
public String getOrganizationUuid() { | |||
return organizationUuid; | |||
} | |||
public OrgActiveRuleDto setOrganizationUuid(String s) { | |||
this.organizationUuid = s; | |||
return this; | |||
} | |||
public String getProfileUuid() { | |||
return profileUuid; | |||
} | |||
public OrgActiveRuleDto setProfileUuid(String s) { | |||
this.profileUuid = s; | |||
return this; | |||
} | |||
} |
@@ -0,0 +1,79 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.db.qualityprofile; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
/** | |||
* Represents the table "org_qprofiles" | |||
*/ | |||
public class OrgQProfileDto { | |||
private String uuid; | |||
private String organizationUuid; | |||
private String rulesProfileUuid; | |||
private String parentUuid; | |||
public String getOrganizationUuid() { | |||
return organizationUuid; | |||
} | |||
public OrgQProfileDto setOrganizationUuid(String organizationUuid) { | |||
this.organizationUuid = organizationUuid; | |||
return this; | |||
} | |||
public String getUuid() { | |||
return uuid; | |||
} | |||
public OrgQProfileDto setUuid(String s) { | |||
this.uuid = s; | |||
return this; | |||
} | |||
public String getRulesProfileUuid() { | |||
return rulesProfileUuid; | |||
} | |||
public OrgQProfileDto setRulesProfileUuid(String s) { | |||
this.rulesProfileUuid = s; | |||
return this; | |||
} | |||
@CheckForNull | |||
public String getParentUuid() { | |||
return parentUuid; | |||
} | |||
public OrgQProfileDto setParentUuid(@Nullable String s) { | |||
this.parentUuid = s; | |||
return this; | |||
} | |||
public static OrgQProfileDto from(QProfileDto qProfileDto) { | |||
return new OrgQProfileDto() | |||
.setUuid(qProfileDto.getKee()) | |||
.setOrganizationUuid(qProfileDto.getOrganizationUuid()) | |||
.setRulesProfileUuid(qProfileDto.getRulesProfileUuid()) | |||
.setParentUuid(qProfileDto.getParentKee()); | |||
} | |||
} |
@@ -41,7 +41,7 @@ public class QProfileChangeDao implements Dao { | |||
public void insert(DbSession dbSession, QProfileChangeDto dto) { | |||
checkState(dto.getCreatedAt() == 0L, "Date of QProfileChangeDto must be set by DAO only. Got %s.", dto.getCreatedAt()); | |||
dto.setKey(uuidFactory.create()); | |||
dto.setUuid(uuidFactory.create()); | |||
dto.setCreatedAt(system2.now()); | |||
mapper(dbSession).insert(dto); | |||
} | |||
@@ -50,13 +50,13 @@ public class QProfileChangeDao implements Dao { | |||
return mapper(dbSession).selectByQuery(query); | |||
} | |||
public int countForProfileUuid(DbSession dbSession, String profileUuid) { | |||
return mapper(dbSession).countForProfileUuid(profileUuid); | |||
public int countForQProfileUuid(DbSession dbSession, String profileUuid) { | |||
return mapper(dbSession).countForQProfileUuid(profileUuid); | |||
} | |||
public void deleteByProfileKeys(DbSession dbSession, Collection<String> profileUuids) { | |||
public void deleteByRulesProfileUuids(DbSession dbSession, Collection<String> ruleProfileUuids) { | |||
QProfileChangeMapper mapper = mapper(dbSession); | |||
DatabaseUtils.executeLargeUpdates(profileUuids, mapper::deleteByProfileUuids); | |||
DatabaseUtils.executeLargeUpdates(ruleProfileUuids, mapper::deleteByRuleProfileUuids); | |||
} | |||
private static QProfileChangeMapper mapper(DbSession dbSession) { |
@@ -29,30 +29,28 @@ import org.sonar.api.utils.KeyValueFormat; | |||
public class QProfileChangeDto { | |||
private String key; | |||
private String profileKey; | |||
// can't be named "type" because it's a reserved word in Oracle | |||
// (used by Mybatis to map DB column with DTO field) | |||
private String uuid; | |||
private String rulesProfileUuid; | |||
private String changeType; | |||
private String login; | |||
private String data; | |||
private long createdAt; | |||
public String getKey() { | |||
return key; | |||
public String getUuid() { | |||
return uuid; | |||
} | |||
public QProfileChangeDto setKey(String s) { | |||
this.key = s; | |||
public QProfileChangeDto setUuid(String s) { | |||
this.uuid = s; | |||
return this; | |||
} | |||
public String getProfileKey() { | |||
return profileKey; | |||
public String getRulesProfileUuid() { | |||
return rulesProfileUuid; | |||
} | |||
public QProfileChangeDto setProfileKey(String s) { | |||
this.profileKey = s; | |||
public QProfileChangeDto setRulesProfileUuid(String s) { | |||
this.rulesProfileUuid = s; | |||
return this; | |||
} | |||
@@ -29,7 +29,7 @@ public interface QProfileChangeMapper { | |||
List<QProfileChangeDto> selectByQuery(@Param("query") QProfileChangeQuery query); | |||
int countForProfileUuid(@Param("profileUuid") String profileUuid); | |||
int countForQProfileUuid(@Param("qProfileUuid") String qProfileUuid); | |||
void deleteByProfileUuids(@Param("profileUuids") Collection<String> profileUuids); | |||
void deleteByRuleProfileUuids(@Param("ruleProfileUuids") Collection<String> uuids); | |||
} |
@@ -26,7 +26,7 @@ import org.apache.commons.lang.builder.ToStringStyle; | |||
import static java.util.Objects.requireNonNull; | |||
public class QProfileChangeQuery { | |||
public final class QProfileChangeQuery { | |||
private final String profileUuid; | |||
private Long fromIncluded; |
@@ -45,20 +45,17 @@ public class QProfileDto { | |||
private Long lastUsed; | |||
private Long userUpdatedAt; | |||
private boolean isBuiltIn; | |||
private String rulesProfileUuid; | |||
public String getOrganizationUuid() { | |||
return organizationUuid; | |||
} | |||
public QProfileDto setOrganizationUuid(String organizationUuid) { | |||
this.organizationUuid = organizationUuid; | |||
public QProfileDto setOrganizationUuid(String s) { | |||
this.organizationUuid = s; | |||
return this; | |||
} | |||
public QProfileDto setKey(String s) { | |||
return setKee(s); | |||
} | |||
public String getKee() { | |||
return kee; | |||
} | |||
@@ -68,6 +65,15 @@ public class QProfileDto { | |||
return this; | |||
} | |||
public String getRulesProfileUuid() { | |||
return rulesProfileUuid; | |||
} | |||
public QProfileDto setRulesProfileUuid(String s) { | |||
this.rulesProfileUuid = s; | |||
return this; | |||
} | |||
public Integer getId() { | |||
return id; | |||
} | |||
@@ -148,7 +154,18 @@ public class QProfileDto { | |||
return this; | |||
} | |||
public static QProfileDto createFor(String key) { | |||
return new QProfileDto().setKee(key); | |||
public static QProfileDto from(OrgQProfileDto org, RulesProfileDto rules) { | |||
return new QProfileDto() | |||
.setIsBuiltIn(rules.isBuiltIn()) | |||
.setKee(org.getUuid()) | |||
.setParentKee(org.getParentUuid()) | |||
.setOrganizationUuid(org.getOrganizationUuid()) | |||
.setId(rules.getId()) | |||
.setRulesProfileUuid(rules.getKee()) | |||
.setLanguage(rules.getLanguage()) | |||
.setName(rules.getName()) | |||
.setRulesUpdatedAt(rules.getRulesUpdatedAt()) | |||
.setLastUsed(rules.getLastUsed()) | |||
.setUserUpdatedAt(rules.getUserUpdatedAt()); | |||
} | |||
} |
@@ -19,7 +19,6 @@ | |||
*/ | |||
package org.sonar.db.qualityprofile; | |||
import com.google.common.base.Preconditions; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Date; | |||
@@ -37,6 +36,7 @@ import org.sonar.db.RowNotFoundException; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static org.sonar.db.DatabaseUtils.executeLargeInputs; | |||
import static org.sonar.db.DatabaseUtils.executeLargeUpdates; | |||
@@ -49,28 +49,42 @@ public class QualityProfileDao implements Dao { | |||
} | |||
@CheckForNull | |||
public QProfileDto selectByUuid(DbSession session, String uuid) { | |||
return mapper(session).selectByUuid(uuid); | |||
public QProfileDto selectByUuid(DbSession dbSession, String uuid) { | |||
return mapper(dbSession).selectByUuid(uuid); | |||
} | |||
public QProfileDto selectOrFailByUuid(DbSession session, String uuid) { | |||
QProfileDto dto = selectByUuid(session, uuid); | |||
public QProfileDto selectOrFailByUuid(DbSession dbSession, String uuid) { | |||
QProfileDto dto = selectByUuid(dbSession, uuid); | |||
if (dto == null) { | |||
throw new RowNotFoundException("Quality profile not found: " + uuid); | |||
} | |||
return dto; | |||
} | |||
public List<QProfileDto> selectByUuids(DbSession session, List<String> uuids) { | |||
return executeLargeInputs(uuids, mapper(session)::selectByUuids); | |||
public List<QProfileDto> selectByUuids(DbSession dbSession, List<String> uuids) { | |||
return executeLargeInputs(uuids, mapper(dbSession)::selectByUuids); | |||
} | |||
public List<QProfileDto> selectAll(DbSession session, OrganizationDto organization) { | |||
return mapper(session).selectAll(organization.getUuid()); | |||
public List<QProfileDto> selectOrderedByOrganizationUuid(DbSession dbSession, OrganizationDto organization) { | |||
return mapper(dbSession).selectOrderedByOrganizationUuid(organization.getUuid()); | |||
} | |||
public void insert(DbSession session, QProfileDto profile, QProfileDto... otherProfiles) { | |||
QualityProfileMapper mapper = mapper(session); | |||
public List<RulesProfileDto> selectBuiltInRulesProfiles(DbSession dbSession) { | |||
return mapper(dbSession).selectBuiltInRuleProfiles(); | |||
} | |||
public void insert(DbSession dbSession, RulesProfileDto dto) { | |||
QualityProfileMapper mapper = mapper(dbSession); | |||
mapper.insertRuleProfile(dto, new Date(system.now())); | |||
} | |||
public void insert(DbSession dbSession, OrgQProfileDto dto) { | |||
QualityProfileMapper mapper = mapper(dbSession); | |||
mapper.insertOrgQProfile(dto, system.now()); | |||
} | |||
public void insert(DbSession dbSession, QProfileDto profile, QProfileDto... otherProfiles) { | |||
QualityProfileMapper mapper = mapper(dbSession); | |||
doInsert(mapper, profile); | |||
for (QProfileDto other : otherProfiles) { | |||
doInsert(mapper, other); | |||
@@ -78,14 +92,16 @@ public class QualityProfileDao implements Dao { | |||
} | |||
private void doInsert(QualityProfileMapper mapper, QProfileDto profile) { | |||
Preconditions.checkArgument(profile.getId() == null, "Quality profile is already persisted (got id %d)", profile.getId()); | |||
checkArgument(profile.getId() == null, "Quality profile is already persisted (got id %d)", profile.getId()); | |||
long now = system.now(); | |||
mapper.insertRulesProfile(profile, new Date(now)); | |||
mapper.insertOrgQProfile(profile, now); | |||
RulesProfileDto rulesProfile = RulesProfileDto.from(profile); | |||
mapper.insertRuleProfile(rulesProfile, new Date(now)); | |||
mapper.insertOrgQProfile(OrgQProfileDto.from(profile), now); | |||
profile.setId(rulesProfile.getId()); | |||
} | |||
public void update(DbSession session, QProfileDto profile, QProfileDto... otherProfiles) { | |||
QualityProfileMapper mapper = mapper(session); | |||
public void update(DbSession dbSession, QProfileDto profile, QProfileDto... otherProfiles) { | |||
QualityProfileMapper mapper = mapper(dbSession); | |||
long now = system.now(); | |||
doUpdate(mapper, profile, now); | |||
for (QProfileDto otherProfile : otherProfiles) { | |||
@@ -94,55 +110,55 @@ public class QualityProfileDao implements Dao { | |||
} | |||
private void doUpdate(QualityProfileMapper mapper, QProfileDto profile, long now) { | |||
mapper.updateRulesProfile(profile, new Date(now)); | |||
mapper.updateRuleProfile(profile, new Date(now)); | |||
mapper.updateOrgQProfile(profile, now); | |||
} | |||
public List<QProfileDto> selectDefaultProfiles(DbSession session, OrganizationDto organization, Collection<String> languages) { | |||
return mapper(session).selectDefaultProfiles(organization.getUuid(), languages); | |||
public List<QProfileDto> selectDefaultProfiles(DbSession dbSession, OrganizationDto organization, Collection<String> languages) { | |||
return mapper(dbSession).selectDefaultProfiles(organization.getUuid(), languages); | |||
} | |||
@CheckForNull | |||
public QProfileDto selectDefaultProfile(DbSession session, OrganizationDto organization, String language) { | |||
return mapper(session).selectDefaultProfile(organization.getUuid(), language); | |||
public QProfileDto selectDefaultProfile(DbSession dbSession, OrganizationDto organization, String language) { | |||
return mapper(dbSession).selectDefaultProfile(organization.getUuid(), language); | |||
} | |||
@CheckForNull | |||
public QProfileDto selectAssociatedToProjectAndLanguage(DbSession session, ComponentDto project, String language) { | |||
return mapper(session).selectAssociatedToProjectUuidAndLanguage(project.getOrganizationUuid(), project.projectUuid(), language); | |||
public QProfileDto selectAssociatedToProjectAndLanguage(DbSession dbSession, ComponentDto project, String language) { | |||
return mapper(dbSession).selectAssociatedToProjectUuidAndLanguage(project.getOrganizationUuid(), project.projectUuid(), language); | |||
} | |||
public List<QProfileDto> selectAssociatedToProjectUuidAndLanguages(DbSession session, ComponentDto project, Collection<String> languages) { | |||
return mapper(session).selectAssociatedToProjectUuidAndLanguages(project.getOrganizationUuid(), project.uuid(), languages); | |||
public List<QProfileDto> selectAssociatedToProjectUuidAndLanguages(DbSession dbSession, ComponentDto project, Collection<String> languages) { | |||
return mapper(dbSession).selectAssociatedToProjectUuidAndLanguages(project.getOrganizationUuid(), project.uuid(), languages); | |||
} | |||
public List<QProfileDto> selectByLanguage(DbSession dbSession, OrganizationDto organization, String language) { | |||
return mapper(dbSession).selectByLanguage(organization.getUuid(), language); | |||
} | |||
public List<QProfileDto> selectChildren(DbSession session, String uuid) { | |||
return mapper(session).selectChildren(uuid); | |||
public List<QProfileDto> selectChildren(DbSession dbSession, QProfileDto profile) { | |||
return mapper(dbSession).selectChildren(profile.getKee()); | |||
} | |||
/** | |||
* All descendants, in the top-down order. | |||
*/ | |||
public List<QProfileDto> selectDescendants(DbSession session, String uuid) { | |||
public List<QProfileDto> selectDescendants(DbSession dbSession, QProfileDto profile) { | |||
List<QProfileDto> descendants = new ArrayList<>(); | |||
for (QProfileDto child : selectChildren(session, uuid)) { | |||
for (QProfileDto child : selectChildren(dbSession, profile)) { | |||
descendants.add(child); | |||
descendants.addAll(selectDescendants(session, child.getKee())); | |||
descendants.addAll(selectDescendants(dbSession, child)); | |||
} | |||
return descendants; | |||
} | |||
@CheckForNull | |||
public QProfileDto selectByNameAndLanguage(DbSession session, OrganizationDto organization, String name, String language) { | |||
return mapper(session).selectByNameAndLanguage(organization.getUuid(), name, language); | |||
public QProfileDto selectByNameAndLanguage(DbSession dbSession, OrganizationDto organization, String name, String language) { | |||
return mapper(dbSession).selectByNameAndLanguage(organization.getUuid(), name, language); | |||
} | |||
public List<QProfileDto> selectByNameAndLanguages(DbSession session, OrganizationDto organization, String name, Collection<String> languages) { | |||
return mapper(session).selectByNameAndLanguages(organization.getUuid(), name, languages); | |||
public List<QProfileDto> selectByNameAndLanguages(DbSession dbSession, OrganizationDto organization, String name, Collection<String> languages) { | |||
return mapper(dbSession).selectByNameAndLanguages(organization.getUuid(), name, languages); | |||
} | |||
public Map<String, Long> countProjectsByProfileUuid(DbSession dbSession, OrganizationDto organization) { | |||
@@ -166,38 +182,42 @@ public class QualityProfileDao implements Dao { | |||
DatabaseUtils.executeLargeUpdates(profileUuids, mapper::deleteProjectAssociationByProfileUuids); | |||
} | |||
public List<ProjectQprofileAssociationDto> selectSelectedProjects(DbSession session, OrganizationDto organization, QProfileDto profile, @Nullable String query) { | |||
public List<ProjectQprofileAssociationDto> selectSelectedProjects(DbSession dbSession, OrganizationDto organization, QProfileDto profile, @Nullable String query) { | |||
String nameQuery = sqlQueryString(query); | |||
return mapper(session).selectSelectedProjects(organization.getUuid(), profile.getKee(), nameQuery); | |||
return mapper(dbSession).selectSelectedProjects(organization.getUuid(), profile.getKee(), nameQuery); | |||
} | |||
public List<ProjectQprofileAssociationDto> selectDeselectedProjects(DbSession session, OrganizationDto organization, QProfileDto profile, @Nullable String query) { | |||
public List<ProjectQprofileAssociationDto> selectDeselectedProjects(DbSession dbSession, OrganizationDto organization, QProfileDto profile, @Nullable String query) { | |||
String nameQuery = sqlQueryString(query); | |||
return mapper(session).selectDeselectedProjects(organization.getUuid(), profile.getKee(), nameQuery); | |||
return mapper(dbSession).selectDeselectedProjects(organization.getUuid(), profile.getKee(), nameQuery); | |||
} | |||
public List<ProjectQprofileAssociationDto> selectProjectAssociations(DbSession session, OrganizationDto organization, QProfileDto profile, @Nullable String query) { | |||
public List<ProjectQprofileAssociationDto> selectProjectAssociations(DbSession dbSession, OrganizationDto organization, QProfileDto profile, @Nullable String query) { | |||
String nameQuery = sqlQueryString(query); | |||
return mapper(session).selectProjectAssociations(organization.getUuid(), profile.getKee(), nameQuery); | |||
return mapper(dbSession).selectProjectAssociations(organization.getUuid(), profile.getKee(), nameQuery); | |||
} | |||
public Collection<String> selectUuidsOfCustomRulesProfiles(DbSession dbSession, String language, String name) { | |||
return mapper(dbSession).selectUuidsOfCustomQProfiles(language, name); | |||
return mapper(dbSession).selectUuidsOfCustomRuleProfiles(language, name); | |||
} | |||
public void renameRulesProfilesAndCommit(DbSession dbSession, Collection<String> rulesProfileUuids, String newName) { | |||
QualityProfileMapper mapper = mapper(dbSession); | |||
Date now = new Date(system.now()); | |||
executeLargeUpdates(rulesProfileUuids, partition -> { | |||
mapper.renameRulesProfiles(newName, now, partition); | |||
mapper.renameRuleProfiles(newName, now, partition); | |||
dbSession.commit(); | |||
}); | |||
} | |||
public void deleteByUuids(DbSession dbSession, Collection<String> profileUuids) { | |||
public void deleteOrgQProfilesByUuids(DbSession dbSession, Collection<String> profileUuids) { | |||
QualityProfileMapper mapper = mapper(dbSession); | |||
DatabaseUtils.executeLargeUpdates(profileUuids, mapper::deleteOrgQProfilesByUuids); | |||
DatabaseUtils.executeLargeUpdates(profileUuids, mapper::deleteRulesProfilesByUuids); | |||
} | |||
public void deleteRulesProfilesByUuids(DbSession dbSession, Collection<String> rulesProfileUuids) { | |||
QualityProfileMapper mapper = mapper(dbSession); | |||
DatabaseUtils.executeLargeUpdates(rulesProfileUuids, mapper::deleteRuleProfilesByUuids); | |||
} | |||
private static String sqlQueryString(@Nullable String query) { | |||
@@ -207,7 +227,7 @@ public class QualityProfileDao implements Dao { | |||
return "%" + query.toUpperCase(Locale.ENGLISH) + "%"; | |||
} | |||
private static QualityProfileMapper mapper(DbSession session) { | |||
return session.getMapper(QualityProfileMapper.class); | |||
private static QualityProfileMapper mapper(DbSession dbSession) { | |||
return dbSession.getMapper(QualityProfileMapper.class); | |||
} | |||
} |
@@ -28,19 +28,21 @@ import org.sonar.db.KeyLongValue; | |||
public interface QualityProfileMapper { | |||
void insertOrgQProfile(@Param("dto") QProfileDto dto, @Param("now") long now); | |||
void insertOrgQProfile(@Param("dto") OrgQProfileDto dto, @Param("now") long now); | |||
void insertRulesProfile(@Param("dto") QProfileDto dto, @Param("now") Date now); | |||
void insertRuleProfile(@Param("dto") RulesProfileDto dto, @Param("now") Date now); | |||
void updateRulesProfile(@Param("dto") QProfileDto dto, @Param("now") Date now); | |||
void updateRuleProfile(@Param("dto") QProfileDto dto, @Param("now") Date now); | |||
void updateOrgQProfile(@Param("dto") QProfileDto dto, @Param("now") long now); | |||
void deleteRulesProfilesByUuids(@Param("uuids") Collection<String> uuids); | |||
void deleteRuleProfilesByUuids(@Param("uuids") Collection<String> uuids); | |||
void deleteOrgQProfilesByUuids(@Param("uuids") Collection<String> uuids); | |||
List<QProfileDto> selectAll(@Param("organizationUuid") String organizationUuid); | |||
List<RulesProfileDto> selectBuiltInRuleProfiles(); | |||
List<QProfileDto> selectOrderedByOrganizationUuid(@Param("organizationUuid") String organizationUuid); | |||
@CheckForNull | |||
QProfileDto selectDefaultProfile(@Param("organizationUuid") String organizationUuid, @Param("language") String language); | |||
@@ -116,7 +118,7 @@ public interface QualityProfileMapper { | |||
@Param("profileUuid") String profileUuid, | |||
@Param("nameQuery") String nameQuery); | |||
List<String> selectUuidsOfCustomQProfiles(@Param("language") String language, @Param("name") String name); | |||
List<String> selectUuidsOfCustomRuleProfiles(@Param("language") String language, @Param("name") String name); | |||
void renameRulesProfiles(@Param("newName") String newName, @Param("updatedAt") Date updatedAt, @Param("uuids") Collection<String> uuids); | |||
void renameRuleProfiles(@Param("newName") String newName, @Param("updatedAt") Date updatedAt, @Param("uuids") Collection<String> uuids); | |||
} |
@@ -0,0 +1,131 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.db.qualityprofile; | |||
import java.util.Date; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.sonar.core.util.UtcDateUtils; | |||
/** | |||
* Represents the table "rules_profiles" | |||
*/ | |||
public class RulesProfileDto { | |||
private Integer id; | |||
private String kee; | |||
private String name; | |||
private String language; | |||
private String rulesUpdatedAt; | |||
private Long lastUsed; | |||
private Long userUpdatedAt; | |||
private boolean isBuiltIn; | |||
public String getKee() { | |||
return kee; | |||
} | |||
public RulesProfileDto setKee(String s) { | |||
this.kee = s; | |||
return this; | |||
} | |||
public Integer getId() { | |||
return id; | |||
} | |||
public RulesProfileDto setId(Integer id) { | |||
this.id = id; | |||
return this; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public RulesProfileDto setName(String name) { | |||
this.name = name; | |||
return this; | |||
} | |||
public String getLanguage() { | |||
return language; | |||
} | |||
public RulesProfileDto setLanguage(String language) { | |||
this.language = language; | |||
return this; | |||
} | |||
public String getRulesUpdatedAt() { | |||
return rulesUpdatedAt; | |||
} | |||
public RulesProfileDto setRulesUpdatedAt(String s) { | |||
this.rulesUpdatedAt = s; | |||
return this; | |||
} | |||
public RulesProfileDto setRulesUpdatedAtAsDate(Date d) { | |||
this.rulesUpdatedAt = UtcDateUtils.formatDateTime(d); | |||
return this; | |||
} | |||
@CheckForNull | |||
public Long getLastUsed() { | |||
return lastUsed; | |||
} | |||
public RulesProfileDto setLastUsed(@Nullable Long lastUsed) { | |||
this.lastUsed = lastUsed; | |||
return this; | |||
} | |||
@CheckForNull | |||
public Long getUserUpdatedAt() { | |||
return userUpdatedAt; | |||
} | |||
public RulesProfileDto setUserUpdatedAt(@Nullable Long userUpdatedAt) { | |||
this.userUpdatedAt = userUpdatedAt; | |||
return this; | |||
} | |||
public boolean isBuiltIn() { | |||
return isBuiltIn; | |||
} | |||
public RulesProfileDto setIsBuiltIn(boolean b) { | |||
this.isBuiltIn = b; | |||
return this; | |||
} | |||
public static RulesProfileDto from(QProfileDto qProfileDto) { | |||
return new RulesProfileDto() | |||
.setKee(qProfileDto.getRulesProfileUuid()) | |||
.setLanguage(qProfileDto.getLanguage()) | |||
.setName(qProfileDto.getName()) | |||
.setIsBuiltIn(qProfileDto.isBuiltIn()) | |||
.setId(qProfileDto.getId()) | |||
.setLastUsed(qProfileDto.getLastUsed()) | |||
.setRulesUpdatedAt(qProfileDto.getRulesUpdatedAt()) | |||
.setUserUpdatedAt(qProfileDto.getUserUpdatedAt()); | |||
} | |||
} |
@@ -88,6 +88,11 @@ public class RuleDao implements Dao { | |||
return executeLargeInputs(ids, mapper(session)::selectDefinitionByIds); | |||
} | |||
public List<RuleDto> selectByKeys(DbSession session, OrganizationDto organization, Collection<RuleKey> keys) { | |||
return ensureOrganizationIsSet(organization.getUuid(), | |||
executeLargeInputs(keys, chunk -> mapper(session).selectByKeys(organization.getUuid(), chunk))); | |||
} | |||
public List<RuleDto> selectByKeys(DbSession session, String organizationUuid, Collection<RuleKey> keys) { | |||
return ensureOrganizationIsSet(organizationUuid, | |||
executeLargeInputs(keys, chunk -> mapper(session).selectByKeys(organizationUuid, chunk))); |
@@ -129,18 +129,10 @@ | |||
and gu.user_id = #{userId,jdbcType=INTEGER} | |||
</select> | |||
<select id="selectWithoutQualityProfile" parameterType="map" resultType="Organization"> | |||
select | |||
<include refid="selectColumns"/> | |||
from organizations org | |||
where not exists ( | |||
select 1 from rules_profiles p | |||
inner join org_qprofiles oqp on oqp.rules_profile_uuid = p.kee | |||
where oqp.organization_uuid = org.uuid | |||
and p.language = #{profileLanguage, jdbcType=VARCHAR} | |||
and p.name = #{profileName, jdbcType=VARCHAR} | |||
) | |||
<select id="selectAllUuids" resultType="String"> | |||
select uuid from organizations | |||
</select> | |||
<select id="selectDefaultGroupIdByUuid" resultType="Integer"> | |||
select org.default_group_id | |||
from organizations org |
@@ -3,7 +3,7 @@ | |||
<mapper namespace="org.sonar.db.qualityprofile.ActiveRuleMapper"> | |||
<sql id="activeRuleKeyColumns"> | |||
<sql id="activeRuleColumns"> | |||
a.id, | |||
a.profile_id as "profileId", | |||
a.rule_id as "ruleId", | |||
@@ -11,106 +11,145 @@ | |||
a.inheritance as "inheritance", | |||
r.plugin_rule_key as "rulefield", | |||
r.plugin_name as "repository", | |||
qp.kee as "profileKey", | |||
rp.kee as "ruleProfileUuid", | |||
a.created_at as "createdAt", | |||
a.updated_at as "updatedAt" | |||
</sql> | |||
<sql id="orgActiveRuleColumns"> | |||
a.id, | |||
a.profile_id as "profileId", | |||
a.rule_id as "ruleId", | |||
a.failure_level as "severity", | |||
a.inheritance as "inheritance", | |||
r.plugin_rule_key as "rulefield", | |||
r.plugin_name as "repository", | |||
rp.kee as "ruleProfileUuid", | |||
a.created_at as "createdAt", | |||
a.updated_at as "updatedAt", | |||
oqp.organization_uuid as "organizationUuid", | |||
oqp.uuid as "profileUuid" | |||
</sql> | |||
<sql id="activeRuleKeyJoin"> | |||
inner join rules_profiles qp on qp.id=a.profile_id | |||
inner join org_qprofiles oqp on oqp.rules_profile_uuid = qp.kee | |||
inner join rules_profiles rp on rp.id = a.profile_id | |||
inner join rules r on r.id = a.rule_id | |||
</sql> | |||
<insert id="insert" parameterType="ActiveRule" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> | |||
INSERT INTO active_rules (profile_id, rule_id, failure_level, inheritance, created_at, updated_at) | |||
VALUES (#{profileId}, #{ruleId}, #{severity}, #{inheritance}, #{createdAt}, #{updatedAt}) | |||
insert into active_rules ( | |||
profile_id, | |||
rule_id, | |||
failure_level, | |||
inheritance, | |||
created_at, | |||
updated_at | |||
) values ( | |||
#{profileId, jdbcType=BIGINT}, | |||
#{ruleId, jdbcType=BIGINT}, | |||
#{severity, jdbcType=INTEGER}, | |||
#{inheritance, jdbcType=VARCHAR}, | |||
#{createdAt, jdbcType=BIGINT}, | |||
#{updatedAt, jdbcType=BIGINT} | |||
) | |||
</insert> | |||
<update id="update" parameterType="ActiveRule"> | |||
UPDATE active_rules SET | |||
failure_level=#{severity}, | |||
inheritance=#{inheritance}, | |||
updated_at=#{updatedAt} | |||
WHERE id=#{id} | |||
update active_rules | |||
set | |||
failure_level = #{severity, jdbcType=INTEGER}, | |||
inheritance = #{inheritance, jdbcType=VARCHAR}, | |||
updated_at = #{updatedAt, jdbcType=BIGINT} | |||
where | |||
id = #{id, jdbcType=BIGINT} | |||
</update> | |||
<update id="delete" parameterType="int"> | |||
DELETE FROM active_rules WHERE id=#{id} | |||
</update> | |||
<delete id="delete" parameterType="int"> | |||
delete from active_rules | |||
where | |||
id=#{id, jdbcType=BIGINT} | |||
</delete> | |||
<update id="deleteByProfileKeys" parameterType="String"> | |||
<delete id="deleteByRuleProfileUuids" parameterType="String"> | |||
delete from active_rules | |||
where exists ( | |||
select 1 | |||
from rules_profiles p | |||
where p.id = profile_id and p.kee in | |||
<foreach collection="profileKeys" open="(" close=")" item="profileKey" separator=",">#{profileKey, jdbcType=VARCHAR}</foreach> | |||
from rules_profiles rp | |||
where rp.id = profile_id | |||
and rp.kee in | |||
<foreach collection="rulesProfileUuids" open="(" close=")" item="rulesProfileUuid" separator=",">#{rulesProfileUuid, jdbcType=VARCHAR}</foreach> | |||
) | |||
</update> | |||
</delete> | |||
<select id="selectByKey" parameterType="map" resultType="ActiveRule"> | |||
SELECT | |||
<include refid="activeRuleKeyColumns"/> | |||
FROM active_rules a | |||
select | |||
<include refid="activeRuleColumns"/> | |||
from active_rules a | |||
<include refid="activeRuleKeyJoin"/> | |||
WHERE | |||
qp.kee = #{profileKey} | |||
AND r.plugin_rule_key = #{rule} | |||
AND r.plugin_name = #{repository} | |||
where | |||
rp.kee = #{ruleProfileUuid, jdbcType=VARCHAR} | |||
and r.plugin_rule_key = #{rule, jdbcType=VARCHAR} | |||
and r.plugin_name = #{repository, jdbcType=VARCHAR} | |||
</select> | |||
<select id="selectByKeys" parameterType="map" resultType="ActiveRule"> | |||
SELECT | |||
<include refid="activeRuleKeyColumns"/> | |||
FROM active_rules a | |||
select | |||
<include refid="activeRuleColumns"/> | |||
from active_rules a | |||
<include refid="activeRuleKeyJoin"/> | |||
WHERE | |||
where | |||
<foreach collection="keys" item="key" open="(" separator=" or " close=")"> | |||
(qp.kee = #{key.qualityProfileKey} | |||
AND r.plugin_rule_key = #{key.ruleKey.rule} | |||
AND r.plugin_name = #{key.ruleKey.repository} | |||
(rp.kee = #{key.ruleProfileUuid, jdbcType=VARCHAR} | |||
AND r.plugin_rule_key = #{key.ruleKey.rule, jdbcType=VARCHAR} | |||
AND r.plugin_name = #{key.ruleKey.repository, jdbcType=VARCHAR} | |||
) | |||
</foreach> | |||
</select> | |||
<select id="selectByProfileKey" parameterType="string" resultType="ActiveRule"> | |||
SELECT | |||
<include refid="activeRuleKeyColumns"/> | |||
FROM active_rules a | |||
INNER JOIN rules_profiles qp ON qp.id=a.profile_id | |||
INNER JOIN rules r ON r.id = a.rule_id AND r.status != 'REMOVED' | |||
where qp.kee=#{id} | |||
<select id="selectByProfileUuid" parameterType="string" resultType="org.sonar.db.qualityprofile.OrgActiveRuleDto"> | |||
select | |||
<include refid="orgActiveRuleColumns"/> | |||
from active_rules a | |||
inner join rules_profiles rp on rp.id = a.profile_id | |||
inner join org_qprofiles oqp on oqp.rules_profile_uuid = rp.kee | |||
inner join rules r on r.id = a.rule_id and r.status != 'REMOVED' | |||
where oqp.uuid = #{id, jdbcType=VARCHAR} | |||
</select> | |||
<select id="selectByRuleId" parameterType="map" resultType="ActiveRule"> | |||
SELECT | |||
<include refid="activeRuleKeyColumns"/> | |||
FROM active_rules a | |||
<include refid="activeRuleKeyJoin"/> | |||
WHERE a.rule_id=#{ruleId, jdbcType=BIGINT} | |||
AND oqp.organization_uuid=#{organizationUuid, jdbcType=VARCHAR} | |||
<select id="selectByRuleId" parameterType="map" resultType="org.sonar.db.qualityprofile.OrgActiveRuleDto"> | |||
select | |||
<include refid="orgActiveRuleColumns"/> | |||
from active_rules a | |||
inner join rules_profiles rp on rp.id = a.profile_id | |||
inner join org_qprofiles oqp on oqp.rules_profile_uuid = rp.kee | |||
inner join rules r on r.id = a.rule_id | |||
where | |||
a.rule_id = #{ruleId, jdbcType=BIGINT} | |||
and oqp.organization_uuid = #{organizationUuid, jdbcType=VARCHAR} | |||
</select> | |||
<select id="selectByRuleIdOfAllOrganizations" parameterType="Integer" resultType="ActiveRule"> | |||
SELECT | |||
<include refid="activeRuleKeyColumns"/> | |||
FROM active_rules a | |||
select | |||
<include refid="activeRuleColumns"/> | |||
from active_rules a | |||
<include refid="activeRuleKeyJoin"/> | |||
WHERE a.rule_id=#{ruleId} | |||
where | |||
a.rule_id = #{ruleId, jdbcType=BIGINT} | |||
</select> | |||
<select id="selectByRuleIds" parameterType="List" resultType="ActiveRule"> | |||
SELECT | |||
<include refid="activeRuleKeyColumns"/> | |||
FROM active_rules a | |||
<include refid="activeRuleKeyJoin"/> | |||
WHERE | |||
<select id="selectByRuleIds" parameterType="List" resultType="org.sonar.db.qualityprofile.OrgActiveRuleDto"> | |||
select | |||
<include refid="orgActiveRuleColumns"/> | |||
from active_rules a | |||
inner join rules_profiles rp on rp.id = a.profile_id | |||
inner join org_qprofiles oqp on oqp.rules_profile_uuid = rp.kee | |||
inner join rules r on r.id = a.rule_id | |||
where | |||
a.rule_id in | |||
<foreach collection="ruleIds" item="ruleId" separator="," open="(" close=")"> | |||
#{ruleId} | |||
#{ruleId, jdbcType=BIGINT} | |||
</foreach> | |||
AND oqp.organization_uuid=#{organizationUuid, jdbcType=VARCHAR} | |||
and oqp.organization_uuid = #{organizationUuid, jdbcType=VARCHAR} | |||
</select> | |||
<!-- Parameters --> | |||
@@ -124,43 +163,52 @@ | |||
</sql> | |||
<insert id="insertParameter" parameterType="ActiveRuleParam" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> | |||
INSERT INTO active_rule_parameters (active_rule_id, rules_parameter_id, rules_parameter_key, value) | |||
VALUES (#{activeRuleId}, #{rulesParameterId}, #{key}, #{value}) | |||
insert into active_rule_parameters ( | |||
active_rule_id, | |||
rules_parameter_id, | |||
rules_parameter_key, | |||
value | |||
) values ( | |||
#{activeRuleId, jdbcType=BIGINT}, | |||
#{rulesParameterId, jdbcType=BIGINT}, | |||
#{key, jdbcType=VARCHAR}, | |||
#{value, jdbcType=VARCHAR} | |||
) | |||
</insert> | |||
<update id="updateParameter" parameterType="ActiveRuleParam"> | |||
UPDATE active_rule_parameters SET | |||
value=#{value} | |||
WHERE id=#{id} | |||
value=#{value, jdbcType=VARCHAR} | |||
WHERE id=#{id, jdbcType=BIGINT} | |||
</update> | |||
<update id="deleteParameters" parameterType="int"> | |||
DELETE FROM active_rule_parameters WHERE active_rule_id=#{id} | |||
</update> | |||
<delete id="deleteParameters" parameterType="int"> | |||
DELETE FROM active_rule_parameters WHERE active_rule_id=#{id, jdbcType=BIGINT} | |||
</delete> | |||
<update id="deleteParametersByProfileKeys" parameterType="String"> | |||
<delete id="deleteParametersByRuleProfileUuids" parameterType="String"> | |||
delete from active_rule_parameters | |||
where exists ( | |||
select 1 from active_rules ar | |||
inner join rules_profiles p on p.id = ar.profile_id | |||
inner join rules_profiles rp on rp.id = ar.profile_id | |||
where ar.id = active_rule_id | |||
and p.kee in | |||
<foreach collection="profileKeys" open="(" close=")" item="profileKey" separator=","> | |||
#{profileKey, jdbcType=VARCHAR} | |||
and rp.kee in | |||
<foreach collection="rulesProfileUuids" open="(" close=")" item="rulesProfileUuid" separator=","> | |||
#{rulesProfileUuid, jdbcType=VARCHAR} | |||
</foreach> | |||
) | |||
</update> | |||
</delete> | |||
<update id="deleteParameter" parameterType="int"> | |||
DELETE FROM active_rule_parameters WHERE id=#{id} | |||
</update> | |||
<delete id="deleteParameter" parameterType="int"> | |||
DELETE FROM active_rule_parameters WHERE id=#{id, jdbcType=BIGINT} | |||
</delete> | |||
<select id="selectParamsByActiveRuleId" parameterType="Integer" resultType="ActiveRuleParam"> | |||
select | |||
<include refid="activeRuleParamColumns"/> | |||
from active_rule_parameters p | |||
<where> | |||
p.active_rule_id=#{id} | |||
p.active_rule_id=#{id, jdbcType=BIGINT} | |||
</where> | |||
</select> | |||
@@ -170,51 +218,35 @@ | |||
from active_rule_parameters p | |||
<where> | |||
<foreach collection="ids" item="id" open="(" separator=" or " close=")"> | |||
p.active_rule_id=#{id} | |||
p.active_rule_id=#{id, jdbcType=BIGINT} | |||
</foreach> | |||
</where> | |||
</select> | |||
<select id="selectParamByActiveRuleAndKey" parameterType="map" resultType="ActiveRuleParam"> | |||
SELECT | |||
<include refid="activeRuleParamColumns"/> | |||
FROM active_rule_parameters p | |||
<where> | |||
AND p.active_rule_id=#{activeRuleId} | |||
AND p.rules_parameter_key=#{key} | |||
</where> | |||
</select> | |||
<select id="selectAllParams" resultType="ActiveRuleParam"> | |||
select | |||
<include refid="activeRuleParamColumns"/> | |||
from active_rule_parameters p | |||
</select> | |||
<select id="countActiveRulesByProfileKey" resultType="KeyLongValue" parameterType="map"> | |||
select rp.kee as "key", count(ar.id) as "value" | |||
<select id="countActiveRulesByProfileUuid" resultType="KeyLongValue" parameterType="map"> | |||
select oqp.uuid as "key", count(ar.id) as "value" | |||
from active_rules ar | |||
inner join rules_profiles rp on rp.id = ar.profile_id | |||
inner join org_qprofiles oqp on oqp.rules_profile_uuid = rp.kee | |||
inner join rules r on r.id = ar.rule_id | |||
where oqp.organization_uuid = #{organizationUuid, jdbcType=VARCHAR} | |||
and r.status != 'REMOVED' | |||
group by rp.kee | |||
group by oqp.uuid | |||
</select> | |||
<select id="countActiveRulesForRuleStatusByProfileKey" resultType="KeyLongValue" parameterType="map"> | |||
select rp.kee as "key", count(ar.id) as "value" | |||
<select id="countActiveRulesForRuleStatusByProfileUuid" resultType="KeyLongValue" parameterType="map"> | |||
select oqp.uuid as "key", count(ar.id) as "value" | |||
from active_rules ar | |||
inner join rules_profiles rp on rp.id = ar.profile_id | |||
inner join org_qprofiles oqp on oqp.rules_profile_uuid = rp.kee | |||
inner join rules r on r.id = ar.rule_id | |||
where oqp.organization_uuid = #{organizationUuid, jdbcType=VARCHAR} | |||
and r.status = #{ruleStatus, jdbcType=VARCHAR} | |||
group by rp.kee | |||
group by oqp.uuid | |||
</select> | |||
<select id="countActiveRulesForInheritanceByProfileKey" resultType="KeyLongValue" parameterType="map"> | |||
select rp.kee as "key", count(ar.id) as "value" | |||
<select id="countActiveRulesForInheritanceByProfileUuid" resultType="KeyLongValue" parameterType="map"> | |||
select oqp.uuid as "key", count(ar.id) as "value" | |||
from active_rules ar | |||
inner join rules_profiles rp on rp.id = ar.profile_id | |||
inner join org_qprofiles oqp on oqp.rules_profile_uuid = rp.kee | |||
@@ -222,7 +254,7 @@ | |||
where oqp.organization_uuid = #{organizationUuid, jdbcType=VARCHAR} | |||
and ar.inheritance = #{inheritance, jdbcType=VARCHAR} | |||
and r.status != 'REMOVED' | |||
group by rp.kee | |||
group by oqp.uuid | |||
</select> | |||
</mapper> | |||
@@ -3,28 +3,41 @@ | |||
<mapper namespace="org.sonar.db.qualityprofile.QProfileChangeMapper"> | |||
<sql id="selectColumns"> | |||
qpc.kee as "uuid", | |||
qpc.qprofile_key as rulesProfileUuid, | |||
qpc.created_at as createdAt, | |||
qpc.user_login as login, | |||
qpc.change_type as changeType, | |||
qpc.change_data as data | |||
</sql> | |||
<insert id="insert" useGeneratedKeys="false" parameterType="org.sonar.db.qualityprofile.QProfileChangeDto"> | |||
insert into qprofile_changes | |||
( | |||
kee, | |||
qprofile_key, | |||
created_at, | |||
user_login, | |||
change_type, | |||
change_data | |||
kee, | |||
qprofile_key, | |||
created_at, | |||
user_login, | |||
change_type, | |||
change_data | |||
) values ( | |||
#{key,jdbcType=VARCHAR}, | |||
#{profileKey,jdbcType=VARCHAR}, | |||
#{createdAt,jdbcType=BIGINT}, | |||
#{login,jdbcType=VARCHAR}, | |||
#{changeType,jdbcType=VARCHAR}, | |||
#{data,jdbcType=VARCHAR} | |||
#{uuid, jdbcType=VARCHAR}, | |||
#{rulesProfileUuid, jdbcType=VARCHAR}, | |||
#{createdAt, jdbcType=BIGINT}, | |||
#{login, jdbcType=VARCHAR}, | |||
#{changeType, jdbcType=VARCHAR}, | |||
#{data, jdbcType=VARCHAR} | |||
) | |||
</insert> | |||
<select id="countForProfileUuid" resultType="int"> | |||
select count(kee) from qprofile_changes | |||
where qprofile_key = #{profileUuid, jdbcType=VARCHAR} | |||
<select id="countForQProfileUuid" resultType="int"> | |||
select count(qpc.kee) | |||
from qprofile_changes qpc | |||
inner join rules_profiles rp on rp.kee = qpc.qprofile_key | |||
inner join org_qprofiles oqp on oqp.rules_profile_uuid = rp.kee | |||
where | |||
oqp.uuid = #{qProfileUuid, jdbcType=VARCHAR} | |||
</select> | |||
<select id="selectByQuery" resultType="org.sonar.db.qualityprofile.QProfileChangeDto"> | |||
@@ -40,8 +53,8 @@ | |||
</select> | |||
<select id="selectByQuery" databaseId="oracle" resultType="org.sonar.db.qualityprofile.QProfileChangeDto"> | |||
select "key", profileKey, createdAt, login, changeType, data from ( | |||
select rownum rnum, "key", profileKey, createdAt, login, changeType, data from ( | |||
select "uuid", rulesProfileUuid, createdAt, login, changeType, data from ( | |||
select rownum rnum, "uuid", rulesProfileUuid, createdAt, login, changeType, data from ( | |||
<include refid="sqlSelectByQuery" /> | |||
) | |||
where rownum <= #{query.total} | |||
@@ -49,33 +62,27 @@ | |||
where rnum > #{query.offset} | |||
</select> | |||
<sql id="sqlColumns"> | |||
kee as "key", | |||
qprofile_key as profileKey, | |||
created_at as createdAt, | |||
user_login as login, | |||
change_type as changeType, | |||
change_data as data | |||
</sql> | |||
<sql id="sqlSelectByQuery"> | |||
select <include refid="sqlColumns" /> | |||
from qprofile_changes | |||
where qprofile_key = #{query.profileUuid, jdbcType=VARCHAR} | |||
<if test="query.fromIncluded != null"> | |||
and created_at >= #{query.fromIncluded} | |||
</if> | |||
<if test="query.toExcluded != null"> | |||
and created_at < #{query.toExcluded} | |||
</if> | |||
order by created_at desc | |||
select <include refid="selectColumns" /> | |||
from qprofile_changes qpc | |||
inner join rules_profiles rp on rp.kee = qpc.qprofile_key | |||
inner join org_qprofiles oqp on oqp.rules_profile_uuid = rp.kee | |||
where | |||
oqp.uuid = #{query.profileUuid, jdbcType=VARCHAR} | |||
<if test="query.fromIncluded != null"> | |||
and qpc.created_at >= #{query.fromIncluded} | |||
</if> | |||
<if test="query.toExcluded != null"> | |||
and qpc.created_at < #{query.toExcluded} | |||
</if> | |||
order by qpc.created_at desc | |||
</sql> | |||
<delete id="deleteByProfileUuids" parameterType="String"> | |||
<delete id="deleteByRuleProfileUuids" parameterType="String"> | |||
delete from qprofile_changes | |||
where qprofile_key in | |||
<foreach collection="profileUuids" open="(" close=")" item="profileUuid" separator=","> | |||
#{profileUuid, jdbcType=VARCHAR} | |||
<foreach collection="ruleProfileUuids" open="(" close=")" item="ruleProfileUuid" separator=","> | |||
#{ruleProfileUuid, jdbcType=VARCHAR} | |||
</foreach> | |||
</delete> | |||
</mapper> |
@@ -8,6 +8,7 @@ | |||
oqp.organization_uuid as organizationUuid, | |||
oqp.parent_uuid as parentKee, | |||
rp.id as id, | |||
rp.kee as rulesProfileUuid, | |||
rp.name as name, | |||
rp.language as language, | |||
rp.rules_updated_at as rulesUpdatedAt, | |||
@@ -16,7 +17,18 @@ | |||
rp.is_built_in as isBuiltIn | |||
</sql> | |||
<insert id="insertRulesProfile" parameterType="map" keyColumn="id" useGeneratedKeys="true" keyProperty="dto.id"> | |||
<sql id="ruleProfileColumns"> | |||
rp.id as id, | |||
rp.kee as kee, | |||
rp.name as name, | |||
rp.language as language, | |||
rp.rules_updated_at as rulesUpdatedAt, | |||
rp.last_used as lastUsed, | |||
rp.user_updated_at as userUpdatedAt, | |||
rp.is_built_in as isBuiltIn | |||
</sql> | |||
<insert id="insertRuleProfile" parameterType="map" keyColumn="id" useGeneratedKeys="true" keyProperty="dto.id"> | |||
insert into rules_profiles ( | |||
kee, | |||
name, | |||
@@ -49,16 +61,16 @@ | |||
created_at, | |||
updated_at | |||
) values ( | |||
#{dto.kee, jdbcType=VARCHAR}, | |||
#{dto.uuid, jdbcType=VARCHAR}, | |||
#{dto.organizationUuid, jdbcType=VARCHAR}, | |||
#{dto.kee, jdbcType=VARCHAR}, | |||
#{dto.parentKee, jdbcType=VARCHAR}, | |||
#{dto.rulesProfileUuid, jdbcType=VARCHAR}, | |||
#{dto.parentUuid, jdbcType=VARCHAR}, | |||
#{now, jdbcType=BIGINT}, | |||
#{now, jdbcType=BIGINT} | |||
) | |||
</insert> | |||
<update id="updateRulesProfile" parameterType="map"> | |||
<update id="updateRuleProfile" parameterType="map"> | |||
update rules_profiles | |||
set | |||
name = #{dto.name, jdbcType=VARCHAR}, | |||
@@ -69,7 +81,7 @@ | |||
user_updated_at = #{dto.userUpdatedAt, jdbcType=BIGINT}, | |||
is_built_in = #{dto.isBuiltIn, jdbcType=BOOLEAN} | |||
where | |||
kee = #{dto.kee, jdbcType=VARCHAR} | |||
kee = #{dto.rulesProfileUuid, jdbcType=VARCHAR} | |||
</update> | |||
<update id="updateOrgQProfile" parameterType="map"> | |||
@@ -81,7 +93,7 @@ | |||
uuid = #{dto.kee, jdbcType=VARCHAR} | |||
</update> | |||
<delete id="deleteRulesProfilesByUuids" parameterType="String"> | |||
<delete id="deleteRuleProfilesByUuids" parameterType="String"> | |||
delete from rules_profiles | |||
where kee in | |||
<foreach collection="uuids" open="(" close=")" item="uuid" separator=",">#{uuid, jdbcType=VARCHAR}</foreach> | |||
@@ -93,7 +105,13 @@ | |||
<foreach collection="uuids" open="(" close=")" item="uuid" separator=",">#{uuid, jdbcType=VARCHAR}</foreach> | |||
</delete> | |||
<select id="selectAll" parameterType="map" resultType="org.sonar.db.qualityprofile.QProfileDto"> | |||
<select id="selectBuiltInRuleProfiles" resultType="org.sonar.db.qualityprofile.RulesProfileDto"> | |||
select <include refid="ruleProfileColumns"/> | |||
from rules_profiles rp | |||
where rp.is_built_in = ${_true} | |||
</select> | |||
<select id="selectOrderedByOrganizationUuid" parameterType="map" resultType="org.sonar.db.qualityprofile.QProfileDto"> | |||
select | |||
<include refid="qProfileColumns"/> | |||
from org_qprofiles oqp | |||
@@ -124,7 +142,7 @@ | |||
inner join default_qprofiles dp on dp.qprofile_uuid = oqp.uuid | |||
where | |||
dp.language in <foreach collection="languages" open="(" close=")" item="language" separator=",">#{language, jdbcType=VARCHAR}</foreach> | |||
and dp.organization_uuid = #{organizationUuid, jdbcType=VARCHAR} | |||
and dp.organization_uuid = oqp.organization_uuid | |||
and rp.language = dp.language | |||
and oqp.organization_uuid = #{organizationUuid, jdbcType=VARCHAR} | |||
</select> | |||
@@ -166,7 +184,7 @@ | |||
from org_qprofiles oqp | |||
inner join rules_profiles rp on oqp.rules_profile_uuid = rp.kee | |||
where | |||
oqp.uuid in <foreach collection="uuids" open="(" close=")" item="uuid" separator=",">#{uuid}</foreach> | |||
oqp.uuid in <foreach collection="uuids" open="(" close=")" item="uuid" separator=",">#{uuid, jdbcType=VARCHAR}</foreach> | |||
</select> | |||
<select id="selectByLanguage" parameterType="String" resultType="org.sonar.db.qualityprofile.QProfileDto"> | |||
@@ -300,8 +318,8 @@ | |||
ORDER BY pj.name ASC | |||
</select> | |||
<select id="selectUuidsOfCustomQProfiles" parameterType="map" resultType="string"> | |||
select oqp.uuid | |||
<select id="selectUuidsOfCustomRuleProfiles" parameterType="map" resultType="string"> | |||
select oqp.rules_profile_uuid | |||
from org_qprofiles oqp | |||
inner join organizations o on o.uuid = oqp.organization_uuid | |||
inner join rules_profiles rp on rp.kee = oqp.rules_profile_uuid | |||
@@ -311,7 +329,7 @@ | |||
and rp.is_built_in = ${_false} | |||
</select> | |||
<update id="renameRulesProfiles" parameterType="map"> | |||
<update id="renameRuleProfiles" parameterType="map"> | |||
update rules_profiles | |||
set | |||
name = #{newName, jdbcType=VARCHAR}, |
@@ -229,6 +229,7 @@ public class DbTester extends AbstractDbTester<TestDb> { | |||
@Override | |||
protected void after() { | |||
if (session != null) { | |||
session.rollback(); | |||
session.close(); | |||
} | |||
db.stop(); |
@@ -41,7 +41,6 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.dialect.Dialect; | |||
import org.sonar.db.dialect.Oracle; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.user.GroupDto; | |||
import org.sonar.db.user.GroupTesting; | |||
import org.sonar.db.user.UserDto; | |||
@@ -873,19 +872,6 @@ public class OrganizationDaoTest { | |||
.containsOnlyOnce(organization.getUuid()); | |||
} | |||
@Test | |||
public void selectWithoutQualityProfile_returns_() { | |||
OrganizationDto orgWithoutAnyProfiles = dbTester.organizations().insert(); | |||
OrganizationDto orgWithProfiles = dbTester.organizations().insert(); | |||
QProfileDto profile = dbTester.qualityProfiles().insert(orgWithProfiles); | |||
assertThat(underTest.selectWithoutQualityProfile(dbSession, "js", "foo")) | |||
.extracting(OrganizationDto::getUuid).containsExactlyInAnyOrder(orgWithoutAnyProfiles.getUuid(), orgWithProfiles.getUuid()); | |||
assertThat(underTest.selectWithoutQualityProfile(dbSession, profile.getLanguage(), profile.getName())) | |||
.extracting(OrganizationDto::getUuid).containsExactlyInAnyOrder(orgWithoutAnyProfiles.getUuid()); | |||
} | |||
private void expectDtoCanNotBeNull() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("OrganizationDto can't be null"); |
@@ -22,18 +22,18 @@ package org.sonar.db.qualityprofile; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.junit.After; | |||
import java.util.Objects; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.api.server.rule.RuleParamType; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.api.utils.internal.TestSystem2; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.RowNotFoundException; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.organization.OrganizationTesting; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
@@ -44,10 +44,8 @@ import static com.google.common.collect.Lists.newArrayList; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.emptyList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.tuple; | |||
import static org.assertj.core.data.MapEntry.entry; | |||
import static org.assertj.guava.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.api.rule.Severity.BLOCKER; | |||
import static org.sonar.api.rule.Severity.MAJOR; | |||
import static org.sonar.db.qualityprofile.ActiveRuleDto.INHERITED; | |||
@@ -61,97 +59,59 @@ public class ActiveRuleDaoTest { | |||
private static final long NOW = 10_000_000L; | |||
private OrganizationDto organization = OrganizationTesting.newOrganizationDto(); | |||
private QProfileDto profile1 = QProfileDto.createFor("qp1").setOrganizationUuid(organization.getUuid()).setName("QProfile1"); | |||
private QProfileDto profile2 = QProfileDto.createFor("qp2").setOrganizationUuid(organization.getUuid()).setName("QProfile2"); | |||
private RuleDefinitionDto rule1 = RuleTesting.newRule(RuleTesting.XOO_X1); | |||
private RuleDefinitionDto rule2 = RuleTesting.newRule(RuleTesting.XOO_X2); | |||
private RuleDefinitionDto rule3 = RuleTesting.newRule(RuleTesting.XOO_X3); | |||
private RuleDefinitionDto removedRule = RuleTesting.newRule().setStatus(RuleStatus.REMOVED); | |||
private OrganizationDto organization; | |||
private QProfileDto profile1; | |||
private QProfileDto profile2; | |||
private RuleDefinitionDto rule1; | |||
private RuleDefinitionDto rule2; | |||
private RuleDefinitionDto rule3; | |||
private RuleDefinitionDto removedRule; | |||
private RuleParamDto rule1Param1; | |||
private RuleParamDto rule1Param2; | |||
private RuleParamDto rule2Param1; | |||
private System2 system = mock(System2.class); | |||
private System2 system = new TestSystem2().setNow(NOW); | |||
@Rule | |||
public DbTester dbTester = DbTester.create(system); | |||
public DbTester db = DbTester.create(system); | |||
private DbClient dbClient = dbTester.getDbClient(); | |||
private DbSession dbSession = dbTester.getSession(); | |||
private DbSession dbSession = db.getSession(); | |||
private ActiveRuleDao underTest = dbTester.getDbClient().activeRuleDao(); | |||
private ActiveRuleDao underTest = db.getDbClient().activeRuleDao(); | |||
@Before | |||
public void setUp() { | |||
when(system.now()).thenReturn(NOW); | |||
dbClient.qualityProfileDao().insert(dbSession, profile1); | |||
dbClient.qualityProfileDao().insert(dbSession, profile2); | |||
dbTester.rules().insert(rule1); | |||
dbTester.rules().insert(rule2); | |||
dbTester.rules().insert(rule3); | |||
dbTester.rules().insert(removedRule); | |||
organization = db.organizations().insert(); | |||
profile1 = db.qualityProfiles().insert(organization); | |||
profile2 = db.qualityProfiles().insert(organization); | |||
rule1 = db.rules().insert(); | |||
rule2 = db.rules().insert(); | |||
rule3 = db.rules().insert(); | |||
removedRule = db.rules().insert(r -> r.setStatus(RuleStatus.REMOVED)); | |||
rule1Param1 = new RuleParamDto() | |||
.setName("param1") | |||
.setDefaultValue("value1") | |||
.setType(RuleParamType.STRING.toString()); | |||
dbClient.ruleDao().insertRuleParam(dbSession, rule1, rule1Param1); | |||
rule1Param2 = new RuleParamDto() | |||
.setRuleId(rule1.getId()) | |||
.setName("param2") | |||
.setDefaultValue("2") | |||
.setType(RuleParamType.INTEGER.toString()); | |||
dbClient.ruleDao().insertRuleParam(dbSession, rule1, rule1Param2); | |||
rule2Param1 = new RuleParamDto() | |||
.setRuleId(rule2.getId()) | |||
.setName("param1") | |||
.setDefaultValue("1") | |||
.setType(RuleParamType.INTEGER.toString()); | |||
dbClient.ruleDao().insertRuleParam(dbSession, rule2, rule2Param1); | |||
dbSession.commit(); | |||
} | |||
@After | |||
public void tearDown() { | |||
// minor optimization, no need to commit pending operations | |||
dbSession.rollback(); | |||
rule1Param1 = db.rules().insertRuleParam(rule1); | |||
rule1Param2 = db.rules().insertRuleParam(rule1); | |||
rule2Param1 = db.rules().insertRuleParam(rule2); | |||
} | |||
@Test | |||
public void select_by_key() { | |||
public void selectByKey() { | |||
ActiveRuleDto activeRule = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbSession, activeRule); | |||
assertThat(underTest.selectByKey(dbSession, activeRule.getKey())).isPresent(); | |||
assertThat(underTest.selectByKey(dbSession, ActiveRuleKey.of(profile2.getKee(), rule2.getKey()))).isAbsent(); | |||
} | |||
@Test | |||
public void select_or_fail_by_key() { | |||
ActiveRuleDto activeRule = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbSession, activeRule); | |||
assertThat(underTest.selectOrFailByKey(dbSession, activeRule.getKey())).isNotNull(); | |||
thrown.expect(RowNotFoundException.class); | |||
thrown.expectMessage("Active rule with key 'qp2:xoo:x2' does not exist"); | |||
underTest.selectOrFailByKey(dbSession, ActiveRuleKey.of(profile2.getKee(), rule2.getKey())); | |||
assertThat(underTest.selectByKey(dbSession, ActiveRuleKey.of(profile2, rule2.getKey()))).isEmpty(); | |||
} | |||
@Test | |||
public void select_by_rule() { | |||
ActiveRuleDto activeRule1 = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
ActiveRuleDto activeRule2 = createFor(profile2, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule1); | |||
underTest.insert(dbTester.getSession(), activeRule2); | |||
underTest.insert(dbSession, activeRule1); | |||
underTest.insert(dbSession, activeRule2); | |||
dbSession.commit(); | |||
assertThat(underTest.selectByRuleId(dbSession, organization, rule1.getId())).extracting("key").containsOnly(activeRule1.getKey(), activeRule2.getKey()); | |||
@@ -168,31 +128,34 @@ public class ActiveRuleDaoTest { | |||
underTest.insert(dbSession, activeRule3); | |||
dbSession.commit(); | |||
assertThat(underTest.selectByRuleIds(dbSession, organization.getUuid(), Collections.singletonList(rule1.getId()))) | |||
assertThat(underTest.selectByRuleIds(dbSession, organization, Collections.singletonList(rule1.getId()))) | |||
.extracting("key").containsOnly(activeRule1.getKey(), activeRule3.getKey()); | |||
assertThat(underTest.selectByRuleIds(dbSession, organization.getUuid(), newArrayList(rule1.getId(), rule2.getId()))) | |||
assertThat(underTest.selectByRuleIds(dbSession, organization, newArrayList(rule1.getId(), rule2.getId()))) | |||
.extracting("key").containsOnly(activeRule1.getKey(), activeRule2.getKey(), activeRule3.getKey()); | |||
} | |||
@Test | |||
public void select_by_profile() { | |||
public void selectByProfile() { | |||
ActiveRuleDto activeRule1 = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
ActiveRuleDto activeRule2 = createFor(profile1, rule2).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule1); | |||
underTest.insert(dbTester.getSession(), activeRule2); | |||
dbSession.commit(); | |||
underTest.insert(dbSession, activeRule1); | |||
underTest.insert(dbSession, activeRule2); | |||
assertThat(underTest.selectByProfileKey(dbSession, profile1.getKee())).hasSize(2); | |||
assertThat(underTest.selectByProfileKey(dbSession, profile2.getKee())).isEmpty(); | |||
List<OrgActiveRuleDto> result = underTest.selectByProfile(dbSession, profile1); | |||
assertThat(result) | |||
.hasSize(2) | |||
.extracting(OrgActiveRuleDto::getOrganizationUuid, OrgActiveRuleDto::getProfileUuid, OrgActiveRuleDto::getProfileId) | |||
.containsOnly(tuple(organization.getUuid(), profile1.getKee(), profile1.getId())); | |||
assertThat(underTest.selectByProfile(dbSession, profile2)).isEmpty(); | |||
} | |||
@Test | |||
public void select_by_profile_ignore_removed_rules() throws Exception { | |||
public void selectByProfileUuid_ignores_removed_rules() throws Exception { | |||
ActiveRuleDto activeRule = createFor(profile1, removedRule).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule); | |||
dbSession.commit(); | |||
underTest.insert(dbSession, activeRule); | |||
assertThat(underTest.selectByProfileKey(dbSession, profile1.getKee())).isEmpty(); | |||
assertThat(underTest.selectByProfile(dbSession, profile1)).isEmpty(); | |||
} | |||
@Test | |||
@@ -202,12 +165,12 @@ public class ActiveRuleDaoTest { | |||
.setInheritance(INHERITED) | |||
.setCreatedAt(1000L) | |||
.setUpdatedAt(2000L); | |||
underTest.insert(dbTester.getSession(), activeRule); | |||
underTest.insert(dbSession, activeRule); | |||
dbSession.commit(); | |||
ActiveRuleDto result = underTest.selectOrFailByKey(dbSession, activeRule.getKey()); | |||
ActiveRuleDto result = underTest.selectByKey(dbSession, activeRule.getKey()).get(); | |||
assertThat(result.getId()).isEqualTo(activeRule.getId()); | |||
assertThat(result.getKey()).isEqualTo(ActiveRuleKey.of(profile1.getKee(), rule1.getKey())); | |||
assertThat(result.getKey()).isEqualTo(ActiveRuleKey.of(profile1, rule1.getKey())); | |||
assertThat(result.getRuleId()).isEqualTo(rule1.getId()); | |||
assertThat(result.getProfileId()).isEqualTo(profile1.getId()); | |||
assertThat(result.getSeverityString()).isEqualTo(BLOCKER); | |||
@@ -221,7 +184,7 @@ public class ActiveRuleDaoTest { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Quality profile is not persisted (missing id)"); | |||
underTest.insert(dbTester.getSession(), createFor(profile1, rule1).setProfileId(null)); | |||
underTest.insert(dbSession, createFor(profile1, rule1).setProfileId(null)); | |||
} | |||
@Test | |||
@@ -229,7 +192,7 @@ public class ActiveRuleDaoTest { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Rule is not persisted"); | |||
underTest.insert(dbTester.getSession(), createFor(profile1, rule1).setRuleId(null)); | |||
underTest.insert(dbSession, createFor(profile1, rule1).setRuleId(null)); | |||
} | |||
@Test | |||
@@ -237,7 +200,7 @@ public class ActiveRuleDaoTest { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("ActiveRule is already persisted"); | |||
underTest.insert(dbTester.getSession(), createFor(profile1, rule1).setId(100)); | |||
underTest.insert(dbSession, createFor(profile1, rule1).setId(100)); | |||
} | |||
@Test | |||
@@ -247,7 +210,7 @@ public class ActiveRuleDaoTest { | |||
.setInheritance(INHERITED) | |||
.setCreatedAt(1000L) | |||
.setUpdatedAt(2000L); | |||
underTest.insert(dbTester.getSession(), activeRule); | |||
underTest.insert(dbSession, activeRule); | |||
dbSession.commit(); | |||
ActiveRuleDto activeRuleUpdated = activeRule | |||
@@ -256,12 +219,12 @@ public class ActiveRuleDaoTest { | |||
// created at should not be updated | |||
.setCreatedAt(3000L) | |||
.setUpdatedAt(4000L); | |||
underTest.update(dbTester.getSession(), activeRuleUpdated); | |||
underTest.update(dbSession, activeRuleUpdated); | |||
dbSession.commit(); | |||
ActiveRuleDto result = underTest.selectOrFailByKey(dbSession, ActiveRuleKey.of(profile1.getKee(), rule1.getKey())); | |||
ActiveRuleDto result = underTest.selectByKey(dbSession, ActiveRuleKey.of(profile1, rule1.getKey())).get(); | |||
assertThat(result.getId()).isEqualTo(activeRule.getId()); | |||
assertThat(result.getKey()).isEqualTo(ActiveRuleKey.of(profile1.getKee(), rule1.getKey())); | |||
assertThat(result.getKey()).isEqualTo(ActiveRuleKey.of(profile1, rule1.getKey())); | |||
assertThat(result.getRuleId()).isEqualTo(rule1.getId()); | |||
assertThat(result.getProfileId()).isEqualTo(profile1.getId()); | |||
assertThat(result.getSeverityString()).isEqualTo(MAJOR); | |||
@@ -275,7 +238,7 @@ public class ActiveRuleDaoTest { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Quality profile is not persisted (missing id)"); | |||
underTest.update(dbTester.getSession(), createFor(profile1, rule1).setId(100).setProfileId(null)); | |||
underTest.update(dbSession, createFor(profile1, rule1).setId(100).setProfileId(null)); | |||
} | |||
@Test | |||
@@ -283,7 +246,7 @@ public class ActiveRuleDaoTest { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Rule is not persisted"); | |||
underTest.update(dbTester.getSession(), createFor(profile1, rule1).setId(100).setRuleId(null)); | |||
underTest.update(dbSession, createFor(profile1, rule1).setId(100).setRuleId(null)); | |||
} | |||
@Test | |||
@@ -291,7 +254,7 @@ public class ActiveRuleDaoTest { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("ActiveRule is not persisted"); | |||
underTest.update(dbTester.getSession(), createFor(profile1, rule1).setId(null)); | |||
underTest.update(dbSession, createFor(profile1, rule1).setId(null)); | |||
} | |||
@Test | |||
@@ -305,33 +268,33 @@ public class ActiveRuleDaoTest { | |||
underTest.delete(dbSession, activeRule.getKey()); | |||
assertThat(underTest.selectByKey(dbSession, ActiveRuleKey.of(profile1.getKee(), rule1.getKey()))).isAbsent(); | |||
assertThat(underTest.selectByKey(dbSession, ActiveRuleKey.of(profile1, rule1.getKey()))).isEmpty(); | |||
} | |||
@Test | |||
public void delete_does_not_fail_when_active_rule_does_not_exist() { | |||
underTest.delete(dbSession, ActiveRuleKey.of(profile1.getKee(), rule1.getKey())); | |||
underTest.delete(dbSession, ActiveRuleKey.of(profile1, rule1.getKey())); | |||
} | |||
@Test | |||
public void deleteByKeys_deletes_rows_from_table() { | |||
public void deleteByRuleProfileUuids_deletes_rows_from_table() { | |||
underTest.insert(dbSession, newRow(profile1, rule1)); | |||
underTest.insert(dbSession, newRow(profile1, rule2)); | |||
underTest.insert(dbSession, newRow(profile2, rule1)); | |||
underTest.deleteByProfileKeys(dbSession, asList(profile1.getKee())); | |||
underTest.deleteByRuleProfileUuids(dbSession, asList(profile1.getRulesProfileUuid())); | |||
assertThat(dbTester.countRowsOfTable(dbSession, "active_rules")).isEqualTo(1); | |||
assertThat(underTest.selectByKey(dbSession, ActiveRuleKey.of(profile2.getKee(), rule1.getKey()))).isPresent(); | |||
assertThat(db.countRowsOfTable(dbSession, "active_rules")).isEqualTo(1); | |||
assertThat(underTest.selectByKey(dbSession, ActiveRuleKey.of(profile2, rule1.getKey()))).isPresent(); | |||
} | |||
@Test | |||
public void deleteByKeys_does_not_fail_when_profile_with_specified_key_does_not_exist() { | |||
public void deleteByRuleProfileUuids_does_not_fail_when_rules_profile_with_specified_key_does_not_exist() { | |||
underTest.insert(dbSession, newRow(profile1, rule1)); | |||
underTest.deleteByProfileKeys(dbSession, asList("does_not_exist")); | |||
underTest.deleteByRuleProfileUuids(dbSession, asList("does_not_exist")); | |||
assertThat(dbTester.countRowsOfTable(dbSession, "active_rules")).isEqualTo(1); | |||
assertThat(db.countRowsOfTable(dbSession, "active_rules")).isEqualTo(1); | |||
} | |||
private static ActiveRuleDto newRow(QProfileDto profile, RuleDefinitionDto rule) { | |||
@@ -341,7 +304,7 @@ public class ActiveRuleDaoTest { | |||
@Test | |||
public void select_params_by_active_rule_id() { | |||
ActiveRuleDto activeRule = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule); | |||
underTest.insert(dbSession, activeRule); | |||
ActiveRuleParamDto activeRuleParam1 = ActiveRuleParamDto.createFor(rule1Param1); | |||
underTest.insertParam(dbSession, activeRule, activeRuleParam1); | |||
ActiveRuleParamDto activeRuleParam2 = ActiveRuleParamDto.createFor(rule1Param2); | |||
@@ -354,12 +317,12 @@ public class ActiveRuleDaoTest { | |||
@Test | |||
public void select_params_by_active_rule_ids() { | |||
ActiveRuleDto activeRule1 = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule1); | |||
underTest.insert(dbSession, activeRule1); | |||
underTest.insertParam(dbSession, activeRule1, ActiveRuleParamDto.createFor(rule1Param1)); | |||
underTest.insertParam(dbSession, activeRule1, ActiveRuleParamDto.createFor(rule1Param2)); | |||
ActiveRuleDto activeRule2 = createFor(profile1, rule2).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule2); | |||
underTest.insert(dbSession, activeRule2); | |||
underTest.insertParam(dbSession, activeRule2, ActiveRuleParamDto.createFor(rule2Param1)); | |||
dbSession.commit(); | |||
@@ -367,100 +330,70 @@ public class ActiveRuleDaoTest { | |||
} | |||
@Test | |||
public void select_param_by_key_and_name() { | |||
ActiveRuleDto activeRule = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule); | |||
ActiveRuleParamDto activeRuleParam1 = ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue1"); | |||
underTest.insertParam(dbSession, activeRule, activeRuleParam1); | |||
underTest.insertParam(dbSession, activeRule, ActiveRuleParamDto.createFor(rule1Param2)); | |||
dbSession.commit(); | |||
assertThat(underTest.selectParamByKeyAndName(activeRule.getKey(), activeRuleParam1.getKey(), dbSession)).isNotNull(); | |||
assertThat(underTest.selectParamByKeyAndName(activeRule.getKey(), "unknown", dbSession)).isNull(); | |||
assertThat(underTest.selectParamByKeyAndName(ActiveRuleKey.of(profile2.getKee(), rule1.getKey()), "unknown", dbSession)).isNull(); | |||
} | |||
@Test | |||
public void select_all_params() { | |||
ActiveRuleDto activeRule1 = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule1); | |||
underTest.insertParam(dbSession, activeRule1, ActiveRuleParamDto.createFor(rule1Param1)); | |||
underTest.insertParam(dbSession, activeRule1, ActiveRuleParamDto.createFor(rule1Param2)); | |||
ActiveRuleDto activeRule2 = createFor(profile1, rule2).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule2); | |||
underTest.insertParam(dbSession, activeRule2, ActiveRuleParamDto.createFor(rule2Param1)); | |||
dbSession.commit(); | |||
assertThat(underTest.selectAllParams(dbSession)).hasSize(3); | |||
} | |||
@Test | |||
public void insert_param() { | |||
ActiveRuleDto activeRule = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule); | |||
ActiveRuleParamDto activeRuleParam1 = ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue1"); | |||
underTest.insertParam(dbSession, activeRule, activeRuleParam1); | |||
dbSession.commit(); | |||
public void insertParam() { | |||
ActiveRuleDto activeRule = createFor(profile1, rule1).setSeverity(Severity.CRITICAL); | |||
underTest.insert(dbSession, activeRule); | |||
ActiveRuleParamDto result = underTest.selectParamByKeyAndName(activeRule.getKey(), activeRuleParam1.getKey(), dbSession); | |||
assertThat(result).isNotNull(); | |||
ActiveRuleParamDto activeRuleParam = ActiveRuleParamDto.createFor(rule1Param1).setValue("foo"); | |||
underTest.insertParam(dbSession, activeRule, activeRuleParam); | |||
assertThat(result.getId()).isEqualTo(activeRuleParam1.getId()); | |||
assertThat(result.getKey()).isEqualTo(activeRuleParam1.getKey()); | |||
assertThat(result.getActiveRuleId()).isEqualTo(activeRule.getId()); | |||
assertThat(result.getRulesParameterId()).isEqualTo(rule1Param1.getId()); | |||
assertThat(result.getValue()).isEqualTo("activeValue1"); | |||
List<ActiveRuleParamDto> reloaded = underTest.selectParamsByActiveRuleId(dbSession, activeRule.getId()); | |||
assertThat(reloaded).hasSize(1); | |||
assertThat(reloaded.get(0)) | |||
.matches(p -> Objects.equals(p.getId(), activeRuleParam.getId())) | |||
.matches(p -> p.getKey().equals(activeRuleParam.getKey())) | |||
.matches(p -> p.getActiveRuleId().equals(activeRule.getId())) | |||
.matches(p -> p.getRulesParameterId().equals(rule1Param1.getId())) | |||
.matches(p -> p.getValue().equals("foo")); | |||
} | |||
@Test | |||
public void fail_to_insert_param_when_active_rule_id_is_null() { | |||
public void insertParam_fails_when_active_rule_id_is_null() { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("ActiveRule is not persisted"); | |||
underTest.insertParam(dbTester.getSession(), | |||
underTest.insertParam(dbSession, | |||
createFor(profile1, rule1).setId(null), | |||
ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue1")); | |||
} | |||
@Test | |||
public void fail_to_insert_param_when_active_rule_param_id_is_null() { | |||
public void insertParam_fails_when_active_rule_param_id_is_null() { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("ActiveRuleParam is already persisted"); | |||
underTest.insertParam(dbTester.getSession(), | |||
underTest.insertParam(dbSession, | |||
createFor(profile1, rule1).setId(100), | |||
ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue1").setId(100)); | |||
} | |||
@Test | |||
public void fail_to_insert_param_when_id_is_not_null() { | |||
public void insertParam_fails_when_id_is_not_null() { | |||
thrown.expect(NullPointerException.class); | |||
thrown.expectMessage("Rule param is not persisted"); | |||
underTest.insertParam(dbTester.getSession(), | |||
underTest.insertParam(dbSession, | |||
createFor(profile1, rule1).setId(100), | |||
ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue1").setRulesParameterId(null)); | |||
} | |||
@Test | |||
public void update_param() { | |||
ActiveRuleDto activeRule = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule); | |||
ActiveRuleParamDto activeRuleParam1 = ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue"); | |||
underTest.insertParam(dbSession, activeRule, activeRuleParam1); | |||
dbSession.commit(); | |||
public void updateParam() { | |||
ActiveRuleDto activeRule = createFor(profile1, rule1).setSeverity(Severity.CRITICAL); | |||
underTest.insert(dbSession, activeRule); | |||
ActiveRuleParamDto activeRuleParam = ActiveRuleParamDto.createFor(rule1Param1).setValue("foo"); | |||
underTest.insertParam(dbSession, activeRule, activeRuleParam); | |||
underTest.updateParam(dbSession, activeRule, activeRuleParam1.setValue("updatedActiveValue")); | |||
dbSession.commit(); | |||
underTest.updateParam(dbSession, activeRuleParam.setValue("bar")); | |||
ActiveRuleParamDto result = underTest.selectParamByKeyAndName(activeRule.getKey(), activeRuleParam1.getKey(), dbSession); | |||
assertThat(result.getId()).isEqualTo(activeRuleParam1.getId()); | |||
assertThat(result.getKey()).isEqualTo(activeRuleParam1.getKey()); | |||
assertThat(result.getActiveRuleId()).isEqualTo(activeRule.getId()); | |||
assertThat(result.getRulesParameterId()).isEqualTo(rule1Param1.getId()); | |||
assertThat(result.getValue()).isEqualTo("updatedActiveValue"); | |||
List<ActiveRuleParamDto> reloaded = underTest.selectParamsByActiveRuleId(dbSession, activeRule.getId()); | |||
assertThat(reloaded).hasSize(1); | |||
assertThat(reloaded.get(0)) | |||
.matches(p -> Objects.equals(p.getId(), activeRuleParam.getId())) | |||
.matches(p -> p.getKey().equals(activeRuleParam.getKey())) | |||
.matches(p -> p.getActiveRuleId().equals(activeRule.getId())) | |||
.matches(p -> p.getRulesParameterId().equals(rule1Param1.getId())) | |||
.matches(p -> p.getValue().equals("bar")); | |||
} | |||
@Test | |||
@@ -470,13 +403,13 @@ public class ActiveRuleDaoTest { | |||
ActiveRuleParamDto param = ActiveRuleParamDto.createFor(rule1Param1).setValue("foo"); | |||
underTest.insertParam(dbSession, activeRule, param); | |||
underTest.deleteParam(dbSession, activeRule, param); | |||
underTest.deleteParam(dbSession, param); | |||
assertThat(underTest.selectParamByKeyAndName(activeRule.getKey(), param.getKey(), dbSession)).isNull(); | |||
assertThat(underTest.selectParamsByActiveRuleId(dbSession, activeRule.getId())).hasSize(0); | |||
} | |||
@Test | |||
public void deleteParametersByProfileKeys_deletes_rows_by_profile_keys() { | |||
public void deleteParametersByRuleProfileUuids_deletes_rows_by_rule_profile_uuids() { | |||
ActiveRuleDto activeRuleInProfile1 = newRow(profile1, rule1); | |||
underTest.insert(dbSession, activeRuleInProfile1); | |||
ActiveRuleParamDto param1 = ActiveRuleParamDto.createFor(rule1Param1).setValue("foo"); | |||
@@ -486,102 +419,54 @@ public class ActiveRuleDaoTest { | |||
ActiveRuleParamDto param2 = ActiveRuleParamDto.createFor(rule1Param1).setValue("bar"); | |||
underTest.insertParam(dbSession, activeRuleInProfile2, param2); | |||
underTest.deleteParametersByProfileKeys(dbSession, asList(profile1.getKee(), "does_not_exist")); | |||
underTest.deleteParametersByRuleProfileUuids(dbSession, asList(profile1.getRulesProfileUuid(), "does_not_exist")); | |||
List<ActiveRuleParamDto> params = underTest.selectAllParams(dbSession); | |||
assertThat(params).hasSize(1); | |||
assertThat(params.get(0).getActiveRuleId()).isEqualTo(activeRuleInProfile2.getId()); | |||
assertThat(underTest.selectParamsByActiveRuleId(dbSession, activeRuleInProfile1.getId())).isEmpty(); | |||
assertThat(underTest.selectParamsByActiveRuleId(dbSession, activeRuleInProfile2.getId())) | |||
.extracting(ActiveRuleParamDto::getKey, ActiveRuleParamDto::getValue) | |||
.containsExactly(tuple(rule1Param1.getName(), "bar")); | |||
} | |||
@Test | |||
public void deleteParametersByProfileKeys_does_nothing_if_keys_are_empty() { | |||
public void deleteParametersByRuleProfileUuids_does_nothing_if_keys_are_empty() { | |||
ActiveRuleDto activeRuleInProfile1 = newRow(profile1, rule1); | |||
underTest.insert(dbSession, activeRuleInProfile1); | |||
ActiveRuleParamDto param1 = ActiveRuleParamDto.createFor(rule1Param1).setValue("foo"); | |||
underTest.insertParam(dbSession, activeRuleInProfile1, param1); | |||
underTest.deleteParametersByProfileKeys(dbSession, emptyList()); | |||
List<ActiveRuleParamDto> params = underTest.selectAllParams(dbSession); | |||
assertThat(params).hasSize(1); | |||
assertThat(params.get(0).getActiveRuleId()).isEqualTo(activeRuleInProfile1.getId()); | |||
} | |||
@Test | |||
public void deleteParamByKeyAndName_deletes_rows_by_key_and_name() { | |||
ActiveRuleDto activeRule = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule); | |||
ActiveRuleParamDto activeRuleParam1 = ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue1"); | |||
underTest.insertParam(dbSession, activeRule, activeRuleParam1); | |||
dbSession.commit(); | |||
underTest.deleteParamByKeyAndName(dbSession, activeRule.getKey(), rule1Param1.getName()); | |||
dbSession.commit(); | |||
underTest.deleteParametersByRuleProfileUuids(dbSession, emptyList()); | |||
assertThat(underTest.selectParamByKeyAndName(activeRule.getKey(), activeRuleParam1.getKey(), dbSession)).isNull(); | |||
assertThat(underTest.selectParamsByActiveRuleId(dbSession, activeRuleInProfile1.getId())) | |||
.hasSize(1); | |||
} | |||
@Test | |||
public void does_not_fail_to_delete_param_by_key_and_name_when_active_rule_does_not_exist() { | |||
underTest.deleteParamByKeyAndName(dbSession, ActiveRuleKey.of(profile1.getKee(), rule1.getKey()), rule1Param1.getName()); | |||
} | |||
@Test | |||
public void does_not_fail_to_delete_param_by_key_and_name_when_active_rule_param_does_not_exist() { | |||
ActiveRuleDto activeRule = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule); | |||
ActiveRuleParamDto activeRuleParam1 = ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue1"); | |||
underTest.insertParam(dbSession, activeRule, activeRuleParam1); | |||
dbSession.commit(); | |||
underTest.deleteParamByKeyAndName(dbSession, activeRule.getKey(), "unknown"); | |||
} | |||
@Test | |||
public void delete_param_by_rule_param() { | |||
public void deleteParamsByRuleParamOfAllOrganizations() { | |||
ActiveRuleDto activeRule1 = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule1); | |||
ActiveRuleParamDto activeRuleParam1 = ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue1"); | |||
underTest.insert(dbSession, activeRule1); | |||
ActiveRuleParamDto activeRuleParam1 = ActiveRuleParamDto.createFor(rule1Param1).setValue("foo"); | |||
underTest.insertParam(dbSession, activeRule1, activeRuleParam1); | |||
ActiveRuleDto activeRule2 = createFor(profile2, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule2); | |||
ActiveRuleParamDto activeRuleParam2 = ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue2"); | |||
underTest.insert(dbSession, activeRule2); | |||
ActiveRuleParamDto activeRuleParam2 = ActiveRuleParamDto.createFor(rule1Param1).setValue("bar"); | |||
underTest.insertParam(dbSession, activeRule2, activeRuleParam2); | |||
dbSession.commit(); | |||
List<Integer> activeRuleIds = asList(activeRule1.getId(), activeRule2.getId()); | |||
assertThat(underTest.selectParamsByActiveRuleIds(dbSession, activeRuleIds)).hasSize(2); | |||
underTest.deleteParamsByRuleParamOfAllOrganizations(dbSession, rule1.getId(), rule1Param1.getName()); | |||
dbSession.commit(); | |||
assertThat(underTest.selectParamByKeyAndName(activeRule1.getKey(), activeRuleParam1.getKey(), dbSession)).isNull(); | |||
assertThat(underTest.selectParamByKeyAndName(activeRule2.getKey(), activeRuleParam2.getKey(), dbSession)).isNull(); | |||
} | |||
@Test | |||
public void does_not_fail_to_delete_param_by_rule_param_when_active_param_name_not_found() { | |||
ActiveRuleDto activeRule1 = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule1); | |||
ActiveRuleParamDto activeRuleParam1 = ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue1"); | |||
underTest.insertParam(dbSession, activeRule1, activeRuleParam1); | |||
ActiveRuleDto activeRule2 = createFor(profile2, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule2); | |||
ActiveRuleParamDto activeRuleParam2 = ActiveRuleParamDto.createFor(rule1Param1).setValue("activeValue2"); | |||
underTest.insertParam(dbSession, activeRule2, activeRuleParam2); | |||
dbSession.commit(); | |||
underTest.deleteParamsByRuleParamOfAllOrganizations(dbSession, rule1Param1); | |||
underTest.deleteParamsByRuleParamOfAllOrganizations(dbSession, rule1.getId(), "unknown"); | |||
assertThat(underTest.selectParamsByActiveRuleIds(dbSession, activeRuleIds)).isEmpty(); | |||
} | |||
@Test | |||
public void test_countActiveRulesByProfileKey_for_a_specified_organization() { | |||
dbTester.qualityProfiles().activateRule(profile1, rule1); | |||
dbTester.qualityProfiles().activateRule(profile1, rule2); | |||
dbTester.qualityProfiles().activateRule(profile2, rule1); | |||
db.qualityProfiles().activateRule(profile1, rule1); | |||
db.qualityProfiles().activateRule(profile1, rule2); | |||
db.qualityProfiles().activateRule(profile2, rule1); | |||
Map<String, Long> counts = underTest.countActiveRulesByProfileKey(dbSession, organization); | |||
Map<String, Long> counts = underTest.countActiveRulesByProfileUuid(dbSession, organization); | |||
assertThat(counts).containsOnly( | |||
entry(profile1.getKee(), 2L), | |||
@@ -590,86 +475,86 @@ public class ActiveRuleDaoTest { | |||
@Test | |||
public void countActiveRulesByProfileKey_returns_empty_map_if_organization_does_not_exist() { | |||
Map<String, Long> counts = underTest.countActiveRulesByProfileKey(dbSession, OrganizationTesting.newOrganizationDto()); | |||
Map<String, Long> counts = underTest.countActiveRulesByProfileUuid(dbSession, OrganizationTesting.newOrganizationDto()); | |||
assertThat(counts).isEmpty(); | |||
} | |||
@Test | |||
public void countActiveRulesByProfileKey_returns_empty_map_if_profile_does_not_have_active_rules() { | |||
Map<String, Long> counts = underTest.countActiveRulesByProfileKey(dbSession, organization); | |||
Map<String, Long> counts = underTest.countActiveRulesByProfileUuid(dbSession, organization); | |||
assertThat(counts).isEmpty(); | |||
} | |||
@Test | |||
public void countActiveRulesByProfileKey_ignores_removed_rules() { | |||
dbTester.qualityProfiles().activateRule(profile1, rule1); | |||
dbTester.qualityProfiles().activateRule(profile1, removedRule); | |||
db.qualityProfiles().activateRule(profile1, rule1); | |||
db.qualityProfiles().activateRule(profile1, removedRule); | |||
Map<String, Long> counts = underTest.countActiveRulesByProfileKey(dbSession, organization); | |||
Map<String, Long> counts = underTest.countActiveRulesByProfileUuid(dbSession, organization); | |||
assertThat(counts).containsExactly(entry(profile1.getKee(), 1L)); | |||
} | |||
@Test | |||
public void test_countActiveRulesForRuleStatusByProfileKey_for_a_specified_organization() { | |||
RuleDefinitionDto betaRule1 = dbTester.rules().insertRule(RuleTesting.newRuleDto().setStatus(RuleStatus.BETA)).getDefinition(); | |||
RuleDefinitionDto betaRule2 = dbTester.rules().insertRule(RuleTesting.newRuleDto().setStatus(RuleStatus.BETA)).getDefinition(); | |||
dbTester.qualityProfiles().activateRule(profile1, rule1); | |||
dbTester.qualityProfiles().activateRule(profile2, betaRule1); | |||
dbTester.qualityProfiles().activateRule(profile2, betaRule2); | |||
RuleDefinitionDto betaRule1 = db.rules().insertRule(RuleTesting.newRuleDto().setStatus(RuleStatus.BETA)).getDefinition(); | |||
RuleDefinitionDto betaRule2 = db.rules().insertRule(RuleTesting.newRuleDto().setStatus(RuleStatus.BETA)).getDefinition(); | |||
db.qualityProfiles().activateRule(profile1, rule1); | |||
db.qualityProfiles().activateRule(profile2, betaRule1); | |||
db.qualityProfiles().activateRule(profile2, betaRule2); | |||
Map<String, Long> counts = underTest.countActiveRulesForRuleStatusByProfileKey(dbSession, organization, RuleStatus.BETA); | |||
Map<String, Long> counts = underTest.countActiveRulesForRuleStatusByProfileUuid(dbSession, organization, RuleStatus.BETA); | |||
assertThat(counts).containsOnly(entry(profile2.getKee(), 2L)); | |||
} | |||
@Test | |||
public void countActiveRulesForRuleStatusByProfileKey_returns_empty_map_if_organization_does_not_exist() { | |||
Map<String, Long> counts = underTest.countActiveRulesForRuleStatusByProfileKey(dbSession, OrganizationTesting.newOrganizationDto(), RuleStatus.READY); | |||
Map<String, Long> counts = underTest.countActiveRulesForRuleStatusByProfileUuid(dbSession, OrganizationTesting.newOrganizationDto(), RuleStatus.READY); | |||
assertThat(counts).isEmpty(); | |||
} | |||
@Test | |||
public void countActiveRulesForRuleStatusByProfileKey_returns_empty_map_if_profile_does_not_have_rules_with_specified_status() { | |||
Map<String, Long> counts = underTest.countActiveRulesForRuleStatusByProfileKey(dbSession, organization, RuleStatus.DEPRECATED); | |||
Map<String, Long> counts = underTest.countActiveRulesForRuleStatusByProfileUuid(dbSession, organization, RuleStatus.DEPRECATED); | |||
assertThat(counts).isEmpty(); | |||
} | |||
@Test | |||
public void test_countActiveRulesForInheritanceByProfileKey_for_a_specified_organization() { | |||
dbTester.qualityProfiles().activateRule(profile1, rule1); | |||
dbTester.qualityProfiles().activateRule(profile2, rule1, ar -> ar.setInheritance(ActiveRuleDto.OVERRIDES)); | |||
dbTester.qualityProfiles().activateRule(profile2, rule2, ar -> ar.setInheritance(ActiveRuleDto.INHERITED)); | |||
db.qualityProfiles().activateRule(profile1, rule1); | |||
db.qualityProfiles().activateRule(profile2, rule1, ar -> ar.setInheritance(ActiveRuleDto.OVERRIDES)); | |||
db.qualityProfiles().activateRule(profile2, rule2, ar -> ar.setInheritance(ActiveRuleDto.INHERITED)); | |||
Map<String, Long> counts = underTest.countActiveRulesForInheritanceByProfileKey(dbSession, organization, ActiveRuleDto.OVERRIDES); | |||
Map<String, Long> counts = underTest.countActiveRulesForInheritanceByProfileUuid(dbSession, organization, ActiveRuleDto.OVERRIDES); | |||
assertThat(counts).containsOnly(entry(profile2.getKee(), 1L)); | |||
} | |||
@Test | |||
public void countActiveRulesForInheritanceByProfileKey_returns_empty_map_if_organization_does_not_exist() { | |||
Map<String, Long> counts = underTest.countActiveRulesForInheritanceByProfileKey(dbSession, OrganizationTesting.newOrganizationDto(), ActiveRuleDto.OVERRIDES); | |||
Map<String, Long> counts = underTest.countActiveRulesForInheritanceByProfileUuid(dbSession, OrganizationTesting.newOrganizationDto(), ActiveRuleDto.OVERRIDES); | |||
assertThat(counts).isEmpty(); | |||
} | |||
@Test | |||
public void countActiveRulesForInheritanceByProfileKey_returns_empty_map_if_profile_does_not_have_rules_with_specified_status() { | |||
Map<String, Long> counts = underTest.countActiveRulesForInheritanceByProfileKey(dbSession, organization, ActiveRuleDto.OVERRIDES); | |||
Map<String, Long> counts = underTest.countActiveRulesForInheritanceByProfileUuid(dbSession, organization, ActiveRuleDto.OVERRIDES); | |||
assertThat(counts).isEmpty(); | |||
} | |||
@Test | |||
public void countActiveRulesForInheritanceByProfileKey_ignores_removed_rules() { | |||
dbTester.qualityProfiles().activateRule(profile1, rule1, ar -> ar.setInheritance(ActiveRuleDto.OVERRIDES)); | |||
dbTester.qualityProfiles().activateRule(profile1, removedRule, ar -> ar.setInheritance(ActiveRuleDto.OVERRIDES)); | |||
db.qualityProfiles().activateRule(profile1, rule1, ar -> ar.setInheritance(ActiveRuleDto.OVERRIDES)); | |||
db.qualityProfiles().activateRule(profile1, removedRule, ar -> ar.setInheritance(ActiveRuleDto.OVERRIDES)); | |||
Map<String, Long> counts = underTest.countActiveRulesForInheritanceByProfileKey(dbSession, organization, ActiveRuleDto.OVERRIDES); | |||
Map<String, Long> counts = underTest.countActiveRulesForInheritanceByProfileUuid(dbSession, organization, ActiveRuleDto.OVERRIDES); | |||
assertThat(counts).containsOnly(entry(profile1.getKee(), 1L)); | |||
} |
@@ -24,53 +24,36 @@ import org.sonar.api.rule.RuleKey; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.junit.Assert.fail; | |||
import static org.sonar.db.qualityprofile.QualityProfileTesting.newQualityProfileDto; | |||
public class ActiveRuleKeyTest { | |||
@Test | |||
public void of() { | |||
RuleKey ruleKey = RuleKey.of("xoo", "R1"); | |||
ActiveRuleKey key = ActiveRuleKey.of("P1", ruleKey); | |||
assertThat(key.qProfile()).isEqualTo("P1"); | |||
assertThat(key.ruleKey()).isSameAs(ruleKey); | |||
assertThat(key.toString()).isEqualTo("P1:xoo:R1"); | |||
QProfileDto profile = newQualityProfileDto(); | |||
ActiveRuleKey key = ActiveRuleKey.of(profile, ruleKey); | |||
assertThat(key.getRuleProfileUuid()).isEqualTo(profile.getRulesProfileUuid()); | |||
assertThat(key.getRuleKey()).isSameAs(ruleKey); | |||
assertThat(key.toString()).isEqualTo(profile.getRulesProfileUuid() + ":xoo:R1"); | |||
} | |||
@Test | |||
public void rule_key_can_contain_colons() { | |||
RuleKey ruleKey = RuleKey.of("squid", "Key:With:Some::Colons"); | |||
ActiveRuleKey key = ActiveRuleKey.of("P1", ruleKey); | |||
assertThat(key.qProfile()).isEqualTo("P1"); | |||
assertThat(key.ruleKey()).isSameAs(ruleKey); | |||
assertThat(key.toString()).isEqualTo("P1:squid:Key:With:Some::Colons"); | |||
} | |||
@Test | |||
public void profile_must_not_be_null() { | |||
try { | |||
ActiveRuleKey.of(null, RuleKey.of("xoo", "R1")); | |||
fail(); | |||
} catch (NullPointerException e) { | |||
assertThat(e).hasMessage("QProfile is missing"); | |||
} | |||
} | |||
@Test | |||
public void rule_key_must_not_be_null() { | |||
try { | |||
ActiveRuleKey.of("P1", null); | |||
fail(); | |||
} catch (NullPointerException e) { | |||
assertThat(e).hasMessage("RuleKey is missing"); | |||
} | |||
QProfileDto profile = newQualityProfileDto(); | |||
ActiveRuleKey key = ActiveRuleKey.of(profile, ruleKey); | |||
assertThat(key.getRuleProfileUuid()).isEqualTo(profile.getRulesProfileUuid()); | |||
assertThat(key.getRuleKey()).isSameAs(ruleKey); | |||
assertThat(key.toString()).isEqualTo(profile.getRulesProfileUuid() + ":squid:Key:With:Some::Colons"); | |||
} | |||
@Test | |||
public void parse() { | |||
ActiveRuleKey key = ActiveRuleKey.parse("P1:xoo:R1"); | |||
assertThat(key.qProfile()).isEqualTo("P1"); | |||
assertThat(key.ruleKey().repository()).isEqualTo("xoo"); | |||
assertThat(key.ruleKey().rule()).isEqualTo("R1"); | |||
assertThat(key.getRuleProfileUuid()).isEqualTo("P1"); | |||
assertThat(key.getRuleKey().repository()).isEqualTo("xoo"); | |||
assertThat(key.getRuleKey().rule()).isEqualTo("R1"); | |||
} | |||
@Test |
@@ -26,66 +26,53 @@ import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.utils.internal.AlwaysIncreasingSystem2; | |||
import org.sonar.core.util.SequenceUuidFactory; | |||
import org.sonar.core.util.UuidFactory; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class QProfileChangeDaoTest { | |||
private static final long A_DATE = 1_500_000_000_000L; | |||
private System2 system2 = mock(System2.class); | |||
private System2 system2 = new AlwaysIncreasingSystem2(); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public DbTester dbTester = DbTester.create(system2); | |||
public DbTester db = DbTester.create(system2); | |||
private DbSession dbSession = dbTester.getSession(); | |||
private UuidFactory uuidFactory = mock(UuidFactory.class); | |||
private DbSession dbSession = db.getSession(); | |||
private UuidFactory uuidFactory = new SequenceUuidFactory(); | |||
private QProfileChangeDao underTest = new QProfileChangeDao(system2, uuidFactory); | |||
@Test | |||
public void test_insert_without_null_fields() { | |||
when(system2.now()).thenReturn(A_DATE); | |||
when(uuidFactory.create()).thenReturn("C1"); | |||
String profileKey = "P1"; | |||
String login = "marcel"; | |||
String type = "ACTIVATED"; | |||
String data = "some_data"; | |||
insertChange(profileKey, type, login, data); | |||
public void insert() { | |||
QProfileChangeDto dto = insertChange("P1", "ACTIVATED", "marcel", "some_data"); | |||
Map<String, Object> row = selectChangeByKey("C1"); | |||
assertThat(row.get("qprofileKey")).isEqualTo(profileKey); | |||
assertThat(row.get("createdAt")).isEqualTo(A_DATE); | |||
assertThat(row.get("login")).isEqualTo(login); | |||
assertThat(row.get("changeType")).isEqualTo(type); | |||
assertThat(row.get("changeData")).isEqualTo(data); | |||
verifyInserted(dto); | |||
} | |||
/** | |||
* user_login and data can be null | |||
*/ | |||
@Test | |||
public void test_insert_with_nullable_fields() { | |||
when(system2.now()).thenReturn(A_DATE); | |||
when(uuidFactory.create()).thenReturn("C1"); | |||
public void test_insert_with_null_fields() { | |||
QProfileChangeDto dto = insertChange("P1", "ACTIVATED", null, null); | |||
insertChange("P1", "ACTIVATED", null, null); | |||
verifyInserted(dto); | |||
} | |||
Map<String, Object> row = selectChangeByKey("C1"); | |||
assertThat(row.get("qprofileKey")).isEqualTo("P1"); | |||
assertThat(row.get("createdAt")).isEqualTo(A_DATE); | |||
assertThat(row.get("changeType")).isEqualTo("ACTIVATED"); | |||
assertThat(row.get("login")).isNull(); | |||
assertThat(row.get("changeData")).isNull(); | |||
private void verifyInserted(QProfileChangeDto dto) { | |||
QProfileChangeDto reloaded = selectChangeByUuid(dto.getUuid()); | |||
assertThat(reloaded.getUuid()).isEqualTo(dto.getUuid()); | |||
assertThat(reloaded.getChangeType()).isEqualTo(dto.getChangeType()); | |||
assertThat(reloaded.getData()).isEqualTo(dto.getData()); | |||
assertThat(reloaded.getLogin()).isEqualTo(dto.getLogin()); | |||
assertThat(reloaded.getRulesProfileUuid()).isEqualTo(dto.getRulesProfileUuid()); | |||
assertThat(reloaded.getCreatedAt()).isPositive(); | |||
} | |||
@Test | |||
@@ -97,151 +84,169 @@ public class QProfileChangeDaoTest { | |||
} | |||
@Test | |||
public void selectByQuery_returns_empty_list_if_no_profile_changes() { | |||
public void selectByQuery_returns_empty_list_if_profile_does_not_exist() { | |||
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, new QProfileChangeQuery("P1")); | |||
assertThat(changes).isEmpty(); | |||
} | |||
@Test | |||
public void selectByQuery_returns_changes_ordered_by_descending_date() { | |||
when(system2.now()).thenReturn(A_DATE, A_DATE + 1, A_DATE + 2); | |||
when(uuidFactory.create()).thenReturn("C1", "C2", "C3"); | |||
QProfileDto profile1 = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
QProfileDto profile2 = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
// profile P1 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C1 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C2 | |||
// profile P2: C3 | |||
insertChange("P2", "ACTIVATED", null, null);// key: C3 | |||
QProfileChangeDto change1OnP1 = insertChange(profile1, "ACTIVATED", null, null); | |||
QProfileChangeDto change2OnP1 = insertChange(profile1, "ACTIVATED", null, null); | |||
QProfileChangeDto changeOnP2 = insertChange(profile2, "ACTIVATED", null, null); | |||
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, new QProfileChangeQuery("P1")); | |||
assertThat(changes).extracting(QProfileChangeDto::getKey).containsExactly("C2", "C1"); | |||
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, new QProfileChangeQuery(profile1.getKee())); | |||
assertThat(changes) | |||
.extracting(QProfileChangeDto::getUuid) | |||
.containsExactly(change2OnP1.getUuid(), change1OnP1.getUuid()); | |||
} | |||
@Test | |||
public void selectByQuery_supports_pagination_of_changes() { | |||
when(system2.now()).thenReturn(A_DATE, A_DATE + 10, A_DATE + 20, A_DATE + 30); | |||
when(uuidFactory.create()).thenReturn("C1", "C2", "C3", "C4"); | |||
insertChange("P1", "ACTIVATED", null, null);// key: C1 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C2 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C3 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C4 | |||
QProfileChangeQuery query = new QProfileChangeQuery("P1"); | |||
QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
QProfileChangeDto change1 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeDto change2 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeDto change3 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeDto change4 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeQuery query = new QProfileChangeQuery(profile.getKee()); | |||
query.setOffset(2); | |||
query.setLimit(1); | |||
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, query); | |||
assertThat(changes).extracting(QProfileChangeDto::getKey).containsExactly("C2"); | |||
assertThat(changes) | |||
.extracting(QProfileChangeDto::getUuid) | |||
.containsExactly(change2.getUuid()); | |||
} | |||
@Test | |||
public void selectByQuery_returns_changes_after_given_date() { | |||
when(system2.now()).thenReturn(A_DATE, A_DATE + 10, A_DATE + 20); | |||
when(uuidFactory.create()).thenReturn("C1", "C2", "C3", "C4"); | |||
insertChange("P1", "ACTIVATED", null, null);// key: C1 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C2 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C3 | |||
QProfileChangeQuery query = new QProfileChangeQuery("P1"); | |||
query.setFromIncluded(A_DATE + 10); | |||
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, query); | |||
assertThat(changes).extracting(QProfileChangeDto::getKey).containsExactly("C3", "C2"); | |||
QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
QProfileChangeDto change1 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeDto change2 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeDto change3 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeQuery query = new QProfileChangeQuery(profile.getKee()); | |||
query.setFromIncluded(change1.getCreatedAt() + 1); | |||
assertThat(underTest.selectByQuery(dbSession, query)) | |||
.extracting(QProfileChangeDto::getUuid) | |||
.containsExactly(change3.getUuid(), change2.getUuid()); | |||
} | |||
@Test | |||
public void selectByQuery_returns_changes_before_given_date() { | |||
when(system2.now()).thenReturn(A_DATE, A_DATE + 10, A_DATE + 20); | |||
when(uuidFactory.create()).thenReturn("C1", "C2", "C3", "C4"); | |||
insertChange("P1", "ACTIVATED", null, null);// key: C1 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C2 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C3 | |||
QProfileChangeQuery query = new QProfileChangeQuery("P1"); | |||
query.setToExcluded(A_DATE + 12); | |||
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, query); | |||
assertThat(changes).extracting(QProfileChangeDto::getKey).containsExactly("C2", "C1"); | |||
QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
QProfileChangeDto change1 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeDto change2 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeDto change3 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeQuery query = new QProfileChangeQuery(profile.getKee()); | |||
query.setToExcluded(change2.getCreatedAt() + 1); | |||
assertThat(underTest.selectByQuery(dbSession, query)) | |||
.extracting(QProfileChangeDto::getUuid) | |||
.containsExactly(change2.getUuid(), change1.getUuid()); | |||
} | |||
@Test | |||
public void selectByQuery_returns_changes_in_a_range_of_dates() { | |||
when(system2.now()).thenReturn(A_DATE, A_DATE + 10, A_DATE + 20, A_DATE + 30); | |||
when(uuidFactory.create()).thenReturn("C1", "C2", "C3", "C4"); | |||
insertChange("P1", "ACTIVATED", null, null);// key: C1 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C2 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C3 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C4 | |||
QProfileChangeQuery query = new QProfileChangeQuery("P1"); | |||
query.setFromIncluded(A_DATE + 8); | |||
query.setToExcluded(A_DATE + 22); | |||
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, query); | |||
assertThat(changes).extracting(QProfileChangeDto::getKey).containsExactly("C3", "C2"); | |||
QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
QProfileChangeDto change1 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeDto change2 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeDto change3 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeDto change4 = insertChange(profile, "ACTIVATED", null, null); | |||
QProfileChangeQuery query = new QProfileChangeQuery(profile.getKee()); | |||
query.setFromIncluded(change1.getCreatedAt() + 1); | |||
query.setToExcluded(change4.getCreatedAt()); | |||
assertThat(underTest.selectByQuery(dbSession, query)) | |||
.extracting(QProfileChangeDto::getUuid) | |||
.containsExactly(change3.getUuid(), change2.getUuid()); | |||
} | |||
@Test | |||
public void selectByQuery_mapping() { | |||
when(system2.now()).thenReturn(A_DATE); | |||
when(uuidFactory.create()).thenReturn("C1"); | |||
insertChange("P1", "ACTIVATED", "Oscar", "data"); | |||
public void test_selectByQuery_mapping() { | |||
QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
QProfileChangeDto inserted = insertChange(profile, "ACTIVATED", "theLogin", "theData"); | |||
List<QProfileChangeDto> result = underTest.selectByQuery(dbSession, new QProfileChangeQuery("P1")); | |||
List<QProfileChangeDto> result = underTest.selectByQuery(dbSession, new QProfileChangeQuery(profile.getKee())); | |||
assertThat(result).hasSize(1); | |||
QProfileChangeDto change = result.get(0); | |||
assertThat(change.getProfileKey()).isEqualTo("P1"); | |||
assertThat(change.getLogin()).isEqualTo("Oscar"); | |||
assertThat(change.getData()).isEqualTo("data"); | |||
assertThat(change.getChangeType()).isEqualTo("ACTIVATED"); | |||
assertThat(change.getKey()).isEqualTo("C1"); | |||
assertThat(change.getCreatedAt()).isEqualTo(A_DATE); | |||
assertThat(change.getRulesProfileUuid()).isEqualTo(inserted.getRulesProfileUuid()); | |||
assertThat(change.getLogin()).isEqualTo(inserted.getLogin()); | |||
assertThat(change.getData()).isEqualTo(inserted.getData()); | |||
assertThat(change.getChangeType()).isEqualTo(inserted.getChangeType()); | |||
assertThat(change.getUuid()).isEqualTo(inserted.getUuid()); | |||
assertThat(change.getCreatedAt()).isEqualTo(inserted.getCreatedAt()); | |||
} | |||
@Test | |||
public void test_countForProfileKey() { | |||
when(system2.now()).thenReturn(A_DATE, A_DATE + 10); | |||
when(uuidFactory.create()).thenReturn("C1", "C2"); | |||
insertChange("P1", "ACTIVATED", null, null);// key: C1 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C2 | |||
assertThat(underTest.countForProfileUuid(dbSession, "P1")).isEqualTo(2); | |||
assertThat(underTest.countForProfileUuid(dbSession, "P2")).isEqualTo(0); | |||
public void countForQProfileUuid() { | |||
QProfileDto profile1 = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
QProfileDto profile2 = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
insertChange(profile1, "ACTIVATED", null, null); | |||
insertChange(profile1, "ACTIVATED", null, null); | |||
insertChange(profile2, "ACTIVATED", null, null); | |||
assertThat(underTest.countForQProfileUuid(dbSession, profile1.getKee())).isEqualTo(2); | |||
assertThat(underTest.countForQProfileUuid(dbSession, profile2.getKee())).isEqualTo(1); | |||
assertThat(underTest.countForQProfileUuid(dbSession, "does_not_exist")).isEqualTo(0); | |||
} | |||
@Test | |||
public void deleteByProfileKeys_deletes_rows_with_specified_keys() { | |||
when(uuidFactory.create()).thenReturn("C1", "C2", "C3"); | |||
insertChange("P1", "ACTIVATED", null, null);// key: C1 | |||
insertChange("P1", "ACTIVATED", null, null);// key: C2 | |||
insertChange("P2", "ACTIVATED", null, null);// key: C3 | |||
public void deleteByRulesProfileUuids() { | |||
QProfileDto profile1 = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
QProfileDto profile2 = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
insertChange(profile1, "ACTIVATED", null, null); | |||
insertChange(profile1, "ACTIVATED", null, null); | |||
insertChange(profile2, "ACTIVATED", null, null); | |||
underTest.deleteByProfileKeys(dbSession, asList("P1")); | |||
underTest.deleteByRulesProfileUuids(dbSession, asList(profile1.getRulesProfileUuid())); | |||
assertThat(underTest.countForProfileUuid(dbSession, "P1")).isEqualTo(0); | |||
assertThat(underTest.countForProfileUuid(dbSession, "P2")).isEqualTo(1); | |||
assertThat(underTest.countForQProfileUuid(dbSession, profile1.getKee())).isEqualTo(0); | |||
assertThat(underTest.countForQProfileUuid(dbSession, profile2.getKee())).isEqualTo(1); | |||
} | |||
@Test | |||
public void deleteByProfileKeys_does_nothing_if_row_with_specified_key_does_not_exist() { | |||
when(uuidFactory.create()).thenReturn("C1"); | |||
insertChange("P1", "ACTIVATED", null, null); | |||
QProfileDto profile1 = db.qualityProfiles().insert(db.getDefaultOrganization()); | |||
insertChange(profile1.getRulesProfileUuid(), "ACTIVATED", null, null); | |||
underTest.deleteByProfileKeys(dbSession, asList("does_not_exist")); | |||
underTest.deleteByRulesProfileUuids(dbSession, asList("does not exist")); | |||
assertThat(underTest.countForQProfileUuid(dbSession, profile1.getKee())).isEqualTo(1); | |||
} | |||
assertThat(underTest.countForProfileUuid(dbSession, "P1")).isEqualTo(1); | |||
private QProfileChangeDto insertChange(QProfileDto profile, String type, @Nullable String login, @Nullable String data) { | |||
return insertChange(profile.getRulesProfileUuid(), type, login, data); | |||
} | |||
private void insertChange(String profileKey, String type, @Nullable String login, @Nullable String data) { | |||
private QProfileChangeDto insertChange(String rulesProfileUuid, String type, @Nullable String login, @Nullable String data) { | |||
QProfileChangeDto dto = new QProfileChangeDto() | |||
.setProfileKey(profileKey) | |||
.setRulesProfileUuid(rulesProfileUuid) | |||
.setLogin(login) | |||
.setChangeType(type) | |||
.setData(data); | |||
underTest.insert(dbSession, dto); | |||
return dto; | |||
} | |||
private Map<String, Object> selectChangeByKey(String key) { | |||
return dbTester.selectFirst(dbSession, | |||
"select qprofile_key as \"qprofileKey\", created_at as \"createdAt\", user_login as \"login\", change_type as \"changeType\", change_data as \"changeData\" from qprofile_changes where kee='" | |||
+ key + "'"); | |||
private QProfileChangeDto selectChangeByUuid(String uuid) { | |||
Map<String, Object> map = db.selectFirst(dbSession, | |||
"select kee as \"uuid\", qprofile_key as \"rulesProfileUuid\", created_at as \"createdAt\", user_login as \"login\", change_type as \"changeType\", change_data as \"changeData\" from qprofile_changes where kee='" | |||
+ uuid + "'"); | |||
return new QProfileChangeDto() | |||
.setUuid((String) map.get("uuid")) | |||
.setRulesProfileUuid((String) map.get("rulesProfileUuid")) | |||
.setCreatedAt((long) map.get("createdAt")) | |||
.setLogin((String) map.get("login")) | |||
.setChangeType((String) map.get("changeType")) | |||
.setData((String) map.get("changeData")); | |||
} | |||
} |
@@ -32,6 +32,7 @@ import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.core.util.UtcDateUtils; | |||
import org.sonar.core.util.Uuids; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
@@ -43,6 +44,7 @@ import static com.google.common.collect.Lists.newArrayList; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.emptyList; | |||
import static java.util.Collections.singletonList; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.tuple; | |||
import static org.mockito.Mockito.mock; | |||
@@ -54,16 +56,16 @@ public class QualityProfileDaoTest { | |||
private System2 system = mock(System2.class); | |||
@Rule | |||
public DbTester dbTester = DbTester.create(system); | |||
public DbTester db = DbTester.create(system); | |||
private DbSession dbSession = dbTester.getSession(); | |||
private QualityProfileDao underTest = dbTester.getDbClient().qualityProfileDao(); | |||
private DbSession dbSession = db.getSession(); | |||
private QualityProfileDao underTest = db.getDbClient().qualityProfileDao(); | |||
private OrganizationDto organization; | |||
@Before | |||
public void before() { | |||
when(system.now()).thenReturn(UtcDateUtils.parseDateTime("2014-01-20T12:00:00+0000").getTime()); | |||
organization = dbTester.organizations().insertForUuid("QualityProfileDaoTest-ORG"); | |||
organization = db.organizations().insertForUuid("QualityProfileDaoTest-ORG"); | |||
} | |||
@After | |||
@@ -73,7 +75,9 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void test_insert() { | |||
QProfileDto dto = QProfileDto.createFor("theUuid") | |||
QProfileDto dto = new QProfileDto() | |||
.setKee("theUuid") | |||
.setRulesProfileUuid("theRulesProfileUuid") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("theName") | |||
.setLanguage("theLang") | |||
@@ -87,6 +91,7 @@ public class QualityProfileDaoTest { | |||
QProfileDto reloaded = underTest.selectByUuid(dbSession, dto.getKee()); | |||
assertThat(reloaded.getKee()).isEqualTo(dto.getKee()); | |||
assertThat(reloaded.getRulesProfileUuid()).isEqualTo(dto.getRulesProfileUuid()); | |||
assertThat(reloaded.getId()).isNotNull().isNotZero(); | |||
assertThat(reloaded.getLanguage()).isEqualTo(dto.getLanguage()); | |||
assertThat(reloaded.getName()).isEqualTo(dto.getName()); | |||
@@ -99,7 +104,9 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void test_update() { | |||
QProfileDto initial = QProfileDto.createFor("theUuid") | |||
QProfileDto initial = new QProfileDto() | |||
.setKee("theUuid") | |||
.setRulesProfileUuid("theRulesProfileUuid") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("theName") | |||
.setLanguage("theLang") | |||
@@ -110,7 +117,9 @@ public class QualityProfileDaoTest { | |||
.setIsBuiltIn(true); | |||
underTest.insert(dbSession, initial); | |||
QProfileDto update = QProfileDto.createFor(initial.getKee()) | |||
QProfileDto update = new QProfileDto() | |||
.setKee(initial.getKee()) | |||
.setRulesProfileUuid(initial.getRulesProfileUuid()) | |||
.setName("theNewName") | |||
.setLanguage("theNewLang") | |||
.setLastUsed(11_000L) | |||
@@ -137,41 +146,59 @@ public class QualityProfileDaoTest { | |||
} | |||
@Test | |||
public void test_deleteByUuids() { | |||
QProfileDto p1 = dbTester.qualityProfiles().insert(organization); | |||
QProfileDto p2 = dbTester.qualityProfiles().insert(organization); | |||
QProfileDto p3 = dbTester.qualityProfiles().insert(organization); | |||
public void deleteRulesProfilesByUuids() { | |||
RulesProfileDto rp1 = insertRulesProfile(); | |||
RulesProfileDto rp2 = insertRulesProfile(); | |||
underTest.deleteByUuids(dbSession, asList(p1.getKee(), p3.getKee(), "does_not_exist")); | |||
underTest.deleteRulesProfilesByUuids(dbSession, asList(rp1.getKee())); | |||
List<QProfileDto> profiles = underTest.selectAll(dbSession, organization); | |||
assertThat(profiles).extracting(QProfileDto::getKee).containsExactly(p2.getKee()); | |||
List<Map<String, Object>> uuids = db.select(dbSession, "select kee as \"uuid\" from rules_profiles"); | |||
assertThat(uuids).hasSize(1); | |||
assertThat(uuids.get(0).get("uuid")).isEqualTo(rp2.getKee()); | |||
} | |||
@Test | |||
public void deleteByUuids_does_nothing_if_empty_uuids() { | |||
dbTester.qualityProfiles().insert(organization); | |||
public void deleteRulesProfilesByUuids_does_nothing_if_empty_input() { | |||
insertRulesProfile(); | |||
underTest.deleteByUuids(dbSession, Collections.emptyList()); | |||
underTest.deleteRulesProfilesByUuids(dbSession, emptyList()); | |||
assertThat(dbTester.countRowsOfTable(dbSession, "rules_profiles")).isEqualTo(1); | |||
assertThat(dbTester.countRowsOfTable(dbSession, "org_qprofiles")).isEqualTo(1); | |||
assertThat(db.countRowsOfTable(dbSession, "rules_profiles")).isEqualTo(1); | |||
} | |||
@Test | |||
public void deleteRulesProfilesByUuids_does_nothing_if_specified_uuid_does_not_exist() { | |||
insertRulesProfile(); | |||
underTest.deleteRulesProfilesByUuids(dbSession, asList("does_not_exist")); | |||
assertThat(db.countRowsOfTable(dbSession, "rules_profiles")).isEqualTo(1); | |||
} | |||
private RulesProfileDto insertRulesProfile() { | |||
RulesProfileDto dto = new RulesProfileDto() | |||
.setName(randomAlphanumeric(10)) | |||
.setLanguage(randomAlphanumeric(3)) | |||
.setKee(Uuids.createFast()) | |||
.setIsBuiltIn(false); | |||
db.getDbClient().qualityProfileDao().insert(dbSession, dto); | |||
return dto; | |||
} | |||
@Test | |||
public void test_deleteProjectAssociationsByProfileUuids() { | |||
QProfileDto profile1 = dbTester.qualityProfiles().insert(organization); | |||
QProfileDto profile2 = dbTester.qualityProfiles().insert(organization); | |||
ComponentDto project1 = dbTester.components().insertPrivateProject(organization); | |||
ComponentDto project2 = dbTester.components().insertPrivateProject(organization); | |||
ComponentDto project3 = dbTester.components().insertPrivateProject(organization); | |||
dbTester.qualityProfiles().associateWithProject(project1, profile1); | |||
dbTester.qualityProfiles().associateWithProject(project2, profile1); | |||
dbTester.qualityProfiles().associateWithProject(project3, profile2); | |||
QProfileDto profile1 = db.qualityProfiles().insert(organization); | |||
QProfileDto profile2 = db.qualityProfiles().insert(organization); | |||
ComponentDto project1 = db.components().insertPrivateProject(organization); | |||
ComponentDto project2 = db.components().insertPrivateProject(organization); | |||
ComponentDto project3 = db.components().insertPrivateProject(organization); | |||
db.qualityProfiles().associateWithProject(project1, profile1); | |||
db.qualityProfiles().associateWithProject(project2, profile1); | |||
db.qualityProfiles().associateWithProject(project3, profile2); | |||
underTest.deleteProjectAssociationsByProfileUuids(dbSession, asList(profile1.getKee(), "does_not_exist")); | |||
List<Map<String, Object>> rows = dbTester.select(dbSession, "select project_uuid as \"projectUuid\", profile_key as \"profileKey\" from project_qprofiles"); | |||
List<Map<String, Object>> rows = db.select(dbSession, "select project_uuid as \"projectUuid\", profile_key as \"profileKey\" from project_qprofiles"); | |||
assertThat(rows).hasSize(1); | |||
assertThat(rows.get(0).get("projectUuid")).isEqualTo(project3.uuid()); | |||
assertThat(rows.get(0).get("profileKey")).isEqualTo(profile2.getKee()); | |||
@@ -179,20 +206,20 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void deleteProjectAssociationsByProfileUuids_does_nothing_if_empty_uuids() { | |||
QProfileDto profile = dbTester.qualityProfiles().insert(organization); | |||
ComponentDto project = dbTester.components().insertPrivateProject(); | |||
dbTester.qualityProfiles().associateWithProject(project, profile); | |||
QProfileDto profile = db.qualityProfiles().insert(organization); | |||
ComponentDto project = db.components().insertPrivateProject(); | |||
db.qualityProfiles().associateWithProject(project, profile); | |||
underTest.deleteProjectAssociationsByProfileUuids(dbSession, Collections.emptyList()); | |||
assertThat(dbTester.countRowsOfTable(dbSession, "project_qprofiles")).isEqualTo(1); | |||
assertThat(db.countRowsOfTable(dbSession, "project_qprofiles")).isEqualTo(1); | |||
} | |||
@Test | |||
public void test_selectAll() { | |||
List<QProfileDto> sharedData = createSharedData(); | |||
List<QProfileDto> reloadeds = underTest.selectAll(dbSession, organization); | |||
List<QProfileDto> reloadeds = underTest.selectOrderedByOrganizationUuid(dbSession, organization); | |||
assertThat(reloadeds).hasSize(sharedData.size()); | |||
@@ -212,13 +239,14 @@ public class QualityProfileDaoTest { | |||
assertThat(reloaded.getLastUsed()).isEqualTo(original.getLastUsed()); | |||
assertThat(reloaded.getUserUpdatedAt()).isEqualTo(original.getUserUpdatedAt()); | |||
assertThat(reloaded.isBuiltIn()).isEqualTo(original.isBuiltIn()); | |||
} | |||
); | |||
}); | |||
} | |||
@Test | |||
public void find_all_is_sorted_by_profile_name() { | |||
QProfileDto dto1 = QProfileDto.createFor("js_first") | |||
QProfileDto dto1 = new QProfileDto() | |||
.setKee("js_first") | |||
.setRulesProfileUuid("rp-js_first") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("First") | |||
.setLanguage("js") | |||
@@ -228,7 +256,9 @@ public class QualityProfileDaoTest { | |||
.setIsBuiltIn(false); | |||
underTest.insert(dbSession, dto1); | |||
QProfileDto dto2 = QProfileDto.createFor("js_second") | |||
QProfileDto dto2 = new QProfileDto() | |||
.setKee("js_second") | |||
.setRulesProfileUuid("rp-js_second") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("Second") | |||
.setLanguage("js") | |||
@@ -238,7 +268,9 @@ public class QualityProfileDaoTest { | |||
.setIsBuiltIn(false); | |||
underTest.insert(dbSession, dto2); | |||
QProfileDto dto3 = QProfileDto.createFor("js_third") | |||
QProfileDto dto3 = new QProfileDto() | |||
.setKee("js_third") | |||
.setRulesProfileUuid("rp-js_third") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("Third") | |||
.setLanguage("js") | |||
@@ -248,30 +280,28 @@ public class QualityProfileDaoTest { | |||
.setIsBuiltIn(false); | |||
underTest.insert(dbSession, dto3); | |||
List<QProfileDto> dtos = underTest.selectAll(dbSession, organization); | |||
List<QProfileDto> dtos = underTest.selectOrderedByOrganizationUuid(dbSession, organization); | |||
assertThat(dtos).hasSize(3); | |||
assertThat(dtos.get(0).getName()).isEqualTo("First"); | |||
assertThat(dtos.get(1).getName()).isEqualTo("Second"); | |||
assertThat(dtos.get(2).getName()).isEqualTo("Third"); | |||
underTest.deleteByUuids(dbSession, Arrays.asList("js_first", "js_second", "js_third")); | |||
} | |||
@Test | |||
public void get_default_profile() { | |||
public void selectDefaultProfile() { | |||
List<QProfileDto> sharedData = createSharedData(); | |||
QProfileDto java = underTest.selectDefaultProfile(dbSession, organization, "java"); | |||
assertThat(java).isNotNull(); | |||
assertThat(java.getKee()).isEqualTo("java_sonar_way"); | |||
assertThat(underTest.selectDefaultProfile(dbSession, dbTester.organizations().insert(), "java")).isNull(); | |||
assertThat(underTest.selectDefaultProfile(dbSession, db.organizations().insert(), "java")).isNull(); | |||
assertThat(underTest.selectDefaultProfile(dbSession, organization, "js")).isNull(); | |||
} | |||
@Test | |||
public void get_default_profiles() { | |||
public void selectDefaultProfiles() { | |||
List<QProfileDto> sharedData = createSharedData(); | |||
List<QProfileDto> java = underTest.selectDefaultProfiles(dbSession, organization, singletonList("java")); | |||
@@ -312,7 +342,7 @@ public class QualityProfileDaoTest { | |||
} | |||
@Test | |||
public void should_find_by_language() { | |||
public void selectByLanguage() { | |||
QProfileDto profile = QualityProfileTesting.newQualityProfileDto() | |||
.setOrganizationUuid(organization.getUuid()); | |||
underTest.insert(dbSession, profile); | |||
@@ -326,6 +356,7 @@ public class QualityProfileDaoTest { | |||
assertThat(result.getKee()).isEqualTo(profile.getKee()); | |||
assertThat(result.getLanguage()).isEqualTo(profile.getLanguage()); | |||
assertThat(result.getOrganizationUuid()).isEqualTo(profile.getOrganizationUuid()); | |||
assertThat(result.getRulesProfileUuid()).isEqualTo(profile.getRulesProfileUuid()); | |||
} | |||
@Test | |||
@@ -348,10 +379,11 @@ public class QualityProfileDaoTest { | |||
assertThat(results).isEmpty(); | |||
} | |||
@Test | |||
public void find_children() { | |||
QProfileDto original1 = QProfileDto.createFor("java_child1") | |||
QProfileDto original1 = new QProfileDto() | |||
.setKee("java_child1") | |||
.setRulesProfileUuid("rp-java_child1") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("Child1") | |||
.setLanguage("java") | |||
@@ -362,7 +394,9 @@ public class QualityProfileDaoTest { | |||
.setIsBuiltIn(false); | |||
underTest.insert(dbSession, original1); | |||
QProfileDto original2 = QProfileDto.createFor("java_child2") | |||
QProfileDto original2 = new QProfileDto() | |||
.setKee("java_child2") | |||
.setRulesProfileUuid("rp-java_child2") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("Child2") | |||
.setLanguage("java") | |||
@@ -373,7 +407,9 @@ public class QualityProfileDaoTest { | |||
.setIsBuiltIn(false); | |||
underTest.insert(dbSession, original2); | |||
QProfileDto original3 = QProfileDto.createFor("java_parent") | |||
QProfileDto original3 = new QProfileDto() | |||
.setKee("java_parent") | |||
.setRulesProfileUuid("rp-java_parent") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("Parent") | |||
.setLanguage("java") | |||
@@ -383,7 +419,9 @@ public class QualityProfileDaoTest { | |||
.setIsBuiltIn(false); | |||
underTest.insert(dbSession, original3); | |||
QProfileDto original4 = QProfileDto.createFor("js_child1") | |||
QProfileDto original4 = new QProfileDto() | |||
.setKee("js_child1") | |||
.setRulesProfileUuid("rp-js_child1") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("Child1") | |||
.setLanguage("js") | |||
@@ -394,7 +432,9 @@ public class QualityProfileDaoTest { | |||
.setIsBuiltIn(false); | |||
underTest.insert(dbSession, original4); | |||
QProfileDto original5 = QProfileDto.createFor("js_child2") | |||
QProfileDto original5 = new QProfileDto() | |||
.setKee("js_child2") | |||
.setRulesProfileUuid("rp-js_child2") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("Child2") | |||
.setLanguage("js") | |||
@@ -405,7 +445,9 @@ public class QualityProfileDaoTest { | |||
.setIsBuiltIn(false); | |||
underTest.insert(dbSession, original5); | |||
QProfileDto original6 = QProfileDto.createFor("js_parent") | |||
QProfileDto original6 = new QProfileDto() | |||
.setKee("js_parent") | |||
.setRulesProfileUuid("rp-js_parent") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("Parent") | |||
.setLanguage("js") | |||
@@ -415,7 +457,7 @@ public class QualityProfileDaoTest { | |||
.setIsBuiltIn(false); | |||
underTest.insert(dbSession, original6); | |||
List<QProfileDto> dtos = underTest.selectChildren(dbSession, "java_parent"); | |||
List<QProfileDto> dtos = underTest.selectChildren(dbSession, original3); | |||
assertThat(dtos).hasSize(2); | |||
@@ -428,23 +470,21 @@ public class QualityProfileDaoTest { | |||
assertThat(dto2.getName()).isEqualTo("Child2"); | |||
assertThat(dto2.getLanguage()).isEqualTo("java"); | |||
assertThat(dto2.getParentKee()).isEqualTo("java_parent"); | |||
underTest.deleteByUuids(dbSession, Arrays.asList("java_parent", "java_child1", "java_child2", "js_parent", "js_child1", "js_child2")); | |||
} | |||
@Test | |||
public void countProjectsByProfileKey() { | |||
QProfileDto profileWithoutProjects = dbTester.qualityProfiles().insert(organization); | |||
QProfileDto profileWithProjects = dbTester.qualityProfiles().insert(organization); | |||
ComponentDto project1 = dbTester.components().insertPrivateProject(organization); | |||
ComponentDto project2 = dbTester.components().insertPrivateProject(organization); | |||
dbTester.qualityProfiles().associateWithProject(project1, profileWithProjects); | |||
dbTester.qualityProfiles().associateWithProject(project2, profileWithProjects); | |||
OrganizationDto otherOrg = dbTester.organizations().insert(); | |||
QProfileDto profileInOtherOrg = dbTester.qualityProfiles().insert(otherOrg); | |||
ComponentDto projectInOtherOrg = dbTester.components().insertPrivateProject(otherOrg); | |||
dbTester.qualityProfiles().associateWithProject(projectInOtherOrg, profileInOtherOrg); | |||
QProfileDto profileWithoutProjects = db.qualityProfiles().insert(organization); | |||
QProfileDto profileWithProjects = db.qualityProfiles().insert(organization); | |||
ComponentDto project1 = db.components().insertPrivateProject(organization); | |||
ComponentDto project2 = db.components().insertPrivateProject(organization); | |||
db.qualityProfiles().associateWithProject(project1, profileWithProjects); | |||
db.qualityProfiles().associateWithProject(project2, profileWithProjects); | |||
OrganizationDto otherOrg = db.organizations().insert(); | |||
QProfileDto profileInOtherOrg = db.qualityProfiles().insert(otherOrg); | |||
ComponentDto projectInOtherOrg = db.components().insertPrivateProject(otherOrg); | |||
db.qualityProfiles().associateWithProject(projectInOtherOrg, profileInOtherOrg); | |||
assertThat(underTest.countProjectsByProfileUuid(dbSession, organization)).containsOnly( | |||
MapEntry.entry(profileWithProjects.getKee(), 2L)); | |||
@@ -452,12 +492,12 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void test_selectAssociatedToProjectAndLanguage() { | |||
OrganizationDto org = dbTester.organizations().insert(); | |||
ComponentDto project1 = dbTester.components().insertPublicProject(org); | |||
ComponentDto project2 = dbTester.components().insertPublicProject(org); | |||
QProfileDto javaProfile = dbTester.qualityProfiles().insert(org, p -> p.setLanguage("java")); | |||
QProfileDto jsProfile = dbTester.qualityProfiles().insert(org, p -> p.setLanguage("js")); | |||
dbTester.qualityProfiles().associateWithProject(project1, javaProfile, jsProfile); | |||
OrganizationDto org = db.organizations().insert(); | |||
ComponentDto project1 = db.components().insertPublicProject(org); | |||
ComponentDto project2 = db.components().insertPublicProject(org); | |||
QProfileDto javaProfile = db.qualityProfiles().insert(org, p -> p.setLanguage("java")); | |||
QProfileDto jsProfile = db.qualityProfiles().insert(org, p -> p.setLanguage("js")); | |||
db.qualityProfiles().associateWithProject(project1, javaProfile, jsProfile); | |||
assertThat(underTest.selectAssociatedToProjectAndLanguage(dbSession, project1, "java").getKee()) | |||
.isEqualTo(javaProfile.getKee()); | |||
@@ -471,12 +511,12 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void test_selectAssociatedToProjectUuidAndLanguages() { | |||
OrganizationDto org = dbTester.organizations().insert(); | |||
ComponentDto project1 = dbTester.components().insertPublicProject(org); | |||
ComponentDto project2 = dbTester.components().insertPublicProject(org); | |||
QProfileDto javaProfile = dbTester.qualityProfiles().insert(org, p -> p.setLanguage("java")); | |||
QProfileDto jsProfile = dbTester.qualityProfiles().insert(org, p -> p.setLanguage("js")); | |||
dbTester.qualityProfiles().associateWithProject(project1, javaProfile, jsProfile); | |||
OrganizationDto org = db.organizations().insert(); | |||
ComponentDto project1 = db.components().insertPublicProject(org); | |||
ComponentDto project2 = db.components().insertPublicProject(org); | |||
QProfileDto javaProfile = db.qualityProfiles().insert(org, p -> p.setLanguage("java")); | |||
QProfileDto jsProfile = db.qualityProfiles().insert(org, p -> p.setLanguage("js")); | |||
db.qualityProfiles().associateWithProject(project1, javaProfile, jsProfile); | |||
assertThat(underTest.selectAssociatedToProjectUuidAndLanguages(dbSession, project1, singletonList("java"))) | |||
.extracting(QProfileDto::getKee).containsOnly(javaProfile.getKee()); | |||
@@ -492,12 +532,12 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void test_updateProjectProfileAssociation() { | |||
OrganizationDto org = dbTester.organizations().insert(); | |||
ComponentDto project = dbTester.components().insertPrivateProject(org); | |||
QProfileDto javaProfile1 = dbTester.qualityProfiles().insert(org, p -> p.setLanguage("java")); | |||
QProfileDto jsProfile = dbTester.qualityProfiles().insert(org, p -> p.setLanguage("js")); | |||
QProfileDto javaProfile2 = dbTester.qualityProfiles().insert(org, p -> p.setLanguage("java")); | |||
dbTester.qualityProfiles().associateWithProject(project, javaProfile1, jsProfile); | |||
OrganizationDto org = db.organizations().insert(); | |||
ComponentDto project = db.components().insertPrivateProject(org); | |||
QProfileDto javaProfile1 = db.qualityProfiles().insert(org, p -> p.setLanguage("java")); | |||
QProfileDto jsProfile = db.qualityProfiles().insert(org, p -> p.setLanguage("js")); | |||
QProfileDto javaProfile2 = db.qualityProfiles().insert(org, p -> p.setLanguage("java")); | |||
db.qualityProfiles().associateWithProject(project, javaProfile1, jsProfile); | |||
underTest.updateProjectProfileAssociation(dbSession, project, javaProfile2.getKee(), javaProfile1.getKee()); | |||
@@ -507,7 +547,7 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void selectByKeys() { | |||
dbTester.qualityProfiles().insert(newQualityProfileDto().setKey("qp-key-1"), newQualityProfileDto().setKee("qp-key-2"), newQualityProfileDto().setKee("qp-key-3")); | |||
db.qualityProfiles().insert(newQualityProfileDto().setKee("qp-key-1"), newQualityProfileDto().setKee("qp-key-2"), newQualityProfileDto().setKee("qp-key-3")); | |||
assertThat(underTest.selectOrFailByUuid(dbSession, "qp-key-1")).isNotNull(); | |||
assertThat(underTest.selectByUuid(dbSession, "qp-key-1")).isNotNull(); | |||
@@ -520,20 +560,20 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void select_selected_projects() throws Exception { | |||
ComponentDto project1 = dbTester.components().insertPrivateProject(t -> t.setName("Project1 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project2 = dbTester.components().insertPrivateProject(t -> t.setName("Project2 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project3 = dbTester.components().insertPrivateProject(t -> t.setName("Project3 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
OrganizationDto organization2 = dbTester.organizations().insert(); | |||
ComponentDto project4 = dbTester.components().insertPrivateProject(t -> t.setName("Project4 name"), t -> t.setOrganizationUuid(organization2.getUuid())); | |||
ComponentDto project1 = db.components().insertPrivateProject(t -> t.setName("Project1 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project2 = db.components().insertPrivateProject(t -> t.setName("Project2 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project3 = db.components().insertPrivateProject(t -> t.setName("Project3 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
OrganizationDto organization2 = db.organizations().insert(); | |||
ComponentDto project4 = db.components().insertPrivateProject(t -> t.setName("Project4 name"), t -> t.setOrganizationUuid(organization2.getUuid())); | |||
QProfileDto profile1 = newQualityProfileDto(); | |||
dbTester.qualityProfiles().insert(profile1); | |||
dbTester.qualityProfiles().associateWithProject(project1, profile1); | |||
dbTester.qualityProfiles().associateWithProject(project2, profile1); | |||
db.qualityProfiles().insert(profile1); | |||
db.qualityProfiles().associateWithProject(project1, profile1); | |||
db.qualityProfiles().associateWithProject(project2, profile1); | |||
QProfileDto profile2 = newQualityProfileDto(); | |||
dbTester.qualityProfiles().insert(profile2); | |||
dbTester.qualityProfiles().associateWithProject(project3, profile2); | |||
db.qualityProfiles().insert(profile2); | |||
db.qualityProfiles().associateWithProject(project3, profile2); | |||
QProfileDto profile3 = newQualityProfileDto(); | |||
assertThat(underTest.selectSelectedProjects(dbSession, organization, profile1, null)) | |||
@@ -548,19 +588,19 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void select_deselected_projects() throws Exception { | |||
ComponentDto project1 = dbTester.components().insertPrivateProject(t -> t.setName("Project1 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project2 = dbTester.components().insertPrivateProject(t -> t.setName("Project2 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project3 = dbTester.components().insertPrivateProject(t -> t.setName("Project3 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
OrganizationDto organization2 = dbTester.organizations().insert(); | |||
ComponentDto project4 = dbTester.components().insertPrivateProject(t -> t.setName("Project4 name"), t -> t.setOrganizationUuid(organization2.getUuid())); | |||
ComponentDto project1 = db.components().insertPrivateProject(t -> t.setName("Project1 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project2 = db.components().insertPrivateProject(t -> t.setName("Project2 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project3 = db.components().insertPrivateProject(t -> t.setName("Project3 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
OrganizationDto organization2 = db.organizations().insert(); | |||
ComponentDto project4 = db.components().insertPrivateProject(t -> t.setName("Project4 name"), t -> t.setOrganizationUuid(organization2.getUuid())); | |||
QProfileDto profile1 = newQualityProfileDto(); | |||
dbTester.qualityProfiles().insert(profile1); | |||
dbTester.qualityProfiles().associateWithProject(project1, profile1); | |||
db.qualityProfiles().insert(profile1); | |||
db.qualityProfiles().associateWithProject(project1, profile1); | |||
QProfileDto profile2 = newQualityProfileDto(); | |||
dbTester.qualityProfiles().insert(profile2); | |||
dbTester.qualityProfiles().associateWithProject(project2, profile2); | |||
db.qualityProfiles().insert(profile2); | |||
db.qualityProfiles().associateWithProject(project2, profile2); | |||
QProfileDto profile3 = newQualityProfileDto(); | |||
assertThat(underTest.selectDeselectedProjects(dbSession, organization, profile1, null)) | |||
@@ -575,19 +615,19 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void select_project_associations() throws Exception { | |||
ComponentDto project1 = dbTester.components().insertPrivateProject(t -> t.setName("Project1 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project2 = dbTester.components().insertPrivateProject(t -> t.setName("Project2 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project3 = dbTester.components().insertPrivateProject(t -> t.setName("Project3 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
OrganizationDto organization2 = dbTester.organizations().insert(); | |||
ComponentDto project4 = dbTester.components().insertPrivateProject(t -> t.setName("Project4 name"), t -> t.setOrganizationUuid(organization2.getUuid())); | |||
ComponentDto project1 = db.components().insertPrivateProject(t -> t.setName("Project1 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project2 = db.components().insertPrivateProject(t -> t.setName("Project2 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
ComponentDto project3 = db.components().insertPrivateProject(t -> t.setName("Project3 name"), t -> t.setOrganizationUuid(organization.getUuid())); | |||
OrganizationDto organization2 = db.organizations().insert(); | |||
ComponentDto project4 = db.components().insertPrivateProject(t -> t.setName("Project4 name"), t -> t.setOrganizationUuid(organization2.getUuid())); | |||
QProfileDto profile1 = newQualityProfileDto(); | |||
dbTester.qualityProfiles().insert(profile1); | |||
dbTester.qualityProfiles().associateWithProject(project1, profile1); | |||
db.qualityProfiles().insert(profile1); | |||
db.qualityProfiles().associateWithProject(project1, profile1); | |||
QProfileDto profile2 = newQualityProfileDto(); | |||
dbTester.qualityProfiles().insert(profile2); | |||
dbTester.qualityProfiles().associateWithProject(project2, profile2); | |||
db.qualityProfiles().insert(profile2); | |||
db.qualityProfiles().associateWithProject(project2, profile2); | |||
QProfileDto profile3 = newQualityProfileDto(); | |||
assertThat(underTest.selectProjectAssociations(dbSession, organization, profile1, null)) | |||
@@ -602,19 +642,19 @@ public class QualityProfileDaoTest { | |||
} | |||
@Test | |||
public void selectOutdatedProfiles_returns_the_custom_profiles_with_specified_name() { | |||
OrganizationDto org1 = dbTester.organizations().insert(); | |||
OrganizationDto org2 = dbTester.organizations().insert(); | |||
OrganizationDto org3 = dbTester.organizations().insert(); | |||
QProfileDto outdatedProfile1 = dbTester.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); | |||
QProfileDto outdatedProfile2 = dbTester.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); | |||
QProfileDto builtInProfile = dbTester.qualityProfiles().insert(org3, p -> p.setIsBuiltIn(true).setLanguage("java").setName("foo")); | |||
QProfileDto differentLanguage = dbTester.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(false).setLanguage("cobol").setName("foo")); | |||
QProfileDto differentName = dbTester.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(false).setLanguage("java").setName("bar")); | |||
public void selectUuidsOfCustomRulesProfiles_returns_the_custom_profiles_with_specified_name() { | |||
OrganizationDto org1 = db.organizations().insert(); | |||
OrganizationDto org2 = db.organizations().insert(); | |||
OrganizationDto org3 = db.organizations().insert(); | |||
QProfileDto outdatedProfile1 = db.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); | |||
QProfileDto outdatedProfile2 = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); | |||
QProfileDto builtInProfile = db.qualityProfiles().insert(org3, p -> p.setIsBuiltIn(true).setLanguage("java").setName("foo")); | |||
QProfileDto differentLanguage = db.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(false).setLanguage("cobol").setName("foo")); | |||
QProfileDto differentName = db.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(false).setLanguage("java").setName("bar")); | |||
Collection<String> keys = underTest.selectUuidsOfCustomRulesProfiles(dbSession, "java", "foo"); | |||
assertThat(keys).containsExactlyInAnyOrder(outdatedProfile1.getKee(), outdatedProfile2.getKee()); | |||
assertThat(keys).containsExactlyInAnyOrder(outdatedProfile1.getRulesProfileUuid(), outdatedProfile2.getRulesProfileUuid()); | |||
} | |||
@Test | |||
@@ -624,13 +664,13 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void renameAndCommit_updates_name_of_specified_profiles() { | |||
OrganizationDto org1 = dbTester.organizations().insert(); | |||
OrganizationDto org2 = dbTester.organizations().insert(); | |||
QProfileDto fooInOrg1 = dbTester.qualityProfiles().insert(org1, p -> p.setName("foo")); | |||
QProfileDto fooInOrg2 = dbTester.qualityProfiles().insert(org2, p -> p.setName("foo")); | |||
QProfileDto bar = dbTester.qualityProfiles().insert(org1, p -> p.setName("bar")); | |||
OrganizationDto org1 = db.organizations().insert(); | |||
OrganizationDto org2 = db.organizations().insert(); | |||
QProfileDto fooInOrg1 = db.qualityProfiles().insert(org1, p -> p.setName("foo")); | |||
QProfileDto fooInOrg2 = db.qualityProfiles().insert(org2, p -> p.setName("foo")); | |||
QProfileDto bar = db.qualityProfiles().insert(org1, p -> p.setName("bar")); | |||
underTest.renameRulesProfilesAndCommit(dbSession, asList(fooInOrg1.getKee(), fooInOrg2.getKee()), "foo (copy)"); | |||
underTest.renameRulesProfilesAndCommit(dbSession, asList(fooInOrg1.getRulesProfileUuid(), fooInOrg2.getRulesProfileUuid()), "foo (copy)"); | |||
assertThat(underTest.selectOrFailByUuid(dbSession, fooInOrg1.getKee()).getName()).isEqualTo("foo (copy)"); | |||
assertThat(underTest.selectOrFailByUuid(dbSession, fooInOrg2.getKee()).getName()).isEqualTo("foo (copy)"); | |||
@@ -639,8 +679,8 @@ public class QualityProfileDaoTest { | |||
@Test | |||
public void renameAndCommit_does_nothing_if_empty_keys() { | |||
OrganizationDto org = dbTester.organizations().insert(); | |||
QProfileDto profile = dbTester.qualityProfiles().insert(org, p -> p.setName("foo")); | |||
OrganizationDto org = db.organizations().insert(); | |||
QProfileDto profile = db.qualityProfiles().insert(org, p -> p.setName("foo")); | |||
underTest.renameRulesProfilesAndCommit(dbSession, Collections.emptyList(), "foo (copy)"); | |||
@@ -648,7 +688,9 @@ public class QualityProfileDaoTest { | |||
} | |||
private List<QProfileDto> createSharedData() { | |||
QProfileDto dto1 = QProfileDto.createFor("java_sonar_way") | |||
QProfileDto dto1 = new QProfileDto() | |||
.setKee("java_sonar_way") | |||
.setRulesProfileUuid("rp-java_sonar_way") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("Sonar Way") | |||
.setLanguage("java") | |||
@@ -658,7 +700,9 @@ public class QualityProfileDaoTest { | |||
.setIsBuiltIn(true); | |||
underTest.insert(dbSession, dto1); | |||
QProfileDto dto2 = QProfileDto.createFor("js_sonar_way") | |||
QProfileDto dto2 = new QProfileDto() | |||
.setKee("js_sonar_way") | |||
.setRulesProfileUuid("rp-js_sonar_way") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("Sonar Way") | |||
.setLanguage("js") | |||
@@ -672,7 +716,7 @@ public class QualityProfileDaoTest { | |||
.setQProfileUuid(dto1.getKee()) | |||
.setLanguage(dto1.getLanguage()) | |||
.setOrganizationUuid(organization.getUuid()); | |||
dbTester.getDbClient().defaultQProfileDao().insertOrUpdate(dbSession, DefaultQProfileDto.from(dto1)); | |||
db.getDbClient().defaultQProfileDao().insertOrUpdate(dbSession, DefaultQProfileDto.from(dto1)); | |||
return Arrays.asList(dto1, dto2); | |||
} |
@@ -35,7 +35,9 @@ public class QualityProfileTesting { | |||
*/ | |||
public static QProfileDto newQualityProfileDto() { | |||
String uuid = Uuids.createFast(); | |||
return QProfileDto.createFor(uuid) | |||
return new QProfileDto() | |||
.setKee(uuid) | |||
.setRulesProfileUuid(Uuids.createFast()) | |||
.setOrganizationUuid(randomAlphanumeric(40)) | |||
.setName(uuid) | |||
.setLanguage(randomAlphanumeric(20)) | |||
@@ -48,8 +50,8 @@ public class QualityProfileTesting { | |||
*/ | |||
public static QProfileChangeDto newQProfileChangeDto() { | |||
return new QProfileChangeDto() | |||
.setKey(randomAlphanumeric(40)) | |||
.setProfileKey(randomAlphanumeric(40)) | |||
.setUuid(randomAlphanumeric(40)) | |||
.setRulesProfileUuid(randomAlphanumeric(40)) | |||
.setCreatedAt(nextLong()) | |||
.setChangeType("ACTIVATED") | |||
.setLogin(randomAlphanumeric(10)); |
@@ -302,8 +302,8 @@ public class RuleTesting { | |||
return rule -> rule.setSystemTags(copyOf(tags)); | |||
} | |||
public static Consumer<RuleMetadataDto> setOrganizationUuid(String organizationUuid) { | |||
return rule -> rule.setOrganizationUuid(organizationUuid); | |||
public static Consumer<RuleMetadataDto> setOrganization(OrganizationDto organization) { | |||
return rule -> rule.setOrganizationUuid(organization.getUuid()); | |||
} | |||
public static Consumer<RuleMetadataDto> setTags(String... tags) { |
@@ -50,6 +50,9 @@ public class DbVersion65 implements DbVersion { | |||
.add(1721, "Drop rules_profiles.is_default", DropIsDefaultColumnFromRulesProfiles.class) | |||
.add(1722, "Create table qprofiles", CreateTableQProfiles.class) | |||
.add(1723, "Populate table qprofiles", PopulateQProfiles.class) | |||
.add(1724, "Drop columns organization_uuid and parent_kee from rules_profiles", DropOrgUuidAndParentKeeFromRulesProfiles.class); | |||
.add(1724, "Drop columns organization_uuid and parent_kee from rules_profiles", DropOrgUuidAndParentKeeFromRulesProfiles.class) | |||
.add(1725, "Mark rules_profiles.is_built_in to true for default organization", SetRulesProfilesIsBuiltInToTrueForDefaultOrganization.class) | |||
.add(1726, "Update OrgQProfiles to point to built-in profiles", UpdateOrgQProfilesToPointToBuiltInProfiles.class) | |||
.add(1727, "Delete orphans rules_profiles table and associated tables", DeleteOrphansFromRulesProfiles.class); | |||
} | |||
} |
@@ -0,0 +1,110 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.v65; | |||
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 DeleteOrphansFromRulesProfiles extends DataChange { | |||
public DeleteOrphansFromRulesProfiles(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
protected void execute(Context context) throws SQLException { | |||
deleteOrphansFromRulesProfiles(context); | |||
deleteOrphansFromActiveRules(context); | |||
deleteOrphansFromActiveRuleParameters(context); | |||
deleteOrphansFromQProfileChanges(context); | |||
} | |||
private static void deleteOrphansFromRulesProfiles(Context context) throws SQLException { | |||
MassUpdate massUpdate = context.prepareMassUpdate() | |||
.rowPluralName("rules profiles"); | |||
massUpdate.select("select rp.kee " + | |||
" from rules_profiles rp" + | |||
" where not exists " + | |||
" ( select 1 from org_qprofiles oqp where oqp.rules_profile_uuid = rp.kee )"); | |||
massUpdate.update("delete from rules_profiles where kee = ?") | |||
.execute((row, update) -> { | |||
String kee = row.getString(1); | |||
update.setString(1, kee); | |||
return true; | |||
}); | |||
} | |||
private static void deleteOrphansFromActiveRules(Context context) throws SQLException { | |||
MassUpdate massUpdate = context.prepareMassUpdate() | |||
.rowPluralName("active rules"); | |||
massUpdate.select("select ar.id " + | |||
" from active_rules ar " + | |||
" where not exists " + | |||
" ( select 1 from rules_profiles rp where ar.profile_id = rp.id )"); | |||
massUpdate.update("delete from active_rules where id = ?") | |||
.execute((row, update) -> { | |||
int id = row.getInt(1); | |||
update.setInt(1, id); | |||
return true; | |||
}); | |||
} | |||
private static void deleteOrphansFromActiveRuleParameters(Context context) throws SQLException { | |||
MassUpdate massUpdate = context.prepareMassUpdate() | |||
.rowPluralName("active rule parameters"); | |||
massUpdate.select("select arp.id " + | |||
" from active_rule_parameters arp " + | |||
" where not exists " + | |||
" ( select 1 from active_rules ar where ar.id = arp.active_rule_id )"); | |||
massUpdate.update("delete from active_rule_parameters where id = ?") | |||
.execute((row, update) -> { | |||
int id = row.getInt(1); | |||
update.setInt(1, id); | |||
return true; | |||
}); | |||
} | |||
private static void deleteOrphansFromQProfileChanges(Context context) throws SQLException { | |||
MassUpdate massUpdate = context.prepareMassUpdate() | |||
.rowPluralName("qprofile changes"); | |||
massUpdate.select("select qpc.kee " + | |||
" from qprofile_changes qpc" + | |||
" where not exists " + | |||
" ( select 1 from rules_profiles rp where qpc.qprofile_key = rp.kee )"); | |||
massUpdate.update("delete from qprofile_changes where kee = ?") | |||
.execute((row, update) -> { | |||
String kee = row.getString(1); | |||
update.setString(1, kee); | |||
return true; | |||
}); | |||
} | |||
} |
@@ -0,0 +1,78 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.v65; | |||
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; | |||
import static com.google.common.base.Preconditions.checkState; | |||
public class SetRulesProfilesIsBuiltInToTrueForDefaultOrganization extends DataChange { | |||
private static final String PROP_DEFAULT_ORGANIZATION_UUID = "organization.default"; | |||
private static final String PROP_ORGANIZATION_ENABLED = "organization.enabled"; | |||
public SetRulesProfilesIsBuiltInToTrueForDefaultOrganization(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
protected void execute(Context context) throws SQLException { | |||
if (!isOrganizationEnabled(context)) { | |||
return; | |||
} | |||
String defaultOrganizationUuid = getDefaultOrganizationUuid(context); | |||
checkState(defaultOrganizationUuid!=null, "Missing internal property: '%s'", PROP_DEFAULT_ORGANIZATION_UUID); | |||
MassUpdate massUpdate = context.prepareMassUpdate() | |||
.rowPluralName("rules profiles"); | |||
massUpdate.select("select rp.kee " + | |||
"from rules_profiles rp " + | |||
"inner join org_qprofiles oqp on rp.kee = oqp.rules_profile_uuid " + | |||
"where oqp.organization_uuid = ? ") | |||
.setString(1, defaultOrganizationUuid); | |||
massUpdate.update("update rules_profiles " + | |||
"set is_built_in=? " + | |||
"where kee=?").execute((row, update) -> { | |||
String rulesProfilesUuid = row.getString(1); | |||
update.setBoolean(1, true); | |||
update.setString(2, rulesProfilesUuid); | |||
return true; | |||
}); | |||
} | |||
private static String getDefaultOrganizationUuid(Context context) throws SQLException { | |||
return context.prepareSelect("select text_value from internal_properties where kee=?") | |||
.setString(1, PROP_DEFAULT_ORGANIZATION_UUID) | |||
.get(row -> row.getString(1)); | |||
} | |||
private static boolean isOrganizationEnabled(Context context) throws SQLException { | |||
String value = context.prepareSelect("select text_value from internal_properties where kee=?") | |||
.setString(1, PROP_ORGANIZATION_ENABLED) | |||
.get(row -> row.getNullableString(1)); | |||
return "true".equals(value); | |||
} | |||
} |
@@ -0,0 +1,124 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.v65; | |||
import com.google.common.collect.HashBasedTable; | |||
import com.google.common.collect.Table; | |||
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; | |||
import static com.google.common.base.Preconditions.checkState; | |||
public class UpdateOrgQProfilesToPointToBuiltInProfiles extends DataChange { | |||
private static final String PROP_DEFAULT_ORGANIZATION_UUID = "organization.default"; | |||
private static final String PROP_ORGANIZATION_ENABLED = "organization.enabled"; | |||
public UpdateOrgQProfilesToPointToBuiltInProfiles(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
protected void execute(Context context) throws SQLException { | |||
if (!isOrganizationEnabled(context)) { | |||
return; | |||
} | |||
String defaultOrganizationUuid = getDefaultOrganizationUuid(context); | |||
BuiltInRulesProfiles builtInRulesProfiles = retrieveBuiltInRulesProfiles(context); | |||
MassUpdate massUpdate = context.prepareMassUpdate() | |||
.rowPluralName("org qprofiles"); | |||
massUpdate.select("select oqp.uuid, rp.language, rp.name " + | |||
" from org_qprofiles oqp " + | |||
" inner join rules_profiles rp on rp.kee = oqp.rules_profile_uuid " + | |||
" where oqp.organization_uuid <> ? " + | |||
" and rp.is_built_in = ? " + | |||
" and rp.user_updated_at is null") | |||
.setString(1, defaultOrganizationUuid) | |||
.setBoolean(2, false); | |||
massUpdate.update("update org_qprofiles " + | |||
"set rules_profile_uuid = ? " + | |||
"where uuid=?") | |||
.execute((row, update) -> { | |||
String orgQProfileUuid = row.getString(1); | |||
String language = row.getString(2); | |||
String name = row.getString(3); | |||
if (!builtInRulesProfiles.contains(name, language)) { | |||
return false; | |||
} | |||
update.setString(1, builtInRulesProfiles.get(name, language)); | |||
update.setString(2, orgQProfileUuid); | |||
return true; | |||
}); | |||
} | |||
private static String getDefaultOrganizationUuid(Context context) throws SQLException { | |||
String defaultOrganizationUuid = context.prepareSelect("select text_value from internal_properties where kee=?") | |||
.setString(1, PROP_DEFAULT_ORGANIZATION_UUID) | |||
.get(row -> row.getString(1)); | |||
checkState(defaultOrganizationUuid != null, "Missing internal property: '%s'", PROP_DEFAULT_ORGANIZATION_UUID); | |||
return defaultOrganizationUuid; | |||
} | |||
private static boolean isOrganizationEnabled(Context context) throws SQLException { | |||
String value = context.prepareSelect("select text_value from internal_properties where kee=?") | |||
.setString(1, PROP_ORGANIZATION_ENABLED) | |||
.get(row -> row.getNullableString(1)); | |||
return "true".equals(value); | |||
} | |||
private static BuiltInRulesProfiles retrieveBuiltInRulesProfiles(Context context) throws SQLException { | |||
BuiltInRulesProfiles result = new BuiltInRulesProfiles(); | |||
context.prepareSelect("select name, language, kee" + | |||
" from rules_profiles " + | |||
" where is_built_in = ? ") | |||
.setBoolean(1, true) | |||
.list(row -> result.put(row.getString(1), row.getString(2), row.getString(3))); | |||
return result; | |||
} | |||
private static class BuiltInRulesProfiles { | |||
private Table<String, String, String> table = HashBasedTable.create(); | |||
private String put(String name, String language, String rulesProfileUuid) { | |||
return table.put(name, language, rulesProfileUuid); | |||
} | |||
private boolean contains(String name, String language) { | |||
return table.contains(name, language); | |||
} | |||
private String get(String name, String language) { | |||
return table.get(name, language); | |||
} | |||
} | |||
} |
@@ -35,6 +35,6 @@ public class DbVersion65Test { | |||
@Test | |||
public void verify_migration_count() { | |||
verifyMigrationCount(underTest, 25); | |||
verifyMigrationCount(underTest, 28); | |||
} | |||
} |
@@ -0,0 +1,277 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.v65; | |||
import java.sql.Date; | |||
import java.sql.SQLException; | |||
import java.util.List; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.CoreDbTester; | |||
import static java.lang.String.format; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class DeleteOrphansFromRulesProfilesTest { | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(DeleteOrphansFromRulesProfilesTest.class, "initial.sql"); | |||
private DeleteOrphansFromRulesProfiles underTest = new DeleteOrphansFromRulesProfiles(db.database()); | |||
@Test | |||
public void migration() throws SQLException { | |||
long rulesProfileId1 = insertRulesProfile("RP_UUID_1", "Sonar Way", "Java", 1_000L, true); | |||
long rulesProfileId2 = insertRulesProfile("RP_UUID_2", "Sonar Way", "JavaScript", 1_000L, false); | |||
insertRulesProfile("RP_UUID_3", "Sonar Way", "PL/SQL", 1_000L, false); | |||
insertRulesProfile("RP_UUID_4", "Sonar Way", "Cobol", 1_000L, false); | |||
insertRulesProfile("RP_UUID_5", "Sonar Way", "Cobol", 1_000L, false); | |||
insertRulesProfile("RP_UUID_6", "Sonar Way", "Cobol", 1_000L, true); | |||
insertOrgQProfile("ORG_QP_UUID_1", "ORG_UUID_1", "RP_UUID_1"); | |||
insertOrgQProfile("ORG_QP_UUID_2", "ORG_UUID_1", "RP_UUID_2"); | |||
long activeRuleId1 = insertActiveRule(rulesProfileId1, 1); | |||
long activeRuleId2 = insertActiveRule(rulesProfileId2, 1); | |||
insertActiveRule(-1, 1); | |||
insertActiveRule(-2, 1); | |||
long param1 = insertActiveRuleParameter(activeRuleId1, 1); | |||
long param2 = insertActiveRuleParameter(activeRuleId1, 2); | |||
long param3 = insertActiveRuleParameter(activeRuleId2, 2); | |||
insertActiveRuleParameter(-1, 1); | |||
insertActiveRuleParameter(-2, 1); | |||
insertQProfileChange("QPC_UUID1", "RP_UUID_1", "A"); | |||
insertQProfileChange("QPC_UUID2", "RP_UUID_2", "B"); | |||
insertQProfileChange("QPC_UUID3", "RP_UUID_3", "A"); | |||
insertQProfileChange("QPC_UUID4", "RP_UUID_4", "A"); | |||
underTest.execute(); | |||
assertThat(selectRulesProfiles()).containsExactlyInAnyOrder("RP_UUID_1", "RP_UUID_2"); | |||
assertThat(selectActiveRules()).containsExactlyInAnyOrder(activeRuleId1, activeRuleId2); | |||
assertThat(selectActiveRuleParameters()).containsExactlyInAnyOrder(param1, param2, param3); | |||
assertThat(selectQProfileChanges()).containsExactlyInAnyOrder("QPC_UUID1", "QPC_UUID2"); | |||
} | |||
@Test | |||
public void delete_rules_profiles_without_reference_in_qprofiles() throws SQLException { | |||
insertRulesProfile("RP_UUID_1", "Sonar Way", "Java", 1_000L, true); | |||
insertRulesProfile("RP_UUID_2", "Sonar Way", "JavaScript", 1_000L, false); | |||
insertRulesProfile("RP_UUID_5", "Sonar Way", "Cobol", 1_000L, false); | |||
insertRulesProfile("RP_UUID_6", "Sonar Way", "Cobol", 1_000L, true); | |||
insertOrgQProfile("ORG_QP_UUID_1", "ORG_UUID_1", "RP_UUID_5"); | |||
insertOrgQProfile("ORG_QP_UUID_2", "ORG_UUID_1", "RP_UUID_6"); | |||
underTest.execute(); | |||
assertThat(selectRulesProfiles()).containsExactlyInAnyOrder("RP_UUID_5", "RP_UUID_6"); | |||
} | |||
@Test | |||
public void delete_active_rules_without_rules_profiles() throws SQLException { | |||
long rulesProfileId1 = insertRulesProfile("RP_UUID_1", "Sonar Way", "Java", 1_000L, true); | |||
long rulesProfileId2 = insertRulesProfile("RP_UUID_2", "Sonar Way", "JavaScript", 1_000L, false); | |||
insertOrgQProfile("ORG_QP_UUID_1", "ORG_UUID_1", "RP_UUID_1"); | |||
insertOrgQProfile("ORG_QP_UUID_2", "ORG_UUID_1", "RP_UUID_2"); | |||
long activeRule1 = insertActiveRule(rulesProfileId1, 1); | |||
long activeRule2 = insertActiveRule(rulesProfileId2, 1); | |||
insertActiveRule(-1, 1); | |||
insertActiveRule(-2, 1); | |||
underTest.execute(); | |||
assertThat(selectActiveRules()).containsExactlyInAnyOrder(activeRule1, activeRule2); | |||
} | |||
@Test | |||
public void delete_active_rule_parameters_without_active_rules() throws SQLException { | |||
long rulesProfileId1 = insertRulesProfile("RP_UUID_1", "Sonar Way", "Java", 1_000L, true); | |||
long rulesProfileId2 = insertRulesProfile("RP_UUID_2", "Sonar Way", "JavaScript", 1_000L, false); | |||
insertOrgQProfile("ORG_QP_UUID_1", "ORG_UUID_1", "RP_UUID_1"); | |||
insertOrgQProfile("ORG_QP_UUID_2", "ORG_UUID_1", "RP_UUID_2"); | |||
long activeRuleId1 = insertActiveRule(rulesProfileId1, 1); | |||
long activeRuleId2 = insertActiveRule(rulesProfileId2, 1); | |||
long param1 = insertActiveRuleParameter(activeRuleId1, 1); | |||
long param2 = insertActiveRuleParameter(activeRuleId1, 2); | |||
long param3 = insertActiveRuleParameter(activeRuleId2, 2); | |||
insertActiveRuleParameter(-1, 1); | |||
insertActiveRuleParameter(-2, 1); | |||
underTest.execute(); | |||
assertThat(selectActiveRuleParameters()).containsExactlyInAnyOrder(param1, param2, param3); | |||
} | |||
@Test | |||
public void delete_qprofile_changes_without_rules_profiles() throws SQLException { | |||
long rulesProfileId1 = insertRulesProfile("RP_UUID_1", "Sonar Way", "Java", 1_000L, true); | |||
long rulesProfileId2 = insertRulesProfile("RP_UUID_2", "Sonar Way", "JavaScript", 1_000L, false); | |||
insertOrgQProfile("ORG_QP_UUID_1", "ORG_UUID_1", "RP_UUID_1"); | |||
insertOrgQProfile("ORG_QP_UUID_2", "ORG_UUID_1", "RP_UUID_2"); | |||
insertQProfileChange("QPC_UUID1", "RP_UUID_1", "A"); | |||
insertQProfileChange("QPC_UUID2", "RP_UUID_2", "B"); | |||
insertQProfileChange("QPC_UUID3", "RP_UUID_3", "A"); | |||
insertQProfileChange("QPC_UUID4", "RP_UUID_4", "A"); | |||
underTest.execute(); | |||
assertThat(selectQProfileChanges()).containsExactlyInAnyOrder("QPC_UUID1", "QPC_UUID2"); | |||
} | |||
@Test | |||
public void reentrant_migration() throws SQLException { | |||
long rulesProfileId1 = insertRulesProfile("RP_UUID_1", "Sonar Way", "Java", 1_000L, true); | |||
long rulesProfileId2 = insertRulesProfile("RP_UUID_2", "Sonar Way", "JavaScript", 1_000L, false); | |||
insertRulesProfile("RP_UUID_3", "Sonar Way", "PL/SQL", 1_000L, false); | |||
insertRulesProfile("RP_UUID_4", "Sonar Way", "Cobol", 1_000L, false); | |||
insertRulesProfile("RP_UUID_5", "Sonar Way", "Cobol", 1_000L, false); | |||
insertRulesProfile("RP_UUID_6", "Sonar Way", "Cobol", 1_000L, true); | |||
insertOrgQProfile("ORG_QP_UUID_1", "ORG_UUID_1", "RP_UUID_1"); | |||
insertOrgQProfile("ORG_QP_UUID_2", "ORG_UUID_1", "RP_UUID_2"); | |||
long activeRuleId1 = insertActiveRule(rulesProfileId1, 1); | |||
long activeRuleId2 = insertActiveRule(rulesProfileId2, 1); | |||
insertActiveRule(-1, 1); | |||
insertActiveRule(-2, 1); | |||
insertActiveRuleParameter(activeRuleId1, 1); | |||
insertActiveRuleParameter(activeRuleId1, 2); | |||
insertActiveRuleParameter(activeRuleId2, 2); | |||
insertActiveRuleParameter(-1, 1); | |||
insertActiveRuleParameter(-2, 1); | |||
insertQProfileChange("QPC_UUID1", "RP_UUID_1", "A"); | |||
insertQProfileChange("QPC_UUID2", "RP_UUID_2", "B"); | |||
insertQProfileChange("QPC_UUID3", "RP_UUID_3", "A"); | |||
insertQProfileChange("QPC_UUID4", "RP_UUID_4", "A"); | |||
underTest.execute(); | |||
underTest.execute(); | |||
assertThat(countRows("rules_profiles")).isEqualTo(2); | |||
assertThat(countRows("active_rules")).isEqualTo(2); | |||
assertThat(countRows("active_rule_parameters")).isEqualTo(3); | |||
assertThat(countRows("qprofile_changes")).isEqualTo(2); | |||
} | |||
private int countRows(String table) { | |||
return db.countSql(format("select count(*) from %s", table)); | |||
} | |||
private List<String> selectRulesProfiles() { | |||
return db.select("select kee as \"kee\" from rules_profiles") | |||
.stream() | |||
.map(row -> (String) row.get("kee")) | |||
.collect(MoreCollectors.toList()); | |||
} | |||
private List<String> selectQProfileChanges() { | |||
return db.select("select kee as \"kee\" from qprofile_changes") | |||
.stream() | |||
.map(row -> (String) row.get("kee")) | |||
.collect(MoreCollectors.toList()); | |||
} | |||
private List<Long> selectActiveRules() { | |||
return db.select("select id as \"id\" from active_rules") | |||
.stream() | |||
.map(row -> (Long) row.get("id")) | |||
.collect(MoreCollectors.toList()); | |||
} | |||
private List<Long> selectActiveRuleParameters() { | |||
return db.select("select id as \"id\" from active_rule_parameters") | |||
.stream() | |||
.map(row -> (Long) row.get("id")) | |||
.collect(MoreCollectors.toList()); | |||
} | |||
private long insertRulesProfile(String rulesProfileUuid, String name, String language, Long userUpdatedAt, boolean isBuiltIn) { | |||
db.executeInsert("RULES_PROFILES", | |||
"NAME", name, | |||
"LANGUAGE", language, | |||
"KEE", rulesProfileUuid, | |||
"USER_UPDATED_AT", userUpdatedAt, | |||
"IS_BUILT_IN", isBuiltIn, | |||
"LAST_USED", 1_000L, | |||
"CREATED_AT", new Date(1_000L), | |||
"UPDATED_AT", new Date(1_000L)); | |||
return (Long) db.selectFirst( | |||
format("select id as \"id\" from rules_profiles where kee='%s'", rulesProfileUuid)).get("id"); | |||
} | |||
private void insertOrgQProfile(String orgQProfileUuid, String orgUuid, String rulesProfileUuid) { | |||
db.executeInsert("ORG_QPROFILES", | |||
"UUID", orgQProfileUuid, | |||
"ORGANIZATION_UUID", orgUuid, | |||
"RULES_PROFILE_UUID", rulesProfileUuid, | |||
"CREATED_AT", 1_000L, | |||
"UPDATED_AT", 2_000L); | |||
} | |||
private long insertActiveRule(long profileId, long ruleId) { | |||
db.executeInsert("ACTIVE_RULES", | |||
"PROFILE_ID", profileId, | |||
"RULE_ID", ruleId, | |||
"FAILURE_LEVEL", 1, | |||
"INHERITANCE", "", | |||
"CREATED_AT", 1_000L, | |||
"UPDATED_AT", 2_000L); | |||
return (Long) db.selectFirst( | |||
format("select id as \"id\" from active_rules where profile_id = %d and rule_id = %d", profileId, ruleId)).get("id"); | |||
} | |||
private long insertActiveRuleParameter(long activeRuleId, long rulesParameterId) { | |||
db.executeInsert("ACTIVE_RULE_PARAMETERS", | |||
"ACTIVE_RULE_ID", activeRuleId, | |||
"RULES_PARAMETER_ID", rulesParameterId, | |||
"RULES_PARAMETER_KEY", "", | |||
"VALUE", ""); | |||
return (Long) db.selectFirst( | |||
format("select id as \"id\" from active_rule_parameters where active_rule_id=%d and rules_parameter_id=%d", activeRuleId, rulesParameterId)).get("id"); | |||
} | |||
private void insertQProfileChange(String uuid, String rulesProfileUuid, String changeType) { | |||
db.executeInsert("QPROFILE_CHANGES", | |||
"KEE", uuid, | |||
"QPROFILE_KEY", rulesProfileUuid, | |||
"CHANGE_TYPE", changeType, | |||
"USER_LOGIN", "", | |||
"CHANGE_DATA", "", | |||
"CREATED_AT", 1_000L); | |||
} | |||
} |
@@ -0,0 +1,158 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.v65; | |||
import java.sql.SQLException; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import java.util.stream.IntStream; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.db.CoreDbTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class SetRulesProfilesIsBuiltInToTrueForDefaultOrganizationTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(SetRulesProfilesIsBuiltInToTrueForDefaultOrganizationTest.class, "initial.sql"); | |||
private SetRulesProfilesIsBuiltInToTrueForDefaultOrganization underTest = new SetRulesProfilesIsBuiltInToTrueForDefaultOrganization(db.database()); | |||
@Test | |||
public void has_no_effect_if_table_is_empty() throws SQLException { | |||
underTest.execute(); | |||
assertThat(db.countRowsOfTable("rules_profiles")).isEqualTo(0); | |||
} | |||
@Test | |||
public void mark_rules_profiles_of_default_org_as_built_in() throws SQLException { | |||
enableOrganization(); | |||
String defaultOrganizationUuid = "ORG_UUID_1"; | |||
setDefaultOrganization(defaultOrganizationUuid); | |||
IntStream.rangeClosed(1, 3).forEach(i -> { | |||
insertProfile(defaultOrganizationUuid, "RP_UUID_" + i, false); | |||
insertProfile("ORG_UUID_404", "RP_UUID_404_" + i, false); | |||
}); | |||
underTest.execute(); | |||
assertThat(selectRulesProfiles(true)).containsExactlyInAnyOrder("RP_UUID_1", "RP_UUID_2", "RP_UUID_3"); | |||
assertThat(selectRulesProfiles(false)).containsExactlyInAnyOrder("RP_UUID_404_1", "RP_UUID_404_2", "RP_UUID_404_3"); | |||
} | |||
@Test | |||
public void do_nothing_if_org_disabled() throws SQLException { | |||
String defaultOrganizationUuid = "ORG_UUID_1"; | |||
setDefaultOrganization(defaultOrganizationUuid); | |||
IntStream.rangeClosed(1, 3).forEach(i -> { | |||
insertProfile(defaultOrganizationUuid, "RP_UUID_" + i, false); | |||
insertProfile("ORG_UUID_404", "RP_UUID_404_" + i, false); | |||
}); | |||
underTest.execute(); | |||
assertThat(selectRulesProfiles(false)).containsExactlyInAnyOrder("RP_UUID_1", "RP_UUID_2", "RP_UUID_3", "RP_UUID_404_1", "RP_UUID_404_2", "RP_UUID_404_3"); | |||
} | |||
@Test | |||
public void reentrant_migration() throws SQLException { | |||
enableOrganization(); | |||
String defaultOrganizationUuid = "ORG_UUID_1"; | |||
setDefaultOrganization(defaultOrganizationUuid); | |||
IntStream.rangeClosed(1, 3).forEach(i -> { | |||
insertProfile(defaultOrganizationUuid, "RP_UUID_" + i, false); | |||
insertProfile("ORG_UUID_404", "RP_UUID_404_" + i, false); | |||
}); | |||
underTest.execute(); | |||
underTest.execute(); | |||
assertThat(selectRulesProfiles(true)).containsExactlyInAnyOrder("RP_UUID_1", "RP_UUID_2", "RP_UUID_3"); | |||
assertThat(selectRulesProfiles(false)).containsExactlyInAnyOrder("RP_UUID_404_1", "RP_UUID_404_2", "RP_UUID_404_3"); | |||
} | |||
@Test | |||
public void reentrant_of_crashed_migration() throws SQLException { | |||
enableOrganization(); | |||
String defaultOrganizationUuid = "ORG_UUID_1"; | |||
setDefaultOrganization(defaultOrganizationUuid); | |||
insertProfile(defaultOrganizationUuid, "RP_UUID_1", true); | |||
insertProfile(defaultOrganizationUuid, "RP_UUID_2", false); | |||
insertProfile(defaultOrganizationUuid, "RP_UUID_3", false); | |||
underTest.execute(); | |||
assertThat(selectRulesProfiles(true)).containsExactlyInAnyOrder("RP_UUID_1", "RP_UUID_2", "RP_UUID_3"); | |||
} | |||
@Test | |||
public void fail_if_no_default_org_and_org_activated() throws SQLException { | |||
enableOrganization(); | |||
insertProfile("ORG_UUID_1", "RP_UUID_1", false); | |||
expectedException.expect(IllegalStateException.class); | |||
expectedException.expectMessage("Missing internal property: 'organization.default'"); | |||
underTest.execute(); | |||
} | |||
private Set<String> selectRulesProfiles(boolean isBuiltIn) { | |||
return db.select("select rp.kee as \"uuid\", rp.is_built_in as \"isBuiltIn\" from rules_profiles rp") | |||
.stream() | |||
.filter(row -> (boolean) row.get("isBuiltIn") == isBuiltIn) | |||
.map(row -> (String) row.get("uuid")) | |||
.collect(Collectors.toSet()); | |||
} | |||
private void enableOrganization() { | |||
db.executeInsert("INTERNAL_PROPERTIES", | |||
"KEE", "organization.enabled", | |||
"TEXT_VALUE", "true", | |||
"IS_EMPTY", false); | |||
} | |||
private void setDefaultOrganization(String uuid) { | |||
db.executeInsert("INTERNAL_PROPERTIES", | |||
"KEE", "organization.default", | |||
"TEXT_VALUE", uuid, | |||
"IS_EMPTY", false); | |||
} | |||
private void insertProfile(String orgUuid, String rulesProfileUuid, boolean isBuiltIn) { | |||
db.executeInsert("ORG_QPROFILES", | |||
"ORGANIZATION_UUID", orgUuid, | |||
"UUID", "OQP_UUID_" + rulesProfileUuid, | |||
"RULES_PROFILE_UUID", rulesProfileUuid, | |||
"CREATED_AT", 1_000L, | |||
"UPDATED_AT", 2_000L); | |||
db.executeInsert("RULES_PROFILES", | |||
"NAME", "name_" + rulesProfileUuid, | |||
"KEE", rulesProfileUuid, | |||
"LANGUAGE", "LANG_" + rulesProfileUuid, | |||
"IS_BUILT_IN", isBuiltIn); | |||
} | |||
} |
@@ -0,0 +1,201 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.v65; | |||
import java.sql.SQLException; | |||
import java.util.List; | |||
import javax.annotation.Nullable; | |||
import org.assertj.core.groups.Tuple; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.CoreDbTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.tuple; | |||
public class UpdateOrgQProfilesToPointToBuiltInProfilesTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(UpdateOrgQProfilesToPointToBuiltInProfilesTest.class, "initial.sql"); | |||
private UpdateOrgQProfilesToPointToBuiltInProfiles underTest = new UpdateOrgQProfilesToPointToBuiltInProfiles(db.database()); | |||
@Test | |||
public void has_no_effect_if_table_is_empty() throws SQLException { | |||
underTest.execute(); | |||
assertThat(db.countRowsOfTable("rules_profiles")).isEqualTo(0); | |||
} | |||
@Test | |||
public void has_no_effect_if_organization_are_disabled() throws SQLException { | |||
String defaultOrgUuid = "DEFAULT_ORG_UUID"; | |||
setDefaultOrganization(defaultOrgUuid); | |||
String sonarWayJava = "RP_UUID_1"; | |||
String sonarWayJavascript = "RP_UUID_2"; | |||
insertProfile(defaultOrgUuid, "OQP_UUID_1", sonarWayJava, "Sonar way", "Java", true, 1_000_000_000L); | |||
insertProfile(defaultOrgUuid, "OQP_UUID_2", sonarWayJavascript, "Sonar way", "Javascript", true, null); | |||
insertProfile(defaultOrgUuid, "OQP_UUID_3", "RP_UUID_3", "Sonar way", "Cobol", true, null); | |||
insertProfile(defaultOrgUuid, "OQP_UUID_4", "RP_UUID_4", "My Sonar way", "Java", false, null); | |||
underTest.execute(); | |||
assertThat(selectRulesProfiles()).containsExactlyInAnyOrder( | |||
tuple("OQP_UUID_1", sonarWayJava), | |||
tuple("OQP_UUID_2", sonarWayJavascript), | |||
tuple("OQP_UUID_3", "RP_UUID_3"), | |||
tuple("OQP_UUID_4", "RP_UUID_4")); | |||
} | |||
@Test | |||
public void update_org_qprofiles_to_point_to_built_in_rules_profiles() throws SQLException { | |||
enableOrganization(); | |||
String defaultOrgUuid = "DEFAULT_ORG_UUID"; | |||
setDefaultOrganization(defaultOrgUuid); | |||
String sonarWayJava = "RP_UUID_1"; | |||
String sonarWayJavascript = "RP_UUID_2"; | |||
insertProfile(defaultOrgUuid, "OQP_UUID_1", sonarWayJava, "Sonar way", "Java", true, 1_000_000_000L); | |||
insertProfile(defaultOrgUuid, "OQP_UUID_2", sonarWayJavascript, "Sonar way", "Javascript", true, null); | |||
insertProfile(defaultOrgUuid, "OQP_UUID_3", "RP_UUID_3", "Sonar way", "Cobol", true, null); | |||
insertProfile("ORG_UUID_1", "OQP_UUID_4", "RP_UUID_4", "Sonar way", "Java", false, null); | |||
insertProfile("ORG_UUID_1", "OQP_UUID_5", "RP_UUID_5", "My Sonar way", "Java", false, null); | |||
insertProfile("ORG_UUID_2", "OQP_UUID_6", "RP_UUID_6", "Sonar way", "Javascript", false, null); | |||
insertProfile("ORG_UUID_2", "OQP_UUID_7", "RP_UUID_7", "Sonar way", "Python", false, null); | |||
insertProfile("ORG_UUID_2", "OQP_UUID_8", "RP_UUID_8", "Sonar way", "Java", false, 2_000_000_000L); | |||
underTest.execute(); | |||
assertThat(selectRulesProfiles()).containsExactlyInAnyOrder( | |||
tuple("OQP_UUID_1", sonarWayJava), | |||
tuple("OQP_UUID_2", sonarWayJavascript), | |||
tuple("OQP_UUID_3", "RP_UUID_3"), | |||
tuple("OQP_UUID_4", sonarWayJava), | |||
tuple("OQP_UUID_5", "RP_UUID_5"), | |||
tuple("OQP_UUID_6", sonarWayJavascript), | |||
tuple("OQP_UUID_7", "RP_UUID_7"), | |||
tuple("OQP_UUID_8", "RP_UUID_8")); | |||
} | |||
@Test | |||
public void migration_is_reentrant() throws SQLException { | |||
enableOrganization(); | |||
String defaultOrgUuid = "DEFAULT_ORG_UUID"; | |||
setDefaultOrganization(defaultOrgUuid); | |||
String sonarWayJava = "RP_UUID_1"; | |||
String sonarWayJavascript = "RP_UUID_2"; | |||
insertProfile(defaultOrgUuid, "OQP_UUID_1", sonarWayJava, "Sonar way", "Java", true, 1_000_000_000L); | |||
insertProfile(defaultOrgUuid, "OQP_UUID_2", sonarWayJavascript, "Sonar way", "Javascript", true, null); | |||
insertProfile("ORG_UUID_1", "OQP_UUID_4", "RP_UUID_4", "Sonar way", "Java", false, null); | |||
insertProfile("ORG_UUID_1", "OQP_UUID_5", "RP_UUID_5", "My Sonar way", "Java", false, null); | |||
underTest.execute(); | |||
underTest.execute(); | |||
assertThat(selectRulesProfiles()).containsExactlyInAnyOrder( | |||
tuple("OQP_UUID_1", sonarWayJava), | |||
tuple("OQP_UUID_2", sonarWayJavascript), | |||
tuple("OQP_UUID_4", sonarWayJava), | |||
tuple("OQP_UUID_5", "RP_UUID_5")); | |||
} | |||
@Test | |||
public void crashed_migration_is_reentrant() throws SQLException { | |||
enableOrganization(); | |||
String defaultOrgUuid = "DEFAULT_ORG_UUID"; | |||
setDefaultOrganization(defaultOrgUuid); | |||
String sonarWayJava = "RP_UUID_1"; | |||
String sonarWayJavascript = "RP_UUID_2"; | |||
insertProfile(defaultOrgUuid, "OQP_UUID_1", sonarWayJava, "Sonar way", "Java", true, 1_000_000_000L); | |||
insertProfile(defaultOrgUuid, "OQP_UUID_2", sonarWayJavascript, "Sonar way", "Javascript", true, null); | |||
insertOrgQProfile("ORG_UUID_1", "OQP_UUID_3", sonarWayJava); | |||
insertProfile("ORG_UUID_1", "OQP_UUID_4", "RP_UUID_4", "Sonar way", "Javascript", false, null); | |||
insertProfile("ORG_UUID_1", "OQP_UUID_5", "RP_UUID_5", "My Sonar way", "Java", false, null); | |||
underTest.execute(); | |||
assertThat(selectRulesProfiles()).containsExactlyInAnyOrder( | |||
tuple("OQP_UUID_1", sonarWayJava), | |||
tuple("OQP_UUID_2", sonarWayJavascript), | |||
tuple("OQP_UUID_3", sonarWayJava), | |||
tuple("OQP_UUID_4", sonarWayJavascript), | |||
tuple("OQP_UUID_5", "RP_UUID_5")); | |||
} | |||
@Test | |||
public void fail_if_no_default_org_and_org_activated() throws SQLException { | |||
enableOrganization(); | |||
expectedException.expect(IllegalStateException.class); | |||
expectedException.expectMessage("Missing internal property: 'organization.default'"); | |||
underTest.execute(); | |||
} | |||
private List<Tuple> selectRulesProfiles() { | |||
return db.select("select oqp.uuid as \"uuid\", oqp.rules_profile_uuid as \"rulesProfileUuid\" from org_qprofiles oqp") | |||
.stream() | |||
.map(row -> tuple(row.get("uuid"), row.get("rulesProfileUuid"))) | |||
.collect(MoreCollectors.toList()); | |||
} | |||
private void enableOrganization() { | |||
db.executeInsert("INTERNAL_PROPERTIES", | |||
"KEE", "organization.enabled", | |||
"TEXT_VALUE", "true", | |||
"IS_EMPTY", false); | |||
} | |||
private void setDefaultOrganization(String uuid) { | |||
db.executeInsert("INTERNAL_PROPERTIES", | |||
"KEE", "organization.default", | |||
"TEXT_VALUE", uuid, | |||
"IS_EMPTY", false); | |||
} | |||
private void insertProfile(String orgUuid, String orgQProfileUuid, String rulesProfileUuid, String name, String language, boolean isBuiltIn, @Nullable Long userUpdatedAt) { | |||
db.executeInsert("ORG_QPROFILES", | |||
"ORGANIZATION_UUID", orgUuid, | |||
"UUID", orgQProfileUuid, | |||
"RULES_PROFILE_UUID", rulesProfileUuid, | |||
"CREATED_AT", 1_000L, | |||
"UPDATED_AT", 2_000L); | |||
db.executeInsert("RULES_PROFILES", | |||
"NAME", name, | |||
"KEE", rulesProfileUuid, | |||
"LANGUAGE", language, | |||
"IS_BUILT_IN", isBuiltIn, | |||
"USER_UPDATED_AT", userUpdatedAt); | |||
} | |||
private void insertOrgQProfile(String orgUuid, String orgQProfileUuid, String rulesProfileUuid) { | |||
db.executeInsert("ORG_QPROFILES", | |||
"ORGANIZATION_UUID", orgUuid, | |||
"UUID", orgQProfileUuid, | |||
"RULES_PROFILE_UUID", rulesProfileUuid, | |||
"CREATED_AT", 1_000L, | |||
"UPDATED_AT", 2_000L); | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
CREATE TABLE "RULES_PROFILES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"NAME" VARCHAR(100) NOT NULL, | |||
"LANGUAGE" VARCHAR(20), | |||
"KEE" VARCHAR(255) NOT NULL, | |||
"RULES_UPDATED_AT" VARCHAR(100), | |||
"CREATED_AT" TIMESTAMP, | |||
"UPDATED_AT" TIMESTAMP, | |||
"LAST_USED" BIGINT, | |||
"USER_UPDATED_AT" BIGINT, | |||
"IS_BUILT_IN" BOOLEAN NOT NULL | |||
); | |||
CREATE UNIQUE INDEX "UNIQ_QPROF_KEY" ON "RULES_PROFILES" ("KEE"); | |||
CREATE TABLE "ORG_QPROFILES" ( | |||
"UUID" VARCHAR(40) NOT NULL PRIMARY KEY, | |||
"ORGANIZATION_UUID" VARCHAR(40) NOT NULL, | |||
"RULES_PROFILE_UUID" VARCHAR(40) NOT NULL, | |||
"PARENT_UUID" VARCHAR(40), | |||
"CREATED_AT" BIGINT NOT NULL, | |||
"UPDATED_AT" BIGINT NOT NULL | |||
); | |||
CREATE INDEX "ORG_QPROFILES_ORG_UUID" ON "ORG_QPROFILES" ("ORGANIZATION_UUID"); | |||
CREATE INDEX "ORG_QPROFILES_RP_UUID" ON "ORG_QPROFILES" ("RULES_PROFILE_UUID"); | |||
CREATE TABLE "ACTIVE_RULES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"PROFILE_ID" INTEGER NOT NULL, | |||
"RULE_ID" INTEGER NOT NULL, | |||
"FAILURE_LEVEL" INTEGER NOT NULL, | |||
"INHERITANCE" VARCHAR(10), | |||
"CREATED_AT" BIGINT, | |||
"UPDATED_AT" BIGINT | |||
); | |||
CREATE UNIQUE INDEX "ACTIVE_RULES_UNIQUE" ON "ACTIVE_RULES" ("PROFILE_ID","RULE_ID"); | |||
CREATE TABLE "ACTIVE_RULE_PARAMETERS" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"ACTIVE_RULE_ID" INTEGER NOT NULL, | |||
"RULES_PARAMETER_ID" INTEGER NOT NULL, | |||
"RULES_PARAMETER_KEY" VARCHAR(128), | |||
"VALUE" VARCHAR(4000) | |||
); | |||
CREATE INDEX "IX_ARP_ON_ACTIVE_RULE_ID" ON "ACTIVE_RULE_PARAMETERS" ("ACTIVE_RULE_ID"); | |||
CREATE TABLE "QPROFILE_CHANGES" ( | |||
"KEE" VARCHAR(40) NOT NULL PRIMARY KEY, | |||
"QPROFILE_KEY" VARCHAR(255) NOT NULL, | |||
"CHANGE_TYPE" VARCHAR(20) NOT NULL, | |||
"CREATED_AT" BIGINT NOT NULL, | |||
"USER_LOGIN" VARCHAR(255), | |||
"CHANGE_DATA" CLOB | |||
); | |||
CREATE INDEX "QPROFILE_CHANGES_QPROFILE_KEY" ON "QPROFILE_CHANGES" ("QPROFILE_KEY"); |
@@ -0,0 +1,34 @@ | |||
CREATE TABLE "RULES_PROFILES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"NAME" VARCHAR(100) NOT NULL, | |||
"LANGUAGE" VARCHAR(20), | |||
"KEE" VARCHAR(255) NOT NULL, | |||
"RULES_UPDATED_AT" VARCHAR(100), | |||
"CREATED_AT" TIMESTAMP, | |||
"UPDATED_AT" TIMESTAMP, | |||
"LAST_USED" BIGINT, | |||
"USER_UPDATED_AT" BIGINT, | |||
"IS_BUILT_IN" BOOLEAN NOT NULL | |||
); | |||
CREATE UNIQUE INDEX "UNIQ_QPROF_KEY" ON "RULES_PROFILES" ("KEE"); | |||
CREATE TABLE "ORG_QPROFILES" ( | |||
"UUID" VARCHAR(40) NOT NULL PRIMARY KEY, | |||
"ORGANIZATION_UUID" VARCHAR(40) NOT NULL, | |||
"RULES_PROFILE_UUID" VARCHAR(40) NOT NULL, | |||
"PARENT_UUID" VARCHAR(40), | |||
"CREATED_AT" BIGINT NOT NULL, | |||
"UPDATED_AT" BIGINT NOT NULL | |||
); | |||
CREATE INDEX "ORG_QPROFILES_ORG_UUID" ON "ORG_QPROFILES" ("ORGANIZATION_UUID"); | |||
CREATE INDEX "ORG_QPROFILES_RP_UUID" ON "ORG_QPROFILES" ("RULES_PROFILE_UUID"); | |||
CREATE TABLE "INTERNAL_PROPERTIES" ( | |||
"KEE" VARCHAR(50) NOT NULL PRIMARY KEY, | |||
"IS_EMPTY" BOOLEAN NOT NULL, | |||
"TEXT_VALUE" VARCHAR(4000), | |||
"CLOB_VALUE" CLOB, | |||
"CREATED_AT" BIGINT | |||
); | |||
CREATE UNIQUE INDEX "UNIQ_INTERNAL_PROPERTIES" ON "INTERNAL_PROPERTIES" ("KEE"); |
@@ -0,0 +1,33 @@ | |||
CREATE TABLE "RULES_PROFILES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"NAME" VARCHAR(100) NOT NULL, | |||
"LANGUAGE" VARCHAR(20), | |||
"KEE" VARCHAR(255) NOT NULL, | |||
"RULES_UPDATED_AT" VARCHAR(100), | |||
"CREATED_AT" TIMESTAMP, | |||
"UPDATED_AT" TIMESTAMP, | |||
"LAST_USED" BIGINT, | |||
"USER_UPDATED_AT" BIGINT, | |||
"IS_BUILT_IN" BOOLEAN NOT NULL | |||
); | |||
CREATE UNIQUE INDEX "UNIQ_QPROF_KEY" ON "RULES_PROFILES" ("KEE"); | |||
CREATE TABLE "ORG_QPROFILES" ( | |||
"UUID" VARCHAR(40) NOT NULL PRIMARY KEY, | |||
"ORGANIZATION_UUID" VARCHAR(40) NOT NULL, | |||
"RULES_PROFILE_UUID" VARCHAR(40) NOT NULL, | |||
"PARENT_UUID" VARCHAR(40), | |||
"CREATED_AT" BIGINT NOT NULL, | |||
"UPDATED_AT" BIGINT NOT NULL | |||
); | |||
CREATE INDEX "ORG_QPROFILES_ORG_UUID" ON "ORG_QPROFILES" ("ORGANIZATION_UUID"); | |||
CREATE INDEX "ORG_QPROFILES_RP_UUID" ON "ORG_QPROFILES" ("RULES_PROFILE_UUID"); | |||
CREATE TABLE "INTERNAL_PROPERTIES" ( | |||
"KEE" VARCHAR(50) NOT NULL PRIMARY KEY, | |||
"IS_EMPTY" BOOLEAN NOT NULL, | |||
"TEXT_VALUE" VARCHAR(4000), | |||
"CLOB_VALUE" CLOB, | |||
"CREATED_AT" BIGINT | |||
); | |||
CREATE UNIQUE INDEX "UNIQ_INTERNAL_PROPERTIES" ON "INTERNAL_PROPERTIES" ("KEE"); |
@@ -20,12 +20,11 @@ | |||
package org.sonar.server.es; | |||
import java.util.Date; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import static com.google.common.collect.Maps.newHashMap; | |||
/** | |||
* Base implementation for business objects based on elasticsearch document | |||
*/ | |||
@@ -34,7 +33,7 @@ public abstract class BaseDoc { | |||
protected final Map<String, Object> fields; | |||
protected BaseDoc() { | |||
this.fields = newHashMap(); | |||
this.fields = new HashMap<>(); | |||
} | |||
protected BaseDoc(Map<String, Object> fields) { |
@@ -140,7 +140,7 @@ public class BulkIndexer implements Startable { | |||
} | |||
public void addDeletion(IndexType indexType, String id) { | |||
add(client.prepareDelete(indexType, id).request()); | |||
add(client.prepareDelete(indexType, id).setRouting(id).request()); | |||
} | |||
public void addDeletion(IndexType indexType, String id, String routing) { |
@@ -32,7 +32,7 @@ public class IssueIteratorFactory { | |||
} | |||
public IssueIterator createForAll() { | |||
return createForProject((String) null); | |||
return createForProject(null); | |||
} | |||
public IssueIterator createForProject(@Nullable String projectUuid) { |
@@ -19,14 +19,15 @@ | |||
*/ | |||
package org.sonar.server.organization; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Optional; | |||
import java.util.function.Consumer; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.core.config.CorePropertyDefinitions; | |||
import org.sonar.core.util.UuidFactory; | |||
import org.sonar.db.DbClient; | |||
@@ -39,13 +40,14 @@ import org.sonar.db.permission.OrganizationPermission; | |||
import org.sonar.db.permission.UserPermissionDto; | |||
import org.sonar.db.permission.template.PermissionTemplateCharacteristicDto; | |||
import org.sonar.db.permission.template.PermissionTemplateDto; | |||
import org.sonar.db.qualityprofile.DefaultQProfileDto; | |||
import org.sonar.db.qualityprofile.OrgQProfileDto; | |||
import org.sonar.db.user.GroupDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.db.user.UserGroupDto; | |||
import org.sonar.server.qualityprofile.BuiltInQProfile; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileInsert; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileRepository; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.qualityprofile.QProfileName; | |||
import org.sonar.server.user.index.UserIndexer; | |||
import org.sonar.server.usergroups.DefaultGroupCreator; | |||
@@ -56,11 +58,11 @@ import static org.sonar.api.web.UserRole.ADMIN; | |||
import static org.sonar.api.web.UserRole.CODEVIEWER; | |||
import static org.sonar.api.web.UserRole.ISSUE_ADMIN; | |||
import static org.sonar.api.web.UserRole.USER; | |||
import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex; | |||
import static org.sonar.db.permission.OrganizationPermission.SCAN; | |||
import static org.sonar.server.organization.OrganizationCreation.NewOrganization.newOrganizationBuilder; | |||
public class OrganizationCreationImpl implements OrganizationCreation { | |||
private static final Logger LOGGER = Loggers.get(OrganizationCreationImpl.class); | |||
private final DbClient dbClient; | |||
private final System2 system2; | |||
@@ -68,15 +70,13 @@ public class OrganizationCreationImpl implements OrganizationCreation { | |||
private final OrganizationValidation organizationValidation; | |||
private final Settings settings; | |||
private final BuiltInQProfileRepository builtInQProfileRepository; | |||
private final BuiltInQProfileInsert builtInQProfileInsert; | |||
private final DefaultGroupCreator defaultGroupCreator; | |||
private final UserIndexer userIndexer; | |||
private final ActiveRuleIndexer activeRuleIndexer; | |||
public OrganizationCreationImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory, | |||
OrganizationValidation organizationValidation, Settings settings, UserIndexer userIndexer, | |||
BuiltInQProfileRepository builtInQProfileRepository, BuiltInQProfileInsert builtInQProfileInsert, | |||
DefaultGroupCreator defaultGroupCreator, ActiveRuleIndexer activeRuleIndexer) { | |||
BuiltInQProfileRepository builtInQProfileRepository, | |||
DefaultGroupCreator defaultGroupCreator) { | |||
this.dbClient = dbClient; | |||
this.system2 = system2; | |||
this.uuidFactory = uuidFactory; | |||
@@ -84,9 +84,7 @@ public class OrganizationCreationImpl implements OrganizationCreation { | |||
this.settings = settings; | |||
this.userIndexer = userIndexer; | |||
this.builtInQProfileRepository = builtInQProfileRepository; | |||
this.builtInQProfileInsert = builtInQProfileInsert; | |||
this.defaultGroupCreator = defaultGroupCreator; | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
} | |||
@Override | |||
@@ -111,7 +109,6 @@ public class OrganizationCreationImpl implements OrganizationCreation { | |||
dbSession.commit(); | |||
batchDbSession.commit(); | |||
activeRuleIndexer.index(); | |||
// Elasticsearch is updated when DB session is committed | |||
userIndexer.index(userCreator.getLogin()); | |||
@@ -150,7 +147,6 @@ public class OrganizationCreationImpl implements OrganizationCreation { | |||
dbSession.commit(); | |||
batchDbSession.commit(); | |||
activeRuleIndexer.index(); | |||
// Elasticsearch is updated when DB session is committed | |||
userIndexer.index(newUser.getLogin()); | |||
@@ -268,16 +264,31 @@ public class OrganizationCreationImpl implements OrganizationCreation { | |||
} | |||
private void insertQualityProfiles(DbSession dbSession, DbSession batchDbSession, OrganizationDto organization) { | |||
builtInQProfileRepository.getQProfilesByLanguage().entrySet() | |||
.stream() | |||
.flatMap(entry -> entry.getValue().stream()) | |||
.forEach(profile -> insertQualityProfile(dbSession, batchDbSession, profile, organization)); | |||
} | |||
private void insertQualityProfile(DbSession regularSession, DbSession batchDbSession, BuiltInQProfile profile, OrganizationDto organization) { | |||
LOGGER.debug("Creating quality profile {} for language {} for organization {}", profile.getName(), profile.getLanguage(), organization.getKey()); | |||
Map<QProfileName, BuiltInQProfile> builtInsPerName = builtInQProfileRepository.get().stream() | |||
.collect(uniqueIndex(BuiltInQProfile::getQProfileName)); | |||
List<DefaultQProfileDto> defaults = new ArrayList<>(); | |||
dbClient.qualityProfileDao().selectBuiltInRulesProfiles(dbSession).forEach(rulesProfile -> { | |||
OrgQProfileDto dto = new OrgQProfileDto() | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setRulesProfileUuid(rulesProfile.getKee()) | |||
.setUuid(uuidFactory.create()); | |||
QProfileName name = new QProfileName(rulesProfile.getLanguage(), rulesProfile.getName()); | |||
BuiltInQProfile builtIn = builtInsPerName.get(name); | |||
if (builtIn != null && builtIn.isDefault()) { | |||
// rows of table default_qprofiles must be inserted after org_qprofiles | |||
// in order to benefit from batch SQL inserts | |||
defaults.add(new DefaultQProfileDto() | |||
.setQProfileUuid(dto.getUuid()) | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setLanguage(builtIn.getLanguage())); | |||
} | |||
dbClient.qualityProfileDao().insert(batchDbSession, dto); | |||
}); | |||
builtInQProfileInsert.create(regularSession, batchDbSession, profile, organization); | |||
defaults.forEach(defaultQProfileDto -> dbClient.defaultQProfileDao().insertOrUpdate(dbSession, defaultQProfileDto)); | |||
} | |||
/** |
@@ -23,7 +23,6 @@ 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; | |||
@@ -134,12 +133,8 @@ public class DeleteAction implements OrganizationsWsAction { | |||
} | |||
private void deleteQualityProfiles(DbSession dbSession, OrganizationDto organization) { | |||
List<QProfileDto> profiles = dbClient.qualityProfileDao().selectAll(dbSession, organization); | |||
List<String> profileKeys = profiles.stream() | |||
.map(QProfileDto::getKee) | |||
.collect(MoreCollectors.toArrayList(profiles.size())); | |||
qProfileFactory.deleteByKeys(dbSession, profileKeys); | |||
dbSession.commit(); | |||
List<QProfileDto> profiles = dbClient.qualityProfileDao().selectOrderedByOrganizationUuid(dbSession, organization); | |||
qProfileFactory.delete(dbSession, profiles); | |||
} | |||
private void deleteOrganization(DbSession dbSession, OrganizationDto organization) { |
@@ -141,7 +141,6 @@ import org.sonar.server.projecttag.ws.ProjectTagsWsModule; | |||
import org.sonar.server.property.InternalPropertiesImpl; | |||
import org.sonar.server.property.ws.PropertiesWs; | |||
import org.sonar.server.qualitygate.QualityGateModule; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileInsertImpl; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileRepositoryImpl; | |||
import org.sonar.server.qualityprofile.QProfileBackuperImpl; | |||
import org.sonar.server.qualityprofile.QProfileComparison; | |||
@@ -153,6 +152,7 @@ import org.sonar.server.qualityprofile.QProfileResetImpl; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.RuleActivatorContextFactory; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIteratorFactory; | |||
import org.sonar.server.qualityprofile.ws.OldRestoreAction; | |||
import org.sonar.server.qualityprofile.ws.ProfilesWs; | |||
import org.sonar.server.qualityprofile.ws.QProfilesWsModule; | |||
@@ -260,7 +260,7 @@ public class PlatformLevel4 extends PlatformLevel { | |||
// quality profile | |||
BuiltInQProfileRepositoryImpl.class, | |||
BuiltInQProfileInsertImpl.class, | |||
ActiveRuleIteratorFactory.class, | |||
ActiveRuleIndexer.class, | |||
XMLProfileParser.class, | |||
XMLProfileSerializer.class, |
@@ -25,6 +25,7 @@ import org.sonar.server.organization.DefaultOrganizationEnforcer; | |||
import org.sonar.server.platform.ServerLifecycleNotifier; | |||
import org.sonar.server.platform.web.RegisterServletFilters; | |||
import org.sonar.server.qualitygate.RegisterQualityGates; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileInsertImpl; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileLoader; | |||
import org.sonar.server.qualityprofile.RegisterQualityProfiles; | |||
import org.sonar.server.rule.RegisterRules; | |||
@@ -56,6 +57,7 @@ public class PlatformLevelStartup extends PlatformLevel { | |||
RegisterRules.class); | |||
add(BuiltInQProfileLoader.class); | |||
addIfStartupLeader( | |||
BuiltInQProfileInsertImpl.class, | |||
RegisterQualityProfiles.class, | |||
RegisterPermissionTemplates.class, | |||
RenameDeprecatedPropertyKeys.class, |
@@ -20,17 +20,19 @@ | |||
package org.sonar.server.qualityprofile; | |||
import com.google.common.base.MoreObjects; | |||
import com.google.common.collect.Maps; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.qualityprofile.QProfileChangeDto; | |||
public class ActiveRuleChange { | |||
private ActiveRuleDto activeRule; | |||
public enum Type { | |||
ACTIVATED, DEACTIVATED, UPDATED | |||
} | |||
@@ -39,9 +41,15 @@ public class ActiveRuleChange { | |||
private final ActiveRuleKey key; | |||
private String severity = null; | |||
private ActiveRule.Inheritance inheritance = null; | |||
private Map<String, String> parameters = Maps.newHashMap(); | |||
private final Map<String, String> parameters = new HashMap<>(); | |||
public ActiveRuleChange(Type type, ActiveRuleDto activeRule) { | |||
this.type = type; | |||
this.key = activeRule.getKey(); | |||
this.activeRule = activeRule; | |||
} | |||
private ActiveRuleChange(Type type, ActiveRuleKey key) { | |||
public ActiveRuleChange(Type type, ActiveRuleKey key) { | |||
this.type = type; | |||
this.key = key; | |||
} | |||
@@ -89,14 +97,23 @@ public class ActiveRuleChange { | |||
return this; | |||
} | |||
@CheckForNull | |||
public ActiveRuleDto getActiveRule() { | |||
return activeRule; | |||
} | |||
public ActiveRuleChange setActiveRule(@Nullable ActiveRuleDto activeRule) { | |||
this.activeRule = activeRule; | |||
return this; | |||
} | |||
public QProfileChangeDto toDto(@Nullable String login) { | |||
QProfileChangeDto dto = new QProfileChangeDto(); | |||
dto.setChangeType(type.name()); | |||
dto.setProfileKey(getKey().qProfile()); | |||
dto.setRulesProfileUuid(getKey().getRuleProfileUuid()); | |||
dto.setLogin(login); | |||
Map<String, String> data = new HashMap<>(); | |||
data.put("key", getKey().toString()); | |||
data.put("ruleKey", getKey().ruleKey().toString()); | |||
data.put("ruleKey", getKey().getRuleKey().toString()); | |||
parameters.entrySet().stream() | |||
.filter(param -> !param.getKey().isEmpty()) | |||
@@ -112,10 +129,6 @@ public class ActiveRuleChange { | |||
return dto; | |||
} | |||
public static ActiveRuleChange createFor(Type type, ActiveRuleKey key) { | |||
return new ActiveRuleChange(type, key); | |||
} | |||
@Override | |||
public String toString() { | |||
return MoreObjects.toStringHelper(this) |
@@ -35,7 +35,7 @@ public final class BuiltInQProfile { | |||
private final List<org.sonar.api.rules.ActiveRule> activeRules; | |||
private BuiltInQProfile(Builder builder) { | |||
this.qProfileName = new QProfileName(builder.language, builder.getName()); | |||
this.qProfileName = new QProfileName(builder.language, builder.name); | |||
this.isDefault = builder.declaredDefault || builder.computedDefault; | |||
this.activeRules = ImmutableList.copyOf(builder.activeRules); | |||
} |
@@ -20,8 +20,11 @@ | |||
package org.sonar.server.qualityprofile; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
public interface BuiltInQProfileInsert { | |||
void create(DbSession session, DbSession batchSession, BuiltInQProfile builtInQProfile, OrganizationDto organization); | |||
/** | |||
* Persist a built-in profile and associate it to all existing organizations. | |||
* Db sessions are committed. | |||
*/ | |||
void create(DbSession session, DbSession batchSession, BuiltInQProfile builtInQProfile); | |||
} |
@@ -22,6 +22,7 @@ package org.sonar.server.qualityprofile; | |||
import com.google.common.base.Splitter; | |||
import com.google.common.collect.ImmutableSet; | |||
import com.google.common.collect.Sets; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.Date; | |||
import java.util.HashMap; | |||
@@ -42,14 +43,15 @@ import org.sonar.core.util.UuidFactory; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.DefaultQProfileDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.qualityprofile.OrgQProfileDto; | |||
import org.sonar.db.qualityprofile.RulesProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.util.TypeValidations; | |||
import static com.google.common.base.MoreObjects.firstNonNull; | |||
@@ -61,64 +63,98 @@ public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert { | |||
private final System2 system2; | |||
private final UuidFactory uuidFactory; | |||
private final TypeValidations typeValidations; | |||
private final ActiveRuleIndexer activeRuleIndexer; | |||
private RuleRepository ruleRepository; | |||
public BuiltInQProfileInsertImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory, TypeValidations typeValidations) { | |||
public BuiltInQProfileInsertImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory, TypeValidations typeValidations, ActiveRuleIndexer activeRuleIndexer) { | |||
this.dbClient = dbClient; | |||
this.system2 = system2; | |||
this.uuidFactory = uuidFactory; | |||
this.typeValidations = typeValidations; | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
} | |||
@Override | |||
public void create(DbSession session, DbSession batchSession, BuiltInQProfile builtInQProfile, OrganizationDto organization) { | |||
initRuleRepository(batchSession); | |||
public void create(DbSession dbSession, DbSession batchDbSession, BuiltInQProfile builtInQProfile) { | |||
initRuleRepository(batchDbSession); | |||
Date now = new Date(system2.now()); | |||
QProfileDto profileDto = insertQualityProfile(session, builtInQProfile, organization, now); | |||
RulesProfileDto ruleProfile = insertRulesProfile(dbSession, builtInQProfile, now); | |||
List<ActiveRuleChange> localChanges = builtInQProfile.getActiveRules() | |||
.stream() | |||
.map(activeRule -> insertActiveRule(session, profileDto, activeRule, now.getTime())) | |||
.map(activeRule -> insertActiveRule(dbSession, ruleProfile, activeRule, now.getTime())) | |||
.collect(MoreCollectors.toList()); | |||
localChanges.forEach(change -> dbClient.qProfileChangeDao().insert(batchSession, change.toDto(null))); | |||
localChanges.forEach(change -> dbClient.qProfileChangeDao().insert(batchDbSession, change.toDto(null))); | |||
associateToOrganizations(dbSession, batchDbSession, builtInQProfile, ruleProfile); | |||
dbSession.commit(); | |||
batchDbSession.commit(); | |||
activeRuleIndexer.indexRuleProfile(dbSession, ruleProfile); | |||
} | |||
private void initRuleRepository(DbSession session) { | |||
private void associateToOrganizations(DbSession dbSession, DbSession batchDbSession, BuiltInQProfile builtInQProfile, RulesProfileDto rulesProfileDto) { | |||
List<String> orgUuids = dbClient.organizationDao().selectAllUuids(dbSession); | |||
List<DefaultQProfileDto> defaults = new ArrayList<>(); | |||
orgUuids.forEach(orgUuid -> { | |||
OrgQProfileDto dto = new OrgQProfileDto() | |||
.setOrganizationUuid(orgUuid) | |||
.setRulesProfileUuid(rulesProfileDto.getKee()) | |||
.setUuid(uuidFactory.create()); | |||
if (builtInQProfile.isDefault()) { | |||
// rows of table default_qprofiles must be inserted after | |||
// in order to benefit from batch SQL inserts | |||
defaults.add(new DefaultQProfileDto() | |||
.setQProfileUuid(dto.getUuid()) | |||
.setOrganizationUuid(orgUuid) | |||
.setLanguage(builtInQProfile.getLanguage())); | |||
} | |||
dbClient.qualityProfileDao().insert(batchDbSession, dto); | |||
}); | |||
defaults.forEach(defaultQProfileDto -> dbClient.defaultQProfileDao().insertOrUpdate(dbSession, defaultQProfileDto)); | |||
} | |||
private void initRuleRepository(DbSession dbSession) { | |||
if (ruleRepository == null) { | |||
ruleRepository = new RuleRepository(dbClient, session); | |||
ruleRepository = new RuleRepository(dbClient, dbSession); | |||
} | |||
} | |||
private QProfileDto insertQualityProfile(DbSession dbSession, BuiltInQProfile builtInQProfile, OrganizationDto organization, Date now) { | |||
QProfileDto profileDto = QProfileDto.createFor(uuidFactory.create()) | |||
.setName(builtInQProfile.getName()) | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setLanguage(builtInQProfile.getLanguage()) | |||
private RulesProfileDto insertRulesProfile(DbSession dbSession, BuiltInQProfile builtIn, Date now) { | |||
RulesProfileDto dto = new RulesProfileDto() | |||
.setKee(uuidFactory.create()) | |||
.setName(builtIn.getName()) | |||
.setLanguage(builtIn.getLanguage()) | |||
.setIsBuiltIn(true) | |||
.setRulesUpdatedAtAsDate(now); | |||
dbClient.qualityProfileDao().insert(dbSession, profileDto); | |||
if (builtInQProfile.isDefault()) { | |||
dbClient.defaultQProfileDao().insertOrUpdate(dbSession, DefaultQProfileDto.from(profileDto)); | |||
} | |||
return profileDto; | |||
dbClient.qualityProfileDao().insert(dbSession, dto); | |||
return dto; | |||
} | |||
private ActiveRuleChange insertActiveRule(DbSession session, QProfileDto profileDto, org.sonar.api.rules.ActiveRule activeRule, long now) { | |||
private ActiveRuleChange insertActiveRule(DbSession dbSession, RulesProfileDto rulesProfileDto, org.sonar.api.rules.ActiveRule activeRule, long now) { | |||
RuleKey ruleKey = RuleKey.of(activeRule.getRepositoryKey(), activeRule.getRuleKey()); | |||
RuleDefinitionDto ruleDefinitionDto = ruleRepository.getDefinition(ruleKey) | |||
.orElseThrow(() -> new IllegalStateException("RuleDefinition not found for key " + ruleKey)); | |||
ActiveRuleDto dto = ActiveRuleDto.createFor(profileDto, ruleDefinitionDto); | |||
ActiveRuleDto dto = new ActiveRuleDto(); | |||
dto.setProfileId(rulesProfileDto.getId()); | |||
dto.setRuleId(ruleDefinitionDto.getId()); | |||
dto.setKey(ActiveRuleKey.of(rulesProfileDto, ruleDefinitionDto.getKey())); | |||
dto.setSeverity(firstNonNull(activeRule.getSeverity().name(), ruleDefinitionDto.getSeverityString())); | |||
dto.setUpdatedAt(now); | |||
dto.setCreatedAt(now); | |||
dbClient.activeRuleDao().insert(session, dto); | |||
dbClient.activeRuleDao().insert(dbSession, dto); | |||
List<ActiveRuleParamDto> paramDtos = insertActiveRuleParams(session, activeRule, ruleKey, dto); | |||
List<ActiveRuleParamDto> paramDtos = insertActiveRuleParams(dbSession, activeRule, ruleKey, dto); | |||
ActiveRuleChange change = ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(profileDto.getKee(), ruleKey)); | |||
ActiveRuleChange change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, dto); | |||
change.setSeverity(dto.getSeverityString()); | |||
paramDtos.forEach(paramDto -> change.setParameter(paramDto.getKey(), paramDto.getValue())); | |||
return change; | |||
@@ -161,20 +197,20 @@ public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert { | |||
return value; | |||
} | |||
public static class RuleRepository { | |||
private final Map<RuleKey, RuleDefinitionDto> ruleDefinitions; | |||
private final Map<RuleKey, Set<RuleParamDto>> ruleParams; | |||
private static class RuleRepository { | |||
private final Map<RuleKey, RuleDefinitionDto> definitions; | |||
private final Map<RuleKey, Set<RuleParamDto>> params; | |||
private RuleRepository(DbClient dbClient, DbSession session) { | |||
this.ruleDefinitions = dbClient.ruleDao().selectAllDefinitions(session) | |||
this.definitions = dbClient.ruleDao().selectAllDefinitions(session) | |||
.stream() | |||
.collect(Collectors.toMap(RuleDefinitionDto::getKey, Function.identity())); | |||
Map<Integer, RuleKey> ruleIdsByKey = ruleDefinitions.values() | |||
Map<Integer, RuleKey> ruleIdsByKey = definitions.values() | |||
.stream() | |||
.collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getId, RuleDefinitionDto::getKey)); | |||
this.ruleParams = new HashMap<>(ruleIdsByKey.size()); | |||
dbClient.ruleDao().selectRuleParamsByRuleKeys(session, ruleDefinitions.keySet()) | |||
.forEach(ruleParam -> ruleParams.compute( | |||
this.params = new HashMap<>(ruleIdsByKey.size()); | |||
dbClient.ruleDao().selectRuleParamsByRuleKeys(session, definitions.keySet()) | |||
.forEach(ruleParam -> params.compute( | |||
ruleIdsByKey.get(ruleParam.getRuleId()), | |||
(key, value) -> { | |||
if (value == null) { | |||
@@ -184,12 +220,12 @@ public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert { | |||
})); | |||
} | |||
Optional<RuleDefinitionDto> getDefinition(RuleKey ruleKey) { | |||
return Optional.ofNullable(ruleDefinitions.get(requireNonNull(ruleKey, "RuleKey can't be null"))); | |||
private Optional<RuleDefinitionDto> getDefinition(RuleKey ruleKey) { | |||
return Optional.ofNullable(definitions.get(requireNonNull(ruleKey, "RuleKey can't be null"))); | |||
} | |||
Set<RuleParamDto> getRuleParams(RuleKey ruleKey) { | |||
Set<RuleParamDto> res = ruleParams.get(requireNonNull(ruleKey, "RuleKey can't be null")); | |||
private Set<RuleParamDto> getRuleParams(RuleKey ruleKey) { | |||
Set<RuleParamDto> res = params.get(requireNonNull(ruleKey, "RuleKey can't be null")); | |||
return res == null ? Collections.emptySet() : res; | |||
} | |||
} |
@@ -20,7 +20,6 @@ | |||
package org.sonar.server.qualityprofile; | |||
import java.util.List; | |||
import java.util.Map; | |||
public interface BuiltInQProfileRepository { | |||
/** | |||
@@ -34,9 +33,9 @@ public interface BuiltInQProfileRepository { | |||
void initialize(); | |||
/** | |||
* @return an immutable map containing immutable lists. | |||
* @return an immutable list | |||
* | |||
* @throws IllegalStateException if {@link #initialize()} has not been called | |||
*/ | |||
Map<String, List<BuiltInQProfile>> getQProfilesByLanguage(); | |||
List<BuiltInQProfile> get(); | |||
} |
@@ -52,7 +52,7 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository | |||
private final Languages languages; | |||
private final List<ProfileDefinition> definitions; | |||
private Map<String, List<BuiltInQProfile>> qProfilesByLanguage; | |||
private List<BuiltInQProfile> qProfiles; | |||
/** | |||
* Requires for pico container when no {@link ProfileDefinition} is defined at all | |||
@@ -68,20 +68,20 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository | |||
@Override | |||
public void initialize() { | |||
checkState(qProfilesByLanguage == null, "initialize must be called only once"); | |||
checkState(qProfiles == null, "initialize must be called only once"); | |||
Profiler profiler = Profiler.create(Loggers.get(getClass())).startInfo("Load quality profiles"); | |||
ListMultimap<String, RulesProfile> rulesProfilesByLanguage = buildRulesProfilesByLanguage(); | |||
validateAndClean(rulesProfilesByLanguage); | |||
this.qProfilesByLanguage = toQualityProfilesByLanguage(rulesProfilesByLanguage); | |||
this.qProfiles = toFlatList(rulesProfilesByLanguage); | |||
profiler.stopDebug(); | |||
} | |||
@Override | |||
public Map<String, List<BuiltInQProfile>> getQProfilesByLanguage() { | |||
checkState(qProfilesByLanguage != null, "initialize must be called first"); | |||
public List<BuiltInQProfile> get() { | |||
checkState(qProfiles != null, "initialize must be called first"); | |||
return qProfilesByLanguage; | |||
return qProfiles; | |||
} | |||
/** | |||
@@ -125,7 +125,7 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository | |||
}); | |||
} | |||
private static Map<String, List<BuiltInQProfile>> toQualityProfilesByLanguage(ListMultimap<String, RulesProfile> rulesProfilesByLanguage) { | |||
private static List<BuiltInQProfile> toFlatList(ListMultimap<String, RulesProfile> rulesProfilesByLanguage) { | |||
Map<String, List<BuiltInQProfile.Builder>> buildersByLanguage = Multimaps.asMap(rulesProfilesByLanguage) | |||
.entrySet() | |||
.stream() | |||
@@ -134,7 +134,9 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository | |||
.entrySet() | |||
.stream() | |||
.filter(BuiltInQProfileRepositoryImpl::ensureAtMostOneDeclaredDefault) | |||
.collect(MoreCollectors.uniqueIndex(Map.Entry::getKey, entry -> toQualityProfiles(entry.getValue()), buildersByLanguage.size())); | |||
.map(entry -> toQualityProfiles(entry.getValue())) | |||
.flatMap(Collection::stream) | |||
.collect(MoreCollectors.toList()); | |||
} | |||
/** |
@@ -47,6 +47,7 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.OrgActiveRuleDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
@@ -82,13 +83,13 @@ public class QProfileBackuperImpl implements QProfileBackuper { | |||
} | |||
@Override | |||
public void backup(DbSession dbSession, QProfileDto profileDto, Writer writer) { | |||
List<ActiveRuleDto> activeRules = db.activeRuleDao().selectByProfileKey(dbSession, profileDto.getKee()); | |||
public void backup(DbSession dbSession, QProfileDto profile, Writer writer) { | |||
List<OrgActiveRuleDto> activeRules = db.activeRuleDao().selectByProfile(dbSession, profile); | |||
activeRules.sort(BackupActiveRuleComparator.INSTANCE); | |||
writeXml(dbSession, writer, profileDto, activeRules.iterator()); | |||
writeXml(dbSession, writer, profile, activeRules.iterator()); | |||
} | |||
private void writeXml(DbSession dbSession, Writer writer, QProfileDto profile, Iterator<ActiveRuleDto> activeRules) { | |||
private void writeXml(DbSession dbSession, Writer writer, QProfileDto profile, Iterator<OrgActiveRuleDto> activeRules) { | |||
XmlWriter xml = XmlWriter.of(writer).declaration(); | |||
xml.begin(ATTRIBUTE_PROFILE); | |||
xml.prop(ATTRIBUTE_NAME, profile.getName()); | |||
@@ -97,8 +98,8 @@ public class QProfileBackuperImpl implements QProfileBackuper { | |||
while (activeRules.hasNext()) { | |||
ActiveRuleDto activeRule = activeRules.next(); | |||
xml.begin(ATTRIBUTE_RULE); | |||
xml.prop(ATTRIBUTE_REPOSITORY_KEY, activeRule.getKey().ruleKey().repository()); | |||
xml.prop(ATTRIBUTE_KEY, activeRule.getKey().ruleKey().rule()); | |||
xml.prop(ATTRIBUTE_REPOSITORY_KEY, activeRule.getRuleKey().repository()); | |||
xml.prop(ATTRIBUTE_KEY, activeRule.getRuleKey().rule()); | |||
xml.prop(ATTRIBUTE_PRIORITY, activeRule.getSeverityString()); | |||
xml.begin(ATTRIBUTE_PARAMETERS); | |||
for (ActiveRuleParamDto param : db.activeRuleDao().selectParamsByActiveRuleId(dbSession, activeRule.getId())) { | |||
@@ -247,8 +248,8 @@ public class QProfileBackuperImpl implements QProfileBackuper { | |||
@Override | |||
public int compare(ActiveRuleDto o1, ActiveRuleDto o2) { | |||
return new CompareToBuilder() | |||
.append(o1.getKey().ruleKey().repository(), o2.getKey().ruleKey().repository()) | |||
.append(o1.getKey().ruleKey().rule(), o2.getKey().ruleKey().rule()) | |||
.append(o1.getRuleKey().repository(), o2.getRuleKey().repository()) | |||
.append(o1.getRuleKey().rule(), o2.getRuleKey().rule()) | |||
.toComparison(); | |||
} | |||
} |
@@ -36,6 +36,7 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.OrgActiveRuleDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
@ServerSide | |||
@@ -49,8 +50,8 @@ public class QProfileComparison { | |||
} | |||
public QProfileComparisonResult compare(DbSession dbSession, QProfileDto left, QProfileDto right) { | |||
Map<RuleKey, ActiveRuleDto> leftActiveRulesByRuleKey = loadActiveRules(dbSession, left); | |||
Map<RuleKey, ActiveRuleDto> rightActiveRulesByRuleKey = loadActiveRules(dbSession, right); | |||
Map<RuleKey, OrgActiveRuleDto> leftActiveRulesByRuleKey = loadActiveRules(dbSession, left); | |||
Map<RuleKey, OrgActiveRuleDto> rightActiveRulesByRuleKey = loadActiveRules(dbSession, right); | |||
Set<RuleKey> allRules = Sets.newHashSet(); | |||
allRules.addAll(leftActiveRulesByRuleKey.keySet()); | |||
@@ -70,7 +71,7 @@ public class QProfileComparison { | |||
} | |||
private void compareActivationParams(DbSession session, ActiveRuleDto leftRule, ActiveRuleDto rightRule, QProfileComparisonResult result) { | |||
RuleKey key = leftRule.getKey().ruleKey(); | |||
RuleKey key = leftRule.getRuleKey(); | |||
Map<String, String> leftParams = paramDtoToMap(dbClient.activeRuleDao().selectParamsByActiveRuleId(session, leftRule.getId())); | |||
Map<String, String> rightParams = paramDtoToMap(dbClient.activeRuleDao().selectParamsByActiveRuleId(session, rightRule.getId())); | |||
if (leftParams.equals(rightParams) && leftRule.getSeverityString().equals(rightRule.getSeverityString())) { | |||
@@ -86,8 +87,8 @@ public class QProfileComparison { | |||
} | |||
} | |||
private Map<RuleKey, ActiveRuleDto> loadActiveRules(DbSession session, QProfileDto profile) { | |||
return Maps.uniqueIndex(dbClient.activeRuleDao().selectByProfileKey(session, profile.getKee()), ActiveRuleToRuleKey.INSTANCE); | |||
private Map<RuleKey, OrgActiveRuleDto> loadActiveRules(DbSession dbSession, QProfileDto profile) { | |||
return Maps.uniqueIndex(dbClient.activeRuleDao().selectByProfile(dbSession, profile), ActiveRuleToRuleKey.INSTANCE); | |||
} | |||
public static class QProfileComparisonResult { | |||
@@ -161,7 +162,7 @@ public class QProfileComparison { | |||
@Override | |||
public RuleKey apply(@Nonnull ActiveRuleDto input) { | |||
return input.getKey().ruleKey(); | |||
return input.getRuleKey(); | |||
} | |||
} | |||
@@ -44,6 +44,7 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.OrgActiveRuleDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
@@ -103,29 +104,27 @@ public class QProfileExporters { | |||
return exporter.getMimeType(); | |||
} | |||
public void export(QProfileDto profile, String exporterKey, Writer writer) { | |||
public void export(DbSession dbSession, QProfileDto profile, String exporterKey, Writer writer) { | |||
ProfileExporter exporter = findExporter(exporterKey); | |||
exporter.exportProfile(wrap(profile), writer); | |||
exporter.exportProfile(wrap(dbSession, profile), writer); | |||
} | |||
private RulesProfile wrap(QProfileDto profile) { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
RulesProfile target = new RulesProfile(profile.getName(), profile.getLanguage()); | |||
List<ActiveRuleDto> activeRuleDtos = dbClient.activeRuleDao().selectByProfileKey(dbSession, profile.getKee()); | |||
List<ActiveRuleParamDto> activeRuleParamDtos = dbClient.activeRuleDao().selectParamsByActiveRuleIds(dbSession, Lists.transform(activeRuleDtos, ActiveRuleDto::getId)); | |||
ListMultimap<Integer, ActiveRuleParamDto> activeRuleParamsByActiveRuleId = FluentIterable.from(activeRuleParamDtos).index(ActiveRuleParamDto::getActiveRuleId); | |||
for (ActiveRuleDto activeRule : activeRuleDtos) { | |||
// TODO all rules should be loaded by using one query with all active rule keys as parameter | |||
Rule rule = ruleFinder.findByKey(activeRule.getKey().ruleKey()); | |||
org.sonar.api.rules.ActiveRule wrappedActiveRule = target.activateRule(rule, RulePriority.valueOf(activeRule.getSeverityString())); | |||
List<ActiveRuleParamDto> paramDtos = activeRuleParamsByActiveRuleId.get(activeRule.getId()); | |||
for (ActiveRuleParamDto activeRuleParamDto : paramDtos) { | |||
wrappedActiveRule.setParameter(activeRuleParamDto.getKey(), activeRuleParamDto.getValue()); | |||
} | |||
private RulesProfile wrap(DbSession dbSession, QProfileDto profile) { | |||
RulesProfile target = new RulesProfile(profile.getName(), profile.getLanguage()); | |||
List<OrgActiveRuleDto> activeRuleDtos = dbClient.activeRuleDao().selectByProfile(dbSession, profile); | |||
List<ActiveRuleParamDto> activeRuleParamDtos = dbClient.activeRuleDao().selectParamsByActiveRuleIds(dbSession, Lists.transform(activeRuleDtos, ActiveRuleDto::getId)); | |||
ListMultimap<Integer, ActiveRuleParamDto> activeRuleParamsByActiveRuleId = FluentIterable.from(activeRuleParamDtos).index(ActiveRuleParamDto::getActiveRuleId); | |||
for (ActiveRuleDto activeRule : activeRuleDtos) { | |||
// TODO all rules should be loaded by using one query with all active rule keys as parameter | |||
Rule rule = ruleFinder.findByKey(activeRule.getRuleKey()); | |||
org.sonar.api.rules.ActiveRule wrappedActiveRule = target.activateRule(rule, RulePriority.valueOf(activeRule.getSeverityString())); | |||
List<ActiveRuleParamDto> paramDtos = activeRuleParamsByActiveRuleId.get(activeRule.getId()); | |||
for (ActiveRuleParamDto activeRuleParamDto : paramDtos) { | |||
wrappedActiveRule.setParameter(activeRuleParamDto.getKey(), activeRuleParamDto.getValue()); | |||
} | |||
return target; | |||
} | |||
return target; | |||
} | |||
private ProfileExporter findExporter(String exporterKey) { |
@@ -19,9 +19,13 @@ | |||
*/ | |||
package org.sonar.server.qualityprofile; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Date; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.Objects; | |||
import java.util.Set; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.utils.System2; | |||
@@ -85,21 +89,14 @@ public class QProfileFactory { | |||
return doCreate(dbSession, organization, name, false, false); | |||
} | |||
/** | |||
* Create the quality profile in DB with the specified name. | |||
* | |||
* A DB error will be thrown if the quality profile already exists. | |||
*/ | |||
public QProfileDto createBuiltIn(DbSession dbSession, OrganizationDto organization, QProfileName name, boolean isDefault) { | |||
return doCreate(dbSession, requireNonNull(organization), name, isDefault, true); | |||
} | |||
private QProfileDto doCreate(DbSession dbSession, OrganizationDto organization, QProfileName name, boolean isDefault, boolean isBuiltIn) { | |||
if (StringUtils.isEmpty(name.getName())) { | |||
throw BadRequestException.create("quality_profiles.profile_name_cant_be_blank"); | |||
} | |||
Date now = new Date(system2.now()); | |||
QProfileDto dto = QProfileDto.createFor(uuidFactory.create()) | |||
QProfileDto dto = new QProfileDto() | |||
.setKee(uuidFactory.create()) | |||
.setRulesProfileUuid(uuidFactory.create()) | |||
.setName(name.getName()) | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setLanguage(name.getLanguage()) | |||
@@ -113,24 +110,44 @@ public class QProfileFactory { | |||
} | |||
// ------------- DELETION | |||
/** | |||
* Deletes the profiles with specified keys from database and Elasticsearch. | |||
* All related information are deleted. The profiles marked as "default" | |||
* are deleted too. Deleting a parent profile does not delete descendants | |||
* if their keys are not listed. | |||
* Deletes the specified profiles from database and Elasticsearch. | |||
* All information related to custom profiles are deleted. Only association | |||
* with built-in profiles are deleted. | |||
* The profiles marked as "default" are deleted too. Deleting a parent profile | |||
* does not delete descendants if the latter are not listed. | |||
*/ | |||
public void deleteByKeys(DbSession dbSession, Collection<String> profileUuids) { | |||
if (!profileUuids.isEmpty()) { | |||
db.qualityProfileDao().deleteProjectAssociationsByProfileUuids(dbSession, profileUuids); | |||
db.activeRuleDao().deleteParametersByProfileKeys(dbSession, profileUuids); | |||
db.activeRuleDao().deleteByProfileKeys(dbSession, profileUuids); | |||
db.qProfileChangeDao().deleteByProfileKeys(dbSession, profileUuids); | |||
db.defaultQProfileDao().deleteByQProfileUuids(dbSession, profileUuids); | |||
db.qualityProfileDao().deleteByUuids(dbSession, profileUuids); | |||
dbSession.commit(); | |||
activeRuleIndexer.deleteByProfileKeys(profileUuids); | |||
public void delete(DbSession dbSession, Collection<QProfileDto> profiles) { | |||
if (profiles.isEmpty()) { | |||
return; | |||
} | |||
} | |||
Set<String> uuids = new HashSet<>(); | |||
List<QProfileDto> customProfiles = new ArrayList<>(); | |||
Set<String> rulesProfileUuidsOfCustomProfiles = new HashSet<>(); | |||
profiles.forEach(p -> { | |||
uuids.add(p.getKee()); | |||
if (!p.isBuiltIn()) { | |||
customProfiles.add(p); | |||
rulesProfileUuidsOfCustomProfiles.add(p.getRulesProfileUuid()); | |||
} | |||
}); | |||
// tables org_qprofiles, default_qprofiles and project_qprofiles | |||
// are deleted whatever custom or built-in | |||
db.qualityProfileDao().deleteProjectAssociationsByProfileUuids(dbSession, uuids); | |||
db.defaultQProfileDao().deleteByQProfileUuids(dbSession, uuids); | |||
db.qualityProfileDao().deleteOrgQProfilesByUuids(dbSession, uuids); | |||
// tables related to rules_profiles and active_rules are deleted | |||
// only for custom profiles | |||
if (!rulesProfileUuidsOfCustomProfiles.isEmpty()) { | |||
db.activeRuleDao().deleteParametersByRuleProfileUuids(dbSession, rulesProfileUuidsOfCustomProfiles); | |||
db.activeRuleDao().deleteByRuleProfileUuids(dbSession, rulesProfileUuidsOfCustomProfiles); | |||
db.qProfileChangeDao().deleteByRulesProfileUuids(dbSession, rulesProfileUuidsOfCustomProfiles); | |||
db.qualityProfileDao().deleteRulesProfilesByUuids(dbSession, rulesProfileUuidsOfCustomProfiles); | |||
} | |||
dbSession.commit(); | |||
activeRuleIndexer.deleteByProfiles(customProfiles); | |||
} | |||
} |
@@ -39,7 +39,7 @@ public class QProfileLookup { | |||
} | |||
public List<QProfileDto> allProfiles(DbSession dbSession, OrganizationDto organization) { | |||
return db.qualityProfileDao().selectAll(dbSession, organization); | |||
return db.qualityProfileDao().selectOrderedByOrganizationUuid(dbSession, organization); | |||
} | |||
public Collection<QProfileDto> profiles(DbSession dbSession, String language, OrganizationDto organization) { |
@@ -29,7 +29,6 @@ import org.sonar.api.server.ServerSide; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
@@ -57,16 +56,16 @@ public class QProfileResetImpl implements QProfileReset { | |||
BulkChangeResult result = new BulkChangeResult(); | |||
Set<RuleKey> ruleToBeDeactivated = Sets.newHashSet(); | |||
// Keep reference to all the activated rules before backup restore | |||
for (ActiveRuleDto activeRuleDto : db.activeRuleDao().selectByProfileKey(dbSession, profile.getKee())) { | |||
for (ActiveRuleDto activeRuleDto : db.activeRuleDao().selectByProfile(dbSession, profile)) { | |||
if (activeRuleDto.getInheritance() == null) { | |||
// inherited rules can't be deactivated | |||
ruleToBeDeactivated.add(activeRuleDto.getKey().ruleKey()); | |||
ruleToBeDeactivated.add(activeRuleDto.getRuleKey()); | |||
} | |||
} | |||
for (RuleActivation activation : activations) { | |||
try { | |||
List<ActiveRuleChange> changes = activator.activate(dbSession, activation, profile.getKee()); | |||
List<ActiveRuleChange> changes = activator.activate(dbSession, activation, profile); | |||
ruleToBeDeactivated.remove(activation.getRuleKey()); | |||
result.incrementSucceeded(); | |||
result.addChanges(changes); | |||
@@ -80,13 +79,13 @@ public class QProfileResetImpl implements QProfileReset { | |||
changes.addAll(result.getChanges()); | |||
for (RuleKey ruleKey : ruleToBeDeactivated) { | |||
try { | |||
changes.addAll(activator.deactivate(dbSession, ActiveRuleKey.of(profile.getKee(), ruleKey))); | |||
changes.addAll(activator.deactivate(dbSession, profile, ruleKey)); | |||
} catch (BadRequestException e) { | |||
// ignore, probably a rule inherited from parent that can't be deactivated | |||
} | |||
} | |||
dbSession.commit(); | |||
activeRuleIndexer.index(changes); | |||
activeRuleIndexer.indexChanges(dbSession, changes); | |||
return result; | |||
} | |||
@@ -21,14 +21,14 @@ package org.sonar.server.qualityprofile; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Set; | |||
import org.sonar.api.server.ServerSide; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.api.utils.log.Profiler; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import static java.lang.String.format; | |||
@@ -43,55 +43,41 @@ public class RegisterQualityProfiles { | |||
private final BuiltInQProfileRepository builtInQProfileRepository; | |||
private final DbClient dbClient; | |||
private final BuiltInQProfileInsert builtInQProfileInsert; | |||
private final ActiveRuleIndexer activeRuleIndexer; | |||
public RegisterQualityProfiles(BuiltInQProfileRepository builtInQProfileRepository, | |||
DbClient dbClient, BuiltInQProfileInsert builtInQProfileInsert, ActiveRuleIndexer activeRuleIndexer) { | |||
DbClient dbClient, BuiltInQProfileInsert builtInQProfileInsert) { | |||
this.builtInQProfileRepository = builtInQProfileRepository; | |||
this.dbClient = dbClient; | |||
this.builtInQProfileInsert = builtInQProfileInsert; | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
} | |||
public void start() { | |||
Profiler profiler = Profiler.create(Loggers.get(getClass())).startInfo("Register quality profiles"); | |||
if (builtInQProfileRepository.getQProfilesByLanguage().isEmpty()) { | |||
List<BuiltInQProfile> builtInQProfiles = builtInQProfileRepository.get(); | |||
if (builtInQProfiles.isEmpty()) { | |||
return; | |||
} | |||
try (DbSession session = dbClient.openSession(false); | |||
DbSession batchSession = dbClient.openSession(true)) { | |||
builtInQProfileRepository.getQProfilesByLanguage() | |||
.forEach((key, value) -> registerPerLanguage(session, batchSession, value)); | |||
activeRuleIndexer.index(); | |||
profiler.stopDebug(); | |||
} | |||
} | |||
Profiler profiler = Profiler.create(Loggers.get(getClass())).startInfo("Register quality profiles"); | |||
try (DbSession dbSession = dbClient.openSession(false); | |||
DbSession batchDbSession = dbClient.openSession(true)) { | |||
Set<QProfileName> namesExistingInDb = dbClient.qualityProfileDao().selectBuiltInRulesProfiles(dbSession).stream() | |||
.map(dto -> new QProfileName(dto.getLanguage(), dto.getName())) | |||
.collect(MoreCollectors.toSet()); | |||
private void registerPerLanguage(DbSession session, DbSession batchSession, List<BuiltInQProfile> qualityProfiles) { | |||
qualityProfiles.forEach(qp -> registerPerQualityProfile(session, batchSession, qp)); | |||
builtInQProfiles.stream() | |||
.filter(p -> !namesExistingInDb.contains(p.getQProfileName())) | |||
.forEach(profile -> register(dbSession, batchDbSession, profile)); | |||
} | |||
profiler.stopDebug(); | |||
} | |||
private void registerPerQualityProfile(DbSession dbSession, DbSession batchSession, BuiltInQProfile builtInProfile) { | |||
private void register(DbSession dbSession, DbSession batchDbSession, BuiltInQProfile builtInProfile) { | |||
LOGGER.info("Register profile {}", builtInProfile.getQProfileName()); | |||
Profiler profiler = Profiler.create(Loggers.get(getClass())); | |||
renameOutdatedProfiles(dbSession, builtInProfile); | |||
dbClient.organizationDao().selectWithoutQualityProfile(dbSession, builtInProfile.getLanguage(), builtInProfile.getName()).forEach( | |||
organization -> registerProfileOnOrganization(dbSession, batchSession, builtInProfile, organization, profiler)); | |||
} | |||
private void registerProfileOnOrganization(DbSession session, DbSession batchSession, | |||
BuiltInQProfile builtInQProfile, OrganizationDto organization, Profiler profiler) { | |||
profiler.start(); | |||
builtInQProfileInsert.create(session, batchSession, builtInQProfile, organization); | |||
session.commit(); | |||
batchSession.commit(); | |||
profiler.stopDebug(format("Register profile %s for organization %s", builtInQProfile.getQProfileName(), organization.getKey())); | |||
builtInQProfileInsert.create(dbSession, batchDbSession, builtInProfile); | |||
} | |||
/** | |||
@@ -108,8 +94,10 @@ public class RegisterQualityProfiles { | |||
if (uuids.isEmpty()) { | |||
return; | |||
} | |||
Profiler profiler = Profiler.createIfDebug(Loggers.get(getClass())).start(); | |||
String newName = profile.getName() + " (outdated copy)"; | |||
LOGGER.info("Rename Quality profiles [{}/{}] to [{}] in {} organizations", profile.getLanguage(), profile.getName(), newName, uuids.size()); | |||
dbClient.qualityProfileDao().renameRulesProfilesAndCommit(dbSession, uuids, newName); | |||
profiler.stopDebug(format("%d Quality profiles renamed to [%s]", uuids.size(), newName)); | |||
} | |||
} |
@@ -36,7 +36,6 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.ActiveRuleDao; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
@@ -77,11 +76,6 @@ public class RuleActivator { | |||
this.userSession = userSession; | |||
} | |||
public List<ActiveRuleChange> activate(DbSession dbSession, RuleActivation activation, String profileKey) { | |||
RuleActivatorContext context = contextFactory.create(profileKey, activation.getRuleKey(), dbSession); | |||
return doActivate(dbSession, activation, context); | |||
} | |||
public List<ActiveRuleChange> activate(DbSession dbSession, RuleActivation activation, QProfileDto profileDto) { | |||
RuleActivatorContext context = contextFactory.create(profileDto, activation.getRuleKey(), dbSession); | |||
return doActivate(dbSession, activation, context); | |||
@@ -100,7 +94,7 @@ public class RuleActivator { | |||
return changes; | |||
} | |||
// new activation | |||
change = ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, context.activeRuleKey()); | |||
change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, context.activeRuleKey()); | |||
applySeverityAndParamToChange(activation, context, change); | |||
if (activation.isCascade() || context.isSameAsParent(change)) { | |||
change.setInheritance(ActiveRule.Inheritance.INHERITED); | |||
@@ -111,7 +105,7 @@ public class RuleActivator { | |||
// propagating to descendants, but child profile already overrides rule -> stop propagation | |||
return changes; | |||
} | |||
change = ActiveRuleChange.createFor(ActiveRuleChange.Type.UPDATED, context.activeRuleKey()); | |||
change = new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, context.activeRuleKey()); | |||
if (activation.isCascade() && activeRule.getInheritance() == null) { | |||
// activate on child, then on parent -> mark child as overriding parent | |||
change.setInheritance(ActiveRule.Inheritance.OVERRIDES); | |||
@@ -224,21 +218,19 @@ public class RuleActivator { | |||
return null; | |||
} | |||
private List<ActiveRuleChange> cascadeActivation(DbSession session, RuleActivation activation, QProfileDto qProfileDto) { | |||
List<ActiveRuleChange> changes = Lists.newArrayList(); | |||
private List<ActiveRuleChange> cascadeActivation(DbSession dbSession, RuleActivation activation, QProfileDto profile) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
// get all inherited profiles | |||
String qualityProfileKey = qProfileDto.getKee(); | |||
List<QProfileDto> children = getChildren(session, qualityProfileKey); | |||
for (QProfileDto child : children) { | |||
getChildren(dbSession, profile).forEach(child -> { | |||
RuleActivation childActivation = new RuleActivation(activation).setCascade(true); | |||
changes.addAll(activate(session, childActivation, child)); | |||
} | |||
changes.addAll(activate(dbSession, childActivation, child)); | |||
}); | |||
return changes; | |||
} | |||
protected List<QProfileDto> getChildren(DbSession session, String qualityProfileKey) { | |||
return db.qualityProfileDao().selectChildren(session, qualityProfileKey); | |||
protected List<QProfileDto> getChildren(DbSession session, QProfileDto profile) { | |||
return db.qualityProfileDao().selectChildren(session, profile); | |||
} | |||
private ActiveRuleDto persist(ActiveRuleChange change, RuleActivatorContext context, DbSession dbSession) { | |||
@@ -247,12 +239,12 @@ public class RuleActivator { | |||
activeRule = doInsert(change, context, dbSession); | |||
} else if (change.getType() == ActiveRuleChange.Type.DEACTIVATED) { | |||
ActiveRuleDao dao = db.activeRuleDao(); | |||
dao.delete(dbSession, change.getKey()); | |||
activeRule = dao.delete(dbSession, change.getKey()).orElse(null); | |||
} else if (change.getType() == ActiveRuleChange.Type.UPDATED) { | |||
activeRule = doUpdate(change, context, dbSession); | |||
} | |||
change.setActiveRule(activeRule); | |||
db.qProfileChangeDao().insert(dbSession, change.toDto(userSession.getLogin())); | |||
return activeRule; | |||
} | |||
@@ -309,9 +301,9 @@ public class RuleActivator { | |||
} else { | |||
if (param.getValue() != null) { | |||
activeRuleParamDto.setValue(param.getValue()); | |||
dao.updateParam(dbSession, activeRule, activeRuleParamDto); | |||
dao.updateParam(dbSession, activeRuleParamDto); | |||
} else { | |||
dao.deleteParam(dbSession, activeRule, activeRuleParamDto); | |||
dao.deleteParam(dbSession, activeRuleParamDto); | |||
} | |||
} | |||
} | |||
@@ -323,28 +315,27 @@ public class RuleActivator { | |||
* Deactivate a rule on a Quality profile. Does nothing if the rule is not activated, but | |||
* fails (fast) if the rule or the profile does not exist. | |||
*/ | |||
public List<ActiveRuleChange> deactivateAndUpdateIndex(DbSession dbSession, ActiveRuleKey key) { | |||
List<ActiveRuleChange> changes = deactivate(dbSession, key); | |||
public void deactivateAndUpdateIndex(DbSession dbSession, QProfileDto profile, RuleKey ruleKey) { | |||
List<ActiveRuleChange> changes = deactivate(dbSession, profile, ruleKey); | |||
dbSession.commit(); | |||
activeRuleIndexer.index(changes); | |||
return changes; | |||
activeRuleIndexer.indexChanges(dbSession, changes); | |||
} | |||
/** | |||
* Deactivate a rule on a Quality profile WITHOUT committing db session and WITHOUT checking permissions | |||
*/ | |||
List<ActiveRuleChange> deactivate(DbSession dbSession, ActiveRuleKey key) { | |||
return deactivate(dbSession, key, false); | |||
List<ActiveRuleChange> deactivate(DbSession dbSession, QProfileDto profile, RuleKey ruleKey) { | |||
return deactivate(dbSession, profile, ruleKey, false); | |||
} | |||
/** | |||
* Deactivate a rule on a Quality profile WITHOUT committing db session, WITHOUT checking permissions, and forcing removal of inherited rules | |||
*/ | |||
public List<ActiveRuleChange> deactivateOfAllOrganizations(DbSession dbSession, RuleDefinitionDto ruleDto) { | |||
List<ActiveRuleChange> changes = Lists.newArrayList(); | |||
List<ActiveRuleDto> activeRules = db.activeRuleDao().selectByRuleIdOfAllOrganizations(dbSession, ruleDto.getId()); | |||
public List<ActiveRuleChange> deactivateOfAllOrganizations(DbSession dbSession, RuleDefinitionDto rule) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
List<ActiveRuleDto> activeRules = db.activeRuleDao().selectByRuleIdOfAllOrganizations(dbSession, rule.getId()); | |||
for (ActiveRuleDto activeRule : activeRules) { | |||
changes.addAll(deactivate(dbSession, activeRule.getKey(), true)); | |||
// FIXME changes.addAll(deactivate(dbSession, activeRule.getKey(), rule.getKey(), true)); | |||
} | |||
return changes; | |||
} | |||
@@ -352,30 +343,26 @@ public class RuleActivator { | |||
/** | |||
* @param force if true then inherited rules are deactivated | |||
*/ | |||
public List<ActiveRuleChange> deactivate(DbSession dbSession, ActiveRuleKey key, boolean force) { | |||
return cascadeDeactivation(key, dbSession, false, force); | |||
public List<ActiveRuleChange> deactivate(DbSession dbSession, QProfileDto profile, RuleKey ruleKey, boolean force) { | |||
return cascadeDeactivation(dbSession, profile, ruleKey, false, force); | |||
} | |||
private List<ActiveRuleChange> cascadeDeactivation(ActiveRuleKey key, DbSession dbSession, boolean isCascade, boolean force) { | |||
List<ActiveRuleChange> changes = Lists.newArrayList(); | |||
RuleActivatorContext context = contextFactory.create(key.qProfile(), key.ruleKey(), dbSession); | |||
private List<ActiveRuleChange> cascadeDeactivation(DbSession dbSession, QProfileDto profile, RuleKey ruleKey, boolean isCascade, boolean force) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
RuleActivatorContext context = contextFactory.create(profile, ruleKey, dbSession); | |||
ActiveRuleChange change; | |||
ActiveRuleDto activeRuleDto = context.activeRule(); | |||
if (activeRuleDto == null) { | |||
return changes; | |||
} | |||
checkRequest(force || isCascade || activeRuleDto.getInheritance() == null, "Cannot deactivate inherited rule '%s'", key.ruleKey()); | |||
change = ActiveRuleChange.createFor(ActiveRuleChange.Type.DEACTIVATED, key); | |||
checkRequest(force || isCascade || activeRuleDto.getInheritance() == null, "Cannot deactivate inherited rule '%s'", ruleKey); | |||
change = new ActiveRuleChange(ActiveRuleChange.Type.DEACTIVATED, activeRuleDto); | |||
changes.add(change); | |||
persist(change, context, dbSession); | |||
// get all inherited profiles | |||
List<QProfileDto> profiles = getChildren(dbSession, key.qProfile()); | |||
for (QProfileDto profile : profiles) { | |||
ActiveRuleKey activeRuleKey = ActiveRuleKey.of(profile.getKee(), key.ruleKey()); | |||
changes.addAll(cascadeDeactivation(activeRuleKey, dbSession, true, force)); | |||
} | |||
getChildren(dbSession, profile).forEach(child -> changes.addAll(cascadeDeactivation(dbSession, child, ruleKey, true, force))); | |||
if (!changes.isEmpty()) { | |||
updateProfileDates(dbSession, context); | |||
@@ -398,83 +385,70 @@ public class RuleActivator { | |||
return value; | |||
} | |||
public BulkChangeResult bulkActivate(RuleQuery ruleQuery, String profileKey, @Nullable String severity) { | |||
DbSession dbSession = db.openSession(false); | |||
public BulkChangeResult bulkActivate(DbSession dbSession, RuleQuery ruleQuery, QProfileDto profile, @Nullable String severity) { | |||
BulkChangeResult result = new BulkChangeResult(); | |||
try { | |||
Iterator<RuleKey> rules = ruleIndex.searchAll(ruleQuery); | |||
while (rules.hasNext()) { | |||
RuleKey ruleKey = rules.next(); | |||
try { | |||
RuleActivation activation = new RuleActivation(ruleKey); | |||
activation.setSeverity(severity); | |||
List<ActiveRuleChange> changes = activate(dbSession, activation, profileKey); | |||
result.addChanges(changes); | |||
if (!changes.isEmpty()) { | |||
result.incrementSucceeded(); | |||
} | |||
} catch (BadRequestException e) { | |||
// other exceptions stop the bulk activation | |||
result.incrementFailed(); | |||
result.getErrors().addAll(e.errors()); | |||
Iterator<RuleKey> rules = ruleIndex.searchAll(ruleQuery); | |||
while (rules.hasNext()) { | |||
RuleKey ruleKey = rules.next(); | |||
try { | |||
RuleActivation activation = new RuleActivation(ruleKey); | |||
activation.setSeverity(severity); | |||
List<ActiveRuleChange> changes = activate(dbSession, activation, profile); | |||
result.addChanges(changes); | |||
if (!changes.isEmpty()) { | |||
result.incrementSucceeded(); | |||
} | |||
} catch (BadRequestException e) { | |||
// other exceptions stop the bulk activation | |||
result.incrementFailed(); | |||
result.getErrors().addAll(e.errors()); | |||
} | |||
dbSession.commit(); | |||
activeRuleIndexer.index(result.getChanges()); | |||
} finally { | |||
dbSession.close(); | |||
} | |||
dbSession.commit(); | |||
activeRuleIndexer.indexChanges(dbSession, result.getChanges()); | |||
return result; | |||
} | |||
public BulkChangeResult bulkDeactivate(RuleQuery ruleQuery, String profile) { | |||
DbSession dbSession = db.openSession(false); | |||
public BulkChangeResult bulkDeactivate(DbSession dbSession, RuleQuery ruleQuery, QProfileDto profile) { | |||
BulkChangeResult result = new BulkChangeResult(); | |||
try { | |||
Iterator<RuleKey> rules = ruleIndex.searchAll(ruleQuery); | |||
while (rules.hasNext()) { | |||
try { | |||
RuleKey ruleKey = rules.next(); | |||
ActiveRuleKey key = ActiveRuleKey.of(profile, ruleKey); | |||
List<ActiveRuleChange> changes = deactivate(dbSession, key); | |||
result.addChanges(changes); | |||
if (!changes.isEmpty()) { | |||
result.incrementSucceeded(); | |||
} | |||
} catch (BadRequestException e) { | |||
// other exceptions stop the bulk activation | |||
result.incrementFailed(); | |||
result.getErrors().addAll(e.errors()); | |||
Iterator<RuleKey> rules = ruleIndex.searchAll(ruleQuery); | |||
while (rules.hasNext()) { | |||
try { | |||
RuleKey ruleKey = rules.next(); | |||
List<ActiveRuleChange> changes = deactivate(dbSession, profile, ruleKey); | |||
result.addChanges(changes); | |||
if (!changes.isEmpty()) { | |||
result.incrementSucceeded(); | |||
} | |||
} catch (BadRequestException e) { | |||
// other exceptions stop the bulk activation | |||
result.incrementFailed(); | |||
result.getErrors().addAll(e.errors()); | |||
} | |||
dbSession.commit(); | |||
activeRuleIndexer.index(result.getChanges()); | |||
return result; | |||
} finally { | |||
dbSession.close(); | |||
} | |||
dbSession.commit(); | |||
activeRuleIndexer.indexChanges(dbSession, result.getChanges()); | |||
return result; | |||
} | |||
public List<ActiveRuleChange> setParent(DbSession dbSession, String profileKey, @Nullable String parentKey) { | |||
QProfileDto profile = db.qualityProfileDao().selectOrFailByUuid(dbSession, profileKey); | |||
public List<ActiveRuleChange> setParent(DbSession dbSession, QProfileDto profile, @Nullable QProfileDto parent) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
if (parentKey == null) { | |||
if (parent == null) { | |||
// unset if parent is defined, else nothing to do | |||
changes.addAll(removeParent(dbSession, profile)); | |||
} else if (profile.getParentKee() == null || !parentKey.equals(profile.getParentKee())) { | |||
QProfileDto parentProfile = db.qualityProfileDao().selectOrFailByUuid(dbSession, parentKey); | |||
checkRequest(!isDescendant(dbSession, profile, parentProfile), "Descendant profile '%s' can not be selected as parent of '%s'", parentKey, profileKey); | |||
} else if (profile.getParentKee() == null || !parent.getKee().equals(profile.getParentKee())) { | |||
checkRequest(!isDescendant(dbSession, profile, parent), "Descendant profile '%s' can not be selected as parent of '%s'", parent.getKee(), profile.getKee()); | |||
changes.addAll(removeParent(dbSession, profile)); | |||
// set new parent | |||
profile.setParentKee(parentKey); | |||
profile.setParentKee(parent.getKee()); | |||
db.qualityProfileDao().update(dbSession, profile); | |||
for (ActiveRuleDto parentActiveRule : db.activeRuleDao().selectByProfileKey(dbSession, parentKey)) { | |||
for (ActiveRuleDto parentActiveRule : db.activeRuleDao().selectByProfile(dbSession, parent)) { | |||
try { | |||
RuleActivation activation = new RuleActivation(parentActiveRule.getKey().ruleKey()); | |||
changes.addAll(activate(dbSession, activation, profileKey)); | |||
RuleActivation activation = new RuleActivation(parentActiveRule.getRuleKey()); | |||
changes.addAll(activate(dbSession, activation, profile)); | |||
} catch (BadRequestException e) { | |||
// for example because rule status is REMOVED | |||
// TODO return errors | |||
@@ -482,26 +456,26 @@ public class RuleActivator { | |||
} | |||
} | |||
dbSession.commit(); | |||
activeRuleIndexer.index(changes); | |||
activeRuleIndexer.indexChanges(dbSession, changes); | |||
return changes; | |||
} | |||
/** | |||
* Does not commit | |||
*/ | |||
private List<ActiveRuleChange> removeParent(DbSession dbSession, QProfileDto profileDto) { | |||
if (profileDto.getParentKee() != null) { | |||
private List<ActiveRuleChange> removeParent(DbSession dbSession, QProfileDto profile) { | |||
if (profile.getParentKee() != null) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
profileDto.setParentKee(null); | |||
db.qualityProfileDao().update(dbSession, profileDto); | |||
for (ActiveRuleDto activeRule : db.activeRuleDao().selectByProfileKey(dbSession, profileDto.getKee())) { | |||
profile.setParentKee(null); | |||
db.qualityProfileDao().update(dbSession, profile); | |||
for (ActiveRuleDto activeRule : db.activeRuleDao().selectByProfile(dbSession, profile)) { | |||
if (ActiveRuleDto.INHERITED.equals(activeRule.getInheritance())) { | |||
changes.addAll(deactivate(dbSession, activeRule.getKey(), true)); | |||
changes.addAll(deactivate(dbSession, profile, activeRule.getRuleKey(), true)); | |||
} else if (ActiveRuleDto.OVERRIDES.equals(activeRule.getInheritance())) { | |||
activeRule.setInheritance(null); | |||
activeRule.setUpdatedAt(system2.now()); | |||
db.activeRuleDao().update(dbSession, activeRule); | |||
changes.add(ActiveRuleChange.createFor(ActiveRuleChange.Type.UPDATED, activeRule.getKey()).setInheritance(null)); | |||
changes.add(new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRule).setInheritance(null)); | |||
} | |||
} | |||
return changes; | |||
@@ -509,7 +483,7 @@ public class RuleActivator { | |||
return Collections.emptyList(); | |||
} | |||
boolean isDescendant(DbSession dbSession, QProfileDto childProfile, @Nullable QProfileDto parentProfile) { | |||
private boolean isDescendant(DbSession dbSession, QProfileDto childProfile, @Nullable QProfileDto parentProfile) { | |||
QProfileDto currentParent = parentProfile; | |||
while (currentParent != null) { | |||
if (childProfile.getName().equals(currentParent.getName())) { |
@@ -51,7 +51,7 @@ class RuleActivatorContext { | |||
} | |||
ActiveRuleKey activeRuleKey() { | |||
return ActiveRuleKey.of(profile.getKee(), rule.getKey()); | |||
return ActiveRuleKey.of(profile, rule.getKey()); | |||
} | |||
RuleDefinitionDto rule() { |
@@ -44,24 +44,17 @@ public class RuleActivatorContextFactory { | |||
this.db = db; | |||
} | |||
RuleActivatorContext create(String profileKey, RuleKey ruleKey, DbSession session) { | |||
RuleActivatorContext context = new RuleActivatorContext(); | |||
QProfileDto profile = getQualityProfileDto(session, profileKey); | |||
checkRequest(profile != null, "Quality profile not found: %s", profileKey); | |||
context.setProfile(profile); | |||
return create(ruleKey, session, context); | |||
} | |||
RuleActivatorContext create(QProfileDto profile, RuleKey ruleKey, DbSession session) { | |||
return create(ruleKey, session, new RuleActivatorContext().setProfile(profile)); | |||
} | |||
private RuleActivatorContext create(RuleKey ruleKey, DbSession session, RuleActivatorContext context) { | |||
initRule(ruleKey, context, session); | |||
initActiveRules(context.profile().getKee(), ruleKey, context, session, false); | |||
private RuleActivatorContext create(RuleKey ruleKey, DbSession dbSession, RuleActivatorContext context) { | |||
initRule(ruleKey, context, dbSession); | |||
initActiveRules(context.profile(), ruleKey, context, dbSession, false); | |||
String parentKee = context.profile().getParentKee(); | |||
if (parentKee != null) { | |||
initActiveRules(parentKee, ruleKey, context, session, true); | |||
QProfileDto parent = getQualityProfileDto(dbSession, parentKee); | |||
initActiveRules(parent, ruleKey, context, dbSession, true); | |||
} | |||
return context; | |||
} | |||
@@ -75,8 +68,8 @@ public class RuleActivatorContextFactory { | |||
return ruleDefinitionDto; | |||
} | |||
private void initActiveRules(String profileKey, RuleKey ruleKey, RuleActivatorContext context, DbSession session, boolean parent) { | |||
ActiveRuleKey key = ActiveRuleKey.of(profileKey, ruleKey); | |||
private void initActiveRules(QProfileDto profile, RuleKey ruleKey, RuleActivatorContext context, DbSession session, boolean parent) { | |||
ActiveRuleKey key = ActiveRuleKey.of(profile, ruleKey); | |||
Optional<ActiveRuleDto> activeRule = getActiveRule(session, key); | |||
Collection<ActiveRuleParamDto> activeRuleParams = null; | |||
if (activeRule.isPresent()) { | |||
@@ -103,11 +96,11 @@ public class RuleActivatorContextFactory { | |||
return db.ruleDao().selectRuleParamsByRuleKey(dbSession, ruleDefinitionDto.getKey()); | |||
} | |||
Optional<ActiveRuleDto> getActiveRule(DbSession session, ActiveRuleKey key) { | |||
return Optional.ofNullable(db.activeRuleDao().selectByKey(session, key).orNull()); | |||
Optional<ActiveRuleDto> getActiveRule(DbSession dbSession, ActiveRuleKey key) { | |||
return db.activeRuleDao().selectByKey(dbSession, key); | |||
} | |||
List<ActiveRuleParamDto> getActiveRuleParams(DbSession session, ActiveRuleDto activeRuleDto) { | |||
return db.activeRuleDao().selectParamsByActiveRuleId(session, activeRuleDto.getId()); | |||
List<ActiveRuleParamDto> getActiveRuleParams(DbSession dbSession, ActiveRuleDto activeRuleDto) { | |||
return db.activeRuleDao().selectParamsByActiveRuleId(dbSession, activeRuleDto.getId()); | |||
} | |||
} |
@@ -20,39 +20,33 @@ | |||
package org.sonar.server.qualityprofile.index; | |||
import com.google.common.collect.Maps; | |||
import java.util.Map; | |||
import javax.annotation.Nullable; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.server.es.BaseDoc; | |||
import org.sonar.server.qualityprofile.ActiveRule; | |||
import static com.google.common.base.Preconditions.checkNotNull; | |||
import static org.apache.commons.lang.StringUtils.containsIgnoreCase; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_KEY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_ORGANIZATION_UUID; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_UUID; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_REPOSITORY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_RULE_KEY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_UPDATED_AT; | |||
public class ActiveRuleDoc extends BaseDoc { | |||
private final ActiveRuleKey key; | |||
public ActiveRuleDoc(ActiveRuleKey key) { | |||
public ActiveRuleDoc(String id) { | |||
super(Maps.newHashMapWithExpectedSize(9)); | |||
checkNotNull(key, "ActiveRuleKey cannot be null"); | |||
this.key = key; | |||
setField(FIELD_ACTIVE_RULE_KEY, key.toString()); | |||
setField(FIELD_ACTIVE_RULE_PROFILE_KEY, key.qProfile()); | |||
setField(FIELD_ACTIVE_RULE_RULE_KEY, key.ruleKey().toString()); | |||
setField(FIELD_ACTIVE_RULE_REPOSITORY, key.ruleKey().repository()); | |||
setField("_id", id); | |||
} | |||
public ActiveRuleDoc(Map<String,Object> source) { | |||
super(source); | |||
} | |||
@Override | |||
public String getId() { | |||
return key().toString(); | |||
return getField("_id"); | |||
} | |||
@Override | |||
@@ -62,32 +56,42 @@ public class ActiveRuleDoc extends BaseDoc { | |||
@Override | |||
public String getParent() { | |||
return key.ruleKey().toString(); | |||
return getRuleKey().toString(); | |||
} | |||
public ActiveRuleKey key() { | |||
return key; | |||
RuleKey getRuleKey() { | |||
return RuleKey.parse(getField(FIELD_ACTIVE_RULE_RULE_KEY)); | |||
} | |||
String organizationUuid() { | |||
return getField(FIELD_ACTIVE_RULE_ORGANIZATION_UUID); | |||
String getRuleRepository() { | |||
return getField(FIELD_ACTIVE_RULE_REPOSITORY); | |||
} | |||
public ActiveRuleDoc setOrganizationUuid(String s) { | |||
setField(FIELD_ACTIVE_RULE_ORGANIZATION_UUID, s); | |||
String getSeverity() { | |||
return getNullableField(FIELD_ACTIVE_RULE_SEVERITY); | |||
} | |||
ActiveRuleDoc setSeverity(@Nullable String s) { | |||
setField(FIELD_ACTIVE_RULE_SEVERITY, s); | |||
return this; | |||
} | |||
String severity() { | |||
return getNullableField(FIELD_ACTIVE_RULE_SEVERITY); | |||
ActiveRuleDoc setRuleKey(RuleKey ruleKey) { | |||
setField(FIELD_ACTIVE_RULE_RULE_KEY, ruleKey.toString()); | |||
setField(FIELD_ACTIVE_RULE_REPOSITORY, ruleKey.repository()); | |||
return this; | |||
} | |||
public ActiveRuleDoc setSeverity(@Nullable String s) { | |||
setField(FIELD_ACTIVE_RULE_SEVERITY, s); | |||
String getRuleProfileUuid() { | |||
return getField(FIELD_ACTIVE_RULE_PROFILE_UUID); | |||
} | |||
ActiveRuleDoc setRuleProfileUuid(String s) { | |||
setField(FIELD_ACTIVE_RULE_PROFILE_UUID, s); | |||
return this; | |||
} | |||
ActiveRule.Inheritance inheritance() { | |||
ActiveRule.Inheritance getInheritance() { | |||
String inheritance = getNullableField(FIELD_ACTIVE_RULE_INHERITANCE); | |||
if (inheritance == null || inheritance.isEmpty() || | |||
containsIgnoreCase(inheritance, "none")) { | |||
@@ -105,13 +109,4 @@ public class ActiveRuleDoc extends BaseDoc { | |||
setField(FIELD_ACTIVE_RULE_INHERITANCE, s); | |||
return this; | |||
} | |||
long updatedAt() { | |||
return (Long) getField(FIELD_ACTIVE_RULE_UPDATED_AT); | |||
} | |||
public ActiveRuleDoc setUpdatedAt(@Nullable Long l) { | |||
setField(FIELD_ACTIVE_RULE_UPDATED_AT, l); | |||
return this; | |||
} | |||
} |
@@ -19,107 +19,128 @@ | |||
*/ | |||
package org.sonar.server.qualityprofile.index; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
import org.elasticsearch.action.index.IndexRequest; | |||
import org.elasticsearch.action.search.SearchRequestBuilder; | |||
import org.elasticsearch.index.query.QueryBuilders; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.server.es.BaseIndexer; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.qualityprofile.RulesProfileDto; | |||
import org.sonar.server.es.BulkIndexer; | |||
import org.sonar.server.es.BulkIndexer.Size; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.IndexType; | |||
import org.sonar.server.es.StartupIndexer; | |||
import org.sonar.server.qualityprofile.ActiveRuleChange; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import static org.elasticsearch.index.query.QueryBuilders.termsQuery; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_KEY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_UPDATED_AT; | |||
import static org.elasticsearch.index.query.QueryBuilders.termQuery; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_UUID; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_RULE_KEY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX_TYPE_ACTIVE_RULE; | |||
public class ActiveRuleIndexer extends BaseIndexer { | |||
public class ActiveRuleIndexer implements StartupIndexer { | |||
private final DbClient dbClient; | |||
private final EsClient esClient; | |||
private final ActiveRuleIteratorFactory activeRuleIteratorFactory; | |||
public ActiveRuleIndexer(System2 system2, DbClient dbClient, EsClient esClient) { | |||
super(system2, esClient, 300, INDEX_TYPE_ACTIVE_RULE, FIELD_ACTIVE_RULE_UPDATED_AT); | |||
public ActiveRuleIndexer(DbClient dbClient, EsClient esClient, ActiveRuleIteratorFactory activeRuleIteratorFactory) { | |||
this.dbClient = dbClient; | |||
this.esClient = esClient; | |||
this.activeRuleIteratorFactory = activeRuleIteratorFactory; | |||
} | |||
@Override | |||
protected long doIndex(long lastUpdatedAt) { | |||
return doIndex(createBulkIndexer(), lastUpdatedAt); | |||
public void indexOnStartup(Set<IndexType> emptyIndexTypes) { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
ActiveRuleIterator dbCursor = activeRuleIteratorFactory.createForAll(dbSession); | |||
scrollDbAndIndex(dbCursor, Size.LARGE); | |||
} | |||
} | |||
public void index(Iterator<ActiveRuleDoc> rules) { | |||
doIndex(createBulkIndexer(), rules); | |||
@Override | |||
public Set<IndexType> getIndexTypes() { | |||
return ImmutableSet.of(RuleIndexDefinition.INDEX_TYPE_ACTIVE_RULE); | |||
} | |||
private long doIndex(BulkIndexer bulk, long lastUpdatedAt) { | |||
long maxDate; | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
ActiveRuleResultSetIterator rowIt = ActiveRuleResultSetIterator.create(dbClient, dbSession, lastUpdatedAt); | |||
maxDate = doIndex(bulk, rowIt); | |||
rowIt.close(); | |||
return maxDate; | |||
/** | |||
* Important - the existing documents are not deleted, so this method | |||
* does not guarantee consistency of index. | |||
*/ | |||
public void indexRuleProfile(DbSession dbSession, RulesProfileDto ruleProfile) { | |||
try (ActiveRuleIterator dbCursor = activeRuleIteratorFactory.createForRuleProfile(dbSession, ruleProfile)) { | |||
scrollDbAndIndex(dbCursor, Size.REGULAR); | |||
} | |||
} | |||
private static long doIndex(BulkIndexer bulk, Iterator<ActiveRuleDoc> activeRules) { | |||
public void indexChanges(DbSession dbSession, List<ActiveRuleChange> changes) { | |||
BulkIndexer bulk = createBulkIndexer(Size.REGULAR); | |||
bulk.start(); | |||
long maxDate = 0L; | |||
while (activeRules.hasNext()) { | |||
ActiveRuleDoc activeRule = activeRules.next(); | |||
bulk.add(newIndexRequest(activeRule)); | |||
// it's more efficient to sort programmatically than in SQL on some databases (MySQL for instance) | |||
maxDate = Math.max(maxDate, activeRule.updatedAt()); | |||
List<Integer> idsOfTouchedActiveRules = new ArrayList<>(); | |||
changes.stream() | |||
.filter(c -> c.getActiveRule() != null) | |||
.forEach(c -> { | |||
if (c.getType().equals(ActiveRuleChange.Type.DEACTIVATED)) { | |||
bulk.addDeletion(INDEX_TYPE_ACTIVE_RULE, String.valueOf(c.getActiveRule().getId())); | |||
} else { | |||
idsOfTouchedActiveRules.add(c.getActiveRule().getId()); | |||
} | |||
}); | |||
try (ActiveRuleIterator dbCursor = activeRuleIteratorFactory.createForActiveRules(dbSession, idsOfTouchedActiveRules)) { | |||
while (dbCursor.hasNext()) { | |||
ActiveRuleDoc activeRule = dbCursor.next(); | |||
bulk.add(newIndexRequest(activeRule)); | |||
} | |||
} | |||
bulk.stop(); | |||
return maxDate; | |||
} | |||
public void index(List<ActiveRuleChange> changes) { | |||
deleteKeys(changes.stream() | |||
.filter(c -> c.getType().equals(ActiveRuleChange.Type.DEACTIVATED)) | |||
.map(ActiveRuleChange::getKey) | |||
.collect(MoreCollectors.toList(changes.size()))); | |||
index(); | |||
} | |||
public void deleteByProfileKeys(Collection<String> profileKeys) { | |||
BulkIndexer bulk = createBulkIndexer(); | |||
public void deleteByProfiles(Collection<QProfileDto> profiles) { | |||
BulkIndexer bulk = createBulkIndexer(Size.REGULAR); | |||
bulk.start(); | |||
profileKeys.forEach(profileKey -> { | |||
profiles.forEach(profile -> { | |||
SearchRequestBuilder search = esClient.prepareSearch(INDEX_TYPE_ACTIVE_RULE) | |||
.setQuery(QueryBuilders.boolQuery().must(termsQuery(FIELD_ACTIVE_RULE_PROFILE_KEY, profileKey))); | |||
.setQuery(QueryBuilders.boolQuery().must(termQuery(FIELD_ACTIVE_RULE_PROFILE_UUID, profile.getRulesProfileUuid()))); | |||
bulk.addDeletion(search); | |||
}); | |||
bulk.stop(); | |||
} | |||
private void deleteKeys(List<ActiveRuleKey> keys) { | |||
BulkIndexer bulk = createBulkIndexer(); | |||
public void deleteByRuleKeys(Collection<RuleKey> ruleKeys) { | |||
BulkIndexer bulk = createBulkIndexer(Size.REGULAR); | |||
bulk.start(); | |||
SearchRequestBuilder search = esClient.prepareSearch(INDEX_TYPE_ACTIVE_RULE) | |||
.setQuery(QueryBuilders.boolQuery().must(termsQuery(FIELD_ACTIVE_RULE_KEY, keys))); | |||
bulk.addDeletion(search); | |||
ruleKeys.forEach(ruleKey -> { | |||
SearchRequestBuilder search = esClient.prepareSearch(INDEX_TYPE_ACTIVE_RULE) | |||
.setQuery(QueryBuilders.boolQuery().must(termQuery(FIELD_ACTIVE_RULE_RULE_KEY, ruleKey.toString()))); | |||
bulk.addDeletion(search); | |||
}); | |||
bulk.stop(); | |||
} | |||
private BulkIndexer createBulkIndexer() { | |||
return new BulkIndexer(esClient, INDEX_TYPE_ACTIVE_RULE.getIndex(), Size.REGULAR); | |||
private BulkIndexer createBulkIndexer(Size size) { | |||
return new BulkIndexer(esClient, INDEX_TYPE_ACTIVE_RULE.getIndex(), size); | |||
} | |||
private static IndexRequest newIndexRequest(ActiveRuleDoc doc) { | |||
return new IndexRequest(INDEX_TYPE_ACTIVE_RULE.getIndex(), INDEX_TYPE_ACTIVE_RULE.getType(), doc.key().toString()) | |||
.parent(doc.key().ruleKey().toString()) | |||
return new IndexRequest(INDEX_TYPE_ACTIVE_RULE.getIndex(), INDEX_TYPE_ACTIVE_RULE.getType(), doc.getId()) | |||
.parent(doc.getRuleKey().toString()) | |||
.source(doc.getFields()); | |||
} | |||
private void scrollDbAndIndex(ActiveRuleIterator dbCursor, Size size) { | |||
BulkIndexer bulk = new BulkIndexer(esClient, INDEX_TYPE_ACTIVE_RULE.getIndex(), size); | |||
bulk.start(); | |||
while (dbCursor.hasNext()) { | |||
ActiveRuleDoc activeRule = dbCursor.next(); | |||
bulk.add(newIndexRequest(activeRule)); | |||
} | |||
bulk.stop(); | |||
} | |||
} |
@@ -19,23 +19,9 @@ | |||
*/ | |||
package org.sonar.server.qualityprofile.index; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.rule.RuleTesting; | |||
import java.util.Iterator; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; | |||
public class ActiveRuleDocTesting { | |||
public static ActiveRuleDoc newDoc() { | |||
return newDoc(ActiveRuleKey.of("sonar-way", RuleTesting.XOO_X1)); | |||
} | |||
public static ActiveRuleDoc newDoc(ActiveRuleKey key) { | |||
return new ActiveRuleDoc(key) | |||
.setOrganizationUuid(randomAlphabetic(40)) | |||
.setSeverity(Severity.CRITICAL) | |||
.setInheritance(null) | |||
.setUpdatedAt(1_600_000_000L); | |||
} | |||
public interface ActiveRuleIterator extends Iterator<ActiveRuleDoc>, AutoCloseable { | |||
@Override | |||
void close(); | |||
} |
@@ -0,0 +1,48 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.qualityprofile.index; | |||
import java.util.Collection; | |||
import org.sonar.api.server.ServerSide; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.RulesProfileDto; | |||
@ServerSide | |||
public class ActiveRuleIteratorFactory { | |||
private final DbClient dbClient; | |||
public ActiveRuleIteratorFactory(DbClient dbClient) { | |||
this.dbClient = dbClient; | |||
} | |||
public ActiveRuleIterator createForAll(DbSession dbSession) { | |||
return new ActiveRuleIteratorForSingleChunk(dbClient, dbSession); | |||
} | |||
public ActiveRuleIterator createForRuleProfile(DbSession dbSession, RulesProfileDto ruleProfile) { | |||
return new ActiveRuleIteratorForSingleChunk(dbClient, dbSession, ruleProfile); | |||
} | |||
public ActiveRuleIterator createForActiveRules(DbSession dbSession, Collection<Integer> activeRuleIds) { | |||
return new ActiveRuleIteratorForMultipleChunks(dbClient, dbSession, activeRuleIds); | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.qualityprofile.index; | |||
import java.util.Collection; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import org.sonar.db.DatabaseUtils; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import static java.util.Optional.ofNullable; | |||
public class ActiveRuleIteratorForMultipleChunks implements ActiveRuleIterator { | |||
private final DbClient dbClient; | |||
private final DbSession dbSession; | |||
private final Iterator<List<Integer>> iteratorOverChunks; | |||
private ActiveRuleIteratorForSingleChunk currentChunk; | |||
public ActiveRuleIteratorForMultipleChunks(DbClient dbClient, DbSession dbSession, Collection<Integer> activeRuleIds) { | |||
this.dbClient = dbClient; | |||
this.dbSession = dbSession; | |||
this.iteratorOverChunks = DatabaseUtils.toUniqueAndSortedPartitions(activeRuleIds).iterator(); | |||
} | |||
@Override | |||
public boolean hasNext() { | |||
if (currentChunk != null && currentChunk.hasNext()) { | |||
return true; | |||
} | |||
return iteratorOverChunks.hasNext(); | |||
} | |||
@Override | |||
public ActiveRuleDoc next() { | |||
if (currentChunk == null || !currentChunk.hasNext()) { | |||
currentChunk = nextChunk(); | |||
} | |||
return currentChunk.next(); | |||
} | |||
private ActiveRuleIteratorForSingleChunk nextChunk() { | |||
List<Integer> nextInput = iteratorOverChunks.next(); | |||
return new ActiveRuleIteratorForSingleChunk(dbClient, dbSession, nextInput); | |||
} | |||
@Override | |||
public void close() { | |||
ofNullable(currentChunk).ifPresent(ActiveRuleIterator::close); | |||
} | |||
} |
@@ -0,0 +1,132 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.qualityprofile.index; | |||
import java.sql.PreparedStatement; | |||
import java.sql.ResultSet; | |||
import java.sql.SQLException; | |||
import java.util.List; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.db.DatabaseUtils; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.ResultSetIterator; | |||
import org.sonar.db.qualityprofile.RulesProfileDto; | |||
import org.sonar.db.rule.SeverityUtil; | |||
import org.sonar.server.qualityprofile.ActiveRule; | |||
import static org.apache.commons.lang.StringUtils.repeat; | |||
/** | |||
* Scrolls over table ISSUES and reads documents to populate | |||
* the issues index | |||
*/ | |||
class ActiveRuleIteratorForSingleChunk implements ActiveRuleIterator { | |||
private static final String[] COLUMNS = { | |||
"ar.id", | |||
"ar.failure_level", | |||
"ar.inheritance", | |||
"r.plugin_name", | |||
"r.plugin_rule_key", | |||
"rp.kee" | |||
}; | |||
private static final String SQL_ALL = "select " + StringUtils.join(COLUMNS, ",") + " from active_rules ar " + | |||
" inner join rules_profiles rp on rp.id = ar.profile_id " + | |||
" inner join rules r on r.id = ar.rule_id "; | |||
private final PreparedStatement stmt; | |||
private final ResultSetIterator<ActiveRuleDoc> iterator; | |||
ActiveRuleIteratorForSingleChunk(DbClient dbClient, DbSession dbSession) { | |||
try { | |||
stmt = dbClient.getMyBatis().newScrollingSelectStatement(dbSession, SQL_ALL); | |||
iterator = new ActiveRuleIteratorInternal(stmt); | |||
} catch (Exception e) { | |||
throw new IllegalStateException("Fail to prepare SQL request to select all active_rules", e); | |||
} | |||
} | |||
ActiveRuleIteratorForSingleChunk(DbClient dbClient, DbSession dbSession, RulesProfileDto ruleProfile) { | |||
try { | |||
stmt = dbClient.getMyBatis().newScrollingSelectStatement(dbSession, SQL_ALL + " where rp.kee = ?"); | |||
stmt.setString(1, ruleProfile.getKee()); | |||
iterator = new ActiveRuleIteratorInternal(stmt); | |||
} catch (Exception e) { | |||
throw new IllegalStateException("Fail to prepare SQL request to select active_rules of profile " + ruleProfile.getKee(), e); | |||
} | |||
} | |||
ActiveRuleIteratorForSingleChunk(DbClient dbClient, DbSession dbSession, List<Integer> activeRuleIds) { | |||
try { | |||
stmt = dbClient.getMyBatis().newScrollingSelectStatement(dbSession, SQL_ALL + " where ar.id in (" + repeat("?", ",", activeRuleIds.size()) + ")"); | |||
for (int i = 0; i < activeRuleIds.size(); i++) { | |||
stmt.setInt(i + 1, activeRuleIds.get(i)); | |||
} | |||
iterator = new ActiveRuleIteratorInternal(stmt); | |||
} catch (Exception e) { | |||
throw new IllegalStateException("Fail to prepare SQL request to select active_rules", e); | |||
} | |||
} | |||
@Override | |||
public boolean hasNext() { | |||
return iterator.hasNext(); | |||
} | |||
@Override | |||
public ActiveRuleDoc next() { | |||
return iterator.next(); | |||
} | |||
@Override | |||
public void close() { | |||
try { | |||
iterator.close(); | |||
} finally { | |||
DatabaseUtils.closeQuietly(stmt); | |||
} | |||
} | |||
private static final class ActiveRuleIteratorInternal extends ResultSetIterator<ActiveRuleDoc> { | |||
ActiveRuleIteratorInternal(PreparedStatement stmt) throws SQLException { | |||
super(stmt); | |||
} | |||
@Override | |||
protected ActiveRuleDoc read(ResultSet rs) throws SQLException { | |||
long activeRuleId = rs.getLong(1); | |||
int severity = rs.getInt(2); | |||
String inheritance = rs.getString(3); | |||
RuleKey ruleKey = RuleKey.of(rs.getString(4), rs.getString(5)); | |||
String ruleProfileUuid = rs.getString(6); | |||
return new ActiveRuleDoc(String.valueOf(activeRuleId)) | |||
.setRuleProfileUuid(ruleProfileUuid) | |||
.setRuleKey(ruleKey) | |||
// all the fields must be present, even if value is null | |||
.setSeverity(SeverityUtil.getSeverityFromOrdinal(severity)) | |||
.setInheritance(inheritance == null ? ActiveRule.Inheritance.NONE.name() : inheritance); | |||
} | |||
} | |||
} |
@@ -1,93 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.qualityprofile.index; | |||
import java.sql.PreparedStatement; | |||
import java.sql.ResultSet; | |||
import java.sql.SQLException; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.ResultSetIterator; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.rule.SeverityUtil; | |||
import org.sonar.server.qualityprofile.ActiveRule; | |||
/** | |||
* Scrolls over table ACTIVE_RULES and reads documents to populate the active rules index | |||
*/ | |||
public class ActiveRuleResultSetIterator extends ResultSetIterator<ActiveRuleDoc> { | |||
private static final String[] FIELDS = { | |||
"ar.failure_level", | |||
"ar.inheritance", | |||
"r.plugin_name", | |||
"r.plugin_rule_key", | |||
"oqp.organization_uuid", | |||
"oqp.uuid", | |||
"ar.updated_at" | |||
}; | |||
private static final String SQL_ALL = "select " + StringUtils.join(FIELDS, ",") + " from active_rules ar " + | |||
" inner join rules_profiles rp on rp.id = ar.profile_id " + | |||
" inner join org_qprofiles oqp on oqp.uuid = rp.kee " + | |||
" inner join rules r on r.id = ar.rule_id "; | |||
private static final String SQL_AFTER_DATE = SQL_ALL + " where ar.updated_at>?"; | |||
private ActiveRuleResultSetIterator(PreparedStatement stmt) throws SQLException { | |||
super(stmt); | |||
} | |||
static ActiveRuleResultSetIterator create(DbClient dbClient, DbSession session, long afterDate) { | |||
try { | |||
String sql = afterDate > 0L ? SQL_AFTER_DATE : SQL_ALL; | |||
PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(session, sql); | |||
if (afterDate > 0L) { | |||
stmt.setLong(1, afterDate); | |||
} | |||
return new ActiveRuleResultSetIterator(stmt); | |||
} catch (SQLException e) { | |||
throw new IllegalStateException("Fail to prepare SQL request to select all active rules", e); | |||
} | |||
} | |||
@Override | |||
protected ActiveRuleDoc read(ResultSet rs) throws SQLException { | |||
int severity = rs.getInt(1); | |||
String inheritance = rs.getString(2); | |||
RuleKey ruleKey = RuleKey.of(rs.getString(3), rs.getString(4)); | |||
String organizationUuid = rs.getString(5); | |||
String profileKey = rs.getString(6); | |||
ActiveRuleKey activeRuleKey = ActiveRuleKey.of(profileKey, ruleKey); | |||
ActiveRuleDoc doc = new ActiveRuleDoc(activeRuleKey); | |||
doc.setOrganizationUuid(organizationUuid); | |||
// all the fields must be present, even if value is null | |||
doc.setSeverity(SeverityUtil.getSeverityFromOrdinal(severity)); | |||
doc.setInheritance(inheritance == null ? ActiveRule.Inheritance.NONE.name() : inheritance); | |||
doc.setUpdatedAt(rs.getLong(7)); | |||
return doc; | |||
} | |||
} |
@@ -110,9 +110,9 @@ public class ActivateRuleAction implements QProfileWsAction { | |||
QProfileDto profile = wsSupport.getProfile(dbSession, QProfileReference.fromKey(profileKey)); | |||
wsSupport.checkPermission(dbSession, profile); | |||
wsSupport.checkNotBuiltInt(profile); | |||
List<ActiveRuleChange> changes = ruleActivator.activate(dbSession, activation, profileKey); | |||
List<ActiveRuleChange> changes = ruleActivator.activate(dbSession, activation, profile); | |||
dbSession.commit(); | |||
activeRuleIndexer.index(changes); | |||
activeRuleIndexer.indexChanges(dbSession, changes); | |||
} | |||
response.noContent(); | |||
} |
@@ -86,7 +86,7 @@ public class ActivateRulesAction implements QProfileWsAction { | |||
QProfileDto profile = wsSupport.getProfile(dbSession, fromKey(qualityProfileKey)); | |||
wsSupport.checkPermission(dbSession, profile); | |||
wsSupport.checkNotBuiltInt(profile); | |||
result = ruleActivator.bulkActivate(ruleQueryFactory.createRuleQuery(dbSession, request), qualityProfileKey, request.param(SEVERITY)); | |||
result = ruleActivator.bulkActivate(dbSession, ruleQueryFactory.createRuleQuery(dbSession, request), profile, request.param(SEVERITY)); | |||
} | |||
BulkChangeWsResponse.writeResponse(result, response); | |||
} |
@@ -95,13 +95,13 @@ public class ChangeParentAction implements QProfileWsAction { | |||
String parentKey = request.param(PARAM_PARENT_KEY); | |||
String parentName = request.param(PARAM_PARENT_NAME); | |||
if (isEmpty(parentKey) && isEmpty(parentName)) { | |||
ruleActivator.setParent(dbSession, profile.getKee(), null); | |||
ruleActivator.setParent(dbSession, profile, null); | |||
} else { | |||
String parentOrganizationKey = parentKey == null ? organization.getKey() : null; | |||
String parentLanguage = parentKey == null ? request.param(PARAM_LANGUAGE) : null; | |||
QProfileReference parentRef = QProfileReference.from(parentKey, parentOrganizationKey, parentLanguage, parentName); | |||
QProfileDto parent = wsSupport.getProfile(dbSession, parentRef); | |||
ruleActivator.setParent(dbSession, profile.getKee(), parent.getKee()); | |||
ruleActivator.setParent(dbSession, profile, parent); | |||
} | |||
response.noContent(); | |||
} |
@@ -125,7 +125,7 @@ public class ChangelogAction implements QProfileWsAction { | |||
json.endObject().close(); | |||
} | |||
private void writeParameters(JsonWriter json, ChangelogLoader.Change change) { | |||
private static void writeParameters(JsonWriter json, ChangelogLoader.Change change) { | |||
json.name("params").beginObject() | |||
.prop("severity", change.getSeverity()); | |||
for (Map.Entry<String, String> param : change.getParams().entrySet()) { |
@@ -58,7 +58,7 @@ public class ChangelogLoader { | |||
.collect(MoreCollectors.toList(dtos.size())); | |||
completeUserAndRuleNames(dbSession, changes); | |||
int total = dbClient.qProfileChangeDao().countForProfileUuid(dbSession, query.getProfileUuid()); | |||
int total = dbClient.qProfileChangeDao().countForQProfileUuid(dbSession, query.getProfileUuid()); | |||
return new Changelog(total, changes); | |||
} | |||
@@ -158,7 +158,7 @@ public class ChangelogLoader { | |||
private static Change from(QProfileChangeDto dto) { | |||
Map<String, String> data = dto.getDataAsMap(); | |||
Change change = new Change(); | |||
change.key = dto.getKey(); | |||
change.key = dto.getUuid(); | |||
change.userLogin = dto.getLogin(); | |||
change.type = dto.getChangeType(); | |||
change.at = dto.getCreatedAt(); |
@@ -134,7 +134,7 @@ public class CreateAction implements QProfileWsAction { | |||
} | |||
} | |||
dbSession.commit(); | |||
activeRuleIndexer.index(result.getChanges()); | |||
activeRuleIndexer.indexChanges(dbSession, result.getChanges()); | |||
return buildResponse(result, organization); | |||
} | |||
@@ -27,7 +27,6 @@ import org.sonar.api.server.ws.WebService; | |||
import org.sonar.core.util.Uuids; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.user.UserSession; | |||
@@ -79,8 +78,7 @@ public class DeactivateRuleAction implements QProfileWsAction { | |||
QProfileDto profile = wsSupport.getProfile(dbSession, QProfileReference.fromKey(qualityProfileKey)); | |||
wsSupport.checkPermission(dbSession, profile); | |||
wsSupport.checkNotBuiltInt(profile); | |||
ActiveRuleKey activeRuleKey = ActiveRuleKey.of(qualityProfileKey, ruleKey); | |||
ruleActivator.deactivateAndUpdateIndex(dbSession, activeRuleKey); | |||
ruleActivator.deactivateAndUpdateIndex(dbSession, profile, ruleKey); | |||
} | |||
response.noContent(); | |||
} |
@@ -80,7 +80,7 @@ public class DeactivateRulesAction implements QProfileWsAction { | |||
QProfileDto profile = wsSupport.getProfile(dbSession, QProfileReference.fromKey(qualityProfileKey)); | |||
wsSupport.checkPermission(dbSession, profile); | |||
wsSupport.checkNotBuiltInt(profile); | |||
result = ruleActivator.bulkDeactivate(ruleQueryFactory.createRuleQuery(dbSession, request), qualityProfileKey); | |||
result = ruleActivator.bulkDeactivate(dbSession, ruleQueryFactory.createRuleQuery(dbSession, request), profile); | |||
} | |||
BulkChangeWsResponse.writeResponse(result, response); | |||
} |
@@ -79,14 +79,14 @@ public class DeleteAction implements QProfileWsAction { | |||
List<QProfileDto> descendants = selectDescendants(dbSession, profile); | |||
ensureNoneIsMarkedAsDefault(dbSession, profile, descendants); | |||
profileFactory.deleteByKeys(dbSession, toKeys(profile, descendants)); | |||
profileFactory.delete(dbSession, merge(profile, descendants)); | |||
dbSession.commit(); | |||
} | |||
response.noContent(); | |||
} | |||
private List<QProfileDto> selectDescendants(DbSession dbSession, QProfileDto profile) { | |||
return dbClient.qualityProfileDao().selectDescendants(dbSession, profile.getKee()); | |||
return dbClient.qualityProfileDao().selectDescendants(dbSession, profile); | |||
} | |||
private void ensureNoneIsMarkedAsDefault(DbSession dbSession, QProfileDto profile, List<QProfileDto> descendants) { | |||
@@ -105,9 +105,8 @@ public class DeleteAction implements QProfileWsAction { | |||
}); | |||
} | |||
private static List<String> toKeys(QProfileDto profile, List<QProfileDto> descendants) { | |||
private static List<QProfileDto> merge(QProfileDto profile, List<QProfileDto> descendants) { | |||
return Stream.concat(Stream.of(profile), descendants.stream()) | |||
.map(QProfileDto::getKee) | |||
.collect(MoreCollectors.toList(descendants.size() + 1)); | |||
} | |||
} |
@@ -126,7 +126,7 @@ public class ExportAction implements QProfileWsAction { | |||
backuper.backup(dbSession, profile, writer); | |||
} else { | |||
stream.setMediaType(exporters.mimeType(exporterKey)); | |||
exporters.export(profile, exporterKey, writer); | |||
exporters.export(dbSession, profile, exporterKey, writer); | |||
} | |||
} | |||
} |
@@ -76,7 +76,7 @@ public class InheritanceAction implements QProfileWsAction { | |||
OrganizationDto organization = dbClient.organizationDao().selectByUuid(dbSession, organizationUuid) | |||
.orElseThrow(() -> new IllegalStateException(String.format("Could not find organization with uuid '%s' for quality profile '%s'", organizationUuid, profile.getKee()))); | |||
List<QProfileDto> ancestors = profileLookup.ancestors(profile, dbSession); | |||
List<QProfileDto> children = dbClient.qualityProfileDao().selectChildren(dbSession, profile.getKee()); | |||
List<QProfileDto> children = dbClient.qualityProfileDao().selectChildren(dbSession, profile); | |||
Statistics statistics = new Statistics(dbSession, organization); | |||
writeProtobuf(buildResponse(profile, ancestors, children, statistics), request, response); | |||
@@ -121,8 +121,8 @@ public class InheritanceAction implements QProfileWsAction { | |||
private Statistics(DbSession dbSession, OrganizationDto organization) { | |||
ActiveRuleDao dao = dbClient.activeRuleDao(); | |||
countRulesByProfileKey = dao.countActiveRulesByProfileKey(dbSession, organization); | |||
countOverridingRulesByProfileKey = dao.countActiveRulesForInheritanceByProfileKey(dbSession, organization, ActiveRuleDto.OVERRIDES); | |||
countRulesByProfileKey = dao.countActiveRulesByProfileUuid(dbSession, organization); | |||
countOverridingRulesByProfileKey = dao.countActiveRulesForInheritanceByProfileUuid(dbSession, organization, ActiveRuleDto.OVERRIDES); | |||
} | |||
} | |||
} |
@@ -162,8 +162,8 @@ public class SearchAction implements QProfileWsAction { | |||
return new SearchData() | |||
.setOrganization(organization) | |||
.setProfiles(profiles) | |||
.setActiveRuleCountByProfileKey(dbClient.activeRuleDao().countActiveRulesByProfileKey(dbSession, organization)) | |||
.setActiveDeprecatedRuleCountByProfileKey(dbClient.activeRuleDao().countActiveRulesForRuleStatusByProfileKey(dbSession, organization, RuleStatus.DEPRECATED)) | |||
.setActiveRuleCountByProfileKey(dbClient.activeRuleDao().countActiveRulesByProfileUuid(dbSession, organization)) | |||
.setActiveDeprecatedRuleCountByProfileKey(dbClient.activeRuleDao().countActiveRulesForRuleStatusByProfileUuid(dbSession, organization, RuleStatus.DEPRECATED)) | |||
.setProjectCountByProfileKey(dbClient.qualityProfileDao().countProjectsByProfileUuid(dbSession, organization)) | |||
.setDefaultProfileKeys(defaultProfiles); | |||
} |
@@ -96,12 +96,12 @@ public class RegisterRules implements Startable { | |||
@Override | |||
public void start() { | |||
Profiler profiler = Profiler.create(LOG).startInfo("Register rules"); | |||
try (DbSession session = dbClient.openSession(false)) { | |||
Map<RuleKey, RuleDefinitionDto> allRules = loadRules(session); | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
Map<RuleKey, RuleDefinitionDto> allRules = loadRules(dbSession); | |||
List<RuleKey> keysToIndex = new ArrayList<>(); | |||
RulesDefinition.Context context = defLoader.load(); | |||
boolean orgsEnabled = organizationFlags.isEnabled(session); | |||
boolean orgsEnabled = organizationFlags.isEnabled(dbSession); | |||
for (RulesDefinition.ExtendedRepository repoDef : getRepositories(context)) { | |||
if (languages.get(repoDef.language()) != null) { | |||
for (RulesDefinition.Rule ruleDef : repoDef.rules()) { | |||
@@ -116,22 +116,22 @@ public class RegisterRules implements Startable { | |||
} | |||
continue; | |||
} | |||
boolean relevantForIndex = registerRule(ruleDef, allRules, session); | |||
boolean relevantForIndex = registerRule(ruleDef, allRules, dbSession); | |||
if (relevantForIndex) { | |||
keysToIndex.add(ruleKey); | |||
} | |||
} | |||
session.commit(); | |||
dbSession.commit(); | |||
} | |||
} | |||
List<RuleDefinitionDto> removedRules = processRemainingDbRules(allRules.values(), session); | |||
List<ActiveRuleChange> changes = removeActiveRulesOnStillExistingRepositories(session, removedRules, context); | |||
session.commit(); | |||
List<RuleDefinitionDto> removedRules = processRemainingDbRules(allRules.values(), dbSession); | |||
List<ActiveRuleChange> changes = removeActiveRulesOnStillExistingRepositories(dbSession, removedRules, context); | |||
dbSession.commit(); | |||
keysToIndex.addAll(removedRules.stream().map(RuleDefinitionDto::getKey).collect(Collectors.toList())); | |||
persistRepositories(session, context.repositories()); | |||
persistRepositories(dbSession, context.repositories()); | |||
ruleIndexer.indexRuleDefinitions(keysToIndex); | |||
activeRuleIndexer.index(changes); | |||
activeRuleIndexer.indexChanges(dbSession, changes); | |||
profiler.stopDebug(); | |||
webServerRuleFinder.startCaching(); | |||
@@ -336,7 +336,7 @@ public class RegisterRules implements Startable { | |||
RulesDefinition.Param paramDef = ruleDef.param(paramDto.getName()); | |||
if (paramDef == null) { | |||
profiler.start(); | |||
dbClient.activeRuleDao().deleteParamsByRuleParamOfAllOrganizations(session, rule.getId(), paramDto.getName()); | |||
dbClient.activeRuleDao().deleteParamsByRuleParamOfAllOrganizations(session, paramDto); | |||
profiler.stopDebug(format("Propagate deleted param with name %s to active rules of rule %s", paramDto.getName(), rule.getKey())); | |||
dbClient.ruleDao().deleteRuleParam(session, paramDto.getId()); | |||
} else { |
@@ -43,6 +43,7 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.OrgActiveRuleDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
@@ -232,8 +233,8 @@ public class RuleUpdater { | |||
} | |||
private Multimap<ActiveRuleDto, ActiveRuleParamDto> getActiveRuleParamsByActiveRule(DbSession dbSession, OrganizationDto organization, RuleDto customRule) { | |||
List<ActiveRuleDto> activeRuleDtos = dbClient.activeRuleDao().selectByRuleId(dbSession, organization, customRule.getId()); | |||
Map<Integer, ActiveRuleDto> activeRuleById = from(activeRuleDtos).uniqueIndex(ActiveRuleDto::getId); | |||
List<OrgActiveRuleDto> activeRuleDtos = dbClient.activeRuleDao().selectByRuleId(dbSession, organization, customRule.getId()); | |||
Map<Integer, OrgActiveRuleDto> activeRuleById = from(activeRuleDtos).uniqueIndex(ActiveRuleDto::getId); | |||
List<Integer> activeRuleIds = Lists.transform(activeRuleDtos, ActiveRuleDto::getId); | |||
List<ActiveRuleParamDto> activeRuleParamDtos = dbClient.activeRuleDao().selectParamsByActiveRuleIds(dbSession, activeRuleIds); | |||
return from(activeRuleParamDtos) | |||
@@ -272,14 +273,14 @@ public class RuleUpdater { | |||
} | |||
private static class ActiveRuleParamToActiveRule implements Function<ActiveRuleParamDto, ActiveRuleDto> { | |||
private final Map<Integer, ActiveRuleDto> activeRuleById; | |||
private final Map<Integer, OrgActiveRuleDto> activeRuleById; | |||
private ActiveRuleParamToActiveRule(Map<Integer, ActiveRuleDto> activeRuleById) { | |||
private ActiveRuleParamToActiveRule(Map<Integer, OrgActiveRuleDto> activeRuleById) { | |||
this.activeRuleById = activeRuleById; | |||
} | |||
@Override | |||
public ActiveRuleDto apply(@Nonnull ActiveRuleParamDto input) { | |||
public OrgActiveRuleDto apply(@Nonnull ActiveRuleParamDto input) { | |||
return activeRuleById.get(input.getActiveRuleId()); | |||
} | |||
} | |||
@@ -303,7 +304,7 @@ public class RuleUpdater { | |||
.uniqueIndex(ActiveRuleParamDto::getKey); | |||
ActiveRuleParamDto activeRuleParamDto = activeRuleParamByKey.get(ruleParamDto.getName()); | |||
if (activeRuleParamDto != null) { | |||
dbClient.activeRuleDao().updateParam(dbSession, activeRuleDto, activeRuleParamDto.setValue(ruleParamDto.getDefaultValue())); | |||
dbClient.activeRuleDao().updateParam(dbSession, activeRuleParamDto.setValue(ruleParamDto.getDefaultValue())); | |||
} else { | |||
dbClient.activeRuleDao().insertParam(dbSession, activeRuleDto, ActiveRuleParamDto.createFor(ruleParamDto).setValue(ruleParamDto.getDefaultValue())); | |||
} |
@@ -76,8 +76,7 @@ import static org.sonar.server.es.EsUtils.SCROLL_TIME_IN_MINUTES; | |||
import static org.sonar.server.es.EsUtils.escapeSpecialRegexChars; | |||
import static org.sonar.server.es.EsUtils.scrollIds; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_ORGANIZATION_UUID; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_UUID; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_CREATED_AT; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_EXTENSION_SCOPE; | |||
@@ -251,11 +250,10 @@ public class RuleIndex { | |||
if (isNotEmpty(query.getTags())) { | |||
BoolQueryBuilder q = boolQuery(); | |||
String organizationUuid = query.getOrganizationUuid(); | |||
query.getTags().stream() | |||
.map(tag -> boolQuery() | |||
.filter(QueryBuilders.termQuery(FIELD_RULE_EXTENSION_TAGS, tag)) | |||
.filter(termsQuery(FIELD_RULE_EXTENSION_SCOPE, RuleExtensionScope.system().getScope(), RuleExtensionScope.organization(organizationUuid).getScope()))) | |||
.filter(termsQuery(FIELD_RULE_EXTENSION_SCOPE, RuleExtensionScope.system().getScope(), RuleExtensionScope.organization(query.getOrganization()).getScope()))) | |||
.map(childQuery -> QueryBuilders.hasChildQuery(INDEX_TYPE_RULE_EXTENSION.getType(), childQuery)) | |||
.forEach(q::filter); | |||
filters.put(FIELD_RULE_EXTENSION_TAGS, q); | |||
@@ -293,14 +291,13 @@ public class RuleIndex { | |||
} | |||
/* Implementation of activation query */ | |||
if (query.getActivation() != null) { | |||
if (query.getActivation() != null && query.getQProfile() != null) { | |||
// ActiveRule Filter (profile and inheritance) | |||
BoolQueryBuilder childrenFilter = boolQuery(); | |||
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_PROFILE_KEY, query.getQProfileKey()); | |||
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_PROFILE_UUID, query.getQProfile().getRulesProfileUuid()); | |||
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_INHERITANCE, query.getInheritance()); | |||
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_SEVERITY, query.getActiveSeverities()); | |||
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_ORGANIZATION_UUID, query.getOrganizationUuid()); | |||
// ChildQuery | |||
QueryBuilder childQuery; | |||
@@ -370,15 +367,14 @@ public class RuleIndex { | |||
} | |||
if (options.getFacets().contains(FACET_TAGS) || options.getFacets().contains(FACET_OLD_DEFAULT)) { | |||
Collection<String> tags = query.getTags(); | |||
String organizationUuid = query.getOrganizationUuid(); | |||
checkArgument(organizationUuid != null, "Cannot use tags facet, if no organization is specified.", query.getTags()); | |||
checkArgument(query.getOrganization() != null, "Cannot use tags facet, if no organization is specified.", query.getTags()); | |||
Function<TermsBuilder, AggregationBuilder<?>> childFeature = termsAggregation -> { | |||
FilterAggregationBuilder scopeAggregation = AggregationBuilders.filter("scope_filter_for_" + FACET_TAGS).filter( | |||
termsQuery(FIELD_RULE_EXTENSION_SCOPE, | |||
RuleExtensionScope.system().getScope(), | |||
RuleExtensionScope.organization(organizationUuid).getScope())) | |||
RuleExtensionScope.organization(query.getOrganization()).getScope())) | |||
.subAggregation(termsAggregation); | |||
return AggregationBuilders.children("children_for_" + termsAggregation.getName()) | |||
@@ -433,7 +429,7 @@ public class RuleIndex { | |||
// Rebuilding the active rule filter without severities | |||
BoolQueryBuilder childrenFilter = boolQuery(); | |||
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_PROFILE_KEY, query.getQProfileKey()); | |||
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_PROFILE_UUID, query.getQProfile().getRulesProfileUuid()); | |||
RuleIndex.addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_INHERITANCE, query.getInheritance()); | |||
QueryBuilder activeRuleFilter; | |||
if (childrenFilter.hasClauses()) { |
@@ -71,19 +71,30 @@ public class RuleIndexDefinition implements IndexDefinition { | |||
// Active rule fields | |||
public static final IndexType INDEX_TYPE_ACTIVE_RULE = new IndexType(INDEX, "activeRule"); | |||
public static final String FIELD_ACTIVE_RULE_ORGANIZATION_UUID = "organizationUuid"; | |||
public static final String FIELD_ACTIVE_RULE_KEY = "key"; | |||
public static final String FIELD_ACTIVE_RULE_REPOSITORY = "repo"; | |||
public static final String FIELD_ACTIVE_RULE_INHERITANCE = "inheritance"; | |||
public static final String FIELD_ACTIVE_RULE_PROFILE_KEY = "profile"; | |||
public static final String FIELD_ACTIVE_RULE_PROFILE_UUID = "ruleProfile"; | |||
public static final String FIELD_ACTIVE_RULE_SEVERITY = "severity"; | |||
public static final String FIELD_ACTIVE_RULE_RULE_KEY = "ruleKey"; | |||
public static final String FIELD_ACTIVE_RULE_UPDATED_AT = "updatedAt"; | |||
private final Settings settings; | |||
private final boolean enableSource; | |||
public RuleIndexDefinition(Settings settings) { | |||
this(settings, false); | |||
} | |||
private RuleIndexDefinition(Settings settings, boolean enableSource) { | |||
this.settings = settings; | |||
this.enableSource = enableSource; | |||
} | |||
/** | |||
* Keep the document sources in index so that indexer tests can verify content | |||
* of indexed documents. | |||
*/ | |||
public static RuleIndexDefinition createForTest(Settings settings) { | |||
return new RuleIndexDefinition(settings, true); | |||
} | |||
@Override | |||
@@ -95,21 +106,18 @@ public class RuleIndexDefinition implements IndexDefinition { | |||
// Active rule type | |||
NewIndex.NewIndexType activeRuleMapping = index.createType(INDEX_TYPE_ACTIVE_RULE.getType()); | |||
activeRuleMapping.setEnableSource(false); | |||
activeRuleMapping.setEnableSource(enableSource); | |||
activeRuleMapping.setAttribute("_parent", ImmutableMap.of("type", INDEX_TYPE_RULE.getType())); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_ORGANIZATION_UUID).disableNorms().build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_KEY).addSubFields(SORTABLE_ANALYZER).build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_RULE_KEY).addSubFields(SORTABLE_ANALYZER).build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_REPOSITORY).build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_PROFILE_KEY).disableNorms().build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_PROFILE_UUID).disableNorms().build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_INHERITANCE).disableNorms().build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_SEVERITY).disableNorms().build(); | |||
activeRuleMapping.createLongField(FIELD_ACTIVE_RULE_UPDATED_AT); | |||
// Rule extension type | |||
NewIndex.NewIndexType ruleExtensionType = index.createType(INDEX_TYPE_RULE_EXTENSION.getType()); | |||
ruleExtensionType.setEnableSource(false); | |||
ruleExtensionType.setEnableSource(enableSource); | |||
ruleExtensionType.setAttribute("_parent", ImmutableMap.of("type", INDEX_TYPE_RULE.getType())); | |||
ruleExtensionType.stringFieldBuilder(FIELD_RULE_EXTENSION_SCOPE).disableNorms().build(); | |||
@@ -118,7 +126,7 @@ public class RuleIndexDefinition implements IndexDefinition { | |||
// Rule type | |||
NewIndex.NewIndexType ruleMapping = index.createType(INDEX_TYPE_RULE.getType()); | |||
ruleMapping.setEnableSource(false); | |||
ruleMapping.setEnableSource(enableSource); | |||
ruleMapping.stringFieldBuilder(FIELD_RULE_KEY).addSubFields(SORTABLE_ANALYZER).build(); | |||
ruleMapping.stringFieldBuilder(FIELD_RULE_RULE_KEY).addSubFields(SORTABLE_ANALYZER).build(); | |||
@@ -137,7 +145,7 @@ public class RuleIndexDefinition implements IndexDefinition { | |||
ruleMapping.createBooleanField(FIELD_RULE_IS_TEMPLATE); | |||
ruleMapping.stringFieldBuilder(FIELD_RULE_TEMPLATE_KEY).disableNorms().build(); | |||
ruleMapping.stringFieldBuilder(FIELD_RULE_TYPE).disableNorms().build(); | |||
ruleMapping.createLongField(FIELD_RULE_CREATED_AT); |
@@ -49,8 +49,8 @@ public class RuleIteratorForSingleChunk implements RuleIterator { | |||
private static final String[] FIELDS = { | |||
// column 1 | |||
"r.plugin_rule_key", | |||
"r.plugin_name", | |||
"r.plugin_rule_key", | |||
"r.name", | |||
"r.description", | |||
"r.description_format", | |||
@@ -159,8 +159,8 @@ public class RuleIteratorForSingleChunk implements RuleIterator { | |||
RuleDoc doc = new RuleDoc(); | |||
RuleExtensionDoc extensionDoc = new RuleExtensionDoc().setScope(RuleExtensionScope.system()); | |||
String ruleKey = rs.getString(1); | |||
String repositoryKey = rs.getString(2); | |||
String repositoryKey = rs.getString(1); | |||
String ruleKey = rs.getString(2); | |||
RuleKey key = RuleKey.of(repositoryKey, ruleKey); | |||
extensionDoc.setRuleKey(key); | |||
@@ -109,8 +109,8 @@ public class RuleMetadataIterator implements Iterator<RuleExtensionDoc>, AutoClo | |||
protected RuleExtensionDoc read(ResultSet rs) throws SQLException { | |||
RuleExtensionDoc doc = new RuleExtensionDoc(); | |||
String ruleKey = rs.getString(1); | |||
String repositoryKey = rs.getString(2); | |||
String repositoryKey = rs.getString(1); | |||
String ruleKey = rs.getString(2); | |||
RuleKey key = RuleKey.of(repositoryKey, ruleKey); | |||
doc.setRuleKey(key); | |||
doc.setScope(RuleExtensionScope.organization(rs.getString(3))); |