1 package com.quadcap.sql; 2 3 40 41 import java.io.ByteArrayOutputStream ; 42 import java.io.IOException ; 43 import java.io.ObjectInput ; 44 import java.io.ObjectOutput ; 45 46 import java.util.Enumeration ; 47 import java.util.Hashtable ; 48 import java.util.Vector ; 49 50 import java.sql.SQLException ; 51 52 import com.quadcap.sql.io.ObjectOutputStream; 53 54 import com.quadcap.sql.file.ByteUtil; 55 56 import com.quadcap.sql.index.Btree; 57 import com.quadcap.sql.index.Comparator; 58 59 import com.quadcap.sql.types.Op; 60 import com.quadcap.sql.types.Value; 61 import com.quadcap.sql.types.ValueException; 62 import com.quadcap.sql.types.ValueInteger; 63 import com.quadcap.sql.types.ValueNull; 64 65 import com.quadcap.util.Debug; 66 import com.quadcap.util.Util; 67 68 73 public class IndexCursor extends BC_Cursor { 74 Table table; 75 IndexConstraint constraint; 76 Btree index; 77 Comparator compare; 78 Vector indexNames = null; 79 StaticCursor startVals = null; 80 StaticCursor stopVals = null; 81 82 byte[] startVal; 83 byte[] stopVal; 84 85 86 90 public IndexCursor(Table table, Session session, 91 IndexConstraint constraint, Expression where, 92 String qualifier, Cursor outerCursor) 93 throws SQLException , IOException 94 { 95 super(session, qualifier, outerCursor); 96 this.table = table; 97 this.constraint = constraint; 98 this.index = constraint.getIndex(session.getDatabase()); 99 this.compare = index.getComparator(); 100 101 addColumns(session, table); 102 103 this.indexNames = constraint.getColumnNames(); 104 reset(where, outerCursor); 105 } 106 public void checkCursor() throws SQLException { 107 if (bc == null) { 108 throw new SQLException ("Cursor closed"); 109 } 110 } 111 112 public long getCurrentRowId() throws SQLException { 113 checkCursor(); 114 return ByteUtil.getLong(bc.getValBuf(), 0); 115 } 116 117 public void fetchCurrentRow() throws SQLException , IOException { 118 session.getDatabase().getRow(rowId, row, false); 119 rowValid = true; 120 } 121 122 public IndexConstraint getConstraint() { 123 return constraint; 124 } 125 126 public void reset(Expression where, Cursor outer) 127 throws SQLException 128 { 129 try { 130 this.setOuterCursor(outer); 131 startVal = null; 132 stopVal = null; 133 if (indexNames != null && indexNames.size() > 0) { 134 startVals = makeValues(session, table, ValueNull.valueNull); 135 stopVals = makeValues(session, table, ValueNull.valueLastNull); 136 getCursorRange(session, where, startVals, stopVals); 137 startVal = constraint.makeKey(session, startVals.getRow(), 138 Long.MIN_VALUE); 139 stopVal = constraint.makeKey(session, stopVals.getRow(), 140 Long.MAX_VALUE); 141 } 144 145 this.row = new LazyRow(table.getColumnCount()); 146 bc = index.getCursor(false); 147 if (startVal != null) { 148 bc.seek(startVal); 149 } else { 150 bc.beforeFirst(); 151 } 152 } catch (IOException e) { 153 throw DbException.wrapThrowable(e); 154 } 155 } 156 157 161 StaticCursor makeValues(Session session, Table table, Value v) 162 throws SQLException 163 { 164 Row r = new Row(table.getColumnCount()); 165 for (int i = 1; i <= r.size(); i++) { 166 r.set(i, v); 167 } 168 StaticCursor s = new StaticCursor(session, table, r); 169 s.absolute(1); 170 return s; 171 } 172 173 static String isa(Object x) { 175 return x == null ? "null" : 176 x.getClass().getName() + ":" + x; 177 } 178 180 184 void getCursorRange(Session session, Expression e, 185 StaticCursor startVals, StaticCursor stopVals) 186 throws SQLException 187 { 188 if (e instanceof BinaryExpression) { 189 BinaryExpression b = (BinaryExpression)e; 190 switch (b.op) { 191 case Op.EQ: 192 if (b.e instanceof NameExpression) { 196 NameExpression ne = (NameExpression)b.e; 197 String name = session.getConnection().resolveColname(ne.getName(), table); 198 String tname = table.getName(); 199 if (name.startsWith(tname)) name = name.substring(tname.length() + 1); 200 if (startVals.get(name) != null) { 202 try { 203 Value v = b.f.getValue(session, outer); 204 startVals.put(name, v); 206 stopVals.put(name, v); 207 return; 208 } catch (SQLException se) {} 209 } 210 } 211 if (b.f instanceof NameExpression) { 212 NameExpression nf = (NameExpression)b.f; 213 String name = session.getConnection().resolveColname(nf.getName(), table); 214 if (startVals.get(name) != null) { 215 try { 216 Value v = b.e.getValue(session, outer); 217 startVals.put(name, v); 218 stopVals.put(name, v); 219 } catch (SQLException se) {} 220 } 221 } 222 break; 223 case Op.AND: 224 getCursorRange(session, b.e, startVals, stopVals); 225 getCursorRange(session, b.f, startVals, stopVals); 226 break; 227 case Op.LT: 228 case Op.LE: 229 doOneBound(session, b.e, b.f, startVals, stopVals); 230 break; 231 case Op.GT: 232 case Op.GE: 233 doOneBound(session, b.f, b.e, startVals, stopVals); 234 break; 235 } 236 } else if (e instanceof TernaryExpression) { 237 TernaryExpression t = (TernaryExpression)e; 238 if (t.op == Op.BETWEEN) { 239 if (!t.not) { 240 doOneBound(session, t.f, t.e, startVals, stopVals); 241 doOneBound(session, t.e, t.g, startVals, stopVals); 242 } 243 } 244 } 245 } 246 247 251 void doOneBound(Session session, Expression a, Expression b, 252 StaticCursor startVals, StaticCursor stopVals) 253 throws SQLException 254 { 255 if (a instanceof NameExpression) { 256 NameExpression na = (NameExpression)a; 257 String name = na.getName(); 258 Value s = (Value)stopVals.get(name); 259 if (s != null) { 260 Value v = b.getValue(session, null); Value cmp = Value.binop(Op.COMPARE, v, s); 262 ValueInteger vi = (ValueInteger)cmp; 263 int ret = vi.intValue(); 264 if (ret < 0) { 265 stopVals.put(name, v); 266 } 267 } 268 } else if (b instanceof NameExpression) { 269 NameExpression nb = (NameExpression)b; 270 String name = nb.getName(); 271 Value s = (Value)startVals.get(name); 272 if (s != null) { 273 Value v = a.getValue(session, null); Value cmp = Value.binop(Op.COMPARE, v, s); 275 ValueInteger vi = (ValueInteger)cmp; 276 int ret = vi.intValue(); 277 if (ret > 0) { 278 startVals.put(name, v); 279 } 280 } 281 } 282 } 283 284 287 public boolean next() throws SQLException { 288 boolean ret = super.next(); 289 if (ret) { 290 if (stopVal != null) { 291 if (compare.compare(bc.getKeyBuf(), 0, bc.getKeyLen(), 292 stopVal, 0, stopVal.length) > 0) { 293 ret = false; 294 } 295 } 296 } 297 return ret; 298 } 299 300 303 public boolean prev() throws SQLException { 304 boolean ret = super.prev(); 305 if (ret) { 306 if (startVal != null) { 307 if (compare.compare(bc.getKeyBuf(), 0, bc.getKeyLen(), 308 startVal, 0, startVal.length) < 0) { 309 ret = false; 310 } 311 } 312 } 313 return ret; 314 } 315 316 319 public void updateRow(Row row) throws SQLException { 320 try { 321 TableOps.updateRow(session, table, 322 bc.getKey(), rowId, 323 row, constraint); 324 } catch (IOException e) { 325 throw DbException.wrapThrowable(e); 326 } 327 } 328 329 332 public void insertRow(Row row) throws SQLException { 333 try { 334 TableOps.insertRow(session, table, row); 335 } catch (IOException e) { 336 throw DbException.wrapThrowable(e); 337 } 338 } 339 340 343 public void deleteRow() throws SQLException { 344 try { 345 TableOps.deleteRow(session, table, 346 rowId, getRow(), constraint); 347 } catch (IOException e) { 348 throw DbException.wrapThrowable(e); 349 } 350 } 351 352 355 public void beforeFirst() throws SQLException { 356 try { 357 rowValid = false; 358 rowId = 0; 359 checkCursor(); 360 if (startVal != null) bc.seek(startVal); 361 else bc.beforeFirst(); 362 } catch (IOException e) { 363 throw DbException.wrapThrowable(e); 364 } 365 } 366 367 370 public void afterLast() throws SQLException { 371 try { 372 rowValid = false; 373 rowId = 0; 374 checkCursor(); 375 if (stopVal != null) bc.seek(stopVal); 376 else bc.afterLast(); 377 } catch (IOException e) { 378 throw DbException.wrapThrowable(e); 379 } 380 } 381 382 389 392 public boolean isWritable(int col) { 393 return true; 394 } 395 396 400 public Table getTable() { return table; } 401 402 public String toString() { 404 try { 405 StringBuffer sb = 406 new StringBuffer (Table.strip(getClass().getName())); 407 sb.append(": "); 408 sb.append(constraint.getName()); 409 if (outer != null) { 410 sb.append(" (outer "); 411 sb.append(outer.toString()); sb.append(")"); 413 } 414 sb.append(" {"); 415 for (int i = 1; i <= getColumnCount(); i++) { 416 Column c = getColumn(i); 417 if (i > 1) sb.append(','); 418 sb.append(c.getName()); 419 } 420 sb.append('}'); 421 return sb.toString(); 422 } catch (Exception e) { 423 Debug.print(e); 424 return this.getClass().getName(); 425 } 426 } 427 } 429 | Popular Tags |