A few changes:
authorChris Jaekl <chris@ringo.jaekl.net>
Fri, 25 Sep 2015 13:01:59 +0000 (22:01 +0900)
committerChris Jaekl <chris@ringo.jaekl.net>
Fri, 25 Sep 2015 13:01:59 +0000 (22:01 +0900)
(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

prod/cfb.properties
prod/net/jaekl/cfb/CFB.java
prod/net/jaekl/cfb/analyze/MessageMap.java
prod/net/jaekl/cfb/db/CfbSchema.java
prod/net/jaekl/cfb/db/Schema.java
prod/net/jaekl/cfb/db/driver/DbDriver.java
prod/net/jaekl/cfb/db/driver/PostgresqlDriver.java
prod/net/jaekl/cfb/xml/messages/BugCategory.java
prod/net/jaekl/cfb/xml/messages/BugPattern.java

index 78c33520181377b2e20c1fd8a0352468f82e3800..50278187010526e786517f685c6b6a9c26e2f378 100644 (file)
@@ -1,5 +1,5 @@
 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<-----
index f229ce1d7eae767674bfdb268ec9f377a55c4767..924d33182d28c4824207b6fde0712d4362d6d6b7 100644 (file)
@@ -47,6 +47,7 @@ public class CFB {
        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();
@@ -62,6 +63,7 @@ public class CFB {
                m_pass = "";
                m_user = "user";
                m_buildNum = null;
+               m_removeSchema = false;
        }
        
        Options createOptions() {
@@ -72,6 +74,7 @@ public class CFB {
                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");
                
@@ -98,6 +101,7 @@ public class CFB {
                        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"));
                        }
@@ -160,6 +164,11 @@ public class CFB {
                
                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) {
index ac5288faf7e673b48fbf9f6c51fb4264f8f7a057..97180030af8a9b80e109278532fe81f4afc29436 100644 (file)
@@ -36,9 +36,11 @@ public class MessageMap {
                
                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()) {
index 1b989ff5e3ba6a91c372d06dd32e29b86715d9ff..d80be57940a084ebeb81dbe17844f7d5cde4c103 100644 (file)
@@ -7,9 +7,12 @@ import static net.jaekl.cfb.db.Column.Type.*;
 
 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 {
@@ -115,8 +118,51 @@ 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);
+       }
 }
index 4937fae153eae94dacf8c051c8c49d07b7775892..898687ee4db5fd65112c10d6c39663b1891b4765 100644 (file)
@@ -41,12 +41,17 @@ public class Schema {
                }
                
                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 
@@ -90,6 +95,17 @@ public class Schema {
                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)) {
@@ -99,6 +115,17 @@ public class Schema {
                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);
        }
index ac9f8ccdad2030150d25d0fe06cd15078c8d7fb4..ecfe2a7eae6bd48e4eef3d0160e0380a09a3274d 100644 (file)
@@ -30,7 +30,8 @@ public abstract class DbDriver {
        
        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();
@@ -42,6 +43,17 @@ public abstract class DbDriver {
                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);
@@ -55,6 +67,17 @@ public abstract class DbDriver {
                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
        {
@@ -74,7 +97,7 @@ public abstract class DbDriver {
                                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);
@@ -120,6 +143,22 @@ public abstract class DbDriver {
                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;
@@ -247,10 +286,26 @@ public abstract class DbDriver {
                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);
 }
index a8d28f9bb0a3b6700a92953bb00f3589cf01bb29..8e19fc49aca4f63ef76336e2fa0309a13d18c228 100644 (file)
@@ -7,6 +7,8 @@ import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.util.Properties;
 
+import net.jaekl.cfb.db.Sequence;
+
 public class PostgresqlDriver extends DbDriver {
 
        @Override
@@ -26,4 +28,10 @@ public class PostgresqlDriver extends DbDriver {
                //props.setProperty("ssl", "true");
                return DriverManager.getConnection(url, props);
        }
+       
+       @Override 
+       public String nextValSql(Sequence seq) 
+       {
+               return " SELECT NEXTVAL('" + seq.getName() + "') ";
+       }
 }
index 6b5b492bd86fac8ebf2f3b57079c16f9954154c1..9e1f53920766e89bd2d8fbd384761b9f58d174ec 100644 (file)
@@ -21,9 +21,9 @@ public class BugCategory extends ParseResult {
        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 = "";
        }
        
index 82ada92f7f69cbf41cf3379c9f7fbfbe0675bdc5..b75733b162d14e39ccc16e835b4873b502119412 100644 (file)
@@ -21,9 +21,9 @@ public class BugPattern extends ParseResult {
        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 = "";
        }