Ver código fonte

Fixed timestamps in SQLs

Lukas Cerny 1 ano atrás
pai
commit
ea5b80fca1

+ 98 - 86
src/main/java/cz/senslog/telemetry/database/repository/MapLogRepository.java

@@ -12,7 +12,6 @@ import java.time.OffsetDateTime;
 import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
 import static java.lang.String.format;
@@ -1281,10 +1280,10 @@ public class MapLogRepository implements SensLogRepository {
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
-            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $4 > c.from_time THEN c.from_time ELSE $4 END) AND tel.time_stamp <= (CASE WHEN $5 > c.to_time THEN c.to_time ELSE $5 END)";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $4 < c.from_time THEN c.from_time ELSE $4 END) AND tel.time_stamp <= (CASE WHEN $5 > c.to_time THEN c.to_time ELSE $5 END)";
             tupleParams = Tuple.of(campaignId, offset, limit, from, to);
         } else if (from != null) {
-            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $4 > c.from_time THEN c.from_time ELSE $4 END) AND tel.time_stamp <= c.to_time";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $4 < c.from_time THEN c.from_time ELSE $4 END) AND tel.time_stamp <= c.to_time";
             tupleParams = Tuple.of(campaignId, offset, limit, from);
         } else if (to != null) {
             whereTimestampClause = "tel.time_stamp >= c.from_time AND tel.time_stamp <= (CASE WHEN $4 > c.to_time THEN c.to_time ELSE $4 END)";
@@ -1308,9 +1307,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -1361,10 +1360,10 @@ public class MapLogRepository implements SensLogRepository {
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
-            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 > c.from_time THEN c.from_time ELSE $5 END) AND tel.time_stamp <= (CASE WHEN $6 > c.to_time THEN c.to_time ELSE $6 END)";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 < c.from_time THEN c.from_time ELSE $5 END) AND tel.time_stamp <= (CASE WHEN $6 > c.to_time THEN c.to_time ELSE $6 END)";
             tupleParams = Tuple.of(campaignId, offset, limit, userIdentity, from, to);
         } else if (from != null) {
-            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 > c.from_time THEN c.from_time ELSE $5 END) AND tel.time_stamp <= c.to_time";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 < c.from_time THEN c.from_time ELSE $5 END) AND tel.time_stamp <= c.to_time";
             tupleParams = Tuple.of(campaignId, offset, limit, userIdentity, from);
         } else if (to != null) {
             whereTimestampClause = "tel.time_stamp >= c.from_time AND tel.time_stamp <= (CASE WHEN $5 > c.to_time THEN c.to_time ELSE $5 END)";
@@ -1388,9 +1387,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -1444,10 +1443,10 @@ public class MapLogRepository implements SensLogRepository {
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
-            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 > utc.from_time THEN utc.from_time ELSE $5 END) AND tel.time_stamp <= (CASE WHEN $6 > utc.to_time THEN utc.to_time ELSE $6 END)";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 < utc.from_time THEN utc.from_time ELSE $5 END) AND tel.time_stamp <= (CASE WHEN $6 > utc.to_time THEN utc.to_time ELSE $6 END)";
             tupleParams = Tuple.of(campaignId, unitId, offset, limit, from, to);
         } else if (from != null) {
-            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 > utc.from_time THEN utc.from_time ELSE $5 END) AND tel.time_stamp <= utc.to_time";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 < utc.from_time THEN utc.from_time ELSE $5 END) AND tel.time_stamp <= utc.to_time";
             tupleParams = Tuple.of(campaignId, unitId, offset, limit, from);
         } else if (to != null) {
             whereTimestampClause = "tel.time_stamp >= utc.from_time AND tel.time_stamp <= (CASE WHEN $5 > utc.to_time THEN utc.to_time ELSE $5 END)";
@@ -1471,9 +1470,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -1522,10 +1521,10 @@ public class MapLogRepository implements SensLogRepository {
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
-            whereTimestampClause = "tel.time_stamp <= (CASE WHEN $6 > utc.to_time THEN utc.to_time ELSE $6 END) AND tel.time_stamp >= (CASE WHEN $7 > utc.from_time THEN utc.from_time ELSE $7 END)";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $6 < utc.from_time THEN utc.from_time ELSE $6 END) AND tel.time_stamp <= (CASE WHEN $7 > utc.to_time THEN utc.to_time ELSE $7 END)";
             tupleParams = Tuple.of(campaignId, unitId, offset, limit, userIdentity, from, to);
         } else if (from != null) {
-            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $6 > utc.from_time THEN utc.from_time ELSE $6 END) AND tel.time_stamp <= utc.to_time";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $6 < utc.from_time THEN utc.from_time ELSE $6 END) AND tel.time_stamp <= utc.to_time";
             tupleParams = Tuple.of(campaignId, unitId, offset, limit, userIdentity, from);
         } else if (to != null) {
             whereTimestampClause = "tel.time_stamp >= utc.from_time AND tel.time_stamp <= (CASE WHEN $6 > utc.to_time THEN utc.to_time ELSE $6 END)";
@@ -1549,9 +1548,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -1600,7 +1599,7 @@ public class MapLogRepository implements SensLogRepository {
     public Future<List<UnitTelemetry>> findObservationsByEventId(
             long eventId, OffsetDateTime from, OffsetDateTime to, int offset, int limit, List<Filter> filters
     ) {
-        String whereTimestampClause;
+        String whereTimestampClause; // TODO check timestamps
         Tuple tupleParams;
         if (from != null && to != null) {
             whereTimestampClause = "tel.time_stamp >= (CASE WHEN $4 < e.from_time THEN $4 ELSE e.from_time END) AND tel.time_stamp <= (CASE WHEN e.to_time IS NULL OR $5 < e.to_time THEN $5 ELSE e.to_time END)";
@@ -1630,9 +1629,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -1679,7 +1678,7 @@ public class MapLogRepository implements SensLogRepository {
     public Future<List<UnitTelemetry>> findObservationsByIdentityAndEventId(
             String userIdentity, long eventId, OffsetDateTime from, OffsetDateTime to, int offset, int limit, List<Filter> filters
     ) {
-        String whereTimestampClause;
+        String whereTimestampClause; // TODO check timestamps
         Tuple tupleParams;
         if (from != null && to != null) {
             whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 < e.from_time THEN $5 ELSE e.from_time END) AND tel.time_stamp <= (CASE WHEN e.to_time IS NULL OR $6 < e.to_time THEN $6 ELSE e.to_time END)";
@@ -1709,9 +1708,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -1764,10 +1763,10 @@ public class MapLogRepository implements SensLogRepository {
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
-            whereTimestampClause = "tel.time_stamp <= (CASE WHEN $6 > utc.to_time THEN utc.to_time ELSE $6 END) AND tel.time_stamp >= (CASE WHEN $7 > utc.from_time THEN utc.from_time ELSE $7 END)";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $6 < utc.from_time THEN utc.from_time ELSE $6 END) AND tel.time_stamp <= (CASE WHEN $7 > utc.to_time THEN utc.to_time ELSE $7 END)";
             tupleParams = Tuple.of(campaignId, unitId, sensorId, offset, limit, from, to);
         } else if (from != null) {
-            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $6 > utc.from_time THEN utc.from_time ELSE $6 END) AND tel.time_stamp <= utc.to_time";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $6 < utc.from_time THEN utc.from_time ELSE $6 END) AND tel.time_stamp <= utc.to_time";
             tupleParams = Tuple.of(campaignId, unitId, sensorId, offset, limit, from);
         } else if (to != null) {
             whereTimestampClause = "tel.time_stamp >= utc.from_time AND tel.time_stamp <= (CASE WHEN $6 > utc.to_time THEN utc.to_time ELSE $6 END)";
@@ -1791,9 +1790,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -1835,10 +1834,10 @@ public class MapLogRepository implements SensLogRepository {
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
-            whereTimestampClause = "tel.time_stamp <= (CASE WHEN $7 > utc.to_time THEN utc.to_time ELSE $7 END) AND tel.time_stamp >= (CASE WHEN $8 > utc.from_time THEN utc.from_time ELSE $8 END)";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $7 < utc.from_time THEN utc.from_time ELSE $7 END) AND tel.time_stamp <= (CASE WHEN $8 > utc.to_time THEN utc.to_time ELSE $8 END)";
             tupleParams = Tuple.of(campaignId, unitId, sensorId, offset, limit, userIdentity, from, to);
         } else if (from != null) {
-            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $7 > utc.from_time THEN utc.from_time ELSE $7 END) AND tel.time_stamp <= utc.to_time";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $7 < utc.from_time THEN utc.from_time ELSE $7 END) AND tel.time_stamp <= utc.to_time";
             tupleParams = Tuple.of(campaignId, unitId, sensorId, offset, limit, userIdentity, from);
         } else if (to != null) {
             whereTimestampClause = "tel.time_stamp >= utc.from_time AND tel.time_stamp <= (CASE WHEN $7 > utc.to_time THEN utc.to_time ELSE $7 END)";
@@ -1862,9 +1861,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -1910,10 +1909,10 @@ public class MapLogRepository implements SensLogRepository {
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
-            whereTimestampClause = "tel.time_stamp <= (CASE WHEN $5 > utc.to_time THEN utc.to_time ELSE $5 END) AND tel.time_stamp >= (CASE WHEN $6 > utc.from_time THEN utc.from_time ELSE $6 END)";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 < utc.from_time THEN utc.from_time ELSE $5 END) AND tel.time_stamp <= (CASE WHEN $6 > utc.to_time THEN utc.to_time ELSE $6 END)";
             tupleParams = Tuple.of(campaignId, unitId, offset, limit, from, to);
         } else if (from != null) {
-            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 > utc.from_time THEN utc.from_time ELSE $5 END) AND tel.time_stamp <= utc.to_time";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 < utc.from_time THEN utc.from_time ELSE $5 END) AND tel.time_stamp <= utc.to_time";
             tupleParams = Tuple.of(campaignId, unitId, offset, limit, from);
         } else if (to != null) {
             whereTimestampClause = "tel.time_stamp >= utc.from_time AND tel.time_stamp <= (CASE WHEN $5 > utc.to_time THEN utc.to_time ELSE $5 END)";
@@ -1937,10 +1936,10 @@ public class MapLogRepository implements SensLogRepository {
                        }
                    }
                 case SENSOR -> {
-                       switch (filter.getAttribute()) {
-                            case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                    .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
-                                    .ifPresent(whereFiltersClause::append);
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
+                                .ifPresent(whereFiltersClause::append);
                     }
                 }
             }
@@ -1979,10 +1978,10 @@ public class MapLogRepository implements SensLogRepository {
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
-            whereTimestampClause = "tel.time_stamp <= (CASE WHEN $6 > utc.to_time THEN utc.to_time ELSE $6 END) AND tel.time_stamp >= (CASE WHEN $7 > utc.from_time THEN utc.from_time ELSE $7 END)";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $6 < utc.from_time THEN utc.from_time ELSE $6 END) AND tel.time_stamp <= (CASE WHEN $7 > utc.to_time THEN utc.to_time ELSE $7 END)";
             tupleParams = Tuple.of(campaignId, unitId, offset, limit, userIdentity, from, to);
         } else if (from != null) {
-            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $6 > utc.from_time THEN utc.from_time ELSE $6 END) AND tel.time_stamp <= utc.to_time";
+            whereTimestampClause = "tel.time_stamp >= (CASE WHEN $6 < utc.from_time THEN utc.from_time ELSE $6 END) AND tel.time_stamp <= utc.to_time";
             tupleParams = Tuple.of(campaignId, unitId, offset, limit, userIdentity, from);
         } else if (to != null) {
             whereTimestampClause = "tel.time_stamp >= utc.from_time AND tel.time_stamp <= (CASE WHEN $6 > utc.to_time THEN utc.to_time ELSE $6 END)";
@@ -2006,9 +2005,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -2048,7 +2047,7 @@ public class MapLogRepository implements SensLogRepository {
     public Future<List<UnitLocation>> findLocationsByEventId(
             long eventId, OffsetDateTime from, OffsetDateTime to, int offset, int limit, List<Filter> filters
     ) {
-        String whereTimestampClause;
+        String whereTimestampClause; // TODO check timestamps
         Tuple tupleParams;
         if (from != null && to != null) {
             whereTimestampClause = "tel.time_stamp >= (CASE WHEN $4 < e.from_time THEN $4 ELSE e.from_time END) AND tel.time_stamp <= (CASE WHEN e.to_time IS NULL OR $5 < e.to_time THEN $5 ELSE e.to_time END)";
@@ -2078,9 +2077,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -2116,7 +2115,7 @@ public class MapLogRepository implements SensLogRepository {
     public Future<List<UnitLocation>> findLocationsByIdentityAndEventId(
             String userIdentity, long eventId, OffsetDateTime from, OffsetDateTime to, int offset, int limit, List<Filter> filters
     ) {
-        String whereTimestampClause;
+        String whereTimestampClause; // TODO check timestamps
         Tuple tupleParams;
         if (from != null && to != null) {
             whereTimestampClause = "tel.time_stamp >= (CASE WHEN $5 < e.from_time THEN $5 ELSE e.from_time END) AND tel.time_stamp <= (CASE WHEN e.to_time IS NULL OR $6 < e.to_time THEN $6 ELSE e.to_time END)";
@@ -2146,9 +2145,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (tel.observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -2216,9 +2215,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -2283,9 +2282,9 @@ public class MapLogRepository implements SensLogRepository {
                     }
                 }
                 case SENSOR -> {
-                    switch (filter.getAttribute()) {
-                        case ID          -> of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
-                                .map(p -> format(" AND (observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size()-1, opt, p.size()))
+                    if (Objects.requireNonNull(filter.getAttribute()) == FilterAttribute.ID) {
+                        of(tupleParams.addLong(filter.getAttributeValueAsLong()).addFloat(optValue))
+                                .map(p -> format(" AND (observed_values::jsonb ->> $%d::bigint::text::varchar)::double precision %s $%d", p.size() - 1, opt, p.size()))
                                 .ifPresent(whereFiltersClause::append);
                     }
                 }
@@ -2413,7 +2412,7 @@ public class MapLogRepository implements SensLogRepository {
                         "WHERE e.from_time <= a.time_stamp AND (CASE WHEN e.to_time IS NULL THEN now() ELSE e.to_time END) >= a.time_stamp " +
                             "AND e.id = $1 AND a.status = ANY($2) " +
                         "ORDER BY a.time_stamp "+sortType.name())
-                .execute(Tuple.of(eventId, statusFilter))
+                .execute(Tuple.of(eventId, (Object) statusFilter.toArray(AlertStatus[]::new)))
                 .map(rs -> StreamSupport.stream(rs.spliterator(), false)
                         .map(r -> Alert.of(
                                 r.getLong("id"),
@@ -2495,20 +2494,22 @@ public class MapLogRepository implements SensLogRepository {
             statusFilter = Set.of(AlertStatus.CREATED, AlertStatus.INFORMED, AlertStatus.IN_PROCESS, AlertStatus.SOLVED);
         }
 
+        AlertStatus[] statuses = statusFilter.toArray(AlertStatus[]::new);
+
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
             whereTimestampClause = "WHERE utc.campaign_id = $1 AND a.status = ANY($2) AND a.time_stamp >= (CASE WHEN utc.from_time > $3 THEN utc.from_time ELSE $3 END) AND a.time_stamp <= (CASE WHEN utc.to_time < $4 THEN utc.to_time ELSE $4 END)";
-            tupleParams = Tuple.of(campaignId, statusFilter, from, to);
+            tupleParams = Tuple.of(campaignId, statuses, from, to);
         } else if (from != null) {
             whereTimestampClause = "WHERE utc.campaign_id = $1 AND a.status = ANY($2) AND a.time_stamp >= (CASE WHEN utc.from_time > $3 THEN utc.from_time ELSE $3 END) AND a.time_stamp <= utc.to_time";
-            tupleParams = Tuple.of(campaignId, statusFilter, from);
+            tupleParams = Tuple.of(campaignId, statuses, from);
         } else if (to != null) {
             whereTimestampClause = "WHERE utc.campaign_id = $1 AND a.status = ANY($2) AND a.time_stamp >= utc.from_time AND a.time_stamp <= (CASE WHEN utc.to_time < $3 THEN utc.to_time ELSE $3 END)";
-            tupleParams = Tuple.of(campaignId, statusFilter, to);
+            tupleParams = Tuple.of(campaignId, statuses, to);
         } else {
             whereTimestampClause = "WHERE utc.campaign_id = $1 AND a.status = ANY($2)";
-            tupleParams = Tuple.of(campaignId, statusFilter);
+            tupleParams = Tuple.of(campaignId, (Object) statuses);
         }
 
         return client.preparedQuery("SELECT a.id, utc.campaign_id, a.unit_id, a.message, a.time_stamp, a.status FROM maplog.alert AS a " +
@@ -2528,25 +2529,29 @@ public class MapLogRepository implements SensLogRepository {
     }
 
     @Override
-    public Future<List<CampaignUnitAlert>> findAlertsByIdentityAndCampaignId(String userIdentity, long campaignId, OffsetDateTime from, OffsetDateTime to, Set<AlertStatus> statusFilter, SortType sort) {
+    public Future<List<CampaignUnitAlert>> findAlertsByIdentityAndCampaignId(
+            String userIdentity, long campaignId, OffsetDateTime from, OffsetDateTime to, Set<AlertStatus> statusFilter, SortType sort
+    ) {
         if (statusFilter.isEmpty()) {
             statusFilter = Set.of(AlertStatus.CREATED, AlertStatus.INFORMED, AlertStatus.IN_PROCESS, AlertStatus.SOLVED);
         }
 
+        AlertStatus[] statuses = statusFilter.toArray(AlertStatus[]::new);
+
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
             whereTimestampClause = "utc.campaign_id = $1 AND su.identity = $2 AND a.status = ANY($3) AND a.time_stamp >= (CASE WHEN utc.from_time > $4 THEN utc.from_time ELSE $4 END) AND a.time_stamp <= (CASE WHEN utc.to_time < $5 THEN utc.to_time ELSE $5 END)";
-            tupleParams = Tuple.of(campaignId, userIdentity, statusFilter.toArray(AlertStatus[]::new), from, to);
+            tupleParams = Tuple.of(campaignId, userIdentity, statuses, from, to);
         } else if (from != null) {
             whereTimestampClause = "utc.campaign_id = $1 AND su.identity = $2 AND a.status = ANY($3) AND a.time_stamp >= (CASE WHEN utc.from_time > $4 THEN utc.from_time ELSE $4 END) AND a.time_stamp <= utc.to_time";
-            tupleParams = Tuple.of(campaignId, userIdentity, statusFilter.toArray(AlertStatus[]::new), from);
+            tupleParams = Tuple.of(campaignId, userIdentity, statuses, from);
         } else if (to != null) {
             whereTimestampClause = "utc.campaign_id = $1 AND su.identity = $2 AND a.status = ANY($3) AND a.time_stamp >= utc.from_time AND a.time_stamp <= (CASE WHEN utc.to_time < $4 THEN utc.to_time ELSE $4 END)";
-            tupleParams = Tuple.of(campaignId, userIdentity, statusFilter.toArray(AlertStatus[]::new), to);
+            tupleParams = Tuple.of(campaignId, userIdentity, statuses, to);
         } else {
             whereTimestampClause = "utc.campaign_id = $1 AND su.identity = $2 AND a.status = ANY($3)";
-            tupleParams = Tuple.of(campaignId, userIdentity, statusFilter.toArray(AlertStatus[]::new));
+            tupleParams = Tuple.of(campaignId, userIdentity, statuses);
         }
 
         return client.preparedQuery("SELECT a.id, utc.campaign_id, a.unit_id, a.message, a.time_stamp, a.status FROM maplog.alert AS a " +
@@ -2570,26 +2575,29 @@ public class MapLogRepository implements SensLogRepository {
     }
 
     @Override
-    public Future<List<UnitAlert>> findAlertsByCampaignIdAndUnitId(long campaignId, long unitId, OffsetDateTime from, OffsetDateTime to, Set<AlertStatus> statusFilter, SortType sort) {
-
+    public Future<List<UnitAlert>> findAlertsByCampaignIdAndUnitId(
+            long campaignId, long unitId, OffsetDateTime from, OffsetDateTime to, Set<AlertStatus> statusFilter, SortType sort
+    ) {
         if (statusFilter.isEmpty()) {
             statusFilter = Set.of(AlertStatus.CREATED, AlertStatus.INFORMED, AlertStatus.IN_PROCESS, AlertStatus.SOLVED);
         }
 
+        AlertStatus[] statuses = statusFilter.toArray(AlertStatus[]::new);
+
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
             whereTimestampClause = "WHERE utc.campaign_id = $1 AND utc.unit_id = $2 AND a.status = ANY($3) AND a.time_stamp >= (CASE WHEN utc.from_time > $4 THEN utc.from_time ELSE $4 END) AND a.time_stamp <= (CASE WHEN utc.to_time < $5 THEN utc.to_time ELSE $5 END)";
-            tupleParams = Tuple.of(campaignId, unitId, statusFilter, from, to);
+            tupleParams = Tuple.of(campaignId, unitId, statuses, from, to);
         } else if (from != null) {
             whereTimestampClause = "WHERE utc.campaign_id = $1 AND utc.unit_id = $2 AND a.status = ANY($3) AND a.time_stamp >= (CASE WHEN utc.from_time > $4 THEN utc.from_time ELSE $4 END) AND a.time_stamp <= utc.to_time";
-            tupleParams = Tuple.of(campaignId, unitId, statusFilter, from);
+            tupleParams = Tuple.of(campaignId, unitId, statuses, from);
         } else if (to != null) {
             whereTimestampClause = "WHERE utc.campaign_id = $1 AND utc.unit_id = $2 AND a.status = ANY($3) AND a.time_stamp >= utc.from_time AND a.time_stamp <= (CASE WHEN utc.to_time < $4 THEN utc.to_time ELSE $4 END)";
-            tupleParams = Tuple.of(campaignId, unitId, statusFilter, to);
+            tupleParams = Tuple.of(campaignId, unitId, statuses, to);
         } else {
             whereTimestampClause = "WHERE utc.campaign_id = $1 AND utc.unit_id = $2 AND a.status = ANY($3)";
-            tupleParams = Tuple.of(campaignId, unitId, statusFilter);
+            tupleParams = Tuple.of(campaignId, unitId, statuses);
         }
 
         return client.preparedQuery("SELECT a.id, a.unit_id, a.message, a.time_stamp, a.status FROM maplog.alert AS a " +
@@ -2608,25 +2616,29 @@ public class MapLogRepository implements SensLogRepository {
     }
 
     @Override
-    public Future<List<UnitAlert>> findAlertsByIdentityAndCampaignIdAndUnitId(String userIdentity, long campaignId, long unitId, OffsetDateTime from, OffsetDateTime to, Set<AlertStatus> statusFilter, SortType sort) {
+    public Future<List<UnitAlert>> findAlertsByIdentityAndCampaignIdAndUnitId(
+            String userIdentity, long campaignId, long unitId, OffsetDateTime from, OffsetDateTime to, Set<AlertStatus> statusFilter, SortType sort
+    ) {
         if (statusFilter.isEmpty()) {
             statusFilter = Set.of(AlertStatus.CREATED, AlertStatus.INFORMED, AlertStatus.IN_PROCESS, AlertStatus.SOLVED);
         }
 
+        AlertStatus[] statuses = statusFilter.toArray(AlertStatus[]::new);
+
         String whereTimestampClause;
         Tuple tupleParams;
         if (from != null && to != null) {
             whereTimestampClause = "utc.campaign_id = $1 AND utc.unit_id = $2 AND su.identity = $3 AND a.status = ANY($4) AND a.time_stamp >= (CASE WHEN utc.from_time > $5 THEN utc.from_time ELSE $5 END) AND a.time_stamp <= (CASE WHEN utc.to_time < $6 THEN utc.to_time ELSE $6 END)";
-            tupleParams = Tuple.of(campaignId, unitId, userIdentity, statusFilter.toArray(AlertStatus[]::new), from, to);
+            tupleParams = Tuple.of(campaignId, unitId, userIdentity, statuses, from, to);
         } else if (from != null) {
             whereTimestampClause = "utc.campaign_id = $1 AND utc.unit_id = $2 AND su.identity = $3 AND a.status = ANY($4) AND a.time_stamp >= (CASE WHEN utc.from_time > $5 THEN utc.from_time ELSE $5 END) AND a.time_stamp <= utc.to_time";
-            tupleParams = Tuple.of(campaignId, unitId, userIdentity, statusFilter.toArray(AlertStatus[]::new), from);
+            tupleParams = Tuple.of(campaignId, unitId, userIdentity, statuses, from);
         } else if (to != null) {
             whereTimestampClause = "utc.campaign_id = $1 AND utc.unit_id = $2 AND su.identity = $3 AND a.status = ANY($4) AND a.time_stamp >= utc.from_time AND a.time_stamp <= (CASE WHEN utc.to_time < $5 THEN utc.to_time ELSE $5 END)";
-            tupleParams = Tuple.of(campaignId, unitId, userIdentity, statusFilter.toArray(AlertStatus[]::new), to);
+            tupleParams = Tuple.of(campaignId, unitId, userIdentity, statuses, to);
         } else {
             whereTimestampClause = "utc.campaign_id = $1 AND utc.unit_id = $2 AND su.identity = $3 AND a.status = ANY($4)";
-            tupleParams = Tuple.of(campaignId, unitId, userIdentity, statusFilter.toArray(AlertStatus[]::new));
+            tupleParams = Tuple.of(campaignId, unitId, userIdentity, statuses);
         }
 
         return client.preparedQuery("SELECT a.id, a.unit_id, a.message, a.time_stamp, a.status FROM maplog.alert AS a " +
@@ -2661,7 +2673,7 @@ public class MapLogRepository implements SensLogRepository {
                             "AND e.from_time <= a.time_stamp AND (CASE WHEN e.to_time IS NULL THEN now() ELSE e.to_time END) >= a.time_stamp " +
                             "AND a.status = ANY($4)" +
                         "ORDER BY a.time_stamp "+sort.name())
-                .execute(Tuple.of(entityId, actionId, unitId, statusFilter))
+                .execute(Tuple.of(entityId, actionId, unitId, statusFilter.toArray(AlertStatus[]::new)))
                 .map(rs -> StreamSupport.stream(rs.spliterator(), false)
                         .map(r -> Alert.of(
                                 r.getLong("id"),

+ 4 - 2
src/main/java/cz/senslog/telemetry/database/validation/UnitTelemetryValidation.java

@@ -16,11 +16,13 @@ import static java.util.stream.Collectors.*;
 public class UnitTelemetryValidation {
 
     public static boolean isTelemetryWithinCampaign(Campaign campaign, UnitTelemetry telemetry) {
-        return ofBoundary(campaign.getFromTime(), campaign.getToTime()).isWithinEqual(telemetry.getTimestamp());
+        OffsetDateTime toTime = campaign.getToTime() != null ? campaign.getToTime() : OffsetDateTime.now();
+        return ofBoundary(campaign.getFromTime(), toTime).isWithinEqual(telemetry.getTimestamp());
     }
 
     public static List<UnitTelemetry> telemetriesWithinCampaign(Campaign campaign, List<UnitTelemetry> telemetries) {
-        ComparisonOperators.BoundaryComparison campBound = ofBoundary(campaign.getFromTime(), campaign.getToTime());
+        OffsetDateTime toTime = campaign.getToTime() != null ? campaign.getToTime() : OffsetDateTime.now();
+        ComparisonOperators.BoundaryComparison campBound = ofBoundary(campaign.getFromTime(), toTime);
         OffsetDateTime firstTelTime = telemetries.get(0).getTimestamp();
         OffsetDateTime lastTelTime = telemetries.get(telemetries.size() - 1).getTimestamp();