import net.jaekl.cfb.analyze.Analysis;
import net.jaekl.cfb.analyze.Analyzer;
+import net.jaekl.cfb.analyze.Delta;
import net.jaekl.cfb.analyze.MessageMap;
import net.jaekl.cfb.db.CfbSchema;
import net.jaekl.cfb.db.TypeMismatchException;
DbStore store = new DbStore(con, m_driver, messageMap.getColl());
store.put(analysis);
+ Analysis prior = store.getPrior(analysis);
+ Delta delta = new Delta(prior, analysis);
+ delta.dump(pw);
}
catch (SQLException exc) {
reportUnableToConnect(pw, exc);
result.setEnd(new Date());
result.parse(new InputSource(fbOutput.getAbsolutePath()));
- result.dump(pw);
+ // result.dump(pw);
return result;
}
package net.jaekl.cfb.analyze;
+import java.io.PrintWriter;
import java.util.HashSet;
import net.jaekl.cfb.xml.BugInstance;
public BugInstance[] getNew() { return m_new.toArray(new BugInstance[m_new.size()]); }
public int getNumNew() { return m_new.size(); }
+ public void dump(PrintWriter pw) {
+ pw.println("=========================");
+ pw.println(" NEW BUGS (" + m_new.size() + ")");
+ pw.println("-------------------------");
+ for (BugInstance bug : m_new) {
+ bug.dump(pw, 2);
+ }
+
+ pw.println("=========================");
+ pw.println(" FIXED BUGS (" + m_fixed.size() + ")");
+ pw.println("-------------------------");
+ for (BugInstance bug : m_fixed) {
+ bug.dump(pw, 2);
+ }
+
+ pw.println("=========================");
+ pw.println(" OLD BUGS (" + m_common.size() + ")");
+ pw.println("-------------------------");
+ for (BugInstance bug : m_common) {
+ bug.dump(pw, 2);
+ }
+ }
+
void computeDelta(Analysis before, Analysis after)
{
m_fixed.clear();
HashSet<BugInstance> beforeBugs = new HashSet<BugInstance>();
- beforeBugs.addAll(before.getBugCollection().getBugs());
+ if (null != before) {
+ beforeBugs.addAll(before.getBugCollection().getBugs());
+ }
for (BugInstance bug : after.getBugCollection().getBugs()) {
if (beforeBugs.contains(bug)) {
}
}
+ if (null == before) {
+ return;
+ }
+
for (BugInstance bug : before.getBugCollection().getBugs()) {
if (! m_common.contains(bug)) {
m_fixed.add(bug);
List<Row> rows = driver.select(con, columns, tables, conditions);
for (Row row : rows) {
- long catId = row.getLong(0);
+ Long catId = row.getLong(0);
String catName = row.getString(1);
BugCategory cat = getColl().getCategory(catName);
List<Row> rows = driver.select(con, columns, tables, conditions);
for (Row row: rows) {
- long bugId = row.getLong(0);
+ Long bugId = row.getLong(0);
String type = row.getString(1);
BugPattern bug = getColl().getPattern(type);
package net.jaekl.cfb.db;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Date;
+
import net.jaekl.cfb.util.Util;
// Copyright (C) 2015 Christian Jaekl
return new Column(name, type, width.intValue(), canBeNull);
}
+ // Wrapper around PreparedStatement.setObject().
+ // Note that indices start at 1, not at zero.
+ public void setObject(PreparedStatement ps, int idx, Object obj) throws SQLException
+ {
+ if (this.getType().equals(Type.TIMESTAMPTZ)) {
+ // Special case: because there's no good way to read a TIMESTAMPTZ from
+ // the database using JDBC, we store it as an integer (milliseconds since
+ // the epoch, 01.01.1970 00:00:00.000 UTC).
+ Date date = (Date)obj;
+ ps.setLong(idx, date.getTime());
+ }
+ else {
+ ps.setObject(idx, obj);
+ }
+ }
+
@Override
public boolean equals(Object obj)
{
return num.intValue();
}
- public long getLong(int index) throws TypeMismatchException
+ public Long getLong(int index) throws TypeMismatchException
{
checkType(index, Column.Type.INTEGER);
+ if (null == m_values[index]) {
+ return null;
+ }
+
Number num = (Number)m_values[index];
return num.longValue();
}
public java.util.Date getDate(int index) throws TypeMismatchException
{
- checkType(index, Column.Type.INTEGER);
- long milliseconds = (Long)m_values[index];
- java.util.Date date = new java.util.Date(milliseconds);
- return date;
+ checkType(index, Column.Type.TIMESTAMPTZ);
+ return (java.util.Date)m_values[index];
}
protected void checkType(int index, Column.Type type) throws TypeMismatchException {
Column column = m_columns[index];
- if (column.getType().equals(type)) {
+ Column.Type columnType = column.getType();
+
+ if (columnType.equals(Column.Type.TIMESTAMPTZ)) {
+ // Special case: TIMESTAMPTZ is stored as an INTEGER
+ if ( Column.Type.TIMESTAMPTZ.equals(type)
+ || Column.Type.INTEGER.equals(type) )
+ {
+ return;
+ }
+ }
+
+ if (columnType.equals(type)) {
return;
}
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
import net.jaekl.cfb.db.Column;
int index = 0;
for (Condition condition : conditions) {
if (condition.getOperation().hasParam()) {
+ Column column = condition.getColumn();
index++;
- ps.setObject(index, condition.getValue());
+ column.setObject(ps, index, condition.getValue());
}
}
}
}
}
+ catch (SQLException se) {
+ throw new SQLException("Error with SQL: " + sql, se);
+ }
return result;
}
assert(null != data);
assert(data.length == table.getNumColumns());
- for (int col = 0; col < data.length; ++col) {
- Object obj = data[col];
- Column column = table.getColumn(col);
- if (column.getType().equals(Type.TIMESTAMPTZ)) {
- // Special case: because there's no good way to read a TIMESTAMPTZ from
- // the database using JDBC, we store it as an integer (milliseconds since
- // the epoch, 01.01.1970 00:00:00.000 UTC).
- Date date = (Date)obj;
- ps.setLong(col + 1, date.getTime());
- }
- else {
- ps.setObject(col + 1, data[col]);
- }
+ for (int idx = 0; idx < data.length; ++idx) {
+ Object obj = data[idx];
+ Column column = table.getColumn(idx);
+ column.setObject(ps, idx + 1, obj);
pendingValues++;
}
ps.addBatch();
sb.append(sort.getColumn().getName());
if (sort.getDirection().equals(Sort.Direction.ASCENDING)) {
- sb.append(" ASCENDING ");
+ sb.append(" ASC ");
}
else {
- sb.append(" DESCENDING ");
+ sb.append(" DESC ");
}
}
}
Location getLoc(Long locId) throws SQLException, TypeMismatchException
{
+ if (null == locId) {
+ return null;
+ }
+
Column[] columns = { CfbSchema.CLASSNAME, CfbSchema.METHODNAME, CfbSchema.METHODROLE, CfbSchema.STARTLINE, CfbSchema.ENDLINE };
Table[] tables = { CfbSchema.LOCATIONS };
Condition[] conditions = { new Condition(CfbSchema.LOCID, locId, Operation.EQUAL) };
String className = row.getString(0);
String methodName = row.getString(1);
String methodRole = row.getString(2);
- long startLine = row.getLong(3);
- long endLine = row.getLong(4);
+ Integer startLine = row.getInt(3);
+ Integer endLine = row.getInt(4);
Location loc = new Location(locId, className, methodName, methodRole, startLine, endLine);
return loc;
LocalVariable getVar(Long varId) throws SQLException, TypeMismatchException
{
+ if (null == varId) {
+ return null;
+ }
+
Column[] columns = { CfbSchema.NAME, CfbSchema.VARROLE };
Table[] tables = { CfbSchema.VARIABLES };
Condition[] conditions = { new Condition(CfbSchema.VARID_PK, varId, Operation.EQUAL) };
return rows.get(0).getLong(0);
}
- Analysis getAnalysis(Long priorId) throws SQLException, TypeMismatchException
+ Analysis getAnalysis(Long analysisId) throws SQLException, TypeMismatchException
{
Column[] columns = { CfbSchema.VERSION, CfbSchema.STARTTIME, CfbSchema.ENDTIME };
Table[] tables = { CfbSchema.RUNS };
- Condition[] conditions = { new Condition( CfbSchema.RUNID, priorId, Operation.EQUAL ) };
+ Condition[] conditions = { new Condition( CfbSchema.RUNID, analysisId, Operation.EQUAL ) };
List<Row> rows = m_driver.select(m_con, columns, tables, conditions);
if (rows.size() < 1) {
java.util.Date end = row.getDate(2);
Analysis prior = new Analysis(version);
- prior.setId(priorId.longValue());
+ prior.setId(analysisId.longValue());
prior.setStart(start);
prior.setEnd(end);
- prior.setBugCollection(getBugCollection(priorId));
+ prior.setBugCollection(getBugCollection(analysisId));
return prior;
}
for (Row row : rows) {
// long foundId = row.getLong(0);
- long bugId = row.getLong(1);
- long categoryId = row.getLong(2);
- long firstLocId = row.getLong(3);
- long secondLocId = row.getLong(4);
- long thirdLocId = row.getLong(5);
- long varId = row.getLong(6);
+ Long bugId = row.getLong(1);
+ Long categoryId = row.getLong(2);
+ Long firstLocId = row.getLong(3);
+ Long secondLocId = row.getLong(4);
+ Long thirdLocId = row.getLong(5);
+ Long varId = row.getLong(6);
String bugType = getBugType(bugId);
String category = getCategoryName(categoryId);
Location[] locations = { getLoc(firstLocId), getLoc(secondLocId), getLoc(thirdLocId) };
- LocalVariable[] vars = { getVar(Long.valueOf(varId)) };
+ LocalVariable[] vars = { getVar(varId) };
BugInstance bug = new BugInstance(bugId, category, bugType, locations, vars);
- coll.getBugs().add(bug);
+ coll.add(bug);
}
return coll;
package net.jaekl.cfb.store;
+import java.io.PrintWriter;
+
+import net.jaekl.cfb.util.Util;
import net.jaekl.cfb.xml.BugClass;
import net.jaekl.cfb.xml.BugMethod;
import net.jaekl.cfb.xml.SourceLine;
String m_className;
String m_methodName;
String m_methodRole;
- int m_startLine;
- int m_endLine;
+ Integer m_startLine;
+ Integer m_endLine;
public Location(SourceLine sourceLine)
{
m_className = bugClass.getClassName();
}
- public Location(Long id, String className, String methodName, String methodRole, long startLine, long endLine)
+ public Location(Long id, String className, String methodName, String methodRole, Integer startLine, Integer endLine)
{
-
+ m_id = id;
+ m_className = className;
+ m_methodName = methodName;
+ m_methodRole = methodRole;
+ m_startLine = startLine;
+ m_endLine = endLine;
}
public String getClassName() { return m_className; }
public int getStart() { return m_startLine; }
public int getEnd() { return m_endLine; }
+ public void dump(PrintWriter pw, int indent)
+ {
+ String margin = String.format("%" + indent + "s", "");
+ String tab = margin + " ";
+ pw.println(margin + "Location");
+ if (null != m_className) {
+ pw.println(tab + "classname = " + m_className);
+ }
+ if (null != m_methodName) {
+ if (null != m_methodRole) {
+ pw.println(tab + "method = " + m_methodName + " (" + m_methodRole + ")");
+ }
+ else {
+ pw.println(tab + "method = " + m_methodName);
+ }
+ }
+ if (null != m_startLine) {
+ pw.println(tab + "lines = " + m_startLine + " .. " + m_endLine);
+ }
+ }
+
+ public boolean fuzzyEquals(Location that)
+ {
+ if (null == that) {
+ return false;
+ }
+
+ if (! Util.objsAreEqual(this.m_className, that.m_className)) {
+ return false;
+ }
+
+ if (! Util.objsAreEqual(this.m_methodName, that.m_methodName)) {
+ return false;
+ }
+
+ if (! Util.objsAreEqual(this.m_methodRole, that.m_methodRole)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if (null == other) {
+ return false;
+ }
+ if (other instanceof Location) {
+ return fuzzyEquals((Location)other);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Util.objHashCode(m_className)
+ ^ Util.objHashCode(m_methodName)
+ ^ Util.objHashCode(m_methodRole);
+ }
+
private void init(SourceLine[] sourceLines)
{
if (sourceLines.length > 0) {
}
public List<BugInstance> getBugs() { return Collections.unmodifiableList(m_bugs); }
+ public void add(BugInstance bug) { m_bugs.add(bug); }
@Override
public void endContents(String uri, String localName, String qName, String chars)
m_id = id;
m_category = category;
m_type = type;
- m_classes = null;
- m_methods = null;
- m_lines = null;
+
+ m_classes = new ArrayList<BugClass>();
+ m_methods = new ArrayList<BugMethod>();
+ m_lines = new ArrayList<SourceLine>();
+
m_locations = new ArrayList<Location>(Arrays.asList(locations));
m_locals = new ArrayList<LocalVariable>(Arrays.asList(variables));
}
bm.dump(pw, childIndent);
}
for (LocalVariable lv : m_locals) {
- lv.dump(pw, childIndent);
+ if (null != lv) {
+ lv.dump(pw, childIndent);
+ }
}
for (SourceLine sl : m_lines) {
sl.dump(pw, childIndent);
}
+ for (Location loc : m_locations) {
+ if (null != loc) {
+ loc.dump(pw, childIndent);
+ }
+ }
}
// Note that this is a heuristic, "fuzzy", equals.
}
}
else {
- if (! Util.objsAreEqual(thisLoc.getClassName(), thatLoc.getClassName())) {
- return false;
- }
- if (! Util.objsAreEqual(thisLoc.getMethodName(), thatLoc.getMethodName())) {
+ if (! thisLoc.fuzzyEquals(thatLoc)) {
return false;
}
}
- if (! Util.objsAreEqual(this.getVariables(), that.getVariables())) {
- return false;
- }
-
return true;
}
return false;
public int hashCode()
{
int code = Util.objHashCode(m_type)
- * Util.objHashCode(m_category)
- * Util.objHashCode(getPrincipalLocation())
- * Util.objHashCode(getVariables());
+ ^ Util.objHashCode(m_category)
+ ^ Util.objHashCode(getPrincipalLocation());
return code;
}