mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
CE-781 initial set of tets for mongodb
This commit is contained in:
@ -25,10 +25,12 @@ package com.kingsrook.qqq.backend.module.mongodb.actions;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import com.kingsrook.qqq.backend.core.actions.QBackendTransaction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
@ -86,7 +88,8 @@ public class AbstractMongoDBAction
|
||||
return (new MongoClientContainer(mongoDBTransaction.getMongoClient(), mongoDBTransaction.getClientSession(), false));
|
||||
}
|
||||
|
||||
ConnectionString connectionString = new ConnectionString("mongodb://" + backend.getHost() + ":" + backend.getPort() + "/");
|
||||
String suffix = StringUtils.hasContent(backend.getUrlSuffix()) ? "?" + backend.getUrlSuffix() : "";
|
||||
ConnectionString connectionString = new ConnectionString("mongodb://" + backend.getHost() + ":" + backend.getPort() + "/" + suffix);
|
||||
|
||||
MongoCredential credential = MongoCredential.createCredential(backend.getUsername(), backend.getAuthSourceDatabase(), backend.getPassword().toCharArray());
|
||||
|
||||
@ -165,19 +168,66 @@ public class AbstractMongoDBAction
|
||||
QRecord record = new QRecord();
|
||||
record.setTableName(table.getName());
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// todo - this - or iterate over the values in the document?? //
|
||||
// seems like, maybe, this is an attribute in the table-backend-details? //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// first iterate over the table's fields, looking for them (at their backend name (path, //
|
||||
// if it has dots) inside the document note that we'll remove values from the document //
|
||||
// as we go - then after this loop, will handle all remaining values as unstructured fields //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Map<String, Serializable> values = record.getValues();
|
||||
for(QFieldMetaData field : table.getFields().values())
|
||||
{
|
||||
String fieldName = field.getName();
|
||||
String fieldBackendName = getFieldBackendName(field);
|
||||
Object value = document.get(fieldBackendName);
|
||||
String fieldName = field.getName();
|
||||
|
||||
setValue(values, fieldName, value);
|
||||
if(fieldBackendName.contains("."))
|
||||
{
|
||||
/////////////////////////////////////////////////////////////
|
||||
// process backend-names with dots as hierarchical objects //
|
||||
/////////////////////////////////////////////////////////////
|
||||
String[] parts = fieldBackendName.split("\\.");
|
||||
Document tmpDocument = document;
|
||||
for(int i = 0; i < parts.length - 1; i++)
|
||||
{
|
||||
if(!tmpDocument.containsKey(parts[i]))
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if we can't find the sub-document, break, and we won't have a value for this field (do we want null?) //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
setValue(values, fieldName, null);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(tmpDocument.get(parts[i]) instanceof Document subDocument)
|
||||
{
|
||||
tmpDocument = subDocument;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.warn("Unexpected - In table [" + table.getName() + "] found a non-document at sub-key [" + parts[i] + "] for field [" + field.getName() + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object value = tmpDocument.remove(parts[parts.length - 1]);
|
||||
setValue(values, fieldName, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Object value = document.remove(fieldBackendName);
|
||||
setValue(values, fieldName, value);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// handle remaining values in the document as un-structured //
|
||||
//////////////////////////////////////////////////////////////
|
||||
for(String subFieldName : document.keySet())
|
||||
{
|
||||
Object subValue = document.get(subFieldName);
|
||||
setValue(values, subFieldName, subValue);
|
||||
}
|
||||
|
||||
return (record);
|
||||
}
|
||||
|
||||
@ -227,17 +277,23 @@ public class AbstractMongoDBAction
|
||||
/*******************************************************************************
|
||||
** Convert a QRecord to a mongodb document.
|
||||
*******************************************************************************/
|
||||
protected Document recordToDocument(QTableMetaData table, QRecord record)
|
||||
protected Document recordToDocument(QTableMetaData table, QRecord record) throws QException
|
||||
{
|
||||
Document document = new Document();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// todo - this - or iterate over the values in the record?? //
|
||||
// seems like, maybe, this is an attribute in the table-backend-details? //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// first iterate over fields defined in the table - put them in the document for mongo first. //
|
||||
// track the names that we've processed in a set. then later we'll go over all values in the //
|
||||
// record and send them all to mongo (skipping ones we knew about from the table definition) //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Set<String> processedFields = new HashSet<>();
|
||||
|
||||
for(QFieldMetaData field : table.getFields().values())
|
||||
{
|
||||
if(field.getName().equals(table.getPrimaryKeyField()) && record.getValue(field.getName()) == null)
|
||||
Serializable value = record.getValue(field.getName());
|
||||
processedFields.add(field.getName());
|
||||
|
||||
if(field.getName().equals(table.getPrimaryKeyField()) && value == null)
|
||||
{
|
||||
////////////////////////////////////
|
||||
// let mongodb client generate id //
|
||||
@ -246,8 +302,53 @@ public class AbstractMongoDBAction
|
||||
}
|
||||
|
||||
String fieldBackendName = getFieldBackendName(field);
|
||||
document.append(fieldBackendName, record.getValue(field.getName()));
|
||||
if(fieldBackendName.contains("."))
|
||||
{
|
||||
/////////////////////////////////////////////////////////////
|
||||
// process backend-names with dots as hierarchical objects //
|
||||
/////////////////////////////////////////////////////////////
|
||||
String[] parts = fieldBackendName.split("\\.");
|
||||
Document tmpDocument = document;
|
||||
for(int i = 0; i < parts.length - 1; i++)
|
||||
{
|
||||
if(!tmpDocument.containsKey(parts[i]))
|
||||
{
|
||||
Document subDocument = new Document();
|
||||
tmpDocument.put(parts[i], subDocument);
|
||||
tmpDocument = subDocument;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(tmpDocument.get(parts[i]) instanceof Document subDocument)
|
||||
{
|
||||
tmpDocument = subDocument;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw (new QException("Fields in table [" + table.getName() + "] specify both a sub-object and a field at the key: " + parts[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
tmpDocument.append(parts[parts.length - 1], value);
|
||||
}
|
||||
else
|
||||
{
|
||||
document.append(fieldBackendName, value);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// do remaining values //
|
||||
/////////////////////////
|
||||
// for(Map.Entry<String, Serializable> entry : clone.getValues().entrySet())
|
||||
for(Map.Entry<String, Serializable> entry : record.getValues().entrySet())
|
||||
{
|
||||
if(!processedFields.contains(entry.getKey()))
|
||||
{
|
||||
document.append(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return (document);
|
||||
}
|
||||
|
||||
|
@ -141,126 +141,6 @@ public class MongoDBInsertAction extends AbstractMongoDBAction implements Insert
|
||||
}
|
||||
|
||||
return (rs);
|
||||
|
||||
/*
|
||||
try
|
||||
{
|
||||
List<QFieldMetaData> insertableFields = table.getFields().values().stream()
|
||||
.filter(field -> !field.getName().equals("id")) // todo - intent here is to avoid non-insertable fields.
|
||||
.toList();
|
||||
|
||||
String columns = insertableFields.stream()
|
||||
.map(f -> "`" + getColumnName(f) + "`")
|
||||
.collect(Collectors.joining(", "));
|
||||
String questionMarks = insertableFields.stream()
|
||||
.map(x -> "?")
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
List<QRecord> outputRecords = new ArrayList<>();
|
||||
rs.setRecords(outputRecords);
|
||||
|
||||
Connection connection;
|
||||
boolean needToCloseConnection = false;
|
||||
if(insertInput.getTransaction() != null && insertInput.getTransaction() instanceof RDBMSTransaction rdbmsTransaction)
|
||||
{
|
||||
connection = rdbmsTransaction.getConnection();
|
||||
}
|
||||
else
|
||||
{
|
||||
connection = getConnection(insertInput);
|
||||
needToCloseConnection = true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
for(List<QRecord> page : CollectionUtils.getPages(insertInput.getRecords(), QueryManager.PAGE_SIZE))
|
||||
{
|
||||
String tableName = escapeIdentifier(getTableName(table));
|
||||
StringBuilder sql = new StringBuilder("INSERT INTO ").append(tableName).append("(").append(columns).append(") VALUES");
|
||||
List<Object> params = new ArrayList<>();
|
||||
int recordIndex = 0;
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// for each record in the page: //
|
||||
// - if it has errors, skip it //
|
||||
// - else add a "(?,?,...,?)," clause to the INSERT //
|
||||
// - then add all fields into the params list //
|
||||
//////////////////////////////////////////////////////
|
||||
for(QRecord record : page)
|
||||
{
|
||||
if(CollectionUtils.nullSafeHasContents(record.getErrors()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(recordIndex++ > 0)
|
||||
{
|
||||
sql.append(",");
|
||||
}
|
||||
sql.append("(").append(questionMarks).append(")");
|
||||
|
||||
for(QFieldMetaData field : insertableFields)
|
||||
{
|
||||
Serializable value = record.getValue(field.getName());
|
||||
value = scrubValue(field, value);
|
||||
params.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if all records had errors, copy them to the output, and continue w/o running query //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(recordIndex == 0)
|
||||
{
|
||||
for(QRecord record : page)
|
||||
{
|
||||
QRecord outputRecord = new QRecord(record);
|
||||
outputRecords.add(outputRecord);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Long mark = System.currentTimeMillis();
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// execute the insert, then foreach record in the input, //
|
||||
// add it to the output, and set its generated id too. //
|
||||
///////////////////////////////////////////////////////////
|
||||
// todo sql customization - can edit sql and/or param list
|
||||
// todo - non-serial-id style tables
|
||||
// todo - other generated values, e.g., createDate... maybe need to re-select?
|
||||
List<Integer> idList = QueryManager.executeInsertForGeneratedIds(connection, sql.toString(), params);
|
||||
int index = 0;
|
||||
for(QRecord record : page)
|
||||
{
|
||||
QRecord outputRecord = new QRecord(record);
|
||||
outputRecords.add(outputRecord);
|
||||
|
||||
if(CollectionUtils.nullSafeIsEmpty(record.getErrors()))
|
||||
{
|
||||
Integer id = idList.get(index++);
|
||||
outputRecord.setValue(table.getPrimaryKeyField(), id);
|
||||
}
|
||||
}
|
||||
|
||||
logSQL(sql, params, mark);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(needToCloseConnection)
|
||||
{
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
return rs;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new QException("Error executing insert: " + e.getMessage(), e);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,8 +26,17 @@ import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.actions.AbstractMongoDBAction;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.actions.MongoClientContainer;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.model.metadata.MongoDBBackendMetaData;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -37,6 +46,27 @@ public class BaseTest
|
||||
{
|
||||
private static final QLogger LOG = QLogger.getLogger(BaseTest.class);
|
||||
|
||||
private static GenericContainer<?> mongoDBContainer;
|
||||
|
||||
private static final String MONGO_IMAGE = "mongo:4.2.0-bionic";
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@BeforeAll
|
||||
static void beforeAll()
|
||||
{
|
||||
mongoDBContainer = new GenericContainer<>(DockerImageName.parse(MONGO_IMAGE))
|
||||
.withEnv("MONGO_INITDB_ROOT_USERNAME", TestUtils.MONGO_USERNAME)
|
||||
.withEnv("MONGO_INITDB_ROOT_PASSWORD", TestUtils.MONGO_PASSWORD)
|
||||
.withEnv("MONGO_INITDB_DATABASE", TestUtils.MONGO_DATABASE)
|
||||
.withExposedPorts(TestUtils.MONGO_PORT);
|
||||
|
||||
mongoDBContainer.start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -46,6 +76,13 @@ public class BaseTest
|
||||
void baseBeforeEach()
|
||||
{
|
||||
QContext.init(TestUtils.defineInstance(), new QSession());
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// host could(?) be different, and mapped port will be, so set them in backend meta-data based on our running container //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
MongoDBBackendMetaData backend = (MongoDBBackendMetaData) QContext.getQInstance().getBackend(TestUtils.DEFAULT_BACKEND_NAME);
|
||||
backend.setHost(mongoDBContainer.getHost());
|
||||
backend.setPort(mongoDBContainer.getMappedPort(TestUtils.MONGO_PORT));
|
||||
}
|
||||
|
||||
|
||||
@ -56,11 +93,43 @@ public class BaseTest
|
||||
@AfterEach
|
||||
void baseAfterEach()
|
||||
{
|
||||
///////////////////////////////////////
|
||||
// clear test database between tests //
|
||||
///////////////////////////////////////
|
||||
MongoClient mongoClient = getMongoClient();
|
||||
MongoDatabase database = mongoClient.getDatabase(TestUtils.MONGO_DATABASE);
|
||||
database.drop();
|
||||
|
||||
QContext.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
protected static MongoClient getMongoClient()
|
||||
{
|
||||
MongoDBBackendMetaData backend = (MongoDBBackendMetaData) QContext.getQInstance().getBackend(TestUtils.DEFAULT_BACKEND_NAME);
|
||||
MongoClientContainer mongoClientContainer = new AbstractMongoDBAction().openClient(backend, null);
|
||||
MongoClient mongoClient = mongoClientContainer.getMongoClient();
|
||||
return mongoClient;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@AfterAll
|
||||
static void afterAll()
|
||||
{
|
||||
// this.mongoDbReplicaSet.close();
|
||||
mongoDBContainer.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** if needed, re-initialize the QInstance in context.
|
||||
*******************************************************************************/
|
||||
|
@ -43,6 +43,13 @@ public class TestUtils
|
||||
|
||||
public static final String SECURITY_KEY_STORE_ALL_ACCESS = "storeAllAccess";
|
||||
|
||||
public static final String MONGO_USERNAME = "mongoUser";
|
||||
public static final String MONGO_PASSWORD = "password";
|
||||
public static final Integer MONGO_PORT = 27017;
|
||||
public static final String MONGO_DATABASE = "testDatabase";
|
||||
|
||||
public static final String TEST_COLLECTION = "testTable";
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -105,12 +112,11 @@ public class TestUtils
|
||||
return (new MongoDBBackendMetaData()
|
||||
.withName(DEFAULT_BACKEND_NAME)
|
||||
.withHost("localhost")
|
||||
.withPort(27017)
|
||||
.withUsername("ctliveuser")
|
||||
.withPassword("uoaKOIjfk23h8lozK983L")
|
||||
.withPort(TestUtils.MONGO_PORT)
|
||||
.withUsername(TestUtils.MONGO_USERNAME)
|
||||
.withPassword(TestUtils.MONGO_PASSWORD)
|
||||
.withAuthSourceDatabase("admin")
|
||||
.withDatabaseName("testDatabase")
|
||||
/*.withUrlSuffix("?tls=true&tlsCAFile=global-bundle.pem&retryWrites=false")*/);
|
||||
.withDatabaseName(TestUtils.MONGO_DATABASE));
|
||||
}
|
||||
|
||||
|
||||
@ -128,8 +134,8 @@ public class TestUtils
|
||||
.withBackendName(DEFAULT_BACKEND_NAME)
|
||||
.withPrimaryKeyField("id")
|
||||
.withField(new QFieldMetaData("id", QFieldType.STRING).withBackendName("_id"))
|
||||
.withField(new QFieldMetaData("createDate", QFieldType.DATE_TIME))
|
||||
.withField(new QFieldMetaData("modifyDate", QFieldType.DATE_TIME))
|
||||
.withField(new QFieldMetaData("createDate", QFieldType.DATE_TIME).withBackendName("metaData.createDate"))
|
||||
.withField(new QFieldMetaData("modifyDate", QFieldType.DATE_TIME).withBackendName("metaData.modifyDate"))
|
||||
.withField(new QFieldMetaData("firstName", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("lastName", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("birthDate", QFieldType.DATE))
|
||||
@ -139,7 +145,7 @@ public class TestUtils
|
||||
.withField(new QFieldMetaData("daysWorked", QFieldType.INTEGER))
|
||||
.withField(new QFieldMetaData("homeTown", QFieldType.STRING))
|
||||
.withBackendDetails(new MongoDBTableBackendDetails()
|
||||
.withTableName("testTable"));
|
||||
.withTableName(TEST_COLLECTION));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.module.mongodb.actions;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.AggregateAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.Aggregate;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.GroupBy;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByAggregate;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByGroupBy;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.BaseTest;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for MongoDBQueryAction
|
||||
*******************************************************************************/
|
||||
class MongoDBAggregateActionTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_PERSON);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("firstName", "Darin").withValue("lastName", "Kelkhoff").withValue("isEmployed", true).withValue("annualSalary", 1),
|
||||
new QRecord().withValue("firstName", "Linda").withValue("lastName", "Kelkhoff").withValue("isEmployed", true).withValue("annualSalary", 5),
|
||||
new QRecord().withValue("firstName", "Tim").withValue("lastName", "Chamberlain").withValue("isEmployed", true).withValue("annualSalary", 3),
|
||||
new QRecord().withValue("firstName", "James").withValue("lastName", "Maes").withValue("isEmployed", true).withValue("annualSalary", 5),
|
||||
new QRecord().withValue("firstName", "J.D.").withValue("lastName", "Maes").withValue("isEmployed", false).withValue("annualSalary", 0)
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
{
|
||||
AggregateInput aggregateInput = new AggregateInput();
|
||||
aggregateInput.setTableName(TestUtils.TABLE_NAME_PERSON);
|
||||
aggregateInput.setFilter(new QQueryFilter()
|
||||
.withOrderBy(new QFilterOrderByAggregate(new Aggregate("annualSalary", AggregateOperator.MAX)).withIsAscending(false))
|
||||
.withOrderBy(new QFilterOrderByGroupBy(new GroupBy(QFieldType.STRING, "lastName")))
|
||||
);
|
||||
aggregateInput.withAggregate(new Aggregate("id", AggregateOperator.COUNT));
|
||||
aggregateInput.withAggregate(new Aggregate("annualSalary", AggregateOperator.SUM));
|
||||
aggregateInput.withAggregate(new Aggregate("annualSalary", AggregateOperator.MAX));
|
||||
aggregateInput.withGroupBy(new GroupBy(QFieldType.STRING, "lastName"));
|
||||
aggregateInput.withGroupBy(new GroupBy(QFieldType.BOOLEAN, "isEmployed"));
|
||||
AggregateOutput aggregateOutput = new AggregateAction().execute(aggregateInput);
|
||||
// todo - actual assertions
|
||||
}
|
||||
{
|
||||
AggregateInput aggregateInput = new AggregateInput();
|
||||
aggregateInput.setTableName(TestUtils.TABLE_NAME_PERSON);
|
||||
aggregateInput.withAggregate(new Aggregate("id", AggregateOperator.COUNT));
|
||||
aggregateInput.withAggregate(new Aggregate("annualSalary", AggregateOperator.AVG));
|
||||
AggregateOutput aggregateOutput = new AggregateAction().execute(aggregateInput);
|
||||
// todo - actual assertions
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.module.mongodb.actions;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||
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.query.QCriteriaOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.BaseTest;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.TestUtils;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import org.bson.Document;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for MongoDBQueryAction
|
||||
*******************************************************************************/
|
||||
class MongoDBCountActionTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// directly insert some mongo records //
|
||||
////////////////////////////////////////
|
||||
MongoDatabase database = getMongoClient().getDatabase(TestUtils.MONGO_DATABASE);
|
||||
MongoCollection<Document> collection = database.getCollection(TestUtils.TEST_COLLECTION);
|
||||
collection.insertMany(List.of(
|
||||
Document.parse("""
|
||||
{"firstName": "Darin", "lastName": "Kelkhoff"}"""),
|
||||
Document.parse("""
|
||||
{"firstName": "Tylers", "lastName": "Sample"}"""),
|
||||
Document.parse("""
|
||||
{"firstName": "Tylers", "lastName": "Simple"}"""),
|
||||
Document.parse("""
|
||||
{"firstName": "Thom", "lastName": "Chutterloin"}""")
|
||||
));
|
||||
|
||||
CountInput countInput = new CountInput();
|
||||
countInput.setTableName(TestUtils.TABLE_NAME_PERSON);
|
||||
assertEquals(4, new CountAction().execute(countInput).getCount());
|
||||
|
||||
countInput.setFilter(new QQueryFilter(new QFilterCriteria("firstName", QCriteriaOperator.EQUALS, "Tylers")));
|
||||
assertEquals(2, new CountAction().execute(countInput).getCount());
|
||||
|
||||
countInput.setFilter(new QQueryFilter(new QFilterCriteria("firstName", QCriteriaOperator.EQUALS, "assdf")));
|
||||
assertEquals(0, new CountAction().execute(countInput).getCount());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.module.mongodb.actions;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.BaseTest;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.TestUtils;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import org.bson.Document;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for MongoDBQueryAction
|
||||
*******************************************************************************/
|
||||
class MongoDBDeleteActionTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// directly insert some mongo records //
|
||||
////////////////////////////////////////
|
||||
MongoDatabase database = getMongoClient().getDatabase(TestUtils.MONGO_DATABASE);
|
||||
MongoCollection<Document> collection = database.getCollection(TestUtils.TEST_COLLECTION);
|
||||
collection.insertMany(List.of(
|
||||
Document.parse("""
|
||||
{"firstName": "Darin", "lastName": "Kelkhoff"}"""),
|
||||
Document.parse("""
|
||||
{"firstName": "Tylers", "lastName": "Sample"}"""),
|
||||
Document.parse("""
|
||||
{"firstName": "Tylers", "lastName": "Simple"}"""),
|
||||
Document.parse("""
|
||||
{"firstName": "Thom", "lastName": "Chutterloin"}""")
|
||||
));
|
||||
assertEquals(4, collection.countDocuments());
|
||||
|
||||
//////////////////////////////////////////
|
||||
// do a delete by id (look it up first) //
|
||||
//////////////////////////////////////////
|
||||
{
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(TestUtils.TABLE_NAME_PERSON);
|
||||
queryInput.setFilter(new QQueryFilter(new QFilterCriteria("firstName", QCriteriaOperator.EQUALS, "Darin")));
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
String id0 = queryOutput.getRecords().get(0).getValueString("id");
|
||||
|
||||
DeleteInput deleteInput = new DeleteInput();
|
||||
deleteInput.setTableName(TestUtils.TABLE_NAME_PERSON);
|
||||
deleteInput.setPrimaryKeys(List.of(id0));
|
||||
assertEquals(1, new DeleteAction().execute(deleteInput).getDeletedRecordCount());
|
||||
}
|
||||
assertEquals(3, collection.countDocuments());
|
||||
|
||||
///////////////////////////
|
||||
// do a delete by filter //
|
||||
///////////////////////////
|
||||
{
|
||||
DeleteInput deleteInput = new DeleteInput();
|
||||
deleteInput.setTableName(TestUtils.TABLE_NAME_PERSON);
|
||||
deleteInput.setQueryFilter(new QQueryFilter(new QFilterCriteria("firstName", QCriteriaOperator.EQUALS, "Tylers")));
|
||||
assertEquals(2, new DeleteAction().execute(deleteInput).getDeletedRecordCount());
|
||||
}
|
||||
assertEquals(1, collection.countDocuments());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.module.mongodb.actions;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
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.module.mongodb.BaseTest;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.TestUtils;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import org.bson.Document;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for MongoDBQueryAction
|
||||
*******************************************************************************/
|
||||
class MongoDBInsertActionTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_PERSON);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("firstName", "Darin")
|
||||
.withValue("unmappedField", 1701)
|
||||
.withValue("unmappedList", new ArrayList<>(List.of("A", "B", "C")))
|
||||
.withValue("unmappedObject", new HashMap<>(Map.of("A", 1, "C", true))),
|
||||
new QRecord().withValue("firstName", "Tim"),
|
||||
new QRecord().withValue("firstName", "Tyler")
|
||||
));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
|
||||
/////////////////////////////////////////
|
||||
// make sure id got put on all records //
|
||||
/////////////////////////////////////////
|
||||
for(QRecord record : insertOutput.getRecords())
|
||||
{
|
||||
assertNotNull(record.getValueString("id"));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// directly query mongo for the inserted records //
|
||||
///////////////////////////////////////////////////
|
||||
MongoDatabase database = getMongoClient().getDatabase(TestUtils.MONGO_DATABASE);
|
||||
MongoCollection<Document> collection = database.getCollection(TestUtils.TEST_COLLECTION);
|
||||
assertEquals(3, collection.countDocuments());
|
||||
for(Document document : collection.find())
|
||||
{
|
||||
/////////////////////////////////////////////////////////////
|
||||
// make sure values got set - including some nested values //
|
||||
/////////////////////////////////////////////////////////////
|
||||
assertNotNull(document.get("firstName"));
|
||||
assertNotNull(document.get("metaData"));
|
||||
assertThat(document.get("metaData")).isInstanceOf(Document.class);
|
||||
assertNotNull(((Document) document.get("metaData")).get("createDate"));
|
||||
}
|
||||
|
||||
Document document = collection.find(new Document("firstName", "Darin")).first();
|
||||
assertNotNull(document);
|
||||
assertEquals(1701, document.get("unmappedField"));
|
||||
assertEquals(List.of("A", "B", "C"), document.get("unmappedList"));
|
||||
assertEquals(Map.of("A", 1, "C", true), document.get("unmappedObject"));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.module.mongodb.actions;
|
||||
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.BaseTest;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.TestUtils;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import org.bson.Document;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for MongoDBQueryAction
|
||||
*******************************************************************************/
|
||||
class MongoDBQueryActionTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@BeforeEach
|
||||
void beforeEach()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// directly insert some mongo records //
|
||||
////////////////////////////////////////
|
||||
MongoDatabase database = getMongoClient().getDatabase(TestUtils.MONGO_DATABASE);
|
||||
MongoCollection<Document> collection = database.getCollection(TestUtils.TEST_COLLECTION);
|
||||
collection.insertMany(List.of(
|
||||
Document.parse("""
|
||||
{ "metaData": {"createDate": "2023-01-09T01:01:01.123Z", "modifyDate": "2023-01-09T02:02:02.123Z", "oops": "All Crunchberries"},
|
||||
"firstName": "Darin",
|
||||
"lastName": "Kelkhoff",
|
||||
"unmappedField": 1701,
|
||||
"unmappedList": [1,2,3],
|
||||
"unmappedObject": {
|
||||
"A": "B",
|
||||
"One": 2,
|
||||
"subSub": {
|
||||
"so": true
|
||||
}
|
||||
}
|
||||
}"""),
|
||||
Document.parse("""
|
||||
{"metaData": {"createDate": "2023-01-09T03:03:03.123Z", "modifyDate": "2023-01-09T04:04:04.123Z"}, "firstName": "Tylers", "lastName": "Sample"}""")
|
||||
));
|
||||
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(TestUtils.TABLE_NAME_PERSON);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
|
||||
assertEquals(2, queryOutput.getRecords().size());
|
||||
|
||||
QRecord record = queryOutput.getRecords().get(0);
|
||||
assertEquals(Instant.parse("2023-01-09T01:01:01.123Z"), record.getValueInstant("createDate"));
|
||||
assertEquals(Instant.parse("2023-01-09T02:02:02.123Z"), record.getValueInstant("modifyDate"));
|
||||
assertThat(record.getValue("id")).isInstanceOf(String.class);
|
||||
assertEquals("Darin", record.getValueString("firstName"));
|
||||
assertEquals("Kelkhoff", record.getValueString("lastName"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// test that un-mapped (or un-structured) fields come through, with their shape as they exist in the mongo record //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
assertEquals(1701, record.getValueInteger("unmappedField"));
|
||||
assertEquals(List.of(1, 2, 3), record.getValue("unmappedList"));
|
||||
assertEquals(Map.of("A", "B", "One", 2, "subSub", Map.of("so", true)), record.getValue("unmappedObject"));
|
||||
assertEquals(Map.of("oops", "All Crunchberries"), record.getValue("metaData"));
|
||||
|
||||
record = queryOutput.getRecords().get(1);
|
||||
assertEquals(Instant.parse("2023-01-09T03:03:03.123Z"), record.getValueInstant("createDate"));
|
||||
assertEquals(Instant.parse("2023-01-09T04:04:04.123Z"), record.getValueInstant("modifyDate"));
|
||||
assertEquals("Tylers", record.getValueString("firstName"));
|
||||
assertEquals("Sample", record.getValueString("lastName"));
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
@ -19,26 +19,27 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.actions.interfaces;
|
||||
package com.kingsrook.qqq.backend.module.mongodb.actions;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.actions.QBackendTransaction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
|
||||
import com.kingsrook.qqq.backend.module.mongodb.BaseTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Unit test for MongoDBUpdateAction
|
||||
*******************************************************************************/
|
||||
public interface QActionInterface
|
||||
class MongoDBUpdateActionTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
default QBackendTransaction openTransaction(AbstractTableActionInput input) throws QException
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
return (new QBackendTransaction());
|
||||
// todo - test!!
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user