*/
package org.sonar.ce.task.projectanalysis.analysis;
+import java.util.Objects;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@Immutable
public class Analysis {
- private long id;
private String uuid;
private long createdAt;
private Analysis(Builder builder) {
- this.id = builder.id;
this.uuid = builder.uuid;
this.createdAt = builder.createdAt;
}
- public long getId() {
- return id;
- }
-
public String getUuid() {
return uuid;
}
}
public static final class Builder {
- @CheckForNull
- private Long id;
@CheckForNull
private String uuid;
@CheckForNull
private Long createdAt;
- public Builder setId(long id) {
- this.id = id;
- return this;
- }
-
public Builder setUuid(String uuid) {
this.uuid = uuid;
return this;
}
public Analysis build() {
- checkNotNull(id, "id cannot be null");
checkNotNull(uuid, "uuid cannot be null");
checkNotNull(createdAt, "createdAt cannot be null");
return new Analysis(this);
}
Analysis analysis = (Analysis) o;
- return id == analysis.id;
+ return Objects.equals(uuid, analysis.uuid);
}
@Override
public int hashCode() {
- return (int) (id ^ (id >>> 32));
+ return Objects.hash(uuid);
}
@Override
public String toString() {
return "Analysis{" +
- "id=" + id +
- ", uuid='" + uuid + '\'' +
+ "uuid='" + uuid + '\'' +
", createdAt=" + createdAt +
'}';
}
private static Analysis toAnalysis(SnapshotDto dto) {
return new Analysis.Builder()
- .setId(dto.getId())
.setUuid(dto.getUuid())
.setCreatedAt(dto.getCreatedAt())
.build();
@Test
public void build_snapshot() {
Analysis analysis = new Analysis.Builder()
- .setId(ID)
.setUuid(UUID)
.setCreatedAt(CREATED_AT)
.build();
- assertThat(analysis.getId()).isEqualTo(ID);
assertThat(analysis.getUuid()).isEqualTo(UUID);
assertThat(analysis.getCreatedAt()).isEqualTo(CREATED_AT);
}
- @Test
- public void fail_with_NPE_when_building_snapshot_without_id() {
- thrown.expect(NullPointerException.class);
- thrown.expectMessage("id cannot be null");
-
- new Analysis.Builder()
- .setUuid(UUID)
- .setCreatedAt(CREATED_AT)
- .build();
- }
-
@Test
public void fail_with_NPE_when_building_snapshot_without_uuid() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("uuid cannot be null");
new Analysis.Builder()
- .setId(ID)
.setCreatedAt(CREATED_AT)
.build();
}
thrown.expectMessage("createdAt cannot be null");
new Analysis.Builder()
- .setId(ID)
.setUuid(UUID)
.build();
}
@Test
public void test_toString() {
assertThat(new Analysis.Builder()
- .setId(ID)
.setUuid(UUID)
.setCreatedAt(CREATED_AT)
.build().toString())
- .isEqualTo("Analysis{id=10, uuid='uuid ', createdAt=123456789}");
+ .isEqualTo("Analysis{uuid='uuid ', createdAt=123456789}");
}
@Test
public void test_equals_and_hascode() {
Analysis analysis = new Analysis.Builder()
- .setId(ID)
.setUuid(UUID)
.setCreatedAt(CREATED_AT)
.build();
Analysis sameAnalysis = new Analysis.Builder()
- .setId(ID)
.setUuid(UUID)
.setCreatedAt(CREATED_AT)
.build();
- Analysis sameAnalysisNotSameUuid = new Analysis.Builder()
- .setId(ID)
- .setUuid("other uuid")
- .setCreatedAt(CREATED_AT)
- .build();
Analysis otherAnalysis = new Analysis.Builder()
- .setId(11L)
- .setUuid(UUID)
+ .setUuid("other uuid")
.setCreatedAt(CREATED_AT)
.build();
assertThat(analysis).isEqualTo(analysis);
assertThat(analysis).isEqualTo(sameAnalysis);
- assertThat(analysis).isEqualTo(sameAnalysisNotSameUuid);
assertThat(analysis).isNotEqualTo(otherAnalysis);
assertThat(analysis).isNotEqualTo(null);
assertThat(analysis.hashCode()).isEqualTo(analysis.hashCode());
assertThat(analysis.hashCode()).isEqualTo(sameAnalysis.hashCode());
- assertThat(analysis.hashCode()).isEqualTo(sameAnalysisNotSameUuid.hashCode());
assertThat(analysis.hashCode()).isNotEqualTo(otherAnalysis.hashCode());
}
}
public class AnalysisMetadataHolderImplTest {
private static Analysis baseProjectAnalysis = new Analysis.Builder()
- .setId(1)
.setUuid("uuid_1")
.setCreatedAt(123456789L)
.build();
public class FileMoveDetectionStepTest {
- private static final long SNAPSHOT_ID = 98765;
+ private static final String SNAPSHOT_UUID = "uuid_1";
private static final Analysis ANALYSIS = new Analysis.Builder()
- .setId(SNAPSHOT_ID)
- .setUuid("uuid_1")
+ .setUuid(SNAPSHOT_UUID)
.setCreatedAt(86521)
.build();
private static final int ROOT_REF = 1;
static final int FILE_REF = 1;
static final Component FILE = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").build();
static final long DATE_1 = 123456789L;
- static final long DATE_2 = 1234567810L;
static Analysis baseProjectAnalysis = new Analysis.Builder()
- .setId(1)
.setUuid("uuid_1")
.setCreatedAt(123456789L)
.build();
import org.sonar.scanner.protocol.output.ScannerReport;
import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
dbSession.commit();
baseProjectAnalysis = new Analysis.Builder()
- .setId(projectSnapshot.getId())
.setUuid(projectSnapshot.getUuid())
.setCreatedAt(projectSnapshot.getCreatedAt())
.build();
.setStartTokenIndex(0)
.setEndTokenIndex(10)
.build();
- batchReportReader.putDuplicationBlocks(FILE_REF, asList(originBlock));
+ batchReportReader.putDuplicationBlocks(FILE_REF, singletonList(originBlock));
underTest.execute(new TestComputationStepContext());
verify(integrateCrossProjectDuplications).computeCpd(CURRENT_FILE,
- asList(
+ singletonList(
new Block.Builder()
.setResourceId(CURRENT_FILE_KEY)
.setBlockHash(new ByteArray(hash))
.setLines(originBlock.getStartLine(), originBlock.getEndLine())
.setUnit(originBlock.getStartTokenIndex(), originBlock.getEndTokenIndex())
.build()),
- asList(
+ singletonList(
new Block.Builder()
.setResourceId(otherFile.getDbKey())
.setBlockHash(new ByteArray(hash))
.setStartTokenIndex(0)
.setEndTokenIndex(10)
.build();
- batchReportReader.putDuplicationBlocks(FILE_REF, asList(originBlock));
+ batchReportReader.putDuplicationBlocks(FILE_REF, singletonList(originBlock));
underTest.execute(new TestComputationStepContext());
underTest.execute(new TestComputationStepContext());
- verifyZeroInteractions(integrateCrossProjectDuplications);
+ verifyNoInteractions(integrateCrossProjectDuplications);
}
@Test
.setStartTokenIndex(0)
.setEndTokenIndex(10)
.build();
- batchReportReader.putDuplicationBlocks(FILE_REF, asList(originBlock));
+ batchReportReader.putDuplicationBlocks(FILE_REF, singletonList(originBlock));
underTest.execute(new TestComputationStepContext());
- verifyZeroInteractions(integrateCrossProjectDuplications);
+ verifyNoInteractions(integrateCrossProjectDuplications);
}
private ComponentDto createProject(String projectKey) {
public static final int MAX_VERSION_LENGTH = 100;
public static final int MAX_BUILD_STRING_LENGTH = 100;
- private Long id;
private String uuid;
private String componentUuid;
private Long createdAt;
@Nullable
private String revision;
- public Long getId() {
- return id;
- }
-
- public SnapshotDto setId(Long id) {
- this.id = id;
- return this;
- }
-
public SnapshotDto setUuid(String s) {
this.uuid = s;
return this;
return false;
}
SnapshotDto that = (SnapshotDto) o;
- return Objects.equals(id, that.id) &&
- Objects.equals(uuid, that.uuid) &&
+ return Objects.equals(uuid, that.uuid) &&
Objects.equals(componentUuid, that.componentUuid) &&
Objects.equals(createdAt, that.createdAt) &&
Objects.equals(buildDate, that.buildDate) &&
@Override
public int hashCode() {
- return Objects.hash(id, uuid, componentUuid, createdAt, buildDate, status, last, projectVersion, buildString, periodMode, periodParam, periodDate);
+ return Objects.hash(uuid, componentUuid, createdAt, buildDate, status, last, projectVersion, buildString, periodMode, periodParam, periodDate);
}
@Override
public String toString() {
return "SnapshotDto{" +
- "id=" + id +
- ", uuid='" + uuid + '\'' +
+ "uuid='" + uuid + '\'' +
", componentUuid='" + componentUuid + '\'' +
", createdAt=" + createdAt +
", buildDate=" + buildDate +
*/
public class PurgeableAnalysisDto implements Comparable<PurgeableAnalysisDto> {
private Date date;
- private long analysisId;
private String analysisUuid;
private String version;
private boolean hasEvents;
return this;
}
- public long getAnalysisId() {
- return analysisId;
- }
-
- public PurgeableAnalysisDto setAnalysisId(long analysisId) {
- this.analysisId = analysisId;
- return this;
- }
-
public String getAnalysisUuid() {
return analysisUuid;
}
<mapper namespace="org.sonar.db.component.SnapshotMapper">
<sql id="snapshotColumns">
- s.id,
s.uuid as uuid,
s.component_uuid as componentUuId,
s.created_at as createdAt,
where uuid = #{uuid,jdbcType=VARCHAR}
</update>
- <insert id="insert" parameterType="Snapshot" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
+ <insert id="insert" parameterType="Snapshot" useGeneratedKeys="false">
insert into snapshots (
uuid,
component_uuid,
<select id="selectPurgeableAnalyses" parameterType="String" resultType="PurgeableAnalysis">
select
- s.id as "analysisId",
s.uuid as "analysisUuid",
s.created_at as "date",
case when ve.analysis_uuid is not null then ${_true} else ${_false} end as "hasEvents",
CREATE UNIQUE INDEX "UNIQ_QPROF_KEY" ON "RULES_PROFILES"("KEE");
CREATE TABLE "SNAPSHOTS"(
- "ID" INTEGER NOT NULL AUTO_INCREMENT (1,1),
"UUID" VARCHAR(50) NOT NULL,
"COMPONENT_UUID" VARCHAR(50) NOT NULL,
"STATUS" VARCHAR(4) DEFAULT 'U' NOT NULL,
"PERIOD5_DATE" BIGINT,
"CREATED_AT" BIGINT
);
-ALTER TABLE "SNAPSHOTS" ADD CONSTRAINT "PK_SNAPSHOTS" PRIMARY KEY("ID");
+ALTER TABLE "SNAPSHOTS" ADD CONSTRAINT "PK_SNAPSHOTS" PRIMARY KEY("UUID");
CREATE UNIQUE INDEX "ANALYSES_UUID" ON "SNAPSHOTS"("UUID");
CREATE INDEX "SNAPSHOT_COMPONENT" ON "SNAPSHOTS"("COMPONENT_UUID");
.setRevision("sha1"));
SnapshotDto result = underTest.selectByUuid(db.getSession(), "ABCD").get();
- assertThat(result.getId()).isNotNull();
assertThat(result.getUuid()).isEqualTo("ABCD");
assertThat(result.getComponentUuid()).isEqualTo(project.uuid());
assertThat(result.getStatus()).isEqualTo("P");
List<SnapshotDto> result = underTest.selectLastAnalysesByRootComponentUuids(dbSession, newArrayList(firstProject.uuid(), secondProject.uuid()));
- assertThat(result).extracting(SnapshotDto::getId).containsOnly(lastSnapshotOfFirstProject.getId(), lastSnapshotOfSecondProject.getId());
+ assertThat(result).extracting(SnapshotDto::getUuid).containsOnly(lastSnapshotOfFirstProject.getUuid(), lastSnapshotOfSecondProject.getUuid());
}
@Test
.setBuildDate(1500000000006L)
.setCreatedAt(1403042400000L));
- assertThat(dto.getId()).isNotNull();
assertThat(dto.getUuid()).isNotNull();
assertThat(dto.getComponentUuid()).isEqualTo(project.uuid());
assertThat(dto.getStatus()).isEqualTo("P");
@Test
public void test_getter_and_setter() {
SnapshotDto snapshotDto = new SnapshotDto()
- .setId(10L)
.setBuildDate(parseDate("2014-07-02").getTime())
.setComponentUuid("uuid_21")
.setLast(true)
.setPeriodParam("param1")
.setPeriodDate(parseDate("2014-06-01").getTime());
- assertThat(snapshotDto.getId()).isEqualTo(10L);
assertThat(snapshotDto.getBuildDate()).isEqualTo(parseDate("2014-07-02").getTime());
assertThat(snapshotDto.getComponentUuid()).isEqualTo("uuid_21");
assertThat(snapshotDto.getLast()).isTrue();
*/
package org.sonar.db.purge;
-import com.google.common.collect.ImmutableList;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.util.List;
import java.util.Random;
import java.util.function.Consumer;
-import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.After;
import org.sonar.db.user.UserDto;
import static com.google.common.collect.Lists.newArrayList;
+import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
-import static java.util.stream.Collectors.toList;
import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.db.component.ComponentTesting.newBranchDto;
SnapshotDto analysis2 = dbTester.components().insertSnapshot(project);
SnapshotDto analysis3 = dbTester.components().insertSnapshot(project);
SnapshotDto analysis4 = dbTester.components().insertSnapshot(project);
- int count = 1 + random.nextInt(12);
- for (SnapshotDto analysis : Arrays.asList(analysis1, analysis2, analysis3, analysis4)) {
+ int count = 8;
+ for (SnapshotDto analysis : asList(analysis1, analysis2, analysis3, analysis4)) {
IntStream.range(0, count).forEach(i -> insertDuplication(project, analysis));
}
- underTest.purgeAnalyses(ImmutableList.of(analysis1.getUuid()));
+ underTest.purgeAnalyses(singletonList(analysis1.getUuid()));
assertThat(countDuplications(analysis1)).isZero();
assertThat(countDuplications(analysis2)).isEqualTo(count);
assertThat(countDuplications(analysis3)).isEqualTo(count);
assertThat(countDuplications(analysis4)).isEqualTo(count);
- underTest.purgeAnalyses(ImmutableList.of(analysis1.getUuid(), analysis3.getUuid(), analysis4.getUuid()));
+ underTest.purgeAnalyses(asList(analysis1.getUuid(), analysis3.getUuid(), analysis4.getUuid()));
assertThat(countDuplications(analysis1)).isZero();
assertThat(countDuplications(analysis2)).isEqualTo(count);
assertThat(countDuplications(analysis3)).isZero();
public void deleteComponents_delete_tree_of_components_of_a_view(OrganizationDto organizationDto, ComponentDto view) {
dbTester.organizations().insert(organizationDto);
dbTester.components().insertComponent(view);
- ComponentDto otherView = dbTester.components().insertView(organizationDto);
+ ComponentDto otherView = dbTester.components().insertPrivatePortfolio(organizationDto);
Stream.of(view, otherView).forEach(vw -> {
dbTester.components().insertSubView(vw);
dbTester.components().insertComponent(newProjectCopy(dbTester.components().insertPrivateProject(), vw));
public void deleteAnalyses_by_rootUuid_deletes_event_component_changes(ComponentDto projectOrView) {
dbTester.components().insertComponent(projectOrView);
ComponentDto otherProject = dbTester.components().insertPrivateProject();
- int count = 1 + new Random().nextInt(20);
+ int count = 5;
IntStream.range(0, count).forEach(i -> {
insertRandomEventComponentChange(projectOrView);
insertRandomEventComponentChange(otherProject);
ComponentDto otherProject = dbTester.components().insertPrivateProject();
SnapshotDto otherAnalysis1 = dbTester.components().insertSnapshot(otherProject);
SnapshotDto otherAnalysis2 = dbTester.components().insertSnapshot(otherProject);
- int count = 1 + new Random().nextInt(20);
+ int count = 7;
IntStream.range(0, count).forEach(i -> {
dbTester.events().insertEvent(analysis1);
dbTester.events().insertEvent(analysis2);
ComponentDto otherProject = dbTester.components().insertPrivateProject();
SnapshotDto otherAnalysis1 = dbTester.components().insertSnapshot(otherProject);
SnapshotDto otherAnalysis2 = dbTester.components().insertSnapshot(otherProject);
- int count = 1 + new Random().nextInt(20);
+ int count = 5;
Stream.of(metric1, metric2)
.forEach(metric -> {
IntStream.range(0, count).forEach(i -> {
ComponentDto otherProject = dbTester.components().insertPrivateProject();
SnapshotDto otherAnalysis1 = dbTester.components().insertSnapshot(otherProject);
SnapshotDto otherAnalysis2 = dbTester.components().insertSnapshot(otherProject);
- int count = 1 + new Random().nextInt(20);
+ int count = 5;
IntStream.range(0, count).forEach(i -> {
insertRandomAnalysisProperty(analysis1);
insertRandomAnalysisProperty(analysis2);
@UseDataProvider("projectsAndViews")
public void deleteAnalyses_by_analyses_deletes_specified_analysis(ComponentDto projectOrView) {
dbTester.components().insertComponent(projectOrView);
- List<SnapshotDto> analyses = IntStream.range(0, 5 + random.nextInt(10))
- .mapToObj(i -> dbTester.components().insertSnapshot(projectOrView, randomLastAndStatus()))
- .collect(toList());
+ SnapshotDto analysis1 = dbTester.components().insertSnapshot(projectOrView, s -> s.setStatus(STATUS_PROCESSED));
+ SnapshotDto analysis2 = dbTester.components().insertSnapshot(projectOrView, s -> s.setStatus(STATUS_PROCESSED));
+ SnapshotDto analysis3 = dbTester.components().insertSnapshot(projectOrView, s -> s.setStatus(STATUS_UNPROCESSED));
+ SnapshotDto analysis4 = dbTester.components().insertSnapshot(projectOrView, s -> s.setStatus(STATUS_UNPROCESSED));
- underTest.deleteAnalyses(singletonList(analyses.get(0).getUuid()));
+ underTest.deleteAnalyses(singletonList(analysis1.getUuid()));
assertThat(uuidsOfAnalysesOfRoot(projectOrView))
- .containsOnly(analyses.stream().skip(1).map(SnapshotDto::getUuid).toArray(String[]::new));
+ .containsOnly(analysis2.getUuid(), analysis3.getUuid(), analysis4.getUuid());
- underTest.deleteAnalyses(analyses.stream().map(SnapshotDto::getUuid).skip(1).limit(3).collect(Collectors.toList()));
+ underTest.deleteAnalyses(asList(analysis2.getUuid(), analysis3.getUuid()));
assertThat(uuidsOfAnalysesOfRoot(projectOrView))
- .containsOnly(analyses.stream().skip(4).map(SnapshotDto::getUuid).toArray(String[]::new));
+ .containsOnly(analysis4.getUuid());
- underTest.deleteAnalyses(analyses.stream().map(SnapshotDto::getUuid).collect(Collectors.toList()));
+ underTest.deleteAnalyses(asList(analysis1.getUuid(), analysis2.getUuid(), analysis3.getUuid(), analysis4.getUuid()));
assertThat(uuidsOfAnalysesOfRoot(projectOrView)).isEmpty();
}
dbTester.components().insertComponent(projectOrView);
SnapshotDto analysis = dbTester.components().insertSnapshot(projectOrView, randomLastAndStatus());
SnapshotDto otherAnalysis = dbTester.components().insertSnapshot(projectOrView);
- int count = 1 + new Random().nextInt(20);
+ int count = 5;
IntStream.range(0, count).forEach(i -> {
insertRandomEventComponentChange(analysis);
insertRandomEventComponentChange(otherAnalysis);
dbTester.components().insertComponent(projectOrView);
SnapshotDto analysis = dbTester.components().insertSnapshot(projectOrView, randomLastAndStatus());
SnapshotDto otherAnalysis = dbTester.components().insertSnapshot(projectOrView);
- int count = 1 + new Random().nextInt(20);
+ int count = 5;
IntStream.range(0, count).forEach(i -> {
dbTester.events().insertEvent(analysis);
dbTester.events().insertEvent(otherAnalysis);
dbTester.components().insertComponent(projectOrView);
SnapshotDto analysis = dbTester.components().insertSnapshot(projectOrView, randomLastAndStatus());
SnapshotDto otherAnalysis = dbTester.components().insertSnapshot(projectOrView);
- int count = 1 + new Random().nextInt(20);
+ int count = 5;
Stream.of(metric1, metric2)
.forEach(metric -> {
IntStream.range(0, count).forEach(i -> {
dbTester.components().insertComponent(projectOrView);
SnapshotDto analysis = dbTester.components().insertSnapshot(projectOrView, randomLastAndStatus());
SnapshotDto otherAnalysis = dbTester.components().insertSnapshot(projectOrView);
- int count = 1 + new Random().nextInt(20);
+ int count = 4;
IntStream.range(0, count).forEach(i -> {
insertRandomAnalysisProperty(analysis);
insertRandomAnalysisProperty(otherAnalysis);
ComponentDto file = dbTester.components().insertComponent(newFileDto(projectOrView));
ComponentDto otherProject = dbTester.components().insertPrivateProject();
ComponentDto otherFile = dbTester.components().insertComponent(newFileDto(otherProject));
- int count = 5 + random.nextInt(10);
+ int count = 5;
IntStream.range(0, count).forEach(i -> {
Stream.of(rule1, rule2).forEach(rule -> {
dbTester.issues().insertIssue(t -> t.setRule(rule).setProject(projectOrView).setComponent(projectOrView));
RuleDefinitionDto rule = dbTester.rules().insert();
dbTester.components().insertComponent(projectOrView);
ComponentDto file = dbTester.components().insertComponent(newFileDto(projectOrView));
- int count = 5 + random.nextInt(10);
+ int count = 5;
IntStream.range(0, count).forEach(i -> {
IssueDto issue = dbTester.issues().insertIssue(t -> t.setRule(rule).setProject(projectOrView).setComponent(projectOrView));
dbTester.issues().insertChange(issue);
BranchDto branch = newBranchDto(project);
dbTester.components().insertProjectBranch(project, branch);
- //global settings
+ // global settings
dbTester.newCodePeriods().insert(NewCodePeriodType.PREVIOUS_VERSION, null);
- //project settings
+ // project settings
dbTester.newCodePeriods().insert(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "20");
- //branch settings
+ // branch settings
dbTester.newCodePeriods().insert(project.uuid(), branch.getUuid(), NewCodePeriodType.NUMBER_OF_DAYS, "1");
PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2);
purgeCommands.deleteNewCodePeriods(branch.getUuid());
- //should delete branch settings only
+ // should delete branch settings only
assertThat(dbTester.countRowsOfTable("new_code_periods")).isEqualTo(2);
}
BranchDto branch = newBranchDto(project);
dbTester.components().insertProjectBranch(project, branch);
- //global settings
+ // global settings
dbTester.newCodePeriods().insert(NewCodePeriodType.PREVIOUS_VERSION, null);
- //project settings
+ // project settings
dbTester.newCodePeriods().insert(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "20");
- //branch settings
+ // branch settings
dbTester.newCodePeriods().insert(project.uuid(), branch.getUuid(), NewCodePeriodType.NUMBER_OF_DAYS, "1");
PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2);
purgeCommands.deleteNewCodePeriods(project.uuid());
- //should delete branch and project settings only
+ // should delete branch and project settings only
assertThat(dbTester.countRowsOfTable("new_code_periods")).isEqualTo(1);
}
BranchDto branch = newBranchDto(project);
dbTester.components().insertProjectBranch(project, branch);
- //global settings
+ // global settings
dbTester.newCodePeriods().insert(NewCodePeriodType.PREVIOUS_VERSION, null);
- //project settings
+ // project settings
dbTester.newCodePeriods().insert(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "20");
- //branch settings
+ // branch settings
dbTester.newCodePeriods().insert(project.uuid(), branch.getUuid(), NewCodePeriodType.NUMBER_OF_DAYS, "1");
PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2);
purgeCommands.deleteNewCodePeriods(null);
- //should delete branch and project settings only
+ // should delete branch and project settings only
assertThat(dbTester.countRowsOfTable("new_code_periods")).isEqualTo(3);
}
*/
package org.sonar.db.purge;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.io.ByteArrayInputStream;
import java.time.LocalDateTime;
ComponentDto otherProject = db.components().insertPrivateProject();
SnapshotDto otherAnalysis1 = db.components().insertSnapshot(otherProject);
- underTest.deleteAnalyses(dbSession, new PurgeProfiler(), ImmutableList.of(analysis1.getUuid()));
+ underTest.deleteAnalyses(dbSession, new PurgeProfiler(), singletonList(analysis1.getUuid()));
assertThat(uuidsIn("snapshots")).containsOnly(analysis2.getUuid(), analysis3.getUuid(), otherAnalysis1.getUuid());
- underTest.deleteAnalyses(dbSession, new PurgeProfiler(), ImmutableList.of(analysis1.getUuid(), analysis3.getUuid(), otherAnalysis1.getUuid()));
+ underTest.deleteAnalyses(dbSession, new PurgeProfiler(), asList(analysis1.getUuid(), analysis3.getUuid(), otherAnalysis1.getUuid()));
assertThat(uuidsIn("snapshots")).containsOnly(analysis2.getUuid());
}
assertThat(uuidsIn("events"))
.containsOnly(projectEvent1.getUuid(), projectEvent2.getUuid(), projectEvent3.getUuid());
- underTest.deleteAnalyses(dbSession, new PurgeProfiler(), singletonList(projectAnalysis1.getUuid()));
+ underTest.deleteAnalyses(dbSession, new PurgeProfiler(), singletonList(projectAnalysis1.getUuid()));
assertThat(uuidsIn("event_component_changes", "event_analysis_uuid"))
.containsOnly(projectAnalysis2.getUuid());
assertThat(db.countRowsOfTable("event_component_changes"))
assertThat(uuidsIn("events"))
.containsOnly(projectEvent2.getUuid(), projectEvent3.getUuid());
- underTest.deleteAnalyses(dbSession, new PurgeProfiler(), singletonList(projectAnalysis3.getUuid()));
+ underTest.deleteAnalyses(dbSession, new PurgeProfiler(), singletonList(projectAnalysis3.getUuid()));
assertThat(uuidsIn("event_component_changes", "event_analysis_uuid"))
.containsOnly(projectAnalysis2.getUuid());
assertThat(db.countRowsOfTable("event_component_changes"))
assertThat(uuidsIn("events"))
.containsOnly(projectEvent2.getUuid());
- underTest.deleteAnalyses(dbSession, new PurgeProfiler(), singletonList(projectAnalysis2.getUuid()));
+ underTest.deleteAnalyses(dbSession, new PurgeProfiler(), singletonList(projectAnalysis2.getUuid()));
assertThat(db.countRowsOfTable("event_component_changes"))
.isZero();
assertThat(db.countRowsOfTable("events"))
.stream()
.map(t -> (String) t.get("UUID"));
}
+
}
PurgeDao dao = mock(PurgeDao.class);
DbSession session = mock(DbSession.class);
when(dao.selectPurgeableAnalyses("uuid_123", session)).thenReturn(Arrays.asList(
- new PurgeableAnalysisDto().setAnalysisId(999).setAnalysisUuid("u999").setDate(System2.INSTANCE.now()),
- new PurgeableAnalysisDto().setAnalysisId(456).setAnalysisUuid("u456").setDate(System2.INSTANCE.now())
+ new PurgeableAnalysisDto().setAnalysisUuid("u999").setDate(System2.INSTANCE.now()),
+ new PurgeableAnalysisDto().setAnalysisUuid("u456").setDate(System2.INSTANCE.now())
));
Filter filter1 = newFirstSnapshotInListFilter();
Filter filter2 = newFirstSnapshotInListFilter();
inOrder.verify(filter1).log();
inOrder.verify(dao, times(1)).deleteAnalyses(eq(session), eq(profiler), eq(ImmutableList.of("u999")));
inOrder.verify(filter2).log();
- inOrder.verify(dao, times(1)).deleteAnalyses(eq(session), eq(profiler), eq(ImmutableList.of( "u456")));
+ inOrder.verify(dao, times(1)).deleteAnalyses(eq(session), eq(profiler), eq(ImmutableList.of("u456")));
inOrder.verifyNoMoreInteractions();
}
import org.sonar.server.platform.db.migration.version.v83.notifications.DropPrimaryKeyOnIdColumnOfNotificationTable;
import org.sonar.server.platform.db.migration.version.v83.notifications.MakeNotificationUuidAndCreatedAtColumnsNotNullable;
import org.sonar.server.platform.db.migration.version.v83.notifications.PopulateNotificationUuidAndCreatedAt;
+import org.sonar.server.platform.db.migration.version.v83.snapshots.issues.AddPrimaryKeyOnUuidColumnOfSnapshotsTable;
+import org.sonar.server.platform.db.migration.version.v83.snapshots.issues.DropIdColumnOfSnapshotsTable;
+import org.sonar.server.platform.db.migration.version.v83.snapshots.issues.DropPrimaryKeyOnIdColumnOfSnapshotsTable;
public class DbVersion83 implements DbVersion {
@Override
.add(3410, "Add primary key on 'KEE' column of 'ISSUES' table", AddPrimaryKeyOnKeeColumnOfIssuesTable.class)
.add(3411, "Drop column 'ID' of 'ISSUES' table", DropIdColumnOfIssuesTable.class)
+ // Migration on SNAPSHOTS table
+ .add(3412, "Drop primary key on 'ID' column of 'SNAPSHOTS' table", DropPrimaryKeyOnIdColumnOfSnapshotsTable.class)
+ .add(3413, "Add primary key on 'UUID' column of 'SNAPSHOTS' table", AddPrimaryKeyOnUuidColumnOfSnapshotsTable.class)
+ .add(3414, "Drop column 'ID' of 'SNAPSHOTS' table", DropIdColumnOfSnapshotsTable.class)
+
;
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v83.snapshots.issues;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+import org.sonar.server.platform.db.migration.version.v83.util.AddPrimaryKeyBuilder;
+
+public class AddPrimaryKeyOnUuidColumnOfSnapshotsTable extends DdlChange {
+
+ public AddPrimaryKeyOnUuidColumnOfSnapshotsTable(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new AddPrimaryKeyBuilder("snapshots", "uuid").build());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v83.snapshots.issues;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class DropIdColumnOfSnapshotsTable extends DdlChange {
+
+ private Database db;
+
+ public DropIdColumnOfSnapshotsTable(Database db) {
+ super(db);
+ this.db = db;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new DropColumnsBuilder(db.getDialect(), "snapshots", "id").build());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v83.snapshots.issues;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator;
+
+public class DropPrimaryKeyOnIdColumnOfSnapshotsTable extends DdlChange {
+
+ private final DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator;
+
+ public DropPrimaryKeyOnIdColumnOfSnapshotsTable(Database db, DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator) {
+ super(db);
+ this.dropPrimaryKeySqlGenerator = dropPrimaryKeySqlGenerator;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(dropPrimaryKeySqlGenerator.generate("snapshots", "snapshots","id"));
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v83.snapshots;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.version.v83.snapshots.issues.AddPrimaryKeyOnUuidColumnOfSnapshotsTable;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class AddPrimaryKeyOnUuidColumnOfSnapshotsTableTest {
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(AddPrimaryKeyOnUuidColumnOfSnapshotsTableTest.class, "schema.sql");
+
+ private AddPrimaryKeyOnUuidColumnOfSnapshotsTable underTest = new AddPrimaryKeyOnUuidColumnOfSnapshotsTable(db.database());
+
+ @Test
+ public void execute() throws SQLException {
+ underTest.execute();
+
+ db.assertPrimaryKey("snapshots", "pk_snapshots", "uuid");
+ }
+
+ @Test
+ public void migration_is_not_re_entrant() throws SQLException {
+ underTest.execute();
+
+ assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v83.snapshots;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.version.v83.snapshots.issues.DropIdColumnOfSnapshotsTable;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class DropIdColumnOfSnapshotsTableTest {
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(DropIdColumnOfSnapshotsTableTest.class, "schema.sql");
+
+ private DropIdColumnOfSnapshotsTable underTest = new DropIdColumnOfSnapshotsTable(db.database());
+
+ @Test
+ public void execute() throws SQLException {
+ underTest.execute();
+
+ db.assertColumnDoesNotExist("snapshots", "id");
+ }
+
+ @Test
+ public void migration_is_not_re_entrant() throws SQLException {
+ underTest.execute();
+
+ assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.platform.db.migration.version.v83.snapshots;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.version.v83.snapshots.issues.DropPrimaryKeyOnIdColumnOfSnapshotsTable;
+import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator;
+import org.sonar.server.platform.db.migration.version.v83.util.GetConstraintHelper;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class DropPrimaryKeyOnIdColumnOfSnapshotsTableTest {
+
+ private static final String TABLE_NAME = "snapshots";
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(DropPrimaryKeyOnIdColumnOfSnapshotsTableTest.class, "schema.sql");
+
+ private DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator = new DropPrimaryKeySqlGenerator(db.database(), new GetConstraintHelper(db.database()));
+
+ private DropPrimaryKeyOnIdColumnOfSnapshotsTable underTest = new DropPrimaryKeyOnIdColumnOfSnapshotsTable(db.database(), dropPrimaryKeySqlGenerator);
+
+ @Test
+ public void execute() throws SQLException {
+ underTest.execute();
+
+ db.assertNoPrimaryKey(TABLE_NAME);
+ }
+
+ @Test
+ public void migration_is_not_re_entrant() throws SQLException {
+ underTest.execute();
+
+ assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
+ }
+}
--- /dev/null
+CREATE TABLE "SNAPSHOTS"(
+ "ID" INTEGER NOT NULL,
+ "UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "STATUS" VARCHAR(4) DEFAULT 'U' NOT NULL,
+ "ISLAST" BOOLEAN DEFAULT FALSE NOT NULL,
+ "VERSION" VARCHAR(500),
+ "PURGE_STATUS" INTEGER,
+ "BUILD_STRING" VARCHAR(100),
+ "REVISION" VARCHAR(100),
+ "BUILD_DATE" BIGINT,
+ "PERIOD1_MODE" VARCHAR(100),
+ "PERIOD1_PARAM" VARCHAR(100),
+ "PERIOD2_MODE" VARCHAR(100),
+ "PERIOD2_PARAM" VARCHAR(100),
+ "PERIOD3_MODE" VARCHAR(100),
+ "PERIOD3_PARAM" VARCHAR(100),
+ "PERIOD4_MODE" VARCHAR(100),
+ "PERIOD4_PARAM" VARCHAR(100),
+ "PERIOD5_MODE" VARCHAR(100),
+ "PERIOD5_PARAM" VARCHAR(100),
+ "PERIOD1_DATE" BIGINT,
+ "PERIOD2_DATE" BIGINT,
+ "PERIOD3_DATE" BIGINT,
+ "PERIOD4_DATE" BIGINT,
+ "PERIOD5_DATE" BIGINT,
+ "CREATED_AT" BIGINT
+);
+CREATE UNIQUE INDEX "ANALYSES_UUID" ON "SNAPSHOTS"("UUID");
+CREATE INDEX "SNAPSHOT_COMPONENT" ON "SNAPSHOTS"("COMPONENT_UUID");
--- /dev/null
+CREATE TABLE "SNAPSHOTS"(
+ "ID" INTEGER NOT NULL,
+ "UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "STATUS" VARCHAR(4) DEFAULT 'U' NOT NULL,
+ "ISLAST" BOOLEAN DEFAULT FALSE NOT NULL,
+ "VERSION" VARCHAR(500),
+ "PURGE_STATUS" INTEGER,
+ "BUILD_STRING" VARCHAR(100),
+ "REVISION" VARCHAR(100),
+ "BUILD_DATE" BIGINT,
+ "PERIOD1_MODE" VARCHAR(100),
+ "PERIOD1_PARAM" VARCHAR(100),
+ "PERIOD2_MODE" VARCHAR(100),
+ "PERIOD2_PARAM" VARCHAR(100),
+ "PERIOD3_MODE" VARCHAR(100),
+ "PERIOD3_PARAM" VARCHAR(100),
+ "PERIOD4_MODE" VARCHAR(100),
+ "PERIOD4_PARAM" VARCHAR(100),
+ "PERIOD5_MODE" VARCHAR(100),
+ "PERIOD5_PARAM" VARCHAR(100),
+ "PERIOD1_DATE" BIGINT,
+ "PERIOD2_DATE" BIGINT,
+ "PERIOD3_DATE" BIGINT,
+ "PERIOD4_DATE" BIGINT,
+ "PERIOD5_DATE" BIGINT,
+ "CREATED_AT" BIGINT
+);
+ALTER TABLE "SNAPSHOTS" ADD CONSTRAINT "PK_SNAPSHOTS" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "ANALYSES_UUID" ON "SNAPSHOTS"("UUID");
+CREATE INDEX "SNAPSHOT_COMPONENT" ON "SNAPSHOTS"("COMPONENT_UUID");
--- /dev/null
+CREATE TABLE "SNAPSHOTS"(
+ "ID" INTEGER NOT NULL AUTO_INCREMENT (1,1),
+ "UUID" VARCHAR(50) NOT NULL,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "STATUS" VARCHAR(4) DEFAULT 'U' NOT NULL,
+ "ISLAST" BOOLEAN DEFAULT FALSE NOT NULL,
+ "VERSION" VARCHAR(500),
+ "PURGE_STATUS" INTEGER,
+ "BUILD_STRING" VARCHAR(100),
+ "REVISION" VARCHAR(100),
+ "BUILD_DATE" BIGINT,
+ "PERIOD1_MODE" VARCHAR(100),
+ "PERIOD1_PARAM" VARCHAR(100),
+ "PERIOD2_MODE" VARCHAR(100),
+ "PERIOD2_PARAM" VARCHAR(100),
+ "PERIOD3_MODE" VARCHAR(100),
+ "PERIOD3_PARAM" VARCHAR(100),
+ "PERIOD4_MODE" VARCHAR(100),
+ "PERIOD4_PARAM" VARCHAR(100),
+ "PERIOD5_MODE" VARCHAR(100),
+ "PERIOD5_PARAM" VARCHAR(100),
+ "PERIOD1_DATE" BIGINT,
+ "PERIOD2_DATE" BIGINT,
+ "PERIOD3_DATE" BIGINT,
+ "PERIOD4_DATE" BIGINT,
+ "PERIOD5_DATE" BIGINT,
+ "CREATED_AT" BIGINT
+);
+ALTER TABLE "SNAPSHOTS" ADD CONSTRAINT "PK_SNAPSHOTS" PRIMARY KEY("ID");
+CREATE UNIQUE INDEX "ANALYSES_UUID" ON "SNAPSHOTS"("UUID");
+CREATE INDEX "SNAPSHOT_COMPONENT" ON "SNAPSHOTS"("COMPONENT_UUID");