1 24 25 package com.mckoi.database; 26 27 import com.mckoi.debug.*; 28 import com.mckoi.util.Cache; 29 import com.mckoi.database.global.ByteLongObject; 30 import com.mckoi.database.global.Ref; 31 import com.mckoi.database.jdbc.SQLQuery; 32 import java.util.HashMap ; 33 import java.util.ArrayList ; 34 import java.math.BigDecimal ; 35 36 42 43 public class DatabaseConnection implements TriggerListener { 44 45 48 private User user; 49 50 53 private Database database; 54 55 58 private DebugLogger logger; 59 60 65 private CallBack call_back; 66 67 70 private LockingMechanism locking_mechanism; 71 72 76 private TableDataConglomerate conglomerate; 77 78 81 private Transaction transaction; 82 83 87 private java.sql.Connection jdbc_connection; 88 89 93 private HashMap tables_cache; 94 95 100 private ArrayList trigger_event_buffer; 101 102 108 private ArrayList trigger_event_list; 109 110 115 private boolean auto_commit; 116 117 122 private int transaction_isolation; 123 124 130 private boolean close_transaction_disabled; 131 132 137 private String current_schema; 138 139 142 private GrantManager grant_manager; 143 144 147 private ProcedureManager procedure_manager; 148 149 153 private ConnectionTriggerManager connection_trigger_manager; 154 155 159 private ViewManager view_manager; 160 161 166 private ArrayList table_backed_cache_list; 167 168 173 private ConnectionInternalTableInfo connection_internal_table_info; 174 175 177 181 private boolean error_on_dirty_select; 182 183 186 private boolean case_insensitive_identifiers; 187 188 190 194 private OldAndNewInternalTableInfo old_new_table_info; 195 196 200 private OldNewTableState current_old_new_state = new OldNewTableState(); 201 202 203 204 207 DatabaseConnection(Database database, User user, CallBack call_back) { 208 this.database = database; 209 this.user = user; 210 this.logger = database.Debug(); 211 this.call_back = call_back; 212 this.conglomerate = database.getConglomerate(); 213 this.locking_mechanism = new LockingMechanism(Debug()); 214 this.trigger_event_buffer = new ArrayList (); 215 this.trigger_event_list = new ArrayList (); 216 tables_cache = new HashMap (); 217 auto_commit = true; 218 219 current_schema = Database.DEFAULT_SCHEMA; 220 this.close_transaction_disabled = false; 221 222 this.table_backed_cache_list = new ArrayList (); 223 224 connection_internal_table_info = new ConnectionInternalTableInfo(); 225 old_new_table_info = new OldAndNewInternalTableInfo(); 226 227 error_on_dirty_select = 228 database.getSystem().transactionErrorOnDirtySelect(); 229 case_insensitive_identifiers = database.getSystem().ignoreIdentifierCase(); 230 231 } 232 233 237 void init() { 238 grant_manager = new GrantManager(this); 240 procedure_manager = new ProcedureManager(this); 242 connection_trigger_manager = new ConnectionTriggerManager(this); 244 view_manager = new ViewManager(this); 246 } 247 248 252 private Transaction getTransaction() { 253 synchronized (this) { 254 if (transaction == null) { 255 transaction = conglomerate.createTransaction(); 256 transaction.setErrorOnDirtySelect(error_on_dirty_select); 257 transaction.addInternalTableInfo(connection_internal_table_info); 259 transaction.addInternalTableInfo(old_new_table_info); 261 transaction.addInternalTableInfo( 263 ViewManager.createInternalTableInfo(view_manager, transaction)); 264 transaction.addInternalTableInfo( 266 ProcedureManager.createInternalTableInfo(transaction)); 267 transaction.addInternalTableInfo( 269 SequenceManager.createInternalTableInfo(transaction)); 270 transaction.addInternalTableInfo( 272 ConnectionTriggerManager.createInternalTableInfo(transaction)); 273 274 int sz = table_backed_cache_list.size(); 276 for (int i = 0; i < sz; ++i) { 277 TableBackedCache cache = 278 (TableBackedCache) table_backed_cache_list.get(i); 279 cache.transactionStarted(); 280 } 281 282 } 283 } 284 return transaction; 285 } 286 287 291 QueryPlanNode createViewQueryPlanNode(TableName table_name) { 292 return view_manager.createViewQueryPlanNode(table_name); 293 } 294 295 316 public java.sql.Connection getJDBCConnection() { 317 if (jdbc_connection == null) { 318 jdbc_connection = 319 InternalJDBCHelper.createJDBCConnection(getUser(), this); 320 } 321 return jdbc_connection; 322 } 323 324 335 ProcedureConnection createProcedureConnection(User user) { 336 DCProcedureConnection c = new DCProcedureConnection(); 338 c.previous_user = getUser(); 340 c.transaction_disabled_flag = close_transaction_disabled; 342 setUser(user); 344 close_transaction_disabled = true; 346 return c; 348 } 349 350 354 void disposeProcedureConnection(ProcedureConnection connection) { 355 DCProcedureConnection c = (DCProcedureConnection) connection; 356 setUser(c.previous_user); 358 close_transaction_disabled = c.transaction_disabled_flag; 360 c.dispose(); 362 } 363 364 367 public DatabaseSystem getSystem() { 368 return database.getSystem(); 369 } 370 371 374 public Database getDatabase() { 375 return database; 376 } 377 378 381 TableDataConglomerate getConglomerate() { 382 return conglomerate; 383 } 384 385 390 void setUser(User user) { 391 this.user = user; 392 } 393 394 397 public User getUser() { 398 return user; 399 } 400 401 404 public final DebugLogger Debug() { 405 return logger; 406 } 407 408 411 public ConnectionTriggerManager getConnectionTriggerManager() { 412 return connection_trigger_manager; 413 } 414 415 419 public GrantManager getGrantManager() { 420 return grant_manager; 421 } 422 423 427 public ProcedureManager getProcedureManager() { 428 return procedure_manager; 429 } 430 431 434 public void setAutoCommit(boolean status) { 435 auto_commit = status; 436 } 437 438 441 public void setTransactionIsolation(String name) { 442 if (name.equals("serializable")) { 443 transaction_isolation = 4; 444 } 445 else { 446 throw new Error ("Can not set transaction isolation to " + name); 447 } 448 } 449 450 460 public void setVar(String name, Expression exp) { 461 if (name.toUpperCase().equals("ERROR_ON_DIRTY_SELECT")) { 462 error_on_dirty_select = toBooleanValue(exp); 463 } 464 else if (name.toUpperCase().equals("CASE_INSENSITIVE_IDENTIFIERS")) { 465 case_insensitive_identifiers = toBooleanValue(exp); 466 } 467 } 468 469 472 private static boolean toBooleanValue(Expression exp) { 473 Boolean b = exp.evaluate(null, null, null).toBoolean(); 474 if (b == null) { 475 throw new StatementException( 476 "Expression does not evaluate to a boolean (true or false)."); 477 } 478 return b.booleanValue(); 479 } 480 481 485 public boolean getAutoCommit() { 486 return auto_commit; 487 } 488 489 492 public int getTransactionIsolation() { 493 return transaction_isolation; 494 } 495 496 499 public String getTransactionIsolationAsString() { 500 int il = getTransactionIsolation(); 501 if (il == 1) { 502 return "read uncommitted"; 503 } 504 else if (il == 2) { 505 return "read committed"; 506 } 507 else if (il == 3) { 508 return "repeatable read"; 509 } 510 else if (il == 4) { 511 return "serializable"; 512 } 513 else { 514 return "unknown isolation level"; 515 } 516 } 517 518 521 public String getCurrentSchema() { 522 return current_schema; 523 } 524 525 529 public boolean isInCaseInsensitiveMode() { 530 return case_insensitive_identifiers; 531 } 532 533 536 public void setCurrentSchema(String current_schema) { 537 this.current_schema = current_schema; 538 } 539 540 545 public LockingMechanism getLockingMechanism() { 546 return locking_mechanism; 547 } 548 549 554 void attachTableBackedCache(TableBackedCache cache) { 555 cache.attachTo(conglomerate); 556 table_backed_cache_list.add(cache); 557 } 558 559 566 public TableName[] getTableList() { 567 return getTransaction().getTableList(); 568 } 569 570 573 public boolean tableExists(String table_name) { 574 return tableExists(new TableName(current_schema, table_name)); 575 } 576 577 580 public boolean tableExists(TableName table_name) { 581 table_name = substituteReservedTableName(table_name); 582 return getTransaction().tableExists(table_name); 583 } 584 585 589 public String getTableType(TableName table_name) { 590 table_name = substituteReservedTableName(table_name); 591 return getTransaction().getTableType(table_name); 592 } 593 594 602 public TableName tryResolveCase(TableName table_name) { 603 table_name = substituteReservedTableName(table_name); 604 table_name = getTransaction().tryResolveCase(table_name); 605 return table_name; 606 } 607 608 615 public TableName resolveTableName(String name) { 616 TableName table_name = TableName.resolve(getCurrentSchema(), name); 617 table_name = substituteReservedTableName(table_name); 618 if (isInCaseInsensitiveMode()) { 619 table_name = tryResolveCase(table_name); 621 } 622 return table_name; 623 } 624 625 630 public TableName resolveToTableName(String name) { 631 TableName table_name = TableName.resolve(getCurrentSchema(), name); 632 if (table_name.getName().equalsIgnoreCase("OLD")) { 633 return Database.OLD_TRIGGER_TABLE; 634 } 635 else if (table_name.getName().equalsIgnoreCase("NEW")) { 636 return Database.NEW_TRIGGER_TABLE; 637 } 638 639 return getTransaction().resolveToTableName(getCurrentSchema(), name, 640 isInCaseInsensitiveMode()); 641 642 } 643 644 647 public DataTableDef getDataTableDef(TableName name) { 648 name = substituteReservedTableName(name); 649 return getTransaction().getDataTableDef(name); 650 } 651 652 656 public DataTable getTable(TableName name) { 657 name = substituteReservedTableName(name); 658 659 try { 660 if (name.equals(Database.OLD_TRIGGER_TABLE)) { 663 if (current_old_new_state.OLD_data_table == null) { 664 current_old_new_state.OLD_data_table = 665 new DataTable(this, getTransaction().getTable(name)); 666 } 667 return current_old_new_state.OLD_data_table; 668 } 669 else if (name.equals(Database.NEW_TRIGGER_TABLE)) { 670 if (current_old_new_state.NEW_data_table == null) { 671 current_old_new_state.NEW_data_table = 672 new DataTable(this, getTransaction().getTable(name)); 673 } 674 return current_old_new_state.NEW_data_table; 675 } 676 677 MutableTableDataSource table = getTransaction().getTable(name); 679 680 DataTable dtable = (DataTable) tables_cache.get(table); 682 if (dtable == null) { 684 dtable = new DataTable(this, table); 685 tables_cache.put(table, dtable); 686 } 687 return dtable; 689 690 } 691 catch (DatabaseException e) { 692 Debug().writeException(e); 693 throw new Error ("Database Exception: " + e.getMessage()); 694 } 695 696 } 697 698 702 public DataTable getTable(String table_name) { 703 return getTable(new TableName(current_schema, table_name)); 704 } 705 706 710 public void createTable(DataTableDef table_def) { 711 checkAllowCreate(table_def.getTableName()); 712 getTransaction().createTable(table_def); 713 } 714 715 721 public void createTable(DataTableDef table_def, 722 int data_sector_size, int index_sector_size) { 723 checkAllowCreate(table_def.getTableName()); 724 getTransaction().createTable(table_def, 725 data_sector_size, index_sector_size); 726 } 727 728 735 public void createView(SQLQuery query, ViewDef view) { 736 checkAllowCreate(view.getDataTableDef().getTableName()); 737 738 try { 739 view_manager.defineView(view, query, getUser()); 740 } 741 catch (DatabaseException e) { 742 Debug().writeException(e); 743 throw new RuntimeException ("Database Exception: " + e.getMessage()); 744 } 745 746 } 747 748 755 public boolean dropView(TableName view_name) { 756 757 try { 758 return view_manager.deleteView(view_name); 759 } 760 catch (DatabaseException e) { 761 Debug().writeException(e); 762 throw new RuntimeException ("Database Exception: " + e.getMessage()); 763 } 764 765 } 766 767 771 public void updateTable(DataTableDef table_def) { 772 checkAllowCreate(table_def.getTableName()); 773 getTransaction().alterTable(table_def.getTableName(), table_def); 774 } 775 776 783 public void updateTable(DataTableDef table_def, 784 int data_sector_size, int index_sector_size) { 785 checkAllowCreate(table_def.getTableName()); 786 getTransaction().alterTable(table_def.getTableName(), table_def, 787 data_sector_size, index_sector_size); 788 } 789 790 799 public void alterCreateTable(DataTableDef table_def, 800 int data_sector_size, int index_sector_size) { 801 if (!tableExists(table_def.getTableName())) { 802 createTable(table_def, data_sector_size, index_sector_size); 803 } 804 else { 805 updateTable(table_def, data_sector_size, index_sector_size); 806 } 807 } 808 809 813 public void alterCreateTable(DataTableDef table_def) { 814 if (!tableExists(table_def.getTableName())) { 815 createTable(table_def); 816 } 817 else { 818 updateTable(table_def); 819 } 820 } 821 822 826 void databaseObjectCreated(TableName table_name) { 827 getTransaction().databaseObjectCreated(table_name); 828 } 829 830 834 void databaseObjectDropped(TableName table_name) { 835 getTransaction().databaseObjectDropped(table_name); 836 } 837 838 846 public void checkAllConstraints(TableName table_name) { 847 checkExclusive(); 849 getTransaction().checkAllConstraints(table_name); 850 } 851 852 856 public void dropTable(String table_name) { 857 dropTable(new TableName(current_schema, table_name)); 858 } 859 860 864 public void dropTable(TableName table_name) { 865 getTransaction().dropTable(table_name); 866 } 867 868 872 public void compactTable(String table_name) { 873 compactTable(new TableName(current_schema, table_name)); 874 } 875 876 880 public void compactTable(TableName table_name) { 881 getTransaction().compactTable(table_name); 882 } 883 884 888 public void addSelectedFromTable(String table_name) { 889 addSelectedFromTable(new TableName(current_schema, table_name)); 890 } 891 892 896 public void addSelectedFromTable(TableName name) { 897 getTransaction().addSelectedFromTable(name); 898 } 899 900 906 public long nextSequenceValue(String name) { 907 TableName seq_name = resolveToTableName(name); 909 return getTransaction().nextSequenceValue(seq_name); 910 } 911 912 921 public long lastSequenceValue(String name) { 922 TableName seq_name = resolveToTableName(name); 924 return getTransaction().lastSequenceValue(seq_name); 925 } 926 927 935 public void setSequenceValue(String name, long value) { 936 TableName seq_name = resolveToTableName(name); 938 getTransaction().setSequenceValue(seq_name, value); 939 } 940 941 944 public long nextUniqueID(TableName name) { 945 return getTransaction().nextUniqueID(name); 946 } 947 948 952 public long nextUniqueID(String table_name) { 953 TableName tname = TableName.resolve(current_schema, table_name); 954 return nextUniqueID(tname); 955 } 956 957 962 static TableName substituteReservedTableName(TableName table_name) { 963 String name = table_name.getName(); 965 if (name.equalsIgnoreCase("OLD")) { 966 return Database.OLD_TRIGGER_TABLE; 967 } 968 if (name.equalsIgnoreCase("NEW")) { 969 return Database.NEW_TRIGGER_TABLE; 970 } 971 return table_name; 972 } 973 974 979 static void checkAllowCreate(TableName table_name) { 980 String name = table_name.getName(); 982 if (name.equalsIgnoreCase("OLD") || 983 name.equalsIgnoreCase("NEW")) { 984 throw new StatementException("Table name '" + table_name + 985 "' is reserved."); 986 } 987 } 988 989 994 public void createSequenceGenerator( 995 TableName name, long start_value, long increment_by, 996 long min_value, long max_value, long cache, boolean cycle) { 997 998 checkAllowCreate(name); 1000 1001 getTransaction().createSequenceGenerator(name, 1002 start_value, increment_by, min_value, max_value, cache, cycle); 1003 } 1004 1005 1008 public void dropSequenceGenerator(TableName name) { 1009 getTransaction().dropSequenceGenerator(name); 1010 } 1011 1012 1019 public void createTrigger(String trigger_name, 1020 String trigger_source, int type) { 1021 database.getTriggerManager().addTriggerListener( 1022 this, trigger_name, type, trigger_source, this); 1023 } 1024 1025 1029 public void deleteTrigger(String trigger_name) { 1030 database.getTriggerManager().removeTriggerListener(this, trigger_name); 1031 } 1032 1033 1037 public void notifyTriggerEvent(TriggerEvent evt) { 1038 trigger_event_list.add(evt); 1039 } 1040 1041 1050 public Ref createNewLargeObject(byte type, long object_size) { 1051 if (type == 3 || type == 4) { 1053 type = (byte) (type | 0x010); 1054 } 1055 return conglomerate.createNewLargeObject(type, object_size); 1056 } 1057 1058 1066 public void flushBlobStore() { 1067 conglomerate.flushBlobStore(); 1068 } 1069 1070 1083 public TableQueryDef getTableQueryDef(final TableName table_name, 1084 final TableName aliased_as) { 1085 1086 DataTableDef dtf = getDataTableDef(table_name); 1088 if (aliased_as != null) { 1090 dtf = new DataTableDef(dtf); 1091 dtf.setTableName(aliased_as); 1092 dtf.setImmutable(); 1093 } 1094 final DataTableDef data_table_def = dtf; 1095 1098 return new TableQueryDef() { 1099 public DataTableDef getDataTableDef() { 1100 return data_table_def; 1101 } 1102 public QueryPlanNode getQueryPlanNode() { 1103 return createObjectFetchQueryPlan(table_name, aliased_as); 1104 } 1105 }; 1106 1107 } 1108 1109 1113 public QueryPlanNode createObjectFetchQueryPlan(TableName table_name, 1114 TableName aliased_name) { 1115 String table_type = getTableType(table_name); 1116 if (table_type.equals("VIEW")) { 1117 return new QueryPlan.FetchViewNode(table_name, aliased_name); 1118 } 1119 else { 1120 return new QueryPlan.FetchTableNode(table_name, aliased_name); 1121 } 1122 } 1123 1124 1131 1134 public void setDefaultSchema(String schema_name) { 1135 boolean ignore_case = isInCaseInsensitiveMode(); 1136 SchemaDef schema = resolveSchemaCase(schema_name, ignore_case); 1137 if (schema == null) { 1138 throw new Error ("Schema '" + schema_name + "' does not exist."); 1139 } 1140 else { 1141 setCurrentSchema(schema.getName()); 1143 } 1144 } 1145 1146 1149 private void checkExclusive() { 1150 if (!getLockingMechanism().isInExclusiveMode()) { 1151 throw new Error ("Assertion failed: Expected to be in exclusive mode."); 1152 } 1153 } 1154 1155 1158 public void createSchema(String name, String type) { 1159 checkExclusive(); 1161 getTransaction().createSchema(name, type); 1162 } 1163 1164 1167 public void dropSchema(String name) { 1168 checkExclusive(); 1170 getTransaction().dropSchema(name); 1171 } 1172 1173 1176 public boolean schemaExists(String name) { 1177 return getTransaction().schemaExists(name); 1178 } 1179 1180 1183 public SchemaDef resolveSchemaCase(String name, boolean ignore_case) { 1184 return getTransaction().resolveSchemaCase(name, ignore_case); 1185 } 1186 1187 1192 public SchemaDef resolveSchemaName(String name) { 1193 boolean ignore_case = isInCaseInsensitiveMode(); 1194 return resolveSchemaCase(name, ignore_case); 1195 } 1196 1197 1200 public SchemaDef[] getSchemaList() { 1201 return getTransaction().getSchemaList(); 1202 } 1203 1204 1207 public void setPersistentVar(String variable, String value) { 1208 checkExclusive(); 1210 getTransaction().setPersistentVar(variable, value); 1211 } 1212 1213 1216 public String getPersistentVar(String variable) { 1217 return getTransaction().getPersistantVar(variable); 1218 } 1219 1220 1223 public void addUniqueConstraint(TableName table_name, String [] cols, 1224 short deferred, String constraint_name) { 1225 checkExclusive(); 1227 getTransaction().addUniqueConstraint(table_name, cols, 1228 deferred, constraint_name); 1229 } 1230 1231 1234 public void addForeignKeyConstraint(TableName table, String [] cols, 1235 TableName ref_table, String [] ref_cols, 1236 String delete_rule, String update_rule, 1237 short deferred, String constraint_name) { 1238 checkExclusive(); 1240 getTransaction().addForeignKeyConstraint(table, cols, ref_table, ref_cols, 1241 delete_rule, update_rule, 1242 deferred, constraint_name); 1243 } 1244 1245 1248 public void addPrimaryKeyConstraint(TableName table_name, String [] cols, 1249 short deferred, String constraint_name) { 1250 checkExclusive(); 1252 getTransaction().addPrimaryKeyConstraint(table_name, cols, 1253 deferred, constraint_name); 1254 } 1255 1256 1259 public void addCheckConstraint(TableName table_name, 1260 Expression expression, short deferred, String constraint_name) { 1261 checkExclusive(); 1263 getTransaction().addCheckConstraint(table_name, expression, 1264 deferred, constraint_name); 1265 } 1266 1267 1270 public void dropAllConstraintsForTable(TableName table_name) { 1271 checkExclusive(); 1273 getTransaction().dropAllConstraintsForTable(table_name); 1274 } 1275 1276 1279 public int dropNamedConstraint(TableName table_name, 1280 String constraint_name) { 1281 checkExclusive(); 1283 return getTransaction().dropNamedConstraint(table_name, constraint_name); 1284 } 1285 1286 1289 public boolean dropPrimaryKeyConstraintForTable( 1290 TableName table_name, String constraint_name) { 1291 checkExclusive(); 1293 return getTransaction().dropPrimaryKeyConstraintForTable(table_name, 1294 constraint_name); 1295 } 1296 1297 1300 public TableName[] queryTablesRelationallyLinkedTo(TableName table) { 1301 return Transaction.queryTablesRelationallyLinkedTo(getTransaction(), table); 1302 } 1303 1304 1307 public Transaction.ColumnGroup[] queryTableUniqueGroups( 1308 TableName table_name) { 1309 return Transaction.queryTableUniqueGroups(getTransaction(), table_name); 1310 } 1311 1312 1315 public Transaction.ColumnGroup queryTablePrimaryKeyGroup( 1316 TableName table_name) { 1317 return Transaction.queryTablePrimaryKeyGroup(getTransaction(), table_name); 1318 } 1319 1320 1323 public Transaction.CheckExpression[] queryTableCheckExpressions( 1324 TableName table_name) { 1325 return Transaction.queryTableCheckExpressions(getTransaction(), table_name); 1326 } 1327 1328 1331 public Transaction.ColumnGroupReference[] queryTableForeignKeyReferences( 1332 TableName table_name) { 1333 return Transaction.queryTableForeignKeyReferences(getTransaction(), 1334 table_name); 1335 } 1336 1337 1340 public Transaction.ColumnGroupReference[] 1341 queryTableImportedForeignKeyReferences(TableName table_name) { 1342 return Transaction.queryTableImportedForeignKeyReferences(getTransaction(), 1343 table_name); 1344 } 1345 1346 1347 1353 1356 OldNewTableState getOldNewTableState() { 1357 return current_old_new_state; 1358 } 1359 1360 1365 void setOldNewTableState(OldNewTableState state) { 1366 current_old_new_state = state; 1367 } 1368 1369 1371 1377 void fireTableEvent(TableModificationEvent evt) { 1378 connection_trigger_manager.performTriggerAction(evt); 1379 } 1380 1381 1383 1390 public void fireTrigger(DatabaseConnection database, String trigger_name, 1391 TriggerEvent evt) { 1392 1393 if (this != database) { 1394 throw new Error ("User object mismatch."); 1395 } 1396 1397 try { 1398 if (call_back != null) { 1400 synchronized (trigger_event_buffer) { 1401 if (transaction == null) { 1403 call_back.triggerNotify(trigger_name, evt.getType(), 1404 evt.getSource(), evt.getCount()); 1405 } 1406 else { 1408 trigger_event_buffer.add(trigger_name); 1409 trigger_event_buffer.add(evt); 1410 } 1411 } 1412 } 1413 } 1414 catch (Throwable e) { 1415 Debug().write(Lvl.ERROR, this, "TRIGGER Exception: " + e.getMessage()); 1416 } 1417 } 1418 1419 1422 private void firePendingTriggerEvents() { 1423 int sz; 1424 synchronized (trigger_event_buffer) { 1425 sz = trigger_event_buffer.size(); 1426 } 1427 if (sz > 0) { 1428 Runnable runner = new Runnable () { 1430 public void run() { 1431 synchronized (trigger_event_buffer) { 1432 for (int i = 0; i < trigger_event_buffer.size(); i += 2) { 1434 String trigger_name = (String ) trigger_event_buffer.get(i); 1435 TriggerEvent evt = 1436 (TriggerEvent) trigger_event_buffer.get(i + 1); 1437 call_back.triggerNotify(trigger_name, evt.getType(), 1438 evt.getSource(), evt.getCount()); 1439 } 1440 trigger_event_buffer.clear(); 1442 } 1443 } 1444 }; 1445 1446 database.postEvent(3, database.createEvent(runner)); 1448 } 1449 1450 } 1451 1452 1455 private void disposeTransaction() { 1456 transaction = null; 1458 firePendingTriggerEvents(); 1460 trigger_event_list.clear(); 1462 1463 int sz = table_backed_cache_list.size(); 1465 for (int i = 0; i < sz; ++i) { 1466 TableBackedCache cache = 1467 (TableBackedCache) table_backed_cache_list.get(i); 1468 cache.transactionFinished(); 1469 } 1470 } 1471 1472 1484 public void commit() throws TransactionException { 1485 if (close_transaction_disabled) { 1487 throw new RuntimeException ("Commit is not allowed."); 1488 } 1489 1490 if (user != null) { 1491 user.refreshLastCommandTime(); 1492 } 1493 1494 getLockingMechanism().reset(); 1496 tables_cache.clear(); 1497 1498 if (transaction != null) { 1499 try { 1500 1501 transaction.closeAndCommit(); 1503 1504 database.getTriggerManager().flushTriggerEvents(trigger_event_list); 1506 1507 1508 } 1509 finally { 1510 disposeTransaction(); 1512 } 1513 } 1514 } 1515 1516 1525 public void rollback() { 1526 if (close_transaction_disabled) { 1528 throw new RuntimeException ("Rollback is not allowed."); 1529 } 1530 1531 if (user != null) { 1532 user.refreshLastCommandTime(); 1533 } 1534 1535 tables_cache.clear(); 1537 1538 if (transaction != null) { 1539 getLockingMechanism().reset(); 1540 try { 1541 transaction.closeAndRollback(); 1542 } 1543 finally { 1544 disposeTransaction(); 1546 if (jdbc_connection != null) { 1548 try { 1549 InternalJDBCHelper.disposeJDBCConnection(jdbc_connection); 1550 } 1551 catch (Throwable e) { 1552 Debug().write(Lvl.ERROR, this, 1553 "Error disposing internal JDBC connection."); 1554 Debug().writeException(Lvl.ERROR, e); 1555 } 1557 jdbc_connection = null; 1558 } 1559 } 1560 } 1561 } 1562 1563 1566 public void close() { 1567 try { 1568 rollback(); 1569 } 1570 catch (Throwable e) { 1571 e.printStackTrace(System.err); 1572 } 1573 finally { 1574 if (table_backed_cache_list != null) { 1575 try { 1576 int sz = table_backed_cache_list.size(); 1577 for (int i = 0; i < sz; ++i) { 1578 TableBackedCache cache = 1579 (TableBackedCache) table_backed_cache_list.get(i); 1580 cache.detatchFrom(conglomerate); 1581 } 1582 table_backed_cache_list = null; 1583 } 1584 catch (Throwable e) { 1585 e.printStackTrace(System.err); 1586 } 1587 } 1588 database.getTriggerManager().clearAllDatabaseConnectionTriggers(this); 1590 } 1591 } 1592 1593 1594 public void finalize() throws Throwable { 1595 super.finalize(); 1596 close(); 1597 } 1598 1599 1601 1604 private class DCProcedureConnection implements ProcedureConnection { 1605 1606 1609 private User previous_user; 1610 1611 1614 private boolean transaction_disabled_flag; 1615 1616 1619 private java.sql.Connection jdbc_connection; 1620 1621 1622 public java.sql.Connection getJDBCConnection() { 1623 if (jdbc_connection == null) { 1624 jdbc_connection = InternalJDBCHelper.createJDBCConnection(getUser(), 1625 DatabaseConnection.this); 1626 } 1627 return jdbc_connection; 1628 } 1629 1630 public Database getDatabase() { 1631 return DatabaseConnection.this.getDatabase(); 1632 } 1633 1634 1635 void dispose() { 1636 previous_user = null; 1637 if (jdbc_connection != null) { 1638 try { 1639 InternalJDBCHelper.disposeJDBCConnection(jdbc_connection); 1640 } 1641 catch (Throwable e) { 1642 Debug().write(Lvl.ERROR, this, 1643 "Error disposing internal JDBC connection."); 1644 Debug().writeException(Lvl.ERROR, e); 1645 } 1647 } 1648 } 1649 1650 } 1651 1652 1656 private class OldAndNewInternalTableInfo implements InternalTableInfo { 1657 1658 private boolean hasOLDTable() { 1659 return current_old_new_state.OLD_row_index != -1; 1660 } 1661 1662 private boolean hasNEWTable() { 1663 return current_old_new_state.NEW_row_data != null; 1664 } 1665 1666 public int getTableCount() { 1667 int count = 0; 1668 if (hasOLDTable()) { 1669 ++count; 1670 } 1671 if (hasNEWTable()) { 1672 ++count; 1673 } 1674 return count; 1675 } 1676 1677 public int findTableName(TableName name) { 1678 if (hasOLDTable() && name.equals(Database.OLD_TRIGGER_TABLE)) { 1679 return 0; 1680 } 1681 if (hasNEWTable() && name.equals(Database.NEW_TRIGGER_TABLE)) { 1682 if (hasOLDTable()) { 1683 return 1; 1684 } 1685 else { 1686 return 0; 1687 } 1688 } 1689 return -1; 1690 } 1691 1692 public TableName getTableName(int i) { 1693 if (hasOLDTable()) { 1694 if (i == 0) { 1695 return Database.OLD_TRIGGER_TABLE; 1696 } 1697 } 1698 return Database.NEW_TRIGGER_TABLE; 1699 } 1700 1701 public boolean containsTableName(TableName name) { 1702 return findTableName(name) != -1; 1703 } 1704 1705 public String getTableType(int i) { 1706 return "SYSTEM TABLE"; 1707 } 1708 1709 public DataTableDef getDataTableDef(int i) { 1710 DataTableDef table_def = DatabaseConnection.this.getDataTableDef( 1711 current_old_new_state.trigger_source); 1712 DataTableDef new_table_def = new DataTableDef(table_def); 1713 new_table_def.setTableName(getTableName(i)); 1714 return new_table_def; 1715 } 1716 1717 public MutableTableDataSource createInternalTable(int index) { 1718 DataTableDef t_def = getDataTableDef(index); 1719 1720 TriggeredOldNewDataSource table = 1721 new TriggeredOldNewDataSource(getSystem(), t_def); 1722 1723 if (hasOLDTable()) { 1724 if (index == 0) { 1725 1726 DataTable dtable = DatabaseConnection.this.getTable( 1728 current_old_new_state.trigger_source); 1729 RowData old_row_data = new RowData(table); 1730 int row_index = current_old_new_state.OLD_row_index; 1731 for (int i = 0; i < t_def.columnCount(); ++i) { 1732 old_row_data.setColumnDataFromTObject(i, 1733 dtable.getCellContents(i, row_index)); 1734 } 1735 table.setImmutable(true); 1737 table.setRowData(old_row_data); 1738 1739 return table; 1740 } 1741 } 1742 1743 table.setImmutable(!current_old_new_state.mutable_NEW); 1744 table.setRowData(current_old_new_state.NEW_row_data); 1745 1746 return table; 1747 } 1748 1749 } 1750 1751 1755 private static class TriggeredOldNewDataSource extends GTDataSource { 1756 1757 private DataTableDef table_def; 1758 1759 private RowData content; 1760 1761 private boolean immutable; 1762 1763 1766 public TriggeredOldNewDataSource(TransactionSystem system, 1767 DataTableDef table_def) { 1768 super(system); 1769 this.table_def = table_def; 1770 } 1771 1772 void setImmutable(boolean im) { 1773 this.immutable = im; 1774 } 1775 1776 void setRowData(RowData row_data) { 1777 this.content = row_data; 1778 } 1779 1780 public DataTableDef getDataTableDef() { 1781 return table_def; 1782 } 1783 1784 public int getRowCount() { 1785 return 1; 1786 } 1787 1788 public TObject getCellContents(final int column, final int row) { 1789 if (row < 0 || row > 0) { 1790 throw new RuntimeException ("Row index out of bounds."); 1791 } 1792 return content.getCellData(column); 1793 } 1794 1795 public int addRow(RowData row_data) { 1796 throw new RuntimeException ("Inserting into table '" + 1797 getDataTableDef().getTableName() + "' is not permitted."); 1798 } 1799 1800 public void removeRow(int row_index) { 1801 throw new RuntimeException ("Deleting from table '" + 1802 getDataTableDef().getTableName() + "' is not permitted."); 1803 } 1804 1805 public int updateRow(int row_index, RowData row_data) { 1806 if (immutable) { 1807 throw new RuntimeException ("Updating table '" + 1808 getDataTableDef().getTableName() + "' is not permitted."); 1809 } 1810 if (row_index < 0 || row_index > 0) { 1811 throw new RuntimeException ("Row index out of bounds."); 1812 } 1813 1814 int sz = getDataTableDef().columnCount(); 1815 for (int i = 0; i < sz; ++i) { 1816 content.setColumnDataFromTObject(i, row_data.getCellData(i)); 1817 } 1818 1819 return 0; 1820 } 1821 1822 public MasterTableJournal getJournal() { 1823 throw new RuntimeException ("Invalid method used."); 1825 } 1826 1827 public void flushIndexChanges() { 1828 throw new RuntimeException ("Invalid method used."); 1830 } 1831 1832 public void constraintIntegrityCheck() { 1833 } 1835 1836 } 1837 1838 1842 private final static DataTableDef[] INTERNAL_DEF_LIST; 1843 1844 static { 1845 INTERNAL_DEF_LIST = new DataTableDef[5]; 1846 INTERNAL_DEF_LIST[0] = GTStatisticsDataSource.DEF_DATA_TABLE_DEF; 1847 INTERNAL_DEF_LIST[1] = GTConnectionInfoDataSource.DEF_DATA_TABLE_DEF; 1848 INTERNAL_DEF_LIST[2] = GTCurrentConnectionsDataSource.DEF_DATA_TABLE_DEF; 1849 INTERNAL_DEF_LIST[3] = GTSQLTypeInfoDataSource.DEF_DATA_TABLE_DEF; 1850 INTERNAL_DEF_LIST[4] = GTPrivMapDataSource.DEF_DATA_TABLE_DEF; 1851 } 1852 1853 1857 private class ConnectionInternalTableInfo extends AbstractInternalTableInfo { 1858 1859 1862 public ConnectionInternalTableInfo() { 1863 super("SYSTEM TABLE", INTERNAL_DEF_LIST); 1864 } 1865 1866 1868 public MutableTableDataSource createInternalTable(int index) { 1869 if (index == 0) { 1870 return new GTStatisticsDataSource(DatabaseConnection.this).init(); 1871 } 1872 else if (index == 1) { 1873 return new GTConnectionInfoDataSource(DatabaseConnection.this).init(); 1874 } 1875 else if (index == 2) { 1876 return new GTCurrentConnectionsDataSource( 1877 DatabaseConnection.this).init(); 1878 } 1879 else if (index == 3) { 1880 return new GTSQLTypeInfoDataSource(DatabaseConnection.this).init(); 1881 } 1882 else if (index == 4) { 1883 return new GTPrivMapDataSource(DatabaseConnection.this); 1884 } 1885 else { 1886 throw new RuntimeException (); 1887 } 1888 } 1889 1890 } 1891 1892 1895 public static interface CallBack { 1896 1897 1901 void triggerNotify(String trigger_name, int trigger_event, 1902 String trigger_source, int fire_count); 1903 1904 } 1905 1906 1910 static class OldNewTableState { 1911 1912 1915 TableName trigger_source; 1916 1917 1921 int OLD_row_index = -1; 1922 1923 1927 RowData NEW_row_data; 1928 1929 1934 boolean mutable_NEW; 1935 1936 1939 DataTable OLD_data_table; 1940 1941 1944 DataTable NEW_data_table; 1945 1946 1949 OldNewTableState(TableName table_source, 1950 int old_d, RowData new_d, boolean is_mutable) { 1951 this.trigger_source = table_source; 1952 this.OLD_row_index = old_d; 1953 this.NEW_row_data = new_d; 1954 this.mutable_NEW = is_mutable; 1955 } 1956 1957 1960 OldNewTableState() { 1961 } 1962 1963 } 1964 1965} 1966 | Popular Tags |