1 24 25 package com.mckoi.database; 26 27 import com.mckoi.database.global.SQLTypes; 28 import com.mckoi.util.IntegerVector; 29 import com.mckoi.debug.*; 30 import java.math.BigDecimal ; 31 import java.util.Vector ; 32 import java.util.ArrayList ; 33 import java.io.IOException ; 34 import java.io.OutputStream ; 35 import java.io.InputStream ; 36 import java.io.File ; 37 38 46 47 public final class DataTable extends DefaultDataTable { 48 49 52 private DatabaseConnection connection; 53 54 57 private MutableTableDataSource data_source; 58 59 60 68 69 final static boolean LOCK_DEBUG = true; 70 71 74 private int debug_read_lock_count = 0; 75 76 80 private int debug_write_lock_count = 0; 81 82 83 84 85 86 89 DataTable(DatabaseConnection connection, 90 MutableTableDataSource data_source) throws DatabaseException { 91 super(connection.getDatabase()); 92 this.connection = connection; 93 this.data_source = data_source; 94 } 95 96 99 public final DebugLogger Debug() { 100 return connection.getSystem().Debug(); 101 } 102 103 107 protected void blankSelectableSchemes(int type) { 108 } 109 110 117 protected SelectableScheme getRootColumnScheme(int column) { 118 checkReadLock(); 120 return data_source.getColumnScheme(column); 121 } 122 123 128 public ReferenceTable declareAs(TableName new_name) { 129 return new ReferenceTable(this, new_name); 130 } 131 132 137 public final RowData createRowDataObject(QueryContext context) { 138 checkSafeOperation(); return new RowData(this); 140 } 141 142 146 public int getRowCount() { 147 checkReadLock(); 149 return data_source.getRowCount(); 150 } 151 152 168 public final void add(RowData row_data) throws DatabaseException { 169 checkReadWriteLock(); 171 if (!row_data.isSameTable(this)) { 172 throw new DatabaseException( 173 "Internal Error: Using RowData from different table"); 174 } 175 176 addRow(row_data); 178 179 data_source.constraintIntegrityCheck(); 181 } 182 183 199 public final void add(RowData[] row_data_arr) throws DatabaseException { 200 checkReadWriteLock(); 202 for (int i = 0; i < row_data_arr.length; ++i) { 203 RowData row_data = row_data_arr[i]; 204 if (!row_data.isSameTable(this)) { 205 throw new DatabaseException( 206 "Internal Error: Using RowData from different table"); 207 } 208 addRow(row_data); 209 } 210 211 data_source.constraintIntegrityCheck(); 213 } 214 215 220 private void addRow(RowData row) throws DatabaseException { 221 222 TableName table_name = getTableName(); 224 225 connection.fireTableEvent(new TableModificationEvent(connection, table_name, 227 row, true)); 228 229 int row_number = data_source.addRow(row); 231 232 connection.fireTableEvent(new TableModificationEvent(connection, table_name, 234 row, false)); 235 236 239 } 240 241 247 private void removeRow(int row_number) throws DatabaseException { 248 249 TableName table_name = getTableName(); 251 252 connection.fireTableEvent(new TableModificationEvent(connection, table_name, 254 row_number, true)); 255 256 data_source.removeRow(row_number); 258 259 connection.fireTableEvent(new TableModificationEvent(connection, table_name, 261 row_number, false)); 262 263 } 264 265 270 private void updateRow(int row_number, RowData row) 271 throws DatabaseException { 272 273 TableName table_name = getTableName(); 275 276 connection.fireTableEvent( 278 new TableModificationEvent(connection, table_name, 279 row_number, row, true)); 280 281 data_source.updateRow(row_number, row); 283 284 connection.fireTableEvent( 286 new TableModificationEvent(connection, table_name, 287 row_number, row, false)); 288 289 } 290 291 313 public int delete(Table table, int limit) throws DatabaseException { 314 checkReadWriteLock(); 316 IntegerVector row_set = new IntegerVector(table.getRowCount()); 317 RowEnumeration e = table.rowEnumeration(); 318 while (e.hasMoreRows()) { 319 row_set.addInt(e.nextRowIndex()); 320 } 321 e = null; 322 323 int first_column = table.findFieldName(getResolvedVariable(0)); 327 328 if (first_column == -1) { 329 throw new DatabaseException("Search table does not contain any " + 330 "reference to table being deleted from"); 331 } 332 333 table.setToRowTableDomain(first_column, row_set, this); 335 336 row_set.quickSort(); 339 340 if (limit < 0) { 342 limit = Integer.MAX_VALUE; 343 } 344 345 int len = Math.min(row_set.size(), limit); 348 int last_removed = -1; 349 int remove_count = 0; 350 for (int i = 0; i < len; ++i) { 351 int to_remove = row_set.intAt(i); 352 if (to_remove < last_removed) { 353 throw new DatabaseException( 354 "Internal error: row sorting error or row_set not in the range > 0"); 355 } 356 357 if (to_remove != last_removed) { 358 removeRow(to_remove); 359 last_removed = to_remove; 360 ++remove_count; 361 } 362 363 } 364 365 if (remove_count > 0) { 366 data_source.constraintIntegrityCheck(); 368 } 369 370 return remove_count; 371 } 372 373 public int delete(Table table) throws DatabaseException { 375 return delete(table, -1); 376 } 377 378 399 public final int update(QueryContext context, 400 Table table, Assignment[] assign_list, int limit) 401 throws DatabaseException { 402 checkReadWriteLock(); 404 IntegerVector row_set = new IntegerVector(); 406 RowEnumeration e = table.rowEnumeration(); 407 while (e.hasMoreRows()) { 408 row_set.addInt(e.nextRowIndex()); 409 } 410 e = null; 411 412 int first_column = table.findFieldName(getResolvedVariable(0)); 416 if (first_column == -1) { 417 throw new DatabaseException("Search table does not contain any " + 418 "reference to table being updated from"); 419 } 420 421 table.setToRowTableDomain(first_column, row_set, this); 423 424 426 RowData original_data = createRowDataObject(context); 427 RowData row_data = createRowDataObject(context); 428 429 if (limit < 0) { 431 limit = Integer.MAX_VALUE; 432 } 433 434 int len = Math.min(row_set.size(), limit); 436 int update_count = 0; 437 for (int i = 0; i < len; ++i) { 438 int to_update = row_set.intAt(i); 439 440 original_data.setFromRow(to_update); 443 row_data.setFromRow(to_update); 444 445 for (int n = 0; n < assign_list.length; ++n) { 447 Assignment assignment = assign_list[n]; 448 row_data.evaluate(assignment, context); 449 } 450 451 updateRow(to_update, row_data); 453 454 ++update_count; 455 } 456 457 if (update_count > 0) { 458 data_source.constraintIntegrityCheck(); 460 } 461 462 return update_count; 463 464 } 465 466 473 public DataTableDef getDataTableDef() { 474 checkSafeOperation(); 476 return data_source.getDataTableDef(); 477 } 478 479 482 public String getSchema() { 483 checkSafeOperation(); 485 return getDataTableDef().getSchema(); 486 } 487 488 498 public void addDataTableListener(DataTableListener listener) { 499 } 501 502 508 public void removeDataTableListener(DataTableListener listener) { 509 } 511 512 513 514 515 517 524 void setToRowTableDomain(int column, IntegerVector row_set, 525 TableDataSource ancestor) { 526 checkReadLock(); 528 if (ancestor != this && ancestor != data_source) { 529 throw new RuntimeException ("Method routed to incorrect table ancestor."); 530 } 531 } 532 533 538 public TObject getCellContents(int column, int row) { 539 checkSafeOperation(); 541 return data_source.getCellContents(column, row); 542 } 543 544 548 public RowEnumeration rowEnumeration() { 549 checkReadLock(); 551 return data_source.rowEnumeration(); 552 } 553 554 555 564 public void lockRoot(int lock_key) { 565 checkSafeOperation(); 567 data_source.addRootLock(); 568 } 569 570 575 public void unlockRoot(int lock_key) { 576 checkSafeOperation(); 578 data_source.removeRootLock(); 579 } 580 581 585 public boolean hasRootsLocked() { 586 throw new Error ("hasRootsLocked is deprecated."); 590 } 591 592 593 594 595 596 598 603 final void notifyAddRWLock(int lock_type) { 604 if (LOCK_DEBUG) { 605 if (lock_type == Lock.READ) { 606 ++debug_read_lock_count; 607 } 608 else if (lock_type == Lock.WRITE) { 609 ++debug_write_lock_count; 610 if (debug_write_lock_count > 1) { 611 throw new Error (">1 write lock on table " + getTableName()); 612 } 613 } 614 else { 615 throw new Error ("Unknown lock type: " + lock_type); 616 } 617 } 618 } 619 620 625 final void notifyReleaseRWLock(int lock_type) { 626 if (LOCK_DEBUG) { 627 if (lock_type == Lock.READ) { 628 --debug_read_lock_count; 629 } 630 else if (lock_type == Lock.WRITE) { 631 --debug_write_lock_count; 632 } 633 else { 634 Debug().writeException( 635 new RuntimeException ("Unknown lock type: " + lock_type)); 636 } 637 } 638 } 639 640 643 private boolean isInExclusiveMode() { 644 return connection.getLockingMechanism().isInExclusiveMode(); 646 } 647 648 651 private void checkInExclusiveMode() { 652 if (!isInExclusiveMode()) { 653 Debug().writeException(new RuntimeException ( 654 "Performed exclusive operation on table and not in exclusive mode!")); 655 } 656 } 657 658 661 private void checkReadLock() { 662 if (LOCK_DEBUG) { 663 666 boolean is_internal_table = 667 getTableName().getSchema().equals(Database.SYSTEM_SCHEMA); 668 669 if (!(is_internal_table || 670 debug_read_lock_count > 0 || 671 debug_write_lock_count > 0 || 672 isInExclusiveMode())) { 673 674 System.err.println(); 675 System.err.print(" is_internal_table = " + is_internal_table); 676 System.err.print(" debug_read_lock_count = " + debug_read_lock_count); 677 System.err.print(" debug_write_lock_count = " + debug_write_lock_count); 678 System.err.println(" isInExclusiveMode = " + isInExclusiveMode()); 679 680 Debug().writeException(new Error ( 681 "Invalid read access on table '" + getTableName() + "'")); 682 } 683 } 684 } 685 686 690 private void checkReadWriteLock() { 691 if (LOCK_DEBUG) { 692 if (!(debug_write_lock_count == 1 || isInExclusiveMode())) { 694 Debug().writeException( 695 new Error ("Invalid read/write access on table '" + 696 getTableName() + "'")); 697 } 698 } 699 } 700 701 704 private void checkSafeOperation() { 705 } 707 708 709 710 713 public int getColumnCount() { 714 checkSafeOperation(); 716 return super.getColumnCount(); 717 } 718 719 public Variable getResolvedVariable(int column) { 720 checkSafeOperation(); 722 return super.getResolvedVariable(column); 723 } 724 725 public int findFieldName(Variable v) { 726 checkSafeOperation(); 728 return super.findFieldName(v); 729 } 730 731 SelectableScheme getSelectableSchemeFor(int column, int original_column, 732 Table table) { 733 checkReadLock(); 735 return super.getSelectableSchemeFor(column, original_column, table); 736 } 737 738 RawTableInformation resolveToRawTable(RawTableInformation info) { 739 checkReadLock(); 741 return super.resolveToRawTable(info); 742 } 743 744 } 745 | Popular Tags |