aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java2
-rw-r--r--server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java1
-rw-r--r--server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl18
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java2
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java7
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java2
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDto.java13
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/component/ResourceDto.java11
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java100
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDto.java141
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java58
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDao.java36
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDto.java12
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureMapper.java24
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureQuery.java29
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureTreeQuery.java17
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/measure/PastMeasureDto.java14
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java39
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java34
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeConfiguration.java4
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java1
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java2
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml3
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml110
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml105
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml15
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java2
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java1
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDtoTest.java4
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/measure/LiveMeasureDaoTest.java146
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDaoTest.java361
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDbTester.java12
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureQueryTest.java7
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTesting.java23
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTreeQueryTest.java3
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/measure/PastMeasureDtoTest.java10
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/measure/ProjectMeasuresIndexerIteratorTest.java225
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java2
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java27
-rw-r--r--server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml2
-rw-r--r--server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml59
-rw-r--r--server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/with_some_measures_for_developer.xml123
-rw-r--r--server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingAnalysis.xml19
-rw-r--r--server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeAnalysis.xml1
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/BaseSqlStatement.java11
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/DataChange.java5
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/SqlStatement.java2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasures.java125
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70.java8
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasures.java84
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasures.java40
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasures.java72
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasuresTest.java59
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70Test.java2
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasuresTest.java125
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasuresTest.java48
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasuresTest.java140
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasuresTest/empty.sql0
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasuresTest/initial.sql98
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasuresTest/initial.sql21
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasuresTest/initial.sql116
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/branch/ws/ListAction.java20
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/ws/AppAction.java34
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectCleaner.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/BestValueOptimization.java7
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MapBasedRawMeasureRepository.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepository.java9
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryImpl.java44
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureToMeasureDto.java27
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistLiveMeasuresStep.java133
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStep.java80
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/duplication/ws/ShowAction.java11
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentAction.java53
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java33
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java8
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeRequest.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java7
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/ws/MetricDtoWithBestValue.java18
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java14
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java23
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java10
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java48
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatter.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java18
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/branch/ws/ListActionTest.java4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ws/AppActionTest.java20
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java44
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/BestValueOptimizationTest.java70
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryRule.java32
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureToMeasureDtoTest.java41
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistLiveMeasuresStepTest.java290
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStepTest.java409
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/duplication/ws/ShowActionTest.java7
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentActionTest.java199
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java141
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java8
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java385
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchHistoryActionTest.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchMyProjectsActionTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java86
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest.java4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java28
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java19
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java17
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java6
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/RuleMeasure.java3
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureTest.java17
-rw-r--r--tests/src/test/java/util/ItUtils.java2
110 files changed, 3087 insertions, 2165 deletions
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
index 5a9d59c19ed..950cbde71b7 100644
--- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
+++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
@@ -115,7 +115,7 @@ public class ComputeEngineContainerImplTest {
assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize(
COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION
+ 26 // level 1
- + 51 // content of DaoModule
+ + 52 // content of DaoModule
+ 3 // content of EsSearchModule
+ 67 // content of CorePropertyDefinitions
+ 1 // StopFlagContainer
diff --git a/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java b/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java
index c01be6b844a..421e67fa5e8 100644
--- a/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java
+++ b/server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java
@@ -69,6 +69,7 @@ public final class SqTables {
"internal_properties",
"issues",
"issue_changes",
+ "live_measures",
"manual_measures",
"metrics",
"notifications",
diff --git a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
index a4b54efd55e..1e43bd3cfbb 100644
--- a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
+++ b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
@@ -284,6 +284,23 @@ CREATE INDEX "DUPLICATIONS_INDEX_HASH" ON "DUPLICATIONS_INDEX" ("HASH");
CREATE INDEX "DUPLICATION_ANALYSIS_COMPONENT" ON "DUPLICATIONS_INDEX" ("ANALYSIS_UUID", "COMPONENT_UUID");
+CREATE TABLE "LIVE_MEASURES" (
+ "UUID" VARCHAR(40) NOT NULL PRIMARY KEY,
+ "PROJECT_UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "METRIC_ID" INTEGER NOT NULL,
+ "VALUE" DOUBLE,
+ "TEXT_VALUE" VARCHAR(4000),
+ "VARIATION" DOUBLE,
+ "MEASURE_DATA" BINARY,
+ "UPDATE_MARKER" VARCHAR(40),
+ "CREATED_AT" BIGINT NOT NULL,
+ "UPDATED_AT" BIGINT NOT NULL
+);
+CREATE INDEX "LIVE_MEASURES_PROJECT" ON "LIVE_MEASURES" ("PROJECT_UUID");
+CREATE UNIQUE INDEX "LIVE_MEASURES_COMPONENT" ON "LIVE_MEASURES" ("COMPONENT_UUID", "METRIC_ID");
+
+
CREATE TABLE "PROJECT_MEASURES" (
"ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"VALUE" DOUBLE,
@@ -304,7 +321,6 @@ CREATE TABLE "PROJECT_MEASURES" (
);
CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES" ("COMPONENT_UUID");
CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES" ("ANALYSIS_UUID", "METRIC_ID");
-CREATE INDEX "MEASURES_PERSON" ON "PROJECT_MEASURES" ("PERSON_ID");
CREATE TABLE "INTERNAL_PROPERTIES" (
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
index 06a3216c6c7..e9419b755fb 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
@@ -39,6 +39,7 @@ import org.sonar.db.es.EsQueueDao;
import org.sonar.db.event.EventDao;
import org.sonar.db.issue.IssueChangeDao;
import org.sonar.db.issue.IssueDao;
+import org.sonar.db.measure.LiveMeasureDao;
import org.sonar.db.measure.MeasureDao;
import org.sonar.db.measure.custom.CustomMeasureDao;
import org.sonar.db.metric.MetricDao;
@@ -92,6 +93,7 @@ public class DaoModule extends Module {
ComponentDao.class,
ComponentKeyUpdaterDao.class,
ComponentLinkDao.class,
+ LiveMeasureDao.class,
CustomMeasureDao.class,
DefaultQProfileDao.class,
DuplicationDao.class,
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
index 1cc3778af49..ce3e71e8087 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
@@ -37,6 +37,7 @@ import org.sonar.db.es.EsQueueDao;
import org.sonar.db.event.EventDao;
import org.sonar.db.issue.IssueChangeDao;
import org.sonar.db.issue.IssueDao;
+import org.sonar.db.measure.LiveMeasureDao;
import org.sonar.db.measure.MeasureDao;
import org.sonar.db.measure.custom.CustomMeasureDao;
import org.sonar.db.metric.MetricDao;
@@ -130,6 +131,7 @@ public class DbClient {
private final AnalysisPropertiesDao analysisPropertiesDao;
private final QProfileEditUsersDao qProfileEditUsersDao;
private final QProfileEditGroupsDao qProfileEditGroupsDao;
+ private final LiveMeasureDao liveMeasureDao;
public DbClient(Database database, MyBatis myBatis, DBSessions dbSessions, Dao... daos) {
this.database = database;
@@ -191,6 +193,7 @@ public class DbClient {
analysisPropertiesDao = getDao(map, AnalysisPropertiesDao.class);
qProfileEditUsersDao = getDao(map, QProfileEditUsersDao.class);
qProfileEditGroupsDao = getDao(map, QProfileEditGroupsDao.class);
+ liveMeasureDao = getDao(map, LiveMeasureDao.class);
}
public DbSession openSession(boolean batch) {
@@ -405,6 +408,10 @@ public class DbClient {
return qProfileEditGroupsDao;
}
+ public LiveMeasureDao liveMeasureDao() {
+ return liveMeasureDao;
+ }
+
protected <K extends Dao> K getDao(Map<Class, Dao> map, Class<K> clazz) {
return (K) map.get(clazz);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
index 03f2eb1a556..0310390b272 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
@@ -62,6 +62,7 @@ import org.sonar.db.issue.IssueChangeMapper;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.issue.IssueMapper;
import org.sonar.db.issue.ShortBranchIssueDto;
+import org.sonar.db.measure.LiveMeasureMapper;
import org.sonar.db.measure.MeasureDto;
import org.sonar.db.measure.MeasureMapper;
import org.sonar.db.measure.custom.CustomMeasureDto;
@@ -207,6 +208,7 @@ public class MyBatis implements Startable {
ComponentKeyUpdaterMapper.class,
ComponentLinkMapper.class,
ComponentMapper.class,
+ LiveMeasureMapper.class,
CustomMeasureMapper.class,
DefaultQProfileMapper.class,
DuplicationMapper.class,
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDto.java
index 9e69d55f2d9..65e14a2d8a8 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDto.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDto.java
@@ -138,7 +138,6 @@ public class ComponentDto {
private String moduleUuid;
private String moduleUuidPath;
private String copyComponentUuid;
- private String developerUuid;
private String scope;
private String qualifier;
private String path;
@@ -401,16 +400,6 @@ public class ComponentDto {
return this;
}
- @CheckForNull
- public String getDeveloperUuid() {
- return developerUuid;
- }
-
- public ComponentDto setDeveloperUuid(@Nullable String developerUuid) {
- this.developerUuid = developerUuid;
- return this;
- }
-
public Date getCreatedAt() {
return createdAt;
}
@@ -488,7 +477,6 @@ public class ComponentDto {
.append("rootUuid", rootUuid)
.append("mainBranchProjectUuid", mainBranchProjectUuid)
.append("copyComponentUuid", copyComponentUuid)
- .append("developerUuid", developerUuid)
.append("path", path)
.append("deprecatedKey", deprecatedKey)
.append("name", name)
@@ -513,7 +501,6 @@ public class ComponentDto {
copy.moduleUuid = moduleUuid;
copy.moduleUuidPath = moduleUuidPath;
copy.copyComponentUuid = copyComponentUuid;
- copy.developerUuid = developerUuid;
copy.scope = scope;
copy.qualifier = qualifier;
copy.path = path;
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ResourceDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ResourceDto.java
index b8cc1cf53f6..46b06fe7a48 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ResourceDto.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ResourceDto.java
@@ -45,7 +45,6 @@ public class ResourceDto {
private String description;
private String language;
private String copyComponentUuid;
- private String developerUuid;
private Date createdAt;
public Long getId() {
@@ -202,16 +201,6 @@ public class ResourceDto {
return this;
}
- @CheckForNull
- public String getDeveloperUuid() {
- return developerUuid;
- }
-
- public ResourceDto setDeveloperUuid(@Nullable String developerUuid) {
- this.developerUuid = developerUuid;
- return this;
- }
-
public Date getCreatedAt() {
return createdAt;
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java
new file mode 100644
index 00000000000..353e1297327
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java
@@ -0,0 +1,100 @@
+/*
+ * 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.measure;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import javax.annotation.Nullable;
+import org.apache.ibatis.session.ResultHandler;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.Uuids;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+
+import static java.util.Collections.singletonList;
+import static org.sonar.db.DatabaseUtils.executeLargeInputs;
+
+public class LiveMeasureDao implements Dao {
+
+ private final System2 system2;
+
+ public LiveMeasureDao(System2 system2) {
+ this.system2 = system2;
+ }
+
+ public List<LiveMeasureDto> selectByComponentUuids(DbSession dbSession, Collection<String> largeComponentUuids, Collection<Integer> metricIds) {
+ if (largeComponentUuids.isEmpty() || metricIds.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ return executeLargeInputs(
+ largeComponentUuids,
+ componentUuids -> mapper(dbSession).selectByComponentUuidsAndMetricIds(componentUuids, metricIds));
+ }
+
+ public List<LiveMeasureDto> selectByComponentUuidsAndMetricKeys(DbSession dbSession, Collection<String> largeComponentUuids, Collection<String> metricKeys) {
+ if (largeComponentUuids.isEmpty() || metricKeys.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ return executeLargeInputs(
+ largeComponentUuids,
+ componentUuids -> mapper(dbSession).selectByComponentUuidsAndMetricKeys(componentUuids, metricKeys));
+ }
+
+ public Optional<LiveMeasureDto> selectMeasure(DbSession dbSession, String componentUuid, String metricKey) {
+ List<LiveMeasureDto> measures = selectByComponentUuidsAndMetricKeys(dbSession, singletonList(componentUuid), singletonList(metricKey));
+ // couple of columns [component_uuid, metric_id] is unique. List can't have more than 1 item.
+ if (measures.size() == 1) {
+ return Optional.of(measures.get(0));
+ }
+ return Optional.empty();
+ }
+
+ public void selectTreeByQuery(DbSession dbSession, ComponentDto baseComponent, MeasureTreeQuery query, ResultHandler<LiveMeasureDto> resultHandler) {
+ if (query.returnsEmpty()) {
+ return;
+ }
+ mapper(dbSession).selectTreeByQuery(query, baseComponent.uuid(), query.getUuidPath(baseComponent), resultHandler);
+ }
+
+ public void insert(DbSession dbSession, LiveMeasureDto dto) {
+ mapper(dbSession).insert(dto, Uuids.create(), null, system2.now());
+ }
+
+ public void insertOrUpdate(DbSession dbSession, LiveMeasureDto dto, @Nullable String marker) {
+ LiveMeasureMapper mapper = mapper(dbSession);
+ long now = system2.now();
+ if (mapper.update(dto, marker, now) == 0) {
+ mapper.insert(dto, Uuids.create(), marker, now);
+ }
+ }
+
+ public void deleteByProjectUuidExcludingMarker(DbSession dbSession, String projectUuid, String marker) {
+ mapper(dbSession).deleteByProjectUuidExcludingMarker(projectUuid, marker);
+ }
+
+ private static LiveMeasureMapper mapper(DbSession dbSession) {
+ return dbSession.getMapper(LiveMeasureMapper.class);
+ }
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDto.java
new file mode 100644
index 00000000000..b8b9d78aa49
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDto.java
@@ -0,0 +1,141 @@
+/*
+ * 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.measure;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+public class LiveMeasureDto {
+
+ private static final int MAX_TEXT_VALUE_LENGTH = 4000;
+
+ private String componentUuid;
+ private String projectUuid;
+ private int metricId;
+ @Nullable
+ private Double value;
+ @Nullable
+ private String textValue;
+ @Nullable
+ private byte[] data;
+ @Nullable
+ private Double variation;
+
+ public String getComponentUuid() {
+ return componentUuid;
+ }
+
+ public LiveMeasureDto setComponentUuid(String s) {
+ this.componentUuid = s;
+ return this;
+ }
+
+ public String getProjectUuid() {
+ return projectUuid;
+ }
+
+ public LiveMeasureDto setProjectUuid(String s) {
+ this.projectUuid = s;
+ return this;
+ }
+
+ public int getMetricId() {
+ return metricId;
+ }
+
+ public LiveMeasureDto setMetricId(int i) {
+ this.metricId = i;
+ return this;
+ }
+
+ @CheckForNull
+ public Double getValue() {
+ return value;
+ }
+
+ public LiveMeasureDto setValue(@Nullable Double value) {
+ this.value = value;
+ return this;
+ }
+
+ @CheckForNull
+ public String getTextValue() {
+ return textValue;
+ }
+
+ @CheckForNull
+ public byte[] getData() {
+ return data;
+ }
+
+ @CheckForNull
+ public String getDataAsString() {
+ if (data != null) {
+ return new String(data, StandardCharsets.UTF_8);
+ }
+ return textValue;
+ }
+
+ public LiveMeasureDto setData(@Nullable String data) {
+ if (data == null) {
+ this.textValue = null;
+ this.data = null;
+ } else if (data.length() > MAX_TEXT_VALUE_LENGTH) {
+ this.textValue = null;
+ this.data = data.getBytes(StandardCharsets.UTF_8);
+ } else {
+ this.textValue = data;
+ this.data = null;
+ }
+ return this;
+ }
+
+ public LiveMeasureDto setData(@Nullable byte[] data) {
+ this.textValue = null;
+ this.data = data;
+ return this;
+ }
+
+ @CheckForNull
+ public Double getVariation() {
+ return variation;
+ }
+
+ public LiveMeasureDto setVariation(@Nullable Double variation) {
+ this.variation = variation;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("LiveMeasureDto{");
+ sb.append("componentUuid='").append(componentUuid).append('\'');
+ sb.append(", projectUuid='").append(projectUuid).append('\'');
+ sb.append(", metricId=").append(metricId);
+ sb.append(", value=").append(value);
+ sb.append(", variation=").append(variation);
+ sb.append(", textValue='").append(textValue).append('\'');
+ sb.append(", data=").append(Arrays.toString(data));
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java
new file mode 100644
index 00000000000..4cdfa215381
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java
@@ -0,0 +1,58 @@
+/*
+ * 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.measure;
+
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.session.ResultHandler;
+
+public interface LiveMeasureMapper {
+
+ List<LiveMeasureDto> selectByComponentUuidsAndMetricIds(
+ @Param("componentUuids") List<String> componentUuids,
+ @Param("metricIds") Collection<Integer> metricIds);
+
+ List<LiveMeasureDto> selectByComponentUuidsAndMetricKeys(
+ @Param("componentUuids") List<String> componentUuids,
+ @Param("metricKeys") Collection<String> metricKeys);
+
+ void selectTreeByQuery(
+ @Param("query") MeasureTreeQuery measureQuery,
+ @Param("baseUuid") String baseUuid,
+ @Param("baseUuidPath") String baseUuidPath,
+ ResultHandler<LiveMeasureDto> resultHandler);
+
+ void insert(
+ @Param("dto") LiveMeasureDto dto,
+ @Param("uuid") String uuid,
+ @Nullable @Param("marker") String marker,
+ @Param("now") long now);
+
+ int update(
+ @Param("dto") LiveMeasureDto dto,
+ @Nullable @Param("marker") String marker,
+ @Param("now") long now);
+
+ void deleteByProjectUuidExcludingMarker(
+ @Param("projectUuid") String projectUuid,
+ @Param("marker") String marker);
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDao.java
index 1656c3229a2..f6ba91fde59 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDao.java
@@ -19,24 +19,24 @@
*/
package org.sonar.db.measure;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
-import org.apache.ibatis.session.ResultHandler;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
import static java.util.Collections.emptyList;
import static org.sonar.db.DatabaseUtils.executeLargeInputs;
public class MeasureDao implements Dao {
- public Optional<MeasureDto> selectSingle(DbSession dbSession, MeasureQuery query) {
- List<MeasureDto> measures = selectByQuery(dbSession, query);
- return Optional.ofNullable(Iterables.getOnlyElement(measures, null));
+ public Optional<MeasureDto> selectLastMeasure(DbSession dbSession, String componentUuid, String metricKey) {
+ return Optional.ofNullable(mapper(dbSession).selectLastMeasure(componentUuid, metricKey));
+ }
+
+ public Optional<MeasureDto> selectMeasure(DbSession dbSession, String analysisUuid, String componentUuid, String metricKey) {
+ return Optional.ofNullable(mapper(dbSession).selectMeasure(analysisUuid, componentUuid, metricKey));
}
/**
@@ -47,10 +47,6 @@ public class MeasureDao implements Dao {
* - A list of components in {@link MeasureQuery#componentUuids} with one mandatory project in {@link MeasureQuery#projectUuids}
* - One single component in {@link MeasureQuery#componentUuids}
* <p>
- * In addition, this method returns measures which are not associated to any developer, unless one is specified in
- * {@link MeasureQuery#personId}.
- * </p>
- * <p>
* Returned measure can optionally be filtered metric (either by specifying {@link MeasureQuery#metricIds}
* or {@link MeasureQuery#metricKeys}).
* </p>
@@ -78,13 +74,6 @@ public class MeasureDao implements Dao {
return mapper(dbSession).selectByQueryOnSingleComponent(query);
}
- public void selectTreeByQuery(DbSession dbSession, ComponentDto baseComponent, MeasureTreeQuery query, ResultHandler<MeasureDto> resultHandler) {
- if (query.returnsEmpty()) {
- return;
- }
- mapper(dbSession).selectTreeByQuery(query, baseComponent.uuid(), query.getUuidPath(baseComponent), resultHandler);
- }
-
public List<PastMeasureDto> selectPastMeasures(DbSession dbSession, String componentUuid, String analysisUuid, Collection<Integer> metricIds) {
if (metricIds.isEmpty()) {
return emptyList();
@@ -107,19 +96,6 @@ public class MeasureDao implements Dao {
return mapper(dbSession).selectPastMeasuresOnSeveralAnalyses(query);
}
- /**
- * Used by developer cockpit.
- */
- public List<MeasureDto> selectProjectMeasuresOfDeveloper(DbSession dbSession, long developerId, Collection<Integer> metricIds) {
- return executeLargeInputs(
- metricIds,
- ids -> mapper(dbSession).selectProjectMeasuresOfDeveloper(developerId, metricIds));
- }
-
- public List<MeasureDto> selectByComponentsAndMetrics(DbSession dbSession, Collection<String> componentUuids, Collection<Integer> metricIds) {
- return executeLargeInputs(componentUuids, partitionComponentUuids -> mapper(dbSession).selectByComponentsAndMetrics(partitionComponentUuids, metricIds));
- }
-
public void insert(DbSession session, MeasureDto measureDto) {
mapper(session).insert(measureDto);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDto.java
index fbf5fae3594..d5161b1a117 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDto.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDto.java
@@ -36,7 +36,6 @@ public class MeasureDto {
private String componentUuid;
private String analysisUuid;
private int metricId;
- private Long developerId;
@CheckForNull
public Double getValue() {
@@ -128,16 +127,6 @@ public class MeasureDto {
return this;
}
- @CheckForNull
- public Long getDeveloperId() {
- return developerId;
- }
-
- public MeasureDto setDeveloperId(@Nullable Long developerId) {
- this.developerId = developerId;
- return this;
- }
-
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
@@ -150,7 +139,6 @@ public class MeasureDto {
.add("componentUuid", componentUuid)
.add("analysisUuid", analysisUuid)
.add("metricId", metricId)
- .add("developerId", developerId)
.toString();
}
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureMapper.java
index 4250ac4f067..c059728466e 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureMapper.java
@@ -19,31 +19,35 @@
*/
package org.sonar.db.measure;
-import java.util.Collection;
import java.util.List;
+import javax.annotation.CheckForNull;
import org.apache.ibatis.annotations.Param;
-import org.apache.ibatis.session.ResultHandler;
public interface MeasureMapper {
+ @CheckForNull
+ MeasureDto selectLastMeasure(
+ @Param("componentUuid") String componentUuid,
+ @Param("metricKey") String metricKey
+ );
+
+ @CheckForNull
+ MeasureDto selectMeasure(
+ @Param("analysisUuid") String analysisUuid,
+ @Param("componentUuid") String componentUuid,
+ @Param("metricKey") String metricKey
+ );
+
List<MeasureDto> selectByQueryOnProjects(@Param("query") MeasureQuery query);
List<MeasureDto> selectByQueryOnComponents(@Param("query") MeasureQuery query);
List<MeasureDto> selectByQueryOnSingleComponent(@Param("query") MeasureQuery query);
- void selectTreeByQuery(@Param("query") MeasureTreeQuery measureQuery, @Param("baseUuid") String baseUuid, @Param("baseUuidPath") String baseUuidPath,
- ResultHandler<MeasureDto> resultHandler);
-
-
List<PastMeasureDto> selectPastMeasuresOnSingleAnalysis(@Param("componentUuid") String componentUuid, @Param("analysisUuid") String analysisUuid,
@Param("metricIds") List<Integer> metricIds);
List<MeasureDto> selectPastMeasuresOnSeveralAnalyses(@Param("query") PastMeasureQuery query);
- List<MeasureDto> selectProjectMeasuresOfDeveloper(@Param("developerId") long developerId, @Param("metricIds") Collection<Integer> metricIds);
-
- List<MeasureDto> selectByComponentsAndMetrics(@Param("componentUuids") List<String> componentUuids, @Param("metricIds") Collection<Integer> metricIds);
-
void insert(MeasureDto measureDto);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureQuery.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureQuery.java
index 0b2685ebbe5..5d074d93da7 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureQuery.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureQuery.java
@@ -44,19 +44,15 @@ public class MeasureQuery {
@CheckForNull
private final Collection<String> metricKeys;
- @CheckForNull
- private final Long personId;
-
private MeasureQuery(Builder builder) {
- this(builder.analysisUuid, builder.projectUuids, builder.componentUuids, builder.metricIds, builder.metricKeys, builder.personId);
+ this(builder.analysisUuid, builder.projectUuids, builder.componentUuids, builder.metricIds, builder.metricKeys);
}
private MeasureQuery(@Nullable String analysisUuid,
@Nullable Collection<String> projectUuids,
@Nullable Collection<String> componentUuids,
@Nullable Collection<Integer> metricIds,
- @Nullable Collection<String> metricKeys,
- @Nullable Long personId) {
+ @Nullable Collection<String> metricKeys) {
checkArgument(metricIds == null || metricKeys == null, "Metric IDs and keys must not be set both");
checkArgument(projectUuids != null || componentUuids != null, "At least one filter on component UUID is expected");
checkArgument(componentUuids == null || componentUuids.size() == 1 || (projectUuids != null && projectUuids.size() == 1),
@@ -67,7 +63,6 @@ public class MeasureQuery {
this.componentUuids = componentUuids;
this.metricIds = metricIds;
this.metricKeys = metricKeys;
- this.personId = personId;
}
public String getAnalysisUuid() {
@@ -104,11 +99,6 @@ public class MeasureQuery {
return metricKeys;
}
- @CheckForNull
- public Long getPersonId() {
- return personId;
- }
-
public boolean returnsEmpty() {
return (projectUuids != null && projectUuids.isEmpty())
|| (componentUuids != null && componentUuids.isEmpty())
@@ -141,13 +131,12 @@ public class MeasureQuery {
Objects.equals(projectUuids, that.projectUuids) &&
Objects.equals(componentUuids, that.componentUuids) &&
Objects.equals(metricIds, that.metricIds) &&
- Objects.equals(metricKeys, that.metricKeys) &&
- Objects.equals(personId, that.personId);
+ Objects.equals(metricKeys, that.metricKeys);
}
@Override
public int hashCode() {
- return Objects.hash(analysisUuid, componentUuids, metricIds, metricKeys, personId);
+ return Objects.hash(analysisUuid, componentUuids, metricIds, metricKeys);
}
public static Builder builder() {
@@ -155,11 +144,11 @@ public class MeasureQuery {
}
static MeasureQuery copyWithSubsetOfProjectUuids(MeasureQuery query, Collection<String> projectUuids) {
- return new MeasureQuery(query.analysisUuid, projectUuids, query.componentUuids, query.metricIds, query.metricKeys, query.personId);
+ return new MeasureQuery(query.analysisUuid, projectUuids, query.componentUuids, query.metricIds, query.metricKeys);
}
static MeasureQuery copyWithSubsetOfComponentUuids(MeasureQuery query, Collection<String> componentUuids) {
- return new MeasureQuery(query.analysisUuid, query.projectUuids, componentUuids, query.metricIds, query.metricKeys, query.personId);
+ return new MeasureQuery(query.analysisUuid, query.projectUuids, componentUuids, query.metricIds, query.metricKeys);
}
public static final class Builder {
@@ -168,7 +157,6 @@ public class MeasureQuery {
private Collection<String> componentUuids;
private Collection<Integer> metricIds;
private Collection<String> metricKeys;
- private Long personId;
private Builder() {
// see MeasureQuery#builder()
@@ -230,11 +218,6 @@ public class MeasureQuery {
return this;
}
- public Builder setPersonId(@Nullable Long l) {
- this.personId = l;
- return this;
- }
-
public MeasureQuery build() {
return new MeasureQuery(this);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureTreeQuery.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureTreeQuery.java
index 04df1a38f17..0f368911b78 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureTreeQuery.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureTreeQuery.java
@@ -47,15 +47,11 @@ public class MeasureTreeQuery {
@CheckForNull
private final Collection<Integer> metricIds;
- @CheckForNull
- private final Long personId;
-
private MeasureTreeQuery(Builder builder) {
this.nameOrKeyQuery = builder.nameOrKeyQuery;
this.qualifiers = builder.qualifiers == null ? null : newArrayList(builder.qualifiers);
this.strategy = requireNonNull(builder.strategy);
this.metricIds = builder.metricIds;
- this.personId = builder.personId;
}
@CheckForNull
@@ -85,11 +81,6 @@ public class MeasureTreeQuery {
return metricIds;
}
- @CheckForNull
- public Long getPersonId() {
- return personId;
- }
-
public String getUuidPath(ComponentDto component) {
switch (strategy) {
case CHILDREN:
@@ -120,9 +111,6 @@ public class MeasureTreeQuery {
@CheckForNull
private Collection<Integer> metricIds;
- @CheckForNull
- private Long personId;
-
private Builder() {
}
@@ -149,11 +137,6 @@ public class MeasureTreeQuery {
return this;
}
- public Builder setPersonId(@Nullable Long personId) {
- this.personId = personId;
- return this;
- }
-
public MeasureTreeQuery build() {
return new MeasureTreeQuery(this);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/PastMeasureDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/PastMeasureDto.java
index 0e5ccfb91aa..324c24a29ff 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/PastMeasureDto.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/PastMeasureDto.java
@@ -31,9 +31,6 @@ public class PastMeasureDto {
@CheckForNull
private Double value;
- @CheckForNull
- private Long personId;
-
public double getValue() {
requireNonNull(value);
return value;
@@ -56,15 +53,4 @@ public class PastMeasureDto {
this.metricId = i;
return this;
}
-
- @CheckForNull
- public Long getPersonId() {
- return personId;
- }
-
- PastMeasureDto setPersonId(@Nullable Long l) {
- this.personId = l;
- return this;
- }
-
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java
index d6cd39815a9..b922e5a9ba2 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java
@@ -69,24 +69,23 @@ public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMea
CoreMetrics.NEW_LINES_KEY,
CoreMetrics.NEW_RELIABILITY_RATING_KEY);
- private static final String SQL_PROJECTS = "SELECT p.organization_uuid, p.uuid, p.kee, p.name, s.uuid, s.created_at, p.tags " +
+ private static final String SQL_PROJECTS = "SELECT p.organization_uuid, p.uuid, p.kee, p.name, s.created_at, p.tags " +
"FROM projects p " +
"LEFT OUTER JOIN snapshots s ON s.component_uuid=p.uuid AND s.islast=? " +
"WHERE p.enabled=? AND p.scope=? AND p.qualifier=? and p.main_branch_project_uuid is null ";
private static final String PROJECT_FILTER = " AND p.uuid=?";
- private static final String SQL_MEASURES = "SELECT m.name, pm.value, pm.variation_value_1, pm.text_value FROM project_measures pm " +
+ private static final String SQL_MEASURES = "SELECT m.name, pm.value, pm.variation, pm.text_value FROM live_measures pm " +
"INNER JOIN metrics m ON m.id = pm.metric_id " +
- "WHERE pm.component_uuid = ? AND pm.analysis_uuid = ? " +
+ "WHERE pm.component_uuid = ? " +
"AND m.name IN ({metricNames}) " +
- "AND (pm.value IS NOT NULL OR pm.variation_value_1 IS NOT NULL OR pm.text_value IS NOT NULL) " +
- "AND pm.person_id IS NULL " +
+ "AND (pm.value IS NOT NULL OR pm.variation IS NOT NULL OR pm.text_value IS NOT NULL) " +
"AND m.enabled = ? ";
private static final boolean ENABLED = true;
private static final int FIELD_METRIC_NAME = 1;
private static final int FIELD_MEASURE_VALUE = 2;
- private static final int FIELD_MEASURE_VARIATION_VALUE_1 = 3;
+ private static final int FIELD_MEASURE_VARIATION = 3;
private static final int FIELD_MEASURE_TEXT_VALUE = 4;
private final PreparedStatement measuresStatement;
@@ -116,10 +115,9 @@ public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMea
String uuid = rs.getString(2);
String key = rs.getString(3);
String name = rs.getString(4);
- String analysisUuid = DatabaseUtils.getString(rs, 5);
- Long analysisDate = DatabaseUtils.getLong(rs, 6);
- List<String> tags = readDbTags(DatabaseUtils.getString(rs, 7));
- Project project = new Project(orgUuid, uuid, key, name, tags, analysisUuid, analysisDate);
+ Long analysisDate = DatabaseUtils.getLong(rs, 5);
+ List<String> tags = readDbTags(DatabaseUtils.getString(rs, 6));
+ Project project = new Project(orgUuid, uuid, key, name, tags, analysisDate);
projects.add(project);
}
return projects;
@@ -165,20 +163,16 @@ public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMea
return null;
}
Project project = projects.next();
- Measures measures = selectMeasures(project.getUuid(), project.getAnalysisUuid());
+ Measures measures = selectMeasures(project.getUuid());
return new ProjectMeasures(project, measures);
}
- private Measures selectMeasures(String projectUuid, @Nullable String analysisUuid) {
+ private Measures selectMeasures(String projectUuid) {
Measures measures = new Measures();
- if (analysisUuid == null) {
- return measures;
- }
ResultSet rs = null;
try {
AtomicInteger index = new AtomicInteger(1);
measuresStatement.setString(index.getAndIncrement(), projectUuid);
- measuresStatement.setString(index.getAndIncrement(), analysisUuid);
METRIC_KEYS.forEach(DatabaseUtils.setStrings(measuresStatement, index::getAndIncrement));
measuresStatement.setBoolean(index.getAndIncrement(), ENABLED);
rs = measuresStatement.executeQuery();
@@ -187,7 +181,7 @@ public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMea
}
return measures;
} catch (Exception e) {
- throw new IllegalStateException(String.format("Fail to execute request to select measures of project %s, analysis %s", projectUuid, analysisUuid), e);
+ throw new IllegalStateException(String.format("Fail to execute request to select measures of project %s", projectUuid), e);
} finally {
DatabaseUtils.closeQuietly(rs);
}
@@ -195,7 +189,7 @@ public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMea
private static void readMeasure(ResultSet rs, Measures measures) throws SQLException {
String metricKey = rs.getString(FIELD_METRIC_NAME);
- Optional<Double> value = metricKey.startsWith("new_") ? getDouble(rs, FIELD_MEASURE_VARIATION_VALUE_1) : getDouble(rs, FIELD_MEASURE_VALUE);
+ Optional<Double> value = metricKey.startsWith("new_") ? getDouble(rs, FIELD_MEASURE_VARIATION) : getDouble(rs, FIELD_MEASURE_VALUE);
if (value.isPresent()) {
measures.addNumericMeasure(metricKey, value.get());
return;
@@ -239,17 +233,15 @@ public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMea
private final String uuid;
private final String key;
private final String name;
- private final String analysisUuid;
private final Long analysisDate;
private final List<String> tags;
- public Project(String organizationUuid, String uuid, String key, String name, List<String> tags, @Nullable String analysisUuid, @Nullable Long analysisDate) {
+ public Project(String organizationUuid, String uuid, String key, String name, List<String> tags, @Nullable Long analysisDate) {
this.organizationUuid = organizationUuid;
this.uuid = uuid;
this.key = key;
this.name = name;
this.tags = tags;
- this.analysisUuid = analysisUuid;
this.analysisDate = analysisDate;
}
@@ -274,11 +266,6 @@ public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMea
}
@CheckForNull
- public String getAnalysisUuid() {
- return analysisUuid;
- }
-
- @CheckForNull
public Long getAnalysisDate() {
return analysisDate;
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java
index 9d65a9834c8..4ea14787571 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java
@@ -21,13 +21,11 @@ package org.sonar.db.purge;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
+import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.sonar.db.DbSession;
-import static com.google.common.collect.FluentIterable.from;
-import static java.util.Arrays.asList;
-
class PurgeCommands {
private static final int MAX_SNAPSHOTS_PER_QUERY = 1000;
@@ -56,14 +54,14 @@ class PurgeCommands {
return purgeMapper.selectAnalysisIdsAndUuids(query);
}
- void deleteAnalyses(String rootUuid) {
+ void deleteAnalyses(String rootComponentUuid) {
profiler.start("deleteAnalyses (events)");
- purgeMapper.deleteEventsByComponentUuid(rootUuid);
+ purgeMapper.deleteEventsByComponentUuid(rootComponentUuid);
session.commit();
profiler.stop();
- List<List<String>> analysisUuidsPartitions = Lists.partition(IdUuidPairs.uuids(purgeMapper.selectAnalysisIdsAndUuids(new PurgeSnapshotQuery().setComponentUuid(rootUuid))),
- MAX_SNAPSHOTS_PER_QUERY);
+ List<List<String>> analysisUuidsPartitions = Lists.partition(IdUuidPairs.uuids(
+ purgeMapper.selectAnalysisIdsAndUuids(new PurgeSnapshotQuery().setComponentUuid(rootComponentUuid))), MAX_SNAPSHOTS_PER_QUERY);
deleteAnalysisDuplications(analysisUuidsPartitions);
@@ -84,9 +82,10 @@ class PurgeCommands {
}
void deleteAnalyses(PurgeSnapshotQuery... queries) {
- List<IdUuidPair> snapshotIds = from(asList(queries))
- .transformAndConcat(purgeMapper::selectAnalysisIdsAndUuids)
- .toList();
+ List<IdUuidPair> snapshotIds = Arrays.stream(queries)
+ .flatMap(q -> purgeMapper.selectAnalysisIdsAndUuids(q).stream())
+ .collect(Collectors.toList());
+
deleteAnalyses(snapshotIds);
}
@@ -124,9 +123,11 @@ class PurgeCommands {
profiler.start("deleteSnapshotWastedMeasures (project_measures)");
List<Long> metricIdsWithoutHistoricalData = purgeMapper.selectMetricIdsWithoutHistoricalData();
- analysisUuidsPartitions
- .forEach(analysisUuidsPartition -> purgeMapper.deleteAnalysisWastedMeasures(analysisUuidsPartition, metricIdsWithoutHistoricalData));
- session.commit();
+ if (!metricIdsWithoutHistoricalData.isEmpty()) {
+ analysisUuidsPartitions
+ .forEach(analysisUuidsPartition -> purgeMapper.deleteAnalysisWastedMeasures(analysisUuidsPartition, metricIdsWithoutHistoricalData));
+ session.commit();
+ }
profiler.stop();
profiler.start("updatePurgeStatusToOne (snapshots)");
@@ -272,4 +273,11 @@ class PurgeCommands {
session.commit();
profiler.stop();
}
+
+ void deleteLiveMeasures(String rootUuid) {
+ profiler.start("deleteLiveMeasures (live_measures)");
+ purgeMapper.deleteLiveMeasuresByProjectUuid(rootUuid);
+ session.commit();
+ profiler.stop();
+ }
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeConfiguration.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeConfiguration.java
index c9d903f883f..245c23c7c6a 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeConfiguration.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeConfiguration.java
@@ -49,12 +49,12 @@ public class PurgeConfiguration {
this.maxAgeInDaysOfInactiveShortLivingBranches = maxAgeInDaysOfInactiveShortLivingBranches;
}
- public static PurgeConfiguration newDefaultPurgeConfiguration(Configuration config, IdUuidPair idUuidPair, Collection<String> disabledComponentUuids) {
+ public static PurgeConfiguration newDefaultPurgeConfiguration(Configuration config, IdUuidPair rootId, Collection<String> disabledComponentUuids) {
String[] scopes = new String[] {Scopes.FILE};
if (config.getBoolean(PurgeConstants.PROPERTY_CLEAN_DIRECTORY).orElse(false)) {
scopes = new String[] {Scopes.DIRECTORY, Scopes.FILE};
}
- return new PurgeConfiguration(idUuidPair, scopes, config.getInt(PurgeConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES).get(),
+ return new PurgeConfiguration(rootId, scopes, config.getInt(PurgeConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES).get(),
config.getInt(PurgeConstants.DAYS_BEFORE_DELETING_INACTIVE_SHORT_LIVING_BRANCHES), System2.INSTANCE, disabledComponentUuids);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java
index de29166e268..cad8376dc39 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java
@@ -204,6 +204,7 @@ public class PurgeDao implements Dao {
commands.deleteCeQueue(rootUuid);
commands.deleteWebhookDeliveries(rootUuid);
commands.deleteBranch(rootUuid);
+ commands.deleteLiveMeasures(rootUuid);
}
/**
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java
index 3961aa6a335..c6393dc4e86 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java
@@ -97,4 +97,6 @@ public interface PurgeMapper {
void deleteWebhookDeliveriesByProjectUuid(@Param("projectUuid") String projectUuid);
void deleteBranchByUuid(@Param("uuid") String uuid);
+
+ void deleteLiveMeasuresByProjectUuid(@Param("projectUuid") String projectUuid);
}
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml
index 5d7e051032f..22991a65e29 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml
@@ -24,7 +24,6 @@
p.path as path,
p.enabled as enabled,
p.copy_component_uuid as copyComponentUuid,
- p.developer_uuid as developerUuid,
p.private as isPrivate,
p.created_at as createdAt
</sql>
@@ -512,7 +511,6 @@
root_uuid,
path,
copy_component_uuid,
- developer_uuid,
enabled,
created_at,
b_changed,
@@ -548,7 +546,6 @@
#{rootUuid,jdbcType=VARCHAR},
#{path,jdbcType=VARCHAR},
#{copyComponentUuid,jdbcType=VARCHAR},
- #{developerUuid,jdbcType=VARCHAR},
#{enabled,jdbcType=BOOLEAN},
#{createdAt,jdbcType=TIMESTAMP},
${_false},
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml
new file mode 100644
index 00000000000..57eb8f87008
--- /dev/null
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.db.measure.LiveMeasureMapper">
+
+ <sql id="columns">
+ lm.component_uuid as componentUuid,
+ lm.project_uuid as projectUuid,
+ lm.metric_id as metricId,
+ lm.value as value,
+ lm.text_value as textValue,
+ lm.measure_data as data,
+ lm.variation as variation
+ </sql>
+
+ <select id="selectByComponentUuidsAndMetricIds" parameterType="map" resultType="org.sonar.db.measure.LiveMeasureDto">
+ select <include refid="columns"/> from live_measures lm
+ where
+ lm.metric_id in <foreach item="metricId" collection="metricIds" open="(" separator="," close=")">#{metricId, jdbcType=INTEGER}</foreach>
+ and lm.component_uuid in
+ <foreach item="componentUuid" collection="componentUuids" open="(" separator="," close=")">
+ #{componentUuid, jdbcType=VARCHAR}
+ </foreach>
+ </select>
+
+ <select id="selectByComponentUuidsAndMetricKeys" parameterType="map" resultType="org.sonar.db.measure.LiveMeasureDto">
+ select <include refid="columns"/> from live_measures lm
+ inner join metrics m on m.id = lm.metric_id
+ where
+ m.name in <foreach item="metricKey" collection="metricKeys" open="(" separator="," close=")">#{metricKey, jdbcType=VARCHAR}</foreach>
+ and lm.component_uuid in
+ <foreach item="componentUuid" collection="componentUuids" open="(" separator="," close=")">
+ #{componentUuid, jdbcType=VARCHAR}
+ </foreach>
+ </select>
+
+ <insert id="insert" parameterType="map" useGeneratedKeys="false">
+ insert into live_measures (
+ uuid,
+ component_uuid,
+ project_uuid,
+ metric_id,
+ value,
+ text_value,
+ variation,
+ measure_data,
+ update_marker,
+ created_at,
+ updated_at
+ ) values (
+ #{uuid, jdbcType=VARCHAR},
+ #{dto.componentUuid, jdbcType=VARCHAR},
+ #{dto.projectUuid, jdbcType=VARCHAR},
+ #{dto.metricId, jdbcType=INTEGER},
+ #{dto.value, jdbcType=DOUBLE},
+ #{dto.textValue, jdbcType=VARCHAR},
+ #{dto.variation, jdbcType=DOUBLE},
+ #{dto.data, jdbcType=BINARY},
+ #{marker, jdbcType=VARCHAR},
+ #{now, jdbcType=BIGINT},
+ #{now, jdbcType=BIGINT}
+ )
+ </insert>
+
+ <update id="update" parameterType="map">
+ update live_measures set
+ value = #{dto.value, jdbcType=DOUBLE},
+ variation = #{dto.variation, jdbcType=DOUBLE},
+ text_value = #{dto.textValue, jdbcType=VARCHAR},
+ measure_data = #{dto.data, jdbcType=BINARY},
+ update_marker = #{marker, jdbcType=VARCHAR},
+ updated_at = #{now, jdbcType=BIGINT}
+ where
+ component_uuid = #{dto.componentUuid, jdbcType=VARCHAR}
+ and metric_id = #{dto.metricId, jdbcType=INTEGER}
+ </update>
+
+ <delete id="deleteByProjectUuidExcludingMarker" parameterType="map">
+ delete from live_measures
+ where
+ project_uuid = #{projectUuid, jdbcType=VARCHAR} and
+ (update_marker != #{marker, jdbcType=VARCHAR} or update_marker is null)
+ </delete>
+
+ <select id="selectTreeByQuery" parameterType="map" resultType="org.sonar.db.measure.LiveMeasureDto" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
+ select <include refid="columns"/> from live_measures lm
+ inner join projects p on p.uuid = lm.component_uuid
+ <!-- TODO do we really need another join on projects ? Using lm.project_uuid should be enough -->
+ <include refid="org.sonar.db.component.ComponentMapper.selectDescendantsJoins"/>
+ <where>
+ <if test="query.getMetricIds() != null">
+ lm.metric_id in
+ <foreach item="metricId" collection="query.getMetricIds()" open="(" separator="," close=")">#{metricId,jdbcType=INTEGER}</foreach>
+ </if>
+ <include refid="org.sonar.db.component.ComponentMapper.selectDescendantsFilters"/>
+ </where>
+
+ -- Add measures of base component
+ union all
+ select <include refid="columns"/> from live_measures lm
+ inner join projects p on p.uuid = lm.component_uuid and lm.component_uuid = #{baseUuid, jdbcType=VARCHAR}
+ <where>
+ <if test="query.getMetricIds() != null">
+ lm.metric_id in
+ <foreach item="metricId" collection="query.getMetricIds()" open="(" separator="," close=")">#{metricId,jdbcType=INTEGER}</foreach>
+ </if>
+ <include refid="org.sonar.db.component.ComponentMapper.selectDescendantsFilters"/>
+ </where>
+ </select>
+</mapper>
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml
index 860b4e73f47..4dd4ecd7504 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml
@@ -5,7 +5,6 @@
<sql id="measureColumns">
pm.metric_id as metricId,
- pm.person_id as developerId,
pm.component_uuid as componentUuid,
pm.analysis_uuid as analysisUuid,
pm.value as value,
@@ -16,10 +15,27 @@
pm.variation_value_1 as variation
</sql>
- <sql id="extendedMeasureColumns">
- <include refid="measureColumns"/>,
- metric.name as metricKey
- </sql>
+ <select id="selectLastMeasure" parameterType="map" resultType="Measure">
+ select <include refid="measureColumns"/>
+ from project_measures pm
+ inner join metrics m on m.id = pm.metric_id
+ inner join snapshots s on s.uuid = pm.analysis_uuid
+ where
+ pm.component_uuid = #{componentUuid,jdbcType=VARCHAR} and
+ m.name = #{metricKey,jdbcType=VARCHAR} and
+ s.islast= ${_true}
+ </select>
+
+ <select id="selectMeasure" parameterType="map" resultType="Measure">
+ select <include refid="measureColumns"/>
+ from project_measures pm
+ inner join metrics m on m.id = pm.metric_id
+ inner join snapshots s on s.uuid = pm.analysis_uuid
+ where
+ pm.component_uuid = #{componentUuid,jdbcType=VARCHAR} and
+ m.name = #{metricKey,jdbcType=VARCHAR} and
+ s.uuid = #{analysisUuid,jdbcType=VARCHAR}
+ </select>
<select id="selectByQueryOnProjects" parameterType="map" resultType="Measure">
select <include refid="measureColumns"/> from project_measures pm
@@ -79,60 +95,16 @@
#{metricKey,jdbcType=VARCHAR}
</foreach>
</if>
- <choose>
- <when test="query.getPersonId() != null">
- and pm.person_id = #{query.personId,jdbcType=BIGINT}
- </when>
- <otherwise>
- and pm.person_id is null
- </otherwise>
- </choose>
- </sql>
-
- <select id="selectTreeByQuery" parameterType="map" resultType="Measure" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
- select <include refid="measureColumns"/> from project_measures pm
- inner join snapshots analysis on analysis.uuid = pm.analysis_uuid
- inner join projects p on p.project_uuid=analysis.component_uuid and p.uuid=pm.component_uuid
- <include refid="org.sonar.db.component.ComponentMapper.selectDescendantsJoins"/>
- <where>
- <include refid="selectTreeByQueryFilters"/>
- </where>
- -- Add measures of base component
- union all
- select <include refid="measureColumns"/> from project_measures pm
- inner join snapshots analysis on analysis.uuid = pm.analysis_uuid
- inner join projects p on p.project_uuid=analysis.component_uuid and p.uuid=pm.component_uuid and pm.component_uuid=#{baseUuid}
- <where>
- <include refid="selectTreeByQueryFilters"/>
- </where>
- </select>
-
- <sql id="selectTreeByQueryFilters">
- and analysis.islast=${_true}
- <if test="query.getMetricIds() != null">
- and pm.metric_id in
- <foreach item="metricId" collection="query.getMetricIds()" open="(" separator="," close=")">#{metricId}</foreach>
- </if>
- <choose>
- <when test="query.getPersonId() != null">
- and pm.person_id = #{query.personId,jdbcType=BIGINT}
- </when>
- <otherwise>
- and pm.person_id is null
- </otherwise>
- </choose>
- <include refid="org.sonar.db.component.ComponentMapper.selectDescendantsFilters"/>
</sql>
<select id="selectPastMeasuresOnSingleAnalysis" parameterType="map" resultType="org.sonar.db.measure.PastMeasureDto">
- select pm.id as id, pm.metric_id as metricId, pm.person_id as personId, pm.value as value
+ select pm.id as id, pm.metric_id as metricId, pm.value as value
from project_measures pm
inner join snapshots analysis on analysis.uuid = pm.analysis_uuid
where
pm.component_uuid = #{componentUuid,jdbcType=VARCHAR}
and analysis.uuid = #{analysisUuid,jdbcType=VARCHAR}
and pm.metric_id in <foreach item="metricId" collection="metricIds" open="(" separator="," close=")">#{metricId}</foreach>
- and pm.person_id is null
</select>
<select id="selectPastMeasuresOnSeveralAnalyses" parameterType="map" resultType="Measure">
@@ -148,40 +120,9 @@
and analysis.created_at&lt;#{query.to, jdbcType=BIGINT}
</if>
and pm.metric_id in <foreach item="metricId" collection="query.metricIds" open="(" separator="," close=")">#{metricId, jdbcType=VARCHAR}</foreach>
- and pm.person_id is null
and analysis.status=#{query.status, jdbcType=VARCHAR}
</select>
- <select id="selectProjectMeasuresOfDeveloper" parameterType="map" resultType="Measure">
- SELECT
- <include refid="measureColumns"/>
- from
- project_measures pm, snapshots s, projects p
- where
- pm.person_id=#{developerId,jdbcType=BIGINT}
- and pm.metric_id in
- <foreach item="metricId" collection="metricIds" open="(" separator="," close=")">
- #{metricId}
- </foreach>
- and s.uuid=pm.analysis_uuid
- and s.islast=${_true}
- and p.uuid=pm.component_uuid
- and p.scope='PRJ'
- and p.qualifier='TRK'
- </select>
-
- <select id="selectByComponentsAndMetrics" parameterType="map" resultType="Measure">
- select <include refid="measureColumns"/>
- from project_measures pm
- inner join snapshots analysis on analysis.uuid = pm.analysis_uuid and analysis.islast=${_true}
- inner join projects p on p.project_uuid=analysis.component_uuid and p.uuid=pm.component_uuid
- <where>
- and p.uuid in <foreach item="componentUuid" collection="componentUuids" open="(" separator="," close=")">#{componentUuid,jdbcType=VARCHAR}</foreach>
- and pm.metric_id in <foreach item="metricId" collection="metricIds" open="(" separator="," close=")">#{metricId,jdbcType=INTEGER}</foreach>
- and pm.person_id is null
- </where>
- </select>
-
<insert id="insert" parameterType="Measure" useGeneratedKeys="false">
insert into project_measures (
value,
@@ -191,7 +132,6 @@
text_value,
alert_status,
alert_text,
- person_id,
variation_value_1,
measure_data)
VALUES (
@@ -202,7 +142,6 @@
#{textValue, jdbcType=VARCHAR},
#{alertStatus, jdbcType=VARCHAR},
#{alertText, jdbcType=VARCHAR},
- #{developerId, jdbcType=INTEGER},
#{variation, jdbcType=DOUBLE},
#{dataValue, jdbcType=BINARY}
)
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml
index 36f668e5626..471bd59dbb1 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml
@@ -151,14 +151,10 @@
<foreach collection="analysisUuids" open="(" close=")" item="analysisUuid" separator=",">
#{analysisUuid}
</foreach>
- and (person_id is not null
- <if test="metricIds.size()>0">
- or metric_id in
- <foreach collection="metricIds" open="(" item="metricId" separator="," close=")">
- #{metricId}
- </foreach>
- </if>
- )
+ and metric_id in
+ <foreach collection="metricIds" open="(" item="metricId" separator="," close=")">
+ #{metricId,jdbcType=INTEGER}
+ </foreach>
</where>
</delete>
@@ -332,5 +328,8 @@
delete from project_branches where uuid=#{uuid,jdbcType=VARCHAR}
</delete>
+ <delete id="deleteLiveMeasuresByProjectUuid">
+ delete from live_measures where project_uuid = #{projectUuid,jdbcType=VARCHAR}
+ </delete>
</mapper>
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java
index d79b8f289e8..5ff22c1e2fd 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java
@@ -30,6 +30,6 @@ public class DaoModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new DaoModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 51);
+ assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 52);
}
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java
index 140a3a0bfd3..7ffbbb8371e 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java
@@ -111,7 +111,6 @@ public class ComponentDaoTest {
assertThat(result.scope()).isEqualTo("PRJ");
assertThat(result.language()).isNull();
assertThat(result.getCopyResourceUuid()).isNull();
- assertThat(result.getDeveloperUuid()).isNull();
assertThat(result.isPrivate()).isTrue();
assertThat(underTest.selectByUuid(dbSession, "UNKNOWN")).isAbsent();
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDtoTest.java
index 143f2abdf43..f79ea9c4e70 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDtoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDtoTest.java
@@ -42,8 +42,7 @@ public class ComponentDtoTest {
.setDescription("desc")
.setPath("src/org/struts/RequestContext.java")
.setCopyComponentUuid("uuid_5")
- .setRootUuid("uuid_3")
- .setDeveloperUuid("uuid_6");
+ .setRootUuid("uuid_3");
assertThat(componentDto.getId()).isEqualTo(1L);
assertThat(componentDto.getDbKey()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java");
@@ -58,7 +57,6 @@ public class ComponentDtoTest {
assertThat(componentDto.description()).isEqualTo("desc");
assertThat(componentDto.getRootUuid()).isEqualTo("uuid_3");
assertThat(componentDto.getCopyResourceUuid()).isEqualTo("uuid_5");
- assertThat(componentDto.getDeveloperUuid()).isEqualTo("uuid_6");
assertThat(componentDto.isPrivate()).isFalse();
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/LiveMeasureDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/LiveMeasureDaoTest.java
new file mode 100644
index 00000000000..c4ab865c43f
--- /dev/null
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/LiveMeasureDaoTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.measure;
+
+import java.util.List;
+import org.assertj.core.groups.Tuple;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.db.metric.MetricDto;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.measure.MeasureTesting.newLiveMeasure;
+
+public class LiveMeasureDaoTest {
+
+ private static final int A_METRIC_ID = 42;
+
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+
+ private LiveMeasureDao underTest = db.getDbClient().liveMeasureDao();
+
+ @Test
+ public void test_selectByComponentUuids() {
+ LiveMeasureDto measure1 = newLiveMeasure().setMetricId(A_METRIC_ID);
+ LiveMeasureDto measure2 = newLiveMeasure().setMetricId(A_METRIC_ID);
+ underTest.insert(db.getSession(), measure1);
+ underTest.insert(db.getSession(), measure2);
+
+ List<LiveMeasureDto> selected = underTest.selectByComponentUuids(db.getSession(), asList(measure1.getComponentUuid(), measure2.getComponentUuid()), singletonList(A_METRIC_ID));
+ assertThat(selected)
+ .extracting(LiveMeasureDto::getComponentUuid, LiveMeasureDto::getProjectUuid, LiveMeasureDto::getMetricId, LiveMeasureDto::getValue, LiveMeasureDto::getDataAsString)
+ .containsExactlyInAnyOrder(
+ Tuple.tuple(measure1.getComponentUuid(), measure1.getProjectUuid(), measure1.getMetricId(), measure1.getValue(), measure1.getDataAsString()),
+ Tuple.tuple(measure2.getComponentUuid(), measure2.getProjectUuid(), measure2.getMetricId(), measure2.getValue(), measure2.getDataAsString()));
+ }
+
+ @Test
+ public void selectByComponentUuids_returns_empty_list_if_metric_does_not_match() {
+ LiveMeasureDto measure = newLiveMeasure().setMetricId(10);
+ underTest.insert(db.getSession(), measure);
+
+ List<LiveMeasureDto> selected = underTest.selectByComponentUuids(db.getSession(), singletonList(measure.getComponentUuid()), singletonList(222));
+
+ assertThat(selected).isEmpty();
+ }
+
+ @Test
+ public void selectByComponentUuids_returns_empty_list_if_component_does_not_match() {
+ LiveMeasureDto measure = newLiveMeasure();
+ underTest.insert(db.getSession(), measure);
+
+ List<LiveMeasureDto> selected = underTest.selectByComponentUuids(db.getSession(), singletonList("_missing_"), singletonList(measure.getMetricId()));
+
+ assertThat(selected).isEmpty();
+ }
+
+ @Test
+ public void test_selectMeasure() {
+ MetricDto metric = db.measures().insertMetric();
+ LiveMeasureDto stored = newLiveMeasure().setMetricId(metric.getId());
+ underTest.insert(db.getSession(), stored);
+
+ // metric exists but not component
+ assertThat(underTest.selectMeasure(db.getSession(), "_missing_", metric.getKey())).isEmpty();
+
+ // component exists but not metric
+ assertThat(underTest.selectMeasure(db.getSession(), stored.getComponentUuid(), "_missing_")).isEmpty();
+
+ // component and metric don't match
+ assertThat(underTest.selectMeasure(db.getSession(), "_missing_", "_missing_")).isEmpty();
+
+ // matches
+ assertThat(underTest.selectMeasure(db.getSession(), stored.getComponentUuid(), metric.getKey()).get())
+ .isEqualToComparingFieldByField(stored);
+ }
+
+ @Test
+ public void test_insertOrUpdate() {
+ // insert
+ LiveMeasureDto dto = newLiveMeasure();
+ underTest.insertOrUpdate(db.getSession(), dto, "foo");
+ verifyPersisted(dto);
+ verifyTableSize(1);
+
+ // update
+ dto.setValue(dto.getValue() + 1);
+ dto.setVariation(dto.getVariation() + 10);
+ dto.setData(dto.getDataAsString() + "_new");
+ underTest.insertOrUpdate(db.getSession(), dto, "foo");
+ verifyPersisted(dto);
+ verifyTableSize(1);
+ }
+
+ @Test
+ public void deleteByProjectUuidExcludingMarker() {
+ LiveMeasureDto measure1 = newLiveMeasure().setProjectUuid("P1");
+ LiveMeasureDto measure2 = newLiveMeasure().setProjectUuid("P1");
+ LiveMeasureDto measure3DifferentMarker = newLiveMeasure().setProjectUuid("P1");
+ LiveMeasureDto measure4NoMarker = newLiveMeasure().setProjectUuid("P1");
+ LiveMeasureDto measure5OtherProject = newLiveMeasure().setProjectUuid("P2");
+ underTest.insertOrUpdate(db.getSession(), measure1, "foo");
+ underTest.insertOrUpdate(db.getSession(), measure2, "foo");
+ underTest.insertOrUpdate(db.getSession(), measure3DifferentMarker, "bar");
+ underTest.insertOrUpdate(db.getSession(), measure4NoMarker, null);
+ underTest.insertOrUpdate(db.getSession(), measure5OtherProject, "foo");
+
+ underTest.deleteByProjectUuidExcludingMarker(db.getSession(), "P1", "foo");
+
+ verifyTableSize(3);
+ verifyPersisted(measure1);
+ verifyPersisted(measure2);
+ verifyPersisted(measure5OtherProject);
+ }
+
+ private void verifyTableSize(int expectedSize) {
+ assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isEqualTo(expectedSize);
+ }
+
+ private void verifyPersisted(LiveMeasureDto dto) {
+ List<LiveMeasureDto> selected = underTest.selectByComponentUuids(db.getSession(), singletonList(dto.getComponentUuid()), singletonList(dto.getMetricId()));
+ assertThat(selected).hasSize(1);
+ assertThat(selected.get(0)).isEqualToComparingFieldByField(dto);
+ }
+}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDaoTest.java
index 40067b96321..05d9444c1af 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDaoTest.java
@@ -19,45 +19,34 @@
*/
package org.sonar.db.measure;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
-import java.util.Optional;
-import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
-import org.sonar.core.util.UuidFactoryImpl;
+import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.component.SnapshotTesting;
+import org.sonar.db.metric.MetricDto;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.resources.Qualifiers.FILE;
-import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE;
import static org.sonar.api.utils.DateUtils.parseDate;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newModuleDto;
import static org.sonar.db.component.SnapshotTesting.newAnalysis;
-import static org.sonar.db.measure.MeasureTreeQuery.Strategy.CHILDREN;
-import static org.sonar.db.measure.MeasureTreeQuery.Strategy.LEAVES;
public class MeasureDaoTest {
private static final int COVERAGE_METRIC_ID = 10;
private static final int COMPLEXITY_METRIC_ID = 11;
private static final int NCLOC_METRIC_ID = 12;
- private static final long A_PERSON_ID = 444L;
- private static final String LAST_ANALYSIS_UUID = "A1";
- private static final String OTHER_ANALYSIS_UUID = "A2";
- private static final String PREVIOUS_ANALYSIS_UUID = "previous analysis UUID";
@Rule
public ExpectedException expectedException = ExpectedException.none();
@@ -70,37 +59,48 @@ public class MeasureDaoTest {
private MeasureDao underTest = db.getDbClient().measureDao();
@Test
- public void test_inserted_and_selected_columns() {
+ public void test_selectLastMeasure() {
+ MetricDto metric = db.measures().insertMetric();
ComponentDto project = db.components().insertPrivateProject();
- insertAnalysis(LAST_ANALYSIS_UUID, project.uuid(), true);
- db.components().insertComponent(newFileDto(project).setUuid("C4"));
-
- MeasureDto inserted = new MeasureDto()
- .setAnalysisUuid(LAST_ANALYSIS_UUID)
- .setMetricId(2)
- .setDeveloperId(3L)
- .setComponentUuid("C4")
- .setValue(5.0d)
- .setData("data")
- .setVariation(1d)
- .setAlertStatus("alert")
- .setAlertText("alert-text");
- underTest.insert(db.getSession(), inserted);
- db.commit();
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
+ SnapshotDto lastAnalysis = insertAnalysis(project.uuid(), true);
+ SnapshotDto pastAnalysis = insertAnalysis(project.uuid(), false);
+
+ MeasureDto pastMeasure = MeasureTesting.newMeasureDto(metric, file, pastAnalysis);
+ MeasureDto lastMeasure = MeasureTesting.newMeasureDto(metric, file, lastAnalysis);
+ underTest.insert(db.getSession(), pastMeasure);
+ underTest.insert(db.getSession(), lastMeasure);
+
+ MeasureDto selected = underTest.selectLastMeasure(db.getSession(), file.uuid(), metric.getKey()).get();
+ assertThat(selected).isEqualToComparingFieldByField(lastMeasure);
+
+ assertThat(underTest.selectLastMeasure(dbSession, "_missing_", metric.getKey())).isEmpty();
+ assertThat(underTest.selectLastMeasure(dbSession, file.uuid(), "_missing_")).isEmpty();
+ assertThat(underTest.selectLastMeasure(dbSession, "_missing_", "_missing_")).isEmpty();
+ }
+
+ @Test
+ public void test_selectMeasure() {
+ MetricDto metric = db.measures().insertMetric();
+ ComponentDto project = db.components().insertPrivateProject();
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
+ SnapshotDto lastAnalysis = insertAnalysis(project.uuid(), true);
+ SnapshotDto pastAnalysis = insertAnalysis(project.uuid(), false);
+
+ MeasureDto pastMeasure = MeasureTesting.newMeasureDto(metric, file, pastAnalysis);
+ MeasureDto lastMeasure = MeasureTesting.newMeasureDto(metric, file, lastAnalysis);
+ underTest.insert(db.getSession(), pastMeasure);
+ underTest.insert(db.getSession(), lastMeasure);
+
+ assertThat(underTest.selectMeasure(db.getSession(), lastAnalysis.getUuid(), file.uuid(), metric.getKey()).get())
+ .isEqualToComparingFieldByField(lastMeasure);
+
+ assertThat(underTest.selectMeasure(db.getSession(), pastAnalysis.getUuid(), file.uuid(), metric.getKey()).get())
+ .isEqualToComparingFieldByField(pastMeasure);
- MeasureDto selected = underTest.selectSingle(db.getSession(), MeasureQuery.builder()
- .setComponentUuid(inserted.getComponentUuid())
- .setPersonId(inserted.getDeveloperId())
- .build()).get();
- assertThat(selected.getAnalysisUuid()).isEqualTo(inserted.getAnalysisUuid());
- assertThat(selected.getMetricId()).isEqualTo(inserted.getMetricId());
- assertThat(selected.getDeveloperId()).isEqualTo(inserted.getDeveloperId());
- assertThat(selected.getComponentUuid()).isEqualTo(inserted.getComponentUuid());
- assertThat(selected.getValue()).isEqualTo(inserted.getValue());
- assertThat(selected.getData()).isEqualTo(inserted.getData());
- assertThat(selected.getVariation()).isEqualTo(inserted.getVariation());
- assertThat(selected.getAlertStatus()).isEqualTo(inserted.getAlertStatus());
- assertThat(selected.getAlertText()).isEqualTo(inserted.getAlertText());
+ assertThat(underTest.selectMeasure(db.getSession(), "_missing_", file.uuid(), metric.getKey())).isEmpty();
+ assertThat(underTest.selectMeasure(db.getSession(), pastAnalysis.getUuid(), "_missing_", metric.getKey())).isEmpty();
+ assertThat(underTest.selectMeasure(db.getSession(), pastAnalysis.getUuid(), file.uuid(), "_missing_")).isEmpty();
}
@Test
@@ -109,28 +109,25 @@ public class MeasureDaoTest {
ComponentDto module = db.components().insertComponent(newModuleDto(project1));
db.components().insertComponent(newFileDto(module).setUuid("C1"));
db.components().insertComponent(newFileDto(module).setUuid("C2"));
- insertAnalysis(LAST_ANALYSIS_UUID, project1.uuid(), true);
- insertAnalysis(OTHER_ANALYSIS_UUID, project1.uuid(), false);
+ SnapshotDto lastAnalysis = insertAnalysis(project1.uuid(), true);
+ SnapshotDto pastAnalysis = insertAnalysis(project1.uuid(), false);
- String project2LastAnalysisUuid = "P2_LAST_ANALYSIS";
ComponentDto project2 = db.components().insertPrivateProject();
- insertAnalysis(project2LastAnalysisUuid, project2.uuid(), true);
+ SnapshotDto project2LastAnalysis = insertAnalysis(project2.uuid(), true);
// project 1
- insertMeasure("P1_M1", LAST_ANALYSIS_UUID, project1.uuid(), NCLOC_METRIC_ID);
- insertMeasure("P1_M2", LAST_ANALYSIS_UUID, project1.uuid(), COVERAGE_METRIC_ID);
- insertMeasure("P1_M3", OTHER_ANALYSIS_UUID, project1.uuid(), NCLOC_METRIC_ID);
+ insertMeasure("P1_M1", lastAnalysis.getUuid(), project1.uuid(), NCLOC_METRIC_ID);
+ insertMeasure("P1_M2", lastAnalysis.getUuid(), project1.uuid(), COVERAGE_METRIC_ID);
+ insertMeasure("P1_M3", pastAnalysis.getUuid(), project1.uuid(), NCLOC_METRIC_ID);
// project 2
- insertMeasure("P2_M1", project2LastAnalysisUuid, project2.uuid(), NCLOC_METRIC_ID);
- insertMeasure("P2_M2", project2LastAnalysisUuid, project2.uuid(), COVERAGE_METRIC_ID);
+ insertMeasure("P2_M1", project2LastAnalysis.getUuid(), project2.uuid(), NCLOC_METRIC_ID);
+ insertMeasure("P2_M2", project2LastAnalysis.getUuid(), project2.uuid(), COVERAGE_METRIC_ID);
// component C1
- insertMeasure("M1", OTHER_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID);
- insertMeasure("M2", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID);
- insertMeasure("M3", LAST_ANALYSIS_UUID, "C1", COVERAGE_METRIC_ID);
- insertMeasureOnPerson("M4", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID, A_PERSON_ID);
- insertMeasureOnPerson("M5", OTHER_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID, 123L);
+ insertMeasure("M1", pastAnalysis.getUuid(), "C1", NCLOC_METRIC_ID);
+ insertMeasure("M2", lastAnalysis.getUuid(), "C1", NCLOC_METRIC_ID);
+ insertMeasure("M3", lastAnalysis.getUuid(), "C1", COVERAGE_METRIC_ID);
// component C2
- insertMeasure("M6", LAST_ANALYSIS_UUID, "C2", NCLOC_METRIC_ID);
+ insertMeasure("M6", lastAnalysis.getUuid(), "C2", NCLOC_METRIC_ID);
db.commit();
verifyZeroMeasures(MeasureQuery.builder().setComponentUuids(project1.uuid(), emptyList()));
@@ -141,51 +138,37 @@ public class MeasureDaoTest {
// all measures of component C1 of last analysis
verifyMeasures(MeasureQuery.builder().setComponentUuid("C1"), "M2", "M3");
// all measures of component C1 of non last analysis
- verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID), "M1");
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(pastAnalysis.getUuid()), "M1");
// all measures of component C1 of last analysis by UUID
- verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID), "M2", "M3");
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(lastAnalysis.getUuid()), "M2", "M3");
// ncloc measure of component C1 of last analysis
verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setMetricId(NCLOC_METRIC_ID), "M2");
// ncloc measure of component C1 of non last analysis
- verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID).setMetricId(NCLOC_METRIC_ID), "M1");
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(pastAnalysis.getUuid()).setMetricId(NCLOC_METRIC_ID), "M1");
// ncloc measure of component C1 of last analysis by UUID
- verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setMetricId(NCLOC_METRIC_ID), "M2");
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(lastAnalysis.getUuid()).setMetricId(NCLOC_METRIC_ID), "M2");
// multiple measures of component C1 of last analysis
verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setMetricIds(asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID)), "M2", "M3");
// multiple measures of component C1 of non last analysis
- verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID).setMetricIds(asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID)), "M1");
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(pastAnalysis.getUuid()).setMetricIds(asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID)), "M1");
// multiple measures of component C1 of last analysis by UUID
- verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setMetricIds(asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID)), "M2", "M3");
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(lastAnalysis.getUuid()).setMetricIds(asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID)), "M2", "M3");
// missing measure of component C1 of last analysis
verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setMetricId(COMPLEXITY_METRIC_ID));
// missing measure of component C1 of non last analysis
- verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID).setMetricId(COMPLEXITY_METRIC_ID));
+ verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(pastAnalysis.getUuid()).setMetricId(COMPLEXITY_METRIC_ID));
// missing measure of component C1 of last analysis by UUID
- verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setMetricId(COMPLEXITY_METRIC_ID));
+ verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(lastAnalysis.getUuid()).setMetricId(COMPLEXITY_METRIC_ID));
// ncloc measures of components C1, C2 and C3 (which does not exist) of last analysis
verifyMeasures(MeasureQuery.builder().setComponentUuids(project1.uuid(), asList("C1", "C2", "C3")), "M2", "M3", "M6");
// ncloc measures of components C1, C2 and C3 (which does not exist) of non last analysis
- verifyMeasures(MeasureQuery.builder().setComponentUuids(project1.uuid(), asList("C1", "C2", "C3")).setAnalysisUuid(OTHER_ANALYSIS_UUID), "M1");
+ verifyMeasures(MeasureQuery.builder().setComponentUuids(project1.uuid(), asList("C1", "C2", "C3")).setAnalysisUuid(pastAnalysis.getUuid()), "M1");
// ncloc measures of components C1, C2 and C3 (which does not exist) of last analysis by UUID
- verifyMeasures(MeasureQuery.builder().setComponentUuids(project1.uuid(), asList("C1", "C2", "C3")).setAnalysisUuid(LAST_ANALYSIS_UUID), "M2", "M3", "M6");
-
- // measures of missing developer of component C1 of last analysis
- verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setPersonId(123L));
- // measures of missing developer of component C1 of non last analysis
- verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID).setPersonId(123L), "M5");
- // measures of missing developer of component C1 of last analysis by UUID
- verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setPersonId(123L));
-
- // developer measures of component C1 of last analysis
- verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setPersonId(A_PERSON_ID), "M4");
- // developer measures of component C1 of non last analysis
- verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID).setPersonId(A_PERSON_ID));
- // developer measures of component C1 of last analysis by UUID
- verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setPersonId(A_PERSON_ID), "M4");
+ verifyMeasures(MeasureQuery.builder().setComponentUuids(project1.uuid(), asList("C1", "C2", "C3")).setAnalysisUuid(lastAnalysis.getUuid()), "M2", "M3", "M6");
// projects measures of last analysis
verifyMeasures(MeasureQuery.builder().setProjectUuids(singletonList(project1.uuid())).setMetricId(NCLOC_METRIC_ID), "P1_M1");
@@ -194,113 +177,8 @@ public class MeasureDaoTest {
verifyMeasures(MeasureQuery.builder().setProjectUuids(asList(project1.uuid(), project2.uuid(), "UNKNOWN")).setMetricId(NCLOC_METRIC_ID), "P1_M1", "P2_M1");
// projects measures of none last analysis
- verifyMeasures(MeasureQuery.builder().setProjectUuids(singletonList(project1.uuid())).setMetricId(NCLOC_METRIC_ID).setAnalysisUuid(OTHER_ANALYSIS_UUID), "P1_M3");
- verifyMeasures(MeasureQuery.builder().setProjectUuids(asList(project1.uuid(), project2.uuid())).setMetricId(NCLOC_METRIC_ID).setAnalysisUuid(OTHER_ANALYSIS_UUID), "P1_M3");
- }
-
- @Test
- public void selectSingle() {
- ComponentDto project = db.components().insertPrivateProject();
- db.components().insertComponent(newFileDto(project).setUuid("C1"));
- insertAnalysis(LAST_ANALYSIS_UUID, project.uuid(), true);
- insertMeasure("M1", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID);
- insertMeasure("M2", LAST_ANALYSIS_UUID, "C1", COMPLEXITY_METRIC_ID);
- db.commit();
-
- assertThat(selectSingle(MeasureQuery.builder().setComponentUuids(project.uuid(), emptyList()))).isNotPresent();
- assertThat(selectSingle(MeasureQuery.builder().setComponentUuid("MISSING_COMPONENT"))).isNotPresent();
-
- // select a single measure
- assertThat(selectSingle(MeasureQuery.builder().setComponentUuid("C1").setMetricId(NCLOC_METRIC_ID))).isPresent();
-
- // select multiple measures -> fail
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("expected one element");
- selectSingle(MeasureQuery.builder().setComponentUuid("C1"));
- }
-
- @Test
- public void select_tree_by_query() {
- ComponentDto project = db.components().insertPrivateProject();
- ComponentDto module1 = db.components().insertComponent(newModuleDto(project));
- ComponentDto module2 = db.components().insertComponent(newModuleDto(project));
- ComponentDto file1 = db.components().insertComponent(newFileDto(module1).setUuid("C1").setName("File One"));
- db.components().insertComponent(newFileDto(module2).setUuid("C2").setName("File Two").setQualifier(UNIT_TEST_FILE));
- insertAnalysis(LAST_ANALYSIS_UUID, project.uuid(), true);
-
- // project
- insertMeasure("PROJECT_M1", LAST_ANALYSIS_UUID, project.uuid(), NCLOC_METRIC_ID);
- // module 1
- insertMeasure("MODULE_M1", LAST_ANALYSIS_UUID, module1.uuid(), NCLOC_METRIC_ID);
- // component C1
- insertMeasure("M2", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID);
- insertMeasure("M3", LAST_ANALYSIS_UUID, "C1", COVERAGE_METRIC_ID);
- insertMeasureOnPerson("M4", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID, A_PERSON_ID);
- // component C2
- insertMeasure("M6", LAST_ANALYSIS_UUID, "C2", NCLOC_METRIC_ID);
- db.commit();
-
- // Children measures of project
- verifyMeasures(project, MeasureTreeQuery.builder().setStrategy(CHILDREN), "PROJECT_M1", "MODULE_M1");
-
- // Children measures of module 1
- verifyMeasures(module1, MeasureTreeQuery.builder().setStrategy(CHILDREN), "M2", "M3", "MODULE_M1");
-
- // Children measure on file => only measures from itself
- verifyMeasures(file1, MeasureTreeQuery.builder().setStrategy(CHILDREN), "M2", "M3");
-
- // Leaves measures of project
- verifyMeasures(project, MeasureTreeQuery.builder().setStrategy(LEAVES), "PROJECT_M1", "MODULE_M1", "M2", "M3", "M6");
-
- // Leaves measures of module 1
- verifyMeasures(module1, MeasureTreeQuery.builder().setStrategy(LEAVES), "MODULE_M1", "M2", "M3");
-
- // Leaves measures of project by metric ids
- verifyMeasures(project, MeasureTreeQuery.builder().setMetricIds(asList(NCLOC_METRIC_ID)).setStrategy(LEAVES), "PROJECT_M1", "MODULE_M1", "M2",
- "M6");
-
- // Leaves measure on file
- verifyMeasures(file1, MeasureTreeQuery.builder().setStrategy(LEAVES), "M2", "M3");
-
- // Leaves measures of project matching name
- verifyMeasures(project, MeasureTreeQuery.builder().setNameOrKeyQuery("OnE").setStrategy(LEAVES), "M2", "M3");
-
- // Leaves measures of project matching qualifiers
- verifyMeasures(project, MeasureTreeQuery.builder().setQualifiers(asList(FILE)).setStrategy(LEAVES), "M2", "M3");
- verifyMeasures(project, MeasureTreeQuery.builder().setQualifiers(asList(FILE, UNIT_TEST_FILE)).setStrategy(LEAVES), "M2", "M3", "M6");
- }
-
- @Test
- public void select_tree_by_query_use_only_latest_analysis() {
- ComponentDto project = db.components().insertPrivateProject();
- ComponentDto file1 = db.components().insertComponent(newFileDto(project).setUuid("C1").setName("File One"));
- db.components().insertComponent(newFileDto(project).setUuid("C2").setName("File Two").setQualifier(UNIT_TEST_FILE));
- insertAnalysis(LAST_ANALYSIS_UUID, project.uuid(), true);
- insertAnalysis(OTHER_ANALYSIS_UUID, project.uuid(), false);
-
- // project
- insertMeasure("PROJECT_M1", LAST_ANALYSIS_UUID, project.uuid(), NCLOC_METRIC_ID);
- insertMeasure("PROJECT_M2", OTHER_ANALYSIS_UUID, project.uuid(), NCLOC_METRIC_ID);
- // component C1
- insertMeasure("M2", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID);
- insertMeasure("M3", LAST_ANALYSIS_UUID, "C1", COVERAGE_METRIC_ID);
- insertMeasure("M4", OTHER_ANALYSIS_UUID, "C1", COVERAGE_METRIC_ID);
- // component C2
- insertMeasure("M5", LAST_ANALYSIS_UUID, "C2", NCLOC_METRIC_ID);
- insertMeasure("M6", OTHER_ANALYSIS_UUID, "C2", NCLOC_METRIC_ID);
- db.commit();
-
- // Children measures of project
- verifyMeasures(project, MeasureTreeQuery.builder().setStrategy(CHILDREN), "PROJECT_M1", "M2", "M3", "M5");
-
- // Children measure on file => only measures from itself
- verifyMeasures(file1, MeasureTreeQuery.builder().setStrategy(CHILDREN), "M2", "M3");
-
- // Leaves measures of project
- verifyMeasures(project, MeasureTreeQuery.builder().setStrategy(LEAVES), "PROJECT_M1", "M2", "M3", "M5");
-
- // Leaves measure on file
- verifyMeasures(file1, MeasureTreeQuery.builder().setStrategy(LEAVES), "M2", "M3");
+ verifyMeasures(MeasureQuery.builder().setProjectUuids(singletonList(project1.uuid())).setMetricId(NCLOC_METRIC_ID).setAnalysisUuid(pastAnalysis.getUuid()), "P1_M3");
+ verifyMeasures(MeasureQuery.builder().setProjectUuids(asList(project1.uuid(), project2.uuid())).setMetricId(NCLOC_METRIC_ID).setAnalysisUuid(pastAnalysis.getUuid()), "P1_M3");
}
@Test
@@ -309,14 +187,14 @@ public class MeasureDaoTest {
long lastAnalysisDate = parseDate("2017-01-25").getTime();
long previousAnalysisDate = lastAnalysisDate - 10_000_000_000L;
long oldAnalysisDate = lastAnalysisDate - 100_000_000_000L;
- dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setUuid(LAST_ANALYSIS_UUID).setCreatedAt(lastAnalysisDate));
- dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setUuid(OTHER_ANALYSIS_UUID).setCreatedAt(previousAnalysisDate).setLast(false));
- dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setUuid("OLD_ANALYSIS_UUID").setCreatedAt(oldAnalysisDate).setLast(false));
+ SnapshotDto lastAnalysis = dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setCreatedAt(lastAnalysisDate));
+ SnapshotDto pastAnalysis = dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setCreatedAt(previousAnalysisDate).setLast(false));
+ dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setCreatedAt(oldAnalysisDate).setLast(false));
db.commit();
// project
- insertMeasure("PROJECT_M1", LAST_ANALYSIS_UUID, project.uuid(), NCLOC_METRIC_ID);
- insertMeasure("PROJECT_M2", OTHER_ANALYSIS_UUID, project.uuid(), NCLOC_METRIC_ID);
+ insertMeasure("PROJECT_M1", lastAnalysis.getUuid(), project.uuid(), NCLOC_METRIC_ID);
+ insertMeasure("PROJECT_M2", pastAnalysis.getUuid(), project.uuid(), NCLOC_METRIC_ID);
insertMeasure("PROJECT_M3", "OLD_ANALYSIS_UUID", project.uuid(), NCLOC_METRIC_ID);
db.commit();
@@ -327,58 +205,6 @@ public class MeasureDaoTest {
assertThat(result).hasSize(2).extracting(MeasureDto::getData).containsOnly("PROJECT_M1", "PROJECT_M2");
}
- @Test
- public void selectByComponentsAndMetrics() {
- ComponentDto project1 = db.components().insertPrivateProject(db.getDefaultOrganization(), "P1");
- ComponentDto module = db.components().insertComponent(newModuleDto(project1));
- db.components().insertComponent(newFileDto(module).setUuid("C1"));
- db.components().insertComponent(newFileDto(module).setUuid("C2"));
- insertAnalysis(LAST_ANALYSIS_UUID, project1.uuid(), true);
- insertAnalysis(OTHER_ANALYSIS_UUID, project1.uuid(), false);
-
- String project2LastAnalysisUuid = "P2_LAST_ANALYSIS";
- ComponentDto project2 = db.components().insertPrivateProject(db.getDefaultOrganization(), "P2");
- insertAnalysis(project2LastAnalysisUuid, project2.uuid(), true);
-
- // project 1
- insertMeasure("P1_M1", LAST_ANALYSIS_UUID, project1.uuid(), NCLOC_METRIC_ID);
- insertMeasure("P1_M2", LAST_ANALYSIS_UUID, project1.uuid(), COVERAGE_METRIC_ID);
- insertMeasure("P1_M3", OTHER_ANALYSIS_UUID, project1.uuid(), NCLOC_METRIC_ID);
- // project 2
- insertMeasure("P2_M1", project2LastAnalysisUuid, project2.uuid(), NCLOC_METRIC_ID);
- insertMeasure("P2_M2", project2LastAnalysisUuid, project2.uuid(), COVERAGE_METRIC_ID);
- // component C1
- insertMeasure("M1", OTHER_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID);
- insertMeasure("M2", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID);
- insertMeasure("M3", LAST_ANALYSIS_UUID, "C1", COVERAGE_METRIC_ID);
- insertMeasureOnPerson("M4", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID, A_PERSON_ID);
- insertMeasureOnPerson("M5", OTHER_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID, 123L);
- // component C2
- insertMeasure("M6", LAST_ANALYSIS_UUID, "C2", NCLOC_METRIC_ID);
- db.commit();
-
- assertThat(underTest.selectByComponentsAndMetrics(db.getSession(), Collections.emptyList(), Collections.emptyList())).isEmpty();
-
- // Measures of component C1
- assertThat(underTest.selectByComponentsAndMetrics(db.getSession(), singletonList("C1"), singletonList(NCLOC_METRIC_ID))).extracting(MeasureDto::getData).containsOnly("M2");
- assertThat(underTest.selectByComponentsAndMetrics(db.getSession(), singletonList("C1"), asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID))).extracting(MeasureDto::getData)
- .containsOnly("M2", "M3");
-
- // ncloc measures of components C1, C2
- assertThat(underTest.selectByComponentsAndMetrics(db.getSession(), asList("C1", "C2"), asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID))).extracting(MeasureDto::getData)
- .containsOnly("M2", "M3", "M6");
-
- // projects measures of last analysis
- assertThat(underTest.selectByComponentsAndMetrics(db.getSession(), singletonList("P1"), singletonList(NCLOC_METRIC_ID))).extracting(MeasureDto::getData)
- .containsOnly("P1_M1");
- assertThat(underTest.selectByComponentsAndMetrics(db.getSession(), asList("P1", "P2"), asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID))).extracting(MeasureDto::getData)
- .containsOnly("P1_M1", "P1_M2", "P2_M1", "P2_M2");
- }
-
- private Optional<MeasureDto> selectSingle(MeasureQuery.Builder query) {
- return underTest.selectSingle(db.getSession(), query.build());
- }
-
private void verifyMeasures(MeasureQuery.Builder query, String... expectedIds) {
List<MeasureDto> measures = underTest.selectByQuery(db.getSession(), query.build());
assertThat(measures).extracting(MeasureDto::getData).containsOnly(expectedIds);
@@ -388,63 +214,22 @@ public class MeasureDaoTest {
assertThat(underTest.selectByQuery(db.getSession(), query.build())).isEmpty();
}
- private void verifyMeasures(ComponentDto baseComponent, MeasureTreeQuery.Builder measureQuery, String... expectedIds) {
- List<MeasureDto> measures = new ArrayList<>();
- underTest.selectTreeByQuery(db.getSession(), baseComponent, measureQuery.build(), result -> measures.add(result.getResultObject()));
- assertThat(measures).extracting(MeasureDto::getData).containsOnly(expectedIds);
- }
-
private void insertMeasure(String id, String analysisUuid, String componentUuid, int metricId) {
- insertMeasure(id, analysisUuid, componentUuid, null, metricId);
- }
-
- private void insertMeasure(String id, String analysisUuid, String componentUuid, @Nullable Long developerId, int metricId) {
MeasureDto measure = MeasureTesting.newMeasure()
.setAnalysisUuid(analysisUuid)
.setComponentUuid(componentUuid)
.setMetricId(metricId)
// as ids can't be forced when inserting measures, the field "data"
// is used to store a virtual id. It is used then in assertions.
- .setData(id)
- .setDeveloperId(developerId);
- db.getDbClient().measureDao().insert(db.getSession(), measure);
- }
-
- private String insertComponent(String scope, String qualifier, boolean enabled) {
- String uuid = UuidFactoryImpl.INSTANCE.create();
- ComponentDto componentDto = new ComponentDto()
- .setOrganizationUuid("org1")
- .setUuid(uuid)
- .setScope(scope)
- .setQualifier(qualifier)
- .setProjectUuid("don't care")
- .setRootUuid("don't care")
- .setUuidPath("don't care")
- .setDbKey("kee_" + uuid)
- .setEnabled(enabled);
- db.getDbClient().componentDao().insert(db.getSession(), componentDto);
- return uuid;
- }
-
- private void insertMeasureOnPerson(String id, String analysisUuid, String componentUuid, int metricId, long personId) {
- MeasureDto measure = MeasureTesting.newMeasure()
- .setAnalysisUuid(analysisUuid)
- .setComponentUuid(componentUuid)
- .setMetricId(metricId)
- .setDeveloperId(personId)
- // as ids can't be forced when inserting measures, the field "data"
- // is used to store a virtual id. It is used then in assertions.
.setData(id);
db.getDbClient().measureDao().insert(db.getSession(), measure);
}
- private SnapshotDto insertAnalysis(String uuid, String projectUuid, boolean isLast) {
+ private SnapshotDto insertAnalysis(String projectUuid, boolean isLast) {
return db.getDbClient().snapshotDao().insert(db.getSession(), SnapshotTesting.newSnapshot()
- .setUuid(uuid)
+ .setUuid(Uuids.createFast())
.setComponentUuid(projectUuid)
.setLast(isLast));
}
- // TODO test selectPastMeasures
-
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDbTester.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDbTester.java
index b1d45914ec3..30ba72b4a30 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDbTester.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDbTester.java
@@ -28,16 +28,15 @@ import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.metric.MetricDto;
+import static org.sonar.db.measure.MeasureTesting.newLiveMeasure;
import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
import static org.sonar.db.metric.MetricTesting.newMetricDto;
public class MeasureDbTester {
- private final DbTester db;
private final DbClient dbClient;
private final DbSession dbSession;
public MeasureDbTester(DbTester db) {
- this.db = db;
this.dbClient = db.getDbClient();
this.dbSession = db.getSession();
}
@@ -52,6 +51,15 @@ public class MeasureDbTester {
}
@SafeVarargs
+ public final LiveMeasureDto insertLiveMeasure(ComponentDto component, MetricDto metric, Consumer<LiveMeasureDto>... consumers){
+ LiveMeasureDto dto = newLiveMeasure(component, metric);
+ Arrays.stream(consumers).forEach(c -> c.accept(dto));
+ dbClient.liveMeasureDao().insert(dbSession, dto);
+ dbSession.commit();
+ return dto;
+ }
+
+ @SafeVarargs
public final MetricDto insertMetric(Consumer<MetricDto>... consumers){
MetricDto metricDto = newMetricDto();
Arrays.stream(consumers).forEach(c -> c.accept(metricDto));
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureQueryTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureQueryTest.java
index 3e083c415bb..959edae309c 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureQueryTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureQueryTest.java
@@ -82,13 +82,6 @@ public class MeasureQueryTest {
}
@Test
- public void create_query_from_person_id() {
- MeasureQuery query = MeasureQuery.builder().setProjectUuids(asList("PROJECT_1", "PROJECT_2")).setPersonId(100L).build();
-
- assertThat(query.getPersonId()).isEqualTo(100L);
- }
-
- @Test
public void return_empty_when_metrics_are_empty() {
assertThat(MeasureQuery.builder()
.setProjectUuids(asList("PROJECT_1", "PROJECT_2"))
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTesting.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTesting.java
index 39e7671a281..34f8ba2a927 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTesting.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTesting.java
@@ -50,10 +50,29 @@ public class MeasureTesting {
.setMetricId(cursor++)
.setComponentUuid(String.valueOf(cursor++))
.setAnalysisUuid(String.valueOf(cursor++))
- .setDeveloperId(null)
.setData(String.valueOf(cursor++))
.setAlertStatus(String.valueOf(cursor++))
.setAlertText(String.valueOf(cursor++))
- .setValue((double)cursor++);
+ .setValue((double) cursor++);
+ }
+
+ public static LiveMeasureDto newLiveMeasure() {
+ return new LiveMeasureDto()
+ .setMetricId(cursor++)
+ .setComponentUuid(String.valueOf(cursor++))
+ .setProjectUuid(String.valueOf(cursor++))
+ .setData(String.valueOf(cursor++))
+ .setValue((double) cursor++)
+ .setVariation((double) cursor++);
+ }
+
+ public static LiveMeasureDto newLiveMeasure(ComponentDto component, MetricDto metric) {
+ return new LiveMeasureDto()
+ .setMetricId(metric.getId())
+ .setComponentUuid(component.uuid())
+ .setProjectUuid(component.projectUuid())
+ .setData(String.valueOf(cursor++))
+ .setValue((double) cursor++)
+ .setVariation((double) cursor++);
}
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTreeQueryTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTreeQueryTest.java
index 925f0765c95..54dbde3ea54 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTreeQueryTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTreeQueryTest.java
@@ -43,14 +43,12 @@ public class MeasureTreeQueryTest {
.setQualifiers(asList("FIL", "DIR"))
.setNameOrKeyQuery("teSt")
.setMetricIds(asList(10, 11))
- .setPersonId(100L)
.build();
assertThat(query.getStrategy()).isEqualTo(CHILDREN);
assertThat(query.getQualifiers()).containsOnly("FIL", "DIR");
assertThat(query.getNameOrKeyQuery()).isEqualTo("teSt");
assertThat(query.getMetricIds()).containsOnly(10, 11);
- assertThat(query.getPersonId()).isEqualTo(100L);
}
@Test
@@ -63,7 +61,6 @@ public class MeasureTreeQueryTest {
assertThat(query.getQualifiers()).isNull();
assertThat(query.getNameOrKeyQuery()).isNull();
assertThat(query.getMetricIds()).isNull();
- assertThat(query.getPersonId()).isNull();
}
@Test
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/PastMeasureDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/PastMeasureDtoTest.java
index 07a630ad5f7..02fe87598bc 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/PastMeasureDtoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/PastMeasureDtoTest.java
@@ -29,26 +29,22 @@ public class PastMeasureDtoTest {
public void test_getter_and_setter() throws Exception {
PastMeasureDto dto = new PastMeasureDto()
.setValue(1d)
- .setMetricId(2)
- .setPersonId(5L);
+ .setMetricId(2);
assertThat(dto.hasValue()).isTrue();
assertThat(dto.getValue()).isEqualTo(1d);
assertThat(dto.getMetricId()).isEqualTo(2);
- assertThat(dto.getPersonId()).isEqualTo(5L);
}
@Test
public void test_has_value() throws Exception {
PastMeasureDto measureWithValue = new PastMeasureDto()
.setValue(1d)
- .setMetricId(2)
- .setPersonId(5L);
+ .setMetricId(2);
assertThat(measureWithValue.hasValue()).isTrue();
PastMeasureDto measureWithoutValue = new PastMeasureDto()
- .setMetricId(2)
- .setPersonId(5L);
+ .setMetricId(2);
assertThat(measureWithoutValue.hasValue()).isFalse();
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/ProjectMeasuresIndexerIteratorTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/ProjectMeasuresIndexerIteratorTest.java
index 5c475437ed3..2d78a96a857 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/ProjectMeasuresIndexerIteratorTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/ProjectMeasuresIndexerIteratorTest.java
@@ -25,7 +25,6 @@ import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.api.measures.Metric;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
@@ -35,7 +34,6 @@ import org.sonar.db.component.ComponentTesting;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.measure.ProjectMeasuresIndexerIterator.ProjectMeasures;
import org.sonar.db.metric.MetricDto;
-import org.sonar.db.metric.MetricTesting;
import org.sonar.db.organization.OrganizationDto;
import static org.assertj.core.api.Assertions.assertThat;
@@ -48,7 +46,6 @@ import static org.sonar.api.measures.Metric.ValueType.DISTRIB;
import static org.sonar.api.measures.Metric.ValueType.INT;
import static org.sonar.api.measures.Metric.ValueType.LEVEL;
import static org.sonar.api.measures.Metric.ValueType.STRING;
-import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
import static org.sonar.db.component.ComponentTesting.newView;
import static org.sonar.db.component.SnapshotTesting.newAnalysis;
@@ -64,12 +61,13 @@ public class ProjectMeasuresIndexerIteratorTest {
@Test
public void return_project_measure() {
- MetricDto metric1 = insertIntMetric("ncloc");
- MetricDto metric2 = insertIntMetric("coverage");
- ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization()).setDbKey("Project-Key").setName("Project Name").setTagsString("platform,java");
- SnapshotDto analysis = dbTester.components().insertProjectAndSnapshot(project);
- insertMeasure(project, analysis, metric1, 10d);
- insertMeasure(project, analysis, metric2, 20d);
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto project = dbTester.components().insertPrivateProject(organization, p -> p.setDbKey("Project-Key").setName("Project Name").setTagsString("platform,java"));
+ SnapshotDto analysis = dbTester.components().insertSnapshot(project);
+ MetricDto metric1 = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()).setKey("ncloc"));
+ MetricDto metric2 = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()).setKey("coverage"));
+ dbTester.measures().insertLiveMeasure(project, metric1, m -> m.setValue(10d));
+ dbTester.measures().insertLiveMeasure(project, metric2, m -> m.setValue(20d));
Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
@@ -81,15 +79,15 @@ public class ProjectMeasuresIndexerIteratorTest {
assertThat(doc.getProject().getName()).isEqualTo("Project Name");
assertThat(doc.getProject().getTags()).containsExactly("platform", "java");
assertThat(doc.getProject().getAnalysisDate()).isNotNull().isEqualTo(analysis.getCreatedAt());
- assertThat(doc.getMeasures().getNumericMeasures()).containsOnly(entry("ncloc", 10d), entry("coverage", 20d));
+ assertThat(doc.getMeasures().getNumericMeasures()).containsOnly(entry(metric1.getKey(), 10d), entry(metric2.getKey(), 20d));
}
@Test
public void return_project_measure_having_leak() throws Exception {
- MetricDto metric = insertIntMetric("new_lines");
- ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization());
- SnapshotDto analysis = dbTester.components().insertProjectAndSnapshot(project);
- insertMeasureOnLeak(project, analysis, metric, 10d);
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto project = dbTester.components().insertPrivateProject(organization, p -> p.setDbKey("Project-Key").setName("Project Name").setTagsString("platform,java"));
+ MetricDto metric = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()).setKey("new_lines"));
+ dbTester.measures().insertLiveMeasure(project, metric, m -> m.setVariation(10d));
Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
@@ -98,34 +96,40 @@ public class ProjectMeasuresIndexerIteratorTest {
@Test
public void return_quality_gate_status_measure() throws Exception {
- MetricDto metric = insertMetric("alert_status", LEVEL);
- insertProjectAndMeasure("project1", metric, WARN.name());
- insertProjectAndMeasure("project2", metric, OK.name());
- insertProjectAndMeasure("project3", metric, ERROR.name());
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto project1 = dbTester.components().insertPrivateProject(organization);
+ ComponentDto project2 = dbTester.components().insertPrivateProject(organization);
+ ComponentDto project3 = dbTester.components().insertPrivateProject(organization);
+ MetricDto metric = dbTester.measures().insertMetric(m -> m.setValueType(LEVEL.name()).setKey("alert_status"));
+ dbTester.measures().insertLiveMeasure(project1, metric, m -> m.setValue(null).setData(WARN.name()));
+ dbTester.measures().insertLiveMeasure(project2, metric, m -> m.setValue(null).setData(OK.name()));
+ dbTester.measures().insertLiveMeasure(project3, metric, m -> m.setValue(null).setData(ERROR.name()));
Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
- assertThat(docsById.get("project1").getMeasures().getQualityGateStatus()).isEqualTo("WARN");
- assertThat(docsById.get("project2").getMeasures().getQualityGateStatus()).isEqualTo("OK");
- assertThat(docsById.get("project3").getMeasures().getQualityGateStatus()).isEqualTo("ERROR");
+ assertThat(docsById.get(project1.uuid()).getMeasures().getQualityGateStatus()).isEqualTo("WARN");
+ assertThat(docsById.get(project2.uuid()).getMeasures().getQualityGateStatus()).isEqualTo("OK");
+ assertThat(docsById.get(project3.uuid()).getMeasures().getQualityGateStatus()).isEqualTo("ERROR");
}
@Test
public void does_not_fail_when_quality_gate_has_no_value() throws Exception {
- MetricDto metric = insertMetric("alert_status", LEVEL);
- insertProjectAndMeasure("project", metric, null);
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto project = dbTester.components().insertPrivateProject(organization);
+ MetricDto metric = dbTester.measures().insertMetric(m -> m.setValueType(LEVEL.name()).setKey("alert_status"));
+ dbTester.measures().insertLiveMeasure(project, metric, m -> m.setValue(null).setVariation(null).setData((String) null));
Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
- assertThat(docsById.get("project").getMeasures().getNumericMeasures()).isEmpty();
+ assertThat(docsById.get(project.uuid()).getMeasures().getNumericMeasures()).isEmpty();
}
@Test
public void return_language_distribution_measure() throws Exception {
- MetricDto metric = insertMetric("ncloc_language_distribution", DATA);
- ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization());
- SnapshotDto analysis = dbTester.components().insertProjectAndSnapshot(project);
- insertMeasure(project, analysis, metric, "<null>=2;java=6;xoo=18");
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto project = dbTester.components().insertPrivateProject(organization);
+ MetricDto metric = dbTester.measures().insertMetric(m -> m.setValueType(DATA.name()).setKey("ncloc_language_distribution"));
+ dbTester.measures().insertLiveMeasure(project, metric, m -> m.setValue(null).setData("<null>=2;java=6;xoo=18"));
Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
@@ -135,14 +139,14 @@ public class ProjectMeasuresIndexerIteratorTest {
@Test
public void does_not_return_none_numeric_metrics() throws Exception {
- MetricDto dataMetric = insertMetric("data", DATA);
- MetricDto distribMetric = insertMetric("distrib", DISTRIB);
- MetricDto stringMetric = insertMetric("string", STRING);
- ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization());
- SnapshotDto analysis = dbTester.components().insertProjectAndSnapshot(project);
- insertMeasure(project, analysis, dataMetric, "dat");
- insertMeasure(project, analysis, distribMetric, "dis");
- insertMeasure(project, analysis, stringMetric, "str");
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto project = dbTester.components().insertPrivateProject(organization);
+ MetricDto dataMetric = dbTester.measures().insertMetric(m -> m.setValueType(DATA.name()).setKey("data"));
+ MetricDto distribMetric = dbTester.measures().insertMetric(m -> m.setValueType(DISTRIB.name()).setKey("distrib"));
+ MetricDto stringMetric = dbTester.measures().insertMetric(m -> m.setValueType(STRING.name()).setKey("string"));
+ dbTester.measures().insertLiveMeasure(project, dataMetric, m -> m.setData("dat"));
+ dbTester.measures().insertLiveMeasure(project, distribMetric, m -> m.setData("dis"));
+ dbTester.measures().insertLiveMeasure(project, stringMetric, m -> m.setData("str"));
Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
@@ -151,10 +155,10 @@ public class ProjectMeasuresIndexerIteratorTest {
@Test
public void does_not_return_disabled_metrics() throws Exception {
- MetricDto disabledMetric = insertMetric("disabled", false, false, INT);
- ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization());
- SnapshotDto analysis = dbTester.components().insertProjectAndSnapshot(project);
- insertMeasure(project, analysis, disabledMetric, 10d);
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto project = dbTester.components().insertPrivateProject(organization);
+ MetricDto disabledMetric = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()).setEnabled(false).setHidden(false).setKey("disabled"));
+ dbTester.measures().insertLiveMeasure(project, disabledMetric, m -> m.setValue(10d));
Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
@@ -163,29 +167,28 @@ public class ProjectMeasuresIndexerIteratorTest {
@Test
public void ignore_measure_that_does_not_have_value() throws Exception {
- MetricDto metric1 = insertIntMetric("coverage");
- MetricDto metric2 = insertIntMetric("ncloc");
- MetricDto leakMetric = insertIntMetric("new_lines");
- ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization());
- SnapshotDto analysis = dbTester.components().insertProjectAndSnapshot(project);
+ OrganizationDto organization = dbTester.organizations().insert();
+ MetricDto metric1 = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()).setKey("coverage"));
+ MetricDto metric2 = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()).setKey("ncloc"));
+ MetricDto leakMetric = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()).setKey("new_lines"));
+ ComponentDto project = dbTester.components().insertPrivateProject(organization);
- MeasureDto withValue = insertMeasure(project, analysis, metric1, 10d);
- MeasureDto withLeakValue = insertMeasure(project, analysis, leakMetric, null, 20d);
- MeasureDto withoutValue = insertMeasure(project, analysis, metric2, null, null);
+ dbTester.measures().insertLiveMeasure(project, metric1, m -> m.setValue(10d));
+ dbTester.measures().insertLiveMeasure(project, leakMetric, m -> m.setValue(null).setVariation(20d));
+ dbTester.measures().insertLiveMeasure(project, metric2, m -> m.setValue(null).setVariation(null));
Map<String, Double> numericMeasures = createResultSetAndReturnDocsById().get(project.uuid()).getMeasures().getNumericMeasures();
- assertThat(numericMeasures).containsOnly(entry("coverage", 10d), entry("new_lines", 20d));
+ assertThat(numericMeasures).containsOnly(entry(metric1.getKey(), 10d), entry(leakMetric.getKey(), 20d));
}
@Test
public void ignore_numeric_measure_that_has_text_value_but_not_numeric_value() throws Exception {
- MetricDto metric1 = insertIntMetric("coverage");
- MetricDto metric2 = insertIntMetric("ncloc");
- ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization());
- SnapshotDto analysis = dbTester.components().insertProjectAndSnapshot(project);
-
- MeasureDto withNumericValue = insertMeasure(project, analysis, metric1, 10d);
- MeasureDto withTextValue = insertMeasure(project, analysis, metric2, "foo");
+ OrganizationDto organization = dbTester.organizations().insert();
+ MetricDto metric1 = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()).setKey("coverage"));
+ MetricDto metric2 = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()).setKey("ncloc"));
+ ComponentDto project = dbTester.components().insertPrivateProject(organization);
+ dbTester.measures().insertLiveMeasure(project, metric1, m -> m.setValue(10d).setData((String) null));
+ dbTester.measures().insertLiveMeasure(project, metric2, m -> m.setValue(null).setData("foo"));
Map<String, Double> numericMeasures = createResultSetAndReturnDocsById().get(project.uuid()).getMeasures().getNumericMeasures();
assertThat(numericMeasures).containsOnly(entry("coverage", 10d));
@@ -193,9 +196,13 @@ public class ProjectMeasuresIndexerIteratorTest {
@Test
public void return_many_project_measures() {
- dbTester.components().insertProjectAndSnapshot(ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization()));
- dbTester.components().insertProjectAndSnapshot(ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization()));
- dbTester.components().insertProjectAndSnapshot(ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization()));
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto project1 = dbTester.components().insertPrivateProject(organization);
+ ComponentDto project2 = dbTester.components().insertPrivateProject(organization);
+ ComponentDto project3 = dbTester.components().insertPrivateProject(organization);
+ dbTester.components().insertSnapshot(project1);
+ dbTester.components().insertSnapshot(project2);
+ dbTester.components().insertSnapshot(project3);
assertThat(createResultSetAndReturnDocsById()).hasSize(3);
}
@@ -215,42 +222,47 @@ public class ProjectMeasuresIndexerIteratorTest {
@Test
public void does_not_return_non_active_projects() throws Exception {
+ OrganizationDto organization = dbTester.organizations().insert();
// Disabled project
- dbTester.components().insertProjectAndSnapshot(ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization()).setEnabled(false));
+ dbTester.components().insertProjectAndSnapshot(ComponentTesting.newPrivateProjectDto(organization).setEnabled(false));
// Disabled project with analysis
- ComponentDto project = dbTester.components().insertComponent(ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization()).setEnabled(false));
+ ComponentDto project = dbTester.components().insertComponent(ComponentTesting.newPrivateProjectDto(organization).setEnabled(false));
dbClient.snapshotDao().insert(dbSession, newAnalysis(project));
// A view
- dbTester.components().insertProjectAndSnapshot(newView(dbTester.getDefaultOrganization()));
+ dbTester.components().insertProjectAndSnapshot(newView(organization));
dbSession.commit();
- assertResultSetIsEmpty();
+ assertThat(createResultSetAndReturnDocsById()).isEmpty();
}
@Test
public void return_only_docs_from_given_project() throws Exception {
- OrganizationDto organizationDto = dbTester.organizations().insert();
- ComponentDto project = ComponentTesting.newPrivateProjectDto(organizationDto);
- SnapshotDto analysis = dbTester.components().insertProjectAndSnapshot(project);
- dbTester.components().insertProjectAndSnapshot(ComponentTesting.newPrivateProjectDto(organizationDto));
- dbTester.components().insertProjectAndSnapshot(ComponentTesting.newPrivateProjectDto(organizationDto));
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto project1 = dbTester.components().insertPrivateProject(organization);
+ ComponentDto project2 = dbTester.components().insertPrivateProject(organization);
+ ComponentDto project3 = dbTester.components().insertPrivateProject(organization);
+ SnapshotDto analysis1 = dbTester.components().insertSnapshot(project1);
+ SnapshotDto analysis2 = dbTester.components().insertSnapshot(project2);
+ SnapshotDto analysis3 = dbTester.components().insertSnapshot(project3);
- Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(project.uuid());
+ Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(project1.uuid());
assertThat(docsById).hasSize(1);
- ProjectMeasures doc = docsById.get(project.uuid());
+ ProjectMeasures doc = docsById.get(project1.uuid());
assertThat(doc).isNotNull();
- assertThat(doc.getProject().getUuid()).isEqualTo(project.uuid());
- assertThat(doc.getProject().getKey()).isNotNull().isEqualTo(project.getDbKey());
- assertThat(doc.getProject().getName()).isNotNull().isEqualTo(project.name());
- assertThat(doc.getProject().getAnalysisDate()).isNotNull().isEqualTo(analysis.getCreatedAt());
+ assertThat(doc.getProject().getUuid()).isEqualTo(project1.uuid());
+ assertThat(doc.getProject().getKey()).isNotNull().isEqualTo(project1.getDbKey());
+ assertThat(doc.getProject().getName()).isNotNull().isEqualTo(project1.name());
+ assertThat(doc.getProject().getAnalysisDate()).isNotNull().isEqualTo(analysis1.getCreatedAt());
}
@Test
public void return_nothing_on_unknown_project() throws Exception {
- dbTester.components().insertProjectAndSnapshot(ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization()));
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto project = dbTester.components().insertPrivateProject(organization);
+ dbTester.components().insertSnapshot(project);
Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById("UNKNOWN");
@@ -259,14 +271,13 @@ public class ProjectMeasuresIndexerIteratorTest {
@Test
public void non_main_branches_are_not_indexed() {
- MetricDto metric = insertIntMetric("ncloc");
- ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization());
- SnapshotDto projectAnalysis = dbTester.components().insertProjectAndSnapshot(project);
- insertMeasure(project, projectAnalysis, metric, 10d);
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto project = dbTester.components().insertPrivateProject(organization);
+ MetricDto metric = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()).setKey("ncloc"));
+ dbTester.measures().insertLiveMeasure(project, metric, m -> m.setValue(10d));
ComponentDto branch = dbTester.components().insertProjectBranch(project, b -> b.setKey("feature/foo"));
- SnapshotDto branchAnalysis = dbTester.components().insertSnapshot(branch);
- insertMeasure(branch, branchAnalysis, metric, 20d);
+ dbTester.measures().insertLiveMeasure(branch, metric, m -> m.setValue(20d));
Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
@@ -284,56 +295,4 @@ public class ProjectMeasuresIndexerIteratorTest {
it.close();
return docsById;
}
-
- private void assertResultSetIsEmpty() {
- assertThat(createResultSetAndReturnDocsById()).isEmpty();
- }
-
- private MetricDto insertIntMetric(String metricKey) {
- return insertMetric(metricKey, true, false, INT);
- }
-
- private MetricDto insertMetric(String metricKey, Metric.ValueType type) {
- return insertMetric(metricKey, true, false, type);
- }
-
- private MetricDto insertMetric(String metricKey, boolean enabled, boolean hidden, Metric.ValueType type) {
- MetricDto metric = dbClient.metricDao().insert(dbSession,
- MetricTesting.newMetricDto()
- .setKey(metricKey)
- .setEnabled(enabled)
- .setHidden(hidden)
- .setValueType(type.name()));
- dbSession.commit();
- return metric;
- }
-
- private MeasureDto insertProjectAndMeasure(String projectUuid, MetricDto metric, String value) {
- ComponentDto project = newPrivateProjectDto(dbTester.getDefaultOrganization(), projectUuid);
- SnapshotDto analysis1 = dbTester.components().insertProjectAndSnapshot(project);
- return insertMeasure(project, analysis1, metric, value);
- }
-
- private MeasureDto insertMeasure(ComponentDto project, SnapshotDto analysis, MetricDto metric, double value) {
- return insertMeasure(project, analysis, metric, value, null);
- }
-
- private MeasureDto insertMeasureOnLeak(ComponentDto project, SnapshotDto analysis, MetricDto metric, double value) {
- return insertMeasure(project, analysis, metric, null, value);
- }
-
- private MeasureDto insertMeasure(ComponentDto project, SnapshotDto analysis, MetricDto metric, String value) {
- return insertMeasure(MeasureTesting.newMeasureDto(metric, project, analysis).setData(value));
- }
-
- private MeasureDto insertMeasure(ComponentDto project, SnapshotDto analysis, MetricDto metric, @Nullable Double value, @Nullable Double leakValue) {
- return insertMeasure(MeasureTesting.newMeasureDto(metric, project, analysis).setValue(value).setVariation(leakValue));
- }
-
- private MeasureDto insertMeasure(MeasureDto measure) {
- dbClient.measureDao().insert(dbSession, measure);
- dbSession.commit();
- return measure;
- }
-
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java
index d6b7f01f9f9..ba0126ffbdb 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java
@@ -164,7 +164,7 @@ public class PurgeCommandsTest {
@Test
public void deletePermissions_deletes_permissions_of_view() {
OrganizationDto organization = dbTester.organizations().insert();
- ComponentDto project = dbTester.components().insertView(organization);
+ ComponentDto project = dbTester.components().insertPublicPortfolio(organization);
addPermissions(organization, project);
PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler);
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
index e48f5c90b70..f618a131fa4 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
@@ -50,6 +50,7 @@ import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.measure.MeasureDto;
import org.sonar.db.measure.custom.CustomMeasureDto;
+import org.sonar.db.metric.MetricDto;
import org.sonar.db.property.PropertyDto;
import org.sonar.db.rule.RuleDefinitionDto;
@@ -86,7 +87,7 @@ public class PurgeDaoTest {
private PurgeDao underTest = dbTester.getDbClient().purgeDao();
@Test
- public void shouldDeleteAbortedBuilds() {
+ public void purge_failed_ce_tasks() {
dbTester.prepareDbUnit(getClass(), "shouldDeleteAbortedBuilds.xml");
underTest.purge(dbSession, newConfigurationWith30Days(), PurgeListener.EMPTY, new PurgeProfiler());
@@ -96,7 +97,7 @@ public class PurgeDaoTest {
}
@Test
- public void should_purge_project() {
+ public void purge_history_of_project() {
dbTester.prepareDbUnit(getClass(), "shouldPurgeProject.xml");
underTest.purge(dbSession, newConfigurationWith30Days(), PurgeListener.EMPTY, new PurgeProfiler());
dbSession.commit();
@@ -104,7 +105,7 @@ public class PurgeDaoTest {
}
@Test
- public void should_purge_inactive_short_living_branches() {
+ public void purge_inactive_short_living_branches() {
when(system2.now()).thenReturn(new Date().getTime());
RuleDefinitionDto rule = dbTester.rules().insert();
ComponentDto project = dbTester.components().insertMainBranch();
@@ -394,6 +395,26 @@ public class PurgeDaoTest {
verifyNoEffect(componentDbTester.insertView(), componentDbTester.insertPrivateProject(), componentDbTester.insertPublicProject());
}
+ @Test
+ public void delete_live_measures_when_deleting_project() {
+ MetricDto metric = dbTester.measures().insertMetric();
+
+ ComponentDto project1 = dbTester.components().insertPublicProject();
+ ComponentDto module1 = dbTester.components().insertComponent(ComponentTesting.newModuleDto(project1));
+ dbTester.measures().insertLiveMeasure(project1, metric);
+ dbTester.measures().insertLiveMeasure(module1, metric);
+
+ ComponentDto project2 = dbTester.components().insertPublicProject();
+ ComponentDto module2 = dbTester.components().insertComponent(ComponentTesting.newModuleDto(project2));
+ dbTester.measures().insertLiveMeasure(project2, metric);
+ dbTester.measures().insertLiveMeasure(module2, metric);
+
+ underTest.deleteProject(dbSession, project1.uuid());
+
+ assertThat(dbClient.liveMeasureDao().selectByComponentUuids(dbSession, asList(project1.uuid(), module1.uuid()), asList(metric.getId()))).isEmpty();
+ assertThat(dbClient.liveMeasureDao().selectByComponentUuids(dbSession, asList(project2.uuid(), module2.uuid()), asList(metric.getId()))).hasSize(2);
+ }
+
private void verifyNoEffect(ComponentDto firstRoot, ComponentDto... otherRoots) {
DbSession dbSession = mock(DbSession.class);
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml
index 692539f175b..2af5e30c370 100644
--- a/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml
+++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml
@@ -4,7 +4,7 @@
analysis_uuid="u2"
metric_id="3"
component_uuid="FILE1"
- person_id="23"
+ person_id="[null]"
value="2.0"
text_value="measure-value"
measure_data="[null]"
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml
deleted file mode 100644
index d1886556bef..00000000000
--- a/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<dataset>
-
- <metrics delete_historical_data="[null]"
- id="1"
- name="sqale_index"
- VAL_TYPE="INT"
- DESCRIPTION="[null]"
- enabled="[true]"/>
-
- <!-- project -->
- <projects organization_uuid="org1"
- uuid="ABCD"
- uuid_path="NOT_USED"
- project_uuid="ABCD"
- module_uuid="[null]"
- module_uuid_path=".ABCD."
- enabled="[true]"
- long_name="[null]"
- id="1"
- scope="PRJ"
- qualifier="TRK"
- kee="project"
- name="project"
- root_uuid="ABCD"/>
-
- <!-- snapshots -->
- <snapshots id="1000"
- uuid="u1000"
- component_uuid="ABCD"
- created_at="1225544280000"
- build_date="1225544280000"
- version="[null]"
- status="P"
- islast="[false]"
- />
-
- <!-- project measures -->
- <project_measures id="1"
- VALUE="60"
- METRIC_ID="1"
- analysis_uuid="u1000"
- person_id="[null]"
- component_uuid="ABCD"/>
-
- <project_measures id="2"
- VALUE="20"
- METRIC_ID="1"
- analysis_uuid="u1000"
- person_id="20"
- component_uuid="ABCD"/>
-
- <project_measures id="3"
- VALUE="40"
- METRIC_ID="1"
- analysis_uuid="u1000"
- person_id="21"
- component_uuid="ABCD"/>
-
-</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/with_some_measures_for_developer.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/with_some_measures_for_developer.xml
deleted file mode 100644
index 67736536768..00000000000
--- a/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/MeasureDaoTest/with_some_measures_for_developer.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-<dataset>
-
- <metrics id="10"
- name="authors_by_line"/>
- <metrics id="11"
- name="coverage_line_hits_data"/>
- <metrics id="12"
- name="ncloc"/>
-
- <projects organization_uuid="org1"
- uuid="uuid_1"
- uuid_path="NOT_USED"
- root_uuid="uuid_1"
- id="1"
- kee="org.struts:struts-core:src/org/struts/RequestContext.java"
- enabled="[true]"/>
- <projects organization_uuid="org1"
- uuid="333"
- uuid_path="NOT_USED"
- root_uuid="333"
- id="333"
- kee="dev:John-Doe"
- enabled="[true]"/>
-
- <snapshots id="5"
- uuid="u5"
- component_uuid="uuid_1"
- islast="[true]"
- />
-
- <project_measures id="20"
- analysis_uuid="u5"
- metric_id="10"
- value="[null]"
- text_value="0123456789012345678901234567890123456789"
- measure_data="[null]"
- variation_value_1="[null]"
- variation_value_2="[null]"
- variation_value_3="[null]"
- variation_value_4="[null]"
- variation_value_5="[null]"
- alert_status="[null]"
- alert_text="[null]"
- person_id="[null]"
- component_uuid="1"/>
- <project_measures id="21"
- analysis_uuid="u5"
- metric_id="11"
- value="[null]"
- text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1"
- measure_data="[null]"
- variation_value_1="[null]"
- variation_value_2="[null]"
- variation_value_3="[null]"
- variation_value_4="[null]"
- variation_value_5="[null]"
- alert_status="[null]"
- alert_text="[null]"
- person_id="[null]"
- component_uuid="1"/>
- <project_measures id="22"
- analysis_uuid="u5"
- metric_id="12"
- value="10"
- text_value="[null]"
- measure_data="[null]"
- variation_value_1="1"
- variation_value_2="2"
- variation_value_3="3"
- variation_value_4="4"
- variation_value_5="-5"
- alert_status="OK"
- alert_text="Green"
- person_id="[null]"
- component_uuid="1"/>
- <!--measures for developer 333-->
- <project_measures id="30"
- analysis_uuid="u5"
- metric_id="10"
- value="[null]"
- text_value="0123456789012345678901234567890123456789"
- measure_data="[null]"
- variation_value_1="[null]"
- variation_value_2="[null]"
- variation_value_3="[null]"
- variation_value_4="[null]"
- variation_value_5="[null]"
- alert_status="[null]"
- alert_text="[null]"
- person_id="333"
- component_uuid="1"/>
- <project_measures id="31"
- analysis_uuid="u5"
- metric_id="11"
- value="[null]"
- text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1"
- measure_data="[null]"
- variation_value_1="[null]"
- variation_value_2="[null]"
- variation_value_3="[null]"
- variation_value_4="[null]"
- variation_value_5="[null]"
- alert_status="[null]"
- alert_text="[null]"
- person_id="333"
- component_uuid="1"/>
- <project_measures id="32"
- analysis_uuid="u5"
- metric_id="12"
- value="10"
- text_value="[null]"
- measure_data="[null]"
- variation_value_1="1"
- variation_value_2="2"
- variation_value_3="3"
- variation_value_4="4"
- variation_value_5="-5"
- alert_status="OK"
- alert_text="Green"
- person_id="333"
- component_uuid="1"/>
-
-</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingAnalysis.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingAnalysis.xml
index 2c0a7c2df25..d683a6acfe6 100644
--- a/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingAnalysis.xml
+++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingAnalysis.xml
@@ -90,23 +90,4 @@
description="[null]"
measure_data="[null]"/>
- <!-- delete measure on developers -->
- <project_measures id="7"
- component_uuid="1"
- analysis_uuid="u1"
- metric_id="2"
- variation_value_1="[null]"
- variation_value_2="[null]"
- variation_value_3="[null]"
- person_id="123456"
- variation_value_4="[null]"
- variation_value_5="[null]"
- alert_text="[null]"
- value="10.0"
- text_value="[null]"
- tendency="[null]"
- measure_date="[null]"
- alert_status="[null]"
- description="[null]"
- measure_data="[null]"/>
</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeAnalysis.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeAnalysis.xml
index 70b5a8db7c1..5e2e4c4e819 100644
--- a/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeAnalysis.xml
+++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeAnalysis.xml
@@ -111,7 +111,6 @@
<project_measures ID="2"
component_uuid="2"
analysis_uuid="u2"
- characteristic_id="[null]"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/BaseSqlStatement.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/BaseSqlStatement.java
index 6444617dc6e..ebb62540d0b 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/BaseSqlStatement.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/BaseSqlStatement.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.platform.db.migration.step;
+import java.io.ByteArrayInputStream;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
@@ -77,6 +78,16 @@ class BaseSqlStatement<CHILD extends SqlStatement> implements SqlStatement<CHILD
}
@Override
+ public CHILD setBytes(int columnIndex, @Nullable byte[] value) throws SQLException {
+ if (value == null) {
+ pstmt.setNull(columnIndex, Types.BINARY);
+ } else {
+ pstmt.setBinaryStream(columnIndex, new ByteArrayInputStream(value));
+ }
+ return (CHILD) this;
+ }
+
+ @Override
public CHILD setDouble(int columnIndex, @Nullable Double value) throws SQLException {
if (value == null) {
pstmt.setNull(columnIndex, Types.DECIMAL);
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/DataChange.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/DataChange.java
index 64aea4df5d9..2264d774ca5 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/DataChange.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/DataChange.java
@@ -22,6 +22,7 @@ package org.sonar.server.platform.db.migration.step;
import java.sql.Connection;
import java.sql.SQLException;
import org.sonar.db.Database;
+import org.sonar.db.dialect.Dialect;
public abstract class DataChange implements MigrationStep {
@@ -31,6 +32,10 @@ public abstract class DataChange implements MigrationStep {
this.db = db;
}
+ protected final Dialect getDialect() {
+ return db.getDialect();
+ }
+
@Override
public final void execute() throws SQLException {
try (Connection readConnection = createReadUncommittedConnection();
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/SqlStatement.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/SqlStatement.java
index f9628f7c658..c15db0f90d6 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/SqlStatement.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/SqlStatement.java
@@ -26,6 +26,8 @@ import javax.annotation.Nullable;
public interface SqlStatement<CHILD extends SqlStatement> extends AutoCloseable {
CHILD setBoolean(int columnIndex, @Nullable Boolean value) throws SQLException;
+ CHILD setBytes(int columnIndex, @Nullable byte[] value) throws SQLException;
+
CHILD setDate(int columnIndex, @Nullable Date value) throws SQLException;
CHILD setDouble(int columnIndex, @Nullable Double value) throws SQLException;
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasures.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasures.java
new file mode 100644
index 00000000000..bc37773d96c
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasures.java
@@ -0,0 +1,125 @@
+/*
+ * 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.v70;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.sql.CreateTableBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder;
+import static org.sonar.server.platform.db.migration.def.BlobColumnDef.newBlobColumnDefBuilder;
+import static org.sonar.server.platform.db.migration.def.DecimalColumnDef.newDecimalColumnDefBuilder;
+import static org.sonar.server.platform.db.migration.def.IntegerColumnDef.newIntegerColumnDefBuilder;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class CreateTableLiveMeasures extends DdlChange {
+
+ private static final String TABLE_NAME = "live_measures";
+
+ public CreateTableLiveMeasures(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new CreateTableBuilder(getDialect(), TABLE_NAME)
+ .addPkColumn(newVarcharColumnDefBuilder()
+ .setColumnName("uuid")
+ .setIsNullable(false)
+ .setLimit(VarcharColumnDef.UUID_SIZE)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("project_uuid")
+ .setIsNullable(false)
+ .setLimit(VarcharColumnDef.UUID_VARCHAR_SIZE)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("component_uuid")
+ .setIsNullable(false)
+ .setLimit(VarcharColumnDef.UUID_VARCHAR_SIZE)
+ .build())
+ .addColumn(newIntegerColumnDefBuilder()
+ .setColumnName("metric_id")
+ .setIsNullable(false)
+ .build())
+ .addColumn(newDecimalColumnDefBuilder()
+ .setColumnName("value")
+ .setPrecision(38)
+ .setScale(20)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("text_value")
+ .setIsNullable(true)
+ .setLimit(4_000)
+ .build())
+ .addColumn(newDecimalColumnDefBuilder()
+ .setColumnName("variation")
+ .setPrecision(38)
+ .setScale(20)
+ .build())
+ .addColumn(newBlobColumnDefBuilder()
+ .setColumnName("measure_data")
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("update_marker")
+ .setIsNullable(true)
+ .setLimit(UUID_SIZE)
+ .build())
+ .addColumn(newBigIntegerColumnDefBuilder()
+ .setColumnName("created_at")
+ .setIsNullable(false)
+ .build())
+ .addColumn(newBigIntegerColumnDefBuilder()
+ .setColumnName("updated_at")
+ .setIsNullable(false)
+ .build())
+ .build());
+
+ context.execute(new CreateIndexBuilder(getDialect())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("project_uuid")
+ .setIsNullable(false)
+ .setLimit(VarcharColumnDef.UUID_VARCHAR_SIZE)
+ .build())
+ .setUnique(false)
+ .setTable(TABLE_NAME)
+ .setName("live_measures_project")
+ .build());
+
+ context.execute(new CreateIndexBuilder(getDialect())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("component_uuid")
+ .setIsNullable(false)
+ .setLimit(VarcharColumnDef.UUID_VARCHAR_SIZE)
+ .build())
+ .addColumn(newIntegerColumnDefBuilder()
+ .setColumnName("metric_id")
+ .setIsNullable(false)
+ .build())
+ .setUnique(true)
+ .setTable(TABLE_NAME)
+ .setName("live_measures_component")
+ .build());
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70.java
index f03ca93038b..e51e2426a93 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70.java
@@ -32,7 +32,11 @@ public class DbVersion70 implements DbVersion {
.add(1902, "Make QUALITY_GATES.IS_BUILT_IN not null", MakeQualityGatesIsBuiltInNotNullable.class)
.add(1903, "Remove quality gates loaded templates", RemoveQualityGateLoadedTemplates.class)
.add(1904, "Rename quality gate \"SonarQube way\" to \"Sonar way\"", RenameOldSonarQubeWayQualityGate.class)
- .add(1905, "Drop LOADED_TEMPLATES table", DropLoadedTemplatesTable.class);
+ .add(1905, "Drop LOADED_TEMPLATES table", DropLoadedTemplatesTable.class)
+ .add(1906, "Create table live_measures", CreateTableLiveMeasures.class)
+ .add(1907, "Populate table live_measures", PopulateLiveMeasures.class)
+ .add(1908, "Delete person and file measures", DeletePersonAndFileMeasures.class)
+ .add(1909, "Drop index on project_measures.person_id", DropIndexOnPersonMeasures.class)
+ ;
}
-
}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasures.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasures.java
new file mode 100644
index 00000000000..92ba449f7cd
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasures.java
@@ -0,0 +1,84 @@
+/*
+ * 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.v70;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.dialect.H2;
+import org.sonar.db.dialect.MsSql;
+import org.sonar.db.dialect.MySql;
+import org.sonar.db.dialect.Oracle;
+import org.sonar.db.dialect.PostgreSql;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.MassUpdate;
+
+public class DeletePersonAndFileMeasures extends DataChange {
+ public DeletePersonAndFileMeasures(Database db) {
+ super(db);
+ }
+
+ @Override
+ protected void execute(Context context) throws SQLException {
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate.select("select uuid from snapshots");
+ massUpdate.rowPluralName("snapshots");
+ massUpdate.update(getDeleteSql());
+
+ massUpdate.execute((row, update) -> {
+ update.setString(1, row.getString(1));
+ return true;
+ });
+ }
+
+ private String getDeleteSql() {
+ switch (getDialect().getId()) {
+ case MySql.ID:
+ case MsSql.ID:
+ return "delete pm from project_measures pm " +
+ "inner join projects c on c.uuid = pm.component_uuid " +
+ "where pm.analysis_uuid = ? " +
+ "and (c.qualifier in ('UTS', 'FIL') or pm.person_id is not null)";
+ case H2.ID:
+ return "delete from project_measures " +
+ "where id in ( " +
+ " select pm.id from project_measures pm " +
+ " inner join projects c on c.uuid = pm.component_uuid " +
+ " where pm.analysis_uuid = ? " +
+ " and (c.qualifier in ('UTS', 'FIL') or pm.person_id is not null) " +
+ ")";
+ case PostgreSql.ID:
+ return "delete from project_measures pm " +
+ "using projects c " +
+ "where pm.analysis_uuid = ? " +
+ "and c.uuid = pm.component_uuid " +
+ "and (c.qualifier in ('UTS', 'FIL') or pm.person_id is not null) ";
+ case Oracle.ID:
+ return "delete from project_measures pm where exists (" +
+ " select 1 from project_measures pm2 " +
+ " inner join projects c on c.uuid = pm2.component_uuid " +
+ " where pm2.analysis_uuid = ? " +
+ " and (c.qualifier in ('UTS', 'FIL') or pm.person_id is not null) " +
+ " and pm.id = pm2.id" +
+ ")";
+ default:
+ throw new IllegalStateException("Unsupported DB dialect: " + getDialect());
+ }
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasures.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasures.java
new file mode 100644
index 00000000000..c11e4e48c8b
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasures.java
@@ -0,0 +1,40 @@
+/*
+ * 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.v70;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.DropIndexBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class DropIndexOnPersonMeasures extends DdlChange {
+
+ public DropIndexOnPersonMeasures(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new DropIndexBuilder(getDialect())
+ .setTable("project_measures")
+ .setName("measures_person")
+ .build());
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasures.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasures.java
new file mode 100644
index 00000000000..1d226fca4f1
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasures.java
@@ -0,0 +1,72 @@
+/*
+ * 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.v70;
+
+import java.sql.SQLException;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.Uuids;
+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 PopulateLiveMeasures extends DataChange {
+
+ private final System2 system2;
+
+ public PopulateLiveMeasures(Database db, System2 system2) {
+ super(db);
+ this.system2 = system2;
+ }
+
+ @Override
+ protected void execute(Context context) throws SQLException {
+ long now = system2.now();
+ // reentrancy of migration
+ context.prepareUpsert("TRUNCATE TABLE live_measures").execute();
+
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate.select("SELECT p.uuid, p.project_uuid, pm.metric_id, pm.value, pm.text_value, pm.variation_value_1, pm.measure_data " +
+ "FROM project_measures pm " +
+ "INNER JOIN projects p on p.uuid = pm.component_uuid " +
+ "INNER JOIN snapshots s on s.uuid = pm.analysis_uuid " +
+ "WHERE s.islast = ?")
+ .setBoolean(1, true);
+
+ massUpdate.update("INSERT INTO live_measures "
+ + "(uuid, component_uuid, project_uuid, metric_id, value, text_value, variation, measure_data, created_at, updated_at) "
+ + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+
+ massUpdate.rowPluralName("live measures");
+ massUpdate.execute((row, update) -> {
+ update.setString(1, Uuids.create());
+ update.setString(2, row.getString(1));
+ update.setString(3, row.getString(2));
+ update.setInt(4, row.getInt(3));
+ update.setDouble(5, row.getNullableDouble(4));
+ update.setString(6, row.getString(5));
+ update.setDouble(7, row.getNullableDouble(6));
+ update.setBytes(8, row.getNullableBytes(7));
+ update.setLong(9, now);
+ update.setLong(10, now);
+ return true;
+ });
+ }
+
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasuresTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasuresTest.java
new file mode 100644
index 00000000000..806e0ea00e8
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasuresTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.v70;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CreateTableLiveMeasuresTest {
+ private static final String TABLE = "live_measures";
+
+ @Rule
+ public final CoreDbTester db = CoreDbTester.createForSchema(CreateTableLiveMeasuresTest.class, "empty.sql");
+
+ private CreateTableLiveMeasures underTest = new CreateTableLiveMeasures(db.database());
+
+ @Test
+ public void creates_table_on_empty_db() throws SQLException {
+ underTest.execute();
+
+ assertThat(db.countRowsOfTable(TABLE)).isEqualTo(0);
+
+ db.assertColumnDefinition(TABLE, "uuid", Types.VARCHAR, 40, false);
+ db.assertColumnDefinition(TABLE, "project_uuid", Types.VARCHAR, 50, false);
+ db.assertColumnDefinition(TABLE, "component_uuid", Types.VARCHAR, 50, false);
+ db.assertColumnDefinition(TABLE, "metric_id", Types.INTEGER, null, false);
+ db.assertColumnDefinition(TABLE, "value", Types.DOUBLE, null, true);
+ db.assertColumnDefinition(TABLE, "text_value", Types.VARCHAR, 4_000, true);
+ db.assertColumnDefinition(TABLE, "variation", Types.DOUBLE, null, true);
+ db.assertColumnDefinition(TABLE, "measure_data", Types.BLOB, null, true);
+ db.assertColumnDefinition(TABLE, "update_marker", Types.VARCHAR, 40, true);
+ db.assertColumnDefinition(TABLE, "created_at", Types.BIGINT, null, false);
+ db.assertColumnDefinition(TABLE, "updated_at", Types.BIGINT, null, false);
+
+ db.assertIndex(TABLE, "live_measures_project", "project_uuid");
+ db.assertUniqueIndex(TABLE, "live_measures_component", "component_uuid", "metric_id");
+ }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70Test.java
index ece11091b41..fa47fed02ed 100644
--- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70Test.java
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70Test.java
@@ -35,7 +35,7 @@ public class DbVersion70Test {
@Test
public void verify_migration_count() {
- verifyMigrationCount(underTest, 6);
+ verifyMigrationCount(underTest, 10);
}
}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasuresTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasuresTest.java
new file mode 100644
index 00000000000..2019003f8e0
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasuresTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.v70;
+
+import java.sql.SQLException;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.commons.lang.math.RandomUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DeletePersonAndFileMeasuresTest {
+ private static final AtomicInteger GENERATOR = new AtomicInteger();
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(DeletePersonAndFileMeasuresTest.class, "initial.sql");
+
+ private DataChange underTest = new DeletePersonAndFileMeasures(db.database());
+
+ @Test
+ public void delete_file_and_person_measures() throws SQLException {
+ insertComponent("P1", "PRJ", "TRK");
+ insertComponent("D1", "DIR", "DIR");
+ insertComponent("F1", "FIL", "FIL");
+ insertComponent("F2", "FIL", "UTS");
+ insertSnapshot("S1", "P1", false);
+ insertSnapshot("S2", "P1", true);
+ // past measures
+ long m1 = insertMeasure("P1", "S1");
+ long m2 = insertMeasure("D1", "S1");
+ long m3 = insertMeasure("F1", "S1");
+ long m4 = insertMeasure("F2", "S1");
+ long m5 = insertPersonMeasure("P1", "S1");
+ long m6 = insertPersonMeasure("F1", "S1");
+ // last measures
+ long m7 = insertMeasure("P1", "S2");
+ long m8 = insertMeasure("D1", "S2");
+ long m9 = insertMeasure("F1", "S2");
+ long m10 = insertMeasure("F2", "S2");
+ long m11 = insertPersonMeasure("P1", "S2");
+ long m12 = insertPersonMeasure("F1", "S2");
+
+ underTest.execute();
+
+ assertThat(db.countRowsOfTable("PROJECTS")).isEqualTo(4);
+ assertThat(db.countRowsOfTable("SNAPSHOTS")).isEqualTo(2);
+ assertThatMeasuresAreExactly(m1, m2, m7, m8);
+
+ // migration is re-entrant
+ underTest.execute();
+ assertThat(db.countRowsOfTable("PROJECTS")).isEqualTo(4);
+ assertThat(db.countRowsOfTable("SNAPSHOTS")).isEqualTo(2);
+ assertThatMeasuresAreExactly(m1, m2, m7, m8);
+ }
+
+ private void assertThatMeasuresAreExactly(long... expectedMeasureIds) {
+ long[] ids = db.select("select id as \"id\" from project_measures")
+ .stream()
+ .mapToLong(m -> (Long) m.get("id"))
+ .toArray();
+ assertThat(ids).containsOnly(expectedMeasureIds);
+ }
+
+ private void insertComponent(String uuid, String scope, String qualifier) {
+ db.executeInsert("PROJECTS",
+ "ORGANIZATION_UUID", "O1",
+ "KEE", "" + GENERATOR.incrementAndGet(),
+ "UUID", uuid,
+ "PROJECT_UUID", "" + GENERATOR.incrementAndGet(),
+ "MAIN_BRANCH_PROJECT_UUID", "" + GENERATOR.incrementAndGet(),
+ "UUID_PATH", ".",
+ "ROOT_UUID", "" + GENERATOR.incrementAndGet(),
+ "PRIVATE", "true",
+ "QUALIFIER", qualifier,
+ "SCOPE", scope);
+ }
+
+ private void insertSnapshot(String uuid, String projectUuid, boolean last) {
+ db.executeInsert("SNAPSHOTS",
+ "UUID", uuid,
+ "COMPONENT_UUID", projectUuid,
+ "STATUS", "P",
+ "ISLAST", last);
+ }
+
+ private long insertMeasure(String componentUuid, String analysisUuid) {
+ long id = GENERATOR.incrementAndGet();
+ db.executeInsert("PROJECT_MEASURES",
+ "ID", id,
+ "METRIC_ID", "42",
+ "COMPONENT_UUID", componentUuid,
+ "ANALYSIS_UUID", analysisUuid);
+ return id;
+ }
+
+ private long insertPersonMeasure(String componentUuid, String analysisUuid) {
+ long id = GENERATOR.incrementAndGet();
+ db.executeInsert("PROJECT_MEASURES",
+ "ID", id,
+ "METRIC_ID", "42",
+ "COMPONENT_UUID", componentUuid,
+ "ANALYSIS_UUID", analysisUuid,
+ "PERSON_ID", RandomUtils.nextInt(100));
+ return id;
+ }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasuresTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasuresTest.java
new file mode 100644
index 00000000000..08bf2079eec
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasuresTest.java
@@ -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.platform.db.migration.version.v70;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class DropIndexOnPersonMeasuresTest {
+
+ private static final String TABLE = "project_measures";
+ private static final String INDEX = "measures_person";
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(DropIndexOnPersonMeasuresTest.class, "initial.sql");
+
+ private DdlChange underTest = new DropIndexOnPersonMeasures(db.database());
+
+ @Test
+ public void drop_index() throws SQLException {
+ db.assertIndex(TABLE, INDEX, "person_id");
+
+ underTest.execute();
+
+ db.assertIndexDoesNotExist(TABLE, INDEX);
+ }
+}
+
+
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasuresTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasuresTest.java
new file mode 100644
index 00000000000..7a2fc7e9e2c
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasuresTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.v70;
+
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import org.assertj.core.groups.Tuple;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+
+public class PopulateLiveMeasuresTest {
+
+ private System2 system2 = new TestSystem2().setNow(1_500_000_000_000L);
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(PopulateLiveMeasuresTest.class, "initial.sql");
+
+ private PopulateLiveMeasures underTest = new PopulateLiveMeasures(db.database(), system2);
+
+ @Test
+ public void do_nothing_when_no_data() throws SQLException {
+ assertThat(db.countRowsOfTable("PROJECT_MEASURES")).isEqualTo(0);
+ underTest.execute();
+ assertThat(db.countRowsOfTable("LIVE_MEASURES")).isEqualTo(0);
+ }
+
+ @Test
+ public void execute_must_update_database() throws SQLException {
+ generateProjectMeasures();
+
+ underTest.execute();
+
+ assertThat(getLiveMeasures()).extracting(
+ field("COMPONENT_UUID"),
+ field("PROJECT_UUID"),
+ field("METRIC_ID"),
+ field("VALUE"),
+ field("TEXT_VALUE"),
+ field("VARIATION"),
+ field("MEASURE_DATA")
+ ).containsExactlyInAnyOrder(generateLiveMeasures());
+ }
+
+ private Function<Map<String, Object>, Object> field(String name) {
+ return m -> m.get(name);
+ }
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ generateProjectMeasures();
+
+ underTest.execute();
+ underTest.execute();
+
+ assertThat(getLiveMeasures()).extracting(
+ field("COMPONENT_UUID"),
+ field("PROJECT_UUID"),
+ field("METRIC_ID"),
+ field("VALUE"),
+ field("TEXT_VALUE"),
+ field("VARIATION"),
+ field("MEASURE_DATA")
+ ).containsExactlyInAnyOrder(generateLiveMeasures());
+ }
+
+ private void generateProjectMeasures() {
+ Map<String, Object> project = new HashMap<>();
+ project.put("UUID", "PRJ1");
+ project.put("ORGANIZATION_UUID", "ORG1");
+ project.put("UUID_PATH", "X");
+ project.put("ROOT_UUID", "X");
+ project.put("PROJECT_UUID", "PRJ1");
+ project.put("PRIVATE", "FALSE");
+ db.executeInsert("PROJECTS", project);
+
+ Map<String, Object> analysis1 = new HashMap<>();
+ analysis1.put("UUID", "A1");
+ analysis1.put("ISLAST", "FALSE");
+ analysis1.put("COMPONENT_UUID", "PRJ1");
+ db.executeInsert("SNAPSHOTS", analysis1);
+
+ Map<String, Object> analysis2 = new HashMap<>();
+ analysis2.put("UUID", "A2");
+ analysis2.put("ISLAST", "TRUE");
+ analysis2.put("COMPONENT_UUID", "PRJ1");
+ db.executeInsert("SNAPSHOTS", analysis2);
+
+ Map<String, Object> measure1 = new HashMap<>();
+ measure1.put("COMPONENT_UUID", "PRJ1");
+ measure1.put("ANALYSIS_UUID", "A1");
+ measure1.put("METRIC_ID", "123");
+ db.executeInsert("PROJECT_MEASURES", measure1);
+
+ Map<String, Object> measure2 = new HashMap<>();
+ measure2.put("COMPONENT_UUID", "PRJ1");
+ measure2.put("ANALYSIS_UUID", "A2");
+ measure2.put("METRIC_ID", "123");
+ measure2.put("VALUE", "234");
+ measure2.put("TEXT_VALUE", "TEXT_VALUEx");
+ measure2.put("VARIATION_VALUE_1", "345");
+ measure2.put("MEASURE_DATA", "FFFF");
+ db.executeInsert("PROJECT_MEASURES", measure2);
+ }
+
+ private List<Map<String, Object>> getLiveMeasures() {
+ return db.select("SELECT * FROM LIVE_MEASURES");
+ }
+
+ private Tuple[] generateLiveMeasures() {
+ return new Tuple[] {
+ tuple("PRJ1", "PRJ1", 123L, 234.0, "TEXT_VALUEx", 345.0, new byte[] {-1, -1})
+ };
+ }
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasuresTest/empty.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasuresTest/empty.sql
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/CreateTableLiveMeasuresTest/empty.sql
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasuresTest/initial.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasuresTest/initial.sql
new file mode 100644
index 00000000000..be55d6f14e8
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/DeletePersonAndFileMeasuresTest/initial.sql
@@ -0,0 +1,98 @@
+CREATE TABLE "PROJECTS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+ "KEE" VARCHAR(400),
+ "UUID" VARCHAR(50) NOT NULL,
+ "UUID_PATH" VARCHAR(1500) NOT NULL,
+ "ROOT_UUID" VARCHAR(50) NOT NULL,
+ "PROJECT_UUID" VARCHAR(50) NOT NULL,
+ "MODULE_UUID" VARCHAR(50),
+ "MODULE_UUID_PATH" VARCHAR(1500),
+ "MAIN_BRANCH_PROJECT_UUID" VARCHAR(50),
+ "NAME" VARCHAR(2000),
+ "DESCRIPTION" VARCHAR(2000),
+ "PRIVATE" BOOLEAN NOT NULL,
+ "TAGS" VARCHAR(500),
+ "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
+ "SCOPE" VARCHAR(3),
+ "QUALIFIER" VARCHAR(10),
+ "DEPRECATED_KEE" VARCHAR(400),
+ "PATH" VARCHAR(2000),
+ "LANGUAGE" VARCHAR(20),
+ "COPY_COMPONENT_UUID" VARCHAR(50),
+ "LONG_NAME" VARCHAR(2000),
+ "DEVELOPER_UUID" VARCHAR(50),
+ "CREATED_AT" TIMESTAMP,
+ "AUTHORIZATION_UPDATED_AT" BIGINT,
+ "B_CHANGED" BOOLEAN,
+ "B_COPY_COMPONENT_UUID" VARCHAR(50),
+ "B_DESCRIPTION" VARCHAR(2000),
+ "B_ENABLED" BOOLEAN,
+ "B_UUID_PATH" VARCHAR(1500),
+ "B_LANGUAGE" VARCHAR(20),
+ "B_LONG_NAME" VARCHAR(500),
+ "B_MODULE_UUID" VARCHAR(50),
+ "B_MODULE_UUID_PATH" VARCHAR(1500),
+ "B_NAME" VARCHAR(500),
+ "B_PATH" VARCHAR(2000),
+ "B_QUALIFIER" VARCHAR(10)
+);
+CREATE INDEX "PROJECTS_ORGANIZATION" ON "PROJECTS" ("ORGANIZATION_UUID");
+CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE");
+CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID");
+CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID");
+CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID");
+CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID");
+CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER");
+
+
+CREATE TABLE "SNAPSHOTS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "UUID" VARCHAR(50) NOT NULL,
+ "CREATED_AT" BIGINT,
+ "BUILD_DATE" BIGINT,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U',
+ "PURGE_STATUS" INTEGER,
+ "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
+ "VERSION" VARCHAR(500),
+ "PERIOD1_MODE" VARCHAR(100),
+ "PERIOD1_PARAM" VARCHAR(100),
+ "PERIOD1_DATE" BIGINT,
+ "PERIOD2_MODE" VARCHAR(100),
+ "PERIOD2_PARAM" VARCHAR(100),
+ "PERIOD2_DATE" BIGINT,
+ "PERIOD3_MODE" VARCHAR(100),
+ "PERIOD3_PARAM" VARCHAR(100),
+ "PERIOD3_DATE" BIGINT,
+ "PERIOD4_MODE" VARCHAR(100),
+ "PERIOD4_PARAM" VARCHAR(100),
+ "PERIOD4_DATE" BIGINT,
+ "PERIOD5_MODE" VARCHAR(100),
+ "PERIOD5_PARAM" VARCHAR(100),
+ "PERIOD5_DATE" BIGINT
+);
+CREATE INDEX "SNAPSHOT_COMPONENT" ON "SNAPSHOTS" ("COMPONENT_UUID");
+CREATE UNIQUE INDEX "ANALYSES_UUID" ON "SNAPSHOTS" ("UUID");
+
+
+CREATE TABLE "PROJECT_MEASURES" (
+ "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "VALUE" DOUBLE,
+ "METRIC_ID" INTEGER NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "PERSON_ID" INTEGER,
+ "VARIATION_VALUE_1" DOUBLE,
+ "VARIATION_VALUE_2" DOUBLE,
+ "VARIATION_VALUE_3" DOUBLE,
+ "VARIATION_VALUE_4" DOUBLE,
+ "VARIATION_VALUE_5" DOUBLE,
+ "MEASURE_DATA" BINARY
+);
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES" ("COMPONENT_UUID");
+CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES" ("ANALYSIS_UUID", "METRIC_ID");
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasuresTest/initial.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasuresTest/initial.sql
new file mode 100644
index 00000000000..00ef5e22307
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/DropIndexOnPersonMeasuresTest/initial.sql
@@ -0,0 +1,21 @@
+CREATE TABLE "PROJECT_MEASURES" (
+ "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "VALUE" DOUBLE,
+ "METRIC_ID" INTEGER NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "PERSON_ID" INTEGER,
+ "VARIATION_VALUE_1" DOUBLE,
+ "VARIATION_VALUE_2" DOUBLE,
+ "VARIATION_VALUE_3" DOUBLE,
+ "VARIATION_VALUE_4" DOUBLE,
+ "VARIATION_VALUE_5" DOUBLE,
+ "MEASURE_DATA" BINARY
+);
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES" ("COMPONENT_UUID");
+CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES" ("ANALYSIS_UUID", "METRIC_ID");
+CREATE INDEX "MEASURES_PERSON" ON "PROJECT_MEASURES" ("PERSON_ID");
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasuresTest/initial.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasuresTest/initial.sql
new file mode 100644
index 00000000000..b3dc4557dbb
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasuresTest/initial.sql
@@ -0,0 +1,116 @@
+CREATE TABLE "PROJECTS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+ "KEE" VARCHAR(400),
+ "UUID" VARCHAR(50) NOT NULL,
+ "UUID_PATH" VARCHAR(1500) NOT NULL,
+ "ROOT_UUID" VARCHAR(50) NOT NULL,
+ "PROJECT_UUID" VARCHAR(50) NOT NULL,
+ "MODULE_UUID" VARCHAR(50),
+ "MODULE_UUID_PATH" VARCHAR(1500),
+ "MAIN_BRANCH_PROJECT_UUID" VARCHAR(50),
+ "NAME" VARCHAR(2000),
+ "DESCRIPTION" VARCHAR(2000),
+ "PRIVATE" BOOLEAN NOT NULL,
+ "TAGS" VARCHAR(500),
+ "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
+ "SCOPE" VARCHAR(3),
+ "QUALIFIER" VARCHAR(10),
+ "DEPRECATED_KEE" VARCHAR(400),
+ "PATH" VARCHAR(2000),
+ "LANGUAGE" VARCHAR(20),
+ "COPY_COMPONENT_UUID" VARCHAR(50),
+ "LONG_NAME" VARCHAR(2000),
+ "DEVELOPER_UUID" VARCHAR(50),
+ "CREATED_AT" TIMESTAMP,
+ "AUTHORIZATION_UPDATED_AT" BIGINT,
+ "B_CHANGED" BOOLEAN,
+ "B_COPY_COMPONENT_UUID" VARCHAR(50),
+ "B_DESCRIPTION" VARCHAR(2000),
+ "B_ENABLED" BOOLEAN,
+ "B_UUID_PATH" VARCHAR(1500),
+ "B_LANGUAGE" VARCHAR(20),
+ "B_LONG_NAME" VARCHAR(500),
+ "B_MODULE_UUID" VARCHAR(50),
+ "B_MODULE_UUID_PATH" VARCHAR(1500),
+ "B_NAME" VARCHAR(500),
+ "B_PATH" VARCHAR(2000),
+ "B_QUALIFIER" VARCHAR(10)
+);
+CREATE INDEX "PROJECTS_ORGANIZATION" ON "PROJECTS" ("ORGANIZATION_UUID");
+CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE");
+CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID");
+CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID");
+CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID");
+CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID");
+CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER");
+
+CREATE TABLE "SNAPSHOTS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "UUID" VARCHAR(50) NOT NULL,
+ "CREATED_AT" BIGINT,
+ "BUILD_DATE" BIGINT,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U',
+ "PURGE_STATUS" INTEGER,
+ "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
+ "VERSION" VARCHAR(500),
+ "PERIOD1_MODE" VARCHAR(100),
+ "PERIOD1_PARAM" VARCHAR(100),
+ "PERIOD1_DATE" BIGINT,
+ "PERIOD2_MODE" VARCHAR(100),
+ "PERIOD2_PARAM" VARCHAR(100),
+ "PERIOD2_DATE" BIGINT,
+ "PERIOD3_MODE" VARCHAR(100),
+ "PERIOD3_PARAM" VARCHAR(100),
+ "PERIOD3_DATE" BIGINT,
+ "PERIOD4_MODE" VARCHAR(100),
+ "PERIOD4_PARAM" VARCHAR(100),
+ "PERIOD4_DATE" BIGINT,
+ "PERIOD5_MODE" VARCHAR(100),
+ "PERIOD5_PARAM" VARCHAR(100),
+ "PERIOD5_DATE" BIGINT
+);
+CREATE INDEX "SNAPSHOT_COMPONENT" ON "SNAPSHOTS" ("COMPONENT_UUID");
+CREATE UNIQUE INDEX "ANALYSES_UUID" ON "SNAPSHOTS" ("UUID");
+
+
+CREATE TABLE "LIVE_MEASURES" (
+ "UUID" VARCHAR(40) NOT NULL PRIMARY KEY,
+ "PROJECT_UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "METRIC_ID" INTEGER NOT NULL,
+ "VALUE" DOUBLE,
+ "TEXT_VALUE" VARCHAR(4000),
+ "VARIATION" DOUBLE,
+ "MEASURE_DATA" BINARY,
+ "UPDATE_MARKER" VARCHAR(40),
+ "CREATED_AT" BIGINT NOT NULL,
+ "UPDATED_AT" BIGINT NOT NULL
+);
+CREATE INDEX "LIVE_MEASURES_PROJECT" ON "LIVE_MEASURES" ("PROJECT_UUID");
+CREATE UNIQUE INDEX "LIVE_MEASURES_COMPONENT" ON "LIVE_MEASURES" ("COMPONENT_UUID", "METRIC_ID");
+
+
+CREATE TABLE "PROJECT_MEASURES" (
+ "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "VALUE" DOUBLE,
+ "METRIC_ID" INTEGER NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "PERSON_ID" INTEGER,
+ "VARIATION_VALUE_1" DOUBLE,
+ "VARIATION_VALUE_2" DOUBLE,
+ "VARIATION_VALUE_3" DOUBLE,
+ "VARIATION_VALUE_4" DOUBLE,
+ "VARIATION_VALUE_5" DOUBLE,
+ "MEASURE_DATA" BINARY
+);
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES" ("COMPONENT_UUID");
+CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES" ("ANALYSIS_UUID", "METRIC_ID");
+CREATE INDEX "MEASURES_PERSON" ON "PROJECT_MEASURES" ("PERSON_ID");
+
diff --git a/server/sonar-server/src/main/java/org/sonar/server/branch/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/branch/ws/ListAction.java
index d337d8ca5fd..65af52a7b87 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/branch/ws/ListAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/branch/ws/ListAction.java
@@ -31,14 +31,14 @@ import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.web.UserRole;
+import org.sonar.core.util.Protobuf;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.metric.MetricDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.issue.index.BranchStatistics;
import org.sonar.server.issue.index.IssueIndex;
@@ -97,13 +97,12 @@ public class ListAction implements BranchWsAction {
checkArgument(project.isEnabled() && PROJECT.equals(project.qualifier()), "Invalid project key");
Collection<BranchDto> branches = dbClient.branchDao().selectByComponent(dbSession, project);
- MetricDto qualityGateMetric = dbClient.metricDao().selectOrFailByKey(dbSession, ALERT_STATUS_KEY);
Map<String, BranchDto> mergeBranchesByUuid = dbClient.branchDao()
.selectByUuids(dbSession, branches.stream().map(BranchDto::getMergeBranchUuid).filter(Objects::nonNull).collect(toList()))
.stream().collect(uniqueIndex(BranchDto::getUuid));
- Map<String, MeasureDto> qualityGateMeasuresByComponentUuids = dbClient.measureDao()
- .selectByComponentsAndMetrics(dbSession, branches.stream().map(BranchDto::getUuid).collect(toList()), singletonList(qualityGateMetric.getId()))
- .stream().collect(uniqueIndex(MeasureDto::getComponentUuid));
+ Map<String, LiveMeasureDto> qualityGateMeasuresByComponentUuids = dbClient.liveMeasureDao()
+ .selectByComponentUuidsAndMetricKeys(dbSession, branches.stream().map(BranchDto::getUuid).collect(toList()), singletonList(ALERT_STATUS_KEY))
+ .stream().collect(uniqueIndex(LiveMeasureDto::getComponentUuid));
Map<String, BranchStatistics> branchStatisticsByBranchUuid = issueIndex.searchBranchStatistics(project.uuid(), branches.stream()
.filter(b -> b.getBranchType().equals(SHORT))
.map(BranchDto::getUuid).collect(toList()))
@@ -113,15 +112,14 @@ public class ListAction implements BranchWsAction {
.stream().collect(uniqueIndex(SnapshotDto::getComponentUuid, s -> formatDateTime(s.getCreatedAt())));
ProjectBranches.ListWsResponse.Builder protobufResponse = ProjectBranches.ListWsResponse.newBuilder();
- branches.stream()
- .forEach(b -> addBranch(protobufResponse, b, mergeBranchesByUuid, qualityGateMeasuresByComponentUuids.get(b.getUuid()), branchStatisticsByBranchUuid.get(b.getUuid()),
+ branches.forEach(b -> addBranch(protobufResponse, b, mergeBranchesByUuid, qualityGateMeasuresByComponentUuids.get(b.getUuid()), branchStatisticsByBranchUuid.get(b.getUuid()),
analysisDateByBranchUuid.get(b.getUuid())));
WsUtils.writeProtobuf(protobufResponse.build(), request, response);
}
}
private static void addBranch(ProjectBranches.ListWsResponse.Builder response, BranchDto branch, Map<String, BranchDto> mergeBranchesByUuid,
- @Nullable MeasureDto qualityGateMeasure, BranchStatistics branchStatistics, @Nullable String analysisDate) {
+ @Nullable LiveMeasureDto qualityGateMeasure, BranchStatistics branchStatistics, @Nullable String analysisDate) {
ProjectBranches.Branch.Builder builder = toBranchBuilder(branch, Optional.ofNullable(mergeBranchesByUuid.get(branch.getMergeBranchUuid())));
setBranchStatus(builder, branch, qualityGateMeasure, branchStatistics);
if (analysisDate != null) {
@@ -147,11 +145,11 @@ public class ListAction implements BranchWsAction {
return builder;
}
- private static void setBranchStatus(ProjectBranches.Branch.Builder builder, BranchDto branch, @Nullable MeasureDto qualityGateMeasure,
+ private static void setBranchStatus(ProjectBranches.Branch.Builder builder, BranchDto branch, @Nullable LiveMeasureDto qualityGateMeasure,
@Nullable BranchStatistics branchStatistics) {
ProjectBranches.Branch.Status.Builder statusBuilder = ProjectBranches.Branch.Status.newBuilder();
if (branch.getBranchType() == LONG && qualityGateMeasure != null) {
- statusBuilder.setQualityGateStatus(qualityGateMeasure.getData());
+ Protobuf.setNullable(qualityGateMeasure.getDataAsString(), statusBuilder::setQualityGateStatus);
}
if (branch.getBranchType() == BranchType.SHORT) {
statusBuilder.setBugs(branchStatistics == null ? 0L : branchStatistics.getBugs());
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/AppAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/AppAction.java
index 56d4f4aa89f..901da41760b 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/AppAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/AppAction.java
@@ -19,12 +19,10 @@
*/
package org.sonar.server.component.ws;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.lang.BooleanUtils;
@@ -37,8 +35,7 @@ import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.measure.MeasureQuery;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.property.PropertyDto;
import org.sonar.db.property.PropertyQuery;
@@ -46,6 +43,8 @@ import org.sonar.server.component.ComponentFinder;
import org.sonar.server.user.UserSession;
import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableList;
import static org.sonar.api.measures.CoreMetrics.COVERAGE;
import static org.sonar.api.measures.CoreMetrics.COVERAGE_KEY;
import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY;
@@ -66,12 +65,12 @@ public class AppAction implements ComponentsWsAction {
private static final String PARAM_COMPONENT_ID = "componentId";
private static final String PARAM_COMPONENT = "component";
- private static final List<String> METRIC_KEYS = ImmutableList.of(
+ private static final List<String> METRIC_KEYS = unmodifiableList(asList(
LINES_KEY,
VIOLATIONS_KEY,
COVERAGE_KEY,
DUPLICATED_LINES_DENSITY_KEY,
- TESTS_KEY);
+ TESTS_KEY));
private final DbClient dbClient;
@@ -121,7 +120,7 @@ public class AppAction implements ComponentsWsAction {
JsonWriter json = response.newJsonWriter();
json.beginObject();
- Map<String, MeasureDto> measuresByMetricKey = measuresByMetricKey(component, session);
+ Map<String, LiveMeasureDto> measuresByMetricKey = loadMeasuresGroupedByMetricKey(component, session);
appendComponent(json, component, userSession, session);
appendPermissions(json, userSession);
appendMeasures(json, measuresByMetricKey);
@@ -177,7 +176,7 @@ public class AppAction implements ComponentsWsAction {
json.prop("canMarkAsFavorite", userSession.isLoggedIn());
}
- private static void appendMeasures(JsonWriter json, Map<String, MeasureDto> measuresByMetricKey) {
+ private static void appendMeasures(JsonWriter json, Map<String, LiveMeasureDto> measuresByMetricKey) {
json.name("measures").beginObject();
json.prop("lines", formatMeasure(measuresByMetricKey, LINES));
json.prop("coverage", formatMeasure(measuresByMetricKey, COVERAGE));
@@ -187,12 +186,11 @@ public class AppAction implements ComponentsWsAction {
json.endObject();
}
- private Map<String, MeasureDto> measuresByMetricKey(ComponentDto component, DbSession session) {
- MeasureQuery query = MeasureQuery.builder().setComponentUuid(component.uuid()).setMetricKeys(METRIC_KEYS).build();
- List<MeasureDto> measures = dbClient.measureDao().selectByQuery(session, query);
- Set<Integer> metricIds = measures.stream().map(MeasureDto::getMetricId).collect(Collectors.toSet());
- List<MetricDto> metrics = dbClient.metricDao().selectByIds(session, metricIds);
+ private Map<String, LiveMeasureDto> loadMeasuresGroupedByMetricKey(ComponentDto component, DbSession dbSession) {
+ List<MetricDto> metrics = dbClient.metricDao().selectByKeys(dbSession, METRIC_KEYS);
Map<Integer, MetricDto> metricsById = Maps.uniqueIndex(metrics, MetricDto::getId);
+ List<LiveMeasureDto> measures = dbClient.liveMeasureDao()
+ .selectByComponentUuids(dbSession, Collections.singletonList(component.uuid()), metricsById.keySet());
return Maps.uniqueIndex(measures, m -> metricsById.get(m.getMetricId()).getKey());
}
@@ -205,12 +203,12 @@ public class AppAction implements ComponentsWsAction {
}
@CheckForNull
- private static String formatMeasure(Map<String, MeasureDto> measuresByMetricKey, Metric metric) {
- MeasureDto measure = measuresByMetricKey.get(metric.getKey());
+ private static String formatMeasure(Map<String, LiveMeasureDto> measuresByMetricKey, Metric metric) {
+ LiveMeasureDto measure = measuresByMetricKey.get(metric.getKey());
return formatMeasure(measure, metric);
}
- private static String formatMeasure(@Nullable MeasureDto measure, Metric metric) {
+ private static String formatMeasure(@Nullable LiveMeasureDto measure, Metric metric) {
if (measure == null) {
return null;
}
@@ -222,7 +220,7 @@ public class AppAction implements ComponentsWsAction {
}
@CheckForNull
- private static Double getDoubleValue(MeasureDto measure, Metric metric) {
+ private static Double getDoubleValue(LiveMeasureDto measure, Metric metric) {
Double value = measure.getValue();
if (BooleanUtils.isTrue(metric.isOptimizedBestValue()) && value == null) {
value = metric.getBestValue();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectCleaner.java b/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectCleaner.java
index 1def57fd52b..455bfbcb8c7 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectCleaner.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectCleaner.java
@@ -54,11 +54,11 @@ public class ProjectCleaner {
this.purgeListener = purgeListener;
}
- public ProjectCleaner purge(DbSession session, IdUuidPair idUuidPair, Configuration projectConfig, Collection<String> disabledComponentUuids) {
+ public ProjectCleaner purge(DbSession session, IdUuidPair rootId, Configuration projectConfig, Collection<String> disabledComponentUuids) {
long start = System.currentTimeMillis();
profiler.reset();
- PurgeConfiguration configuration = newDefaultPurgeConfiguration(projectConfig, idUuidPair, disabledComponentUuids);
+ PurgeConfiguration configuration = newDefaultPurgeConfiguration(projectConfig, rootId, disabledComponentUuids);
periodCleaner.clean(session, configuration.rootProjectIdUuid().getUuid(), projectConfig);
purgeDao.purge(session, configuration, purgeListener, profiler);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/BestValueOptimization.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/BestValueOptimization.java
index bce3c7c57a7..52f30c83cb1 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/BestValueOptimization.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/BestValueOptimization.java
@@ -19,8 +19,7 @@
*/
package org.sonar.server.computation.task.projectanalysis.measure;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
+import java.util.function.Predicate;
import javax.annotation.Nonnull;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.metric.Metric;
@@ -40,7 +39,7 @@ public class BestValueOptimization implements Predicate<Measure> {
if (isBestValueOptimized(metric) && isBestValueOptimized(component)) {
return new BestValueOptimization(metric);
}
- return Predicates.alwaysFalse();
+ return x -> false;
}
private static boolean isBestValueOptimized(Metric metric) {
@@ -52,7 +51,7 @@ public class BestValueOptimization implements Predicate<Measure> {
}
@Override
- public boolean apply(@Nonnull Measure measure) {
+ public boolean test(@Nonnull Measure measure) {
return isBestValueOptimized(measure);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MapBasedRawMeasureRepository.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MapBasedRawMeasureRepository.java
index 751a962bf20..8410b834599 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MapBasedRawMeasureRepository.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MapBasedRawMeasureRepository.java
@@ -24,7 +24,6 @@ import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.SetMultimap;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -61,11 +60,6 @@ public final class MapBasedRawMeasureRepository<T> implements MeasureRepository
}
@Override
- public int loadAsRawMeasures(Collection<Component> components, Collection<Metric> metrics) {
- throw new UnsupportedOperationException("This implementation of MeasureRepository supports only raw measures");
- }
-
- @Override
public Optional<Measure> getRawMeasure(final Component component, final Metric metric) {
// fail fast
requireNonNull(component);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepository.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepository.java
index ecc86ce8c5e..c5acb1d03c2 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepository.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepository.java
@@ -19,16 +19,13 @@
*/
package org.sonar.server.computation.task.projectanalysis.measure;
-import java.util.Collection;
+import com.google.common.base.Optional;
+import com.google.common.collect.SetMultimap;
import java.util.Set;
-
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.metric.Metric;
import org.sonar.server.computation.task.projectanalysis.metric.MetricImpl;
-import com.google.common.base.Optional;
-import com.google.common.collect.SetMultimap;
-
public interface MeasureRepository {
/**
@@ -43,8 +40,6 @@ public interface MeasureRepository {
*/
Optional<Measure> getBaseMeasure(Component component, Metric metric);
- int loadAsRawMeasures(Collection<Component> components, Collection<Metric> metrics);
-
/**
* Retrieves the measure created during the current analysis for the specified {@link Component} for the specified
* {@link Metric} if it exists (ie. one created by the Compute Engine or the Batch) and which is <strong>not</strong>
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryImpl.java
index 9a0942003b3..5755fb91cde 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryImpl.java
@@ -19,21 +19,14 @@
*/
package org.sonar.server.computation.task.projectanalysis.measure;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.server.computation.task.projectanalysis.component.ComponentFunctions.toReportRef;
-
-import java.util.Collection;
+import com.google.common.base.Optional;
+import com.google.common.collect.SetMultimap;
import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
-
import org.sonar.core.util.CloseableIterator;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.measure.MeasureQuery;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader;
import org.sonar.server.computation.task.projectanalysis.component.Component;
@@ -42,8 +35,8 @@ import org.sonar.server.computation.task.projectanalysis.metric.Metric;
import org.sonar.server.computation.task.projectanalysis.metric.MetricRepository;
import org.sonar.server.computation.task.projectanalysis.metric.ReportMetricValidator;
-import com.google.common.base.Optional;
-import com.google.common.collect.SetMultimap;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.server.computation.task.projectanalysis.component.ComponentFunctions.toReportRef;
public class MeasureRepositoryImpl implements MeasureRepository {
private final MapBasedRawMeasureRepository<Integer> delegate = new MapBasedRawMeasureRepository<>(toReportRef());
@@ -72,8 +65,7 @@ public class MeasureRepositoryImpl implements MeasureRepository {
requireNonNull(metric);
try (DbSession dbSession = dbClient.openSession(false)) {
- MeasureQuery query = MeasureQuery.builder().setComponentUuid(component.getUuid()).setMetricKey(metric.getKey()).build();
- java.util.Optional<MeasureDto> measureDto = dbClient.measureDao().selectSingle(dbSession, query);
+ java.util.Optional<MeasureDto> measureDto = dbClient.measureDao().selectLastMeasure(dbSession, component.getUuid(), metric.getKey());
if (measureDto.isPresent()) {
return measureTransformer.toMeasure(measureDto.get(), metric);
}
@@ -82,32 +74,6 @@ public class MeasureRepositoryImpl implements MeasureRepository {
}
@Override
- public int loadAsRawMeasures(Collection<Component> components, Collection<Metric> metrics) {
- requireNonNull(components);
- requireNonNull(metrics);
-
- Map<String, Component> componentsByUuid = components.stream()
- .collect(Collectors.toMap(Component::getUuid, c -> c));
- Map<Integer, Metric> metricsById = metrics.stream()
- .collect(Collectors.toMap(Metric::getId, m -> m));
-
- List<MeasureDto> measuresDto;
- try (DbSession dbSession = dbClient.openSession(false)) {
- measuresDto = dbClient.measureDao().selectByComponentsAndMetrics(dbSession, componentsByUuid.keySet(), metricsById.keySet());
- }
-
- for (MeasureDto dto : measuresDto) {
-
- Metric metric = metricsById.get(dto.getMetricId());
- Component component = componentsByUuid.get(dto.getComponentUuid());
- Measure measure = measureTransformer.toMeasure(dto, metric).get();
-
- delegate.add(component, metric, measure);
- }
- return measuresDto.size();
- }
-
- @Override
public Optional<Measure> getRawMeasure(Component component, Metric metric) {
Optional<Measure> local = delegate.getRawMeasure(component, metric);
if (local.isPresent()) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureToMeasureDto.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureToMeasureDto.java
index cc1935fe7b2..1970b18db37 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureToMeasureDto.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureToMeasureDto.java
@@ -20,25 +20,23 @@
package org.sonar.server.computation.task.projectanalysis.measure;
import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.measure.MeasureDto;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.server.computation.task.projectanalysis.component.Component;
-import org.sonar.server.computation.task.projectanalysis.component.DbIdsRepository;
-import org.sonar.server.computation.task.projectanalysis.component.Developer;
+import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
import org.sonar.server.computation.task.projectanalysis.metric.Metric;
public class MeasureToMeasureDto {
- private final DbIdsRepository dbIdsRepository;
private final AnalysisMetadataHolder analysisMetadataHolder;
+ private final TreeRootHolder treeRootHolder;
- public MeasureToMeasureDto(DbIdsRepository dbIdsRepository, AnalysisMetadataHolder analysisMetadataHolder) {
- this.dbIdsRepository = dbIdsRepository;
+ public MeasureToMeasureDto(AnalysisMetadataHolder analysisMetadataHolder, TreeRootHolder treeRootHolder) {
this.analysisMetadataHolder = analysisMetadataHolder;
+ this.treeRootHolder = treeRootHolder;
}
- @Nonnull
public MeasureDto toMeasureDto(Measure measure, Metric metric, Component component) {
MeasureDto out = new MeasureDto();
out.setMetricId(metric.getId());
@@ -50,9 +48,18 @@ public class MeasureToMeasureDto {
if (measure.hasQualityGateStatus()) {
setAlert(out, measure.getQualityGateStatus());
}
- Developer developer = measure.getDeveloper();
- if (developer != null) {
- out.setDeveloperId(dbIdsRepository.getDeveloperId(developer));
+ out.setValue(valueAsDouble(measure));
+ out.setData(data(measure));
+ return out;
+ }
+
+ public LiveMeasureDto toLiveMeasureDto(Measure measure, Metric metric, Component component) {
+ LiveMeasureDto out = new LiveMeasureDto();
+ out.setMetricId(metric.getId());
+ out.setComponentUuid(component.getUuid());
+ out.setProjectUuid(treeRootHolder.getRoot().getUuid());
+ if (measure.hasVariation()) {
+ out.setVariation(measure.getVariation());
}
out.setValue(valueAsDouble(measure));
out.setData(data(measure));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistLiveMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistLiveMeasuresStep.java
new file mode 100644
index 00000000000..507f152f347
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistLiveMeasuresStep.java
@@ -0,0 +1,133 @@
+/*
+ * 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.computation.task.projectanalysis.step;
+
+import com.google.common.collect.Multimap;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import javax.annotation.Nonnull;
+import org.sonar.core.util.Uuids;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.measure.LiveMeasureDao;
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
+import org.sonar.server.computation.task.projectanalysis.component.DepthTraversalTypeAwareCrawler;
+import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
+import org.sonar.server.computation.task.projectanalysis.component.TypeAwareVisitorAdapter;
+import org.sonar.server.computation.task.projectanalysis.measure.BestValueOptimization;
+import org.sonar.server.computation.task.projectanalysis.measure.Measure;
+import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepository;
+import org.sonar.server.computation.task.projectanalysis.measure.MeasureToMeasureDto;
+import org.sonar.server.computation.task.projectanalysis.metric.Metric;
+import org.sonar.server.computation.task.projectanalysis.metric.MetricRepository;
+import org.sonar.server.computation.task.step.ComputationStep;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableSet;
+import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION_KEY;
+import static org.sonar.api.measures.CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION_KEY;
+import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY;
+import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER;
+
+public class PersistLiveMeasuresStep implements ComputationStep {
+
+ /**
+ * List of metrics that should not be persisted on file measure.
+ */
+ private static final Set<String> NOT_TO_PERSIST_ON_FILE_METRIC_KEYS = unmodifiableSet(new HashSet<>(asList(
+ FILE_COMPLEXITY_DISTRIBUTION_KEY,
+ FUNCTION_COMPLEXITY_DISTRIBUTION_KEY,
+ CLASS_COMPLEXITY_DISTRIBUTION_KEY)));
+
+ private final DbClient dbClient;
+ private final MetricRepository metricRepository;
+ private final MeasureToMeasureDto measureToMeasureDto;
+ private final TreeRootHolder treeRootHolder;
+ private final MeasureRepository measureRepository;
+
+ public PersistLiveMeasuresStep(DbClient dbClient, MetricRepository metricRepository, MeasureToMeasureDto measureToMeasureDto,
+ TreeRootHolder treeRootHolder, MeasureRepository measureRepository) {
+ this.dbClient = dbClient;
+ this.metricRepository = metricRepository;
+ this.measureToMeasureDto = measureToMeasureDto;
+ this.treeRootHolder = treeRootHolder;
+ this.measureRepository = measureRepository;
+ }
+
+ @Override
+ public String getDescription() {
+ return "Persist live measures";
+ }
+
+ @Override
+ public void execute() {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ String marker = Uuids.create();
+ Component root = treeRootHolder.getRoot();
+ new DepthTraversalTypeAwareCrawler(new MeasureVisitor(dbSession, marker)).visit(root);
+ dbClient.liveMeasureDao().deleteByProjectUuidExcludingMarker(dbSession, root.getUuid(), marker);
+ dbSession.commit();
+ }
+ }
+
+ private class MeasureVisitor extends TypeAwareVisitorAdapter {
+ private final DbSession dbSession;
+ private final String marker;
+
+ private MeasureVisitor(DbSession dbSession, String marker) {
+ super(CrawlerDepthLimit.LEAVES, PRE_ORDER);
+ this.dbSession = dbSession;
+ this.marker = marker;
+ }
+
+ @Override
+ public void visitAny(Component component) {
+ LiveMeasureDao dao = dbClient.liveMeasureDao();
+ Multimap<String, Measure> measures = measureRepository.getRawMeasures(component);
+ for (Map.Entry<String, Collection<Measure>> measuresByMetricKey : measures.asMap().entrySet()) {
+ String metricKey = measuresByMetricKey.getKey();
+ if (NOT_TO_PERSIST_ON_FILE_METRIC_KEYS.contains(metricKey) && component.getType() == Component.Type.FILE) {
+ continue;
+ }
+ Metric metric = metricRepository.getByKey(metricKey);
+ Predicate<Measure> notBestValueOptimized = BestValueOptimization.from(metric, component).negate();
+ measuresByMetricKey.getValue().stream()
+ .filter(NonEmptyMeasure.INSTANCE)
+ .filter(notBestValueOptimized)
+ .map(measure -> measureToMeasureDto.toLiveMeasureDto(measure, metric, component))
+ .forEach(dto -> dao.insertOrUpdate(dbSession, dto, marker));
+ }
+ }
+ }
+
+ private enum NonEmptyMeasure implements Predicate<Measure> {
+ INSTANCE;
+
+ @Override
+ public boolean test(@Nonnull Measure input) {
+ return input.getValueType() != Measure.ValueType.NO_VALUE || input.hasVariation() || input.getData() != null;
+ }
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStep.java
index 69d10747645..6c9f03a5427 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStep.java
@@ -19,24 +19,23 @@
*/
package org.sonar.server.computation.task.projectanalysis.step;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Multimap;
import java.util.Collection;
-import java.util.List;
import java.util.Map;
+import java.util.function.Predicate;
import javax.annotation.Nonnull;
+import org.sonar.core.config.PurgeConstants;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.measure.MeasureDao;
import org.sonar.db.measure.MeasureDto;
import org.sonar.server.computation.task.projectanalysis.component.Component;
+import org.sonar.server.computation.task.projectanalysis.component.ConfigurationRepository;
import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
import org.sonar.server.computation.task.projectanalysis.component.DepthTraversalTypeAwareCrawler;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
import org.sonar.server.computation.task.projectanalysis.component.TypeAwareVisitorAdapter;
-import org.sonar.server.computation.task.projectanalysis.measure.BestValueOptimization;
import org.sonar.server.computation.task.projectanalysis.measure.Measure;
import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepository;
import org.sonar.server.computation.task.projectanalysis.measure.MeasureToMeasureDto;
@@ -44,35 +43,32 @@ import org.sonar.server.computation.task.projectanalysis.metric.Metric;
import org.sonar.server.computation.task.projectanalysis.metric.MetricRepository;
import org.sonar.server.computation.task.step.ComputationStep;
-import static com.google.common.collect.FluentIterable.from;
-import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION_KEY;
-import static org.sonar.api.measures.CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION_KEY;
-import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY;
import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER;
public class PersistMeasuresStep implements ComputationStep {
- /**
- * List of metrics that should not be persisted on file measure (Waiting for SONAR-6688 to be implemented)
- */
- private static final List<String> NOT_TO_PERSIST_ON_FILE_METRIC_KEYS = ImmutableList.of(
- FILE_COMPLEXITY_DISTRIBUTION_KEY,
- FUNCTION_COMPLEXITY_DISTRIBUTION_KEY,
- CLASS_COMPLEXITY_DISTRIBUTION_KEY);
-
private final DbClient dbClient;
private final MetricRepository metricRepository;
private final MeasureToMeasureDto measureToMeasureDto;
private final TreeRootHolder treeRootHolder;
private final MeasureRepository measureRepository;
+ private final boolean persistDirectories;
public PersistMeasuresStep(DbClient dbClient, MetricRepository metricRepository, MeasureToMeasureDto measureToMeasureDto,
- TreeRootHolder treeRootHolder, MeasureRepository measureRepository) {
+ TreeRootHolder treeRootHolder, MeasureRepository measureRepository, ConfigurationRepository settings) {
+ this(dbClient, metricRepository, measureToMeasureDto, treeRootHolder,measureRepository,
+ !settings.getConfiguration().getBoolean(PurgeConstants.PROPERTY_CLEAN_DIRECTORY).orElseThrow(() -> new IllegalStateException("Missing default value")));
+ }
+
+ @VisibleForTesting
+ PersistMeasuresStep(DbClient dbClient, MetricRepository metricRepository, MeasureToMeasureDto measureToMeasureDto, TreeRootHolder treeRootHolder,
+ MeasureRepository measureRepository, boolean persistDirectories) {
this.dbClient = dbClient;
this.metricRepository = metricRepository;
this.measureToMeasureDto = measureToMeasureDto;
this.treeRootHolder = treeRootHolder;
this.measureRepository = measureRepository;
+ this.persistDirectories = persistDirectories;
}
@Override
@@ -97,25 +93,47 @@ public class PersistMeasuresStep implements ComputationStep {
}
@Override
- public void visitAny(Component component) {
- Multimap<String, Measure> measures = measureRepository.getRawMeasures(component);
- persistMeasures(component, measures);
+ public void visitProject(Component project) {
+ persistMeasures(project);
+ }
+
+ @Override
+ public void visitModule(Component module) {
+ persistMeasures(module);
+ }
+
+ @Override
+ public void visitDirectory(Component directory) {
+ if (persistDirectories) {
+ persistMeasures(directory);
+ }
+ }
+
+ @Override
+ public void visitView(Component view) {
+ persistMeasures(view);
+ }
+
+ @Override
+ public void visitSubView(Component subView) {
+ persistMeasures(subView);
}
- private void persistMeasures(Component component, Multimap<String, Measure> batchReportMeasures) {
- for (Map.Entry<String, Collection<Measure>> measures : batchReportMeasures.asMap().entrySet()) {
- String metricKey = measures.getKey();
- if (NOT_TO_PERSIST_ON_FILE_METRIC_KEYS.contains(metricKey) && component.getType() == Component.Type.FILE) {
- continue;
- }
+ @Override
+ public void visitProjectView(Component projectView) {
+ persistMeasures(projectView);
+ }
+ private void persistMeasures(Component component) {
+ Multimap<String, Measure> measures = measureRepository.getRawMeasures(component);
+ for (Map.Entry<String, Collection<Measure>> measuresByMetricKey : measures.asMap().entrySet()) {
+ String metricKey = measuresByMetricKey.getKey();
Metric metric = metricRepository.getByKey(metricKey);
- Predicate<Measure> notBestValueOptimized = Predicates.not(BestValueOptimization.from(metric, component));
MeasureDao measureDao = dbClient.measureDao();
- for (Measure measure : from(measures.getValue()).filter(NonEmptyMeasure.INSTANCE).filter(notBestValueOptimized)) {
+ measuresByMetricKey.getValue().stream().filter(NonEmptyMeasure.INSTANCE).forEach(measure -> {
MeasureDto measureDto = measureToMeasureDto.toMeasureDto(measure, metric, component);
measureDao.insert(session, measureDto);
- }
+ });
}
}
@@ -125,7 +143,7 @@ public class PersistMeasuresStep implements ComputationStep {
INSTANCE;
@Override
- public boolean apply(@Nonnull Measure input) {
+ public boolean test(@Nonnull Measure input) {
return input.getValueType() != Measure.ValueType.NO_VALUE || input.hasVariation() || input.getData() != null;
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java
index 108ca3b9d84..d9b4a87e366 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java
@@ -88,6 +88,7 @@ public class ReportComputationSteps extends AbstractComputationSteps {
PersistAnalysisStep.class,
PersistAnalysisPropertiesStep.class,
PersistMeasuresStep.class,
+ PersistLiveMeasuresStep.class,
PersistIssuesStep.class,
PersistProjectLinksStep.class,
PersistEventsStep.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/duplication/ws/ShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/duplication/ws/ShowAction.java
index 73b428f2345..6136a64d95f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/duplication/ws/ShowAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/duplication/ws/ShowAction.java
@@ -30,8 +30,7 @@ import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.measure.MeasureQuery;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.user.UserSession;
@@ -110,12 +109,8 @@ public class ShowAction implements DuplicationsWsAction {
@CheckForNull
private String findDataFromComponent(DbSession dbSession, ComponentDto component) {
- MeasureQuery query = MeasureQuery.builder()
- .setComponentUuid(component.uuid())
- .setMetricKey(CoreMetrics.DUPLICATIONS_DATA_KEY)
- .build();
- return dbClient.measureDao().selectSingle(dbSession, query)
- .map(MeasureDto::getData)
+ return dbClient.liveMeasureDao().selectMeasure(dbSession, component.uuid(), CoreMetrics.DUPLICATIONS_DATA_KEY)
+ .map(LiveMeasureDto::getDataAsString)
.orElse(null);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentAction.java
index 59633ac3d74..37fbe9a40f2 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentAction.java
@@ -43,25 +43,22 @@ import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.measure.MeasureQuery;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.metric.MetricDtoFunctions;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.measure.ws.MetricDtoWithBestValue.MetricDtoToMetricDtoWithBestValueFunction;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Measures;
import org.sonarqube.ws.Measures.ComponentWsResponse;
import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
-import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
+import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
import static org.sonar.server.component.ComponentFinder.ParamNames.COMPONENT_ID_AND_COMPONENT;
-import static org.sonar.server.component.ComponentFinder.ParamNames.DEVELOPER_ID_AND_KEY;
import static org.sonar.server.measure.ws.ComponentDtoToWsComponent.componentDtoToWsComponent;
import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createAdditionalFieldsParameter;
import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createDeveloperParameters;
@@ -133,6 +130,10 @@ public class ComponentAction implements MeasuresWsAction {
@Override
public void handle(Request request, Response response) throws Exception {
+ if (request.param(PARAM_DEVELOPER_ID) != null || request.param(PARAM_DEVELOPER_KEY) != null) {
+ throw new NotFoundException("The Developer Cockpit feature has been dropped. The specified developer cannot be found.");
+ }
+
ComponentWsResponse componentWsResponse = doHandle(toComponentWsRequest(request));
writeProtobuf(componentWsResponse, request, response);
}
@@ -140,13 +141,12 @@ public class ComponentAction implements MeasuresWsAction {
private ComponentWsResponse doHandle(ComponentRequest request) {
try (DbSession dbSession = dbClient.openSession(false)) {
ComponentDto component = loadComponent(dbSession, request);
- Long developerId = searchDeveloperId(dbSession, request);
Optional<ComponentDto> refComponent = getReferenceComponent(dbSession, component);
checkPermissions(component);
SnapshotDto analysis = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, component.projectUuid()).orElse(null);
List<MetricDto> metrics = searchMetrics(dbSession, request);
List<Measures.Period> periods = snapshotToWsPeriods(analysis);
- List<MeasureDto> measures = searchMeasures(dbSession, component, analysis, metrics, developerId);
+ List<LiveMeasureDto> measures = searchMeasures(dbSession, component, metrics);
return buildResponse(request, component, refComponent, measures, metrics, periods);
}
@@ -162,15 +162,6 @@ public class ComponentAction implements MeasuresWsAction {
: componentFinder.getByKeyAndBranch(dbSession, componentKey, branch);
}
- @CheckForNull
- private Long searchDeveloperId(DbSession dbSession, ComponentRequest request) {
- if (request.getDeveloperId() == null && request.getDeveloperKey() == null) {
- return null;
- }
-
- return componentFinder.getByUuidOrKey(dbSession, request.getDeveloperId(), request.getDeveloperKey(), DEVELOPER_ID_AND_KEY).getId();
- }
-
private Optional<ComponentDto> getReferenceComponent(DbSession dbSession, ComponentDto component) {
if (component.getCopyResourceUuid() == null) {
return Optional.absent();
@@ -179,12 +170,12 @@ public class ComponentAction implements MeasuresWsAction {
return dbClient.componentDao().selectByUuid(dbSession, component.getCopyResourceUuid());
}
- private static ComponentWsResponse buildResponse(ComponentRequest request, ComponentDto component, Optional<ComponentDto> refComponent, List<MeasureDto> measures,
+ private static ComponentWsResponse buildResponse(ComponentRequest request, ComponentDto component, Optional<ComponentDto> refComponent, List<LiveMeasureDto> measures,
List<MetricDto> metrics, List<Measures.Period> periods) {
ComponentWsResponse.Builder response = ComponentWsResponse.newBuilder();
Map<Integer, MetricDto> metricsById = Maps.uniqueIndex(metrics, MetricDto::getId);
- Map<MetricDto, MeasureDto> measuresByMetric = new HashMap<>();
- for (MeasureDto measure : measures) {
+ Map<MetricDto, LiveMeasureDto> measuresByMetric = new HashMap<>();
+ for (LiveMeasureDto measure : measures) {
MetricDto metric = metricsById.get(measure.getMetricId());
measuresByMetric.put(metric, measure);
}
@@ -223,20 +214,10 @@ public class ComponentAction implements MeasuresWsAction {
return metrics;
}
- private List<MeasureDto> searchMeasures(DbSession dbSession, ComponentDto component, @Nullable SnapshotDto analysis, List<MetricDto> metrics, @Nullable Long developerId) {
- if (analysis == null) {
- return emptyList();
- }
-
+ private List<LiveMeasureDto> searchMeasures(DbSession dbSession, ComponentDto component, List<MetricDto> metrics) {
List<Integer> metricIds = Lists.transform(metrics, MetricDto::getId);
- MeasureQuery query = MeasureQuery.builder()
- .setPersonId(developerId)
- .setMetricIds(metricIds)
- .setComponentUuid(component.uuid())
- .build();
- List<MeasureDto> measures = dbClient.measureDao().selectByQuery(dbSession, query);
+ List<LiveMeasureDto> measures = dbClient.liveMeasureDao().selectByComponentUuids(dbSession, singletonList(component.uuid()), metricIds);
addBestValuesToMeasures(measures, component, metrics);
-
return measures;
}
@@ -247,16 +228,16 @@ public class ComponentAction implements MeasuresWsAction {
* <li>metric is optimized for best value</li>
* </ul>
*/
- private static void addBestValuesToMeasures(List<MeasureDto> measures, ComponentDto component, List<MetricDto> metrics) {
+ private static void addBestValuesToMeasures(List<LiveMeasureDto> measures, ComponentDto component, List<MetricDto> metrics) {
if (!QUALIFIERS_ELIGIBLE_FOR_BEST_VALUE.contains(component.qualifier())) {
return;
}
List<MetricDtoWithBestValue> metricWithBestValueList = metrics.stream()
.filter(MetricDtoFunctions.isOptimizedForBestValue())
- .map(new MetricDtoToMetricDtoWithBestValueFunction())
+ .map(MetricDtoWithBestValue::new)
.collect(MoreCollectors.toList(metrics.size()));
- Map<Integer, MeasureDto> measuresByMetricId = Maps.uniqueIndex(measures, MeasureDto::getMetricId);
+ Map<Integer, LiveMeasureDto> measuresByMetricId = Maps.uniqueIndex(measures, LiveMeasureDto::getMetricId);
for (MetricDtoWithBestValue metricWithBestValue : metricWithBestValueList) {
if (measuresByMetricId.get(metricWithBestValue.getMetric().getId()) == null) {
@@ -271,9 +252,7 @@ public class ComponentAction implements MeasuresWsAction {
.setComponent(request.param(PARAM_COMPONENT))
.setBranch(request.param(PARAM_BRANCH))
.setAdditionalFields(request.paramAsStrings(PARAM_ADDITIONAL_FIELDS))
- .setMetricKeys(request.mandatoryParamAsStrings(PARAM_METRIC_KEYS))
- .setDeveloperId(request.param(PARAM_DEVELOPER_ID))
- .setDeveloperKey(request.param(PARAM_DEVELOPER_KEY));
+ .setMetricKeys(request.mandatoryParamAsStrings(PARAM_METRIC_KEYS));
checkRequest(!componentRequest.getMetricKeys().isEmpty(), "At least one metric key must be provided");
return componentRequest;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java
index 959d707acdf..66470ef3f8c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java
@@ -22,7 +22,7 @@ package org.sonar.server.measure.ws;
import java.util.Map;
import org.sonar.core.util.Protobuf;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonarqube.ws.Measures;
import org.sonarqube.ws.Measures.Component;
@@ -32,7 +32,7 @@ class ComponentDtoToWsComponent {
// static methods only
}
- static Component.Builder componentDtoToWsComponent(ComponentDto component, Map<MetricDto, MeasureDto> measuresByMetric,
+ static Component.Builder componentDtoToWsComponent(ComponentDto component, Map<MetricDto, LiveMeasureDto> measuresByMetric,
Map<String, ComponentDto> referenceComponentsByUuid) {
Component.Builder wsComponent = componentDtoToWsComponent(component);
@@ -43,7 +43,7 @@ class ComponentDtoToWsComponent {
}
Measures.Measure.Builder measureBuilder = Measures.Measure.newBuilder();
- for (Map.Entry<MetricDto, MeasureDto> entry : measuresByMetric.entrySet()) {
+ for (Map.Entry<MetricDto, LiveMeasureDto> entry : measuresByMetric.entrySet()) {
MeasureDtoToWsMeasure.updateMeasureBuilder(measureBuilder, entry.getKey(), entry.getValue());
wsComponent.addMeasures(measureBuilder);
measureBuilder.clear();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java
index e47c71bb1a6..4a1b94aa3e7 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java
@@ -61,7 +61,7 @@ import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTreeQuery;
import org.sonar.db.component.ComponentTreeQuery.Strategy;
import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.measure.MeasureTreeQuery;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.metric.MetricDtoFunctions;
@@ -94,8 +94,8 @@ import static org.sonar.server.measure.ws.MetricDtoToWsMetric.metricDtoToWsMetri
import static org.sonar.server.measure.ws.SnapshotDtoToWsPeriods.snapshotToWsPeriods;
import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext;
import static org.sonar.server.ws.WsParameterBuilder.createQualifiersParameter;
+import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext;
import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.ACTION_COMPONENT_TREE;
@@ -261,6 +261,10 @@ public class ComponentTreeAction implements MeasuresWsAction {
}
private ComponentTreeWsResponse doHandle(ComponentTreeRequest request) {
+ if (request.getDeveloperId() != null || request.getDeveloperKey() != null) {
+ return emptyResponse(null, request);
+ }
+
ComponentTreeData data = load(request);
if (data.getComponents() == null) {
return emptyResponse(data.getBaseComponent(), request);
@@ -320,13 +324,15 @@ public class ComponentTreeAction implements MeasuresWsAction {
return additionalFields != null && additionalFields.contains(ADDITIONAL_PERIODS);
}
- private static ComponentTreeWsResponse emptyResponse(ComponentDto baseComponent, ComponentTreeRequest request) {
+ private static ComponentTreeWsResponse emptyResponse(@Nullable ComponentDto baseComponent, ComponentTreeRequest request) {
ComponentTreeWsResponse.Builder response = ComponentTreeWsResponse.newBuilder();
response.getPagingBuilder()
.setPageIndex(request.getPage())
.setPageSize(request.getPageSize())
.setTotal(0);
- response.setBaseComponent(componentDtoToWsComponent(baseComponent));
+ if (baseComponent != null) {
+ response.setBaseComponent(componentDtoToWsComponent(baseComponent));
+ }
return response.build();
}
@@ -395,14 +401,13 @@ public class ComponentTreeAction implements MeasuresWsAction {
.setBaseComponent(baseComponent)
.build();
}
- Long developerId = searchDeveloperId(dbSession, wsRequest);
ComponentTreeQuery componentTreeQuery = toComponentTreeQuery(wsRequest, baseComponent);
List<ComponentDto> components = searchComponents(dbSession, componentTreeQuery);
List<MetricDto> metrics = searchMetrics(dbSession, wsRequest);
Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric = searchMeasuresByComponentUuidAndMetric(dbSession, baseComponent, componentTreeQuery,
components,
- metrics, developerId);
+ metrics);
components = filterComponents(components, measuresByComponentUuidAndMetric, metrics, wsRequest);
components = sortComponents(components, wsRequest, metrics, measuresByComponentUuidAndMetric);
@@ -432,15 +437,6 @@ public class ComponentTreeAction implements MeasuresWsAction {
: componentFinder.getByKeyAndBranch(dbSession, componentKey, branch);
}
- @CheckForNull
- private Long searchDeveloperId(DbSession dbSession, ComponentTreeRequest wsRequest) {
- if (wsRequest.getDeveloperId() == null && wsRequest.getDeveloperKey() == null) {
- return null;
- }
-
- return componentFinder.getByUuidOrKey(dbSession, wsRequest.getDeveloperId(), wsRequest.getDeveloperKey(), DEVELOPER_ID_AND_KEY).getId();
- }
-
private Map<String, ComponentDto> searchReferenceComponentsById(DbSession dbSession, List<ComponentDto> components) {
List<String> referenceComponentUUids = components.stream()
.map(ComponentDto::getCopyResourceUuid)
@@ -483,20 +479,19 @@ public class ComponentTreeAction implements MeasuresWsAction {
}
private Table<String, MetricDto, ComponentTreeData.Measure> searchMeasuresByComponentUuidAndMetric(DbSession dbSession, ComponentDto baseComponent,
- ComponentTreeQuery componentTreeQuery, List<ComponentDto> components, List<MetricDto> metrics, @Nullable Long developerId) {
+ ComponentTreeQuery componentTreeQuery, List<ComponentDto> components, List<MetricDto> metrics) {
Map<Integer, MetricDto> metricsById = Maps.uniqueIndex(metrics, MetricDto::getId);
MeasureTreeQuery measureQuery = MeasureTreeQuery.builder()
.setStrategy(MeasureTreeQuery.Strategy.valueOf(componentTreeQuery.getStrategy().name()))
.setNameOrKeyQuery(componentTreeQuery.getNameOrKeyQuery())
.setQualifiers(componentTreeQuery.getQualifiers())
- .setPersonId(developerId)
.setMetricIds(new ArrayList<>(metricsById.keySet()))
.build();
Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric = HashBasedTable.create(components.size(), metrics.size());
- dbClient.measureDao().selectTreeByQuery(dbSession, baseComponent, measureQuery, result -> {
- MeasureDto measureDto = result.getResultObject();
+ dbClient.liveMeasureDao().selectTreeByQuery(dbSession, baseComponent, measureQuery, result -> {
+ LiveMeasureDto measureDto = result.getResultObject();
measuresByComponentUuidAndMetric.put(
measureDto.getComponentUuid(),
metricsById.get(measureDto.getMetricId()),
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java
index 16a7d522dbc..5a871110bb8 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java
@@ -25,7 +25,7 @@ import java.util.Map;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonarqube.ws.Measures;
@@ -149,9 +149,9 @@ class ComponentTreeData {
private String data;
private double variation;
- private Measure(MeasureDto measureDto) {
+ private Measure(LiveMeasureDto measureDto) {
this.value = toPrimitive(measureDto.getValue());
- this.data = measureDto.getData();
+ this.data = measureDto.getDataAsString();
this.variation = toPrimitive(measureDto.getVariation());
}
@@ -176,7 +176,7 @@ class ComponentTreeData {
return !isNaN(variation);
}
- static Measure createFromMeasureDto(MeasureDto measureDto) {
+ static Measure createFromMeasureDto(LiveMeasureDto measureDto) {
return new Measure(measureDto);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeRequest.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeRequest.java
index 909a133e1bc..79ed3e383dd 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeRequest.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeRequest.java
@@ -26,7 +26,6 @@ import javax.annotation.Nullable;
class ComponentTreeRequest {
private String baseComponentId;
- private String baseComponentKey;
private String component;
private String branch;
private String strategy;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java
index 3764c46b903..c0bbad0037a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java
@@ -20,6 +20,7 @@
package org.sonar.server.measure.ws;
import javax.annotation.Nullable;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.measure.MeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonarqube.ws.Measures;
@@ -40,6 +41,12 @@ class MeasureDtoToWsMeasure {
updateMeasureBuilder(measureBuilder, metricDto, value == null ? Double.NaN : value, measureDto.getData(), variation == null ? Double.NaN : variation);
}
+ static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metricDto, LiveMeasureDto measureDto) {
+ Double value = measureDto.getValue();
+ Double variation = measureDto.getVariation();
+ updateMeasureBuilder(measureBuilder, metricDto, value == null ? Double.NaN : value, measureDto.getDataAsString(), variation == null ? Double.NaN : variation);
+ }
+
static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metric, double doubleValue, @Nullable String stringValue, double variation) {
measureBuilder.setMetric(metric.getKey());
// a measure value can be null, new_violations metric for example
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MetricDtoWithBestValue.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MetricDtoWithBestValue.java
index f4d920f1b30..a76ee049fd5 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MetricDtoWithBestValue.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MetricDtoWithBestValue.java
@@ -22,12 +22,10 @@ package org.sonar.server.measure.ws;
import com.google.common.collect.ImmutableSortedSet;
import java.util.Locale;
import java.util.Set;
-import java.util.function.Function;
import java.util.function.Predicate;
-import javax.annotation.Nonnull;
import org.sonar.api.resources.Qualifiers;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
class MetricDtoWithBestValue {
@@ -35,11 +33,11 @@ class MetricDtoWithBestValue {
private static final Set<String> QUALIFIERS_ELIGIBLE_FOR_BEST_VALUE = ImmutableSortedSet.of(Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE);
private final MetricDto metric;
- private final MeasureDto bestValue;
+ private final LiveMeasureDto bestValue;
MetricDtoWithBestValue(MetricDto metric) {
this.metric = metric;
- MeasureDto measure = new MeasureDto().setMetricId(metric.getId());
+ LiveMeasureDto measure = new LiveMeasureDto().setMetricId(metric.getId());
boolean isNewTypeMetric = metric.getKey().toLowerCase(Locale.ENGLISH).startsWith(LOWER_CASE_NEW_METRIC_PREFIX);
if (isNewTypeMetric) {
measure.setVariation(metric.getBestValue());
@@ -54,19 +52,11 @@ class MetricDtoWithBestValue {
return metric;
}
- MeasureDto getBestValue() {
+ LiveMeasureDto getBestValue() {
return bestValue;
}
static Predicate<ComponentDto> isEligibleForBestValue() {
return component -> QUALIFIERS_ELIGIBLE_FOR_BEST_VALUE.contains(component.qualifier());
}
-
- static class MetricDtoToMetricDtoWithBestValueFunction implements Function<MetricDto, MetricDtoWithBestValue> {
-
- @Override
- public MetricDtoWithBestValue apply(@Nonnull MetricDto input) {
- return new MetricDtoWithBestValue(input);
- }
- }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java
index dbbda02517f..bdd6d5b2738 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java
@@ -34,7 +34,7 @@ import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Measures.Measure;
@@ -105,7 +105,7 @@ public class SearchAction implements MeasuresWsAction {
private SearchRequest request;
private List<ComponentDto> projects;
private List<MetricDto> metrics;
- private List<MeasureDto> measures;
+ private List<LiveMeasureDto> measures;
ResponseBuilder(Request httpRequest, DbSession dbSession) {
this.dbSession = dbSession;
@@ -161,10 +161,10 @@ public class SearchAction implements MeasuresWsAction {
.collect(toList());
}
- private List<MeasureDto> searchMeasures() {
- return dbClient.measureDao().selectByComponentsAndMetrics(dbSession,
- projects.stream().map(ComponentDto::uuid).collect(toList()),
- metrics.stream().map(MetricDto::getId).collect(toList()));
+ private List<LiveMeasureDto> searchMeasures() {
+ return dbClient.liveMeasureDao().selectByComponentUuids(dbSession,
+ projects.stream().map(ComponentDto::uuid).collect(MoreCollectors.toArrayList(projects.size())),
+ metrics.stream().map(MetricDto::getId).collect(MoreCollectors.toArrayList(metrics.size())));
}
private SearchWsResponse buildResponse() {
@@ -179,7 +179,7 @@ public class SearchAction implements MeasuresWsAction {
Map<String, String> componentNamesByKey = projects.stream().collect(toMap(ComponentDto::getDbKey, ComponentDto::name));
Map<Integer, MetricDto> metricsById = metrics.stream().collect(toMap(MetricDto::getId, identity()));
- Function<MeasureDto, MetricDto> dbMeasureToDbMetric = dbMeasure -> metricsById.get(dbMeasure.getMetricId());
+ Function<LiveMeasureDto, MetricDto> dbMeasureToDbMetric = dbMeasure -> metricsById.get(dbMeasure.getMetricId());
Function<Measure, String> byMetricKey = Measure::getMetric;
Function<Measure, String> byComponentName = wsMeasure -> componentNamesByKey.get(wsMeasure.getComponent());
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java
index 37867d57e77..74f41d8fc9d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java
@@ -19,12 +19,13 @@
*/
package org.sonar.server.project.ws;
-import java.util.List;
-import java.util.function.Function;
-
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
+import java.util.List;
+import java.util.function.Function;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.server.ws.Change;
@@ -39,19 +40,15 @@ import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentLinkDto;
import org.sonar.db.component.ComponentQuery;
import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.measure.MeasureQuery;
-import org.sonar.db.metric.MetricDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Projects.SearchMyProjectsWsResponse;
import org.sonarqube.ws.Projects.SearchMyProjectsWsResponse.Link;
import org.sonarqube.ws.Projects.SearchMyProjectsWsResponse.Project;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.base.Strings.isNullOrEmpty;
+import static java.util.Collections.singletonList;
import static java.util.Objects.requireNonNull;
import static org.sonar.api.utils.Paging.offset;
import static org.sonar.core.util.Protobuf.setNullable;
@@ -177,12 +174,8 @@ public class SearchMyProjectsAction implements ProjectsWsAction {
List<String> projectUuids = Lists.transform(projects, ComponentDto::projectUuid);
List<ComponentLinkDto> projectLinks = dbClient.componentLinkDao().selectByComponentUuids(dbSession, projectUuids);
List<SnapshotDto> snapshots = dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, projectUuids);
- MetricDto gateStatusMetric = dbClient.metricDao().selectOrFailByKey(dbSession, CoreMetrics.ALERT_STATUS_KEY);
- MeasureQuery measureQuery = MeasureQuery.builder()
- .setProjectUuids(projectUuids)
- .setMetricId(gateStatusMetric.getId())
- .build();
- List<MeasureDto> qualityGates = dbClient.measureDao().selectByQuery(dbSession, measureQuery);
+ List<LiveMeasureDto> qualityGates = dbClient.liveMeasureDao()
+ .selectByComponentUuidsAndMetricKeys(dbSession, projectUuids, singletonList(CoreMetrics.ALERT_STATUS_KEY));
data.setProjects(projects)
.setProjectLinks(projectLinks)
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java
index 9e389e76aef..49f746d3a8c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java
@@ -29,7 +29,7 @@ import java.util.stream.Collectors;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentLinkDto;
import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.LiveMeasureDto;
import static com.google.common.collect.ImmutableList.copyOf;
import static java.util.Objects.requireNonNull;
@@ -86,16 +86,16 @@ class SearchMyProjectsData {
snapshot -> formatDateTime(snapshot.getCreatedAt()))));
}
- private static Map<String, String> buildQualityGateStatuses(List<MeasureDto> measures) {
+ private static Map<String, String> buildQualityGateStatuses(List<LiveMeasureDto> measures) {
return ImmutableMap.copyOf(measures.stream()
- .collect(Collectors.toMap(MeasureDto::getComponentUuid, MeasureDto::getData)));
+ .collect(Collectors.toMap(LiveMeasureDto::getComponentUuid, LiveMeasureDto::getDataAsString)));
}
static class Builder {
private List<ComponentDto> projects;
private List<ComponentLinkDto> projectLinks;
private List<SnapshotDto> snapshots;
- private List<MeasureDto> qualityGates;
+ private List<LiveMeasureDto> qualityGates;
private Integer totalNbOfProjects;
private Builder() {
@@ -117,7 +117,7 @@ class SearchMyProjectsData {
return this;
}
- public Builder setQualityGates(List<MeasureDto> qGateStatuses) {
+ public Builder setQualityGates(List<LiveMeasureDto> qGateStatuses) {
this.qualityGates = qGateStatuses;
return this;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java
index 53c9b817282..7bd685e3203 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java
@@ -19,11 +19,11 @@
*/
package org.sonar.server.qualitygate.ws;
-import com.google.common.base.Optional;
import java.util.Arrays;
-import java.util.List;
+import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
@@ -35,8 +35,8 @@ import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.measure.MeasureQuery;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.component.ComponentFinder.ParamNames;
import org.sonar.server.exceptions.BadRequestException;
@@ -45,7 +45,6 @@ import org.sonar.server.ws.KeyExamples;
import org.sonarqube.ws.Qualitygates.ProjectStatusResponse;
import static com.google.common.base.Strings.isNullOrEmpty;
-import static java.util.Collections.singletonList;
import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
import static org.sonar.server.ws.WsUtils.checkRequest;
@@ -88,8 +87,7 @@ public class ProjectStatusAction implements QualityGatesWsAction {
.setSince("5.3")
.setHandler(this)
.setChangelog(
- new Change("6.4", "The field 'ignoredConditions' is added to the response")
- );
+ new Change("6.4", "The field 'ignoredConditions' is added to the response"));
action.createParam(PARAM_ANALYSIS_ID)
.setDescription("Analysis id")
@@ -120,11 +118,11 @@ public class ProjectStatusAction implements QualityGatesWsAction {
writeProtobuf(projectStatusResponse, request, response);
}
- private ProjectStatusResponse doHandle(String analysisId, String projectId, String projectKey) {
+ private ProjectStatusResponse doHandle(@Nullable String analysisId, @Nullable String projectId, @Nullable String projectKey) {
try (DbSession dbSession = dbClient.openSession(false)) {
ProjectAndSnapshot projectAndSnapshot = getProjectAndSnapshot(dbSession, analysisId, projectId, projectKey);
checkPermission(projectAndSnapshot.project);
- Optional<String> measureData = getQualityGateDetailsMeasureData(dbSession, projectAndSnapshot.project);
+ Optional<String> measureData = loadQualityGateDetails(dbSession, projectAndSnapshot, analysisId != null);
return ProjectStatusResponse.newBuilder()
.setProjectStatus(new QualityGateDetailsFormatter(measureData, projectAndSnapshot.snapshotDto).format())
@@ -132,10 +130,11 @@ public class ProjectStatusAction implements QualityGatesWsAction {
}
}
- private ProjectAndSnapshot getProjectAndSnapshot(DbSession dbSession, String analysisId, String projectId, String projectKey) {
+ private ProjectAndSnapshot getProjectAndSnapshot(DbSession dbSession, @Nullable String analysisId, @Nullable String projectId, @Nullable String projectKey) {
if (!isNullOrEmpty(analysisId)) {
return getSnapshotThenProject(dbSession, analysisId);
- } else if (!isNullOrEmpty(projectId) ^ !isNullOrEmpty(projectKey)) {
+ }
+ if (!isNullOrEmpty(projectId) ^ !isNullOrEmpty(projectKey)) {
return getProjectThenSnapshot(dbSession, projectId, projectKey);
}
@@ -144,7 +143,7 @@ public class ProjectStatusAction implements QualityGatesWsAction {
private ProjectAndSnapshot getProjectThenSnapshot(DbSession dbSession, String projectId, String projectKey) {
ComponentDto projectDto = componentFinder.getByUuidOrKey(dbSession, projectId, projectKey, ParamNames.PROJECT_ID_AND_KEY);
- java.util.Optional<SnapshotDto> snapshot = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, projectDto.projectUuid());
+ Optional<SnapshotDto> snapshot = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, projectDto.projectUuid());
return new ProjectAndSnapshot(projectDto, snapshot.orElse(null));
}
@@ -155,20 +154,24 @@ public class ProjectStatusAction implements QualityGatesWsAction {
}
private SnapshotDto getSnapshot(DbSession dbSession, String analysisUuid) {
- java.util.Optional<SnapshotDto> snapshotDto = dbClient.snapshotDao().selectByUuid(dbSession, analysisUuid);
+ Optional<SnapshotDto> snapshotDto = dbClient.snapshotDao().selectByUuid(dbSession, analysisUuid);
return checkFoundWithOptional(snapshotDto, "Analysis with id '%s' is not found", analysisUuid);
}
- private Optional<String> getQualityGateDetailsMeasureData(DbSession dbSession, ComponentDto project) {
- MeasureQuery measureQuery = MeasureQuery.builder()
- .setProjectUuids(singletonList(project.projectUuid()))
- .setMetricKey(CoreMetrics.QUALITY_GATE_DETAILS_KEY)
- .build();
- List<MeasureDto> measures = dbClient.measureDao().selectByQuery(dbSession, measureQuery);
+ private Optional<String> loadQualityGateDetails(DbSession dbSession, ProjectAndSnapshot projectAndSnapshot, boolean onAnalysis) {
+ if (onAnalysis) {
+ if (!projectAndSnapshot.snapshotDto.isPresent()) {
+ return Optional.empty();
+ }
+ // get the gate status as it was computed during the specified analysis
+ String analysisUuid = projectAndSnapshot.snapshotDto.get().getUuid();
+ return dbClient.measureDao().selectMeasure(dbSession, analysisUuid, projectAndSnapshot.project.projectUuid(), CoreMetrics.QUALITY_GATE_DETAILS_KEY)
+ .map(MeasureDto::getData);
+ }
- return measures.isEmpty()
- ? Optional.absent()
- : Optional.fromNullable(measures.get(0).getData());
+ // do not restrict to a specified analysis, use the live measure
+ Optional<LiveMeasureDto> measure = dbClient.liveMeasureDao().selectMeasure(dbSession, projectAndSnapshot.project.projectUuid(), CoreMetrics.QUALITY_GATE_DETAILS_KEY);
+ return measure.map(LiveMeasureDto::getDataAsString);
}
private void checkPermission(ComponentDto project) {
@@ -178,13 +181,14 @@ public class ProjectStatusAction implements QualityGatesWsAction {
}
}
+ @Immutable
private static class ProjectAndSnapshot {
private final ComponentDto project;
private final Optional<SnapshotDto> snapshotDto;
private ProjectAndSnapshot(ComponentDto project, @Nullable SnapshotDto snapshotDto) {
this.project = project;
- this.snapshotDto = Optional.fromNullable(snapshotDto);
+ this.snapshotDto = Optional.ofNullable(snapshotDto);
}
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatter.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatter.java
index 84c902f8729..10dfbb4831d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatter.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatter.java
@@ -19,11 +19,11 @@
*/
package org.sonar.server.qualitygate.ws;
-import com.google.common.base.Optional;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
+import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.StreamSupport;
import javax.annotation.Nullable;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java
index a55d2ebcfe8..34156db7759 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java
@@ -26,9 +26,7 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Predicate;
-import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.ResourceType;
@@ -45,8 +43,7 @@ import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.measure.MeasureQuery;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.permission.OrganizationPermission;
import org.sonar.db.property.PropertyDto;
@@ -166,10 +163,6 @@ public class ComponentAction implements NavigationWsAction {
.endObject();
}
- private static Function<MeasureDto, Stream<QualityProfile>> toQualityProfiles() {
- return dbMeasure -> QPMeasureData.fromJson(dbMeasure.getData()).getProfiles().stream();
- }
-
private static void writePage(JsonWriter json, Page page) {
json.beginObject()
.prop("key", page.getKey())
@@ -205,12 +198,11 @@ public class ComponentAction implements NavigationWsAction {
return componentFavourites.size() == 1;
}
- private void writeProfiles(JsonWriter json, DbSession session, ComponentDto component) {
+ private void writeProfiles(JsonWriter json, DbSession dbSession, ComponentDto component) {
json.name("qualityProfiles").beginArray();
- dbClient.measureDao().selectSingle(session, MeasureQuery.builder().setComponentUuid(component.projectUuid()).setMetricKey(QUALITY_PROFILES_KEY).build())
- .ifPresent(dbMeasure -> Stream.of(dbMeasure)
- .flatMap(toQualityProfiles())
- .forEach(writeToJson(json)));
+ dbClient.liveMeasureDao().selectMeasure(dbSession, component.projectUuid(), QUALITY_PROFILES_KEY)
+ .map(LiveMeasureDto::getDataAsString)
+ .ifPresent(data -> QPMeasureData.fromJson(data).getProfiles().forEach(writeToJson(json)));
json.endArray();
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/branch/ws/ListActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/branch/ws/ListActionTest.java
index bb8a93ae72b..2415c9cc93a 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/branch/ws/ListActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/branch/ws/ListActionTest.java
@@ -34,7 +34,6 @@ import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.component.ResourceTypesRule;
-import org.sonar.db.component.SnapshotDto;
import org.sonar.db.component.SnapshotTesting;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.organization.OrganizationDto;
@@ -250,8 +249,7 @@ public class ListActionTest {
ComponentDto project = db.components().insertMainBranch();
userSession.logIn().addProjectPermission(UserRole.USER, project);
ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.LONG));
- SnapshotDto branchAnalysis = db.components().insertSnapshot(branch);
- db.measures().insertMeasure(branch, branchAnalysis, qualityGateStatus, m -> m.setData("OK"));
+ db.measures().insertLiveMeasure(branch, qualityGateStatus, m -> m.setData("OK"));
ListWsResponse response = ws.newRequest()
.setParam("project", project.getKey())
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/AppActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/AppActionTest.java
index 7eb2c50a074..be66db8cebe 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/AppActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/AppActionTest.java
@@ -25,7 +25,6 @@ import org.junit.rules.ExpectedException;
import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.server.component.TestComponentFinder;
import org.sonar.server.exceptions.ForbiddenException;
@@ -135,19 +134,18 @@ public class AppActionTest {
ComponentDto project = db.components().insertPrivateProject();
ComponentDto directory = db.components().insertComponent(newDirectory(project, "src"));
ComponentDto file = db.components().insertComponent(newFileDto(project, directory));
- SnapshotDto analysis = db.components().insertSnapshot(project);
MetricDto lines = db.measures().insertMetric(m -> m.setKey(LINES_KEY));
- db.measures().insertMeasure(file, analysis, lines, m -> m.setValue(200d));
+ db.measures().insertLiveMeasure(file, lines, m -> m.setValue(200d));
MetricDto duplicatedLines = db.measures().insertMetric(m -> m.setKey(DUPLICATED_LINES_DENSITY_KEY));
- db.measures().insertMeasure(file, analysis, duplicatedLines, m -> m.setValue(7.4));
+ db.measures().insertLiveMeasure(file, duplicatedLines, m -> m.setValue(7.4));
MetricDto tests = db.measures().insertMetric(m -> m.setKey(TESTS_KEY));
- db.measures().insertMeasure(file, analysis, tests, m -> m.setValue(3d));
+ db.measures().insertLiveMeasure(file, tests, m -> m.setValue(3d));
MetricDto technicalDebt = db.measures().insertMetric(m -> m.setKey(TECHNICAL_DEBT_KEY));
- db.measures().insertMeasure(file, analysis, technicalDebt, m -> m.setValue(182d));
+ db.measures().insertLiveMeasure(file, technicalDebt, m -> m.setValue(182d));
MetricDto issues = db.measures().insertMetric(m -> m.setKey(VIOLATIONS_KEY));
- db.measures().insertMeasure(file, analysis, issues, m -> m.setValue(231d));
+ db.measures().insertLiveMeasure(file, issues, m -> m.setValue(231d));
MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY));
- db.measures().insertMeasure(file, analysis, coverage, m -> m.setValue(95.4d));
+ db.measures().insertLiveMeasure(file, coverage, m -> m.setValue(95.4d));
userSession.logIn("john").addProjectPermission(USER, project);
String result = ws.newRequest()
@@ -170,9 +168,8 @@ public class AppActionTest {
public void get_by_uuid() {
ComponentDto project = db.components().insertPrivateProject();
ComponentDto file = db.components().insertComponent(newFileDto(project, project));
- SnapshotDto analysis = db.components().insertSnapshot(project);
MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY));
- db.measures().insertMeasure(file, analysis, coverage, m -> m.setValue(95.4d));
+ db.measures().insertLiveMeasure(file, coverage, m -> m.setValue(95.4d));
userSession.logIn("john").addProjectPermission(USER, project);
String result = ws.newRequest()
@@ -258,9 +255,8 @@ public class AppActionTest {
ComponentDto module = db.components().insertComponent(newModuleDto(branch));
ComponentDto directory = db.components().insertComponent(newDirectory(module, "src"));
ComponentDto file = db.components().insertComponent(newFileDto(module, directory));
- SnapshotDto analysis = db.components().insertSnapshot(branch);
MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY));
- db.measures().insertMeasure(file, analysis, coverage, m -> m.setValue(95.4d));
+ db.measures().insertLiveMeasure(file, coverage, m -> m.setValue(95.4d));
String result = ws.newRequest()
.setParam("component", file.getKey())
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java
index 77ba51d4a7e..afddc8ae32c 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java
@@ -41,8 +41,7 @@ import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.property.PropertyDto;
@@ -316,9 +315,9 @@ public class SearchProjectsActionTest {
userSession.logIn();
OrganizationDto organizationDto = db.organizations().insert();
MetricDto qualityGateStatus = db.measures().insertMetric(c -> c.setKey(QUALITY_GATE_STATUS).setValueType(LEVEL.name()));
- ComponentDto project1 = insertProject(organizationDto, new Measure(qualityGateStatus, c -> c.setData("OK")));
- ComponentDto project2 = insertProject(organizationDto, new Measure(qualityGateStatus, c -> c.setData("OK")));
- ComponentDto project3 = insertProject(organizationDto, new Measure(qualityGateStatus, c -> c.setData("ERROR")));
+ ComponentDto project1 = insertProject(organizationDto, new Measure(qualityGateStatus, c -> c.setValue(null).setData("OK")));
+ ComponentDto project2 = insertProject(organizationDto, new Measure(qualityGateStatus, c -> c.setValue(null).setData("OK")));
+ ComponentDto project3 = insertProject(organizationDto, new Measure(qualityGateStatus, c -> c.setValue(null).setData("ERROR")));
SearchProjectsWsResponse result = call(request.setFilter("alert_status = OK"));
@@ -332,10 +331,10 @@ public class SearchProjectsActionTest {
userSession.logIn();
OrganizationDto organizationDto = db.organizations().insert();
MetricDto languagesDistribution = db.measures().insertMetric(c -> c.setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY).setValueType(DATA.name()));
- ComponentDto project1 = insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setData("<null>=2;java=6;xoo=18")));
- ComponentDto project2 = insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setData("java=3;xoo=9")));
- ComponentDto project3 = insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setData("xoo=1")));
- ComponentDto project4 = insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setData("<null>=1;java=5;xoo=13")));
+ ComponentDto project1 = insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setValue(null).setData("<null>=2;java=6;xoo=18")));
+ ComponentDto project2 = insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setValue(null).setData("java=3;xoo=9")));
+ ComponentDto project3 = insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setValue(null).setData("xoo=1")));
+ ComponentDto project4 = insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setValue(null).setData("<null>=1;java=5;xoo=13")));
SearchProjectsWsResponse result = call(request.setFilter("languages IN (java, js, <null>)"));
@@ -628,10 +627,10 @@ public class SearchProjectsActionTest {
userSession.logIn();
OrganizationDto organizationDto = db.organizations().insert();
MetricDto languagesDistribution = db.measures().insertMetric(c -> c.setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY).setValueType(DATA.name()));
- insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setData("<null>=2;java=6;xoo=18")));
- insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setData("java=5;xoo=19")));
- insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setData("xoo=1")));
- insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setData("<null>=1;java=3;xoo=8")));
+ insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setValue(null).setData("<null>=2;java=6;xoo=18")));
+ insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setValue(null).setData("java=5;xoo=19")));
+ insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setValue(null).setData("xoo=1")));
+ insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setValue(null).setData("<null>=1;java=3;xoo=8")));
SearchProjectsWsResponse result = call(request.setFacets(singletonList(FILTER_LANGUAGES)));
@@ -651,8 +650,8 @@ public class SearchProjectsActionTest {
userSession.logIn();
OrganizationDto organizationDto = db.organizations().insert();
MetricDto languagesDistribution = db.measures().insertMetric(c -> c.setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY).setValueType(DATA.name()));
- insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setData("<null>=2;java=6")));
- insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setData("java=5")));
+ insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setValue(null).setData("<null>=2;java=6")));
+ insertProject(organizationDto, new Measure(languagesDistribution, c -> c.setValue(null).setData("java=5")));
SearchProjectsWsResponse result = call(request.setFilter("languages = xoo").setFacets(singletonList(FILTER_LANGUAGES)));
@@ -964,10 +963,10 @@ public class SearchProjectsActionTest {
userSession.logIn();
OrganizationDto organization = db.organizations().insert();
MetricDto qualityGateStatus = db.measures().insertMetric(c -> c.setKey(QUALITY_GATE_STATUS).setValueType(LEVEL.name()));
- ComponentDto project1 = insertProject(organization, c -> c.setName("Sonar Java"), new Measure(qualityGateStatus, c -> c.setData("ERROR")));
- ComponentDto project2 = insertProject(organization, c -> c.setName("Sonar Groovy"), new Measure(qualityGateStatus, c -> c.setData("WARN")));
- ComponentDto project3 = insertProject(organization, c -> c.setName("Sonar Markdown"), new Measure(qualityGateStatus, c -> c.setData("OK")));
- ComponentDto project4 = insertProject(organization, c -> c.setName("Sonar Qube"), new Measure(qualityGateStatus, c -> c.setData("OK")));
+ ComponentDto project1 = insertProject(organization, c -> c.setName("Sonar Java"), new Measure(qualityGateStatus, c -> c.setValue(null).setData("ERROR")));
+ ComponentDto project2 = insertProject(organization, c -> c.setName("Sonar Groovy"), new Measure(qualityGateStatus, c -> c.setValue(null).setData("WARN")));
+ ComponentDto project3 = insertProject(organization, c -> c.setName("Sonar Markdown"), new Measure(qualityGateStatus, c -> c.setValue(null).setData("OK")));
+ ComponentDto project4 = insertProject(organization, c -> c.setName("Sonar Qube"), new Measure(qualityGateStatus, c -> c.setValue(null).setData("OK")));
assertThat(call(request.setSort(QUALITY_GATE_STATUS).setAsc(true)).getComponentsList()).extracting(Component::getKey)
.containsExactly(project3.getDbKey(), project4.getDbKey(), project2.getDbKey(), project1.getDbKey());
@@ -1138,8 +1137,7 @@ public class SearchProjectsActionTest {
private ComponentDto insertProject(OrganizationDto organizationDto, Consumer<ComponentDto> projectConsumer, Measure... measures) {
ComponentDto project = db.components().insertPublicProject(organizationDto, projectConsumer);
- SnapshotDto analysis = db.components().insertSnapshot(project);
- Arrays.stream(measures).forEach(m -> db.measures().insertMeasure(project, analysis, m.metric, m.consumer));
+ Arrays.stream(measures).forEach(m -> db.measures().insertLiveMeasure(project, m.metric, m.consumer));
authorizationIndexerTester.allowOnlyAnyone(project);
projectMeasuresIndexer.indexOnAnalysis(project.uuid());
return project;
@@ -1147,9 +1145,9 @@ public class SearchProjectsActionTest {
private static class Measure {
private final MetricDto metric;
- private final Consumer<MeasureDto> consumer;
+ private final Consumer<LiveMeasureDto> consumer;
- public Measure(MetricDto metric, Consumer<MeasureDto> consumer) {
+ public Measure(MetricDto metric, Consumer<LiveMeasureDto> consumer) {
this.metric = metric;
this.consumer = consumer;
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/BestValueOptimizationTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/BestValueOptimizationTest.java
index 6ad0fbe2841..76d170ac3bd 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/BestValueOptimizationTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/BestValueOptimizationTest.java
@@ -19,7 +19,7 @@
*/
package org.sonar.server.computation.task.projectanalysis.measure;
-import com.google.common.base.Predicate;
+import java.util.function.Predicate;
import org.junit.Test;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
@@ -56,18 +56,18 @@ public class BestValueOptimizationTest {
public void apply_returns_true_for_value_true_for_Boolean_Metric_and_best_value_1() {
Predicate<Measure> underTest = BestValueOptimization.from(METRIC_BOOLEAN_TRUE, FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create(true))).isTrue();
- assertThat(underTest.apply(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(true))).isTrue();
- assertThat(underTest.apply(newMeasureBuilder().create(false))).isFalse();
- assertThat(underTest.apply(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(false))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(true))).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(true))).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().create(false))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(false))).isFalse();
}
@Test
public void apply_returns_false_if_component_is_not_a_FILE_for_Boolean_Metric_and_best_value_1() {
Predicate<Measure> underTest = BestValueOptimization.from(METRIC_BOOLEAN_TRUE, SOME_NON_FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create(true))).isFalse();
- assertThat(underTest.apply(newMeasureBuilder().create(false))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(true))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(false))).isFalse();
}
@Test
@@ -75,8 +75,8 @@ public class BestValueOptimizationTest {
Predicate<Measure> underTest = BestValueOptimization.from(METRIC_BOOLEAN_TRUE, FILE_COMPONENT);
for (Measure.NewMeasureBuilder builder : builders_of_non_bestValueOptimized_measures()) {
- assertThat(underTest.apply(builder.create(true))).isFalse();
- assertThat(underTest.apply(builder.create(false))).isFalse();
+ assertThat(underTest.test(builder.create(true))).isFalse();
+ assertThat(underTest.test(builder.create(false))).isFalse();
}
}
@@ -84,25 +84,25 @@ public class BestValueOptimizationTest {
public void apply_returns_false_if_measure_has_data_for_Boolean_Metric_and_best_value_1() {
Predicate<Measure> underTest = BestValueOptimization.from(METRIC_BOOLEAN_TRUE, FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create(true, SOME_DATA))).isFalse();
- assertThat(underTest.apply(newMeasureBuilder().create(false, SOME_DATA))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(true, SOME_DATA))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(false, SOME_DATA))).isFalse();
}
@Test
public void apply_returns_true_for_value_false_for_Boolean_Metric_and_best_value_not_1() {
Predicate<Measure> underTest = BestValueOptimization.from(METRIC_BOOLEAN_FALSE, FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create(true))).isFalse();
- assertThat(underTest.apply(newMeasureBuilder().create(false))).isTrue();
- assertThat(underTest.apply(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(false))).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().create(true))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(false))).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(false))).isTrue();
}
@Test
public void apply_returns_false_if_component_is_not_a_FILE_for_Boolean_Metric_and_best_value_not_1() {
Predicate<Measure> underTest = BestValueOptimization.from(METRIC_BOOLEAN_FALSE, SOME_NON_FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create(true))).isFalse();
- assertThat(underTest.apply(newMeasureBuilder().create(false))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(true))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(false))).isFalse();
}
@Test
@@ -110,8 +110,8 @@ public class BestValueOptimizationTest {
Predicate<Measure> underTest = BestValueOptimization.from(METRIC_BOOLEAN_FALSE, FILE_COMPONENT);
for (Measure.NewMeasureBuilder builder : builders_of_non_bestValueOptimized_measures()) {
- assertThat(underTest.apply(builder.create(true))).isFalse();
- assertThat(underTest.apply(builder.create(false))).isFalse();
+ assertThat(underTest.test(builder.create(true))).isFalse();
+ assertThat(underTest.test(builder.create(false))).isFalse();
}
}
@@ -119,59 +119,59 @@ public class BestValueOptimizationTest {
public void apply_returns_false_if_measure_has_data_for_Boolean_Metric_and_best_value_not_1() {
Predicate<Measure> underTest = BestValueOptimization.from(METRIC_BOOLEAN_FALSE, FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create(true, SOME_DATA))).isFalse();
- assertThat(underTest.apply(newMeasureBuilder().create(false, SOME_DATA))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(true, SOME_DATA))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(false, SOME_DATA))).isFalse();
}
@Test
public void verify_value_comparison_for_int_metric() {
Predicate<Measure> underTest = BestValueOptimization.from(createMetric(Metric.MetricType.INT, 10), FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create(10))).isTrue();
- assertThat(underTest.apply(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(10))).isTrue();
- assertThat(underTest.apply(newMeasureBuilder().create(11))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(10))).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(10))).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().create(11))).isFalse();
}
@Test
public void verify_value_comparison_for_long_metric() {
Predicate<Measure> underTest = BestValueOptimization.from(createMetric(Metric.MetricType.WORK_DUR, 9511L), FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create(9511L))).isTrue();
- assertThat(underTest.apply(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(9511L))).isTrue();
- assertThat(underTest.apply(newMeasureBuilder().create(963L))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(9511L))).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(9511L))).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().create(963L))).isFalse();
}
@Test
public void verify_value_comparison_for_rating_metric() {
Predicate<Measure> underTest = BestValueOptimization.from(createMetric(Metric.MetricType.RATING, A.getIndex()), FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create(A.getIndex()))).isTrue();
- assertThat(underTest.apply(newMeasureBuilder().setVariation((double) A.getIndex()).createNoValue())).isTrue();
- assertThat(underTest.apply(newMeasureBuilder().create(B.getIndex()))).isFalse();
- assertThat(underTest.apply(newMeasureBuilder().setVariation((double) B.getIndex()).createNoValue())).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(A.getIndex()))).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().setVariation((double) A.getIndex()).createNoValue())).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().create(B.getIndex()))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().setVariation((double) B.getIndex()).createNoValue())).isFalse();
}
@Test
public void verify_value_comparison_for_double_metric() {
Predicate<Measure> underTest = BestValueOptimization.from(createMetric(Metric.MetricType.FLOAT, 36.5d), FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create(36.5d, 1))).isTrue();
- assertThat(underTest.apply(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(36.5d, 1))).isTrue();
- assertThat(underTest.apply(newMeasureBuilder().create(36.6d, 1))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(36.5d, 1))).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(36.5d, 1))).isTrue();
+ assertThat(underTest.test(newMeasureBuilder().create(36.6d, 1))).isFalse();
}
@Test
public void apply_returns_false_for_String_measure() {
Predicate<Measure> underTest = BestValueOptimization.from(createMetric(Metric.MetricType.FLOAT, 36.5d), FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create("aaa"))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create("aaa"))).isFalse();
}
@Test
public void apply_returns_false_for_LEVEL_measure() {
Predicate<Measure> underTest = BestValueOptimization.from(createMetric(Metric.MetricType.STRING, 36.5d), FILE_COMPONENT);
- assertThat(underTest.apply(newMeasureBuilder().create(Measure.Level.OK))).isFalse();
+ assertThat(underTest.test(newMeasureBuilder().create(Measure.Level.OK))).isFalse();
}
private static MetricImpl createMetric(Metric.MetricType metricType, double bestValue) {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryRule.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryRule.java
index 976ea71ae07..a8333648e6d 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryRule.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryRule.java
@@ -19,23 +19,19 @@
*/
package org.sonar.server.computation.task.projectanalysis.measure;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.FluentIterable.from;
-import static com.google.common.collect.Maps.filterKeys;
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
-
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.SetMultimap;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
-
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-
import org.junit.rules.ExternalResource;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.ComponentProvider;
@@ -48,11 +44,12 @@ import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolde
import org.sonar.server.computation.task.projectanalysis.metric.Metric;
import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.SetMultimap;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.FluentIterable.from;
+import static com.google.common.collect.Maps.filterKeys;
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
/**
* An implementation of MeasureRepository as a JUnit rule which provides add methods for raw measures and extra add
@@ -192,13 +189,6 @@ public class MeasureRepositoryRule extends ExternalResource implements MeasureRe
return Optional.fromNullable(baseMeasures.get(new InternalKey(component, metric)));
}
- @Override
- public int loadAsRawMeasures(Collection<Component> components, Collection<Metric> metrics) {
- this.loadedAsRawComponents = components;
- this.loadedAsRawMetrics = metrics;
- return 0;
- }
-
public Collection<Component> getComponentsLoadedAsRaw() {
return loadedAsRawComponents;
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureToMeasureDtoTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureToMeasureDtoTest.java
index 809e3d7c3ec..e3adbf59c28 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureToMeasureDtoTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureToMeasureDtoTest.java
@@ -26,12 +26,11 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.measure.MeasureDto;
import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule;
import org.sonar.server.computation.task.projectanalysis.component.Component;
-import org.sonar.server.computation.task.projectanalysis.component.Developer;
-import org.sonar.server.computation.task.projectanalysis.component.DumbDeveloper;
-import org.sonar.server.computation.task.projectanalysis.component.MutableDbIdsRepositoryRule;
+import org.sonar.server.computation.task.projectanalysis.component.MutableTreeRootHolderRule;
import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
import org.sonar.server.computation.task.projectanalysis.metric.Metric;
import org.sonar.server.computation.task.projectanalysis.metric.MetricImpl;
@@ -41,7 +40,6 @@ import static org.assertj.core.api.Assertions.assertThat;
@RunWith(DataProviderRunner.class)
public class MeasureToMeasureDtoTest {
private static final MetricImpl SOME_METRIC = new MetricImpl(42, "metric_key", "metric_name", Metric.MetricType.STRING);
- private static final int SOME_COMPONENT_ID = 951;
private static final String SOME_DATA = "some_data";
private static final String SOME_STRING = "some_string";
private static final double SOME_VARIATIONS = 1d;
@@ -55,16 +53,15 @@ public class MeasureToMeasureDtoTest {
private static final Component SOME_COMPONENT = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("uuid_1").build();
@Rule
- public MutableDbIdsRepositoryRule dbIdsRepository = MutableDbIdsRepositoryRule.create(SOME_COMPONENT);
+ public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
@Rule
- public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
+ public MutableTreeRootHolderRule treeRootHolder = new MutableTreeRootHolderRule();
- MeasureToMeasureDto underTest = new MeasureToMeasureDto(dbIdsRepository, analysisMetadataHolder);
+ private MeasureToMeasureDto underTest = new MeasureToMeasureDto(analysisMetadataHolder, treeRootHolder);
@Before
public void setUp() throws Exception {
- dbIdsRepository.setComponentId(SOME_COMPONENT, SOME_COMPONENT_ID);
analysisMetadataHolder.setUuid(ANALYSIS_UUID);
}
@@ -130,22 +127,6 @@ public class MeasureToMeasureDtoTest {
MeasureDto measureDto = underTest.toMeasureDto(measure, metric, SOME_COMPONENT);
assertThat(measureDto.getComponentUuid()).isEqualTo(SOME_COMPONENT.getUuid());
- // assertThat(measureDto.getSnapshotId()).isEqualTo(SOME_SNAPSHOT_ID);
- }
-
- @Test
- @UseDataProvider("all_types_Measures")
- public void toMeasureDto_does_no_set_developerId_if_not_set_in_Measure(Measure measure, Metric metric) {
- assertThat(underTest.toMeasureDto(measure, metric, SOME_COMPONENT).getDeveloperId()).isNull();
- }
-
- @Test
- public void toMeasureDto_sets_developerId_if_set_in_Measure() {
- Developer developer = new DumbDeveloper("DEV1");
- dbIdsRepository.setDeveloperId(developer, 42);
- Measure measure = Measure.newMeasureBuilder().forDeveloper(developer).createNoValue();
-
- assertThat(underTest.toMeasureDto(measure, SOME_BOOLEAN_METRIC, SOME_COMPONENT).getDeveloperId()).isEqualTo(42);
}
@Test
@@ -200,4 +181,16 @@ public class MeasureToMeasureDtoTest {
assertThat(trueMeasureDto.getValue()).isNull();
assertThat(trueMeasureDto.getData()).isEqualTo(Measure.Level.OK.name());
}
+
+ @Test
+ public void toLiveMeasureDto() {
+ treeRootHolder.setRoot(SOME_COMPONENT);
+
+ LiveMeasureDto liveMeasureDto = underTest.toLiveMeasureDto(
+ Measure.newMeasureBuilder().create(Measure.Level.OK),
+ SOME_LEVEL_METRIC,
+ SOME_COMPONENT);
+
+ assertThat(liveMeasureDto.getTextValue()).isEqualTo(Measure.Level.OK.name());
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistLiveMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistLiveMeasuresStepTest.java
new file mode 100644
index 00000000000..1a0f07d076a
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistLiveMeasuresStepTest.java
@@ -0,0 +1,290 @@
+/*
+ * 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.computation.task.projectanalysis.step;
+
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.measure.LiveMeasureDto;
+import org.sonar.db.metric.MetricDto;
+import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule;
+import org.sonar.server.computation.task.projectanalysis.analysis.Project;
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
+import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
+import org.sonar.server.computation.task.projectanalysis.component.ViewsComponent;
+import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.task.projectanalysis.measure.MeasureToMeasureDto;
+import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
+import org.sonar.server.computation.task.step.ComputationStep;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.measure.MeasureTesting.newLiveMeasure;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.MODULE;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT_VIEW;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.SUBVIEW;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.VIEW;
+import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
+
+public class PersistLiveMeasuresStepTest extends BaseStepTest {
+
+ private static final Metric STRING_METRIC = new Metric.Builder("string-metric", "String metric", Metric.ValueType.STRING).create();
+ private static final Metric INT_METRIC = new Metric.Builder("int-metric", "int metric", Metric.ValueType.INT).create();
+ private static final Metric METRIC_WITH_BEST_VALUE = new Metric.Builder("best-value-metric", "best value metric", Metric.ValueType.INT)
+ .setBestValue(0.0)
+ .setOptimizedBestValue(true)
+ .create();
+
+ private static final int REF_1 = 1;
+ private static final int REF_2 = 2;
+ private static final int REF_3 = 3;
+ private static final int REF_4 = 4;
+
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+ @Rule
+ public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+ @Rule
+ public MetricRepositoryRule metricRepository = new MetricRepositoryRule();
+ @Rule
+ public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+ @Rule
+ public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
+
+ private DbClient dbClient = db.getDbClient();
+
+ @Before
+ public void setUp() {
+ MetricDto stringMetricDto = db.measures().insertMetric(m -> m.setKey(STRING_METRIC.getKey()).setValueType(Metric.ValueType.STRING.name()));
+ MetricDto intMetricDto = db.measures().insertMetric(m -> m.setKey(INT_METRIC.getKey()).setValueType(Metric.ValueType.INT.name()));
+ MetricDto bestValueMMetricDto = db.measures().insertMetric(m -> m.setKey(METRIC_WITH_BEST_VALUE.getKey()).setValueType(Metric.ValueType.INT.name()).setOptimizedBestValue(true).setBestValue(0.0));
+ metricRepository.add(stringMetricDto.getId(), STRING_METRIC);
+ metricRepository.add(intMetricDto.getId(), INT_METRIC);
+ metricRepository.add(bestValueMMetricDto.getId(), METRIC_WITH_BEST_VALUE);
+ }
+
+ @Test
+ public void persist_live_measures_of_project_analysis() {
+ prepareProject();
+
+ // the computed measures
+ measureRepository.addRawMeasure(REF_1, STRING_METRIC.getKey(), newMeasureBuilder().create("project-value"));
+ measureRepository.addRawMeasure(REF_2, STRING_METRIC.getKey(), newMeasureBuilder().create("module-value"));
+ measureRepository.addRawMeasure(REF_3, STRING_METRIC.getKey(), newMeasureBuilder().create("dir-value"));
+ measureRepository.addRawMeasure(REF_4, STRING_METRIC.getKey(), newMeasureBuilder().create("file-value"));
+
+ step().execute();
+
+ // all measures are persisted, from project to file
+ assertThat(db.countRowsOfTable("live_measures")).isEqualTo(4);
+ assertThat(selectMeasure("project-uuid", STRING_METRIC).get().getDataAsString()).isEqualTo("project-value");
+ assertThat(selectMeasure("module-uuid", STRING_METRIC).get().getDataAsString()).isEqualTo("module-value");
+ assertThat(selectMeasure("dir-uuid", STRING_METRIC).get().getDataAsString()).isEqualTo("dir-value");
+ assertThat(selectMeasure("file-uuid", STRING_METRIC).get().getDataAsString()).isEqualTo("file-value");
+ }
+
+ @Test
+ public void measures_without_value_are_not_persisted() {
+ prepareProject();
+ measureRepository.addRawMeasure(REF_1, STRING_METRIC.getKey(), newMeasureBuilder().createNoValue());
+ measureRepository.addRawMeasure(REF_1, INT_METRIC.getKey(), newMeasureBuilder().createNoValue());
+
+ step().execute();
+
+ assertThatMeasureIsNotPersisted("project-uuid", STRING_METRIC);
+ assertThatMeasureIsNotPersisted("project-uuid", INT_METRIC);
+ }
+
+ @Test
+ public void measures_on_leak_period_are_persisted() {
+ prepareProject();
+ measureRepository.addRawMeasure(REF_1, INT_METRIC.getKey(), newMeasureBuilder().setVariation(42.0).createNoValue());
+
+ step().execute();
+
+ LiveMeasureDto persistedMeasure = selectMeasure("project-uuid", INT_METRIC).get();
+ assertThat(persistedMeasure.getValue()).isNull();
+ assertThat(persistedMeasure.getVariation()).isEqualTo(42.0);
+ }
+
+ @Test
+ public void delete_measures_from_db_if_no_more_computed() {
+ prepareProject();
+ // measure to be updated
+ LiveMeasureDto measureOnFileInProject = insertMeasure("file-uuid", "project-uuid", INT_METRIC);
+ // measure to be deleted because on a file that has been deleted
+ LiveMeasureDto measureOnDeletedFileInProject = insertMeasure("deleted-file-in-project", "project-uuid", INT_METRIC);
+ // measure to be deleted because not computed anymore
+ LiveMeasureDto otherMeasureOnFileInProject = insertMeasure("file-uuid", "project-uuid", STRING_METRIC);
+ // measure in another project, not touched
+ LiveMeasureDto measureInOtherProject = insertMeasure("other-file-uuid", "other-project-uuid", INT_METRIC);
+ db.commit();
+
+ measureRepository.addRawMeasure(REF_4, INT_METRIC.getKey(), newMeasureBuilder().create(42));
+
+ step().execute();
+
+ assertThatMeasureHasValue(measureOnFileInProject, 42);
+ assertThatMeasureDoesNotExist(measureOnDeletedFileInProject);
+ assertThatMeasureDoesNotExist(otherMeasureOnFileInProject);
+ assertThatMeasureHasValue(measureInOtherProject, (int)measureInOtherProject.getValue().doubleValue());
+ }
+
+ @Test
+ public void do_not_persist_file_measures_with_best_value() {
+ prepareProject();
+ // measure to be deleted because new value matches the metric best value
+ LiveMeasureDto oldMeasure = insertMeasure("file-uuid", "project-uuid", INT_METRIC);
+ db.commit();
+
+ // project measure with metric best value -> persist with value 0
+ measureRepository.addRawMeasure(REF_1, METRIC_WITH_BEST_VALUE.getKey(), newMeasureBuilder().create(0));
+ // file measure with metric best value -> do not persist
+ measureRepository.addRawMeasure(REF_4, METRIC_WITH_BEST_VALUE.getKey(), newMeasureBuilder().create(0));
+
+ step().execute();
+
+ assertThatMeasureDoesNotExist(oldMeasure);
+ assertThatMeasureHasValue("project-uuid", METRIC_WITH_BEST_VALUE, 0);
+ }
+
+ @Test
+ public void persist_live_measures_of_portfolio_analysis() {
+ preparePortfolio();
+
+ // the computed measures
+ measureRepository.addRawMeasure(REF_1, STRING_METRIC.getKey(), newMeasureBuilder().create("view-value"));
+ measureRepository.addRawMeasure(REF_2, STRING_METRIC.getKey(), newMeasureBuilder().create("subview-value"));
+ measureRepository.addRawMeasure(REF_3, STRING_METRIC.getKey(), newMeasureBuilder().create("project-value"));
+
+ step().execute();
+
+ assertThat(db.countRowsOfTable("live_measures")).isEqualTo(3);
+ assertThat(selectMeasure("view-uuid", STRING_METRIC).get().getDataAsString()).isEqualTo("view-value");
+ assertThat(selectMeasure("subview-uuid", STRING_METRIC).get().getDataAsString()).isEqualTo("subview-value");
+ assertThat(selectMeasure("project-uuid", STRING_METRIC).get().getDataAsString()).isEqualTo("project-value");
+ }
+
+ private LiveMeasureDto insertMeasure(String componentUuid, String projectUuid, Metric metric) {
+ LiveMeasureDto measure = newLiveMeasure()
+ .setComponentUuid(componentUuid)
+ .setProjectUuid(projectUuid)
+ .setMetricId(metricRepository.getByKey(metric.getKey()).getId());
+ dbClient.liveMeasureDao().insertOrUpdate(db.getSession(), measure, null);
+ return measure;
+ }
+
+ private void assertThatMeasureHasValue(LiveMeasureDto template, int expectedValue) {
+ Optional<LiveMeasureDto> persisted = dbClient.liveMeasureDao().selectMeasure(db.getSession(),
+ template.getComponentUuid(), metricRepository.getById(template.getMetricId()).getKey());
+ assertThat(persisted).isPresent();
+ assertThat(persisted.get().getValue()).isEqualTo((double) expectedValue);
+ }
+
+ private void assertThatMeasureHasValue(String componentUuid, Metric metric, int expectedValue) {
+ Optional<LiveMeasureDto> persisted = dbClient.liveMeasureDao().selectMeasure(db.getSession(),
+ componentUuid, metric.getKey());
+ assertThat(persisted).isPresent();
+ assertThat(persisted.get().getValue()).isEqualTo((double) expectedValue);
+ }
+
+ private void assertThatMeasureDoesNotExist(LiveMeasureDto template) {
+ assertThat(dbClient.liveMeasureDao().selectMeasure(db.getSession(),
+ template.getComponentUuid(), metricRepository.getById(template.getMetricId()).getKey()))
+ .isEmpty();
+ }
+
+ private void prepareProject() {
+ // tree of components as defined by scanner report
+ Component project = ReportComponent.builder(PROJECT, REF_1).setUuid("project-uuid")
+ .addChildren(
+ ReportComponent.builder(MODULE, REF_2).setUuid("module-uuid")
+ .addChildren(
+ ReportComponent.builder(DIRECTORY, REF_3).setUuid("dir-uuid")
+ .addChildren(
+ ReportComponent.builder(FILE, REF_4).setUuid("file-uuid")
+ .build())
+ .build())
+ .build())
+ .build();
+ treeRootHolder.setRoot(project);
+ analysisMetadataHolder.setProject(Project.copyOf(project));
+
+ // components as persisted in db
+ ComponentDto projectDto = insertComponent("project-key", "project-uuid");
+ ComponentDto moduleDto = insertComponent("module-key", "module-uuid");
+ ComponentDto dirDto = insertComponent("dir-key", "dir-uuid");
+ ComponentDto fileDto = insertComponent("file-key", "file-uuid");
+ }
+
+ private void preparePortfolio() {
+ // tree of components
+ Component portfolio = ViewsComponent.builder(VIEW, REF_1).setUuid("view-uuid")
+ .addChildren(
+ ViewsComponent.builder(SUBVIEW, REF_2).setUuid("subview-uuid")
+ .addChildren(
+ ViewsComponent.builder(PROJECT_VIEW, REF_3).setUuid("project-uuid")
+ .build())
+ .build())
+ .build();
+ treeRootHolder.setRoot(portfolio);
+
+ // components as persisted in db
+ ComponentDto portfolioDto = insertComponent("view-key", "view-uuid");
+ ComponentDto subViewDto = insertComponent("subview-key", "subview-uuid");
+ ComponentDto projectDto = insertComponent("project-key", "project-uuid");
+ analysisMetadataHolder.setProject(Project.copyOf(portfolioDto));
+ }
+
+ private void assertThatMeasureIsNotPersisted(String componentUuid, Metric metric) {
+ assertThat(selectMeasure(componentUuid, metric)).isEmpty();
+ }
+
+ private Optional<LiveMeasureDto> selectMeasure(String componentUuid, Metric metric) {
+ return dbClient.liveMeasureDao().selectMeasure(db.getSession(), componentUuid, metric.getKey());
+ }
+
+ private ComponentDto insertComponent(String key, String uuid) {
+ ComponentDto componentDto = new ComponentDto()
+ .setOrganizationUuid("org1")
+ .setDbKey(key)
+ .setUuid(uuid)
+ .setUuidPath(uuid + ".")
+ .setRootUuid(uuid)
+ .setProjectUuid(uuid);
+ dbClient.componentDao().insert(db.getSession(), componentDto);
+ return componentDto;
+ }
+
+ @Override
+ protected ComputationStep step() {
+ return new PersistLiveMeasuresStep(dbClient, metricRepository, new MeasureToMeasureDto(analysisMetadataHolder, treeRootHolder), treeRootHolder, measureRepository);
+ }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStepTest.java
index 61d0099b157..36be1d480af 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStepTest.java
@@ -19,8 +19,7 @@
*/
package org.sonar.server.computation.task.projectanalysis.step;
-import java.util.List;
-import java.util.Map;
+import java.util.Optional;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -29,12 +28,10 @@ import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.rule.RuleDto;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.metric.MetricDto;
import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule;
import org.sonar.server.computation.task.projectanalysis.component.Component;
-import org.sonar.server.computation.task.projectanalysis.component.Developer;
-import org.sonar.server.computation.task.projectanalysis.component.DumbDeveloper;
-import org.sonar.server.computation.task.projectanalysis.component.MutableDbIdsRepositoryRule;
import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.server.computation.task.projectanalysis.component.ViewsComponent;
@@ -44,12 +41,6 @@ import org.sonar.server.computation.task.projectanalysis.metric.MetricRepository
import org.sonar.server.computation.task.step.ComputationStep;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION;
-import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION_KEY;
-import static org.sonar.api.measures.CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION;
-import static org.sonar.api.measures.CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION_KEY;
-import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION;
-import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY;
import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.DIRECTORY;
import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE;
import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.MODULE;
@@ -61,25 +52,18 @@ import static org.sonar.server.computation.task.projectanalysis.measure.Measure.
public class PersistMeasuresStepTest extends BaseStepTest {
- private static final String STRING_METRIC_KEY = "string-metric-key";
- private static final String DOUBLE_METRIC_KEY = "double-metric-key";
- private static final String INT_METRIC_KEY = "int-metric-key";
- private static final String LONG_METRIC_KEY = "long-metric-key";
- private static final String OPTIMIZED_METRIC_KEY = "optimized-metric-key";
-
- private static final Metric STRING_METRIC = new Metric.Builder(STRING_METRIC_KEY, "String metric", Metric.ValueType.STRING).create();
- private static final Metric DOUBLE_METRIC = new Metric.Builder(DOUBLE_METRIC_KEY, "Double metric", Metric.ValueType.FLOAT).create();
- private static final Metric INT_METRIC = new Metric.Builder(INT_METRIC_KEY, "int metric", Metric.ValueType.INT).create();
- private static final Metric LONG_METRIC = new Metric.Builder(LONG_METRIC_KEY, "long metric", Metric.ValueType.WORK_DUR).create();
-
- private static final int ROOT_REF = 1;
- private static final int INTERMEDIATE_1_REF = 2;
- private static final int INTERMEDIATE_2_REF = 3;
- private static final int LEAF_REF = 4;
+ private static final Metric STRING_METRIC = new Metric.Builder("string-metric", "String metric", Metric.ValueType.STRING).create();
+ private static final Metric INT_METRIC = new Metric.Builder("int-metric", "int metric", Metric.ValueType.INT).create();
+
private static final String ANALYSIS_UUID = "a1";
+ private static final int REF_1 = 1;
+ private static final int REF_2 = 2;
+ private static final int REF_3 = 3;
+ private static final int REF_4 = 4;
+
@Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
+ public DbTester db = DbTester.create(System2.INSTANCE);
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
@Rule
@@ -87,299 +71,161 @@ public class PersistMeasuresStepTest extends BaseStepTest {
@Rule
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
@Rule
- public MutableDbIdsRepositoryRule dbIdsRepository = MutableDbIdsRepositoryRule.create(treeRootHolder);
-
- @Rule
public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
- DbClient dbClient = dbTester.getDbClient();
- RuleDto rule;
- ComponentDto rootDto;
- ComponentDto intermediate1Dto;
- ComponentDto intermediate2Dto;
- ComponentDto leafDto;
-
- PersistMeasuresStep underTest;
+ private DbClient dbClient = db.getDbClient();
@Before
public void setUp() {
- underTest = new PersistMeasuresStep(dbClient, metricRepository, new MeasureToMeasureDto(dbIdsRepository, analysisMetadataHolder), treeRootHolder, measureRepository);
analysisMetadataHolder.setUuid(ANALYSIS_UUID);
- }
-
- private void setupReportComponents() {
- Component project = ReportComponent.builder(PROJECT, ROOT_REF).setUuid("root-uuid")
- .addChildren(
- ReportComponent.builder(MODULE, INTERMEDIATE_1_REF).setUuid("intermediate1-uuid")
- .addChildren(
- ReportComponent.builder(DIRECTORY, INTERMEDIATE_2_REF).setUuid("intermediate2-uuid")
- .addChildren(
- ReportComponent.builder(FILE, LEAF_REF).setUuid("leaf-uuid")
- .build())
- .build())
- .build())
- .build();
- treeRootHolder.setRoot(project);
-
- setupDbIds();
- }
-
- private void setupViewsComponents() {
- Component view = ViewsComponent.builder(VIEW, ROOT_REF).setUuid("root-uuid")
- .addChildren(
- ViewsComponent.builder(SUBVIEW, INTERMEDIATE_1_REF).setUuid("intermediate1-uuid")
- .addChildren(
- ViewsComponent.builder(SUBVIEW, INTERMEDIATE_2_REF).setUuid("intermediate2-uuid")
- .addChildren(
- ViewsComponent.builder(PROJECT_VIEW, LEAF_REF).setUuid("leaf-uuid")
- .build())
- .build())
- .build())
- .build();
- treeRootHolder.setRoot(view);
-
- setupDbIds();
- }
-
- private void setupDbIds() {
- rootDto = addComponent("root-key", "root-uuid");
- intermediate1Dto = addComponent("intermediate1-key", "intermediate1-uuid");
- intermediate2Dto = addComponent("intermediate2-key", "intermediate2-uuid");
- leafDto = addComponent("leaf-key", "leaf-uuid");
-
- setDbIds(ROOT_REF, rootDto.getId());
- setDbIds(INTERMEDIATE_1_REF, intermediate1Dto.getId());
- setDbIds(INTERMEDIATE_2_REF, intermediate2Dto.getId());
- setDbIds(LEAF_REF, leafDto.getId());
- }
-
- private void setDbIds(int componentRef, Long dbId) {
- dbIdsRepository.setComponentId(componentRef, dbId);
+ MetricDto stringMetricDto = db.measures().insertMetric(m -> m.setKey(STRING_METRIC.getKey()).setValueType(Metric.ValueType.STRING.name()));
+ MetricDto intMetricDto = db.measures().insertMetric(m -> m.setKey(INT_METRIC.getKey()).setValueType(Metric.ValueType.INT.name()));
+ metricRepository.add(stringMetricDto.getId(), STRING_METRIC);
+ metricRepository.add(intMetricDto.getId(), INT_METRIC);
}
@Test
- public void insert_measures_from_report() {
- setupReportComponents();
+ public void persist_measures_of_project_analysis() {
+ prepareProject();
- insertMeasures();
- }
+ // the computed measures
+ measureRepository.addRawMeasure(REF_1, STRING_METRIC.getKey(), newMeasureBuilder().create("project-value"));
+ measureRepository.addRawMeasure(REF_2, STRING_METRIC.getKey(), newMeasureBuilder().create("module-value"));
+ measureRepository.addRawMeasure(REF_3, STRING_METRIC.getKey(), newMeasureBuilder().create("dir-value"));
+ measureRepository.addRawMeasure(REF_4, STRING_METRIC.getKey(), newMeasureBuilder().create("file-value"));
- @Test
- public void insert_measures_from_views() {
- setupViewsComponents();
-
- insertMeasures();
- }
-
- private void insertMeasures() {
- int stringMetricId = 1;
- int doubleMetricId = 2;
- int intMetricId = 3;
- int longMetricId = 4;
- metricRepository.add(stringMetricId, STRING_METRIC);
- metricRepository.add(doubleMetricId, DOUBLE_METRIC);
- metricRepository.add(intMetricId, INT_METRIC);
- metricRepository.add(longMetricId, LONG_METRIC);
-
- measureRepository.addRawMeasure(ROOT_REF, STRING_METRIC_KEY, newMeasureBuilder().create("measure-data"));
- measureRepository.addRawMeasure(INTERMEDIATE_1_REF, INT_METRIC_KEY, newMeasureBuilder().create(12));
- measureRepository.addRawMeasure(INTERMEDIATE_2_REF, LONG_METRIC_KEY, newMeasureBuilder().create(9635L));
- measureRepository.addRawMeasure(LEAF_REF, DOUBLE_METRIC_KEY, newMeasureBuilder().create(123.123d, 1));
-
- underTest.execute();
-
- assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(4);
-
- List<Map<String, Object>> dtos = selectSnapshots();
-
- Map<String, Object> dto = dtos.get(0);
- assertThat(dto.get("analysisUuid")).isEqualTo(ANALYSIS_UUID);
- assertThat(dto.get("componentUuid")).isEqualTo(rootDto.uuid());
- assertThat(dto.get("metricId")).isEqualTo((long) stringMetricId);
- assertThat(dto.get("value")).isNull();
- assertThat(dto.get("textValue")).isEqualTo("measure-data");
- assertThat(dto.get("severity")).isNull();
-
- dto = dtos.get(1);
- assertThat(dto.get("analysisUuid")).isEqualTo(ANALYSIS_UUID);
- assertThat(dto.get("componentUuid")).isEqualTo(intermediate1Dto.uuid());
- assertThat(dto.get("metricId")).isEqualTo((long) intMetricId);
- assertValue(dto, 12d);
- assertThat(dto.get("textValue")).isNull();
- assertThat(dto.get("severity")).isNull();
-
- dto = dtos.get(2);
- assertThat(dto.get("analysisUuid")).isEqualTo(ANALYSIS_UUID);
- assertThat(dto.get("componentUuid")).isEqualTo(intermediate2Dto.uuid());
- assertThat(dto.get("metricId")).isEqualTo((long) longMetricId);
- assertValue(dto, 9635d);
- assertThat(dto.get("textValue")).isNull();
- assertThat(dto.get("severity")).isNull();
-
- dto = dtos.get(3);
- assertThat(dto.get("analysisUuid")).isEqualTo(ANALYSIS_UUID);
- assertThat(dto.get("componentUuid")).isEqualTo(leafDto.uuid());
- assertThat(dto.get("metricId")).isEqualTo((long) doubleMetricId);
- assertValue(dto, 123.1d);
- assertThat(dto.get("textValue")).isNull();
- assertThat(dto.get("severity")).isNull();
- }
+ execute(true);
- /**
- * Horrible trick to support oracle retuning number as BigDecimal and DbTester#select converting BigDecimal with no
- * scale to Long instead of Double when all other DBs will return a Double anyway.
- */
- private static void assertValue(Map<String, Object> dto, double expected) {
- Object actual = dto.get("value");
- if (expected % 1 == 0d && actual instanceof Long) {
- assertThat(actual).isEqualTo((long) expected);
- } else {
- assertThat(actual).isEqualTo(expected);
- }
+ // project, module and dir measures are persisted, but not file measures
+ assertThat(db.countRowsOfTable("project_measures")).isEqualTo(3);
+ assertThat(selectMeasure("project-uuid", STRING_METRIC).get().getData()).isEqualTo("project-value");
+ assertThat(selectMeasure("module-uuid", STRING_METRIC).get().getData()).isEqualTo("module-value");
+ assertThat(selectMeasure("dir-uuid", STRING_METRIC).get().getData()).isEqualTo("dir-value");
+ assertThatMeasuresAreNotPersisted("file-uuid");
}
@Test
- public void insert_measure_with_variations_from_report() {
- setupReportComponents();
-
- insertMeasureWithVariations();
- }
-
- @Test
- public void insert_measure_with_variations_from_views() {
- setupViewsComponents();
-
- insertMeasureWithVariations();
- }
-
- private void insertMeasureWithVariations() {
- metricRepository.add(1, DOUBLE_METRIC);
+ public void persist_measures_of_project_analysis_excluding_directories() {
+ prepareProject();
- measureRepository.addRawMeasure(ROOT_REF, DOUBLE_METRIC_KEY,
- newMeasureBuilder()
- .setVariation(1.1d)
- .create(10d, 1));
+ // the computed measures
+ measureRepository.addRawMeasure(REF_1, STRING_METRIC.getKey(), newMeasureBuilder().create("project-value"));
+ measureRepository.addRawMeasure(REF_2, STRING_METRIC.getKey(), newMeasureBuilder().create("module-value"));
+ measureRepository.addRawMeasure(REF_3, STRING_METRIC.getKey(), newMeasureBuilder().create("dir-value"));
+ measureRepository.addRawMeasure(REF_4, STRING_METRIC.getKey(), newMeasureBuilder().create("file-value"));
- underTest.execute();
+ execute(false);
- assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
- List<Map<String, Object>> dtos = selectSnapshots();
- Map<String, Object> dto = dtos.get(0);
- assertThat(dto.get("variation_value")).isEqualTo(1.1d);
+ // project, module and dir measures are persisted, but not file measures
+ assertThat(db.countRowsOfTable("project_measures")).isEqualTo(2);
+ assertThat(selectMeasure("project-uuid", STRING_METRIC).get().getData()).isEqualTo("project-value");
+ assertThat(selectMeasure("module-uuid", STRING_METRIC).get().getData()).isEqualTo("module-value");
+ assertThatMeasuresAreNotPersisted("dir-uuid");
+ assertThatMeasuresAreNotPersisted("file-uuid");
}
@Test
- public void bestValue_measure_of_bestValueOptimized_metrics_are_not_persisted() {
- setupReportComponents();
-
- metricRepository.add(1, new Metric.Builder(OPTIMIZED_METRIC_KEY, "Optimized metric", Metric.ValueType.BOOL).setOptimizedBestValue(true).setBestValue(1d).create());
+ public void measures_without_value_are_not_persisted() {
+ prepareProject();
+ measureRepository.addRawMeasure(REF_1, STRING_METRIC.getKey(), newMeasureBuilder().createNoValue());
+ measureRepository.addRawMeasure(REF_1, INT_METRIC.getKey(), newMeasureBuilder().createNoValue());
- measureRepository.addRawMeasure(LEAF_REF, OPTIMIZED_METRIC_KEY, newMeasureBuilder().create(true));
+ execute(false);
- underTest.execute();
-
- assertThat(selectSnapshots()).isEmpty();
+ assertThatMeasureIsNotPersisted("project-uuid", STRING_METRIC);
+ assertThatMeasureIsNotPersisted("project-uuid", INT_METRIC);
}
@Test
- public void empty_values_are_not_persisted() {
- setupReportComponents();
-
- metricRepository.add(1, STRING_METRIC);
- metricRepository.add(2, DOUBLE_METRIC);
-
- measureRepository.addRawMeasure(LEAF_REF, STRING_METRIC_KEY, newMeasureBuilder().createNoValue());
- measureRepository.addRawMeasure(LEAF_REF, DOUBLE_METRIC_KEY, newMeasureBuilder().createNoValue());
+ public void measures_on_leak_period_are_persisted() {
+ prepareProject();
+ measureRepository.addRawMeasure(REF_1, INT_METRIC.getKey(), newMeasureBuilder().setVariation(42.0).createNoValue());
- underTest.execute();
+ execute(false);
- assertThat(selectSnapshots()).isEmpty();
+ MeasureDto persistedMeasure = selectMeasure("project-uuid", INT_METRIC).get();
+ assertThat(persistedMeasure.getValue()).isNull();
+ assertThat(persistedMeasure.getVariation()).isEqualTo(42.0);
}
@Test
- public void do_not_insert_file_complexity_distribution_metric_on_files() {
- setupReportComponents();
+ public void persist_all_measures_of_portfolio_analysis() {
+ preparePortfolio();
- metricRepository.add(1, FILE_COMPLEXITY_DISTRIBUTION);
+ // the computed measures
+ measureRepository.addRawMeasure(REF_1, STRING_METRIC.getKey(), newMeasureBuilder().create("view-value"));
+ measureRepository.addRawMeasure(REF_2, STRING_METRIC.getKey(), newMeasureBuilder().create("subview-value"));
+ measureRepository.addRawMeasure(REF_3, STRING_METRIC.getKey(), newMeasureBuilder().create("project-value"));
- measureRepository.addRawMeasure(ROOT_REF, FILE_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0=1;2=10"));
- measureRepository.addRawMeasure(LEAF_REF, FILE_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0=1;2=10"));
+ execute(true);
- underTest.execute();
-
- assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
-
- List<Map<String, Object>> dtos = selectSnapshots();
-
- Map<String, Object> dto = dtos.get(0);
- assertThat(dto.get("analysisUuid")).isEqualTo(ANALYSIS_UUID);
- assertThat(dto.get("componentUuid")).isEqualTo(rootDto.uuid());
- assertThat(dto.get("textValue")).isEqualTo("0=1;2=10");
+ assertThat(db.countRowsOfTable("project_measures")).isEqualTo(3);
+ assertThat(selectMeasure("view-uuid", STRING_METRIC).get().getData()).isEqualTo("view-value");
+ assertThat(selectMeasure("subview-uuid", STRING_METRIC).get().getData()).isEqualTo("subview-value");
+ assertThat(selectMeasure("project-uuid", STRING_METRIC).get().getData()).isEqualTo("project-value");
}
- @Test
- public void do_not_insert_function_complexity_distribution_metric_on_files() {
- setupReportComponents();
-
- metricRepository.add(1, FUNCTION_COMPLEXITY_DISTRIBUTION);
-
- measureRepository.addRawMeasure(ROOT_REF, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0=1;2=10"));
- measureRepository.addRawMeasure(LEAF_REF, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0=1;2=10"));
-
- underTest.execute();
-
- assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
-
- List<Map<String, Object>> dtos = selectSnapshots();
+ private void prepareProject() {
+ // tree of components as defined by scanner report
+ Component project = ReportComponent.builder(PROJECT, REF_1).setUuid("project-uuid")
+ .addChildren(
+ ReportComponent.builder(MODULE, REF_2).setUuid("module-uuid")
+ .addChildren(
+ ReportComponent.builder(DIRECTORY, REF_3).setUuid("dir-uuid")
+ .addChildren(
+ ReportComponent.builder(FILE, REF_4).setUuid("file-uuid")
+ .build())
+ .build())
+ .build())
+ .build();
+ treeRootHolder.setRoot(project);
- Map<String, Object> dto = dtos.get(0);
- assertThat(dto.get("analysisUuid")).isEqualTo(ANALYSIS_UUID);
- assertThat(dto.get("componentUuid")).isEqualTo(rootDto.uuid());
- assertThat(dto.get("textValue")).isEqualTo("0=1;2=10");
+ // components as persisted in db
+ ComponentDto projectDto = insertComponent("project-key", "project-uuid");
+ ComponentDto moduleDto = insertComponent("module-key", "module-uuid");
+ ComponentDto dirDto = insertComponent("dir-key", "dir-uuid");
+ ComponentDto fileDto = insertComponent("file-key", "file-uuid");
+ db.components().insertSnapshot(projectDto, s -> s.setUuid(ANALYSIS_UUID));
}
- @Test
- public void do_not_insert_class_complexity_distribution_metric_on_files() {
- setupReportComponents();
-
- metricRepository.add(1, CLASS_COMPLEXITY_DISTRIBUTION);
-
- measureRepository.addRawMeasure(ROOT_REF, CLASS_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0=1;2=10"));
- measureRepository.addRawMeasure(LEAF_REF, CLASS_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0=1;2=10"));
-
- underTest.execute();
-
- assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
-
- List<Map<String, Object>> dtos = selectSnapshots();
+ private void preparePortfolio() {
+ // tree of components
+ Component portfolio = ViewsComponent.builder(VIEW, REF_1).setUuid("view-uuid")
+ .addChildren(
+ ViewsComponent.builder(SUBVIEW, REF_2).setUuid("subview-uuid")
+ .addChildren(
+ ViewsComponent.builder(PROJECT_VIEW, REF_3).setUuid("project-uuid")
+ .build())
+ .build())
+ .build();
+ treeRootHolder.setRoot(portfolio);
- Map<String, Object> dto = dtos.get(0);
- assertThat(dto.get("analysisUuid")).isEqualTo(ANALYSIS_UUID);
- assertThat(dto.get("componentUuid")).isEqualTo(rootDto.uuid());
- assertThat(dto.get("textValue")).isEqualTo("0=1;2=10");
+ // components as persisted in db
+ ComponentDto viewDto = insertComponent("view-key", "view-uuid");
+ ComponentDto subViewDto = insertComponent("subview-key", "subview-uuid");
+ ComponentDto projectDto = insertComponent("project-key", "project-uuid");
+ db.components().insertSnapshot(viewDto, s -> s.setUuid(ANALYSIS_UUID));
}
- @Test
- public void insert_developer_measure_from_report() {
- setupReportComponents();
-
- metricRepository.add(1, INT_METRIC);
-
- Developer developer = new DumbDeveloper("DEV1");
- dbIdsRepository.setDeveloperId(developer, 10);
- measureRepository.addRawMeasure(ROOT_REF, INT_METRIC_KEY, newMeasureBuilder().forDeveloper(developer).create(1));
+ private void assertThatMeasureIsNotPersisted(String componentUuid, Metric metric) {
+ assertThat(selectMeasure(componentUuid, metric)).isEmpty();
+ }
- underTest.execute();
+ private void assertThatMeasuresAreNotPersisted(String componentUuid) {
+ assertThatMeasureIsNotPersisted(componentUuid, STRING_METRIC);
+ assertThatMeasureIsNotPersisted(componentUuid, INT_METRIC);
+ }
- assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
- List<Map<String, Object>> dtos = selectSnapshots();
- Map<String, Object> dto = dtos.get(0);
+ private void execute(boolean persistDirectories) {
+ new PersistMeasuresStep(dbClient, metricRepository, new MeasureToMeasureDto(analysisMetadataHolder, treeRootHolder), treeRootHolder, measureRepository, persistDirectories)
+ .execute();
+ }
- assertValue(dto, 1d);
- assertThat(dto.get("developerId")).isEqualTo(10L);
+ private Optional<MeasureDto> selectMeasure(String componentUuid, Metric metric) {
+ return dbClient.measureDao().selectMeasure(db.getSession(), ANALYSIS_UUID, componentUuid, metric.getKey());
}
- private ComponentDto addComponent(String key, String uuid) {
+ private ComponentDto insertComponent(String key, String uuid) {
ComponentDto componentDto = new ComponentDto()
.setOrganizationUuid("org1")
.setDbKey(key)
@@ -387,23 +233,12 @@ public class PersistMeasuresStepTest extends BaseStepTest {
.setUuidPath(uuid + ".")
.setRootUuid(uuid)
.setProjectUuid(uuid);
- dbClient.componentDao().insert(dbTester.getSession(), componentDto);
+ dbClient.componentDao().insert(db.getSession(), componentDto);
return componentDto;
}
- private List<Map<String, Object>> selectSnapshots() {
- return dbTester
- .select(
- "SELECT analysis_uuid as \"analysisUuid\", component_uuid as \"componentUuid\", metric_id as \"metricId\", person_id as \"developerId\", "
- +
- "value as \"value\", text_value as \"textValue\", " +
- "variation_value_1 as \"variation_value\"" +
- "FROM project_measures " +
- "ORDER by id asc");
- }
-
@Override
protected ComputationStep step() {
- return underTest;
+ return new PersistMeasuresStep(dbClient, metricRepository, new MeasureToMeasureDto(analysisMetadataHolder, treeRootHolder), treeRootHolder, measureRepository, true);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/duplication/ws/ShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/duplication/ws/ShowActionTest.java
index c00e6f7f18b..b337a109258 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/duplication/ws/ShowActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/duplication/ws/ShowActionTest.java
@@ -29,7 +29,6 @@ import org.sonar.api.server.ws.WebService;
import org.sonar.api.web.UserRole;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.server.component.TestComponentFinder;
@@ -113,9 +112,8 @@ public class ShowActionTest {
ComponentDto project = db.components().insertMainBranch();
userSessionRule.addProjectPermission(UserRole.CODEVIEWER, project);
ComponentDto branch = db.components().insertProjectBranch(project);
- SnapshotDto analysis = db.components().insertSnapshot(newAnalysis(branch));
ComponentDto file = db.components().insertComponent(newFileDto(branch));
- db.measures().insertMeasure(file, analysis, dataMetric, m -> m.setData(format("<duplications>\n" +
+ db.measures().insertLiveMeasure(file, dataMetric, m -> m.setData(format("<duplications>\n" +
" <g>\n" +
" <b s=\"31\" l=\"5\" r=\"%s\"/>\n" +
" <b s=\"20\" l=\"5\" r=\"%s\"/>\n" +
@@ -224,14 +222,13 @@ public class ShowActionTest {
ComponentDto project = db.components().insertPrivateProject();
userSessionRule.addProjectPermission(UserRole.CODEVIEWER, project);
ComponentDto file = db.components().insertComponent(newFileDto(project).setDbKey("foo.js"));
- SnapshotDto snapshot = db.components().insertSnapshot(newAnalysis(project));
String xml = "<duplications>\n" +
" <g>\n" +
" <b s=\"31\" l=\"5\" r=\"foo.js\"/>\n" +
" <b s=\"20\" l=\"5\" r=\"foo.js\"/>\n" +
" </g>\n" +
"</duplications>\n";
- db.measures().insertMeasure(file, snapshot, dataMetric, m -> m.setData(xml));
+ db.measures().insertLiveMeasure(file, dataMetric, m -> m.setData(xml));
TestRequest request = requestFactory.apply(file);
TestResponse result = request.execute();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentActionTest.java
index 82468f874c4..026a92eb616 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentActionTest.java
@@ -29,7 +29,7 @@ import org.sonar.api.web.UserRole;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.server.component.TestComponentFinder;
@@ -52,7 +52,7 @@ import static org.sonar.api.utils.DateUtils.parseDateTime;
import static org.sonar.api.web.UserRole.USER;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newProjectCopy;
-import static org.sonar.db.component.SnapshotTesting.newAnalysis;
+import static org.sonar.server.computation.task.projectanalysis.metric.Metric.MetricType.INT;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.DEPRECATED_PARAM_COMPONENT_ID;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_ADDITIONAL_FIELDS;
@@ -92,10 +92,10 @@ public class ComponentActionTest {
@Test
public void provided_project() {
ComponentDto project = db.components().insertPrivateProject();
- logAsUser(project);
- insertNclocMetric();
+ userSession.addProjectPermission(UserRole.USER, project);
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
- ComponentWsResponse response = newRequest(project.getKey(), "ncloc");
+ ComponentWsResponse response = newRequest(project.getKey(), metric.getKey());
assertThat(response.getMetrics().getMetricsCount()).isEqualTo(1);
assertThat(response.getPeriods().getPeriodsCount()).isEqualTo(0);
@@ -105,13 +105,13 @@ public class ComponentActionTest {
@Test
public void without_additional_fields() {
ComponentDto project = db.components().insertPrivateProject();
- logAsUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
db.components().insertSnapshot(project);
- insertNclocMetric();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
String response = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
- .setParam(PARAM_METRIC_KEYS, "ncloc")
+ .setParam(PARAM_METRIC_KEYS, metric.getKey())
.execute().getInput();
assertThat(response)
@@ -122,12 +122,12 @@ public class ComponentActionTest {
@Test
public void branch() {
ComponentDto project = db.components().insertPrivateProject();
- logAsUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey("my_branch"));
SnapshotDto analysis = db.components().insertSnapshot(branch);
ComponentDto file = db.components().insertComponent(newFileDto(branch));
- MetricDto complexity = insertComplexityMetric();
- MeasureDto measure = db.measures().insertMeasure(file, analysis, complexity, m -> m.setValue(12.0d).setVariation(2.0d));
+ MetricDto complexity = db.measures().insertMetric(m1 -> m1.setKey("complexity").setValueType(INT.name()));
+ LiveMeasureDto measure = db.measures().insertLiveMeasure(file, complexity, m -> m.setValue(12.0d).setVariation(2.0d));
ComponentWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, file.getKey())
@@ -149,9 +149,9 @@ public class ComponentActionTest {
ComponentDto view = db.components().insertView();
db.components().insertSnapshot(view);
ComponentDto projectCopy = db.components().insertComponent(newProjectCopy("project-uuid-copy", project, view));
- insertNclocMetric();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
- ComponentWsResponse response = newRequest(projectCopy.getKey(), "ncloc");
+ ComponentWsResponse response = newRequest(projectCopy.getKey(), metric.getKey());
assertThat(response.getComponent().getRefId()).isEqualTo(project.uuid());
assertThat(response.getComponent().getRefKey()).isEqualTo(project.getKey());
@@ -160,11 +160,11 @@ public class ComponentActionTest {
@Test
public void return_deprecated_id_in_the_response() {
ComponentDto project = db.components().insertPrivateProject();
- logAsUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
db.components().insertSnapshot(project);
- insertNclocMetric();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
- ComponentWsResponse response = newRequest(project.getKey(), "ncloc");
+ ComponentWsResponse response = newRequest(project.getKey(), metric.getKey());
assertThat(response.getComponent().getId()).isEqualTo(project.uuid());
}
@@ -172,13 +172,13 @@ public class ComponentActionTest {
@Test
public void use_deprecated_component_id_parameter() {
ComponentDto project = db.components().insertPrivateProject();
- logAsUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
userSession.addProjectPermission(USER, project);
- insertNclocMetric();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
ComponentWsResponse response = ws.newRequest()
.setParam("componentId", project.uuid())
- .setParam(PARAM_METRIC_KEYS, "ncloc")
+ .setParam(PARAM_METRIC_KEYS, metric.getKey())
.executeProtobuf(ComponentWsResponse.class);
assertThat(response.getComponent().getKey()).isEqualTo(project.getDbKey());
@@ -187,13 +187,13 @@ public class ComponentActionTest {
@Test
public void use_deprecated_component_key_parameter() {
ComponentDto project = db.components().insertPrivateProject();
- logAsUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
userSession.addProjectPermission(USER, project);
- insertNclocMetric();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
ComponentWsResponse response = ws.newRequest()
.setParam("componentKey", project.getKey())
- .setParam(PARAM_METRIC_KEYS, "ncloc")
+ .setParam(PARAM_METRIC_KEYS, metric.getKey())
.executeProtobuf(ComponentWsResponse.class);
assertThat(response.getComponent().getKey()).isEqualTo(project.getDbKey());
@@ -202,12 +202,11 @@ public class ComponentActionTest {
@Test
public void metric_without_a_domain() {
ComponentDto project = db.components().insertPrivateProject();
- logAsUser(project);
- SnapshotDto analysis = db.getDbClient().snapshotDao().insert(db.getSession(), newAnalysis(project));
+ userSession.addProjectPermission(UserRole.USER, project);
MetricDto metricWithoutDomain = db.measures().insertMetric(m -> m
.setValueType(Measure.ValueType.INT.name())
.setDomain(null));
- db.measures().insertMeasure(project, analysis, metricWithoutDomain);
+ db.measures().insertLiveMeasure(project, metricWithoutDomain);
ComponentWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
@@ -215,36 +214,58 @@ public class ComponentActionTest {
.setParam(PARAM_ADDITIONAL_FIELDS, "metrics")
.executeProtobuf(ComponentWsResponse.class);
- assertThat(response.getComponent().getMeasures(0).getMetric()).isEqualTo(metricWithoutDomain.getKey());
+ assertThat(response.getComponent().getMeasuresList()).extracting(Measures.Measure::getMetric).containsExactly(metricWithoutDomain.getKey());
Common.Metric responseMetric = response.getMetrics().getMetrics(0);
assertThat(responseMetric.getKey()).isEqualTo(metricWithoutDomain.getKey());
assertThat(responseMetric.hasDomain()).isFalse();
}
@Test
+ public void use_best_values() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
+ userSession.addProjectPermission(UserRole.USER, project);
+ MetricDto metric = db.measures().insertMetric(m -> m
+ .setValueType(Measure.ValueType.INT.name())
+ .setBestValue(7.0d)
+ .setOptimizedBestValue(true)
+ .setDomain(null));
+
+ ComponentWsResponse response = ws.newRequest()
+ .setParam(PARAM_COMPONENT, file.getKey())
+ .setParam(PARAM_METRIC_KEYS, metric.getKey())
+ .setParam(PARAM_ADDITIONAL_FIELDS, "metrics")
+ .executeProtobuf(ComponentWsResponse.class);
+
+ assertThat(response.getComponent().getMeasuresList())
+ .extracting(Measures.Measure::getMetric, Measures.Measure::getValue)
+ .containsExactly(tuple(metric.getKey(), "7"));
+ }
+
+ @Test
public void fail_when_developer_is_not_found() {
ComponentDto project = db.components().insertPrivateProject();
- logAsUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
db.components().insertSnapshot(project);
- insertNclocMetric();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
expectedException.expect(NotFoundException.class);
- expectedException.expectMessage("Component id 'unknown-developer-id' not found");
+ expectedException.expectMessage("The Developer Cockpit feature has been dropped. The specified developer cannot be found.");
ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
- .setParam(PARAM_METRIC_KEYS, "ncloc")
+ .setParam(PARAM_METRIC_KEYS, metric.getKey())
.setParam(PARAM_DEVELOPER_ID, "unknown-developer-id").executeProtobuf(ComponentWsResponse.class);
}
@Test
public void fail_when_a_metric_is_not_found() {
ComponentDto project = db.components().insertPrivateProject();
- logAsUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
db.components().insertSnapshot(project);
- insertNclocMetric();
- insertComplexityMetric();
+ db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.name()));
+ db.measures().insertMetric(m -> m.setKey("complexity").setValueType(INT.name()));
expectedException.expect(NotFoundException.class);
expectedException.expectMessage("The following metric keys are not found: unknown-metric, another-unknown-metric");
@@ -255,7 +276,7 @@ public class ComponentActionTest {
@Test
public void fail_when_empty_metric_keys_parameter() {
ComponentDto project = db.components().insertPrivateProject();
- logAsUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
db.components().insertSnapshot(project);
expectedException.expect(BadRequestException.class);
@@ -269,39 +290,39 @@ public class ComponentActionTest {
userSession.logIn();
ComponentDto project = db.components().insertPrivateProject();
db.components().insertSnapshot(project);
- insertNclocMetric();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
expectedException.expect(ForbiddenException.class);
- newRequest(project.getKey(), "ncloc");
+ newRequest(project.getKey(), metric.getKey());
}
@Test
public void fail_when_component_does_not_exist() {
- insertNclocMetric();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
expectedException.expect(NotFoundException.class);
expectedException.expectMessage("Component key 'project-key' not found");
ws.newRequest()
.setParam(PARAM_COMPONENT, "project-key")
- .setParam(PARAM_METRIC_KEYS, "ncloc")
+ .setParam(PARAM_METRIC_KEYS, metric.getKey())
.execute();
}
@Test
public void fail_when_component_is_removed() {
ComponentDto project = db.components().insertPrivateProject(p -> p.setEnabled(false));
- logAsUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
userSession.addProjectPermission(USER, project);
- insertNclocMetric();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
expectedException.expect(NotFoundException.class);
expectedException.expectMessage(String.format("Component key '%s' not found", project.getKey()));
ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
- .setParam(PARAM_METRIC_KEYS, "ncloc")
+ .setParam(PARAM_METRIC_KEYS, metric.getKey())
.execute();
}
@@ -345,14 +366,14 @@ public class ComponentActionTest {
ComponentDto project = db.components().insertMainBranch(organization);
userSession.logIn().addProjectPermission(UserRole.USER, project);
ComponentDto branch = db.components().insertProjectBranch(project);
- insertNclocMetric();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
expectedException.expect(NotFoundException.class);
expectedException.expectMessage(format("Component key '%s' not found", branch.getDbKey()));
ws.newRequest()
.setParam(PARAM_COMPONENT, branch.getDbKey())
- .setParam(PARAM_METRIC_KEYS, "ncloc")
+ .setParam(PARAM_METRIC_KEYS, metric.getKey())
.execute();
}
@@ -362,21 +383,21 @@ public class ComponentActionTest {
ComponentDto project = db.components().insertMainBranch(organization);
userSession.logIn().addProjectPermission(UserRole.USER, project);
ComponentDto branch = db.components().insertProjectBranch(project);
- insertNclocMetric();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(INT.name()));
expectedException.expect(NotFoundException.class);
expectedException.expectMessage(format("Component id '%s' not found", branch.uuid()));
ws.newRequest()
.setParam(DEPRECATED_PARAM_COMPONENT_ID, branch.uuid())
- .setParam(PARAM_METRIC_KEYS, "ncloc")
+ .setParam(PARAM_METRIC_KEYS, metric.getKey())
.execute();
}
@Test
public void json_example() {
ComponentDto project = db.components().insertPrivateProject();
- logAsUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
SnapshotDto analysis = db.components().insertSnapshot(project,
s -> s.setPeriodDate(parseDateTime("2016-01-11T10:49:50+0100").getTime())
.setPeriodMode("previous_version")
@@ -386,66 +407,36 @@ public class ComponentActionTest {
.setName("ElementImpl.java")
.setLanguage("java")
.setPath("src/main/java/com/sonarsource/markdown/impl/ElementImpl.java"));
- MetricDto complexity = insertComplexityMetric();
- db.measures().insertMeasure(file, analysis, complexity,
- m -> m.setValue(12.0d)
- .setVariation(2.0d)
- .setData(null));
- MetricDto ncloc = insertNclocMetric();
- db.measures().insertMeasure(file, analysis, ncloc,
- m -> m.setValue(114.0d)
- .setVariation(3.0d)
- .setData(null));
- MetricDto newViolations = insertNewViolationMetric();
- db.measures().insertMeasure(file, analysis, newViolations,
- m -> m.setVariation(25.0d)
- .setValue(null)
- .setData(null));
-
- String response = ws.newRequest()
- .setParam(PARAM_COMPONENT, file.getKey())
- .setParam(PARAM_METRIC_KEYS, "ncloc, complexity, new_violations")
- .setParam(PARAM_ADDITIONAL_FIELDS, "metrics,periods")
- .execute()
- .getInput();
- assertJson(response).isSimilarTo(getClass().getResource("component-example.json"));
- }
-
- private ComponentWsResponse newRequest(String componentKey, String metricKeys) {
- return ws.newRequest()
- .setParam(PARAM_COMPONENT, componentKey)
- .setParam(PARAM_METRIC_KEYS, metricKeys)
- .setParam(PARAM_ADDITIONAL_FIELDS, "metrics,periods")
- .executeProtobuf(ComponentWsResponse.class);
- }
-
- private MetricDto insertNclocMetric() {
- return db.measures().insertMetric(m -> m.setKey("ncloc")
- .setShortName("Lines of code")
- .setDescription("Non Commenting Lines of Code")
- .setDomain("Size")
+ MetricDto complexity = db.measures().insertMetric(m -> m.setKey("complexity")
+ .setShortName("Complexity")
+ .setDescription("Cyclomatic complexity")
+ .setDomain("Complexity")
.setValueType("INT")
.setDirection(-1)
.setQualitative(false)
.setHidden(false)
.setUserManaged(false));
- }
+ db.measures().insertLiveMeasure(file, complexity,
+ m -> m.setValue(12.0d)
+ .setVariation(2.0d)
+ .setData((String) null));
- private MetricDto insertComplexityMetric() {
- return db.measures().insertMetric(m -> m.setKey("complexity")
- .setShortName("Complexity")
- .setDescription("Cyclomatic complexity")
- .setDomain("Complexity")
+ MetricDto ncloc = db.measures().insertMetric(m1 -> m1.setKey("ncloc")
+ .setShortName("Lines of code")
+ .setDescription("Non Commenting Lines of Code")
+ .setDomain("Size")
.setValueType("INT")
.setDirection(-1)
.setQualitative(false)
.setHidden(false)
.setUserManaged(false));
- }
+ db.measures().insertLiveMeasure(file, ncloc,
+ m -> m.setValue(114.0d)
+ .setVariation(3.0d)
+ .setData((String) null));
- private MetricDto insertNewViolationMetric() {
- return db.measures().insertMetric(m -> m.setKey("new_violations")
+ MetricDto newViolations = db.measures().insertMetric(m -> m.setKey("new_violations")
.setShortName("New issues")
.setDescription("New Issues")
.setDomain("Issues")
@@ -454,10 +445,26 @@ public class ComponentActionTest {
.setQualitative(true)
.setHidden(false)
.setUserManaged(false));
- }
+ db.measures().insertLiveMeasure(file, newViolations,
+ m -> m.setVariation(25.0d)
+ .setValue(null)
+ .setData((String) null));
- private void logAsUser(ComponentDto project) {
- userSession.addProjectPermission(UserRole.USER, project);
+ String response = ws.newRequest()
+ .setParam(PARAM_COMPONENT, file.getKey())
+ .setParam(PARAM_METRIC_KEYS, "ncloc, complexity, new_violations")
+ .setParam(PARAM_ADDITIONAL_FIELDS, "metrics,periods")
+ .execute()
+ .getInput();
+
+ assertJson(response).isSimilarTo(getClass().getResource("component-example.json"));
}
+ private ComponentWsResponse newRequest(String componentKey, String metricKeys) {
+ return ws.newRequest()
+ .setParam(PARAM_COMPONENT, componentKey)
+ .setParam(PARAM_METRIC_KEYS, metricKeys)
+ .setParam(PARAM_ADDITIONAL_FIELDS, "metrics,periods")
+ .executeProtobuf(ComponentWsResponse.class);
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java
index c5ab5886cda..8909b85dd04 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java
@@ -37,7 +37,7 @@ import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ResourceTypesRule;
import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.metric.MetricTesting;
import org.sonar.db.organization.OrganizationDto;
@@ -73,7 +73,6 @@ import static org.sonar.db.component.ComponentTesting.newDirectory;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newProjectCopy;
import static org.sonar.db.component.SnapshotTesting.newAnalysis;
-import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
import static org.sonar.server.measure.ws.ComponentTreeAction.LEAVES_STRATEGY;
import static org.sonar.server.measure.ws.ComponentTreeAction.METRIC_PERIOD_SORT;
import static org.sonar.server.measure.ws.ComponentTreeAction.METRIC_SORT;
@@ -142,33 +141,19 @@ public class ComponentTreeActionTest {
.setQualifier(DIRECTORY));
MetricDto complexity = insertComplexityMetric();
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(complexity, file1, analysis)
- .setValue(12.0d),
- newMeasureDto(complexity, dir, analysis)
- .setValue(35.0d)
- .setVariation(0.0d),
- newMeasureDto(complexity, project, analysis)
- .setValue(42.0d));
+ db.measures().insertLiveMeasure(file1, complexity, m -> m.setValue(12.0d));
+ db.measures().insertLiveMeasure(dir, complexity, m -> m.setValue(35.0d).setVariation(0.0d));
+ db.measures().insertLiveMeasure(project, complexity, m -> m.setValue(42.0d));
MetricDto ncloc = insertNclocMetric();
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(ncloc, file1, analysis)
- .setValue(114.0d),
- newMeasureDto(ncloc, dir, analysis)
- .setValue(217.0d)
- .setVariation(0.0d),
- newMeasureDto(ncloc, project, analysis)
- .setValue(1984.0d));
+ db.measures().insertLiveMeasure(file1, ncloc, m -> m.setValue(114.0d));
+ db.measures().insertLiveMeasure(dir, ncloc, m -> m.setValue(217.0d).setVariation(0.0d));
+ db.measures().insertLiveMeasure(project, ncloc, m -> m.setValue(1984.0d));
MetricDto newViolations = insertNewViolationsMetric();
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(newViolations, file1, analysis)
- .setVariation(25.0d),
- newMeasureDto(newViolations, dir, analysis)
- .setVariation(25.0d),
- newMeasureDto(newViolations, project, analysis)
- .setVariation(255.0d));
+ db.measures().insertLiveMeasure(file1, newViolations, m -> m.setVariation(25.0d));
+ db.measures().insertLiveMeasure(dir, newViolations, m -> m.setVariation(25.0d));
+ db.measures().insertLiveMeasure(project, newViolations, m -> m.setVariation(255.0d));
db.commit();
@@ -206,17 +191,16 @@ public class ComponentTreeActionTest {
.setPeriodMode("last_version")
.setPeriodDate(System.currentTimeMillis()));
userSession.anonymous().addProjectPermission(UserRole.USER, project);
- ComponentDto directoryDto = newDirectory(project, "directory-uuid", "path/to/directory").setName("directory-1");
- componentDb.insertComponent(directoryDto);
- ComponentDto file = newFileDto(directoryDto, null, "file-uuid").setName("file-1");
+ ComponentDto directory = newDirectory(project, "directory-uuid", "path/to/directory").setName("directory-1");
+ componentDb.insertComponent(directory);
+ ComponentDto file = newFileDto(directory, null, "file-uuid").setName("file-1");
componentDb.insertComponent(file);
MetricDto ncloc = insertNclocMetric();
MetricDto coverage = insertCoverageMetric();
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(ncloc, file, projectSnapshot).setValue(5.0d).setVariation(4.0d),
- newMeasureDto(coverage, file, projectSnapshot).setValue(15.5d),
- newMeasureDto(coverage, directoryDto, projectSnapshot).setValue(15.0d));
db.commit();
+ db.measures().insertLiveMeasure(file, ncloc, m -> m.setValue(5.0d).setVariation(4.0d));
+ db.measures().insertLiveMeasure(file, coverage, m -> m.setValue(15.5d));
+ db.measures().insertLiveMeasure(directory, coverage, m -> m.setValue(15.5d));
ComponentTreeWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
@@ -237,9 +221,9 @@ public class ComponentTreeActionTest {
ComponentDto project = db.components().insertPrivateProject();
SnapshotDto projectSnapshot = db.components().insertSnapshot(project);
userSession.anonymous().addProjectPermission(UserRole.USER, project);
- ComponentDto directoryDto = newDirectory(project, "directory-uuid", "path/to/directory").setName("directory-1");
- componentDb.insertComponent(directoryDto);
- ComponentDto file = newFileDto(directoryDto, null, "file-uuid").setName("file-1");
+ ComponentDto directory = newDirectory(project, "directory-uuid", "path/to/directory").setName("directory-1");
+ componentDb.insertComponent(directory);
+ ComponentDto file = newFileDto(directory, null, "file-uuid").setName("file-1");
componentDb.insertComponent(file);
MetricDto coverage = insertCoverageMetric();
dbClient.metricDao().insert(dbSession, MetricTesting.newMetricDto()
@@ -253,10 +237,9 @@ public class ComponentTreeActionTest {
.setOptimizedBestValue(true)
.setBestValue(1984.0d)
.setValueType(INT.name()));
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(coverage, file, projectSnapshot).setValue(15.5d),
- newMeasureDto(coverage, directoryDto, projectSnapshot).setValue(42.0d));
db.commit();
+ db.measures().insertLiveMeasure(file, coverage, m -> m.setValue(15.5d));
+ db.measures().insertLiveMeasure(directory, coverage, m -> m.setValue(42.0d));
ComponentTreeWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
@@ -284,17 +267,17 @@ public class ComponentTreeActionTest {
.setPeriodDate(parseDateTime("2016-01-11T10:49:50+0100").getTime())
.setPeriodMode("previous_version")
.setPeriodParam("1.0-SNAPSHOT"));
- ComponentDto directoryDto = newDirectory(project, "directory-uuid", "path/to/directory").setName("directory-1");
- componentDb.insertComponent(directoryDto);
- ComponentDto file = newFileDto(directoryDto, null, "file-uuid").setName("file-1");
+ ComponentDto directory = newDirectory(project, "directory-uuid", "path/to/directory").setName("directory-1");
+ componentDb.insertComponent(directory);
+ ComponentDto file = newFileDto(directory, null, "file-uuid").setName("file-1");
componentDb.insertComponent(file);
MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDto()
.setKey(NEW_SECURITY_RATING_KEY)
.setOptimizedBestValue(true)
.setBestValue(1d)
.setValueType(RATING.name()));
- dbClient.measureDao().insert(dbSession, newMeasureDto(metric, directoryDto, projectSnapshot).setVariation(2d));
db.commit();
+ db.measures().insertLiveMeasure(directory, metric, m -> m.setVariation(2d));
ComponentTreeWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
@@ -322,17 +305,16 @@ public class ComponentTreeActionTest {
ComponentDto file2 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-2").setName("file-1"));
ComponentDto file1 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-1").setName("file-1"));
MetricDto coverage = insertCoverageMetric();
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(coverage, file1, projectSnapshot).setValue(1.0d),
- newMeasureDto(coverage, file2, projectSnapshot).setValue(2.0d),
- newMeasureDto(coverage, file3, projectSnapshot).setValue(3.0d),
- newMeasureDto(coverage, file4, projectSnapshot).setValue(4.0d),
- newMeasureDto(coverage, file5, projectSnapshot).setValue(5.0d),
- newMeasureDto(coverage, file6, projectSnapshot).setValue(6.0d),
- newMeasureDto(coverage, file7, projectSnapshot).setValue(7.0d),
- newMeasureDto(coverage, file8, projectSnapshot).setValue(8.0d),
- newMeasureDto(coverage, file9, projectSnapshot).setValue(9.0d));
db.commit();
+ db.measures().insertLiveMeasure(file1, coverage, m -> m.setValue(1.0d));
+ db.measures().insertLiveMeasure(file2, coverage, m -> m.setValue(2.0d));
+ db.measures().insertLiveMeasure(file3, coverage, m -> m.setValue(3.0d));
+ db.measures().insertLiveMeasure(file4, coverage, m -> m.setValue(4.0d));
+ db.measures().insertLiveMeasure(file5, coverage, m -> m.setValue(5.0d));
+ db.measures().insertLiveMeasure(file6, coverage, m -> m.setValue(6.0d));
+ db.measures().insertLiveMeasure(file7, coverage, m -> m.setValue(7.0d));
+ db.measures().insertLiveMeasure(file8, coverage, m -> m.setValue(8.0d));
+ db.measures().insertLiveMeasure(file9, coverage, m -> m.setValue(9.0d));
ComponentTreeWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
@@ -361,11 +343,10 @@ public class ComponentTreeActionTest {
ComponentDto file2 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-2"));
MetricDto ncloc = newMetricDto().setKey("ncloc").setValueType(INT.name()).setDirection(1);
dbClient.metricDao().insert(dbSession, ncloc);
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(ncloc, file1, projectSnapshot).setValue(1.0d),
- newMeasureDto(ncloc, file2, projectSnapshot).setValue(2.0d),
- newMeasureDto(ncloc, file3, projectSnapshot).setValue(3.0d));
db.commit();
+ db.measures().insertLiveMeasure(file1, ncloc, m -> m.setValue(1.0d));
+ db.measures().insertLiveMeasure(file2, ncloc, m -> m.setValue(2.0d));
+ db.measures().insertLiveMeasure(file3, ncloc, m -> m.setValue(3.0d));
ComponentTreeWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
@@ -392,12 +373,11 @@ public class ComponentTreeActionTest {
componentDb.insertComponent(file4);
MetricDto ncloc = newMetricDto().setKey("ncloc").setValueType(INT.name()).setDirection(1);
dbClient.metricDao().insert(dbSession, ncloc);
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(ncloc, file1, projectSnapshot).setValue(1.0d),
- newMeasureDto(ncloc, file2, projectSnapshot).setValue(2.0d),
- newMeasureDto(ncloc, file3, projectSnapshot).setValue(3.0d),
- // measure on period 1
- newMeasureDto(ncloc, file4, projectSnapshot).setVariation(4.0d));
+ db.measures().insertLiveMeasure(file1, ncloc, m -> m.setData((String) null).setValue(1.0d).setVariation(null));
+ db.measures().insertLiveMeasure(file2, ncloc, m -> m.setData((String) null).setValue(2.0d).setVariation(null));
+ db.measures().insertLiveMeasure(file3, ncloc, m -> m.setData((String) null).setValue(3.0d).setVariation(null));
+ // measure on period 1
+ db.measures().insertLiveMeasure(file4, ncloc, m -> m.setData((String) null).setValue(null).setVariation(4.0d));
db.commit();
ComponentTreeWsResponse response = ws.newRequest()
@@ -423,11 +403,10 @@ public class ComponentTreeActionTest {
ComponentDto file2 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-2"));
MetricDto ncloc = newMetricDto().setKey("ncloc").setValueType(INT.name()).setDirection(1);
dbClient.metricDao().insert(dbSession, ncloc);
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(ncloc, file1, projectSnapshot).setVariation(1.0d),
- newMeasureDto(ncloc, file2, projectSnapshot).setVariation(2.0d),
- newMeasureDto(ncloc, file3, projectSnapshot).setVariation(3.0d));
db.commit();
+ db.measures().insertLiveMeasure(file1, ncloc, m -> m.setVariation(1.0d));
+ db.measures().insertLiveMeasure(file2, ncloc, m -> m.setVariation(2.0d));
+ db.measures().insertLiveMeasure(file3, ncloc, m -> m.setVariation(3.0d));
ComponentTreeWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
@@ -450,12 +429,11 @@ public class ComponentTreeActionTest {
ComponentDto file1 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-1"));
MetricDto ncloc = newMetricDto().setKey("new_ncloc").setValueType(INT.name()).setDirection(1);
dbClient.metricDao().insert(dbSession, ncloc);
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(ncloc, file1, projectSnapshot).setVariation(1.0d),
- newMeasureDto(ncloc, file2, projectSnapshot).setVariation(2.0d),
- newMeasureDto(ncloc, file3, projectSnapshot).setVariation(3.0d),
- // file 4 measure is on absolute value
- newMeasureDto(ncloc, file4, projectSnapshot).setValue(4.0d));
+ db.measures().insertLiveMeasure(file1, ncloc, m -> m.setData((String) null).setValue(null).setVariation(1.0d));
+ db.measures().insertLiveMeasure(file2, ncloc, m -> m.setData((String) null).setValue(null).setVariation(2.0d));
+ db.measures().insertLiveMeasure(file3, ncloc, m -> m.setData((String) null).setValue(null).setVariation(3.0d));
+ // file 4 measure is on absolute value
+ db.measures().insertLiveMeasure(file4, ncloc, m -> m.setData((String) null).setValue(4.0d).setVariation(null));
db.commit();
ComponentTreeWsResponse response = ws.newRequest()
@@ -492,12 +470,13 @@ public class ComponentTreeActionTest {
@Test
public void branch() {
- ComponentDto project = db.components().insertPrivateProject();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto project = db.components().insertPrivateProject(organization);
ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey("my_branch"));
SnapshotDto analysis = db.components().insertSnapshot(branch);
ComponentDto file = db.components().insertComponent(newFileDto(branch));
- MetricDto complexity = insertComplexityMetric();
- MeasureDto measure = db.measures().insertMeasure(file, analysis, complexity, m -> m.setValue(12.0d));
+ MetricDto complexity = db.measures().insertMetric(m -> m.setValueType(INT.name()));
+ LiveMeasureDto measure = db.measures().insertLiveMeasure(file, complexity, m -> m.setValue(12.0d));
ComponentTreeWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, file.getKey())
@@ -518,7 +497,7 @@ public class ComponentTreeActionTest {
SnapshotDto analysis = db.components().insertSnapshot(project);
ComponentDto file = componentDb.insertComponent(newFileDto(project));
MetricDto ncloc = insertNclocMetric();
- db.measures().insertMeasure(file, analysis, ncloc, m -> m.setValue(2d));
+ db.measures().insertLiveMeasure(file, ncloc, m -> m.setValue(2d));
ComponentTreeWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
@@ -565,7 +544,7 @@ public class ComponentTreeActionTest {
MetricDto metricWithoutDomain = db.measures().insertMetric(m -> m
.setValueType(Metric.ValueType.INT.name())
.setDomain(null));
- db.measures().insertMeasure(project, analysis, metricWithoutDomain);
+ db.measures().insertLiveMeasure(project, metricWithoutDomain);
ComponentTreeWsResponse result = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
@@ -582,11 +561,11 @@ public class ComponentTreeActionTest {
@Test
public void reference_component() {
ComponentDto project = db.components().insertPrivateProject();
- ComponentDto view = db.components().insertView();
+ ComponentDto view = db.components().insertPrivatePortfolio(db.getDefaultOrganization());
SnapshotDto viewAnalysis = db.components().insertSnapshot(view);
ComponentDto projectCopy = db.components().insertComponent(newProjectCopy(project, view));
MetricDto ncloc = insertNclocMetric();
- db.measures().insertMeasure(projectCopy, viewAnalysis, ncloc, m -> m.setValue(5d));
+ db.measures().insertLiveMeasure(projectCopy, ncloc, m -> m.setValue(5d));
ComponentTreeWsResponse result = ws.newRequest()
.setParam(PARAM_COMPONENT, view.getKey())
@@ -903,7 +882,7 @@ public class ComponentTreeActionTest {
.setShortName("Lines of code")
.setDescription("Non Commenting Lines of Code")
.setDomain("Size")
- .setValueType("INT")
+ .setValueType(INT.name())
.setDirection(-1)
.setQualitative(false)
.setHidden(false)
@@ -918,7 +897,7 @@ public class ComponentTreeActionTest {
.setShortName("Complexity")
.setDescription("Cyclomatic complexity")
.setDomain("Complexity")
- .setValueType("INT")
+ .setValueType(INT.name())
.setDirection(-1)
.setQualitative(false)
.setHidden(false)
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java
index 839a9c05864..438ca643ee6 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java
@@ -30,7 +30,7 @@ import org.sonar.api.measures.Metric.ValueType;
import org.sonar.api.resources.Qualifiers;
import org.sonar.core.util.Uuids;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
import static com.google.common.collect.Lists.newArrayList;
@@ -78,9 +78,9 @@ public class ComponentTreeSortTest {
// same number than path field
double currentValue = 9;
for (ComponentDto component : components) {
- measuresByComponentUuidAndMetric.put(component.uuid(), violationsMetric, createFromMeasureDto(new MeasureDto().setValue(currentValue)
+ measuresByComponentUuidAndMetric.put(component.uuid(), violationsMetric, createFromMeasureDto(new LiveMeasureDto().setValue(currentValue)
.setVariation(-currentValue)));
- measuresByComponentUuidAndMetric.put(component.uuid(), sqaleIndexMetric, createFromMeasureDto(new MeasureDto().setData(String.valueOf(currentValue))));
+ measuresByComponentUuidAndMetric.put(component.uuid(), sqaleIndexMetric, createFromMeasureDto(new LiveMeasureDto().setData(String.valueOf(currentValue))));
currentValue--;
}
}
@@ -167,7 +167,7 @@ public class ComponentTreeSortTest {
for (int i = 0; i < components.size(); i++) {
ComponentDto component = components.get(i);
String alertStatus = statuses.get(i % 3);
- measuresByComponentUuidAndMetric.put(component.uuid(), metrics.get(0), createFromMeasureDto(new MeasureDto().setData(alertStatus)));
+ measuresByComponentUuidAndMetric.put(component.uuid(), metrics.get(0), createFromMeasureDto(new LiveMeasureDto().setData(alertStatus)));
}
ComponentTreeRequest wsRequest = newRequest(newArrayList(METRIC_SORT, NAME_SORT), true, CoreMetrics.ALERT_STATUS_KEY);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java
index 535eeb75696..0ed7e63c25c 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java
@@ -20,29 +20,21 @@
package org.sonar.server.measure.ws;
import com.google.common.base.Joiner;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nullable;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.api.measures.Metric;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentTesting;
-import org.sonar.db.component.SnapshotDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.user.UserDto;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
@@ -57,16 +49,12 @@ import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
-import static org.sonar.api.utils.DateUtils.parseDateTime;
-import static org.sonar.db.component.ComponentTesting.newApplication;
+import static org.sonar.api.measures.Metric.ValueType.FLOAT;
+import static org.sonar.api.measures.Metric.ValueType.INT;
import static org.sonar.db.component.ComponentTesting.newDirectory;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newModuleDto;
import static org.sonar.db.component.ComponentTesting.newSubView;
-import static org.sonar.db.component.ComponentTesting.newView;
-import static org.sonar.db.component.SnapshotTesting.newAnalysis;
-import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
-import static org.sonar.db.metric.MetricTesting.newMetricDto;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_KEYS;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_PROJECT_KEYS;
@@ -77,25 +65,41 @@ public class SearchActionTest {
public ExpectedException expectedException = ExpectedException.none();
@Rule
- public UserSessionRule userSession = UserSessionRule.standalone();
+ public UserSessionRule userSession = UserSessionRule.standalone().logIn();
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
- private DbClient dbClient = db.getDbClient();
- private DbSession dbSession = db.getSession();
- private UserDto user;
- private WsActionTester ws = new WsActionTester(new SearchAction(userSession, dbClient));
-
- @Before
- public void setUp() throws Exception {
- user = db.users().insertUser("john");
- userSession.logIn(user);
- }
+ private WsActionTester ws = new WsActionTester(new SearchAction(userSession, db.getDbClient()));
@Test
public void json_example() {
- List<String> projectKeys = insertJsonExampleData();
+ OrganizationDto organization = db.organizations().insert();
+
+ ComponentDto project1 = db.components().insertPrivateProject(organization, p -> p.setDbKey("MY_PROJECT_1").setName("Project 1"));
+ ComponentDto project2 = db.components().insertPrivateProject(organization, p -> p.setDbKey("MY_PROJECT_2").setName("Project 2"));
+ ComponentDto project3 = db.components().insertPrivateProject(organization, p -> p.setDbKey("MY_PROJECT_3").setName("Project 3"));
+
+ userSession.addProjectPermission(UserRole.USER, project1);
+ userSession.addProjectPermission(UserRole.USER, project2);
+ userSession.addProjectPermission(UserRole.USER, project3);
+
+ MetricDto complexity = db.measures().insertMetric(m -> m.setKey("complexity").setValueType(INT.name()));
+ db.measures().insertLiveMeasure(project1, complexity, m -> m.setValue(12.0d));
+ db.measures().insertLiveMeasure(project2, complexity, m -> m.setValue(35.0d).setVariation(0.0d));
+ db.measures().insertLiveMeasure(project3, complexity, m -> m.setValue(42.0d));
+
+ MetricDto ncloc = db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.name()));
+ db.measures().insertLiveMeasure(project1, ncloc, m -> m.setValue(114.0d));
+ db.measures().insertLiveMeasure(project2, ncloc, m -> m.setValue(217.0d).setVariation(0.0d));
+ db.measures().insertLiveMeasure(project3, ncloc, m -> m.setValue(1984.0d));
+
+ MetricDto newViolations = db.measures().insertMetric(m -> m.setKey("new_violations").setValueType(INT.name()));
+ db.measures().insertLiveMeasure(project1, newViolations, m -> m.setVariation(25.0d));
+ db.measures().insertLiveMeasure(project2, newViolations, m -> m.setVariation(25.0d));
+ db.measures().insertLiveMeasure(project3, newViolations, m -> m.setVariation(255.0d));
+
+ List<String> projectKeys = Arrays.asList(project1.getDbKey(), project2.getDbKey(), project3.getDbKey());
String result = ws.newRequest()
.setParam(PARAM_PROJECT_KEYS, Joiner.on(",").join(projectKeys))
@@ -108,40 +112,34 @@ public class SearchActionTest {
@Test
public void return_measures() throws Exception {
- ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
- SnapshotDto projectSnapshot = db.components().insertProjectAndSnapshot(project);
- setBrowsePermissionOnUser(project);
- MetricDto coverage = insertCoverageMetric();
- dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, project, projectSnapshot).setValue(15.5d));
- db.commit();
+ ComponentDto project = db.components().insertPrivateProject(db.getDefaultOrganization());
+ userSession.addProjectPermission(UserRole.USER, project);
+ MetricDto coverage = db.measures().insertMetric(m -> m.setValueType(FLOAT.name()));
+ db.measures().insertLiveMeasure(project, coverage, m -> m.setValue(15.5d));
- SearchWsResponse result = call(singletonList(project.getDbKey()), singletonList("coverage"));
+ SearchWsResponse result = call(singletonList(project.getDbKey()), singletonList(coverage.getKey()));
List<Measure> measures = result.getMeasuresList();
assertThat(measures).hasSize(1);
Measure measure = measures.get(0);
- assertThat(measure.getMetric()).isEqualTo("coverage");
+ assertThat(measure.getMetric()).isEqualTo(coverage.getKey());
assertThat(measure.getValue()).isEqualTo("15.5");
}
@Test
public void return_measures_on_leak_period() throws Exception {
- ComponentDto project = ComponentTesting.newPrivateProjectDto(db.organizations().insert());
- SnapshotDto projectSnapshot = db.components().insertProjectAndSnapshot(project);
- setBrowsePermissionOnUser(project);
- MetricDto coverage = insertCoverageMetric();
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(coverage, project, projectSnapshot)
- .setValue(15.5d)
- .setVariation(10d));
- db.commit();
-
- SearchWsResponse result = call(singletonList(project.getDbKey()), singletonList("coverage"));
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto project = db.components().insertPrivateProject(organization);
+ userSession.addProjectPermission(UserRole.USER, project);
+ MetricDto coverage = db.measures().insertMetric(m -> m.setValueType(FLOAT.name()));
+ db.measures().insertLiveMeasure(project, coverage, m -> m.setValue(15.5d).setVariation(10d));
+
+ SearchWsResponse result = call(singletonList(project.getDbKey()), singletonList(coverage.getKey()));
List<Measure> measures = result.getMeasuresList();
assertThat(measures).hasSize(1);
Measure measure = measures.get(0);
- assertThat(measure.getMetric()).isEqualTo("coverage");
+ assertThat(measure.getMetric()).isEqualTo(coverage.getKey());
assertThat(measure.getValue()).isEqualTo("15.5");
assertThat(measure.getPeriods().getPeriodsValueList())
.extracting(Measures.PeriodValue::getIndex, Measures.PeriodValue::getValue)
@@ -150,130 +148,121 @@ public class SearchActionTest {
@Test
public void sort_by_metric_key_then_project_name() throws Exception {
- MetricDto coverage = insertCoverageMetric();
- MetricDto complexity = insertComplexityMetric();
- OrganizationDto organizationDto = db.organizations().insert();
- ComponentDto project1 = ComponentTesting.newPrivateProjectDto(organizationDto).setName("C");
- SnapshotDto projectSnapshot1 = db.components().insertProjectAndSnapshot(project1);
- ComponentDto project2 = ComponentTesting.newPrivateProjectDto(organizationDto).setName("A");
- SnapshotDto projectSnapshot2 = db.components().insertProjectAndSnapshot(project2);
- ComponentDto project3 = ComponentTesting.newPrivateProjectDto(organizationDto).setName("B");
- SnapshotDto projectSnapshot3 = db.components().insertProjectAndSnapshot(project3);
- setBrowsePermissionOnUser(project1, project2, project3);
- dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, project1, projectSnapshot1).setValue(5.5d));
- dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, project2, projectSnapshot2).setValue(6.5d));
- dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, project3, projectSnapshot3).setValue(7.5d));
- dbClient.measureDao().insert(dbSession, newMeasureDto(complexity, project1, projectSnapshot1).setValue(10d));
- dbClient.measureDao().insert(dbSession, newMeasureDto(complexity, project2, projectSnapshot2).setValue(15d));
- dbClient.measureDao().insert(dbSession, newMeasureDto(complexity, project3, projectSnapshot3).setValue(20d));
- db.commit();
-
- SearchWsResponse result = call(asList(project1.getDbKey(), project2.getDbKey(), project3.getDbKey()), asList("coverage", "complexity"));
+ MetricDto coverage = db.measures().insertMetric(m -> m.setKey("coverage").setValueType(FLOAT.name()));
+ MetricDto complexity = db.measures().insertMetric(m -> m.setKey("complexity").setValueType(INT.name()));
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto project1 = db.components().insertPrivateProject(organization, p -> p.setName("C"));
+ ComponentDto project2 = db.components().insertPrivateProject(organization, p -> p.setName("A"));
+ ComponentDto project3 = db.components().insertPrivateProject(organization, p -> p.setName("B"));
+ userSession.addProjectPermission(UserRole.USER, project1);
+ userSession.addProjectPermission(UserRole.USER, project2);
+ userSession.addProjectPermission(UserRole.USER, project3);
+ db.measures().insertLiveMeasure(project1, coverage, m -> m.setValue(5.5d));
+ db.measures().insertLiveMeasure(project2, coverage, m -> m.setValue(6.5d));
+ db.measures().insertLiveMeasure(project3, coverage, m -> m.setValue(7.5d));
+ db.measures().insertLiveMeasure(project1, complexity, m -> m.setValue(10d));
+ db.measures().insertLiveMeasure(project2, complexity, m -> m.setValue(15d));
+ db.measures().insertLiveMeasure(project3, complexity, m -> m.setValue(20d));
+
+ SearchWsResponse result = call(asList(project1.getDbKey(), project2.getDbKey(), project3.getDbKey()), asList(coverage.getKey(), complexity.getKey()));
assertThat(result.getMeasuresList()).extracting(Measure::getMetric, Measure::getComponent)
.containsExactly(
- tuple("complexity", project2.getDbKey()), tuple("complexity", project3.getDbKey()), tuple("complexity", project1.getDbKey()),
- tuple("coverage", project2.getDbKey()), tuple("coverage", project3.getDbKey()), tuple("coverage", project1.getDbKey()));
+ tuple(complexity.getKey(), project2.getDbKey()), tuple(complexity.getKey(), project3.getDbKey()), tuple(complexity.getKey(), project1.getDbKey()),
+ tuple(coverage.getKey(), project2.getDbKey()), tuple(coverage.getKey(), project3.getDbKey()), tuple(coverage.getKey(), project1.getDbKey()));
}
@Test
public void return_measures_on_view() throws Exception {
- ComponentDto view = newView(db.getDefaultOrganization());
- SnapshotDto viewSnapshot = db.components().insertProjectAndSnapshot(view);
- MetricDto coverage = insertCoverageMetric();
- dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, view, viewSnapshot).setValue(15.5d));
- db.commit();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto view = db.components().insertPrivatePortfolio(organization);
+ userSession.addProjectPermission(UserRole.USER, view);
+ MetricDto coverage = db.measures().insertMetric(m -> m.setValueType(FLOAT.name()));
+ db.measures().insertLiveMeasure(view, coverage, m -> m.setValue(15.5d));
- SearchWsResponse result = call(singletonList(view.getDbKey()), singletonList("coverage"));
+ SearchWsResponse result = call(singletonList(view.getDbKey()), singletonList(coverage.getKey()));
List<Measure> measures = result.getMeasuresList();
assertThat(measures).hasSize(1);
Measure measure = measures.get(0);
- assertThat(measure.getMetric()).isEqualTo("coverage");
+ assertThat(measure.getMetric()).isEqualTo(coverage.getKey());
assertThat(measure.getValue()).isEqualTo("15.5");
}
@Test
public void return_measures_on_application() throws Exception {
- ComponentDto application = newApplication(db.getDefaultOrganization());
- SnapshotDto viewSnapshot = db.components().insertProjectAndSnapshot(application);
- MetricDto coverage = insertCoverageMetric();
- dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, application, viewSnapshot).setValue(15.5d));
- db.commit();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto application = db.components().insertPrivateApplication(organization);
+ userSession.addProjectPermission(UserRole.USER, application);
+ MetricDto coverage = db.measures().insertMetric(m -> m.setValueType(FLOAT.name()));
+ db.measures().insertLiveMeasure(application, coverage, m -> m.setValue(15.5d));
- SearchWsResponse result = call(singletonList(application.getDbKey()), singletonList("coverage"));
+ SearchWsResponse result = call(singletonList(application.getDbKey()), singletonList(coverage.getKey()));
List<Measure> measures = result.getMeasuresList();
assertThat(measures).hasSize(1);
Measure measure = measures.get(0);
- assertThat(measure.getMetric()).isEqualTo("coverage");
+ assertThat(measure.getMetric()).isEqualTo(coverage.getKey());
assertThat(measure.getValue()).isEqualTo("15.5");
}
@Test
public void return_measures_on_sub_view() throws Exception {
- ComponentDto view = newView(db.getDefaultOrganization());
- SnapshotDto viewSnapshot = db.components().insertProjectAndSnapshot(view);
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto view = db.components().insertPrivatePortfolio(organization);
ComponentDto subView = db.components().insertComponent(newSubView(view));
- MetricDto coverage = insertCoverageMetric();
- dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, subView, viewSnapshot).setValue(15.5d));
- db.commit();
+ userSession.addProjectPermission(UserRole.USER, subView);
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(FLOAT.name()));
+ db.measures().insertLiveMeasure(subView, metric, m -> m.setValue(15.5d));
- SearchWsResponse result = call(singletonList(subView.getDbKey()), singletonList("coverage"));
+ SearchWsResponse result = call(singletonList(subView.getDbKey()), singletonList(metric.getKey()));
List<Measure> measures = result.getMeasuresList();
assertThat(measures).hasSize(1);
Measure measure = measures.get(0);
- assertThat(measure.getMetric()).isEqualTo("coverage");
+ assertThat(measure.getMetric()).isEqualTo(metric.getKey());
assertThat(measure.getValue()).isEqualTo("15.5");
}
@Test
public void only_returns_authorized_projects() {
- MetricDto metricDto = insertComplexityMetric();
- ComponentDto project1 = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
- SnapshotDto projectSnapshot1 = db.components().insertProjectAndSnapshot(project1);
- ComponentDto project2 = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
- SnapshotDto projectSnapshot2 = db.components().insertProjectAndSnapshot(project2);
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(metricDto, project1, projectSnapshot1).setValue(15.5d),
- newMeasureDto(metricDto, project2, projectSnapshot2).setValue(42.0d));
- db.commit();
- setBrowsePermissionOnUser(project1);
-
- SearchWsResponse result = call(asList(project1.getDbKey(), project2.getDbKey()), singletonList("complexity"));
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(FLOAT.name()));
+ ComponentDto project1 = db.components().insertPrivateProject(db.getDefaultOrganization());
+ ComponentDto project2 = db.components().insertPrivateProject(db.getDefaultOrganization());
+ db.measures().insertLiveMeasure(project1, metric, m -> m.setValue(15.5d));
+ db.measures().insertLiveMeasure(project2, metric, m -> m.setValue(42.0d));
+ Arrays.stream(new ComponentDto[]{project1}).forEach(p -> userSession.addProjectPermission(UserRole.USER, p));
+
+ SearchWsResponse result = call(asList(project1.getDbKey(), project2.getDbKey()), singletonList(metric.getKey()));
assertThat(result.getMeasuresList()).extracting(Measure::getComponent).containsOnly(project1.getDbKey());
}
@Test
public void do_not_verify_permissions_if_user_is_root() {
- MetricDto metricDto = insertComplexityMetric();
- ComponentDto project1 = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
- SnapshotDto projectSnapshot1 = db.components().insertProjectAndSnapshot(project1);
- dbClient.measureDao().insert(dbSession, newMeasureDto(metricDto, project1, projectSnapshot1).setValue(15.5d));
- db.commit();
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType(FLOAT.name()));
+ ComponentDto project1 = db.components().insertPrivateProject(db.getDefaultOrganization());
+ db.measures().insertLiveMeasure(project1, metric, m -> m.setValue(15.5d));
userSession.setNonRoot();
- SearchWsResponse result = call(asList(project1.getDbKey()), singletonList("complexity"));
+ SearchWsResponse result = call(singletonList(project1.getDbKey()), singletonList(metric.getKey()));
assertThat(result.getMeasuresCount()).isEqualTo(0);
userSession.setRoot();
- result = call(asList(project1.getDbKey()), singletonList("complexity"));
+ result = call(singletonList(project1.getDbKey()), singletonList(metric.getKey()));
assertThat(result.getMeasuresCount()).isEqualTo(1);
}
@Test
public void does_not_return_branch_when_using_db_key() {
- MetricDto coverage = insertCoverageMetric();
+ MetricDto coverage = db.measures().insertMetric(m -> m.setValueType(FLOAT.name()));
ComponentDto project = db.components().insertMainBranch();
ComponentDto branch = db.components().insertProjectBranch(project);
- SnapshotDto analysis = db.components().insertSnapshot(branch);
- db.measures().insertMeasure(branch, analysis, coverage, m -> m.setValue(10d));
- setBrowsePermissionOnUser(project);
+ db.measures().insertLiveMeasure(branch, coverage, m -> m.setValue(10d));
+ userSession.addProjectPermission(UserRole.USER, project);
- SearchWsResponse result = call(asList(branch.getDbKey()), singletonList(coverage.getKey()));
+ SearchWsResponse result = call(singletonList(branch.getDbKey()), singletonList(coverage.getKey()));
assertThat(result.getMeasuresList()).isEmpty();
}
@@ -281,7 +270,7 @@ public class SearchActionTest {
@Test
public void fail_if_no_metric() {
ComponentDto project = db.components().insertPrivateProject();
- setBrowsePermissionOnUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("The 'metricKeys' parameter is missing");
@@ -292,7 +281,7 @@ public class SearchActionTest {
@Test
public void fail_if_empty_metric() {
ComponentDto project = db.components().insertPrivateProject();
- setBrowsePermissionOnUser(project);
+ userSession.addProjectPermission(UserRole.USER, project);
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Metric keys must be provided");
@@ -303,33 +292,33 @@ public class SearchActionTest {
@Test
public void fail_if_unknown_metric() {
ComponentDto project = db.components().insertPrivateProject();
- setBrowsePermissionOnUser(project);
- insertComplexityMetric();
+ userSession.addProjectPermission(UserRole.USER, project);
+ MetricDto metric = db.measures().insertMetric();
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("The following metrics are not found: ncloc, violations");
- call(singletonList(project.getDbKey()), newArrayList("violations", "complexity", "ncloc"));
+ call(singletonList(project.getDbKey()), newArrayList("violations", metric.getKey(), "ncloc"));
}
@Test
public void fail_if_no_project() {
- insertComplexityMetric();
+ MetricDto metric = db.measures().insertMetric();
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Project keys must be provided");
- call(null, singletonList("complexity"));
+ call(null, singletonList(metric.getKey()));
}
@Test
public void fail_if_empty_project_key() {
- insertComplexityMetric();
+ MetricDto metric = db.measures().insertMetric();
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Project keys must be provided");
- call(emptyList(), singletonList("complexity"));
+ call(emptyList(), singletonList(metric.getKey()));
}
@Test
@@ -338,12 +327,12 @@ public class SearchActionTest {
.mapToObj(i -> db.components().insertPrivateProject())
.map(ComponentDto::getDbKey)
.collect(Collectors.toList());
- insertComplexityMetric();
+ MetricDto metric = db.measures().insertMetric();
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("101 projects provided, more than maximum authorized (100)");
- call(keys, singletonList("complexity"));
+ call(keys, singletonList(metric.getKey()));
}
@Test
@@ -352,48 +341,48 @@ public class SearchActionTest {
.mapToObj(i -> db.components().insertPrivateProject())
.map(ComponentDto::getDbKey)
.collect(Collectors.toList());
- insertComplexityMetric();
+ MetricDto metric = db.measures().insertMetric();
- call(keys, singletonList("complexity"));
+ call(keys, singletonList(metric.getKey()));
}
@Test
public void fail_if_module() {
ComponentDto project = db.components().insertPrivateProject();
ComponentDto module = db.components().insertComponent(newModuleDto(project));
- setBrowsePermissionOnUser(project);
- insertComplexityMetric();
+ userSession.addProjectPermission(UserRole.USER, project);
+ MetricDto metric = db.measures().insertMetric();
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Only component of qualifiers [TRK, APP, VW, SVW] are allowed");
- call(singletonList(module.getDbKey()), singletonList("complexity"));
+ call(singletonList(module.getDbKey()), singletonList(metric.getKey()));
}
@Test
public void fail_if_directory() {
ComponentDto project = db.components().insertPrivateProject();
ComponentDto dir = db.components().insertComponent(newDirectory(project, "dir"));
- setBrowsePermissionOnUser(project);
- insertComplexityMetric();
+ userSession.addProjectPermission(UserRole.USER, project);
+ MetricDto metric = db.measures().insertMetric();
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Only component of qualifiers [TRK, APP, VW, SVW] are allowed");
- call(singletonList(dir.getDbKey()), singletonList("complexity"));
+ call(singletonList(dir.getDbKey()), singletonList(metric.getKey()));
}
@Test
public void fail_if_file() {
ComponentDto project = db.components().insertPrivateProject();
ComponentDto file = db.components().insertComponent(newFileDto(project));
- setBrowsePermissionOnUser(project);
- insertComplexityMetric();
+ userSession.addProjectPermission(UserRole.USER, project);
+ MetricDto metric = db.measures().insertMetric();
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Only component of qualifiers [TRK, APP, VW, SVW] are allowed");
- call(singletonList(file.getDbKey()), singletonList("complexity"));
+ call(singletonList(file.getDbKey()), singletonList(metric.getKey()));
}
@Test
@@ -418,132 +407,4 @@ public class SearchActionTest {
}
return request.executeProtobuf(SearchWsResponse.class);
}
-
- private static MetricDto newMetricDtoWithoutOptimization() {
- return newMetricDto()
- .setWorstValue(null)
- .setBestValue(null)
- .setOptimizedBestValue(false)
- .setUserManaged(false);
- }
-
- private MetricDto insertNewViolationsMetric() {
- MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDtoWithoutOptimization()
- .setKey("new_violations")
- .setShortName("New issues")
- .setDescription("New Issues")
- .setDomain("Issues")
- .setValueType("INT")
- .setDirection(-1)
- .setQualitative(true)
- .setHidden(false)
- .setUserManaged(false)
- .setOptimizedBestValue(true)
- .setBestValue(0.0d));
- db.commit();
- return metric;
- }
-
- private MetricDto insertNclocMetric() {
- MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDtoWithoutOptimization()
- .setKey("ncloc")
- .setShortName("Lines of code")
- .setDescription("Non Commenting Lines of Code")
- .setDomain("Size")
- .setValueType("INT")
- .setDirection(-1)
- .setQualitative(false)
- .setHidden(false)
- .setUserManaged(false));
- db.commit();
- return metric;
- }
-
- private MetricDto insertComplexityMetric() {
- MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDtoWithoutOptimization()
- .setKey("complexity")
- .setShortName("Complexity")
- .setDescription("Cyclomatic complexity")
- .setDomain("Complexity")
- .setValueType("INT")
- .setDirection(-1)
- .setQualitative(false)
- .setHidden(false)
- .setUserManaged(false));
- db.commit();
- return metric;
- }
-
- private MetricDto insertCoverageMetric() {
- MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDtoWithoutOptimization()
- .setKey("coverage")
- .setShortName("Coverage")
- .setDescription("Code Coverage")
- .setDomain("Coverage")
- .setValueType(Metric.ValueType.FLOAT.name())
- .setDirection(1)
- .setQualitative(false)
- .setHidden(false)
- .setUserManaged(false));
- db.commit();
- return metric;
- }
-
- private List<String> insertJsonExampleData() {
- List<String> projectKeys = new ArrayList<>();
- OrganizationDto organizationDto = db.organizations().insert();
- ComponentDto project1 = ComponentTesting.newPrivateProjectDto(organizationDto).setDbKey("MY_PROJECT_1").setName("Project 1");
- ComponentDto project2 = ComponentTesting.newPrivateProjectDto(organizationDto).setDbKey("MY_PROJECT_2").setName("Project 2");
- ComponentDto project3 = ComponentTesting.newPrivateProjectDto(organizationDto).setDbKey("MY_PROJECT_3").setName("Project 3");
- projectKeys.addAll(asList(project1.getDbKey(), project2.getDbKey(), project3.getDbKey()));
- db.components().insertComponents(project1, project2, project3);
- SnapshotDto projectSnapshot1 = dbClient.snapshotDao().insert(dbSession, newAnalysis(project1)
- .setPeriodDate(parseDateTime("2016-01-11T10:49:50+0100").getTime())
- .setPeriodMode("previous_version")
- .setPeriodParam("1.0-SNAPSHOT"));
- SnapshotDto projectSnapshot2 = dbClient.snapshotDao().insert(dbSession, newAnalysis(project2)
- .setPeriodDate(parseDateTime("2016-01-11T10:49:50+0100").getTime())
- .setPeriodMode("previous_version")
- .setPeriodParam("1.0-SNAPSHOT"));
- SnapshotDto projectSnapshot3 = dbClient.snapshotDao().insert(dbSession, newAnalysis(project3)
- .setPeriodDate(parseDateTime("2016-01-11T10:49:50+0100").getTime())
- .setPeriodMode("previous_version")
- .setPeriodParam("1.0-SNAPSHOT"));
-
- MetricDto complexity = insertComplexityMetric();
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(complexity, project1, projectSnapshot1)
- .setValue(12.0d),
- newMeasureDto(complexity, project2, projectSnapshot2)
- .setValue(35.0d)
- .setVariation(0.0d),
- newMeasureDto(complexity, project3, projectSnapshot3)
- .setValue(42.0d));
-
- MetricDto ncloc = insertNclocMetric();
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(ncloc, project1, projectSnapshot1)
- .setValue(114.0d),
- newMeasureDto(ncloc, project2, projectSnapshot2)
- .setValue(217.0d)
- .setVariation(0.0d),
- newMeasureDto(ncloc, project3, projectSnapshot3)
- .setValue(1984.0d));
-
- MetricDto newViolations = insertNewViolationsMetric();
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(newViolations, project1, projectSnapshot1)
- .setVariation(25.0d),
- newMeasureDto(newViolations, project2, projectSnapshot2)
- .setVariation(25.0d),
- newMeasureDto(newViolations, project3, projectSnapshot3)
- .setVariation(255.0d));
- db.commit();
- setBrowsePermissionOnUser(project1, project2, project3);
- return projectKeys;
- }
-
- private void setBrowsePermissionOnUser(ComponentDto... projects) {
- Arrays.stream(projects).forEach(p -> userSession.addProjectPermission(UserRole.USER, p));
- }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchHistoryActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchHistoryActionTest.java
index f778f3fdac0..1544e8a77b3 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchHistoryActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchHistoryActionTest.java
@@ -265,20 +265,6 @@ public class SearchHistoryActionTest {
}
@Test
- public void do_not_return_developer_measures() {
- wsRequest.setMetrics(singletonList(complexityMetric.getKey()));
- dbClient.measureDao().insert(dbSession, newMeasureDto(complexityMetric, project, analysis).setDeveloperId(42L));
- db.commit();
-
- SearchHistoryResponse result = call();
-
- assertThat(result.getMeasuresCount()).isEqualTo(1);
- assertThat(result.getMeasures(0).getHistoryCount()).isEqualTo(1);
- assertThat(result.getMeasures(0).getHistory(0).hasDate()).isTrue();
- assertThat(result.getMeasures(0).getHistory(0).hasValue()).isFalse();
- }
-
- @Test
public void branch() {
ComponentDto project = db.components().insertPrivateProject();
userSession.addProjectPermission(UserRole.USER, project);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchMyProjectsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchMyProjectsActionTest.java
index d0d986e8b0e..14148994fce 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchMyProjectsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchMyProjectsActionTest.java
@@ -52,7 +52,7 @@ import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
import static org.sonar.db.component.ComponentTesting.newView;
import static org.sonar.db.component.SnapshotTesting.newAnalysis;
-import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
+import static org.sonar.db.measure.MeasureTesting.newLiveMeasure;
import static org.sonar.db.metric.MetricTesting.newMetricDto;
import static org.sonar.db.user.UserTesting.newUserDto;
import static org.sonar.test.JsonAssert.assertJson;
@@ -95,8 +95,8 @@ public class SearchMyProjectsActionTest {
long anotherTime = DateUtils.parseDateTime("2016-06-11T14:25:53+0000").getTime();
SnapshotDto jdk7Snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(jdk7).setCreatedAt(oneTime));
SnapshotDto cLangSnapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(cLang).setCreatedAt(anotherTime));
- dbClient.measureDao().insert(dbSession, newMeasureDto(alertStatusMetric, jdk7, jdk7Snapshot).setData(Level.ERROR.name()));
- dbClient.measureDao().insert(dbSession, newMeasureDto(alertStatusMetric, cLang, cLangSnapshot).setData(Level.OK.name()));
+ dbClient.liveMeasureDao().insert(dbSession, newLiveMeasure(jdk7, alertStatusMetric).setData(Level.ERROR.name()));
+ dbClient.liveMeasureDao().insert(dbSession, newLiveMeasure(cLang, alertStatusMetric).setData(Level.OK.name()));
db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7);
db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, cLang);
db.commit();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java
index 2bf2c728243..242bbc6b553 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java
@@ -51,6 +51,7 @@ import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.sonar.db.component.SnapshotTesting.newAnalysis;
+import static org.sonar.db.measure.MeasureTesting.newLiveMeasure;
import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
import static org.sonar.db.metric.MetricTesting.newMetricDto;
import static org.sonar.test.JsonAssert.assertJson;
@@ -71,17 +72,22 @@ public class ProjectStatusActionTest {
private WsActionTester ws;
private DbClient dbClient;
private DbSession dbSession;
+ private MetricDto gateDetailsMetric;
@Before
public void setUp() {
dbClient = db.getDbClient();
dbSession = db.getSession();
+ gateDetailsMetric = dbClient.metricDao().insert(dbSession, newMetricDto()
+ .setEnabled(true)
+ .setKey(CoreMetrics.QUALITY_GATE_DETAILS_KEY));
+
ws = new WsActionTester(new ProjectStatusAction(dbClient, TestComponentFinder.from(db), userSession));
}
@Test
- public void definition() throws Exception {
+ public void test_definition() throws Exception {
WebService.Action def = ws.getDef();
assertThat(def.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("analysisId", "projectKey", "projectId");
assertThat(def.changelog()).extracting(Change::getVersion, Change::getDescription).containsExactly(
@@ -90,7 +96,7 @@ public class ProjectStatusActionTest {
}
@Test
- public void json_example() throws IOException {
+ public void test_json_example() throws IOException {
ComponentDto project = db.components().insertPrivateProject(db.organizations().insert());
userSession.addProjectPermission(UserRole.USER, project);
@@ -98,11 +104,8 @@ public class ProjectStatusActionTest {
.setPeriodMode("last_version")
.setPeriodParam("2015-12-07")
.setPeriodDate(956789123987L));
- MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDto()
- .setEnabled(true)
- .setKey(CoreMetrics.QUALITY_GATE_DETAILS_KEY));
dbClient.measureDao().insert(dbSession,
- newMeasureDto(metric, project, snapshot)
+ newMeasureDto(gateDetailsMetric, project, snapshot)
.setData(IOUtils.toString(getClass().getResource("ProjectStatusActionTest/measure_data.json"))));
dbSession.commit();
@@ -114,17 +117,43 @@ public class ProjectStatusActionTest {
}
@Test
- public void return_status_by_project_id() throws IOException {
+ public void return_past_status_when_project_is_referenced_by_past_analysis_id() throws IOException {
ComponentDto project = db.components().insertPrivateProject(db.organizations().insert());
- SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(project)
+ SnapshotDto pastAnalysis = dbClient.snapshotDao().insert(dbSession, newAnalysis(project)
+ .setLast(false)
.setPeriodMode("last_version")
.setPeriodParam("2015-12-07")
.setPeriodDate(956789123987L));
- MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDto()
- .setEnabled(true)
- .setKey(CoreMetrics.QUALITY_GATE_DETAILS_KEY));
+ SnapshotDto lastAnalysis = dbClient.snapshotDao().insert(dbSession, newAnalysis(project)
+ .setLast(true)
+ .setPeriodMode("last_version")
+ .setPeriodParam("2016-12-07")
+ .setPeriodDate(1_500L));
dbClient.measureDao().insert(dbSession,
- newMeasureDto(metric, project, snapshot)
+ newMeasureDto(gateDetailsMetric, project, pastAnalysis)
+ .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionTest/measure_data.json"))));
+ dbClient.measureDao().insert(dbSession,
+ newMeasureDto(gateDetailsMetric, project, lastAnalysis)
+ .setData("not_used"));
+ dbSession.commit();
+ userSession.addProjectPermission(UserRole.USER, project);
+
+ String response = ws.newRequest()
+ .setParam(PARAM_ANALYSIS_ID, pastAnalysis.getUuid())
+ .execute().getInput();
+
+ assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json"));
+ }
+
+ @Test
+ public void return_live_status_when_project_is_referenced_by_its_id() throws IOException {
+ ComponentDto project = db.components().insertPrivateProject(db.organizations().insert());
+ dbClient.snapshotDao().insert(dbSession, newAnalysis(project)
+ .setPeriodMode("last_version")
+ .setPeriodParam("2015-12-07")
+ .setPeriodDate(956789123987L));
+ dbClient.liveMeasureDao().insert(dbSession,
+ newLiveMeasure(project, gateDetailsMetric)
.setData(IOUtils.toString(getClass().getResource("ProjectStatusActionTest/measure_data.json"))));
dbSession.commit();
userSession.addProjectPermission(UserRole.USER, project);
@@ -137,17 +166,14 @@ public class ProjectStatusActionTest {
}
@Test
- public void return_status_by_project_key() throws IOException {
+ public void return_live_status_when_project_is_referenced_by_its_key() throws IOException {
ComponentDto project = db.components().insertComponent(ComponentTesting.newPrivateProjectDto(db.organizations().insert()).setDbKey("project-key"));
- SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(project)
+ dbClient.snapshotDao().insert(dbSession, newAnalysis(project)
.setPeriodMode("last_version")
.setPeriodParam("2015-12-07")
.setPeriodDate(956789123987L));
- MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDto()
- .setEnabled(true)
- .setKey(CoreMetrics.QUALITY_GATE_DETAILS_KEY));
- dbClient.measureDao().insert(dbSession,
- newMeasureDto(metric, project, snapshot)
+ dbClient.liveMeasureDao().insert(dbSession,
+ newLiveMeasure(project, gateDetailsMetric)
.setData(IOUtils.toString(getClass().getResource("ProjectStatusActionTest/measure_data.json"))));
dbSession.commit();
userSession.addProjectPermission(UserRole.USER, project);
@@ -160,24 +186,24 @@ public class ProjectStatusActionTest {
}
@Test
- public void return_undefined_status_if_measure_is_not_found() {
+ public void return_undefined_status_if_specified_analysis_is_not_found() {
ComponentDto project = db.components().insertPrivateProject(db.organizations().insert());
SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(project));
dbSession.commit();
userSession.addProjectPermission(UserRole.USER, project);
- ProjectStatusResponse result = call(snapshot.getUuid());
+ ProjectStatusResponse result = callByAnalysisId(snapshot.getUuid());
assertThat(result.getProjectStatus().getStatus()).isEqualTo(Status.NONE);
assertThat(result.getProjectStatus().getConditionsCount()).isEqualTo(0);
}
@Test
- public void return_undefined_status_if_snapshot_is_not_found() {
+ public void return_undefined_status_if_project_is_not_analyzed() {
ComponentDto project = db.components().insertPrivateProject(db.organizations().insert());
userSession.addProjectPermission(UserRole.USER, project);
- ProjectStatusResponse result = callByProjectUuid(project.uuid());
+ ProjectStatusResponse result = callByProjectId(project.uuid());
assertThat(result.getProjectStatus().getStatus()).isEqualTo(Status.NONE);
assertThat(result.getProjectStatus().getConditionsCount()).isEqualTo(0);
@@ -190,7 +216,7 @@ public class ProjectStatusActionTest {
dbSession.commit();
userSession.addProjectPermission(UserRole.ADMIN, project);
- call(snapshot.getUuid());
+ callByAnalysisId(snapshot.getUuid());
}
@Test
@@ -200,7 +226,7 @@ public class ProjectStatusActionTest {
dbSession.commit();
userSession.addProjectPermission(UserRole.USER, project);
- call(snapshot.getUuid());
+ callByAnalysisId(snapshot.getUuid());
}
@Test
@@ -210,7 +236,7 @@ public class ProjectStatusActionTest {
expectedException.expect(NotFoundException.class);
expectedException.expectMessage("Analysis with id 'task-uuid' is not found");
- call(ANALYSIS_ID);
+ callByAnalysisId(ANALYSIS_ID);
}
@Test
@@ -222,7 +248,7 @@ public class ProjectStatusActionTest {
expectedException.expect(ForbiddenException.class);
- call(snapshot.getUuid());
+ callByAnalysisId(snapshot.getUuid());
}
@Test
@@ -280,13 +306,13 @@ public class ProjectStatusActionTest {
.execute();
}
- private ProjectStatusResponse call(String taskId) {
+ private ProjectStatusResponse callByAnalysisId(String taskId) {
return ws.newRequest()
- .setParam("analysisId", taskId)
+ .setParam(PARAM_ANALYSIS_ID, taskId)
.executeProtobuf(ProjectStatusResponse.class);
}
- private ProjectStatusResponse callByProjectUuid(String projectUuid) {
+ private ProjectStatusResponse callByProjectId(String projectUuid) {
return ws.newRequest()
.setParam(PARAM_PROJECT_ID, projectUuid)
.executeProtobuf(ProjectStatusResponse.class);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest.java
index 62f96974cf8..816bac90633 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest.java
@@ -19,9 +19,9 @@
*/
package org.sonar.server.qualitygate.ws;
-import com.google.common.base.Optional;
import java.io.IOException;
import java.util.List;
+import java.util.Optional;
import javax.annotation.Nullable;
import org.apache.commons.io.IOUtils;
import org.junit.Rule;
@@ -150,6 +150,6 @@ public class QualityGateDetailsFormatterTest {
}
private static QualityGateDetailsFormatter newQualityGateDetailsFormatter(@Nullable String measureData, @Nullable SnapshotDto snapshotDto) {
- return new QualityGateDetailsFormatter(Optional.fromNullable(measureData), Optional.fromNullable(snapshotDto));
+ return new QualityGateDetailsFormatter(Optional.ofNullable(measureData), Optional.ofNullable(snapshotDto));
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java b/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java
index b62eef280f1..f82a9649e93 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java
@@ -41,7 +41,6 @@ import org.sonar.core.platform.PluginRepository;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.server.es.EsTester;
import org.sonar.server.measure.index.ProjectMeasuresIndex;
@@ -126,18 +125,16 @@ public class TelemetryDaemonTest {
ComponentDto project1 = db.components().insertMainBranch(db.getDefaultOrganization());
ComponentDto project1Branch = db.components().insertProjectBranch(project1);
- SnapshotDto analysis1 = db.components().insertSnapshot(project1);
- db.measures().insertMeasure(project1, analysis1, lines, m -> m.setValue(200d));
- db.measures().insertMeasure(project1, analysis1, ncloc, m -> m.setValue(100d));
- db.measures().insertMeasure(project1, analysis1, coverage, m -> m.setValue(80d));
- db.measures().insertMeasure(project1, analysis1, nclocDistrib, m -> m.setData("java=200;js=50"));
+ db.measures().insertLiveMeasure(project1, lines, m -> m.setValue(200d));
+ db.measures().insertLiveMeasure(project1, ncloc, m -> m.setValue(100d));
+ db.measures().insertLiveMeasure(project1, coverage, m -> m.setValue(80d));
+ db.measures().insertLiveMeasure(project1, nclocDistrib, m -> m.setValue(null).setData("java=200;js=50"));
ComponentDto project2 = db.components().insertMainBranch(db.getDefaultOrganization());
- SnapshotDto analysis2 = db.components().insertSnapshot(project2);
- db.measures().insertMeasure(project2, analysis2, lines, m -> m.setValue(300d));
- db.measures().insertMeasure(project2, analysis2, ncloc, m -> m.setValue(200d));
- db.measures().insertMeasure(project2, analysis2, coverage, m -> m.setValue(80d));
- db.measures().insertMeasure(project2, analysis2, nclocDistrib, m -> m.setData("java=300;kotlin=2500"));
+ db.measures().insertLiveMeasure(project2, lines, m -> m.setValue(300d));
+ db.measures().insertLiveMeasure(project2, ncloc, m -> m.setValue(200d));
+ db.measures().insertLiveMeasure(project2, coverage, m -> m.setValue(80d));
+ db.measures().insertLiveMeasure(project2, nclocDistrib, m -> m.setValue(null).setData("java=300;kotlin=2500"));
projectMeasuresIndexer.indexOnStartup(emptySet());
underTest.start();
@@ -173,12 +170,9 @@ public class TelemetryDaemonTest {
ComponentDto project = db.components().insertMainBranch(db.getDefaultOrganization());
ComponentDto longBranch = db.components().insertProjectBranch(project, b -> b.setBranchType(LONG));
ComponentDto shortBranch = db.components().insertProjectBranch(project, b -> b.setBranchType(SHORT));
- SnapshotDto projectAnalysis = db.components().insertSnapshot(project);
- SnapshotDto longBranchAnalysis = db.components().insertSnapshot(longBranch);
- SnapshotDto shortBranchAnalysis = db.components().insertSnapshot(shortBranch);
- db.measures().insertMeasure(project, projectAnalysis, ncloc, m -> m.setValue(10d));
- db.measures().insertMeasure(longBranch, longBranchAnalysis, ncloc, m -> m.setValue(20d));
- db.measures().insertMeasure(shortBranch, shortBranchAnalysis, ncloc, m -> m.setValue(30d));
+ db.measures().insertLiveMeasure(project, ncloc, m -> m.setValue(10d));
+ db.measures().insertLiveMeasure(longBranch, ncloc, m -> m.setValue(20d));
+ db.measures().insertLiveMeasure(shortBranch, ncloc, m -> m.setValue(30d));
projectMeasuresIndexer.indexOnStartup(emptySet());
underTest.start();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java
index 536795e12b1..6c376653434 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java
@@ -76,7 +76,7 @@ import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newModuleDto;
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
import static org.sonar.db.component.SnapshotTesting.newAnalysis;
-import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
+import static org.sonar.db.measure.MeasureTesting.newLiveMeasure;
import static org.sonar.db.metric.MetricTesting.newMetricDto;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_GATES;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
@@ -262,8 +262,7 @@ public class ComponentActionTest {
public void return_quality_profiles() throws Exception {
init();
componentDbTester.insertComponent(project);
- SnapshotDto analysis = componentDbTester.insertSnapshot(newAnalysis(project));
- addQualityProfiles(project, analysis,
+ addQualityProfiles(project,
createQProfile("qp1", "Sonar Way Java", "java"),
createQProfile("qp2", "Sonar Way Xoo", "xoo"));
userSession.addProjectPermission(UserRole.USER, project);
@@ -329,7 +328,7 @@ public class ComponentActionTest {
.build();
init(page);
- ComponentDto application = componentDbTester.insertApplication(dbTester.getDefaultOrganization());
+ ComponentDto application = componentDbTester.insertPublicApplication(dbTester.getDefaultOrganization());
userSession.registerComponents(application);
String result = ws.newRequest()
@@ -471,7 +470,7 @@ public class ComponentActionTest {
when(resourceTypes.get(project.qualifier())).thenReturn(DefaultResourceTypes.get().getRootType());
UserDto user = dbTester.users().insertUser("obiwan");
propertyDbTester.insertProperty(new PropertyDto().setKey("favourite").setResourceId(project.getId()).setUserId(user.getId()));
- addQualityProfiles(project, analysis,
+ addQualityProfiles(project,
createQProfile("qp1", "Sonar Way Java", "java"),
createQProfile("qp2", "Sonar Way Xoo", "xoo"));
QualityGateDto qualityGateDto = dbTester.qualityGates().insertQualityGate("Sonar way");
@@ -580,11 +579,11 @@ public class ComponentActionTest {
verify(execute(componentKey), expectedJson);
}
- private void addQualityProfiles(ComponentDto project, SnapshotDto analysis, QualityProfile... qps) {
- MetricDto metricDto = newMetricDto().setKey(QUALITY_PROFILES_KEY);
- dbClient.metricDao().insert(dbTester.getSession(), metricDto);
- dbClient.measureDao().insert(dbTester.getSession(),
- newMeasureDto(metricDto, project, analysis)
+ private void addQualityProfiles(ComponentDto project, QualityProfile... qps) {
+ MetricDto metric = newMetricDto().setKey(QUALITY_PROFILES_KEY);
+ dbClient.metricDao().insert(dbTester.getSession(), metric);
+ dbClient.liveMeasureDao().insert(dbTester.getSession(),
+ newLiveMeasure(project, metric)
.setData(qualityProfilesToJson(qps)));
dbTester.commit();
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
index 58dec513e16..2d9eceb4190 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
@@ -60,7 +60,6 @@ public class Measure<G extends Serializable> implements Serializable {
protected Double variation4;
protected Double variation5;
protected String url;
- protected Integer personId;
protected PersistenceMode persistenceMode = PersistenceMode.FULL;
public Measure(String metricKey) {
@@ -609,17 +608,20 @@ public class Measure<G extends Serializable> implements Serializable {
/**
* @since 2.14
+ * @deprecated in 6.5 with end of support of Developer cockpit plugin. Always return {@code null}.
*/
@CheckForNull
+ @Deprecated
public Integer getPersonId() {
- return personId;
+ return null;
}
/**
* @since 2.14
+ * @deprecated in 6.5 with end of support of Developer cockpit plugin.
*/
+ @Deprecated
public Measure<G> setPersonId(@Nullable Integer i) {
- this.personId = i;
return this;
}
@@ -663,17 +665,12 @@ public class Measure<G extends Serializable> implements Serializable {
}
Measure measure = (Measure) o;
- if (metricKey != null ? !metricKey.equals(measure.metricKey) : (measure.metricKey != null)) {
- return false;
- }
- return !(personId != null ? !personId.equals(measure.personId) : (measure.personId != null));
+ return metricKey != null ? metricKey.equals(measure.metricKey) : (measure.metricKey == null);
}
@Override
public int hashCode() {
- int result = metricKey != null ? metricKey.hashCode() : 0;
- result = 31 * result + (personId != null ? personId.hashCode() : 0);
- return result;
+ return metricKey != null ? metricKey.hashCode() : 0;
}
@Override
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java
index 7049e46d852..37bc32af4ab 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java
@@ -64,8 +64,7 @@ public final class MeasuresFilters {
}
for (Measure measure : measures) {
if (measure.getClass().equals(Measure.class) &&
- measure.getMetricKey().equals(metricKey) &&
- measure.getPersonId() == null) {
+ measure.getMetricKey().equals(metricKey)) {
return measure;
}
}
@@ -107,7 +106,7 @@ public final class MeasuresFilters {
private boolean apply(Measure measure) {
return measure instanceof RuleMeasure && metric.equals(measure.getMetric())
- && measure.getPersonId() == null && ((RuleMeasure) measure).ruleKey() != null;
+ && ((RuleMeasure) measure).ruleKey() != null;
}
@Override
@@ -157,7 +156,6 @@ public final class MeasuresFilters {
private boolean apply(Measure measure) {
return measure instanceof RuleMeasure
&& filterOnMetricKey().equals(measure.getMetricKey())
- && measure.getPersonId() == null
&& doApply((RuleMeasure) measure);
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/RuleMeasure.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/RuleMeasure.java
index 26abdc18b84..6956b04b490 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/RuleMeasure.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/RuleMeasure.java
@@ -133,7 +133,6 @@ public class RuleMeasure extends Measure {
RuleMeasure other = (RuleMeasure) obj;
return new EqualsBuilder()
.append(getMetric(), other.getMetric())
- .append(personId, other.personId)
.append(ruleKey, other.ruleKey)
.isEquals();
}
@@ -147,7 +146,6 @@ public class RuleMeasure extends Measure {
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(getMetric())
- .append(personId)
.append(ruleKey)
.toHashCode();
}
@@ -156,7 +154,6 @@ public class RuleMeasure extends Measure {
public String toString() {
return new ToStringBuilder(this)
.append("metric", metric)
- .append("personId", personId)
.append("ruleKey", ruleKey)
.append("value", value)
.append("data", data)
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureTest.java
index af76fcdc2f5..8e3d97f8658 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureTest.java
@@ -114,23 +114,6 @@ public class MeasureTest {
assertThat(measure2.equals(measure1)).isTrue();
assertThat(measure1.hashCode()).isEqualTo(measure2.hashCode());
- // different committer
- measure1.setPersonId(1);
- assertThat(measure1.equals(measure2)).isFalse();
- assertThat(measure2.equals(measure1)).isFalse();
- assertThat(measure1.hashCode()).isNotEqualTo(measure2.hashCode());
-
- measure2.setPersonId(2);
- assertThat(measure1.equals(measure2)).isFalse();
- assertThat(measure2.equals(measure1)).isFalse();
- assertThat(measure1.hashCode()).isNotEqualTo(measure2.hashCode());
-
- // same committer
- measure2.setPersonId(1);
- assertThat(measure1.equals(measure2)).isTrue();
- assertThat(measure2.equals(measure1)).isTrue();
- assertThat(measure1.hashCode()).isEqualTo(measure2.hashCode());
-
// value doesn't matter
measure1.setValue(1.0);
measure2.setValue(2.0);
diff --git a/tests/src/test/java/util/ItUtils.java b/tests/src/test/java/util/ItUtils.java
index 7a9fbafcd54..9d09abf7dfb 100644
--- a/tests/src/test/java/util/ItUtils.java
+++ b/tests/src/test/java/util/ItUtils.java
@@ -344,7 +344,7 @@ public class ItUtils {
@CheckForNull
public static Measure getMeasureWithVariation(Orchestrator orchestrator, String componentKey, String metricKey) {
Measures.ComponentWsResponse response = newWsClient(orchestrator).measures().component(new ComponentRequest()
- .setComponentKey(componentKey)
+ .setComponent(componentKey)
.setMetricKeys(singletonList(metricKey))
.setAdditionalFields(singletonList("periods")));
List<Measure> measures = response.getComponent().getMeasuresList();