refactor IDEMPIERE-1132 foreign key management for ticket IDEMPIERE-2745

This commit is contained in:
Carlos Ruiz 2015-08-17 19:27:33 -05:00
parent 95a4c42e88
commit 4d933e8287
6 changed files with 364 additions and 382 deletions

View File

@ -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
;

View File

@ -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
;

View File

@ -128,14 +128,14 @@ public class ColumnSync extends SvrProcess
MColumn[] cols = table.getColumns(false); MColumn[] cols = table.getColumns(false);
for (MColumn col : cols) 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) if (fkConstraintSql != null && fkConstraintSql.length() > 0)
sql += fkConstraintSql; sql += fkConstraintSql;
} }
} }
else 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) if (fkConstraintSql != null && fkConstraintSql.length() > 0)
sql += fkConstraintSql; sql += fkConstraintSql;
} }

View File

@ -32,7 +32,6 @@ import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import org.adempiere.exceptions.DBException; import org.adempiere.exceptions.DBException;
import org.compiere.process.CreateForeignKey;
import org.compiere.util.CCache; import org.compiere.util.CCache;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.DB; 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 * Get MColumn from Cache
@ -840,7 +839,7 @@ public class MColumn extends X_AD_Column
return table; 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(); StringBuilder fkConstraintSql = new StringBuilder();
@ -859,29 +858,35 @@ public class MColumn extends X_AD_Column
else if (md.storesLowerCaseIdentifiers()) else if (md.storesLowerCaseIdentifiers())
referenceTableName = referenceTableName.toLowerCase(); referenceTableName = referenceTableName.toLowerCase();
ResultSet rs = md.getCrossReference(catalog, schema, referenceTableName, catalog, schema, tableName); if (!isNoTable) {
while (rs.next()) ResultSet rs = null;
{ try {
String dbFKName = rs.getString("FK_NAME"); rs = md.getCrossReference(catalog, schema, referenceTableName, catalog, schema, tableName);
if (dbFKName == null) while (rs.next())
continue; {
String dbFKName = rs.getString("FK_NAME");
if (dbFKName == null)
continue;
String dbFKTable = rs.getString("FKTABLE_NAME"); String dbFKTable = rs.getString("FKTABLE_NAME");
short deleteRule = rs.getShort("DELETE_RULE"); short deleteRule = rs.getShort("DELETE_RULE");
String key = dbFKName.toLowerCase(); String key = dbFKName.toLowerCase();
DatabaseKey dbForeignKey = htForeignKeys.get(key); DatabaseKey dbForeignKey = htForeignKeys.get(key);
if (dbForeignKey == null) if (dbForeignKey == null)
dbForeignKey = new DatabaseKey(dbFKName, dbFKTable, new String[30], deleteRule); dbForeignKey = new DatabaseKey(dbFKName, dbFKTable, new String[30], deleteRule);
String columnName = rs.getString("FKCOLUMN_NAME"); String columnName = rs.getString("FKCOLUMN_NAME");
int pos = (rs.getShort("KEY_SEQ")); int pos = (rs.getShort("KEY_SEQ"));
if (pos > 0) if (pos > 0)
dbForeignKey.getKeyColumns()[pos-1] = columnName; dbForeignKey.getKeyColumns()[pos-1] = columnName;
htForeignKeys.put(key, dbForeignKey); htForeignKeys.put(key, dbForeignKey);
}
} finally {
DB.close(rs); rs = null;
}
} }
rs.close();
Enumeration<String> en = htForeignKeys.keys(); Enumeration<String> en = htForeignKeys.keys();
while (en.hasMoreElements()) while (en.hasMoreElements())
@ -900,24 +905,34 @@ public class MColumn extends X_AD_Column
DatabaseKey dbForeignKey = htForeignKeys.get(key); DatabaseKey dbForeignKey = htForeignKeys.get(key);
if (dbForeignKey.getKeyColumns()[0].equalsIgnoreCase(column.getColumnName())) if (dbForeignKey.getKeyColumns()[0].equalsIgnoreCase(column.getColumnName()))
{ {
DatabaseKey primaryKey = CreateForeignKey.getPrimaryKey(md, referenceTableName); DatabaseKey primaryKey = getPrimaryKey(md, referenceTableName);
if (primaryKey != null) if (primaryKey != null)
{ {
fkConstraintSql.append(DB.SQLSTATEMENT_SEPARATOR); fkConstraintSql.append(DB.SQLSTATEMENT_SEPARATOR);
fkConstraintSql.append("ALTER TABLE ").append(table.getTableName()); fkConstraintSql.append("ALTER TABLE ").append(table.getTableName());
fkConstraintSql.append(" DROP CONSTRAINT ").append(dbForeignKey.getKeyName()); fkConstraintSql.append(" DROP CONSTRAINT ").append(dbForeignKey.getKeyName());
String dbDeleteRule = MColumn.FKCONSTRAINTTYPE_NoAction; String dbDeleteRule = null;
if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyCascade) if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyCascade)
dbDeleteRule = MColumn.FKCONSTRAINTTYPE_Cascade; dbDeleteRule = MColumn.FKCONSTRAINTTYPE_Cascade;
else if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeySetNull) else if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeySetNull)
dbDeleteRule = MColumn.FKCONSTRAINTTYPE_SetNull; dbDeleteRule = MColumn.FKCONSTRAINTTYPE_SetNull;
else if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyNoAction || dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyRestrict)
dbDeleteRule = MColumn.FKCONSTRAINTTYPE_NoAction;
String fkConstraintType = column.getFKConstraintType(); String fkConstraintType = column.getFKConstraintType();
if (fkConstraintType == null) if (fkConstraintType == null) {
fkConstraintType = dbDeleteRule; fkConstraintType = dbDeleteRule;
if (fkConstraintType == null) if (fkConstraintType == null) {
fkConstraintType = MColumn.FKCONSTRAINTTYPE_NoAction; 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)) if (!fkConstraintType.equals(MColumn.FKCONSTRAINTTYPE_DoNotCreate))
{ {
String fkConstraintName = column.getFKConstraintName(); String fkConstraintName = column.getFKConstraintName();
@ -962,7 +977,7 @@ public class MColumn extends X_AD_Column
if (!modified) if (!modified)
{ {
String fkConstraint = CreateForeignKey.getForeignKeyConstraint(md, table, column); String fkConstraint = getForeignKeyConstraint(md, table, column);
if (fkConstraint != null && fkConstraint.length() > 0) if (fkConstraint != null && fkConstraint.length() > 0)
{ {
fkConstraintSql.append(DB.SQLSTATEMENT_SEPARATOR); fkConstraintSql.append(DB.SQLSTATEMENT_SEPARATOR);
@ -977,4 +992,114 @@ public class MColumn extends X_AD_Column
return fkConstraintSql.toString(); 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 } // MColumn

View File

@ -26,7 +26,6 @@ import org.compiere.model.MColumn;
import org.compiere.model.MTable; import org.compiere.model.MTable;
import org.compiere.model.PO; import org.compiere.model.PO;
import org.compiere.util.DB; import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Msg; import org.compiere.util.Msg;
import org.compiere.util.Trx; 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); 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(); DatabaseMetaData md = trx.getConnection().getMetaData();
if (p_AD_Column_ID > 0) if (p_AD_Column_ID > 0)
@ -88,14 +87,14 @@ public class CreateForeignKey extends SvrProcess {
else if (p_AD_Table_ID > 0) else if (p_AD_Table_ID > 0)
{ {
MTable table = new MTable(getCtx(), p_AD_Table_ID, get_TrxName()); 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); processDatabaseTableColumn(md, table, null);
}
} }
else else
processDatabase(md); processDatabase(md);
trx.close();
return Msg.getMsg(getCtx(), "CreateForeignKeyProcessResult", new Object[] {countTable, countForeignKey, countError}); 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 schema = DB.getDatabase().getSchema();
String[] types = {"TABLE"}; String[] types = {"TABLE"};
ResultSet rs = md.getTables(catalog, schema, tableName, types); ResultSet rs = null;
while (rs.next()) try {
{ rs = md.getTables(catalog, schema, tableName, types);
String dbTableName = rs.getString("TABLE_NAME"); while (rs.next())
if (dbTableName == null) {
continue; String dbTableName = rs.getString("TABLE_NAME");
MTable table = MTable.get(getCtx(), dbTableName); if (dbTableName == null)
if (table != null) // exists in AD_Table continue;
processDatabaseTableColumn(md, table, null); 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 private void processDatabaseTableColumn(DatabaseMetaData md, MTable table, MColumn column) throws Exception
@ -133,13 +138,9 @@ public class CreateForeignKey extends SvrProcess {
else if (md.storesLowerCaseIdentifiers()) else if (md.storesLowerCaseIdentifiers())
tableName = tableName.toLowerCase(); tableName = tableName.toLowerCase();
addLog(Msg.getMsg(getCtx(), "CreateForeignKeyProcessTable") + tableName); ResultSet rs = null;
addLog(table.getAD_Table_ID(), null, null, table.toString(), table.get_Table_ID(), table.getAD_Table_ID()); try {
++countTable; rs = md.getImportedKeys(catalog, schema, tableName);
if (column == null)
{
ResultSet rs = md.getImportedKeys(catalog, schema, tableName);
while (rs.next()) while (rs.next())
{ {
String dbFKName = rs.getString("FK_NAME"); String dbFKName = rs.getString("FK_NAME");
@ -148,7 +149,7 @@ public class CreateForeignKey extends SvrProcess {
String dbFKTable = rs.getString("FKTABLE_NAME"); String dbFKTable = rs.getString("FKTABLE_NAME");
short deleteRule = rs.getShort("DELETE_RULE"); short deleteRule = rs.getShort("DELETE_RULE");
String key = dbFKName.toLowerCase(); String key = dbFKName.toLowerCase();
DatabaseKey dbForeignKey = htForeignKeys.get(key); DatabaseKey dbForeignKey = htForeignKeys.get(key);
if (dbForeignKey == null) if (dbForeignKey == null)
@ -161,336 +162,164 @@ public class CreateForeignKey extends SvrProcess {
htForeignKeys.put(key, dbForeignKey); htForeignKeys.put(key, dbForeignKey);
} }
rs.close(); } finally {
DB.close(rs); rs = null;
Enumeration<String> en = htForeignKeys.keys(); }
Enumeration<String> 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()) while (en.hasMoreElements())
{ {
String key = en.nextElement(); String key = en.nextElement();
DatabaseKey dbForeignKey = htForeignKeys.get(key); 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()); String dbDeleteRule = null;
if (AD_Column_ID > 0) if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyCascade)
{ dbDeleteRule = MColumn.FKCONSTRAINTTYPE_Cascade;
column = MColumn.get(getCtx(), AD_Column_ID); else if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeySetNull)
if (column == null) dbDeleteRule = MColumn.FKCONSTRAINTTYPE_SetNull;
continue; else if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyNoAction || dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyRestrict)
dbDeleteRule = MColumn.FKCONSTRAINTTYPE_NoAction;
boolean modified = false; String fkConstraintType = column.getFKConstraintType();
en = htForeignKeys.keys(); if (fkConstraintType == null) {
while (en.hasMoreElements()) fkConstraintType = dbDeleteRule;
{ if (fkConstraintType == null) {
String key = en.nextElement(); if ( "AD_Client_ID".equals(column.getColumnName())
DatabaseKey dbForeignKey = htForeignKeys.get(key); || "AD_Org_ID".equals(column.getColumnName())
|| "CreatedBy".equals(column.getColumnName())
String dbDeleteRule = MColumn.FKCONSTRAINTTYPE_NoAction; || "UpdatedBy".equals(column.getColumnName())
if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeyCascade) )
dbDeleteRule = MColumn.FKCONSTRAINTTYPE_Cascade; fkConstraintType = MColumn.FKCONSTRAINTTYPE_DoNotCreate;
else if (dbForeignKey.getDeleteRule() == DatabaseMetaData.importedKeySetNull) else
dbDeleteRule = MColumn.FKCONSTRAINTTYPE_SetNull;
String fkConstraintType = column.getFKConstraintType();
if (fkConstraintType == null)
fkConstraintType = MColumn.FKCONSTRAINTTYPE_NoAction; 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<String> 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(); if (dbForeignKey.getKeyColumns()[0].equalsIgnoreCase(column.getColumnName()))
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)
{ {
DatabaseKey primaryKey = getPrimaryKey(md, referenceTableName); if (dbDeleteRule.equals(fkConstraintType))
if (primaryKey != null)
{ {
String fkConstraintName = column.getFKConstraintName(); addLog(column.getAD_Column_ID(), null, null,
if (fkConstraintName == null || fkConstraintName.trim().length() == 0) Msg.getMsg(getCtx(), "CreateForeignKeyProcessColumn") + column.getColumnName()+ " / " +
{ Msg.getMsg(getCtx(), "CreateForeignKeyProcessExists") + dbForeignKey.getKeyName(),
String columnName = column.getColumnName(); column.get_Table_ID(), column.getAD_Column_ID());
if (columnName.toUpperCase().endsWith("_ID")) modified = true;
columnName = columnName.substring(0, columnName.length() - 3); column.setFKConstraintName(dbForeignKey.getKeyName());
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.setFKConstraintType(fkConstraintType);
column.saveEx(); 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;
}
} }

View File

@ -232,14 +232,7 @@ public class ColumnElementHandler extends AbstractElementHandler {
MColumn[] cols = table.getColumns(false); MColumn[] cols = table.getColumns(false);
for (MColumn col : cols) for (MColumn col : cols)
{ {
String fkConstraintSql; sql += addConstraint(table, md, catalog, schema, tableName, col);
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;
} }
} else { } else {
// //
@ -256,14 +249,7 @@ public class ColumnElementHandler extends AbstractElementHandler {
// No existing column // No existing column
sql = column.getSQLAdd(table); sql = column.getSQLAdd(table);
} }
String fkConstraintSql; sql += addConstraint(table, md, catalog, schema, tableName, column);
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;
} }
//execute modify or add if needed //execute modify or add if needed
@ -310,6 +296,19 @@ public class ColumnElementHandler extends AbstractElementHandler {
return 1; 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 { public void endElement(PIPOContext ctx, Element element) throws SAXException {
} }