diff --git a/src/main/java/it/unibz/inf/isochrone/db/Database.java b/src/main/java/it/unibz/inf/isochrone/db/Database.java index d988e3842f42b6d9bede233544b8987de14d8a7d..60aa66a29c95fd222b76574de22893480d151dc2 100644 --- a/src/main/java/it/unibz/inf/isochrone/db/Database.java +++ b/src/main/java/it/unibz/inf/isochrone/db/Database.java @@ -42,13 +42,10 @@ import java.util.Set; * @version 2.2 */ public class Database { - private static final boolean USE_IN_QUERY = true; protected static final byte NW_MODE_CONTINUOUS = 0; protected static final byte NW_MODE_DISCRETE = 1; private final String queryEarliestArrivalTimeHomo; - private final String queryEarliestArrivalTimeHomoInQuery; private final String queryLatestDepartureTimeHomo; - private final String queryLatestDepartureTimeHomoInQuery; private final String queryGetAllEdges; private final String queryGetAdjLinks; private final String queryGetAdjContinuousLinks; @@ -84,16 +81,10 @@ public class Database { final String configVertexDensity = config.getTableVertexDensity(); queryEarliestArrivalTimeHomo = "SELECT TIME_D, TIME_A, ROUTE_ID FROM " + configSchedule - + " WHERE SOURCE = ? AND TARGET = ? AND ROUTE_ID IN (%S) AND TIME_D>=? AND TIME_D<=? AND SERVICE_ID IN (%S) AND TIME_A <= ?"; - - queryEarliestArrivalTimeHomoInQuery = "SELECT SOURCE, TARGET, TIME_D, TIME_A, ROUTE_ID FROM " + configSchedule - + " WHERE SOURCE = ? AND TARGET IN (%S) AND ROUTE_ID IN (%S) AND TIME_D>=? AND TIME_D<=? AND SERVICE_ID IN (%S) AND TIME_A <= ?"; + + " WHERE SOURCE = ? AND TARGET = ? AND ROUTE_ID IN (%S) AND (TIME_D BETWEEN ? AND ?) AND SERVICE_ID IN (%S) AND TIME_A <= ?"; queryLatestDepartureTimeHomo = "SELECT TIME_D, TIME_A, ROUTE_ID FROM " + configSchedule - + " WHERE SOURCE = ? AND TARGET = ? AND ROUTE_ID IN (%S) AND TIME_A>=? AND TIME_A<=? AND SERVICE_ID IN (%S) AND TIME_D >= ?"; - - queryLatestDepartureTimeHomoInQuery = "SELECT SOURCE, TARGET, TIME_D, TIME_A, ROUTE_ID FROM " + configSchedule - + " WHERE SOURCE IN (%S) AND TARGET = ? AND ROUTE_ID IN (%S) AND TIME_A>=? AND TIME_A<=? AND SERVICE_ID IN (%S) AND TIME_D >= ?"; + + " WHERE SOURCE = ? AND TARGET = ? AND ROUTE_ID IN (%S) AND (TIME_A BETWEEN ? AND ?) AND SERVICE_ID IN (%S) AND TIME_D >= ?"; queryGetAllEdges = "SELECT ID, SOURCE, TARGET, LENGTH, EDGE_MODE, ROUTE_ID FROM " + configEdges; @@ -237,11 +228,50 @@ public class Database { * @return the cost of for traveling from the start node to the end node */ public Map<Node, Long> getAdjNodeCost(final NodeConnection nConnection, final Collection<Integer> dateCodes, final long fromTime, final long toTime) { - if (USE_IN_QUERY) { - return getAdjNodeCostByInQuery(nConnection, dateCodes, fromTime, toTime); + final Object[] arrDateCodes = dateCodes.toArray(); + + final Node node = nConnection.getSourceNode(); + final Set<Entry<Node, Collection<Link>>> entries = nConnection.getTargetEntries().entrySet(); + final Map<Node, Long> results = new LinkedHashMap<>(entries.size()); + for (final Entry<Node, Collection<Link>> entry : entries) { + final Node targetNode = entry.getKey(); + final Collection<Integer> routes = NodeConnection.getTargetRoutes(entry.getValue()); + + ResultSet rs = null; + try { + if (isIncoming) { + rs = getLatestDepartureTime(targetNode.getId(), node.getId(), routes, arrDateCodes, fromTime, Math.round(toTime - node.getDistance())); + while (rs.next()) { + final long departureTime = rs.getLong("TIME_D"); + final long arrivalTime = rs.getLong("TIME_A"); + final short routeId = rs.getShort("ROUTE_ID"); + targetNode.setDepartureTime(routeId, departureTime); + node.setArrivalTime(routeId, arrivalTime); + + final long distance = toTime - departureTime; + updateDistanceMap(results, routeId, targetNode, distance); + } + } else { + rs = getEarliestArrivalTime(node.getId(), targetNode.getId(), routes, arrDateCodes, Math.round(fromTime + node.getDistance()), toTime); + while (rs.next()) { + final long departureTime = rs.getLong("TIME_D"); + final long arrivalTime = rs.getLong("TIME_A"); + final short routeId = rs.getShort("ROUTE_ID"); + targetNode.setArrivalTime(routeId, arrivalTime); + node.setDepartureTime(routeId, departureTime); + + final long distance = arrivalTime > 0 ? arrivalTime - fromTime : Long.MAX_VALUE; + updateDistanceMap(results, routeId, targetNode, distance); + } + } + } catch (final SQLException e) { + e.printStackTrace(); + } finally { + DbUtils.closeQuietly(rs); + } } - return getAdjNodeCostByLoops(nConnection, dateCodes, fromTime, toTime); + return results; } /** @@ -618,157 +648,30 @@ public class Database { return new Link(linkId, start, end, routeId); } - @SuppressFBWarnings( - value = "UPM_UNCALLED_PRIVATE_METHOD", - justification = "Calling of this method is handeled by a boolean flag" - ) - private Map<Node, Long> getAdjNodeCostByInQuery(final NodeConnection nConnection, final Collection<Integer> dateCodes, final long fromTime, final long toTime) { - final Map<Node, Long> results = new LinkedHashMap<>(); - final Node node = nConnection.getSourceNode(); - - ResultSet rs = null; - try { - if (isIncoming) { - rs = getLatestDepartureTime(nConnection, dateCodes, fromTime, Math.round(toTime - node.getDistance())); - while (rs.next()) { - final long departureTime = rs.getLong("TIME_D"); - final long arrivalTime = rs.getLong("TIME_A"); - final int routeId = rs.getInt("ROUTE_ID"); - final int adjNodeId = rs.getInt("SOURCE"); - final Node adjNode = nConnection.getTargetNode(adjNodeId); - adjNode.setDepartureTime(routeId, departureTime); - node.setArrivalTime(routeId, arrivalTime); - - final long distance = toTime - departureTime; - updateDistanceMap(results, routeId, adjNode, distance); - } - } else { - rs = getEarliestArrivalTime(nConnection, dateCodes, Math.round(fromTime + node.getDistance()), toTime); - while (rs.next()) { - final long departureTime = rs.getLong("TIME_D"); - final long arrivalTime = rs.getLong("TIME_A"); - final int routeId = rs.getInt("ROUTE_ID"); - final int adjNodeId = rs.getInt("TARGET"); - final Node adjNode = nConnection.getTargetNode(adjNodeId); - node.setDepartureTime(routeId, departureTime); - adjNode.setArrivalTime(routeId, arrivalTime); - - final long distance = arrivalTime > 0 ? arrivalTime - fromTime : Long.MAX_VALUE; - updateDistanceMap(results, routeId, adjNode, distance); - } - } - } catch (final SQLException e) { - e.printStackTrace(); - } finally { - DbUtils.closeQuietly(rs); - } - - return results; - } - - @SuppressFBWarnings( - value = "UPM_UNCALLED_PRIVATE_METHOD", - justification = "Calling of this method is handeled by a boolean flag" - ) - private Map<Node, Long> getAdjNodeCostByLoops(final NodeConnection nConnection, final Collection<Integer> dateCodes, final long fromTime, final long toTime) { - final Node node = nConnection.getSourceNode(); - final Set<Entry<Node, Collection<Link>>> entries = nConnection.getTargetEntries().entrySet(); - final Map<Node, Long> results = new LinkedHashMap<>(entries.size()); - for (final Entry<Node, Collection<Link>> entry : entries) { - final Node targetNode = entry.getKey(); - final Collection<Integer> routes = NodeConnection.getTargetRoutes(entry.getValue()); - - ResultSet rs = null; - try { - if (isIncoming) { - rs = getLatestDepartureTime(targetNode.getId(), node.getId(), routes, dateCodes, fromTime, Math.round(toTime - node.getDistance())); - while (rs.next()) { - final long departureTime = rs.getLong("TIME_D"); - final long arrivalTime = rs.getLong("TIME_A"); - final short routeId = rs.getShort("ROUTE_ID"); - targetNode.setDepartureTime(routeId, departureTime); - node.setArrivalTime(routeId, arrivalTime); - - final long distance = toTime - departureTime; - updateDistanceMap(results, routeId, targetNode, distance); - } - } else { - rs = getEarliestArrivalTime(node.getId(), targetNode.getId(), routes, dateCodes, Math.round(fromTime + node.getDistance()), toTime); - while (rs.next()) { - final long departureTime = rs.getLong("TIME_D"); - final long arrivalTime = rs.getLong("TIME_A"); - final short routeId = rs.getShort("ROUTE_ID"); - targetNode.setArrivalTime(routeId, arrivalTime); - node.setDepartureTime(routeId, departureTime); - - final long distance = arrivalTime > 0 ? arrivalTime - fromTime : Long.MAX_VALUE; - updateDistanceMap(results, routeId, targetNode, distance); - } - } - } catch (final SQLException e) { - e.printStackTrace(); - } finally { - DbUtils.closeQuietly(rs); - } - } - - return results; - } - /** * Gets the earliest arrival time at the target when traveled from the source. * * @param sId the id of the source node * @param tId the id of the target node * @param rIds the identifiers of the routes that should be considered - * @param dateCodes the date codes for which the times are calculated + * @param arrDateCodes the date codes for which the times are calculated * @param from the earliest time for which we want to calculate the departure time * @param to the latest time for which we want to calculate the departure time * @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set) * @return a resultSet with all the times that come into consideration */ - private ResultSet getEarliestArrivalTime(final int sId, final int tId, final Collection<Integer> rIds, final Collection<Integer> dateCodes, final long from, final long to) throws SQLException { - final String sql = String.format(queryEarliestArrivalTimeHomo, preparePlaceHolders(rIds.size()), preparePlaceHolders(dateCodes.size())); + private ResultSet getEarliestArrivalTime(final int sId, final int tId, final Collection<Integer> rIds, final Object[] arrDateCodes, final long from, final long to) throws SQLException { + final Object[] arrRoutes = rIds.toArray(); + final String sql = String.format(queryEarliestArrivalTimeHomo, preparePlaceHolders(arrRoutes.length), preparePlaceHolders(arrDateCodes.length)); final PreparedStatement statement = getPstmt(sql); // CHECKSTYLE:OFF MagicNumber statement.setInt(1, sId); statement.setInt(2, tId); - int idx = setValues(3, statement, rIds.toArray()); + int idx = setValues(3, statement, arrRoutes); statement.setLong(idx++, from); statement.setLong(idx++, to); - idx = setValues(idx, statement, dateCodes.toArray()); - statement.setLong(idx, to); - // CHECKSTYLE:ON MagicNumber - - return statement.executeQuery(); - } - - /** - * Gets the earliest arrival time at the target when traveled from the source. - * - * @param nConnection (contains the source node id, the targetIds and the route ids) - * @param dates the date codes for which the times are calculated - * @param from the earliest time for which we want to calculate the departure time - * @param to the latest time for which we want to calculate the departure time - * @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set) - * @return a resultSet with all the times that come into consideration - */ - private ResultSet getEarliestArrivalTime(final NodeConnection nConnection, final Collection<Integer> dates, final long from, final long to) throws SQLException { - final int sId = nConnection.getSourceNode().getId(); - final Collection<Integer> tIds = nConnection.getAllTargetNodes(); - final Collection<Integer> rIds = nConnection.getAllRoutes(); - - final String sql = String.format(queryEarliestArrivalTimeHomoInQuery, preparePlaceHolders(tIds.size()), preparePlaceHolders(rIds.size()), preparePlaceHolders(dates.size())); - final PreparedStatement statement = getPstmt(sql); - - // CHECKSTYLE:OFF MagicNumber - statement.setInt(1, sId); - int idx = setValues(2, statement, tIds.toArray()); - idx = setValues(idx, statement, rIds.toArray()); - statement.setLong(idx++, from); - statement.setLong(idx++, to); - idx = setValues(idx, statement, dates.toArray()); + idx = setValues(idx, statement, arrDateCodes); statement.setLong(idx, to); // CHECKSTYLE:ON MagicNumber @@ -781,61 +684,30 @@ public class Database { * @param sId the id of the source node * @param tId the id of the target node * @param rIds the identifiers of the routes that should be considered - * @param dateCodes the date codes for which the times are calculated + * @param arrDateCodes the date codes for which the times are calculated * @param from the earliest time for which we want to calculate the departure time * @param to the latest time for which we want to calculate the departure time * @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set) * @return a resultSet with all the times that come into consideration */ - private ResultSet getLatestDepartureTime(final int sId, final int tId, final Collection<Integer> rIds, final Collection<Integer> dateCodes, final long from, final long to) throws SQLException { - final String sql = String.format(queryLatestDepartureTimeHomo, preparePlaceHolders(rIds.size()), preparePlaceHolders(dateCodes.size())); + private ResultSet getLatestDepartureTime(final int sId, final int tId, final Collection<Integer> rIds, final Object[] arrDateCodes, final long from, final long to) throws SQLException { + final Object[] arrRoutes = rIds.toArray(); + final String sql = String.format(queryLatestDepartureTimeHomo, preparePlaceHolders(arrRoutes.length), preparePlaceHolders(arrDateCodes.length)); final PreparedStatement statement = getPstmt(sql); // CHECKSTYLE:OFF MagicNumber statement.setInt(1, sId); statement.setInt(2, tId); - int idx = setValues(3, statement, rIds.toArray()); + int idx = setValues(3, statement, arrRoutes); statement.setLong(idx++, from); statement.setLong(idx++, to); - idx = setValues(idx, statement, dateCodes.toArray()); + idx = setValues(idx, statement, arrDateCodes); statement.setLong(idx, from); // CHECKSTYLE:ON MagicNumber return statement.executeQuery(); } - /** - * Gets the latest departure time to start from source, to arrive at the target in time. - * - * @param nConnection (contains the sourceIds, the target node id and the route ids) - * @param dates the date codes for which the times are calculated - * @param from the earliest time for which we want to calculate the departure time - * @param to the latest time for which we want to calculate the departure time - * @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set) - * @return a resultSet with all the times that come into consideration - */ - private ResultSet getLatestDepartureTime(final NodeConnection nConnection, final Collection<Integer> dates, final long from, final long to) throws SQLException { - final int tId = nConnection.getSourceNode().getId(); - final Collection<Integer> sIds = nConnection.getAllTargetNodes(); - final Collection<Integer> routeIds = nConnection.getAllRoutes(); - - final String sql = String.format(queryLatestDepartureTimeHomoInQuery, preparePlaceHolders(sIds.size()), preparePlaceHolders(routeIds.size()), preparePlaceHolders(dates.size())); - final PreparedStatement statement = getPstmt(sql); - - // CHECKSTYLE:OFF MagicNumber - int idx = setValues(1, statement, sIds.toArray()); - statement.setInt(idx++, tId); - idx = setValues(idx, statement, routeIds.toArray()); - statement.setLong(idx++, from); - statement.setLong(idx++, to); - idx = setValues(idx, statement, dates.toArray()); - statement.setLong(idx, from); - // CHECKSTYLE:ON MagicNumber - - return statement.executeQuery(); - } - - // Protected static methods /** @@ -866,12 +738,16 @@ public class Database { * @return a string with the placeholders plugged in to a statement. */ private static String preparePlaceHolders(final int length) { - final StringBuilder builder = new StringBuilder(); - for (int i = 0; i < length; ++i) { - builder.append("?"); - if (i + 1 < length) { - builder.append(","); - } + if (length <= 0) { + return ""; + } + + final StringBuilder builder = new StringBuilder((2 * length) - 1); + builder.append("?"); + + final int max = length - 1; + for (int i = 0; i < max; ++i) { + builder.append(",?"); } return builder.toString();