package jeql.command.db;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import jeql.api.error.ExecutionException;
import jeql.api.row.Row;
import jeql.api.row.RowIterator;
import jeql.api.row.RowList;
import jeql.api.row.RowSchema;
import jeql.command.db.driver.JdbcUtil;
import jeql.command.db.driver.RowMapper;
public class DbRowList
implements RowList
{
public static final int DEFAULT_FETCH_SIZE = 1000;
private String driverClassName;
private String connectString;
private String user;
private String password;
private RowMapper rowMapper;
private String sql;
private int fetchSize = 1;
private Connection conn = null;
private Statement stmt = null;
private ResultSet rs = null;
private RowSchema schema;
private boolean isRead = false;
public DbRowList(String driverClassName, String connectString,
String user, String password,
String sql,
int fetchSize,
RowMapper rowMapper)
{
this.driverClassName = driverClassName;
this.connectString = connectString;
this.user = user;
this.password = password;
this.sql = sql;
this.fetchSize = fetchSize;
this.rowMapper = rowMapper;
open();
}
private void open()
{
conn = JdbcUtil.createConnection(driverClassName, connectString, user, password);
try {
conn.setAutoCommit(false); // this allows cursor-driven fetching (for PostGIS at least)
stmt = conn.createStatement();
stmt.setFetchSize(fetchSize);
rs = stmt.executeQuery(sql);
schema = rowMapper.getSchema(rs);
}
catch (SQLException ex) {
close();
throw new ExecutionException(ex.getMessage());
}
}
public RowSchema getSchema() {
return schema;
}
public RowIterator iterator()
{
if (isRead)
throw new ExecutionException("Attempt to re-read streamed table");
isRead = true;
return new DbRowIterator(this);
}
//private ResultSet getRS() { return rs; }
private void close() {
try {
if (rs != null)
rs.close();
} catch (SQLException ex) {
// eat this exception - nothing we can do about it now
}
rs = null;
try {
if (stmt != null)
stmt.close();
} catch (SQLException ex) {
// eat this exception - nothing we can do about it now
}
stmt = null;
try {
if (conn != null)
conn.close();
conn = null;
} catch (SQLException ex) {
// eat this exception - nothing we can do about it now
}
}
//=============================================
private static class DbRowIterator
implements RowIterator
{
private DbRowList dbRL;
private RowSchema schema = null;
public DbRowIterator(DbRowList dbRL) {
this.dbRL = dbRL;
schema = dbRL.getSchema();
}
public RowSchema getSchema() {
return schema;
}
public Row next()
{
if (dbRL == null) return null;
Row row = null;
try {
if (dbRL.rs.next()) {
row = dbRL.rowMapper.createRow(dbRL.schema, dbRL.rs);
}
// else drop through and close the rowlist
}
catch (Exception ex) {
throw new ExecutionException(ex.getMessage());
}
finally {
if (row == null) {
dbRL.close();
dbRL = null;
}
}
return row;
}
}
}