From 1116966de8d5a00ce36f3d85a0c790f0f8162b2f Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Wed, 3 Sep 2014 16:49:06 -0500 Subject: [PATCH] IDEMPIERE-2060 Move some Delete Cascade Constraints to Model classes / based on idea and patch from Adnan Touati --- .../oracle/201409031529_IDEMPIERE-2060.sql | 35 ++++++++++++++++ .../201409031529_IDEMPIERE-2060.sql | 32 ++++++++++++++ .../src/org/compiere/model/MOrder.java | 5 +-- .../src/org/compiere/model/PO.java | 5 +++ .../src/org/compiere/model/PO_Record.java | 42 ++++++++++++++++++- .../src/org/compiere/model/X_AD_Column.java | 4 +- 6 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 migration/i2.0z/oracle/201409031529_IDEMPIERE-2060.sql create mode 100644 migration/i2.0z/postgresql/201409031529_IDEMPIERE-2060.sql diff --git a/migration/i2.0z/oracle/201409031529_IDEMPIERE-2060.sql b/migration/i2.0z/oracle/201409031529_IDEMPIERE-2060.sql new file mode 100644 index 0000000000..5bcbdc66b4 --- /dev/null +++ b/migration/i2.0z/oracle/201409031529_IDEMPIERE-2060.sql @@ -0,0 +1,35 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Sep 3, 2014 3:26:22 PM COT +-- IDEMPIERE-2060 Move some Delete Cascade Constraints to Model classes +INSERT INTO AD_Ref_List (AD_Ref_List_ID,AD_Reference_ID,AD_Ref_List_UU,Name,Value,CreatedBy,Updated,UpdatedBy,IsActive,EntityType,AD_Client_ID,AD_Org_ID,Created) VALUES (200278,200075,'c0542a52-fe58-4b87-8bd4-9dc2fe3afa7a','Model Cascade','M',100,TO_DATE('2014-09-03 15:26:21','YYYY-MM-DD HH24:MI:SS'),100,'Y','D',0,0,TO_DATE('2014-09-03 15:26:21','YYYY-MM-DD HH24:MI:SS')) +; + +-- Sep 3, 2014 3:44:58 PM COT +UPDATE AD_Column SET IsUpdateable='N', FKConstraintType='M',Updated=TO_DATE('2014-09-03 15:44:58','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2213 +; + +-- Sep 3, 2014 3:46:37 PM COT +ALTER TABLE C_OrderLine MODIFY C_Order_ID NUMBER(10) +; + +-- Sep 3, 2014 3:46:37 PM COT +ALTER TABLE C_OrderLine DROP CONSTRAINT corder_corderline +; + +-- Sep 3, 2014 3:46:37 PM COT +ALTER TABLE C_OrderLine ADD CONSTRAINT corder_corderline FOREIGN KEY (C_Order_ID) REFERENCES c_order(c_order_id) DEFERRABLE INITIALLY DEFERRED +; + +-- Sep 3, 2014 4:36:39 PM COT +INSERT INTO AD_Val_Rule (Code,AD_Val_Rule_ID,EntityType,Name,Description,Type,AD_Val_Rule_UU,CreatedBy,UpdatedBy,Updated,AD_Org_ID,IsActive,AD_Client_ID,Created) VALUES ('(AD_Ref_List.Value!=''M'' OR @AD_Reference_ID@ IN (18,19,30))',200064,'D','FKConstraintType Model just for Direct Foreign Keys','Ref List by Reference','S','a56bce78-de21-4cfa-b18d-2dd367464c01',100,100,TO_DATE('2014-09-03 16:36:39','YYYY-MM-DD HH24:MI:SS'),0,'Y',0,TO_DATE('2014-09-03 16:36:39','YYYY-MM-DD HH24:MI:SS')) +; + +-- Sep 3, 2014 4:36:48 PM COT +UPDATE AD_Column SET AD_Val_Rule_ID=200064,Updated=TO_DATE('2014-09-03 16:36:48','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=210872 +; + +SELECT register_migration_script('201409031529_IDEMPIERE-2060.sql') FROM dual +; + diff --git a/migration/i2.0z/postgresql/201409031529_IDEMPIERE-2060.sql b/migration/i2.0z/postgresql/201409031529_IDEMPIERE-2060.sql new file mode 100644 index 0000000000..5f9dc6aea9 --- /dev/null +++ b/migration/i2.0z/postgresql/201409031529_IDEMPIERE-2060.sql @@ -0,0 +1,32 @@ +-- Sep 3, 2014 3:26:22 PM COT +-- IDEMPIERE-2060 Move some Delete Cascade Constraints to Model classes +INSERT INTO AD_Ref_List (AD_Ref_List_ID,AD_Reference_ID,AD_Ref_List_UU,Name,Value,CreatedBy,Updated,UpdatedBy,IsActive,EntityType,AD_Client_ID,AD_Org_ID,Created) VALUES (200278,200075,'c0542a52-fe58-4b87-8bd4-9dc2fe3afa7a','Model Cascade','M',100,TO_TIMESTAMP('2014-09-03 15:26:21','YYYY-MM-DD HH24:MI:SS'),100,'Y','D',0,0,TO_TIMESTAMP('2014-09-03 15:26:21','YYYY-MM-DD HH24:MI:SS')) +; + +-- Sep 3, 2014 3:44:58 PM COT +UPDATE AD_Column SET IsUpdateable='N', FKConstraintType='M',Updated=TO_TIMESTAMP('2014-09-03 15:44:58','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2213 +; + +-- Sep 3, 2014 3:46:37 PM COT +INSERT INTO t_alter_column values('c_orderline','C_Order_ID','NUMERIC(10)',null,null) +; + +-- Sep 3, 2014 3:46:37 PM COT +ALTER TABLE C_OrderLine DROP CONSTRAINT corder_corderline +; + +-- Sep 3, 2014 3:46:37 PM COT +ALTER TABLE C_OrderLine ADD CONSTRAINT corder_corderline FOREIGN KEY (C_Order_ID) REFERENCES c_order(c_order_id) DEFERRABLE INITIALLY DEFERRED +; + +-- Sep 3, 2014 4:36:39 PM COT +INSERT INTO AD_Val_Rule (Code,AD_Val_Rule_ID,EntityType,Name,Description,Type,AD_Val_Rule_UU,CreatedBy,UpdatedBy,Updated,AD_Org_ID,IsActive,AD_Client_ID,Created) VALUES ('(AD_Ref_List.Value!=''M'' OR @AD_Reference_ID@ IN (18,19,30))',200064,'D','FKConstraintType Model just for Direct Foreign Keys','Ref List by Reference','S','a56bce78-de21-4cfa-b18d-2dd367464c01',100,100,TO_TIMESTAMP('2014-09-03 16:36:39','YYYY-MM-DD HH24:MI:SS'),0,'Y',0,TO_TIMESTAMP('2014-09-03 16:36:39','YYYY-MM-DD HH24:MI:SS')) +; + +-- Sep 3, 2014 4:36:48 PM COT +UPDATE AD_Column SET AD_Val_Rule_ID=200064,Updated=TO_TIMESTAMP('2014-09-03 16:36:48','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=210872 +; + +SELECT register_migration_script('201409031529_IDEMPIERE-2060.sql') FROM dual +; + diff --git a/org.adempiere.base/src/org/compiere/model/MOrder.java b/org.adempiere.base/src/org/compiere/model/MOrder.java index 23f0389722..2d4b64a396 100644 --- a/org.adempiere.base/src/org/compiere/model/MOrder.java +++ b/org.adempiere.base/src/org/compiere/model/MOrder.java @@ -1193,10 +1193,7 @@ public class MOrder extends X_C_Order implements DocAction { if (isProcessed()) return false; - - for (MOrderLine line : getLines()) { - line.deleteEx(true); - } + // automatic deletion of lines is driven by model cascade definition in dictionary - see IDEMPIERE-2060 return true; } // beforeDelete diff --git a/org.adempiere.base/src/org/compiere/model/PO.java b/org.adempiere.base/src/org/compiere/model/PO.java index ba284f96b3..68ed51ce89 100644 --- a/org.adempiere.base/src/org/compiere/model/PO.java +++ b/org.adempiere.base/src/org/compiere/model/PO.java @@ -3242,6 +3242,11 @@ public abstract class PO deleteTranslations(localTrxName); // Delete Cascade AD_Table_ID/Record_ID (Attachments, ..) PO_Record.deleteCascade(AD_Table_ID, Record_ID, localTrxName); + + //delete cascade only for single key column record + if (m_KeyColumns != null && m_KeyColumns.length == 1) { + PO_Record.deleteModelCascade(p_info.getTableName(), Record_ID, localTrxName); + } // The Delete Statement StringBuilder sql = new StringBuilder ("DELETE FROM ") //jz why no FROM?? diff --git a/org.adempiere.base/src/org/compiere/model/PO_Record.java b/org.adempiere.base/src/org/compiere/model/PO_Record.java index e5967e9923..4e83fab914 100644 --- a/org.adempiere.base/src/org/compiere/model/PO_Record.java +++ b/org.adempiere.base/src/org/compiere/model/PO_Record.java @@ -18,10 +18,14 @@ package org.compiere.model; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; import java.util.logging.Level; +import org.adempiere.exceptions.DBException; import org.compiere.util.CLogger; import org.compiere.util.DB; +import org.compiere.util.DisplayType; import org.compiere.util.Env; /** @@ -147,7 +151,43 @@ public class PO_Record } } return true; - } // deleteCascase + } // deleteCascade + + //IDEMPIERE-2060 + public static void deleteModelCascade(String tableName, int Record_ID, String trxName) { + //find dependent tables to delete cascade + final String sql = "" + + "SELECT t.TableName, " + + " c.ColumnName " + + "FROM AD_Column c " + + " JOIN AD_Table t ON c.AD_Table_ID = t.AD_Table_ID " + + " LEFT JOIN AD_Ref_Table r ON c.AD_Reference_Value_ID = r.AD_Reference_ID " + + " LEFT JOIN AD_Table tr ON r.AD_Table_ID = tr.AD_Table_ID " + + "WHERE t.IsView = 'N' " + + " AND t.IsActive = 'Y' " + + " AND c.IsActive = 'Y' " + + " AND ( ( c.AD_Reference_ID = " + DisplayType.TableDir + + " AND c.ColumnName = ? || '_ID' ) " + + " OR ( c.AD_Reference_ID IN ( " + DisplayType.Table + ", " + DisplayType.Search + " ) " + + " AND ( tr.TableName = ? OR ( tr.TableName IS NULL AND c.ColumnName = ? || '_ID' ) ) ) ) " + + " AND c.FKConstraintType = '" + MColumn.FKCONSTRAINTTYPE_ModelCascade + "' "; + + List> dependents = DB.getSQLArrayObjectsEx(trxName, sql, tableName, tableName, tableName); + if (dependents != null) { + for (List row : dependents) { + String dependentTableName = (String) row.get(0); + String dependentColumnName = (String) row.get(1); + String dependentWhere = dependentColumnName + "=?"; + List poList = new Query(Env.getCtx(), + dependentTableName, + dependentWhere, + trxName).setParameters(Record_ID).list(); + for (PO po : poList) { + po.deleteEx(true, trxName); + } + } + } + } /** * An entry Exists for restrict table/record combination diff --git a/org.adempiere.base/src/org/compiere/model/X_AD_Column.java b/org.adempiere.base/src/org/compiere/model/X_AD_Column.java index 324de4c82c..9ffc7e8406 100644 --- a/org.adempiere.base/src/org/compiere/model/X_AD_Column.java +++ b/org.adempiere.base/src/org/compiere/model/X_AD_Column.java @@ -32,7 +32,7 @@ public class X_AD_Column extends PO implements I_AD_Column, I_Persistent /** * */ - private static final long serialVersionUID = 20131031L; + private static final long serialVersionUID = 20140903L; /** Standard Constructor */ public X_AD_Column (Properties ctx, int AD_Column_ID, String trxName) @@ -487,6 +487,8 @@ public class X_AD_Column extends PO implements I_AD_Column, I_Persistent public static final String FKCONSTRAINTTYPE_Cascade = "C"; /** Set Null = S */ public static final String FKCONSTRAINTTYPE_SetNull = "S"; + /** Model Cascade = M */ + public static final String FKCONSTRAINTTYPE_ModelCascade = "M"; /** Set Constraint Type. @param FKConstraintType Constraint Type */ public void setFKConstraintType (String FKConstraintType)