org.firebirdsql.jdbc.FBCachedFetcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jaybird Show documentation
Show all versions of jaybird Show documentation
JDBC Driver for the Firebird RDBMS
package org.firebirdsql.jdbc;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import org.firebirdsql.gds.GDSException;
import org.firebirdsql.gds.XSQLVAR;
import org.firebirdsql.gds.impl.AbstractIscStmtHandle;
import org.firebirdsql.gds.impl.GDSHelper;
import org.firebirdsql.jdbc.field.FBField;
import org.firebirdsql.jdbc.field.FBFlushableField;
import org.firebirdsql.jdbc.field.FieldDataProvider;
class FBCachedFetcher implements FBFetcher {
private boolean forwardOnly;
private Object[] rowsArray;
private int rowNum = 0;
private int fetchSize;
private FBObjectListener.FetcherListener fetcherListener;
FBCachedFetcher(GDSHelper gdsHelper, int fetchSize, int maxRows,
AbstractIscStmtHandle stmt_handle, FBObjectListener.FetcherListener fetcherListener, boolean forwardOnly) throws SQLException
{
this.fetcherListener = fetcherListener;
this.forwardOnly = forwardOnly;
ArrayList rowsSets = new ArrayList(100);
AbstractIscStmtHandle stmt = stmt_handle;
byte[][] localRow = null;
XSQLVAR[] xsqlvars = stmt_handle.getOutSqlda().sqlvar;
//
// Check if there is blobs to catch
//
boolean[] isBlob = new boolean[xsqlvars.length];
boolean hasBlobs = false;
for (int i = 0; i < xsqlvars.length; i++){
isBlob[i] = FBField.isType(xsqlvars[i], Types.BLOB) ||
FBField.isType(xsqlvars[i], Types.BINARY) ||
FBField.isType(xsqlvars[i], Types.LONGVARCHAR);
if (isBlob[i])
hasBlobs = true;
}
//
// load all rows from statement
//
int rowsCount = 0;
try {
if (fetchSize == 0)
fetchSize = MAX_FETCH_ROWS;
this.fetchSize = fetchSize;
// the following if, is only for callable statement
if (!stmt.isAllRowsFetched() && stmt.size() == 0) {
do {
if (maxRows != 0 && fetchSize > maxRows - stmt.size())
fetchSize = maxRows - stmt.size();
gdsHelper.fetch(stmt, fetchSize);
if (stmt.size() > 0){
rowsSets.add(stmt.getRows());
rowsCount += stmt.size();
stmt.removeRows();
}
} while (!stmt.isAllRowsFetched() && (maxRows==0 || rowsCount rowsCount-rowCount){
System.arraycopy(oneSet, 0, rowsArray, rowCount, rowsCount-rowCount);
rowCount = rowsCount;
}
else{
System.arraycopy(oneSet, 0, rowsArray, rowCount, oneSet.length);
rowCount += oneSet.length;
}
}
rowsSets.clear();
}
else {
rowsArray = stmt.getRows();
stmt.removeRows();
}
//
if (hasBlobs){
for (int i=0;i< rowsArray.length; i++){
localRow = (byte[][])rowsArray[i];
//ugly blob caching workaround.
for (int j = 0; j < localRow.length; j++){
// if field is blob and there is a value in cache
if (isBlob[j] && localRow[j] != null ) {
// anonymous implementation of the FieldDataProvider interface
final byte[] tempData = localRow[j];
FieldDataProvider dataProvider = new FieldDataProvider() {
public byte[] getFieldData() {
return tempData;
}
public void setFieldData(byte[] data) {
throw new UnsupportedOperationException();
}
};
// copy data from current row
FBField localField = FBField.createField(
xsqlvars[j], dataProvider, gdsHelper, false);
FBFlushableField blob = (FBFlushableField)localField;
localRow[j] = blob.getCachedObject();
}
}
}
}
gdsHelper.closeStatement(stmt, false);
}
catch (GDSException ge) {
throw new FBSQLException(ge);
}
}
FBCachedFetcher(ArrayList rows, FBObjectListener.FetcherListener fetcherListener) throws SQLException {
rowsArray = rows.toArray();
this.fetcherListener = fetcherListener;
}
public boolean next() throws SQLException {
if (isEmpty())
return false;
rowNum++;
if (isAfterLast()) {
fetcherListener.rowChanged(this, null);
// keep cursor right after last row
rowNum = rowsArray.length + 1;
return false;
}
fetcherListener.rowChanged(this, (byte[][])rowsArray[rowNum-1]);
return true;
}
public boolean previous() throws SQLException {
if (forwardOnly)
throw new FBDriverNotCapableException(
"Result set is TYPE_FORWARD_ONLY");
if (isEmpty())
return false;
rowNum--;
if(isBeforeFirst()) {
fetcherListener.rowChanged(this, null);
// keep cursor right before the first row
rowNum = 0;
return false;
}
fetcherListener.rowChanged(this, (byte[][])rowsArray[rowNum-1]);
return true;
}
public boolean absolute(int row) throws SQLException {
if (forwardOnly)
throw new FBDriverNotCapableException(
"Result set is TYPE_FORWARD_ONLY");
return absolute(row, false);
}
private boolean absolute(int row, boolean internal) throws SQLException {
if (forwardOnly && !internal)
throw new FBDriverNotCapableException(
"Result set is TYPE_FORWARD_ONLY");
if (row < 0)
row = rowsArray.length + row + 1;
if (row == 0 && !internal)
throw new FBSQLException(
"You cannot position to the row 0 with absolute() method.");
if (isEmpty())
return false;
rowNum = row;
if(isBeforeFirst()) {
fetcherListener.rowChanged(this, null);
// keep cursor right before the first row
rowNum = 0;
return false;
}
if (isAfterLast()) {
fetcherListener.rowChanged(this, null);
rowNum = rowsArray.length + 1;
return false;
}
fetcherListener.rowChanged(this, (byte[][])rowsArray[rowNum-1]);
return true;
}
public boolean first() throws SQLException {
if (forwardOnly)
throw new FBDriverNotCapableException(
"Result set is TYPE_FORWARD_ONLY");
return absolute(1, true);
}
public boolean last() throws SQLException {
if (forwardOnly)
throw new FBDriverNotCapableException(
"Result set is TYPE_FORWARD_ONLY");
return absolute(-1, true);
}
public boolean relative(int row) throws SQLException {
if (forwardOnly)
throw new FBDriverNotCapableException(
"Result set is TYPE_FORWARD_ONLY");
return absolute(rowNum + row, true);
}
public void beforeFirst() throws SQLException {
first();
previous();
}
public void afterLast() throws SQLException {
last();
next();
}
public void close() throws SQLException {
}
public int getRowNum() {
return rowNum;
}
public boolean isEmpty() {
return rowsArray == null || rowsArray.length == 0;
}
public boolean isBeforeFirst() {
return !isEmpty() && rowNum < 1;
}
public boolean isFirst() {
return rowNum == 1;
}
public boolean isLast() {
return rowsArray != null ? rowNum == rowsArray.length : false;
}
public boolean isAfterLast() {
return rowNum > rowsArray.length;
}
/* (non-Javadoc)
* @see org.firebirdsql.jdbc.FBFetcher#deleteRow()
*/
public void deleteRow() throws SQLException {
Object[] newRows = new Object[rowsArray.length - 1];
System.arraycopy(rowsArray, 0, newRows, 0, rowNum - 1);
if (rowNum < rowsArray.length)
System.arraycopy(rowsArray, rowNum, newRows, rowNum - 1, rowsArray.length - rowNum);
rowsArray = newRows;
if (isAfterLast())
fetcherListener.rowChanged(this, null);
else
if (isBeforeFirst())
fetcherListener.rowChanged(this, null);
else
fetcherListener.rowChanged(this, (byte[][])rowsArray[rowNum-1]);
}
/* (non-Javadoc)
* @see org.firebirdsql.jdbc.FBFetcher#insertRow(byte[][])
*/
public void insertRow(byte[][] data) throws SQLException {
Object[] newRows = new Object[rowsArray.length + 1];
if (rowNum == 0)
rowNum++;
System.arraycopy(rowsArray, 0, newRows, 0, rowNum - 1);
System.arraycopy(rowsArray, rowNum - 1, newRows, rowNum, rowsArray.length - rowNum + 1);
newRows[rowNum - 1] = data;
rowsArray = newRows;
if (isAfterLast())
fetcherListener.rowChanged(this, null);
else
if (isBeforeFirst())
fetcherListener.rowChanged(this, null);
else
fetcherListener.rowChanged(this, (byte[][])rowsArray[rowNum-1]);
}
/* (non-Javadoc)
* @see org.firebirdsql.jdbc.FBFetcher#updateRow(byte[][])
*/
public void updateRow(byte[][] data) throws SQLException {
if (!isAfterLast() && !isBeforeFirst()) {
rowsArray[rowNum - 1] = data;
fetcherListener.rowChanged(this, data);
}
}
public int getFetchSize(){
return fetchSize;
}
public void setFetchSize(int fetchSize){
this.fetchSize = fetchSize;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy