/******************************************************************************* * Copyright (c) 2012-2015 INRIA. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Generoso Pagano - initial API and implementation ******************************************************************************/ package fr.inria.soctrace.lib.query; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import fr.inria.soctrace.lib.model.Trace; import fr.inria.soctrace.lib.model.TraceParam; import fr.inria.soctrace.lib.model.TraceParamType; import fr.inria.soctrace.lib.model.TraceType; import fr.inria.soctrace.lib.model.utils.SoCTraceException; import fr.inria.soctrace.lib.query.conditions.ICondition; import fr.inria.soctrace.lib.storage.DBObject; import fr.inria.soctrace.lib.storage.SystemDBObject; import fr.inria.soctrace.lib.storage.utils.DBModelConstants.TraceTableModel; import fr.inria.soctrace.lib.storage.utils.SQLConstants.FramesocTable; import fr.inria.soctrace.lib.utils.SoctraceUtils; /** * Query class for Trace self-defining-pattern tables. * * @author "Generoso Pagano <generoso.pagano@inria.fr>" * */ public class TraceQuery extends SelfDefiningElementQuery { private ICondition typeWhere; /** * The constructor. * * @param sysDB * System DB object where the query is performed. */ public TraceQuery(SystemDBObject sysDB) { super(sysDB); clear(); } @Override public void clear() { super.clear(); this.typeWhere = null; } @Override public String getElementTableName() { return FramesocTable.TRACE.toString(); } @Override public ParamType getParamType(String typeName, int typeId) throws SoCTraceException { return getTraceParamType(typeName, typeId); } @Override public int getTypeId(String typeName) throws SoCTraceException { return getTraceTypeId(typeName); } @Override public DBObject getDBObject() { return dbObj; } /** * Set the condition to be put in the WHERE clause of TRACE_TYPE table. * * @param typeCondition * condition to be applied to the trace type table */ public void setTypeWhere(ICondition typeCondition) { where = true; this.typeWhere = typeCondition; } /** * Builds a list of Trace respecting the condition specified by elementWhere * AND typeWhere AND parametersConditions. The different parameter * conditions are evaluated in OR, since they refer to different trace types * so it makes no sense having an AND. * * @return the Trace list. * @throws SoCTraceException */ @Override public List<Trace> getList() throws SoCTraceException { try { boolean first = true; StringBuilder traceQuery = new StringBuilder("SELECT * FROM " + FramesocTable.TRACE + " "); if (where) { traceQuery.append(" WHERE "); } if (elementWhere != null) { first = false; traceQuery.append(elementWhere.getSQLString()); } if (typeWhere != null) { if (!first) traceQuery.append(" AND "); else first = false; traceQuery.append("( TRACE_TYPE_ID IN ( SELECT ID FROM " + FramesocTable.TRACE_TYPE + " WHERE " + typeWhere.getSQLString() + " ) )"); } if (parametersConditions.size()>0) { if (!first) traceQuery.append(" AND "); else first = false; traceQuery.append( getParamConditionsString() ); } if (orderBy) { traceQuery.append(" ORDER BY " + orderByColumn + " " + orderByCriterium); } if (isLimitSet()) { traceQuery.append(" LIMIT " + getLimit()); } String query = traceQuery.toString(); debug(query); Statement stm = dbObj.getConnection().createStatement(); ResultSet rs = stm.executeQuery(query); List<Trace> traces = getTraces(rs); stm.close(); return traces; } catch (SQLException e) { throw new SoCTraceException(e); } } /** * Return the list of Trace having the specified IDs. * * @param ids * list of trace IDs * @return the list of Trace * @throws SoCTraceException */ public List<Trace> getTraces(List<Integer> ids) throws SoCTraceException { try { ValueListString vls = new ValueListString(); for (Integer i: ids) { vls.addValue(i.toString()); } if (vls.size() == 0) return new LinkedList<Trace>(); Statement stm = dbObj.getConnection().createStatement(); ResultSet rs = stm.executeQuery("SELECT * FROM " + FramesocTable.TRACE + " WHERE ID IN " + vls.getValueString()); return getTraces(rs); } catch (SQLException e) { throw new SoCTraceException(e); } } /* * U t i l i t i e s */ /** * Rebuilds the traces corresponding to the result set. * * @param rs * Result set corresponding to a SELECT * FROM TRACE ... * @return a list of Trace * @throws SoCTraceException */ private List<Trace> getTraces(ResultSet rs) throws SoCTraceException { ValueListString vls = new ValueListString(); List<Trace> list = new LinkedList<Trace>(); Map<Integer, Trace> tmp = new HashMap<Integer, Trace>(); try { while (rs.next()) { Trace t = rebuildTrace(rs); list.add(t); // to rebuild all params tmp.put(t.getId(), t); vls.addValue(String.valueOf(t.getId())); } if (vls.size() == 0) return list; Statement stm = dbObj.getConnection().createStatement(); ResultSet prs = stm.executeQuery("SELECT * FROM " + FramesocTable.TRACE_PARAM + " WHERE TRACE_ID IN " + vls.getValueString()); while (prs.next()) { rebuildTraceParam(prs, tmp); } return list; } catch (SQLException e) { throw new SoCTraceException(e); } } /** * Get the trace type ID given the trace type name. * * @param name * trace type name * @return the corresponding trace type ID or -1 if not found * @throws SoCTraceException */ private int getTraceTypeId(String name) throws SoCTraceException { try { Statement stm = dbObj.getConnection().createStatement(); ResultSet rs = stm.executeQuery("SELECT * FROM " + FramesocTable.TRACE_TYPE + " WHERE NAME='" + name + "'"); if (rs.next()) { return rs.getInt("ID"); } return -1; } catch (SQLException e) { throw new SoCTraceException(e); } } /** * Get the trace param type with the given name, for the trace type whose ID * is passed. * * TODO: this can be optimized with the type cache * * @param name * the trace param type name * @param traceTypeId * the trace type ID * @return the corresponding trace param type or null if not found * @throws SoCTraceException */ private ParamType getTraceParamType(String name, int traceTypeId) throws SoCTraceException { try { Statement stm = dbObj.getConnection().createStatement(); String query = "SELECT * FROM " + FramesocTable.TRACE_PARAM_TYPE + " WHERE NAME='" + name + "' AND TRACE_TYPE_ID=" + traceTypeId; debug(query); ResultSet rs = stm.executeQuery(query); if (rs.next()) { return new ParamType(rs.getInt("ID"), name, rs.getString("TYPE")); } return null; } catch (SQLException e) { throw new SoCTraceException(e); } } /** * Rebuild a Trace, given the corresponding TRACE table row. * * @param rs * TRACE table row * @return the Trace * @throws SQLException * @throws SoCTraceException */ private Trace rebuildTrace(ResultSet rs) throws SQLException, SoCTraceException { Trace t = new Trace(rs.getInt(TraceTableModel.ID.getPosition())); SystemDBObject sysDB = (SystemDBObject)dbObj; TraceType tt = sysDB.getTraceTypeCache().get(TraceType.class, rs.getInt(TraceTableModel.TRACE_TYPE_ID.getPosition())); t.setType(tt); // XXX see note at the bottom of ModelVisitor.java t.setTracingDate(SoctraceUtils.stringToTimestamp(rs.getString(TraceTableModel.TRACING_DATE.getPosition()))); t.setTracedApplication(rs.getString(TraceTableModel.TRACED_APPLICATION.getPosition())); t.setBoard(rs.getString(TraceTableModel.BOARD.getPosition())); t.setOperatingSystem(rs.getString(TraceTableModel.OPERATING_SYSTEM.getPosition())); t.setNumberOfCpus(rs.getInt(TraceTableModel.NUMBER_OF_CPUS.getPosition())); t.setNumberOfEvents(rs.getInt(TraceTableModel.NUMBER_OF_EVENTS.getPosition())); t.setOutputDevice(rs.getString(TraceTableModel.OUTPUT_DEVICE.getPosition())); t.setDescription(rs.getString(TraceTableModel.DESCRIPTION.getPosition())); t.setProcessed(rs.getBoolean(TraceTableModel.PROCESSED.getPosition())); t.setDbName(rs.getString(TraceTableModel.TRACE_DB_NAME.getPosition())); t.setAlias(rs.getString(TraceTableModel.ALIAS.getPosition())); t.setMinTimestamp(rs.getLong(TraceTableModel.MIN_TIMESTAMP.getPosition())); t.setMaxTimestamp(rs.getLong(TraceTableModel.MAX_TIMESTAMP.getPosition())); t.setTimeUnit(rs.getInt(TraceTableModel.TIMEUNIT.getPosition())); t.setNumberOfProducers(rs.getInt(TraceTableModel.NUMBER_OF_PRODUCERS.getPosition())); return t; } /** * Rebuild a TraceParam, given the corresponding TRACE_PARAM table row. * * @param prs * TRACE_PARAM table row * @param tmp * map containing the Traces returned by the query * @return the TraceParam * @throws SQLException * @throws SoCTraceException */ private TraceParam rebuildTraceParam(ResultSet prs, Map<Integer, Trace> tmp) throws SQLException, SoCTraceException { TraceParam tp = new TraceParam(prs.getInt(1)); tp.setTrace(tmp.get(prs.getInt(2))); SystemDBObject sysDB = (SystemDBObject)dbObj; tp.setTraceParamType(sysDB.getTraceTypeCache().get(TraceParamType.class, prs.getInt(3))); tp.setValue(prs.getString(4)); return tp; } }