(1) improve sequence support so that sequences can have their next value fetched from the DB
(2) add option ("-r") to remove (drop) the schema and all associated data from the db
(3) populate the bugs and categories tables when creating the database
analysis.failed=Attempt to analyze source code failed. Will now stop.
-cannot.connect.to.db=Unable to connect to database {2} on {0}:{1} as user {3}.
+cannot.connect.to.db=Unable to connect to, or to initialize, database {2} on {0}:{1} as user {3}.
cannot.exec=Got result code {1} when attempting to execute command-line: {0}
stderr.was=-----8<------ Error (stderr) output was: ------8<-----
stdout.was=-----8<----- Console (stdout) output was: -----8<-----
String m_user; // db user
String m_pass; // db password
String m_buildNum; // build number (version)
+ boolean m_removeSchema; // purge DB schema
CFB(Locale locale) {
m_driver = new PostgresqlDriver();
m_pass = "";
m_user = "user";
m_buildNum = null;
+ m_removeSchema = false;
}
Options createOptions() {
opt.addOption("h", "host", true, "DB hostname");
opt.addOption("n", "number", true, "Build number (version)");
opt.addOption("p", "pass", true, "DB password");
+ opt.addOption("r", "remove", false, "Remove database schema (drop all data)");
opt.addOption("t", "port", true, "DB port");
opt.addOption("u", "user", true, "DB username");
if (line.hasOption("p")) {
m_pass = line.getOptionValue("p");
}
+ m_removeSchema = line.hasOption("r");
if (line.hasOption("t")) {
m_port = Integer.parseInt(line.getOptionValue("t"));
}
try (Connection con = m_driver.connect(m_host, m_port, m_dbName, m_user, m_pass)) {
m_schema.setMessageMap(messageMap);
+
+ if (m_removeSchema) {
+ m_schema.purge(con);
+ return;
+ }
m_schema.ensureDbInitialized(con);
}
catch (SQLException exc) {
String langName = locale.getLanguage();
- File msgXml = new File(findBugsDir.getAbsolutePath() + File.separator + MESSAGES + "_" + langName + "." + XML);
+ String basePath = findBugsDir.getAbsolutePath() + File.separator + "etc" + File.separator;
+
+ File msgXml = new File(basePath + MESSAGES + "_" + langName + "." + XML);
if (! msgXml.canRead()) {
- msgXml = new File(findBugsDir.getAbsolutePath() + File.separator + MESSAGES + "." + XML);
+ msgXml = new File(basePath + MESSAGES + "." + XML);
}
if (! msgXml.canRead()) {
import java.sql.Connection;
import java.sql.SQLException;
+import java.util.Collection;
import net.jaekl.cfb.analyze.MessageMap;
import net.jaekl.cfb.db.driver.DbDriver;
+import net.jaekl.cfb.xml.messages.BugCategory;
+import net.jaekl.cfb.xml.messages.BugPattern;
public class CfbSchema extends Schema {
boolean postCreationInit(Connection con) throws SQLException {
assert(null != m_msgMap);
-
+ if (! insertCategories(con)) {
+ return false;
+ }
+ if (! insertPatterns(con)) {
+ return false;
+ }
return true;
}
+
+ boolean insertCategories(Connection con) throws SQLException {
+ Collection<BugCategory> categories = m_msgMap.getColl().getCategories();
+
+ Object[][] values = new Object[categories.size()][CATEGORIES.getNumColumns()];
+
+ int row = 0;
+ for (BugCategory cat : categories) {
+ long categoryId = m_driver.nextVal(con, CATEGORY_SEQ);
+
+ values[row][0] = Long.valueOf(categoryId);
+ values[row][1] = cat.getCategory();
+ row++;
+ }
+
+ int count = m_driver.insert(con, CATEGORIES, values);
+
+ return (categories.size() == count);
+ }
+
+ boolean insertPatterns(Connection con) throws SQLException {
+ Collection<BugPattern> patterns = m_msgMap.getColl().getPatterns();
+
+ Object[][] values = new Object[patterns.size()][BUGS.getNumColumns()];
+
+ int row = 0;
+ for (BugPattern bug : patterns) {
+ long bugId = m_driver.nextVal(con, BUG_SEQ);
+
+ values[row][0] = Long.valueOf(bugId);
+ values[row][1] = bug.getType();
+ row++;
+ }
+
+ int count = m_driver.insert(con, BUGS, values);
+
+ return (patterns.size() == count);
+ }
}
}
if (!postCreationInit(con)) {
-
+ return false;
}
return true;
}
+ public void purge(Connection con) throws SQLException {
+ dropAllTables(con);
+ dropAllSequences(con);
+ }
+
boolean postCreationInit(Connection con) throws SQLException {
// no-op
// Override this in a derived class if you need to initialize something
return true;
}
+ void dropAllTables(Connection con) {
+ for (Table table : m_tables) {
+ try {
+ m_driver.dropTable(con, table);
+ }
+ catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
boolean createAllSequences(Connection con) throws SQLException {
for (Sequence seq : m_sequences) {
if (!m_driver.createSequence(con, seq)) {
return true;
}
+ void dropAllSequences(Connection con) {
+ for (Sequence seq : m_sequences) {
+ try {
+ m_driver.dropSequence(con, seq);
+ }
+ catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
void addTable(Table table) {
m_tables.add(table);
}
public abstract Connection connect(String host, int port, String dbName, String user, String pass) throws SQLException;
- public boolean createTable(Connection con, Table table) throws SQLException {
+ public boolean createTable(Connection con, Table table) throws SQLException
+ {
String sql = createTableSql(table);
try (PreparedStatement ps = con.prepareStatement(sql)) {
ps.executeUpdate();
return true;
}
+ public void dropTable(Connection con, Table table) throws SQLException
+ {
+ String sql = dropTableSql(table);
+ try (PreparedStatement ps = con.prepareStatement(sql)) {
+ ps.executeUpdate();
+ }
+ catch (SQLException exc) {
+ throw new SQLException("Failed to drop table: " + sql, exc);
+ }
+ }
+
public boolean createSequence(Connection con, Sequence seq) throws SQLException
{
String sql = createSequenceSql(seq);
return true;
}
+ public void dropSequence(Connection con, Sequence seq) throws SQLException
+ {
+ String sql = dropSequenceSql(seq);
+ try (PreparedStatement ps = con.prepareStatement(sql)) {
+ ps.executeUpdate();
+ }
+ catch (SQLException exc) {
+ throw new SQLException("Failed to drop sequence: " + sql, exc);
+ }
+ }
+
public List<Row> select(Connection con, Column[] columns, Table[] tables, Condition[] conditions)
throws SQLException
{
while (rs.next()) {
Object[] values = new Object[columns.length];
for (index = 0; index < columns.length; ++index) {
- values[index] = rs.getObject(index);
+ values[index] = rs.getObject(index + 1);
}
Row row = new Row(columns, values);
result.add(row);
return count;
}
+ public long nextVal(Connection con, Sequence seq) throws SQLException
+ {
+ String sql = nextValSql(seq);
+
+ try (PreparedStatement ps = con.prepareStatement(sql))
+ {
+ try (ResultSet rs = ps.executeQuery()) {
+ if (rs.next()) {
+ return rs.getLong(1);
+ }
+ }
+ }
+
+ throw new SQLException("No value returned for sequence: " + sql);
+ }
+
int checkFlushBatch(PreparedStatement ps, int pendingValues, boolean forceFlush) throws SQLException
{
int count = 0;
return sb.toString();
}
+ protected String dropTableSql(Table table) {
+ assert(null != table);
+ assert(null != table.getName());
+
+ return "DROP TABLE " + table.getName();
+ }
+
protected String createSequenceSql(Sequence seq) {
assert(null != seq);
assert(null != seq.getName());
return "CREATE SEQUENCE " + seq.getName();
}
+
+ protected String dropSequenceSql(Sequence seq) {
+ assert(null != seq);
+ assert(null != seq.getName());
+
+ return "DROP SEQUENCE " + seq.getName();
+ }
+
+ abstract protected String nextValSql(Sequence seq);
}
import java.sql.SQLException;
import java.util.Properties;
+import net.jaekl.cfb.db.Sequence;
+
public class PostgresqlDriver extends DbDriver {
@Override
//props.setProperty("ssl", "true");
return DriverManager.getConnection(url, props);
}
+
+ @Override
+ public String nextValSql(Sequence seq)
+ {
+ return " SELECT NEXTVAL('" + seq.getName() + "') ";
+ }
}
String m_abbrev;
String m_details;
- public BugCategory(String tagName, String[] internalMemberTags, Object[][] externalParserTags)
+ public BugCategory()
{
- super(tagName, internalMemberTags, externalParserTags);
+ super(TAG, INTERNAL, EXTERNAL);
m_category = m_descr = m_abbrev = m_details = "";
}
String m_long;
String m_details;
- public BugPattern(String tagName, String[] internalMemberTags, Object[][] externalParserTags)
+ public BugPattern()
{
- super(tagName, internalMemberTags, externalParserTags);
+ super(TAG, INTERNAL, EXTERNAL);
m_type = m_short = m_long = m_details = "";
}