package org.openhab.persistence.jdbc.db;
import java.math.BigDecimal;
-import java.sql.Timestamp;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
Yank.execute(sql, null);
}
- public void doStoreItemValue(Item item, ItemVO vo) {
- ItemVO storedVO = storeItemValueProvider(item, vo);
+ public void doStoreItemValue(Item item, State itemState, ItemVO vo) {
+ ItemVO storedVO = storeItemValueProvider(item, itemState, vo);
String sql = StringUtilsExt.replaceArrayMerge(sqlInsertItemValue,
new String[] { "#tableName#", "#tablePrimaryValue#" },
new String[] { storedVO.getTableName(), sqlTypes.get("tablePrimaryValue") });
Yank.execute(sql, params);
}
+ public void doStoreItemValue(Item item, State itemState, ItemVO vo, ZonedDateTime date) {
+ ItemVO storedVO = storeItemValueProvider(item, itemState, vo);
+ String sql = StringUtilsExt.replaceArrayMerge(sqlInsertItemValue,
+ new String[] { "#tableName#", "#tablePrimaryValue#" }, new String[] { storedVO.getTableName(), "?" });
+ java.sql.Timestamp timestamp = new java.sql.Timestamp(date.toInstant().toEpochMilli());
+ Object[] params = new Object[] { storedVO.getValue(), timestamp, storedVO.getValue() };
+ logger.debug("JDBC::doStoreItemValue sql={} timestamp={} value='{}'", sql, timestamp, storedVO.getValue());
+ Yank.execute(sql, params);
+ }
+
public List<HistoricItem> doGetHistItemFilterQuery(Item item, FilterCriteria filter, int numberDecimalcount,
String table, String name, ZoneId timeZone) {
String sql = histItemFilterQueryProvider(filter, numberDecimalcount, table, name, timeZone);
.collect(Collectors.<HistoricItem> toList());
}
+ public void doDeleteItemValues(Item item, FilterCriteria filter, String table, ZoneId timeZone) {
+ String sql = histItemFilterDeleteProvider(filter, table, timeZone);
+ logger.debug("JDBC::doDeleteItemValues sql={}", sql);
+ Yank.execute(sql, null);
+ }
+
/*************
* Providers *
*************/
"JDBC::getHistItemFilterQueryProvider filter = {}, numberDecimalcount = {}, table = {}, simpleName = {}",
filter, numberDecimalcount, table, simpleName);
- String filterString = "";
- if (filter.getBeginDate() != null) {
- filterString += filterString.isEmpty() ? " WHERE" : " AND";
- filterString += " TIME>'" + JDBC_DATE_FORMAT.format(filter.getBeginDate().withZoneSameInstant(timeZone))
- + "'";
- }
- if (filter.getEndDate() != null) {
- filterString += filterString.isEmpty() ? " WHERE" : " AND";
- filterString += " TIME<'" + JDBC_DATE_FORMAT.format(filter.getEndDate().withZoneSameInstant(timeZone))
- + "'";
- }
- filterString += (filter.getOrdering() == Ordering.ASCENDING) ? " ORDER BY time ASC" : " ORDER BY time DESC ";
- if (filter.getPageSize() != 0x7fffffff) {
+ String filterString = resolveTimeFilter(filter, timeZone);
+ filterString += (filter.getOrdering() == Ordering.ASCENDING) ? " ORDER BY time ASC" : " ORDER BY time DESC";
+ if (filter.getPageSize() != Integer.MAX_VALUE) {
filterString += " LIMIT " + filter.getPageNumber() * filter.getPageSize() + "," + filter.getPageSize();
}
// SELECT time, ROUND(value,3) FROM number_item_0114 ORDER BY time DESC LIMIT 0,1
return queryString;
}
+ protected String histItemFilterDeleteProvider(FilterCriteria filter, String table, ZoneId timeZone) {
+ logger.debug("JDBC::histItemFilterDeleteProvider filter = {}, table = {}", filter, table);
+
+ String filterString = resolveTimeFilter(filter, timeZone);
+ String deleteString = "DELETE FROM " + table;
+ if (!filterString.isEmpty()) {
+ deleteString += filterString;
+ }
+ logger.debug("JDBC::delete deleteString = {}", deleteString);
+ return deleteString;
+ }
+
+ protected String resolveTimeFilter(FilterCriteria filter, ZoneId timeZone) {
+ String filterString = "";
+ if (filter.getBeginDate() != null) {
+ filterString += filterString.isEmpty() ? " WHERE" : " AND";
+ filterString += " TIME>'" + JDBC_DATE_FORMAT.format(filter.getBeginDate().withZoneSameInstant(timeZone))
+ + "'";
+ }
+ if (filter.getEndDate() != null) {
+ filterString += filterString.isEmpty() ? " WHERE" : " AND";
+ filterString += " TIME<'" + JDBC_DATE_FORMAT.format(filter.getEndDate().withZoneSameInstant(timeZone))
+ + "'";
+ }
+ return filterString;
+ }
+
private String updateItemTableNamesProvider(List<ItemVO> namesList) {
logger.debug("JDBC::updateItemTableNamesProvider namesList.size = {}", namesList.size());
String queryString = "";
return queryString;
}
- protected ItemVO storeItemValueProvider(Item item, ItemVO vo) {
+ protected ItemVO storeItemValueProvider(Item item, State itemState, ItemVO vo) {
String itemType = getItemType(item);
logger.debug("JDBC::storeItemValueProvider: item '{}' as Type '{}' in '{}' with state '{}'", item.getName(),
- itemType, vo.getTableName(), item.getState());
+ itemType, vo.getTableName(), itemState);
// insertItemValue
- logger.debug("JDBC::storeItemValueProvider: getState: '{}'", item.getState());
+ logger.debug("JDBC::storeItemValueProvider: itemState: '{}'", itemState);
/*
* !!ATTENTION!!
*
switch (itemType) {
case "COLORITEM":
vo.setValueTypes(getSqlTypes().get(itemType), java.lang.String.class);
- vo.setValue(item.getState().toString());
+ vo.setValue(itemState.toString());
break;
case "NUMBERITEM":
- State state = item.getState();
- State convertedState = state;
- if (item instanceof NumberItem && state instanceof QuantityType) {
+ State convertedState = itemState;
+ if (item instanceof NumberItem && itemState instanceof QuantityType) {
Unit<? extends Quantity<?>> unit = ((NumberItem) item).getUnit();
if (unit != null && !Units.ONE.equals(unit)) {
- convertedState = ((QuantityType<?>) state).toUnit(unit);
+ convertedState = ((QuantityType<?>) itemState).toUnit(unit);
if (convertedState == null) {
logger.warn(
"JDBC::storeItemValueProvider: Failed to convert state '{}' to unit '{}'. Please check your item definition for correctness.",
- state, unit);
- convertedState = state;
+ itemState, unit);
+ convertedState = itemState;
}
}
}
vo.setValue(value);
} else {// fall back to String
vo.setValueTypes(it, java.lang.String.class);
- logger.warn("JDBC::storeItemValueProvider: item.getState().toString(): '{}'", convertedState);
+ logger.warn("JDBC::storeItemValueProvider: itemState: '{}'", convertedState);
vo.setValue(convertedState.toString());
}
break;
case "ROLLERSHUTTERITEM":
case "DIMMERITEM":
vo.setValueTypes(getSqlTypes().get(itemType), java.lang.Integer.class);
- int value = ((DecimalType) item.getState()).intValue();
+ int value = ((DecimalType) itemState).intValue();
logger.debug("JDBC::storeItemValueProvider: newVal.intValue: '{}'", value);
vo.setValue(value);
break;
case "DATETIMEITEM":
vo.setValueTypes(getSqlTypes().get(itemType), java.sql.Timestamp.class);
java.sql.Timestamp d = new java.sql.Timestamp(
- ((DateTimeType) item.getState()).getZonedDateTime().toInstant().toEpochMilli());
+ ((DateTimeType) itemState).getZonedDateTime().toInstant().toEpochMilli());
logger.debug("JDBC::storeItemValueProvider: DateTimeItem: '{}'", d);
vo.setValue(d);
break;
default:
// All other items should return the best format by default
vo.setValueTypes(getSqlTypes().get(itemType), java.lang.String.class);
- logger.debug("JDBC::storeItemValueProvider: other: item.getState().toString(): '{}'", item.getState());
- vo.setValue(item.getState().toString());
+ logger.debug("JDBC::storeItemValueProvider: other: itemState: '{}'", itemState);
+ vo.setValue(itemState.toString());
break;
}
return vo;
protected ZonedDateTime objectAsDate(Object v) {
if (v instanceof java.lang.String) {
- return ZonedDateTime.ofInstant(Timestamp.valueOf(v.toString()).toInstant(), ZoneId.systemDefault());
+ return ZonedDateTime.ofInstant(java.sql.Timestamp.valueOf(v.toString()).toInstant(),
+ ZoneId.systemDefault());
}
- return ZonedDateTime.ofInstant(((Timestamp) v).toInstant(), ZoneId.systemDefault());
+ return ZonedDateTime.ofInstant(((java.sql.Timestamp) v).toInstant(), ZoneId.systemDefault());
}
protected Long objectAsLong(Object v) {
import org.openhab.core.persistence.FilterCriteria;
import org.openhab.core.persistence.FilterCriteria.Ordering;
import org.openhab.core.persistence.HistoricItem;
+import org.openhab.core.types.State;
import org.openhab.persistence.jdbc.dto.ItemVO;
import org.openhab.persistence.jdbc.dto.ItemsVO;
import org.openhab.persistence.jdbc.dto.JdbcHistoricItem;
}
@Override
- public void doStoreItemValue(Item item, ItemVO vo) {
- vo = storeItemValueProvider(item, vo);
+ public void doStoreItemValue(Item item, State itemState, ItemVO vo) {
+ ItemVO storedVO = storeItemValueProvider(item, itemState, vo);
String sql = StringUtilsExt.replaceArrayMerge(sqlInsertItemValue,
new String[] { "#tableName#", "#dbType#", "#tablePrimaryValue#" },
- new String[] { vo.getTableName().toUpperCase(), vo.getDbType(), sqlTypes.get("tablePrimaryValue") });
- Object[] params = new Object[] { vo.getValue() };
- logger.debug("JDBC::doStoreItemValue sql={} value='{}'", sql, vo.getValue());
+ new String[] { storedVO.getTableName().toUpperCase(), storedVO.getDbType(),
+ sqlTypes.get("tablePrimaryValue") });
+ Object[] params = new Object[] { storedVO.getValue() };
+ logger.debug("JDBC::doStoreItemValue sql={} value='{}'", sql, storedVO.getValue());
Yank.execute(sql, params);
}
import org.knowm.yank.Yank;
import org.openhab.core.items.Item;
+import org.openhab.core.types.State;
import org.openhab.persistence.jdbc.dto.ItemVO;
import org.openhab.persistence.jdbc.utils.StringUtilsExt;
import org.slf4j.Logger;
* ITEM DAOs *
*************/
@Override
- public void doStoreItemValue(Item item, ItemVO vo) {
- vo = storeItemValueProvider(item, vo);
+ public void doStoreItemValue(Item item, State itemState, ItemVO vo) {
+ ItemVO storedVO = storeItemValueProvider(item, itemState, vo);
String sql = StringUtilsExt.replaceArrayMerge(sqlInsertItemValue,
new String[] { "#tableName#", "#dbType#", "#tablePrimaryValue#" },
- new String[] { vo.getTableName(), vo.getDbType(), sqlTypes.get("tablePrimaryValue") });
- Object[] params = new Object[] { vo.getValue() };
- logger.debug("JDBC::doStoreItemValue sql={} value='{}'", sql, vo.getValue());
+ new String[] { storedVO.getTableName(), storedVO.getDbType(), sqlTypes.get("tablePrimaryValue") });
+ Object[] params = new Object[] { storedVO.getValue() };
+ logger.debug("JDBC::doStoreItemValue sql={} value='{}'", sql, storedVO.getValue());
Yank.execute(sql, params);
}
import org.knowm.yank.Yank;
import org.openhab.core.items.Item;
+import org.openhab.core.types.State;
import org.openhab.persistence.jdbc.dto.ItemVO;
import org.openhab.persistence.jdbc.dto.ItemsVO;
import org.openhab.persistence.jdbc.utils.StringUtilsExt;
* ITEM DAOs *
*************/
@Override
- public void doStoreItemValue(Item item, ItemVO vo) {
- vo = storeItemValueProvider(item, vo);
+ public void doStoreItemValue(Item item, State itemState, ItemVO vo) {
+ ItemVO storedVO = storeItemValueProvider(item, itemState, vo);
String sql = StringUtilsExt.replaceArrayMerge(sqlInsertItemValue,
- new String[] { "#tableName#", "#dbType#", "#tableName#", "#tablePrimaryValue#" }, new String[] {
- vo.getTableName(), vo.getDbType(), vo.getTableName(), sqlTypes.get("tablePrimaryValue") });
- Object[] params = new Object[] { vo.getValue() };
- logger.debug("JDBC::doStoreItemValue sql={} value='{}'", sql, vo.getValue());
+ new String[] { "#tableName#", "#dbType#", "#tableName#", "#tablePrimaryValue#" },
+ new String[] { storedVO.getTableName(), storedVO.getDbType(), storedVO.getTableName(),
+ sqlTypes.get("tablePrimaryValue") });
+ Object[] params = new Object[] { storedVO.getValue() };
+ logger.debug("JDBC::doStoreItemValue sql={} value='{}'", sql, storedVO.getValue());
Yank.execute(sql, params);
}
import org.openhab.core.items.Item;
import org.openhab.core.persistence.FilterCriteria;
import org.openhab.core.persistence.FilterCriteria.Ordering;
+import org.openhab.core.types.State;
import org.openhab.persistence.jdbc.dto.ItemVO;
import org.openhab.persistence.jdbc.dto.ItemsVO;
import org.openhab.persistence.jdbc.utils.StringUtilsExt;
* ITEM DAOs *
*************/
@Override
- public void doStoreItemValue(Item item, ItemVO vo) {
- vo = storeItemValueProvider(item, vo);
+ public void doStoreItemValue(Item item, State itemState, ItemVO vo) {
+ ItemVO storedVO = storeItemValueProvider(item, itemState, vo);
String sql = StringUtilsExt.replaceArrayMerge(sqlInsertItemValue,
new String[] { "#tableName#", "#dbType#", "#tablePrimaryValue#" },
- new String[] { vo.getTableName(), vo.getDbType(), sqlTypes.get("tablePrimaryValue") });
- Object[] params = new Object[] { vo.getValue() };
- logger.debug("JDBC::doStoreItemValue sql={} value='{}'", sql, vo.getValue());
+ new String[] { storedVO.getTableName(), storedVO.getDbType(), sqlTypes.get("tablePrimaryValue") });
+ Object[] params = new Object[] { storedVO.getValue() };
+ logger.debug("JDBC::doStoreItemValue sql={} value='{}'", sql, storedVO.getValue());
Yank.execute(sql, params);
}
import org.knowm.yank.Yank;
import org.openhab.core.items.Item;
+import org.openhab.core.types.State;
import org.openhab.persistence.jdbc.dto.ItemVO;
import org.openhab.persistence.jdbc.dto.ItemsVO;
import org.openhab.persistence.jdbc.utils.StringUtilsExt;
* ITEM DAOs *
*************/
@Override
- public void doStoreItemValue(Item item, ItemVO vo) {
- vo = storeItemValueProvider(item, vo);
+ public void doStoreItemValue(Item item, State itemState, ItemVO vo) {
+ ItemVO storedVO = storeItemValueProvider(item, itemState, vo);
String sql = StringUtilsExt.replaceArrayMerge(sqlInsertItemValue,
new String[] { "#tableName#", "#dbType#", "#tablePrimaryValue#" },
- new String[] { vo.getTableName(), vo.getDbType(), sqlTypes.get("tablePrimaryValue") });
- Object[] params = new Object[] { vo.getValue() };
- logger.debug("JDBC::doStoreItemValue sql={} value='{}'", sql, vo.getValue());
+ new String[] { storedVO.getTableName(), storedVO.getDbType(), sqlTypes.get("tablePrimaryValue") });
+ Object[] params = new Object[] { storedVO.getValue() };
+ logger.debug("JDBC::doStoreItemValue sql={} value='{}'", sql, storedVO.getValue());
Yank.execute(sql, params);
}
import java.util.Date;
import java.util.Objects;
+import org.eclipse.jdt.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final long serialVersionUID = 1871441039821454890L;
private String tableName;
- private String newTableName;
+ private @Nullable String newTableName;
private String dbType;
private String jdbcType;
private String itemType;
private Date time;
private Object value;
- public ItemVO(String tableName, String newTableName) {
+ public ItemVO(String tableName, @Nullable String newTableName) {
logger.debug("JDBC:ItemVO tableName={}; newTableName={}; ", tableName, newTableName);
this.tableName = tableName;
this.newTableName = newTableName;
this.tableName = tableName;
}
- public String getNewTableName() {
+ public @Nullable String getNewTableName() {
return newTableName;
}
this.value = value;
}
- /**
- * (non-Javadoc)
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
@Override
public boolean equals(Object obj) {
if (this == obj) {
@Override
public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("ItemVO [tableName=");
- builder.append(tableName);
- builder.append(", newTableName=");
- builder.append(newTableName);
- builder.append(", dbType=");
- builder.append(dbType);
- builder.append(", javaType=");
- builder.append(javaType);
- builder.append(", time=");
- builder.append(time);
- builder.append(", value=");
- builder.append(value);
- builder.append("]");
- return builder.toString();
+ return new StringBuilder("ItemVO [tableName=").append(tableName).append(", newTableName=").append(newTableName)
+ .append(", dbType=").append(dbType).append(", javaType=").append(javaType).append(", time=")
+ .append(time).append(", value=").append(value).append("]").toString();
}
}
*/
package org.openhab.persistence.jdbc.internal;
+import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
+import org.eclipse.jdt.annotation.Nullable;
import org.knowm.yank.Yank;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.items.Item;
import org.openhab.core.persistence.FilterCriteria;
import org.openhab.core.persistence.HistoricItem;
import org.openhab.core.persistence.PersistenceItemInfo;
+import org.openhab.core.types.State;
import org.openhab.persistence.jdbc.dto.ItemVO;
import org.openhab.persistence.jdbc.dto.ItemsVO;
import org.openhab.persistence.jdbc.dto.JdbcPersistenceItemInfo;
return vo;
}
- public Item storeItemValue(Item item) {
- logger.debug("JDBC::storeItemValue: item={}", item);
+ public Item storeItemValue(Item item, State itemState, @Nullable ZonedDateTime date) {
+ logger.debug("JDBC::storeItemValue: item={} state={} date={}", item, itemState, date);
String tableName = getTable(item);
if (tableName == null) {
logger.error("JDBC::store: Unable to store item '{}'.", item.getName());
return item;
}
long timerStart = System.currentTimeMillis();
- conf.getDBDAO().doStoreItemValue(item, new ItemVO(tableName, null));
+ if (date == null) {
+ conf.getDBDAO().doStoreItemValue(item, itemState, new ItemVO(tableName, null));
+ } else {
+ conf.getDBDAO().doStoreItemValue(item, itemState, new ItemVO(tableName, null), date);
+ }
logTime("storeItemValue", timerStart, System.currentTimeMillis());
errCnt = 0;
return item;
return null;
}
+ public boolean deleteItemValues(FilterCriteria filter, String table, Item item) {
+ logger.debug("JDBC::deleteItemValues filter='{}' table='{}' item='{}' itemName='{}'", (filter != null), table,
+ item, item.getName());
+ if (table != null) {
+ long timerStart = System.currentTimeMillis();
+ conf.getDBDAO().doDeleteItemValues(item, filter, table, timeZoneProvider.getTimeZone());
+ logTime("deleteItemValues", timerStart, System.currentTimeMillis());
+ errCnt = 0;
+ return true;
+ } else {
+ logger.error("JDBC::deleteItemValues: TABLE is NULL; cannot delete data from non-existent table.");
+ return false;
+ }
+ }
+
/***********************
* DATABASE CONNECTION *
***********************/
*/
package org.openhab.persistence.jdbc.internal;
+import java.time.ZonedDateTime;
+import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.persistence.FilterCriteria;
import org.openhab.core.persistence.HistoricItem;
+import org.openhab.core.persistence.ModifiablePersistenceService;
import org.openhab.core.persistence.PersistenceItemInfo;
import org.openhab.core.persistence.PersistenceService;
import org.openhab.core.persistence.QueryablePersistenceService;
import org.openhab.core.persistence.strategy.PersistenceStrategy;
+import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
QueryablePersistenceService.class }, configurationPid = "org.openhab.jdbc", //
property = Constants.SERVICE_PID + "=org.openhab.jdbc")
@ConfigurableService(category = "persistence", label = "JDBC Persistence Service", description_uri = JdbcPersistenceService.CONFIG_URI)
-public class JdbcPersistenceService extends JdbcMapper implements QueryablePersistenceService {
+public class JdbcPersistenceService extends JdbcMapper implements ModifiablePersistenceService {
+ private static final String SERVICE_ID = "jdbc";
+ private static final String SERVICE_LABEL = "JDBC";
protected static final String CONFIG_URI = "persistence:jdbc";
private final Logger logger = LoggerFactory.getLogger(JdbcPersistenceService.class);
@Override
public String getId() {
logger.debug("JDBC::getName: returning name 'jdbc' for queryable persistence service.");
- return "jdbc";
+ return SERVICE_ID;
}
@Override
public String getLabel(@Nullable Locale locale) {
- return "JDBC";
+ return SERVICE_LABEL;
}
@Override
public void store(Item item) {
- store(item, null);
+ internalStore(item, null, item.getState());
}
- /**
- * @{inheritDoc
- */
@Override
public void store(Item item, @Nullable String alias) {
+ // alias is not supported
+ internalStore(item, null, item.getState());
+ }
+
+ @Override
+ public void store(Item item, ZonedDateTime date, State state) {
+ internalStore(item, date, state);
+ }
+
+ private void internalStore(Item item, @Nullable ZonedDateTime date, State state) {
// Do not store undefined/uninitialized data
- if (item.getState() instanceof UnDefType) {
+ if (state instanceof UnDefType) {
logger.debug("JDBC::store: ignore Item '{}' because it is UnDefType", item.getName());
return;
}
if (!checkDBAccessability()) {
logger.warn(
- "JDBC::store: No connection to database. Cannot persist item '{}'! Will retry connecting to database when error count:{} equals errReconnectThreshold:{}",
- item, errCnt, conf.getErrReconnectThreshold());
+ "JDBC::store: No connection to database. Cannot persist state '{}' for item '{}'! Will retry connecting to database when error count:{} equals errReconnectThreshold:{}",
+ state, item, errCnt, conf.getErrReconnectThreshold());
return;
}
long timerStart = System.currentTimeMillis();
- storeItemValue(item);
- logger.debug("JDBC: Stored item '{}' as '{}' in SQL database at {} in {} ms.", item.getName(), item.getState(),
- new java.util.Date(), System.currentTimeMillis() - timerStart);
+ storeItemValue(item, state, date);
+ if (logger.isDebugEnabled()) {
+ logger.debug("JDBC: Stored item '{}' as '{}' in SQL database at {} in {} ms.", item.getName(), state,
+ new Date(), System.currentTimeMillis() - timerStart);
+ }
}
@Override
public List<PersistenceStrategy> getDefaultStrategies() {
return List.of(PersistenceStrategy.Globals.CHANGE);
}
+
+ @Override
+ public boolean remove(FilterCriteria filter) throws IllegalArgumentException {
+ if (!checkDBAccessability()) {
+ logger.warn("JDBC::remove: database not connected, remove aborted for item '{}'", filter.getItemName());
+ return false;
+ }
+
+ // Get the item name from the filter
+ // Also get the Item object so we can determine the type
+ Item item = null;
+ String itemName = filter.getItemName();
+ logger.debug("JDBC::remove: item is {}", itemName);
+ if (itemName == null) {
+ throw new IllegalArgumentException("Item name must not be null");
+ }
+ try {
+ item = itemRegistry.getItem(itemName);
+ } catch (ItemNotFoundException e) {
+ logger.error("JDBC::remove: unable to get item for itemName: '{}'. Ignore and give up!", itemName);
+ return false;
+ }
+
+ String table = sqlTables.get(itemName);
+ if (table == null) {
+ logger.debug("JDBC::remove: unable to find table for item with name: '{}', no data in database.", itemName);
+ return false;
+ }
+
+ long timerStart = System.currentTimeMillis();
+ boolean result = deleteItemValues(filter, table, item);
+ if (logger.isDebugEnabled()) {
+ logger.debug("JDBC: Deleted values for item '{}' in SQL database at {} in {} ms.", item.getName(),
+ new Date(), System.currentTimeMillis() - timerStart);
+ }
+
+ return result;
+ }
}
--- /dev/null
+/**
+ * Copyright (c) 2010-2022 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.persistence.jdbc.db;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openhab.core.persistence.FilterCriteria;
+import org.openhab.core.persistence.FilterCriteria.Ordering;
+
+/**
+ * Tests the {@link JdbcBaseDAO}.
+ *
+ * @author Christoph Weitkamp - Initial contribution
+ */
+@NonNullByDefault
+public class JdbcBaseDAOTest {
+
+ private static final String DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
+ private static final DateTimeFormatter DATE_PARSER = DateTimeFormatter.ofPattern(DATE_PATTERN);
+ private static final ZoneId UTC_ZONE_ID = ZoneId.of("UTC");
+ private static final String DB_TABLE_NAME = "testitem";
+
+ private final JdbcBaseDAO jdbcBaseDAO = new JdbcBaseDAO();
+ private @NonNullByDefault({}) FilterCriteria filter;
+
+ @BeforeEach
+ public void setup() {
+ filter = new FilterCriteria();
+ }
+
+ @Test
+ public void testHistItemFilterQueryProviderReturnsSelectQueryWithoutWhereClauseDescendingOrder() {
+ String sql = jdbcBaseDAO.histItemFilterQueryProvider(filter, 0, DB_TABLE_NAME, "TEST", UTC_ZONE_ID);
+ assertThat(sql, is("SELECT time, value FROM " + DB_TABLE_NAME + " ORDER BY time DESC"));
+ }
+
+ @Test
+ public void testHistItemFilterQueryProviderReturnsSelectQueryWithoutWhereClauseAscendingOrder() {
+ filter.setOrdering(Ordering.ASCENDING);
+
+ String sql = jdbcBaseDAO.histItemFilterQueryProvider(filter, 0, DB_TABLE_NAME, "TEST", UTC_ZONE_ID);
+ assertThat(sql, is("SELECT time, value FROM " + DB_TABLE_NAME + " ORDER BY time ASC"));
+ }
+
+ @Test
+ public void testHistItemFilterQueryProviderWithStartAndEndDateReturnsDeleteQueryWithWhereClauseDescendingOrder() {
+ filter.setBeginDate(parseDateTimeString("2022-01-10T15:01:44"));
+ filter.setEndDate(parseDateTimeString("2022-01-15T15:01:44"));
+
+ 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"));
+ }
+
+ @Test
+ public void testHistItemFilterQueryProviderReturnsSelectQueryWithoutWhereClauseDescendingOrderAndLimit() {
+ filter.setPageSize(1);
+
+ String sql = jdbcBaseDAO.histItemFilterQueryProvider(filter, 0, DB_TABLE_NAME, "TEST", UTC_ZONE_ID);
+ assertThat(sql, is("SELECT time, value FROM " + DB_TABLE_NAME + " ORDER BY time DESC LIMIT 0,1"));
+ }
+
+ @Test
+ public void testHistItemFilterDeleteProviderReturnsDeleteQueryWithoutWhereClause() {
+ String sql = jdbcBaseDAO.histItemFilterDeleteProvider(filter, DB_TABLE_NAME, UTC_ZONE_ID);
+ assertThat(sql, is("DELETE FROM " + DB_TABLE_NAME));
+ }
+
+ @Test
+ public void testHistItemFilterDeleteProviderWithStartAndEndDateReturnsDeleteQueryWithWhereClause() {
+ filter.setBeginDate(parseDateTimeString("2022-01-10T15:01:44"));
+ filter.setEndDate(parseDateTimeString("2022-01-15T15:01:44"));
+
+ 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()) + "'"));
+ }
+
+ @Test
+ public void testResolveTimeFilterWithNoDatesReturnsEmptyString() {
+ String sql = jdbcBaseDAO.resolveTimeFilter(filter, UTC_ZONE_ID);
+ assertThat(sql, is(""));
+ }
+
+ @Test
+ public void testResolveTimeFilterWithStartDateOnlyReturnsWhereClause() {
+ 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()) + "'"));
+ }
+
+ @Test
+ public void testResolveTimeFilterWithEndDateOnlyReturnsWhereClause() {
+ 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()) + "'"));
+ }
+
+ @Test
+ public void testResolveTimeFilterWithStartAndEndDateReturnsWhereClauseWithTwoConditions() {
+ filter.setBeginDate(parseDateTimeString("2022-01-10T15:01:44"));
+ 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()) + "'"));
+ }
+
+ private ZonedDateTime parseDateTimeString(String dts) {
+ return ZonedDateTime.of(LocalDateTime.parse(dts, DATE_PARSER), UTC_ZONE_ID);
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2022 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.persistence.jdbc.internal;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.core.items.ItemRegistry;
+import org.openhab.core.persistence.FilterCriteria;
+
+/**
+ * Tests the {@link JdbcPersistenceService}.
+ *
+ * @author Christoph Weitkamp - Initial contribution
+ */
+@NonNullByDefault
+public class JdbcPersistenceServiceTest {
+
+ private final JdbcPersistenceService jdbcPersistenceService = new JdbcPersistenceService(mock(ItemRegistry.class),
+ mock(TimeZoneProvider.class)) {
+ @Override
+ protected boolean checkDBAccessability() {
+ return true;
+ }
+ };
+ private @NonNullByDefault({}) FilterCriteria filter;
+
+ @BeforeEach
+ public void setup() {
+ filter = new FilterCriteria();
+ }
+
+ @Test
+ void removeThrowsIllegalArgumentExceptionIfItemNameOfFilterIsNull() {
+ assertThrows(IllegalArgumentException.class, () -> jdbcPersistenceService.remove(filter));
+ }
+}