*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ---------------
* Join.java
* ---------------
* Author: Volker Berlin
*
*/
package smallsql.database;
final class Join extends RowSource{
Expression condition; private int type;
RowSource left; RowSource right;
private boolean isBeforeFirst = true;
private boolean isAfterLast;
private boolean isOuterValid = true;
private boolean[] isFullNotValid;
private int fullRightRowCounter;
private int fullRowCount;
private int fullReturnCounter = -1;
private LongLongList rowPositions; private int row;
Join( int type, RowSource left, RowSource right, Expression condition ){
this.type = type;
this.condition = condition;
this.left = left;
this.right = right;
if(type == FULL_JOIN){
isFullNotValid = new boolean[10];
}
}
final boolean isScrollable(){
return false; }
void beforeFirst() throws Exception{
left.beforeFirst();
right.beforeFirst();
isBeforeFirst = true;
isAfterLast = false;
fullRightRowCounter = 0;
fullRowCount = 0;
fullReturnCounter = -1;
row = 0;
}
boolean first() throws Exception{
boolean result = left.first() && right.first();
row = 1;
isBeforeFirst= false;
isAfterLast = false;
if(!result) noRow();
return result;
}
boolean next() throws Exception{
if(isAfterLast) return false;
boolean result;
row++;
if(fullReturnCounter >=0){
do{
if(fullReturnCounter >= fullRowCount){
noRow();
return false;
}
right.next();
}while(isFullNotValid[fullReturnCounter++]);
return true;
}
do{
if(isBeforeFirst){
result = left.next();
if(result){
result = right.first();
if(!result){
switch(type){
case LEFT_JOIN:
case FULL_JOIN:
isOuterValid = false;
isBeforeFirst = false;
right.nullRow();
return true;
}
}else fullRightRowCounter++;
}else{
if(type == FULL_JOIN){
while(right.next()){
fullRightRowCounter++;
}
fullRowCount = fullRightRowCounter;
}
}
}else{
result = right.next();
if(!result){
switch(type){
case LEFT_JOIN:
case FULL_JOIN:
if(isOuterValid){
isOuterValid = false;
right.nullRow();
return true;
}
fullRowCount = Math.max( fullRowCount, fullRightRowCounter);
fullRightRowCounter = 0;
}
isOuterValid = true;
result = left.next();
if(result){
result = right.first();
if(!result){
switch(type){
case LEFT_JOIN:
case FULL_JOIN:
isOuterValid = false;
right.nullRow();
return true;
}
}else fullRightRowCounter++;
}
}else fullRightRowCounter++;
}
isBeforeFirst = false;
}while(result && !getBoolean());
isOuterValid = false;
if(type == FULL_JOIN){
if(fullRightRowCounter >= isFullNotValid.length){
boolean[] temp = new boolean[fullRightRowCounter << 1];
System.arraycopy( isFullNotValid, 0, temp, 0, fullRightRowCounter);
isFullNotValid = temp;
}
if(!result){
if(fullRowCount == 0){
noRow();
return false;
}
if(fullReturnCounter<0) {
fullReturnCounter = 0;
right.first();
left.nullRow();
}
while(isFullNotValid[fullReturnCounter++]){
if(fullReturnCounter >= fullRowCount){
noRow();
return false;
}
right.next();
}
return true;
}else
isFullNotValid[fullRightRowCounter-1] = result;
}
if(!result){
noRow();
}
return result;
}
void afterLast(){
isAfterLast = true;
noRow();
}
int getRow(){
return row;
}
final long getRowPosition(){
if(rowPositions == null) rowPositions = new LongLongList();
rowPositions.add( left.getRowPosition(), right.getRowPosition());
return rowPositions.size()-1;
}
final void setRowPosition(long rowPosition) throws Exception{
left .setRowPosition( rowPositions.get1((int)rowPosition));
right.setRowPosition( rowPositions.get2((int)rowPosition));
}
final boolean rowInserted(){
return left.rowInserted() || right.rowInserted();
}
final boolean rowDeleted(){
return left.rowDeleted() || right.rowDeleted();
}
void nullRow(){
left.nullRow();
right.nullRow();
row = 0;
}
void noRow(){
isAfterLast = true;
left.noRow();
right.noRow();
row = 0;
}
void execute() throws Exception{
left.execute();
right.execute();
}
private boolean getBoolean() throws Exception{
return type == CROSS_JOIN || condition.getBoolean();
}
static final int CROSS_JOIN = 1;
static final int INNER_JOIN = 2;
static final int LEFT_JOIN = 3;
static final int FULL_JOIN = 4;
static final int RIGHT_JOIN = 5;
}