--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.custommeasure.persistence;
+
+import com.google.common.base.Function;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import org.sonar.api.server.ServerSide;
+import org.sonar.core.custommeasure.db.CustomMeasureDto;
+import org.sonar.core.custommeasure.db.CustomMeasureMapper;
+import org.sonar.core.persistence.DaoComponent;
+import org.sonar.core.persistence.DaoUtils;
+import org.sonar.core.persistence.DbSession;
+
+@ServerSide
+public class CustomMeasureDao implements DaoComponent {
+ public void insert(DbSession session, CustomMeasureDto customMeasureDto) {
+ mapper(session).insert(customMeasureDto);
+ }
+
+ public void deleteByMetricIds(final DbSession session, final List<Integer> metricIds) {
+ DaoUtils.executeLargeInputsWithoutOutput(metricIds, new Function<List<Integer>, Void>() {
+ @Override
+ public Void apply(@Nonnull List<Integer> input) {
+ mapper(session).deleteByMetricIds(metricIds);
+ return null;
+ }
+ });
+ }
+
+ @CheckForNull
+ public CustomMeasureDto selectNullableById(DbSession session, long id) {
+ return mapper(session).selectById(id);
+ }
+
+ private CustomMeasureMapper mapper(DbSession session) {
+ return session.getMapper(CustomMeasureMapper.class);
+ }
+}
import org.sonar.server.component.db.ComponentLinkDao;
import org.sonar.server.component.db.SnapshotDao;
import org.sonar.server.computation.db.AnalysisReportDao;
+import org.sonar.server.custommeasure.persistence.CustomMeasureDao;
import org.sonar.server.dashboard.db.DashboardDao;
import org.sonar.server.dashboard.db.WidgetDao;
import org.sonar.server.dashboard.db.WidgetPropertyDao;
private final ComponentLinkDao componentLinkDao;
private final EventDao eventDao;
private final PurgeDao purgeDao;
+ private final CustomMeasureDao customMeasureDao;
public DbClient(Database db, MyBatis myBatis, DaoComponent... daoComponents) {
this.db = db;
resourceDao = getDao(map, ResourceDao.class);
measureDao = getDao(map, MeasureDao.class);
metricDao = getDao(map, MetricDao.class);
+ customMeasureDao = getDao(map, CustomMeasureDao.class);
activityDao = getDao(map, ActivityDao.class);
authorizationDao = getDao(map, AuthorizationDao.class);
userDao = getDao(map, UserDao.class);
return metricDao;
}
+ public CustomMeasureDao customMeasureDao() {
+ return customMeasureDao;
+ }
+
public ActivityDao activityDao() {
return activityDao;
}
package org.sonar.server.metric.persistence;
+import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Maps;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.apache.ibatis.session.RowBounds;
import org.sonar.api.server.ServerSide;
import org.sonar.core.metric.db.MetricDto;
import org.sonar.core.metric.db.MetricMapper;
import org.sonar.core.persistence.DaoComponent;
+import org.sonar.core.persistence.DaoUtils;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.es.SearchOptions;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.util.List;
-import java.util.Map;
-
import static com.google.common.collect.Lists.newArrayList;
@ServerSide
private MetricMapper mapper(DbSession session) {
return session.getMapper(MetricMapper.class);
}
+
+ public List<MetricDto> selectByKeys(final DbSession session, List<String> keys) {
+ return DaoUtils.executeLargeInputs(keys, new Function<List<String>, List<MetricDto>>() {
+ @Override
+ public List<MetricDto> apply(@Nonnull List<String> input) {
+ return mapper(session).selectByKeys(input);
+ }
+ });
+ }
+
+ public void disable(final DbSession session, List<Integer> ids) {
+ DaoUtils.executeLargeInputsWithoutOutput(ids, new Function<List<Integer>, Void>() {
+ @Override
+ public Void apply(@Nonnull List<Integer> input) {
+ mapper(session).disable(input);
+ return null;
+ }
+ });
+ }
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.metric.ws;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+import java.util.List;
+import javax.annotation.Nonnull;
+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.metric.db.MetricDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.user.UserSession;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+public class DeleteAction implements MetricsWsAction {
+ public static final String PARAM_IDS = "ids";
+ public static final String PARAM_KEYS = "keys";
+
+ private final DbClient dbClient;
+ private final UserSession userSession;
+
+ public DeleteAction(DbClient dbClient, UserSession userSession) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context.createAction("delete")
+ .setHandler(this)
+ .setSince("5.2")
+ .setPost(true)
+ .setDescription("Delete metrics and associated measures. Delete only custom metrics.<br />Ids or keys must be provided. <br />Requires 'Administer System' permission.");
+
+ action.createParam(PARAM_IDS)
+ .setDescription("Metrics ids to delete.")
+ .setExampleValue("5, 23, 42");
+
+ action.createParam(PARAM_KEYS)
+ .setDescription("Metrics keys to delete")
+ .setExampleValue("team_size, business_value");
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ List<Integer> ids = loadIds(dbSession, request);
+ dbClient.metricDao().disable(dbSession, ids);
+ dbClient.customMeasureDao().deleteByMetricIds(dbSession, ids);
+ dbSession.commit();
+ } finally {
+ MyBatis.closeQuietly(dbSession);
+ }
+
+ response.noContent();
+ }
+
+ private List<Integer> loadIds(DbSession dbSession, Request request) {
+ List<String> idsAsStrings = request.paramAsStrings(PARAM_IDS);
+ List<String> keys = request.paramAsStrings(PARAM_KEYS);
+ checkArgument(idsAsStrings != null || keys != null, "Ids or keys must be provided.");
+ List<Integer> ids = null;
+ if (idsAsStrings != null) {
+ ids = Lists.transform(idsAsStrings, new Function<String, Integer>() {
+ @Override
+ public Integer apply(String id) {
+ return Integer.valueOf(id);
+ }
+ });
+ } else if (keys != null) {
+ ids = Lists.transform(dbClient.metricDao().selectByKeys(dbSession, keys), new Function<MetricDto, Integer>() {
+ @Override
+ public Integer apply(@Nonnull MetricDto input) {
+ return input.getId();
+ }
+ });
+ }
+
+ return ids;
+ }
+}
import org.sonar.server.component.db.ComponentLinkDao;
import org.sonar.server.component.db.SnapshotDao;
import org.sonar.server.computation.db.AnalysisReportDao;
+import org.sonar.server.custommeasure.persistence.CustomMeasureDao;
import org.sonar.server.dashboard.db.DashboardDao;
import org.sonar.server.dashboard.db.WidgetDao;
import org.sonar.server.dashboard.db.WidgetPropertyDao;
MeasureDao.class,
MetricDao.class,
MeasureFilterDao.class,
+ CustomMeasureDao.class,
// components
ComponentDao.class,
org.sonar.server.metric.ws.ListAction.class,
org.sonar.server.metric.ws.TypesAction.class,
org.sonar.server.metric.ws.DomainsAction.class,
+ org.sonar.server.metric.ws.DeleteAction.class,
// quality gates
QualityGateDao.class,
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.custommeasure.persistence;
+
+import java.util.Arrays;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.core.custommeasure.db.CustomMeasureDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.db.DbClient;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.offset;
+
+@Category(DbTests.class)
+public class CustomMeasureDaoTest {
+ @ClassRule
+ public static DbTester db = new DbTester();
+
+ CustomMeasureDao sut;
+ DbSession session;
+
+ @Before
+ public void setUp() {
+ DbClient dbClient = new DbClient(db.database(), db.myBatis(), new CustomMeasureDao());
+ session = dbClient.openSession(false);
+ sut = dbClient.customMeasureDao();
+ db.truncateTables();
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void insert() {
+ CustomMeasureDto measure = CustomMeasureTesting.newDto();
+
+ sut.insert(session, measure);
+
+ CustomMeasureDto result = sut.selectNullableById(session, measure.getId());
+ assertThat(result.getId()).isEqualTo(measure.getId());
+ assertThat(result.getMetricId()).isEqualTo(measure.getMetricId());
+ assertThat(result.getResourceId()).isEqualTo(measure.getResourceId());
+ assertThat(result.getDescription()).isEqualTo(measure.getDescription());
+ assertThat(result.getUserLogin()).isEqualTo(measure.getUserLogin());
+ assertThat(result.getTextValue()).isEqualTo(measure.getTextValue());
+ assertThat(result.getValue()).isCloseTo(measure.getValue(), offset(0.001d));
+ assertThat(result.getCreatedAt()).isEqualTo(measure.getCreatedAt());
+ assertThat(result.getUpdatedAt()).isEqualTo(measure.getUpdatedAt());
+ }
+
+ @Test
+ public void delete() {
+ CustomMeasureDto measure = CustomMeasureTesting.newDto();
+ sut.insert(session, measure);
+ assertThat(sut.selectNullableById(session, measure.getId())).isNotNull();
+
+ sut.deleteByMetricIds(session, Arrays.asList(measure.getMetricId()));
+
+ assertThat(sut.selectNullableById(session, measure.getId())).isNull();
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.custommeasure.persistence;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.commons.lang.math.RandomUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.core.custommeasure.db.CustomMeasureDto;
+
+public class CustomMeasureTesting {
+ private CustomMeasureTesting() {
+ // static stuff only
+ }
+
+ public static CustomMeasureDto newDto() {
+ return new CustomMeasureDto()
+ .setDescription(RandomStringUtils.random(255))
+ .setTextValue(RandomStringUtils.random(255))
+ .setUserLogin(RandomStringUtils.random(255))
+ .setValue(RandomUtils.nextDouble())
+ .setMetricId(RandomUtils.nextInt())
+ .setResourceId(RandomUtils.nextInt())
+ .setCreatedAt(System2.INSTANCE.now())
+ .setUpdatedAt(System2.INSTANCE.now())
+ ;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.metric.ws;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.core.custommeasure.db.CustomMeasureDto;
+import org.sonar.core.metric.db.MetricDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.custommeasure.persistence.CustomMeasureDao;
+import org.sonar.server.custommeasure.persistence.CustomMeasureTesting;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.metric.persistence.MetricDao;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class DeleteActionTest {
+
+ @ClassRule
+ public static DbTester db = new DbTester();
+ @Rule
+ public UserSessionRule userSessionRule = UserSessionRule.standalone();
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ DbClient dbClient;
+ DbSession dbSession;
+ WsTester ws;
+ MetricDao metricDao;
+
+ @Before
+ public void setUp() throws Exception {
+ dbClient = new DbClient(db.database(), db.myBatis(), new MetricDao(), new CustomMeasureDao());
+ dbSession = dbClient.openSession(false);
+ db.truncateTables();
+ userSessionRule.login("login").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+ ws = new WsTester(new MetricsWs(new DeleteAction(dbClient, userSessionRule)));
+ metricDao = dbClient.metricDao();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ dbSession.close();
+ }
+
+ @Test
+ public void delete_by_keys() throws Exception {
+ insertCustomEnabledMetrics(1, 2, 3);
+ dbSession.commit();
+
+ newRequest().setParam("keys", "key-1, key-3").execute();
+ dbSession.commit();
+
+ List<MetricDto> disabledMetrics = metricDao.selectByKeys(dbSession, Arrays.asList("key-1", "key-3"));
+ assertThat(disabledMetrics).extracting("enabled").containsOnly(false);
+ assertThat(metricDao.selectByKey(dbSession, "key-2").isEnabled()).isTrue();
+ }
+
+ @Test
+ public void delete_by_id() throws Exception {
+ MetricDto metric = newCustomEnabledMetric(1);
+ metricDao.insert(dbSession, metric);
+ dbSession.commit();
+
+ WsTester.Result result = newRequest().setParam("ids", String.valueOf(metric.getId())).execute();
+ dbSession.commit();
+
+ assertThat(metricDao.selectEnabled(dbSession)).isEmpty();
+ result.assertNoContent();
+ }
+
+ @Test
+ public void do_not_delete_non_custom_metric() throws Exception {
+ metricDao.insert(dbSession, newCustomEnabledMetric(1).setUserManaged(false));
+ dbSession.commit();
+
+ newRequest().setParam("keys", "key-1").execute();
+ dbSession.commit();
+
+ MetricDto metric = metricDao.selectByKey(dbSession, "key-1");
+ assertThat(metric.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void delete_associated_measures() throws Exception {
+ MetricDto metric = newCustomEnabledMetric(1);
+ metricDao.insert(dbSession, metric);
+ CustomMeasureDto customMeasure = CustomMeasureTesting.newDto().setMetricId(metric.getId());
+ CustomMeasureDto undeletedCustomMeasure = CustomMeasureTesting.newDto().setMetricId(metric.getId() + 1);
+ dbClient.customMeasureDao().insert(dbSession, customMeasure);
+ dbClient.customMeasureDao().insert(dbSession, undeletedCustomMeasure);
+ dbSession.commit();
+
+ newRequest().setParam("keys", "key-1").execute();
+
+ assertThat(dbClient.customMeasureDao().selectNullableById(dbSession, customMeasure.getId())).isNull();
+ assertThat(dbClient.customMeasureDao().selectNullableById(dbSession, undeletedCustomMeasure.getId())).isNotNull();
+ }
+
+ @Test
+ public void fail_when_no_argument() throws Exception {
+ expectedException.expect(IllegalArgumentException.class);
+
+ newRequest().execute();
+ }
+
+ @Test
+ public void fail_when_insufficient_privileges() throws Exception {
+ expectedException.expect(ForbiddenException.class);
+
+ userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+ insertCustomEnabledMetrics(1);
+
+ newRequest().setParam("keys", "key-1").execute();
+ }
+
+ private MetricDto newCustomEnabledMetric(int id) {
+ return MetricTesting.newDto().setEnabled(true).setUserManaged(true).setKey("key-" + id);
+ }
+
+ private void insertCustomEnabledMetrics(int... ids) {
+ for (int id : ids) {
+ metricDao.insert(dbSession, newCustomEnabledMetric(id));
+ }
+
+ dbSession.commit();
+ }
+
+ private WsTester.TestRequest newRequest() {
+ return ws.newPostRequest(MetricsWs.ENDPOINT, "delete");
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.custommeasure.db;
+
+public class CustomMeasureDto {
+ private long id;
+ private int metricId;
+ private int resourceId;
+ private double value;
+ private String textValue;
+ private String userLogin;
+ private String description;
+ private long createdAt;
+ private long updatedAt;
+
+ public String getDescription() {
+ return description;
+ }
+
+ public CustomMeasureDto setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public String getUserLogin() {
+ return userLogin;
+ }
+
+ public CustomMeasureDto setUserLogin(String userLogin) {
+ this.userLogin = userLogin;
+ return this;
+ }
+
+ public String getTextValue() {
+ return textValue;
+ }
+
+ public CustomMeasureDto setTextValue(String textValue) {
+ this.textValue = textValue;
+ return this;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ public CustomMeasureDto setValue(double value) {
+ this.value = value;
+ return this;
+ }
+
+ public int getResourceId() {
+ return resourceId;
+ }
+
+ public CustomMeasureDto setResourceId(int resourceId) {
+ this.resourceId = resourceId;
+ return this;
+ }
+
+ public int getMetricId() {
+ return metricId;
+ }
+
+ public CustomMeasureDto setMetricId(int metricId) {
+ this.metricId = metricId;
+ return this;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public CustomMeasureDto setId(long id) {
+ this.id = id;
+ return this;
+ }
+
+ public long getUpdatedAt() {
+ return updatedAt;
+ }
+
+ public CustomMeasureDto setUpdatedAt(long updatedAt) {
+ this.updatedAt = updatedAt;
+ return this;
+ }
+
+ public long getCreatedAt() {
+ return createdAt;
+ }
+
+ public CustomMeasureDto setCreatedAt(long createdAt) {
+ this.createdAt = createdAt;
+ return this;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.custommeasure.db;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+
+public interface CustomMeasureMapper {
+ void insert(CustomMeasureDto customMeasureDto);
+
+ void deleteByMetricIds(@Param("metricIds") List<Integer> metricIds);
+
+ CustomMeasureDto selectById(long id);
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.core.custommeasure.db;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
package org.sonar.core.metric.db;
-import org.apache.ibatis.annotations.Param;
-import org.apache.ibatis.session.RowBounds;
-
import java.util.List;
import java.util.Map;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.session.RowBounds;
public interface MetricMapper {
void insert(MetricDto dto);
List<String> selectDomains();
+
+ List<MetricDto> selectByKeys(@Param("keys") List<String> keys);
+
+ void disable(@Param("ids") List<Integer> ids);
}
return results;
}
+ /**
+ * Partition by 1000 elements a list of input and execute a function on each part.
+ * The function has not output (ex: delete operation)
+ *
+ * The goal is to prevent issue with ORACLE when there's more than 1000 elements in a 'in ('X', 'Y', ...)'
+ * and with MsSQL when there's more than 2000 parameters in a query
+ */
+ public static <INPUT> void executeLargeInputsWithoutOutput(Collection<INPUT> input, Function<List<INPUT>, Void> function) {
+ if (input.isEmpty()) {
+ return;
+ }
+
+ List<List<INPUT>> partitions = Lists.partition(newArrayList(input), PARTITION_SIZE_FOR_ORACLE);
+ for (List<INPUT> partition : partitions) {
+ function.apply(partition);
+ }
+ }
+
public static String repeatCondition(String sql, int count, String separator) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++) {
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.computation.db.AnalysisReportMapper;
import org.sonar.core.config.Logback;
+import org.sonar.core.custommeasure.db.CustomMeasureDto;
+import org.sonar.core.custommeasure.db.CustomMeasureMapper;
import org.sonar.core.dashboard.ActiveDashboardDto;
import org.sonar.core.dashboard.ActiveDashboardMapper;
import org.sonar.core.dashboard.DashboardDto;
loadAlias(conf, "FilePathWithHash", FilePathWithHashDto.class);
loadAlias(conf, "UuidWithProjectUuid", UuidWithProjectUuidDto.class);
loadAlias(conf, "Event", EventDto.class);
+ loadAlias(conf, "CustomMeasure", CustomMeasureDto.class);
// AuthorizationMapper has to be loaded before IssueMapper because this last one used it
loadMapper(conf, "org.sonar.core.user.AuthorizationMapper");
ActionPlanStatsMapper.class,
NotificationQueueMapper.class, CharacteristicMapper.class,
GroupMembershipMapper.class, QualityProfileMapper.class, ActiveRuleMapper.class,
- MeasureMapper.class, MetricMapper.class, QualityGateMapper.class, QualityGateConditionMapper.class, ComponentMapper.class, SnapshotMapper.class,
+ MeasureMapper.class, MetricMapper.class, CustomMeasureMapper.class, QualityGateMapper.class, QualityGateConditionMapper.class, ComponentMapper.class, SnapshotMapper.class,
ProjectQgateAssociationMapper.class, EventMapper.class,
AnalysisReportMapper.class, ComponentIndexMapper.class, ComponentLinkMapper.class,
Migration45Mapper.class, Migration50Mapper.class
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.core.custommeasure.db.CustomMeasureMapper">
+ <sql id="selectColumns">
+ m.id,
+ m.metric_id as metricId,
+ m.resource_id as resourceId,
+ m.value,
+ m.text_value as textValue,
+ m.user_login as userLogin,
+ m.description,
+ m.created_at as createdAt,
+ m.updated_at as updatedAt
+ </sql>
+
+ <select id="selectById" resultType="CustomMeasure">
+ select
+ <include refid="selectColumns"/>
+ from manual_measures m
+ where m.id=#{id}
+ </select>
+
+ <insert id="insert" parameterType="CustomMeasure" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+ INSERT INTO manual_measures (
+ metric_id, resource_id, value, text_value, user_login, description, created_at, updated_at
+ )
+ VALUES (
+ #{metricId, jdbcType=INTEGER}, #{resourceId, jdbcType=INTEGER}, #{value, jdbcType=DOUBLE},
+ #{textValue, jdbcType=VARCHAR}, #{userLogin, jdbcType=VARCHAR},#{description, jdbcType=VARCHAR},
+ #{createdAt, jdbcType=BIGINT}, #{updatedAt, jdbcType=BIGINT}
+ )
+ </insert>
+
+ <delete id="deleteByMetricIds">
+ delete from manual_measures
+ where metric_id in
+ <foreach collection="metricIds" item="metricId" open="(" close=")" separator=",">
+ #{metricId}
+ </foreach>
+ </delete>
+</mapper>
ORDER BY UPPER(m.short_name)
</select>
- <insert id="insert" parameterType="org.sonar.core.metric.db.MetricDto" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+ <insert id="insert" parameterType="org.sonar.core.metric.db.MetricDto" useGeneratedKeys="true" keyColumn="id"
+ keyProperty="id">
INSERT INTO metrics (
- name, description, direction, domain, short_name, qualitative, val_type, user_managed, enabled, origin, worst_value, best_value, optimized_best_value, hidden, delete_historical_data)
+ name, description, direction, domain, short_name, qualitative, val_type, user_managed, enabled, origin, worst_value,
+ best_value, optimized_best_value, hidden, delete_historical_data)
VALUES (
#{name, jdbcType=VARCHAR}, #{description, jdbcType=VARCHAR}, #{direction, jdbcType=INTEGER},
#{domain, jdbcType=VARCHAR}, #{shortName, jdbcType=VARCHAR}, #{qualitative, jdbcType=BOOLEAN},
where m.domain is not null
</select>
+ <update id="disable">
+ update metrics
+ set enabled=${_false}
+ <where>
+ AND user_managed=${_true}
+ AND id in
+ <foreach item="id" collection="ids" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </where>
+ </update>
+
+ <select id="selectByKeys" resultType="org.sonar.core.metric.db.MetricDto">
+ SELECT
+ <include refid="metricColumns"/>
+ FROM metrics m
+ <where>
+ AND m.name in
+ <foreach item="key" collection="keys" open="(" separator="," close=")">
+ #{key}
+ </foreach>
+ </where>
+ </select>
+
</mapper>