aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTravis Collins <travistx@gmail.com>2025-03-13 14:49:26 -0600
committerMatteo Mara <matteo.mara@sonarsource.com>2025-03-17 22:23:20 +0100
commit9042dc991247cb82fe011994c8e0414658164e83 (patch)
treef9b244e8752e27912433d01f5ba7fa92c5605dcc
parent0cb598a8d618308002ee5c9a15f43b9d13ab2dc3 (diff)
downloadsonarqube-9042dc991247cb82fe011994c8e0414658164e83.tar.gz
sonarqube-9042dc991247cb82fe011994c8e0414658164e83.zip
SCA-125 Perf: releases endpoint (#13178)
-rw-r--r--server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaDependenciesDaoIT.java26
-rw-r--r--server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaReleasesDaoIT.java31
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaDependenciesMapper.xml6
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesDetailsMapper.xml5
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesMapper.xml3
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaReleasesMapper.xml6
-rw-r--r--server/sonar-db-dao/src/schema/schema-sq.ddl2
-rw-r--r--server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaReleasesDbTester.java14
-rw-r--r--server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuidTest.java53
-rw-r--r--server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponentTest.java58
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuid.java58
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503.java42
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponent.java33
14 files changed, 283 insertions, 56 deletions
diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaDependenciesDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaDependenciesDaoIT.java
index 67546dd215f..f122c8eefb8 100644
--- a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaDependenciesDaoIT.java
+++ b/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaDependenciesDaoIT.java
@@ -41,7 +41,7 @@ class ScaDependenciesDaoIT {
@Test
void insert_shouldPersistScaDependencies() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaDependencyDto scaDependencyDto = db.getScaDependenciesDbTester().insertScaDependency(componentDto.uuid(), "scaReleaseUuid", "1", true);
List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_dependencies");
@@ -63,7 +63,7 @@ class ScaDependenciesDaoIT {
@Test
void deleteByUuid_shouldDeleteScaDependencies() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaDependencyDto scaDependencyDto = db.getScaDependenciesDbTester().insertScaDependency(componentDto.uuid(), "scaReleaseUuid", "1", true);
List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_dependencies");
@@ -77,7 +77,7 @@ class ScaDependenciesDaoIT {
@Test
void selectByUuid_shouldLoadScaDependency() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaDependencyDto scaDependencyDto = db.getScaDependenciesDbTester().insertScaDependency(componentDto.uuid(), "scaReleaseUuid", "1", true);
var loadedOptional = scaDependenciesDao.selectByUuid(db.getSession(), scaDependencyDto.uuid());
@@ -87,7 +87,7 @@ class ScaDependenciesDaoIT {
@Test
void selectByReleaseUuids_shouldReturnScaDependencies() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaDependencyDto scaDependencyDto1a = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1a", true, PackageManager.MAVEN, "foo.bar1");
// same release, different dependency
ScaDependencyDto scaDependencyDto1b = db.getScaDependenciesDbTester().insertScaDependency(componentDto.uuid(), scaDependencyDto1a.scaReleaseUuid(), "1b", false);
@@ -103,7 +103,7 @@ class ScaDependenciesDaoIT {
@Test
void selectByQuery_shouldReturnScaDependencies_whenQueryByBranchUuid() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaDependencyDto scaDependencyDto1 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1", true, PackageManager.MAVEN, "foo.bar");
// same release, different dependency
ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependency(componentDto.uuid(), scaDependencyDto1.scaReleaseUuid(), "2", false);
@@ -116,7 +116,7 @@ class ScaDependenciesDaoIT {
@Test
void selectByQuery_shouldReturnPaginatedScaDependencies() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaDependencyDto scaDependencyDto1 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1", true, PackageManager.MAVEN, "foo.bar");
ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "2", true, PackageManager.MAVEN, "foo.bar");
ScaDependencyDto scaDependencyDto3 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "3", true, PackageManager.MAVEN, "something");
@@ -135,7 +135,7 @@ class ScaDependenciesDaoIT {
@Test
void selectByQuery_shouldPartiallyMatchPackageName_whenQueriedByText() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaDependencyDto scaDependencyDto1 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1", true, PackageManager.MAVEN, "foo.bar");
@SuppressWarnings("unused")
ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "2", true, PackageManager.MAVEN, "bar.mee");
@@ -160,7 +160,7 @@ class ScaDependenciesDaoIT {
@Test
void selectByQuery_shouldReturnScaDependencies_whenQueryByDirect() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaDependencyDto scaDependencyDto1 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1", true, PackageManager.MAVEN, "foo.bar");
ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "2", false, PackageManager.MAVEN, "foo.bar");
@@ -179,7 +179,7 @@ class ScaDependenciesDaoIT {
@Test
void selectByQuery_shouldReturnScaDependencies_whenQueryByPackageManager() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaDependencyDto scaDependencyDto1 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1", true, PackageManager.MAVEN, "foo.bar");
ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "2", true, PackageManager.NPM, "foo.bar");
ScaDependencyDto scaDependencyDto3 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "3", true, PackageManager.CARGO, "foo.bar");
@@ -201,7 +201,7 @@ class ScaDependenciesDaoIT {
@Test
void update_shouldUpdateScaDependency() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaDependencyDto scaDependencyDto = db.getScaDependenciesDbTester().insertScaDependency(componentDto.uuid(), "scaReleaseUuid", "1", true);
ScaDependencyDto updatedScaDependency = scaDependencyDto.toBuilder().setUpdatedAt(scaDependencyDto.updatedAt() + 1).setDirect(false).setLockfileDependencyFilePath("lockfile2")
.build();
@@ -227,7 +227,7 @@ class ScaDependenciesDaoIT {
@Test
void countByQuery_shouldReturnTheTotalOfDependencies() {
- ComponentDto componentDto1 = prepareComponentDto("1");
+ ComponentDto componentDto1 = prepareComponentDto();
db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto1.uuid(), "1", true, PackageManager.MAVEN, "foo.bar");
db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto1.uuid(), "2", true, PackageManager.MAVEN, "foo.bar.mee");
db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto1.uuid(), "3", true, PackageManager.MAVEN, "bar.foo");
@@ -239,8 +239,8 @@ class ScaDependenciesDaoIT {
assertThat(scaDependenciesDao.countByQuery(db.getSession(), new ScaDependenciesQuery("another_branch_uuid", null, null, null))).isZero();
}
- private ComponentDto prepareComponentDto(String suffix) {
+ private ComponentDto prepareComponentDto() {
ProjectData projectData = db.components().insertPublicProject();
- return db.getScaDependenciesDbTester().insertComponent(projectData.mainBranchUuid(), suffix);
+ return projectData.getMainBranchComponent();
}
}
diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaReleasesDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaReleasesDaoIT.java
index 42ffcfd2c7a..e29c0f54521 100644
--- a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaReleasesDaoIT.java
+++ b/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaReleasesDaoIT.java
@@ -45,7 +45,7 @@ class ScaReleasesDaoIT {
@Test
void insert_shouldPersistScaReleases() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaReleaseDto scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1");
List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_releases");
@@ -68,7 +68,7 @@ class ScaReleasesDaoIT {
@Test
void deleteByUuid_shouldDeleteScaReleases() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaReleaseDto scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1");
List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_releases");
@@ -82,7 +82,7 @@ class ScaReleasesDaoIT {
@Test
void selectByUuid_shouldLoadScaRelease() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaReleaseDto scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1");
var loadedOptional = scaReleasesDao.selectByUuid(db.getSession(), scaReleaseDto.uuid());
@@ -92,7 +92,7 @@ class ScaReleasesDaoIT {
@Test
void selectByUuid_shouldLoadScaReleases() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaReleaseDto scaReleaseDto1 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1");
db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "2");
ScaReleaseDto scaReleaseDto3 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "3");
@@ -105,7 +105,7 @@ class ScaReleasesDaoIT {
@Test
void selectByUuid_shouldLoadEmptyScaReleases() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1");
db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "2");
db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "3");
@@ -117,8 +117,9 @@ class ScaReleasesDaoIT {
@Test
void selectByQuery_shouldReturnScaReleases_whenQueryByBranchUuid() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaReleaseDto scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1");
+ System.out.println("componentDto = " + componentDto);
ScaReleasesQuery scaReleasesQuery = new ScaReleasesQuery(componentDto.branchUuid(), null, null, null, null);
List<ScaReleaseDto> results = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesQuery, Pagination.all());
@@ -129,7 +130,7 @@ class ScaReleasesDaoIT {
@Test
void selectByQuery_shouldReturnPaginatedScaReleases() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaReleaseDto scaReleaseDto1 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1");
ScaReleaseDto scaReleaseDto2 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "2");
ScaReleaseDto scaReleaseDto3 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "3");
@@ -148,7 +149,7 @@ class ScaReleasesDaoIT {
@Test
void selectByQuery_shouldPartiallyMatchPackageName_whenQueriedByText() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaReleaseDto scaReleaseDto1 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1", PackageManager.MAVEN, "foo.bar");
db.getScaDependenciesDbTester().insertScaDependency(componentDto.uuid(), scaReleaseDto1, "1", true);
db.getScaDependenciesDbTester().insertScaDependency(componentDto.uuid(), scaReleaseDto1, "2", false);
@@ -187,7 +188,7 @@ class ScaReleasesDaoIT {
@Test
void selectByQuery_shouldReturnScaReleases_whenQueryByDirect() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaReleaseDto scaReleaseDto1 = db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto.uuid(), "1", 2, true, PackageManager.MAVEN, "foo.bar");
ScaReleaseDto scaReleaseDto2 = db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto.uuid(), "2", 3, false, PackageManager.MAVEN, "foo.bar");
@@ -206,7 +207,7 @@ class ScaReleasesDaoIT {
@Test
void selectByQuery_shouldReturnScaReleases_whenQueryByPackageManager() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaReleaseDto scaReleaseDto1 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1", PackageManager.MAVEN, "foo.bar");
ScaReleaseDto scaReleaseDto2 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "2", PackageManager.NPM, "foo.bar");
ScaReleaseDto scaReleaseDto3 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "3", PackageManager.CARGO, "foo.bar");
@@ -228,7 +229,7 @@ class ScaReleasesDaoIT {
@Test
void update_shouldUpdateScaRelease() {
- ComponentDto componentDto = prepareComponentDto("1");
+ ComponentDto componentDto = prepareComponentDto();
ScaReleaseDto scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1", PackageManager.MAVEN, "foo.bar");
ScaReleaseDto updatedScaRelease = scaReleaseDto.toBuilder().setUpdatedAt(scaReleaseDto.updatedAt() + 1).setVersion("newVersion").build();
@@ -254,7 +255,7 @@ class ScaReleasesDaoIT {
@Test
void countByQuery_shouldReturnTheTotalOfReleases() {
- ComponentDto componentDto1 = prepareComponentDto("1");
+ ComponentDto componentDto1 = prepareComponentDto();
db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "1", 1, true, PackageManager.MAVEN, "foo.bar");
db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "2", 2, true, PackageManager.MAVEN, "foo.bar.mee");
db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "3", 3, true, PackageManager.MAVEN, "bar.fo");
@@ -266,14 +267,14 @@ class ScaReleasesDaoIT {
assertThat(scaReleasesDao.countByQuery(db.getSession(), new ScaReleasesQuery("another_branch_uuid", null, null, null, null))).isZero();
}
- private ComponentDto prepareComponentDto(String suffix) {
+ private ComponentDto prepareComponentDto() {
ProjectData projectData = db.components().insertPublicProject();
- return db.getScaReleasesDbTester().insertComponent(projectData.mainBranchUuid(), suffix);
+ return projectData.getMainBranchComponent();
}
@Test
void countByPlatformQuery_shouldReturnPlatforms() {
- ComponentDto componentDto1 = prepareComponentDto("1");
+ ComponentDto componentDto1 = prepareComponentDto();
db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "1", 1, true, PackageManager.MAVEN, "foo.bar");
db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "2", 2, true, PackageManager.NPM, "foo.bar.mee");
db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "3", 3, true, PackageManager.MAVEN, "bar.foo");
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaDependenciesMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaDependenciesMapper.xml
index 5df91bc63d7..86ffed52578 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaDependenciesMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaDependenciesMapper.xml
@@ -88,8 +88,7 @@
select <include refid="scaDependenciesColumns"/>
from sca_dependencies sd
inner join sca_releases sr on sd.sca_release_uuid = sr.uuid
- inner join components c on sr.component_uuid = c.uuid
- where c.branch_uuid = #{branchUuid,jdbcType=VARCHAR}
+ where sr.component_uuid = #{branchUuid,jdbcType=VARCHAR}
</select>
<select id="selectByQuery" parameterType="map" resultMap="scaDependencyResultMap">
@@ -107,8 +106,7 @@
<sql id="sqlSelectByQuery">
from sca_dependencies sd
inner join sca_releases sr on sd.sca_release_uuid = sr.uuid
- inner join components c on sr.component_uuid = c.uuid
- where c.branch_uuid = #{query.branchUuid,jdbcType=VARCHAR}
+ where sr.component_uuid = #{query.branchUuid,jdbcType=VARCHAR}
<if test="query.direct != null">
AND sd.direct = #{query.direct,jdbcType=BOOLEAN}
</if>
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesDetailsMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesDetailsMapper.xml
index b884961612b..50fc85e9db4 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesDetailsMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesDetailsMapper.xml
@@ -48,7 +48,6 @@
from sca_issues_releases sir
inner join sca_issues si on sir.sca_issue_uuid = si.uuid
inner join sca_releases sr on sir.sca_release_uuid = sr.uuid
- inner join components c on sr.component_uuid = c.uuid
left join sca_vulnerability_issues svi on sir.sca_issue_uuid = svi.uuid
</sql>
@@ -64,7 +63,7 @@
<sql id="sqlSelectByBranchUuid">
<include refid="sqlBaseJoins"/>
- where c.branch_uuid = #{branchUuid,jdbcType=VARCHAR}
+ where sr.component_uuid = #{branchUuid,jdbcType=VARCHAR}
</sql>
<select id="selectByReleaseUuid" parameterType="map" resultMap="scaIssueReleaseDetailsResultMap">
@@ -92,7 +91,7 @@
<sql id="sqlSelectByQueryWhereClause">
<where>
- c.branch_uuid = #{query.branchUuid,jdbcType=VARCHAR}
+ sr.component_uuid = #{query.branchUuid,jdbcType=VARCHAR}
<if test="query.vulnerabilityIdSubstring != null">
<!-- this screens out non-vulnerability-having issue types even if the search is for empty string -->
AND si.vulnerability_id != '${@org.sonar.db.sca.ScaIssueDto@NULL_VALUE}'
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesMapper.xml
index 38c7fb400e2..0ba02352a77 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesMapper.xml
@@ -52,8 +52,7 @@
select <include refid="scaIssuesReleasesColumns"/>
from sca_issues_releases sir
inner join sca_releases sr on sir.sca_release_uuid = sr.uuid
- inner join components c on sr.component_uuid = c.uuid
- where c.branch_uuid = #{branchUuid,jdbcType=VARCHAR}
+ where sr.component_uuid = #{branchUuid,jdbcType=VARCHAR}
order by sir.uuid asc
</select>
</mapper>
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaReleasesMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaReleasesMapper.xml
index 192df570755..b4d9ae9c4f3 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaReleasesMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaReleasesMapper.xml
@@ -75,8 +75,7 @@
<select id="selectByBranchUuid" parameterType="string" resultType="org.sonar.db.sca.ScaReleaseDto">
select <include refid="scaReleasesColumns"/>
from sca_releases sr
- inner join components c on sr.component_uuid = c.uuid
- where c.branch_uuid = #{branchUuid,jdbcType=VARCHAR}
+ where sr.component_uuid = #{branchUuid,jdbcType=VARCHAR}
order by <include refid="scaReleasesOrderBy"/>
</select>
@@ -102,8 +101,7 @@
<sql id="sqlSelectByQuery">
from sca_releases sr
- inner join components c on sr.component_uuid = c.uuid
- where c.branch_uuid = #{query.branchUuid,jdbcType=VARCHAR}
+ where sr.component_uuid = #{query.branchUuid,jdbcType=VARCHAR}
<if test="query.direct != null">
<!-- we only want each sca_releases row once, so this isn't a join. -->
AND exists (select 1 from sca_dependencies sd where sd.sca_release_uuid = sr.uuid and sd.direct = #{query.direct,jdbcType=BOOLEAN})
diff --git a/server/sonar-db-dao/src/schema/schema-sq.ddl b/server/sonar-db-dao/src/schema/schema-sq.ddl
index c4be3c824db..8a5b9a31de0 100644
--- a/server/sonar-db-dao/src/schema/schema-sq.ddl
+++ b/server/sonar-db-dao/src/schema/schema-sq.ddl
@@ -1087,7 +1087,7 @@ CREATE TABLE "SCA_RELEASES"(
"NEW_IN_PULL_REQUEST" BOOLEAN DEFAULT FALSE NOT NULL
);
ALTER TABLE "SCA_RELEASES" ADD CONSTRAINT "PK_SCA_RELEASES" PRIMARY KEY("UUID");
-CREATE INDEX "SCA_RELEASES_COMP_UUID" ON "SCA_RELEASES"("COMPONENT_UUID" NULLS FIRST);
+CREATE INDEX "SCA_RELEASES_COMP_UUID_UUID" ON "SCA_RELEASES"("COMPONENT_UUID" NULLS FIRST, "UUID" NULLS FIRST);
CREATE TABLE "SCA_VULNERABILITY_ISSUES"(
"UUID" CHARACTER VARYING(40) NOT NULL,
diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaReleasesDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaReleasesDbTester.java
index fa6137fa702..9f96277c5c6 100644
--- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaReleasesDbTester.java
+++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaReleasesDbTester.java
@@ -21,7 +21,6 @@ package org.sonar.db.sca;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
public class ScaReleasesDbTester {
private final DbTester db;
@@ -46,19 +45,6 @@ public class ScaReleasesDbTester {
2L);
}
- public ComponentDto newComponentDto(String branchUuid, String suffix) {
- return new ComponentDto().setUuid("uuid" + suffix)
- .setKey("key" + suffix)
- .setUuidPath("uuidPath" + suffix)
- .setBranchUuid(branchUuid);
- }
-
- public ComponentDto insertComponent(String branchUuid, String suffix) {
- ComponentDto componentDto = newComponentDto(branchUuid, suffix);
- db.components().insertComponent(componentDto);
- return componentDto;
- }
-
public ScaReleaseDto insertScaRelease(String componentUuid, String suffix) {
return insertScaRelease(componentUuid, suffix, PackageManager.MAVEN, "packageName" + suffix);
}
diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuidTest.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuidTest.java
new file mode 100644
index 00000000000..d7630686669
--- /dev/null
+++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuidTest.java
@@ -0,0 +1,53 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2025 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.v202503;
+
+import java.sql.SQLException;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.sonar.db.MigrationDbTester;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.db.MigrationDbTester.createForMigrationStep;
+import static org.sonar.server.platform.db.migration.version.v202503.CreateIndexOnScaReleasesComponentUuid.COLUMN_NAME_COMPONENT_UUID;
+import static org.sonar.server.platform.db.migration.version.v202503.CreateIndexOnScaReleasesComponentUuid.COLUMN_NAME_UUID;
+import static org.sonar.server.platform.db.migration.version.v202503.CreateIndexOnScaReleasesComponentUuid.INDEX_NAME;
+import static org.sonar.server.platform.db.migration.version.v202503.CreateIndexOnScaReleasesComponentUuid.TABLE_NAME;
+
+class CreateIndexOnScaReleasesComponentUuidTest {
+ @RegisterExtension
+ public final MigrationDbTester db = createForMigrationStep(CreateIndexOnScaReleasesComponentUuid.class);
+ private final DdlChange underTest = new CreateIndexOnScaReleasesComponentUuid(db.database());
+
+ @Test
+ void execute_shouldCreateIndex() throws SQLException {
+ db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME);
+ underTest.execute();
+ db.assertIndex(TABLE_NAME, INDEX_NAME, COLUMN_NAME_COMPONENT_UUID, COLUMN_NAME_UUID);
+ }
+
+ @Test
+ void execute_shouldBeReentrant() throws SQLException {
+ db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME);
+ underTest.execute();
+ underTest.execute();
+ db.assertIndex(TABLE_NAME, INDEX_NAME, COLUMN_NAME_COMPONENT_UUID, COLUMN_NAME_UUID);
+ }
+}
diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponentTest.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponentTest.java
new file mode 100644
index 00000000000..97f8a4d557d
--- /dev/null
+++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponentTest.java
@@ -0,0 +1,58 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2025 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.v202503;
+
+import java.sql.SQLException;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.sonar.db.MigrationDbTester;
+
+import static org.sonar.db.MigrationDbTester.createForMigrationStep;
+
+class DropIndexOnScaReleasesComponentTest {
+
+ private static final String TABLE_NAME = "sca_releases";
+ private static final String COLUMN_NAME = "component_uuid";
+ private static final String INDEX_NAME = "sca_releases_comp_uuid";
+
+ @RegisterExtension
+ public final MigrationDbTester db = createForMigrationStep(DropIndexOnScaReleasesComponent.class);
+ private final DropIndexOnScaReleasesComponent underTest = new DropIndexOnScaReleasesComponent(db.database());
+
+ @Test
+ void index_is_dropped() throws SQLException {
+ db.assertIndex(TABLE_NAME, INDEX_NAME, COLUMN_NAME);
+
+ underTest.execute();
+
+ db.assertIndexDoesNotExist(TABLE_NAME, COLUMN_NAME);
+ }
+
+ @Test
+ void migration_is_reentrant() throws SQLException {
+ db.assertIndex(TABLE_NAME, INDEX_NAME, COLUMN_NAME);
+
+ underTest.execute();
+ underTest.execute();
+
+ db.assertIndexDoesNotExist(TABLE_NAME, COLUMN_NAME);
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java
index f844369bf02..5b5af55fd0b 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java
@@ -39,6 +39,7 @@ import org.sonar.server.platform.db.migration.version.v107.DbVersion107;
import org.sonar.server.platform.db.migration.version.v108.DbVersion108;
import org.sonar.server.platform.db.migration.version.v202501.DbVersion202501;
import org.sonar.server.platform.db.migration.version.v202502.DbVersion202502;
+import org.sonar.server.platform.db.migration.version.v202503.DbVersion202503;
public class MigrationConfigurationModule extends Module {
@Override
@@ -58,6 +59,7 @@ public class MigrationConfigurationModule extends Module {
DbVersion108.class,
DbVersion202501.class,
DbVersion202502.class,
+ DbVersion202503.class,
// migration steps
MigrationStepRegistryImpl.class,
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuid.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuid.java
new file mode 100644
index 00000000000..85dc6395842
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuid.java
@@ -0,0 +1,58 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2025 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.v202503;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class CreateIndexOnScaReleasesComponentUuid extends DdlChange {
+
+ static final String TABLE_NAME = "sca_releases";
+ // abbreviated for 30 char limit
+ static final String INDEX_NAME = "sca_releases_comp_uuid_uuid";
+ static final String COLUMN_NAME_COMPONENT_UUID = "component_uuid";
+ static final String COLUMN_NAME_UUID = "uuid";
+
+ public CreateIndexOnScaReleasesComponentUuid(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ try (Connection connection = getDatabase().getDataSource().getConnection()) {
+ createIndex(context, connection);
+ }
+ }
+
+ private void createIndex(Context context, Connection connection) {
+ if (!DatabaseUtils.indexExistsIgnoreCase(TABLE_NAME, INDEX_NAME, connection)) {
+ context.execute(new CreateIndexBuilder(getDialect())
+ .setTable(TABLE_NAME)
+ .setName(INDEX_NAME)
+ .addColumn(COLUMN_NAME_COMPONENT_UUID, false)
+ .addColumn(COLUMN_NAME_UUID, false)
+ .build());
+ }
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503.java
new file mode 100644
index 00000000000..c9898d9f923
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503.java
@@ -0,0 +1,42 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2025 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.v202503;
+
+import org.sonar.server.platform.db.migration.step.MigrationStepRegistry;
+import org.sonar.server.platform.db.migration.version.DbVersion;
+
+// ignoring bad number formatting, as it's indented that we align the migration numbers to SQ versions
+@SuppressWarnings("java:S3937")
+public class DbVersion202503 implements DbVersion {
+
+ /**
+ * We use the start of the 10.X cycle as an opportunity to align migration numbers with the SQ version number.
+ * Please follow this pattern:
+ * 2025_03_000
+ * 2025_03_001
+ * 2025_03_002
+ */
+ @Override
+ public void addSteps(MigrationStepRegistry registry) {
+ registry
+ .add(2025_03_000, "Drop 'sca_releases_comp_uuid' index", DropIndexOnScaReleasesComponent.class)
+ .add(2025_03_001, "Create 'sca_releases_comp_uuid_uuid' index", CreateIndexOnScaReleasesComponentUuid.class);
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponent.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponent.java
new file mode 100644
index 00000000000..8001e821463
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponent.java
@@ -0,0 +1,33 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2025 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.v202503;
+
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DropIndexChange;
+
+public class DropIndexOnScaReleasesComponent extends DropIndexChange {
+
+ private static final String TABLE_NAME = "sca_releases";
+ private static final String INDEX_NAME = "sca_releases_comp_uuid";
+
+ public DropIndexOnScaReleasesComponent(Database db) {
+ super(db, INDEX_NAME, TABLE_NAME);
+ }
+}