1 package net.jaekl.cfb.store;
3 import java.sql.Connection;
4 import java.sql.SQLException;
7 import net.jaekl.cfb.analyze.Analysis;
8 import net.jaekl.cfb.db.CfbSchema;
9 import net.jaekl.cfb.db.Column;
10 import net.jaekl.cfb.db.Condition;
11 import net.jaekl.cfb.db.Operation;
12 import net.jaekl.cfb.db.Row;
13 import net.jaekl.cfb.db.Sort;
14 import net.jaekl.cfb.db.Table;
15 import net.jaekl.cfb.db.TypeMismatchException;
16 import net.jaekl.cfb.db.driver.DbDriver;
17 import net.jaekl.cfb.xml.BugCollection;
18 import net.jaekl.cfb.xml.BugInstance;
19 import net.jaekl.cfb.xml.LocalVariable;
20 import net.jaekl.cfb.xml.messages.MessageCollection;
22 public class DbStore {
25 MessageCollection m_msgColl;
27 public DbStore(Connection con, DbDriver driver, MessageCollection msgColl) {
33 public Analysis getPrior(Analysis analysis) throws SQLException, TypeMismatchException {
34 if (null == analysis) {
37 Long priorId = getPriorId(analysis);
38 if (null == priorId) {
42 return getAnalysis(priorId);
45 public boolean put(Analysis analysis) throws SQLException, TypeMismatchException {
46 if (null == analysis) {
50 // ----------------------------------
51 // Add a run record for this analysis
53 long runId = m_driver.nextVal(m_con, CfbSchema.RUN_SEQ);
57 analysis.getProjectName(),
58 analysis.getBuildNumber(),
63 int count = m_driver.insert(m_con, CfbSchema.RUNS, values);
68 // -------------------------------------
69 // Add a found record for each bug found
71 List<BugInstance> bugs = analysis.getBugCollection().getBugs();
72 values = new Object[bugs.size()][CfbSchema.FOUND.getNumColumns()];
75 for (BugInstance bug : bugs)
77 Long foundId = Long.valueOf(m_driver.nextVal(m_con, CfbSchema.FOUND_SEQ));
78 Long bugId = Long.valueOf(m_msgColl.getPattern(bug.getType()).getId());
79 Long categoryId = Long.valueOf(m_msgColl.getCategory(bug.getCategory()).getId());
80 List<Location> locs = bug.getLocations();
81 Location firstLoc = (locs.size() > 0) ? locs.get(0) : null;
82 Location secondLoc = (locs.size() > 1) ? locs.get(1) : null;
83 Location thirdLoc = (locs.size() > 2) ? locs.get(2) : null;
85 values[row][0] = foundId;
86 values[row][1] = runId;
87 values[row][2] = bugId;
88 values[row][3] = categoryId;
89 values[row][4] = getLocId(firstLoc);
90 values[row][5] = getLocId(secondLoc);
91 values[row][6] = getLocId(thirdLoc);
92 values[row][7] = getVarId(bug);
96 count = m_driver.insert(m_con, CfbSchema.FOUND, values);
97 return (bugs.size() == count);
100 String getBugType(Long bugPatternId) throws SQLException, TypeMismatchException
102 Column[] columns = { CfbSchema.TYPE };
103 Table[] tables = { CfbSchema.BUGS };
104 Condition[] conditions = { new Condition(CfbSchema.BUGID, bugPatternId, Operation.EQUAL) };
105 Row row = m_driver.selectExactlyOne(m_con, columns, tables, conditions);
106 String type = row.getString(0);
110 String getCategoryName(Long categoryId) throws SQLException, TypeMismatchException
112 Column[] columns = { CfbSchema.CATEGORY };
113 Table[] tables = { CfbSchema.CATEGORIES };
114 Condition[] conditions = { new Condition(CfbSchema.CATEGORYID, categoryId, Operation.EQUAL) };
115 Row row = m_driver.selectExactlyOne(m_con, columns, tables, conditions);
116 String name = row.getString(0);
121 Location getLoc(Long locId) throws SQLException, TypeMismatchException
127 Column[] columns = { CfbSchema.CLASSNAME, CfbSchema.METHODNAME, CfbSchema.METHODROLE, CfbSchema.STARTLINE, CfbSchema.ENDLINE };
128 Table[] tables = { CfbSchema.LOCATIONS };
129 Condition[] conditions = { new Condition(CfbSchema.LOCID, locId, Operation.EQUAL) };
131 Row row = m_driver.selectExactlyOne(m_con, columns, tables, conditions);
133 String className = row.getString(0);
134 String methodName = row.getString(1);
135 String methodRole = row.getString(2);
136 Integer startLine = row.getInt(3);
137 Integer endLine = row.getInt(4);
139 Location loc = new Location(locId, className, methodName, methodRole, startLine, endLine);
143 Long getLocId(Location loc) throws SQLException, TypeMismatchException
148 Long locId = findLocId(loc);
153 return storeLoc(loc);
156 Long findLocId(Location loc) throws SQLException, TypeMismatchException
158 Column[] columns = { CfbSchema.LOCID };
159 Table[] tables = { CfbSchema.LOCATIONS };
161 Condition[] conditions = {
162 new Condition( CfbSchema.CLASSNAME, loc.getClassName(), Operation.EQUAL ),
163 new Condition( CfbSchema.METHODNAME, loc.getMethodName(), Operation.EQUAL ),
164 new Condition( CfbSchema.METHODROLE, loc.getMethodRole(), Operation.EQUAL ),
165 new Condition( CfbSchema.STARTLINE, loc.getStart(), Operation.EQUAL ),
166 new Condition( CfbSchema.ENDLINE, loc.getEnd(), Operation.EQUAL )
168 List<Row> rows = m_driver.select(m_con, columns, tables, conditions);
169 if (rows.size() > 0) {
170 assert(1 == rows.size()); // should only have one match
172 return rows.get(0).getLong(0);
175 return null; // not found
178 Long storeLoc(Location loc) throws SQLException
180 long locId = m_driver.nextVal(m_con, CfbSchema.LOC_SEQ);
182 Object[][] values = { {
187 Long.valueOf(loc.getStart()),
188 Long.valueOf(loc.getEnd())
190 int count = m_driver.insert(m_con, CfbSchema.LOCATIONS, values);
195 return Long.valueOf(locId);
198 Long getVarId(BugInstance bug) throws SQLException, TypeMismatchException
204 List<LocalVariable> vars = bug.getVariables();
205 if ((null == vars) || (0 == vars.size())) {
209 return getVarId(vars.get(0));
212 LocalVariable getVar(Long varId) throws SQLException, TypeMismatchException
218 Column[] columns = { CfbSchema.NAME, CfbSchema.VARROLE };
219 Table[] tables = { CfbSchema.VARIABLES };
220 Condition[] conditions = { new Condition(CfbSchema.VARID_PK, varId, Operation.EQUAL) };
222 List<Row> result = m_driver.select(m_con, columns, tables, conditions);
223 if (result.size() < 1) {
224 throw new SQLException("No variable found for ID " + varId);
226 if (result.size() > 1) {
227 throw new SQLException("Too many matches (" + result.size() + ") found for variable ID " + varId);
230 String varName = result.get(0).getString(0);
231 String varRole = result.get(0).getString(1);
233 return new LocalVariable(varId, varName, varRole);
236 Long getVarId(LocalVariable var) throws SQLException, TypeMismatchException
242 Long result = findVarId(var);
244 if (null != result) {
248 return storeVar(var);
251 Long findVarId(LocalVariable var) throws SQLException, TypeMismatchException
253 Column[] columns = { CfbSchema.VARID_PK };
254 Table[] tables = { CfbSchema.VARIABLES };
256 Condition[] conditions = {
257 new Condition( CfbSchema.NAME, var.getName(), Operation.EQUAL ),
258 new Condition( CfbSchema.VARROLE, var.getRole(), Operation.EQUAL )
260 List<Row> rows = m_driver.select(m_con, columns, tables, conditions);
261 if (rows.size() > 0) {
262 assert(1 == rows.size()); // should only have one match
264 return rows.get(0).getLong(0);
267 return null; // not found
270 Long storeVar(LocalVariable var) throws SQLException
272 long varId = m_driver.nextVal(m_con, CfbSchema.VARIABLE_SEQ);
274 Object[][] values = { {
279 int count = m_driver.insert(m_con, CfbSchema.VARIABLES, values);
284 return Long.valueOf(varId);
287 Long getPriorId(Analysis analysis) throws SQLException, TypeMismatchException
289 Column[] columns = { CfbSchema.RUNID };
290 Table[] tables = { CfbSchema.RUNS };
291 Condition[] conditions = {
292 new Condition( CfbSchema.PROJNAME, analysis.getProjectName(), Operation.EQUAL ),
293 new Condition( CfbSchema.STARTTIME, analysis.getStart(), Operation.LESS_THAN )
295 Sort[] sorts = { new Sort( CfbSchema.STARTTIME, Sort.Direction.DESCENDING ) };
298 List<Row> rows = m_driver.select(m_con, columns, tables, conditions, sorts, limit);
299 if (rows.size() < 1) {
302 return rows.get(0).getLong(0);
305 Analysis getAnalysis(Long analysisId) throws SQLException, TypeMismatchException
307 Column[] columns = { CfbSchema.PROJNAME, CfbSchema.VERSION, CfbSchema.STARTTIME, CfbSchema.ENDTIME };
308 Table[] tables = { CfbSchema.RUNS };
309 Condition[] conditions = { new Condition( CfbSchema.RUNID, analysisId, Operation.EQUAL ) };
311 List<Row> rows = m_driver.select(m_con, columns, tables, conditions);
312 if (rows.size() < 1) {
316 Row row = rows.get(0);
318 String projName = row.getString(0);
319 String version = row.getString(1);
320 java.util.Date start= row.getDate(2);
321 java.util.Date end = row.getDate(3);
323 Analysis prior = new Analysis(projName, version);
324 prior.setId(analysisId.longValue());
325 prior.setStart(start);
328 prior.setBugCollection(getBugCollection(analysisId));
333 BugCollection getBugCollection(Long runId) throws SQLException, TypeMismatchException
338 CfbSchema.CATEGORYID,
339 CfbSchema.FIRSTLOCID,
340 CfbSchema.SECONDLOCID,
341 CfbSchema.THIRDLOCID,
347 Condition[] conditions = {
348 new Condition(CfbSchema.RUNID, runId, Operation.EQUAL)
351 BugCollection coll = new BugCollection();
353 List<Row> rows = m_driver.select(m_con, columns, tables, conditions);
355 for (Row row : rows) {
356 // long foundId = row.getLong(0);
357 Long bugId = row.getLong(1);
358 Long categoryId = row.getLong(2);
359 Long firstLocId = row.getLong(3);
360 Long secondLocId = row.getLong(4);
361 Long thirdLocId = row.getLong(5);
362 Long varId = row.getLong(6);
364 String bugType = getBugType(bugId);
365 String category = getCategoryName(categoryId);
366 Location[] locations = { getLoc(firstLocId), getLoc(secondLocId), getLoc(thirdLocId) };
367 LocalVariable[] vars = { getVar(varId) };
370 BugInstance bug = new BugInstance(bugId, category, bugType, locations, vars);