mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-21 14:38:43 +00:00
Compare commits
16 Commits
snapshot-f
...
snapshot-f
Author | SHA1 | Date | |
---|---|---|---|
daad8a720a | |||
0ef01efcaa | |||
efe89c7043 | |||
bbf4c2c2ff | |||
ff1e022798 | |||
f09735c811 | |||
7ab9171998 | |||
b979f413c8 | |||
766881dee0 | |||
f65b16df60 | |||
e0597827ef | |||
10014f16ae | |||
526ba6ca30 | |||
b955a20e18 | |||
eb8781db77 | |||
febda51233 |
@ -40,9 +40,9 @@ import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
|
|||||||
** - alertType - name of entry in AlertType enum (ERROR, WARNING, SUCCESS)
|
** - alertType - name of entry in AlertType enum (ERROR, WARNING, SUCCESS)
|
||||||
** - alertHtml - html to display inside the alert (other than its icon)
|
** - alertHtml - html to display inside the alert (other than its icon)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class ProcessAlertWidget extends AbstractWidgetRenderer implements MetaDataProducerInterface<QWidgetMetaData>
|
public class AlertWidgetRenderer extends AbstractWidgetRenderer implements MetaDataProducerInterface<QWidgetMetaData>
|
||||||
{
|
{
|
||||||
public static final String NAME = "ProcessAlertWidget";
|
public static final String NAME = "AlertWidgetRenderer";
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -301,6 +301,9 @@ public class ChildRecordListRenderer extends AbstractWidgetRenderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
widgetData.setAllowRecordEdit(BooleanUtils.isTrue(ValueUtils.getValueAsBoolean(input.getQueryParams().get("allowRecordEdit"))));
|
||||||
|
widgetData.setAllowRecordDelete(BooleanUtils.isTrue(ValueUtils.getValueAsBoolean(input.getQueryParams().get("allowRecordDelete"))));
|
||||||
|
|
||||||
return (new RenderWidgetOutput(widgetData));
|
return (new RenderWidgetOutput(widgetData));
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
|
@ -54,6 +54,7 @@ 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.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.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
@ -266,6 +267,22 @@ public class QueryAction
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** shorthand way to call for the most common use-case, when you just want the
|
||||||
|
** entities to be returned, and you just want to pass in a table name and filter.
|
||||||
|
*******************************************************************************/
|
||||||
|
public static <T extends QRecordEntity> List<T> execute(String tableName, Class<T> entityClass, QQueryFilter filter) throws QException
|
||||||
|
{
|
||||||
|
QueryAction queryAction = new QueryAction();
|
||||||
|
QueryInput queryInput = new QueryInput();
|
||||||
|
queryInput.setTableName(tableName);
|
||||||
|
queryInput.setFilter(filter);
|
||||||
|
QueryOutput queryOutput = queryAction.execute(queryInput);
|
||||||
|
return (queryOutput.getRecordEntities(entityClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** shorthand way to call for the most common use-case, when you just want the
|
** shorthand way to call for the most common use-case, when you just want the
|
||||||
** records to be returned, and you just want to pass in a table name and filter.
|
** records to be returned, and you just want to pass in a table name and filter.
|
||||||
|
@ -404,6 +404,12 @@ public class JoinsContext
|
|||||||
chainIsInner = false;
|
chainIsInner = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(hasAllAccessKey(recordSecurityLock))
|
||||||
|
{
|
||||||
|
queryJoin.withType(QueryJoin.Type.LEFT);
|
||||||
|
chainIsInner = false;
|
||||||
|
}
|
||||||
|
|
||||||
addQueryJoin(queryJoin, "forRecordSecurityLock (non-flipped)", "- ");
|
addQueryJoin(queryJoin, "forRecordSecurityLock (non-flipped)", "- ");
|
||||||
addedQueryJoins.add(queryJoin);
|
addedQueryJoins.add(queryJoin);
|
||||||
tmpTable = instance.getTable(join.getRightTable());
|
tmpTable = instance.getTable(join.getRightTable());
|
||||||
@ -423,6 +429,12 @@ public class JoinsContext
|
|||||||
chainIsInner = false;
|
chainIsInner = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(hasAllAccessKey(recordSecurityLock))
|
||||||
|
{
|
||||||
|
queryJoin.withType(QueryJoin.Type.LEFT);
|
||||||
|
chainIsInner = false;
|
||||||
|
}
|
||||||
|
|
||||||
addQueryJoin(queryJoin, "forRecordSecurityLock (flipped)", "- ");
|
addQueryJoin(queryJoin, "forRecordSecurityLock (flipped)", "- ");
|
||||||
addedQueryJoins.add(queryJoin);
|
addedQueryJoins.add(queryJoin);
|
||||||
tmpTable = instance.getTable(join.getLeftTable());
|
tmpTable = instance.getTable(join.getLeftTable());
|
||||||
@ -456,27 +468,37 @@ public class JoinsContext
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
private boolean hasAllAccessKey(RecordSecurityLock recordSecurityLock)
|
||||||
|
{
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// check if the key type has an all-access key, and if so, if it's set to true for the current user/session //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
QSecurityKeyType securityKeyType = instance.getSecurityKeyType(recordSecurityLock.getSecurityKeyType());
|
||||||
|
if(StringUtils.hasContent(securityKeyType.getAllAccessKeyName()))
|
||||||
|
{
|
||||||
|
QSession session = QContext.getQSession();
|
||||||
|
if(session.hasSecurityKeyValue(securityKeyType.getAllAccessKeyName(), true, QFieldType.BOOLEAN))
|
||||||
|
{
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private void addSubFilterForRecordSecurityLock(RecordSecurityLock recordSecurityLock, QTableMetaData table, String tableNameOrAlias, boolean isOuter, QueryJoin sourceQueryJoin)
|
private void addSubFilterForRecordSecurityLock(RecordSecurityLock recordSecurityLock, QTableMetaData table, String tableNameOrAlias, boolean isOuter, QueryJoin sourceQueryJoin)
|
||||||
{
|
{
|
||||||
QSession session = QContext.getQSession();
|
boolean haveAllAccessKey = hasAllAccessKey(recordSecurityLock);
|
||||||
|
if(haveAllAccessKey)
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// check if the key type has an all-access key, and if so, if it's set to true for the current user/session //
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
QSecurityKeyType securityKeyType = instance.getSecurityKeyType(recordSecurityLock.getSecurityKeyType());
|
|
||||||
boolean haveAllAccessKey = false;
|
|
||||||
if(StringUtils.hasContent(securityKeyType.getAllAccessKeyName()))
|
|
||||||
{
|
{
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// if we have all-access on this key, then we don't need a criterion for it (as long as we're in an AND filter) //
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
if(session.hasSecurityKeyValue(securityKeyType.getAllAccessKeyName(), true, QFieldType.BOOLEAN))
|
|
||||||
{
|
|
||||||
haveAllAccessKey = true;
|
|
||||||
|
|
||||||
if(sourceQueryJoin != null)
|
if(sourceQueryJoin != null)
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -495,7 +517,6 @@ public class JoinsContext
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// for locks w/o a join chain, the lock fieldName will simply be a field on the table. //
|
// for locks w/o a join chain, the lock fieldName will simply be a field on the table. //
|
||||||
@ -545,7 +566,7 @@ public class JoinsContext
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List<Serializable> securityKeyValues = session.getSecurityKeyValues(recordSecurityLock.getSecurityKeyType(), type);
|
List<Serializable> securityKeyValues = QContext.getQSession().getSecurityKeyValues(recordSecurityLock.getSecurityKeyType(), type);
|
||||||
if(CollectionUtils.nullSafeIsEmpty(securityKeyValues))
|
if(CollectionUtils.nullSafeIsEmpty(securityKeyValues))
|
||||||
{
|
{
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
|
package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Model containing datastructure expected by frontend alert widget
|
** Model containing datastructure expected by frontend alert widget
|
||||||
**
|
**
|
||||||
@ -42,6 +45,8 @@ public class AlertData extends QWidgetData
|
|||||||
|
|
||||||
private String html;
|
private String html;
|
||||||
private AlertType alertType;
|
private AlertType alertType;
|
||||||
|
private Boolean hideWidget = false;
|
||||||
|
private List<String> bulletList;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -139,4 +144,66 @@ public class AlertData extends QWidgetData
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for hideWidget
|
||||||
|
*******************************************************************************/
|
||||||
|
public boolean getHideWidget()
|
||||||
|
{
|
||||||
|
return (this.hideWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for hideWidget
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setHideWidget(boolean hideWidget)
|
||||||
|
{
|
||||||
|
this.hideWidget = hideWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for hideWidget
|
||||||
|
*******************************************************************************/
|
||||||
|
public AlertData withHideWidget(boolean hideWidget)
|
||||||
|
{
|
||||||
|
this.hideWidget = hideWidget;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for bulletList
|
||||||
|
*******************************************************************************/
|
||||||
|
public List<String> getBulletList()
|
||||||
|
{
|
||||||
|
return (this.bulletList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for bulletList
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setBulletList(List<String> bulletList)
|
||||||
|
{
|
||||||
|
this.bulletList = bulletList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for bulletList
|
||||||
|
*******************************************************************************/
|
||||||
|
public AlertData withBulletList(List<String> bulletList)
|
||||||
|
{
|
||||||
|
this.bulletList = bulletList;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,9 +39,13 @@ public class ChildRecordListData extends QWidgetData
|
|||||||
private QueryOutput queryOutput;
|
private QueryOutput queryOutput;
|
||||||
private QTableMetaData childTableMetaData;
|
private QTableMetaData childTableMetaData;
|
||||||
|
|
||||||
|
private String tableName;
|
||||||
private String tablePath;
|
private String tablePath;
|
||||||
private String viewAllLink;
|
private String viewAllLink;
|
||||||
private Integer totalRows;
|
private Integer totalRows;
|
||||||
|
private Boolean disableRowClick = false;
|
||||||
|
private Boolean allowRecordEdit = false;
|
||||||
|
private Boolean allowRecordDelete = false;
|
||||||
|
|
||||||
private boolean canAddChildRecord = false;
|
private boolean canAddChildRecord = false;
|
||||||
private Map<String, Serializable> defaultValuesForNewChildRecords;
|
private Map<String, Serializable> defaultValuesForNewChildRecords;
|
||||||
@ -352,4 +356,141 @@ public class ChildRecordListData extends QWidgetData
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for tableName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getTableName()
|
||||||
|
{
|
||||||
|
return (this.tableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for tableName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setTableName(String tableName)
|
||||||
|
{
|
||||||
|
this.tableName = tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for tableName
|
||||||
|
*******************************************************************************/
|
||||||
|
public ChildRecordListData withTableName(String tableName)
|
||||||
|
{
|
||||||
|
this.tableName = tableName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for tablePath
|
||||||
|
*******************************************************************************/
|
||||||
|
public ChildRecordListData withTablePath(String tablePath)
|
||||||
|
{
|
||||||
|
this.tablePath = tablePath;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for disableRowClick
|
||||||
|
*******************************************************************************/
|
||||||
|
public Boolean getDisableRowClick()
|
||||||
|
{
|
||||||
|
return (this.disableRowClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for disableRowClick
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setDisableRowClick(Boolean disableRowClick)
|
||||||
|
{
|
||||||
|
this.disableRowClick = disableRowClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for disableRowClick
|
||||||
|
*******************************************************************************/
|
||||||
|
public ChildRecordListData withDisableRowClick(Boolean disableRowClick)
|
||||||
|
{
|
||||||
|
this.disableRowClick = disableRowClick;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for allowRecordEdit
|
||||||
|
*******************************************************************************/
|
||||||
|
public Boolean getAllowRecordEdit()
|
||||||
|
{
|
||||||
|
return (this.allowRecordEdit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for allowRecordEdit
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setAllowRecordEdit(Boolean allowRecordEdit)
|
||||||
|
{
|
||||||
|
this.allowRecordEdit = allowRecordEdit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for allowRecordEdit
|
||||||
|
*******************************************************************************/
|
||||||
|
public ChildRecordListData withAllowRecordEdit(Boolean allowRecordEdit)
|
||||||
|
{
|
||||||
|
this.allowRecordEdit = allowRecordEdit;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for allowRecordDelete
|
||||||
|
*******************************************************************************/
|
||||||
|
public Boolean getAllowRecordDelete()
|
||||||
|
{
|
||||||
|
return (this.allowRecordDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for allowRecordDelete
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setAllowRecordDelete(Boolean allowRecordDelete)
|
||||||
|
{
|
||||||
|
this.allowRecordDelete = allowRecordDelete;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for allowRecordDelete
|
||||||
|
*******************************************************************************/
|
||||||
|
public ChildRecordListData withAllowRecordDelete(Boolean allowRecordDelete)
|
||||||
|
{
|
||||||
|
this.allowRecordDelete = allowRecordDelete;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ import java.util.Map;
|
|||||||
** Base class for the data returned by rendering a Widget.
|
** Base class for the data returned by rendering a Widget.
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public abstract class QWidgetData
|
public abstract class QWidgetData implements Serializable
|
||||||
{
|
{
|
||||||
private String label;
|
private String label;
|
||||||
private String sublabel;
|
private String sublabel;
|
||||||
|
@ -40,6 +40,10 @@ import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwith
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class ExtractViaBasepullQueryStep extends ExtractViaQueryStep implements BasepullExtractStepInterface
|
public class ExtractViaBasepullQueryStep extends ExtractViaQueryStep implements BasepullExtractStepInterface
|
||||||
{
|
{
|
||||||
|
protected static final String SECONDS_TO_SUBTRACT_FROM_THIS_RUN_TIME_KEY = "secondsToSubtractFromThisRunTimeForTimestampQuery";
|
||||||
|
protected static final String SECONDS_TO_SUBTRACT_FROM_LAST_RUN_TIME_KEY = "secondsToSubtractFromLastRunTimeForTimestampQuery";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
@ -125,6 +129,7 @@ public class ExtractViaBasepullQueryStep extends ExtractViaQueryStep implements
|
|||||||
protected String getLastRunTimeString(RunBackendStepInput runBackendStepInput) throws QException
|
protected String getLastRunTimeString(RunBackendStepInput runBackendStepInput) throws QException
|
||||||
{
|
{
|
||||||
Instant lastRunTime = runBackendStepInput.getBasepullLastRunTime();
|
Instant lastRunTime = runBackendStepInput.getBasepullLastRunTime();
|
||||||
|
Instant updatedRunTime = lastRunTime;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// allow the timestamps to be adjusted by the specified number of seconds. //
|
// allow the timestamps to be adjusted by the specified number of seconds. //
|
||||||
@ -135,10 +140,19 @@ public class ExtractViaBasepullQueryStep extends ExtractViaQueryStep implements
|
|||||||
Serializable basepullConfigurationValue = runBackendStepInput.getValue(RunProcessAction.BASEPULL_CONFIGURATION);
|
Serializable basepullConfigurationValue = runBackendStepInput.getValue(RunProcessAction.BASEPULL_CONFIGURATION);
|
||||||
if(basepullConfigurationValue instanceof BasepullConfiguration basepullConfiguration && basepullConfiguration.getSecondsToSubtractFromLastRunTimeForTimestampQuery() != null)
|
if(basepullConfigurationValue instanceof BasepullConfiguration basepullConfiguration && basepullConfiguration.getSecondsToSubtractFromLastRunTimeForTimestampQuery() != null)
|
||||||
{
|
{
|
||||||
lastRunTime = lastRunTime.minusSeconds(basepullConfiguration.getSecondsToSubtractFromLastRunTimeForTimestampQuery());
|
updatedRunTime = lastRunTime.minusSeconds(basepullConfiguration.getSecondsToSubtractFromLastRunTimeForTimestampQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
return (lastRunTime.toString());
|
//////////////////////////////////////////////////////////////
|
||||||
|
// if an override was found in the params, use that instead //
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
if(runBackendStepInput.getValueString(SECONDS_TO_SUBTRACT_FROM_LAST_RUN_TIME_KEY) != null)
|
||||||
|
{
|
||||||
|
int secondsBack = Integer.parseInt(runBackendStepInput.getValueString(SECONDS_TO_SUBTRACT_FROM_LAST_RUN_TIME_KEY));
|
||||||
|
updatedRunTime = lastRunTime.minusSeconds(secondsBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (updatedRunTime.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -149,13 +163,23 @@ public class ExtractViaBasepullQueryStep extends ExtractViaQueryStep implements
|
|||||||
protected String getThisRunTimeString(RunBackendStepInput runBackendStepInput) throws QException
|
protected String getThisRunTimeString(RunBackendStepInput runBackendStepInput) throws QException
|
||||||
{
|
{
|
||||||
Instant thisRunTime = runBackendStepInput.getValueInstant(RunProcessAction.BASEPULL_THIS_RUNTIME_KEY);
|
Instant thisRunTime = runBackendStepInput.getValueInstant(RunProcessAction.BASEPULL_THIS_RUNTIME_KEY);
|
||||||
|
Instant updatedRunTime = thisRunTime;
|
||||||
|
|
||||||
Serializable basepullConfigurationValue = runBackendStepInput.getValue(RunProcessAction.BASEPULL_CONFIGURATION);
|
Serializable basepullConfigurationValue = runBackendStepInput.getValue(RunProcessAction.BASEPULL_CONFIGURATION);
|
||||||
if(basepullConfigurationValue instanceof BasepullConfiguration basepullConfiguration && basepullConfiguration.getSecondsToSubtractFromThisRunTimeForTimestampQuery() != null)
|
if(basepullConfigurationValue instanceof BasepullConfiguration basepullConfiguration && basepullConfiguration.getSecondsToSubtractFromThisRunTimeForTimestampQuery() != null)
|
||||||
{
|
{
|
||||||
thisRunTime = thisRunTime.minusSeconds(basepullConfiguration.getSecondsToSubtractFromThisRunTimeForTimestampQuery());
|
updatedRunTime = thisRunTime.minusSeconds(basepullConfiguration.getSecondsToSubtractFromThisRunTimeForTimestampQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
return (thisRunTime.toString());
|
//////////////////////////////////////////////////////////////
|
||||||
|
// if an override was found in the params, use that instead //
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
if(runBackendStepInput.getValueString(SECONDS_TO_SUBTRACT_FROM_THIS_RUN_TIME_KEY) != null)
|
||||||
|
{
|
||||||
|
int secondsBack = Integer.parseInt(runBackendStepInput.getValueString(SECONDS_TO_SUBTRACT_FROM_THIS_RUN_TIME_KEY));
|
||||||
|
updatedRunTime = thisRunTime.minusSeconds(secondsBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (updatedRunTime.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,9 @@ package com.kingsrook.qqq.backend.core.processes.implementations.tablesync;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -35,6 +38,7 @@ import java.util.Set;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
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.QPossibleValueTranslator;
|
import com.kingsrook.qqq.backend.core.actions.values.QPossibleValueTranslator;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
|
||||||
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.logging.QLogger;
|
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||||
@ -53,6 +57,7 @@ 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.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.session.QSession;
|
||||||
import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwithfrontend.AbstractTransformStep;
|
import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwithfrontend.AbstractTransformStep;
|
||||||
import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwithfrontend.StreamedETLWithFrontendProcess;
|
import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwithfrontend.StreamedETLWithFrontendProcess;
|
||||||
import com.kingsrook.qqq.backend.core.processes.implementations.general.StandardProcessSummaryLineProducer;
|
import com.kingsrook.qqq.backend.core.processes.implementations.general.StandardProcessSummaryLineProducer;
|
||||||
@ -113,6 +118,7 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
|
|||||||
|
|
||||||
protected static final String SYNC_TABLE_PERFORM_INSERTS_KEY = "syncTablePerformInsertsKey";
|
protected static final String SYNC_TABLE_PERFORM_INSERTS_KEY = "syncTablePerformInsertsKey";
|
||||||
protected static final String SYNC_TABLE_PERFORM_UPDATES_KEY = "syncTablePerformUpdatesKey";
|
protected static final String SYNC_TABLE_PERFORM_UPDATES_KEY = "syncTablePerformUpdatesKey";
|
||||||
|
protected static final String LOG_TRANSFORM_RESULTS = "logTransformResults";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -196,26 +202,6 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
void setPerformInserts(boolean performInserts)
|
|
||||||
{
|
|
||||||
this.setPerformInserts(performInserts);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
void setPerformUpdates(boolean performUpdates)
|
|
||||||
{
|
|
||||||
this.setPerformUpdates(performUpdates);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** artificial method, here to make jacoco see that this class is indeed
|
** artificial method, here to make jacoco see that this class is indeed
|
||||||
** included in test coverage...
|
** included in test coverage...
|
||||||
@ -237,6 +223,7 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
|
|||||||
{
|
{
|
||||||
if(CollectionUtils.nullSafeIsEmpty(runBackendStepInput.getRecords()))
|
if(CollectionUtils.nullSafeIsEmpty(runBackendStepInput.getRecords()))
|
||||||
{
|
{
|
||||||
|
LOG.info("No input records were found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,13 +237,14 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
if(runBackendStepInput.getValueString(SYNC_TABLE_PERFORM_INSERTS_KEY) != null)
|
if(runBackendStepInput.getValueString(SYNC_TABLE_PERFORM_INSERTS_KEY) != null)
|
||||||
{
|
{
|
||||||
config.setPerformInserts(Boolean.parseBoolean(runBackendStepInput.getValueString(SYNC_TABLE_PERFORM_INSERTS_KEY)));
|
boolean performInserts = Boolean.parseBoolean(runBackendStepInput.getValueString(SYNC_TABLE_PERFORM_INSERTS_KEY));
|
||||||
|
config = new SyncProcessConfig(config.sourceTable, config.sourceTableKeyField, config.destinationTable, config.destinationTableForeignKey, performInserts, config.performUpdates);
|
||||||
}
|
}
|
||||||
if(runBackendStepInput.getValueString(SYNC_TABLE_PERFORM_UPDATES_KEY) != null)
|
if(runBackendStepInput.getValueString(SYNC_TABLE_PERFORM_UPDATES_KEY) != null)
|
||||||
{
|
{
|
||||||
config.setPerformUpdates(Boolean.parseBoolean(runBackendStepInput.getValueString(SYNC_TABLE_PERFORM_UPDATES_KEY)));
|
boolean performUpdates = Boolean.parseBoolean(runBackendStepInput.getValueString(SYNC_TABLE_PERFORM_UPDATES_KEY));
|
||||||
|
config = new SyncProcessConfig(config.sourceTable, config.sourceTableKeyField, config.destinationTable, config.destinationTableForeignKey, config.performUpdates, performUpdates);
|
||||||
}
|
}
|
||||||
|
|
||||||
String sourceTableKeyField = config.sourceTableKeyField;
|
String sourceTableKeyField = config.sourceTableKeyField;
|
||||||
String destinationTableForeignKeyField = config.destinationTableForeignKey;
|
String destinationTableForeignKeyField = config.destinationTableForeignKey;
|
||||||
String destinationTableName = config.destinationTable;
|
String destinationTableName = config.destinationTable;
|
||||||
@ -406,6 +394,59 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
|
|||||||
possibleValueTranslator.translatePossibleValuesInRecords(QContext.getQInstance().getTable(destinationTableName), runBackendStepOutput.getRecords());
|
possibleValueTranslator.translatePossibleValuesInRecords(QContext.getQInstance().getTable(destinationTableName), runBackendStepOutput.getRecords());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Boolean.parseBoolean(runBackendStepInput.getValueString(LOG_TRANSFORM_RESULTS)))
|
||||||
|
{
|
||||||
|
logResults(runBackendStepInput, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Log results of transformation
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
protected void logResults(RunBackendStepInput runBackendStepInput, SyncProcessConfig syncProcessConfig)
|
||||||
|
{
|
||||||
|
String timezone = QContext.getQSession().getValue(QSession.VALUE_KEY_USER_TIMEZONE);
|
||||||
|
if(timezone == null)
|
||||||
|
{
|
||||||
|
timezone = QContext.getQInstance().getDefaultTimeZoneId();
|
||||||
|
}
|
||||||
|
Instant lastRunTime = Instant.now();
|
||||||
|
if(runBackendStepInput.getBasepullLastRunTime() != null)
|
||||||
|
{
|
||||||
|
lastRunTime = runBackendStepInput.getBasepullLastRunTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
ZonedDateTime dateTime = lastRunTime.atZone(ZoneId.of(timezone));
|
||||||
|
|
||||||
|
if(syncProcessConfig.performInserts)
|
||||||
|
{
|
||||||
|
if(okToInsert.getCount() == 0)
|
||||||
|
{
|
||||||
|
LOG.info("No Records were found to insert since " + QValueFormatter.formatDateTimeWithZone(dateTime) + ".");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String pluralized = okToInsert.getCount() > 1 ? " Records were " : " Record was ";
|
||||||
|
LOG.info(okToInsert.getCount() + pluralized + " found to insert since " + QValueFormatter.formatDateTimeWithZone(dateTime) + ".", logPair("primaryKeys", okToInsert.getPrimaryKeys()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(syncProcessConfig.performUpdates)
|
||||||
|
{
|
||||||
|
if(okToUpdate.getCount() == 0)
|
||||||
|
{
|
||||||
|
LOG.info("No Records were found to update since " + QValueFormatter.formatDateTimeWithZone(dateTime) + ".");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String pluralized = okToUpdate.getCount() > 1 ? " Records were " : " Record was ";
|
||||||
|
LOG.info(okToUpdate.getCount() + pluralized + " found to update since " + QValueFormatter.formatDateTimeWithZone(dateTime) + ".", logPair("primaryKeys", okToInsert.getPrimaryKeys()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,6 +94,29 @@ public class CountingHash<K extends Serializable> extends AbstractMap<K, Integer
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** increment the value for the specified key
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Integer put(K key)
|
||||||
|
{
|
||||||
|
return (add(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Set the value for the specified key by the supplied value
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Integer put(K key, Integer value)
|
||||||
|
{
|
||||||
|
this.map.put(key, value);
|
||||||
|
return (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -35,9 +35,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Unit test for ProcessAlertWidget
|
** Unit test for AlertWidgetRenderer
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
class ProcessAlertWidgetTest extends BaseTest
|
class AlertWidgetRendererTest extends BaseTest
|
||||||
{
|
{
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -46,10 +46,10 @@ class ProcessAlertWidgetTest extends BaseTest
|
|||||||
@Test
|
@Test
|
||||||
void test() throws QException
|
void test() throws QException
|
||||||
{
|
{
|
||||||
MetaDataProducerHelper.processAllMetaDataProducersInPackage(QContext.getQInstance(), ProcessAlertWidget.class.getPackageName());
|
MetaDataProducerHelper.processAllMetaDataProducersInPackage(QContext.getQInstance(), AlertWidgetRenderer.class.getPackageName());
|
||||||
|
|
||||||
RenderWidgetInput input = new RenderWidgetInput();
|
RenderWidgetInput input = new RenderWidgetInput();
|
||||||
input.setWidgetMetaData(QContext.getQInstance().getWidget(ProcessAlertWidget.NAME));
|
input.setWidgetMetaData(QContext.getQInstance().getWidget(AlertWidgetRenderer.NAME));
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// make sure we run w/o exceptions (and w/ default outputs) if there are no query params //
|
// make sure we run w/o exceptions (and w/ default outputs) if there are no query params //
|
@ -73,4 +73,19 @@ class CountingHashTest extends BaseTest
|
|||||||
assertEquals(1, alwaysMutable.get("B"));
|
assertEquals(1, alwaysMutable.get("B"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testPut()
|
||||||
|
{
|
||||||
|
CountingHash<String> alwaysMutable = new CountingHash<>(Map.of("A", 5));
|
||||||
|
alwaysMutable.put("A", 25);
|
||||||
|
assertEquals(25, alwaysMutable.get("A"));
|
||||||
|
alwaysMutable.put("A");
|
||||||
|
assertEquals(26, alwaysMutable.get("A"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -212,7 +212,7 @@ public class RDBMSCountActionTest extends RDBMSActionTest
|
|||||||
CountInput countInput = new CountInput();
|
CountInput countInput = new CountInput();
|
||||||
countInput.setTableName(TestUtils.TABLE_NAME_WAREHOUSE);
|
countInput.setTableName(TestUtils.TABLE_NAME_WAREHOUSE);
|
||||||
|
|
||||||
assertThat(new CountAction().execute(countInput).getCount()).isEqualTo(1);
|
assertThat(new CountAction().execute(countInput).getCount()).isEqualTo(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -771,6 +771,61 @@ public class RDBMSQueryActionJoinsTest extends RDBMSActionTest
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Error seen in CTLive - query for a record in a sub-table, but whose security
|
||||||
|
** key comes from a main table, but the main-table record doesn't exist.
|
||||||
|
**
|
||||||
|
** In this QInstance, our warehouse table's security key comes from
|
||||||
|
** storeWarehouseInt.storeId - so if we insert a warehouse, but no stores, we
|
||||||
|
** might not be able to find it (if this bug exists!)
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testRequestedJoinWithTableWhoseSecurityFieldIsInMainTableAndNoRowIsInMainTable() throws Exception
|
||||||
|
{
|
||||||
|
runTestSql("INSERT INTO warehouse (name) VALUES ('Springfield')", null);
|
||||||
|
|
||||||
|
QueryInput queryInput = new QueryInput();
|
||||||
|
queryInput.setTableName(TestUtils.TABLE_NAME_WAREHOUSE);
|
||||||
|
queryInput.setFilter(new QQueryFilter(new QFilterCriteria("name", QCriteriaOperator.EQUALS, "Springfield")));
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// with all access key, should find it //
|
||||||
|
/////////////////////////////////////////
|
||||||
|
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_STORE_ALL_ACCESS, true));
|
||||||
|
assertThat(new QueryAction().execute(queryInput).getRecords()).hasSize(1);
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// with a regular key, should not find it //
|
||||||
|
////////////////////////////////////////////
|
||||||
|
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.TABLE_NAME_STORE, 1));
|
||||||
|
assertThat(new QueryAction().execute(queryInput).getRecords()).hasSize(0);
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// now assign the warehouse to a store //
|
||||||
|
/////////////////////////////////////////
|
||||||
|
runTestSql("INSERT INTO warehouse_store_int (store_id, warehouse_id) SELECT 1, id FROM warehouse WHERE name='Springfield'", null);
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// with all access key, should find it //
|
||||||
|
/////////////////////////////////////////
|
||||||
|
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_STORE_ALL_ACCESS, true));
|
||||||
|
assertThat(new QueryAction().execute(queryInput).getRecords()).hasSize(1);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
// with a regular key, should find it if key matches //
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.TABLE_NAME_STORE, 1));
|
||||||
|
assertThat(new QueryAction().execute(queryInput).getRecords()).hasSize(1);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// with a regular key, should not find it if key does not match //
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.TABLE_NAME_STORE, 2));
|
||||||
|
assertThat(new QueryAction().execute(queryInput).getRecords()).hasSize(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -888,7 +943,10 @@ public class RDBMSQueryActionJoinsTest extends RDBMSActionTest
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Note, this test was originally written asserting size=1... but reading
|
||||||
|
** the data, for an all-access key, that seems wrong - as the user should see
|
||||||
|
** all the records in this table, not just ones associated with a store...
|
||||||
|
** so, switching to 4 (same issue in CountActionTest too).
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@Test
|
@Test
|
||||||
void testRecordSecurityWithLockFromJoinTableWhereTheKeyIsOnTheManySide() throws QException
|
void testRecordSecurityWithLockFromJoinTableWhereTheKeyIsOnTheManySide() throws QException
|
||||||
@ -897,8 +955,9 @@ public class RDBMSQueryActionJoinsTest extends RDBMSActionTest
|
|||||||
QueryInput queryInput = new QueryInput();
|
QueryInput queryInput = new QueryInput();
|
||||||
queryInput.setTableName(TestUtils.TABLE_NAME_WAREHOUSE);
|
queryInput.setTableName(TestUtils.TABLE_NAME_WAREHOUSE);
|
||||||
|
|
||||||
assertThat(new QueryAction().execute(queryInput).getRecords())
|
List<QRecord> records = new QueryAction().execute(queryInput).getRecords();
|
||||||
.hasSize(1);
|
assertThat(records)
|
||||||
|
.hasSize(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user