oldAutoCommitKnown = true;
conn.setAutoCommit(false); // everything will be handled within the same transaction
if (command.equalsIgnoreCase(REPLICATION_CMD)) {
for (int i=0; i < rows.size(); i++) {
SqlRow row = ((SqlRow)rows.get(i)).cloneRow();
// TODO consistency check
action = getStringAttribute(ACTION_ATTR, row, description);
originalCatalog = getStringAttribute(CATALOG_ATTR, row, description);
originalSchema = getStringAttribute(SCHEMA_ATTR, row, description);
originalTable = getStringAttribute(TABLE_NAME_ATTR, row, description);
// row specific but still without considering colums
catalog = this.mapper.getMappedCatalog(originalCatalog, originalSchema, originalTable, null, originalCatalog);
schema = this.mapper.getMappedSchema(originalCatalog, originalSchema, originalTable, null, originalSchema);
table = this.mapper.getMappedTable(originalCatalog, originalSchema, originalTable, null, originalTable);
if (action == null)
throw new Exception(ME + ".store: row with no action invoked '" + row.toXml("", true, false, true));
int count = modifyColumnsIfNecessary(originalCatalog, originalSchema, originalTable, row);
if (count != 0) {
if (log.isLoggable(Level.FINE)) log.fine("modified '" + count + "' entries");
}
if (log.isLoggable(Level.FINE)) log.fine("store: " + row.toXml("", true, true, true));
SqlDescription desc = getTableDescription(catalog, schema, table, conn);
boolean process = true;
if (this.prePostStatement != null) // row is the modified column name
process = this.prePostStatement.preStatement(action, conn, dbInfo, desc, row);
if (process) {
if (action.equalsIgnoreCase(INSERT_ACTION)) {
desc.insert(conn, row);
}
else if (action.equalsIgnoreCase(UPDATE_ACTION)) {
desc.update(conn, row, this.parserForOldInUpdates);
}
else if (action.equalsIgnoreCase(DELETE_ACTION)) {
desc.delete(conn, row);
}
else { // TODO implement this possibility too
if (action.equalsIgnoreCase(CREATE_ACTION) ||
action.equalsIgnoreCase(ALTER_ACTION) ||
action.equalsIgnoreCase(DROP_ACTION)) {
throw new Exception("The execution of action='" + action + "' inside a multi-operation transaction is not implemented");
}
else // we don't throw an exception here to be backwards compatible. In future we can throw one
log.severe("The action='" + action + "' is not recognized as an SQL operation and will therefore not be executed");
}
if (this.prePostStatement != null)
this.prePostStatement.postStatement(action, conn, dbInfo, desc, row);
}
}
}
else { // then it is a CREATE / DROP / ALTER or DUMP command (does not have any rows associated)
if (action.equalsIgnoreCase(CREATE_ACTION)) {
if (this.doCreate) {
// check if the table already exists ...
ResultSet rs = conn.getMetaData().getTables(catalog, schema, table, null);
boolean tableExistsAlready = rs.next();
rs.close();
boolean invokeCreate = true;
completeTableName = table;
if (schema != null && schema.length() > 1)
completeTableName = schema + "." + table;
boolean process = true;
SqlDescription desc = getTableDescription(catalog, schema, table, conn);
if (this.prePostStatement != null) {
final SqlRow currentRow = null;
process = this.prePostStatement.preStatement(action, conn, dbInfo, desc, currentRow);
}
if (process) {
if (tableExistsAlready) {
if (!this.overwriteTables) {
throw new Exception("ReplicationStorer.store: the table '" + completeTableName + "' exists already and 'replication.overwriteTables' is set to 'false'");
}
else {
if (this.recreateTables) {
log.warning("store: the table '" + completeTableName + "' exists already. 'replication.overwriteTables' is set to 'true': will drop the table and recreate it");
Statement st = conn.createStatement();
st.executeUpdate("DROP TABLE " + completeTableName);
st.close();
}
else {
log.warning("store: the table '" + completeTableName + "' exists already. 'replication.overwriteTables' is set to 'true' and 'replication.recreateTables' is set to false. Will only delete contents of table but keep the old structure");
invokeCreate = false;
}
}
}
String sql = null;
if (invokeCreate) {
sql = this.dbSpecific.getCreateTableStatement(description, this.mapper);
log.info("CREATE STATEMENT: '" + sql + "'");
}
else {
sql = "DELETE FROM " + completeTableName;
log.info("CLEANING UP TABLE '" + completeTableName + "'");
}
Statement st = conn.createStatement();
try {
st.executeUpdate(sql);
}
finally {
st.close();
}
if (this.prePostStatement != null) {
final SqlRow currentRow = null;
this.prePostStatement.postStatement(action, conn, dbInfo, desc, currentRow);
}
}
}
else
log.fine("CREATE is disabled for this writer");
}
else if (action.equalsIgnoreCase(DROP_ACTION)) {
if (this.doDrop) {
boolean process = true;
SqlDescription desc = getTableDescription(catalog, schema, table, conn);
if (this.prePostStatement != null) {
final SqlRow currentRow = null;
process = this.prePostStatement.preStatement(action, conn, dbInfo, desc, currentRow);
}
if (process) {
completeTableName = table;
if (schema != null && schema.length() > 1)
completeTableName = schema + "." + table;
String sql = "DROP TABLE " + completeTableName;
Statement st = conn.createStatement();
try {
st.executeUpdate(sql);
}
catch (SQLException e) {
// this is currently only working on oracle: TODO make it work for other DB too.
if (e.getMessage().indexOf("does not exist") > -1)
log.warning("table '" + completeTableName + "' was not found and could therefore not be dropped. Continuing anyway");
else
throw e;
}
finally {
st.close();
}
if (this.prePostStatement != null) {
final SqlRow currentRow = null;
this.prePostStatement.postStatement(action, conn, dbInfo, desc, currentRow);
}
}
}
else
log.fine("DROP is disabled for this writer");
}
else if (action.equalsIgnoreCase(ALTER_ACTION)) {
if (this.doAlter) {
boolean process = true;
SqlDescription desc = getTableDescription(catalog, schema, table, conn);
if (this.prePostStatement != null) {
final SqlRow currentRow = null;
process = this.prePostStatement.preStatement(action, conn, dbInfo, desc, currentRow);
}
if (process) {
log.severe("store: operation '" + action + "' invoked but not implemented yet '" + description.toXml(""));
if (this.prePostStatement != null) {
final SqlRow currentRow = null;
this.prePostStatement.postStatement(action, conn, dbInfo, desc, currentRow);
}
}
}
else