aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-db-dao
diff options
context:
space:
mode:
authorEric Hartmann <hartmann.eric@gmail.com>2017-06-19 16:41:19 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2017-07-05 21:02:58 +0200
commit884e73d80752e779949284176173028f5feb0100 (patch)
treee341f05bb80751f4056a7615d360b6fc9dd7d32e /server/sonar-db-dao
parente964104ca94fdd7b975dedbbe8b15eb578b41f53 (diff)
downloadsonarqube-884e73d80752e779949284176173028f5feb0100.tar.gz
sonarqube-884e73d80752e779949284176173028f5feb0100.zip
MMF-935 experiment ES resilience of user creation
Diffstat (limited to 'server/sonar-db-dao')
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java2
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java7
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java2
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueDao.java79
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueDto.java72
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueMapper.java33
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/es/package-info.java24
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDao.java3
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java6
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java42
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDto.java4
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/user/UserMapper.java11
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/es/EsQueueMapper.xml67
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserMapper.xml104
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java2
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/es/EsQueueDaoTest.java129
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/user/RootFlagAssertions.java4
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java135
18 files changed, 599 insertions, 127 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
index d6ad5559e52..9ee4a9586cf 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
@@ -35,6 +35,7 @@ import org.sonar.db.duplication.DuplicationDao;
import org.sonar.db.event.EventDao;
import org.sonar.db.issue.IssueChangeDao;
import org.sonar.db.issue.IssueDao;
+import org.sonar.db.es.EsQueueDao;
import org.sonar.db.loadedtemplate.LoadedTemplateDao;
import org.sonar.db.measure.MeasureDao;
import org.sonar.db.measure.custom.CustomMeasureDao;
@@ -86,6 +87,7 @@ public class DaoModule extends Module {
CustomMeasureDao.class,
DefaultQProfileDao.class,
DuplicationDao.class,
+ EsQueueDao.class,
EventDao.class,
FileSourceDao.class,
GroupDao.class,
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
index f2eb34c6bb1..6eb7c664a25 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
@@ -34,6 +34,7 @@ import org.sonar.db.duplication.DuplicationDao;
import org.sonar.db.event.EventDao;
import org.sonar.db.issue.IssueChangeDao;
import org.sonar.db.issue.IssueDao;
+import org.sonar.db.es.EsQueueDao;
import org.sonar.db.loadedtemplate.LoadedTemplateDao;
import org.sonar.db.measure.MeasureDao;
import org.sonar.db.measure.custom.CustomMeasureDao;
@@ -118,6 +119,7 @@ public class DbClient {
private final UserPermissionDao userPermissionDao;
private final WebhookDeliveryDao webhookDeliveryDao;
private final DefaultQProfileDao defaultQProfileDao;
+ private final EsQueueDao esQueueDao;
public DbClient(Database database, MyBatis myBatis, Dao... daos) {
this.database = database;
@@ -173,6 +175,7 @@ public class DbClient {
userPermissionDao = getDao(map, UserPermissionDao.class);
webhookDeliveryDao = getDao(map, WebhookDeliveryDao.class);
defaultQProfileDao = getDao(map, DefaultQProfileDao.class);
+ esQueueDao = getDao(map, EsQueueDao.class);
}
public DbSession openSession(boolean batch) {
@@ -367,6 +370,10 @@ public class DbClient {
return defaultQProfileDao;
}
+ public EsQueueDao esQueueDao() {
+ return esQueueDao;
+ }
+
protected <K extends Dao> K getDao(Map<Class, Dao> map, Class<K> clazz) {
return (K) map.get(clazz);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
index e99aec847ea..044086a79b3 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
@@ -55,6 +55,7 @@ import org.sonar.db.issue.IssueChangeDto;
import org.sonar.db.issue.IssueChangeMapper;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.issue.IssueMapper;
+import org.sonar.db.es.EsQueueMapper;
import org.sonar.db.loadedtemplate.LoadedTemplateDto;
import org.sonar.db.loadedtemplate.LoadedTemplateMapper;
import org.sonar.db.measure.MeasureDto;
@@ -197,6 +198,7 @@ public class MyBatis implements Startable {
CustomMeasureMapper.class,
DefaultQProfileMapper.class,
DuplicationMapper.class,
+ EsQueueMapper.class,
EventMapper.class,
FileSourceMapper.class,
GroupMapper.class,
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueDao.java
new file mode 100644
index 00000000000..c47e087047d
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueDao.java
@@ -0,0 +1,79 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.db.es;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+
+import static java.util.Collections.singletonList;
+import static org.sonar.core.util.stream.MoreCollectors.toArrayList;
+import static org.sonar.db.DatabaseUtils.executeLargeUpdates;
+
+public class EsQueueDao implements Dao {
+
+ private final System2 system2;
+ private final UuidFactory uuidFactory;
+
+ public EsQueueDao(System2 system2, UuidFactory uuidFactory) {
+ this.system2 = system2;
+ this.uuidFactory = uuidFactory;
+ }
+
+ public EsQueueDto insert(DbSession dbSession, EsQueueDto item) {
+ insert(dbSession, singletonList(item));
+ return item;
+ }
+
+ public Collection<EsQueueDto> insert(DbSession dbSession, Collection<EsQueueDto> items) {
+ long now = system2.now();
+ EsQueueMapper mapper = mapper(dbSession);
+ items.forEach(item -> {
+ item.setUuid(uuidFactory.create());
+ mapper.insert(item, now);
+ });
+ return items;
+ }
+
+ public void delete(DbSession dbSession, EsQueueDto item) {
+ delete(dbSession, singletonList(item));
+ }
+
+ public void delete(DbSession dbSession, Collection<EsQueueDto> items) {
+ EsQueueMapper mapper = mapper(dbSession);
+ List<String> uuids = items.stream()
+ .map(EsQueueDto::getUuid)
+ .filter(Objects::nonNull)
+ .collect(toArrayList(items.size()));
+ executeLargeUpdates(uuids, mapper::delete);
+ }
+
+ public Collection<EsQueueDto> selectForRecovery(DbSession dbSession, long beforeDate, long limit) {
+ return mapper(dbSession).selectForRecovery(beforeDate, limit);
+ }
+
+ private static EsQueueMapper mapper(DbSession dbSession) {
+ return dbSession.getMapper(EsQueueMapper.class);
+ }
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueDto.java
new file mode 100644
index 00000000000..feb3148fa57
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueDto.java
@@ -0,0 +1,72 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.db.es;
+
+public final class EsQueueDto {
+
+ public enum Type {
+ USER
+ }
+
+ private String uuid;
+ private Type docType;
+ private String docUuid;
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ EsQueueDto setUuid(String uuid) {
+ this.uuid = uuid;
+ return this;
+ }
+
+ public Type getDocType() {
+ return docType;
+ }
+
+ private EsQueueDto setDocType(Type t) {
+ this.docType = t;
+ return this;
+ }
+
+ public String getDocUuid() {
+ return docUuid;
+ }
+
+ private EsQueueDto setDocUuid(String s) {
+ this.docUuid = s;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("EsQueueDto{");
+ sb.append("uuid='").append(uuid).append('\'');
+ sb.append(", docType=").append(docType);
+ sb.append(", docUuid='").append(docUuid).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public static EsQueueDto create(Type docType, String docUuid) {
+ return new EsQueueDto().setDocType(docType).setDocUuid(docUuid);
+ }
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueMapper.java
new file mode 100644
index 00000000000..04837587182
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/es/EsQueueMapper.java
@@ -0,0 +1,33 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.db.es;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+
+public interface EsQueueMapper {
+
+ void insert(@Param("dto") EsQueueDto dto, @Param("now") long now);
+
+ void delete(@Param("uuids") List<String> uuids);
+
+ Collection<EsQueueDto> selectForRecovery(@Param("beforeDate") long beforeDate, @Param("limit") long limit);
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/es/package-info.java b/server/sonar-db-dao/src/main/java/org/sonar/db/es/package-info.java
new file mode 100644
index 00000000000..5b01ba2c8f2
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/es/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.db.es;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDao.java
index abc23c06245..4b0c91bcf32 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDao.java
@@ -20,6 +20,7 @@
package org.sonar.db.organization;
+import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -70,7 +71,7 @@ public class OrganizationMemberDao implements Dao {
*
* @param loginOrganizationConsumer {@link BiConsumer}<String,String> (login, organization uuid)
*/
- public void selectForUserIndexing(DbSession dbSession, List<String> logins, BiConsumer<String, String> loginOrganizationConsumer) {
+ public void selectForUserIndexing(DbSession dbSession, Collection<String> logins, BiConsumer<String, String> loginOrganizationConsumer) {
executeLargeInputsWithoutOutput(logins, list -> mapper(dbSession).selectForIndexing(list)
.forEach(row -> loginOrganizationConsumer.accept(row.get("login"), row.get("organizationUuid"))));
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java
index b0156a8c79a..966b5a564b0 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java
@@ -33,12 +33,12 @@ import javax.annotation.Nullable;
import org.sonar.api.resources.Scopes;
import org.sonar.api.utils.System2;
import org.sonar.db.Dao;
-import org.sonar.db.DatabaseUtils;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
import org.sonar.db.WildcardPosition;
import static com.google.common.base.Preconditions.checkArgument;
+import static org.apache.commons.lang.StringUtils.repeat;
import static org.sonar.db.DaoDatabaseUtils.buildLikeValue;
import static org.sonar.db.DatabaseUtils.executeLargeInputs;
import static org.sonar.db.DatabaseUtils.executeLargeInputsWithoutOutput;
@@ -89,7 +89,7 @@ public class PropertiesDao implements Dao {
String sql = "SELECT count(1) FROM properties pp " +
"left outer join projects pj on pp.resource_id = pj.id " +
"where pp.user_id is not null and (pp.resource_id is null or pj.uuid=?) " +
- "and (" + DatabaseUtils.repeatCondition("pp.prop_key like ?", dispatcherKeys.size(), "or") + ")";
+ "and (" + repeat("pp.prop_key like ?", " or ", dispatcherKeys.size()) + ")";
PreparedStatement res = connection.prepareStatement(sql);
res.setString(1, projectUuid);
int index = 2;
@@ -282,7 +282,7 @@ public class PropertiesDao implements Dao {
executeLargeInputsWithoutOutput(ids, list -> getMapper(dbSession).deleteByIds(list));
}
- public void deleteByKeyAndValue(DbSession dbSession, String key, String value){
+ public void deleteByKeyAndValue(DbSession dbSession, String key, String value) {
getMapper(dbSession).deleteByKeyAndValue(key, value);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java
index ecc767b006f..ef7c49d07de 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java
@@ -19,13 +19,15 @@
*/
package org.sonar.db.user;
-import com.google.common.base.Function;
-import com.google.common.base.Predicates;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.sonar.api.user.UserQuery;
@@ -34,8 +36,8 @@ import org.sonar.db.Dao;
import org.sonar.db.DbSession;
import org.sonar.db.RowNotFoundException;
-import static com.google.common.collect.FluentIterable.from;
import static org.sonar.db.DatabaseUtils.executeLargeInputs;
+import static org.sonar.db.DatabaseUtils.executeLargeInputsWithoutOutput;
public class UserDao implements Dao {
@@ -82,7 +84,10 @@ public class UserDao implements Dao {
*/
public List<UserDto> selectByOrderedLogins(DbSession session, Collection<String> logins) {
List<UserDto> unordered = selectByLogins(session, logins);
- return from(logins).transform(new LoginToUser(unordered)).filter(Predicates.notNull()).toList();
+ return logins.stream()
+ .map(new LoginToUser(unordered))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
}
public List<UserDto> selectUsers(DbSession dbSession, UserQuery query) {
@@ -94,12 +99,17 @@ public class UserDao implements Dao {
}
public UserDto insert(DbSession session, UserDto dto) {
- mapper(session).insert(dto);
+ long now = system2.now();
+ mapper(session).insert(dto, now);
+ dto.setCreatedAt(now);
+ dto.setUpdatedAt(now);
return dto;
}
public UserDto update(DbSession session, UserDto dto) {
- mapper(session).update(dto);
+ long now = system2.now();
+ mapper(session).update(dto, now);
+ dto.setUpdatedAt(now);
return dto;
}
@@ -107,8 +117,8 @@ public class UserDao implements Dao {
mapper(session).setRoot(login, root, system2.now());
}
- public void deactivateUserById(DbSession dbSession, int userId) {
- mapper(dbSession).deactivateUser(userId, system2.now());
+ public void deactivateUser(DbSession dbSession, UserDto user) {
+ mapper(dbSession).deactivateUser(user.getLogin(), system2.now());
}
@CheckForNull
@@ -140,6 +150,22 @@ public class UserDao implements Dao {
return mapper(dbSession).countByEmail(email.toLowerCase(Locale.ENGLISH)) > 0;
}
+ public void scrollByLogins(DbSession dbSession, Collection<String> logins, Consumer<UserDto> consumer) {
+ UserMapper mapper = mapper(dbSession);
+
+ executeLargeInputsWithoutOutput(logins,
+ pageOfLogins -> mapper
+ .selectByLogins(pageOfLogins)
+ .forEach(consumer));
+ }
+
+ public void scrollAll(DbSession dbSession, Consumer<UserDto> consumer) {
+ mapper(dbSession).scrollAll(context -> {
+ UserDto user = (UserDto) context.getResultObject();
+ consumer.accept(user);
+ });
+ }
+
private static UserMapper mapper(DbSession session) {
return session.getMapper(UserMapper.class);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDto.java
index e85f6ed8785..fc3dd43df6f 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDto.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDto.java
@@ -189,7 +189,7 @@ public class UserDto {
return createdAt;
}
- public UserDto setCreatedAt(Long createdAt) {
+ UserDto setCreatedAt(long createdAt) {
this.createdAt = createdAt;
return this;
}
@@ -198,7 +198,7 @@ public class UserDto {
return updatedAt;
}
- public UserDto setUpdatedAt(Long updatedAt) {
+ UserDto setUpdatedAt(long updatedAt) {
this.updatedAt = updatedAt;
return this;
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserMapper.java
index 17c8cc0bbec..e2938d4a776 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserMapper.java
@@ -22,6 +22,7 @@ package org.sonar.db.user;
import java.util.List;
import javax.annotation.CheckForNull;
import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.session.ResultHandler;
import org.sonar.api.user.UserQuery;
public interface UserMapper {
@@ -51,6 +52,8 @@ public interface UserMapper {
List<UserDto> selectByIds(@Param("ids") List<Integer> ids);
+ void scrollAll(ResultHandler handler);
+
long countByEmail(String email);
/**
@@ -58,14 +61,12 @@ public interface UserMapper {
*/
long countRootUsersButLogin(@Param("login") String login);
- void insert(UserDto userDto);
+ void insert(@Param("user") UserDto userDto, @Param("now") long now);
- void update(UserDto userDto);
+ void update(@Param("user") UserDto userDto, @Param("now") long now);
void setRoot(@Param("login") String login, @Param("root") boolean root, @Param("now") long now);
- void deleteOrganisationMembership(int userId);
-
- void deactivateUser(@Param("id") int userId, @Param("now") long now);
+ void deactivateUser(@Param("login") String login, @Param("now") long now);
}
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/es/EsQueueMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/es/EsQueueMapper.xml
new file mode 100644
index 00000000000..08b3761380c
--- /dev/null
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/es/EsQueueMapper.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.db.es.EsQueueMapper">
+
+ <sql id="esQueueColumns">
+ uuid,
+ doc_type as docType,
+ doc_uuid as docUuid,
+ created_at as createdAt
+ </sql>
+
+ <insert id="insert" parameterType="map" useGeneratedKeys="false">
+ insert into es_queue (
+ uuid,
+ doc_type,
+ doc_uuid,
+ created_at
+ ) values (
+ #{dto.uuid, jdbcType=VARCHAR},
+ #{dto.docType, jdbcType=VARCHAR},
+ #{dto.docUuid, jdbcType=VARCHAR},
+ #{now, jdbcType=BIGINT}
+ )
+ </insert>
+
+ <delete id="delete" parameterType="string">
+ delete from es_queue
+ where uuid in
+ <foreach item="uuid" collection="uuids" open="(" separator="," close=")">
+ #{uuid, jdbcType=VARCHAR}
+ </foreach>
+ </delete>
+
+ <select id="selectForRecovery" parameterType="map" resultType="org.sonar.db.es.EsQueueDto">
+ select <include refid="esQueueColumns" />
+ from es_queue
+ where
+ created_at &lt;= #{beforeDate, jdbcType=BIGINT}
+ order by created_at desc
+ limit #{limit, jdbcType=INTEGER}
+ </select>
+
+ <select id="selectForRecovery" parameterType="map" resultType="org.sonar.db.es.EsQueueDto" databaseId="oracle">
+ select * from (
+ select rownum as rn, t.* from (
+ select <include refid="esQueueColumns" />
+ from es_queue
+ where
+ created_at &lt;= #{beforeDate, jdbcType=BIGINT}
+ order by created_at desc
+ ) t
+ ) t
+ where
+ t.rn &lt;= #{limit, jdbcType=INTEGER}
+ </select>
+
+ <select id="selectForRecovery" parameterType="map" resultType="org.sonar.db.es.EsQueueDto" databaseId="mssql">
+ select top(#{limit, jdbcType=INTEGER}) <include refid="esQueueColumns" />
+ from es_queue
+ where
+ created_at &lt;= #{beforeDate, jdbcType=BIGINT}
+ order by created_at desc
+ </select>
+
+</mapper>
+
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserMapper.xml
index ef9d08398df..9dddabd501d 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserMapper.xml
@@ -62,6 +62,11 @@
</foreach>
</select>
+ <select id="scrollAll" resultType="User" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
+ select <include refid="userColumns"/>
+ from users u
+ </select>
+
<select id="selectByIds" parameterType="string" resultType="User">
SELECT
<include refid="userColumns"/>
@@ -116,35 +121,31 @@
and u.login &lt;&gt; #{login}
</select>
- <delete id="deleteOrganisationMembership" parameterType="int">
- DELETE FROM organization_members WHERE user_id=#{id,jdbcType=BIGINT}
- </delete>
-
<update id="deactivateUser" parameterType="map">
- UPDATE users SET
- active=${_false},
- email=null,
- scm_accounts=null,
- external_identity=null,
- external_identity_provider=null,
- salt=null,
- crypted_password=null,
- updated_at=#{now,jdbcType=BIGINT}
- WHERE
- id=#{id,jdbcType=INTEGER}
+ update users set
+ active = ${_false},
+ email = null,
+ scm_accounts = null,
+ external_identity = null,
+ external_identity_provider = null,
+ salt = null,
+ crypted_password = null,
+ updated_at = #{now, jdbcType=BIGINT}
+ where
+ login = #{login, jdbcType=VARCHAR}
</update>
<update id="setRoot">
update users set
- is_root = #{root,jdbcType=BOOLEAN},
- updated_at=#{now,jdbcType=BIGINT}
+ is_root = #{root, jdbcType=BOOLEAN},
+ updated_at = #{now, jdbcType=BIGINT}
where
- login = #{login,jdbcType=VARCHAR}
+ login = #{login, jdbcType=VARCHAR}
and active = ${_true}
</update>
- <insert id="insert" parameterType="User" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
- INSERT INTO users (
+ <insert id="insert" parameterType="map" keyColumn="id" useGeneratedKeys="true" keyProperty="user.id">
+ insert into users (
login,
name,
email,
@@ -159,40 +160,39 @@
onboarded,
created_at,
updated_at
- )
- VALUES (
- #{login,jdbcType=VARCHAR},
- #{name,jdbcType=VARCHAR},
- #{email,jdbcType=VARCHAR},
- #{active,jdbcType=BOOLEAN},
- #{scmAccounts,jdbcType=VARCHAR},
- #{externalIdentity,jdbcType=VARCHAR},
- #{externalIdentityProvider,jdbcType=VARCHAR},
- #{local,jdbcType=BOOLEAN},
- #{salt,jdbcType=VARCHAR},
- #{cryptedPassword,jdbcType=VARCHAR},
- #{root,jdbcType=BOOLEAN},
- #{onboarded,jdbcType=BOOLEAN},
- #{createdAt,jdbcType=BIGINT},
- #{updatedAt,jdbcType=BIGINT}
+ ) values (
+ #{user.login,jdbcType=VARCHAR},
+ #{user.name,jdbcType=VARCHAR},
+ #{user.email,jdbcType=VARCHAR},
+ #{user.active,jdbcType=BOOLEAN},
+ #{user.scmAccounts,jdbcType=VARCHAR},
+ #{user.externalIdentity,jdbcType=VARCHAR},
+ #{user.externalIdentityProvider,jdbcType=VARCHAR},
+ #{user.local,jdbcType=BOOLEAN},
+ #{user.salt,jdbcType=VARCHAR},
+ #{user.cryptedPassword,jdbcType=VARCHAR},
+ #{user.root,jdbcType=BOOLEAN},
+ #{user.onboarded,jdbcType=BOOLEAN},
+ #{now,jdbcType=BIGINT},
+ #{now,jdbcType=BIGINT}
)
</insert>
- <insert id="update" parameterType="User" useGeneratedKeys="false">
- UPDATE users set
- name=#{name,jdbcType=VARCHAR},
- email=#{email,jdbcType=VARCHAR},
- active=#{active,jdbcType=BOOLEAN},
- scm_accounts=#{scmAccounts,jdbcType=VARCHAR},
- external_identity=#{externalIdentity,jdbcType=VARCHAR},
- external_identity_provider=#{externalIdentityProvider,jdbcType=VARCHAR},
- user_local=#{local,jdbcType=BOOLEAN},
- onboarded=#{onboarded,jdbcType=BOOLEAN},
- salt=#{salt,jdbcType=VARCHAR},
- crypted_password=#{cryptedPassword,jdbcType=BIGINT},
- updated_at=#{updatedAt,jdbcType=BIGINT}
- WHERE
- login = #{login,jdbcType=VARCHAR}
- </insert>
+ <update id="update" parameterType="map">
+ update users set
+ name = #{user.name, jdbcType=VARCHAR},
+ email = #{user.email, jdbcType=VARCHAR},
+ active = #{user.active, jdbcType=BOOLEAN},
+ scm_accounts = #{user.scmAccounts, jdbcType=VARCHAR},
+ external_identity = #{user.externalIdentity, jdbcType=VARCHAR},
+ external_identity_provider = #{user.externalIdentityProvider, jdbcType=VARCHAR},
+ user_local = #{user.local, jdbcType=BOOLEAN},
+ onboarded = #{user.onboarded, jdbcType=BOOLEAN},
+ salt = #{user.salt, jdbcType=VARCHAR},
+ crypted_password = #{user.cryptedPassword, jdbcType=BIGINT},
+ updated_at = #{now, jdbcType=BIGINT}
+ where
+ login = #{user.login, jdbcType=VARCHAR}
+ </update>
</mapper>
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java
index 4e2c7cb812e..2ffc454abd9 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/DaoModuleTest.java
@@ -29,6 +29,6 @@ public class DaoModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new DaoModule().configure(container);
- assertThat(container.size()).isEqualTo(2 + 46);
+ assertThat(container.size()).isEqualTo(2 + 47);
}
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/es/EsQueueDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/es/EsQueueDaoTest.java
new file mode 100644
index 00000000000..373a88b2013
--- /dev/null
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/es/EsQueueDaoTest.java
@@ -0,0 +1,129 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.db.es;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.stream.IntStream;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class EsQueueDaoTest {
+
+ private static final int LIMIT = 10;
+ private static TestSystem2 system2 = new TestSystem2().setNow(1_000);
+
+ @Rule
+ public DbTester dbTester = DbTester.create(system2);
+
+ private DbSession dbSession = dbTester.getSession();
+ private EsQueueDao underTest = dbTester.getDbClient().esQueueDao();
+
+ @Test
+ public void insert_data() {
+ int nbOfInsert = 10 + new Random().nextInt(20);
+ List<EsQueueDto> esQueueDtos = new ArrayList<>();
+ IntStream.rangeClosed(1, nbOfInsert).forEach(
+ i -> esQueueDtos.add(EsQueueDto.create(EsQueueDto.Type.USER, UuidFactoryFast.getInstance().create()))
+ );
+ underTest.insert(dbSession, esQueueDtos);
+
+ assertThat(dbTester.countSql(dbSession, "select count(*) from es_queue")).isEqualTo(nbOfInsert);
+ }
+
+ @Test
+ public void delete_unknown_EsQueueDto_does_not_throw_exception() {
+ int nbOfInsert = 10 + new Random().nextInt(20);
+ List<EsQueueDto> esQueueDtos = new ArrayList<>();
+ IntStream.rangeClosed(1, nbOfInsert).forEach(
+ i -> esQueueDtos.add(EsQueueDto.create(EsQueueDto.Type.USER, UuidFactoryFast.getInstance().create()))
+ );
+ underTest.insert(dbSession, esQueueDtos);
+
+ underTest.delete(dbSession, EsQueueDto.create(EsQueueDto.Type.USER, UuidFactoryFast.getInstance().create()));
+
+ assertThat(dbTester.countSql(dbSession, "select count(*) from es_queue")).isEqualTo(nbOfInsert);
+ }
+
+ @Test
+ public void delete_EsQueueDto_does_not_throw_exception() {
+ int nbOfInsert = 10 + new Random().nextInt(20);
+ List<EsQueueDto> esQueueDtos = new ArrayList<>();
+ IntStream.rangeClosed(1, nbOfInsert).forEach(
+ i -> esQueueDtos.add(EsQueueDto.create(EsQueueDto.Type.USER, UuidFactoryFast.getInstance().create()))
+ );
+ underTest.insert(dbSession, esQueueDtos);
+ assertThat(dbTester.countSql(dbSession, "select count(*) from es_queue")).isEqualTo(nbOfInsert);
+
+ underTest.delete(dbSession, esQueueDtos);
+
+ assertThat(dbTester.countSql(dbSession, "select count(*) from es_queue")).isEqualTo(0);
+ }
+
+ @Test
+ public void selectForRecovery_must_return_limit_when_there_are_more_rows() {
+ system2.setNow(1_000L);
+ EsQueueDto i1 = underTest.insert(dbSession, EsQueueDto.create(EsQueueDto.Type.USER, UuidFactoryFast.getInstance().create()));
+ system2.setNow(1_001L);
+ EsQueueDto i2 = underTest.insert(dbSession, EsQueueDto.create(EsQueueDto.Type.USER, UuidFactoryFast.getInstance().create()));
+ system2.setNow(1_002L);
+ EsQueueDto i3 = underTest.insert(dbSession, EsQueueDto.create(EsQueueDto.Type.USER, UuidFactoryFast.getInstance().create()));
+
+ assertThat(underTest.selectForRecovery(dbSession, 2_000, 1))
+ .extracting(EsQueueDto::getUuid)
+ .containsExactly(i3.getUuid());
+
+ assertThat(underTest.selectForRecovery(dbSession, 2_000, 2))
+ .extracting(EsQueueDto::getUuid)
+ .containsExactly(i3.getUuid(), i2.getUuid());
+
+ assertThat(underTest.selectForRecovery(dbSession, 2_000, 10))
+ .extracting(EsQueueDto::getUuid)
+ .containsExactly(i3.getUuid(), i2.getUuid(), i1.getUuid());
+ }
+
+ @Test
+ public void selectForRecovery_returns_ordered_rows_created_before_date() {
+ system2.setNow(1_000L);
+ EsQueueDto i1 = underTest.insert(dbSession, EsQueueDto.create(EsQueueDto.Type.USER, UuidFactoryFast.getInstance().create()));
+ system2.setNow(1_001L);
+ EsQueueDto i2 = underTest.insert(dbSession, EsQueueDto.create(EsQueueDto.Type.USER, UuidFactoryFast.getInstance().create()));
+ system2.setNow(1_002L);
+ EsQueueDto i3 = underTest.insert(dbSession, EsQueueDto.create(EsQueueDto.Type.USER, UuidFactoryFast.getInstance().create()));
+
+ assertThat(underTest.selectForRecovery(dbSession, 999, LIMIT)).hasSize(0);
+ assertThat(underTest.selectForRecovery(dbSession, 1_000, LIMIT))
+ .extracting(EsQueueDto::getUuid)
+ .containsExactly(i1.getUuid());
+ assertThat(underTest.selectForRecovery(dbSession, 1_001, LIMIT))
+ .extracting(EsQueueDto::getUuid)
+ .containsExactly(i2.getUuid(), i1.getUuid());
+ assertThat(underTest.selectForRecovery(dbSession, 2_000, LIMIT))
+ .extracting(EsQueueDto::getUuid)
+ .containsExactly(i3.getUuid(), i2.getUuid(), i1.getUuid());
+ }
+}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/user/RootFlagAssertions.java b/server/sonar-db-dao/src/test/java/org/sonar/db/user/RootFlagAssertions.java
index 42c78876717..0885c813365 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/user/RootFlagAssertions.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/user/RootFlagAssertions.java
@@ -31,10 +31,6 @@ public class RootFlagAssertions {
this.db = db;
}
- public void verifyUnchanged(UserDto user) {
- verify(user, user.isRoot(), user.getUpdatedAt());
- }
-
public void verify(UserDto userDto, boolean root, long updatedAt) {
Map<String, Object> row = db.selectFirst("select is_root as \"isRoot\", updated_at as \"updatedAt\" from users where login = '" + userDto.getLogin() + "'");
Object isRoot = row.get("isRoot");
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java
index ef3d48316b9..773c0eb1fa4 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.db.user;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.junit.Before;
@@ -28,6 +29,7 @@ import org.junit.rules.ExpectedException;
import org.sonar.api.user.UserQuery;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
+import org.sonar.db.DatabaseUtils;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
@@ -37,6 +39,7 @@ import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -58,7 +61,7 @@ public class UserDaoTest {
private UserDao underTest = db.getDbClient().userDao();
@Before
- public void setUp() throws Exception {
+ public void setUp() {
when(system2.now()).thenReturn(NOW);
}
@@ -337,23 +340,19 @@ public class UserDaoTest {
assertThat(user.getExternalIdentityProvider()).isEqualTo("github");
assertThat(user.isLocal()).isTrue();
assertThat(user.isRoot()).isFalse();
- assertThat(user.getCreatedAt()).isEqualTo(date);
- assertThat(user.getUpdatedAt()).isEqualTo(date);
}
@Test
public void update_user() {
- UserDto existingUser = db.users().insertUser(user -> user
+ UserDto user = db.users().insertUser(u -> u
.setLogin("john")
.setName("John")
.setEmail("jo@hn.com")
- .setCreatedAt(1418215735482L)
- .setUpdatedAt(1418215735482L)
.setActive(true)
.setLocal(true)
.setOnboarded(false));
- UserDto userDto = new UserDto()
+ UserDto userUpdate = new UserDto()
.setId(1)
.setLogin("john")
.setName("John Doo")
@@ -365,38 +364,34 @@ public class UserDaoTest {
.setCryptedPassword("abcde")
.setExternalIdentity("johngithub")
.setExternalIdentityProvider("github")
- .setLocal(false)
- .setUpdatedAt(1500000000000L);
- underTest.update(db.getSession(), userDto);
- db.getSession().commit();
-
- UserDto user = underTest.selectUserById(db.getSession(), existingUser.getId());
- assertThat(user).isNotNull();
- assertThat(user.getId()).isEqualTo(existingUser.getId());
- assertThat(user.getLogin()).isEqualTo("john");
- assertThat(user.getName()).isEqualTo("John Doo");
- assertThat(user.getEmail()).isEqualTo("jodoo@hn.com");
- assertThat(user.isActive()).isFalse();
- assertThat(user.isOnboarded()).isTrue();
- assertThat(user.getScmAccounts()).isEqualTo(",jo.hn,john2,johndoo,");
- assertThat(user.getSalt()).isEqualTo("12345");
- assertThat(user.getCryptedPassword()).isEqualTo("abcde");
- assertThat(user.getExternalIdentity()).isEqualTo("johngithub");
- assertThat(user.getExternalIdentityProvider()).isEqualTo("github");
- assertThat(user.isLocal()).isFalse();
- assertThat(user.isRoot()).isFalse();
- assertThat(user.getCreatedAt()).isEqualTo(1418215735482L);
- assertThat(user.getUpdatedAt()).isEqualTo(1500000000000L);
- }
-
- @Test
- public void deactivate_user() throws Exception {
- UserDto user = newActiveUser();
+ .setLocal(false);
+ underTest.update(db.getSession(), userUpdate);
+
+ UserDto reloaded = underTest.selectByLogin(db.getSession(), user.getLogin());
+ assertThat(reloaded).isNotNull();
+ assertThat(reloaded.getId()).isEqualTo(user.getId());
+ assertThat(reloaded.getLogin()).isEqualTo(user.getLogin());
+ assertThat(reloaded.getName()).isEqualTo("John Doo");
+ assertThat(reloaded.getEmail()).isEqualTo("jodoo@hn.com");
+ assertThat(reloaded.isActive()).isFalse();
+ assertThat(reloaded.isOnboarded()).isTrue();
+ assertThat(reloaded.getScmAccounts()).isEqualTo(",jo.hn,john2,johndoo,");
+ assertThat(reloaded.getSalt()).isEqualTo("12345");
+ assertThat(reloaded.getCryptedPassword()).isEqualTo("abcde");
+ assertThat(reloaded.getExternalIdentity()).isEqualTo("johngithub");
+ assertThat(reloaded.getExternalIdentityProvider()).isEqualTo("github");
+ assertThat(reloaded.isLocal()).isFalse();
+ assertThat(reloaded.isRoot()).isFalse();
+ }
+
+ @Test
+ public void deactivate_user() {
+ UserDto user = insertActiveUser();
insertUserGroup(user);
- UserDto otherUser = newActiveUser();
+ UserDto otherUser = insertActiveUser();
session.commit();
- underTest.deactivateUserById(session, user.getId());
+ underTest.deactivateUser(session, user);
UserDto userReloaded = underTest.selectUserById(session, user.getId());
assertThat(userReloaded.isActive()).isFalse();
@@ -413,7 +408,7 @@ public class UserDaoTest {
@Test
public void does_not_fail_to_deactivate_missing_user() {
- underTest.deactivateUserById(session, 123);
+ underTest.deactivateUser(session, UserTesting.newUserDto());
}
@Test
@@ -425,13 +420,11 @@ public class UserDaoTest {
.setActive(true)
.setScmAccounts("\nma\nmarius33\n")
.setSalt("79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365")
- .setCryptedPassword("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg")
- .setCreatedAt(1418215735482L)
- .setUpdatedAt(1418215735485L));
- UserDto user2 = db.users().insertUser(user -> user.setLogin("sbrandhof"));
+ .setCryptedPassword("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg"));
+ UserDto user2 = db.users().insertUser();
underTest.setRoot(session, user2.getLogin(), true);
- UserDto dto = underTest.selectOrFailByLogin(session, "marius");
+ UserDto dto = underTest.selectOrFailByLogin(session, user1.getLogin());
assertThat(dto.getId()).isEqualTo(user1.getId());
assertThat(dto.getLogin()).isEqualTo("marius");
assertThat(dto.getName()).isEqualTo("Marius");
@@ -441,10 +434,10 @@ public class UserDaoTest {
assertThat(dto.getSalt()).isEqualTo("79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365");
assertThat(dto.getCryptedPassword()).isEqualTo("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg");
assertThat(dto.isRoot()).isFalse();
- assertThat(dto.getCreatedAt()).isEqualTo(1418215735482L);
- assertThat(dto.getUpdatedAt()).isEqualTo(1418215735485L);
+ assertThat(dto.getCreatedAt()).isEqualTo(user1.getCreatedAt());
+ assertThat(dto.getUpdatedAt()).isEqualTo(user1.getUpdatedAt());
- dto = underTest.selectOrFailByLogin(session, "sbrandhof");
+ dto = underTest.selectOrFailByLogin(session, user2.getLogin());
assertThat(dto.isRoot()).isTrue();
}
@@ -490,8 +483,8 @@ public class UserDaoTest {
}
@Test
- public void exists_by_email() throws Exception {
- UserDto activeUser = newActiveUser();
+ public void exists_by_email() {
+ UserDto activeUser = insertActiveUser();
UserDto disableUser = insertUser(false);
assertThat(underTest.doesEmailExist(session, activeUser.getEmail())).isTrue();
@@ -507,8 +500,8 @@ public class UserDaoTest {
@Test
public void setRoot_set_root_flag_of_specified_user_to_specified_value_and_updates_udpateAt() {
- String login = newActiveUser().getLogin();
- UserDto otherUser = newActiveUser();
+ String login = insertActiveUser().getLogin();
+ UserDto otherUser = insertActiveUser();
assertThat(underTest.selectByLogin(session, login).isRoot()).isEqualTo(false);
assertThat(underTest.selectByLogin(session, otherUser.getLogin()).isRoot()).isEqualTo(false);
@@ -550,7 +543,7 @@ public class UserDaoTest {
assertThat(underTest.selectByLogin(session, nonRootInactiveUser).isRoot()).isFalse();
// create inactive root user
- UserDto rootUser = newActiveUser();
+ UserDto rootUser = insertActiveUser();
commit(() -> underTest.setRoot(session, rootUser.getLogin(), true));
rootUser.setActive(false);
commit(() -> underTest.update(session, rootUser));
@@ -562,12 +555,52 @@ public class UserDaoTest {
assertThat(underTest.selectByLogin(session, inactiveRootUser.getLogin()).isRoot()).isTrue();
}
+ @Test
+ public void scrollByLogins() {
+ UserDto u1 = insertUser(true);
+ UserDto u2 = insertUser(false);
+ UserDto u3 = insertUser(false);
+
+ List<UserDto> result = new ArrayList<>();
+ underTest.scrollByLogins(db.getSession(), asList(u2.getLogin(), u3.getLogin(), "does not exist"), result::add);
+
+ assertThat(result).extracting(UserDto::getLogin, UserDto::getName)
+ .containsExactlyInAnyOrder(tuple(u2.getLogin(), u2.getName()), tuple(u3.getLogin(), u3.getName()));
+ }
+
+ @Test
+ public void scrollByLogins_scrolls_by_pages_of_1000_logins() {
+ List<String> logins = new ArrayList<>();
+ for (int i = 0; i < DatabaseUtils.PARTITION_SIZE_FOR_ORACLE + 10; i++) {
+ logins.add(insertUser(true).getLogin());
+ }
+
+ List<UserDto> result = new ArrayList<>();
+ underTest.scrollByLogins(db.getSession(), logins, result::add);
+
+ assertThat(result)
+ .extracting(UserDto::getLogin)
+ .containsExactlyInAnyOrder(logins.toArray(new String[0]));
+ }
+
+ @Test
+ public void scrollAll() {
+ UserDto u1 = insertUser(true);
+ UserDto u2 = insertUser(false);
+
+ List<UserDto> result = new ArrayList<>();
+ underTest.scrollAll(db.getSession(), result::add);
+
+ assertThat(result).extracting(UserDto::getLogin, UserDto::getName)
+ .containsExactlyInAnyOrder(tuple(u1.getLogin(), u1.getName()), tuple(u2.getLogin(), u2.getName()));
+ }
+
private void commit(Runnable runnable) {
runnable.run();
session.commit();
}
- private UserDto newActiveUser() {
+ private UserDto insertActiveUser() {
return insertUser(true);
}