package jeql.engine.query.join;
import jeql.api.error.ImplementationException;
import jeql.api.row.BasicRow;
import jeql.api.row.Row;
import jeql.api.row.RowIterator;
import jeql.api.row.RowList;
import jeql.api.row.RowSchema;
/**
* A simplistic nested loop join processor,
* which does not support a filter expression.
*
* @author Martin Davis
*
*/
public class SimpleNestedLoopJoinRowList
implements RowList
{
private RowSchema schema = null;
private RowList[] rowStr = new RowList[2];
private int rsCount = 0;
public SimpleNestedLoopJoinRowList() {
}
public void addRowStream(RowList rs)
{
rowStr[rsCount++] = rs;
buildSchema();
}
private void buildSchema()
{
if (rsCount == 1) {
schema = new RowSchema(rowStr[0].getSchema());
return;
}
else if (rsCount == 2) {
schema = new RowSchema(rowStr[0].getSchema(), rowStr[1].getSchema());
return;
}
// should never get here
throw new ImplementationException("Too many tables in join");
}
public RowSchema getSchema() { return schema; }
public RowIterator iterator()
{
return new SimpleNestedLoopJoinRowIterator(schema, rowStr);
}
private static class SimpleNestedLoopJoinRowIterator
implements RowIterator
{
private RowSchema schema;
private RowList[] rowStr;
private RowIterator[] rowIt;
private Row row0;
private Row row1;
private BasicRow joinRow = null;
public SimpleNestedLoopJoinRowIterator(RowSchema schema, RowList[] rowStr)
{
this.schema = schema;
this.rowStr = rowStr;
rowIt = new RowIterator[rowStr.length];
rowIt[0] = rowStr[0].iterator();
rowIt[1] = rowStr[1].iterator();
}
public RowSchema getSchema() { return schema; }
public Row next()
{
if (joinRow == null) { // just started
// get first rows in each stream
row0 = rowIt[0].next();
if (row0 == null) return null;
row1 = rowIt[1].next();
if (row1 == null) return null;
return createRow();
}
// here we can assume left rows are non-null
// can also assume that right table is non-empty (otherwise would have returned above)
row1 = rowIt[1].next();
if (row1 != null) {
return createRow();
}
row0 = rowIt[0].next();
if (row0 != null) {
rowIt[1]= rowStr[1].iterator();
row1 = rowIt[1].next();
return createRow();
}
return null;
}
private void copyToJoin(Row srcRow, int startIndex)
{
for (int i = 0; i < srcRow.size(); i++) {
joinRow.setValue(i + startIndex, srcRow.getValue(i));
}
}
private Row createRow()
{
if (joinRow == null) {
joinRow = new BasicRow(schema.size());
}
copyToJoin(row0, 0);
copyToJoin(row1, row0.size());
return joinRow;
}
}
}