1 package com.quadcap.sql; 2 3 40 41 import java.io.ByteArrayOutputStream ; 42 import java.io.BufferedInputStream ; 43 import java.io.BufferedOutputStream ; 44 import java.io.Externalizable ; 45 import java.io.IOException ; 46 import java.io.InputStream ; 47 import java.io.ObjectInput ; 48 import java.io.ObjectOutput ; 49 import java.io.OutputStream ; 50 51 import java.util.BitSet ; 52 import java.util.Hashtable ; 53 import java.util.Vector ; 54 55 import java.sql.ResultSet ; 56 import java.sql.ResultSetMetaData ; 57 import java.sql.SQLException ; 58 59 import com.quadcap.sql.io.ObjectInputStream; 60 import com.quadcap.sql.io.ObjectOutputStream; 61 62 import com.quadcap.sql.index.Btree; 63 64 import com.quadcap.sql.file.BlockFile; 65 import com.quadcap.sql.file.ByteUtil; 66 import com.quadcap.sql.file.Datafile; 67 import com.quadcap.sql.file.Page; 68 import com.quadcap.sql.file.PageManager; 69 import com.quadcap.sql.file.RandomAccess; 70 import com.quadcap.sql.file.RandomAccessOutputStream; 71 import com.quadcap.sql.file.SubPageManager; 72 73 import com.quadcap.sql.types.Type; 74 import com.quadcap.sql.types.TypeBlob; 75 import com.quadcap.sql.types.TypeClob; 76 import com.quadcap.sql.types.Value; 77 78 import com.quadcap.util.ConfigNumber; 79 import com.quadcap.util.Debug; 80 import com.quadcap.util.Util; 81 82 83 88 public class Table extends TupleImpl implements Relation, Externalizable { 89 91 int modifiers = 0; 92 Constraint[] constraints = new Constraint[0]; 93 transient boolean underConstruction = false; 94 95 transient int hasBlobs = 0; 97 98 102 public static final int TEMPORARY = 1; 103 public static final int LOCAL = 2; 104 public static final int GLOBAL = 4; 105 public static final int STATEMENT_TEMP = 8; 106 107 110 long tableIdentity = 1; 111 112 115 public Table() {} 116 117 120 public Table(String tableName, int modifiers) { 121 super(tableName); 122 this.modifiers = modifiers; 123 } 124 125 129 public boolean isUnderConstruction() { return underConstruction; } 130 131 134 public void setUnderConstruction(boolean v) { underConstruction = v; } 135 136 139 public int getModifiers() { return modifiers; } 140 141 144 public boolean hasBlobs() throws SQLException { 145 if (hasBlobs == 0) { 146 hasBlobs = 2; 147 for (int i = 1; hasBlobs == 2 && i <= getColumnCount(); i++) { 148 Column c = getColumn(i); 149 Type t = c.getType(); 150 if (t instanceof TypeBlob || t instanceof TypeClob) { 151 hasBlobs = 1; 152 } 153 } 154 } 155 return hasBlobs == 1; 156 } 157 158 161 public void readExternal(ObjectInput in) 162 throws IOException , ClassNotFoundException 163 { 164 super.readExternal(in); 165 constraints = new Constraint[in.readInt()]; 166 for (int i = 0; i < constraints.length; i++) { 167 constraints[i] = (Constraint)in.readObject(); 168 try { 169 constraints[i].setTable(this); 170 } catch (SQLException ex) { 171 Debug.print(ex); 172 } 173 } 174 } 175 176 179 public void writeExternal(ObjectOutput out) throws IOException { 180 super.writeExternal(out); 181 out.writeInt(constraints.length); 182 for (int i = 0; i < constraints.length; i++) { 183 out.writeObject(constraints[i]); 184 } 185 } 186 187 191 public void addColumn(Column col) throws SQLException { 192 super.addColumn(col); 193 Vector v = col.getConstraints(); 194 if (v != null) { 195 for (int i = 0; i < v.size(); i++) { 196 Constraint c = (Constraint)v.elementAt(i); 197 c.setColumn(col); 198 } 199 } 200 } 201 202 205 final public Constraint getConstraint(int num) { 206 return constraints[num]; 207 } 208 209 212 final public int getNumConstraints() { 213 return constraints.length; 214 } 215 216 221 public Constraint getConstraint(String name) { 222 for (int i = 0; i < constraints.length; i++) { 223 Constraint c = constraints[i]; 224 if (c.getName().equals(name)) { 225 return c; 226 } 227 } 228 return null; 229 } 230 231 235 public UniqueConstraint getPrimaryKey() { 236 UniqueConstraint uc = null; 237 for (int i = 0; i < constraints.length; i++) { 238 Constraint c = constraints[i]; 239 if (c instanceof PrimaryKeyConstraint) { 240 return (PrimaryKeyConstraint)c; 241 } else if (uc == null && c instanceof UniqueConstraint) { 242 uc = (UniqueConstraint)c; 243 } 244 } 245 return uc; 246 } 247 248 252 public void nameConstraint(Constraint c) { 253 String name = c.getName(); 254 if (name == null) { 255 name = c.getClass().getName(); 256 int idx = name.lastIndexOf('.'); 257 if (idx > 0) name = name.substring(idx+1); 258 name += "_"; 259 name += Integer.toString(constraints.length); 260 c.setName(name); 261 } 262 } 263 264 267 public void addConstraint(Constraint c) throws SQLException { 268 Constraint[] nc = new Constraint[constraints.length + 1]; 269 boolean added = false; 270 for (int i = 0; i < constraints.length; i++) { 271 Constraint ci = constraints[i]; 272 if (added) { 273 nc[i+1] = ci; 274 } else { 275 if (c.getPriority() >= ci.getPriority()) { 276 nc[i] = ci; 277 } else { 278 nc[i] = c; 279 nc[i+1] = ci; 280 added = true; 281 } 282 } 283 } 284 if (!added) nc[constraints.length] = c; 285 nameConstraint(c); 286 constraints = nc; 287 c.setTable(this); 288 final int notnull = ResultSetMetaData.columnNoNulls; 289 if (c instanceof NotNullConstraint || 290 c instanceof PrimaryKeyConstraint) { 291 int[] cols = c.getColumns(); 292 for (int i = 0; i < cols.length; i++) { 293 getColumn(cols[i]).setNullable(notnull); 294 } 295 } 296 } 297 298 301 public void deleteConstraint(String name) 302 throws SQLException , IOException 303 { 304 int off = 0; 305 for (int i = 0; i < constraints.length; i++) { 306 if (constraints[i].getName().equals(name)) { 307 off++; 308 } else if (off > 0) { 309 constraints[i-off] = constraints[i]; 310 } 311 } 312 if (off > 0) { 313 Constraint[] nc = new Constraint[constraints.length - off]; 314 System.arraycopy(constraints, 0, nc, 0, nc.length); 315 constraints = nc; 316 } else { 317 throw new SQLException ("No constraint: " + name + " for table " + 318 getName(), "42000"); 319 } 320 } 321 322 326 public void deleteColumn(int c) throws SQLException , IOException { 327 super.deleteColumn(c); 328 resetColumnConstraints(); 329 } 330 331 335 public void resetColumnConstraints() throws SQLException { 336 final int num = getNumConstraints(); 337 for (int i = 0; i < num; i++) { 338 Constraint con = getConstraint(i); 339 con.resetColumns(); 340 } 341 } 342 343 346 public static final long putRow(Session session, Tuple t, Row row) 347 throws SQLException , IOException 348 { 349 return session.getDatabase().putRow(session, session.getFile(), t, row); 350 } 351 352 367 378 static final String strip(String s) { 379 int idx = s.lastIndexOf("."); 380 if (idx >= 0) s = s.substring(idx+1); 381 return s; 382 } 383 384 Row getRow(Database db, long rowId) throws IOException , SQLException { 385 LazyRow row = new LazyRow(getColumnCount()); 386 db.getRow(rowId, row, false); 387 return row; 388 } 389 390 393 public Cursor getCursor(Session session, Expression where, 394 String asName, Cursor outer) 395 throws SQLException 396 { 397 try { 398 session.getTableReadLock(getName()); 399 Hashtable t = getNames(where); 400 IndexConstraint con = getIndexForNames(session, t); 401 String qualName = asName; 402 if (qualName == null) qualName = getName(); 403 Cursor c = new IndexCursor(this, session, con, where, 404 qualName, outer); 405 return c; 406 } catch (IOException e) { 407 throw DbException.wrapThrowable(e); 408 } 409 } 410 411 public Cursor getCursor(Session session, Expression where, 412 String asName) 413 throws SQLException 414 { 415 return getCursor(session, where, asName, null); 416 } 417 418 public IndexCursor getCursor(Session session, IndexConstraint notMe) 419 throws SQLException 420 { 421 try { 422 session.getTableReadLock(getName()); 423 IndexConstraint con = getAnyIndexBut(session, notMe); 424 if (con == null) return null; 425 return new IndexCursor(this, session, con, null, getName(), null); 426 } catch (IOException e) { 427 throw DbException.wrapThrowable(e); 428 } 429 } 430 431 class GetNames implements ExpressionVisitor { 432 Hashtable t = new Hashtable (); 433 public void visit(Expression ex) { 434 String name = ex.getName(); 435 if (name != null) { 436 t.put(name, name); 437 } else { 438 ex.visitSubExpressions(this); 439 } 440 } 441 } 442 443 Hashtable getNames(Expression ex) { 444 GetNames get = new GetNames(); 445 if (ex != null) get.visit(ex); 446 return get.t; 447 } 448 449 final IndexConstraint getAnyIndex(Session session) 450 throws IOException , SQLException 451 { 452 return getIndexConstraint(session, null, null); 453 } 454 455 final IndexConstraint getIndexForNames(Session session, Hashtable names) 456 throws IOException , SQLException 457 { 458 return getIndexConstraint(session, names, null); 459 } 460 461 final IndexConstraint getAnyIndexBut(Session session, IndexConstraint notMe) 462 throws IOException , SQLException 463 { 464 return getIndexConstraint(session, null, notMe); 465 } 466 467 IndexConstraint getIndexConstraint(Session session, Hashtable names, 468 IndexConstraint notMe) 469 throws IOException , SQLException 470 { 471 UniqueConstraint wcon = null; 474 IndexConstraint icon = null; 476 UniqueConstraint ucon = null; 478 IndexConstraint acon = null; 480 481 String sc = ""; 482 String nm = getName(); 483 int idx = nextUnquotedPeriod(nm); 484 if (idx >= 0) { 485 sc = nm.substring(0, idx); 486 nm = nm.substring(idx+1); 487 } 488 489 for (int ci = 0; ci < constraints.length; ci++) { 490 Constraint con = constraints[ci]; 491 if (con == notMe) continue; 492 if (con instanceof IndexConstraint) { 493 acon = (IndexConstraint)con; 494 Vector cnames = con.getColumnNames(); 495 if (cnames == null) { 496 throw new SQLException ("Index constraint has no columns: "+ 499 con); 500 } 504 boolean matched = false; 505 if (names != null) { 506 matched = true; 507 for (int i = 0; matched && i < cnames.size(); i++) { 508 String cnam = cnames.get(i).toString(); 509 if (names.get(cnam) == null && 510 names.get(nm + "." + cnam) == null && 511 names.get(sc + "." + nm + "." + cnam) == null) { 512 matched = false; 513 } 514 } 515 } 516 if (matched) { 517 if (acon instanceof UniqueConstraint) { 518 wcon = (UniqueConstraint)acon; 519 } else { 520 icon = acon; 521 } 522 } else { 523 if (acon instanceof UniqueConstraint) { 524 ucon = (UniqueConstraint)acon; 525 } 526 } 527 } 528 } 529 530 if (wcon != null) return wcon; 531 if (icon != null) return icon; 532 if (ucon != null) return ucon; 533 if (acon != null) return acon; 534 535 if (notMe == null) { 537 throw new SQLException ("No index", "42000"); 538 } else { 539 return null; 540 } 541 } 542 543 UniqueConstraint getIndexForColumns(int[] cols) throws SQLException { 544 BitSet match = new BitSet (); 545 for (int i = 0; i < cols.length; i++) { 546 match.set(cols[i]); 547 } 548 for (int i = 0; i < constraints.length; i++) { 549 Constraint con = constraints[i]; 550 if (con instanceof UniqueConstraint) { 551 int[] tcols = con.getColumns(); 552 BitSet tmatch = new BitSet (); 553 for (int j = 0; j < tcols.length; j++) { 554 tmatch.set(tcols[j]); 555 } 556 if (match.equals(tmatch)) return (UniqueConstraint)con; 557 } 558 } 559 return null; 560 } 561 562 565 public String getType() { 566 if ((modifiers & TEMPORARY) != 0) { 567 if ((modifiers & GLOBAL) != 0) { 568 return "GLOBAL TEMPORARY"; 569 } 570 if ((modifiers & LOCAL) != 0) { 571 return "LOCAL TEMPORARY"; 572 } 573 } 574 return "TABLE"; 575 } 576 577 582 public boolean isUpdatable() { return true; } 583 584 588 public String toString() { 589 StringBuffer sb = new StringBuffer (super.toString()); 590 sb.append("Constraints:\n"); 591 for (int i = 0; i < constraints.length; i++) { 592 Constraint c = constraints[i]; 593 sb.append(" "); 594 sb.append(String.valueOf(c)); 595 sb.append("\n"); 596 } 597 return sb.toString(); 598 } 599 601 public void insertRow(Session session, Row row) 602 throws SQLException , IOException 603 { 604 TableOps.insertRow(session, this, row); 605 } 606 607 } 608 609 | Popular Tags |