return falseSqlValue;
}
+ @Override
+ public String getSqlFromDual() {
+ return "";
+ }
+
@Override
public final String getValidationQuery() {
return validationQuery;
*/
String getFalseSqlValue();
+ String getSqlFromDual();
+
/**
* Query used to validate the jdbc connection.
*
public boolean supportsMigration() {
return true;
}
+
+ @Override
+ public String getSqlFromDual() {
+ return "from dual";
+ }
}
public List<String> getConnectionInitStatements() {
return INIT_STATEMENTS;
}
+
+ @Override
+ public String getSqlFromDual() {
+ return "from dual";
+ }
}
public class H2Test {
- H2 dialect = new H2();
+ private H2 underTest = new H2();
@Test
public void matchesJdbcURL() {
- assertThat(dialect.matchesJdbcURL("jdbc:h2:foo")).isTrue();
- assertThat(dialect.matchesJdbcURL("jdbc:hsql:foo")).isFalse();
+ assertThat(underTest.matchesJdbcURL("jdbc:h2:foo")).isTrue();
+ assertThat(underTest.matchesJdbcURL("jdbc:hsql:foo")).isFalse();
}
@Test
public void testBooleanSqlValues() {
- assertThat(dialect.getTrueSqlValue()).isEqualTo("true");
- assertThat(dialect.getFalseSqlValue()).isEqualTo("false");
+ assertThat(underTest.getTrueSqlValue()).isEqualTo("true");
+ assertThat(underTest.getFalseSqlValue()).isEqualTo("false");
}
@Test
public void should_configure() {
- assertThat(dialect.getId()).isEqualTo("h2");
- assertThat(dialect.getDefaultDriverClassName()).isEqualTo("org.h2.Driver");
- assertThat(dialect.getValidationQuery()).isEqualTo("SELECT 1");
+ assertThat(underTest.getId()).isEqualTo("h2");
+ assertThat(underTest.getDefaultDriverClassName()).isEqualTo("org.h2.Driver");
+ assertThat(underTest.getValidationQuery()).isEqualTo("SELECT 1");
}
@Test
public void testFetchSizeForScrolling() {
- assertThat(dialect.getScrollDefaultFetchSize()).isEqualTo(200);
+ assertThat(underTest.getScrollDefaultFetchSize()).isEqualTo(200);
}
@Test
public void h2_does_not_supportMigration() {
- assertThat(dialect.supportsMigration()).isFalse();
+ assertThat(underTest.supportsMigration()).isFalse();
+ }
+
+ @Test
+ public void getSqlFromDual() {
+ assertThat(underTest.getSqlFromDual()).isEqualTo("");
}
}
public class MsSqlTest {
- private MsSql msSql = new MsSql();
+ private MsSql underTest = new MsSql();
@Test
public void matchesJdbcURL() {
- assertThat(msSql.matchesJdbcURL("jdbc:sqlserver://localhost:1433;databasename=sonar")).isTrue();
+ assertThat(underTest.matchesJdbcURL("jdbc:sqlserver://localhost:1433;databasename=sonar")).isTrue();
- assertThat(msSql.matchesJdbcURL("jdbc:hsql:foo")).isFalse();
- assertThat(msSql.matchesJdbcURL("jdbc:mysql:foo")).isFalse();
+ assertThat(underTest.matchesJdbcURL("jdbc:hsql:foo")).isFalse();
+ assertThat(underTest.matchesJdbcURL("jdbc:mysql:foo")).isFalse();
}
@Test
public void testBooleanSqlValues() {
- assertThat(msSql.getTrueSqlValue()).isEqualTo("1");
- assertThat(msSql.getFalseSqlValue()).isEqualTo("0");
+ assertThat(underTest.getTrueSqlValue()).isEqualTo("1");
+ assertThat(underTest.getFalseSqlValue()).isEqualTo("0");
}
@Test
public void should_configure() {
- assertThat(msSql.getId()).isEqualTo("mssql");
- assertThat(msSql.getDefaultDriverClassName()).isEqualTo("com.microsoft.sqlserver.jdbc.SQLServerDriver");
- assertThat(msSql.getValidationQuery()).isEqualTo("SELECT 1");
+ assertThat(underTest.getId()).isEqualTo("mssql");
+ assertThat(underTest.getDefaultDriverClassName()).isEqualTo("com.microsoft.sqlserver.jdbc.SQLServerDriver");
+ assertThat(underTest.getValidationQuery()).isEqualTo("SELECT 1");
}
@Test
public void do_not_support_jtds_since_5_2() {
- assertThat(msSql.matchesJdbcURL("jdbc:jtds:sqlserver://localhost;databaseName=SONAR;SelectMethod=Cursor")).isFalse();
+ assertThat(underTest.matchesJdbcURL("jdbc:jtds:sqlserver://localhost;databaseName=SONAR;SelectMethod=Cursor")).isFalse();
}
@Test
public void msSql_does_supportMigration() {
- assertThat(msSql.supportsMigration()).isTrue();
+ assertThat(underTest.supportsMigration()).isTrue();
+ }
+
+ @Test
+ public void getSqlFromDual() {
+ assertThat(underTest.getSqlFromDual()).isEqualTo("");
}
}
public class MySqlTest {
- private MySql mySql = new MySql();
+ private MySql underTest = new MySql();
@Test
public void matchesJdbcURL() {
- assertThat(mySql.matchesJdbcURL("jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8")).isTrue();
- assertThat(mySql.matchesJdbcURL("JDBC:MYSQL://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8")).isTrue();
+ assertThat(underTest.matchesJdbcURL("jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8")).isTrue();
+ assertThat(underTest.matchesJdbcURL("JDBC:MYSQL://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8")).isTrue();
- assertThat(mySql.matchesJdbcURL("jdbc:hsql:foo")).isFalse();
- assertThat(mySql.matchesJdbcURL("jdbc:oracle:foo")).isFalse();
+ assertThat(underTest.matchesJdbcURL("jdbc:hsql:foo")).isFalse();
+ assertThat(underTest.matchesJdbcURL("jdbc:oracle:foo")).isFalse();
}
@Test
public void testBooleanSqlValues() {
- assertThat(mySql.getTrueSqlValue()).isEqualTo("true");
- assertThat(mySql.getFalseSqlValue()).isEqualTo("false");
+ assertThat(underTest.getTrueSqlValue()).isEqualTo("true");
+ assertThat(underTest.getFalseSqlValue()).isEqualTo("false");
}
@Test
public void should_configure() {
- assertThat(mySql.getId()).isEqualTo("mysql");
- assertThat(mySql.getDefaultDriverClassName()).isEqualTo("com.mysql.jdbc.Driver");
- assertThat(mySql.getValidationQuery()).isEqualTo("SELECT 1");
+ assertThat(underTest.getId()).isEqualTo("mysql");
+ assertThat(underTest.getDefaultDriverClassName()).isEqualTo("com.mysql.jdbc.Driver");
+ assertThat(underTest.getValidationQuery()).isEqualTo("SELECT 1");
}
@Test
public void testFetchSizeForScrolling() {
- assertThat(mySql.getScrollDefaultFetchSize()).isEqualTo(Integer.MIN_VALUE);
- assertThat(mySql.getScrollSingleRowFetchSize()).isEqualTo(Integer.MIN_VALUE);
+ assertThat(underTest.getScrollDefaultFetchSize()).isEqualTo(Integer.MIN_VALUE);
+ assertThat(underTest.getScrollSingleRowFetchSize()).isEqualTo(Integer.MIN_VALUE);
}
@Test
public void mysql_does_supportMigration() {
- assertThat(mySql.supportsMigration()).isTrue();
+ assertThat(underTest.supportsMigration()).isTrue();
+ }
+
+ @Test
+ public void getSqlFromDual() {
+ assertThat(underTest.getSqlFromDual()).isEqualTo("from dual");
}
}
public void oracle_does_supportMigration() {
assertThat(underTest.supportsMigration()).isTrue();
}
+
+ @Test
+ public void getSqlFromDual() {
+ assertThat(underTest.getSqlFromDual()).isEqualTo("from dual");
+ }
}
public class PostgreSqlTest {
- PostgreSql dialect = new PostgreSql();
+ private PostgreSql underTest = new PostgreSql();
@Test
public void matchesJdbcURL() {
- assertThat(dialect.matchesJdbcURL("jdbc:postgresql://localhost/sonar")).isTrue();
- assertThat(dialect.matchesJdbcURL("jdbc:hsql:foo")).isFalse();
+ assertThat(underTest.matchesJdbcURL("jdbc:postgresql://localhost/sonar")).isTrue();
+ assertThat(underTest.matchesJdbcURL("jdbc:hsql:foo")).isFalse();
}
@Test
public void should_set_connection_properties() {
- assertThat(dialect.getConnectionInitStatements()).isEqualTo(PostgreSql.INIT_STATEMENTS);
+ assertThat(underTest.getConnectionInitStatements()).isEqualTo(PostgreSql.INIT_STATEMENTS);
}
@Test
public void testBooleanSqlValues() {
- assertThat(dialect.getTrueSqlValue()).isEqualTo("true");
- assertThat(dialect.getFalseSqlValue()).isEqualTo("false");
+ assertThat(underTest.getTrueSqlValue()).isEqualTo("true");
+ assertThat(underTest.getFalseSqlValue()).isEqualTo("false");
}
@Test
public void should_configure() {
- assertThat(dialect.getId()).isEqualTo("postgresql");
- assertThat(dialect.getDefaultDriverClassName()).isEqualTo("org.postgresql.Driver");
- assertThat(dialect.getValidationQuery()).isEqualTo("SELECT 1");
+ assertThat(underTest.getId()).isEqualTo("postgresql");
+ assertThat(underTest.getDefaultDriverClassName()).isEqualTo("org.postgresql.Driver");
+ assertThat(underTest.getValidationQuery()).isEqualTo("SELECT 1");
}
@Test
public void testFetchSizeForScrolling() {
- assertThat(dialect.getScrollDefaultFetchSize()).isEqualTo(200);
+ assertThat(underTest.getScrollDefaultFetchSize()).isEqualTo(200);
}
@Test
public void postgres_does_supportMigration() {
- assertThat(dialect.supportsMigration()).isTrue();
+ assertThat(underTest.supportsMigration()).isTrue();
+ }
+
+ @Test
+ public void getSqlFromDual() {
+ assertThat(underTest.getSqlFromDual()).isEqualTo("");
}
}
this.conf.setDatabaseId(dialect.getId());
this.conf.getVariables().setProperty("_true", dialect.getTrueSqlValue());
this.conf.getVariables().setProperty("_false", dialect.getFalseSqlValue());
+ this.conf.getVariables().setProperty("_from_dual", dialect.getSqlFromDual());
this.conf.getVariables().setProperty("_scrollFetchSize", String.valueOf(dialect.getScrollDefaultFetchSize()));
this.conf.setLocalCacheScope(LocalCacheScope.STATEMENT);
}
return getMapper(dbSession).countTeamsByProjects();
}
+ public List<KeyLongValue> countTeamsByNclocRanges(DbSession dbSession) {
+ return getMapper(dbSession).countTeamsByNclocRanges();
+ }
+
public List<OrganizationDto> selectByQuery(DbSession dbSession, OrganizationQuery organizationQuery, Pagination pagination) {
requireNonNull(organizationQuery, "organizationQuery can't be null");
return getMapper(dbSession).selectByQuery(organizationQuery, pagination);
List<KeyLongValue> countTeamsByProjects();
+ List<KeyLongValue> countTeamsByNclocRanges();
+
List<OrganizationDto> selectByQuery(@Param("query") OrganizationQuery organizationQuery,
@Param("pagination") Pagination pagination);
</sql>
<select id="countTeamsByMembers" resultType="org.sonar.db.KeyLongValue">
- select range as "key", count(1) as "value"
+ select kee as "key", sum(val) as "value"
from (
- select case
- when nb = 0 then '0'
- when nb = 1 then '1'
- when nb >= 2 and nb <= 4 then '2-4'
- when nb >= 5 and nb <= 9 then '5-9'
- when nb >= 10 and nb <= 24 then '10-24'
- else '25+'
- end as range
+ select '0' as kee, 0 as val ${_from_dual}
+ union
+ select '1' as kee, 0 as val ${_from_dual}
+ union
+ select '2-4' as kee, 0 as val ${_from_dual}
+ union
+ select '5-9' as kee, 0 as val ${_from_dual}
+ union
+ select '10-24' as kee, 0 as val ${_from_dual}
+ union
+ select '+25' as kee, 0 as val ${_from_dual}
+ union
+ select kee, count(1) as val
from (
- select o.uuid, count(om.user_id) as nb
- from organizations o
- left join organization_members om on om.organization_uuid = o.uuid
- where not exists(
- select 1
- from users u
- where u.organization_uuid = o.uuid
- and u.active = ${_true}
- )
- group by o.uuid
- ) alias1
- ) alias2
- group by range
+ select case
+ when nb = 0 then '0'
+ when nb = 1 then '1'
+ when nb >= 2 and nb <= 4 then '2-4'
+ when nb >= 5 and nb <= 9 then '5-9'
+ when nb >= 10 and nb <= 24 then '10-24'
+ else '+25'
+ end as kee
+ from (
+ select o.uuid, count(om.user_id) as nb
+ from organizations o
+ left join organization_members om on om.organization_uuid = o.uuid
+ where not exists(
+ select 1
+ from users u
+ where u.organization_uuid = o.uuid
+ and u.active = ${_true}
+ )
+ group by o.uuid
+ ) alias1
+ ) alias2
+ group by kee
+ ) alias3
+ group by kee
</select>
<select id="countTeamsByProjects" resultType="org.sonar.db.KeyLongValue">
- select range as "key", count(1) as "value"
+ select kee as "key", sum(val) as "value"
from (
- select case
- when nb = 0 then '0'
- when nb = 1 then '1'
- when nb >= 2 and nb <= 4 then '2-4'
- when nb >= 5 and nb <= 9 then '5-9'
- when nb >= 10 and nb <= 24 then '10-24'
- else '25+'
- end as range
+ select '0' as kee, 0 as val ${_from_dual}
+ union
+ select '1' as kee, 0 as val ${_from_dual}
+ union
+ select '2-4' as kee, 0 as val ${_from_dual}
+ union
+ select '5-9' as kee, 0 as val ${_from_dual}
+ union
+ select '10-24' as kee, 0 as val ${_from_dual}
+ union
+ select '+25' as kee, 0 as val ${_from_dual}
+ union
+ select kee, count(1) as val
from (
- select o.uuid, count(p.uuid) as nb
- from organizations o
- left join projects p on p.organization_uuid = o.uuid
- where not exists(
- select 1
- from users u
- where u.organization_uuid = o.uuid
- and u.active = ${_true}
- )
- group by o.uuid
- ) alias1
- ) alias2
- group by range
+ select case
+ when nb = 0 then '0'
+ when nb = 1 then '1'
+ when nb >= 2 and nb <= 4 then '2-4'
+ when nb >= 5 and nb <= 9 then '5-9'
+ when nb >= 10 and nb <= 24 then '10-24'
+ else '+25'
+ end as kee
+ from (
+ select o.uuid, count(p.uuid) as nb
+ from organizations o
+ left join projects p on p.organization_uuid = o.uuid
+ where not exists(
+ select 1
+ from users u
+ where u.organization_uuid = o.uuid
+ and u.active = ${_true}
+ )
+ group by o.uuid
+ ) alias1
+ ) alias2
+ group by kee
+ ) alias3
+ group by kee
+ </select>
+
+ <select id="countTeamsByNclocRanges" resultType="org.sonar.db.KeyLongValue">
+ select kee as "key", sum(val) as "value"
+ from (
+ select '100K' as kee, 0 as val ${_from_dual}
+ union
+ select '500K' as kee, 0 as val ${_from_dual}
+ union
+ select '1M' as kee, 0 as val ${_from_dual}
+ union
+ select '2M' as kee, 0 as val ${_from_dual}
+ union
+ select '5M' as kee, 0 as val ${_from_dual}
+ union
+ select '10M' as kee, 0 as val ${_from_dual}
+ union
+ select '20M' as kee, 0 as val ${_from_dual}
+ union
+ select '50M' as kee, 0 as val ${_from_dual}
+ union
+ select '+50M' as kee, 0 as val ${_from_dual}
+ union
+ select kee, count(1) as val
+ from (
+ select case
+ when locs <= 100000 then '100K'
+ when locs > 100000 and locs <= 500000 then '500K'
+ when locs > 500000 and locs <= 1000000 then '1M'
+ when locs > 1000000 and locs <= 2000000 then '2M'
+ when locs > 2000000 and locs <= 5000000 then '5M'
+ when locs > 5000000 and locs <= 10000000 then '10M'
+ when locs > 10000000 and locs <= 20000000 then '20M'
+ when locs > 20000000 and locs <= 50000000 then '50M'
+ else '+50M'
+ end as kee
+ from (
+ select p.organization_uuid as orgUuid, max(lm.value) as locs
+ from live_measures lm
+ inner join metrics m on m.id = lm.metric_id
+ inner join projects p on p.uuid = lm.component_uuid
+ inner join project_branches b on b.uuid = p.uuid
+ where
+ m.name = 'ncloc'
+ and p.enabled = ${_true}
+ and p.scope = 'PRJ'
+ and p.qualifier = 'TRK'
+ and p.copy_component_uuid is null
+ and b.branch_type = 'LONG'
+ and b.key_type = 'BRANCH'
+ -- team orgs
+ and not exists(
+ select 1
+ from users u
+ where u.organization_uuid = p.organization_uuid
+ and u.active = ${_true}
+ )
+ group by p.organization_uuid
+ ) alias1
+ ) alias2
+ group by kee
+ ) alias3
+ group by kee
+
</select>
<select id="selectByPermission" parameterType="map" resultType="Organization">
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.apache.ibatis.exceptions.PersistenceException;
-import org.assertj.core.groups.Tuple;
import org.assertj.core.util.Lists;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.dialect.Dialect;
import org.sonar.db.dialect.Oracle;
+import org.sonar.db.metric.MetricDto;
import org.sonar.db.qualitygate.QGateWithOrgDto;
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.GroupTesting;
}
@Test
- public void countTeamsByMembers() {
- assertThat(underTest.countTeamsByMembers(dbSession)).isEmpty();
+ public void countTeamsByMembers_on_zero_orgs() {
+ assertThat(underTest.countTeamsByMembers(dbSession))
+ .extracting(KeyLongValue::getKey, KeyLongValue::getValue)
+ .containsExactlyInAnyOrder(
+ tuple("0", 0L),
+ tuple("1", 0L),
+ tuple("2-4", 0L),
+ tuple("5-9", 0L),
+ tuple("10-24", 0L),
+ tuple("+25", 0L));
+ }
+ @Test
+ public void countTeamsByMembers() {
UserDto user1 = db.users().insertUser();
UserDto user2 = db.users().insertUser();
UserDto user3 = db.users().insertUser();
OrganizationDto org2 = db.organizations().insert();
db.organizations().addMember(org2, user1);
OrganizationDto org3 = db.organizations().insert();
- db.organizations().addMember(org3, user1, user2, user3);
+ db.organizations().addMember(org3, user1, user2);
assertThat(underTest.countTeamsByMembers(dbSession))
.extracting(KeyLongValue::getKey, KeyLongValue::getValue)
- .containsExactlyInAnyOrder(Tuple.tuple("1", 1L), Tuple.tuple("2-4", 2L));
+ .containsExactlyInAnyOrder(
+ tuple("0", 0L),
+ tuple("1", 1L),
+ tuple("2-4", 2L),
+ tuple("5-9", 0L),
+ tuple("10-24", 0L),
+ tuple("+25", 0L));
+ }
+ @Test
+ public void countTeamsByProjects_on_zero_projects() {
+ assertThat(underTest.countTeamsByProjects(dbSession))
+ .extracting(KeyLongValue::getKey, KeyLongValue::getValue)
+ .containsExactlyInAnyOrder(
+ tuple("0", 0L),
+ tuple("1", 0L),
+ tuple("2-4", 0L),
+ tuple("5-9", 0L),
+ tuple("10-24", 0L),
+ tuple("+25", 0L));
}
@Test
public void countTeamsByProjects() {
- assertThat(underTest.countTeamsByProjects(dbSession)).isEmpty();
-
OrganizationDto org1 = db.organizations().insert();
db.components().insertPrivateProject(org1);
OrganizationDto org2 = db.organizations().insert();
assertThat(underTest.countTeamsByProjects(dbSession))
.extracting(KeyLongValue::getKey, KeyLongValue::getValue)
- .containsExactlyInAnyOrder(Tuple.tuple("1", 1L), Tuple.tuple("2-4", 2L));
+ .containsExactlyInAnyOrder(
+ tuple("0", 0L),
+ tuple("1", 1L),
+ tuple("2-4", 2L),
+ tuple("5-9", 0L),
+ tuple("10-24", 0L),
+ tuple("+25", 0L));
+ }
+ @Test
+ public void countTeamsByNclocRanges() {
+ MetricDto ncloc = db.measures().insertMetric(m -> m.setKey(CoreMetrics.NCLOC_KEY));
+
+ OrganizationDto org1 = db.organizations().insert();
+ // project with highest ncloc in non-main branch
+ ComponentDto project1 = db.components().insertMainBranch(org1);
+ ComponentDto project1Branch = db.components().insertProjectBranch(project1);
+ db.measures().insertLiveMeasure(project1, ncloc, m -> m.setValue(1_000.0));
+ db.measures().insertLiveMeasure(project1Branch, ncloc, m -> m.setValue(110_000.0));
+ // project with only main branch
+ ComponentDto project2 = db.components().insertMainBranch(org1);
+ db.measures().insertLiveMeasure(project2, ncloc, m -> m.setValue(400_000.0));
+
+ OrganizationDto org2 = db.organizations().insert();
+ // project with highest ncloc in main branch
+ ComponentDto project3 = db.components().insertMainBranch(org2);
+ ComponentDto project3Branch = db.components().insertProjectBranch(project3);
+ db.measures().insertLiveMeasure(project3, ncloc, m -> m.setValue(5_800_000.0));
+ db.measures().insertLiveMeasure(project3Branch, ncloc, m -> m.setValue(25_000.0));
+
+ assertThat(underTest.countTeamsByNclocRanges(dbSession))
+ .extracting(KeyLongValue::getKey, KeyLongValue::getValue)
+ .containsExactlyInAnyOrder(
+ tuple("100K", 0L),
+ tuple("500K", 1L),
+ tuple("1M", 0L),
+ tuple("2M", 0L),
+ tuple("5M", 0L),
+ tuple("10M", 1L),
+ tuple("20M", 0L),
+ tuple("50M", 0L),
+ tuple("+50M", 0L));
+ }
+
+ @Test
+ public void countTeamsByNclocRanges_on_zero_orgs() {
+ assertThat(underTest.countTeamsByNclocRanges(dbSession))
+ .extracting(KeyLongValue::getKey, KeyLongValue::getValue)
+ .containsExactlyInAnyOrder(
+ tuple("100K", 0L),
+ tuple("500K", 0L),
+ tuple("1M", 0L),
+ tuple("2M", 0L),
+ tuple("5M", 0L),
+ tuple("10M", 0L),
+ tuple("20M", 0L),
+ tuple("50M", 0L),
+ tuple("+50M", 0L));
}
private void expectDtoCanNotBeNull() {