diff options
author | Eric Giffon <eric.giffon@sonarsource.com> | 2024-09-23 15:58:45 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2024-10-09 20:02:46 +0000 |
commit | a79666b02068f247ea26944d3ea0d0181365c3b7 (patch) | |
tree | 0a90e171f965d6257040150ec99cacceb9cfb4f8 /server | |
parent | 449c62b7f35b191a320f8cfd7d378539c6864a51 (diff) | |
download | sonarqube-a79666b02068f247ea26944d3ea0d0181365c3b7.tar.gz sonarqube-a79666b02068f247ea26944d3ea0d0181365c3b7.zip |
SONAR-22879 Remove code related to live_measures table
Diffstat (limited to 'server')
35 files changed, 11 insertions, 2354 deletions
diff --git a/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistDuplicationDataStepIT.java b/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistDuplicationDataStepIT.java deleted file mode 100644 index f2d17c41ab2..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistDuplicationDataStepIT.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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.ce.task.projectanalysis.step; - -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.sonar.api.measures.Metric; -import org.sonar.api.utils.System2; -import org.sonar.ce.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule; -import org.sonar.ce.task.projectanalysis.duplication.DuplicationRepositoryRule; -import org.sonar.ce.task.projectanalysis.duplication.TextBlock; -import org.sonar.ce.task.projectanalysis.measure.MeasureToMeasureDto; -import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule; -import org.sonar.ce.task.step.ComputationStep; -import org.sonar.ce.task.step.TestComputationStepContext; -import org.sonar.db.DbTester; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.measure.LiveMeasureDto; -import org.sonar.db.metric.MetricDto; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA_KEY; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT; -import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder; - -class PersistDuplicationDataStepIT extends BaseStepJUnit5Test { - - private static final int ROOT_REF = 1; - private static final String PROJECT_KEY = "PROJECT_KEY"; - private static final String PROJECT_UUID = "u1"; - - private static final int FILE_1_REF = 2; - private static final String FILE_1_KEY = "FILE_1_KEY"; - private static final String FILE_1_UUID = "u2"; - - private static final int FILE_2_REF = 3; - private static final String FILE_2_KEY = "FILE_2_KEY"; - private static final String FILE_2_UUID = "u3"; - - @RegisterExtension - private final DbTester db = DbTester.create(System2.INSTANCE); - @RegisterExtension - private final TreeRootHolderRule treeRootHolder = new TreeRootHolderRule() - .setRoot( - builder(PROJECT, ROOT_REF).setKey(PROJECT_KEY).setUuid(PROJECT_UUID) - .addChildren( - builder(FILE, FILE_1_REF).setKey(FILE_1_KEY).setUuid(FILE_1_UUID) - .build(), - builder(FILE, FILE_2_REF).setKey(FILE_2_KEY).setUuid(FILE_2_UUID) - .build()) - .build()); - - @RegisterExtension - private final MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule(); - @RegisterExtension - private final DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder); - @RegisterExtension - private final MetricRepositoryRule metricRepository = new MetricRepositoryRule(); - - @BeforeEach - void setUp() { - MetricDto metric = db.measures().insertMetric(m -> m.setKey(DUPLICATIONS_DATA_KEY).setValueType(Metric.ValueType.STRING.name())); - insertComponent(PROJECT_KEY, PROJECT_UUID); - insertComponent(FILE_1_KEY, FILE_1_UUID); - insertComponent(FILE_2_KEY, FILE_2_UUID); - db.commit(); - metricRepository.add(metric.getUuid(), new Metric.Builder(DUPLICATIONS_DATA_KEY, DUPLICATIONS_DATA_KEY, Metric.ValueType.STRING).create()); - } - - @Override - protected ComputationStep step() { - return underTest(); - } - - @Test - void nothing_to_persist_when_no_duplication() { - TestComputationStepContext context = new TestComputationStepContext(); - - underTest().execute(context); - - assertThatNothingPersisted(); - verifyStatistics(context, 0); - } - - @Test - void compute_duplications_on_same_file() { - duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), new TextBlock(6, 10)); - TestComputationStepContext context = new TestComputationStepContext(); - - underTest().execute(context); - - assertThat(selectMeasureData(FILE_1_UUID)).hasValue("<duplications><g><b s=\"1\" l=\"5\" t=\"false\" r=\"" + FILE_1_KEY + "\"/><b s=\"6\" l=\"5\" t=\"false\" r=\"" - + FILE_1_KEY + "\"/></g></duplications>"); - assertThat(selectMeasureData(FILE_2_UUID)).isEmpty(); - assertThat(selectMeasureData(PROJECT_UUID)).isEmpty(); - } - - @Test - void compute_duplications_on_different_files() { - duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), FILE_2_REF, new TextBlock(6, 10)); - TestComputationStepContext context = new TestComputationStepContext(); - - underTest().execute(context); - - assertThat(selectMeasureData(FILE_1_UUID)).hasValue( - "<duplications><g><b s=\"1\" l=\"5\" t=\"false\" r=\"" + FILE_1_KEY + "\"/><b s=\"6\" l=\"5\" t=\"false\" r=\"" - + FILE_2_KEY + "\"/></g></duplications>"); - assertThat(selectMeasureData(FILE_2_UUID)).isEmpty(); - assertThat(selectMeasureData(PROJECT_UUID)).isEmpty(); - } - - @Test - void compute_duplications_on_unchanged_file() { - duplicationRepository.addExtendedProjectDuplication(FILE_1_REF, new TextBlock(1, 5), FILE_2_REF, new TextBlock(6, 10)); - TestComputationStepContext context = new TestComputationStepContext(); - - underTest().execute(context); - - assertThat(selectMeasureData(FILE_1_UUID)).hasValue( - "<duplications><g><b s=\"1\" l=\"5\" t=\"false\" r=\"" + FILE_1_KEY + "\"/><b s=\"6\" l=\"5\" t=\"true\" r=\"" - + FILE_2_KEY + "\"/></g></duplications>"); - assertThat(selectMeasureData(FILE_2_UUID)).isEmpty(); - assertThat(selectMeasureData(PROJECT_UUID)).isEmpty(); - } - - @Test - void compute_duplications_on_different_projects() { - String fileKeyFromOtherProject = "PROJECT2_KEY:file2"; - duplicationRepository.addCrossProjectDuplication(FILE_1_REF, new TextBlock(1, 5), fileKeyFromOtherProject, new TextBlock(6, 10)); - TestComputationStepContext context = new TestComputationStepContext(); - - underTest().execute(context); - - assertThat(selectMeasureData(FILE_1_UUID)).hasValue( - "<duplications><g><b s=\"1\" l=\"5\" t=\"false\" r=\"" + FILE_1_KEY + "\"/><b s=\"6\" l=\"5\" t=\"false\" r=\"" - + fileKeyFromOtherProject + "\"/></g></duplications>"); - assertThat(selectMeasureData(FILE_2_UUID)).isEmpty(); - assertThat(selectMeasureData(PROJECT_UUID)).isEmpty(); - } - - private PersistDuplicationDataStep underTest() { - return new PersistDuplicationDataStep(db.getDbClient(), treeRootHolder, metricRepository, duplicationRepository, - new MeasureToMeasureDto(analysisMetadataHolder, treeRootHolder)); - } - - private void assertThatNothingPersisted() { - assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isZero(); - } - - private Optional<String> selectMeasureData(String componentUuid) { - return db.getDbClient().liveMeasureDao().selectMeasure(db.getSession(), componentUuid, "duplications_data") - .map(LiveMeasureDto::getTextValue); - } - - private ComponentDto insertComponent(String key, String uuid) { - ComponentDto componentDto = new ComponentDto() - .setKey(key) - .setUuid(uuid) - .setUuidPath(uuid + ".") - .setBranchUuid(uuid); - db.components().insertComponent(componentDto); - return componentDto; - } - - private static void verifyStatistics(TestComputationStepContext context, int expectedInsertsOrUpdates) { - context.getStatistics().assertValue("insertsOrUpdates", expectedInsertsOrUpdates); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistLiveMeasuresStepIT.java b/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistLiveMeasuresStepIT.java deleted file mode 100644 index 6156d54843b..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistLiveMeasuresStepIT.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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.ce.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.ce.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule; -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.FileStatuses; -import org.sonar.ce.task.projectanalysis.component.ReportComponent; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule; -import org.sonar.ce.task.projectanalysis.component.ViewsComponent; -import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule; -import org.sonar.ce.task.projectanalysis.measure.MeasureToMeasureDto; -import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule; -import org.sonar.ce.task.step.ComputationStep; -import org.sonar.ce.task.step.TestComputationStepContext; -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.project.Project; - -import static java.util.Collections.emptyList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.sonar.api.measures.CoreMetrics.BUGS; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT_VIEW; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.SUBVIEW; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.VIEW; -import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder; -import static org.sonar.db.measure.MeasureTesting.newLiveMeasure; - -public class PersistLiveMeasuresStepIT 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 final FileStatuses fileStatuses = mock(FileStatuses.class); - private final DbClient dbClient = db.getDbClient(); - private final TestComputationStepContext context = new TestComputationStepContext(); - - @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)); - MetricDto bugs = db.measures().insertMetric(m -> m.setKey(BUGS.getKey())); - metricRepository.add(stringMetricDto.getUuid(), STRING_METRIC); - metricRepository.add(intMetricDto.getUuid(), INT_METRIC); - metricRepository.add(bestValueMMetricDto.getUuid(), METRIC_WITH_BEST_VALUE); - metricRepository.add(bugs.getUuid(), BUGS); - } - - @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_3, STRING_METRIC.getKey(), newMeasureBuilder().create("dir-value")); - measureRepository.addRawMeasure(REF_4, STRING_METRIC.getKey(), newMeasureBuilder().create("file-value")); - - step().execute(context); - - // all measures are persisted, from project to file - assertThat(db.countRowsOfTable("live_measures")).isEqualTo(3); - assertThat(selectMeasure("project-uuid", STRING_METRIC).get().getDataAsString()).isEqualTo("project-value"); - assertThat(selectMeasure("dir-uuid", STRING_METRIC).get().getDataAsString()).isEqualTo("dir-value"); - assertThat(selectMeasure("file-uuid", STRING_METRIC).get().getDataAsString()).isEqualTo("file-value"); - verifyStatistics(context, 3); - } - - @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(context); - - assertThatMeasureIsNotPersisted("project-uuid", STRING_METRIC); - assertThatMeasureIsNotPersisted("project-uuid", INT_METRIC); - verifyStatistics(context, 0); - } - - @Test - public void measures_on_new_code_period_are_persisted() { - prepareProject(); - measureRepository.addRawMeasure(REF_1, INT_METRIC.getKey(), newMeasureBuilder().create(42.0)); - - step().execute(context); - - LiveMeasureDto persistedMeasure = selectMeasure("project-uuid", INT_METRIC).get(); - assertThat(persistedMeasure.getValue()).isEqualTo(42.0); - verifyStatistics(context, 1); - } - - @Test - public void delete_measures_from_db_if_no_longer_computed() { - prepareProject(); - // measure to be updated - LiveMeasureDto measureOnFileInProject = insertMeasure("file-uuid", "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(context); - - assertThatMeasureHasValue(measureOnFileInProject, 42); - assertThatMeasureDoesNotExist(otherMeasureOnFileInProject); - assertThatMeasureHasValue(measureInOtherProject, (int) measureInOtherProject.getValue().doubleValue()); - verifyStatistics(context, 1); - } - - @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(context); - - assertThatMeasureDoesNotExist(oldMeasure); - assertThatMeasureHasValue("project-uuid", METRIC_WITH_BEST_VALUE, 0); - verifyStatistics(context, 1); - } - - @Test - public void keep_measures_for_unchanged_files() { - prepareProject(); - LiveMeasureDto oldMeasure = insertMeasure("file-uuid", "project-uuid", BUGS); - db.commit(); - when(fileStatuses.isDataUnchanged(any(Component.class))).thenReturn(true); - // this new value won't be persisted - measureRepository.addRawMeasure(REF_4, BUGS.getKey(), newMeasureBuilder().create(oldMeasure.getValue() + 1, 0)); - step().execute(context); - assertThat(selectMeasure("file-uuid", BUGS).get().getValue()).isEqualTo(oldMeasure.getValue()); - } - - @Test - public void dont_keep_measures_for_unchanged_files() { - prepareProject(); - LiveMeasureDto oldMeasure = insertMeasure("file-uuid", "project-uuid", BUGS); - db.commit(); - when(fileStatuses.isDataUnchanged(any(Component.class))).thenReturn(false); - // this new value will be persisted - measureRepository.addRawMeasure(REF_4, BUGS.getKey(), newMeasureBuilder().create(oldMeasure.getValue() + 1, 0)); - step().execute(context); - assertThat(selectMeasure("file-uuid", BUGS).get().getValue()).isEqualTo(oldMeasure.getValue() + 1); - } - - @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(context); - - 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"); - verifyStatistics(context, 3); - } - - private LiveMeasureDto insertMeasure(String componentUuid, String projectUuid, Metric metric) { - LiveMeasureDto measure = newLiveMeasure() - .setComponentUuid(componentUuid) - .setProjectUuid(projectUuid) - .setMetricUuid(metricRepository.getByKey(metric.getKey()).getUuid()); - dbClient.liveMeasureDao().insertOrUpdate(db.getSession(), measure); - return measure; - } - - private void assertThatMeasureHasValue(LiveMeasureDto template, int expectedValue) { - Optional<LiveMeasureDto> persisted = dbClient.liveMeasureDao().selectMeasure(db.getSession(), - template.getComponentUuid(), metricRepository.getByUuid(template.getMetricUuid()).getKey()); - assertThat(persisted).isPresent(); - assertThat(persisted.get().getValue()).isEqualTo(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(expectedValue); - } - - private void assertThatMeasureDoesNotExist(LiveMeasureDto template) { - assertThat(dbClient.liveMeasureDao().selectMeasure(db.getSession(), - template.getComponentUuid(), metricRepository.getByUuid(template.getMetricUuid()).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(DIRECTORY, REF_3).setUuid("dir-uuid") - .addChildren( - ReportComponent.builder(FILE, REF_4).setUuid("file-uuid") - .build()) - .build()) - .build(); - treeRootHolder.setRoot(project); - analysisMetadataHolder.setProject(new Project(project.getUuid(), project.getKey(), project.getName(), project.getDescription(), emptyList())); - - // components as persisted in db - ComponentDto projectDto = insertComponent("project-key", "project-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.from(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() - .setKey(key) - .setUuid(uuid) - .setUuidPath(uuid + ".") - .setBranchUuid(uuid); - db.components().insertComponent(componentDto); - return componentDto; - } - - @Override - protected ComputationStep step() { - return new PersistLiveMeasuresStep(dbClient, metricRepository, new MeasureToMeasureDto(analysisMetadataHolder, treeRootHolder), treeRootHolder, measureRepository, - Optional.of(fileStatuses)); - } - - private static void verifyStatistics(TestComputationStepContext context, int expectedInsertsOrUpdates) { - context.getStatistics().assertValue("insertsOrUpdates", expectedInsertsOrUpdates); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistProjectMeasuresStepIT.java b/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistProjectMeasuresStepIT.java index 94f98923ae7..b8899a7fd91 100644 --- a/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistProjectMeasuresStepIT.java +++ b/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistProjectMeasuresStepIT.java @@ -211,7 +211,7 @@ public class PersistProjectMeasuresStepIT extends BaseStepTest { private TestComputationStepContext execute() { TestComputationStepContext context = new TestComputationStepContext(); - new PersistProjectMeasuresStep(dbClient, metricRepository, new MeasureToMeasureDto(analysisMetadataHolder, treeRootHolder), treeRootHolder, measureRepository) + new PersistProjectMeasuresStep(dbClient, metricRepository, new MeasureToMeasureDto(analysisMetadataHolder), treeRootHolder, measureRepository) .execute(context); return context; } @@ -236,6 +236,6 @@ public class PersistProjectMeasuresStepIT extends BaseStepTest { @Override protected ComputationStep step() { - return new PersistProjectMeasuresStep(dbClient, metricRepository, new MeasureToMeasureDto(analysisMetadataHolder, treeRootHolder), treeRootHolder, measureRepository); + return new PersistProjectMeasuresStep(dbClient, metricRepository, new MeasureToMeasureDto(analysisMetadataHolder), treeRootHolder, measureRepository); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/LiveMeasureDtoToMeasure.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/LiveMeasureDtoToMeasure.java deleted file mode 100644 index 1c0e3eedaac..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/LiveMeasureDtoToMeasure.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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.ce.task.projectanalysis.measure; - -import java.util.Optional; -import javax.annotation.Nullable; -import org.sonar.ce.task.projectanalysis.metric.Metric; -import org.sonar.db.measure.LiveMeasureDto; - -import static java.util.Objects.requireNonNull; -import static java.util.Optional.of; -import static org.sonar.ce.task.projectanalysis.measure.Measure.Level.toLevel; - -public class LiveMeasureDtoToMeasure { - - private LiveMeasureDtoToMeasure() { - // utility class - } - - public static Optional<Measure> toMeasure(@Nullable LiveMeasureDto measureDto, Metric metric) { - requireNonNull(metric); - if (measureDto == null) { - return Optional.empty(); - } - Double value = measureDto.getValue(); - String data = measureDto.getDataAsString(); - switch (metric.getType().getValueType()) { - case INT: - return toIntegerMeasure(value, data); - case LONG: - return toLongMeasure(value, data); - case DOUBLE: - return toDoubleMeasure(value, data); - case BOOLEAN: - return toBooleanMeasure(value, data); - case STRING: - return toStringMeasure(data); - case LEVEL: - return toLevelMeasure(data); - case NO_VALUE: - return toNoValueMeasure(); - default: - throw new IllegalArgumentException("Unsupported Measure.ValueType " + metric.getType().getValueType()); - } - } - - private static Optional<Measure> toIntegerMeasure(@Nullable Double value, @Nullable String data) { - if (value == null) { - return toNoValueMeasure(); - } - return of(Measure.newMeasureBuilder().create(value.intValue(), data)); - } - - private static Optional<Measure> toLongMeasure(@Nullable Double value, @Nullable String data) { - if (value == null) { - return toNoValueMeasure(); - } - return of(Measure.newMeasureBuilder().create(value.longValue(), data)); - } - - private static Optional<Measure> toDoubleMeasure(@Nullable Double value, @Nullable String data) { - if (value == null) { - return toNoValueMeasure(); - } - - return of(Measure.newMeasureBuilder().create(value, org.sonar.api.measures.Metric.MAX_DECIMAL_SCALE, data)); - } - - private static Optional<Measure> toBooleanMeasure(@Nullable Double value, @Nullable String data) { - if (value == null) { - return toNoValueMeasure(); - } - return of(Measure.newMeasureBuilder().create(Double.compare(value, 1.0D) == 0, data)); - } - - private static Optional<Measure> toStringMeasure(@Nullable String data) { - if (data == null) { - return toNoValueMeasure(); - } - return of(Measure.newMeasureBuilder().create(data)); - } - - private static Optional<Measure> toLevelMeasure(@Nullable String data) { - if (data == null) { - return toNoValueMeasure(); - } - Optional<Measure.Level> level = toLevel(data); - if (!level.isPresent()) { - return toNoValueMeasure(); - } - return of(Measure.newMeasureBuilder().create(level.get())); - } - - private static Optional<Measure> toNoValueMeasure() { - return of(Measure.newMeasureBuilder().createNoValue()); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDto.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDto.java index c6714ff74f7..da52e8a1ed5 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDto.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDto.java @@ -22,19 +22,15 @@ package org.sonar.ce.task.projectanalysis.measure; import javax.annotation.CheckForNull; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; import org.sonar.ce.task.projectanalysis.metric.Metric; -import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.measure.ProjectMeasureDto; public class MeasureToMeasureDto { private final AnalysisMetadataHolder analysisMetadataHolder; - private final TreeRootHolder treeRootHolder; - public MeasureToMeasureDto(AnalysisMetadataHolder analysisMetadataHolder, TreeRootHolder treeRootHolder) { + public MeasureToMeasureDto(AnalysisMetadataHolder analysisMetadataHolder) { this.analysisMetadataHolder = analysisMetadataHolder; - this.treeRootHolder = treeRootHolder; } public ProjectMeasureDto toProjectMeasureDto(Measure measure, Metric metric, Component component) { @@ -50,16 +46,6 @@ public class MeasureToMeasureDto { return out; } - public LiveMeasureDto toLiveMeasureDto(Measure measure, Metric metric, Component component) { - LiveMeasureDto out = new LiveMeasureDto(); - out.setMetricUuid(metric.getUuid()); - out.setComponentUuid(component.getUuid()); - out.setProjectUuid(treeRootHolder.getRoot().getUuid()); - out.setValue(valueAsDouble(measure)); - out.setData(data(measure)); - return out; - } - public static Object getMeasureValue(Measure measure) { Double doubleValue = valueAsDouble(measure); if (doubleValue != null) { diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistDuplicationDataStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistDuplicationDataStep.java deleted file mode 100644 index 1e04b79de3d..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistDuplicationDataStep.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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.ce.task.projectanalysis.step; - -import java.util.ArrayList; -import java.util.List; -import org.apache.commons.text.StringEscapeUtils; -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit; -import org.sonar.ce.task.projectanalysis.component.DepthTraversalTypeAwareCrawler; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; -import org.sonar.ce.task.projectanalysis.component.TypeAwareVisitorAdapter; -import org.sonar.ce.task.projectanalysis.duplication.CrossProjectDuplicate; -import org.sonar.ce.task.projectanalysis.duplication.Duplicate; -import org.sonar.ce.task.projectanalysis.duplication.Duplication; -import org.sonar.ce.task.projectanalysis.duplication.DuplicationRepository; -import org.sonar.ce.task.projectanalysis.duplication.InExtendedProjectDuplicate; -import org.sonar.ce.task.projectanalysis.duplication.InProjectDuplicate; -import org.sonar.ce.task.projectanalysis.duplication.InnerDuplicate; -import org.sonar.ce.task.projectanalysis.duplication.TextBlock; -import org.sonar.ce.task.projectanalysis.measure.Measure; -import org.sonar.ce.task.projectanalysis.measure.MeasureToMeasureDto; -import org.sonar.ce.task.projectanalysis.metric.Metric; -import org.sonar.ce.task.projectanalysis.metric.MetricRepository; -import org.sonar.ce.task.step.ComputationStep; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.measure.LiveMeasureDto; - -import static com.google.common.collect.Iterables.isEmpty; -import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA_KEY; -import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER; - -/** - * Compute duplication data measures on files, based on the {@link DuplicationRepository} - */ -public class PersistDuplicationDataStep implements ComputationStep { - - private final DbClient dbClient; - private final TreeRootHolder treeRootHolder; - private final DuplicationRepository duplicationRepository; - private final MeasureToMeasureDto measureToMeasureDto; - private final Metric duplicationDataMetric; - - public PersistDuplicationDataStep(DbClient dbClient, TreeRootHolder treeRootHolder, MetricRepository metricRepository, - DuplicationRepository duplicationRepository, MeasureToMeasureDto measureToMeasureDto) { - this.dbClient = dbClient; - this.treeRootHolder = treeRootHolder; - this.duplicationRepository = duplicationRepository; - this.measureToMeasureDto = measureToMeasureDto; - this.duplicationDataMetric = metricRepository.getByKey(DUPLICATIONS_DATA_KEY); - } - - @Override - public void execute(ComputationStep.Context context) { - boolean supportUpsert = dbClient.getDatabase().getDialect().supportsUpsert(); - - // batch mode of DB session does not have benefits: - // - on postgres the multi-row upserts are the major optimization and have exactly the same - // performance between batch and non-batch sessions - // - on other dbs the sequence of inserts and updates, in order to emulate upserts, - // breaks the constraint of batch sessions (consecutive requests should have the same - // structure (same PreparedStatement)) - try (DbSession dbSession = dbClient.openSession(false); - DuplicationVisitor visitor = new DuplicationVisitor(dbSession, supportUpsert)) { - new DepthTraversalTypeAwareCrawler(visitor).visit(treeRootHolder.getRoot()); - context.getStatistics().add("insertsOrUpdates", visitor.insertsOrUpdates); - } - } - - private class DuplicationVisitor extends TypeAwareVisitorAdapter implements AutoCloseable { - private final DbSession dbSession; - private final boolean supportUpsert; - private final List<LiveMeasureDto> nonPersistedBuffer = new ArrayList<>(); - private int insertsOrUpdates = 0; - - private DuplicationVisitor(DbSession dbSession, boolean supportUpsert) { - super(CrawlerDepthLimit.FILE, PRE_ORDER); - this.dbSession = dbSession; - this.supportUpsert = supportUpsert; - } - - @Override - public void visitFile(Component file) { - Iterable<Duplication> duplications = duplicationRepository.getDuplications(file); - if (!isEmpty(duplications)) { - computeDuplications(file, duplications); - } - } - - private void computeDuplications(Component component, Iterable<Duplication> duplications) { - Measure measure = generateMeasure(component.getKey(), duplications); - LiveMeasureDto dto = measureToMeasureDto.toLiveMeasureDto(measure, duplicationDataMetric, component); - nonPersistedBuffer.add(dto); - persist(false); - } - - private void persist(boolean force) { - // Persist a bunch of 100 or less measures. That prevents from having more than 100 XML documents - // in memory. Consumption of memory does not explode with the number of duplications and is kept - // under control. - // Measures are upserted and transactions are committed every 100 rows (arbitrary number to - // maximize the performance of a multi-rows request on PostgreSQL). - // On PostgreSQL, a bunch of 100 measures is persisted into a single request (multi-rows upsert). - // On other DBs, measures are persisted one by one, with update-or-insert requests. - boolean shouldPersist = !nonPersistedBuffer.isEmpty() && (force || nonPersistedBuffer.size() > 100); - if (!shouldPersist) { - return; - } - if (supportUpsert) { - nonPersistedBuffer.forEach(d -> dbClient.liveMeasureDao().upsert(dbSession, d)); - } else { - nonPersistedBuffer.forEach(d -> dbClient.liveMeasureDao().insertOrUpdate(dbSession, d)); - } - insertsOrUpdates += nonPersistedBuffer.size(); - nonPersistedBuffer.clear(); - dbSession.commit(); - } - - @Override - public void close() { - // persist the measures remaining in the buffer - persist(true); - } - - private Measure generateMeasure(String componentDbKey, Iterable<Duplication> duplications) { - StringBuilder xml = new StringBuilder(); - xml.append("<duplications>"); - for (Duplication duplication : duplications) { - xml.append("<g>"); - appendDuplication(xml, componentDbKey, duplication.getOriginal(), false); - for (Duplicate duplicate : duplication.getDuplicates()) { - processDuplicationBlock(xml, duplicate, componentDbKey); - } - xml.append("</g>"); - } - xml.append("</duplications>"); - return Measure.newMeasureBuilder().create(xml.toString()); - } - - private void processDuplicationBlock(StringBuilder xml, Duplicate duplicate, String componentDbKey) { - if (duplicate instanceof InnerDuplicate) { - // Duplication is on the same file - appendDuplication(xml, componentDbKey, duplicate); - } else if (duplicate instanceof InExtendedProjectDuplicate inExtendedProjectDuplicate) { - // Duplication is on a different file that is not saved in the DB - appendDuplication(xml, inExtendedProjectDuplicate.getFile().getKey(), duplicate.getTextBlock(), true); - } else if (duplicate instanceof InProjectDuplicate inProjectDuplicate) { - // Duplication is on a different file - appendDuplication(xml, inProjectDuplicate.getFile().getKey(), duplicate); - } else if (duplicate instanceof CrossProjectDuplicate crossProjectDuplicate) { - // Only componentKey is set for cross project duplications - String crossProjectComponentKey = crossProjectDuplicate.getFileKey(); - appendDuplication(xml, crossProjectComponentKey, duplicate); - } else { - throw new IllegalArgumentException("Unsupported type of Duplicate " + duplicate.getClass().getName()); - } - } - - private void appendDuplication(StringBuilder xml, String componentDbKey, Duplicate duplicate) { - appendDuplication(xml, componentDbKey, duplicate.getTextBlock(), false); - } - - private void appendDuplication(StringBuilder xml, String componentDbKey, TextBlock textBlock, boolean disableLink) { - int length = textBlock.getEnd() - textBlock.getStart() + 1; - xml.append("<b s=\"").append(textBlock.getStart()) - .append("\" l=\"").append(length) - .append("\" t=\"").append(disableLink) - .append("\" r=\"").append(StringEscapeUtils.escapeXml10(componentDbKey)) - .append("\"/>"); - } - } - - @Override - public String getDescription() { - return "Persist duplication data"; - } - -} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistLiveMeasuresStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistLiveMeasuresStep.java deleted file mode 100644 index 42497ea5066..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistLiveMeasuresStep.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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.ce.task.projectanalysis.step; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.function.Predicate; -import javax.annotation.Nonnull; -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit; -import org.sonar.ce.task.projectanalysis.component.DepthTraversalTypeAwareCrawler; -import org.sonar.ce.task.projectanalysis.component.FileStatuses; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; -import org.sonar.ce.task.projectanalysis.component.TypeAwareVisitorAdapter; -import org.sonar.ce.task.projectanalysis.measure.BestValueOptimization; -import org.sonar.ce.task.projectanalysis.measure.Measure; -import org.sonar.ce.task.projectanalysis.measure.MeasureRepository; -import org.sonar.ce.task.projectanalysis.measure.MeasureToMeasureDto; -import org.sonar.ce.task.projectanalysis.metric.Metric; -import org.sonar.ce.task.projectanalysis.metric.MetricRepository; -import org.sonar.ce.task.step.ComputationStep; -import org.sonar.core.metric.SoftwareQualitiesMetrics; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.measure.LiveMeasureDto; - -import static org.sonar.api.measures.CoreMetrics.ACCEPTED_ISSUES_KEY; -import static org.sonar.api.measures.CoreMetrics.BLOCKER_VIOLATIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.BUGS_KEY; -import static org.sonar.api.measures.CoreMetrics.CLASSES_KEY; -import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_KEY; -import static org.sonar.api.measures.CoreMetrics.CODE_SMELLS_KEY; -import static org.sonar.api.measures.CoreMetrics.COGNITIVE_COMPLEXITY_KEY; -import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_DENSITY_KEY; -import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_KEY; -import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_CLASSES_KEY; -import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_FUNCTIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_KEY; -import static org.sonar.api.measures.CoreMetrics.CONFIRMED_ISSUES_KEY; -import static org.sonar.api.measures.CoreMetrics.CRITICAL_VIOLATIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.DEVELOPMENT_COST_KEY; -import static org.sonar.api.measures.CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY; -import static org.sonar.api.measures.CoreMetrics.FALSE_POSITIVE_ISSUES_KEY; -import static org.sonar.api.measures.CoreMetrics.FILES_KEY; -import static org.sonar.api.measures.CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION_KEY; -import static org.sonar.api.measures.CoreMetrics.FILE_COMPLEXITY_KEY; -import static org.sonar.api.measures.CoreMetrics.FUNCTIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY; -import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_KEY; -import static org.sonar.api.measures.CoreMetrics.GENERATED_LINES_KEY; -import static org.sonar.api.measures.CoreMetrics.GENERATED_NCLOC_KEY; -import static org.sonar.api.measures.CoreMetrics.INFO_VIOLATIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.LINES_KEY; -import static org.sonar.api.measures.CoreMetrics.MAJOR_VIOLATIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.MINOR_VIOLATIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.NCLOC_DATA_KEY; -import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; -import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY; -import static org.sonar.api.measures.CoreMetrics.OPEN_ISSUES_KEY; -import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY; -import static org.sonar.api.measures.CoreMetrics.RELIABILITY_REMEDIATION_EFFORT_KEY; -import static org.sonar.api.measures.CoreMetrics.REOPENED_ISSUES_KEY; -import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_KEY; -import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_KEY; -import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY; -import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY; -import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY; -import static org.sonar.api.measures.CoreMetrics.SECURITY_REMEDIATION_EFFORT_KEY; -import static org.sonar.api.measures.CoreMetrics.SECURITY_REVIEW_RATING_KEY; -import static org.sonar.api.measures.CoreMetrics.SQALE_DEBT_RATIO_KEY; -import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY; -import static org.sonar.api.measures.CoreMetrics.STATEMENTS_KEY; -import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT_KEY; -import static org.sonar.api.measures.CoreMetrics.VIOLATIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.VULNERABILITIES_KEY; -import static org.sonar.ce.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 = Set.of(FILE_COMPLEXITY_DISTRIBUTION_KEY, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY); - private static final Set<String> NOT_TO_PERSIST_ON_UNCHANGED_FILES = Set.of( - BLOCKER_VIOLATIONS_KEY, BUGS_KEY, CLASS_COMPLEXITY_KEY, CLASSES_KEY, CODE_SMELLS_KEY, COGNITIVE_COMPLEXITY_KEY, COMMENT_LINES_KEY, COMMENT_LINES_DENSITY_KEY, - COMPLEXITY_KEY, COMPLEXITY_IN_CLASSES_KEY, COMPLEXITY_IN_FUNCTIONS_KEY, CONFIRMED_ISSUES_KEY, CRITICAL_VIOLATIONS_KEY, DEVELOPMENT_COST_KEY, - EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, FALSE_POSITIVE_ISSUES_KEY, FILE_COMPLEXITY_KEY, FILE_COMPLEXITY_DISTRIBUTION_KEY, FILES_KEY, FUNCTION_COMPLEXITY_KEY, - FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, FUNCTIONS_KEY, GENERATED_LINES_KEY, GENERATED_NCLOC_KEY, INFO_VIOLATIONS_KEY, LINES_KEY, - MAJOR_VIOLATIONS_KEY, MINOR_VIOLATIONS_KEY, NCLOC_KEY, NCLOC_DATA_KEY, NCLOC_LANGUAGE_DISTRIBUTION_KEY, OPEN_ISSUES_KEY, RELIABILITY_RATING_KEY, - RELIABILITY_REMEDIATION_EFFORT_KEY, REOPENED_ISSUES_KEY, SECURITY_HOTSPOTS_KEY, SECURITY_HOTSPOTS_REVIEWED_KEY, SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY, - SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY, SECURITY_RATING_KEY, SECURITY_REMEDIATION_EFFORT_KEY, SECURITY_REVIEW_RATING_KEY, SQALE_DEBT_RATIO_KEY, TECHNICAL_DEBT_KEY, - SQALE_RATING_KEY, STATEMENTS_KEY, VIOLATIONS_KEY, VULNERABILITIES_KEY, ACCEPTED_ISSUES_KEY, - - SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, - SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY, - SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY, - SoftwareQualitiesMetrics.EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY, - SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY, - SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT_KEY, - SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT_KEY, - SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY - ); - private final DbClient dbClient; - private final MetricRepository metricRepository; - private final MeasureToMeasureDto measureToMeasureDto; - private final TreeRootHolder treeRootHolder; - private final MeasureRepository measureRepository; - private final Optional<FileStatuses> fileStatuses; - - public PersistLiveMeasuresStep(DbClient dbClient, MetricRepository metricRepository, MeasureToMeasureDto measureToMeasureDto, - TreeRootHolder treeRootHolder, MeasureRepository measureRepository, Optional<FileStatuses> fileStatuses) { - this.dbClient = dbClient; - this.metricRepository = metricRepository; - this.measureToMeasureDto = measureToMeasureDto; - this.treeRootHolder = treeRootHolder; - this.measureRepository = measureRepository; - this.fileStatuses = fileStatuses; - } - - @Override - public String getDescription() { - return "Persist live measures"; - } - - @Override - public void execute(ComputationStep.Context context) { - boolean supportUpsert = dbClient.getDatabase().getDialect().supportsUpsert(); - try (DbSession dbSession = dbClient.openSession(true)) { - Component root = treeRootHolder.getRoot(); - MeasureVisitor visitor = new MeasureVisitor(dbSession, supportUpsert); - new DepthTraversalTypeAwareCrawler(visitor).visit(root); - dbSession.commit(); - context.getStatistics() - .add("insertsOrUpdates", visitor.insertsOrUpdates); - } - } - - private class MeasureVisitor extends TypeAwareVisitorAdapter { - private final DbSession dbSession; - private final boolean supportUpsert; - private int insertsOrUpdates = 0; - - private MeasureVisitor(DbSession dbSession, boolean supportUpsert) { - super(CrawlerDepthLimit.LEAVES, PRE_ORDER); - this.supportUpsert = supportUpsert; - this.dbSession = dbSession; - } - - @Override - public void visitAny(Component component) { - List<String> metricUuids = new ArrayList<>(); - List<String> keptMetricUuids = new ArrayList<>(); - Map<String, Measure> measures = measureRepository.getRawMeasures(component); - List<LiveMeasureDto> dtos = new ArrayList<>(); - for (Map.Entry<String, Measure> measuresByMetricKey : measures.entrySet()) { - String metricKey = measuresByMetricKey.getKey(); - if (NOT_TO_PERSIST_ON_FILE_METRIC_KEYS.contains(metricKey) ) { - continue; - } - Metric metric = metricRepository.getByKey(metricKey); - Predicate<Measure> notBestValueOptimized = BestValueOptimization.from(metric, component).negate(); - Measure m = measuresByMetricKey.getValue(); - if (!NonEmptyMeasure.INSTANCE.test(m) || !notBestValueOptimized.test(m)) { - continue; - } - metricUuids.add(metric.getUuid()); - if (shouldSkipMetricOnUnchangedFile(component, metricKey)) { - keptMetricUuids.add(metric.getUuid()); - continue; - } - - LiveMeasureDto lm = measureToMeasureDto.toLiveMeasureDto(m, metric, component); - dtos.add(lm); - } - - List<String> excludedMetricUuids = supportUpsert ? metricUuids : keptMetricUuids; - deleteNonexistentMeasures(dbSession, component.getUuid(), excludedMetricUuids); - dtos.forEach(dto -> insertMeasureOptimally(dbSession, dto)); - - dbSession.commit(); - insertsOrUpdates += dtos.size(); - } - - private void deleteNonexistentMeasures(DbSession dbSession, String componentUuid, List<String> excludedMetricUuids) { - // The measures that no longer exist on the component must be deleted, for example - // when the coverage on a file goes to the "best value" 100%. - // The measures on deleted components are deleted by the step PurgeDatastoresStep - dbClient.liveMeasureDao().deleteByComponentUuidExcludingMetricUuids(dbSession, componentUuid, excludedMetricUuids); - } - - private void insertMeasureOptimally(DbSession dbSession, LiveMeasureDto dto) { - if (supportUpsert) { - dbClient.liveMeasureDao().upsert(dbSession, dto); - } else { - dbClient.liveMeasureDao().insert(dbSession, dto); - } - } - - private boolean shouldSkipMetricOnUnchangedFile(Component component, String metricKey) { - return component.getType() == Component.Type.FILE && fileStatuses.isPresent() && - fileStatuses.get().isDataUnchanged(component) && NOT_TO_PERSIST_ON_UNCHANGED_FILES.contains(metricKey); - } - } - - private enum NonEmptyMeasure implements Predicate<Measure> { - INSTANCE; - - @Override - public boolean test(@Nonnull Measure input) { - return input.getValueType() != Measure.ValueType.NO_VALUE || input.getData() != null; - } - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java index a5cf39e5c60..466be8f175f 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java @@ -106,9 +106,7 @@ public class ReportComputationSteps extends AbstractComputationSteps { PersistAnalysisStep.class, PersistAnalysisPropertiesStep.class, PersistProjectMeasuresStep.class, - PersistLiveMeasuresStep.class, PersistMeasuresStep.class, - PersistDuplicationDataStep.class, PersistAdHocRulesStep.class, PersistCveStep.class, PersistIssuesStep.class, diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/LiveMeasureDtoToMeasureTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/LiveMeasureDtoToMeasureTest.java deleted file mode 100644 index 587fbacf77a..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/LiveMeasureDtoToMeasureTest.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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.ce.task.projectanalysis.measure; - -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import java.util.Optional; -import org.assertj.core.data.Offset; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.sonar.ce.task.projectanalysis.measure.Measure.Level; -import org.sonar.ce.task.projectanalysis.metric.Metric; -import org.sonar.ce.task.projectanalysis.metric.MetricImpl; -import org.sonar.db.measure.LiveMeasureDto; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.sonar.ce.task.projectanalysis.measure.LiveMeasureDtoToMeasure.*; - -@RunWith(DataProviderRunner.class) -public class LiveMeasureDtoToMeasureTest { - private static final Metric SOME_INT_METRIC = new MetricImpl("42", "int", "name", Metric.MetricType.INT); - private static final Metric SOME_LONG_METRIC = new MetricImpl("42", "long", "name", Metric.MetricType.WORK_DUR); - private static final Metric SOME_DOUBLE_METRIC = new MetricImpl("42", "double", "name", Metric.MetricType.FLOAT); - private static final Metric SOME_STRING_METRIC = new MetricImpl("42", "string", "name", Metric.MetricType.STRING); - private static final Metric SOME_BOOLEAN_METRIC = new MetricImpl("42", "boolean", "name", Metric.MetricType.BOOL); - private static final Metric SOME_LEVEL_METRIC = new MetricImpl("42", "level", "name", Metric.MetricType.LEVEL); - private static final LiveMeasureDto EMPTY_MEASURE_DTO = new LiveMeasureDto(); - - @Test - public void toMeasure_returns_absent_for_null_argument() { - assertThat(toMeasure(null, SOME_INT_METRIC)).isNotPresent(); - } - - @Test - public void toMeasure_throws_NPE_if_metric_argument_is_null() { - assertThatThrownBy(() -> toMeasure(EMPTY_MEASURE_DTO, null)) - .isInstanceOf(NullPointerException.class); - } - - @Test - public void toMeasure_throws_NPE_if_both_arguments_are_null() { - assertThatThrownBy(() -> toMeasure(null, null)) - .isInstanceOf(NullPointerException.class); - } - - @Test - public void toMeasure_returns_no_value_if_dto_has_no_data_for_Level_Metric() { - Optional<Measure> measure = toMeasure(EMPTY_MEASURE_DTO, SOME_LEVEL_METRIC); - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE); - } - - @Test - public void toMeasure_returns_no_value_if_dto_has_invalid_data_for_Level_Metric() { - Optional<Measure> measure = toMeasure(new LiveMeasureDto().setData("trololo"), SOME_LEVEL_METRIC); - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE); - } - - @Test - public void toMeasure_returns_no_value_if_dta_has_data_in_wrong_case_for_Level_Metric() { - Optional<Measure> measure = toMeasure(new LiveMeasureDto().setData("waRn"), SOME_LEVEL_METRIC); - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE); - } - - @Test - public void toMeasure_returns_no_QualityGateStatus_if_dto_has_no_alertStatus_for_Level_Metric() { - Optional<Measure> measure = toMeasure(EMPTY_MEASURE_DTO, SOME_STRING_METRIC); - assertThat(measure).isPresent(); - assertThat(measure.get().hasQualityGateStatus()).isFalse(); - } - - @Test - public void toMeasure_returns_no_QualityGateStatus_if_alertStatus_has_invalid_data_for_Level_Metric() { - Optional<Measure> measure = toMeasure(new LiveMeasureDto().setData("trololo"), SOME_STRING_METRIC); - assertThat(measure).isPresent(); - assertThat(measure.get().hasQualityGateStatus()).isFalse(); - } - - @Test - public void toMeasure_returns_no_QualityGateStatus_if_alertStatus_has_data_in_wrong_case_for_Level_Metric() { - Optional<Measure> measure = toMeasure(new LiveMeasureDto().setData("waRn"), SOME_STRING_METRIC); - assertThat(measure).isPresent(); - assertThat(measure.get().hasQualityGateStatus()).isFalse(); - } - - @Test - public void toMeasure_returns_value_for_LEVEL_Metric() { - for (Level level : Level.values()) { - verify_toMeasure_returns_value_for_LEVEL_Metric(level); - } - } - - private void verify_toMeasure_returns_value_for_LEVEL_Metric(Level expectedLevel) { - Optional<Measure> measure = toMeasure(new LiveMeasureDto().setData(expectedLevel.name()), SOME_LEVEL_METRIC); - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LEVEL); - assertThat(measure.get().getLevelValue()).isEqualTo(expectedLevel); - } - - @Test - public void toMeasure_returns_no_value_if_dto_has_no_value_for_Int_Metric() { - Optional<Measure> measure = toMeasure(EMPTY_MEASURE_DTO, SOME_INT_METRIC); - - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE); - } - - @Test - public void toMeasure_returns_int_part_of_value_in_dto_for_Int_Metric() { - Optional<Measure> measure = toMeasure(new LiveMeasureDto().setValue(1.5d), SOME_INT_METRIC); - - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.INT); - assertThat(measure.get().getIntValue()).isOne(); - } - - @Test - public void toMeasure_returns_no_value_if_dto_has_no_value_for_Long_Metric() { - Optional<Measure> measure = toMeasure(EMPTY_MEASURE_DTO, SOME_LONG_METRIC); - - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE); - } - - @Test - public void toMeasure_returns_long_part_of_value_in_dto_for_Long_Metric() { - Optional<Measure> measure = toMeasure(new LiveMeasureDto().setValue(1.5d), SOME_LONG_METRIC); - - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LONG); - assertThat(measure.get().getLongValue()).isOne(); - } - - @Test - public void toMeasure_returns_no_value_if_dto_has_no_value_for_Double_Metric() { - Optional<Measure> measure = toMeasure(EMPTY_MEASURE_DTO, SOME_DOUBLE_METRIC); - - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE); - } - - @Test - public void toMeasure_returns_no_value_if_dto_has_no_value_for_Boolean_metric() { - Optional<Measure> measure = toMeasure(EMPTY_MEASURE_DTO, SOME_BOOLEAN_METRIC); - - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE); - } - - @Test - public void toMeasure_returns_false_value_if_dto_has_invalid_value_for_Boolean_metric() { - Optional<Measure> measure = toMeasure(new LiveMeasureDto().setValue(1.987d), SOME_BOOLEAN_METRIC); - - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.BOOLEAN); - assertThat(measure.get().getBooleanValue()).isFalse(); - } - - @Test - public void toMeasure_returns_no_value_if_dto_has_no_value_for_String_Metric() { - Optional<Measure> measure = toMeasure(EMPTY_MEASURE_DTO, SOME_STRING_METRIC); - - assertThat(measure).isPresent(); - assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE); - } - - @Test - public void toMeasure_should_not_loose_decimals_of_float_values() { - MetricImpl metric = new MetricImpl("42", "double", "name", Metric.MetricType.FLOAT, 5, null, false, false); - LiveMeasureDto LiveMeasureDto = new LiveMeasureDto() - .setValue(0.12345); - - Optional<Measure> measure = toMeasure(LiveMeasureDto, metric); - - assertThat(measure.get().getDoubleValue()).isEqualTo(0.12345, Offset.offset(0.000001)); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDtoTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDtoTest.java index 2314fc36f53..0abd93882f3 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDtoTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDtoTest.java @@ -28,11 +28,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.sonar.ce.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule; import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.MutableTreeRootHolderRule; import org.sonar.ce.task.projectanalysis.component.ReportComponent; import org.sonar.ce.task.projectanalysis.metric.Metric; import org.sonar.ce.task.projectanalysis.metric.MetricImpl; -import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.measure.ProjectMeasureDto; import static org.assertj.core.api.Assertions.assertThat; @@ -56,10 +54,7 @@ public class MeasureToMeasureDtoTest { @Rule public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule(); - @Rule - public MutableTreeRootHolderRule treeRootHolder = new MutableTreeRootHolderRule(); - - private MeasureToMeasureDto underTest = new MeasureToMeasureDto(analysisMetadataHolder, treeRootHolder); + private final MeasureToMeasureDto underTest = new MeasureToMeasureDto(analysisMetadataHolder); @Before public void setUp() { @@ -172,18 +167,6 @@ public class MeasureToMeasureDtoTest { } @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()); - } - - @Test public void getMeasureValue_returns_null_if_measure_is_empty() { assertThat(getMeasureValue(Measure.newMeasureBuilder().createNoValue())).isNull(); } 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 e72b6326b16..3d5707f371f 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 @@ -66,7 +66,6 @@ public final class SqTables { "issues_fixed", "issues_impacts", "issue_changes", - "live_measures", "measures", "metrics", "new_code_periods", diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/component/BranchDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/component/BranchDaoIT.java index 3240684ee32..f5096c9a414 100644 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/component/BranchDaoIT.java +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/component/BranchDaoIT.java @@ -595,13 +595,6 @@ class BranchDaoIT { ComponentDto project3 = projectData3.getMainBranchComponent(); db.components().insertProjectBranch(project3, b -> b.setBranchType(BRANCH).setKey("p3-branch-1")); - MetricDto unanalyzedC = db.measures().insertMetric(m -> m.setKey("unanalyzed_c")); - MetricDto unanalyzedCpp = db.measures().insertMetric(m -> m.setKey("unanalyzed_cpp")); - db.measures().insertLiveMeasure(project1, unanalyzedC); - db.measures().insertLiveMeasure(project1, unanalyzedCpp); - db.measures().insertLiveMeasure(project2, unanalyzedCpp); - db.measures().insertLiveMeasure(project3, unanalyzedC); - assertThat(underTest.countPrBranchAnalyzedLanguageByProjectUuid(db.getSession())) .extracting(PrBranchAnalyzedLanguageCountByProjectDto::getProjectUuid, PrBranchAnalyzedLanguageCountByProjectDto::getBranch, PrBranchAnalyzedLanguageCountByProjectDto::getPullRequest) diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/measure/LiveMeasureDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/measure/LiveMeasureDaoIT.java deleted file mode 100644 index 6b2796b348c..00000000000 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/measure/LiveMeasureDaoIT.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.IntStream; -import org.apache.commons.lang3.RandomStringUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; -import org.sonar.db.component.BranchDto; -import org.sonar.db.component.BranchType; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ProjectData; -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.assertj.core.groups.Tuple.tuple; -import static org.sonar.api.measures.Metric.ValueType.DATA; -import static org.sonar.api.measures.Metric.ValueType.INT; -import static org.sonar.db.component.ComponentTesting.newFileDto; -import static org.sonar.db.measure.MeasureTesting.newLiveMeasure; - -class LiveMeasureDaoIT { - - @RegisterExtension - private final DbTester db = DbTester.create(System2.INSTANCE); - - private final LiveMeasureDao underTest = db.getDbClient().liveMeasureDao(); - private MetricDto metric; - - private int branchId = 0; - - @BeforeEach - void setUp() { - metric = db.measures().insertMetric(); - } - - @Test - void selectByComponentUuidsAndMetricUuids() { - LiveMeasureDto measure1 = newLiveMeasure().setMetricUuid(metric.getUuid()); - LiveMeasureDto measure2 = newLiveMeasure().setMetricUuid(metric.getUuid()); - underTest.insert(db.getSession(), measure1); - underTest.insert(db.getSession(), measure2); - - List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricUuids(db.getSession(), - asList(measure1.getComponentUuid(), measure2.getComponentUuid()), singletonList(metric.getUuid())); - assertThat(selected) - .extracting(LiveMeasureDto::getComponentUuid, LiveMeasureDto::getProjectUuid, LiveMeasureDto::getMetricUuid, - LiveMeasureDto::getValue, LiveMeasureDto::getDataAsString) - .containsExactlyInAnyOrder( - tuple(measure1.getComponentUuid(), measure1.getProjectUuid(), measure1.getMetricUuid(), measure1.getValue(), - measure1.getDataAsString()), - tuple(measure2.getComponentUuid(), measure2.getProjectUuid(), measure2.getMetricUuid(), measure2.getValue(), - measure2.getDataAsString())); - - assertThat(underTest.selectByComponentUuidsAndMetricUuids(db.getSession(), emptyList(), singletonList(metric.getUuid()))).isEmpty(); - assertThat(underTest.selectByComponentUuidsAndMetricUuids(db.getSession(), singletonList(measure1.getComponentUuid()), emptyList())).isEmpty(); - } - - @Test - void selectByComponentUuidsAndMetricUuids_returns_empty_list_if_metric_does_not_match() { - LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid()); - underTest.insert(db.getSession(), measure); - - String otherMetricUuid = metric.getUuid() + "other"; - List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricUuids(db.getSession(), - singletonList(measure.getComponentUuid()), singletonList(otherMetricUuid)); - - assertThat(selected).isEmpty(); - } - - @Test - void selectByComponentUuidsAndMetricUuids_returns_empty_list_if_component_does_not_match() { - LiveMeasureDto measure = newLiveMeasure(); - underTest.insert(db.getSession(), measure); - - List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricUuids(db.getSession(), singletonList("_missing_"), - singletonList(measure.getMetricUuid())); - - assertThat(selected).isEmpty(); - } - - @Test - void selectByComponentUuidAndMetricKey() { - LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid()); - underTest.insert(db.getSession(), measure); - - Optional<LiveMeasureDto> selected = underTest.selectMeasure(db.getSession(), measure.getComponentUuid(), metric.getKey()); - - assertThat(selected).isNotEmpty(); - assertThat(selected.get()).isEqualToComparingFieldByField(measure); - } - - @Test - void selectByComponentUuidAndMetricKey_return_empty_if_component_does_not_match() { - LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid()); - underTest.insert(db.getSession(), measure); - - assertThat(underTest.selectMeasure(db.getSession(), "_missing_", metric.getKey())).isEmpty(); - } - - @Test - void selectByComponentUuidAndMetricKey_return_empty_if_metric_does_not_match() { - LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid()); - underTest.insert(db.getSession(), measure); - - assertThat(underTest.selectMeasure(db.getSession(), measure.getComponentUuid(), "_missing_")).isEmpty(); - } - - @Test - void selectMeasure() { - MetricDto metric = db.measures().insertMetric(); - LiveMeasureDto stored = newLiveMeasure().setMetricUuid(metric.getUuid()); - 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 - void selectMeasure_map_fields() { - MetricDto metric = db.measures().insertMetric(); - ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); - ComponentDto file = db.components().insertComponent(newFileDto(project)); - underTest.insert(db.getSession(), newLiveMeasure(file, metric).setValue(3.14).setData("text_value")); - - LiveMeasureDto result = - underTest.selectMeasure(db.getSession(), file.uuid(), metric.getKey()).orElseThrow(() -> new IllegalArgumentException("Measure not " + - "found")); - - assertThat(result).as("Fail to map fields of %s", result.toString()).extracting( - LiveMeasureDto::getProjectUuid, LiveMeasureDto::getComponentUuid, LiveMeasureDto::getMetricUuid, LiveMeasureDto::getValue, - LiveMeasureDto::getDataAsString, LiveMeasureDto::getTextValue) - .contains(project.uuid(), file.uuid(), metric.getUuid(), 3.14, "text_value", "text_value"); - } - - @Test - void insert_data() { - byte[] data = "text_value".getBytes(StandardCharsets.UTF_8); - MetricDto metric = db.measures().insertMetric(); - ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); - ComponentDto file = db.components().insertComponent(newFileDto(project)); - LiveMeasureDto measure = newLiveMeasure(file, metric).setData(data); - - underTest.insert(db.getSession(), measure); - - LiveMeasureDto result = - underTest.selectMeasure(db.getSession(), file.uuid(), metric.getKey()).orElseThrow(() -> new IllegalArgumentException("Measure not " + - "found")); - assertThat(new String(result.getData(), StandardCharsets.UTF_8)).isEqualTo("text_value"); - assertThat(result.getDataAsString()).isEqualTo("text_value"); - } - - @Test - void insertOrUpdate() { - // insert - LiveMeasureDto dto = newLiveMeasure(); - underTest.insertOrUpdate(db.getSession(), dto); - verifyPersisted(dto); - verifyTableSize(1); - - // update - dto.setValue(dto.getValue() + 1); - dto.setData(dto.getDataAsString() + "_new"); - underTest.insertOrUpdate(db.getSession(), dto); - verifyPersisted(dto); - verifyTableSize(1); - } - - @Test - void deleteByComponentUuidExcludingMetricUuids() { - LiveMeasureDto measure1 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("1"); - LiveMeasureDto measure2 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("2"); - LiveMeasureDto measure3 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("3"); - LiveMeasureDto measureOtherComponent = newLiveMeasure().setComponentUuid("C2").setMetricUuid("3"); - underTest.insertOrUpdate(db.getSession(), measure1); - underTest.insertOrUpdate(db.getSession(), measure2); - underTest.insertOrUpdate(db.getSession(), measure3); - underTest.insertOrUpdate(db.getSession(), measureOtherComponent); - - underTest.deleteByComponentUuidExcludingMetricUuids(db.getSession(), "C1", Arrays.asList("1", "2")); - - verifyTableSize(3); - verifyPersisted(measure1); - verifyPersisted(measure2); - verifyPersisted(measureOtherComponent); - } - - @Test - void deleteByComponentUuidExcludingMetricUuids_with_empty_metrics() { - LiveMeasureDto measure1 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("1"); - LiveMeasureDto measure2 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("2"); - LiveMeasureDto measureOnOtherComponent = newLiveMeasure().setComponentUuid("C2").setMetricUuid("2"); - underTest.insertOrUpdate(db.getSession(), measure1); - underTest.insertOrUpdate(db.getSession(), measure2); - underTest.insertOrUpdate(db.getSession(), measureOnOtherComponent); - - underTest.deleteByComponentUuidExcludingMetricUuids(db.getSession(), "C1", Collections.emptyList()); - - verifyTableSize(1); - verifyPersisted(measureOnOtherComponent); - } - - @Test - void upsert_inserts_or_updates_row() { - if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) { - return; - } - - // insert - LiveMeasureDto dto = newLiveMeasure(); - int count = underTest.upsert(db.getSession(), dto); - verifyPersisted(dto); - verifyTableSize(1); - assertThat(count).isOne(); - - // update - dto.setValue(dto.getValue() + 1); - dto.setData(dto.getDataAsString() + "_new"); - count = underTest.upsert(db.getSession(), dto); - assertThat(count).isOne(); - verifyPersisted(dto); - verifyTableSize(1); - } - - @Test - void upsert_does_not_update_row_if_values_are_not_changed() { - if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) { - return; - } - - LiveMeasureDto dto = newLiveMeasure(); - underTest.upsert(db.getSession(), dto); - - // update - int count = underTest.upsert(db.getSession(), dto); - assertThat(count).isZero(); - verifyPersisted(dto); - verifyTableSize(1); - } - - @Test - void upsert_updates_row_if_lob_data_is_changed() { - if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) { - return; - } - - LiveMeasureDto dto = newLiveMeasure().setData(RandomStringUtils.random(10_000)); - underTest.upsert(db.getSession(), dto); - - // update - dto.setData(RandomStringUtils.random(dto.getDataAsString().length() + 10)); - int count = underTest.upsert(db.getSession(), dto); - assertThat(count).isOne(); - verifyPersisted(dto); - verifyTableSize(1); - } - - @Test - void upsert_does_not_update_row_if_lob_data_is_not_changed() { - if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) { - return; - } - LiveMeasureDto dto = newLiveMeasure().setData(RandomStringUtils.random(10_000)); - underTest.upsert(db.getSession(), dto); - - // update - int count = underTest.upsert(db.getSession(), dto); - assertThat(count).isZero(); - verifyPersisted(dto); - verifyTableSize(1); - } - - @Test - void upsert_updates_row_if_lob_data_is_removed() { - if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) { - return; - } - - LiveMeasureDto dto = newLiveMeasure().setData(RandomStringUtils.random(10_000)); - underTest.upsert(db.getSession(), dto); - - // update - dto.setData((String) null); - int count = underTest.upsert(db.getSession(), dto); - assertThat(count).isOne(); - verifyPersisted(dto); - verifyTableSize(1); - } - - @Test - void upsert_updates_row_if_value_is_changed() { - if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) { - return; - } - LiveMeasureDto dto = newLiveMeasure().setValue(40.0); - underTest.upsert(db.getSession(), dto); - - // update - dto.setValue(50.0); - int count = underTest.upsert(db.getSession(), dto); - assertThat(count).isOne(); - verifyPersisted(dto); - verifyTableSize(1); - } - - @Test - void upsert_updates_row_if_value_is_removed() { - if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) { - return; - } - LiveMeasureDto dto = newLiveMeasure().setValue(40.0); - underTest.upsert(db.getSession(), dto); - - // update - dto.setValue(null); - int count = underTest.upsert(db.getSession(), dto); - assertThat(count).isOne(); - verifyPersisted(dto); - verifyTableSize(1); - } - - @Test - void upsert_updates_row_if_value_is_added() { - if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) { - return; - } - LiveMeasureDto dto = newLiveMeasure().setValue(null); - underTest.upsert(db.getSession(), dto); - - // update - dto.setValue(40.0); - int count = underTest.upsert(db.getSession(), dto); - assertThat(count).isOne(); - verifyPersisted(dto); - verifyTableSize(1); - } - - @Test - void upsert_multiple_rows() { - if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) { - return; - } - - // insert 30 - List<LiveMeasureDto> inserted = new ArrayList<>(); - IntStream.range(0, 30).forEach(i -> inserted.add(newLiveMeasure())); - for (LiveMeasureDto dto : inserted) { - underTest.upsert(db.getSession(), dto); - } - verifyTableSize(30); - - // update 10 with new values, update 5 without any change and insert new 50 - List<LiveMeasureDto> upserted = new ArrayList<>(); - IntStream.range(0, 10).forEach(i -> { - LiveMeasureDto d = inserted.get(i); - upserted.add(d.setValue(d.getValue() + 123)); - }); - upserted.addAll(inserted.subList(10, 15)); - IntStream.range(0, 50).forEach(i -> upserted.add(newLiveMeasure())); - for (LiveMeasureDto dto : upserted) { - underTest.upsert(db.getSession(), dto); - } - db.getSession().commit(); - verifyTableSize(80); - } - - private void verifyTableSize(int expectedSize) { - assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isEqualTo(expectedSize); - } - - private void verifyPersisted(LiveMeasureDto dto) { - List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricUuids(db.getSession(), singletonList(dto.getComponentUuid()) - , singletonList(dto.getMetricUuid())); - assertThat(selected).hasSize(1); - assertThat(selected.get(0)).isEqualToComparingOnlyGivenFields(dto, - // do not compare the field "uuid", which is used only for insert, not select - "componentUuid", "projectUuid", "metricUuid", "value", "textValue", "data"); - } -} diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java index 56f593919df..594a941b51d 100644 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java @@ -78,7 +78,6 @@ import org.sonar.db.event.EventTesting; import org.sonar.db.issue.AnticipatedTransitionDto; import org.sonar.db.issue.IssueChangeDto; import org.sonar.db.issue.IssueDto; -import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.measure.MeasureDto; import org.sonar.db.measure.ProjectMeasureDto; import org.sonar.db.metric.MetricDto; @@ -324,15 +323,6 @@ project.getProjectDto().getUuid()), PurgeListener.EMPTY, new PurgeProfiler()); MetricDto metric1 = db.measures().insertMetric(); MetricDto metric2 = db.measures().insertMetric(); - LiveMeasureDto liveMeasureMetric1OnFile = db.measures().insertLiveMeasure(srcFile, metric1); - LiveMeasureDto liveMeasureMetric2OnFile = db.measures().insertLiveMeasure(srcFile, metric2); - LiveMeasureDto liveMeasureMetric1OnDir = db.measures().insertLiveMeasure(dir, metric1); - LiveMeasureDto liveMeasureMetric2OnDir = db.measures().insertLiveMeasure(dir, metric2); - LiveMeasureDto liveMeasureMetric1OnProject = db.measures().insertLiveMeasure(mainBranch, metric1); - LiveMeasureDto liveMeasureMetric2OnProject = db.measures().insertLiveMeasure(mainBranch, metric2); - LiveMeasureDto liveMeasureMetric1OnNonSelected = db.measures().insertLiveMeasure(enabledFile, metric1); - LiveMeasureDto liveMeasureMetric2OnNonSelected = db.measures().insertLiveMeasure(enabledFile, metric2); - assertThat(db.countRowsOfTable("live_measures")).isEqualTo(8); db.measures().insertMeasure(srcFile, m -> m.addValue(metric1.getKey(), RandomUtils.nextInt(50)).addValue(metric2.getKey(), RandomUtils.nextInt(50))); @@ -370,18 +360,6 @@ project.getProjectDto().getUuid()), PurgeListener.EMPTY, new PurgeProfiler()); assertThat(db.countRowsOfTable("file_sources")).isOne(); assertThat(db.getDbClient().fileSourceDao().selectByFileUuid(dbSession, nonSelectedFileSource.getFileUuid())).isNotNull(); - // deletes live measure of selected - assertThat(db.countRowsOfTable("live_measures")).isEqualTo(4); - List<LiveMeasureDto> liveMeasureDtos = db.getDbClient().liveMeasureDao() - .selectByComponentUuidsAndMetricUuids(dbSession, Set.of(srcFile.uuid(), dir.uuid(), mainBranch.uuid(), enabledFile.uuid()), - Set.of(metric1.getUuid(), metric2.getUuid())); - assertThat(liveMeasureDtos) - .extracting(LiveMeasureDto::getComponentUuid) - .containsOnly(enabledFile.uuid(), mainBranch.uuid()); - assertThat(liveMeasureDtos) - .extracting(LiveMeasureDto::getMetricUuid) - .containsOnly(metric1.getUuid(), metric2.getUuid()); - // delete measures of selected assertThat(db.countRowsOfTable("measures")).isEqualTo(2); List<MeasureDto> measureDtos = Set.of(srcFile.uuid(), dir.uuid(), mainBranch.uuid(), enabledFile.uuid()).stream() @@ -1714,29 +1692,21 @@ project.getProjectDto().getKey()); } @Test - void delete_live_measures_when_deleting_project() { + void delete_measures_when_deleting_project() { MetricDto metric = db.measures().insertMetric(); ComponentDto project1 = db.components().insertPublicProject().getMainBranchComponent(); ComponentDto dir1 = db.components().insertComponent(newDirectory(project1, "path")); - db.measures().insertLiveMeasure(project1, metric); - db.measures().insertLiveMeasure(dir1, metric); db.measures().insertMeasure(project1, m -> m.addValue(metric.getKey(), RandomUtils.nextInt(50))); db.measures().insertMeasure(dir1, m -> m.addValue(metric.getKey(), RandomUtils.nextInt(50))); ComponentDto project2 = db.components().insertPublicProject().getMainBranchComponent(); ComponentDto dir2 = db.components().insertComponent(newDirectory(project2, "path")); - db.measures().insertLiveMeasure(project2, metric); - db.measures().insertLiveMeasure(dir2, metric); db.measures().insertMeasure(project2, m -> m.addValue(metric.getKey(), RandomUtils.nextInt(50))); db.measures().insertMeasure(dir2, m -> m.addValue(metric.getKey(), RandomUtils.nextInt(50))); underTest.deleteProject(dbSession, project1.uuid(), project1.qualifier(), project1.name(), project1.getKey()); - assertThat(dbClient.liveMeasureDao().selectByComponentUuidsAndMetricUuids(dbSession, List.of(project1.uuid(), dir1.uuid()), - List.of(metric.getUuid()))).isEmpty(); - assertThat(dbClient.liveMeasureDao().selectByComponentUuidsAndMetricUuids(dbSession, List.of(project2.uuid(), dir2.uuid()), - List.of(metric.getUuid()))).hasSize(2); assertThat(dbClient.measureDao().selectByComponentUuid(dbSession, project1.uuid())).isEmpty(); assertThat(dbClient.measureDao().selectByComponentUuid(dbSession, dir1.uuid())).isEmpty(); assertThat(dbClient.measureDao().selectByComponentUuid(dbSession, project2.uuid())).isNotEmpty(); 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 c0852b111a5..2913c653a97 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 @@ -50,7 +50,6 @@ import org.sonar.db.issue.AnticipatedTransitionDao; import org.sonar.db.issue.IssueChangeDao; import org.sonar.db.issue.IssueDao; import org.sonar.db.issue.IssueFixedDao; -import org.sonar.db.measure.LiveMeasureDao; import org.sonar.db.measure.MeasureDao; import org.sonar.db.measure.ProjectMeasureDao; import org.sonar.db.metric.MetricDao; @@ -155,7 +154,6 @@ public class DaoModule extends Module { IssueFixedDao.class, IssuesDependencyDao.class, MeasureDao.class, - LiveMeasureDao.class, ProjectMeasureDao.class, MetricDao.class, NewCodePeriodDao.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 200f3547cb4..46cb3d67623 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 @@ -50,7 +50,6 @@ import org.sonar.db.issue.AnticipatedTransitionDao; import org.sonar.db.issue.IssueChangeDao; import org.sonar.db.issue.IssueDao; import org.sonar.db.issue.IssueFixedDao; -import org.sonar.db.measure.LiveMeasureDao; import org.sonar.db.measure.MeasureDao; import org.sonar.db.measure.ProjectMeasureDao; import org.sonar.db.metric.MetricDao; @@ -177,7 +176,6 @@ public class DbClient { private final AnalysisPropertiesDao analysisPropertiesDao; private final QProfileEditUsersDao qProfileEditUsersDao; private final QProfileEditGroupsDao qProfileEditGroupsDao; - private final LiveMeasureDao liveMeasureDao; private final WebhookDao webhookDao; private final WebhookDeliveryDao webhookDeliveryDao; private final NewCodePeriodDao newCodePeriodDao; @@ -276,7 +274,6 @@ public class DbClient { analysisPropertiesDao = getDao(map, AnalysisPropertiesDao.class); qProfileEditUsersDao = getDao(map, QProfileEditUsersDao.class); qProfileEditGroupsDao = getDao(map, QProfileEditGroupsDao.class); - liveMeasureDao = getDao(map, LiveMeasureDao.class); webhookDao = getDao(map, WebhookDao.class); webhookDeliveryDao = getDao(map, WebhookDeliveryDao.class); internalComponentPropertiesDao = getDao(map, InternalComponentPropertiesDao.class); @@ -580,10 +577,6 @@ 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 9aafec712ab..6239cb6bde9 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 @@ -88,7 +88,6 @@ import org.sonar.db.issue.IssueMapper; import org.sonar.db.issue.NewCodeReferenceIssueDto; import org.sonar.db.issue.PrIssueDto; import org.sonar.db.measure.LargestBranchNclocDto; -import org.sonar.db.measure.LiveMeasureMapper; import org.sonar.db.measure.MeasureMapper; import org.sonar.db.measure.ProjectLocDistributionDto; import org.sonar.db.measure.ProjectMeasureDto; @@ -296,7 +295,6 @@ public class MyBatis { ComponentMapper.class, CveMapper.class, CveCweMapper.class, - LiveMeasureMapper.class, DefaultQProfileMapper.class, DuplicationMapper.class, EntityMapper.class, diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureComparator.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureComparator.java deleted file mode 100644 index 6ebe886adf9..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureComparator.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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.Comparator; - -public enum LiveMeasureComparator implements Comparator<LiveMeasureDto> { - INSTANCE; - - @Override - public int compare(LiveMeasureDto o1, LiveMeasureDto o2) { - int componentUuidComp = o1.getComponentUuid().compareTo(o2.getComponentUuid()); - if (componentUuidComp != 0) { - return componentUuidComp; - } - return o1.getMetricUuid().compareTo(o2.getMetricUuid()); - } -} 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 deleted file mode 100644 index be285e98e4a..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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 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.dialect.Dialect; - -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> selectByComponentUuidsAndMetricUuids(DbSession dbSession, Collection<String> largeComponentUuids, Collection<String> metricUuids) { - if (largeComponentUuids.isEmpty() || metricUuids.isEmpty()) { - return Collections.emptyList(); - } - - return executeLargeInputs( - largeComponentUuids, - componentUuids -> mapper(dbSession).selectByComponentUuidsAndMetricUuids(componentUuids, metricUuids)); - } - - public Optional<LiveMeasureDto> selectMeasure(DbSession dbSession, String componentUuid, String metricKey) { - LiveMeasureDto liveMeasureDto = mapper(dbSession).selectByComponentUuidAndMetricKey(componentUuid, metricKey); - return Optional.ofNullable(liveMeasureDto); - } - - public void insert(DbSession dbSession, LiveMeasureDto dto) { - mapper(dbSession).insert(dto, Uuids.create(), system2.now()); - } - - public void insertOrUpdate(DbSession dbSession, LiveMeasureDto dto) { - LiveMeasureMapper mapper = mapper(dbSession); - long now = system2.now(); - if (mapper.update(dto, now) == 0) { - mapper.insert(dto, Uuids.create(), now); - } - } - - /** - * Similar to {@link #insertOrUpdate(DbSession, LiveMeasureDto)}, except that it triggers a single SQL request - * <strong>This method should not be called unless {@link Dialect#supportsUpsert()} is true</strong> - */ - public int upsert(DbSession dbSession, LiveMeasureDto dto) { - dto.setUuidForUpsert(Uuids.create()); - return mapper(dbSession).upsert(dto, system2.now()); - } - - public void deleteByComponentUuidExcludingMetricUuids(DbSession dbSession, String componentUuid, List<String> excludedMetricUuids) { - mapper(dbSession).deleteByComponentUuidExcludingMetricUuids(componentUuid, excludedMetricUuids); - } - - 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 deleted file mode 100644 index eb60db3dc2d..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDto.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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; - - /** - * UUID generated only for UPSERT statements in PostgreSQL. It's never used - * in SELECT or regular INSERT/UPDATE. - */ - @Nullable - private String uuidForUpsert; - - private String componentUuid; - private String projectUuid; - private String metricUuid; - @Nullable - private Double value; - @Nullable - private String textValue; - @Nullable - private byte[] data; - - void setUuidForUpsert(@Nullable String s) { - this.uuidForUpsert = s; - } - - 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 String getMetricUuid() { - return metricUuid; - } - - public LiveMeasureDto setMetricUuid(String uuid) { - this.metricUuid = uuid; - 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; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("LiveMeasureDto{"); - sb.append("componentUuid='").append(componentUuid).append('\''); - sb.append(", projectUuid='").append(projectUuid).append('\''); - sb.append(", metricUuid=").append(metricUuid); - sb.append(", value=").append(value); - 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 deleted file mode 100644 index 691168ad52e..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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.CheckForNull; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.session.ResultHandler; - -public interface LiveMeasureMapper { - - List<LiveMeasureDto> selectByComponentUuidsAndMetricUuids( - @Param("componentUuids") Collection<String> componentUuids, - @Param("metricUuids") Collection<String> metricUuids); - - LiveMeasureDto selectByComponentUuidAndMetricKey( - @Param("componentUuid") String componentUuid, - @Param("metricKey") String metricKey); - - void insert( - @Param("dto") LiveMeasureDto dto, - @Param("uuid") String uuid, - @Param("now") long now); - - int update( - @Param("dto") LiveMeasureDto dto, - @Param("now") long now); - - int upsert( - @Param("dto") LiveMeasureDto dto, - @Param("now") long now); - - void deleteByComponentUuidExcludingMetricUuids( - @Param("componentUuid") String componentUuid, - @Param("excludedMetricUuids") List<String> excludedMetricUuids); - -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMainBranchLiveMeasureDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMainBranchLiveMeasureDto.java deleted file mode 100644 index 6644b1245bb..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMainBranchLiveMeasureDto.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 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 javax.annotation.Nullable; - -public class ProjectMainBranchLiveMeasureDto { - private String projectUuid; - private String metricUuid; - @Nullable - private Double value; - @Nullable - private String textValue; - - public String getProjectUuid() { - return projectUuid; - } - - @Nullable - public Double getValue() { - return value; - } - - @Nullable - public String getTextValue() { - return textValue; - } - - public String getMetricUuid() { - return metricUuid; - } -} 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 68f55067421..696ad185515 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 @@ -158,15 +158,6 @@ class PurgeCommands { }); profiler.stop(); - profiler.start("purgeDisabledComponents (live_measures)"); - executeLargeInputs( - purgeMapper.selectDisabledComponentsWithLiveMeasures(rootComponentUuid), - input -> { - purgeMapper.deleteLiveMeasuresByComponentUuids(input); - return input; - }); - profiler.stop(); - profiler.start("purgeDisabledComponents (measures)"); executeLargeInputs( purgeMapper.selectDisabledComponentsWithMeasures(rootComponentUuid), @@ -458,13 +449,6 @@ class PurgeCommands { profiler.stop(); } - void deleteLiveMeasures(String rootUuid) { - profiler.start("deleteLiveMeasures (live_measures)"); - purgeMapper.deleteLiveMeasuresByProjectUuid(rootUuid); - session.commit(); - profiler.stop(); - } - void deleteMeasures(String rootUuid) { profiler.start("deleteMeasures (measures)"); purgeMapper.deleteMeasuresByBranchUuid(rootUuid); 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 51e06e94f90..36bf5417a30 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 @@ -271,7 +271,6 @@ public class PurgeDao implements Dao { commands.deleteFileSources(branchUuid); commands.deleteCeActivity(branchUuid); commands.deleteCeQueue(branchUuid); - commands.deleteLiveMeasures(branchUuid); commands.deleteMeasures(branchUuid); commands.deleteNewCodePeriodsForBranch(branchUuid); commands.deleteBranch(branchUuid); @@ -295,7 +294,6 @@ public class PurgeDao implements Dao { commands.deleteCeQueue(projectUuid); commands.deleteWebhooks(projectUuid); commands.deleteWebhookDeliveries(projectUuid); - commands.deleteLiveMeasures(projectUuid); commands.deleteMeasures(projectUuid); commands.deleteProjectAlmSettings(projectUuid); commands.deletePermissions(projectUuid); 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 6053dc0fe32..00c96ee50bd 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 @@ -38,8 +38,6 @@ public interface PurgeMapper { Set<String> selectDisabledComponentsWithUnresolvedIssues(@Param("branchUuid") String branchUuid); - Set<String> selectDisabledComponentsWithLiveMeasures(@Param("branchUuid") String branchUuid); - Set<String> selectDisabledComponentsWithMeasures(@Param("branchUuid") String branchUuid); void deleteAnalyses(@Param("analysisUuids") List<String> analysisUuids); @@ -169,12 +167,8 @@ public interface PurgeMapper { void deleteBranchByUuid(@Param("uuid") String uuid); - void deleteLiveMeasuresByProjectUuid(@Param("projectUuid") String projectUuid); - void deleteMeasuresByBranchUuid(@Param("branchUuid") String branchUuid); - void deleteLiveMeasuresByComponentUuids(@Param("componentUuids") List<String> componentUuids); - void deleteMeasuresByComponentUuids(@Param("componentUuids") List<String> componentUuids); void deleteNewCodePeriodsByProjectUuid(String projectUuid); 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 deleted file mode 100644 index bc684fd1e09..00000000000 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml +++ /dev/null @@ -1,115 +0,0 @@ -<?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_uuid as metricUuid, - lm.value as value, - lm.text_value as textValue, - lm.measure_data as data - </sql> - - <select id="selectByComponentUuidsAndMetricUuids" parameterType="map" resultType="org.sonar.db.measure.LiveMeasureDto"> - select <include refid="columns"/> from live_measures lm - where - lm.metric_uuid in <foreach item="metricUuid" collection="metricUuids" open="(" separator="," - close=")">#{metricUuid, jdbcType=VARCHAR}</foreach> - and lm.component_uuid in - <foreach item="componentUuid" collection="componentUuids" open="(" separator="," close=")"> - #{componentUuid, jdbcType=VARCHAR} - </foreach> - </select> - - <select id="selectByComponentUuidAndMetricKey" parameterType="map" resultType="org.sonar.db.measure.LiveMeasureDto"> - select <include refid="columns"/> from live_measures lm - inner join metrics m on m.uuid = lm.metric_uuid - where - m.name = #{metricKey, jdbcType=VARCHAR} - and lm.component_uuid = #{componentUuid, jdbcType=VARCHAR} - </select> - - <insert id="insert" parameterType="map" useGeneratedKeys="false"> - insert into live_measures ( - uuid, - component_uuid, - project_uuid, - metric_uuid, - value, - text_value, - measure_data, - created_at, - updated_at - ) values ( - #{uuid, jdbcType=VARCHAR}, - #{dto.componentUuid, jdbcType=VARCHAR}, - #{dto.projectUuid, jdbcType=VARCHAR}, - #{dto.metricUuid, jdbcType=VARCHAR}, - #{dto.value, jdbcType=DOUBLE}, - #{dto.textValue, jdbcType=VARCHAR}, - #{dto.data, jdbcType=BINARY}, - #{now, jdbcType=BIGINT}, - #{now, jdbcType=BIGINT} - ) - </insert> - - <update id="update" parameterType="map"> - update live_measures set - value = #{dto.value, jdbcType=DOUBLE}, - text_value = #{dto.textValue, jdbcType=VARCHAR}, - measure_data = #{dto.data, jdbcType=BINARY}, - updated_at = #{now, jdbcType=BIGINT} - where - component_uuid = #{dto.componentUuid, jdbcType=VARCHAR} - and metric_uuid = #{dto.metricUuid, jdbcType=VARCHAR} - </update> - - <update id="upsert" parameterType="map" useGeneratedKeys="false" databaseId="postgresql"> - insert into live_measures ( - uuid, - component_uuid, - project_uuid, - metric_uuid, - value, - text_value, - measure_data, - created_at, - updated_at - ) values ( - #{dto.uuidForUpsert, jdbcType=VARCHAR}, - #{dto.componentUuid, jdbcType=VARCHAR}, - #{dto.projectUuid, jdbcType=VARCHAR}, - #{dto.metricUuid, jdbcType=VARCHAR}, - #{dto.value, jdbcType=DOUBLE}, - #{dto.textValue, jdbcType=VARCHAR}, - #{dto.data, jdbcType=BINARY}, - #{now, jdbcType=BIGINT}, - #{now, jdbcType=BIGINT} - ) - on conflict(component_uuid, metric_uuid) do update set - value = excluded.value, - text_value = excluded.text_value, - measure_data = excluded.measure_data, - updated_at = excluded.updated_at - where - live_measures.value is distinct from excluded.value or - live_measures.text_value is distinct from excluded.text_value or - live_measures.measure_data is distinct from excluded.measure_data - </update> - - <delete id="deleteByComponentUuidExcludingMetricUuids" parameterType="map"> - <include refid="sql_deleteByComponentUuidExcludingMetricUuids"/> - </delete> - - <sql id="sql_deleteByComponentUuidExcludingMetricUuids"> - delete from live_measures - where - component_uuid = #{componentUuid, jdbcType=VARCHAR} - <if test="!excludedMetricUuids.isEmpty()"> - and metric_uuid not in <foreach collection="excludedMetricUuids" item="metricUuid" open="(" close=")" separator=",">#{metricUuid,jdbcType=VARCHAR}</foreach> - </if> - </sql> - -</mapper> 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 7e4ebdafb46..3700a8df647 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 @@ -114,16 +114,6 @@ resolution is null </select> - <select id="selectDisabledComponentsWithLiveMeasures" parameterType="map" resultType="String"> - select - lm.component_uuid - from live_measures lm - inner join components p on - p.uuid = lm.component_uuid - and p.enabled = ${_false} - and p.branch_uuid=#{branchUuid,jdbcType=VARCHAR} - </select> - <select id="selectDisabledComponentsWithMeasures" parameterType="map" resultType="String"> select m.component_uuid @@ -637,19 +627,10 @@ delete from project_branches where uuid=#{uuid,jdbcType=VARCHAR} </delete> - <delete id="deleteLiveMeasuresByProjectUuid"> - delete from live_measures where project_uuid = #{projectUuid,jdbcType=VARCHAR} - </delete> - <delete id="deleteMeasuresByBranchUuid"> delete from measures where branch_uuid = #{branchUuid,jdbcType=VARCHAR} </delete> - <delete id="deleteLiveMeasuresByComponentUuids"> - delete from live_measures where component_uuid in <foreach item="componentUuid" index="index" collection="componentUuids" open="(" - separator="," close=")">#{componentUuid, jdbcType=VARCHAR}</foreach> - </delete> - <delete id="deleteMeasuresByComponentUuids"> delete from measures where component_uuid in <foreach item="componentUuid" index="index" collection="componentUuids" open="(" separator="," close=")">#{componentUuid, jdbcType=VARCHAR}</foreach> diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java index 3e71d2a924a..2e4dc73955e 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java @@ -35,7 +35,6 @@ import org.sonar.db.component.ProjectData; 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.newMeasure; import static org.sonar.db.measure.MeasureTesting.newProjectMeasureDto; import static org.sonar.db.metric.MetricTesting.newMetricDto; @@ -86,29 +85,6 @@ 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(db.getSession(), dto); - db.commit(); - return dto; - } - - @SafeVarargs - public final LiveMeasureDto insertLiveMeasure(BranchDto branchDto, MetricDto metric, Consumer<LiveMeasureDto>... consumers) { - LiveMeasureDto dto = newLiveMeasure(branchDto, metric); - Arrays.stream(consumers).forEach(c -> c.accept(dto)); - dbClient.liveMeasureDao().insert(db.getSession(), dto); - db.commit(); - return dto; - } - - @SafeVarargs - public final LiveMeasureDto insertLiveMeasure(ProjectData projectData, MetricDto metric, Consumer<LiveMeasureDto>... consumers) { - return insertLiveMeasure(projectData.getMainBranchComponent(), metric, consumers); - } - - @SafeVarargs public final MeasureDto insertMeasure(ComponentDto component, Consumer<MeasureDto>... consumers) { return insertMeasure(component.uuid(), component.branchUuid(), consumers); } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureTesting.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureTesting.java index 24379ae20bb..7457e5645b5 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureTesting.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureTesting.java @@ -64,33 +64,6 @@ public class MeasureTesting { .setValue((double) cursor++); } - public static LiveMeasureDto newLiveMeasure() { - return new LiveMeasureDto() - .setMetricUuid(String.valueOf(cursor++)) - .setComponentUuid(String.valueOf(cursor++)) - .setProjectUuid(String.valueOf(cursor++)) - .setData(String.valueOf(cursor++)) - .setValue((double) cursor++); - } - - public static LiveMeasureDto newLiveMeasure(ComponentDto component, MetricDto metric) { - return new LiveMeasureDto() - .setMetricUuid(metric.getUuid()) - .setComponentUuid(component.uuid()) - .setProjectUuid(component.branchUuid()) - .setData(String.valueOf(cursor++)) - .setValue((double) cursor++); - } - - public static LiveMeasureDto newLiveMeasure(BranchDto branchDto, MetricDto metric) { - return new LiveMeasureDto() - .setMetricUuid(metric.getUuid()) - .setComponentUuid(branchDto.getUuid()) - .setProjectUuid(branchDto.getProjectUuid()) - .setData(String.valueOf(cursor++)) - .setValue((double) cursor++); - } - public static MeasureDto newMeasure() { return newMeasure(String.valueOf(cursor++), String.valueOf(cursor++), "metric" + cursor++, (double) cursor++); } diff --git a/server/sonar-db-migration/src/docs/table_ownership.md b/server/sonar-db-migration/src/docs/table_ownership.md index 92aed2c5fc6..99e27309c35 100644 --- a/server/sonar-db-migration/src/docs/table_ownership.md +++ b/server/sonar-db-migration/src/docs/table_ownership.md @@ -49,7 +49,7 @@ Important read: [Data Ownership Principles](https://xtranet-sonarsource.atlassia | issues | Analysis Experience Squad | | issues_fixed | Analysis Experience Squad | | issues_impacts | Analysis Experience Squad | -| live_measures | Analysis Experience Squad | +| measures | Analysis Experience Squad | | metrics | | | new_code_periods | Dev and Team Workflow Squad | | new_code_reference_issues | | @@ -68,7 +68,7 @@ Important read: [Data Ownership Principles](https://xtranet-sonarsource.atlassia | project_badge_token | Dev and Team Workflow Squad | | project_branches | | | project_links | Dev and Team Workflow Squad | -| project_measures | | +| project_measures | Analysis Experience Squad | | project_qgates | Dev and Team Workflow Squad | | project_qprofiles | Dev and Team Workflow Squad | | projects | | diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/StatisticsSupportTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/StatisticsSupportTest.java index d561fa68692..a40f1c639d6 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/StatisticsSupportTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/StatisticsSupportTest.java @@ -35,7 +35,7 @@ public class StatisticsSupportTest { private final StatisticsSupport statisticsSupport = new StatisticsSupport(dbClient); @Test - public void should_return_metric_from_liveMeasureDao() { + public void should_return_metric() { when(dbClient.projectDao().getNclocSum(any(DbSession.class))).thenReturn(1800999L); long linesOfCode = statisticsSupport.getLinesOfCode(); @@ -43,4 +43,4 @@ public class StatisticsSupportTest { assertThat(linesOfCode).isEqualTo(1800999L); } -}
\ No newline at end of file +} diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/ListActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/ListActionIT.java index f21a0eb65df..4e0db4780cd 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/ListActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/ListActionIT.java @@ -37,7 +37,6 @@ import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ProjectData; import org.sonar.db.issue.IssueDto; -import org.sonar.db.metric.MetricDto; import org.sonar.db.protobuf.DbIssues; import org.sonar.db.rule.RuleDto; import org.sonar.db.user.UserDto; @@ -395,8 +394,7 @@ public class ListActionIT { RuleDto rule = newHotspotRule(); db.components().insertSnapshot(project, s -> s.setLast(true).setPeriodMode(REFERENCE_BRANCH.name())); - MetricDto metric = db.measures().insertMetric(metricDto -> metricDto.setKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY)); - db.measures().insertLiveMeasure(project, metric); + db.measures().insertMeasure(project, m -> m.addValue(ANALYSIS_FROM_SONARQUBE_9_4_KEY, 1.0D)); List<String> beforeNewCodePeriod = IntStream.range(0, 10).mapToObj(number -> db.issues().insertHotspot(rule, project, file, i -> i .setEffort(10L) diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/ListActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/ListActionIT.java index 0b207e6a128..4606f7936cb 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/ListActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/ListActionIT.java @@ -42,7 +42,6 @@ import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ProjectData; import org.sonar.db.issue.ImpactDto; import org.sonar.db.issue.IssueDto; -import org.sonar.db.metric.MetricDto; import org.sonar.db.protobuf.DbIssues; import org.sonar.db.rule.RuleDto; import org.sonar.db.user.UserDto; @@ -644,8 +643,7 @@ public class ListActionIT { RuleDto rule = newIssueRule(); db.components().insertSnapshot(project, s -> s.setLast(true).setPeriodMode(REFERENCE_BRANCH.name())); - MetricDto metric = db.measures().insertMetric(metricDto -> metricDto.setKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY)); - db.measures().insertLiveMeasure(project, metric); + db.measures().insertMeasure(project, m -> m.addValue(ANALYSIS_FROM_SONARQUBE_9_4_KEY, 1.0D)); List<String> beforeNewCodePeriod = IntStream.range(0, 10).mapToObj(number -> db.issues().insertIssue(rule, project, file, i -> i .setEffort(10L) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java index 76541f0f628..f2634d39e2f 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java @@ -20,7 +20,6 @@ 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.measure.ProjectMeasureDto; import org.sonar.db.metric.MetricDto; @@ -43,12 +42,6 @@ class MeasureDtoToWsMeasure { updateMeasureBuilder(measureBuilder, metricDto, value, projectMeasureDto.getData(), onNewCode); } - static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metricDto, LiveMeasureDto measureDto) { - double value = measureDto.getValue() == null ? Double.NaN : measureDto.getValue(); - boolean onNewCode = metricDto.getKey().startsWith("new_"); - updateMeasureBuilder(measureBuilder, metricDto, value, measureDto.getDataAsString(), onNewCode); - } - static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metricDto, MeasureDto measureDto) { double doubleValue; String stringValue = null; diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureValueFormatter.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureValueFormatter.java index c9c2bd42db4..e7c730e1d05 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureValueFormatter.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureValueFormatter.java @@ -22,7 +22,6 @@ package org.sonar.server.measure.ws; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.api.measures.Metric; -import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.measure.ProjectMeasureDto; import org.sonar.db.metric.MetricDto; @@ -34,13 +33,6 @@ public class MeasureValueFormatter { } @CheckForNull - public static String formatMeasureValue(LiveMeasureDto measure, MetricDto metric) { - Double doubleValue = measure.getValue(); - String stringValue = measure.getDataAsString(); - return formatMeasureValue(doubleValue == null ? Double.NaN : doubleValue, stringValue, metric); - } - - @CheckForNull static String formatMeasureValue(ProjectMeasureDto measure, MetricDto metric) { Double doubleValue = measure.getValue(); String stringValue = measure.getData(); |