CE-881 - Refactoring exports & reports

- add some fields together into ReportDestination class
- pass more data into export streamers (views) and add preRun method
- Add queryHint POTENTIALLY_LARGE_NUMBER_OF_RESULTS
- add pivot views
- optionally take in full ReportMetaData object instead of a name (e.g., for a user-defined/saved report)
This commit is contained in:
2024-03-27 19:50:06 -05:00
parent 05f31d0722
commit e078015732
17 changed files with 421 additions and 165 deletions

View File

@ -31,6 +31,7 @@ import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
import com.kingsrook.qqq.backend.core.model.data.QRecord; 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.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils;
@ -65,12 +66,12 @@ public class CsvExportStreamer implements ExportStreamerInterface
** **
*******************************************************************************/ *******************************************************************************/
@Override @Override
public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label) throws QReportingException public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label, QReportView view) throws QReportingException
{ {
this.exportInput = exportInput; this.exportInput = exportInput;
this.fields = fields; this.fields = fields;
table = exportInput.getTable(); table = exportInput.getTable();
outputStream = this.exportInput.getReportOutputStream(); outputStream = this.exportInput.getReportDestination().getReportOutputStream();
writeTitleAndHeader(); writeTitleAndHeader();
} }

View File

@ -52,6 +52,7 @@ 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.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; 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.fields.QFieldType;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
import com.kingsrook.qqq.backend.core.model.metadata.tables.ExposedJoin; 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.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher; import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher;
@ -138,7 +139,7 @@ public class ExportAction
/////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////
// check if this report format has a max-rows limit -- if so, do a count to verify we're under the limit // // check if this report format has a max-rows limit -- if so, do a count to verify we're under the limit //
/////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////
ReportFormat reportFormat = exportInput.getReportFormat(); ReportFormat reportFormat = exportInput.getReportDestination().getReportFormat();
verifyCountUnderMax(exportInput, backendModule, reportFormat); verifyCountUnderMax(exportInput, backendModule, reportFormat);
preExecuteRan = true; preExecuteRan = true;
@ -232,6 +233,7 @@ public class ExportAction
} }
queryInput.getFilter().setLimit(exportInput.getLimit()); queryInput.getFilter().setLimit(exportInput.getLimit());
queryInput.setShouldTranslatePossibleValues(true); queryInput.setShouldTranslatePossibleValues(true);
queryInput.withQueryHint(QueryInput.QueryHint.POTENTIALLY_LARGE_NUMBER_OF_RESULTS);
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// tell this query that it needs to put its output into a pipe // // tell this query that it needs to put its output into a pipe //
@ -242,10 +244,19 @@ public class ExportAction
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// set up a report streamer, which will read rows from the pipe, and write formatted report rows to the output stream // // set up a report streamer, which will read rows from the pipe, and write formatted report rows to the output stream //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ReportFormat reportFormat = exportInput.getReportFormat(); ReportFormat reportFormat = exportInput.getReportDestination().getReportFormat();
ExportStreamerInterface reportStreamer = reportFormat.newReportStreamer(); ExportStreamerInterface reportStreamer = reportFormat.newReportStreamer();
List<QFieldMetaData> fields = getFields(exportInput); List<QFieldMetaData> fields = getFields(exportInput);
reportStreamer.start(exportInput, fields, "Sheet 1");
//////////////////////////////////////////////////////////
// it seems we can pass a view with just a name in here //
//////////////////////////////////////////////////////////
List<QReportView> views = new ArrayList<>();
views.add(new QReportView()
.withName("export"));
reportStreamer.preRun(exportInput.getReportDestination(), views);
reportStreamer.start(exportInput, fields, "Sheet 1", views.get(0));
////////////////////////////////////////// //////////////////////////////////////////
// run the query action as an async job // // run the query action as an async job //
@ -334,7 +345,7 @@ public class ExportAction
try try
{ {
exportInput.getReportOutputStream().close(); exportInput.getReportDestination().getReportOutputStream().close();
} }
catch(Exception e) catch(Exception e)
{ {

View File

@ -26,8 +26,10 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import com.kingsrook.qqq.backend.core.exceptions.QReportingException; import com.kingsrook.qqq.backend.core.exceptions.QReportingException;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
import com.kingsrook.qqq.backend.core.model.data.QRecord; 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.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
/******************************************************************************* /*******************************************************************************
@ -35,20 +37,14 @@ import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
*******************************************************************************/ *******************************************************************************/
public interface ExportStreamerInterface public interface ExportStreamerInterface
{ {
/*******************************************************************************
** Called once, before any rows are available. Meant to write a header, for example.
*******************************************************************************/
void start(ExportInput exportInput, List<QFieldMetaData> fields, String label) throws QReportingException;
/******************************************************************************* /*******************************************************************************
** Called as records flow into the pipe. ** Called once, before any sheets are actually being produced.
******************************************************************************/
void addRecords(List<QRecord> recordList) throws QReportingException;
/*******************************************************************************
** Called once, after all rows are available. Meant to write a footer, or close resources, for example.
*******************************************************************************/ *******************************************************************************/
void finish() throws QReportingException; default void preRun(ReportDestination reportDestination, List<QReportView> views) throws QReportingException
{
// noop in base class
}
/******************************************************************************* /*******************************************************************************
** **
@ -58,6 +54,20 @@ public interface ExportStreamerInterface
// noop in base class // noop in base class
} }
/*******************************************************************************
** Called once per sheet, before any rows are available. Meant to write a
** header, for example.
**
** If multiple sheets are being created, there is no separate end-sheet call.
** Rather, a new one will just get started...
*******************************************************************************/
void start(ExportInput exportInput, List<QFieldMetaData> fields, String label, QReportView view) throws QReportingException;
/*******************************************************************************
** Called as records flow into the pipe.
******************************************************************************/
void addRecords(List<QRecord> recordList) throws QReportingException;
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/
@ -65,4 +75,11 @@ public interface ExportStreamerInterface
{ {
addRecords(List.of(record)); addRecords(List.of(record));
} }
/*******************************************************************************
** Called after all sheets are complete. Meant to do a final write, or close
** resources, for example.
*******************************************************************************/
void finish() throws QReportingException;
} }

View File

@ -41,6 +41,7 @@ import com.kingsrook.qqq.backend.core.actions.reporting.customizers.DataSourceQu
import com.kingsrook.qqq.backend.core.actions.reporting.customizers.ReportViewCustomizer; import com.kingsrook.qqq.backend.core.actions.reporting.customizers.ReportViewCustomizer;
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction; import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter; import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
import com.kingsrook.qqq.backend.core.context.QContext;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.exceptions.QFormulaException; import com.kingsrook.qqq.backend.core.exceptions.QFormulaException;
import com.kingsrook.qqq.backend.core.exceptions.QReportingException; import com.kingsrook.qqq.backend.core.exceptions.QReportingException;
@ -108,9 +109,9 @@ public class GenerateReportAction
Map<String, AggregatesInterface<?>> totalAggregates = new HashMap<>(); Map<String, AggregatesInterface<?>> totalAggregates = new HashMap<>();
Map<String, AggregatesInterface<?>> varianceTotalAggregates = new HashMap<>(); Map<String, AggregatesInterface<?>> varianceTotalAggregates = new HashMap<>();
private QReportMetaData report;
private ReportFormat reportFormat;
private ExportStreamerInterface reportStreamer; private ExportStreamerInterface reportStreamer;
private List<QReportDataSource> dataSources;
private List<QReportView> views;
@ -119,33 +120,39 @@ public class GenerateReportAction
*******************************************************************************/ *******************************************************************************/
public void execute(ReportInput reportInput) throws QException public void execute(ReportInput reportInput) throws QException
{ {
report = reportInput.getInstance().getReport(reportInput.getReportName()); QReportMetaData report = getReportMetaData(reportInput);
reportFormat = reportInput.getReportFormat();
this.views = report.getViews();
this.dataSources = report.getDataSources();
ReportFormat reportFormat = reportInput.getReportDestination().getReportFormat();
if(reportFormat == null) if(reportFormat == null)
{ {
throw new QException("Report format was not specified."); throw new QException("Report format was not specified.");
} }
reportStreamer = reportFormat.newReportStreamer(); reportStreamer = reportFormat.newReportStreamer();
reportStreamer.preRun(reportInput.getReportDestination(), views);
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
// foreach data source, do a query (possibly more than 1, if it goes to multiple table views) // // foreach data source, do a query (possibly more than 1, if it goes to multiple table views) //
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
for(QReportDataSource dataSource : report.getDataSources()) for(QReportDataSource dataSource : dataSources)
{ {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// make a list of the views that use this data source for various purposes. // // make a list of the views that use this data source for various purposes. //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
List<QReportView> dataSourceTableViews = report.getViews().stream() List<QReportView> dataSourceTableViews = views.stream()
.filter(v -> v.getType().equals(ReportType.TABLE)) .filter(v -> v.getType().equals(ReportType.TABLE))
.filter(v -> v.getDataSourceName().equals(dataSource.getName())) .filter(v -> v.getDataSourceName().equals(dataSource.getName()))
.toList(); .toList();
List<QReportView> dataSourceSummaryViews = report.getViews().stream() List<QReportView> dataSourceSummaryViews = views.stream()
.filter(v -> v.getType().equals(ReportType.SUMMARY)) .filter(v -> v.getType().equals(ReportType.SUMMARY))
.filter(v -> v.getDataSourceName().equals(dataSource.getName())) .filter(v -> v.getDataSourceName().equals(dataSource.getName()))
.toList(); .toList();
List<QReportView> dataSourceVariantViews = report.getViews().stream() List<QReportView> dataSourceVariantViews = views.stream()
.filter(v -> v.getType().equals(ReportType.SUMMARY)) .filter(v -> v.getType().equals(ReportType.SUMMARY))
.filter(v -> v.getVarianceDataSourceName() != null && v.getVarianceDataSourceName().equals(dataSource.getName())) .filter(v -> v.getVarianceDataSourceName() != null && v.getVarianceDataSourceName().equals(dataSource.getName()))
.toList(); .toList();
@ -190,13 +197,29 @@ public class GenerateReportAction
} }
} }
////////////////////////////////////////
// add pivot sheets //
// todo - but, only for Excel, right? //
////////////////////////////////////////
for(QReportView view : views)
{
if(view.getType().equals(ReportType.PIVOT))
{
startTableView(reportInput, null, view);
//////////////////////////////////////////////////////////////////////////
// there's no data to add to a pivot table, so nothing else to do here. //
//////////////////////////////////////////////////////////////////////////
}
}
outputSummaries(reportInput); outputSummaries(reportInput);
reportStreamer.finish(); reportStreamer.finish();
try try
{ {
reportInput.getReportOutputStream().close(); reportInput.getReportDestination().getReportOutputStream().close();
} }
catch(Exception e) catch(Exception e)
{ {
@ -206,31 +229,50 @@ public class GenerateReportAction
/*******************************************************************************
**
*******************************************************************************/
private QReportMetaData getReportMetaData(ReportInput reportInput) throws QException
{
if(reportInput.getReportMetaData() != null)
{
return reportInput.getReportMetaData();
}
if(StringUtils.hasContent(reportInput.getReportName()))
{
return QContext.getQInstance().getReport(reportInput.getReportName());
}
throw (new QReportingException("ReportInput did not contain required parameters to identify the report being generated"));
}
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/
private void startTableView(ReportInput reportInput, QReportDataSource dataSource, QReportView reportView) throws QException private void startTableView(ReportInput reportInput, QReportDataSource dataSource, QReportView reportView) throws QException
{ {
QTableMetaData table = reportInput.getInstance().getTable(dataSource.getSourceTable());
QMetaDataVariableInterpreter variableInterpreter = new QMetaDataVariableInterpreter(); QMetaDataVariableInterpreter variableInterpreter = new QMetaDataVariableInterpreter();
variableInterpreter.addValueMap("input", reportInput.getInputValues()); variableInterpreter.addValueMap("input", reportInput.getInputValues());
ExportInput exportInput = new ExportInput(); ExportInput exportInput = new ExportInput();
exportInput.setReportFormat(reportFormat); exportInput.setReportDestination(reportInput.getReportDestination());
exportInput.setFilename(reportInput.getFilename());
exportInput.setTitleRow(getTitle(reportView, variableInterpreter)); exportInput.setTitleRow(getTitle(reportView, variableInterpreter));
exportInput.setIncludeHeaderRow(reportView.getIncludeHeaderRow()); exportInput.setIncludeHeaderRow(reportView.getIncludeHeaderRow());
exportInput.setReportOutputStream(reportInput.getReportOutputStream());
JoinsContext joinsContext = null; JoinsContext joinsContext = null;
if(dataSource != null)
{
if(StringUtils.hasContent(dataSource.getSourceTable())) if(StringUtils.hasContent(dataSource.getSourceTable()))
{ {
joinsContext = new JoinsContext(exportInput.getInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins(), dataSource.getQueryFilter()); joinsContext = new JoinsContext(exportInput.getInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins(), dataSource.getQueryFilter());
} }
}
List<QFieldMetaData> fields = new ArrayList<>(); List<QFieldMetaData> fields = new ArrayList<>();
for(QReportField column : reportView.getColumns()) for(QReportField column : CollectionUtils.nonNullList(reportView.getColumns()))
{ {
if(column.getIsVirtual()) if(column.getIsVirtual())
{ {
@ -256,7 +298,7 @@ public class GenerateReportAction
} }
reportStreamer.setDisplayFormats(getDisplayFormatMap(fields)); reportStreamer.setDisplayFormats(getDisplayFormatMap(fields));
reportStreamer.start(exportInput, fields, reportView.getLabel()); reportStreamer.start(exportInput, fields, reportView.getLabel(), reportView);
} }
@ -307,6 +349,7 @@ public class GenerateReportAction
queryInput.setTableName(dataSource.getSourceTable()); queryInput.setTableName(dataSource.getSourceTable());
queryInput.setFilter(queryFilter); queryInput.setFilter(queryFilter);
queryInput.setQueryJoins(dataSource.getQueryJoins()); queryInput.setQueryJoins(dataSource.getQueryJoins());
queryInput.withQueryHint(QueryInput.QueryHint.POTENTIALLY_LARGE_NUMBER_OF_RESULTS);
queryInput.setShouldTranslatePossibleValues(true); queryInput.setShouldTranslatePossibleValues(true);
queryInput.setFieldsToTranslatePossibleValues(setupFieldsToTranslatePossibleValues(reportInput, dataSource, new JoinsContext(reportInput.getInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins(), queryInput.getFilter()))); queryInput.setFieldsToTranslatePossibleValues(setupFieldsToTranslatePossibleValues(reportInput, dataSource, new JoinsContext(reportInput.getInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins(), queryInput.getFilter())));
@ -371,7 +414,7 @@ public class GenerateReportAction
{ {
Set<String> fieldsToTranslatePossibleValues = new HashSet<>(); Set<String> fieldsToTranslatePossibleValues = new HashSet<>();
for(QReportView view : report.getViews()) for(QReportView view : views)
{ {
for(QReportField column : CollectionUtils.nonNullList(view.getColumns())) for(QReportField column : CollectionUtils.nonNullList(view.getColumns()))
{ {
@ -577,22 +620,20 @@ public class GenerateReportAction
*******************************************************************************/ *******************************************************************************/
private void outputSummaries(ReportInput reportInput) throws QReportingException, QFormulaException private void outputSummaries(ReportInput reportInput) throws QReportingException, QFormulaException
{ {
List<QReportView> reportViews = report.getViews().stream().filter(v -> v.getType().equals(ReportType.SUMMARY)).toList(); List<QReportView> reportViews = views.stream().filter(v -> v.getType().equals(ReportType.SUMMARY)).toList();
for(QReportView view : reportViews) for(QReportView view : reportViews)
{ {
QReportDataSource dataSource = report.getDataSource(view.getDataSourceName()); QReportDataSource dataSource = getDataSource(view.getDataSourceName());
QTableMetaData table = reportInput.getInstance().getTable(dataSource.getSourceTable()); QTableMetaData table = reportInput.getInstance().getTable(dataSource.getSourceTable());
SummaryOutput summaryOutput = computeSummaryRowsForView(reportInput, view, table); SummaryOutput summaryOutput = computeSummaryRowsForView(reportInput, view, table);
ExportInput exportInput = new ExportInput(); ExportInput exportInput = new ExportInput();
exportInput.setReportFormat(reportFormat); exportInput.setReportDestination(reportInput.getReportDestination());
exportInput.setFilename(reportInput.getFilename());
exportInput.setTitleRow(summaryOutput.titleRow); exportInput.setTitleRow(summaryOutput.titleRow);
exportInput.setIncludeHeaderRow(view.getIncludeHeaderRow()); exportInput.setIncludeHeaderRow(view.getIncludeHeaderRow());
exportInput.setReportOutputStream(reportInput.getReportOutputStream());
reportStreamer.setDisplayFormats(getDisplayFormatMap(view)); reportStreamer.setDisplayFormats(getDisplayFormatMap(view));
reportStreamer.start(exportInput, getFields(table, view), view.getLabel()); reportStreamer.start(exportInput, getFields(table, view), view.getLabel(), view);
reportStreamer.addRecords(summaryOutput.summaryRows); // todo - what if this set is huge? reportStreamer.addRecords(summaryOutput.summaryRows); // todo - what if this set is huge?
@ -605,6 +646,24 @@ public class GenerateReportAction
/*******************************************************************************
**
*******************************************************************************/
private QReportDataSource getDataSource(String dataSourceName)
{
for(QReportDataSource dataSource : CollectionUtils.nonNullList(dataSources))
{
if(dataSource.getName().equals(dataSourceName))
{
return (dataSource);
}
}
return (null);
}
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/

View File

@ -34,6 +34,7 @@ import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
import com.kingsrook.qqq.backend.core.model.data.QRecord; 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.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.utils.JsonUtils; import com.kingsrook.qqq.backend.core.utils.JsonUtils;
import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils;
@ -69,12 +70,12 @@ public class JsonExportStreamer implements ExportStreamerInterface
** **
*******************************************************************************/ *******************************************************************************/
@Override @Override
public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label) throws QReportingException public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label, QReportView view) throws QReportingException
{ {
this.exportInput = exportInput; this.exportInput = exportInput;
this.fields = fields; this.fields = fields;
table = exportInput.getTable(); table = exportInput.getTable();
outputStream = this.exportInput.getReportOutputStream(); outputStream = this.exportInput.getReportDestination().getReportOutputStream();
try try
{ {

View File

@ -31,6 +31,7 @@ import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
import com.kingsrook.qqq.backend.core.model.data.QRecord; 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.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
/******************************************************************************* /*******************************************************************************
@ -87,7 +88,7 @@ public class ListOfMapsExportStreamer implements ExportStreamerInterface
** **
*******************************************************************************/ *******************************************************************************/
@Override @Override
public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label) throws QReportingException public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label, QReportView view) throws QReportingException
{ {
this.exportInput = exportInput; this.exportInput = exportInput;
this.fields = fields; this.fields = fields;

View File

@ -0,0 +1,51 @@
/*
* 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.core.actions.reporting;
import java.util.List;
import java.util.Optional;
import com.kingsrook.qqq.backend.core.exceptions.QReportingException;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
/*******************************************************************************
**
*******************************************************************************/
public class ReportUtils
{
/*******************************************************************************
**
*******************************************************************************/
public static QReportView getSourceViewForPivotTableView(List<QReportView> views, QReportView pivotTableView) throws QReportingException
{
Optional<QReportView> sourceView = views.stream().filter(v -> v.getName().equals(pivotTableView.getPivotTableSourceViewName())).findFirst();
if(sourceView.isEmpty())
{
throw (new QReportingException("Could not find data view [" + pivotTableView.getPivotTableSourceViewName() + "] for pivot table view [" + pivotTableView.getName() + "]"));
}
return sourceView.get();
}
}

View File

@ -22,7 +22,6 @@
package com.kingsrook.qqq.backend.core.model.actions.reporting; package com.kingsrook.qqq.backend.core.model.actions.reporting;
import java.io.OutputStream;
import java.util.List; import java.util.List;
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput; import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
@ -37,9 +36,8 @@ public class ExportInput extends AbstractTableActionInput
private Integer limit; private Integer limit;
private List<String> fieldNames; private List<String> fieldNames;
private String filename; private ReportDestination reportDestination;
private ReportFormat reportFormat;
private OutputStream reportOutputStream;
private String titleRow; private String titleRow;
private boolean includeHeaderRow = true; private boolean includeHeaderRow = true;
@ -120,71 +118,6 @@ public class ExportInput extends AbstractTableActionInput
/*******************************************************************************
** Getter for filename
**
*******************************************************************************/
public String getFilename()
{
return filename;
}
/*******************************************************************************
** Setter for filename
**
*******************************************************************************/
public void setFilename(String filename)
{
this.filename = filename;
}
/*******************************************************************************
** Getter for reportFormat
**
*******************************************************************************/
public ReportFormat getReportFormat()
{
return reportFormat;
}
/*******************************************************************************
** Setter for reportFormat
**
*******************************************************************************/
public void setReportFormat(ReportFormat reportFormat)
{
this.reportFormat = reportFormat;
}
/*******************************************************************************
** Getter for reportOutputStream
**
*******************************************************************************/
public OutputStream getReportOutputStream()
{
return reportOutputStream;
}
/*******************************************************************************
** Setter for reportOutputStream
**
*******************************************************************************/
public void setReportOutputStream(OutputStream reportOutputStream)
{
this.reportOutputStream = reportOutputStream;
}
/******************************************************************************* /*******************************************************************************
** **
@ -226,4 +159,36 @@ public class ExportInput extends AbstractTableActionInput
this.includeHeaderRow = includeHeaderRow; this.includeHeaderRow = includeHeaderRow;
} }
/*******************************************************************************
** Getter for reportDestination
*******************************************************************************/
public ReportDestination getReportDestination()
{
return (this.reportDestination);
}
/*******************************************************************************
** Setter for reportDestination
*******************************************************************************/
public void setReportDestination(ReportDestination reportDestination)
{
this.reportDestination = reportDestination;
}
/*******************************************************************************
** Fluent setter for reportDestination
*******************************************************************************/
public ExportInput withReportDestination(ReportDestination reportDestination)
{
this.reportDestination = reportDestination;
return (this);
}
} }

View File

@ -0,0 +1,130 @@
/*
* 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.core.model.actions.reporting;
import java.io.OutputStream;
/*******************************************************************************
**
*******************************************************************************/
public class ReportDestination
{
private String filename;
private ReportFormat reportFormat;
private OutputStream reportOutputStream;
/*******************************************************************************
** Getter for filename
*******************************************************************************/
public String getFilename()
{
return (this.filename);
}
/*******************************************************************************
** Setter for filename
*******************************************************************************/
public void setFilename(String filename)
{
this.filename = filename;
}
/*******************************************************************************
** Fluent setter for filename
*******************************************************************************/
public ReportDestination withFilename(String filename)
{
this.filename = filename;
return (this);
}
/*******************************************************************************
** Getter for reportFormat
*******************************************************************************/
public ReportFormat getReportFormat()
{
return (this.reportFormat);
}
/*******************************************************************************
** Setter for reportFormat
*******************************************************************************/
public void setReportFormat(ReportFormat reportFormat)
{
this.reportFormat = reportFormat;
}
/*******************************************************************************
** Fluent setter for reportFormat
*******************************************************************************/
public ReportDestination withReportFormat(ReportFormat reportFormat)
{
this.reportFormat = reportFormat;
return (this);
}
/*******************************************************************************
** Getter for reportOutputStream
*******************************************************************************/
public OutputStream getReportOutputStream()
{
return (this.reportOutputStream);
}
/*******************************************************************************
** Setter for reportOutputStream
*******************************************************************************/
public void setReportOutputStream(OutputStream reportOutputStream)
{
this.reportOutputStream = reportOutputStream;
}
/*******************************************************************************
** Fluent setter for reportOutputStream
*******************************************************************************/
public ReportDestination withReportOutputStream(OutputStream reportOutputStream)
{
this.reportOutputStream = reportOutputStream;
return (this);
}
}

View File

@ -25,10 +25,10 @@ package com.kingsrook.qqq.backend.core.model.actions.reporting;
import java.util.Locale; import java.util.Locale;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.kingsrook.qqq.backend.core.actions.reporting.CsvExportStreamer; import com.kingsrook.qqq.backend.core.actions.reporting.CsvExportStreamer;
import com.kingsrook.qqq.backend.core.actions.reporting.ExcelExportStreamer;
import com.kingsrook.qqq.backend.core.actions.reporting.ExportStreamerInterface; import com.kingsrook.qqq.backend.core.actions.reporting.ExportStreamerInterface;
import com.kingsrook.qqq.backend.core.actions.reporting.JsonExportStreamer; import com.kingsrook.qqq.backend.core.actions.reporting.JsonExportStreamer;
import com.kingsrook.qqq.backend.core.actions.reporting.ListOfMapsExportStreamer; import com.kingsrook.qqq.backend.core.actions.reporting.ListOfMapsExportStreamer;
import com.kingsrook.qqq.backend.core.actions.reporting.excel.poi.ExcelPoiBasedStreamingExportStreamer;
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException; import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils;
import org.dhatim.fastexcel.Worksheet; import org.dhatim.fastexcel.Worksheet;
@ -39,7 +39,13 @@ import org.dhatim.fastexcel.Worksheet;
*******************************************************************************/ *******************************************************************************/
public enum ReportFormat public enum ReportFormat
{ {
XLSX(Worksheet.MAX_ROWS, Worksheet.MAX_COLS, ExcelExportStreamer::new, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"), XLSX(Worksheet.MAX_ROWS, Worksheet.MAX_COLS, ExcelPoiBasedStreamingExportStreamer::new, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
/////////////////////////////////////////////////////////////////////////
// if we need to fall back to Fastexcel, this was its version of this. //
/////////////////////////////////////////////////////////////////////////
// XLSX(Worksheet.MAX_ROWS, Worksheet.MAX_COLS, ExcelFastexcelExportStreamer::new, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
JSON(null, null, JsonExportStreamer::new, "application/json"), JSON(null, null, JsonExportStreamer::new, "application/json"),
CSV(null, null, CsvExportStreamer::new, "text/csv"), CSV(null, null, CsvExportStreamer::new, "text/csv"),
LIST_OF_MAPS(null, null, ListOfMapsExportStreamer::new, null); LIST_OF_MAPS(null, null, ListOfMapsExportStreamer::new, null);

View File

@ -22,11 +22,11 @@
package com.kingsrook.qqq.backend.core.model.actions.reporting; package com.kingsrook.qqq.backend.core.model.actions.reporting;
import java.io.OutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput; import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
/******************************************************************************* /*******************************************************************************
@ -35,11 +35,11 @@ import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
public class ReportInput extends AbstractTableActionInput public class ReportInput extends AbstractTableActionInput
{ {
private String reportName; private String reportName;
private QReportMetaData reportMetaData;
private Map<String, Serializable> inputValues; private Map<String, Serializable> inputValues;
private String filename; private ReportDestination reportDestination;
private ReportFormat reportFormat;
private OutputStream reportOutputStream;
@ -111,66 +111,63 @@ public class ReportInput extends AbstractTableActionInput
/******************************************************************************* /*******************************************************************************
** Getter for filename ** Getter for reportDestination
**
*******************************************************************************/ *******************************************************************************/
public String getFilename() public ReportDestination getReportDestination()
{ {
return filename; return (this.reportDestination);
} }
/******************************************************************************* /*******************************************************************************
** Setter for filename ** Setter for reportDestination
**
*******************************************************************************/ *******************************************************************************/
public void setFilename(String filename) public void setReportDestination(ReportDestination reportDestination)
{ {
this.filename = filename; this.reportDestination = reportDestination;
} }
/******************************************************************************* /*******************************************************************************
** Getter for reportFormat ** Fluent setter for reportDestination
**
*******************************************************************************/ *******************************************************************************/
public ReportFormat getReportFormat() public ReportInput withReportDestination(ReportDestination reportDestination)
{ {
return reportFormat; this.reportDestination = reportDestination;
return (this);
}
/*******************************************************************************
** Getter for reportMetaData
*******************************************************************************/
public QReportMetaData getReportMetaData()
{
return (this.reportMetaData);
} }
/******************************************************************************* /*******************************************************************************
** Setter for reportFormat ** Setter for reportMetaData
**
*******************************************************************************/ *******************************************************************************/
public void setReportFormat(ReportFormat reportFormat) public void setReportMetaData(QReportMetaData reportMetaData)
{ {
this.reportFormat = reportFormat; this.reportMetaData = reportMetaData;
} }
/******************************************************************************* /*******************************************************************************
** Getter for reportOutputStream ** Fluent setter for reportMetaData
**
*******************************************************************************/ *******************************************************************************/
public OutputStream getReportOutputStream() public ReportInput withReportMetaData(QReportMetaData reportMetaData)
{ {
return reportOutputStream; this.reportMetaData = reportMetaData;
return (this);
} }
/*******************************************************************************
** Setter for reportOutputStream
**
*******************************************************************************/
public void setReportOutputStream(OutputStream reportOutputStream)
{
this.reportOutputStream = reportOutputStream;
}
} }

View File

@ -34,6 +34,7 @@ import com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportAction;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput; import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput; import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat; import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData; import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
@ -66,8 +67,9 @@ public class ExecuteReportStep implements BackendStep
{ {
ReportInput reportInput = new ReportInput(); ReportInput reportInput = new ReportInput();
reportInput.setReportName(reportName); reportInput.setReportName(reportName);
reportInput.setReportFormat(ReportFormat.XLSX); // todo - variable reportInput.setReportDestination(new ReportDestination()
reportInput.setReportOutputStream(reportOutputStream); .withReportFormat(ReportFormat.XLSX) // todo - variable
.withReportOutputStream(reportOutputStream));
Map<String, Serializable> values = runBackendStepInput.getValues(); Map<String, Serializable> values = runBackendStepInput.getValues();
reportInput.setInputValues(values); reportInput.setInputValues(values);

View File

@ -26,6 +26,7 @@ import java.io.ByteArrayOutputStream;
import com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportAction; import com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportAction;
import com.kingsrook.qqq.backend.core.context.QContext; import com.kingsrook.qqq.backend.core.context.QContext;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat; import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
@ -204,9 +205,12 @@ public class GenerateReportActionRDBMSTest extends RDBMSActionTest
ReportInput reportInput = new ReportInput(); ReportInput reportInput = new ReportInput();
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_STORE_ALL_ACCESS, true)); QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_STORE_ALL_ACCESS, true));
reportInput.setReportName(TEST_REPORT); reportInput.setReportName(TEST_REPORT);
reportInput.setReportFormat(ReportFormat.CSV);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
reportInput.setReportOutputStream(outputStream);
reportInput.setReportDestination(new ReportDestination()
.withReportFormat(ReportFormat.CSV)
.withReportOutputStream(outputStream));
new GenerateReportAction().execute(reportInput); new GenerateReportAction().execute(reportInput);
return (outputStream.toString()); return (outputStream.toString());
} }

View File

@ -77,6 +77,7 @@ import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataInput;
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataOutput; import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataOutput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportOutput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportOutput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat; import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
import com.kingsrook.qqq.backend.core.model.actions.tables.QInputSource; import com.kingsrook.qqq.backend.core.model.actions.tables.QInputSource;
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput; import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
@ -1492,10 +1493,11 @@ public class QJavalinImplementation
setupSession(context, exportInput); setupSession(context, exportInput);
exportInput.setTableName(tableName); exportInput.setTableName(tableName);
exportInput.setReportFormat(reportFormat);
String filename = optionalFilename.orElse(tableName + "." + reportFormat.toString().toLowerCase(Locale.ROOT)); String filename = optionalFilename.orElse(tableName + "." + reportFormat.toString().toLowerCase(Locale.ROOT));
exportInput.setFilename(filename); exportInput.withReportDestination(new ReportDestination()
.withReportFormat(reportFormat)
.withFilename(filename));
Integer limit = QJavalinUtils.integerQueryParam(context, "limit"); Integer limit = QJavalinUtils.integerQueryParam(context, "limit");
exportInput.setLimit(limit); exportInput.setLimit(limit);
@ -1526,7 +1528,7 @@ public class QJavalinImplementation
UnsafeFunction<PipedOutputStream, ExportAction, Exception> preAction = (PipedOutputStream pos) -> UnsafeFunction<PipedOutputStream, ExportAction, Exception> preAction = (PipedOutputStream pos) ->
{ {
exportInput.setReportOutputStream(pos); exportInput.getReportDestination().setReportOutputStream(pos);
ExportAction exportAction = new ExportAction(); ExportAction exportAction = new ExportAction();
exportAction.preExecute(exportInput); exportAction.preExecute(exportInput);

View File

@ -60,6 +60,7 @@ import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessState;
import com.kingsrook.qqq.backend.core.model.actions.processes.QUploadedFile; import com.kingsrook.qqq.backend.core.model.actions.processes.QUploadedFile;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput; import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput; import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat; import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput; import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
@ -203,10 +204,12 @@ public class QJavalinProcessHandler
QJavalinImplementation.setupSession(context, reportInput); QJavalinImplementation.setupSession(context, reportInput);
PermissionsHelper.checkReportPermissionThrowing(reportInput, reportName); PermissionsHelper.checkReportPermissionThrowing(reportInput, reportName);
reportInput.setReportFormat(reportFormat);
reportInput.setReportName(reportName); reportInput.setReportName(reportName);
reportInput.setInputValues(null); // todo! reportInput.setInputValues(null); // todo!
reportInput.setFilename(filename);
reportInput.setReportDestination(new ReportDestination()
.withReportFormat(reportFormat)
.withFilename(filename));
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
// process the report's input fields, from the query string // // process the report's input fields, from the query string //
@ -239,7 +242,7 @@ public class QJavalinProcessHandler
UnsafeFunction<PipedOutputStream, GenerateReportAction, Exception> preAction = (PipedOutputStream pos) -> UnsafeFunction<PipedOutputStream, GenerateReportAction, Exception> preAction = (PipedOutputStream pos) ->
{ {
reportInput.setReportOutputStream(pos); reportInput.getReportDestination().setReportOutputStream(pos);
GenerateReportAction reportAction = new GenerateReportAction(); GenerateReportAction reportAction = new GenerateReportAction();
// any pre-action?? export uses this for "too many rows" checks... // any pre-action?? export uses this for "too many rows" checks...

View File

@ -60,6 +60,7 @@ import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput; import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportOutput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportOutput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat; import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.AbstractQFieldMapping; import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.AbstractQFieldMapping;
import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.QKeyBasedFieldMapping; import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.QKeyBasedFieldMapping;
@ -618,9 +619,10 @@ public class QPicoCliImplementation
///////////////////////////////////////////// /////////////////////////////////////////////
ExportInput exportInput = new ExportInput(); ExportInput exportInput = new ExportInput();
exportInput.setTableName(tableName); exportInput.setTableName(tableName);
exportInput.setReportFormat(reportFormat); exportInput.setReportDestination(new ReportDestination()
exportInput.setFilename(filename); .withReportFormat(reportFormat)
exportInput.setReportOutputStream(outputStream); .withFilename(filename)
.withReportOutputStream(outputStream));
exportInput.setLimit(subParseResult.matchedOptionValue("limit", null)); exportInput.setLimit(subParseResult.matchedOptionValue("limit", null));
exportInput.setQueryFilter(generateQueryFilter(subParseResult)); exportInput.setQueryFilter(generateQueryFilter(subParseResult));

View File

@ -49,6 +49,7 @@ import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput; import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportOutput; import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportOutput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat; import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput; import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput; import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
@ -429,8 +430,11 @@ public class QSlackImplementation
ExportInput exportInput = new ExportInput(); ExportInput exportInput = new ExportInput();
exportInput.setLimit(1000); exportInput.setLimit(1000);
exportInput.setTableName(tableName); exportInput.setTableName(tableName);
exportInput.setReportFormat(ReportFormat.valueOf(format));
exportInput.setReportOutputStream(baos); exportInput.setReportDestination(new ReportDestination()
.withReportFormat(ReportFormat.valueOf(format))
.withReportOutputStream(baos));
setupSession(context, exportInput); setupSession(context, exportInput);
ExportOutput output = new ExportAction().execute(exportInput); ExportOutput output = new ExportAction().execute(exportInput);