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
This commit is contained in:
parent
158648ccdb
commit
25ea69c62d
|
@ -34,7 +34,6 @@ import org.compiere.model.MTable;
|
||||||
import org.compiere.model.MTree_Base;
|
import org.compiere.model.MTree_Base;
|
||||||
import org.compiere.model.PO;
|
import org.compiere.model.PO;
|
||||||
import org.compiere.model.Query;
|
import org.compiere.model.Query;
|
||||||
import org.compiere.model.X_AD_Package_UUID_Map;
|
|
||||||
import org.compiere.process.ProcessInfoParameter;
|
import org.compiere.process.ProcessInfoParameter;
|
||||||
import org.compiere.process.SvrProcess;
|
import org.compiere.process.SvrProcess;
|
||||||
import org.compiere.util.DB;
|
import org.compiere.util.DB;
|
||||||
|
@ -91,6 +90,7 @@ public class CleanOrphanCascade extends SvrProcess
|
||||||
delTree(treeTable,foreignTable, "Parent_ID", 0);
|
delTree(treeTable,foreignTable, "Parent_ID", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
delTree("AD_Tree_Favorite_Node", "AD_Tree_Favorite_Node", "Parent_ID", 0);
|
||||||
|
|
||||||
List<MTree_Base> trees = new Query(getCtx(), MTree_Base.Table_Name, null, get_TrxName()).list();
|
List<MTree_Base> trees = new Query(getCtx(), MTree_Base.Table_Name, null, get_TrxName()).list();
|
||||||
String treeTable = "AD_TreeNode";
|
String treeTable = "AD_TreeNode";
|
||||||
|
@ -99,6 +99,7 @@ public class CleanOrphanCascade extends SvrProcess
|
||||||
delTree(treeTable,foreignTable, "Parent_ID", tree.getAD_Tree_ID());
|
delTree(treeTable,foreignTable, "Parent_ID", tree.getAD_Tree_ID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get tables with column Record_ID and/or Record_UU
|
||||||
String whereTables = ""
|
String whereTables = ""
|
||||||
+ " IsView = 'N' "
|
+ " IsView = 'N' "
|
||||||
+ "AND EXISTS (SELECT 1 "
|
+ "AND EXISTS (SELECT 1 "
|
||||||
|
@ -108,79 +109,96 @@ public class CleanOrphanCascade extends SvrProcess
|
||||||
+ "AND EXISTS (SELECT 1 "
|
+ "AND EXISTS (SELECT 1 "
|
||||||
+ " FROM AD_Column cr "
|
+ " FROM AD_Column cr "
|
||||||
+ " WHERE cr.IsActive='Y' AND cr.AD_Table_ID = AD_Table.AD_Table_ID "
|
+ " WHERE cr.IsActive='Y' AND cr.AD_Table_ID = AD_Table.AD_Table_ID "
|
||||||
+ " AND cr.ColumnName = 'Record_ID') "
|
+ " AND (cr.ColumnName = 'Record_ID' OR cr.ColumnName = 'Record_UU'))";
|
||||||
+ "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')";
|
|
||||||
|
|
||||||
List<MTable> tables = new Query(getCtx(), "AD_Table", whereTables, get_TrxName())
|
List<MTable> tables = new Query(getCtx(), "AD_Table", whereTables, get_TrxName())
|
||||||
.setOnlyActiveRecords(true)
|
.setOnlyActiveRecords(true)
|
||||||
.setOrderBy("TableName")
|
.setOrderBy("TableName")
|
||||||
.list();
|
.list();
|
||||||
tables.add(MTable.get(getCtx(), X_AD_Package_UUID_Map.Table_Name));
|
|
||||||
for (MTable table : tables) {
|
for (MTable table : tables) {
|
||||||
String tableName = table.getTableName();
|
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();
|
StringBuilder sqlRef = new StringBuilder();
|
||||||
sqlRef.append("SELECT DISTINCT t.AD_Table_ID, ");
|
sqlRef.append("SELECT DISTINCT t.AD_Table_ID, ");
|
||||||
sqlRef.append(" t.TableName, ");
|
sqlRef.append(" t.TableName ");
|
||||||
sqlRef.append(" c.FKConstraintType, ");
|
|
||||||
sqlRef.append(" c.IsMandatory ");
|
|
||||||
sqlRef.append("FROM ").append(tableName).append(" r ");
|
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_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");
|
sqlRef.append("ORDER BY t.Tablename");
|
||||||
List<List<Object>> rowTables = DB.getSQLArrayObjectsEx(get_TrxName(), sqlRef.toString());
|
List<List<Object>> rowTables = DB.getSQLArrayObjectsEx(get_TrxName(), sqlRef.toString());
|
||||||
if (rowTables != null) {
|
if (rowTables != null) {
|
||||||
for (List<Object> row : rowTables) {
|
for (List<Object> row : rowTables) {
|
||||||
int refTableID = ((BigDecimal) row.get(0)).intValue();
|
int refTableID = ((BigDecimal) row.get(0)).intValue();
|
||||||
String refTableName = row.get(1).toString();
|
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);
|
MTable refTable = MTable.get(getCtx(), refTableID);
|
||||||
StringBuilder whereClause = new StringBuilder();
|
String colRef = refTable.getKeyColumns()[0];
|
||||||
whereClause.append("AD_Table_ID = ").append(refTableID);
|
String colRefUU = PO.getUUIDColumnName(refTableName);
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
whereClause.append(" AND NOT EXISTS (SELECT ").append(colRef);
|
if (colRecordID != null && ! refTable.isUUIDKeyTable()) {
|
||||||
whereClause.append(" FROM ").append(refTableName).append(" ");
|
StringBuilder whereClause = new StringBuilder("AD_Table_ID=").append(refTableID)
|
||||||
whereClause.append(" WHERE ").append(refTableName).append(".").append(colRef).append(" = ").append(tableName);
|
.append(" AND Record_ID>0")
|
||||||
if (isUUIDMap) {
|
.append(" AND NOT EXISTS (SELECT ").append(colRef)
|
||||||
whereClause.append(".Target_UUID)");
|
.append(" FROM ").append(refTableName).append(" ")
|
||||||
} else {
|
.append(" WHERE ").append(refTableName).append(".").append(colRef).append(" = ").append(tableName).append(".Record_ID)");
|
||||||
whereClause.append(".Record_ID)");
|
int noDeleted = 0;
|
||||||
|
int noSetNull = 0;
|
||||||
|
int noIgnored = 0;
|
||||||
|
List<PO> 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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (noDeleted > 0 || noSetNull > 0 || noIgnored > 0) {
|
||||||
|
addLog(Msg.parseTranslation(getCtx(), tableName + ".Record_ID: " + noIgnored + " @Ignored@ / " + noDeleted + " @Deleted@ / " + noSetNull + " @Reset@ -> " + refTableName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int noDeleted = 0;
|
if (colRecordUU != null) {
|
||||||
int noSetNull = 0;
|
StringBuilder whereClause = new StringBuilder("AD_Table_ID=").append(refTableID)
|
||||||
List<PO> poList = new Query(getCtx(), tableName, whereClause.toString(), get_TrxName()).list();
|
.append(" AND Record_UU IS NOT NULL")
|
||||||
for (PO po : poList) {
|
.append(" AND NOT EXISTS (SELECT ").append(colRefUU)
|
||||||
if (MColumn.FKCONSTRAINTTYPE_ModelCascade.equals(constraintType)) {
|
.append(" FROM ").append(refTableName).append(" ")
|
||||||
po.deleteEx(true, get_TrxName());
|
.append(" WHERE ").append(refTableName).append(".").append(colRefUU).append(" = ").append(tableName).append(".Record_UU)");
|
||||||
noDeleted++;
|
int noDeleted = 0;
|
||||||
} else if (MColumn.FKCONSTRAINTTYPE_ModelSetNull.equals(constraintType)) {
|
int noSetNull = 0;
|
||||||
if (isMandatory)
|
int noIgnored = 0;
|
||||||
po.set_ValueOfColumn("Record_ID", 0);
|
List<PO> poList = new Query(getCtx(), tableName, whereClause.toString(), get_TrxName()).list();
|
||||||
else
|
for (PO po : poList) {
|
||||||
po.set_ValueOfColumn("Record_ID", null);
|
if (MColumn.FKCONSTRAINTTYPE_ModelCascade.equals(colRecordUU.getFKConstraintType())) {
|
||||||
po.saveEx(get_TrxName());
|
po.deleteEx(true, get_TrxName());
|
||||||
noSetNull++;
|
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue