]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19728 Remove ordering from query, fetch issue keys
authorJacek Poreda <jacek.poreda@sonarsource.com>
Tue, 11 Jul 2023 11:53:31 +0000 (13:53 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 19 Jul 2023 20:03:05 +0000 (20:03 +0000)
server/sonar-db-dao/src/it/java/org/sonar/db/issue/IssueDaoIT.java
server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueMapper.java
server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml
server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/ListAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ListAction.java

index 567af5f835279e6ad7800d682cd4969b93e3cca0..5a3f2a1214c648e6a6e6629032403b1605c4d455 100644 (file)
@@ -579,21 +579,20 @@ public class IssueDaoIT {
   }
 
   @Test
-  public void selectByQuery_shouldBePaginated() {
+  public void selectIssueKeysByQuery_shouldBePaginated() {
     List<IssueDto> issues = generateIssues(10, i -> createIssueWithKey("i-" + i));
     issues.forEach(issue -> underTest.insert(db.getSession(), issue));
 
-    List<IssueDto> results = underTest.selectByQuery(
+    List<String> results = underTest.selectIssueKeysByQuery(
       db.getSession(),
       newIssueListQueryBuilder().project(PROJECT_KEY).build(),
       Pagination.forPage(2).andSize(3));
 
-    List<String> expectedKeys = List.of("i-3", "i-4", "i-5");
-    assertThat(results.stream().map(IssueDto::getKey).toList()).containsExactlyElementsOf(expectedKeys);
+    assertThat(results.stream().toList()).hasSize(3);
   }
 
   @Test
-  public void selectByQuery_whenFilteredByBranch_shouldGetOnlyBranchIssues() {
+  public void selectIssueKeysByQuery_whenFilteredByBranch_shouldGetOnlyBranchIssues() {
     BranchDto branchDto = ComponentTesting.newBranchDto(PROJECT_UUID, BRANCH);
     ComponentDto branch = db.components().insertProjectBranch(projectDto, branchDto);
     ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
@@ -602,17 +601,17 @@ public class IssueDaoIT {
     Stream.concat(mainBranchIssues.stream(), otherBranchIssues.stream())
       .forEach(issue -> underTest.insert(db.getSession(), issue));
 
-    List<IssueDto> results = underTest.selectByQuery(
+    List<String> results = underTest.selectIssueKeysByQuery(
       db.getSession(),
       newIssueListQueryBuilder().project(PROJECT_KEY).branch(branchDto.getKey()).build(),
       Pagination.forPage(1).andSize(6));
 
     List<String> expectedKeys = List.of("branch-0", "branch-1", "branch-2");
-    assertThat(results.stream().map(IssueDto::getKey).toList()).containsExactlyElementsOf(expectedKeys);
+    assertThat(results.stream().toList()).containsExactlyInAnyOrderElementsOf(expectedKeys);
   }
 
   @Test
-  public void selectByQuery_whenFilteredByPullRequest_shouldGetOnlyPRIssues() {
+  public void selectIssueKeysByQuery_whenFilteredByPullRequest_shouldGetOnlyPRIssues() {
     BranchDto pullRequestDto = ComponentTesting.newBranchDto(PROJECT_UUID, PULL_REQUEST);
     ComponentDto branch = db.components().insertProjectBranch(projectDto, pullRequestDto);
     ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
@@ -621,34 +620,34 @@ public class IssueDaoIT {
     Stream.concat(mainBranchIssues.stream(), otherBranchIssues.stream())
       .forEach(issue -> underTest.insert(db.getSession(), issue));
 
-    List<IssueDto> results = underTest.selectByQuery(
+    List<String> results = underTest.selectIssueKeysByQuery(
       db.getSession(),
       newIssueListQueryBuilder().project(PROJECT_KEY).pullRequest(pullRequestDto.getKey()).build(),
       Pagination.forPage(1).andSize(6));
 
     List<String> expectedKeys = List.of("pr-0", "pr-1", "pr-2");
-    assertThat(results.stream().map(IssueDto::getKey).toList()).containsExactlyElementsOf(expectedKeys);
+    assertThat(results.stream().toList()).containsExactlyInAnyOrderElementsOf(expectedKeys);
   }
 
   @Test
-  public void selectByQuery_whenFilteredByTypes_shouldGetIssuesWithSpecifiedTypes() {
+  public void selectIssueKeysByQuery_whenFilteredByTypes_shouldGetIssuesWithSpecifiedTypes() {
     List<IssueDto> bugs = generateIssues(3, i -> createIssueWithKey("bug-" + i).setType(RuleType.BUG));
     List<IssueDto> codeSmells = generateIssues(3, i -> createIssueWithKey("codesmell-" + i).setType(RuleType.CODE_SMELL));
     Stream.of(bugs, codeSmells)
       .flatMap(Collection::stream)
       .forEach(issue -> underTest.insert(db.getSession(), issue));
 
-    List<IssueDto> results = underTest.selectByQuery(
+    List<String> results = underTest.selectIssueKeysByQuery(
       db.getSession(),
       newIssueListQueryBuilder().project(PROJECT_KEY).types(List.of(RuleType.BUG.getDbConstant())).build(),
       Pagination.forPage(1).andSize(10));
 
     List<String> expectedKeys = List.of("bug-0", "bug-1", "bug-2");
-    assertThat(results.stream().map(IssueDto::getKey).toList()).containsExactlyElementsOf(expectedKeys);
+    assertThat(results.stream().toList()).containsExactlyInAnyOrderElementsOf(expectedKeys);
   }
 
   @Test
-  public void selectByQuery_whenFilteredByFilteredStatuses_shouldGetIssuesWithoutSpecifiedStatuses() {
+  public void selectIssueKeysByQuery_whenFilteredByFilteredStatuses_shouldGetIssuesWithoutSpecifiedStatuses() {
     List<IssueDto> openIssues = generateIssues(3, i -> createIssueWithKey("open-" + i).setStatus("OPEN"));
     List<IssueDto> closedIssues = generateIssues(3, i -> createIssueWithKey("closed-" + i).setStatus("CLOSED"));
     List<IssueDto> resolvedIssues = generateIssues(3, i -> createIssueWithKey("resolved-" + i).setStatus("RESOLVED"));
@@ -656,17 +655,17 @@ public class IssueDaoIT {
       .flatMap(Collection::stream)
       .forEach(issue -> underTest.insert(db.getSession(), issue));
 
-    List<IssueDto> results = underTest.selectByQuery(
+    List<String> results = underTest.selectIssueKeysByQuery(
       db.getSession(),
       newIssueListQueryBuilder().project(PROJECT_KEY).statuses(List.of("OPEN")).build(),
       Pagination.forPage(1).andSize(10));
 
     List<String> expectedKeys = List.of("open-0", "open-1", "open-2");
-    assertThat(results.stream().map(IssueDto::getKey).toList()).containsExactlyElementsOf(expectedKeys);
+    assertThat(results.stream().toList()).containsExactlyInAnyOrderElementsOf(expectedKeys);
   }
 
   @Test
-  public void selectByQuery_whenFilteredByFilteredResolutions_shouldGetIssuesWithoutSpecifiedResolution() {
+  public void selectIssueKeysByQuery_whenFilteredByFilteredResolutions_shouldGetIssuesWithoutSpecifiedResolution() {
     List<IssueDto> unresolvedIssues = generateIssues(3, i -> createIssueWithKey("open-" + i).setResolution(null));
     List<IssueDto> wontfixIssues = generateIssues(3, i -> createIssueWithKey("wf-" + i).setResolution("WONTFIX"));
     List<IssueDto> falsePositiveIssues = generateIssues(3, i -> createIssueWithKey("fp-" + i).setResolution("FALSE-POSITIVE"));
@@ -674,17 +673,17 @@ public class IssueDaoIT {
       .flatMap(Collection::stream)
       .forEach(issue -> underTest.insert(db.getSession(), issue));
 
-    List<IssueDto> results = underTest.selectByQuery(
+    List<String> results = underTest.selectIssueKeysByQuery(
       db.getSession(),
       newIssueListQueryBuilder().project(PROJECT_KEY).resolutions(List.of("WONTFIX")).build(),
       Pagination.forPage(1).andSize(10));
 
     List<String> expectedKeys = List.of("wf-0", "wf-1", "wf-2");
-    assertThat(results.stream().map(IssueDto::getKey).toList()).containsExactlyElementsOf(expectedKeys);
+    assertThat(results.stream().toList()).containsExactlyInAnyOrderElementsOf(expectedKeys);
   }
 
   @Test
-  public void selectByQuery_whenFilteredByFileComponent_shouldGetIssuesWithinFileOnly() {
+  public void selectIssueKeysByQuery_whenFilteredByFileComponent_shouldGetIssuesWithinFileOnly() {
     ComponentDto otherFileDto = db.components().insertComponent(newFileDto(projectDto).setUuid("OTHER_UUID").setKey("OTHER_KEY"));
     List<IssueDto> fromFileIssues = generateIssues(3, i -> createIssueWithKey("file-" + i));
     List<IssueDto> fromOtherFileIssues = generateIssues(3, i -> createIssueWithKey("otherfile-" + i, PROJECT_UUID, otherFileDto.uuid()));
@@ -692,17 +691,17 @@ public class IssueDaoIT {
       .flatMap(Collection::stream)
       .forEach(issue -> underTest.insert(db.getSession(), issue));
 
-    List<IssueDto> results = underTest.selectByQuery(
+    List<String> results = underTest.selectIssueKeysByQuery(
       db.getSession(),
       newIssueListQueryBuilder().component(otherFileDto.getKey()).build(),
       Pagination.forPage(1).andSize(10));
 
     List<String> expectedKeys = List.of("otherfile-0", "otherfile-1", "otherfile-2");
-    assertThat(results.stream().map(IssueDto::getKey).toList()).containsExactlyElementsOf(expectedKeys);
+    assertThat(results.stream().toList()).containsExactlyInAnyOrderElementsOf(expectedKeys);
   }
 
   @Test
-  public void selectByQuery_whenFilteredWithInNewCodeReference_shouldGetNewCodeReferenceIssues() {
+  public void selectIssueKeysByQuery_whenFilteredWithInNewCodeReference_shouldGetNewCodeReferenceIssues() {
     List<IssueDto> issues = generateIssues(3, i -> createIssueWithKey("i-" + i));
     List<IssueDto> newCodeRefIssues = generateIssues(3, i -> createIssueWithKey("newCodeRef-" + i));
     Stream.of(issues, newCodeRefIssues)
@@ -710,30 +709,30 @@ public class IssueDaoIT {
       .forEach(issue -> underTest.insert(db.getSession(), issue));
     newCodeRefIssues.forEach(issue -> db.issues().insertNewCodeReferenceIssue(issue));
 
-    List<IssueDto> results = underTest.selectByQuery(
+    List<String> results = underTest.selectIssueKeysByQuery(
       db.getSession(),
       newIssueListQueryBuilder().project(PROJECT_KEY).newCodeOnReference(true).build(),
       Pagination.forPage(1).andSize(10));
 
     List<String> expectedKeys = List.of("newCodeRef-0", "newCodeRef-1", "newCodeRef-2");
-    assertThat(results.stream().map(IssueDto::getKey).toList()).containsExactlyElementsOf(expectedKeys);
+    assertThat(results.stream().toList()).containsExactlyInAnyOrderElementsOf(expectedKeys);
   }
 
   @Test
-  public void selectByQuery_whenFilteredWithCreatedAfter_shouldGetIssuesCreatedAfterDate() {
+  public void selectIssueKeysByQuery_whenFilteredWithCreatedAfter_shouldGetIssuesCreatedAfterDate() {
     List<IssueDto> createdBeforeIssues = generateIssues(3, i -> createIssueWithKey("createdBefore-" + i).setResolution(null).setIssueCreationDate(new Date(1_400_000_000_000L)));
     List<IssueDto> createdAfterIssues = generateIssues(3, i -> createIssueWithKey("createdAfter-" + i).setResolution(null).setIssueCreationDate(new Date(1_420_000_000_000L)));
     Stream.of(createdBeforeIssues, createdAfterIssues)
       .flatMap(Collection::stream)
       .forEach(issue -> underTest.insert(db.getSession(), issue));
 
-    List<IssueDto> results = underTest.selectByQuery(
+    List<String> results = underTest.selectIssueKeysByQuery(
       db.getSession(),
       newIssueListQueryBuilder().project(PROJECT_KEY).createdAfter(1_410_000_000_000L).build(),
       Pagination.forPage(1).andSize(10));
 
     List<String> expectedKeys = List.of("createdAfter-0", "createdAfter-1", "createdAfter-2");
-    assertThat(results.stream().map(IssueDto::getKey).toList()).containsExactlyElementsOf(expectedKeys);
+    assertThat(results.stream().toList()).containsExactlyInAnyOrderElementsOf(expectedKeys);
   }
 
   private static IssueDto createIssueWithKey(String issueKey) {
index 679cf8c0e3483e9eb78cfaca3f5a5e31a753ea6b..4ff0349eef90fbc02cd6436b9cab98fc034ca28d 100644 (file)
@@ -127,8 +127,11 @@ public class IssueDao implements Dao {
     return mapper(dbSession).selectRecentlyClosedIssues(issueQueryParams);
   }
 
-  public List<IssueDto> selectByQuery(DbSession dbSession, IssueListQuery issueListQuery, Pagination pagination) {
-    return mapper(dbSession).selectByQuery(issueListQuery, pagination);
+  /**
+   * Returned results are unordered.
+   */
+  public List<String> selectIssueKeysByQuery(DbSession dbSession, IssueListQuery issueListQuery, Pagination pagination) {
+    return mapper(dbSession).selectIssueKeysByQuery(issueListQuery, pagination);
   }
 
 }
index 3238a8a089fc40ed85d75fe5509179a0320b7631..5191504426a1e2762fa7cc71237c7345f77c2ec5 100644 (file)
@@ -77,5 +77,5 @@ public interface IssueMapper {
 
   List<String> selectRecentlyClosedIssues(@Param("queryParams") IssueQueryParams issueQueryParams);
 
-  List<IssueDto> selectByQuery(@Param("query") IssueListQuery issueListQuery, @Param("pagination") Pagination pagination);
+  List<String> selectIssueKeysByQuery(@Param("query") IssueListQuery issueListQuery, @Param("pagination") Pagination pagination);
 }
index ac6593db8e2851f7c03f1995abe3dd6d019ca5da..61b2b81abfbcdee9e2cfbf7030e0e4c5380fe32e 100644 (file)
         </if>
   </select>
 
-  <select id="selectByQuery" parameterType="map" resultType="Issue">
+  <select id="selectIssueKeysByQuery" parameterType="map" resultType="string">
     select
-    <include refid="issueColumns"/>
+    i.kee
     from issues i
-    inner join rules r on r.uuid=i.rule_uuid
     inner join components p on p.uuid=i.component_uuid
     inner join components root on root.uuid=i.project_uuid
     inner join project_branches pb on pb.uuid=i.project_uuid
         AND i.issue_creation_date &gt;= #{query.createdAfter,jdbcType=BIGINT}
       </if>
     </where>
-    order by i.kee asc
+      <if test="_databaseId == 'mssql'">
+        <!--  order by clause is required if using offset rows fetch next on MSSQL Database   -->
+        order by (select null)
+      </if>
     offset (#{pagination.startRowNumber,jdbcType=INTEGER}-1) rows fetch next #{pagination.pageSize,jdbcType=INTEGER} rows only
   </select>
-
 </mapper>
index 1f44254a25513d08e60f5c27aa503b8575b16840..ba61692dad38044ffdc391be39e758ae5f5b1846 100644 (file)
@@ -165,13 +165,14 @@ public class ListAction implements HotspotsWsAction {
   }
 
   private SearchResponseData searchHotspots(DbSession dbSession, WsRequest wsRequest, ProjectAndBranch projectAndBranch) {
-    List<IssueDto> hotspots = getHotspotKeys(dbSession, wsRequest, projectAndBranch);
+    List<String> hotspotKeys = getHotspotKeys(dbSession, wsRequest, projectAndBranch);
 
-    Paging paging = forPageIndex(wsRequest.page).withPageSize(wsRequest.pageSize).andTotal(hotspots.size());
+    Paging paging = forPageIndex(wsRequest.page).withPageSize(wsRequest.pageSize).andTotal(hotspotKeys.size());
+    List<IssueDto> hotspots = dbClient.issueDao().selectByKeys(dbSession, hotspotKeys);
     return new SearchResponseData(paging, hotspots);
   }
 
-  private List<IssueDto> getHotspotKeys(DbSession dbSession, WsRequest wsRequest, ProjectAndBranch projectAndBranch) {
+  private List<String> getHotspotKeys(DbSession dbSession, WsRequest wsRequest, ProjectAndBranch projectAndBranch) {
     BranchDto branch = projectAndBranch.getBranch();
     IssueListQuery.IssueListQueryBuilder queryBuilder = IssueListQuery.IssueListQueryBuilder.newIssueListQueryBuilder()
       .project(wsRequest.project)
@@ -192,7 +193,7 @@ public class ListAction implements HotspotsWsAction {
     }
 
     Pagination pagination = Pagination.forPage(wsRequest.page).andSize(wsRequest.pageSize);
-    return dbClient.issueDao().selectByQuery(dbSession, queryBuilder.build(), pagination);
+    return dbClient.issueDao().selectIssueKeysByQuery(dbSession, queryBuilder.build(), pagination);
   }
 
   private void loadComponents(DbSession dbSession, SearchResponseData searchResponseData) {
index c53e07826d75a0fd505034d09798277861be000b..229c5b1bf758ef6562f38bf44657eba928384967 100644 (file)
@@ -34,7 +34,6 @@ import org.sonar.db.DbSession;
 import org.sonar.db.Pagination;
 import org.sonar.db.component.BranchDto;
 import org.sonar.db.component.ComponentDto;
-import org.sonar.db.issue.IssueDto;
 import org.sonar.db.issue.IssueListQuery;
 import org.sonar.db.newcodeperiod.NewCodePeriodType;
 import org.sonar.db.project.ProjectDto;
@@ -47,6 +46,7 @@ import org.sonarqube.ws.Common;
 import org.sonarqube.ws.Issues;
 
 import static com.google.common.base.Strings.isNullOrEmpty;
+import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
 import static org.sonar.api.server.ws.WebService.Param.PAGE;
 import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
@@ -136,8 +136,8 @@ public class ListAction implements IssuesWsAction {
   public final void handle(Request request, Response response) {
     WsRequest wsRequest = toWsRequest(request);
     ProjectAndBranch projectAndBranch = validateRequest(wsRequest);
-    List<IssueDto> issues = getIssueKeys(wsRequest, projectAndBranch);
-    Issues.ListWsResponse wsResponse = formatResponse(wsRequest, issues);
+    List<String> issueKeys = getIssueKeys(wsRequest, projectAndBranch);
+    Issues.ListWsResponse wsResponse = formatResponse(wsRequest, issueKeys);
     writeProtobuf(wsResponse, request, response);
   }
 
@@ -190,7 +190,7 @@ public class ListAction implements IssuesWsAction {
     return projectAndBranch;
   }
 
-  private List<IssueDto> getIssueKeys(WsRequest wsRequest, ProjectAndBranch projectAndBranch) {
+  private List<String> getIssueKeys(WsRequest wsRequest, ProjectAndBranch projectAndBranch) {
     try (DbSession dbSession = dbClient.openSession(false)) {
       BranchDto branch = projectAndBranch.getBranch();
       IssueListQuery.IssueListQueryBuilder queryBuilder = IssueListQuery.IssueListQueryBuilder.newIssueListQueryBuilder()
@@ -213,21 +213,20 @@ public class ListAction implements IssuesWsAction {
       }
 
       Pagination pagination = Pagination.forPage(wsRequest.page).andSize(wsRequest.pageSize);
-      return dbClient.issueDao().selectByQuery(dbSession, queryBuilder.build(), pagination);
+      return dbClient.issueDao().selectIssueKeysByQuery(dbSession, queryBuilder.build(), pagination);
     }
   }
 
-  private Issues.ListWsResponse formatResponse(WsRequest request, List<IssueDto> issues) {
+  private Issues.ListWsResponse formatResponse(WsRequest request, List<String> issueKeys) {
     Issues.ListWsResponse.Builder response = Issues.ListWsResponse.newBuilder();
     response.setPaging(Common.Paging.newBuilder()
       .setPageIndex(request.page)
-      .setPageSize(issues.size())
+      .setPageSize(issueKeys.size())
       .build());
 
-    List<String> issueKeys = issues.stream().map(IssueDto::getKey).toList();
     SearchResponseLoader.Collector collector = new SearchResponseLoader.Collector(issueKeys);
     collectLoggedInUser(collector);
-    SearchResponseData preloadedData = new SearchResponseData(issues);
+    SearchResponseData preloadedData = new SearchResponseData(emptyList());
     EnumSet<SearchAdditionalField> additionalFields = EnumSet.of(SearchAdditionalField.ACTIONS, SearchAdditionalField.COMMENTS, SearchAdditionalField.TRANSITIONS);
     SearchResponseData data = searchResponseLoader.load(preloadedData, collector, additionalFields, null);