Support queryJoins and distinctCount in memory count action

This commit is contained in:
2025-05-27 11:34:04 -05:00
parent 2a76736474
commit 23e9ac5b61
3 changed files with 79 additions and 11 deletions

View File

@ -26,7 +26,6 @@ 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;
/*******************************************************************************
@ -43,14 +42,7 @@ 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());
CountOutput countOutput = MemoryRecordStore.getInstance().count(countInput);
return (countOutput);
}
catch(Exception e)

View File

@ -33,10 +33,12 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.DateTimeGroupBy;
@ -54,6 +56,7 @@ 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.count.CountInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
@ -77,6 +80,7 @@ import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
import com.kingsrook.qqq.backend.core.utils.ListingHash;
import com.kingsrook.qqq.backend.core.utils.StringUtils;
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
import org.apache.commons.lang3.BooleanUtils;
/*******************************************************************************
@ -335,17 +339,55 @@ public class MemoryRecordStore
/*******************************************************************************
**
*******************************************************************************/
public Integer count(CountInput input) throws QException
public CountOutput count(CountInput input) throws QException
{
////////////////////////////////////////////////////////////////////////////////////////////
// set up a query input - we'll implement count by counting the records in a query output //
////////////////////////////////////////////////////////////////////////////////////////////
QueryInput queryInput = new QueryInput();
queryInput.setTableName(input.getTableName());
if(input.getFilter() != null)
{
queryInput.setFilter(input.getFilter().clone().withSkip(null).withLimit(null));
}
if(input.getQueryJoins() != null)
{
queryInput.setQueryJoins(new ArrayList<>());
for(QueryJoin queryJoin : input.getQueryJoins())
{
queryInput.getQueryJoins().add(queryJoin.clone());
}
}
///////////////////
// run the query //
///////////////////
List<QRecord> queryResult = query(queryInput);
return (queryResult.size());
////////////////////////
// build count output //
////////////////////////
CountOutput countOutput = new CountOutput();
countOutput.setCount(queryResult.size());
//////////////////////////////////////
// figure out distinct if requested //
//////////////////////////////////////
if(BooleanUtils.isTrue(input.getIncludeDistinctCount()))
{
QTableMetaData table = QContext.getQInstance().getTable(input.getTableName());
String primaryKeyField = table.getPrimaryKeyField();
Set<Serializable> distinctValues = new HashSet<>();
for(QRecord record : queryResult)
{
distinctValues.add(record.getValue(primaryKeyField));
}
countOutput.setDistinctCount(distinctValues.size());
}
return (countOutput);
}

View File

@ -47,6 +47,7 @@ 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.count.CountInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteOutput;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
@ -56,6 +57,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
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.QueryJoin;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput;
@ -725,6 +727,38 @@ class MemoryBackendModuleTest extends BaseTest
/*******************************************************************************
**
*******************************************************************************/
@Test
void testJoins() throws QException
{
QContext.getQSession().setSecurityKeyValues(Map.of(TestUtils.SECURITY_KEY_TYPE_STORE_ALL_ACCESS, List.of(true)));
new InsertAction().execute(new InsertInput(TestUtils.TABLE_NAME_ORDER).withRecords(List.of(
new QRecord().withValue("id", 1),
new QRecord().withValue("id", 2)
)));
new InsertAction().execute(new InsertInput(TestUtils.TABLE_NAME_LINE_ITEM).withRecords(List.of(
new QRecord().withValue("sku", "A").withValue("orderId", 1),
new QRecord().withValue("sku", "B").withValue("orderId", 1),
new QRecord().withValue("sku", "A").withValue("orderId", 2)
)));
QueryOutput queryOutput = new QueryAction().execute(new QueryInput(TestUtils.TABLE_NAME_ORDER)
.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_LINE_ITEM)));
assertEquals(3, queryOutput.getRecords().size());
CountOutput countOutput = new CountAction().execute(new CountInput(TestUtils.TABLE_NAME_ORDER)
.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_LINE_ITEM))
.withIncludeDistinctCount(true));
assertEquals(3, countOutput.getCount());
assertEquals(2, countOutput.getDistinctCount());
}
/*******************************************************************************
**
*******************************************************************************/