Renderer/src/main/java/electrosphere/server/db/DatabaseResultIterator.java
austin 7d6134c183
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
fix tests
2024-11-29 23:09:58 -05:00

122 lines
4.1 KiB
Java

package electrosphere.server.db;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import electrosphere.logger.LoggerInterface;
/**
* Iterates through a database result
*/
public class DatabaseResultIterator implements Iterator<DatabaseResultRow> {
/**
* The result set
*/
ResultSet rs;
/**
* The metadata of the result set
*/
ResultSetMetaData metadata;
/**
* The type list of each column
*/
List<Integer> typeList;
/**
* Creates a result iterator -- used internal to package
* @param result
*/
protected DatabaseResultIterator(ResultSet result){
this.rs = result;
try {
this.metadata = this.rs.getMetaData();
int columnCount = metadata.getColumnCount();
this.typeList = new LinkedList<Integer>();
for(int i = 0; i < columnCount; i++){
//result sets are indexed starting at 1
this.typeList.add(metadata.getColumnType(i+1));
}
//the sqlite driver doesn't support reverse navigation unfortunatelly
//if it did, we'd call this to be explicitly clear where we want to start
//instead the assumption is it always starts ON the first element
// this.rs.first();
//starts before the first, so must iterate once into the result set in order to not double-sample the first row
if(this.rs.isBeforeFirst()){
this.rs.next();
}
} catch (SQLException e) {
LoggerInterface.loggerEngine.ERROR("SQL Exception", e);
}
}
/**
* Lets us know if the result has a next value
*/
@Override
public boolean hasNext() {
try {
boolean rVal = !rs.isAfterLast();
if(!rVal && rs != null){
rs.close();
}
return rVal;
} catch (SQLException e) {
LoggerInterface.loggerEngine.ERROR("Critical failure in DatabaseResultIterator", e);
return false;
}
}
/**
* Gets the next value in the result
*/
@Override
public DatabaseResultRow next() {
DatabaseResultRow row = new DatabaseResultRow();
int columnIncrementer = 0;
//basically go through each type and add it to the row object that we return
//the types are stored in the typeList field on this object when it is created
try {
for(int type : typeList){
//increment at the beginning because result sets are indexed starting at 1
columnIncrementer++;
switch(type){
case Types.INTEGER:
row.putValue(metadata.getColumnName(columnIncrementer), rs.getInt(columnIncrementer));
break;
case Types.VARCHAR:
row.putValue(metadata.getColumnName(columnIncrementer), rs.getString(columnIncrementer));
break;
case Types.BIGINT:
row.putValue(metadata.getColumnName(columnIncrementer), rs.getLong(columnIncrementer));
break;
case Types.FLOAT:
row.putValue(metadata.getColumnName(columnIncrementer), rs.getFloat(columnIncrementer));
break;
case Types.DOUBLE:
row.putValue(metadata.getColumnName(columnIncrementer), rs.getDouble(columnIncrementer));
break;
default:
LoggerInterface.loggerEngine.WARNING("Unsupported type from database in DatabaseResultIterator " + type);
break;
}
}
//make sure to increment the result set so we don't infinitely loop the first element
this.rs.next();
} catch (SQLException e){
LoggerInterface.loggerEngine.ERROR("Unhandled SQL exception", e);
}
return row;
}
}