1 24 25 package com.mckoi.database; 26 27 import com.mckoi.debug.*; 28 import com.mckoi.util.IntegerVector; 29 import com.mckoi.util.BigNumber; 30 import com.mckoi.database.global.ByteLongObject; 31 import com.mckoi.database.global.ObjectTranslator; 32 import java.io.IOException ; 33 import java.util.ArrayList ; 34 import java.util.HashMap ; 35 36 50 51 public class Transaction extends SimpleTransaction { 52 53 56 59 public static final short INITIALLY_DEFERRED = 60 java.sql.DatabaseMetaData.importedKeyInitiallyDeferred; 61 public static final short INITIALLY_IMMEDIATE = 62 java.sql.DatabaseMetaData.importedKeyInitiallyImmediate; 63 public static final short NOT_DEFERRABLE = 64 java.sql.DatabaseMetaData.importedKeyNotDeferrable; 65 66 69 public static final String NO_ACTION = "NO ACTION"; 70 public static final String CASCADE = "CASCADE"; 71 public static final String SET_NULL = "SET NULL"; 72 public static final String SET_DEFAULT = "SET DEFAULT"; 73 74 76 79 private TableDataConglomerate conglomerate; 80 81 85 private long commit_id; 86 87 90 private ArrayList touched_tables; 91 92 95 private ArrayList selected_from_tables; 96 97 101 private ArrayList created_database_objects; 102 103 107 private ArrayList dropped_database_objects; 108 109 113 private TransactionJournal journal; 114 115 119 private InternalTableInfo[] internal_tables; 120 121 124 private int internal_tables_i; 125 126 129 private boolean transaction_error_on_dirty_select; 130 131 134 private boolean closed; 135 136 137 140 Transaction(TableDataConglomerate conglomerate, 141 long commit_id, ArrayList visible_tables, 142 ArrayList table_indices) { 143 144 super(conglomerate.getSystem(), conglomerate.getSequenceManager()); 145 146 this.conglomerate = conglomerate; 147 this.commit_id = commit_id; 148 this.closed = false; 149 150 this.created_database_objects = new ArrayList (); 151 this.dropped_database_objects = new ArrayList (); 152 153 this.touched_tables = new ArrayList (); 154 this.selected_from_tables = new ArrayList (); 155 journal = new TransactionJournal(); 156 157 int sz = visible_tables.size(); 159 for (int i = 0; i < sz; ++i) { 160 addVisibleTable((MasterTableDataSource) visible_tables.get(i), 161 (IndexSet) table_indices.get(i)); 162 } 163 164 internal_tables = new InternalTableInfo[8]; 167 internal_tables_i = 0; 168 addInternalTableInfo(new TransactionInternalTables()); 169 170 getSystem().stats().increment("Transaction.count"); 171 172 transaction_error_on_dirty_select = true; 175 } 176 177 180 final TableDataConglomerate getConglomerate() { 181 return conglomerate; 182 } 183 184 191 void addInternalTableInfo(InternalTableInfo info) { 192 if (internal_tables_i >= internal_tables.length) { 193 throw new RuntimeException ("Internal table list bounds reached."); 194 } 195 internal_tables[internal_tables_i] = info; 196 ++internal_tables_i; 197 } 198 199 206 long getCommitID() { 207 return commit_id; 210 } 211 212 214 220 public MutableTableDataSource 221 createMutableTableDataSourceAtCommit(MasterTableDataSource master) { 222 MutableTableDataSource table = master.createTableDataSourceAtCommit(this); 224 journal.entryAddTouchedTable(master.getTableID()); 226 touched_tables.add(table); 227 return table; 228 } 229 230 238 public void addSelectedFromTable(TableName table_name) { 239 if (isDynamicTable(table_name)) { 241 return; 242 } 243 244 MasterTableDataSource master = findVisibleTable(table_name, false); 245 if (master == null) { 246 throw new StatementException( 247 "Table with name not available: " + table_name); 248 } 249 synchronized (selected_from_tables) { 251 if (!selected_from_tables.contains(master)) { 252 selected_from_tables.add(master); 253 } 254 } 255 256 } 257 258 259 260 267 void liveCopyAllDataTo(TableDataConglomerate dest_conglomerate) { 268 int sz = getVisibleTableCount(); 271 272 ArrayList copy_list = new ArrayList (sz); 275 276 MasterTableDataSource last_entry = null; 277 for (int i = 0; i < sz; ++i) { 278 MasterTableDataSource master_table = getVisibleTable(i); 279 TableName table_name = master_table.getDataTableDef().getTableName(); 280 if (table_name.equals(TableDataConglomerate.SYS_SEQUENCE_INFO)) { 281 last_entry = master_table; 282 } 283 else { 284 copy_list.add(master_table); 285 } 286 } 287 copy_list.add(0, last_entry); 288 289 try { 290 for (int i = 0; i < sz; ++i) { 292 293 MasterTableDataSource master_table = 294 (MasterTableDataSource) copy_list.get(i); 295 TableName table_name = master_table.getDataTableDef().getTableName(); 296 297 Transaction dest_transaction = dest_conglomerate.createTransaction(); 299 300 IndexSet index_set = getIndexSetForTable(master_table); 302 303 if (dest_transaction.tableExists(table_name)) { 305 dest_transaction.dropTable(table_name); 306 } 307 308 dest_transaction.copyTable(master_table, index_set); 310 311 dest_transaction.closeAndCommit(); 313 314 index_set.dispose(); 316 317 } 318 319 } 320 catch (TransactionException e) { 321 Debug().writeException(e); 322 throw new RuntimeException ("Transaction Error when copying table: " + 323 e.getMessage()); 324 } 325 } 326 327 329 333 protected boolean isDynamicTable(TableName table_name) { 334 for (int i = 0; i < internal_tables.length; ++i) { 335 InternalTableInfo info = internal_tables[i]; 336 if (info != null) { 337 if (info.containsTableName(table_name)) { 338 return true; 339 } 340 } 341 } 342 return false; 343 } 344 345 350 protected TableName[] getDynamicTableList() { 351 int sz = 0; 352 for (int i = 0; i < internal_tables.length; ++i) { 353 InternalTableInfo info = internal_tables[i]; 354 if (info != null) { 355 sz += info.getTableCount(); 356 } 357 } 358 359 TableName[] list = new TableName[sz]; 360 int index = 0; 361 362 for (int i = 0; i < internal_tables.length; ++i) { 363 InternalTableInfo info = internal_tables[i]; 364 if (info != null) { 365 sz = info.getTableCount(); 366 for (int n = 0; n < sz; ++n) { 367 list[index] = info.getTableName(n); 368 ++index; 369 } 370 } 371 } 372 373 return list; 374 } 375 376 379 protected DataTableDef getDynamicDataTableDef(TableName table_name) { 380 381 for (int i = 0; i < internal_tables.length; ++i) { 382 InternalTableInfo info = internal_tables[i]; 383 if (info != null) { 384 int index = info.findTableName(table_name); 385 if (index != -1) { 386 return info.getDataTableDef(index); 387 } 388 } 389 } 390 391 throw new RuntimeException ("Not an internal table: " + table_name); 392 } 393 394 398 protected MutableTableDataSource getDynamicTable(TableName table_name) { 399 400 for (int i = 0; i < internal_tables.length; ++i) { 401 InternalTableInfo info = internal_tables[i]; 402 if (info != null) { 403 int index = info.findTableName(table_name); 404 if (index != -1) { 405 return info.createInternalTable(index); 406 } 407 } 408 } 409 410 throw new RuntimeException ("Not an internal table: " + table_name); 411 } 412 413 416 public String getDynamicTableType(TableName table_name) { 417 for (int i = 0; i < internal_tables.length; ++i) { 419 InternalTableInfo info = internal_tables[i]; 420 if (info != null) { 421 int index = info.findTableName(table_name); 422 if (index != -1) { 423 return info.getTableType(index); 424 } 425 } 426 } 427 throw new RuntimeException ("No table '" + table_name + 429 "' to report type for."); 430 } 431 432 433 435 441 public void createTable(DataTableDef table_def, 442 int data_sector_size, int index_sector_size) { 443 444 TableName table_name = table_def.getTableName(); 445 MasterTableDataSource master = findVisibleTable(table_name, false); 446 if (master != null) { 447 throw new StatementException( 448 "Table '" + table_name + "' already exists."); 449 } 450 451 table_def.setImmutable(); 452 453 if (data_sector_size < 27) { 454 data_sector_size = 27; 455 } 456 else if (data_sector_size > 4096) { 457 data_sector_size = 4096; 458 } 459 460 master = conglomerate.createMasterTable(table_def, data_sector_size, 462 index_sector_size); 463 addVisibleTable(master, master.createIndexSet()); 465 466 int table_id = master.getTableID(); 468 journal.entryAddTouchedTable(table_id); 469 470 journal.entryTableCreate(table_id); 472 473 SequenceManager.addNativeTableGenerator(this, table_name); 476 477 databaseObjectCreated(table_name); 479 480 } 481 482 488 public void createTable(DataTableDef table_def) { 489 createTable(table_def, 251, 1024); 492 } 493 494 503 public void alterCreateTable(DataTableDef table_def, 504 int data_sector_size, int index_sector_size) { 505 if (!tableExists(table_def.getTableName())) { 506 createTable(table_def, data_sector_size, index_sector_size); 507 } 508 else { 509 alterTable(table_def.getTableName(), table_def, 510 data_sector_size, index_sector_size); 511 } 512 } 513 514 520 public void dropTable(TableName table_name) { 521 MasterTableDataSource master = findVisibleTable(table_name, false); 523 524 if (master == null) { 525 throw new StatementException( 526 "Table '" + table_name + "' doesn't exist."); 527 } 528 529 removeVisibleTable(master); 531 532 int table_id = master.getTableID(); 534 journal.entryAddTouchedTable(table_id); 535 536 journal.entryTableDrop(table_id); 538 539 SequenceManager.removeNativeTableGenerator(this, table_name); 542 543 databaseObjectDropped(table_name); 545 546 } 547 548 561 public void copyTable( 562 MasterTableDataSource src_master_table, IndexSet index_set) { 563 564 DataTableDef table_def = src_master_table.getDataTableDef(); 565 TableName table_name = table_def.getTableName(); 566 MasterTableDataSource master = findVisibleTable(table_name, false); 567 if (master != null) { 568 throw new StatementException( 569 "Unable to copy. Table '" + table_name + "' already exists."); 570 } 571 572 master = conglomerate.copyMasterTable(src_master_table, index_set); 574 addVisibleTable(master, master.createIndexSet()); 576 577 int table_id = master.getTableID(); 579 journal.entryAddTouchedTable(table_id); 580 581 journal.entryTableCreate(table_id); 583 584 SequenceManager.addNativeTableGenerator(this, table_name); 587 588 databaseObjectCreated(table_name); 590 591 } 592 593 604 public void alterTable(TableName table_name, DataTableDef table_def, 605 int data_sector_size, int index_sector_size) { 606 607 table_def.setImmutable(); 608 609 String current_schema = table_name.getSchema(); 611 SystemQueryContext context = new SystemQueryContext(this, current_schema); 612 613 long next_id = nextUniqueID(table_name); 615 616 MutableTableDataSource c_table = getTable(table_name); 618 dropTable(table_name); 619 createTable(table_def); 621 MutableTableDataSource altered_table = getTable(table_name); 622 623 MasterTableDataSource new_master_table = 625 findVisibleTable(table_name, false); 626 new_master_table.setUniqueID(next_id); 628 629 int[] col_map = new int[table_def.columnCount()]; 631 DataTableDef orig_td = c_table.getDataTableDef(); 632 for (int i = 0; i < col_map.length; ++i) { 633 String col_name = table_def.columnAt(i).getName(); 634 col_map[i] = orig_td.findColumnName(col_name); 635 } 636 637 try { 638 try { 641 RowEnumeration e = c_table.rowEnumeration(); 642 while (e.hasMoreRows()) { 643 int row_index = e.nextRowIndex(); 644 RowData row_data = new RowData(altered_table); 645 for (int i = 0; i < col_map.length; ++i) { 646 int col = col_map[i]; 647 if (col != -1) { 648 row_data.setColumnData(i, 649 c_table.getCellContents(col, row_index)); 650 } 651 } 652 row_data.setDefaultForRest(context); 653 int new_row_number = new_master_table.addRow(row_data); 657 new_master_table.writeRecordType(new_row_number, 0x010); 659 } 660 } 661 catch (DatabaseException e) { 662 Debug().writeException(e); 663 throw new RuntimeException (e.getMessage()); 664 } 665 666 669 new_master_table.buildIndexes(); 671 672 setIndexSetForTable(new_master_table, new_master_table.createIndexSet()); 674 675 flushTableCache(table_name); 677 678 SequenceManager.removeNativeTableGenerator(this, table_name); 680 SequenceManager.addNativeTableGenerator(this, table_name); 681 682 databaseObjectDropped(table_name); 685 databaseObjectCreated(table_name); 686 687 } 688 catch (IOException e) { 689 Debug().writeException(e); 690 throw new RuntimeException (e.getMessage()); 691 } 692 693 } 694 695 702 public void alterTable(TableName table_name, DataTableDef table_def) { 703 704 try { 707 708 int current_data_sector_size; 709 MasterTableDataSource master = findVisibleTable(table_name, false); 710 if (master instanceof V1MasterTableDataSource) { 711 current_data_sector_size = 712 ((V1MasterTableDataSource) master).rawDataSectorSize(); 713 } 714 else { 715 current_data_sector_size = -1; 716 } 717 alterTable(table_name, table_def, current_data_sector_size, 2043); 719 720 } 721 catch (IOException e) { 722 throw new RuntimeException ("IO Error: " + e.getMessage()); 723 } 724 725 } 726 727 728 729 730 731 739 public void checkAllConstraints(TableName table_name) { 740 TableDataSource table = getTable(table_name); 742 int[] rows = new int[table.getRowCount()]; 744 RowEnumeration row_enum = table.rowEnumeration(); 745 int i = 0; 746 while (row_enum.hasMoreRows()) { 747 rows[i] = row_enum.nextRowIndex(); 748 ++i; 749 } 750 TableDataConglomerate.checkAddConstraintViolations( 752 this, table, rows, INITIALLY_IMMEDIATE); 753 754 MasterTableDataSource master = findVisibleTable(table_name, false); 756 if (master == null) { 757 throw new StatementException( 758 "Table '" + table_name + "' doesn't exist."); 759 } 760 761 int table_id = master.getTableID(); 763 764 journal.entryAddTouchedTable(table_id); 765 journal.entryTableConstraintAlter(table_id); 767 768 } 769 770 774 public void compactTable(TableName table_name) { 775 776 MasterTableDataSource current_table = findVisibleTable(table_name, false); 778 if (current_table == null) { 779 throw new StatementException( 780 "Table '" + table_name + "' doesn't exist."); 781 } 782 783 if (current_table.isWorthCompacting()) { 786 IndexSet index_set = getIndexSetForTable(current_table); 788 dropTable(table_name); 790 copyTable(current_table, index_set); 792 } 793 794 } 795 796 797 798 809 boolean transactionErrorOnDirtySelect() { 810 return transaction_error_on_dirty_select; 811 } 812 813 816 void setErrorOnDirtySelect(boolean status) { 817 transaction_error_on_dirty_select = status; 818 } 819 820 834 844 private static String [] toColumns(SimpleTableQuery dt, IntegerVector cols) { 845 int size = cols.size(); 846 String [] list = new String [size]; 847 848 for (int n = 0; n < size; ++n) { 850 for (int i = 0; i < size; ++i) { 852 int row_index = cols.intAt(i); 853 int seq_no = ((BigNumber) dt.get(2, row_index).getObject()).intValue(); 854 if (seq_no == n) { 855 list[n] = dt.get(1, row_index).getObject().toString(); 856 break; 857 } 858 } 859 } 860 861 return list; 862 } 863 864 869 private static String makeUniqueConstraintName(String name, 870 BigNumber unique_id) { 871 if (name == null) { 872 name = "_ANONYMOUS_CONSTRAINT_" + unique_id.toString(); 873 } 874 return name; 875 } 876 877 878 882 void databaseObjectCreated(TableName table_name) { 883 boolean dropped = dropped_database_objects.remove(table_name); 885 if (!dropped) { 888 created_database_objects.add(table_name); 889 } 890 } 891 892 896 void databaseObjectDropped(TableName table_name) { 897 boolean created = created_database_objects.remove(table_name); 899 if (!created) { 902 dropped_database_objects.add(table_name); 903 } 904 } 905 906 910 ArrayList getAllNamesCreated() { 911 return created_database_objects; 912 } 913 914 918 ArrayList getAllNamesDropped() { 919 return dropped_database_objects; 920 } 921 922 923 931 public void createSchema(String name, String type) { 932 TableName table_name = TableDataConglomerate.SCHEMA_INFO_TABLE; 933 MutableTableDataSource t = getTable(table_name); 934 SimpleTableQuery dt = new SimpleTableQuery(t); 935 936 try { 937 if (!dt.existsSingle(1, name)) { 940 RowData rd = new RowData(t); 942 BigNumber unique_id = BigNumber.fromLong(nextUniqueID(table_name)); 943 rd.setColumnDataFromObject(0, unique_id); 944 rd.setColumnDataFromObject(1, name); 945 rd.setColumnDataFromObject(2, type); 946 t.addRow(rd); 948 } 949 else { 950 throw new StatementException("Schema already exists: " + name); 951 } 952 } 953 finally { 954 dt.dispose(); 955 } 956 } 957 958 966 public void dropSchema(String name) { 967 TableName table_name = TableDataConglomerate.SCHEMA_INFO_TABLE; 968 MutableTableDataSource t = getTable(table_name); 969 SimpleTableQuery dt = new SimpleTableQuery(t); 970 971 boolean b = dt.deleteSingle(1, name); 973 dt.dispose(); 974 if (!b) { 975 throw new StatementException("Schema doesn't exists: " + name); 976 } 977 } 978 979 982 public boolean schemaExists(String name) { 983 TableName table_name = TableDataConglomerate.SCHEMA_INFO_TABLE; 984 MutableTableDataSource t = getTable(table_name); 985 SimpleTableQuery dt = new SimpleTableQuery(t); 986 987 boolean b = dt.existsSingle(1, name); 989 dt.dispose(); 990 return b; 991 } 992 993 999 public SchemaDef resolveSchemaCase(String name, boolean ignore_case) { 1000 SimpleTableQuery dt = new SimpleTableQuery( 1002 getTable(TableDataConglomerate.SCHEMA_INFO_TABLE)); 1003 1004 try { 1005 RowEnumeration e = dt.rowEnumeration(); 1006 if (ignore_case) { 1007 SchemaDef result = null; 1008 while (e.hasMoreRows()) { 1009 int row_index = e.nextRowIndex(); 1010 String cur_name = dt.get(1, row_index).getObject().toString(); 1011 if (name.equalsIgnoreCase(cur_name)) { 1012 if (result != null) { 1013 throw new StatementException( 1014 "Ambiguous schema name: '" + name + "'"); 1015 } 1016 String type = dt.get(2, row_index).getObject().toString(); 1017 result = new SchemaDef(cur_name, type); 1018 } 1019 } 1020 return result; 1021 1022 } 1023 else { while (e.hasMoreRows()) { 1025 int row_index = e.nextRowIndex(); 1026 String cur_name = dt.get(1, row_index).getObject().toString(); 1027 if (name.equals(cur_name)) { 1028 String type = dt.get(2, row_index).getObject().toString(); 1029 return new SchemaDef(cur_name, type); 1030 } 1031 } 1032 return null; 1034 } 1035 } 1036 1037 finally { 1038 dt.dispose(); 1039 } 1040 1041 } 1042 1043 1047 public SchemaDef[] getSchemaList() { 1048 SimpleTableQuery dt = new SimpleTableQuery( 1050 getTable(TableDataConglomerate.SCHEMA_INFO_TABLE)); 1051 RowEnumeration e = dt.rowEnumeration(); 1052 SchemaDef[] arr = new SchemaDef[dt.getRowCount()]; 1053 int i = 0; 1054 1055 while (e.hasMoreRows()) { 1056 int row_index = e.nextRowIndex(); 1057 String cur_name = dt.get(1, row_index).getObject().toString(); 1058 String cur_type = dt.get(2, row_index).getObject().toString(); 1059 arr[i] = new SchemaDef(cur_name, cur_type); 1060 ++i; 1061 } 1062 1063 dt.dispose(); 1064 return arr; 1065 } 1066 1067 1068 1075 public void setPersistentVar(String variable, String value) { 1076 TableName table_name = TableDataConglomerate.PERSISTENT_VAR_TABLE; 1077 MutableTableDataSource t = getTable(table_name); 1078 SimpleTableQuery dt = new SimpleTableQuery(t); 1079 dt.setVar(0, new Object [] { variable, value }); 1080 dt.dispose(); 1081 } 1082 1083 1087 public String getPersistantVar(String variable) { 1088 TableName table_name = TableDataConglomerate.PERSISTENT_VAR_TABLE; 1089 MutableTableDataSource t = getTable(table_name); 1090 SimpleTableQuery dt = new SimpleTableQuery(t); 1091 String val = dt.getVar(1, 0, variable).toString(); 1092 dt.dispose(); 1093 return val; 1094 } 1095 1096 1101 public void createSequenceGenerator( 1102 TableName name, long start_value, long increment_by, 1103 long min_value, long max_value, long cache, boolean cycle) { 1104 SequenceManager.createSequenceGenerator(this, 1105 name, start_value, increment_by, min_value, max_value, cache, 1106 cycle); 1107 1108 databaseObjectCreated(name); 1110 } 1111 1112 1115 public void dropSequenceGenerator(TableName name) { 1116 SequenceManager.dropSequenceGenerator(this, name); 1117 flushSequenceManager(name); 1119 1120 databaseObjectDropped(name); 1122 } 1123 1124 1135 public void addUniqueConstraint(TableName table_name, 1136 String [] cols, short deferred, String constraint_name) { 1137 1138 TableName tn1 = TableDataConglomerate.UNIQUE_INFO_TABLE; 1139 TableName tn2 = TableDataConglomerate.UNIQUE_COLS_TABLE; 1140 MutableTableDataSource t = getTable(tn1); 1141 MutableTableDataSource tcols = getTable(tn2); 1142 1143 try { 1144 1145 RowData rd = new RowData(t); 1147 BigNumber unique_id = BigNumber.fromLong(nextUniqueID(tn1)); 1148 constraint_name = makeUniqueConstraintName(constraint_name, unique_id); 1149 rd.setColumnDataFromObject(0, unique_id); 1150 rd.setColumnDataFromObject(1, constraint_name); 1151 rd.setColumnDataFromObject(2, table_name.getSchema()); 1152 rd.setColumnDataFromObject(3, table_name.getName()); 1153 rd.setColumnDataFromObject(4, BigNumber.fromInt(deferred)); 1154 t.addRow(rd); 1155 1156 for (int i = 0; i < cols.length; ++i) { 1158 rd = new RowData(tcols); 1159 rd.setColumnDataFromObject(0, unique_id); rd.setColumnDataFromObject(1, cols[i]); rd.setColumnDataFromObject(2, BigNumber.fromInt(i)); tcols.addRow(rd); 1163 } 1164 1165 } 1166 catch (DatabaseConstraintViolationException e) { 1167 if (e.getErrorCode() == 1170 DatabaseConstraintViolationException.UNIQUE_VIOLATION) { 1171 throw new StatementException( 1174 "Unique constraint name '" + constraint_name + 1175 "' is already being used."); 1176 } 1177 throw e; 1178 } 1179 1180 } 1181 1182 1197 public void addForeignKeyConstraint(TableName table, String [] cols, 1198 TableName ref_table, String [] ref_cols, 1199 String delete_rule, String update_rule, 1200 short deferred, String constraint_name) { 1201 TableName tn1 = TableDataConglomerate.FOREIGN_INFO_TABLE; 1202 TableName tn2 = TableDataConglomerate.FOREIGN_COLS_TABLE; 1203 MutableTableDataSource t = getTable(tn1); 1204 MutableTableDataSource tcols = getTable(tn2); 1205 1206 try { 1207 1208 if (ref_cols.length == 0) { 1211 ColumnGroup set = queryTablePrimaryKeyGroup(this, ref_table); 1212 if (set == null) { 1213 throw new StatementException( 1214 "No primary key defined for referenced table '" + ref_table + "'"); 1215 } 1216 ref_cols = set.columns; 1217 } 1218 1219 if (cols.length != ref_cols.length) { 1220 throw new StatementException("Foreign key reference '" + table + 1221 "' -> '" + ref_table + "' does not have an equal number of " + 1222 "column terms."); 1223 } 1224 1225 if (delete_rule.equals("SET NULL") || 1228 update_rule.equals("SET NULL")) { 1229 DataTableDef table_def = getDataTableDef(table); 1230 for (int i = 0; i < cols.length; ++i) { 1231 DataTableColumnDef column_def = 1232 table_def.columnAt(table_def.findColumnName(cols[i])); 1233 if (column_def.isNotNull()) { 1234 throw new StatementException("Foreign key reference '" + table + 1235 "' -> '" + ref_table + "' update or delete triggered " + 1236 "action is SET NULL for columns that are constrained as " + 1237 "NOT NULL."); 1238 } 1239 } 1240 } 1241 1242 RowData rd = new RowData(t); 1244 BigNumber unique_id = BigNumber.fromLong(nextUniqueID(tn1)); 1245 constraint_name = makeUniqueConstraintName(constraint_name, unique_id); 1246 rd.setColumnDataFromObject(0, unique_id); 1247 rd.setColumnDataFromObject(1, constraint_name); 1248 rd.setColumnDataFromObject(2, table.getSchema()); 1249 rd.setColumnDataFromObject(3, table.getName()); 1250 rd.setColumnDataFromObject(4, ref_table.getSchema()); 1251 rd.setColumnDataFromObject(5, ref_table.getName()); 1252 rd.setColumnDataFromObject(6, update_rule); 1253 rd.setColumnDataFromObject(7, delete_rule); 1254 rd.setColumnDataFromObject(8, BigNumber.fromInt(deferred)); 1255 t.addRow(rd); 1256 1257 for (int i = 0; i < cols.length; ++i) { 1259 rd = new RowData(tcols); 1260 rd.setColumnDataFromObject(0, unique_id); rd.setColumnDataFromObject(1, cols[i]); rd.setColumnDataFromObject(2, ref_cols[i]); rd.setColumnDataFromObject(3, BigNumber.fromInt(i)); tcols.addRow(rd); 1265 } 1266 1267 } 1268 catch (DatabaseConstraintViolationException e) { 1269 if (e.getErrorCode() == 1272 DatabaseConstraintViolationException.UNIQUE_VIOLATION) { 1273 throw new StatementException("Foreign key constraint name '" + 1276 constraint_name + "' is already being used."); 1277 } 1278 throw e; 1279 } 1280 1281 } 1282 1283 1296 public void addPrimaryKeyConstraint(TableName table_name, String [] cols, 1297 short deferred, String constraint_name) { 1298 1299 TableName tn1 = TableDataConglomerate.PRIMARY_INFO_TABLE; 1300 TableName tn2 = TableDataConglomerate.PRIMARY_COLS_TABLE; 1301 MutableTableDataSource t = getTable(tn1); 1302 MutableTableDataSource tcols = getTable(tn2); 1303 1304 try { 1305 1306 RowData rd = new RowData(t); 1308 BigNumber unique_id = BigNumber.fromLong(nextUniqueID(tn1)); 1309 constraint_name = makeUniqueConstraintName(constraint_name, unique_id); 1310 rd.setColumnDataFromObject(0, unique_id); 1311 rd.setColumnDataFromObject(1, constraint_name); 1312 rd.setColumnDataFromObject(2, table_name.getSchema()); 1313 rd.setColumnDataFromObject(3, table_name.getName()); 1314 rd.setColumnDataFromObject(4, BigNumber.fromInt(deferred)); 1315 t.addRow(rd); 1316 1317 for (int i = 0; i < cols.length; ++i) { 1319 rd = new RowData(tcols); 1320 rd.setColumnDataFromObject(0, unique_id); rd.setColumnDataFromObject(1, cols[i]); rd.setColumnDataFromObject(2, BigNumber.fromInt(i)); tcols.addRow(rd); 1324 } 1325 1326 } 1327 catch (DatabaseConstraintViolationException e) { 1328 if (e.getErrorCode() == 1331 DatabaseConstraintViolationException.UNIQUE_VIOLATION) { 1332 throw new StatementException("Primary key constraint name '" + 1335 constraint_name + "' is already being used."); 1336 } 1337 throw e; 1338 } 1339 1340 } 1341 1342 1353 public void addCheckConstraint(TableName table_name, 1354 Expression expression, short deferred, String constraint_name) { 1355 1356 TableName tn = TableDataConglomerate.CHECK_INFO_TABLE; 1357 MutableTableDataSource t = getTable(tn); 1358 int col_count = t.getDataTableDef().columnCount(); 1359 1360 try { 1361 1362 BigNumber unique_id = BigNumber.fromLong(nextUniqueID(tn)); 1364 constraint_name = makeUniqueConstraintName(constraint_name, unique_id); 1365 RowData rd = new RowData(t); 1366 rd.setColumnDataFromObject(0, unique_id); 1367 rd.setColumnDataFromObject(1, constraint_name); 1368 rd.setColumnDataFromObject(2, table_name.getSchema()); 1369 rd.setColumnDataFromObject(3, table_name.getName()); 1370 rd.setColumnDataFromObject(4, new String (expression.text())); 1371 rd.setColumnDataFromObject(5, BigNumber.fromInt(deferred)); 1372 if (col_count > 6) { 1373 ByteLongObject serialized_expression = 1375 ObjectTranslator.serialize(expression); 1376 rd.setColumnDataFromObject(6, serialized_expression); 1377 } 1378 t.addRow(rd); 1379 1380 } 1381 catch (DatabaseConstraintViolationException e) { 1382 if (e.getErrorCode() == 1385 DatabaseConstraintViolationException.UNIQUE_VIOLATION) { 1386 throw new StatementException("Check constraint name '" + 1388 constraint_name + "' is already being used."); 1389 } 1390 throw e; 1391 } 1392 1393 } 1394 1395 1405 public void dropAllConstraintsForTable(TableName table_name) { 1406 ColumnGroup primary = queryTablePrimaryKeyGroup(this, table_name); 1407 ColumnGroup[] uniques = queryTableUniqueGroups(this, table_name); 1408 CheckExpression[] expressions = 1409 queryTableCheckExpressions(this, table_name); 1410 ColumnGroupReference[] refs = 1411 queryTableForeignKeyReferences(this, table_name); 1412 1413 if (primary != null) { 1414 dropPrimaryKeyConstraintForTable(table_name, primary.name); 1415 } 1416 for (int i = 0; i < uniques.length; ++i) { 1417 dropUniqueConstraintForTable(table_name, uniques[i].name); 1418 } 1419 for (int i = 0; i < expressions.length; ++i) { 1420 dropCheckConstraintForTable(table_name, expressions[i].name); 1421 } 1422 for (int i = 0; i < refs.length; ++i) { 1423 dropForeignKeyReferenceConstraintForTable(table_name, refs[i].name); 1424 } 1425 1426 } 1427 1428 1440 public int dropNamedConstraint(TableName table_name, 1441 String constraint_name) { 1442 1443 int drop_count = 0; 1444 if (dropPrimaryKeyConstraintForTable(table_name, constraint_name)) { 1445 ++drop_count; 1446 } 1447 if (dropUniqueConstraintForTable(table_name, constraint_name)) { 1448 ++drop_count; 1449 } 1450 if (dropCheckConstraintForTable(table_name, constraint_name)) { 1451 ++drop_count; 1452 } 1453 if (dropForeignKeyReferenceConstraintForTable(table_name, 1454 constraint_name)) { 1455 ++drop_count; 1456 } 1457 return drop_count; 1458 } 1459 1460 1472 public boolean dropPrimaryKeyConstraintForTable( 1473 TableName table_name, String constraint_name) { 1474 1475 MutableTableDataSource t = 1476 getTable(TableDataConglomerate.PRIMARY_INFO_TABLE); 1477 MutableTableDataSource t2 = 1478 getTable(TableDataConglomerate.PRIMARY_COLS_TABLE); 1479 SimpleTableQuery dt = new SimpleTableQuery(t); SimpleTableQuery dtcols = new SimpleTableQuery(t2); 1482 try { 1483 IntegerVector data; 1484 if (constraint_name != null) { 1485 data = dt.selectIndexesEqual(1, constraint_name, 1488 2, table_name.getSchema()); 1489 } 1490 else { 1491 data = dt.selectIndexesEqual(3, table_name.getName(), 1494 2, table_name.getSchema()); 1495 } 1496 1497 if (data.size() > 1) { 1498 throw new Error ("Assertion failed: multiple primary key for: " + 1499 table_name); 1500 } 1501 else if (data.size() == 1) { 1502 int row_index = data.intAt(0); 1503 TObject id = dt.get(0, row_index); 1505 IntegerVector ivec = dtcols.selectIndexesEqual(0, id); 1507 dtcols.deleteRows(ivec); 1509 dt.deleteRows(data); 1510 return true; 1511 } 1512 return false; 1514 1515 } 1516 finally { 1517 dtcols.dispose(); 1518 dt.dispose(); 1519 } 1520 1521 } 1522 1523 1533 public boolean dropUniqueConstraintForTable( 1534 TableName table, String constraint_name) { 1535 1536 MutableTableDataSource t = 1537 getTable(TableDataConglomerate.UNIQUE_INFO_TABLE); 1538 MutableTableDataSource t2 = 1539 getTable(TableDataConglomerate.UNIQUE_COLS_TABLE); 1540 SimpleTableQuery dt = new SimpleTableQuery(t); SimpleTableQuery dtcols = new SimpleTableQuery(t2); 1543 try { 1544 IntegerVector data = dt.selectIndexesEqual(1, constraint_name, 1547 2, table.getSchema()); 1548 1549 if (data.size() > 1) { 1550 throw new Error ("Assertion failed: multiple unique constraint name: " + 1551 constraint_name); 1552 } 1553 else if (data.size() == 1) { 1554 int row_index = data.intAt(0); 1555 TObject id = dt.get(0, row_index); 1557 IntegerVector ivec = dtcols.selectIndexesEqual(0, id); 1559 dtcols.deleteRows(ivec); 1561 dt.deleteRows(data); 1562 return true; 1563 } 1564 return false; 1566 } 1567 finally { 1568 dtcols.dispose(); 1569 dt.dispose(); 1570 } 1571 1572 } 1573 1574 1584 public boolean dropCheckConstraintForTable( 1585 TableName table, String constraint_name) { 1586 1587 MutableTableDataSource t = 1588 getTable(TableDataConglomerate.CHECK_INFO_TABLE); 1589 SimpleTableQuery dt = new SimpleTableQuery(t); 1591 try { 1592 IntegerVector data = dt.selectIndexesEqual(1, constraint_name, 1595 2, table.getSchema()); 1596 1597 if (data.size() > 1) { 1598 throw new Error ("Assertion failed: multiple check constraint name: " + 1599 constraint_name); 1600 } 1601 else if (data.size() == 1) { 1602 dt.deleteRows(data); 1604 return true; 1605 } 1606 return false; 1608 } 1609 finally { 1610 dt.dispose(); 1611 } 1612 1613 } 1614 1615 1626 public boolean dropForeignKeyReferenceConstraintForTable( 1627 TableName table, String constraint_name) { 1628 1629 MutableTableDataSource t = 1630 getTable(TableDataConglomerate.FOREIGN_INFO_TABLE); 1631 MutableTableDataSource t2 = 1632 getTable(TableDataConglomerate.FOREIGN_COLS_TABLE); 1633 SimpleTableQuery dt = new SimpleTableQuery(t); SimpleTableQuery dtcols = new SimpleTableQuery(t2); 1636 try { 1637 IntegerVector data = dt.selectIndexesEqual(1, constraint_name, 1640 2, table.getSchema()); 1641 1642 if (data.size() > 1) { 1643 throw new Error ("Assertion failed: multiple foreign key constraint " + 1644 "name: " + constraint_name); 1645 } 1646 else if (data.size() == 1) { 1647 int row_index = data.intAt(0); 1648 TObject id = dt.get(0, row_index); 1650 IntegerVector ivec = dtcols.selectIndexesEqual(0, id); 1652 dtcols.deleteRows(ivec); 1654 dt.deleteRows(data); 1655 return true; 1656 } 1657 return false; 1659 } 1660 finally { 1661 dtcols.dispose(); 1662 dt.dispose(); 1663 } 1664 1665 } 1666 1667 1678 public static TableName[] queryTablesRelationallyLinkedTo( 1679 SimpleTransaction transaction, TableName table) { 1680 ArrayList list = new ArrayList (); 1681 ColumnGroupReference[] refs = 1682 queryTableForeignKeyReferences(transaction, table); 1683 for (int i = 0; i < refs.length; ++i) { 1684 TableName tname = refs[i].ref_table_name; 1685 if (!list.contains(tname)) { 1686 list.add(tname); 1687 } 1688 } 1689 refs = queryTableImportedForeignKeyReferences(transaction, table); 1690 for (int i = 0; i < refs.length; ++i) { 1691 TableName tname = refs[i].key_table_name; 1692 if (!list.contains(tname)) { 1693 list.add(tname); 1694 } 1695 } 1696 return (TableName[]) list.toArray(new TableName[list.size()]); 1697 } 1698 1699 1706 public static ColumnGroup[] queryTableUniqueGroups( 1707 SimpleTransaction transaction, TableName table_name) { 1708 TableDataSource t = 1709 transaction.getTableDataSource(TableDataConglomerate.UNIQUE_INFO_TABLE); 1710 TableDataSource t2 = 1711 transaction.getTableDataSource(TableDataConglomerate.UNIQUE_COLS_TABLE); 1712 SimpleTableQuery dt = new SimpleTableQuery(t); SimpleTableQuery dtcols = new SimpleTableQuery(t2); 1715 ColumnGroup[] groups; 1716 try { 1717 IntegerVector data = dt.selectIndexesEqual(3, table_name.getName(), 1720 2, table_name.getSchema()); 1721 groups = new ColumnGroup[data.size()]; 1722 1723 for (int i = 0; i < data.size(); ++i) { 1724 TObject id = dt.get(0, data.intAt(i)); 1725 1726 IntegerVector cols = dtcols.selectIndexesEqual(0, id); 1728 1729 ColumnGroup group = new ColumnGroup(); 1731 group.name = dt.get(1, data.intAt(i)).getObject().toString(); 1733 group.columns = toColumns(dtcols, cols); group.deferred = ((BigNumber) dt.get(4, 1735 data.intAt(i)).getObject()).shortValue(); 1736 groups[i] = group; 1737 } 1738 } 1739 finally { 1740 dt.dispose(); 1741 dtcols.dispose(); 1742 } 1743 1744 return groups; 1745 } 1746 1747 1753 public static ColumnGroup queryTablePrimaryKeyGroup( 1754 SimpleTransaction transaction, TableName table_name) { 1755 TableDataSource t = 1756 transaction.getTableDataSource(TableDataConglomerate.PRIMARY_INFO_TABLE); 1757 TableDataSource t2 = 1758 transaction.getTableDataSource(TableDataConglomerate.PRIMARY_COLS_TABLE); 1759 SimpleTableQuery dt = new SimpleTableQuery(t); SimpleTableQuery dtcols = new SimpleTableQuery(t2); 1762 try { 1763 IntegerVector data = dt.selectIndexesEqual(3, table_name.getName(), 1766 2, table_name.getSchema()); 1767 1768 if (data.size() > 1) { 1769 throw new Error ("Assertion failed: multiple primary key for: " + 1770 table_name); 1771 } 1772 else if (data.size() == 1) { 1773 int row_index = data.intAt(0); 1774 TObject id = dt.get(0, row_index); 1776 IntegerVector ivec = dtcols.selectIndexesEqual(0, id); 1778 ColumnGroup group = new ColumnGroup(); 1780 group.name = dt.get(1, row_index).getObject().toString(); 1781 group.columns = toColumns(dtcols, ivec); 1782 group.deferred = ((BigNumber) dt.get(4, 1783 row_index).getObject()).shortValue(); 1784 return group; 1785 } 1786 else { 1787 return null; 1788 } 1789 } 1790 finally { 1791 dt.dispose(); 1792 dtcols.dispose(); 1793 } 1794 1795 } 1796 1797 1803 public static CheckExpression[] queryTableCheckExpressions( 1804 SimpleTransaction transaction, TableName table_name) { 1805 TableDataSource t = 1806 transaction.getTableDataSource(TableDataConglomerate.CHECK_INFO_TABLE); 1807 SimpleTableQuery dt = new SimpleTableQuery(t); 1809 CheckExpression[] checks; 1810 try { 1811 IntegerVector data = dt.selectIndexesEqual(3, table_name.getName(), 1814 2, table_name.getSchema()); 1815 checks = new CheckExpression[data.size()]; 1816 1817 for (int i = 0; i < checks.length; ++i) { 1818 int row_index = data.intAt(i); 1819 1820 CheckExpression check = new CheckExpression(); 1821 check.name = dt.get(1, row_index).getObject().toString(); 1822 check.deferred = ((BigNumber) dt.get(5, 1823 row_index).getObject()).shortValue(); 1824 if (t.getDataTableDef().columnCount() > 6) { 1826 ByteLongObject sexp = 1827 (ByteLongObject) dt.get(6, row_index).getObject(); 1828 if (sexp != null) { 1829 try { 1830 check.expression = 1832 (Expression) ObjectTranslator.deserialize(sexp); 1833 } 1834 catch (Throwable e) { 1835 transaction.Debug().write(Lvl.WARNING, Transaction.class, 1838 "Unable to deserialize the check expression. " + 1839 "The error is: " + e.getMessage()); 1840 transaction.Debug().write(Lvl.WARNING, Transaction.class, 1841 "Parsing the check expression instead."); 1842 check.expression = null; 1843 } 1844 } 1845 } 1846 if (check.expression == null) { 1848 Expression exp = Expression.parse( 1849 dt.get(4, row_index).getObject().toString()); 1850 check.expression = exp; 1851 } 1852 checks[i] = check; 1853 } 1854 1855 } 1856 finally { 1857 dt.dispose(); 1858 } 1859 1860 return checks; 1861 } 1862 1863 1875 public static ColumnGroupReference[] queryTableForeignKeyReferences( 1876 SimpleTransaction transaction, TableName table_name) { 1877 1878 TableDataSource t = 1879 transaction.getTableDataSource(TableDataConglomerate.FOREIGN_INFO_TABLE); 1880 TableDataSource t2 = 1881 transaction.getTableDataSource(TableDataConglomerate.FOREIGN_COLS_TABLE); 1882 SimpleTableQuery dt = new SimpleTableQuery(t); SimpleTableQuery dtcols = new SimpleTableQuery(t2); 1885 ColumnGroupReference[] groups; 1886 try { 1887 IntegerVector data = dt.selectIndexesEqual(3, table_name.getName(), 1890 2, table_name.getSchema()); 1891 groups = new ColumnGroupReference[data.size()]; 1892 1893 for (int i = 0; i < data.size(); ++i) { 1894 int row_index = data.intAt(i); 1895 1896 TObject id = dt.get(0, row_index); 1898 1899 TableName ref_table_name = new TableName( 1901 dt.get(4, row_index).getObject().toString(), 1902 dt.get(5, row_index).getObject().toString()); 1903 1904 IntegerVector cols = dtcols.selectIndexesEqual(0, id); 1906 1907 ColumnGroupReference group = new ColumnGroupReference(); 1909 group.name = dt.get(1, row_index).getObject().toString(); 1911 group.key_table_name = table_name; 1912 group.ref_table_name = ref_table_name; 1913 group.update_rule = dt.get(6, row_index).getObject().toString(); 1914 group.delete_rule = dt.get(7, row_index).getObject().toString(); 1915 group.deferred = ((BigNumber) dt.get(8, 1916 row_index).getObject()).shortValue(); 1917 1918 int cols_size = cols.size(); 1919 String [] key_cols = new String [cols_size]; 1920 String [] ref_cols = new String [cols_size]; 1921 for (int n = 0; n < cols_size; ++n) { 1922 for (int p = 0; p < cols_size; ++p) { 1923 int cols_index = cols.intAt(p); 1924 if (((BigNumber) dtcols.get(3, 1925 cols_index).getObject()).intValue() == n) { 1926 key_cols[n] = dtcols.get(1, cols_index).getObject().toString(); 1927 ref_cols[n] = dtcols.get(2, cols_index).getObject().toString(); 1928 break; 1929 } 1930 } 1931 } 1932 group.key_columns = key_cols; 1933 group.ref_columns = ref_cols; 1934 1935 groups[i] = group; 1936 } 1937 } 1938 finally { 1939 dt.dispose(); 1940 dtcols.dispose(); 1941 } 1942 1943 return groups; 1944 } 1945 1946 1963 public static ColumnGroupReference[] queryTableImportedForeignKeyReferences( 1964 SimpleTransaction transaction, TableName ref_table_name) { 1965 1966 TableDataSource t = 1967 transaction.getTableDataSource(TableDataConglomerate.FOREIGN_INFO_TABLE); 1968 TableDataSource t2 = 1969 transaction.getTableDataSource(TableDataConglomerate.FOREIGN_COLS_TABLE); 1970 SimpleTableQuery dt = new SimpleTableQuery(t); SimpleTableQuery dtcols = new SimpleTableQuery(t2); 1973 ColumnGroupReference[] groups; 1974 try { 1975 IntegerVector data = dt.selectIndexesEqual(5,ref_table_name.getName(), 1978 4,ref_table_name.getSchema()); 1979 groups = new ColumnGroupReference[data.size()]; 1980 1981 for (int i = 0; i < data.size(); ++i) { 1982 int row_index = data.intAt(i); 1983 1984 TObject id = dt.get(0, row_index); 1986 1987 TableName table_name = new TableName( 1989 dt.get(2, row_index).getObject().toString(), 1990 dt.get(3, row_index).getObject().toString()); 1991 1992 IntegerVector cols = dtcols.selectIndexesEqual(0, id); 1994 1995 ColumnGroupReference group = new ColumnGroupReference(); 1997 group.name = dt.get(1, row_index).getObject().toString(); 1999 group.key_table_name = table_name; 2000 group.ref_table_name = ref_table_name; 2001 group.update_rule = dt.get(6, row_index).getObject().toString(); 2002 group.delete_rule = dt.get(7, row_index).getObject().toString(); 2003 group.deferred = ((BigNumber) dt.get(8, 2004 row_index).getObject()).shortValue(); 2005 2006 int cols_size = cols.size(); 2007 String [] key_cols = new String [cols_size]; 2008 String [] ref_cols = new String [cols_size]; 2009 for (int n = 0; n < cols_size; ++n) { 2010 for (int p = 0; p < cols_size; ++p) { 2011 int cols_index = cols.intAt(p); 2012 if (((BigNumber) dtcols.get(3, 2013 cols_index).getObject()).intValue() == n) { 2014 key_cols[n] = dtcols.get(1, cols_index).getObject().toString(); 2015 ref_cols[n] = dtcols.get(2, cols_index).getObject().toString(); 2016 break; 2017 } 2018 } 2019 } 2020 group.key_columns = key_cols; 2021 group.ref_columns = ref_cols; 2022 2023 groups[i] = group; 2024 } 2025 } 2026 finally { 2027 dt.dispose(); 2028 dtcols.dispose(); 2029 } 2030 2031 return groups; 2032 } 2033 2034 2035 2036 2037 2038 2039 2040 2042 2062 public void closeAndCommit() throws TransactionException { 2063 2064 if (!closed) { 2065 try { 2066 closed = true; 2067 conglomerate.processCommit(this, getVisibleTables(), 2069 selected_from_tables, 2070 touched_tables, journal); 2071 } 2072 finally { 2073 cleanup(); 2074 } 2075 } 2076 2077 } 2078 2079 2085 public void closeAndRollback() { 2086 2087 if (!closed) { 2088 try { 2089 closed = true; 2090 conglomerate.processRollback(this, touched_tables, journal); 2092 } 2093 finally { 2094 cleanup(); 2095 } 2096 } 2097 2098 } 2099 2100 2103 private void cleanup() { 2104 getSystem().stats().decrement("Transaction.count"); 2105 disposeAllIndices(); 2107 2108 try { 2110 for (int i = 0; i < touched_tables.size(); ++i) { 2111 MutableTableDataSource source = 2112 (MutableTableDataSource) touched_tables.get(i); 2113 source.dispose(); 2114 } 2115 } 2116 catch (Throwable e) { 2117 Debug().writeException(e); 2118 } 2119 2120 getSystem().stats().increment("Transaction.cleanup"); 2121 conglomerate = null; 2122 touched_tables = null; 2123 journal = null; 2124 } 2125 2126 2131 void dispose() { 2132 if (!isReadOnly()) { 2133 throw new RuntimeException ( 2134 "Assertion failed - tried to dispose a non read-only transaction."); 2135 } 2136 if (!closed) { 2137 closed = true; 2138 cleanup(); 2139 } 2140 } 2141 2142 2145 public void finalize() throws Throwable { 2146 super.finalize(); 2147 if (!closed) { 2148 Debug().write(Lvl.ERROR, this, "Transaction not closed!"); 2149 closeAndRollback(); 2150 } 2151 } 2152 2153 2154 2155 2157 2161 private final static DataTableDef[] INTERNAL_DEF_LIST; 2162 2163 static { 2164 INTERNAL_DEF_LIST = new DataTableDef[3]; 2165 INTERNAL_DEF_LIST[0] = GTTableColumnsDataSource.DEF_DATA_TABLE_DEF; 2166 INTERNAL_DEF_LIST[1] = GTTableInfoDataSource.DEF_DATA_TABLE_DEF; 2167 INTERNAL_DEF_LIST[2] = GTProductDataSource.DEF_DATA_TABLE_DEF; 2168 } 2169 2170 2175 private class TransactionInternalTables extends AbstractInternalTableInfo { 2176 2177 2180 public TransactionInternalTables() { 2181 super("SYSTEM TABLE", INTERNAL_DEF_LIST); 2182 } 2183 2184 2186 public MutableTableDataSource createInternalTable(int index) { 2187 if (index == 0) { 2188 return new GTTableColumnsDataSource(Transaction.this).init(); 2189 } 2190 else if (index == 1) { 2191 return new GTTableInfoDataSource(Transaction.this).init(); 2192 } 2193 else if (index == 2) { 2194 return new GTProductDataSource(Transaction.this).init(); 2195 } 2196 else { 2197 throw new RuntimeException (); 2198 } 2199 } 2200 2201 } 2202 2203 2207 public static class ColumnGroup { 2208 2209 2212 public String name; 2213 2214 2217 public String [] columns; 2218 2219 2222 public short deferred; 2223 2224 } 2225 2226 2229 public static class CheckExpression { 2230 2231 2234 public String name; 2235 2236 2239 public Expression expression; 2240 2241 2244 public short deferred; 2245 2246 } 2247 2248 2253 public static class ColumnGroupReference { 2254 2255 2258 public String name; 2259 2260 2263 public TableName key_table_name; 2264 2265 2268 public String [] key_columns; 2269 2270 2273 public TableName ref_table_name; 2274 2275 2278 public String [] ref_columns; 2279 2280 2283 public String update_rule; 2284 2285 2288 public String delete_rule; 2289 2290 2293 public short deferred; 2294 2295 } 2296 2297} 2298 | Popular Tags |