From 083fb5094456d37fa4765400a461625635fbf77d Mon Sep 17 00:00:00 2001 From: Chris Jaekl Date: Thu, 24 Sep 2015 22:06:49 +0900 Subject: [PATCH] Restructure database code. --- prod/net/jaekl/cfb/CFB.java | 12 +- prod/net/jaekl/cfb/db/CfbSchema.java | 142 +++++++++++++----- prod/net/jaekl/cfb/db/Schema.java | 23 ++- prod/net/jaekl/cfb/db/driver/DbDriver.java | 70 +++++++++ .../cfb/xml/messages/MessageCollection.java | 7 + 5 files changed, 205 insertions(+), 49 deletions(-) diff --git a/prod/net/jaekl/cfb/CFB.java b/prod/net/jaekl/cfb/CFB.java index 28d2b1c..f229ce1 100644 --- a/prod/net/jaekl/cfb/CFB.java +++ b/prod/net/jaekl/cfb/CFB.java @@ -152,19 +152,21 @@ public class CFB { if ( ! parseArgs(pw, args) ) { return; } + + File findBugsDir = getFindBugsDir(); + File workDir = new File("."); + MessageMap messageMap = new MessageMap(); + messageMap.load(findBugsDir, Locale.getDefault(Category.DISPLAY)); try (Connection con = m_driver.connect(m_host, m_port, m_dbName, m_user, m_pass)) { - m_schema.ensureDbInitialized(con); + m_schema.setMessageMap(messageMap); + m_schema.ensureDbInitialized(con); } catch (SQLException exc) { reportUnableToConnect(pw, exc); return; } - File findBugsDir = getFindBugsDir(); - File workDir = new File("."); - MessageMap messageMap = new MessageMap(); - messageMap.load(findBugsDir, Locale.getDefault(Category.DISPLAY)); Analyzer analyzer = new Analyzer(messageMap); Analysis analysis = analyzer.analyze(pw, workDir, m_fbp, m_buildNum); if (null == analysis) { diff --git a/prod/net/jaekl/cfb/db/CfbSchema.java b/prod/net/jaekl/cfb/db/CfbSchema.java index e214b1b..1b989ff 100644 --- a/prod/net/jaekl/cfb/db/CfbSchema.java +++ b/prod/net/jaekl/cfb/db/CfbSchema.java @@ -4,59 +4,119 @@ package net.jaekl.cfb.db; import static net.jaekl.cfb.db.Column.Null.*; import static net.jaekl.cfb.db.Column.Type.*; + +import java.sql.Connection; +import java.sql.SQLException; + +import net.jaekl.cfb.analyze.MessageMap; import net.jaekl.cfb.db.driver.DbDriver; public class CfbSchema extends Schema { + MessageMap m_msgMap; + + public static final Sequence BUG_SEQ = new Sequence("BUG_SEQ"); + public static final Sequence CATEGORY_SEQ = new Sequence("CATEGORY_SEQ"); + public static final Sequence FOUND_SEQ = new Sequence("FOUND_SEQ"); + public static final Sequence LOC_SEQ = new Sequence("LOC_SEQ"); + public static final Sequence RUN_SEQ = new Sequence("RUN_SEQ"); + + public static final String BUGID = "BUGID"; + public static final String CATEGORYID = "CATEGORYID"; + public static final String FOUNDID = "FOUNDID"; + public static final String LOCID = "LOCID"; + public static final String RUNID = "RUNID"; + // Define each table as follows: // { // { table_name }, // { column_name, type, width (-1 for default), null/not_null } // } - private static final Object[][][] TABLES = { - { - // Description of each possible bug - { "BUG" }, - { "BUGID", INTEGER, -1, NOT_NULL }, - { "TYPE", VARCHAR, 80, NOT_NULL } - }, - { - // Description of each possible bug category - { "CATEGORY" }, - { "CATEGORYID", INTEGER, -1, NOT_NULL }, - { "CATEGORY", VARCHAR, 80, NOT_NULL } - }, - { - // One BugInstance, found during an analysis - { "FOUND" }, - { "FOUNDID", INTEGER, -1, NOT_NULL }, - { "BUGID", INTEGER, -1, NOT_NULL }, - { "CATEGORYID", INTEGER, -1, NOT_NULL }, - { "FIRSTLOCID", INTEGER, -1, NOT_NULL }, - { "SECONDLOCID", INTEGER, -1, NULL }, - { "THIRDLOCID", INTEGER, -1, NULL } - }, - { - // Location in the source code referenced by a BugInstance - { "LOCATION" }, - { "LOCID", INTEGER, -1, NOT_NULL }, - { "CLASSNAME", VARCHAR, 256, NOT_NULL }, - { "STARTLINE", INTEGER, -1, NULL }, - { "ENDLINE", INTEGER, -1, NULL } - }, - { - // Runs of FindBugs, normally one per build version - { "RUN" }, - { "RUNID", INTEGER, -1, NOT_NULL }, - { "VERSION", VARCHAR, 32, NULL }, - { "STARTTIME", TIMESTAMPTZ, -1, NOT_NULL }, - { "ENDTIME", TIMESTAMPTZ, -1, NOT_NULL } - } - }; + private static final Object[][] BUGS_DEFN = + { + // Description of each possible bug + { "BUG" }, + { BUGID, INTEGER, -1, NOT_NULL }, + { "TYPE", VARCHAR, 80, NOT_NULL } + }; + private static final Object[][] CATEGORIES_DEFN = + { + // Description of each possible bug category + { "CATEGORY" }, + { CATEGORYID, INTEGER, -1, NOT_NULL }, + { "CATEGORY", VARCHAR, 80, NOT_NULL } + }; + private static final Object[][] FOUND_DEFN = + { + // One BugInstance, found during an analysis + { "FOUND" }, + { FOUNDID, INTEGER, -1, NOT_NULL }, + { "BUGID", INTEGER, -1, NOT_NULL }, + { "CATEGORYID", INTEGER, -1, NOT_NULL }, + { "FIRSTLOCID", INTEGER, -1, NOT_NULL }, + { "SECONDLOCID", INTEGER, -1, NULL }, + { "THIRDLOCID", INTEGER, -1, NULL } + }; + private static final Object[][] LOCATIONS_DEFN = + { + // Location in the source code referenced by a BugInstance + { "LOCATION" }, + { LOCID, INTEGER, -1, NOT_NULL }, + { "CLASSNAME", VARCHAR, 256, NOT_NULL }, + { "STARTLINE", INTEGER, -1, NULL }, + { "ENDLINE", INTEGER, -1, NULL } + }; + private static final Object[][] RUNS_DEFN = + { + // Runs of FindBugs, normally one per build version + { "RUN" }, + { RUNID, INTEGER, -1, NOT_NULL }, + { "VERSION", VARCHAR, 32, NULL }, + { "STARTTIME", TIMESTAMPTZ, -1, NOT_NULL }, + { "ENDTIME", TIMESTAMPTZ, -1, NOT_NULL } + }; + + public static final Table BUGS = Table.construct(BUGS_DEFN); + public static final Table CATEGORIES = Table.construct(CATEGORIES_DEFN); + public static final Table FOUND = Table.construct(FOUND_DEFN); + public static final Table LOCATIONS = Table.construct(LOCATIONS_DEFN); + public static final Table RUNS = Table.construct(RUNS_DEFN); + + private static final Sequence[] SEQUENCES = { + BUG_SEQ, + CATEGORY_SEQ, + FOUND_SEQ, + LOC_SEQ, + RUN_SEQ + }; + + private static final Table[] TABLES = { + BUGS, + CATEGORIES, + FOUND, + LOCATIONS, + RUNS + }; public CfbSchema(DbDriver driver) { super("CFB", driver); + + m_msgMap = null; addTables(TABLES); - } + addSequences(SEQUENCES); + } + + public void setMessageMap(MessageMap msgMap) { + m_msgMap = msgMap; + } + + @Override + boolean postCreationInit(Connection con) throws SQLException { + assert(null != m_msgMap); + + + + return true; + } } diff --git a/prod/net/jaekl/cfb/db/Schema.java b/prod/net/jaekl/cfb/db/Schema.java index f802b58..4937fae 100644 --- a/prod/net/jaekl/cfb/db/Schema.java +++ b/prod/net/jaekl/cfb/db/Schema.java @@ -40,6 +40,17 @@ public class Schema { return false; } + if (!postCreationInit(con)) { + + } + + return true; + } + + boolean postCreationInit(Connection con) throws SQLException { + // no-op + // Override this in a derived class if you need to initialize something + // after the tables and sequences are created. return true; } @@ -98,14 +109,20 @@ public class Schema { // { table_name }, // { column_name, type, width (-1 for default), null/not_null } // } - void addTables(Object[][][] tables) + void addTables(Table[] tables) { - for (Object[][] table : tables) { - addTable(Table.construct(table)); + for (Table table : tables) { + addTable(table); } } void addSequence(Sequence seq) { m_sequences.add(seq); } + + void addSequences(Sequence[] sequences) { + for (Sequence sequence : sequences) { + addSequence(sequence); + } + } } diff --git a/prod/net/jaekl/cfb/db/driver/DbDriver.java b/prod/net/jaekl/cfb/db/driver/DbDriver.java index 525ca70..ac9f8cc 100644 --- a/prod/net/jaekl/cfb/db/driver/DbDriver.java +++ b/prod/net/jaekl/cfb/db/driver/DbDriver.java @@ -19,6 +19,8 @@ import net.jaekl.cfb.db.Sequence; import net.jaekl.cfb.db.Table; public abstract class DbDriver { + static int PENDING_LIMIT = 1024; // Rough limit at which point we'll start a new batch for batch updates + DbDriver() { } @@ -83,6 +85,74 @@ public abstract class DbDriver { return result; } + // Returns the number of rows inserted + public int insert(Connection con, Table table, Object[][] values) throws SQLException + { + int count = 0; + int pendingValues = 0; + + String sql = insertSql(table); + + try (PreparedStatement ps = con.prepareStatement(sql)) + { + for (int row = 0; row < values.length; ++row) { + Object[] data = values[row]; + + assert(null != data); + assert(data.length == table.getNumColumns()); + + for (int col = 0; col < data.length; ++col) { + ps.setObject(col + 1, data[col]); + pendingValues++; + } + ps.addBatch(); + + int rowsFlushed = checkFlushBatch(ps, pendingValues, false); + if (rowsFlushed > 0) { + count += rowsFlushed; + pendingValues = 0; + } + } + + count += checkFlushBatch(ps, pendingValues, true); + } + + return count; + } + + int checkFlushBatch(PreparedStatement ps, int pendingValues, boolean forceFlush) throws SQLException + { + int count = 0; + + if (forceFlush || (pendingValues >= PENDING_LIMIT)) + { + int[] updateCounts = ps.executeBatch(); + for (int i = 0; i < updateCounts.length; ++i) { + if (updateCounts[i] > 0) { + count += updateCounts[i]; + } + } + } + + return count; + } + + String insertSql(Table table) { + StringBuilder sb = new StringBuilder("INSERT INTO "); + sb.append(table.getName()) + .append(" VALUES ("); + + for (int i = 0; i < table.getNumColumns(); ++i) { + if (i > 0) { + sb.append(","); + } + sb.append("?"); + } + sb.append(")"); + + return sb.toString(); + } + protected String selectSql(Column[] columns, Table[] tables, Condition[] conditions) { StringBuilder sb = new StringBuilder("SELECT "); diff --git a/prod/net/jaekl/cfb/xml/messages/MessageCollection.java b/prod/net/jaekl/cfb/xml/messages/MessageCollection.java index cf16e23..ba4b97c 100644 --- a/prod/net/jaekl/cfb/xml/messages/MessageCollection.java +++ b/prod/net/jaekl/cfb/xml/messages/MessageCollection.java @@ -1,5 +1,6 @@ package net.jaekl.cfb.xml.messages; +import java.util.Collection; import java.util.HashMap; import net.jaekl.qd.xml.ParseResult; @@ -20,6 +21,12 @@ public class MessageCollection extends ParseResult { m_categories = new HashMap(); m_patterns = new HashMap(); } + + public Collection getCategories() { return m_categories.values(); } + public BugCategory getCategory(String category) { return m_categories.get(category); } + + public Collection getPatterns() { return m_patterns.values(); } + public BugPattern getPattern(String type) { return m_patterns.get(type); } @Override public void endContents(String uri, String localName, String qName, String chars) -- 2.30.2