/******************************************************************************* * Copyright (c) 2009 the CHISEL group and contributors. * 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: * Del Myers - initial API and implementation *******************************************************************************/ package ca.uvic.chisel.javasketch.data.internal; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import ca.uvic.chisel.hsqldb.server.IDataPortal; /** * A simple class that contains query information for the database. * * @author Del Myers * */ public class DataUtils { private static final String METHOD_COUNT_STATEMENT = "select count(*) from Method where type_name = ?"; private static final String METHODS_BY_TYPE_STATEMENT = "select type_name, method_name, method_signature from Method where type_name=?"; private static final String METHODS_BY_SIGNATURE_STATEMENT = "SELECT type_name, method_name, method_signature from Method where type_name=? and method_name=? and method_signature=?"; private static final String EVENTS_BY_TEXT_STATEMENT = "SELECT model_id, time, text FROM Event WHERE text=?"; private static final String EVENT_BY_ID_STATEMENT = "SELECT model_id, time, text FROM Event WHERE model_id=?"; private static final String ACTIVATION_BY_ID_STATEMENT = "select model_id, arrival_id, type_name, method_name, method_signature, thread_id, this_type, instance from Activation where model_id=?"; private static final String ACTIVATION_BY_CALLER_STATEMENT = "SELECT " + "a.model_id, " + "a.arrival_id, " + "a.type_name, " + "a.method_name, " + "a.method_signature, " + "a.thread_id, " + "a.this_type, " + "a.instance " + "FROM Activation a, " + "(SELECT model_id FROM Message WHERE order_num=? AND kind='ARRIVE') as m " + "WHERE a.arrival_id=m.model_id " + "AND a.thread_id=?"; private static final String MESSAGE_BY_ID_STATEMENT = "select model_id, kind, activation_id, opposite_id, order_num, time, code_line, sequence from Message where model_id=?"; private static final String THREAD_BY_ID_STATEMENT = "select model_id, thread_id, thread_name, root_id from Thread where model_id=?"; private static final String THREAD_STATEMENT = "select model_id, thread_id, thread_name, root_id from Thread"; private static final String TRACE_CLASS_COUNT_STATEMENT = "Select count(*) from (select distinct type_name from Activation)"; private static final String TRACE_CLASS_BY_NAME_STATEMENT = "Select distinct type_name from Activation where type_name=?"; private static final String TRACE_CLASS_STATEMENT = "Select type_name from TraceClass"; protected static final String TRACE_STATEMENT = "Select model_id, launch_id, time, data_time from Trace"; public static final String MESSAGE_KIND_CALL = "CALL"; public static final String MESSAGE_KIND_ARRIVE = "ARRIVE"; public static final String MESSAGE_KIND_REPLY = "REPLY"; public static final String MESSAGE_KIND_RETURN = "RETURN"; public static final String MESSAGE_KIND_THROW = "THROW"; private static final String REPLY_MESSAGES_STATEMENT = "select m.model_id, m.kind, m.activation_id, m.opposite_id, m.order_num, m.time, m.code_line, m.sequence from (" + "select activation_id, max(order_num) as maxorder from Message where activation_id = ? AND (kind = '"+MESSAGE_KIND_REPLY+"' OR kind ='" +MESSAGE_KIND_THROW+"') group by (activation_id)" + ") as x join Message as m on x.maxorder=m.order_num AND m.activation_id = x.activation_id"; private static final String ORIGIN_MESSAGES_STATEMENT = "select model_id, kind, activation_id, opposite_id, order_num, time, code_line, sequence from Message where activation_id = ? AND (kind = '"+MESSAGE_KIND_CALL+"' OR kind = '"+MESSAGE_KIND_REPLY+"' OR kind ='" +MESSAGE_KIND_THROW+"')"; public static final String MESSAGE_KIND_CATCH = "CATCH"; private static final String TARGE_MESSAGES_STATEMENT = "select model_id, kind, activation_id, opposite_id, order_num, time, code_line, sequence from Message where activation_id = ? AND (kind = '"+MESSAGE_KIND_ARRIVE+"' OR kind = '"+MESSAGE_KIND_RETURN+"' OR kind ='" +MESSAGE_KIND_CATCH+"')"; protected class ExecutableQuery { private String query; private int batchCounter = 0; public ExecutableQuery(String query) { this.query = query; } public ResultSet executeQuery() throws SQLException { return getStatement().executeQuery(); } public boolean execute() throws SQLException { getStatement().addBatch(); batchCounter++; if ((batchCounter % 10000) == 0) { getStatement().executeBatch(); batchCounter = 0; return true; } return true; } public boolean commit() throws SQLException { if (batchCounter > 0) { getStatement().executeBatch(); return true; } return true; } /** * @param i * @param qualifiedName * @throws SQLException */ public void setString(int i, String value) throws SQLException { getStatement().setString(i, value); } private PreparedStatement getStatement() throws SQLException { return getPortal().prepareStatement(query); } /** * @param i * @param id * @throws SQLException */ public void setLong(int i, long value) throws SQLException { getStatement().setLong(i, value); } /** * @param i * @param order * @throws SQLException */ public void setInt(int i, int value) throws SQLException { getStatement().setInt(i, value); } /** * @param i * @param oppositeId * @throws SQLException */ public void setObject(int i, Object value) throws SQLException { getStatement().setObject(i, value); } } private ExecutableQuery activationByIDStatement; private ExecutableQuery eventByIDStatement; private ExecutableQuery eventsByTextStatement; private ExecutableQuery messageByIDStatement; protected ExecutableQuery methodBySignatureStatement; protected ExecutableQuery methodsByTypeStatement; private ExecutableQuery methodCountStatement; private ExecutableQuery threadByIDStatement; private ExecutableQuery threadStatement; private ExecutableQuery traceClassByNameStatement; private ExecutableQuery traceClassCountStatement; private ExecutableQuery traceClassStatement; private ExecutableQuery traceStatement; private ExecutableQuery activationByCallerStatement; private ExecutableQuery originMessagesStatement; private ExecutableQuery targetMessagesStatement; private ExecutableQuery replyMessagesStatement; protected long order_num; private IDataPortal portal; public DataUtils(IDataPortal portal) throws SQLException { this.portal = portal; prepareStatements(); } /** * @throws SQLException */ synchronized void prepareStatements() throws SQLException { traceStatement = new ExecutableQuery(TRACE_STATEMENT); traceClassStatement = new ExecutableQuery(TRACE_CLASS_STATEMENT); traceClassByNameStatement = new ExecutableQuery(TRACE_CLASS_BY_NAME_STATEMENT); traceClassCountStatement = new ExecutableQuery(TRACE_CLASS_COUNT_STATEMENT); threadStatement = new ExecutableQuery(THREAD_STATEMENT); threadByIDStatement = new ExecutableQuery(THREAD_BY_ID_STATEMENT); /* for all messages "model_id", "kind", "activation_id", "opposite_id", "order_num", "time", "code_line", "sequence"*/ messageByIDStatement = new ExecutableQuery(MESSAGE_BY_ID_STATEMENT); originMessagesStatement = new ExecutableQuery(ORIGIN_MESSAGES_STATEMENT); replyMessagesStatement = new ExecutableQuery(REPLY_MESSAGES_STATEMENT); targetMessagesStatement = new ExecutableQuery(TARGE_MESSAGES_STATEMENT); activationByCallerStatement = new ExecutableQuery(ACTIVATION_BY_CALLER_STATEMENT); activationByIDStatement = new ExecutableQuery(ACTIVATION_BY_ID_STATEMENT); eventByIDStatement = new ExecutableQuery(EVENT_BY_ID_STATEMENT); eventsByTextStatement = new ExecutableQuery(EVENTS_BY_TEXT_STATEMENT); methodBySignatureStatement = new ExecutableQuery(METHODS_BY_SIGNATURE_STATEMENT); methodsByTypeStatement = new ExecutableQuery(METHODS_BY_TYPE_STATEMENT); methodCountStatement = new ExecutableQuery(METHOD_COUNT_STATEMENT); } /** * Returns the result set representing the class for the given qualified * name, or null if it could not be found. * * @param qualifiedName * @return * @throws SQLException */ public synchronized ResultSet findTraceClass(String qualifiedName) throws SQLException { traceClassByNameStatement.setString(1, qualifiedName); ResultSet results = traceClassByNameStatement.executeQuery(); if (results.next()) { return results; } return null; } // public synchronized long getOrCreateMethod(String type, String name, // String signature) throws SQLException { // ResultSet results = findMethod(type, name, signature); // if (results != null) { // return results.getLong(1); // } // long modelID = getNextModelID(); // // try and find the class // long typeID = getOrCreateTraceClass(type); // createMethodStatement.setLong(1, modelID); // createMethodStatement.setLong(2, typeID); // createMethodStatement.setString(3, name); // createMethodStatement.setString(4, signature); // createMethodStatement.execute(); // incrementModelNumStatement.execute(); // getConnection().commit(); // return modelID; // } /** * @param arrivalId * @return * @throws SQLException */ public synchronized ResultSet getMessage(long id) throws SQLException { messageByIDStatement.setLong(1, id); ResultSet results = messageByIDStatement.executeQuery(); if (results.next()) { return results; } return null; } /** * @param type * @param name * @param signature * @return * @throws SQLException */ public synchronized ResultSet findMethod(String type, String name, String signature) throws SQLException { methodBySignatureStatement.setString(1, type); methodBySignatureStatement.setString(2, name); methodBySignatureStatement.setString(3, signature); ResultSet results = methodBySignatureStatement.executeQuery(); if (results.next()) { return results; } return null; } /** * Closes the underlying connection for this utility class. Changes to the database are * committed first. * @throws SQLException if an error occurred committing results and closing the database. */ public void close() throws SQLException { getConnection().commit(); getConnection().close(); } /** * @return * @throws SQLException */ public ResultSet getTrace() throws SQLException { ResultSet results = traceStatement.executeQuery(); if (results.next()) { return results; } return null; } /** * @return * @throws SQLException */ public int getClassCount() throws SQLException { ResultSet results = traceClassCountStatement.executeQuery(); if (results.next()) { return results.getInt(1); } return 0; } /** * @return all of the current classes in the database. The result set is set before * the first row of the query. * @throws SQLException */ public ResultSet getTraceClasses() throws SQLException { return traceClassStatement.executeQuery(); } /** * @return * @throws SQLException */ public ResultSet getThreads() throws SQLException { return threadStatement.executeQuery(); } /** * @param modelID * @return * @throws SQLException */ public synchronized ResultSet getThread(long modelID) throws SQLException { threadByIDStatement.setLong(1, modelID); ResultSet results = threadByIDStatement.executeQuery(); if (results.next()) { return results; } return null; } /** * @param modelID * @return * @throws SQLException */ public synchronized ResultSet getMethodsByClass(String name) throws SQLException { methodsByTypeStatement.setString(1, name); ResultSet results = methodsByTypeStatement.executeQuery(); if (results.next()) { return results; } return null; } /** * @param modelID * @return * @throws SQLException */ public synchronized int getMethodCount(String name) throws SQLException { methodCountStatement.setString(1, name); ResultSet results = methodCountStatement.executeQuery(); if (results.next()) return results.getInt(1); return 0; } /** * @param modelID * @return * @throws SQLException */ public synchronized ResultSet getActivation(long modelID) throws SQLException { activationByIDStatement.setLong(1, modelID); ResultSet results = activationByIDStatement.executeQuery(); if (results.next()) { return results; } return null; } /** * @param modelID * @return * @throws SQLException */ public synchronized ResultSet getOriginMessages(long modelID) throws SQLException { originMessagesStatement.setLong(1, modelID); ResultSet results = originMessagesStatement.executeQuery(); return results; } /** * @param modelID * @return * @throws SQLException */ public synchronized ResultSet getTargetMessages(long modelID) throws SQLException { targetMessagesStatement.setLong(1, modelID); ResultSet results = targetMessagesStatement.executeQuery(); return results; } /** * @param modelID * @return * @throws SQLException */ public synchronized ResultSet getReplyMessage(long activationID) throws SQLException { replyMessagesStatement.setLong(1, activationID); ResultSet results = replyMessagesStatement.executeQuery(); if (results.next()) { return results; } return null; } /** * @param modelID * @return * @throws SQLException */ public synchronized ResultSet getEvent(long modelID) throws SQLException { eventByIDStatement.setLong(1, modelID); ResultSet results = eventByIDStatement.executeQuery(); if (results.next()) { return results; } return null; } public synchronized ResultSet getEventByText(String text) throws SQLException { eventsByTextStatement.setString(1, text); return eventsByTextStatement.executeQuery(); } public synchronized ResultSet getActivationByCallerOrder(long order, long thread_id) throws SQLException { // Statement s = getConnection().createStatement(); // ResultSet results1 = s.executeQuery("SELECT * FROM Message WHERE order_num = " + order + " AND kind='ARRIVE'"); // while (results1.next()) { // long message_id = results1.getLong("model_id"); // ResultSet results2 = s.executeQuery("SELECT * FROM Activation WHERE thread_id = " + thread_id + " AND arrival_id = " + message_id); // if (results2.next()) { // return results2; // } // } activationByCallerStatement.setLong(1, order); activationByCallerStatement.setLong(2, thread_id); ResultSet results = activationByCallerStatement.executeQuery(); if (results.next()) { return results; } return null; } public Connection getConnection() throws SQLException { return portal.getDefaultConnection(); } public void reset() { } protected IDataPortal getPortal() { return portal; } }