diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/GetAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/GetAction.java index 0b711bde..088a7b0e 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/GetAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/GetAction.java @@ -36,6 +36,8 @@ import com.kingsrook.qqq.backend.core.actions.interfaces.GetInterface; import com.kingsrook.qqq.backend.core.actions.values.QPossibleValueTranslator; import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter; 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.tables.delete.DeleteInput; import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput; import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput; @@ -53,6 +55,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.cache.CacheUseCase; import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher; import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface; +import com.kingsrook.qqq.backend.core.modules.backend.implementations.utils.BackendQueryFilterUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils; import org.apache.commons.lang.NotImplementedException; @@ -64,6 +67,8 @@ import org.apache.commons.lang.NotImplementedException; *******************************************************************************/ public class GetAction { + private static final QLogger LOG = QLogger.getLogger(InsertAction.class); + private Optional postGetRecordCustomizer; private GetInput getInput; @@ -125,13 +130,34 @@ public class GetAction QRecord recordFromSource = tryToGetFromCacheSource(getInput, getOutput); if(recordFromSource != null) { - QRecord recordToCache = mapSourceRecordToCacheRecord(table, recordFromSource); + QRecord recordToCache = mapSourceRecordToCacheRecord(table, recordFromSource); + boolean shouldCacheRecord = true; - InsertInput insertInput = new InsertInput(); - insertInput.setTableName(getInput.getTableName()); - insertInput.setRecords(List.of(recordToCache)); - InsertOutput insertOutput = new InsertAction().execute(insertInput); - getOutput.setRecord(insertOutput.getRecords().get(0)); + //////////////////////////////////////////////////////////////////////////////// + // see if there are any exclustions that need to be considered for this table // + //////////////////////////////////////////////////////////////////////////////// + recordMatchExclusionLoop: + for(CacheUseCase useCase : CollectionUtils.nonNullList(table.getCacheOf().getUseCases())) + { + for(QQueryFilter filter : CollectionUtils.nonNullList(useCase.getExcludeRecordsMatching())) + { + if(BackendQueryFilterUtils.doesRecordMatch(filter, recordToCache)) + { + LOG.info("Not catching record because it matches a use case's filter exclusion", new LogPair("record", recordToCache), new LogPair("filter", filter)); + shouldCacheRecord = false; + break recordMatchExclusionLoop; + } + } + } + + if(shouldCacheRecord) + { + InsertInput insertInput = new InsertInput(); + insertInput.setTableName(getInput.getTableName()); + insertInput.setRecords(List.of(recordToCache)); + InsertOutput insertOutput = new InsertAction().execute(insertInput); + getOutput.setRecord(insertOutput.getRecords().get(0)); + } } } else @@ -257,7 +283,9 @@ public class GetAction sourceGetInput.setTableName(sourceTableName); sourceGetInput.setUniqueKey(getInput.getUniqueKey()); GetOutput sourceGetOutput = new GetAction().execute(sourceGetInput); - return (sourceGetOutput.getRecord()); + QRecord outputRecord = sourceGetOutput.getRecord(); + + return (outputRecord); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/cache/CacheUseCase.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/cache/CacheUseCase.java index 62def005..1aea5d49 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/cache/CacheUseCase.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/cache/CacheUseCase.java @@ -22,6 +22,8 @@ package com.kingsrook.qqq.backend.core.model.metadata.tables.cache; +import java.util.List; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey; @@ -48,6 +50,8 @@ public class CacheUseCase private UniqueKey cacheUniqueKey; private UniqueKey sourceUniqueKey; + private List excludeRecordsMatching; + /******************************************************************************* @@ -184,4 +188,38 @@ public class CacheUseCase return (this); } + + + /******************************************************************************* + ** Getter for excludeRecordsMatching + ** + *******************************************************************************/ + public List getExcludeRecordsMatching() + { + return excludeRecordsMatching; + } + + + + /******************************************************************************* + ** Setter for excludeRecordsMatching + ** + *******************************************************************************/ + public void setExcludeRecordsMatching(List excludeRecordsMatching) + { + this.excludeRecordsMatching = excludeRecordsMatching; + } + + + + /******************************************************************************* + ** Fluent setter for excludeRecordsMatching + ** + *******************************************************************************/ + public CacheUseCase withExcludeRecordsMatching(List excludeRecordsMatching) + { + this.excludeRecordsMatching = excludeRecordsMatching; + return (this); + } + } diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/tables/GetActionTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/tables/GetActionTest.java index 1aa19cf8..10f8ac07 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/tables/GetActionTest.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/tables/GetActionTest.java @@ -101,7 +101,8 @@ class GetActionTest extends BaseTest TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_PERSON_MEMORY), List.of( new QRecord().withValue("id", 1).withValue("firstName", "George").withValue("lastName", "Washington").withValue("noOfShoes", 5), new QRecord().withValue("id", 2).withValue("firstName", "John").withValue("lastName", "Adams"), - new QRecord().withValue("id", 3).withValue("firstName", "Thomas").withValue("lastName", "Jefferson") + new QRecord().withValue("id", 3).withValue("firstName", "Thomas").withValue("lastName", "Jefferson"), + new QRecord().withValue("id", 3).withValue("firstName", "Thomas 503").withValue("lastName", "Jefferson") )); ///////////////////////////////////////////////////////////////////////////// @@ -117,6 +118,17 @@ class GetActionTest extends BaseTest assertEquals(5, getOutput.getRecord().getValue("noOfShoes")); } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // try to get from the table which caches it - but should not find because use case should filter out because of matching 503 // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + { + GetInput getInput = new GetInput(); + getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY_CACHE); + getInput.setUniqueKey(Map.of("firstName", "Thomas 503", "lastName", "Jefferson")); + GetOutput getOutput = new GetAction().execute(getInput); + assertNull(getOutput.getRecord()); + } + /////////////////////////////////////////////////////////////////////////// // request a row that doesn't exist in cache or source, should miss both // /////////////////////////////////////////////////////////////////////////// diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java index c2690a0d..c87fa80a 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java @@ -739,6 +739,15 @@ public class TestUtils .withSourceUniqueKey(uniqueKey) .withCacheUniqueKey(uniqueKey) .withCacheSourceMisses(false) + .withExcludeRecordsMatching(List.of( + new QQueryFilter( + new QFilterCriteria( + "firstName", + QCriteriaOperator.CONTAINS, + List.of("503") + ) + ) + )) )); } diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java index 0895224c..6ff3a113 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java @@ -739,7 +739,7 @@ public class QueryManager } else if(value instanceof Instant i) { - statement.setString(index, i.toString()); + statement.setString(index, i.toString().replaceAll("T", " ").replaceAll("Z", "")); return (1); } else if(value instanceof LocalDate ld)