From d12bf3decc58532dae66037976469f918a74f01d Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Thu, 27 Apr 2023 12:48:01 -0500 Subject: [PATCH] Make it an option in the module's interface, whether or not to query for all records being updated or deleted first (makes more sense for an api backend to NOT do this). --- .../core/actions/interfaces/DeleteInterface.java | 9 +++++++++ .../core/actions/interfaces/UpdateInterface.java | 10 ++++++++++ .../backend/core/actions/tables/DeleteAction.java | 6 +++--- .../backend/core/actions/tables/UpdateAction.java | 15 +++++++++++---- .../module/api/actions/APIUpdateAction.java | 12 ++++++++++++ 5 files changed, 45 insertions(+), 7 deletions(-) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/interfaces/DeleteInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/interfaces/DeleteInterface.java index 669967d2..43781917 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/interfaces/DeleteInterface.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/interfaces/DeleteInterface.java @@ -50,4 +50,13 @@ public interface DeleteInterface return (false); } + /******************************************************************************* + ** Specify whether this particular module's delete action can & should fetch + ** records before deleting them, e.g., for audits or "not-found-checks" + *******************************************************************************/ + default boolean supportsPreFetchQuery() + { + return (true); + } + } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/interfaces/UpdateInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/interfaces/UpdateInterface.java index fa87f5e8..e89baeed 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/interfaces/UpdateInterface.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/interfaces/UpdateInterface.java @@ -37,4 +37,14 @@ public interface UpdateInterface ** *******************************************************************************/ UpdateOutput execute(UpdateInput updateInput) throws QException; + + /******************************************************************************* + ** Specify whether this particular module's update action can & should fetch + ** records before updating them, e.g., for audits or "not-found-checks" + *******************************************************************************/ + default boolean supportsPreFetchQuery() + { + return (true); + } + } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/DeleteAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/DeleteAction.java index 195200e7..ec240c2c 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/DeleteAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/DeleteAction.java @@ -76,13 +76,13 @@ public class DeleteAction QBackendModuleDispatcher qBackendModuleDispatcher = new QBackendModuleDispatcher(); QBackendModuleInterface qModule = qBackendModuleDispatcher.getQBackendModule(deleteInput.getBackend()); + DeleteInterface deleteInterface = qModule.getDeleteInterface(); if(CollectionUtils.nullSafeHasContents(deleteInput.getPrimaryKeys()) && deleteInput.getQueryFilter() != null) { throw (new QException("A delete request may not contain both a list of primary keys and a query filter.")); } - DeleteInterface deleteInterface = qModule.getDeleteInterface(); if(deleteInput.getQueryFilter() != null && !deleteInterface.supportsQueryFilterInput()) { LOG.info("Querying for primary keys, for backend module " + qModule.getBackendType() + " which does not support queryFilter input for deletes"); @@ -99,8 +99,8 @@ public class DeleteAction } } - List recordListForAudit = getRecordListForAuditIfNeeded(deleteInput); - List recordsWithValidationErrors = validateRecordsExistAndCanBeAccessed(deleteInput, recordListForAudit); + List recordListForAudit = deleteInterface.supportsPreFetchQuery() ? getRecordListForAuditIfNeeded(deleteInput) : new ArrayList<>(); + List recordsWithValidationErrors = deleteInterface.supportsPreFetchQuery() ? validateRecordsExistAndCanBeAccessed(deleteInput, recordListForAudit) : new ArrayList<>(); DeleteOutput deleteOutput = deleteInterface.execute(deleteInput); diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/UpdateAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/UpdateAction.java index 0ada6d9e..17663aa7 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/UpdateAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/UpdateAction.java @@ -33,6 +33,7 @@ import com.kingsrook.qqq.backend.core.actions.ActionHelper; import com.kingsrook.qqq.backend.core.actions.audits.DMLAuditAction; import com.kingsrook.qqq.backend.core.actions.automation.AutomationStatus; import com.kingsrook.qqq.backend.core.actions.automation.RecordAutomationStatusUpdater; +import com.kingsrook.qqq.backend.core.actions.interfaces.UpdateInterface; import com.kingsrook.qqq.backend.core.actions.tables.helpers.ValidateRecordSecurityLockHelper; import com.kingsrook.qqq.backend.core.actions.values.ValueBehaviorApplier; import com.kingsrook.qqq.backend.core.context.QContext; @@ -87,18 +88,24 @@ public class UpdateAction ValueBehaviorApplier.applyFieldBehaviors(updateInput.getInstance(), updateInput.getTable(), updateInput.getRecords()); // todo - need to handle records with errors coming out of here... - List oldRecordList = getOldRecordListForAuditIfNeeded(updateInput); - QBackendModuleDispatcher qBackendModuleDispatcher = new QBackendModuleDispatcher(); QBackendModuleInterface qModule = qBackendModuleDispatcher.getQBackendModule(updateInput.getBackend()); + UpdateInterface updateInterface = qModule.getUpdateInterface(); + + List oldRecordList = updateInterface.supportsPreFetchQuery() ? getOldRecordListForAuditIfNeeded(updateInput) : new ArrayList<>(); validatePrimaryKeysAreGiven(updateInput); - validateRecordsExistAndCanBeAccessed(updateInput, oldRecordList); + + if(updateInterface.supportsPreFetchQuery()) + { + validateRecordsExistAndCanBeAccessed(updateInput, oldRecordList); + } + validateRequiredFields(updateInput); ValidateRecordSecurityLockHelper.validateSecurityFields(updateInput.getTable(), updateInput.getRecords(), ValidateRecordSecurityLockHelper.Action.UPDATE); // todo pre-customization - just get to modify the request? - UpdateOutput updateOutput = qModule.getUpdateInterface().execute(updateInput); + UpdateOutput updateOutput = updateInterface.execute(updateInput); // todo post-customization - can do whatever w/ the result if you want List errors = updateOutput.getRecords().stream().flatMap(r -> r.getErrors().stream()).toList(); diff --git a/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/APIUpdateAction.java b/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/APIUpdateAction.java index 89cafaf5..e0af323d 100644 --- a/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/APIUpdateAction.java +++ b/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/APIUpdateAction.java @@ -45,4 +45,16 @@ public class APIUpdateAction extends AbstractAPIAction implements UpdateInterfac return (apiActionUtil.doUpdate(table, updateInput)); } + + + /******************************************************************************* + ** Specify whether this particular module's update action can & should fetch + ** records before updating them, e.g., for audits or "not-found-checks" + *******************************************************************************/ + @Override + public boolean supportsPreFetchQuery() + { + return (false); + } + }