package net.ttddyy.dsproxy;
import net.ttddyy.dsproxy.listener.QueryExecutionListener;
import net.ttddyy.dsproxy.proxy.jdk.ResultSetProxyJdbcProxyFactory;
import net.ttddyy.dsproxy.support.ProxyDataSource;
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
import org.hsqldb.jdbc.JDBCDataSource;
import org.junit.Test;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Liam Williams
*/
public class ResultSetProxyJdbcProxyFactoryTest {
@Test
public void checkThatResultSetCanBeConsumedMoreThanOnce() throws Exception {
JDBCDataSource dataSourceWithData = dataSourceWithData();
LoggingExecutionListener listener = new LoggingExecutionListener();
ProxyDataSource proxyDataSource = ProxyDataSourceBuilder.create(dataSourceWithData)
.listener(listener)
.build();
proxyDataSource.setJdbcProxyFactory(new ResultSetProxyJdbcProxyFactory());
checkThatResultSetCanBeConsumedViaTheProxyDataSource(proxyDataSource);
checkThatTheResultSetWasAlsoConsumedInTheListener(listener);
}
private void checkThatTheResultSetWasAlsoConsumedInTheListener(LoggingExecutionListener listener) {
assertThat(listener.table.columns).containsExactly("A", "B");
assertThat(listener.table.rows).containsExactly(
new String[]{"1", "2"},
new String[]{"3", "4"},
new String[]{"5", "6"}
);
}
private JDBCDataSource dataSourceWithData() throws SQLException {
JDBCDataSource dataSource = new JDBCDataSource();
dataSource.setDatabase("jdbc:hsqldb:mem:test");
Connection connection = dataSource.getConnection();
connection.createStatement().execute("CREATE TABLE test(a INT, b INT)");
connection.prepareStatement("INSERT INTO test(a, b) VALUES(1,2)").executeUpdate();
connection.prepareStatement("INSERT INTO test(a, b) VALUES(3,4)").executeUpdate();
connection.prepareStatement("INSERT INTO test(a, b) VALUES(5,6)").executeUpdate();
return dataSource;
}
private void checkThatResultSetCanBeConsumedViaTheProxyDataSource(ProxyDataSource proxyDataSource) throws SQLException {
Connection connection = proxyDataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * from test");
ResultSet resultSet = preparedStatement.executeQuery();
resultSet.next();
assertThat(resultSet.getInt("a")).isEqualTo(1);
assertThat(resultSet.getInt(2)).isEqualTo(2);
resultSet.next();
assertThat(resultSet.getInt(1)).isEqualTo(3);
assertThat(resultSet.getInt("b")).isEqualTo(4);
resultSet.next();
assertThat(resultSet.getInt("a")).isEqualTo(5);
assertThat(resultSet.getInt("b")).isEqualTo(6);
assertThat(resultSet.next()).isFalse();
resultSet.close();
}
private static class LoggingExecutionListener implements QueryExecutionListener {
private Table table;
@Override
public void beforeQuery(ExecutionInfo execInfo, List<QueryInfo> queryInfoList) {
}
@Override
public void afterQuery(ExecutionInfo execInfo, List<QueryInfo> queryInfoList) {
if (execInfo.getResult() instanceof ResultSet) {
table = extractTable((ResultSet) execInfo.getResult());
}
}
private static Table extractTable(ResultSet resultSet) {
try {
String[] columns = extractColumns(resultSet);
List<String[]> rows = new ArrayList<String[]>();
while (resultSet.next()) {
rows.add(extractRow(resultSet));
}
resultSet.beforeFirst();
return new Table(columns, rows);
} catch (SQLException e) {
throw new IllegalStateException("Could not extract result set", e);
}
}
private static String[] extractColumns(ResultSet resultSet) throws SQLException {
ResultSetMetaData metaData = resultSet.getMetaData();
String[] columns = new String[metaData.getColumnCount()];
for (int i = 1; i <= metaData.getColumnCount(); i++) {
columns[i - 1] = metaData.getColumnLabel(i);
}
return columns;
}
private static String[] extractRow(ResultSet resultSet) throws SQLException {
ResultSetMetaData metaData = resultSet.getMetaData();
String[] row = new String[metaData.getColumnCount()];
for (int i = 1; i <= metaData.getColumnCount(); i++) {
row[i - 1] = String.valueOf(resultSet.getObject(i));
}
return row;
}
}
private static class Table {
private final String[] columns;
private final List<String[]> rows;
private Table(String[] columns, List<String[]> rows) {
this.columns = columns;
this.rows = rows;
}
}
}