mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-20 06:00:44 +00:00
CE-535 Cleanup in DeleteAction - add omitDmlAudit & auditContext; be more sure not to delete associations if errors
This commit is contained in:
@ -42,6 +42,7 @@ import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
|
||||
import com.kingsrook.qqq.backend.core.actions.interfaces.DeleteInterface;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.logging.LogPair;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.audits.DMLAuditInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
|
||||
@ -117,12 +118,14 @@ public class DeleteAction
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if there's a query filter, but the interface doesn't support using a query filter, then do a query for the filter, to get a list of primary keys instead //
|
||||
// or - anytime there are associations on the table we want primary keys, as that's what the manage associations method uses //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(deleteInput.getQueryFilter() != null && !deleteInterface.supportsQueryFilterInput())
|
||||
if(deleteInput.getQueryFilter() != null && (!deleteInterface.supportsQueryFilterInput() || CollectionUtils.nullSafeHasContents(table.getAssociations())))
|
||||
{
|
||||
LOG.info("Querying for primary keys, for backend module " + qModule.getBackendType() + " which does not support queryFilter input for deletes");
|
||||
LOG.info("Querying for primary keys, for table " + table.getName() + " in backend module " + qModule.getBackendType() + " which does not support queryFilter input for deletes (or the table has associations)");
|
||||
List<Serializable> primaryKeyList = getPrimaryKeysFromQueryFilter(deleteInput);
|
||||
deleteInput.setPrimaryKeys(primaryKeyList);
|
||||
primaryKeys = primaryKeyList;
|
||||
|
||||
if(primaryKeyList.isEmpty())
|
||||
{
|
||||
@ -165,10 +168,22 @@ public class DeleteAction
|
||||
|
||||
if(!primaryKeysToRemoveFromInput.isEmpty())
|
||||
{
|
||||
primaryKeys.removeAll(primaryKeysToRemoveFromInput);
|
||||
if(primaryKeys == null)
|
||||
{
|
||||
LOG.warn("There were primary keys to remove from the input, but no primary key list (filter supplied as input?)", new LogPair("primaryKeysToRemoveFromInput", primaryKeysToRemoveFromInput));
|
||||
}
|
||||
else
|
||||
{
|
||||
primaryKeys.removeAll(primaryKeysToRemoveFromInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// stash a copy of primary keys that didn't have errors (for use in manageAssociations below) //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Set<Serializable> primaryKeysWithoutErrors = new HashSet<>(CollectionUtils.nonNullList(primaryKeys));
|
||||
|
||||
////////////////////////////////////
|
||||
// have the backend do the delete //
|
||||
////////////////////////////////////
|
||||
@ -187,11 +202,13 @@ public class DeleteAction
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if a record had a validation warning, but then an execution error, remove it from the warning list - so it's only in one of them. //
|
||||
// also, always remove from
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
for(QRecord outputRecordWithError : outputRecordsWithErrors)
|
||||
{
|
||||
Serializable pkey = outputRecordWithError.getValue(primaryKeyFieldName);
|
||||
recordsWithValidationWarnings.remove(pkey);
|
||||
primaryKeysWithoutErrors.remove(pkey);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -211,15 +228,23 @@ public class DeleteAction
|
||||
////////////////////////////////////////
|
||||
// delete associations, if applicable //
|
||||
////////////////////////////////////////
|
||||
manageAssociations(deleteInput);
|
||||
manageAssociations(primaryKeysWithoutErrors, deleteInput);
|
||||
|
||||
///////////////////////////////////
|
||||
// do the audit //
|
||||
// todo - add input.omitDmlAudit //
|
||||
///////////////////////////////////
|
||||
DMLAuditInput dmlAuditInput = new DMLAuditInput().withTableActionInput(deleteInput);
|
||||
oldRecordList.ifPresent(l -> dmlAuditInput.setRecordList(l));
|
||||
new DMLAuditAction().execute(dmlAuditInput);
|
||||
//////////////////
|
||||
// do the audit //
|
||||
//////////////////
|
||||
if(deleteInput.getOmitDmlAudit())
|
||||
{
|
||||
LOG.debug("Requested to omit DML audit");
|
||||
}
|
||||
else
|
||||
{
|
||||
DMLAuditInput dmlAuditInput = new DMLAuditInput()
|
||||
.withTableActionInput(deleteInput)
|
||||
.withAuditContext(deleteInput.getAuditContext());
|
||||
oldRecordList.ifPresent(l -> dmlAuditInput.setRecordList(l));
|
||||
new DMLAuditAction().execute(dmlAuditInput);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// finally, run the post-delete customizer, if there is one //
|
||||
@ -340,7 +365,7 @@ public class DeleteAction
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void manageAssociations(DeleteInput deleteInput) throws QException
|
||||
private void manageAssociations(Set<Serializable> primaryKeysWithoutErrors, DeleteInput deleteInput) throws QException
|
||||
{
|
||||
QTableMetaData table = deleteInput.getTable();
|
||||
for(Association association : CollectionUtils.nonNullList(table.getAssociations()))
|
||||
@ -353,7 +378,7 @@ public class DeleteAction
|
||||
|
||||
if(join.getJoinOns().size() == 1 && join.getJoinOns().get(0).getLeftField().equals(table.getPrimaryKeyField()))
|
||||
{
|
||||
filter.addCriteria(new QFilterCriteria(join.getJoinOns().get(0).getRightField(), QCriteriaOperator.IN, deleteInput.getPrimaryKeys()));
|
||||
filter.addCriteria(new QFilterCriteria(join.getJoinOns().get(0).getRightField(), QCriteriaOperator.IN, new ArrayList<>(primaryKeysWithoutErrors)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -51,6 +51,17 @@ public class CountInput extends AbstractTableActionInput
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor
|
||||
**
|
||||
*******************************************************************************/
|
||||
public CountInput(String tableName)
|
||||
{
|
||||
setTableName(tableName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for filter
|
||||
**
|
||||
@ -152,4 +163,15 @@ public class CountInput extends AbstractTableActionInput
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for filter
|
||||
*******************************************************************************/
|
||||
public CountInput withFilter(QQueryFilter filter)
|
||||
{
|
||||
this.filter = filter;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -43,6 +43,9 @@ public class DeleteInput extends AbstractTableActionInput
|
||||
private QQueryFilter queryFilter;
|
||||
private InputSource inputSource = QInputSource.SYSTEM;
|
||||
|
||||
private boolean omitDmlAudit = false;
|
||||
private String auditContext = null;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -211,4 +214,66 @@ public class DeleteInput extends AbstractTableActionInput
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for omitDmlAudit
|
||||
*******************************************************************************/
|
||||
public boolean getOmitDmlAudit()
|
||||
{
|
||||
return (this.omitDmlAudit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for omitDmlAudit
|
||||
*******************************************************************************/
|
||||
public void setOmitDmlAudit(boolean omitDmlAudit)
|
||||
{
|
||||
this.omitDmlAudit = omitDmlAudit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for omitDmlAudit
|
||||
*******************************************************************************/
|
||||
public DeleteInput withOmitDmlAudit(boolean omitDmlAudit)
|
||||
{
|
||||
this.omitDmlAudit = omitDmlAudit;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for auditContext
|
||||
*******************************************************************************/
|
||||
public String getAuditContext()
|
||||
{
|
||||
return (this.auditContext);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for auditContext
|
||||
*******************************************************************************/
|
||||
public void setAuditContext(String auditContext)
|
||||
{
|
||||
this.auditContext = auditContext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for auditContext
|
||||
*******************************************************************************/
|
||||
public DeleteInput withAuditContext(String auditContext)
|
||||
{
|
||||
this.auditContext = auditContext;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user