1 33 package smallsql.database; 34 35 36 final class Join extends RowSource{ 37 38 Expression condition; private int type; 40 RowSource left; RowSource right; 42 private boolean isBeforeFirst = true; 43 private boolean isAfterLast; 44 private boolean isOuterValid = true; 45 46 private boolean[] isFullNotValid; 48 private int fullRightRowCounter; 49 private int fullRowCount; 50 private int fullReturnCounter = -1; 51 52 private LongLongList rowPositions; private int row; 55 56 Join( int type, RowSource left, RowSource right, Expression condition ){ 57 this.type = type; 58 this.condition = condition; 59 this.left = left; 60 this.right = right; 61 if(type == FULL_JOIN){ 62 isFullNotValid = new boolean[10]; 63 } 64 } 65 66 67 final boolean isScrollable(){ 68 return false; } 70 71 72 void beforeFirst() throws Exception { 73 left.beforeFirst(); 74 right.beforeFirst(); 75 isBeforeFirst = true; 76 isAfterLast = false; 77 fullRightRowCounter = 0; 78 fullRowCount = 0; 79 fullReturnCounter = -1; 80 row = 0; 81 } 82 83 boolean first() throws Exception { 84 boolean result = left.first() && right.first(); 85 row = 1; 86 isBeforeFirst= false; 87 isAfterLast = false; 88 if(!result) noRow(); 89 return result; 90 } 91 92 93 boolean next() throws Exception { 94 if(isAfterLast) return false; 95 boolean result; 96 row++; 97 if(fullReturnCounter >=0){ 98 do{ 99 if(fullReturnCounter >= fullRowCount){ 100 noRow(); 101 return false; 102 } 103 right.next(); 104 }while(isFullNotValid[fullReturnCounter++]); 105 return true; 106 } 107 do{ 108 if(isBeforeFirst){ 109 result = left.next(); 110 if(result){ 111 result = right.first(); 112 if(!result){ 113 switch(type){ 114 case LEFT_JOIN: 115 case FULL_JOIN: 116 isOuterValid = false; 117 isBeforeFirst = false; 118 right.nullRow(); 119 return true; 120 } 121 }else fullRightRowCounter++; 122 }else{ 123 if(type == FULL_JOIN){ 125 while(right.next()){ 126 fullRightRowCounter++; 127 } 128 fullRowCount = fullRightRowCounter; 129 } 130 } 131 }else{ 132 result = right.next(); 133 if(!result){ 134 switch(type){ 135 case LEFT_JOIN: 136 case FULL_JOIN: 137 if(isOuterValid){ 138 isOuterValid = false; 139 right.nullRow(); 140 return true; 141 } 142 fullRowCount = Math.max( fullRowCount, fullRightRowCounter); 143 fullRightRowCounter = 0; 144 } 145 isOuterValid = true; 146 result = left.next(); 147 if(result){ 148 result = right.first(); 149 if(!result){ 150 switch(type){ 151 case LEFT_JOIN: 152 case FULL_JOIN: 153 isOuterValid = false; 154 right.nullRow(); 155 return true; 156 } 157 }else fullRightRowCounter++; 158 } 159 160 }else fullRightRowCounter++; 161 } 162 isBeforeFirst = false; 163 }while(result && !getBoolean()); 164 isOuterValid = false; 165 if(type == FULL_JOIN){ 166 if(fullRightRowCounter >= isFullNotValid.length){ 167 boolean[] temp = new boolean[fullRightRowCounter << 1]; 168 System.arraycopy( isFullNotValid, 0, temp, 0, fullRightRowCounter); 169 isFullNotValid = temp; 170 } 171 if(!result){ 172 if(fullRowCount == 0){ 173 noRow(); 174 return false; 175 } 176 if(fullReturnCounter<0) { 177 fullReturnCounter = 0; 178 right.first(); 179 left.nullRow(); 180 } 181 while(isFullNotValid[fullReturnCounter++]){ 182 if(fullReturnCounter >= fullRowCount){ 183 noRow(); 184 return false; 185 } 186 right.next(); 187 } 188 return true; 189 }else 190 isFullNotValid[fullRightRowCounter-1] = result; 191 } 192 if(!result){ 193 noRow(); 194 } 195 return result; 196 } 197 198 199 void afterLast(){ 200 isAfterLast = true; 201 noRow(); 202 } 203 204 205 int getRow(){ 206 return row; 207 } 208 209 210 final long getRowPosition(){ 211 if(rowPositions == null) rowPositions = new LongLongList(); 212 rowPositions.add( left.getRowPosition(), right.getRowPosition()); 213 return rowPositions.size()-1; 214 } 215 216 final void setRowPosition(long rowPosition) throws Exception { 217 left .setRowPosition( rowPositions.get1((int)rowPosition)); 218 right.setRowPosition( rowPositions.get2((int)rowPosition)); 219 } 220 221 222 final boolean rowInserted(){ 223 return left.rowInserted() || right.rowInserted(); 224 } 225 226 227 final boolean rowDeleted(){ 228 return left.rowDeleted() || right.rowDeleted(); 229 } 230 231 232 235 void nullRow(){ 236 left.nullRow(); 237 right.nullRow(); 238 row = 0; 239 } 240 241 242 void noRow(){ 243 isAfterLast = true; 244 left.noRow(); 245 right.noRow(); 246 row = 0; 247 } 248 249 250 void execute() throws Exception { 251 left.execute(); 252 right.execute(); 253 } 254 255 256 private boolean getBoolean() throws Exception { 257 return type == CROSS_JOIN || condition.getBoolean(); 258 } 259 260 261 static final int CROSS_JOIN = 1; 262 static final int INNER_JOIN = 2; 263 static final int LEFT_JOIN = 3; 264 static final int FULL_JOIN = 4; 265 static final int RIGHT_JOIN = 5; 266 } | Popular Tags |