From 4d933e828780b1c672eb2eb6e2b12a2a548f3951 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Mon, 17 Aug 2015 19:27:33 -0500 Subject: [PATCH] refactor IDEMPIERE-1132 foreign key management for ticket IDEMPIERE-2745 --- .../oracle/201508171408_IDEMPIERE-2745.sql | 16 + .../201508171408_IDEMPIERE-2745.sql | 13 + .../src/org/compiere/process/ColumnSync.java | 4 +- .../src/org/compiere/model/MColumn.java | 181 ++++++- .../compiere/process/CreateForeignKey.java | 501 ++++++------------ .../pipo2/handler/ColumnElementHandler.java | 31 +- 6 files changed, 364 insertions(+), 382 deletions(-) create mode 100644 migration/i2.1/oracle/201508171408_IDEMPIERE-2745.sql create mode 100644 migration/i2.1/postgresql/201508171408_IDEMPIERE-2745.sql diff --git a/migration/i2.1/oracle/201508171408_IDEMPIERE-2745.sql b/migration/i2.1/oracle/201508171408_IDEMPIERE-2745.sql new file mode 100644 index 0000000000..8f731e1901 --- /dev/null +++ b/migration/i2.1/oracle/201508171408_IDEMPIERE-2745.sql @@ -0,0 +1,16 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- IDEMPIERE-1132 Improve AD_Index; AD_View; foreign keys management +-- Aug 17, 2015 7:18:22 PM COT +UPDATE AD_Process_Para SET IsMandatory='N',Updated=TO_DATE('2015-08-17 19:18:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200069 +; + +-- IDEMPIERE-2745 2Pack is not creating foreign keys +update ad_column set fkconstrainttype='D' where fkconstrainttype is null and columnname in ('AD_Client_ID','AD_Org_ID','CreatedBy','UpdatedBy') and ad_reference_id in (18,19,30) +; + + +SELECT register_migration_script('201508171408_IDEMPIERE-2745.sql') FROM dual +; + diff --git a/migration/i2.1/postgresql/201508171408_IDEMPIERE-2745.sql b/migration/i2.1/postgresql/201508171408_IDEMPIERE-2745.sql new file mode 100644 index 0000000000..4fc53a975c --- /dev/null +++ b/migration/i2.1/postgresql/201508171408_IDEMPIERE-2745.sql @@ -0,0 +1,13 @@ +-- IDEMPIERE-1132 Improve AD_Index; AD_View; foreign keys management +-- Aug 17, 2015 7:18:22 PM COT +UPDATE AD_Process_Para SET IsMandatory='N',Updated=TO_TIMESTAMP('2015-08-17 19:18:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200069 +; + +-- IDEMPIERE-2745 2Pack is not creating foreign keys +update ad_column set fkconstrainttype='D' where fkconstrainttype is null and columnname in ('AD_Client_ID','AD_Org_ID','CreatedBy','UpdatedBy') and ad_reference_id in (18,19,30) +; + + +SELECT register_migration_script('201508171408_IDEMPIERE-2745.sql') FROM dual +; + diff --git a/org.adempiere.base.process/src/org/compiere/process/ColumnSync.java b/org.adempiere.base.process/src/org/compiere/process/ColumnSync.java index 2c2d9b88eb..a44119b38e 100644 --- a/org.adempiere.base.process/src/org/compiere/process/ColumnSync.java +++ b/org.adempiere.base.process/src/org/compiere/process/ColumnSync.java @@ -128,14 +128,14 @@ public class ColumnSync extends SvrProcess MColumn[] cols = table.getColumns(false); for (MColumn col : cols) { - String fkConstraintSql = MColumn.getForeignKeyConstraintSql(md, catalog, schema, tableName, table, col); + String fkConstraintSql = MColumn.getForeignKeyConstraintSql(md, catalog, schema, tableName, table, col, false); if (fkConstraintSql != null && fkConstraintSql.length() > 0) sql += fkConstraintSql; } } else { - String fkConstraintSql = MColumn.getForeignKeyConstraintSql(md, catalog, schema, tableName, table, column); + String fkConstraintSql = MColumn.getForeignKeyConstraintSql(md, catalog, schema, tableName, table, column, false); if (fkConstraintSql != null && fkConstraintSql.length() > 0) sql += fkConstraintSql; } diff --git a/org.adempiere.base/src/org/compiere/model/MColumn.java b/org.adempiere.base/src/org/compiere/model/MColumn.java index 10c95e5986..8858d88a5c 100644 --- a/org.adempiere.base/src/org/compiere/model/MColumn.java +++ b/org.adempiere.base/src/org/compiere/model/MColumn.java @@ -32,7 +32,6 @@ import java.util.Properties; import java.util.logging.Level; import org.adempiere.exceptions.DBException; -import org.compiere.process.CreateForeignKey; import org.compiere.util.CCache; import org.compiere.util.CLogger; import org.compiere.util.DB; @@ -52,7 +51,7 @@ public class MColumn extends X_AD_Column /** * */ - private static final long serialVersionUID = -3735608010271317406L; + private static final long serialVersionUID = -7261365443985547106L; /** * Get MColumn from Cache @@ -840,7 +839,7 @@ public class MColumn extends X_AD_Column return table; } - public static String getForeignKeyConstraintSql(DatabaseMetaData md, String catalog, String schema, String tableName, MTable table, MColumn column) throws Exception + public static String getForeignKeyConstraintSql(DatabaseMetaData md, String catalog, String schema, String tableName, MTable table, MColumn column, boolean isNoTable) throws Exception { StringBuilder fkConstraintSql = new StringBuilder(); @@ -859,29 +858,35 @@ public class MColumn extends X_AD_Column else if (md.storesLowerCaseIdentifiers()) referenceTableName = referenceTableName.toLowerCase(); - ResultSet rs = md.getCrossReference(catalog, schema, referenceTableName, catalog, schema, tableName); - while (rs.next()) - { - String dbFKName = rs.getString("FK_NAME"); - if (dbFKName == null) - continue; + if (!isNoTable) { + ResultSet rs = null; + try { + rs = md.getCrossReference(catalog, schema, referenceTableName, catalog, schema, tableName); + while (rs.next()) + { + String dbFKName = rs.getString("FK_NAME"); + if (dbFKName == null) + continue; - String dbFKTable = rs.getString("FKTABLE_NAME"); - short deleteRule = rs.getShort("DELETE_RULE"); + String dbFKTable = rs.getString("FKTABLE_NAME"); + short deleteRule = rs.getShort("DELETE_RULE"); - String key = dbFKName.toLowerCase(); - DatabaseKey dbForeignKey = htForeignKeys.get(key); - if (dbForeignKey == null) - dbForeignKey = new DatabaseKey(dbFKName, dbFKTable, new String[30], deleteRule); + String key = dbFKName.toLowerCase(); + DatabaseKey dbForeignKey = htForeignKeys.get(key); + if (dbForeignKey == null) + dbForeignKey = new DatabaseKey(dbFKName, dbFKTable, new String[30], deleteRule); - String columnName = rs.getString("FKCOLUMN_NAME"); - int pos = (rs.getShort("KEY_SEQ")); - if (pos > 0) - dbForeignKey.getKeyColumns()[pos-1] = columnName; + String columnName = rs.getString("FKCOLUMN_NAME"); + int pos = (rs.getShort("KEY_SEQ")); + if (pos > 0) + dbForeignKey.getKeyColumns()[pos-1] = columnName; - htForeignKeys.put(key, dbForeignKey); + htForeignKeys.put(key, dbForeignKey); + } + } finally { + DB.close(rs); rs = null; + } } - rs.close(); Enumeration en = htForeignKeys.keys(); while (en.hasMoreElements()) @@ -900,24 +905,34 @@ public class MColumn extends X_AD_Column DatabaseKey dbForeignKey = htForeignKeys.get(key); if (dbForeignKey.getKeyColumns()[0].equalsIgnoreCase(column.getColumnName())) { - DatabaseKey primaryKey = CreateForeignKey.getPrimaryKey(md, referenceTableName); + DatabaseKey primaryKey = getPrimaryKey(md, referenceTableName); if (primaryKey != null) { fkConstraintSql.append(DB.SQLSTATEMENT_SEPARATOR); fkConstraintSql.append("ALTER TABLE ").append(table.getTableName()); fkConstraintSql.append(" DROP CONSTRAINT ").append(dbForeignKey.getKeyName()); - String dbDeleteRule = MColumn.FKCONSTRAINTTYPE_NoAction; + String dbDeleteRule = null; if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyCascade) dbDeleteRule = MColumn.FKCONSTRAINTTYPE_Cascade; else if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeySetNull) dbDeleteRule = MColumn.FKCONSTRAINTTYPE_SetNull; - + else if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyNoAction || dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyRestrict) + dbDeleteRule = MColumn.FKCONSTRAINTTYPE_NoAction; String fkConstraintType = column.getFKConstraintType(); - if (fkConstraintType == null) + if (fkConstraintType == null) { fkConstraintType = dbDeleteRule; - if (fkConstraintType == null) - fkConstraintType = MColumn.FKCONSTRAINTTYPE_NoAction; + if (fkConstraintType == null) { + if ( "AD_Client_ID".equals(column.getColumnName()) + || "AD_Org_ID".equals(column.getColumnName()) + || "CreatedBy".equals(column.getColumnName()) + || "UpdatedBy".equals(column.getColumnName()) + ) + fkConstraintType = MColumn.FKCONSTRAINTTYPE_DoNotCreate; + else + fkConstraintType = MColumn.FKCONSTRAINTTYPE_NoAction; + } + } if (!fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_DoNotCreate)) { String fkConstraintName = column.getFKConstraintName(); @@ -962,7 +977,7 @@ public class MColumn extends X_AD_Column if (!modified) { - String fkConstraint = CreateForeignKey.getForeignKeyConstraint(md, table, column); + String fkConstraint = getForeignKeyConstraint(md, table, column); if (fkConstraint != null && fkConstraint.length() > 0) { fkConstraintSql.append(DB.SQLSTATEMENT_SEPARATOR); @@ -977,4 +992,114 @@ public class MColumn extends X_AD_Column return fkConstraintSql.toString(); } + public static DatabaseKey getPrimaryKey(DatabaseMetaData md, String primaryTableName) throws Exception + { + DatabaseKey primaryKey = null; + + String catalog = DB.getDatabase().getCatalog(); + String schema = DB.getDatabase().getSchema(); + + String tableName = primaryTableName; + if (md.storesUpperCaseIdentifiers()) + tableName = tableName.toUpperCase(); + else if (md.storesLowerCaseIdentifiers()) + tableName = tableName.toLowerCase(); + + ResultSet rs = null; + try { + rs = md.getPrimaryKeys(catalog, schema, tableName); + while (rs.next()) + { + String primaryKeyName = rs.getString("PK_NAME"); + if (primaryKeyName == null) + continue; + + String primaryKeyTableName = rs.getString("TABLE_NAME"); + short deleteRule = -1; + + if (primaryKey == null) + primaryKey = new DatabaseKey(primaryKeyName, primaryKeyTableName, new String[30], deleteRule); + + String primaryKeyColumn = rs.getString("COLUMN_NAME"); + int pos = (rs.getShort("KEY_SEQ")); + if (pos > 0) + primaryKey.getKeyColumns()[pos-1] = primaryKeyColumn; + } + } catch (Exception e) { + DB.close(rs); rs = null; + } + return primaryKey; + } + + public static String getForeignKeyConstraint(DatabaseMetaData md, MTable table, MColumn column) throws Exception + { + if (!column.isKey() && !column.getColumnName().equals(PO.getUUIDColumnName(table.getTableName()))) + { + String fkConstraintType = column.getFKConstraintType(); + if (fkConstraintType == null) + fkConstraintType = MColumn.FKCONSTRAINTTYPE_NoAction; + + if (fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_DoNotCreate)) + return ""; + + int refid = column.getAD_Reference_ID(); + if (refid != DisplayType.List && refid != DisplayType.Payment) + { + String referenceTableName = column.getReferenceTableName(); + if (referenceTableName != null) + { + DatabaseKey primaryKey = MColumn.getPrimaryKey(md, referenceTableName); + + if (primaryKey != null) + { + String fkConstraintName = column.getFKConstraintName(); + if (fkConstraintName == null || fkConstraintName.trim().length() == 0) + { + String columnName = column.getColumnName(); + if (columnName.toUpperCase().endsWith("_ID")) + columnName = columnName.substring(0, columnName.length() - 3); + + StringBuilder constraintName = new StringBuilder(); + constraintName.append(columnName.replace("_", "")); + constraintName.append("_"); + constraintName.append(table.getTableName().replace("_", "")); + if (constraintName.length() > 30) + constraintName = new StringBuilder(constraintName.substring(0, 30)); + fkConstraintName = constraintName.toString(); + } + + StringBuilder fkConstraint = new StringBuilder(); + fkConstraint.append("CONSTRAINT ").append(fkConstraintName); + fkConstraint.append(" FOREIGN KEY (").append(column.getColumnName()).append(") REFERENCES "); + fkConstraint.append(primaryKey.getKeyTable()).append("(").append(primaryKey.getKeyColumns()[0]); + for (int i = 1; i < primaryKey.getKeyColumns().length; i++) + { + if (primaryKey.getKeyColumns()[i] == null) + break; + fkConstraint.append(", ").append(primaryKey.getKeyColumns()[i]); + } + fkConstraint.append(")"); + + if (fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_NoAction)) + ; + else if (fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_Cascade)) + fkConstraint.append(" ON DELETE CASCADE"); + else if (fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_SetNull)) + fkConstraint.append(" ON DELETE SET NULL"); + + fkConstraint.append(" DEFERRABLE INITIALLY DEFERRED"); + + column.setFKConstraintName(fkConstraintName); + column.setFKConstraintType(fkConstraintType); + column.saveEx(); + + return fkConstraint.toString(); + } + } + } + } + + return ""; + } + } // MColumn diff --git a/org.adempiere.base/src/org/compiere/process/CreateForeignKey.java b/org.adempiere.base/src/org/compiere/process/CreateForeignKey.java index 16619b8cb1..6f0dd64f87 100644 --- a/org.adempiere.base/src/org/compiere/process/CreateForeignKey.java +++ b/org.adempiere.base/src/org/compiere/process/CreateForeignKey.java @@ -26,7 +26,6 @@ import org.compiere.model.MColumn; import org.compiere.model.MTable; import org.compiere.model.PO; import org.compiere.util.DB; -import org.compiere.util.DisplayType; import org.compiere.util.Msg; import org.compiere.util.Trx; @@ -69,7 +68,7 @@ public class CreateForeignKey extends SvrProcess { { if (log.isLoggable(Level.INFO)) log.info("AD_Table_ID=" + p_AD_Table_ID + ", AD_Column_ID=" + p_AD_Column_ID); - Trx trx = Trx.get(get_TrxName(), true); + Trx trx = Trx.get(get_TrxName(), false); DatabaseMetaData md = trx.getConnection().getMetaData(); if (p_AD_Column_ID > 0) @@ -88,14 +87,14 @@ public class CreateForeignKey extends SvrProcess { else if (p_AD_Table_ID > 0) { MTable table = new MTable(getCtx(), p_AD_Table_ID, get_TrxName()); - if (table != null) + if (table != null) { + addLog(table.getAD_Table_ID(), null, null, Msg.getMsg(getCtx(), "CreateForeignKeyProcessTable") + table.getTableName(), table.get_Table_ID(), table.getAD_Table_ID()); processDatabaseTableColumn(md, table, null); + } } else processDatabase(md); - - trx.close(); - + return Msg.getMsg(getCtx(), "CreateForeignKeyProcessResult", new Object[] {countTable, countForeignKey, countError}); } @@ -106,18 +105,24 @@ public class CreateForeignKey extends SvrProcess { String schema = DB.getDatabase().getSchema(); String[] types = {"TABLE"}; - ResultSet rs = md.getTables(catalog, schema, tableName, types); - while (rs.next()) - { - String dbTableName = rs.getString("TABLE_NAME"); - if (dbTableName == null) - continue; - MTable table = MTable.get(getCtx(), dbTableName); - if (table != null) // exists in AD_Table - processDatabaseTableColumn(md, table, null); + ResultSet rs = null; + try { + rs = md.getTables(catalog, schema, tableName, types); + while (rs.next()) + { + String dbTableName = rs.getString("TABLE_NAME"); + if (dbTableName == null) + continue; + MTable table = MTable.get(getCtx(), dbTableName); + if (table != null) { // exists in AD_Table + addLog(table.getAD_Table_ID(), null, null, Msg.getMsg(getCtx(), "CreateForeignKeyProcessTable") + table.getTableName(), table.get_Table_ID(), table.getAD_Table_ID()); + processDatabaseTableColumn(md, table, null); + } + } + } finally { + DB.close(rs); rs = null; } - rs.close(); } private void processDatabaseTableColumn(DatabaseMetaData md, MTable table, MColumn column) throws Exception @@ -133,13 +138,9 @@ public class CreateForeignKey extends SvrProcess { else if (md.storesLowerCaseIdentifiers()) tableName = tableName.toLowerCase(); - addLog(Msg.getMsg(getCtx(), "CreateForeignKeyProcessTable") + tableName); - addLog(table.getAD_Table_ID(), null, null, table.toString(), table.get_Table_ID(), table.getAD_Table_ID()); - ++countTable; - - if (column == null) - { - ResultSet rs = md.getImportedKeys(catalog, schema, tableName); + ResultSet rs = null; + try { + rs = md.getImportedKeys(catalog, schema, tableName); while (rs.next()) { String dbFKName = rs.getString("FK_NAME"); @@ -148,7 +149,7 @@ public class CreateForeignKey extends SvrProcess { String dbFKTable = rs.getString("FKTABLE_NAME"); short deleteRule = rs.getShort("DELETE_RULE"); - + String key = dbFKName.toLowerCase(); DatabaseKey dbForeignKey = htForeignKeys.get(key); if (dbForeignKey == null) @@ -161,336 +162,164 @@ public class CreateForeignKey extends SvrProcess { htForeignKeys.put(key, dbForeignKey); } - rs.close(); - - Enumeration en = htForeignKeys.keys(); + } finally { + DB.close(rs); rs = null; + } + + Enumeration en = htForeignKeys.keys(); + while (en.hasMoreElements()) + { + String key = en.nextElement(); + DatabaseKey dbForeignKey = htForeignKeys.get(key); + if (dbForeignKey.getKeyColumns()[1] != null) + htForeignKeys.remove(key); + } + + ++countTable; + + if (column == null) + { + final String getColumnIDSql = "SELECT AD_Column_ID FROM AD_Column WHERE AD_Table_ID = ? AND LOWER(ColumnName) = ?"; + try { + rs = md.getColumns(catalog, schema, tableName, null); + while (rs.next()) + { + String columnName = rs.getString("COLUMN_NAME"); + if (columnName == null) + continue; + + int AD_Column_ID = DB.getSQLValue(null, getColumnIDSql, table.getAD_Table_ID(), columnName.toLowerCase()); + if (AD_Column_ID > 0) + { + column = MColumn.get(getCtx(), AD_Column_ID); + if (column == null) + continue; + String foreignTable = column.getReferenceTableName(); + if (foreignTable != null && ! "AD_Ref_List".equals(foreignTable)) + processDatabaseTableColumn(md, table, column); + } + } + } finally { + DB.close(rs); rs = null; + } + } + else + { + if (processUI != null) + processUI.statusUpdate(table.getTableName() + "." + column.getColumnName()); + boolean modified = false; + en = htForeignKeys.keys(); while (en.hasMoreElements()) { String key = en.nextElement(); DatabaseKey dbForeignKey = htForeignKeys.get(key); - if (dbForeignKey.getKeyColumns()[1] != null) - htForeignKeys.remove(key); - } - - String getColumnIDSql = "SELECT AD_Column_ID FROM AD_Column WHERE AD_Table_ID = ? AND LOWER(ColumnName) = ?"; - rs = md.getColumns(catalog, schema, tableName, null); - while (rs.next()) - { - String columnName = rs.getString("COLUMN_NAME"); - if (columnName == null) - continue; - int AD_Column_ID = DB.getSQLValue(null, getColumnIDSql, table.getAD_Table_ID(), columnName.toLowerCase()); - if (AD_Column_ID > 0) - { - column = MColumn.get(getCtx(), AD_Column_ID); - if (column == null) - continue; - - boolean modified = false; - en = htForeignKeys.keys(); - while (en.hasMoreElements()) - { - String key = en.nextElement(); - DatabaseKey dbForeignKey = htForeignKeys.get(key); - - String dbDeleteRule = MColumn.FKCONSTRAINTTYPE_NoAction; - if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyCascade) - dbDeleteRule = MColumn.FKCONSTRAINTTYPE_Cascade; - else if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeySetNull) - dbDeleteRule = MColumn.FKCONSTRAINTTYPE_SetNull; - - String fkConstraintType = column.getFKConstraintType(); - if (fkConstraintType == null) + String dbDeleteRule = null; + if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyCascade) + dbDeleteRule = MColumn.FKCONSTRAINTTYPE_Cascade; + else if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeySetNull) + dbDeleteRule = MColumn.FKCONSTRAINTTYPE_SetNull; + else if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyNoAction || dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyRestrict) + dbDeleteRule = MColumn.FKCONSTRAINTTYPE_NoAction; + String fkConstraintType = column.getFKConstraintType(); + if (fkConstraintType == null) { + fkConstraintType = dbDeleteRule; + if (fkConstraintType == null) { + if ( "AD_Client_ID".equals(column.getColumnName()) + || "AD_Org_ID".equals(column.getColumnName()) + || "CreatedBy".equals(column.getColumnName()) + || "UpdatedBy".equals(column.getColumnName()) + ) + fkConstraintType = MColumn.FKCONSTRAINTTYPE_DoNotCreate; + else fkConstraintType = MColumn.FKCONSTRAINTTYPE_NoAction; - - if (dbForeignKey.getKeyColumns()[0].equalsIgnoreCase(column.getColumnName())) - { - if (dbDeleteRule.equals(fkConstraintType)) - { - addLog(Msg.getMsg(getCtx(), "CreateForeignKeyProcessColumn") + column.getColumnName()); - addLog(column.getAD_Column_ID(), null, null, column.toString(), column.get_Table_ID(), column.getAD_Column_ID()); - addLog(0, null, null, Msg.getMsg(getCtx(), "CreateForeignKeyProcessExists") + dbForeignKey.getKeyName()); - modified = true; - column.setFKConstraintName(dbForeignKey.getKeyName()); - column.setFKConstraintType(fkConstraintType); - column.saveEx(); - break; - } - else if (fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_DoNotCreate)) - { - addLog(Msg.getMsg(getCtx(), "CreateForeignKeyProcessColumn") + column.getColumnName()); - addLog(column.getAD_Column_ID(), null, null, column.toString(), column.get_Table_ID(), column.getAD_Column_ID()); - addLog(0, null, null, Msg.getMsg(getCtx(), "CreateForeignKeyProcessExists") + dbForeignKey.getKeyName()); - - StringBuilder sql = new StringBuilder(); - sql.append("ALTER TABLE ").append(table.getTableName()); - sql.append(" DROP CONSTRAINT ").append(dbForeignKey.getKeyName()); - - Trx trx = Trx.get(Trx.createTrxName("CreateForeignKey"), true); - try { - int rvalue = DB.executeUpdate(sql.toString(), (Object[]) null, true, trx.getTrxName()); - addLog(0, null, new BigDecimal(rvalue), sql.toString()); - } catch (Exception e) { - addLog(Msg.getMsg(getCtx(), "Error") + e.getLocalizedMessage()); - if (trx != null) - trx.rollback(); - } finally { - if (trx != null) - trx.close(); - } - - modified = true; - column.setFKConstraintName(dbForeignKey.getKeyName()); - column.setFKConstraintType(fkConstraintType); - column.saveEx(); - break; - } - } - } - - if (modified) - continue; - - if (!column.isKey() && !column.getColumnName().equals(PO.getUUIDColumnName(table.getTableName()))) - { - String fkConstraint = getForeignKeyConstraint(md, table, column); - if (fkConstraint != null && fkConstraint.length() > 0) - { - addLog(Msg.getMsg(getCtx(), "CreateForeignKeyProcessColumn") + column.getColumnName()); - addLog(column.getAD_Column_ID(), null, null, column.toString(), column.get_Table_ID(), column.getAD_Column_ID()); - - StringBuilder sql = new StringBuilder(); - sql.append("ALTER TABLE ").append(table.getTableName()); - sql.append(" ADD "); - sql.append(fkConstraint); - - Trx trx = Trx.get(Trx.createTrxName("CreateForeignKey"), true); - try { - int rvalue = DB.executeUpdate(sql.toString(), (Object[]) null, true, trx.getTrxName()); - addLog(0, null, new BigDecimal(rvalue), sql.toString()); - if (rvalue == -1) - ++countError; - else - ++countForeignKey; - } catch (Exception e) { - addLog(Msg.getMsg(getCtx(), "Error") + e.getLocalizedMessage()); - if (trx != null) - trx.rollback(); - ++countError; - } finally { - if (trx != null) - trx.close(); - } - } } } - } - rs.close(); - } - else - { - int refid = column.getAD_Reference_ID(); - if (refid != DisplayType.List && refid != DisplayType.Payment) - { - String referenceTableName = column.getReferenceTableName(); - - if (referenceTableName != null) - { - if (md.storesUpperCaseIdentifiers()) - referenceTableName = referenceTableName.toUpperCase(); - else if (md.storesLowerCaseIdentifiers()) - referenceTableName = referenceTableName.toLowerCase(); - - ResultSet rs = md.getCrossReference(catalog, schema, referenceTableName, catalog, schema, tableName); - while (rs.next()) - { - String dbFKName = rs.getString("FK_NAME"); - if (dbFKName == null) - continue; - - String dbFKTable = rs.getString("FKTABLE_NAME"); - short deleteRule = rs.getShort("DELETE_RULE"); - - String key = dbFKName.toLowerCase(); - DatabaseKey dbForeignKey = htForeignKeys.get(key); - if (dbForeignKey == null) - dbForeignKey = new DatabaseKey(dbFKName, dbFKTable, new String[30], deleteRule); - - String columnName = rs.getString("FKCOLUMN_NAME"); - int pos = (rs.getShort("KEY_SEQ")); - if (pos > 0) - dbForeignKey.getKeyColumns()[pos-1] = columnName; - - htForeignKeys.put(key, dbForeignKey); - } - rs.close(); - - Enumeration en = htForeignKeys.keys(); - while (en.hasMoreElements()) - { - String key = en.nextElement(); - DatabaseKey dbForeignKey = htForeignKeys.get(key); - if (dbForeignKey.getKeyColumns()[1] != null) - htForeignKeys.remove(key); - } - - en = htForeignKeys.keys(); - while (en.hasMoreElements()) - { - String key = en.nextElement(); - DatabaseKey dbForeignKey = htForeignKeys.get(key); - if (dbForeignKey.getKeyColumns()[0].equalsIgnoreCase(column.getColumnName())) - { - addLog(Msg.getMsg(getCtx(), "CreateForeignKeyProcessColumn") + column.getColumnName()); - addLog(column.getAD_Column_ID(), null, null, column.toString(), column.get_Table_ID(), column.getAD_Column_ID()); - addLog(0, null, null, Msg.getMsg(getCtx(), "CreateForeignKeyProcessExists") + dbForeignKey.getKeyName()); - column.setFKConstraintName(dbForeignKey.getKeyName()); - column.saveEx(); - return; - } - } - - if (!column.isKey() && !column.getColumnName().equals(PO.getUUIDColumnName(table.getTableName()))) - { - String fkConstraint = getForeignKeyConstraint(md, table, column); - if (fkConstraint != null && fkConstraint.length() > 0) - { - addLog(Msg.getMsg(getCtx(), "CreateForeignKeyProcessColumn") + column.getColumnName()); - addLog(column.getAD_Column_ID(), null, null, column.toString(), column.get_Table_ID(), column.getAD_Column_ID()); - StringBuilder sql = new StringBuilder(); - sql.append("ALTER TABLE ").append(table.getTableName()); - sql.append(" ADD "); - sql.append(fkConstraint); - - Trx trx = Trx.get(Trx.createTrxName("CreateForeignKey"), true); - try { - int rvalue = DB.executeUpdate(sql.toString(), (Object[]) null, true, trx.getTrxName()); - addLog(0, null, new BigDecimal(rvalue), sql.toString()); - if (rvalue == -1) - ++countError; - else - ++countForeignKey; - } catch (Exception e) { - addLog(Msg.getMsg(getCtx(), "Error") + e.getLocalizedMessage()); - if (trx != null) - trx.rollback(); - ++countError; - } finally { - if (trx != null) - trx.close(); - } - } - } - } - } - } - } - - public static String getForeignKeyConstraint(DatabaseMetaData md, MTable table, MColumn column) throws Exception - { - if (!column.isKey() && !column.getColumnName().equals(PO.getUUIDColumnName(table.getTableName()))) - { - String fkConstraintType = column.getFKConstraintType(); - if (fkConstraintType == null) - fkConstraintType = MColumn.FKCONSTRAINTTYPE_NoAction; - - if (fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_DoNotCreate)) - return ""; - - int refid = column.getAD_Reference_ID(); - if (refid != DisplayType.List && refid != DisplayType.Payment) - { - String referenceTableName = column.getReferenceTableName(); - if (referenceTableName != null) + if (dbForeignKey.getKeyColumns()[0].equalsIgnoreCase(column.getColumnName())) { - DatabaseKey primaryKey = getPrimaryKey(md, referenceTableName); - - if (primaryKey != null) + if (dbDeleteRule.equals(fkConstraintType)) { - String fkConstraintName = column.getFKConstraintName(); - if (fkConstraintName == null || fkConstraintName.trim().length() == 0) - { - String columnName = column.getColumnName(); - if (columnName.toUpperCase().endsWith("_ID")) - columnName = columnName.substring(0, columnName.length() - 3); - - StringBuilder constraintName = new StringBuilder(); - constraintName.append(columnName.replace("_", "")); - constraintName.append("_"); - constraintName.append(table.getTableName().replace("_", "")); - if (constraintName.length() > 30) - constraintName = new StringBuilder(constraintName.substring(0, 30)); - fkConstraintName = constraintName.toString(); - } - - StringBuilder fkConstraint = new StringBuilder(); - fkConstraint.append("CONSTRAINT ").append(fkConstraintName); - fkConstraint.append(" FOREIGN KEY (").append(column.getColumnName()).append(") REFERENCES "); - fkConstraint.append(primaryKey.getKeyTable()).append("(").append(primaryKey.getKeyColumns()[0]); - for (int i = 1; i < primaryKey.getKeyColumns().length; i++) - { - if (primaryKey.getKeyColumns()[i] == null) - break; - fkConstraint.append(", ").append(primaryKey.getKeyColumns()[i]); - } - fkConstraint.append(")"); - - if (fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_NoAction)) - ; - else if (fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_Cascade)) - fkConstraint.append(" ON DELETE CASCADE"); - else if (fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_SetNull)) - fkConstraint.append(" ON DELETE SET NULL"); - - fkConstraint.append(" DEFERRABLE INITIALLY DEFERRED"); - - column.setFKConstraintName(fkConstraintName); + addLog(column.getAD_Column_ID(), null, null, + Msg.getMsg(getCtx(), "CreateForeignKeyProcessColumn") + column.getColumnName()+ " / " + + Msg.getMsg(getCtx(), "CreateForeignKeyProcessExists") + dbForeignKey.getKeyName(), + column.get_Table_ID(), column.getAD_Column_ID()); + modified = true; + column.setFKConstraintName(dbForeignKey.getKeyName()); column.setFKConstraintType(fkConstraintType); column.saveEx(); + break; + } + else if (fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_DoNotCreate)) + { + addLog(column.getAD_Column_ID(), null, null, + Msg.getMsg(getCtx(), "CreateForeignKeyProcessColumn") + column.getColumnName()+ " / " + + Msg.getMsg(getCtx(), "CreateForeignKeyProcessExists") + dbForeignKey.getKeyName(), + column.get_Table_ID(), column.getAD_Column_ID()); - return fkConstraint.toString(); + StringBuilder sql = new StringBuilder(); + sql.append("ALTER TABLE ").append(table.getTableName()); + sql.append(" DROP CONSTRAINT ").append(dbForeignKey.getKeyName()); + + Trx trx = null; + try { + trx = Trx.get(Trx.createTrxName("CreateForeignKey"), true); + int rvalue = DB.executeUpdate(sql.toString(), (Object[]) null, true, trx.getTrxName()); + addLog(0, null, new BigDecimal(rvalue), sql.toString()); + } catch (Exception e) { + addLog(Msg.getMsg(getCtx(), "Error") + e.getLocalizedMessage()); + if (trx != null) + trx.rollback(); + } finally { + if (trx != null) + trx.close(); + } + + modified = true; + column.setFKConstraintName(dbForeignKey.getKeyName()); + column.setFKConstraintType(fkConstraintType); + column.saveEx(); + break; + } + } + } + + if (modified) + return; + + if (!column.isKey() && !column.getColumnName().equals(PO.getUUIDColumnName(table.getTableName()))) + { + String fkConstraint = MColumn.getForeignKeyConstraint(md, table, column); + if (fkConstraint != null && fkConstraint.length() > 0) + { + addLog(column.getAD_Column_ID(), null, null, Msg.getMsg(getCtx(), "CreateForeignKeyProcessColumn") + column.getColumnName(), column.get_Table_ID(), column.getAD_Column_ID()); + + StringBuilder sql = new StringBuilder(); + sql.append("ALTER TABLE ").append(table.getTableName()); + sql.append(" ADD "); + sql.append(fkConstraint); + + Trx trx = null; + try { + trx = Trx.get(Trx.createTrxName("CreateForeignKey"), true); + int rvalue = DB.executeUpdate(sql.toString(), (Object[]) null, true, trx.getTrxName()); + addLog(0, null, new BigDecimal(rvalue), sql.toString()); + if (rvalue == -1) + ++countError; + else + ++countForeignKey; + } catch (Exception e) { + addLog(Msg.getMsg(getCtx(), "Error") + e.getLocalizedMessage()); + if (trx != null) + trx.rollback(); + ++countError; + } finally { + if (trx != null) + trx.close(); } } } } - - return ""; } - public static DatabaseKey getPrimaryKey(DatabaseMetaData md, String primaryTableName) throws Exception - { - DatabaseKey primaryKey = null; - - String catalog = DB.getDatabase().getCatalog(); - String schema = DB.getDatabase().getSchema(); - - String tableName = primaryTableName; - if (md.storesUpperCaseIdentifiers()) - tableName = tableName.toUpperCase(); - else if (md.storesLowerCaseIdentifiers()) - tableName = tableName.toLowerCase(); - - ResultSet rs = md.getPrimaryKeys(catalog, schema, tableName); - while (rs.next()) - { - String primaryKeyName = rs.getString("PK_NAME"); - if (primaryKeyName == null) - continue; - - String primaryKeyTableName = rs.getString("TABLE_NAME"); - short deleteRule = -1; - - if (primaryKey == null) - primaryKey = new DatabaseKey(primaryKeyName, primaryKeyTableName, new String[30], deleteRule); - - String primaryKeyColumn = rs.getString("COLUMN_NAME"); - int pos = (rs.getShort("KEY_SEQ")); - if (pos > 0) - primaryKey.getKeyColumns()[pos-1] = primaryKeyColumn; - } - rs.close(); - return primaryKey; - } } diff --git a/org.adempiere.pipo.handlers/src/org/adempiere/pipo2/handler/ColumnElementHandler.java b/org.adempiere.pipo.handlers/src/org/adempiere/pipo2/handler/ColumnElementHandler.java index ed28666765..84dbae6dcb 100644 --- a/org.adempiere.pipo.handlers/src/org/adempiere/pipo2/handler/ColumnElementHandler.java +++ b/org.adempiere.pipo.handlers/src/org/adempiere/pipo2/handler/ColumnElementHandler.java @@ -232,14 +232,7 @@ public class ColumnElementHandler extends AbstractElementHandler { MColumn[] cols = table.getColumns(false); for (MColumn col : cols) { - String fkConstraintSql; - try { - fkConstraintSql = MColumn.getForeignKeyConstraintSql(md, catalog, schema, tableName, table, col); - } catch (Exception e) { - throw new AdempiereException(e); - } - if (fkConstraintSql != null && fkConstraintSql.length() > 0) - sql += fkConstraintSql; + sql += addConstraint(table, md, catalog, schema, tableName, col); } } else { // @@ -256,14 +249,7 @@ public class ColumnElementHandler extends AbstractElementHandler { // No existing column sql = column.getSQLAdd(table); } - String fkConstraintSql; - try { - fkConstraintSql = MColumn.getForeignKeyConstraintSql(md, catalog, schema, tableName, table, column); - } catch (Exception e) { - throw new AdempiereException(e); - } - if (fkConstraintSql != null && fkConstraintSql.length() > 0) - sql += fkConstraintSql; + sql += addConstraint(table, md, catalog, schema, tableName, column); } //execute modify or add if needed @@ -310,6 +296,19 @@ public class ColumnElementHandler extends AbstractElementHandler { return 1; } + private String addConstraint(MTable table, DatabaseMetaData md, + String catalog, String schema, String tableName, MColumn col) { + String fkConstraintSql; + try { + fkConstraintSql = MColumn.getForeignKeyConstraintSql(md, catalog, schema, tableName, table, col, false); + } catch (Exception e) { + throw new AdempiereException(e); + } + if (fkConstraintSql != null && fkConstraintSql.length() > 0) + fkConstraintSql = ""; + return fkConstraintSql; + } + public void endElement(PIPOContext ctx, Element element) throws SAXException { }