mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Checkpoint: Added Update (edit) action
This commit is contained in:
@ -9,9 +9,11 @@ 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.QBackendModuleInterface;
|
||||
import com.kingsrook.qqq.backend.core.modules.interfaces.QueryInterface;
|
||||
import com.kingsrook.qqq.backend.core.modules.interfaces.UpdateInterface;
|
||||
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;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.actions.RDBMSUpdateAction;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -40,6 +42,16 @@ public class RDBMSBackendModule implements QBackendModuleInterface
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public UpdateInterface getUpdateInterface()
|
||||
{
|
||||
return (new RDBMSUpdateAction());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
|
@ -59,7 +59,7 @@ public class RDBMSDeleteAction extends AbstractRDBMSAction implements DeleteInte
|
||||
rs.setRecords(recordsWithStatus);
|
||||
for(Serializable primaryKey : deleteRequest.getPrimaryKeys())
|
||||
{
|
||||
QRecord qRecord = new QRecord().withTableName(deleteRequest.getTableName()).withPrimaryKey(primaryKey);
|
||||
QRecord qRecord = new QRecord().withTableName(deleteRequest.getTableName()).withValue("id", primaryKey);
|
||||
// todo uh, identify any errors?
|
||||
QRecordWithStatus recordWithStatus = new QRecordWithStatus(qRecord);
|
||||
recordsWithStatus.add(recordWithStatus);
|
||||
|
@ -86,7 +86,6 @@ public class RDBMSInsertAction extends AbstractRDBMSAction implements InsertInte
|
||||
{
|
||||
Integer id = idList.get(index++);
|
||||
QRecordWithStatus recordWithStatus = new QRecordWithStatus(record);
|
||||
recordWithStatus.setPrimaryKey(id);
|
||||
recordWithStatus.setValue(table.getPrimaryKeyField(), id);
|
||||
recordsWithStatus.add(recordWithStatus);
|
||||
}
|
||||
|
@ -93,6 +93,7 @@ public class RDBMSQueryAction extends AbstractRDBMSAction implements QueryInterf
|
||||
while(resultSet.next())
|
||||
{
|
||||
// todo - should refactor this for view etc to use too.
|
||||
// todo - Add display values (String labels for possibleValues, formatted #'s, etc)
|
||||
QRecord record = new QRecord();
|
||||
records.add(record);
|
||||
record.setTableName(table.getName());
|
||||
@ -104,10 +105,6 @@ public class RDBMSQueryAction extends AbstractRDBMSAction implements QueryInterf
|
||||
QFieldMetaData qFieldMetaData = fieldList.get(i - 1);
|
||||
Serializable value = getValue(qFieldMetaData, resultSet, i);
|
||||
values.put(qFieldMetaData.getName(), value);
|
||||
if(qFieldMetaData.getName().equals(table.getPrimaryKeyField()))
|
||||
{
|
||||
record.setPrimaryKey(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright © 2021-2021. Kingsrook LLC <contact@kingsrook.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.module.rdbms.actions;
|
||||
|
||||
|
||||
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.update.UpdateRequest;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.update.UpdateResult;
|
||||
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.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.modules.interfaces.UpdateInterface;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.RDBMSBackendMetaData;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class RDBMSUpdateAction extends AbstractRDBMSAction implements UpdateInterface
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public UpdateResult execute(UpdateRequest updateRequest) throws QException
|
||||
{
|
||||
try
|
||||
{
|
||||
UpdateResult rs = new UpdateResult();
|
||||
QTableMetaData table = updateRequest.getTable();
|
||||
|
||||
List<QRecordWithStatus> recordsWithStatus = new ArrayList<>();
|
||||
rs.setRecords(recordsWithStatus);
|
||||
|
||||
// todo - sql batch for performance
|
||||
// todo - if setting a bunch of records to have the same value, a single update where id IN?
|
||||
int recordIndex = 0;
|
||||
for(QRecord record : updateRequest.getRecords())
|
||||
{
|
||||
List<QFieldMetaData> updateableFields = table.getFields().values().stream()
|
||||
.filter(field -> !field.getName().equals("id")) // todo - intent here is to avoid non-updateable fields.
|
||||
.filter(field -> record.getValues().containsKey(field.getName()))
|
||||
.toList();
|
||||
|
||||
String columns = updateableFields.stream()
|
||||
.map(f -> this.getColumnName(f) + " = ?")
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
String tableName = table.getName();
|
||||
StringBuilder sql = new StringBuilder("UPDATE ").append(tableName)
|
||||
.append(" SET ").append(columns)
|
||||
.append(" WHERE ").append(getColumnName(table.getField(table.getPrimaryKeyField()))).append(" = ?");
|
||||
|
||||
// todo sql customization - can edit sql and/or param list
|
||||
|
||||
ConnectionManager connectionManager = new ConnectionManager();
|
||||
Connection connection = connectionManager.getConnection(new RDBMSBackendMetaData(updateRequest.getBackend()));
|
||||
|
||||
QRecordWithStatus recordWithStatus = new QRecordWithStatus(record);
|
||||
recordsWithStatus.add(recordWithStatus);
|
||||
|
||||
try
|
||||
{
|
||||
List<Object> params = new ArrayList<>();
|
||||
for(QFieldMetaData field : updateableFields)
|
||||
{
|
||||
params.add(record.getValue(field.getName()));
|
||||
}
|
||||
params.add(record.getValue(table.getPrimaryKeyField()));
|
||||
QueryManager.executeUpdate(connection, sql.toString(), params);
|
||||
// todo - auto-updated values, e.g., modifyDate... maybe need to re-select?
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
recordWithStatus.setErrors(new ArrayList<>(List.of(e)));
|
||||
}
|
||||
}
|
||||
|
||||
return rs;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new QException("Error executing update: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright © 2021-2021. Kingsrook LLC <contact@kingsrook.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.module.rdbms.actions;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.update.UpdateRequest;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.update.UpdateResult;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
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.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class RDBMSUpdateActionTest extends RDBMSActionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@BeforeEach
|
||||
public void beforeEach() throws Exception
|
||||
{
|
||||
super.primeTestDatabase();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testUpdateOne() throws Exception
|
||||
{
|
||||
UpdateRequest updateRequest = initUpdateRequest();
|
||||
QRecord record = new QRecord().withTableName("person")
|
||||
.withValue("id", 2)
|
||||
.withValue("firstName", "James")
|
||||
.withValue("lastName", "Kirk")
|
||||
.withValue("email", "jamestk@starfleet.net")
|
||||
.withValue("birthDate", "2210-05-20");
|
||||
updateRequest.setRecords(List.of(record));
|
||||
UpdateResult updateResult = new RDBMSUpdateAction().execute(updateRequest);
|
||||
assertEquals(1, updateResult.getRecords().size(), "Should return 1 row");
|
||||
assertEquals(2, updateResult.getRecords().get(0).getValue("id"), "Should have id=2 in the row");
|
||||
assertTrue(updateResult.getRecords().stream().noneMatch(qrs -> CollectionUtils.nullSafeHasContents(qrs.getErrors())), "There should be no errors");
|
||||
runTestSql("SELECT * FROM person WHERE last_name = 'Kirk'", (rs -> {
|
||||
int rowsFound = 0;
|
||||
while(rs.next())
|
||||
{
|
||||
rowsFound++;
|
||||
assertEquals(2, rs.getInt("id"));
|
||||
assertEquals("James", rs.getString("first_name"));
|
||||
assertEquals("2210-05-20", rs.getString("birth_date"));
|
||||
}
|
||||
assertEquals(1, rowsFound);
|
||||
}));
|
||||
runTestSql("SELECT * FROM person WHERE last_name = 'Maes'", (rs -> {
|
||||
if(rs.next())
|
||||
{
|
||||
fail("Should not have found Maes any more.");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testUpdateMany() throws Exception
|
||||
{
|
||||
UpdateRequest updateRequest = initUpdateRequest();
|
||||
QRecord record1 = new QRecord().withTableName("person")
|
||||
.withValue("id", 1)
|
||||
.withValue("firstName", "Darren")
|
||||
.withValue("lastName", "From Bewitched")
|
||||
.withValue("birthDate", "1900-01-01");
|
||||
|
||||
QRecord record2 = new QRecord().withTableName("person")
|
||||
.withValue("id", 3)
|
||||
.withValue("firstName", "Wilt")
|
||||
.withValue("birthDate", null);
|
||||
|
||||
updateRequest.setRecords(List.of(record1, record2));
|
||||
UpdateResult updateResult = new RDBMSUpdateAction().execute(updateRequest);
|
||||
assertEquals(2, updateResult.getRecords().size(), "Should return 2 rows");
|
||||
assertEquals(1, updateResult.getRecords().get(0).getValue("id"), "Should have expected ids in the row");
|
||||
assertEquals(3, updateResult.getRecords().get(1).getValue("id"), "Should have expected ids in the row");
|
||||
assertTrue(updateResult.getRecords().stream().noneMatch(qrs -> CollectionUtils.nullSafeHasContents(qrs.getErrors())), "There should be no errors");
|
||||
runTestSql("SELECT * FROM person WHERE last_name = 'From Bewitched'", (rs -> {
|
||||
int rowsFound = 0;
|
||||
while(rs.next())
|
||||
{
|
||||
rowsFound++;
|
||||
assertEquals(1, rs.getInt("id"));
|
||||
assertEquals("Darren", rs.getString("first_name"));
|
||||
assertEquals("From Bewitched", rs.getString("last_name"));
|
||||
assertEquals("1900-01-01", rs.getString("birth_date"));
|
||||
}
|
||||
assertEquals(1, rowsFound);
|
||||
}));
|
||||
runTestSql("SELECT * FROM person WHERE last_name = 'Chamberlain'", (rs -> {
|
||||
int rowsFound = 0;
|
||||
while(rs.next())
|
||||
{
|
||||
rowsFound++;
|
||||
assertEquals(3, rs.getInt("id"));
|
||||
assertEquals("Wilt", rs.getString("first_name"));
|
||||
assertNull(rs.getString("birth_date"));
|
||||
}
|
||||
assertEquals(1, rowsFound);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private UpdateRequest initUpdateRequest()
|
||||
{
|
||||
UpdateRequest updateRequest = new UpdateRequest();
|
||||
updateRequest.setInstance(defineInstance());
|
||||
updateRequest.setTableName(defineTablePerson().getName());
|
||||
return updateRequest;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user