aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2022-02-13 23:34:25 -0800
committerAnton Tananaev <anton.tananaev@gmail.com>2022-02-13 23:34:25 -0800
commit1c73bae2e23242673e0a07cdbc2493700f134ceb (patch)
treed1105368628b5f64fabb657682df58f1641e4d54
parentde110b28ce8adb6ba875d88ede6e8f86dae4dd48 (diff)
downloadtrackermap-server-1c73bae2e23242673e0a07cdbc2493700f134ceb.tar.gz
trackermap-server-1c73bae2e23242673e0a07cdbc2493700f134ceb.tar.bz2
trackermap-server-1c73bae2e23242673e0a07cdbc2493700f134ceb.zip
New storage implementation
-rw-r--r--setup/default.xml30
-rw-r--r--src/main/java/org/traccar/MainEventHandler.java4
-rw-r--r--src/main/java/org/traccar/api/BaseObjectResource.java7
-rw-r--r--src/main/java/org/traccar/api/SecurityRequestFilter.java4
-rw-r--r--src/main/java/org/traccar/api/resource/AttributeResource.java9
-rw-r--r--src/main/java/org/traccar/api/resource/DeviceResource.java3
-rw-r--r--src/main/java/org/traccar/api/resource/EventResource.java6
-rw-r--r--src/main/java/org/traccar/api/resource/PasswordResource.java6
-rw-r--r--src/main/java/org/traccar/api/resource/PermissionsResource.java10
-rw-r--r--src/main/java/org/traccar/api/resource/PositionResource.java4
-rw-r--r--src/main/java/org/traccar/api/resource/ReportResource.java28
-rw-r--r--src/main/java/org/traccar/api/resource/ServerResource.java6
-rw-r--r--src/main/java/org/traccar/api/resource/SessionResource.java6
-rw-r--r--src/main/java/org/traccar/api/resource/StatisticsResource.java4
-rw-r--r--src/main/java/org/traccar/api/resource/UserResource.java3
-rw-r--r--src/main/java/org/traccar/database/BaseObjectManager.java10
-rw-r--r--src/main/java/org/traccar/database/ConnectionManager.java6
-rw-r--r--src/main/java/org/traccar/database/DataManager.java265
-rw-r--r--src/main/java/org/traccar/database/DeviceManager.java28
-rw-r--r--src/main/java/org/traccar/database/ExtendedObjectManager.java6
-rw-r--r--src/main/java/org/traccar/database/GroupsManager.java4
-rw-r--r--src/main/java/org/traccar/database/NotificationManager.java4
-rw-r--r--src/main/java/org/traccar/database/PermissionsManager.java10
-rw-r--r--src/main/java/org/traccar/database/SimpleObjectManager.java6
-rw-r--r--src/main/java/org/traccar/database/StatisticsManager.java4
-rw-r--r--src/main/java/org/traccar/database/UsersManager.java9
-rw-r--r--src/main/java/org/traccar/handler/FilterHandler.java4
-rw-r--r--src/main/java/org/traccar/model/Attribute.java3
-rw-r--r--src/main/java/org/traccar/model/Calendar.java2
-rw-r--r--src/main/java/org/traccar/model/Command.java8
-rw-r--r--src/main/java/org/traccar/model/Device.java7
-rw-r--r--src/main/java/org/traccar/model/Driver.java4
-rw-r--r--src/main/java/org/traccar/model/Event.java3
-rw-r--r--src/main/java/org/traccar/model/Geofence.java2
-rw-r--r--src/main/java/org/traccar/model/Group.java3
-rw-r--r--src/main/java/org/traccar/model/Maintenance.java3
-rw-r--r--src/main/java/org/traccar/model/Notification.java4
-rw-r--r--src/main/java/org/traccar/model/Order.java3
-rw-r--r--src/main/java/org/traccar/model/Position.java15
-rw-r--r--src/main/java/org/traccar/model/Server.java2
-rw-r--r--src/main/java/org/traccar/model/Statistics.java3
-rw-r--r--src/main/java/org/traccar/model/User.java2
-rw-r--r--src/main/java/org/traccar/reports/Events.java6
-rw-r--r--src/main/java/org/traccar/reports/Route.java6
-rw-r--r--src/main/java/org/traccar/reports/Stops.java8
-rw-r--r--src/main/java/org/traccar/reports/Summary.java8
-rw-r--r--src/main/java/org/traccar/reports/Trips.java8
-rw-r--r--src/main/java/org/traccar/storage/DatabaseStorage.java71
-rw-r--r--src/main/java/org/traccar/storage/QueryBuilder.java6
-rw-r--r--src/main/java/org/traccar/storage/Storage.java15
-rw-r--r--src/main/java/org/traccar/storage/query/Columns.java22
-rw-r--r--src/main/java/org/traccar/storage/query/Condition.java42
-rw-r--r--src/main/java/org/traccar/storage/query/Limit.java15
-rw-r--r--src/main/java/org/traccar/storage/query/Request.java22
-rw-r--r--src/test/java/org/traccar/database/DataManagerTest.java81
55 files changed, 420 insertions, 440 deletions
diff --git a/setup/default.xml b/setup/default.xml
index 0d8133627..a1ba5ca33 100644
--- a/setup/default.xml
+++ b/setup/default.xml
@@ -41,37 +41,7 @@
<entry key='commands.queueing'>true</entry>
<entry key='database.ignoreUnknown'>true</entry>
- <entry key='database.generateQueries'>true</entry>
<entry key='database.changelog'>./schema/changelog-master.xml</entry>
-
- <entry key='database.loginUser'>
- SELECT * FROM tc_users
- WHERE email = :email OR login = :email
- </entry>
-
- <entry key='database.selectPositions'>
- SELECT * FROM tc_positions WHERE deviceId = :deviceId AND fixTime BETWEEN :from AND :to ORDER BY fixTime
- </entry>
-
- <entry key='database.selectPrecedingPosition'>
- SELECT * FROM tc_positions WHERE deviceId = :deviceId AND fixTime &lt;= :time ORDER BY fixTime DESC LIMIT 1
- </entry>
-
- <entry key='database.selectLatestPositions'>
- SELECT tc_positions.* FROM tc_positions INNER JOIN tc_devices ON tc_positions.id = tc_devices.positionid;
- </entry>
-
- <entry key='database.updateLatestPosition'>
- UPDATE tc_devices SET positionId = :id WHERE id = :deviceId
- </entry>
-
- <entry key='database.selectEvents'>
- SELECT * FROM tc_events WHERE deviceId = :deviceId AND eventTime BETWEEN :from AND :to ORDER BY eventTime
- </entry>
-
- <entry key='database.selectStatistics'>
- SELECT * FROM tc_statistics WHERE captureTime BETWEEN :from AND :to ORDER BY captureTime
- </entry>
<entry key='gps103.port'>5001</entry>
<entry key='tk103.port'>5002</entry>
diff --git a/src/main/java/org/traccar/MainEventHandler.java b/src/main/java/org/traccar/MainEventHandler.java
index 4889f6a2e..a3f6f4105 100644
--- a/src/main/java/org/traccar/MainEventHandler.java
+++ b/src/main/java/org/traccar/MainEventHandler.java
@@ -27,8 +27,8 @@ import org.traccar.config.Keys;
import org.traccar.database.StatisticsManager;
import org.traccar.helper.DateUtil;
import org.traccar.model.Position;
+import org.traccar.storage.StorageException;
-import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
@@ -57,7 +57,7 @@ public class MainEventHandler extends ChannelInboundHandlerAdapter {
Position position = (Position) msg;
try {
Context.getDeviceManager().updateLatestPosition(position);
- } catch (SQLException error) {
+ } catch (StorageException error) {
LOGGER.warn("Failed to update device", error);
}
diff --git a/src/main/java/org/traccar/api/BaseObjectResource.java b/src/main/java/org/traccar/api/BaseObjectResource.java
index 71f3939cb..22756f62a 100644
--- a/src/main/java/org/traccar/api/BaseObjectResource.java
+++ b/src/main/java/org/traccar/api/BaseObjectResource.java
@@ -41,6 +41,7 @@ import org.traccar.model.Group;
import org.traccar.model.GroupedModel;
import org.traccar.model.ScheduledModel;
import org.traccar.model.User;
+import org.traccar.storage.StorageException;
public abstract class BaseObjectResource<T extends BaseModel> extends BaseResource {
@@ -87,7 +88,7 @@ public abstract class BaseObjectResource<T extends BaseModel> extends BaseResour
}
@POST
- public Response add(T entity) throws SQLException {
+ public Response add(T entity) throws StorageException {
Context.getPermissionsManager().checkReadonly(getUserId());
if (baseClass.equals(Device.class)) {
Context.getPermissionsManager().checkDeviceReadonly(getUserId());
@@ -120,7 +121,7 @@ public abstract class BaseObjectResource<T extends BaseModel> extends BaseResour
@Path("{id}")
@PUT
- public Response update(T entity) throws SQLException {
+ public Response update(T entity) throws StorageException {
Context.getPermissionsManager().checkReadonly(getUserId());
if (baseClass.equals(Device.class)) {
Context.getPermissionsManager().checkDeviceReadonly(getUserId());
@@ -150,7 +151,7 @@ public abstract class BaseObjectResource<T extends BaseModel> extends BaseResour
@Path("{id}")
@DELETE
- public Response remove(@PathParam("id") long id) throws SQLException {
+ public Response remove(@PathParam("id") long id) throws StorageException {
Context.getPermissionsManager().checkReadonly(getUserId());
if (baseClass.equals(Device.class)) {
Context.getPermissionsManager().checkDeviceReadonly(getUserId());
diff --git a/src/main/java/org/traccar/api/SecurityRequestFilter.java b/src/main/java/org/traccar/api/SecurityRequestFilter.java
index 33b6b37df..6b190be9f 100644
--- a/src/main/java/org/traccar/api/SecurityRequestFilter.java
+++ b/src/main/java/org/traccar/api/SecurityRequestFilter.java
@@ -23,6 +23,7 @@ import org.traccar.api.resource.SessionResource;
import org.traccar.database.StatisticsManager;
import org.traccar.helper.DataConverter;
import org.traccar.model.User;
+import org.traccar.storage.StorageException;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
@@ -34,7 +35,6 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
-import java.sql.SQLException;
public class SecurityRequestFilter implements ContainerRequestFilter {
@@ -82,7 +82,7 @@ public class SecurityRequestFilter implements ContainerRequestFilter {
Main.getInjector().getInstance(StatisticsManager.class).registerRequest(user.getId());
securityContext = new UserSecurityContext(new UserPrincipal(user.getId()));
}
- } catch (SQLException e) {
+ } catch (StorageException e) {
throw new WebApplicationException(e);
}
diff --git a/src/main/java/org/traccar/api/resource/AttributeResource.java b/src/main/java/org/traccar/api/resource/AttributeResource.java
index de69d871c..d2dc28903 100644
--- a/src/main/java/org/traccar/api/resource/AttributeResource.java
+++ b/src/main/java/org/traccar/api/resource/AttributeResource.java
@@ -16,8 +16,6 @@
*/
package org.traccar.api.resource;
-import java.sql.SQLException;
-
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
@@ -34,6 +32,7 @@ import org.traccar.api.ExtendedObjectResource;
import org.traccar.model.Attribute;
import org.traccar.model.Position;
import org.traccar.handler.ComputedAttributesHandler;
+import org.traccar.storage.StorageException;
@Path("attributes/computed")
@Produces(MediaType.APPLICATION_JSON)
@@ -75,21 +74,21 @@ public class AttributeResource extends ExtendedObjectResource<Attribute> {
}
@POST
- public Response add(Attribute entity) throws SQLException {
+ public Response add(Attribute entity) throws StorageException {
Context.getPermissionsManager().checkAdmin(getUserId());
return super.add(entity);
}
@Path("{id}")
@PUT
- public Response update(Attribute entity) throws SQLException {
+ public Response update(Attribute entity) throws StorageException {
Context.getPermissionsManager().checkAdmin(getUserId());
return super.update(entity);
}
@Path("{id}")
@DELETE
- public Response remove(@PathParam("id") long id) throws SQLException {
+ public Response remove(@PathParam("id") long id) throws StorageException {
Context.getPermissionsManager().checkAdmin(getUserId());
return super.remove(id);
}
diff --git a/src/main/java/org/traccar/api/resource/DeviceResource.java b/src/main/java/org/traccar/api/resource/DeviceResource.java
index 7006cdb84..9436b59f6 100644
--- a/src/main/java/org/traccar/api/resource/DeviceResource.java
+++ b/src/main/java/org/traccar/api/resource/DeviceResource.java
@@ -21,6 +21,7 @@ import org.traccar.database.DeviceManager;
import org.traccar.helper.LogAction;
import org.traccar.model.Device;
import org.traccar.model.DeviceAccumulators;
+import org.traccar.storage.StorageException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -87,7 +88,7 @@ public class DeviceResource extends BaseObjectResource<Device> {
@Path("{id}/accumulators")
@PUT
- public Response updateAccumulators(DeviceAccumulators entity) throws SQLException {
+ public Response updateAccumulators(DeviceAccumulators entity) throws StorageException {
if (!Context.getPermissionsManager().getUserAdmin(getUserId())) {
Context.getPermissionsManager().checkManager(getUserId());
Context.getPermissionsManager().checkPermission(Device.class, getUserId(), entity.getDeviceId());
diff --git a/src/main/java/org/traccar/api/resource/EventResource.java b/src/main/java/org/traccar/api/resource/EventResource.java
index 34e4a94ce..354d96e4f 100644
--- a/src/main/java/org/traccar/api/resource/EventResource.java
+++ b/src/main/java/org/traccar/api/resource/EventResource.java
@@ -15,8 +15,6 @@
*/
package org.traccar.api.resource;
-import java.sql.SQLException;
-
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@@ -31,16 +29,16 @@ import org.traccar.api.BaseResource;
import org.traccar.model.Event;
import org.traccar.model.Geofence;
import org.traccar.model.Maintenance;
+import org.traccar.storage.StorageException;
@Path("events")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
-
public class EventResource extends BaseResource {
@Path("{id}")
@GET
- public Event get(@PathParam("id") long id) throws SQLException {
+ public Event get(@PathParam("id") long id) throws StorageException {
Event event = Context.getDataManager().getObject(Event.class, id);
if (event == null) {
throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build());
diff --git a/src/main/java/org/traccar/api/resource/PasswordResource.java b/src/main/java/org/traccar/api/resource/PasswordResource.java
index 1868a6191..0642ff3cc 100644
--- a/src/main/java/org/traccar/api/resource/PasswordResource.java
+++ b/src/main/java/org/traccar/api/resource/PasswordResource.java
@@ -21,6 +21,7 @@ import org.traccar.api.BaseResource;
import org.traccar.model.User;
import org.traccar.notification.NotificationMessage;
import org.traccar.notification.TextTemplateFormatter;
+import org.traccar.storage.StorageException;
import javax.annotation.security.PermitAll;
import javax.mail.MessagingException;
@@ -31,7 +32,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-import java.sql.SQLException;
import java.util.UUID;
@Path("password")
@@ -44,7 +44,7 @@ public class PasswordResource extends BaseResource {
@Path("reset")
@PermitAll
@POST
- public Response reset(@FormParam("email") String email) throws SQLException, MessagingException {
+ public Response reset(@FormParam("email") String email) throws StorageException, MessagingException {
for (long userId : Context.getUsersManager().getAllItems()) {
User user = Context.getUsersManager().getById(userId);
if (email.equals(user.getEmail())) {
@@ -66,7 +66,7 @@ public class PasswordResource extends BaseResource {
@PermitAll
@POST
public Response update(
- @FormParam("token") String token, @FormParam("password") String password) throws SQLException {
+ @FormParam("token") String token, @FormParam("password") String password) throws StorageException {
for (long userId : Context.getUsersManager().getAllItems()) {
User user = Context.getUsersManager().getById(userId);
if (token.equals(user.getString(PASSWORD_RESET_TOKEN))) {
diff --git a/src/main/java/org/traccar/api/resource/PermissionsResource.java b/src/main/java/org/traccar/api/resource/PermissionsResource.java
index 54d3964b6..7def38919 100644
--- a/src/main/java/org/traccar/api/resource/PermissionsResource.java
+++ b/src/main/java/org/traccar/api/resource/PermissionsResource.java
@@ -16,7 +16,6 @@
*/
package org.traccar.api.resource;
-import java.sql.SQLException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
@@ -37,6 +36,7 @@ import org.traccar.helper.LogAction;
import org.traccar.model.Device;
import org.traccar.model.Permission;
import org.traccar.model.User;
+import org.traccar.storage.StorageException;
@Path("permissions")
@Produces(MediaType.APPLICATION_JSON)
@@ -71,7 +71,7 @@ public class PermissionsResource extends BaseResource {
@Path("bulk")
@POST
- public Response add(List<LinkedHashMap<String, Long>> entities) throws SQLException, ClassNotFoundException {
+ public Response add(List<LinkedHashMap<String, Long>> entities) throws StorageException, ClassNotFoundException {
Context.getPermissionsManager().checkReadonly(getUserId());
checkPermissionTypes(entities);
for (LinkedHashMap<String, Long> entity: entities) {
@@ -89,13 +89,13 @@ public class PermissionsResource extends BaseResource {
}
@POST
- public Response add(LinkedHashMap<String, Long> entity) throws SQLException, ClassNotFoundException {
+ public Response add(LinkedHashMap<String, Long> entity) throws StorageException, ClassNotFoundException {
return add(Collections.singletonList(entity));
}
@DELETE
@Path("bulk")
- public Response remove(List<LinkedHashMap<String, Long>> entities) throws SQLException, ClassNotFoundException {
+ public Response remove(List<LinkedHashMap<String, Long>> entities) throws StorageException, ClassNotFoundException {
Context.getPermissionsManager().checkReadonly(getUserId());
checkPermissionTypes(entities);
for (LinkedHashMap<String, Long> entity: entities) {
@@ -113,7 +113,7 @@ public class PermissionsResource extends BaseResource {
}
@DELETE
- public Response remove(LinkedHashMap<String, Long> entity) throws SQLException, ClassNotFoundException {
+ public Response remove(LinkedHashMap<String, Long> entity) throws StorageException, ClassNotFoundException {
return remove(Collections.singletonList(entity));
}
diff --git a/src/main/java/org/traccar/api/resource/PositionResource.java b/src/main/java/org/traccar/api/resource/PositionResource.java
index 53157197b..511032402 100644
--- a/src/main/java/org/traccar/api/resource/PositionResource.java
+++ b/src/main/java/org/traccar/api/resource/PositionResource.java
@@ -18,6 +18,7 @@ package org.traccar.api.resource;
import org.traccar.Context;
import org.traccar.api.BaseResource;
import org.traccar.model.Position;
+import org.traccar.storage.StorageException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -25,7 +26,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -41,7 +41,7 @@ public class PositionResource extends BaseResource {
public Collection<Position> getJson(
@QueryParam("deviceId") long deviceId, @QueryParam("id") List<Long> positionIds,
@QueryParam("from") Date from, @QueryParam("to") Date to)
- throws SQLException {
+ throws StorageException {
if (!positionIds.isEmpty()) {
ArrayList<Position> positions = new ArrayList<>();
for (Long positionId : positionIds) {
diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java
index 23ffaf54c..03df0d03a 100644
--- a/src/main/java/org/traccar/api/resource/ReportResource.java
+++ b/src/main/java/org/traccar/api/resource/ReportResource.java
@@ -18,7 +18,6 @@ package org.traccar.api.resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.sql.SQLException;
import java.util.Collection;
import java.util.Date;
import java.util.List;
@@ -51,6 +50,7 @@ import org.traccar.reports.model.SummaryReport;
import org.traccar.reports.model.TripReport;
import org.traccar.reports.Route;
import org.traccar.reports.Stops;
+import org.traccar.storage.StorageException;
@Path("reports")
@Produces(MediaType.APPLICATION_JSON)
@@ -63,11 +63,11 @@ public class ReportResource extends BaseResource {
private static final String CONTENT_DISPOSITION_VALUE_XLSX = "attachment; filename=report.xlsx";
private interface ReportExecutor {
- void execute(ByteArrayOutputStream stream) throws SQLException, IOException;
+ void execute(ByteArrayOutputStream stream) throws StorageException, IOException;
}
private Response executeReport(
- long userId, boolean mail, ReportExecutor executor) throws SQLException, IOException {
+ long userId, boolean mail, ReportExecutor executor) throws StorageException, IOException {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
if (mail) {
new Thread(() -> {
@@ -82,7 +82,7 @@ public class ReportResource extends BaseResource {
Context.getMailManager().sendMessage(
userId, "Report", "The report is in the attachment.", attachment);
- } catch (SQLException | IOException | MessagingException e) {
+ } catch (StorageException | IOException | MessagingException e) {
LOGGER.warn("Report failed", e);
}
}).start();
@@ -98,7 +98,7 @@ public class ReportResource extends BaseResource {
@GET
public Collection<Position> getRoute(
@QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds,
- @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException {
+ @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException {
Context.getPermissionsManager().checkDisableReports(getUserId());
LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds);
return Route.getObjects(getUserId(), deviceIds, groupIds, from, to);
@@ -110,7 +110,7 @@ public class ReportResource extends BaseResource {
public Response getRouteExcel(
@QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds,
@QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail)
- throws SQLException, IOException {
+ throws StorageException, IOException {
Context.getPermissionsManager().checkDisableReports(getUserId());
return executeReport(getUserId(), mail, stream -> {
LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds);
@@ -123,7 +123,7 @@ public class ReportResource extends BaseResource {
public Collection<Event> getEvents(
@QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds,
@QueryParam("type") final List<String> types,
- @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException {
+ @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException {
Context.getPermissionsManager().checkDisableReports(getUserId());
LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds);
return Events.getObjects(getUserId(), deviceIds, groupIds, types, from, to);
@@ -136,7 +136,7 @@ public class ReportResource extends BaseResource {
@QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds,
@QueryParam("type") final List<String> types,
@QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail)
- throws SQLException, IOException {
+ throws StorageException, IOException {
Context.getPermissionsManager().checkDisableReports(getUserId());
return executeReport(getUserId(), mail, stream -> {
LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds);
@@ -149,7 +149,7 @@ public class ReportResource extends BaseResource {
public Collection<SummaryReport> getSummary(
@QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds,
@QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily)
- throws SQLException {
+ throws StorageException {
Context.getPermissionsManager().checkDisableReports(getUserId());
LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds);
return Summary.getObjects(getUserId(), deviceIds, groupIds, from, to, daily);
@@ -162,7 +162,7 @@ public class ReportResource extends BaseResource {
@QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds,
@QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily,
@QueryParam("mail") boolean mail)
- throws SQLException, IOException {
+ throws StorageException, IOException {
Context.getPermissionsManager().checkDisableReports(getUserId());
return executeReport(getUserId(), mail, stream -> {
LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds);
@@ -175,7 +175,7 @@ public class ReportResource extends BaseResource {
@Produces(MediaType.APPLICATION_JSON)
public Collection<TripReport> getTrips(
@QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds,
- @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException {
+ @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException {
Context.getPermissionsManager().checkDisableReports(getUserId());
LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds);
return Trips.getObjects(getUserId(), deviceIds, groupIds, from, to);
@@ -187,7 +187,7 @@ public class ReportResource extends BaseResource {
public Response getTripsExcel(
@QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds,
@QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail)
- throws SQLException, IOException {
+ throws StorageException, IOException {
Context.getPermissionsManager().checkDisableReports(getUserId());
return executeReport(getUserId(), mail, stream -> {
LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds);
@@ -200,7 +200,7 @@ public class ReportResource extends BaseResource {
@Produces(MediaType.APPLICATION_JSON)
public Collection<StopReport> getStops(
@QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds,
- @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException {
+ @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException {
Context.getPermissionsManager().checkDisableReports(getUserId());
LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds);
return Stops.getObjects(getUserId(), deviceIds, groupIds, from, to);
@@ -212,7 +212,7 @@ public class ReportResource extends BaseResource {
public Response getStopsExcel(
@QueryParam("deviceId") final List<Long> deviceIds, @QueryParam("groupId") final List<Long> groupIds,
@QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail)
- throws SQLException, IOException {
+ throws StorageException, IOException {
Context.getPermissionsManager().checkDisableReports(getUserId());
return executeReport(getUserId(), mail, stream -> {
LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds);
diff --git a/src/main/java/org/traccar/api/resource/ServerResource.java b/src/main/java/org/traccar/api/resource/ServerResource.java
index 91488afff..8096c66fa 100644
--- a/src/main/java/org/traccar/api/resource/ServerResource.java
+++ b/src/main/java/org/traccar/api/resource/ServerResource.java
@@ -19,6 +19,7 @@ import org.traccar.Context;
import org.traccar.api.BaseResource;
import org.traccar.helper.LogAction;
import org.traccar.model.Server;
+import org.traccar.storage.StorageException;
import javax.annotation.security.PermitAll;
import javax.ws.rs.Consumes;
@@ -29,7 +30,6 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-import java.sql.SQLException;
@Path("server")
@Produces(MediaType.APPLICATION_JSON)
@@ -38,7 +38,7 @@ public class ServerResource extends BaseResource {
@PermitAll
@GET
- public Server get(@QueryParam("force") boolean force) throws SQLException {
+ public Server get(@QueryParam("force") boolean force) throws StorageException {
if (force) {
return Context.getDataManager().getServer();
} else {
@@ -47,7 +47,7 @@ public class ServerResource extends BaseResource {
}
@PUT
- public Response update(Server entity) throws SQLException {
+ public Response update(Server entity) throws StorageException {
Context.getPermissionsManager().checkAdmin(getUserId());
Context.getPermissionsManager().updateServer(entity);
LogAction.edit(getUserId(), entity);
diff --git a/src/main/java/org/traccar/api/resource/SessionResource.java b/src/main/java/org/traccar/api/resource/SessionResource.java
index 60ce5490a..8422e0b49 100644
--- a/src/main/java/org/traccar/api/resource/SessionResource.java
+++ b/src/main/java/org/traccar/api/resource/SessionResource.java
@@ -21,6 +21,7 @@ import org.traccar.helper.DataConverter;
import org.traccar.helper.ServletHelper;
import org.traccar.helper.LogAction;
import org.traccar.model.User;
+import org.traccar.storage.StorageException;
import javax.annotation.security.PermitAll;
import javax.servlet.http.Cookie;
@@ -40,7 +41,6 @@ import javax.ws.rs.core.Response;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
-import java.sql.SQLException;
@Path("session")
@Produces(MediaType.APPLICATION_JSON)
@@ -56,7 +56,7 @@ public class SessionResource extends BaseResource {
@PermitAll
@GET
- public User get(@QueryParam("token") String token) throws SQLException, UnsupportedEncodingException {
+ public User get(@QueryParam("token") String token) throws StorageException, UnsupportedEncodingException {
if (token != null) {
User user = Context.getUsersManager().getUserByToken(token);
@@ -107,7 +107,7 @@ public class SessionResource extends BaseResource {
@PermitAll
@POST
public User add(
- @FormParam("email") String email, @FormParam("password") String password) throws SQLException {
+ @FormParam("email") String email, @FormParam("password") String password) throws StorageException {
User user = Context.getPermissionsManager().login(email, password);
if (user != null) {
request.getSession().setAttribute(USER_ID_KEY, user.getId());
diff --git a/src/main/java/org/traccar/api/resource/StatisticsResource.java b/src/main/java/org/traccar/api/resource/StatisticsResource.java
index 58073e7d1..5c0734877 100644
--- a/src/main/java/org/traccar/api/resource/StatisticsResource.java
+++ b/src/main/java/org/traccar/api/resource/StatisticsResource.java
@@ -18,6 +18,7 @@ package org.traccar.api.resource;
import org.traccar.Context;
import org.traccar.api.BaseResource;
import org.traccar.model.Statistics;
+import org.traccar.storage.StorageException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -25,7 +26,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
-import java.sql.SQLException;
import java.util.Collection;
import java.util.Date;
@@ -36,7 +36,7 @@ public class StatisticsResource extends BaseResource {
@GET
public Collection<Statistics> get(
- @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException {
+ @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException {
Context.getPermissionsManager().checkAdmin(getUserId());
return Context.getDataManager().getStatistics(from, to);
}
diff --git a/src/main/java/org/traccar/api/resource/UserResource.java b/src/main/java/org/traccar/api/resource/UserResource.java
index d54cc2382..83bb8fd0b 100644
--- a/src/main/java/org/traccar/api/resource/UserResource.java
+++ b/src/main/java/org/traccar/api/resource/UserResource.java
@@ -22,6 +22,7 @@ import org.traccar.database.UsersManager;
import org.traccar.helper.LogAction;
import org.traccar.model.ManagedUser;
import org.traccar.model.User;
+import org.traccar.storage.StorageException;
import javax.annotation.security.PermitAll;
import javax.ws.rs.Consumes;
@@ -67,7 +68,7 @@ public class UserResource extends BaseObjectResource<User> {
@Override
@PermitAll
@POST
- public Response add(User entity) throws SQLException {
+ public Response add(User entity) throws StorageException {
if (!Context.getPermissionsManager().getUserAdmin(getUserId())) {
Context.getPermissionsManager().checkUserUpdate(getUserId(), new User(), entity);
if (Context.getPermissionsManager().getUserManager(getUserId())) {
diff --git a/src/main/java/org/traccar/database/BaseObjectManager.java b/src/main/java/org/traccar/database/BaseObjectManager.java
index be6310033..dd8b3bae4 100644
--- a/src/main/java/org/traccar/database/BaseObjectManager.java
+++ b/src/main/java/org/traccar/database/BaseObjectManager.java
@@ -16,7 +16,6 @@
*/
package org.traccar.database;
-import java.sql.SQLException;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
@@ -29,6 +28,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.traccar.model.BaseModel;
+import org.traccar.storage.StorageException;
public class BaseObjectManager<T extends BaseModel> {
@@ -102,7 +102,7 @@ public class BaseObjectManager<T extends BaseModel> {
removeCachedItem(cachedItemId);
}
}
- } catch (SQLException error) {
+ } catch (StorageException error) {
LOGGER.warn("Error refreshing items", error);
} finally {
writeUnlock();
@@ -119,7 +119,7 @@ public class BaseObjectManager<T extends BaseModel> {
}
}
- public void addItem(T item) throws SQLException {
+ public void addItem(T item) throws StorageException {
dataManager.addObject(item);
addNewItem(item);
}
@@ -133,7 +133,7 @@ public class BaseObjectManager<T extends BaseModel> {
}
}
- public void updateItem(T item) throws SQLException {
+ public void updateItem(T item) throws StorageException {
dataManager.updateObject(item);
updateCachedItem(item);
}
@@ -147,7 +147,7 @@ public class BaseObjectManager<T extends BaseModel> {
}
}
- public void removeItem(long itemId) throws SQLException {
+ public void removeItem(long itemId) throws StorageException {
BaseModel item = getById(itemId);
if (item != null) {
dataManager.removeObject(baseClass, itemId);
diff --git a/src/main/java/org/traccar/database/ConnectionManager.java b/src/main/java/org/traccar/database/ConnectionManager.java
index e12d44612..359061f00 100644
--- a/src/main/java/org/traccar/database/ConnectionManager.java
+++ b/src/main/java/org/traccar/database/ConnectionManager.java
@@ -30,9 +30,9 @@ import org.traccar.model.Device;
import org.traccar.model.DeviceState;
import org.traccar.model.Event;
import org.traccar.model.Position;
+import org.traccar.storage.StorageException;
import java.net.SocketAddress;
-import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -127,8 +127,8 @@ public class ConnectionManager {
try {
Context.getDeviceManager().updateDeviceStatus(device);
- } catch (SQLException error) {
- LOGGER.warn("Update device status error", error);
+ } catch (StorageException e) {
+ LOGGER.warn("Update device status error", e);
}
updateDevice(device);
diff --git a/src/main/java/org/traccar/database/DataManager.java b/src/main/java/org/traccar/database/DataManager.java
index 199167419..303b8e033 100644
--- a/src/main/java/org/traccar/database/DataManager.java
+++ b/src/main/java/org/traccar/database/DataManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2012 - 2022 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,15 +41,20 @@ import org.traccar.model.Group;
import org.traccar.model.Maintenance;
import org.traccar.model.ManagedUser;
import org.traccar.model.Notification;
-import org.traccar.model.Order;
import org.traccar.model.Permission;
import org.traccar.model.Position;
import org.traccar.model.Server;
import org.traccar.model.Statistics;
import org.traccar.model.User;
+import org.traccar.storage.DatabaseStorage;
import org.traccar.storage.QueryBuilder;
-import org.traccar.storage.QueryExtended;
-import org.traccar.storage.QueryIgnore;
+import org.traccar.storage.Storage;
+import org.traccar.storage.StorageException;
+import org.traccar.storage.query.Columns;
+import org.traccar.storage.query.Condition;
+import org.traccar.storage.query.Limit;
+import org.traccar.storage.query.Order;
+import org.traccar.storage.query.Request;
import javax.sql.DataSource;
import java.beans.Introspector;
@@ -57,11 +62,10 @@ import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.sql.SQLException;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.LinkedList;
+import java.util.List;
public class DataManager {
@@ -81,6 +85,8 @@ public class DataManager {
return dataSource;
}
+ private final Storage storage;
+
private boolean generateQueries;
private final boolean forceLdap;
@@ -92,6 +98,8 @@ public class DataManager {
initDatabase();
initDatabaseSchema();
+
+ storage = new DatabaseStorage(dataSource);
}
private void initDatabase() throws Exception {
@@ -134,58 +142,6 @@ public class DataManager {
dataSource = new HikariDataSource(hikariConfig);
}
- public static String constructObjectQuery(String action, Class<?> clazz, boolean extended) {
- switch (action) {
- case ACTION_INSERT:
- case ACTION_UPDATE:
- StringBuilder result = new StringBuilder();
- StringBuilder fields = new StringBuilder();
- StringBuilder values = new StringBuilder();
-
- Set<Method> methods = new HashSet<>(Arrays.asList(clazz.getMethods()));
- methods.removeAll(Arrays.asList(Object.class.getMethods()));
- methods.removeAll(Arrays.asList(BaseModel.class.getMethods()));
- for (Method method : methods) {
- boolean skip;
- if (extended) {
- skip = !method.isAnnotationPresent(QueryExtended.class);
- } else {
- skip = method.isAnnotationPresent(QueryIgnore.class)
- || method.isAnnotationPresent(QueryExtended.class) && !action.equals(ACTION_INSERT);
- }
- if (!skip && method.getName().startsWith("get") && method.getParameterTypes().length == 0) {
- String name = Introspector.decapitalize(method.getName().substring(3));
- if (action.equals(ACTION_INSERT)) {
- fields.append(name).append(", ");
- values.append(":").append(name).append(", ");
- } else {
- fields.append(name).append(" = :").append(name).append(", ");
- }
- }
- }
- fields.setLength(fields.length() - 2);
- if (action.equals(ACTION_INSERT)) {
- values.setLength(values.length() - 2);
- result.append("INSERT INTO ").append(getObjectsTableName(clazz)).append(" (");
- result.append(fields).append(") ");
- result.append("VALUES (").append(values).append(")");
- } else {
- result.append("UPDATE ").append(getObjectsTableName(clazz)).append(" SET ");
- result.append(fields);
- result.append(" WHERE id = :id");
- }
- return result.toString();
- case ACTION_SELECT_ALL:
- return "SELECT * FROM " + getObjectsTableName(clazz);
- case ACTION_SELECT:
- return "SELECT * FROM " + getObjectsTableName(clazz) + " WHERE id = :id";
- case ACTION_DELETE:
- return "DELETE FROM " + getObjectsTableName(clazz) + " WHERE id = :id";
- default:
- throw new IllegalArgumentException("Unknown action");
- }
- }
-
public static String constructPermissionQuery(String action, Class<?> owner, Class<?> property) {
switch (action) {
case ACTION_SELECT_ALL:
@@ -204,39 +160,6 @@ public class DataManager {
}
}
- private String getQuery(String key) {
- String query = config.getString(key);
- if (query == null) {
- LOGGER.info("Query not provided: " + key);
- }
- return query;
- }
-
- public String getQuery(String action, Class<?> clazz) {
- return getQuery(action, clazz, false);
- }
-
- public String getQuery(String action, Class<?> clazz, boolean extended) {
- String queryName;
- if (action.equals(ACTION_SELECT_ALL)) {
- queryName = "database.select" + clazz.getSimpleName() + "s";
- } else {
- queryName = "database." + action.toLowerCase() + clazz.getSimpleName();
- if (extended) {
- queryName += "Extended";
- }
- }
- String query = config.getString(queryName);
- if (query == null) {
- if (generateQueries) {
- query = constructObjectQuery(action, clazz, extended);
- } else {
- LOGGER.info("Query not provided: " + queryName);
- }
- }
- return query;
- }
-
public String getQuery(String action, Class<?> owner, Class<?> property) {
String queryName;
switch (action) {
@@ -302,10 +225,12 @@ public class DataManager {
}
}
- public User login(String email, String password) throws SQLException {
- User user = QueryBuilder.create(dataSource, getQuery("database.loginUser"))
- .setString("email", email.trim())
- .executeQuerySingle(User.class);
+ public User login(String email, String password) throws StorageException {
+ User user = storage.getObject(User.class, new Request(
+ new Columns.Include("id", "login", "hashedPassword", "salt"),
+ new Condition.Or(
+ new Condition.Equals("email", "email", email.trim()),
+ new Condition.Equals("login", "email"))));
LdapProvider ldapProvider = Context.getLdapProvider();
if (user != null) {
if (ldapProvider != null && user.getLogin() != null && ldapProvider.login(user.getLogin(), password)
@@ -322,57 +247,75 @@ public class DataManager {
return null;
}
- public void updateDeviceStatus(Device device) throws SQLException {
- QueryBuilder.create(dataSource, getQuery(ACTION_UPDATE, Device.class, true))
- .setObject(device)
- .executeUpdate();
+ public void updateUserPassword(User user) throws StorageException {
+ storage.updateObject(user, new Request(
+ new Columns.Include("hashedPassword", "salt"),
+ new Condition.Equals("id", "id")));
}
- public Collection<Position> getPositions(long deviceId, Date from, Date to) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery("database.selectPositions"))
- .setLong("deviceId", deviceId)
- .setDate("from", from)
- .setDate("to", to)
- .executeQuery(Position.class);
+ public void updateDeviceStatus(Device device) throws StorageException {
+ storage.updateObject(device, new Request(
+ new Columns.Include("lastUpdate"),
+ new Condition.Equals("id", "id")));
}
- public Position getPrecedingPosition(long deviceId, Date date) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery("database.selectPrecedingPosition"))
- .setLong("deviceId", deviceId)
- .setDate("time", date)
- .executeQuerySingle(Position.class);
+ public Collection<Position> getPositions(long deviceId, Date from, Date to) throws StorageException {
+ return storage.getObjects(Position.class, new Request(
+ new Columns.All(),
+ new Condition.And(
+ new Condition.Equals("deviceId", "deviceId", deviceId),
+ new Condition.Between("fixTime", "from", from, "to", to)),
+ new Order("fixTime")));
}
- public void updateLatestPosition(Position position) throws SQLException {
- QueryBuilder.create(dataSource, getQuery("database.updateLatestPosition"))
- .setDate("now", new Date())
- .setObject(position)
- .executeUpdate();
+ public Position getPrecedingPosition(long deviceId, Date date) throws StorageException {
+ return storage.getObject(Position.class, new Request(
+ new Columns.All(),
+ new Condition.And(
+ new Condition.Equals("deviceId", "deviceId", deviceId),
+ new Condition.Compare("fixTime", "<=", "time", date)),
+ new Order(true, "fixTime"),
+ new Limit(1)));
}
- public Collection<Position> getLatestPositions() throws SQLException {
- return QueryBuilder.create(dataSource, getQuery("database.selectLatestPositions"))
- .executeQuery(Position.class);
+ public void updateLatestPosition(Position position) throws StorageException {
+ Device device = new Device();
+ device.setId(position.getDeviceId());
+ device.setPositionId(position.getId());
+ storage.updateObject(device, new Request(
+ new Columns.Include("positionId"),
+ new Condition.Equals("id", "id")));
+ }
+
+ public Collection<Position> getLatestPositions() throws StorageException {
+ List<Position> positions = new LinkedList<>();
+ List<Device> devices = storage.getObjects(Device.class, new Request(new Columns.Include("positionId")));
+ for (Device device : devices) {
+ positions.addAll(storage.getObjects(Position.class, new Request(
+ new Columns.All(),
+ new Condition.Equals("id", "id", device.getPositionId()))));
+ }
+ return positions;
}
- public Server getServer() throws SQLException {
- return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, Server.class))
- .executeQuerySingle(Server.class);
+ public Server getServer() throws StorageException {
+ return storage.getObject(Server.class, new Request(new Columns.All()));
}
- public Collection<Event> getEvents(long deviceId, Date from, Date to) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery("database.selectEvents"))
- .setLong("deviceId", deviceId)
- .setDate("from", from)
- .setDate("to", to)
- .executeQuery(Event.class);
+ public Collection<Event> getEvents(long deviceId, Date from, Date to) throws StorageException {
+ return storage.getObjects(Event.class, new Request(
+ new Columns.All(),
+ new Condition.And(
+ new Condition.Equals("deviceId", "deviceId", deviceId),
+ new Condition.Between("eventTime", "from", from, "to", to)),
+ new Order("eventTime")));
}
- public Collection<Statistics> getStatistics(Date from, Date to) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery("database.selectStatistics"))
- .setDate("from", from)
- .setDate("to", to)
- .executeQuery(Statistics.class);
+ public Collection<Statistics> getStatistics(Date from, Date to) throws StorageException {
+ return storage.getObjects(Statistics.class, new Request(
+ new Columns.All(),
+ new Condition.Between("captureTime", "from", from, "to", to),
+ new Order("captureTime")));
}
public static Class<?> getClassByName(String name) throws ClassNotFoundException {
@@ -400,7 +343,7 @@ public class DataManager {
case "notification":
return Notification.class;
case "order":
- return Order.class;
+ return org.traccar.model.Order.class;
default:
throw new ClassNotFoundException();
}
@@ -412,51 +355,49 @@ public class DataManager {
}
public Collection<Permission> getPermissions(Class<? extends BaseModel> owner, Class<? extends BaseModel> property)
- throws SQLException, ClassNotFoundException {
- return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, owner, property))
- .executePermissionsQuery();
+ throws StorageException, ClassNotFoundException {
+ try {
+ return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, owner, property))
+ .executePermissionsQuery();
+ } catch (SQLException e) {
+ throw new StorageException(e);
+ }
}
public void linkObject(Class<?> owner, long ownerId, Class<?> property, long propertyId, boolean link)
- throws SQLException {
+ throws StorageException {
+ try {
QueryBuilder.create(dataSource, getQuery(link ? ACTION_INSERT : ACTION_DELETE, owner, property))
.setLong(makeNameId(owner), ownerId)
.setLong(makeNameId(property), propertyId)
.executeUpdate();
+ } catch (SQLException e) {
+ throw new StorageException(e);
+ }
}
- public <T extends BaseModel> T getObject(Class<T> clazz, long entityId) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT, clazz))
- .setLong("id", entityId)
- .executeQuerySingle(clazz);
+ public <T extends BaseModel> T getObject(Class<T> clazz, long entityId) throws StorageException {
+ return storage.getObject(clazz, new Request(
+ new Columns.All(),
+ new Condition.Equals("id", "id", entityId)));
}
- public <T extends BaseModel> Collection<T> getObjects(Class<T> clazz) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, clazz))
- .executeQuery(clazz);
+ public <T extends BaseModel> Collection<T> getObjects(Class<T> clazz) throws StorageException {
+ return storage.getObjects(clazz, new Request(new Columns.All()));
}
- public void addObject(BaseModel entity) throws SQLException {
- entity.setId(QueryBuilder.create(dataSource, getQuery(ACTION_INSERT, entity.getClass()), true)
- .setObject(entity)
- .executeUpdate());
+ public void addObject(BaseModel entity) throws StorageException {
+ entity.setId(storage.addObject(entity, new Request(new Columns.Exclude("id"))));
}
- public void updateObject(BaseModel entity) throws SQLException {
- QueryBuilder.create(dataSource, getQuery(ACTION_UPDATE, entity.getClass()))
- .setObject(entity)
- .executeUpdate();
- if (entity instanceof User && ((User) entity).getHashedPassword() != null) {
- QueryBuilder.create(dataSource, getQuery(ACTION_UPDATE, User.class, true))
- .setObject(entity)
- .executeUpdate();
- }
+ public void updateObject(BaseModel entity) throws StorageException {
+ storage.updateObject(entity, new Request(
+ new Columns.Exclude("id"),
+ new Condition.Equals("id", "id")));
}
- public void removeObject(Class<? extends BaseModel> clazz, long entityId) throws SQLException {
- QueryBuilder.create(dataSource, getQuery(ACTION_DELETE, clazz))
- .setLong("id", entityId)
- .executeUpdate();
+ public void removeObject(Class<? extends BaseModel> clazz, long entityId) throws StorageException {
+ storage.removeObject(clazz, new Request(new Condition.Equals("id", "id", entityId)));
}
}
diff --git a/src/main/java/org/traccar/database/DeviceManager.java b/src/main/java/org/traccar/database/DeviceManager.java
index c8a99274c..40591e869 100644
--- a/src/main/java/org/traccar/database/DeviceManager.java
+++ b/src/main/java/org/traccar/database/DeviceManager.java
@@ -37,6 +37,7 @@ import org.traccar.model.DeviceAccumulators;
import org.traccar.model.Group;
import org.traccar.model.Position;
import org.traccar.model.Server;
+import org.traccar.storage.StorageException;
public class DeviceManager extends BaseObjectManager<Device> implements IdentityManager, ManagableObjects {
@@ -94,13 +95,13 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
}
return device.getId();
- } catch (SQLException e) {
+ } catch (StorageException e) {
LOGGER.warn("Automatic device registration error", e);
return 0;
}
}
- public void updateDeviceCache(boolean force) throws SQLException {
+ public void updateDeviceCache(boolean force) {
long lastUpdate = devicesLastUpdate.get();
if ((force || System.currentTimeMillis() - lastUpdate > dataRefreshDelay)
&& devicesLastUpdate.compareAndSet(lastUpdate, System.currentTimeMillis())) {
@@ -144,24 +145,11 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
return defaultPassword;
}
- public Device getDeviceByPhone(String phone) {
- try {
- readLock();
- return devicesByPhone.get(phone);
- } finally {
- readUnlock();
- }
- }
-
@Override
public Set<Long> getAllItems() {
Set<Long> result = super.getAllItems();
if (result.isEmpty()) {
- try {
- updateDeviceCache(true);
- } catch (SQLException e) {
- LOGGER.warn("Update device cache error", e);
- }
+ updateDeviceCache(true);
result = super.getAllItems();
}
return result;
@@ -309,7 +297,7 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
positions.remove(deviceId);
}
- public void updateDeviceStatus(Device device) throws SQLException {
+ public void updateDeviceStatus(Device device) throws StorageException {
getDataManager().updateDeviceStatus(device);
Device cachedDevice = getById(device.getId());
if (cachedDevice != null) {
@@ -323,7 +311,7 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
for (Position position : getDataManager().getLatestPositions()) {
positions.put(position.getDeviceId(), position);
}
- } catch (SQLException error) {
+ } catch (StorageException error) {
LOGGER.warn("Load latest positions error", error);
}
}
@@ -334,7 +322,7 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
return lastPosition == null || position.getFixTime().compareTo(lastPosition.getFixTime()) >= 0;
}
- public void updateLatestPosition(Position position) throws SQLException {
+ public void updateLatestPosition(Position position) throws StorageException {
if (isLatestPosition(position)) {
@@ -451,7 +439,7 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
return result;
}
- public void resetDeviceAccumulators(DeviceAccumulators deviceAccumulators) throws SQLException {
+ public void resetDeviceAccumulators(DeviceAccumulators deviceAccumulators) throws StorageException {
Position last = positions.get(deviceAccumulators.getDeviceId());
if (last != null) {
if (deviceAccumulators.getTotalDistance() != null) {
diff --git a/src/main/java/org/traccar/database/ExtendedObjectManager.java b/src/main/java/org/traccar/database/ExtendedObjectManager.java
index 93e5820fb..006ed47b2 100644
--- a/src/main/java/org/traccar/database/ExtendedObjectManager.java
+++ b/src/main/java/org/traccar/database/ExtendedObjectManager.java
@@ -16,7 +16,6 @@
*/
package org.traccar.database;
-import java.sql.SQLException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
@@ -30,6 +29,7 @@ import org.traccar.model.Device;
import org.traccar.model.Group;
import org.traccar.model.Permission;
import org.traccar.model.BaseModel;
+import org.traccar.storage.StorageException;
public abstract class ExtendedObjectManager<T extends BaseModel> extends SimpleObjectManager<T> {
@@ -87,7 +87,7 @@ public abstract class ExtendedObjectManager<T extends BaseModel> extends SimpleO
}
@Override
- public void removeItem(long itemId) throws SQLException {
+ public void removeItem(long itemId) throws StorageException {
super.removeItem(itemId);
refreshExtendedPermissions();
}
@@ -133,7 +133,7 @@ public abstract class ExtendedObjectManager<T extends BaseModel> extends SimpleO
}
}
- } catch (SQLException | ClassNotFoundException error) {
+ } catch (StorageException | ClassNotFoundException error) {
LOGGER.warn("Refresh permissions error", error);
} finally {
writeUnlock();
diff --git a/src/main/java/org/traccar/database/GroupsManager.java b/src/main/java/org/traccar/database/GroupsManager.java
index c35f35f93..dafddc0cc 100644
--- a/src/main/java/org/traccar/database/GroupsManager.java
+++ b/src/main/java/org/traccar/database/GroupsManager.java
@@ -16,12 +16,12 @@
*/
package org.traccar.database;
-import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;
import org.traccar.Context;
import org.traccar.model.Group;
+import org.traccar.storage.StorageException;
public class GroupsManager extends BaseObjectManager<Group> implements ManagableObjects {
@@ -57,7 +57,7 @@ public class GroupsManager extends BaseObjectManager<Group> implements Managable
}
@Override
- public void updateItem(Group group) throws SQLException {
+ public void updateItem(Group group) throws StorageException {
checkGroupCycles(group);
super.updateItem(group);
}
diff --git a/src/main/java/org/traccar/database/NotificationManager.java b/src/main/java/org/traccar/database/NotificationManager.java
index 9f9a83cd2..f358b1d4d 100644
--- a/src/main/java/org/traccar/database/NotificationManager.java
+++ b/src/main/java/org/traccar/database/NotificationManager.java
@@ -18,7 +18,6 @@ package org.traccar.database;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.sql.SQLException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
@@ -36,6 +35,7 @@ import org.traccar.model.Event;
import org.traccar.model.Notification;
import org.traccar.model.Position;
import org.traccar.model.Typed;
+import org.traccar.storage.StorageException;
public class NotificationManager extends ExtendedObjectManager<Notification> {
@@ -66,7 +66,7 @@ public class NotificationManager extends ExtendedObjectManager<Notification> {
public void updateEvent(Event event, Position position) {
try {
getDataManager().addObject(event);
- } catch (SQLException error) {
+ } catch (StorageException error) {
LOGGER.warn("Event save error", error);
}
diff --git a/src/main/java/org/traccar/database/PermissionsManager.java b/src/main/java/org/traccar/database/PermissionsManager.java
index ab841a521..2bb808033 100644
--- a/src/main/java/org/traccar/database/PermissionsManager.java
+++ b/src/main/java/org/traccar/database/PermissionsManager.java
@@ -33,8 +33,8 @@ import org.traccar.model.Order;
import org.traccar.model.Permission;
import org.traccar.model.Server;
import org.traccar.model.User;
+import org.traccar.storage.StorageException;
-import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -156,7 +156,7 @@ public class PermissionsManager {
public void refreshServer() {
try {
server = dataManager.getServer();
- } catch (SQLException error) {
+ } catch (StorageException error) {
LOGGER.warn("Refresh server config error", error);
}
}
@@ -193,7 +193,7 @@ public class PermissionsManager {
}
}
- } catch (SQLException | ClassNotFoundException error) {
+ } catch (StorageException | ClassNotFoundException error) {
LOGGER.warn("Refresh device permissions error", error);
}
@@ -499,12 +499,12 @@ public class PermissionsManager {
return server;
}
- public void updateServer(Server server) throws SQLException {
+ public void updateServer(Server server) throws StorageException {
dataManager.updateObject(server);
this.server = server;
}
- public User login(String email, String password) throws SQLException {
+ public User login(String email, String password) throws StorageException {
User user = dataManager.login(email, password);
if (user != null) {
checkUserEnabled(user.getId());
diff --git a/src/main/java/org/traccar/database/SimpleObjectManager.java b/src/main/java/org/traccar/database/SimpleObjectManager.java
index eb8284d4e..78701720f 100644
--- a/src/main/java/org/traccar/database/SimpleObjectManager.java
+++ b/src/main/java/org/traccar/database/SimpleObjectManager.java
@@ -16,7 +16,6 @@
*/
package org.traccar.database;
-import java.sql.SQLException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -28,6 +27,7 @@ import org.traccar.Context;
import org.traccar.model.BaseModel;
import org.traccar.model.Permission;
import org.traccar.model.User;
+import org.traccar.storage.StorageException;
public abstract class SimpleObjectManager<T extends BaseModel> extends BaseObjectManager<T>
implements ManagableObjects {
@@ -83,7 +83,7 @@ public abstract class SimpleObjectManager<T extends BaseModel> extends BaseObjec
Set<Long> items = userItems.computeIfAbsent(permission.getOwnerId(), key -> new HashSet<>());
items.add(permission.getPropertyId());
}
- } catch (SQLException | ClassNotFoundException error) {
+ } catch (StorageException | ClassNotFoundException error) {
LOGGER.warn("Error getting permissions", error);
} finally {
writeUnlock();
@@ -92,7 +92,7 @@ public abstract class SimpleObjectManager<T extends BaseModel> extends BaseObjec
}
@Override
- public void removeItem(long itemId) throws SQLException {
+ public void removeItem(long itemId) throws StorageException {
super.removeItem(itemId);
refreshUserItems();
}
diff --git a/src/main/java/org/traccar/database/StatisticsManager.java b/src/main/java/org/traccar/database/StatisticsManager.java
index 4ad6d9d5c..3579ce7a5 100644
--- a/src/main/java/org/traccar/database/StatisticsManager.java
+++ b/src/main/java/org/traccar/database/StatisticsManager.java
@@ -23,12 +23,12 @@ import org.traccar.config.Config;
import org.traccar.config.Keys;
import org.traccar.helper.DateUtil;
import org.traccar.model.Statistics;
+import org.traccar.storage.StorageException;
import javax.inject.Inject;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
-import java.sql.SQLException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
@@ -106,7 +106,7 @@ public class StatisticsManager {
try {
dataManager.addObject(statistics);
- } catch (SQLException e) {
+ } catch (StorageException e) {
LOGGER.warn("Error saving statistics", e);
}
diff --git a/src/main/java/org/traccar/database/UsersManager.java b/src/main/java/org/traccar/database/UsersManager.java
index b741a85b6..31759dc8b 100644
--- a/src/main/java/org/traccar/database/UsersManager.java
+++ b/src/main/java/org/traccar/database/UsersManager.java
@@ -21,6 +21,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.traccar.model.User;
+import org.traccar.storage.StorageException;
public class UsersManager extends SimpleObjectManager<User> {
@@ -59,6 +60,14 @@ public class UsersManager extends SimpleObjectManager<User> {
}
@Override
+ public void updateItem(User user) throws StorageException {
+ if (user.getHashedPassword() != null) {
+ getDataManager().updateUserPassword(user);
+ }
+ super.updateItem(user);
+ }
+
+ @Override
protected void removeCachedItem(long userId) {
User cachedUser = getById(userId);
if (cachedUser != null) {
diff --git a/src/main/java/org/traccar/handler/FilterHandler.java b/src/main/java/org/traccar/handler/FilterHandler.java
index 2b850c755..e576a26b8 100644
--- a/src/main/java/org/traccar/handler/FilterHandler.java
+++ b/src/main/java/org/traccar/handler/FilterHandler.java
@@ -24,8 +24,8 @@ import org.traccar.config.Config;
import org.traccar.config.Keys;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
+import org.traccar.storage.StorageException;
-import java.sql.SQLException;
import java.util.Date;
@ChannelHandler.Sharable
@@ -174,7 +174,7 @@ public class FilterHandler extends BaseDataHandler {
try {
Date newFixTime = position.getFixTime();
preceding = Context.getDataManager().getPrecedingPosition(deviceId, newFixTime);
- } catch (SQLException e) {
+ } catch (StorageException e) {
LOGGER.warn("Error retrieving preceding position; fallbacking to last received position.", e);
preceding = getLastReceivedPosition(deviceId);
}
diff --git a/src/main/java/org/traccar/model/Attribute.java b/src/main/java/org/traccar/model/Attribute.java
index 45d40b3ec..65f2e3881 100644
--- a/src/main/java/org/traccar/model/Attribute.java
+++ b/src/main/java/org/traccar/model/Attribute.java
@@ -16,6 +16,9 @@
*/
package org.traccar.model;
+import org.traccar.storage.StorageName;
+
+@StorageName("tc_attributes")
public class Attribute extends BaseModel {
private String description;
diff --git a/src/main/java/org/traccar/model/Calendar.java b/src/main/java/org/traccar/model/Calendar.java
index af6364626..102c0be52 100644
--- a/src/main/java/org/traccar/model/Calendar.java
+++ b/src/main/java/org/traccar/model/Calendar.java
@@ -25,6 +25,7 @@ import net.fortuna.ical4j.model.DateTime;
import net.fortuna.ical4j.model.Period;
import net.fortuna.ical4j.model.component.CalendarComponent;
import org.traccar.storage.QueryIgnore;
+import org.traccar.storage.StorageName;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -32,6 +33,7 @@ import java.time.Duration;
import java.util.Collection;
import java.util.Date;
+@StorageName("tc_calendars")
public class Calendar extends ExtendedModel {
private String name;
diff --git a/src/main/java/org/traccar/model/Command.java b/src/main/java/org/traccar/model/Command.java
index 71bc232e9..03961c7b2 100644
--- a/src/main/java/org/traccar/model/Command.java
+++ b/src/main/java/org/traccar/model/Command.java
@@ -18,7 +18,9 @@ package org.traccar.model;
import org.traccar.storage.QueryIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import org.traccar.storage.StorageName;
+@StorageName("tc_commands")
@JsonIgnoreProperties(ignoreUnknown = true)
public class Command extends Message implements Cloneable {
@@ -104,6 +106,12 @@ public class Command extends Message implements Cloneable {
return super.getDeviceId();
}
+ @QueryIgnore
+ @Override
+ public void setDeviceId(long deviceId) {
+ super.setDeviceId(deviceId);
+ }
+
private String description;
public String getDescription() {
diff --git a/src/main/java/org/traccar/model/Device.java b/src/main/java/org/traccar/model/Device.java
index 46de8003d..836a6709c 100644
--- a/src/main/java/org/traccar/model/Device.java
+++ b/src/main/java/org/traccar/model/Device.java
@@ -20,7 +20,9 @@ import java.util.List;
import org.traccar.storage.QueryExtended;
import org.traccar.storage.QueryIgnore;
+import org.traccar.storage.StorageName;
+@StorageName("tc_devices")
public class Device extends GroupedModel {
private String name;
@@ -54,13 +56,13 @@ public class Device extends GroupedModel {
return status != null ? status : STATUS_OFFLINE;
}
+ @QueryIgnore
public void setStatus(String status) {
this.status = status;
}
private Date lastUpdate;
- @QueryExtended
public Date getLastUpdate() {
if (lastUpdate != null) {
return new Date(lastUpdate.getTime());
@@ -69,6 +71,7 @@ public class Device extends GroupedModel {
}
}
+ @QueryExtended
public void setLastUpdate(Date lastUpdate) {
if (lastUpdate != null) {
this.lastUpdate = new Date(lastUpdate.getTime());
@@ -84,6 +87,7 @@ public class Device extends GroupedModel {
return positionId;
}
+ @QueryIgnore
public void setPositionId(long positionId) {
this.positionId = positionId;
}
@@ -95,6 +99,7 @@ public class Device extends GroupedModel {
return geofenceIds;
}
+ @QueryIgnore
public void setGeofenceIds(List<Long> geofenceIds) {
this.geofenceIds = geofenceIds;
}
diff --git a/src/main/java/org/traccar/model/Driver.java b/src/main/java/org/traccar/model/Driver.java
index 05f52fd4d..b9e023088 100644
--- a/src/main/java/org/traccar/model/Driver.java
+++ b/src/main/java/org/traccar/model/Driver.java
@@ -16,6 +16,9 @@
*/
package org.traccar.model;
+import org.traccar.storage.StorageName;
+
+@StorageName("tc_drivers")
public class Driver extends ExtendedModel {
private String name;
@@ -37,4 +40,5 @@ public class Driver extends ExtendedModel {
public void setUniqueId(String uniqueId) {
this.uniqueId = uniqueId;
}
+
}
diff --git a/src/main/java/org/traccar/model/Event.java b/src/main/java/org/traccar/model/Event.java
index a7a134ecf..6e3953fda 100644
--- a/src/main/java/org/traccar/model/Event.java
+++ b/src/main/java/org/traccar/model/Event.java
@@ -15,8 +15,11 @@
*/
package org.traccar.model;
+import org.traccar.storage.StorageName;
+
import java.util.Date;
+@StorageName("tc_events")
public class Event extends Message {
public Event(String type, Position position) {
diff --git a/src/main/java/org/traccar/model/Geofence.java b/src/main/java/org/traccar/model/Geofence.java
index a451da9f5..5b857580d 100644
--- a/src/main/java/org/traccar/model/Geofence.java
+++ b/src/main/java/org/traccar/model/Geofence.java
@@ -26,7 +26,9 @@ import org.traccar.geofence.GeofencePolygon;
import org.traccar.geofence.GeofencePolyline;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.traccar.storage.StorageName;
+@StorageName("tc_geofences")
public class Geofence extends ScheduledModel {
public static final String TYPE_GEOFENCE_CILCLE = "geofenceCircle";
diff --git a/src/main/java/org/traccar/model/Group.java b/src/main/java/org/traccar/model/Group.java
index 91ea2319d..ff69f61fa 100644
--- a/src/main/java/org/traccar/model/Group.java
+++ b/src/main/java/org/traccar/model/Group.java
@@ -15,6 +15,9 @@
*/
package org.traccar.model;
+import org.traccar.storage.StorageName;
+
+@StorageName("tc_groups")
public class Group extends GroupedModel {
private String name;
diff --git a/src/main/java/org/traccar/model/Maintenance.java b/src/main/java/org/traccar/model/Maintenance.java
index 73f67ea96..cad100a3a 100644
--- a/src/main/java/org/traccar/model/Maintenance.java
+++ b/src/main/java/org/traccar/model/Maintenance.java
@@ -16,6 +16,9 @@
*/
package org.traccar.model;
+import org.traccar.storage.StorageName;
+
+@StorageName("tc_maintenances")
public class Maintenance extends ExtendedModel {
private String name;
diff --git a/src/main/java/org/traccar/model/Notification.java b/src/main/java/org/traccar/model/Notification.java
index 01ca2711c..95e446132 100644
--- a/src/main/java/org/traccar/model/Notification.java
+++ b/src/main/java/org/traccar/model/Notification.java
@@ -21,7 +21,9 @@ import java.util.Set;
import org.traccar.storage.QueryIgnore;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.traccar.storage.StorageName;
+@StorageName("tc_notifications")
public class Notification extends ScheduledModel {
private boolean always;
@@ -44,7 +46,6 @@ public class Notification extends ScheduledModel {
this.type = type;
}
-
private String notificators;
public String getNotificators() {
@@ -55,7 +56,6 @@ public class Notification extends ScheduledModel {
this.notificators = transports;
}
-
@JsonIgnore
@QueryIgnore
public Set<String> getNotificatorsTypes() {
diff --git a/src/main/java/org/traccar/model/Order.java b/src/main/java/org/traccar/model/Order.java
index fe6d926b8..7d09b0a47 100644
--- a/src/main/java/org/traccar/model/Order.java
+++ b/src/main/java/org/traccar/model/Order.java
@@ -15,6 +15,9 @@
*/
package org.traccar.model;
+import org.traccar.storage.StorageName;
+
+@StorageName("tc_orders")
public class Order extends ExtendedModel {
private String uniqueId;
diff --git a/src/main/java/org/traccar/model/Position.java b/src/main/java/org/traccar/model/Position.java
index bbea58901..348370e2c 100644
--- a/src/main/java/org/traccar/model/Position.java
+++ b/src/main/java/org/traccar/model/Position.java
@@ -17,8 +17,11 @@ package org.traccar.model;
import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import org.traccar.storage.QueryIgnore;
+import org.traccar.storage.StorageName;
+@StorageName("tc_positions")
public class Position extends Message {
public static final String KEY_ORIGINAL = "raw";
@@ -190,6 +193,7 @@ public class Position extends Message {
this.fixTime = fixTime;
}
+ @QueryIgnore
public void setTime(Date time) {
setDeviceTime(time);
setFixTime(time);
@@ -202,6 +206,7 @@ public class Position extends Message {
return outdated;
}
+ @QueryIgnore
public void setOutdated(boolean outdated) {
this.outdated = outdated;
}
@@ -296,10 +301,18 @@ public class Position extends Message {
this.network = network;
}
- @Override
+ @JsonIgnore
@QueryIgnore
+ @Override
public String getType() {
return super.getType();
}
+ @JsonIgnore
+ @QueryIgnore
+ @Override
+ public void setType(String type) {
+ super.setType(type);
+ }
+
}
diff --git a/src/main/java/org/traccar/model/Server.java b/src/main/java/org/traccar/model/Server.java
index fdb071a18..b48e84939 100644
--- a/src/main/java/org/traccar/model/Server.java
+++ b/src/main/java/org/traccar/model/Server.java
@@ -18,7 +18,9 @@ package org.traccar.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.traccar.Context;
import org.traccar.storage.QueryIgnore;
+import org.traccar.storage.StorageName;
+@StorageName("tc_servers")
@JsonIgnoreProperties(ignoreUnknown = true)
public class Server extends ExtendedModel {
diff --git a/src/main/java/org/traccar/model/Statistics.java b/src/main/java/org/traccar/model/Statistics.java
index a9a117aef..0dc1b98e8 100644
--- a/src/main/java/org/traccar/model/Statistics.java
+++ b/src/main/java/org/traccar/model/Statistics.java
@@ -15,9 +15,12 @@
*/
package org.traccar.model;
+import org.traccar.storage.StorageName;
+
import java.util.Date;
import java.util.Map;
+@StorageName("tc_statistics")
public class Statistics extends ExtendedModel {
private Date captureTime;
diff --git a/src/main/java/org/traccar/model/User.java b/src/main/java/org/traccar/model/User.java
index 447cf691c..94828ab95 100644
--- a/src/main/java/org/traccar/model/User.java
+++ b/src/main/java/org/traccar/model/User.java
@@ -20,9 +20,11 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import org.traccar.storage.QueryExtended;
import org.traccar.storage.QueryIgnore;
import org.traccar.helper.Hashing;
+import org.traccar.storage.StorageName;
import java.util.Date;
+@StorageName("tc_users")
public class User extends ExtendedModel {
private String name;
diff --git a/src/main/java/org/traccar/reports/Events.java b/src/main/java/org/traccar/reports/Events.java
index 66d9e708d..e4b905702 100644
--- a/src/main/java/org/traccar/reports/Events.java
+++ b/src/main/java/org/traccar/reports/Events.java
@@ -20,7 +20,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -35,6 +34,7 @@ import org.traccar.model.Geofence;
import org.traccar.model.Group;
import org.traccar.model.Maintenance;
import org.traccar.reports.model.DeviceReport;
+import org.traccar.storage.StorageException;
public final class Events {
@@ -42,7 +42,7 @@ public final class Events {
}
public static Collection<Event> getObjects(long userId, Collection<Long> deviceIds, Collection<Long> groupIds,
- Collection<String> types, Date from, Date to) throws SQLException {
+ Collection<String> types, Date from, Date to) throws StorageException {
ReportUtils.checkPeriodLimit(from, to);
ArrayList<Event> result = new ArrayList<>();
for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) {
@@ -66,7 +66,7 @@ public final class Events {
public static void getExcel(OutputStream outputStream,
long userId, Collection<Long> deviceIds, Collection<Long> groupIds,
- Collection<String> types, Date from, Date to) throws SQLException, IOException {
+ Collection<String> types, Date from, Date to) throws StorageException, IOException {
ReportUtils.checkPeriodLimit(from, to);
ArrayList<DeviceReport> devicesEvents = new ArrayList<>();
ArrayList<String> sheetNames = new ArrayList<>();
diff --git a/src/main/java/org/traccar/reports/Route.java b/src/main/java/org/traccar/reports/Route.java
index 6adb00aae..4a5edd295 100644
--- a/src/main/java/org/traccar/reports/Route.java
+++ b/src/main/java/org/traccar/reports/Route.java
@@ -20,7 +20,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -31,6 +30,7 @@ import org.traccar.model.Device;
import org.traccar.model.Group;
import org.traccar.model.Position;
import org.traccar.reports.model.DeviceReport;
+import org.traccar.storage.StorageException;
public final class Route {
@@ -38,7 +38,7 @@ public final class Route {
}
public static Collection<Position> getObjects(long userId, Collection<Long> deviceIds, Collection<Long> groupIds,
- Date from, Date to) throws SQLException {
+ Date from, Date to) throws StorageException {
ReportUtils.checkPeriodLimit(from, to);
ArrayList<Position> result = new ArrayList<>();
for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) {
@@ -50,7 +50,7 @@ public final class Route {
public static void getExcel(OutputStream outputStream,
long userId, Collection<Long> deviceIds, Collection<Long> groupIds,
- Date from, Date to) throws SQLException, IOException {
+ Date from, Date to) throws StorageException, IOException {
ReportUtils.checkPeriodLimit(from, to);
ArrayList<DeviceReport> devicesRoutes = new ArrayList<>();
ArrayList<String> sheetNames = new ArrayList<>();
diff --git a/src/main/java/org/traccar/reports/Stops.java b/src/main/java/org/traccar/reports/Stops.java
index 2036b0641..36a4a7549 100644
--- a/src/main/java/org/traccar/reports/Stops.java
+++ b/src/main/java/org/traccar/reports/Stops.java
@@ -21,7 +21,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -35,13 +34,14 @@ import org.traccar.model.Device;
import org.traccar.model.Group;
import org.traccar.reports.model.DeviceReport;
import org.traccar.reports.model.StopReport;
+import org.traccar.storage.StorageException;
public final class Stops {
private Stops() {
}
- private static Collection<StopReport> detectStops(long deviceId, Date from, Date to) throws SQLException {
+ private static Collection<StopReport> detectStops(long deviceId, Date from, Date to) throws StorageException {
boolean ignoreOdometer = Context.getDeviceManager()
.lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true);
@@ -55,7 +55,7 @@ public final class Stops {
public static Collection<StopReport> getObjects(
long userId, Collection<Long> deviceIds, Collection<Long> groupIds,
- Date from, Date to) throws SQLException {
+ Date from, Date to) throws StorageException {
ReportUtils.checkPeriodLimit(from, to);
ArrayList<StopReport> result = new ArrayList<>();
for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) {
@@ -67,7 +67,7 @@ public final class Stops {
public static void getExcel(
OutputStream outputStream, long userId, Collection<Long> deviceIds, Collection<Long> groupIds,
- Date from, Date to) throws SQLException, IOException {
+ Date from, Date to) throws StorageException, IOException {
ReportUtils.checkPeriodLimit(from, to);
ArrayList<DeviceReport> devicesStops = new ArrayList<>();
ArrayList<String> sheetNames = new ArrayList<>();
diff --git a/src/main/java/org/traccar/reports/Summary.java b/src/main/java/org/traccar/reports/Summary.java
index d576ac1e6..4924af062 100644
--- a/src/main/java/org/traccar/reports/Summary.java
+++ b/src/main/java/org/traccar/reports/Summary.java
@@ -20,7 +20,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
@@ -31,6 +30,7 @@ import org.traccar.Context;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
import org.traccar.reports.model.SummaryReport;
+import org.traccar.storage.StorageException;
public final class Summary {
@@ -97,7 +97,7 @@ public final class Summary {
}
private static Collection<SummaryReport> calculateSummaryResults(
- long userId, long deviceId, Date from, Date to, boolean daily) throws SQLException {
+ long userId, long deviceId, Date from, Date to, boolean daily) throws StorageException {
ArrayList<Position> positions = new ArrayList<>(Context.getDataManager().getPositions(deviceId, from, to));
@@ -122,7 +122,7 @@ public final class Summary {
}
public static Collection<SummaryReport> getObjects(long userId, Collection<Long> deviceIds,
- Collection<Long> groupIds, Date from, Date to, boolean daily) throws SQLException {
+ Collection<Long> groupIds, Date from, Date to, boolean daily) throws StorageException {
ReportUtils.checkPeriodLimit(from, to);
ArrayList<SummaryReport> result = new ArrayList<>();
for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) {
@@ -134,7 +134,7 @@ public final class Summary {
public static void getExcel(OutputStream outputStream,
long userId, Collection<Long> deviceIds, Collection<Long> groupIds,
- Date from, Date to, boolean daily) throws SQLException, IOException {
+ Date from, Date to, boolean daily) throws StorageException, IOException {
ReportUtils.checkPeriodLimit(from, to);
Collection<SummaryReport> summaries = getObjects(userId, deviceIds, groupIds, from, to, daily);
String templatePath = Context.getConfig().getString("report.templatesPath",
diff --git a/src/main/java/org/traccar/reports/Trips.java b/src/main/java/org/traccar/reports/Trips.java
index 7c0cd6921..1461b869e 100644
--- a/src/main/java/org/traccar/reports/Trips.java
+++ b/src/main/java/org/traccar/reports/Trips.java
@@ -20,7 +20,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -34,13 +33,14 @@ import org.traccar.model.Device;
import org.traccar.model.Group;
import org.traccar.reports.model.DeviceReport;
import org.traccar.reports.model.TripReport;
+import org.traccar.storage.StorageException;
public final class Trips {
private Trips() {
}
- private static Collection<TripReport> detectTrips(long deviceId, Date from, Date to) throws SQLException {
+ private static Collection<TripReport> detectTrips(long deviceId, Date from, Date to) throws StorageException {
boolean ignoreOdometer = Context.getDeviceManager()
.lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true);
@@ -53,7 +53,7 @@ public final class Trips {
}
public static Collection<TripReport> getObjects(long userId, Collection<Long> deviceIds, Collection<Long> groupIds,
- Date from, Date to) throws SQLException {
+ Date from, Date to) throws StorageException {
ReportUtils.checkPeriodLimit(from, to);
ArrayList<TripReport> result = new ArrayList<>();
for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) {
@@ -65,7 +65,7 @@ public final class Trips {
public static void getExcel(OutputStream outputStream,
long userId, Collection<Long> deviceIds, Collection<Long> groupIds,
- Date from, Date to) throws SQLException, IOException {
+ Date from, Date to) throws StorageException, IOException {
ReportUtils.checkPeriodLimit(from, to);
ArrayList<DeviceReport> devicesTrips = new ArrayList<>();
ArrayList<String> sheetNames = new ArrayList<>();
diff --git a/src/main/java/org/traccar/storage/DatabaseStorage.java b/src/main/java/org/traccar/storage/DatabaseStorage.java
index 0bcab7d20..2c893ebbc 100644
--- a/src/main/java/org/traccar/storage/DatabaseStorage.java
+++ b/src/main/java/org/traccar/storage/DatabaseStorage.java
@@ -2,6 +2,7 @@ package org.traccar.storage;
import org.traccar.storage.query.Columns;
import org.traccar.storage.query.Condition;
+import org.traccar.storage.query.Limit;
import org.traccar.storage.query.Order;
import org.traccar.storage.query.Request;
@@ -24,7 +25,7 @@ public class DatabaseStorage extends Storage {
@Override
public <T> List<T> getObjects(Class<T> clazz, Request request) throws StorageException {
StringBuilder query = new StringBuilder("SELECT ");
- query.append(formatColumns(request.getColumns(), clazz, c -> c));
+ query.append(formatColumns(request.getColumns(), clazz, "get", c -> c));
query.append(" FROM ").append(getTableName(clazz));
query.append(formatCondition(request.getCondition()));
query.append(formatOrder(request.getOrder()));
@@ -44,9 +45,9 @@ public class DatabaseStorage extends Storage {
StringBuilder query = new StringBuilder("INSERT INTO ");
query.append(getTableName(entity.getClass()));
query.append("(");
- query.append(formatColumns(request.getColumns(), entity.getClass(), c -> c));
+ query.append(formatColumns(request.getColumns(), entity.getClass(), "set", c -> c));
query.append(") VALUES (");
- query.append(formatColumns(request.getColumns(), entity.getClass(), c -> ':' + c));
+ query.append(formatColumns(request.getColumns(), entity.getClass(), "set", c -> ':' + c));
query.append(")");
try {
QueryBuilder builder = QueryBuilder.create(dataSource, query.toString(), true);
@@ -62,7 +63,7 @@ public class DatabaseStorage extends Storage {
StringBuilder query = new StringBuilder("UPDATE ");
query.append(getTableName(entity.getClass()));
query.append(" SET ");
- query.append(formatColumns(request.getColumns(), entity.getClass(), c -> c + " = :" + c));
+ query.append(formatColumns(request.getColumns(), entity.getClass(), "set", c -> c + " = :" + c));
query.append(formatCondition(request.getCondition()));
try {
QueryBuilder builder = QueryBuilder.create(dataSource, query.toString());
@@ -101,31 +102,46 @@ public class DatabaseStorage extends Storage {
}
private Map<String, Object> getConditionVariables(Condition genericCondition) {
- Map<String, Object> result = new HashMap<>();
- if (genericCondition instanceof Condition.Equals) {
- Condition.Equals condition = (Condition.Equals) genericCondition;
- result.put(condition.getVariable(), condition.getValue());
+ Map<String, Object> results = new HashMap<>();
+ if (genericCondition instanceof Condition.Compare) {
+ Condition.Compare condition = (Condition.Compare) genericCondition;
+ if (condition.getValue() != null) {
+ results.put(condition.getVariable(), condition.getValue());
+ }
} else if (genericCondition instanceof Condition.Between) {
Condition.Between condition = (Condition.Between) genericCondition;
- result.put(condition.getFromVariable(), condition.getFromValue());
- result.put(condition.getToVariable(), condition.getToValue());
+ results.put(condition.getFromVariable(), condition.getFromValue());
+ results.put(condition.getToVariable(), condition.getToValue());
+ } else if (genericCondition instanceof Condition.Binary) {
+ Condition.Binary condition = (Condition.Binary) genericCondition;
+ results.putAll(getConditionVariables(condition.getFirst()));
+ results.putAll(getConditionVariables(condition.getSecond()));
}
- return result;
+ return results;
}
- private String formatColumns(Columns columns, Class<?> clazz, Function<String, String> mapper) {
- return columns.getColumns(clazz).stream().map(mapper).collect(Collectors.joining(", "));
+ private String formatColumns(
+ Columns columns, Class<?> clazz, String type, Function<String, String> mapper) {
+ return columns.getColumns(clazz, type).stream().map(mapper).collect(Collectors.joining(", "));
}
private String formatCondition(Condition genericCondition) {
+ return formatCondition(genericCondition, true);
+ }
+
+ private String formatCondition(Condition genericCondition, boolean appendWhere) {
StringBuilder result = new StringBuilder();
if (genericCondition != null) {
- result.append(" WHERE ");
- if (genericCondition instanceof Condition.Equals) {
+ if (appendWhere) {
+ result.append(" WHERE ");
+ }
+ if (genericCondition instanceof Condition.Compare) {
- Condition.Equals condition = (Condition.Equals) genericCondition;
+ Condition.Compare condition = (Condition.Compare) genericCondition;
result.append(condition.getColumn());
- result.append(" == :");
+ result.append(" ");
+ result.append(condition.getOperator());
+ result.append(" :");
result.append(condition.getVariable());
} else if (genericCondition instanceof Condition.Between) {
@@ -137,12 +153,14 @@ public class DatabaseStorage extends Storage {
result.append(" AND :");
result.append(condition.getToVariable());
- } else if (genericCondition instanceof Condition.And) {
+ } else if (genericCondition instanceof Condition.Binary) {
- Condition.And condition = (Condition.And) genericCondition;
- result.append(formatCondition(condition.getFirst()));
- result.append(" AND ");
- result.append(formatCondition(condition.getSecond()));
+ Condition.Binary condition = (Condition.Binary) genericCondition;
+ result.append(formatCondition(condition.getFirst(), false));
+ result.append(" ");
+ result.append(condition.getOperator());
+ result.append(" ");
+ result.append(formatCondition(condition.getSecond(), false));
}
}
@@ -161,4 +179,13 @@ public class DatabaseStorage extends Storage {
return result.toString();
}
+ private String formatLimit(Limit limit) {
+ StringBuilder result = new StringBuilder();
+ if (limit != null) {
+ result.append(" LIMIT ");
+ result.append(limit.getValue());
+ }
+ return result.toString();
+ }
+
}
diff --git a/src/main/java/org/traccar/storage/QueryBuilder.java b/src/main/java/org/traccar/storage/QueryBuilder.java
index 838472c8b..edaacb74d 100644
--- a/src/main/java/org/traccar/storage/QueryBuilder.java
+++ b/src/main/java/org/traccar/storage/QueryBuilder.java
@@ -276,8 +276,7 @@ public final class QueryBuilder {
Method[] methods = object.getClass().getMethods();
for (Method method : methods) {
- if (method.getName().startsWith("get") && method.getParameterTypes().length == 0
- && !method.isAnnotationPresent(QueryIgnore.class)) {
+ if (method.getName().startsWith("get") && method.getParameterTypes().length == 0) {
String name = method.getName().substring(3);
try {
if (method.getReturnType().equals(boolean.class)) {
@@ -412,8 +411,7 @@ public final class QueryBuilder {
Method[] methods = clazz.getMethods();
for (final Method method : methods) {
- if (method.getName().startsWith("set") && method.getParameterTypes().length == 1
- && !method.isAnnotationPresent(QueryIgnore.class)) {
+ if (method.getName().startsWith("set") && method.getParameterTypes().length == 1) {
final String name = method.getName().substring(3);
diff --git a/src/main/java/org/traccar/storage/Storage.java b/src/main/java/org/traccar/storage/Storage.java
index b95ce9505..3726fbf50 100644
--- a/src/main/java/org/traccar/storage/Storage.java
+++ b/src/main/java/org/traccar/storage/Storage.java
@@ -6,20 +6,17 @@ import java.util.List;
public abstract class Storage {
- abstract <T> List<T> getObjects(Class<T> clazz, Request request) throws StorageException;
+ public abstract <T> List<T> getObjects(Class<T> clazz, Request request) throws StorageException;
- abstract <T> long addObject(T entity, Request request) throws StorageException;
+ public abstract <T> long addObject(T entity, Request request) throws StorageException;
- abstract <T> void updateObject(T entity, Request request) throws StorageException;
+ public abstract <T> void updateObject(T entity, Request request) throws StorageException;
- abstract void removeObject(Class<?> clazz, Request request) throws StorageException;
+ public abstract void removeObject(Class<?> clazz, Request request) throws StorageException;
- <T> T getObject(Class<T> clazz, Request request) throws StorageException {
+ public <T> T getObject(Class<T> clazz, Request request) throws StorageException {
var objects = getObjects(clazz, request);
- if (objects.isEmpty()) {
- throw new StorageException("No objects found");
- }
- return objects.get(0);
+ return objects.isEmpty() ? null : objects.get(0);
}
}
diff --git a/src/main/java/org/traccar/storage/query/Columns.java b/src/main/java/org/traccar/storage/query/Columns.java
index 1a13665ee..196d2281c 100644
--- a/src/main/java/org/traccar/storage/query/Columns.java
+++ b/src/main/java/org/traccar/storage/query/Columns.java
@@ -1,5 +1,6 @@
package org.traccar.storage.query;
+import org.traccar.storage.QueryExtended;
import org.traccar.storage.QueryIgnore;
import java.lang.reflect.Method;
@@ -11,14 +12,17 @@ import java.util.stream.Collectors;
public abstract class Columns {
- public abstract List<String> getColumns(Class<?> clazz);
+ public abstract List<String> getColumns(Class<?> clazz, String type);
- protected List<String> getAllColumns(Class<?> clazz) {
+ protected List<String> getAllColumns(Class<?> clazz, String type) {
List<String> columns = new LinkedList<>();
Method[] methods = clazz.getMethods();
for (Method method : methods) {
- if (method.getName().startsWith("set") && method.getParameterTypes().length == 1
- && !method.isAnnotationPresent(QueryIgnore.class)) {
+ int parameterCount = type.equals("set") ? 1 : 0;
+ if (method.getName().startsWith(type) && method.getParameterTypes().length == parameterCount
+ && !method.isAnnotationPresent(QueryIgnore.class)
+ && !method.isAnnotationPresent(QueryExtended.class)
+ && !method.getName().equals("getClass")) {
columns.add(method.getName().substring(3).toLowerCase());
}
}
@@ -27,8 +31,8 @@ public abstract class Columns {
public static class All extends Columns {
@Override
- public List<String> getColumns(Class<?> clazz) {
- return getAllColumns(clazz);
+ public List<String> getColumns(Class<?> clazz, String type) {
+ return getAllColumns(clazz, type);
}
}
@@ -40,7 +44,7 @@ public abstract class Columns {
}
@Override
- public List<String> getColumns(Class<?> clazz) {
+ public List<String> getColumns(Class<?> clazz, String type) {
return columns;
}
}
@@ -53,8 +57,8 @@ public abstract class Columns {
}
@Override
- public List<String> getColumns(Class<?> clazz) {
- return getAllColumns(clazz).stream()
+ public List<String> getColumns(Class<?> clazz, String type) {
+ return getAllColumns(clazz, type).stream()
.filter(column -> !columns.contains(column))
.collect(Collectors.toList());
}
diff --git a/src/main/java/org/traccar/storage/query/Condition.java b/src/main/java/org/traccar/storage/query/Condition.java
index 50d520bc7..82c8e8479 100644
--- a/src/main/java/org/traccar/storage/query/Condition.java
+++ b/src/main/java/org/traccar/storage/query/Condition.java
@@ -2,13 +2,25 @@ package org.traccar.storage.query;
public interface Condition {
- class Equals implements Condition {
+ class Equals extends Compare {
+ public Equals(String column, String variable) {
+ this(column, variable, null);
+ }
+
+ public Equals(String column, String variable, Object value) {
+ super(column, "=", variable, value);
+ }
+ }
+
+ class Compare implements Condition {
private final String column;
+ private final String operator;
private final String variable;
private final Object value;
- public Equals(String column, String variable, Object value) {
+ public Compare(String column, String operator, String variable, Object value) {
this.column = column;
+ this.operator = operator;
this.variable = variable;
this.value = value;
}
@@ -17,6 +29,10 @@ public interface Condition {
return column;
}
+ public String getOperator() {
+ return operator;
+ }
+
public String getVariable() {
return variable;
}
@@ -62,13 +78,27 @@ public interface Condition {
}
}
- class And implements Condition {
+ class Or extends Binary {
+ public Or(Condition first, Condition second) {
+ super(first, second, "OR");
+ }
+ }
+
+ class And extends Binary {
+ public And(Condition first, Condition second) {
+ super(first, second, "AND");
+ }
+ }
+
+ class Binary implements Condition {
private final Condition first;
private final Condition second;
+ private final String operator;
- public And(Condition first, Condition second) {
+ public Binary(Condition first, Condition second, String operator) {
this.first = first;
this.second = second;
+ this.operator = operator;
}
public Condition getFirst() {
@@ -78,6 +108,10 @@ public interface Condition {
public Condition getSecond() {
return second;
}
+
+ public String getOperator() {
+ return operator;
+ }
}
}
diff --git a/src/main/java/org/traccar/storage/query/Limit.java b/src/main/java/org/traccar/storage/query/Limit.java
new file mode 100644
index 000000000..4a20f0ce2
--- /dev/null
+++ b/src/main/java/org/traccar/storage/query/Limit.java
@@ -0,0 +1,15 @@
+package org.traccar.storage.query;
+
+public class Limit {
+
+ private final int value;
+
+ public Limit(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+}
diff --git a/src/main/java/org/traccar/storage/query/Request.java b/src/main/java/org/traccar/storage/query/Request.java
index 8536cafd0..a98dd48f7 100644
--- a/src/main/java/org/traccar/storage/query/Request.java
+++ b/src/main/java/org/traccar/storage/query/Request.java
@@ -5,11 +5,29 @@ public class Request {
private final Columns columns;
private final Condition condition;
private final Order order;
+ private final Limit limit;
+
+ public Request(Columns columns) {
+ this(columns, null, null);
+ }
+
+ public Request(Condition condition) {
+ this(null, condition, null);
+ }
+
+ public Request(Columns columns, Condition condition) {
+ this(columns, condition, null);
+ }
public Request(Columns columns, Condition condition, Order order) {
+ this(columns, condition, order, null);
+ }
+
+ public Request(Columns columns, Condition condition, Order order, Limit limit) {
this.columns = columns;
this.condition = condition;
this.order = order;
+ this.limit = limit;
}
public Columns getColumns() {
@@ -24,4 +42,8 @@ public class Request {
return order;
}
+ public Limit getLimit() {
+ return limit;
+ }
+
}
diff --git a/src/test/java/org/traccar/database/DataManagerTest.java b/src/test/java/org/traccar/database/DataManagerTest.java
deleted file mode 100644
index 23043e96e..000000000
--- a/src/test/java/org/traccar/database/DataManagerTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.traccar.database;
-
-import org.junit.Test;
-import org.traccar.model.Attribute;
-import org.traccar.model.Device;
-import org.traccar.model.Driver;
-import org.traccar.model.Geofence;
-import org.traccar.model.Group;
-import org.traccar.model.ManagedUser;
-import org.traccar.model.Position;
-import org.traccar.model.User;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class DataManagerTest {
-
- @Test
- public void constructObjectQuery() {
- assertEquals("SELECT * FROM tc_users",
- DataManager.constructObjectQuery(DataManager.ACTION_SELECT_ALL, User.class, false));
- assertEquals("DELETE FROM tc_groups WHERE id = :id",
- DataManager.constructObjectQuery(DataManager.ACTION_DELETE, Group.class, false));
- assertEquals("SELECT * FROM tc_positions WHERE id = :id",
- DataManager.constructObjectQuery(DataManager.ACTION_SELECT, Position.class, false));
-
- String insertDevice = DataManager.constructObjectQuery(DataManager.ACTION_INSERT, Device.class, false);
- assertFalse(insertDevice.contains("class"));
- assertFalse(insertDevice.contains("id"));
- assertFalse(insertDevice.contains("status"));
- assertFalse(insertDevice.contains("geofenceIds"));
-
- String updateDeviceStatus = DataManager.constructObjectQuery("update", Device.class, true);
- assertTrue(updateDeviceStatus.contains("lastUpdate"));
-
- String updateUser = DataManager.constructObjectQuery(DataManager.ACTION_UPDATE, User.class, false);
- assertFalse(updateUser.contains("class"));
- assertFalse(updateUser.contains("password"));
- assertFalse(updateUser.contains("salt"));
-
- String updateUserPassword = DataManager.constructObjectQuery(DataManager.ACTION_UPDATE, User.class, true);
- assertFalse(updateUserPassword.contains("name"));
- assertTrue(updateUserPassword.contains("hashedPassword"));
- assertTrue(updateUserPassword.contains("salt"));
-
- String insertPosition = DataManager.constructObjectQuery(DataManager.ACTION_INSERT, Position.class, false);
- assertFalse(insertPosition.contains("type"));
- assertFalse(insertPosition.contains("outdated"));
-
- }
-
- @Test
- public void constructPermissionsQuery() {
- assertEquals("SELECT userId, deviceId FROM tc_user_device",
- DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, User.class, Device.class));
-
- assertEquals("SELECT userId, managedUserId FROM tc_user_user",
- DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, User.class, ManagedUser.class));
-
- assertEquals("SELECT deviceId, driverId FROM tc_device_driver",
- DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, Device.class, Driver.class));
-
- assertEquals("SELECT groupId, geofenceId FROM tc_group_geofence",
- DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, Group.class, Geofence.class));
-
- assertEquals("INSERT INTO tc_user_device (userId, deviceId) VALUES (:userId, :deviceId)",
- DataManager.constructPermissionQuery(DataManager.ACTION_INSERT, User.class, Device.class));
-
- assertEquals("DELETE FROM tc_user_user WHERE userId = :userId AND managedUserId = :managedUserId",
- DataManager.constructPermissionQuery(DataManager.ACTION_DELETE, User.class, ManagedUser.class));
-
- assertEquals("INSERT INTO tc_device_geofence (deviceId, geofenceId) VALUES (:deviceId, :geofenceId)",
- DataManager.constructPermissionQuery(DataManager.ACTION_INSERT, Device.class, Geofence.class));
-
- assertEquals("DELETE FROM tc_group_attribute WHERE groupId = :groupId AND attributeId = :attributeId",
- DataManager.constructPermissionQuery(DataManager.ACTION_DELETE, Group.class, Attribute.class));
-
- }
-
-}