diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcBaseDAO.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcBaseDAO.java index ac6194151..61d0a12ae 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcBaseDAO.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcBaseDAO.java @@ -19,6 +19,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; @@ -27,6 +28,7 @@ import java.util.stream.Collectors; import javax.measure.Quantity; import javax.measure.Unit; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.knowm.yank.Yank; import org.openhab.core.items.GroupItem; @@ -65,6 +67,7 @@ import org.slf4j.LoggerFactory; * * @author Helmut Lehmeyer - Initial contribution */ +@NonNullByDefault public class JdbcBaseDAO { private final Logger logger = LoggerFactory.getLogger(JdbcBaseDAO.class); @@ -73,18 +76,18 @@ public class JdbcBaseDAO { public final Map sqlTypes = new HashMap<>(); // Get Database Meta data - protected DbMetaData dbMeta; + protected @Nullable DbMetaData dbMeta; - protected String sqlPingDB; - protected String sqlGetDB; - protected String sqlIfTableExists; - protected String sqlCreateNewEntryInItemsTable; - protected String sqlCreateItemsTableIfNot; - protected String sqlDeleteItemsEntry; - protected String sqlGetItemIDTableNames; - protected String sqlGetItemTables; - protected String sqlCreateItemTable; - protected String sqlInsertItemValue; + protected String sqlPingDB = "SELECT 1"; + protected String sqlGetDB = "SELECT DATABASE()"; + protected String sqlIfTableExists = "SHOW TABLES LIKE '#searchTable#'"; + protected String sqlCreateNewEntryInItemsTable = "INSERT INTO #itemsManageTable# (ItemName) VALUES ('#itemname#')"; + protected String sqlCreateItemsTableIfNot = "CREATE TABLE IF NOT EXISTS #itemsManageTable# (ItemId INT NOT NULL AUTO_INCREMENT,#colname# #coltype# NOT NULL,PRIMARY KEY (ItemId))"; + protected String sqlDeleteItemsEntry = "DELETE FROM items WHERE ItemName=#itemname#"; + protected String sqlGetItemIDTableNames = "SELECT itemid, itemname FROM #itemsManageTable#"; + protected String sqlGetItemTables = "SELECT table_name FROM information_schema.tables WHERE table_type='BASE TABLE' AND table_schema='#jdbcUriDatabaseName#' AND NOT table_name='#itemsManageTable#'"; + protected String sqlCreateItemTable = "CREATE TABLE IF NOT EXISTS #tableName# (time #tablePrimaryKey# NOT NULL, value #dbType#, PRIMARY KEY(time))"; + protected String sqlInsertItemValue = "INSERT INTO #tableName# (TIME, VALUE) VALUES( #tablePrimaryValue#, ? ) ON DUPLICATE KEY UPDATE VALUE= ?"; /******** * INIT * @@ -92,7 +95,6 @@ public class JdbcBaseDAO { public JdbcBaseDAO() { initSqlTypes(); initDbProps(); - initSqlQueries(); } /** @@ -131,21 +133,6 @@ public class JdbcBaseDAO { * */ - private void initSqlQueries() { - logger.debug("JDBC::initSqlQueries: '{}'", this.getClass().getSimpleName()); - sqlPingDB = "SELECT 1"; - sqlGetDB = "SELECT DATABASE()"; - sqlIfTableExists = "SHOW TABLES LIKE '#searchTable#'"; - - sqlCreateNewEntryInItemsTable = "INSERT INTO #itemsManageTable# (ItemName) VALUES ('#itemname#')"; - sqlCreateItemsTableIfNot = "CREATE TABLE IF NOT EXISTS #itemsManageTable# (ItemId INT NOT NULL AUTO_INCREMENT,#colname# #coltype# NOT NULL,PRIMARY KEY (ItemId))"; - sqlDeleteItemsEntry = "DELETE FROM items WHERE ItemName=#itemname#"; - sqlGetItemIDTableNames = "SELECT itemid, itemname FROM #itemsManageTable#"; - sqlGetItemTables = "SELECT table_name FROM information_schema.tables WHERE table_type='BASE TABLE' AND table_schema='#jdbcUriDatabaseName#' AND NOT table_name='#itemsManageTable#'"; - sqlCreateItemTable = "CREATE TABLE IF NOT EXISTS #tableName# (time #tablePrimaryKey# NOT NULL, value #dbType#, PRIMARY KEY(time))"; - sqlInsertItemValue = "INSERT INTO #tableName# (TIME, VALUE) VALUES( #tablePrimaryValue#, ? ) ON DUPLICATE KEY UPDATE VALUE= ?"; - } - /** * INFO: http://www.java2s.com/Code/Java/Database-SQL-JDBC/StandardSQLDataTypeswithTheirJavaEquivalents.htm */ @@ -257,19 +244,19 @@ public class JdbcBaseDAO { /************** * ITEMS DAOs * **************/ - public Integer doPingDB() { - return Yank.queryScalar(sqlPingDB, Integer.class, null); + public @Nullable Integer doPingDB() { + return Yank.queryScalar(sqlPingDB, (Class<@Nullable Integer>) Integer.class, null); } - public String doGetDB() { - return Yank.queryScalar(sqlGetDB, String.class, null); + public @Nullable String doGetDB() { + return Yank.queryScalar(sqlGetDB, (Class<@Nullable String>) String.class, null); } public boolean doIfTableExists(ItemsVO vo) { String sql = StringUtilsExt.replaceArrayMerge(sqlIfTableExists, new String[] { "#searchTable#" }, new String[] { vo.getItemsManageTable() }); logger.debug("JDBC::doIfTableExists sql={}", sql); - return Yank.queryScalar(sql, String.class, null) != null; + return Yank.queryScalar(sql, (Class<@Nullable String>) String.class, null) != null; } public Long doCreateNewEntryInItemsTable(ItemsVO vo) { @@ -477,7 +464,9 @@ public class JdbcBaseDAO { } } String it = getSqlTypes().get(itemType); - if (it.toUpperCase().contains("DOUBLE")) { + if (it == null) { + logger.warn("JDBC::storeItemValueProvider: No SQL type defined for item type {}", itemType); + } else if (it.toUpperCase().contains("DOUBLE")) { vo.setValueTypes(it, java.lang.Double.class); double value = ((Number) convertedState).doubleValue(); logger.debug("JDBC::storeItemValueProvider: newVal.doubleValue: '{}'", value); @@ -537,6 +526,9 @@ public class JdbcBaseDAO { v, unit, v.getClass(), v.getClass().getSimpleName()); if (item instanceof NumberItem) { String it = getSqlTypes().get("NUMBERITEM"); + if (it == null) { + throw new UnsupportedOperationException("No SQL type defined for item type NUMBERITEM"); + } if (it.toUpperCase().contains("DOUBLE")) { return unit == null ? new DecimalType(((Number) v).doubleValue()) : QuantityType.valueOf(((Number) v).doubleValue(), unit); @@ -558,9 +550,17 @@ public class JdbcBaseDAO { } else if (item instanceof ImageItem) { return RawType.valueOf(objectAsString(v)); } else if (item instanceof ContactItem || item instanceof PlayerItem || item instanceof SwitchItem) { - return TypeParser.parseState(item.getAcceptedDataTypes(), ((String) v).toString().trim()); + State state = TypeParser.parseState(item.getAcceptedDataTypes(), ((String) v).toString().trim()); + if (state == null) { + throw new UnsupportedOperationException("Unable to parse state for item " + item.toString()); + } + return state; } else { - return TypeParser.parseState(item.getAcceptedDataTypes(), ((String) v).toString()); + State state = TypeParser.parseState(item.getAcceptedDataTypes(), ((String) v).toString()); + if (state == null) { + throw new UnsupportedOperationException("Unable to parse state for item " + item.toString()); + } + return state; } } @@ -617,13 +617,14 @@ public class JdbcBaseDAO { logger.debug( "JDBC::getItemType: Cannot detect ItemType for {} because the GroupItems' base type isn't set in *.items File.", i.getName()); - item = ((GroupItem) i).getMembers().iterator().next(); - if (item == null) { + Iterator iterator = ((GroupItem) i).getMembers().iterator(); + if (!iterator.hasNext()) { logger.debug( - "JDBC::getItemType: No ItemType found for first Child-Member of GroupItem {}, use ItemType for STRINGITEM as Fallback", + "JDBC::getItemType: No Child-Members of GroupItem {}, use ItemType for STRINGITEM as Fallback", i.getName()); return def; } + item = iterator.next(); } } String itemType = item.getClass().getSimpleName().toUpperCase(); @@ -645,6 +646,10 @@ public class JdbcBaseDAO { } public String getDataType(Item item) { - return sqlTypes.get(getItemType(item)); + String dataType = sqlTypes.get(getItemType(item)); + if (dataType == null) { + throw new UnsupportedOperationException("No data type found for " + getItemType(item)); + } + return dataType; } } diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcDerbyDAO.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcDerbyDAO.java index 6e18c38b0..5c2262f60 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcDerbyDAO.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcDerbyDAO.java @@ -19,6 +19,8 @@ import java.util.stream.Collectors; import javax.measure.Quantity; import javax.measure.Unit; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.knowm.yank.Yank; import org.openhab.core.items.Item; import org.openhab.core.library.items.NumberItem; @@ -40,6 +42,7 @@ import org.slf4j.LoggerFactory; * * @author Helmut Lehmeyer - Initial contribution */ +@NonNullByDefault public class JdbcDerbyDAO extends JdbcBaseDAO { private final Logger logger = LoggerFactory.getLogger(JdbcDerbyDAO.class); @@ -99,8 +102,8 @@ public class JdbcDerbyDAO extends JdbcBaseDAO { * ITEMS DAOs * **************/ @Override - public Integer doPingDB() { - return Yank.queryScalar(sqlPingDB, Integer.class, null); + public @Nullable Integer doPingDB() { + return Yank.queryScalar(sqlPingDB, (Class<@Nullable Integer>) Integer.class, null); } @Override @@ -108,7 +111,7 @@ public class JdbcDerbyDAO extends JdbcBaseDAO { String sql = StringUtilsExt.replaceArrayMerge(sqlIfTableExists, new String[] { "#searchTable#" }, new String[] { vo.getItemsManageTable().toUpperCase() }); logger.debug("JDBC::doIfTableExists sql={}", sql); - return Yank.queryScalar(sql, String.class, null) != null; + return Yank.queryScalar(sql, (Class<@Nullable String>) String.class, null) != null; } @Override diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcH2DAO.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcH2DAO.java index 6fa73951f..8957f5538 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcH2DAO.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcH2DAO.java @@ -12,6 +12,7 @@ */ package org.openhab.persistence.jdbc.db; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.knowm.yank.Yank; import org.openhab.core.items.Item; import org.openhab.core.types.State; @@ -27,6 +28,7 @@ import org.slf4j.LoggerFactory; * * @author Helmut Lehmeyer - Initial contribution */ +@NonNullByDefault public class JdbcH2DAO extends JdbcBaseDAO { private final Logger logger = LoggerFactory.getLogger(JdbcH2DAO.class); diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcHsqldbDAO.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcHsqldbDAO.java index dbc9486f6..8f26945e1 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcHsqldbDAO.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcHsqldbDAO.java @@ -12,6 +12,8 @@ */ package org.openhab.persistence.jdbc.db; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.knowm.yank.Yank; import org.openhab.core.items.Item; import org.openhab.core.types.State; @@ -28,6 +30,7 @@ import org.slf4j.LoggerFactory; * * @author Helmut Lehmeyer - Initial contribution */ +@NonNullByDefault public class JdbcHsqldbDAO extends JdbcBaseDAO { private final Logger logger = LoggerFactory.getLogger(JdbcHsqldbDAO.class); @@ -75,8 +78,8 @@ public class JdbcHsqldbDAO extends JdbcBaseDAO { * ITEMS DAOs * **************/ @Override - public Integer doPingDB() { - return Yank.queryScalar(sqlPingDB, Integer.class, null); + public @Nullable Integer doPingDB() { + return Yank.queryScalar(sqlPingDB, (Class<@Nullable Integer>) Integer.class, null); } @Override diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcMariadbDAO.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcMariadbDAO.java index 30e0c345c..86c8bbb9e 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcMariadbDAO.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcMariadbDAO.java @@ -13,6 +13,7 @@ package org.openhab.persistence.jdbc.db; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.knowm.yank.Yank; import org.openhab.persistence.jdbc.utils.DbMetaData; import org.slf4j.Logger; @@ -75,7 +76,8 @@ public class JdbcMariadbDAO extends JdbcBaseDAO { @Override public void initAfterFirstDbConnection() { logger.debug("JDBC::initAfterFirstDbConnection: Initializing step, after db is connected."); - dbMeta = new DbMetaData(); + DbMetaData dbMeta = new DbMetaData(); + this.dbMeta = dbMeta; // Initialize sqlTypes, depending on DB version for example if (dbMeta.isDbVersionGreater(5, 1)) { sqlTypes.put("DATETIMEITEM", "TIMESTAMP(3)"); @@ -88,8 +90,9 @@ public class JdbcMariadbDAO extends JdbcBaseDAO { * ITEMS DAOs * **************/ @Override - public Integer doPingDB() { - return Yank.queryScalar(sqlPingDB, Long.class, null).intValue(); + public @Nullable Integer doPingDB() { + final @Nullable Long result = Yank.queryScalar(sqlPingDB, (Class<@Nullable Long>) Long.class, null); + return result != null ? result.intValue() : null; } /************* diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcMysqlDAO.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcMysqlDAO.java index f2a9307dc..962938b96 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcMysqlDAO.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcMysqlDAO.java @@ -13,6 +13,7 @@ package org.openhab.persistence.jdbc.db; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.knowm.yank.Yank; import org.openhab.persistence.jdbc.utils.DbMetaData; import org.slf4j.Logger; @@ -78,7 +79,8 @@ public class JdbcMysqlDAO extends JdbcBaseDAO { @Override public void initAfterFirstDbConnection() { logger.debug("JDBC::initAfterFirstDbConnection: Initializing step, after db is connected."); - dbMeta = new DbMetaData(); + DbMetaData dbMeta = new DbMetaData(); + this.dbMeta = dbMeta; // Initialize sqlTypes, depending on DB version for example if (dbMeta.isDbVersionGreater(5, 5)) { sqlTypes.put("DATETIMEITEM", "TIMESTAMP(3)"); @@ -91,8 +93,9 @@ public class JdbcMysqlDAO extends JdbcBaseDAO { * ITEMS DAOs * **************/ @Override - public Integer doPingDB() { - return Yank.queryScalar(sqlPingDB, Long.class, null).intValue(); + public @Nullable Integer doPingDB() { + final @Nullable Long result = Yank.queryScalar(sqlPingDB, (Class<@Nullable Long>) Long.class, null); + return result != null ? result.intValue() : null; } /************* diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcPostgresqlDAO.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcPostgresqlDAO.java index 53a1c4ba6..d754b4d02 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcPostgresqlDAO.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcPostgresqlDAO.java @@ -15,6 +15,7 @@ package org.openhab.persistence.jdbc.db; import java.time.ZoneId; import java.util.List; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.knowm.yank.Yank; import org.openhab.core.items.Item; import org.openhab.core.persistence.FilterCriteria; @@ -33,6 +34,7 @@ import org.slf4j.LoggerFactory; * * @author Helmut Lehmeyer - Initial contribution */ +@NonNullByDefault public class JdbcPostgresqlDAO extends JdbcBaseDAO { private final Logger logger = LoggerFactory.getLogger(JdbcPostgresqlDAO.class); diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcSqliteDAO.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcSqliteDAO.java index e5665e2c0..5096d546c 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcSqliteDAO.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcSqliteDAO.java @@ -12,6 +12,8 @@ */ package org.openhab.persistence.jdbc.db; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.knowm.yank.Yank; import org.openhab.core.items.Item; import org.openhab.core.types.State; @@ -28,6 +30,7 @@ import org.slf4j.LoggerFactory; * * @author Helmut Lehmeyer - Initial contribution */ +@NonNullByDefault public class JdbcSqliteDAO extends JdbcBaseDAO { private final Logger logger = LoggerFactory.getLogger(JdbcSqliteDAO.class); @@ -73,8 +76,8 @@ public class JdbcSqliteDAO extends JdbcBaseDAO { **************/ @Override - public String doGetDB() { - return Yank.queryColumn(sqlGetDB, "file", String.class, null).get(0); + public @Nullable String doGetDB() { + return Yank.queryColumn(sqlGetDB, "file", (Class<@Nullable String>) String.class, null).get(0); } @Override diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcTimescaledbDAO.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcTimescaledbDAO.java index 1a2c32a2d..c27503274 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcTimescaledbDAO.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcTimescaledbDAO.java @@ -14,6 +14,7 @@ package org.openhab.persistence.jdbc.db; import java.util.Properties; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.knowm.yank.Yank; import org.openhab.persistence.jdbc.dto.ItemVO; import org.openhab.persistence.jdbc.utils.StringUtilsExt; @@ -27,6 +28,7 @@ import org.slf4j.LoggerFactory; * @author Riccardo Nimser-Joseph - Initial contribution * @author Dan Cunningham - Fixes and refactoring */ +@NonNullByDefault public class JdbcTimescaledbDAO extends JdbcPostgresqlDAO { private final Logger logger = LoggerFactory.getLogger(JdbcTimescaledbDAO.class); diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcConfiguration.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcConfiguration.java index 7a9a84971..90b4e1cfc 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcConfiguration.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcConfiguration.java @@ -21,6 +21,8 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.persistence.jdbc.db.JdbcBaseDAO; import org.openhab.persistence.jdbc.utils.MovingAverage; import org.openhab.persistence.jdbc.utils.StringUtilsExt; @@ -32,6 +34,7 @@ import org.slf4j.LoggerFactory; * * @author Helmut Lehmeyer - Initial contribution */ +@NonNullByDefault public class JdbcConfiguration { private final Logger logger = LoggerFactory.getLogger(JdbcConfiguration.class); @@ -40,12 +43,12 @@ public class JdbcConfiguration { private Map configuration; - private JdbcBaseDAO dBDAO = null; - private String dbName = null; + private @NonNullByDefault({}) JdbcBaseDAO dBDAO; + private @Nullable String dbName; boolean dbConnected = false; boolean driverAvailable = false; - private String serviceName; + private @Nullable String serviceName; private String name = "jdbc"; public final boolean valid; @@ -70,12 +73,11 @@ public class JdbcConfiguration { public JdbcConfiguration(Map configuration) { logger.debug("JDBC::JdbcConfiguration"); - valid = updateConfig(configuration); + this.configuration = configuration; + valid = updateConfig(); } - private boolean updateConfig(Map config) { - configuration = config; - + private boolean updateConfig() { logger.debug("JDBC::updateConfig: configuration size = {}", configuration.size()); String user = (String) configuration.get("user"); @@ -226,15 +228,17 @@ public class JdbcConfiguration { } private void setDBDAOClass(String sn) { - serviceName = "none"; + String serviceName; // set database type - if (sn == null || sn.isBlank() || sn.length() < 2) { + if (sn.isBlank() || sn.length() < 2) { logger.error( "JDBC::updateConfig: Required database url like 'jdbc::[:;]' - please configure the jdbc:url parameter in openhab.cfg"); + serviceName = "none"; } else { serviceName = sn; } + this.serviceName = serviceName; logger.debug("JDBC::updateConfig: found serviceName = '{}'", serviceName); // set class for database type @@ -277,7 +281,9 @@ public class JdbcConfiguration { } String value = (String) configuration.get(key); logger.debug("JDBC::updateConfig: set sqlTypes: itemType={} value={}", itemType, value); - dBDAO.sqlTypes.put(itemType, value); + if (value != null) { + dBDAO.sqlTypes.put(itemType, value); + } } } @@ -294,28 +300,31 @@ public class JdbcConfiguration { String warn = "" + "\n\n\t!!!\n\tTo avoid this error, place an appropriate JDBC driver file for serviceName '{}' in addons directory.\n" + "\tCopy missing JDBC-Driver-jar to your openHab/addons Folder.\n\t!!!\n" + "\tDOWNLOAD: \n"; - switch (serviceName) { - case "derby": - warn += "\tDerby: version >= 10.11.1.1 from https://mvnrepository.com/artifact/org.apache.derby/derby\n"; - break; - case "h2": - warn += "\tH2: version >= 1.4.189 from https://mvnrepository.com/artifact/com.h2database/h2\n"; - break; - case "hsqldb": - warn += "\tHSQLDB: version >= 2.3.3 from https://mvnrepository.com/artifact/org.hsqldb/hsqldb\n"; - break; - case "mariadb": - warn += "\tMariaDB: version >= 1.2.0 from https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client\n"; - break; - case "mysql": - warn += "\tMySQL: version >= 5.1.36 from https://mvnrepository.com/artifact/mysql/mysql-connector-java\n"; - break; - case "postgresql": - warn += "\tPostgreSQL:version >= 9.4.1208 from https://mvnrepository.com/artifact/org.postgresql/postgresql\n"; - break; - case "sqlite": - warn += "\tSQLite: version >= 3.16.1 from https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc\n"; - break; + String serviceName = this.serviceName; + if (serviceName != null) { + switch (serviceName) { + case "derby": + warn += "\tDerby: version >= 10.11.1.1 from https://mvnrepository.com/artifact/org.apache.derby/derby\n"; + break; + case "h2": + warn += "\tH2: version >= 1.4.189 from https://mvnrepository.com/artifact/com.h2database/h2\n"; + break; + case "hsqldb": + warn += "\tHSQLDB: version >= 2.3.3 from https://mvnrepository.com/artifact/org.hsqldb/hsqldb\n"; + break; + case "mariadb": + warn += "\tMariaDB: version >= 1.2.0 from https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client\n"; + break; + case "mysql": + warn += "\tMySQL: version >= 5.1.36 from https://mvnrepository.com/artifact/mysql/mysql-connector-java\n"; + break; + case "postgresql": + warn += "\tPostgreSQL:version >= 9.4.1208 from https://mvnrepository.com/artifact/org.postgresql/postgresql\n"; + break; + case "sqlite": + warn += "\tSQLite: version >= 3.16.1 from https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc\n"; + break; + } } logger.warn(warn, serviceName); } @@ -330,7 +339,7 @@ public class JdbcConfiguration { return name; } - public String getServiceName() { + public @Nullable String getServiceName() { return serviceName; } @@ -362,7 +371,7 @@ public class JdbcConfiguration { return dBDAO; } - public String getDbName() { + public @Nullable String getDbName() { return dbName; } diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcMapper.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcMapper.java index 3fcdf1e3d..f3aa81a4d 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcMapper.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcMapper.java @@ -21,6 +21,7 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.knowm.yank.Yank; import org.openhab.core.i18n.TimeZoneProvider; @@ -42,6 +43,7 @@ import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException; * * @author Helmut Lehmeyer - Initial contribution */ +@NonNullByDefault public class JdbcMapper { private final Logger logger = LoggerFactory.getLogger(JdbcMapper.class); @@ -50,7 +52,7 @@ public class JdbcMapper { // Error counter - used to reconnect to database on error protected int errCnt; protected boolean initialized = false; - protected JdbcConfiguration conf = null; + protected @NonNullByDefault({}) JdbcConfiguration conf; protected final Map sqlTables = new HashMap<>(); private long afterAccessMin = 10000; private long afterAccessMax = 0; @@ -72,10 +74,15 @@ public class JdbcMapper { logger.debug( "JDBC::pingDB asking db for name as absolutely first db action, after connection is established."); String dbName = conf.getDBDAO().doGetDB(); - conf.setDbName(dbName); - ret = dbName.length() > 0; + if (dbName == null) { + ret = false; + } else { + conf.setDbName(dbName); + ret = dbName.length() > 0; + } } else { - ret = conf.getDBDAO().doPingDB() > 0; + final @Nullable Integer result = conf.getDBDAO().doPingDB(); + ret = result != null && result > 0; } } logTime("pingDB", timerStart, System.currentTimeMillis()); @@ -86,8 +93,8 @@ public class JdbcMapper { logger.debug("JDBC::getDB"); long timerStart = System.currentTimeMillis(); String res = conf.getDBDAO().doGetDB(); - logTime("pingDB", timerStart, System.currentTimeMillis()); - return res; + logTime("getDB", timerStart, System.currentTimeMillis()); + return res != null ? res : ""; } public ItemsVO createNewEntryInItemsTable(ItemsVO vo) { @@ -154,10 +161,6 @@ public class JdbcMapper { 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(); if (date == null) { conf.getDBDAO().doStoreItemValue(item, itemState, new ItemVO(tableName, null)); @@ -173,40 +176,27 @@ public class JdbcMapper { Item item) { logger.debug( "JDBC::getHistItemFilterQuery filter='{}' numberDecimalcount='{}' table='{}' item='{}' itemName='{}'", - (filter != null), numberDecimalcount, table, item, item.getName()); - if (table != null) { - long timerStart = System.currentTimeMillis(); - List result = conf.getDBDAO().doGetHistItemFilterQuery(item, filter, numberDecimalcount, - table, item.getName(), timeZoneProvider.getTimeZone()); - logTime("getHistItemFilterQuery", timerStart, System.currentTimeMillis()); - errCnt = 0; - return result; - } else { - logger.error("JDBC::getHistItemFilterQuery: TABLE is NULL; cannot get data from non-existent table."); - } - return null; + true, numberDecimalcount, table, item, item.getName()); + long timerStart = System.currentTimeMillis(); + List result = conf.getDBDAO().doGetHistItemFilterQuery(item, filter, numberDecimalcount, table, + item.getName(), timeZoneProvider.getTimeZone()); + logTime("getHistItemFilterQuery", timerStart, System.currentTimeMillis()); + errCnt = 0; + return result; } - @SuppressWarnings("null") public boolean deleteItemValues(FilterCriteria filter, String table) { - logger.debug("JDBC::deleteItemValues filter='{}' table='{}' itemName='{}'", (filter != null), table, - filter.getItemName()); - if (table != null) { - long timerStart = System.currentTimeMillis(); - conf.getDBDAO().doDeleteItemValues(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; - } + logger.debug("JDBC::deleteItemValues filter='{}' table='{}' itemName='{}'", true, table, filter.getItemName()); + long timerStart = System.currentTimeMillis(); + conf.getDBDAO().doDeleteItemValues(filter, table, timeZoneProvider.getTimeZone()); + logTime("deleteItemValues", timerStart, System.currentTimeMillis()); + errCnt = 0; + return true; } /*********************** * DATABASE CONNECTION * ***********************/ - @SuppressWarnings("null") protected boolean openConnection() { logger.debug("JDBC::openConnection isDriverAvailable: {}", conf.isDriverAvailable()); if (conf.isDriverAvailable() && !conf.isDbConnected()) { @@ -216,8 +206,9 @@ public class JdbcMapper { conf.setDbConnected(true); return true; } catch (PoolInitializationException e) { - if (e.getCause() instanceof SQLInvalidAuthorizationSpecException) { - logger.warn("JDBC::openConnection: failed to open connection: {}", e.getCause().getMessage()); + Throwable cause = e.getCause(); + if (cause instanceof SQLInvalidAuthorizationSpecException) { + logger.warn("JDBC::openConnection: failed to open connection: {}", cause.getMessage()); } else { logger.warn("JDBC::openConnection: failed to open connection: {}", e.getMessage()); } @@ -303,12 +294,6 @@ public class JdbcMapper { logger.debug("JDBC::getTable: getTableName with rowId={} itemName={}", rowId, itemName); tableName = getTableName(rowId, itemName); - // An error occurred adding the item name into the index list! - if (tableName == null) { - logger.error("JDBC::getTable: tableName was null; could not create a table for item '{}'", itemName); - return null; - } - // Create table for item String dataType = conf.getDBDAO().getDataType(item); ivo = new ItemVO(tableName, itemName); diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/utils/DbMetaData.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/utils/DbMetaData.java index d08740ec4..b15e5b724 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/utils/DbMetaData.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/utils/DbMetaData.java @@ -15,6 +15,8 @@ package org.openhab.persistence.jdbc.utils; import java.sql.DatabaseMetaData; import java.sql.SQLException; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.knowm.yank.Yank; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,6 +28,7 @@ import com.zaxxer.hikari.HikariDataSource; * * @author Helmut Lehmeyer - Initial contribution */ +@NonNullByDefault public class DbMetaData { private final Logger logger = LoggerFactory.getLogger(DbMetaData.class); @@ -34,8 +37,8 @@ public class DbMetaData { private int dbMinorVersion; private int driverMajorVersion; private int driverMinorVersion; - private String dbProductName; - private String dbProductVersion; + private @Nullable String dbProductName; + private @Nullable String dbProductVersion; public DbMetaData() { HikariDataSource h = Yank.getDefaultConnectionPool(); @@ -116,11 +119,11 @@ public class DbMetaData { return false; } - public String getDbProductName() { + public @Nullable String getDbProductName() { return dbProductName; } - public String getDbProductVersion() { + public @Nullable String getDbProductVersion() { return dbProductVersion; } } diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/utils/StringUtilsExt.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/utils/StringUtilsExt.java index 05b761e58..1894126da 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/utils/StringUtilsExt.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/utils/StringUtilsExt.java @@ -101,7 +101,7 @@ public class StringUtilsExt { props = new Properties(def); } - if (url == null || url.length() < 9) { + if (url.length() < 9) { return props; } diff --git a/bundles/org.openhab.persistence.jdbc/src/test/java/org/openhab/persistence/jdbc/db/JdbcBaseDAOTest.java b/bundles/org.openhab.persistence.jdbc/src/test/java/org/openhab/persistence/jdbc/db/JdbcBaseDAOTest.java index 79551fcef..37146ad07 100644 --- a/bundles/org.openhab.persistence.jdbc/src/test/java/org/openhab/persistence/jdbc/db/JdbcBaseDAOTest.java +++ b/bundles/org.openhab.persistence.jdbc/src/test/java/org/openhab/persistence/jdbc/db/JdbcBaseDAOTest.java @@ -14,6 +14,7 @@ package org.openhab.persistence.jdbc.db; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import java.time.LocalDateTime; @@ -79,32 +80,32 @@ public class JdbcBaseDAOTest { public void testObjectAsStateReturnsValidState() { State decimalType = jdbcBaseDAO.objectAsState(new NumberItem("testNumberItem"), null, 7.3); assertInstanceOf(DecimalType.class, decimalType); - assertThat(decimalType, is(DecimalType.valueOf("7.3"))); + assertEquals(DecimalType.valueOf("7.3"), decimalType); State quantityType = jdbcBaseDAO.objectAsState(new NumberItem("testNumberItem"), SIUnits.CELSIUS, 7.3); assertInstanceOf(QuantityType.class, quantityType); - assertThat(quantityType, is(QuantityType.valueOf("7.3 °C"))); + assertEquals(QuantityType.valueOf("7.3 °C"), quantityType); State dateTimeType = jdbcBaseDAO.objectAsState(new DateTimeItem("testDateTimeItem"), null, java.sql.Timestamp.valueOf("2021-02-01 23:30:02.049")); assertInstanceOf(DateTimeType.class, dateTimeType); - assertThat(dateTimeType, is(DateTimeType.valueOf("2021-02-01T23:30:02.049"))); + assertEquals(DateTimeType.valueOf("2021-02-01T23:30:02.049"), dateTimeType); dateTimeType = jdbcBaseDAO.objectAsState(new DateTimeItem("testDateTimeItem"), null, LocalDateTime.parse("2021-02-01T23:30:02.049")); assertInstanceOf(DateTimeType.class, dateTimeType); - assertThat(dateTimeType, is(DateTimeType.valueOf("2021-02-01T23:30:02.049"))); + assertEquals(DateTimeType.valueOf("2021-02-01T23:30:02.049"), dateTimeType); State hsbType = jdbcBaseDAO.objectAsState(new ColorItem("testColorItem"), null, "184,100,52"); assertInstanceOf(HSBType.class, hsbType); - assertThat(hsbType, is(HSBType.valueOf("184,100,52"))); + assertEquals(HSBType.valueOf("184,100,52"), hsbType); State percentType = jdbcBaseDAO.objectAsState(new DimmerItem("testDimmerItem"), null, 52); assertInstanceOf(PercentType.class, percentType); - assertThat(percentType, is(PercentType.valueOf("52"))); + assertEquals(PercentType.valueOf("52"), percentType); percentType = jdbcBaseDAO.objectAsState(new RollershutterItem("testRollershutterItem"), null, 39); assertInstanceOf(PercentType.class, percentType); - assertThat(percentType, is(PercentType.valueOf("39"))); + assertEquals(PercentType.valueOf("39"), percentType); State openClosedType = jdbcBaseDAO.objectAsState(new ContactItem("testContactItem"), null, "OPEN"); assertInstanceOf(OpenClosedType.class, openClosedType); @@ -123,7 +124,7 @@ public class JdbcBaseDAOTest { State stringListType = jdbcBaseDAO.objectAsState(new CallItem("testCallItem"), null, "0699222222,0179999998"); assertInstanceOf(StringListType.class, stringListType); - assertThat(stringListType, is(StringListType.valueOf("0699222222,0179999998"))); + assertEquals(StringListType.valueOf("0699222222,0179999998"), stringListType); State expectedRawType = new RawType(new byte[0], "application/octet-stream"); State rawType = jdbcBaseDAO.objectAsState(new ImageItem("testImageItem"), null, expectedRawType.toFullString()); @@ -132,11 +133,11 @@ public class JdbcBaseDAOTest { State pointType = jdbcBaseDAO.objectAsState(new LocationItem("testLocationItem"), null, "1,2,3"); assertInstanceOf(PointType.class, pointType); - assertThat(pointType, is(PointType.valueOf("1,2,3"))); + assertEquals(PointType.valueOf("1,2,3"), pointType); State stringType = jdbcBaseDAO.objectAsState(new StringItem("testStringItem"), null, "String"); assertInstanceOf(StringType.class, stringType); - assertThat(stringType, is(StringType.valueOf("String"))); + assertEquals(StringType.valueOf("String"), stringType); } @Test