// Proceed with query
//
String itemName = filter.getItemName();
+ if (itemName == null) {
+ logger.warn("Item name is missing in filter {}", filter);
+ return List.of();
+ }
Item item = getItemFromRegistry(itemName);
if (item == null) {
logger.warn("Could not get item {} from registry! Returning empty query results.", itemName);
}
QueryEnhancedRequest.Builder queryBuilder = QueryEnhancedRequest.builder()
.scanIndexForward(filter.getOrdering() == Ordering.ASCENDING);
- addFilterbyItemAndTimeFilter(queryBuilder, expectedTableSchema, filter.getItemName(), filter);
+ String itemName = filter.getItemName();
+ if (itemName == null) {
+ throw new IllegalArgumentException("Item name not set");
+ }
+ addFilterbyItemAndTimeFilter(queryBuilder, expectedTableSchema, itemName, filter);
addStateFilter(queryBuilder, expectedTableSchema, item, dtoClass, filter);
addProjection(dtoClass, expectedTableSchema, queryBuilder);
return queryBuilder.build();
private static void addFilterbyItemAndTimeFilter(QueryEnhancedRequest.Builder queryBuilder,
ExpectedTableSchema expectedTableSchema, String partition, final FilterCriteria filter) {
- boolean hasBegin = filter.getBeginDate() != null;
- boolean hasEnd = filter.getEndDate() != null;
+ ZonedDateTime begin = filter.getBeginDate();
+ ZonedDateTime end = filter.getEndDate();
boolean legacy = expectedTableSchema == ExpectedTableSchema.LEGACY;
AttributeConverter<ZonedDateTime> timeConverter = AbstractDynamoDBItem.getTimestampConverter(legacy);
- if (!hasBegin && !hasEnd) {
- // No need to place time filter filter but we do filter by partition
+ if (begin == null && end == null) {
+ // No need to place time filter, but we do filter by partition
queryBuilder.queryConditional(QueryConditional.keyEqualTo(k -> k.partitionValue(partition)));
- } else if (hasBegin && !hasEnd) {
- queryBuilder.queryConditional(QueryConditional.sortGreaterThan(
- k -> k.partitionValue(partition).sortValue(timeConverter.transformFrom(filter.getBeginDate()))));
- } else if (!hasBegin && hasEnd) {
- queryBuilder.queryConditional(QueryConditional.sortLessThan(
- k -> k.partitionValue(partition).sortValue(timeConverter.transformFrom(filter.getEndDate()))));
- } else {
- assert hasBegin && hasEnd; // invariant
+ } else if (begin != null && end == null) {
+ queryBuilder.queryConditional(QueryConditional
+ .sortGreaterThan(k -> k.partitionValue(partition).sortValue(timeConverter.transformFrom(begin))));
+ } else if (begin == null && end != null) {
+ queryBuilder.queryConditional(QueryConditional
+ .sortLessThan(k -> k.partitionValue(partition).sortValue(timeConverter.transformFrom(end))));
+ } else if (begin != null && end != null) {
queryBuilder.queryConditional(QueryConditional.sortBetween(
- k -> k.partitionValue(partition).sortValue(timeConverter.transformFrom(filter.getBeginDate())),
- k -> k.partitionValue(partition).sortValue(timeConverter.transformFrom(filter.getEndDate()))));
+ k -> k.partitionValue(partition).sortValue(timeConverter.transformFrom(begin)),
+ k -> k.partitionValue(partition).sortValue(timeConverter.transformFrom(end))));
}
}
FilterCriteria criteria = new FilterCriteria();
criteria.setOperator(Operator.GT);
- criteria.setState(getQueryItemStateBetween());
+ State filterState = getQueryItemStateBetween();
+ if (filterState != null) {
+ criteria.setState(filterState);
+ }
criteria.setItemName(getItemName());
criteria.setBeginDate(beforeStore);
criteria.setEndDate(afterStore2);
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
waitForAssert(() -> {
FilterCriteria criteria = new FilterCriteria();
criteria.setItemName(NAME);
- criteria.setBeginDate(storeStart);
+ criteria.setBeginDate(Objects.requireNonNull(storeStart));
criteria.setOrdering(Ordering.ASCENDING);
criteria.setPageNumber(0);
criteria.setPageSize(3);
waitForAssert(() -> {
FilterCriteria criteria = new FilterCriteria();
criteria.setItemName(NAME);
- criteria.setBeginDate(storeStart);
+ criteria.setBeginDate(Objects.requireNonNull(storeStart));
criteria.setOrdering(Ordering.ASCENDING);
criteria.setPageNumber(1);
criteria.setPageSize(3);
waitForAssert(() -> {
FilterCriteria criteria = new FilterCriteria();
criteria.setItemName(NAME);
- criteria.setBeginDate(storeStart);
+ criteria.setBeginDate(Objects.requireNonNull(storeStart));
criteria.setOrdering(Ordering.ASCENDING);
criteria.setPageNumber(3);
criteria.setPageSize(3);
waitForAssert(() -> {
FilterCriteria criteria = new FilterCriteria();
criteria.setItemName(NAME);
- criteria.setBeginDate(storeStart);
+ criteria.setBeginDate(Objects.requireNonNull(storeStart));
criteria.setOrdering(Ordering.ASCENDING);
criteria.setPageNumber(4);
criteria.setPageSize(3);
waitForAssert(() -> {
FilterCriteria criteria = new FilterCriteria();
criteria.setItemName(NAME);
- criteria.setBeginDate(storeStart);
+ criteria.setBeginDate(Objects.requireNonNull(storeStart));
criteria.setOrdering(Ordering.DESCENDING);
criteria.setPageNumber(0);
criteria.setPageSize(3);
waitForAssert(() -> {
FilterCriteria criteria = new FilterCriteria();
criteria.setItemName(NAME);
- criteria.setBeginDate(storeStart);
+ criteria.setBeginDate(Objects.requireNonNull(storeStart));
criteria.setOrdering(Ordering.ASCENDING);
criteria.setPageNumber(0);
criteria.setPageSize(900);
waitForAssert(() -> {
FilterCriteria criteria = new FilterCriteria();
criteria.setItemName(NAME);
- criteria.setBeginDate(storeStart);
+ criteria.setBeginDate(Objects.requireNonNull(storeStart));
criteria.setOrdering(Ordering.ASCENDING);
criteria.setPageNumber(0);
criteria.setPageSize(3);
FilterCriteria criteria = new FilterCriteria();
criteria.setOrdering(Ordering.ASCENDING);
criteria.setItemName(item);
- criteria.setOperator(operator);
- criteria.setState(state);
+ if (operator != null) {
+ criteria.setOperator(operator);
+ }
+ if (state != null) {
+ criteria.setState(state);
+ }
@SuppressWarnings("null")
Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
List<State> actualStatesList = new ArrayList<>();
"Query-Filter: itemname: {}, ordering: {}, state: {}, operator: {}, getBeginDate: {}, getEndDate: {}, getPageSize: {}, getPageNumber: {}",
filter.getItemName(), filter.getOrdering().toString(), filter.getState(), filter.getOperator(),
filter.getBeginDate(), filter.getEndDate(), filter.getPageSize(), filter.getPageNumber());
+ if (filter.getItemName() == null) {
+ logger.warn("Item name is missing in filter {}", filter);
+ return List.of();
+ }
String query = influxDBRepository.createQueryCreator().createQuery(filter,
configuration.getRetentionPolicy());
logger.trace("Query {}", query);
import static org.openhab.persistence.influxdb.internal.InfluxDBConstants.*;
import static org.openhab.persistence.influxdb.internal.InfluxDBStateConvertUtils.stateToObject;
+import java.util.Objects;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.influxdb.dto.Query;
import org.influxdb.querybuilder.Where;
import org.influxdb.querybuilder.clauses.SimpleClause;
import org.openhab.core.persistence.FilterCriteria;
+import org.openhab.core.types.State;
import org.openhab.persistence.influxdb.internal.FilterCriteriaQueryCreator;
import org.openhab.persistence.influxdb.internal.InfluxDBConfiguration;
import org.openhab.persistence.influxdb.internal.InfluxDBMetadataService;
@Override
public String createQuery(FilterCriteria criteria, String retentionPolicy) {
- final String itemName = criteria.getItemName();
+ final String itemName = Objects.requireNonNull(criteria.getItemName()); // we checked non-null before
final String tableName = getTableName(itemName);
final boolean hasCriteriaName = itemName != null;
where.and(BuiltQuery.QueryBuilder.lte(COLUMN_TIME_NAME_V1, criteria.getEndDate().toInstant().toString()));
}
- if (criteria.getState() != null && criteria.getOperator() != null) {
+ State filterState = criteria.getState();
+ if (filterState != null && criteria.getOperator() != null) {
where.and(new SimpleClause(COLUMN_VALUE_NAME_V1,
- getOperationSymbol(criteria.getOperator(), InfluxDBVersion.V1),
- stateToObject(criteria.getState())));
+ getOperationSymbol(criteria.getOperator(), InfluxDBVersion.V1), stateToObject(filterState)));
}
if (criteria.getOrdering() == FilterCriteria.Ordering.DESCENDING) {
import static org.openhab.persistence.influxdb.internal.InfluxDBStateConvertUtils.stateToObject;
import java.time.temporal.ChronoUnit;
+import java.util.Objects;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.persistence.FilterCriteria;
+import org.openhab.core.types.State;
import org.openhab.persistence.influxdb.internal.FilterCriteriaQueryCreator;
import org.openhab.persistence.influxdb.internal.InfluxDBConfiguration;
import org.openhab.persistence.influxdb.internal.InfluxDBMetadataService;
}
flux = range;
- String itemName = criteria.getItemName();
- if (itemName != null) {
- String name = influxDBMetadataService.getMeasurementNameOrDefault(itemName, itemName);
- String measurementName = configuration.isReplaceUnderscore() ? name.replace('_', '.') : name;
- flux = flux.filter(measurement().equal(measurementName));
- if (!measurementName.equals(itemName)) {
- flux = flux.filter(tag(TAG_ITEM_NAME).equal(itemName));
- flux = flux.keep(new String[] { FIELD_MEASUREMENT_NAME, COLUMN_TIME_NAME_V2, COLUMN_VALUE_NAME_V2,
- TAG_ITEM_NAME });
- } else {
- flux = flux.keep(new String[] { FIELD_MEASUREMENT_NAME, COLUMN_TIME_NAME_V2, COLUMN_VALUE_NAME_V2 });
- }
+ String itemName = Objects.requireNonNull(criteria.getItemName()); // we checked non-null before
+ String name = influxDBMetadataService.getMeasurementNameOrDefault(itemName, itemName);
+ String measurementName = configuration.isReplaceUnderscore() ? name.replace('_', '.') : name;
+ flux = flux.filter(measurement().equal(measurementName));
+ if (!measurementName.equals(itemName)) {
+ flux = flux.filter(tag(TAG_ITEM_NAME).equal(itemName));
+ flux = flux.keep(
+ new String[] { FIELD_MEASUREMENT_NAME, COLUMN_TIME_NAME_V2, COLUMN_VALUE_NAME_V2, TAG_ITEM_NAME });
+ } else {
+ flux = flux.keep(new String[] { FIELD_MEASUREMENT_NAME, COLUMN_TIME_NAME_V2, COLUMN_VALUE_NAME_V2 });
}
- if (criteria.getState() != null && criteria.getOperator() != null) {
+ State filterState = criteria.getState();
+ if (filterState != null && criteria.getOperator() != null) {
Restrictions restrictions = Restrictions.and(Restrictions.field().equal(FIELD_VALUE_NAME),
- Restrictions.value().custom(stateToObject(criteria.getState()),
+ Restrictions.value().custom(stateToObject(filterState),
getOperationSymbol(criteria.getOperator(), InfluxDBVersion.V2)));
flux = flux.filter(restrictions);
}
FilterCriteria criteria = createBaseCriteria();
String queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY);
- assertThat(queryV1, equalTo("SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\";"));
+ assertThat(queryV1,
+ equalTo("SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" ORDER BY time DESC;"));
String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY);
assertThat(queryV2, equalTo("""
from(bucket:"origin")
\t|> range(start:-100y, stop:100y)
\t|> filter(fn: (r) => r["_measurement"] == "sampleItem")
- \t|> keep(columns:["_measurement", "_time", "_value"])"""));
- }
-
- @Test
- public void testSimpleUnboundedItemWithoutParams() {
- FilterCriteria criteria = new FilterCriteria();
- criteria.setOrdering(null);
-
- String queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY);
- assertThat(queryV1, equalTo("SELECT \"value\"::field,\"item\"::tag FROM \"origin\"./.*/;"));
-
- String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY);
- assertThat(queryV2, equalTo("from(bucket:\"origin\")\n\t" + "|> range(start:-100y, stop:100y)"));
+ \t|> keep(columns:["_measurement", "_time", "_value"])
+ \t|> sort(desc:true, columns:["_time"])"""));
}
@Test
String queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY);
String expectedQueryV1 = String.format(
- "SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" WHERE time >= '%s' AND time <= '%s';",
+ "SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" WHERE time >= '%s' AND time <= '%s' ORDER BY time DESC;",
now.toInstant(), tomorrow.toInstant());
assertThat(queryV1, equalTo(expectedQueryV1));
from(bucket:"origin")
\t|> range(start:%s, stop:%s)
\t|> filter(fn: (r) => r["_measurement"] == "sampleItem")
- \t|> keep(columns:["_measurement", "_time", "_value"])""",
- INFLUX2_DATE_FORMATTER.format(now.toInstant()), INFLUX2_DATE_FORMATTER.format(tomorrow.toInstant()));
+ \t|> keep(columns:["_measurement", "_time", "_value"])
+ \t|> sort(desc:true, columns:["_time"])""", INFLUX2_DATE_FORMATTER.format(now.toInstant()),
+ INFLUX2_DATE_FORMATTER.format(tomorrow.toInstant()));
assertThat(queryV2, equalTo(expectedQueryV2));
}
criteria.setState(new PercentType(90));
String query = instanceV1.createQuery(criteria, RETENTION_POLICY);
- assertThat(query,
- equalTo("SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" WHERE value <= 90;"));
+ assertThat(query, equalTo(
+ "SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" WHERE value <= 90 ORDER BY time DESC;"));
String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY);
assertThat(queryV2, equalTo("""
\t|> range(start:-100y, stop:100y)
\t|> filter(fn: (r) => r["_measurement"] == "sampleItem")
\t|> keep(columns:["_measurement", "_time", "_value"])
- \t|> filter(fn: (r) => (r["_field"] == "value" and r["_value"] <= 90))"""));
+ \t|> filter(fn: (r) => (r["_field"] == "value" and r["_value"] <= 90))
+ \t|> sort(desc:true, columns:["_time"])"""));
}
@Test
criteria.setPageSize(10);
String query = instanceV1.createQuery(criteria, RETENTION_POLICY);
- assertThat(query,
- equalTo("SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" LIMIT 10 OFFSET 20;"));
+ assertThat(query, equalTo(
+ "SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" ORDER BY time DESC LIMIT 10 OFFSET 20;"));
String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY);
assertThat(queryV2, equalTo("""
\t|> range(start:-100y, stop:100y)
\t|> filter(fn: (r) => r["_measurement"] == "sampleItem")
\t|> keep(columns:["_measurement", "_time", "_value"])
+ \t|> sort(desc:true, columns:["_time"])
\t|> limit(n:10, offset:20)"""));
}
private FilterCriteria createBaseCriteria() {
FilterCriteria criteria = new FilterCriteria();
criteria.setItemName(ITEM_NAME);
- criteria.setOrdering(null);
return criteria;
}
String queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY);
assertThat(queryV1, equalTo(
- "SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"measurementName\" WHERE item = 'sampleItem';"));
+ "SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"measurementName\" WHERE item = 'sampleItem' ORDER BY time DESC;"));
String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY);
assertThat(queryV2, equalTo("""
\t|> range(start:-100y, stop:100y)
\t|> filter(fn: (r) => r["_measurement"] == "measurementName")
\t|> filter(fn: (r) => r["item"] == "sampleItem")
- \t|> keep(columns:["_measurement", "_time", "_value", "item"])"""));
+ \t|> keep(columns:["_measurement", "_time", "_value", "item"])
+ \t|> sort(desc:true, columns:["_time"])"""));
when(metadataRegistry.get(metadataKey))
.thenReturn(new Metadata(metadataKey, "", Map.of("key1", "val1", "key2", "val2")));
queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY);
- assertThat(queryV1, equalTo("SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\";"));
+ assertThat(queryV1,
+ equalTo("SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" ORDER BY time DESC;"));
queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY);
assertThat(queryV2, equalTo("""
from(bucket:"origin")
\t|> range(start:-100y, stop:100y)
\t|> filter(fn: (r) => r["_measurement"] == "sampleItem")
- \t|> keep(columns:["_measurement", "_time", "_value"])"""));
+ \t|> keep(columns:["_measurement", "_time", "_value"])
+ \t|> sort(desc:true, columns:["_time"])"""));
}
}
// Also get the Item object so we can determine the type
Item item = null;
String itemName = filter.getItemName();
+ if (itemName == null) {
+ logger.warn("Item name is missing in filter {}", filter);
+ return List.of();
+ }
logger.debug("JDBC::query: item is {}", itemName);
try {
item = itemRegistry.getItem(itemName);
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
+import java.util.Objects;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.BeforeEach;
String sql = jdbcBaseDAO.histItemFilterQueryProvider(filter, 0, DB_TABLE_NAME, "TEST", UTC_ZONE_ID);
assertThat(sql, is("SELECT time, value FROM " + DB_TABLE_NAME + " WHERE TIME>='" //
- + JdbcBaseDAO.JDBC_DATE_FORMAT.format(filter.getBeginDate()) + "'" //
- + " AND TIME<='" + JdbcBaseDAO.JDBC_DATE_FORMAT.format(filter.getEndDate()) + "' ORDER BY time DESC"));
+ + JdbcBaseDAO.JDBC_DATE_FORMAT.format(Objects.requireNonNull(filter.getBeginDate())) + "'" //
+ + " AND TIME<='" + JdbcBaseDAO.JDBC_DATE_FORMAT.format(Objects.requireNonNull(filter.getEndDate()))
+ + "' ORDER BY time DESC"));
}
@Test
String sql = jdbcBaseDAO.histItemFilterDeleteProvider(filter, DB_TABLE_NAME, UTC_ZONE_ID);
assertThat(sql, is("DELETE FROM " + DB_TABLE_NAME + " WHERE TIME>='" //
- + JdbcBaseDAO.JDBC_DATE_FORMAT.format(filter.getBeginDate()) + "'" //
- + " AND TIME<='" + JdbcBaseDAO.JDBC_DATE_FORMAT.format(filter.getEndDate()) + "'"));
+ + JdbcBaseDAO.JDBC_DATE_FORMAT.format(Objects.requireNonNull(filter.getBeginDate())) + "'" //
+ + " AND TIME<='" + JdbcBaseDAO.JDBC_DATE_FORMAT.format(Objects.requireNonNull(filter.getEndDate()))
+ + "'"));
}
@Test
filter.setBeginDate(parseDateTimeString("2022-01-10T15:01:44"));
String sql = jdbcBaseDAO.resolveTimeFilter(filter, UTC_ZONE_ID);
- assertThat(sql, is(" WHERE TIME>='" + JdbcBaseDAO.JDBC_DATE_FORMAT.format(filter.getBeginDate()) + "'"));
+ assertThat(sql, is(" WHERE TIME>='"
+ + JdbcBaseDAO.JDBC_DATE_FORMAT.format(Objects.requireNonNull(filter.getBeginDate())) + "'"));
}
@Test
filter.setEndDate(parseDateTimeString("2022-01-15T15:01:44"));
String sql = jdbcBaseDAO.resolveTimeFilter(filter, UTC_ZONE_ID);
- assertThat(sql, is(" WHERE TIME<='" + JdbcBaseDAO.JDBC_DATE_FORMAT.format(filter.getEndDate()) + "'"));
+ assertThat(sql, is(" WHERE TIME<='"
+ + JdbcBaseDAO.JDBC_DATE_FORMAT.format(Objects.requireNonNull(filter.getEndDate())) + "'"));
}
@Test
filter.setEndDate(parseDateTimeString("2022-01-15T15:01:44"));
String sql = jdbcBaseDAO.resolveTimeFilter(filter, UTC_ZONE_ID);
- assertThat(sql, is(" WHERE TIME>='" + JdbcBaseDAO.JDBC_DATE_FORMAT.format(filter.getBeginDate()) + "'" //
- + " AND TIME<='" + JdbcBaseDAO.JDBC_DATE_FORMAT.format(filter.getEndDate()) + "'"));
+ assertThat(sql,
+ is(" WHERE TIME>='" + JdbcBaseDAO.JDBC_DATE_FORMAT.format(Objects.requireNonNull(filter.getBeginDate()))
+ + "'" //
+ + " AND TIME<='"
+ + JdbcBaseDAO.JDBC_DATE_FORMAT.format(Objects.requireNonNull(filter.getEndDate())) + "'"));
}
private ZonedDateTime parseDateTimeString(String dts) {
}
String itemName = filter.getItemName();
+ if (itemName == null) {
+ logger.warn("Item name is missing in filter {}", filter);
+ return List.of();
+ }
Item item = getItemFromRegistry(itemName);
if (item == null) {
logger.debug("Item '{}' does not exist in the item registry", itemName);
}
String realItemName = filter.getItemName();
+ if (realItemName == null) {
+ logger.warn("Item name is missing in filter {}", filter);
+ return List.of();
+ }
+
String collectionName = collectionPerItem ? realItemName : this.collection;
@Nullable
DBCollection collection = connectToCollection(collectionName);
if (filter.getItemName() != null) {
query.put(FIELD_ITEM, filter.getItemName());
}
- if (filter.getState() != null && filter.getOperator() != null) {
+ State filterState = filter.getState();
+ if (filterState != null && filter.getOperator() != null) {
@Nullable
String op = convertOperator(filter.getOperator());
return Collections.emptyList();
}
- Object value = convertValue(filter.getState());
+ Object value = convertValue(filterState);
query.put(FIELD_VALUE, new BasicDBObject(op, value));
}
}
String itemName = filter.getItemName();
+ if (itemName == null) {
+ logger.warn("Item name is missing in filter {}", filter);
+ return List.of();
+ }
RrdDb db = null;
try {