package jef.database.jdbc.result;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import javax.persistence.PersistenceException;
import jef.database.Condition;
import jef.database.dialect.DatabaseDialect;
import jef.database.meta.Reference;
import jef.database.wrapper.populator.ColumnMeta;
/**
* 对结果集跳过若干记录,并且限定其最大数的ResultSet实现
*
* @author jiyi
*
*/
final class LimitOffsetResultSet extends AbstractResultSet implements IResultSet{
private int offset;
private int limit;
private ResultSet rs;
/**
* 当前游标所处位置,从0开始。0表示在第一条结果之前。 如果position=Integer.MAX_VALUE则表示在最后一条结果之后
*/
private int position;
/**
* 构造一个可用于跳过条数,以及限制结果数量的ResultSet。
*
* @param rs
* @param offset
* @param limit
*/
public LimitOffsetResultSet(ResultSet rs, int offset, int limit) {
this.offset = offset;
this.limit = limit == 0 ? Integer.MAX_VALUE : limit;
this.rs = rs;
try {
skipOffset(rs, offset);
} catch (SQLException e) {
throw new PersistenceException(e);
}
}
public LimitOffsetResultSet(IResultSet rs, int offset, int limit) {
this.offset = offset;
this.limit = limit == 0 ? Integer.MAX_VALUE : limit;
this.meta=rs.getColumns();
this.profile=rs.getProfile();
this.filters=rs.getFilters();
this.rs = rs;
try {
skipOffset(rs, offset);
} catch (SQLException e) {
throw new PersistenceException(e);
}
}
private void skipOffset(ResultSet rs, int offset) throws SQLException {
for (int i = 0; i < offset; i++) {
if (!rs.next()) {
break;
}
}
}
@SuppressWarnings("all")
@Override
public boolean next(){
if (position >= limit) {
position = Integer.MAX_VALUE;
return false;
}
try{
final boolean next;
if (next = rs.next()) {
position++;
} else {
position = Integer.MAX_VALUE;
}
return next;
}catch(SQLException e){
throw new PersistenceException(e);
}
}
@Override
public void close() throws SQLException {
rs.close();
}
@Override
public ResultSetMetaData getMetaData() throws SQLException {
return rs.getMetaData();
}
@Override
public boolean isBeforeFirst() throws SQLException {
return position == 0;
}
@Override
public boolean isAfterLast() throws SQLException {
return position == Integer.MAX_VALUE;
}
@Override
public void beforeFirst() throws SQLException {
rs.beforeFirst();
skipOffset(rs, offset);
position = 0;
}
@Override
public void afterLast() throws SQLException {
while (next());
}
@Override
public boolean first() throws SQLException {
if (rs.first()) {
skipOffset(rs, offset);
position = 1;
return true;
}
return false;
}
@Override
public boolean last() throws SQLException {
while (position<limit){
if(rs.isLast())break;
next();
}
return true;
}
@Override
public boolean previous() throws SQLException {
if (rs.previous()) {
position--;
return true;
}
return false;
}
@Override
public boolean isClosed() throws SQLException {
return rs.isClosed();
}
@Override
protected ResultSet get() throws SQLException {
return rs;
}
@Override
public boolean isFirst() throws SQLException {
return position == 1;
}
@Override
public boolean isLast() throws SQLException {
return position == limit || rs.isLast();
}
private Map<Reference, List<Condition>> filters;
private DatabaseDialect profile;
private ColumnMeta meta ;
@Override
public Map<Reference, List<Condition>> getFilters() {
return filters;
}
@Override
public DatabaseDialect getProfile() {
return profile;
}
@Override
public ColumnMeta getColumns() {
return meta;
}
}