diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2017-01-13 16:35:16 +0100 |
---|---|---|
committer | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2017-01-16 13:01:40 +0100 |
commit | b063b87fa456cb49cba2afde0e88bff83ecdaedc (patch) | |
tree | ebb11c98dfe5be7e87c1e856debd7686b5b983e6 /sonar-db | |
parent | e09bee5fed18be0ff8730c510ff3d72156957529 (diff) | |
download | sonarqube-b063b87fa456cb49cba2afde0e88bff83ecdaedc.tar.gz sonarqube-b063b87fa456cb49cba2afde0e88bff83ecdaedc.zip |
SONAR-8613 add filter on keys to OrganizationDao.selectByQuery
Diffstat (limited to 'sonar-db')
5 files changed, 215 insertions, 19 deletions
diff --git a/sonar-db/src/main/java/org/sonar/db/organization/OrganizationDao.java b/sonar-db/src/main/java/org/sonar/db/organization/OrganizationDao.java index e39a27d7157..2705c8355e4 100644 --- a/sonar-db/src/main/java/org/sonar/db/organization/OrganizationDao.java +++ b/sonar-db/src/main/java/org/sonar/db/organization/OrganizationDao.java @@ -46,8 +46,9 @@ public class OrganizationDao implements Dao { getMapper(dbSession).insert(organization); } - public List<OrganizationDto> selectByQuery(DbSession dbSession, int offset, int limit) { - return getMapper(dbSession).selectByQuery(offset, limit); + public List<OrganizationDto> selectByQuery(DbSession dbSession, OrganizationQuery organizationQuery, int offset, int limit) { + requireNonNull(organizationQuery, "organizationQuery can't be null"); + return getMapper(dbSession).selectByQuery(organizationQuery, offset, limit); } public Optional<OrganizationDto> selectByUuid(DbSession dbSession, String uuid) { diff --git a/sonar-db/src/main/java/org/sonar/db/organization/OrganizationMapper.java b/sonar-db/src/main/java/org/sonar/db/organization/OrganizationMapper.java index 7da4a027413..8a2b9b3c1fb 100644 --- a/sonar-db/src/main/java/org/sonar/db/organization/OrganizationMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/organization/OrganizationMapper.java @@ -26,7 +26,8 @@ import org.apache.ibatis.annotations.Param; public interface OrganizationMapper { void insert(@Param("organization") OrganizationDto organization); - List<OrganizationDto> selectByQuery(@Param("offset") int offset, @Param("pageSize") int pageSize); + List<OrganizationDto> selectByQuery(@Param("query") OrganizationQuery organizationQuery, + @Param("offset") int offset, @Param("pageSize") int pageSize); @CheckForNull OrganizationDto selectByKey(@Param("key") String key); diff --git a/sonar-db/src/main/java/org/sonar/db/organization/OrganizationQuery.java b/sonar-db/src/main/java/org/sonar/db/organization/OrganizationQuery.java new file mode 100644 index 00000000000..29967eba2b8 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/organization/OrganizationQuery.java @@ -0,0 +1,71 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.db.organization; + +import java.util.Collection; +import java.util.Objects; +import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +import static org.sonar.core.util.stream.Collectors.toSet; + +public class OrganizationQuery { + private static final OrganizationQuery NO_QUERY = newOrganizationQueryBuilder().build(); + private final Set<String> keys; + + private OrganizationQuery(Builder builder) { + this.keys = builder.keys; + } + + public static OrganizationQuery returnAll() { + return NO_QUERY; + } + + public static Builder newOrganizationQueryBuilder() { + return new Builder(); + } + + @CheckForNull + public Set<String> getKeys() { + return keys; + } + + public static class Builder { + private Set<String> keys; + + private Builder() { + // use static factory method + } + + public Builder setKeys(@Nullable Collection<String> keys) { + if (keys != null && !keys.isEmpty()) { + this.keys = keys.stream() + .filter(Objects::nonNull) + .collect(toSet(keys.size())); + } + return this; + } + + public OrganizationQuery build() { + return new OrganizationQuery(this); + } + } +} diff --git a/sonar-db/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml b/sonar-db/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml index e120713908c..c7ab1ea8461 100644 --- a/sonar-db/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml @@ -75,6 +75,14 @@ <sql id="sqlSelectByQuery"> from organizations org + <where> + <if test="query.keys != null"> + org.kee in + <foreach collection="query.keys" open="(" close=")" item="key" separator=","> + #{key, jdbcType=VARCHAR} + </foreach> + </if> + </where> </sql> <insert id="insert" parameterType="Organization" useGeneratedKeys="false"> diff --git a/sonar-db/src/test/java/org/sonar/db/organization/OrganizationDaoTest.java b/sonar-db/src/test/java/org/sonar/db/organization/OrganizationDaoTest.java index 000cb53dac3..88a51f6e658 100644 --- a/sonar-db/src/test/java/org/sonar/db/organization/OrganizationDaoTest.java +++ b/sonar-db/src/test/java/org/sonar/db/organization/OrganizationDaoTest.java @@ -19,6 +19,7 @@ */ package org.sonar.db.organization; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -26,6 +27,7 @@ import java.util.Map; import java.util.Optional; import java.util.Random; import org.apache.ibatis.exceptions.PersistenceException; +import org.assertj.core.util.Lists; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -40,6 +42,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.sonar.db.organization.OrganizationQuery.newOrganizationQueryBuilder; +import static org.sonar.db.organization.OrganizationQuery.returnAll; public class OrganizationDaoTest { private static final long SOME_DATE = 1_200_999L; @@ -256,19 +260,19 @@ public class OrganizationDaoTest { @Test public void selectByQuery_returns_empty_when_table_is_empty() { - assertThat(underTest.selectByQuery(dbSession, 1, 1)).isEmpty(); + assertThat(underTest.selectByQuery(dbSession, returnAll(), 1, 1)).isEmpty(); } @Test public void selectByQuery_returns_single_row_of_table_when_requesting_first_page_of_size_1_or_more() { insertOrganization(ORGANIZATION_DTO_1); - assertThat(underTest.selectByQuery(dbSession, 0, 1)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 0, 1)) .hasSize(1) .extracting("uuid") .containsOnly(ORGANIZATION_DTO_1.getUuid()); - assertThat(underTest.selectByQuery(dbSession, 0, 10)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 0, 10)) .hasSize(1) .extracting("uuid") .containsOnly(ORGANIZATION_DTO_1.getUuid()); @@ -278,9 +282,9 @@ public class OrganizationDaoTest { public void selectByQuery_returns_empty_on_table_with_single_row_when_not_requesting_the_first_page() { insertOrganization(ORGANIZATION_DTO_1); - assertThat(underTest.selectByQuery(dbSession, 1, 1)).isEmpty(); - assertThat(underTest.selectByQuery(dbSession, Math.abs(new Random().nextInt(10)) + 1, 1)).isEmpty(); - assertThat(underTest.selectByQuery(dbSession, 1, 10)).isEmpty(); + assertThat(underTest.selectByQuery(dbSession, returnAll(), 1, 1)).isEmpty(); + assertThat(underTest.selectByQuery(dbSession, returnAll(), Math.abs(new Random().nextInt(10)) + 1, 1)).isEmpty(); + assertThat(underTest.selectByQuery(dbSession, returnAll(), 1, 10)).isEmpty(); } @Test @@ -293,38 +297,149 @@ public class OrganizationDaoTest { insertOrganization(copyOf(ORGANIZATION_DTO_1).setUuid("uuid5").setKey("key-5")); insertOrganization(copyOf(ORGANIZATION_DTO_1).setUuid("uuid4").setKey("key-4")); - assertThat(underTest.selectByQuery(dbSession, 0, 1)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 0, 1)) .extracting("uuid", "key") .containsExactly(tuple("uuid4", "key-4")); - assertThat(underTest.selectByQuery(dbSession, 1, 1)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 1, 1)) .extracting("uuid", "key") .containsExactly(tuple("uuid5", "key-5")); - assertThat(underTest.selectByQuery(dbSession, 2, 1)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 2, 1)) .extracting("uuid", "key") .containsExactly(tuple("uuid2", "key-2")); - assertThat(underTest.selectByQuery(dbSession, 3, 1)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 3, 1)) .extracting("uuid", "key") .containsExactly(tuple("uuid1", "key-1")); - assertThat(underTest.selectByQuery(dbSession, 4, 1)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 4, 1)) .extracting("uuid", "key") .containsExactly(tuple("uuid3", "key-3")); - assertThat(underTest.selectByQuery(dbSession, 5, 1)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 5, 1)) .isEmpty(); - assertThat(underTest.selectByQuery(dbSession, 0, 5)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 0, 5)) .extracting("uuid") .containsExactly("uuid4", "uuid5", "uuid2", "uuid1", "uuid3"); - assertThat(underTest.selectByQuery(dbSession, 5, 5)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 5, 5)) .isEmpty(); - assertThat(underTest.selectByQuery(dbSession, 0, 3)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 0, 3)) .extracting("uuid") .containsExactly("uuid4", "uuid5", "uuid2"); - assertThat(underTest.selectByQuery(dbSession, 3, 3)) + assertThat(underTest.selectByQuery(dbSession, returnAll(), 3, 3)) .extracting("uuid") .containsExactly("uuid1", "uuid3"); } @Test + public void selectByQuery_with_keys_returns_empty_when_table_is_empty() { + assertThat(underTest.selectByQuery(dbSession, newQueryWithKeys("key1", "key2"), 1, 1)) + .isEmpty(); + } + + @Test + public void selectByQuery_with_keys_returns_single_row_of_table_when_requesting_first_page_of_size_1_or_more() { + insertOrganization(ORGANIZATION_DTO_1); + insertOrganization(ORGANIZATION_DTO_2); + + OrganizationQuery organizationQuery = newQueryWithKeys(ORGANIZATION_DTO_1.getKey(), ORGANIZATION_DTO_2.getKey()); + assertThat(underTest.selectByQuery(dbSession, organizationQuery, 0, 1)) + .hasSize(1); + + assertThat(underTest.selectByQuery(dbSession, organizationQuery, 0, 10)) + .hasSize(2) + .extracting(OrganizationDto::getUuid) + .containsOnly(ORGANIZATION_DTO_1.getUuid(), ORGANIZATION_DTO_2.getUuid()); + } + + @Test + public void selectByQuery_with_empty_list_of_keys_returns_all() { + insertOrganization(ORGANIZATION_DTO_1); + insertOrganization(ORGANIZATION_DTO_2); + + OrganizationQuery organizationQuery = newOrganizationQueryBuilder().setKeys(Lists.emptyList()).build(); + assertThat(underTest.selectByQuery(dbSession, organizationQuery, 0, 10)) + .extracting(OrganizationDto::getUuid) + .containsOnly(ORGANIZATION_DTO_1.getUuid(), ORGANIZATION_DTO_2.getUuid()); + } + + @Test + public void selectByQuery_with_only_non_existent_keys_returns_empty() { + insertOrganization(ORGANIZATION_DTO_1); + insertOrganization(ORGANIZATION_DTO_2); + + OrganizationQuery organizationQuery = newQueryWithKeys("foo", "bar", "dog"); + assertThat(underTest.selectByQuery(dbSession, organizationQuery, 0, 10)) + .isEmpty(); + } + + @Test + public void selectByQuery_with_ignores_non_existent_keys() { + insertOrganization(ORGANIZATION_DTO_1); + insertOrganization(ORGANIZATION_DTO_2); + + OrganizationQuery organizationQuery = newQueryWithKeys(ORGANIZATION_DTO_1.getKey(), "foo", ORGANIZATION_DTO_2.getKey(), "bar", "dog"); + assertThat(underTest.selectByQuery(dbSession, organizationQuery, 0, 10)) + .hasSize(2) + .extracting(OrganizationDto::getUuid) + .containsOnly(ORGANIZATION_DTO_1.getUuid(), ORGANIZATION_DTO_2.getUuid()); + } + + @Test + public void selectByQuery_with_keys_returns_empty_on_table_with_single_row_when_not_requesting_the_first_page() { + insertOrganization(ORGANIZATION_DTO_1); + insertOrganization(ORGANIZATION_DTO_2); + + OrganizationQuery organizationQuery = newQueryWithKeys(ORGANIZATION_DTO_1.getKey(), ORGANIZATION_DTO_2.getKey()); + assertThat(underTest.selectByQuery(dbSession, organizationQuery, 2, 2)).isEmpty(); + assertThat(underTest.selectByQuery(dbSession, organizationQuery, Math.abs(new Random().nextInt(10)) + 2, 1)).isEmpty(); + assertThat(underTest.selectByQuery(dbSession, organizationQuery, 2, 10)).isEmpty(); + } + + @Test + public void selectByQuery_with_keys_returns_rows_ordered_by_createdAt_descending_applying_requested_paging() { + long time = 1_999_999L; + when(system2.now()).thenReturn(time, time + 1_000, time + 2_000, time + 3_000, time + 5_000); + insertOrganization(copyOf(ORGANIZATION_DTO_1).setUuid("uuid3").setKey("key-3")); + insertOrganization(copyOf(ORGANIZATION_DTO_1).setUuid("uuid1").setKey("key-1")); + insertOrganization(copyOf(ORGANIZATION_DTO_1).setUuid("uuid2").setKey("key-2")); + insertOrganization(copyOf(ORGANIZATION_DTO_1).setUuid("uuid5").setKey("key-5")); + insertOrganization(copyOf(ORGANIZATION_DTO_1).setUuid("uuid4").setKey("key-4")); + OrganizationQuery allExistingKeys = newQueryWithKeys("key-1", "key-2", "key-3", "key-4", "key-5"); + + assertThat(underTest.selectByQuery(dbSession, allExistingKeys, 0, 1)) + .extracting(OrganizationDto::getUuid, OrganizationDto::getKey) + .containsExactly(tuple("uuid4", "key-4")); + assertThat(underTest.selectByQuery(dbSession, allExistingKeys, 1, 1)) + .extracting(OrganizationDto::getUuid, OrganizationDto::getKey) + .containsExactly(tuple("uuid5", "key-5")); + assertThat(underTest.selectByQuery(dbSession, allExistingKeys, 2, 1)) + .extracting(OrganizationDto::getUuid, OrganizationDto::getKey) + .containsExactly(tuple("uuid2", "key-2")); + assertThat(underTest.selectByQuery(dbSession, allExistingKeys, 3, 1)) + .extracting(OrganizationDto::getUuid, OrganizationDto::getKey) + .containsExactly(tuple("uuid1", "key-1")); + assertThat(underTest.selectByQuery(dbSession, allExistingKeys, 4, 1)) + .extracting(OrganizationDto::getUuid, OrganizationDto::getKey) + .containsExactly(tuple("uuid3", "key-3")); + assertThat(underTest.selectByQuery(dbSession, allExistingKeys, 5, 1)) + .isEmpty(); + + assertThat(underTest.selectByQuery(dbSession, allExistingKeys, 0, 5)) + .extracting(OrganizationDto::getUuid) + .containsExactly("uuid4", "uuid5", "uuid2", "uuid1", "uuid3"); + assertThat(underTest.selectByQuery(dbSession, allExistingKeys, 5, 5)) + .isEmpty(); + assertThat(underTest.selectByQuery(dbSession, allExistingKeys, 0, 3)) + .extracting(OrganizationDto::getUuid) + .containsExactly("uuid4", "uuid5", "uuid2"); + assertThat(underTest.selectByQuery(dbSession, allExistingKeys, 3, 3)) + .extracting(OrganizationDto::getUuid) + .containsExactly("uuid1", "uuid3"); + } + + private static OrganizationQuery newQueryWithKeys(String... keys) { + return newOrganizationQueryBuilder().setKeys(Arrays.asList(keys)).build(); + } + + @Test public void update_fails_with_NPE_if_OrganizationDto_is_null() { expectDtoCanNotBeNull(); |