mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-19 21:50:45 +00:00
handle ExposedJoins in exports
This commit is contained in:
@ -23,8 +23,12 @@ package com.kingsrook.qqq.backend.core.actions.reporting;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||
import com.kingsrook.qqq.backend.core.actions.async.AsyncJobManager;
|
||||
@ -32,6 +36,7 @@ import com.kingsrook.qqq.backend.core.actions.async.AsyncJobState;
|
||||
import com.kingsrook.qqq.backend.core.actions.async.AsyncJobStatus;
|
||||
import com.kingsrook.qqq.backend.core.actions.interfaces.CountInterface;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QReportingException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
@ -41,10 +46,13 @@ import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
||||
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.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.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.ExposedJoin;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
|
||||
@ -95,15 +103,25 @@ public class ExportAction
|
||||
///////////////////////////////////
|
||||
if(CollectionUtils.nullSafeHasContents(exportInput.getFieldNames()))
|
||||
{
|
||||
QTableMetaData table = exportInput.getTable();
|
||||
List<String> badFieldNames = new ArrayList<>();
|
||||
QTableMetaData table = exportInput.getTable();
|
||||
Map<String, QTableMetaData> joinTableMap = getJoinTableMap(table);
|
||||
|
||||
List<String> badFieldNames = new ArrayList<>();
|
||||
for(String fieldName : exportInput.getFieldNames())
|
||||
{
|
||||
try
|
||||
{
|
||||
table.getField(fieldName);
|
||||
if(fieldName.contains("."))
|
||||
{
|
||||
String[] parts = fieldName.split("\\.", 2);
|
||||
joinTableMap.get(parts[0]).getField(parts[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
table.getField(fieldName);
|
||||
}
|
||||
}
|
||||
catch(IllegalArgumentException iae)
|
||||
catch(Exception e)
|
||||
{
|
||||
badFieldNames.add(fieldName);
|
||||
}
|
||||
@ -128,6 +146,21 @@ public class ExportAction
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static Map<String, QTableMetaData> getJoinTableMap(QTableMetaData table)
|
||||
{
|
||||
Map<String, QTableMetaData> joinTableMap = new HashMap<>();
|
||||
for(ExposedJoin exposedJoin : CollectionUtils.nonNullList(table.getExposedJoins()))
|
||||
{
|
||||
joinTableMap.put(exposedJoin.getJoinTable(), QContext.getQInstance().getTable(exposedJoin.getJoinTable()));
|
||||
}
|
||||
return joinTableMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Run the report.
|
||||
*******************************************************************************/
|
||||
@ -151,7 +184,33 @@ public class ExportAction
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(exportInput.getTableName());
|
||||
queryInput.setFilter(exportInput.getQueryFilter());
|
||||
queryInput.setLimit(exportInput.getLimit());
|
||||
|
||||
List<QueryJoin> queryJoins = new ArrayList<>();
|
||||
Set<String> addedJoinNames = new HashSet<>();
|
||||
if(CollectionUtils.nullSafeHasContents(exportInput.getFieldNames()))
|
||||
{
|
||||
for(String fieldName : exportInput.getFieldNames())
|
||||
{
|
||||
if(fieldName.contains("."))
|
||||
{
|
||||
String[] parts = fieldName.split("\\.", 2);
|
||||
String joinTableName = parts[0];
|
||||
if(!addedJoinNames.contains(joinTableName))
|
||||
{
|
||||
queryJoins.add(new QueryJoin(joinTableName).withType(QueryJoin.Type.LEFT).withSelect(true));
|
||||
addedJoinNames.add(joinTableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
queryInput.setQueryJoins(queryJoins);
|
||||
|
||||
if(queryInput.getFilter() == null)
|
||||
{
|
||||
queryInput.setFilter(new QQueryFilter());
|
||||
}
|
||||
queryInput.getFilter().setLimit(exportInput.getLimit());
|
||||
queryInput.setShouldTranslatePossibleValues(true);
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
@ -298,11 +357,29 @@ public class ExportAction
|
||||
*******************************************************************************/
|
||||
private List<QFieldMetaData> getFields(ExportInput exportInput)
|
||||
{
|
||||
QTableMetaData table = exportInput.getTable();
|
||||
Map<String, QTableMetaData> joinTableMap = getJoinTableMap(table);
|
||||
|
||||
List<QFieldMetaData> fieldList;
|
||||
QTableMetaData table = exportInput.getTable();
|
||||
if(exportInput.getFieldNames() != null)
|
||||
{
|
||||
fieldList = exportInput.getFieldNames().stream().map(table::getField).toList();
|
||||
fieldList = new ArrayList<>();
|
||||
for(String fieldName : exportInput.getFieldNames())
|
||||
{
|
||||
if(fieldName.contains("."))
|
||||
{
|
||||
String[] parts = fieldName.split("\\.", 2);
|
||||
QTableMetaData joinTable = joinTableMap.get(parts[0]);
|
||||
QFieldMetaData field = joinTable.getField(parts[1]).clone();
|
||||
field.setName(fieldName);
|
||||
field.setLabel(joinTable.getLabel() + ": " + field.getLabel());
|
||||
fieldList.add(field);
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldList.add(table.getField(fieldName));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -38,13 +38,16 @@ import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
|
||||
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;
|
||||
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.update.UpdateInput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.joins.JoinOn;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.implementations.utils.BackendQueryFilterUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
@ -181,7 +184,7 @@ public class MemoryRecordStore
|
||||
}
|
||||
|
||||
BackendQueryFilterUtils.sortRecordList(input.getFilter(), records);
|
||||
records = BackendQueryFilterUtils.applySkipAndLimit(input, records);
|
||||
records = BackendQueryFilterUtils.applySkipAndLimit(input.getFilter(), records);
|
||||
|
||||
return (records);
|
||||
}
|
||||
@ -191,8 +194,11 @@ public class MemoryRecordStore
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private Collection<QRecord> buildJoinCrossProduct(QueryInput input)
|
||||
private Collection<QRecord> buildJoinCrossProduct(QueryInput input) throws QException
|
||||
{
|
||||
QInstance qInstance = QContext.getQInstance();
|
||||
JoinsContext joinsContext = new JoinsContext(qInstance, input.getTableName(), input.getQueryJoins(), input.getFilter());
|
||||
|
||||
List<QRecord> crossProduct = new ArrayList<>();
|
||||
QTableMetaData leftTable = input.getTable();
|
||||
for(QRecord record : getTableData(leftTable).values())
|
||||
@ -204,16 +210,26 @@ public class MemoryRecordStore
|
||||
|
||||
for(QueryJoin queryJoin : input.getQueryJoins())
|
||||
{
|
||||
QTableMetaData nextTable = QContext.getQInstance().getTable(queryJoin.getJoinTable());
|
||||
QTableMetaData nextTable = qInstance.getTable(queryJoin.getJoinTable());
|
||||
Collection<QRecord> nextTableRecords = getTableData(nextTable).values();
|
||||
|
||||
QJoinMetaData joinMetaData = Objects.requireNonNullElseGet(queryJoin.getJoinMetaData(), () ->
|
||||
{
|
||||
QJoinMetaData found = joinsContext.findJoinMetaData(qInstance, input.getTableName(), queryJoin.getJoinTable());
|
||||
if(found == null)
|
||||
{
|
||||
throw (new RuntimeException("Could not find a join between tables [" + input.getTableName() + "][" + queryJoin.getJoinTable() + "]"));
|
||||
}
|
||||
return (found);
|
||||
});
|
||||
|
||||
List<QRecord> nextLevelProduct = new ArrayList<>();
|
||||
for(QRecord productRecord : crossProduct)
|
||||
{
|
||||
boolean matchFound = false;
|
||||
for(QRecord nextTableRecord : nextTableRecords)
|
||||
{
|
||||
if(joinMatches(productRecord, nextTableRecord, queryJoin))
|
||||
if(joinMatches(productRecord, nextTableRecord, queryJoin, joinMetaData))
|
||||
{
|
||||
QRecord joinRecord = new QRecord(productRecord);
|
||||
addRecordToProduct(joinRecord, nextTableRecord, queryJoin.getJoinTableOrItsAlias());
|
||||
@ -239,9 +255,9 @@ public class MemoryRecordStore
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private boolean joinMatches(QRecord productRecord, QRecord nextTableRecord, QueryJoin queryJoin)
|
||||
private boolean joinMatches(QRecord productRecord, QRecord nextTableRecord, QueryJoin queryJoin, QJoinMetaData joinMetaData)
|
||||
{
|
||||
for(JoinOn joinOn : queryJoin.getJoinMetaData().getJoinOns())
|
||||
for(JoinOn joinOn : joinMetaData.getJoinOns())
|
||||
{
|
||||
Serializable leftValue = productRecord.getValues().containsKey(queryJoin.getBaseTableOrAlias() + "." + joinOn.getLeftField())
|
||||
? productRecord.getValue(queryJoin.getBaseTableOrAlias() + "." + joinOn.getLeftField())
|
||||
|
Reference in New Issue
Block a user