From 074b728bd527e983926114af04630ab1ad4301e8 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Tue, 30 Nov 2021 18:09:00 -0600 Subject: [PATCH] Implemented delete --- .../qqq/backend/module/rdbms/RDBSMModule.java | 13 +++ .../rdbms/actions/RDBMSDeleteAction.java | 72 +++++++++++++ .../module/rdbms/actions/RDBMSActionTest.java | 12 +++ .../rdbms/actions/RDBMSDeleteActionTest.java | 100 ++++++++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java create mode 100644 src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteActionTest.java diff --git a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/RDBSMModule.java b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/RDBSMModule.java index 564ba151..3a3449ce 100644 --- a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/RDBSMModule.java +++ b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/RDBSMModule.java @@ -1,9 +1,11 @@ package com.kingsrook.qqq.backend.module.rdbms; +import com.kingsrook.qqq.backend.core.modules.interfaces.DeleteInterface; import com.kingsrook.qqq.backend.core.modules.interfaces.InsertInterface; import com.kingsrook.qqq.backend.core.modules.interfaces.QModuleInterface; import com.kingsrook.qqq.backend.core.modules.interfaces.QueryInterface; +import com.kingsrook.qqq.backend.module.rdbms.actions.RDBMSDeleteAction; import com.kingsrook.qqq.backend.module.rdbms.actions.RDBMSInsertAction; import com.kingsrook.qqq.backend.module.rdbms.actions.RDBMSQueryAction; @@ -32,4 +34,15 @@ public class RDBSMModule implements QModuleInterface { return (new RDBMSInsertAction()); } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public DeleteInterface getDeleteInterface() + { + return (new RDBMSDeleteAction()); + } } diff --git a/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java new file mode 100644 index 00000000..586eb181 --- /dev/null +++ b/src/main/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteAction.java @@ -0,0 +1,72 @@ +package com.kingsrook.qqq.backend.module.rdbms.actions; + + +import java.io.Serializable; +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.actions.DeleteRequest; +import com.kingsrook.qqq.backend.core.model.actions.DeleteResult; +import com.kingsrook.qqq.backend.core.model.data.QRecord; +import com.kingsrook.qqq.backend.core.model.data.QRecordWithStatus; +import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData; +import com.kingsrook.qqq.backend.core.modules.interfaces.DeleteInterface; +import com.kingsrook.qqq.backend.module.rdbms.RDBSMBackendMetaData; +import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager; +import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class RDBMSDeleteAction extends AbstractRDBMSAction implements DeleteInterface +{ + + /******************************************************************************* + ** + *******************************************************************************/ + public DeleteResult execute(DeleteRequest deleteRequest) throws QException + { + try + { + DeleteResult rs = new DeleteResult(); + QTableMetaData table = deleteRequest.getTable(); + + String tableName = table.getName(); + String primaryKeyName = getColumnName(table.getField(table.getPrimaryKeyField())); + String sql = "DELETE FROM " + + tableName + + " WHERE " + + primaryKeyName + + " IN (" + + deleteRequest.getPrimaryKeys().stream().map(x -> "?").collect(Collectors.joining(",")) + + ")"; + List params = deleteRequest.getPrimaryKeys(); + + // todo sql customization - can edit sql and/or param list + + ConnectionManager connectionManager = new ConnectionManager(); + Connection connection = connectionManager.getConnection(new RDBSMBackendMetaData(deleteRequest.getBackend())); + + QueryManager.executeUpdateForRowCount(connection, sql, params); + List recordsWithStatus = new ArrayList<>(); + rs.setRecords(recordsWithStatus); + for(Serializable primaryKey : deleteRequest.getPrimaryKeys()) + { + QRecord qRecord = new QRecord().withTableName(deleteRequest.getTableName()).withPrimaryKey(primaryKey); + // todo uh, identify any errors? + QRecordWithStatus recordWithStatus = new QRecordWithStatus(qRecord); + recordsWithStatus.add(recordWithStatus); + } + + return rs; + } + catch(Exception e) + { + throw new QException("Error executing delete: " + e.getMessage(), e); + } + } + +} diff --git a/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSActionTest.java b/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSActionTest.java index b6b75d73..85fde61c 100644 --- a/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSActionTest.java +++ b/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSActionTest.java @@ -90,4 +90,16 @@ public class RDBMSActionTest QueryManager.executeUpdate(connection, sql); } } + + + + /******************************************************************************* + ** + *******************************************************************************/ + protected void runTestSql(String sql, QueryManager.ResultSetProcessor resultSetProcessor) throws Exception + { + ConnectionManager connectionManager = new ConnectionManager(); + Connection connection = connectionManager.getConnection(new RDBSMBackendMetaData(defineBackend())); + QueryManager.executeStatement(connection, sql, resultSetProcessor); + } } diff --git a/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteActionTest.java b/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteActionTest.java new file mode 100644 index 00000000..86f562f3 --- /dev/null +++ b/src/test/java/com/kingsrook/qqq/backend/module/rdbms/actions/RDBMSDeleteActionTest.java @@ -0,0 +1,100 @@ +package com.kingsrook.qqq.backend.module.rdbms.actions; + + +import java.util.List; +import com.kingsrook.qqq.backend.core.model.actions.DeleteRequest; +import com.kingsrook.qqq.backend.core.model.actions.DeleteResult; +import com.kingsrook.qqq.backend.core.utils.CollectionUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class RDBMSDeleteActionTest extends RDBMSActionTest +{ + + /******************************************************************************* + ** + *******************************************************************************/ + @BeforeEach + public void beforeEach() throws Exception + { + super.primeTestDatabase(); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + public void testDeleteAll() throws Exception + { + DeleteRequest deleteRequest = initDeleteRequest(); + deleteRequest.setPrimaryKeys(List.of(1, 2, 3, 4, 5)); + DeleteResult deleteResult = new RDBMSDeleteAction().execute(deleteRequest); + assertEquals(5, deleteResult.getRecords().size(), "Unfiltered delete should return all rows"); + assertTrue(deleteResult.getRecords().stream().noneMatch(qrs -> CollectionUtils.nullSafeHasContents(qrs.getErrors())), "There should be no errors"); + runTestSql("SELECT id FROM person", (rs -> assertFalse(rs.next()))); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + public void testDeleteOne() throws Exception + { + DeleteRequest deleteRequest = initDeleteRequest(); + deleteRequest.setPrimaryKeys(List.of(1)); + DeleteResult deleteResult = new RDBMSDeleteAction().execute(deleteRequest); + assertEquals(1, deleteResult.getRecords().size(), "Should delete one row"); + assertTrue(deleteResult.getRecords().stream().noneMatch(qrs -> CollectionUtils.nullSafeHasContents(qrs.getErrors())), "There should be no errors"); + runTestSql("SELECT id FROM person WHERE id = 1", (rs -> assertFalse(rs.next()))); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + public void testDeleteSome() throws Exception + { + DeleteRequest deleteRequest = initDeleteRequest(); + deleteRequest.setPrimaryKeys(List.of(1, 3, 5)); + DeleteResult deleteResult = new RDBMSDeleteAction().execute(deleteRequest); + assertEquals(3, deleteResult.getRecords().size(), "Should delete one row"); + assertTrue(deleteResult.getRecords().stream().noneMatch(qrs -> CollectionUtils.nullSafeHasContents(qrs.getErrors())), "There should be no errors"); + runTestSql("SELECT id FROM person", (rs -> { + int rowsFound = 0; + while(rs.next()) + { + rowsFound++; + assertTrue(rs.getInt(1) == 2 || rs.getInt(1) == 4); + } + assertEquals(2, rowsFound); + })); + + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private DeleteRequest initDeleteRequest() + { + DeleteRequest deleteRequest = new DeleteRequest(); + deleteRequest.setInstance(defineInstance()); + deleteRequest.setTableName(defineTablePerson().getName()); + return deleteRequest; + } + +} \ No newline at end of file