From 081be690d5db338691cd15fb125782a5e91b115f Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Thu, 30 Nov 2023 14:27:15 -0600 Subject: [PATCH] enhanced memory backend somewhat --- .../actions/tables/query/QFilterCriteria.java | 2 +- .../memory/AbstractMemoryAction.java | 59 +++++++++++++++++++ .../memory/MemoryCountAction.java | 7 +++ .../memory/MemoryInsertAction.java | 17 +++++- .../memory/MemoryUpdateAction.java | 16 ++++- .../utils/BackendQueryFilterUtils.java | 8 +-- 6 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/AbstractMemoryAction.java diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QFilterCriteria.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QFilterCriteria.java index 0072b6c9..4a17e6a5 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QFilterCriteria.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QFilterCriteria.java @@ -120,7 +120,7 @@ public class QFilterCriteria implements Serializable, Cloneable } else { - this.values = Arrays.stream(values).toList(); + this.values = new ArrayList<>(Arrays.stream(values).toList()); } } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/AbstractMemoryAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/AbstractMemoryAction.java new file mode 100644 index 00000000..435d0cf3 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/AbstractMemoryAction.java @@ -0,0 +1,59 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2022. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.core.modules.backend.implementations.memory; + + +import java.io.Serializable; +import com.kingsrook.qqq.backend.core.actions.interfaces.QActionInterface; +import com.kingsrook.qqq.backend.core.model.data.QRecord; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; + + +/******************************************************************************* + ** Base class for all core actions in the Memory backend module. + *******************************************************************************/ +public abstract class AbstractMemoryAction implements QActionInterface +{ + + /******************************************************************************* + ** If the table has a field with the given name, then set the given value in the + ** given record. + *******************************************************************************/ + protected void setValueIfTableHasField(QRecord record, QTableMetaData table, String fieldName, Serializable value) + { + try + { + if(table.getFields().containsKey(fieldName)) + { + record.setValue(fieldName, value); + } + } + catch(Exception e) + { + ///////////////////////////////////////////////// + // this means field doesn't exist, so, ignore. // + ///////////////////////////////////////////////// + } + } + +} + diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryCountAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryCountAction.java index 4f5e0d67..cf2c35cc 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryCountAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryCountAction.java @@ -26,6 +26,7 @@ import com.kingsrook.qqq.backend.core.actions.interfaces.CountInterface; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput; import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput; +import com.kingsrook.qqq.backend.core.utils.CollectionUtils; /******************************************************************************* @@ -42,8 +43,14 @@ public class MemoryCountAction implements CountInterface { try { + if(CollectionUtils.nullSafeHasContents(countInput.getQueryJoins())) + { + throw (new UnsupportedOperationException("Performing counts on tables with exposed joins is currently not supported by the Memory Backend.")); + } + CountOutput countOutput = new CountOutput(); countOutput.setCount(MemoryRecordStore.getInstance().count(countInput)); + countOutput.setDistinctCount(countOutput.getCount()); return (countOutput); } catch(Exception e) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryInsertAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryInsertAction.java index 01839359..77ee9635 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryInsertAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryInsertAction.java @@ -22,17 +22,20 @@ package com.kingsrook.qqq.backend.core.modules.backend.implementations.memory; +import java.time.Instant; import com.kingsrook.qqq.backend.core.actions.interfaces.InsertInterface; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput; import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput; +import com.kingsrook.qqq.backend.core.model.data.QRecord; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; /******************************************************************************* ** In-memory version of insert action. ** *******************************************************************************/ -public class MemoryInsertAction implements InsertInterface +public class MemoryInsertAction extends AbstractMemoryAction implements InsertInterface { /******************************************************************************* @@ -42,6 +45,18 @@ public class MemoryInsertAction implements InsertInterface { try { + QTableMetaData table = insertInput.getTable(); + Instant now = Instant.now(); + + for(QRecord record : insertInput.getRecords()) + { + /////////////////////////////////////////// + // todo .. better (not hard-coded names) // + /////////////////////////////////////////// + setValueIfTableHasField(record, table, "createDate", now); + setValueIfTableHasField(record, table, "modifyDate", now); + } + InsertOutput insertOutput = new InsertOutput(); insertOutput.setRecords(MemoryRecordStore.getInstance().insert(insertInput, true)); return (insertOutput); diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryUpdateAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryUpdateAction.java index 97793ce6..68f91a01 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryUpdateAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryUpdateAction.java @@ -22,17 +22,20 @@ package com.kingsrook.qqq.backend.core.modules.backend.implementations.memory; +import java.time.Instant; import com.kingsrook.qqq.backend.core.actions.interfaces.UpdateInterface; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput; import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput; +import com.kingsrook.qqq.backend.core.model.data.QRecord; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; /******************************************************************************* ** In-memory version of update action. ** *******************************************************************************/ -public class MemoryUpdateAction implements UpdateInterface +public class MemoryUpdateAction extends AbstractMemoryAction implements UpdateInterface { /******************************************************************************* @@ -42,6 +45,17 @@ public class MemoryUpdateAction implements UpdateInterface { try { + QTableMetaData table = updateInput.getTable(); + Instant now = Instant.now(); + + for(QRecord record : updateInput.getRecords()) + { + /////////////////////////////////////////// + // todo .. better (not hard-coded names) // + /////////////////////////////////////////// + setValueIfTableHasField(record, table, "modifyDate", now); + } + UpdateOutput updateOutput = new UpdateOutput(); updateOutput.setRecords(MemoryRecordStore.getInstance().update(updateInput, true)); return (updateOutput); diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/utils/BackendQueryFilterUtils.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/utils/BackendQueryFilterUtils.java index c4268e19..86fa2191 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/utils/BackendQueryFilterUtils.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/utils/BackendQueryFilterUtils.java @@ -61,10 +61,10 @@ public class BackendQueryFilterUtils return (true); } - ///////////////////////////////////////////////////////////////////////////////////// - // for an AND query, default to a TRUE answer, and we'll &= each criteria's value. // - // for an OR query, default to FALSE, and |= each criteria's value. // - ///////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////// + // for an AND query, default to a TRUE answer, and we'll &= each criterion's value. // + // for an OR query, default to FALSE, and |= each criterion's value. // + ////////////////////////////////////////////////////////////////////////////////////// AtomicBoolean recordMatches = new AtomicBoolean(filter.getBooleanOperator().equals(QQueryFilter.BooleanOperator.AND) ? true : false); ///////////////////////////////////////