import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.measure.LiveMeasureComparator;
-import org.sonar.db.measure.LiveMeasureDao;
+import org.sonar.db.measure.LiveMeasureDto;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableSet;
@Override
public void execute(ComputationStep.Context context) {
boolean supportUpsert = dbClient.getDatabase().getDialect().supportsUpsert();
- try (DbSession dbSession = dbClient.openSession(supportUpsert)) {
+ try (DbSession dbSession = dbClient.openSession(false)) {
Component root = treeRootHolder.getRoot();
MeasureVisitor visitor = new MeasureVisitor(dbSession, supportUpsert);
new DepthTraversalTypeAwareCrawler(visitor).visit(root);
- context.getStatistics().add("insertsOrUpdates", visitor.insertsOrUpdates);
+ context.getStatistics()
+ .add("insertsOrUpdates", visitor.insertsOrUpdates);
}
}
@Override
public void visitAny(Component component) {
- LiveMeasureDao dao = dbClient.liveMeasureDao();
List<Integer> metricIds = new ArrayList<>();
Multimap<String, Measure> measures = measureRepository.getRawMeasures(component);
+ List<LiveMeasureDto> dtos = new ArrayList<>();
for (Map.Entry<String, Collection<Measure>> measuresByMetricKey : measures.asMap().entrySet()) {
String metricKey = measuresByMetricKey.getKey();
if (NOT_TO_PERSIST_ON_FILE_METRIC_KEYS.contains(metricKey) && component.getType() == Component.Type.FILE) {
// To prevent deadlock, live measures are ordered the same way as in LiveMeasureComputerImpl#refreshComponentsOnSameProject
.sorted(LiveMeasureComparator.INSTANCE)
.forEach(lm -> {
- if (supportUpsert) {
- dao.upsert(dbSession, lm);
- } else {
- dao.insertOrUpdate(dbSession, lm);
- }
+ dtos.add(lm);
metricIds.add(metric.getId());
- insertsOrUpdates++;
});
}
+ if (supportUpsert) {
+ dbClient.liveMeasureDao().upsert(dbSession, dtos);
+ } else {
+ for (LiveMeasureDto dto : dtos) {
+ dbClient.liveMeasureDao().insertOrUpdate(dbSession, dto);
+ }
+ }
+ insertsOrUpdates += dtos.size();
+
// 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
- dao.deleteByComponentUuidExcludingMetricIds(dbSession, component.getUuid(), metricIds);
+ dbClient.liveMeasureDao().deleteByComponentUuidExcludingMetricIds(dbSession, component.getUuid(), metricIds);
dbSession.commit();
}
}
return input.getValueType() != Measure.ValueType.NO_VALUE || input.hasVariation() || input.getData() != null;
}
}
-
-
}
measure_data,
created_at,
updated_at
- ) values (
- #{uuid, jdbcType=VARCHAR},
+ ) values
+ <foreach item="dto" collection="dtos" open="(" separator="),(" close=")">
+ #{dto.uuidForUpsert, jdbcType=VARCHAR},
#{dto.componentUuid, jdbcType=VARCHAR},
#{dto.projectUuid, jdbcType=VARCHAR},
#{dto.metricId, jdbcType=INTEGER},
#{dto.data, jdbcType=BINARY},
#{now, jdbcType=BIGINT},
#{now, jdbcType=BIGINT}
- ) on conflict(component_uuid, metric_id) do update set
+ </foreach>
+ on conflict(component_uuid, metric_id) do update set
value = excluded.value,
variation = excluded.variation,
text_value = excluded.text_value,
measure_data = excluded.measure_data,
updated_at = excluded.updated_at
- where
- <if test="dto.value==null">
- live_measures.value is not null
- </if>
- <if test="dto.value!=null">
- (live_measures.value is null or live_measures.value != excluded.value)
- </if>
- or
- <if test="dto.textValue==null">
- live_measures.text_value is not null
- </if>
- <if test="dto.textValue!=null">
- (live_measures.text_value is null or live_measures.text_value != excluded.text_value)
- </if>
- or
- <if test="dto.variation==null">
- live_measures.variation is not null
- </if>
- <if test="dto.variation!=null">
- (live_measures.variation is null or live_measures.variation != excluded.variation)
- </if>
- or
- <if test="dto.data==null">
- live_measures.measure_data is not null
- </if>
- <if test="dto.data!=null">
- (live_measures.measure_data is null or live_measures.measure_data != excluded.measure_data)
- </if>
+ where
+ live_measures.value is distinct from excluded.value or
+ live_measures.variation is distinct from excluded.variation 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="deleteByComponentUuidExcludingMetricIds" parameterType="map">
import java.util.Collections;
import java.util.List;
import java.util.Optional;
+import java.util.stream.IntStream;
import org.apache.commons.lang.RandomStringUtils;
import org.junit.Before;
import org.junit.Rule;
// insert
LiveMeasureDto dto = newLiveMeasure();
- int count = underTest.upsert(db.getSession(), dto);
+ int count = underTest.upsert(db.getSession(), asList(dto));
verifyPersisted(dto);
verifyTableSize(1);
assertThat(count).isEqualTo(1);
dto.setValue(dto.getValue() + 1);
dto.setVariation(dto.getVariation() + 10);
dto.setData(dto.getDataAsString() + "_new");
- count = underTest.upsert(db.getSession(), dto);
+ count = underTest.upsert(db.getSession(), asList(dto));
assertThat(count).isEqualTo(1);
verifyPersisted(dto);
verifyTableSize(1);
}
LiveMeasureDto dto = newLiveMeasure();
- underTest.upsert(db.getSession(), dto);
+ underTest.upsert(db.getSession(), asList(dto));
// update
- int count = underTest.upsert(db.getSession(), dto);
+ int count = underTest.upsert(db.getSession(), asList(dto));
assertThat(count).isEqualTo(0);
verifyPersisted(dto);
verifyTableSize(1);
}
LiveMeasureDto dto = newLiveMeasure().setData(RandomStringUtils.random(10_000));
- underTest.upsert(db.getSession(), dto);
+ underTest.upsert(db.getSession(), asList(dto));
// update
dto.setData(RandomStringUtils.random(dto.getDataAsString().length() + 10));
- int count = underTest.upsert(db.getSession(), dto);
+ int count = underTest.upsert(db.getSession(), asList(dto));
assertThat(count).isEqualTo(1);
verifyPersisted(dto);
verifyTableSize(1);
return;
}
LiveMeasureDto dto = newLiveMeasure().setData(RandomStringUtils.random(10_000));
- underTest.upsert(db.getSession(), dto);
+ underTest.upsert(db.getSession(), asList(dto));
// update
- int count = underTest.upsert(db.getSession(), dto);
+ int count = underTest.upsert(db.getSession(), asList(dto));
assertThat(count).isEqualTo(0);
verifyPersisted(dto);
verifyTableSize(1);
}
LiveMeasureDto dto = newLiveMeasure().setData(RandomStringUtils.random(10_000));
- underTest.upsert(db.getSession(), dto);
+ underTest.upsert(db.getSession(), asList(dto));
// update
dto.setData((String)null);
- int count = underTest.upsert(db.getSession(), dto);
+ int count = underTest.upsert(db.getSession(), asList(dto));
assertThat(count).isEqualTo(1);
verifyPersisted(dto);
verifyTableSize(1);
return;
}
LiveMeasureDto dto = newLiveMeasure().setVariation(40.0);
- underTest.upsert(db.getSession(), dto);
+ underTest.upsert(db.getSession(), asList(dto));
// update
dto.setVariation(50.0);
- int count = underTest.upsert(db.getSession(), dto);
+ int count = underTest.upsert(db.getSession(), asList(dto));
assertThat(count).isEqualTo(1);
verifyPersisted(dto);
verifyTableSize(1);
return;
}
LiveMeasureDto dto = newLiveMeasure().setVariation(40.0);
- underTest.upsert(db.getSession(), dto);
+ underTest.upsert(db.getSession(), asList(dto));
// update
dto.setVariation(null);
- int count = underTest.upsert(db.getSession(), dto);
+ int count = underTest.upsert(db.getSession(), asList(dto));
assertThat(count).isEqualTo(1);
verifyPersisted(dto);
verifyTableSize(1);
return;
}
LiveMeasureDto dto = newLiveMeasure().setVariation(null);
- underTest.upsert(db.getSession(), dto);
+ underTest.upsert(db.getSession(), asList(dto));
// update
dto.setVariation(40.0);
- int count = underTest.upsert(db.getSession(), dto);
+ int count = underTest.upsert(db.getSession(), asList(dto));
assertThat(count).isEqualTo(1);
verifyPersisted(dto);
verifyTableSize(1);
return;
}
LiveMeasureDto dto = newLiveMeasure().setValue(40.0);
- underTest.upsert(db.getSession(), dto);
+ underTest.upsert(db.getSession(), asList(dto));
// update
dto.setValue(50.0);
- int count = underTest.upsert(db.getSession(), dto);
+ int count = underTest.upsert(db.getSession(), asList(dto));
assertThat(count).isEqualTo(1);
verifyPersisted(dto);
verifyTableSize(1);
return;
}
LiveMeasureDto dto = newLiveMeasure().setValue(40.0);
- underTest.upsert(db.getSession(), dto);
+ underTest.upsert(db.getSession(), asList(dto));
// update
dto.setValue(null);
- int count = underTest.upsert(db.getSession(), dto);
+ int count = underTest.upsert(db.getSession(), asList(dto));
assertThat(count).isEqualTo(1);
verifyPersisted(dto);
verifyTableSize(1);
return;
}
LiveMeasureDto dto = newLiveMeasure().setValue(null);
- underTest.upsert(db.getSession(), dto);
+ underTest.upsert(db.getSession(), asList(dto));
// update
dto.setValue(40.0);
- int count = underTest.upsert(db.getSession(), dto);
+ int count = underTest.upsert(db.getSession(), asList(dto));
assertThat(count).isEqualTo(1);
verifyPersisted(dto);
verifyTableSize(1);
}
+ @Test
+ public 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()));
+ int result = underTest.upsert(db.getSession(), inserted);
+ verifyTableSize(30);
+ assertThat(result).isEqualTo(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()));
+ result = underTest.upsert(db.getSession(), upserted);
+ verifyTableSize(80);
+ assertThat(result).isEqualTo(60);
+ }
+
private void verifyTableSize(int expectedSize) {
assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isEqualTo(expectedSize);
}
private void verifyPersisted(LiveMeasureDto dto) {
List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricIds(db.getSession(), singletonList(dto.getComponentUuid()), singletonList(dto.getMetricId()));
assertThat(selected).hasSize(1);
- assertThat(selected.get(0)).isEqualToComparingFieldByField(dto);
+ assertThat(selected.get(0)).isEqualToComparingOnlyGivenFields(dto,
+ // do not compare the field "uuid", which is used only for insert, not select
+ "componentUuid", "projectUuid", "metricId", "value", "textValue", "data", "variation");
}
}