From 25ea69c62df54a051713dca65f95e18938387090 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Fri, 1 Sep 2023 04:38:57 +0200 Subject: [PATCH] IDEMPIERE-5567 Support of UUID as Key (FHCA-4195) - CleanOrphanCascade (#1987) Fixes for the CleanOrphanCascade process: - add management for AD_Tree_Favorite_Node - remove management for AD_Package_UUID_Map (in the end this is unnecessary to take care of orphans in this table) - implement management for Record_UU columns - fix problem with UUID based tables --- .../idempiere/process/CleanOrphanCascade.java | 116 ++++++++++-------- 1 file changed, 67 insertions(+), 49 deletions(-) diff --git a/org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java b/org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java index 3a480b2b5e..978d171746 100644 --- a/org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java +++ b/org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java @@ -34,7 +34,6 @@ import org.compiere.model.MTable; import org.compiere.model.MTree_Base; import org.compiere.model.PO; import org.compiere.model.Query; -import org.compiere.model.X_AD_Package_UUID_Map; import org.compiere.process.ProcessInfoParameter; import org.compiere.process.SvrProcess; import org.compiere.util.DB; @@ -91,6 +90,7 @@ public class CleanOrphanCascade extends SvrProcess delTree(treeTable,foreignTable, "Parent_ID", 0); } } + delTree("AD_Tree_Favorite_Node", "AD_Tree_Favorite_Node", "Parent_ID", 0); List trees = new Query(getCtx(), MTree_Base.Table_Name, null, get_TrxName()).list(); String treeTable = "AD_TreeNode"; @@ -99,6 +99,7 @@ public class CleanOrphanCascade extends SvrProcess delTree(treeTable,foreignTable, "Parent_ID", tree.getAD_Tree_ID()); } + // get tables with column Record_ID and/or Record_UU String whereTables = "" + " IsView = 'N' " + "AND EXISTS (SELECT 1 " @@ -108,79 +109,96 @@ public class CleanOrphanCascade extends SvrProcess + "AND EXISTS (SELECT 1 " + " FROM AD_Column cr " + " WHERE cr.IsActive='Y' AND cr.AD_Table_ID = AD_Table.AD_Table_ID " - + " AND cr.ColumnName = 'Record_ID') " - + "AND EXISTS (SELECT 1 " - + " FROM AD_Column ck " - + " WHERE ck.IsActive='Y' AND ck.AD_Table_ID = AD_Table.AD_Table_ID " - + " AND ck.ColumnName = AD_Table.TableName || '_ID')"; + + " AND (cr.ColumnName = 'Record_ID' OR cr.ColumnName = 'Record_UU'))"; List tables = new Query(getCtx(), "AD_Table", whereTables, get_TrxName()) .setOnlyActiveRecords(true) .setOrderBy("TableName") .list(); - tables.add(MTable.get(getCtx(), X_AD_Package_UUID_Map.Table_Name)); for (MTable table : tables) { String tableName = table.getTableName(); - boolean isUUIDMap = X_AD_Package_UUID_Map.Table_Name.equals(tableName); + if (tableName.startsWith("T_")) // ignore T_ temporary tables + continue; + MColumn colRecordID = MColumn.get(getCtx(), tableName, "Record_ID", get_TrxName()); + MColumn colRecordUU = MColumn.get(getCtx(), tableName, "Record_UU", get_TrxName()); + + // get the tables referenced within the Record_ID/UU table StringBuilder sqlRef = new StringBuilder(); sqlRef.append("SELECT DISTINCT t.AD_Table_ID, "); - sqlRef.append(" t.TableName, "); - sqlRef.append(" c.FKConstraintType, "); - sqlRef.append(" c.IsMandatory "); + sqlRef.append(" t.TableName "); sqlRef.append("FROM ").append(tableName).append(" r "); sqlRef.append(" JOIN AD_Table t ON ( r.AD_Table_ID = t.AD_Table_ID ) "); - sqlRef.append(" JOIN AD_Column c ON (t.AD_Table_ID = c.AD_Table_ID AND c.ColumnName = 'Record_ID') "); sqlRef.append("ORDER BY t.Tablename"); List> rowTables = DB.getSQLArrayObjectsEx(get_TrxName(), sqlRef.toString()); if (rowTables != null) { for (List row : rowTables) { int refTableID = ((BigDecimal) row.get(0)).intValue(); String refTableName = row.get(1).toString(); - String constraintType = row.get(2).toString(); - Boolean isMandatory = row.get(3).toString().equalsIgnoreCase("Y"); - MTable refTable = MTable.get(getCtx(), refTableID); - StringBuilder whereClause = new StringBuilder(); - whereClause.append("AD_Table_ID = ").append(refTableID); - if (refTable.getKeyColumns().length != 1 && !isUUIDMap) { - log.warning("Wrong reference for table " + tableName + " -> " + refTableName); - whereClause.append(" AND Record_ID>0"); - } else { - String colRef = refTable.getKeyColumns()[0]; - if (isUUIDMap) { - colRef = MTable.getUUIDColumnName(refTable.getTableName()); + String colRef = refTable.getKeyColumns()[0]; + String colRefUU = PO.getUUIDColumnName(refTableName); + + if (colRecordID != null && ! refTable.isUUIDKeyTable()) { + StringBuilder whereClause = new StringBuilder("AD_Table_ID=").append(refTableID) + .append(" AND Record_ID>0") + .append(" AND NOT EXISTS (SELECT ").append(colRef) + .append(" FROM ").append(refTableName).append(" ") + .append(" WHERE ").append(refTableName).append(".").append(colRef).append(" = ").append(tableName).append(".Record_ID)"); + int noDeleted = 0; + int noSetNull = 0; + int noIgnored = 0; + List poList = new Query(getCtx(), tableName, whereClause.toString(), get_TrxName()).list(); + for (PO po : poList) { + if (MColumn.FKCONSTRAINTTYPE_ModelCascade.equals(colRecordID.getFKConstraintType())) { + po.deleteEx(true, get_TrxName()); + noDeleted++; + } else if (MColumn.FKCONSTRAINTTYPE_ModelSetNull.equals(colRecordID.getFKConstraintType())) { + if (colRecordID.isMandatory()) + po.set_ValueOfColumn("Record_ID", 0); + else + po.set_ValueOfColumn("Record_ID", null); + po.saveEx(get_TrxName()); + noSetNull++; + } else { + noIgnored++; + } } - - whereClause.append(" AND NOT EXISTS (SELECT ").append(colRef); - whereClause.append(" FROM ").append(refTableName).append(" "); - whereClause.append(" WHERE ").append(refTableName).append(".").append(colRef).append(" = ").append(tableName); - if (isUUIDMap) { - whereClause.append(".Target_UUID)"); - } else { - whereClause.append(".Record_ID)"); + if (noDeleted > 0 || noSetNull > 0 || noIgnored > 0) { + addLog(Msg.parseTranslation(getCtx(), tableName + ".Record_ID: " + noIgnored + " @Ignored@ / " + noDeleted + " @Deleted@ / " + noSetNull + " @Reset@ -> " + refTableName)); } } - int noDeleted = 0; - int noSetNull = 0; - List poList = new Query(getCtx(), tableName, whereClause.toString(), get_TrxName()).list(); - for (PO po : poList) { - if (MColumn.FKCONSTRAINTTYPE_ModelCascade.equals(constraintType)) { - po.deleteEx(true, get_TrxName()); - noDeleted++; - } else if (MColumn.FKCONSTRAINTTYPE_ModelSetNull.equals(constraintType)) { - if (isMandatory) - po.set_ValueOfColumn("Record_ID", 0); - else - po.set_ValueOfColumn("Record_ID", null); - po.saveEx(get_TrxName()); - noSetNull++; + if (colRecordUU != null) { + StringBuilder whereClause = new StringBuilder("AD_Table_ID=").append(refTableID) + .append(" AND Record_UU IS NOT NULL") + .append(" AND NOT EXISTS (SELECT ").append(colRefUU) + .append(" FROM ").append(refTableName).append(" ") + .append(" WHERE ").append(refTableName).append(".").append(colRefUU).append(" = ").append(tableName).append(".Record_UU)"); + int noDeleted = 0; + int noSetNull = 0; + int noIgnored = 0; + List poList = new Query(getCtx(), tableName, whereClause.toString(), get_TrxName()).list(); + for (PO po : poList) { + if (MColumn.FKCONSTRAINTTYPE_ModelCascade.equals(colRecordUU.getFKConstraintType())) { + po.deleteEx(true, get_TrxName()); + noDeleted++; + } else if (MColumn.FKCONSTRAINTTYPE_ModelSetNull.equals(colRecordUU.getFKConstraintType())) { + if (colRecordUU.isMandatory()) + po.set_ValueOfColumn("Record_UU", ""); + else + po.set_ValueOfColumn("Record_UU", null); + po.saveEx(get_TrxName()); + noSetNull++; + } else { + noIgnored++; + } + } + if (noDeleted > 0 || noSetNull > 0 || noIgnored > 0) { + addLog(Msg.parseTranslation(getCtx(), tableName + ".Record_UU: " + noIgnored + " @Ignored@ / " + noDeleted + " @Deleted@ / " + noSetNull + " @Reset@ -> " + refTableName)); } } - if (noDeleted > 0 || noSetNull > 0) { - addLog(Msg.parseTranslation(getCtx(), tableName + ": " + noDeleted + " @Deleted@ / " + noSetNull + " @Reset@ -> " + refTableName)); - } + } }