package com.aconex.scrutineer.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Iterator;
import org.slf4j.Logger;
import com.aconex.scrutineer.IdAndVersion;
import com.aconex.scrutineer.IdAndVersionFactory;
import com.aconex.scrutineer.IdAndVersionStream;
import com.aconex.scrutineer.LogUtils;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
public class JdbcIdAndVersionStream implements IdAndVersionStream {
private static final Logger LOG = LogUtils.loggerForThisClass();
private final Connection connection;
private final String sql;
private final IdAndVersionFactory factory;
private Statement statement;
private ResultSet resultSet;
private Iterator<IdAndVersion> iterator;
public JdbcIdAndVersionStream(Connection connection, String sql, IdAndVersionFactory factory) {
this.connection = connection;
this.sql = sql;
this.factory = factory;
}
@Override
public void open() {
long begin = System.currentTimeMillis();
this.iterator = createIterator(factory);
LogUtils.info(LOG, "Executed JDBC query in %dms", (System.currentTimeMillis() - begin));
}
@Override
public Iterator<IdAndVersion> iterator() {
return iterator;
}
private Iterator<IdAndVersion> createIterator(IdAndVersionFactory factory) {
try {
statement = connection.createStatement();
resultSet = statement.executeQuery(sql);
return new IdAndVersionResultSetIterator(resultSet, factory);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void close() {
this.iterator = null;
throwExceptionIfAnyCloseFails(closeResultSet(), closeStatement());
}
private void throwExceptionIfAnyCloseFails(SQLException... sqlExceptions) {
if (!Iterables.all(Arrays.asList(sqlExceptions), Predicates.<Object>isNull())) {
throw new RuntimeException("At least one error occured during close, see logs for more details, there may be multiple");
}
}
@SuppressWarnings("PMD.NcssMethodCount")
private SQLException closeStatement() {
SQLException sqlException = null;
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
sqlException = e;
LogUtils.error(LOG, "Cannot close statement", e);
}
}
return sqlException;
}
@SuppressWarnings("PMD.NcssMethodCount")
private SQLException closeResultSet() {
SQLException sqlException = null;
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
sqlException = e;
LogUtils.error(LOG, "Cannot close resultset", e);
}
}
return sqlException;
}
}