From caeec68999317317d0abb0e4aafcf8d48d68ba2d Mon Sep 17 00:00:00 2001 From: Stefan Neuhaus Date: Sun, 19 Feb 2017 17:15:05 +0100 Subject: [PATCH] Refactor CveDB - make class thread-safe and declare so (also DatabaseProperties) - prepared statements represented by enum: performance gain, eases experiments when tuning for performance - minor changes/cleanup/code style --- .../dependencycheck/data/nvdcve/CveDB.java | 328 ++++++++++-------- .../data/nvdcve/DatabaseProperties.java | 3 + .../resources/data/dbStatements.properties | 3 +- 3 files changed, 196 insertions(+), 138 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java index ea63d3935..8c82eeff1 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java @@ -23,8 +23,8 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; import java.util.ArrayList; +import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -35,6 +35,7 @@ import java.util.MissingResourceException; import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.data.cwe.CweDB; import org.owasp.dependencycheck.dependency.Reference; import org.owasp.dependencycheck.dependency.Vulnerability; @@ -47,12 +48,17 @@ import org.owasp.dependencycheck.utils.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.owasp.dependencycheck.data.nvdcve.CveDB.PreparedStatementCveDb.*; + /** * The database holding information about the NVD CVE data. + * This class is safe to be accessed from multiple threads in parallel, however + * internally only one connection will be used. * * @author Jeremy Long */ -public class CveDB { +@ThreadSafe +public final class CveDB { /** * The logger. @@ -61,18 +67,55 @@ public class CveDB { /** * Database connection */ - private Connection conn; + private Connection connection; /** * The bundle of statements used when accessing the database. */ - private ResourceBundle statementBundle = null; - + private final ResourceBundle statementBundle; + /** + * Database properties object containing the 'properties' from the database + * table. + */ + private final DatabaseProperties databaseProperties; /** * Creates a new CveDB object and opens the database connection. Note, the * connection must be closed by the caller by calling the close method. * ======= Does the underlying connection support batch operations? */ - private boolean batchSupported; + private final boolean batchSupported; + /** + * The prepared statements. + */ + private final EnumMap preparedStatements; + + /** + * The enum value names must match the keys of the statements in the + * statement bundles "dbStatements*.properties". + */ + enum PreparedStatementCveDb { + CLEANUP_ORPHANS, + COUNT_CPE, + DELETE_REFERENCE, + DELETE_SOFTWARE, + DELETE_VULNERABILITY, + INSERT_CPE, + INSERT_PROPERTY, + INSERT_REFERENCE, + INSERT_SOFTWARE, + INSERT_VULNERABILITY, + MERGE_PROPERTY, + SELECT_CPE_ENTRIES, + SELECT_CPE_ID, + SELECT_CVE_FROM_SOFTWARE, + SELECT_PROPERTIES, + SELECT_REFERENCES, + SELECT_SOFTWARE, + SELECT_VENDOR_PRODUCT_LIST, + SELECT_VULNERABILITY, + SELECT_VULNERABILITY_ID, + UPDATE_PROPERTY, + UPDATE_VULNERABILITY + } /** * Creates a new CveDB object and opens the database connection. Note, the @@ -82,34 +125,54 @@ public class CveDB { * database. */ public CveDB() throws DatabaseException { - super(); + open(); + final String databaseProductName = determineDatabaseProductName(); + batchSupported = isBatchSupportedFor(databaseProductName); + statementBundle = databaseProductName != null ? + ResourceBundle.getBundle("data/dbStatements", new Locale(databaseProductName)) : + ResourceBundle.getBundle("data/dbStatements"); + preparedStatements = prepareStatements(); + databaseProperties = new DatabaseProperties(this); + } + + /** + * Tries to determine the product name of the database. + * + * @return the product name of the database if successful, {@code null} else + */ + private String determineDatabaseProductName() { try { - open(); - try { - final String databaseProductName = conn.getMetaData().getDatabaseProductName(); - LOGGER.debug("Database dialect: {}", databaseProductName); - final Locale dbDialect = new Locale(databaseProductName); - statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect); - if ("mysql".equalsIgnoreCase(databaseProductName)) { - batchSupported = false; - } - } catch (SQLException se) { - LOGGER.warn("Problem loading database specific dialect!", se); - statementBundle = ResourceBundle.getBundle("data/dbStatements"); - } - databaseProperties = new DatabaseProperties(this); - } catch (DatabaseException ex) { - throw ex; + final String databaseProductName = getConnection().getMetaData().getDatabaseProductName(); + LOGGER.debug("Database product: {}", databaseProductName); + return databaseProductName; + } catch (SQLException se) { + LOGGER.warn("Problem determining database product!", se); + return null; } } + /** + * Returns if the database supports batch execution of statements. + * + * @param databaseProductName the product name of the database + * @return if the database supports batch execution + */ + private boolean isBatchSupportedFor(String databaseProductName) { + if ("mysql".equalsIgnoreCase(databaseProductName)) { + return false; + } + + // per default we do not support batch execution + return false; + } + /** * Returns the database connection. * * @return the database connection */ - protected Connection getConnection() { - return conn; + private Connection getConnection() { + return connection; } /** @@ -119,9 +182,9 @@ public class CveDB { * @throws DatabaseException thrown if there is an error opening the * database connection */ - public final synchronized void open() throws DatabaseException { + public synchronized void open() throws DatabaseException { if (!isOpen()) { - conn = ConnectionFactory.getConnection(); + connection = ConnectionFactory.getConnection(); } } @@ -130,9 +193,10 @@ public class CveDB { * is done being used. */ public synchronized void close() { - if (conn != null) { + if (isOpen()) { + closeStatements(); try { - conn.close(); + getConnection().close(); } catch (SQLException ex) { LOGGER.error("There was an error attempting to close the CveDB, see the log for more details."); LOGGER.debug("", ex); @@ -140,7 +204,7 @@ public class CveDB { LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details."); LOGGER.debug("", ex); } - conn = null; + connection = null; } } @@ -149,8 +213,57 @@ public class CveDB { * * @return whether the database connection is open or closed */ - public synchronized boolean isOpen() { - return conn != null; + private boolean isOpen() { + return getConnection() != null; + } + + /** + * Prepares all statements to be used and returns them. + * + * @return the prepared statements + * @throws DatabaseException thrown if there is an error preparing the statements + */ + private EnumMap prepareStatements() + throws DatabaseException { + + final EnumMap result = new EnumMap(PreparedStatementCveDb.class); + for (PreparedStatementCveDb key : PreparedStatementCveDb.values()) { + final String statementString = statementBundle.getString(key.name()); + final PreparedStatement preparedStatement; + try { + if (key == INSERT_VULNERABILITY || key == INSERT_CPE) { + preparedStatement = getConnection().prepareStatement(statementString, new String[]{"id"}); + } else { + preparedStatement = getConnection().prepareStatement(statementString); + } + } catch (SQLException exception) { + throw new DatabaseException(exception); + } + result.put(key, preparedStatement); + } + return result; + } + + /** + * Closes all prepared statements. + */ + private void closeStatements() { + for (PreparedStatement preparedStatement : preparedStatements.values()) { + DBUtils.closeStatement(preparedStatement); + } + } + + /** + * Returns the specified prepared statement. + * + * @param key the prepared statement from {@link PreparedStatementCveDb} to return + * @return the prepared statement + * @throws SQLException thrown if a SQL Exception occurs + */ + private PreparedStatement getPreparedStatement(PreparedStatementCveDb key) throws SQLException { + final PreparedStatement preparedStatement = preparedStatements.get(key); + preparedStatement.clearParameters(); + return preparedStatement; } /** @@ -160,8 +273,8 @@ public class CveDB { */ public synchronized void commit() throws SQLException { //temporary remove this as autocommit is on. - //if (conn != null) { - // conn.commit(); + //if (isOpen()) { + // getConnection().commit(); //} } @@ -177,11 +290,6 @@ public class CveDB { close(); super.finalize(); } - /** - * Database properties object containing the 'properties' from the database - * table. - */ - private DatabaseProperties databaseProperties; /** * Get the value of databaseProperties. @@ -205,9 +313,8 @@ public class CveDB { public synchronized Set getCPEs(String vendor, String product) { final Set cpe = new HashSet(); ResultSet rs = null; - PreparedStatement ps = null; try { - ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ENTRIES")); + final PreparedStatement ps = getPreparedStatement(SELECT_CPE_ENTRIES); ps.setString(1, vendor); ps.setString(2, product); rs = ps.executeQuery(); @@ -222,7 +329,6 @@ public class CveDB { LOGGER.debug("", ex); } finally { DBUtils.closeResultSet(rs); - DBUtils.closeStatement(ps); } return cpe; } @@ -237,9 +343,8 @@ public class CveDB { public synchronized Set> getVendorProductList() throws DatabaseException { final Set> data = new HashSet>(); ResultSet rs = null; - PreparedStatement ps = null; try { - ps = getConnection().prepareStatement(statementBundle.getString("SELECT_VENDOR_PRODUCT_LIST")); + final PreparedStatement ps = getPreparedStatement(SELECT_VENDOR_PRODUCT_LIST); rs = ps.executeQuery(); while (rs.next()) { data.add(new Pair(rs.getString(1), rs.getString(2))); @@ -249,7 +354,6 @@ public class CveDB { throw new DatabaseException(msg, ex); } finally { DBUtils.closeResultSet(rs); - DBUtils.closeStatement(ps); } return data; } @@ -261,10 +365,9 @@ public class CveDB { */ public synchronized Properties getProperties() { final Properties prop = new Properties(); - PreparedStatement ps = null; ResultSet rs = null; try { - ps = getConnection().prepareStatement(statementBundle.getString("SELECT_PROPERTIES")); + final PreparedStatement ps = getPreparedStatement(SELECT_PROPERTIES); rs = ps.executeQuery(); while (rs.next()) { prop.setProperty(rs.getString(1), rs.getString(2)); @@ -273,7 +376,6 @@ public class CveDB { LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); LOGGER.debug("", ex); } finally { - DBUtils.closeStatement(ps); DBUtils.closeResultSet(rs); } return prop; @@ -288,31 +390,20 @@ public class CveDB { public synchronized void saveProperty(String key, String value) { try { try { - final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY")); - try { - mergeProperty.setString(1, key); - mergeProperty.setString(2, value); - mergeProperty.executeUpdate(); - } finally { - DBUtils.closeStatement(mergeProperty); - } + final PreparedStatement mergeProperty = getPreparedStatement(MERGE_PROPERTY); + mergeProperty.setString(1, key); + mergeProperty.setString(2, value); + mergeProperty.executeUpdate(); } catch (MissingResourceException mre) { // No Merge statement, so doing an Update/Insert... - PreparedStatement updateProperty = null; - PreparedStatement insertProperty = null; - try { - updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY")); - updateProperty.setString(1, value); - updateProperty.setString(2, key); - if (updateProperty.executeUpdate() == 0) { - insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY")); - insertProperty.setString(1, key); - insertProperty.setString(2, value); - insertProperty.executeUpdate(); - } - } finally { - DBUtils.closeStatement(updateProperty); - DBUtils.closeStatement(insertProperty); + final PreparedStatement updateProperty = getPreparedStatement(UPDATE_PROPERTY); + updateProperty.setString(1, value); + updateProperty.setString(2, key); + if (updateProperty.executeUpdate() == 0) { + final PreparedStatement insertProperty = getPreparedStatement(INSERT_PROPERTY); + insertProperty.setString(1, key); + insertProperty.setString(2, value); + insertProperty.executeUpdate(); } } } catch (SQLException ex) { @@ -338,10 +429,9 @@ public class CveDB { final DependencyVersion detectedVersion = parseDependencyVersion(cpe); final List vulnerabilities = new ArrayList(); - PreparedStatement ps = null; ResultSet rs = null; try { - ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CVE_FROM_SOFTWARE")); + final PreparedStatement ps = getPreparedStatement(SELECT_CVE_FROM_SOFTWARE); ps.setString(1, cpe.getVendor()); ps.setString(2, cpe.getProduct()); rs = ps.executeQuery(); @@ -377,7 +467,6 @@ public class CveDB { throw new DatabaseException("Exception retrieving vulnerability for " + cpeStr, ex); } finally { DBUtils.closeResultSet(rs); - DBUtils.closeStatement(ps); } return vulnerabilities; } @@ -390,16 +479,13 @@ public class CveDB { * @throws DatabaseException if an exception occurs */ public synchronized Vulnerability getVulnerability(String cve) throws DatabaseException { - PreparedStatement psV = null; - PreparedStatement psR = null; - PreparedStatement psS = null; ResultSet rsV = null; ResultSet rsR = null; ResultSet rsS = null; Vulnerability vuln = null; try { - psV = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY")); + final PreparedStatement psV = getPreparedStatement(SELECT_VULNERABILITY); psV.setString(1, cve); rsV = psV.executeQuery(); if (rsV.next()) { @@ -423,13 +509,14 @@ public class CveDB { vuln.setCvssIntegrityImpact(rsV.getString(9)); vuln.setCvssAvailabilityImpact(rsV.getString(10)); - psR = getConnection().prepareStatement(statementBundle.getString("SELECT_REFERENCES")); + final PreparedStatement psR = getPreparedStatement(SELECT_REFERENCES); psR.setInt(1, cveId); rsR = psR.executeQuery(); while (rsR.next()) { vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3)); } - psS = getConnection().prepareStatement(statementBundle.getString("SELECT_SOFTWARE")); + + final PreparedStatement psS = getPreparedStatement(SELECT_SOFTWARE); psS.setInt(1, cveId); rsS = psS.executeQuery(); while (rsS.next()) { @@ -448,9 +535,6 @@ public class CveDB { DBUtils.closeResultSet(rsV); DBUtils.closeResultSet(rsR); DBUtils.closeResultSet(rsS); - DBUtils.closeStatement(psV); - DBUtils.closeStatement(psR); - DBUtils.closeStatement(psS); } return vuln; } @@ -463,52 +547,31 @@ public class CveDB { * @throws DatabaseException is thrown if the database */ public synchronized void updateVulnerability(Vulnerability vuln) throws DatabaseException { - PreparedStatement selectVulnerabilityId = null; - PreparedStatement deleteVulnerability = null; - PreparedStatement deleteReferences = null; - PreparedStatement deleteSoftware = null; - PreparedStatement updateVulnerability = null; - PreparedStatement insertVulnerability = null; - PreparedStatement insertReference = null; - PreparedStatement selectCpeId = null; - PreparedStatement insertCpe = null; - PreparedStatement insertSoftware = null; - try { - selectVulnerabilityId = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY_ID")); - deleteVulnerability = getConnection().prepareStatement(statementBundle.getString("DELETE_VULNERABILITY")); - deleteReferences = getConnection().prepareStatement(statementBundle.getString("DELETE_REFERENCE")); - deleteSoftware = getConnection().prepareStatement(statementBundle.getString("DELETE_SOFTWARE")); - updateVulnerability = getConnection().prepareStatement(statementBundle.getString("UPDATE_VULNERABILITY")); - final String[] ids = {"id"}; - insertVulnerability = getConnection().prepareStatement(statementBundle.getString("INSERT_VULNERABILITY"), - //Statement.RETURN_GENERATED_KEYS); - ids); - insertReference = getConnection().prepareStatement(statementBundle.getString("INSERT_REFERENCE")); - selectCpeId = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ID")); - insertCpe = getConnection().prepareStatement(statementBundle.getString("INSERT_CPE"), - //Statement.RETURN_GENERATED_KEYS); - ids); - insertSoftware = getConnection().prepareStatement(statementBundle.getString("INSERT_SOFTWARE")); int vulnerabilityId = 0; + final PreparedStatement selectVulnerabilityId = getPreparedStatement(SELECT_VULNERABILITY_ID); selectVulnerabilityId.setString(1, vuln.getName()); ResultSet rs = selectVulnerabilityId.executeQuery(); if (rs.next()) { vulnerabilityId = rs.getInt(1); // first delete any existing vulnerability info. We don't know what was updated. yes, slower but atm easier. - deleteReferences.setInt(1, vulnerabilityId); - deleteReferences.execute(); + final PreparedStatement deleteReference = getPreparedStatement(DELETE_REFERENCE); + deleteReference.setInt(1, vulnerabilityId); + deleteReference.execute(); + + final PreparedStatement deleteSoftware = getPreparedStatement(DELETE_SOFTWARE); deleteSoftware.setInt(1, vulnerabilityId); deleteSoftware.execute(); } DBUtils.closeResultSet(rs); - rs = null; if (vulnerabilityId != 0) { if (vuln.getDescription().contains("** REJECT **")) { + final PreparedStatement deleteVulnerability = getPreparedStatement(DELETE_VULNERABILITY); deleteVulnerability.setInt(1, vulnerabilityId); deleteVulnerability.executeUpdate(); } else { + final PreparedStatement updateVulnerability = getPreparedStatement(UPDATE_VULNERABILITY); updateVulnerability.setString(1, vuln.getDescription()); updateVulnerability.setString(2, vuln.getCwe()); updateVulnerability.setFloat(3, vuln.getCvssScore()); @@ -522,6 +585,7 @@ public class CveDB { updateVulnerability.executeUpdate(); } } else { + final PreparedStatement insertVulnerability = getPreparedStatement(INSERT_VULNERABILITY); insertVulnerability.setString(1, vuln.getName()); insertVulnerability.setString(2, vuln.getDescription()); insertVulnerability.setString(3, vuln.getCwe()); @@ -542,10 +606,13 @@ public class CveDB { throw new DatabaseException(msg, ex); } finally { DBUtils.closeResultSet(rs); - rs = null; } } + final PreparedStatement insertReference = getPreparedStatement(INSERT_REFERENCE); + if(batchSupported) { + insertReference.clearBatch(); + } for (Reference r : vuln.getReferences()) { insertReference.setInt(1, vulnerabilityId); insertReference.setString(2, r.getName()); @@ -563,8 +630,13 @@ public class CveDB { insertReference.executeBatch(); } + final PreparedStatement insertSoftware = getPreparedStatement(INSERT_SOFTWARE); + if(batchSupported) { + insertSoftware.clearBatch(); + } for (VulnerableSoftware s : vuln.getVulnerableSoftware()) { int cpeProductId = 0; + final PreparedStatement selectCpeId = getPreparedStatement(SELECT_CPE_ID); selectCpeId.setString(1, s.getName()); try { rs = selectCpeId.executeQuery(); @@ -575,10 +647,10 @@ public class CveDB { throw new DatabaseException("Unable to get primary key for new cpe: " + s.getName(), ex); } finally { DBUtils.closeResultSet(rs); - rs = null; } if (cpeProductId == 0) { + final PreparedStatement insertCpe = getPreparedStatement(INSERT_CPE); insertCpe.setString(1, s.getName()); insertCpe.setString(2, s.getVendor()); insertCpe.setString(3, s.getProduct()); @@ -605,7 +677,7 @@ public class CveDB { } catch (SQLException ex) { if (ex.getMessage().contains("Duplicate entry")) { final String msg = String.format("Duplicate software key identified in '%s:%s'", vuln.getName(), s.getName()); - LOGGER.debug(msg, ex); + LOGGER.info(msg, ex); } else { throw ex; } @@ -619,17 +691,6 @@ public class CveDB { final String msg = String.format("Error updating '%s'", vuln.getName()); LOGGER.debug(msg, ex); throw new DatabaseException(msg, ex); - } finally { - DBUtils.closeStatement(selectVulnerabilityId); - DBUtils.closeStatement(deleteReferences); - DBUtils.closeStatement(deleteSoftware); - DBUtils.closeStatement(updateVulnerability); - DBUtils.closeStatement(deleteVulnerability); - DBUtils.closeStatement(insertVulnerability); - DBUtils.closeStatement(insertReference); - DBUtils.closeStatement(selectCpeId); - DBUtils.closeStatement(insertCpe); - DBUtils.closeStatement(insertSoftware); } } @@ -639,17 +700,16 @@ public class CveDB { * @return true if data exists; otherwise false */ public synchronized boolean dataExists() { - Statement cs = null; ResultSet rs = null; try { - cs = conn.createStatement(); - rs = cs.executeQuery("SELECT COUNT(*) records FROM cpeEntry"); + final PreparedStatement cs = getPreparedStatement(COUNT_CPE); + rs = cs.executeQuery(); if (rs.next()) { if (rs.getInt(1) > 0) { return true; } } - } catch (SQLException ex) { + } catch (Exception ex) { String dd; try { dd = Settings.getDataDirectory().getAbsolutePath(); @@ -664,7 +724,6 @@ public class CveDB { LOGGER.debug("", ex); } finally { DBUtils.closeResultSet(rs); - DBUtils.closeStatement(cs); } return false; } @@ -675,17 +734,14 @@ public class CveDB { * ensure orphan entries are removed. */ public synchronized void cleanupDatabase() { - PreparedStatement ps = null; try { - ps = getConnection().prepareStatement(statementBundle.getString("CLEANUP_ORPHANS")); + final PreparedStatement ps = getPreparedStatement(CLEANUP_ORPHANS); if (ps != null) { ps.executeUpdate(); } } catch (SQLException ex) { LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details."); LOGGER.debug("", ex); - } finally { - DBUtils.closeStatement(ps); } } @@ -819,7 +875,6 @@ public class CveDB { ps.executeUpdate(); } catch (SQLException ex) { LOGGER.error("Unable to delete CPE dictionary entries", ex); - } finally { DBUtils.closeStatement(ps); } } @@ -844,7 +899,6 @@ public class CveDB { ps.executeUpdate(); } catch (SQLException ex) { LOGGER.error("Unable to add CPE dictionary entry", ex); - } finally { DBUtils.closeStatement(ps); } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java index 8283fc5f2..a3b2aa86c 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java @@ -21,6 +21,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.TreeMap; +import javax.annotation.concurrent.ThreadSafe; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; @@ -31,9 +32,11 @@ import org.slf4j.LoggerFactory; /** * This is a wrapper around a set of properties that are stored in the database. + * This class is safe to be accessed from multiple threads in parallel. * * @author Jeremy Long */ +@ThreadSafe public class DatabaseProperties { /** diff --git a/dependency-check-core/src/main/resources/data/dbStatements.properties b/dependency-check-core/src/main/resources/data/dbStatements.properties index 6849503d1..d7c4eb276 100644 --- a/dependency-check-core/src/main/resources/data/dbStatements.properties +++ b/dependency-check-core/src/main/resources/data/dbStatements.properties @@ -19,6 +19,7 @@ DELETE_REFERENCE=DELETE FROM reference WHERE cveid = ? DELETE_SOFTWARE=DELETE FROM software WHERE cveid = ? DELETE_VULNERABILITY=DELETE FROM vulnerability WHERE id = ? CLEANUP_ORPHANS=DELETE FROM cpeEntry WHERE id not in (SELECT CPEEntryId FROM software); +COUNT_CPE=SELECT COUNT(*) records FROM cpeEntry INSERT_REFERENCE=INSERT INTO reference (cveid, name, url, source) VALUES (?, ?, ?, ?) INSERT_SOFTWARE=INSERT INTO software (cveid, cpeEntryId, previousVersion) VALUES (?, ?, ?) INSERT_CPE=INSERT INTO cpeEntry (cpe, vendor, product) VALUES (?, ?, ?) @@ -38,6 +39,6 @@ INSERT_PROPERTY=INSERT INTO properties (id, value) VALUES (?, ?) UPDATE_PROPERTY=UPDATE properties SET value = ? WHERE id = ? DELETE_PROPERTY=DELETE FROM properties WHERE id = ? -#the following two statements are unused and are only referenecd in dead code +#the following two statements are unused and are only referenced in dead code DELETE_UNUSED_DICT_CPE=DELETE FROM cpeEntry WHERE dictionaryEntry=true AND id NOT IN (SELECT cpeEntryId FROM software) ADD_DICT_CPE=MERGE INTO cpeEntry (cpe, vendor, product, dictionaryEntry) KEY(cpe) VALUES(?,?,?,true)