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.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput; 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.count.CountOutput;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
/******************************************************************************* /*******************************************************************************
@ -43,14 +42,7 @@ public class MemoryCountAction implements CountInterface
{ {
try try
{ {
if(CollectionUtils.nullSafeHasContents(countInput.getQueryJoins())) CountOutput countOutput = MemoryRecordStore.getInstance().count(countInput);
{
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); return (countOutput);
} }
catch(Exception e) catch(Exception e)

View File

@ -33,10 +33,12 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.DateTimeGroupBy; 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.QFilterOrderByAggregate;
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByGroupBy; 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.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.DeleteInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput; import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext; 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.ListingHash;
import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils;
import com.kingsrook.qqq.backend.core.utils.ValueUtils; 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 queryInput = new QueryInput();
queryInput.setTableName(input.getTableName()); queryInput.setTableName(input.getTableName());
if(input.getFilter() != null) if(input.getFilter() != null)
{ {
queryInput.setFilter(input.getFilter().clone().withSkip(null).withLimit(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); 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.QFilterOrderByAggregate;
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByGroupBy; 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.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.DeleteInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteOutput; import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteOutput;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput; 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.QFilterOrderBy;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; 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.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.query.QueryOutput;
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput; 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.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());
}
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/