From 93de8aa79a96752c31a9ddcfbc3fb1bc1c42cf86 Mon Sep 17 00:00:00 2001 From: mmichalek Date: Wed, 20 Jan 2016 15:51:57 -0500 Subject: [PATCH] Fix to include "SECURED" keyword when triggers wrap tables with row or column level security in z/OS. --- .../db/db2/Db2zOsTriggerTemplate.java | 23 +++++++-- .../java/org/jumpmind/db/model/Table.java | 16 ++++++ .../db/platform/db2/Db2zOsDdlReader.java | 50 ++++++++++++++++++- 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/db2/Db2zOsTriggerTemplate.java b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/db2/Db2zOsTriggerTemplate.java index 821d91cd06..2bb4c07767 100644 --- a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/db2/Db2zOsTriggerTemplate.java +++ b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/db2/Db2zOsTriggerTemplate.java @@ -20,7 +20,13 @@ */ package org.jumpmind.symmetric.db.db2; +import org.jumpmind.db.model.Table; import org.jumpmind.symmetric.db.ISymmetricDialect; +import org.jumpmind.symmetric.io.data.DataEventType; +import org.jumpmind.symmetric.model.Channel; +import org.jumpmind.symmetric.model.Trigger; +import org.jumpmind.symmetric.model.TriggerHistory; +import org.jumpmind.util.FormatUtils; public class Db2zOsTriggerTemplate extends Db2TriggerTemplate { @@ -31,7 +37,7 @@ public Db2zOsTriggerTemplate(ISymmetricDialect symmetricDialect) { "CREATE TRIGGER $(schemaName)$(triggerName) \n" + " AFTER INSERT ON $(schemaName)$(tableName) \n" + " REFERENCING NEW AS NEW \n" + -" FOR EACH ROW MODE DB2SQL \n" + +" FOR EACH ROW MODE DB2SQL $(isAccessControlled) \n" + " WHEN ($(syncOnInsertCondition) and $(syncOnIncomingBatchCondition)) \n" + " BEGIN ATOMIC \n" + " INSERT into $(defaultSchema)$(prefixName)_data \n" + @@ -48,7 +54,7 @@ public Db2zOsTriggerTemplate(ISymmetricDialect symmetricDialect) { "CREATE TRIGGER $(schemaName)$(triggerName) \n"+ " AFTER UPDATE ON $(schemaName)$(tableName) \n"+ " REFERENCING OLD AS OLD NEW AS NEW \n"+ -" FOR EACH ROW MODE DB2SQL \n"+ +" FOR EACH ROW MODE DB2SQL $(isAccessControlled) \n"+ " WHEN ($(syncOnUpdateCondition) and $(syncOnIncomingBatchCondition)) \n"+ " BEGIN ATOMIC \n"+ " INSERT into $(defaultSchema)$(prefixName)_data \n"+ @@ -69,7 +75,7 @@ public Db2zOsTriggerTemplate(ISymmetricDialect symmetricDialect) { "CREATE TRIGGER $(schemaName)$(triggerName) \n" + " AFTER DELETE ON $(schemaName)$(tableName) \n" + " REFERENCING OLD AS OLD \n" + -" FOR EACH ROW MODE DB2SQL \n" + +" FOR EACH ROW MODE DB2SQL $(isAccessControlled) \n" + " WHEN ($(syncOnDeleteCondition) and $(syncOnIncomingBatchCondition)) \n" + " BEGIN ATOMIC \n" + " INSERT into $(defaultSchema)$(prefixName)_data \n" + @@ -86,5 +92,14 @@ public Db2zOsTriggerTemplate(ISymmetricDialect symmetricDialect) { " END \n" ); } - + + @Override + protected String replaceTemplateVariables(DataEventType dml, Trigger trigger, + TriggerHistory history, Channel channel, String tablePrefix, Table originalTable, Table table, + String defaultCatalog, String defaultSchema, String ddl) { + ddl = super.replaceTemplateVariables(dml, trigger, history, channel, tablePrefix, + originalTable, table, defaultCatalog, defaultSchema, ddl); + ddl = FormatUtils.replace("isAccessControlled", table.isAccessControlled() ? " SECURED" : "", ddl); + return ddl; + } } \ No newline at end of file diff --git a/symmetric-db/src/main/java/org/jumpmind/db/model/Table.java b/symmetric-db/src/main/java/org/jumpmind/db/model/Table.java index 49d963bf06..49e4d5890a 100644 --- a/symmetric-db/src/main/java/org/jumpmind/db/model/Table.java +++ b/symmetric-db/src/main/java/org/jumpmind/db/model/Table.java @@ -63,6 +63,8 @@ public class Table implements Serializable, Cloneable, Comparable { /** The table's type as read from the database. */ private String type = null; + + private boolean isAccessControlled; /** The columns in this table. */ private ArrayList columns = new ArrayList(); @@ -1122,6 +1124,20 @@ public void setOldSchema(String oldSchema) { this.oldSchema = oldSchema; } + /** + * @return the isAccessControlled + */ + public boolean isAccessControlled() { + return isAccessControlled; + } + + /** + * @param isAccessControlled the isAccessControlled to set + */ + public void setAccessControlled(boolean isAccessControlled) { + this.isAccessControlled = isAccessControlled; + } + public Table copy() { try { return (Table) this.clone(); diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/db2/Db2zOsDdlReader.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/db2/Db2zOsDdlReader.java index ed7ce0ee10..0ef50dc68f 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/db2/Db2zOsDdlReader.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/db2/Db2zOsDdlReader.java @@ -40,6 +40,55 @@ public Db2zOsDdlReader(IDatabasePlatform platform) { @Override protected void enhanceTableMetaData(Connection connection, DatabaseMetaDataWrapper metaData, Table table) throws SQLException { + setAutoIncrementMetaData(connection, metaData, table); + setIsAccessControlledMetaData(connection, metaData, table); + + } + + /** + * @param connection + * @param metaData + * @param table + */ + protected void setIsAccessControlledMetaData(Connection connection, DatabaseMetaDataWrapper metaData, Table table) throws SQLException { + log.debug("about to read access control meta data."); + + String sql = "SELECT COUNT(*) AS ACCESS_CONTROLS FROM SYSIBM.SYSCONTROLS WHERE TBNAME = ?"; + if (StringUtils.isNotBlank(table.getSchema())) { + sql = sql + " AND TBSCHEMA=?"; + } + + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + pstmt = connection.prepareStatement(sql); + pstmt.setString(1, table.getName()); + if (StringUtils.isNotBlank(table.getSchema())) { + pstmt.setString(2, table.getSchema()); + } + + rs = pstmt.executeQuery(); + if (rs.next()) { + int accessControlCount = rs.getInt(1); + if (accessControlCount > 0) { + table.setAccessControlled(true); + log.debug("Table {} has {} access controls.", table.getName(), accessControlCount); + } + } + } finally { + JdbcSqlTemplate.close(rs); + JdbcSqlTemplate.close(pstmt); + } + log.debug("done reading access control meta data."); + } + + /** + * @param connection + * @param metaData + * @param table + * @throws SQLException + */ + protected void setAutoIncrementMetaData(Connection connection, DatabaseMetaDataWrapper metaData, Table table) throws SQLException { log.debug("about to read additional column data"); /* DB2 does not return the auto-increment status via the database metadata */ @@ -75,7 +124,6 @@ protected void enhanceTableMetaData(Connection connection, DatabaseMetaDataWrapp JdbcSqlTemplate.close(pstmt); } log.debug("done reading additional column data"); - }