Let caller specify type to use for an aggregate expression

This commit is contained in:
2023-03-16 11:38:26 -05:00
parent 939dcc308c
commit b16eaca394
3 changed files with 61 additions and 13 deletions

View File

@ -24,15 +24,18 @@ package com.kingsrook.qqq.backend.core.model.actions.tables.aggregate;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects; import java.util.Objects;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
/******************************************************************************* /*******************************************************************************
** ** Define an "aggregate", e.g., to be selected in an Aggregate action.
** Such as SUM(cost).
*******************************************************************************/ *******************************************************************************/
public class Aggregate implements Serializable public class Aggregate implements Serializable
{ {
private String fieldName; private String fieldName;
private AggregateOperator operator; private AggregateOperator operator;
private QFieldType fieldType;
@ -55,12 +58,14 @@ public class Aggregate implements Serializable
{ {
return true; return true;
} }
if(o == null || getClass() != o.getClass()) if(o == null || getClass() != o.getClass())
{ {
return false; return false;
} }
Aggregate aggregate = (Aggregate) o; Aggregate aggregate = (Aggregate) o;
return Objects.equals(fieldName, aggregate.fieldName) && operator == aggregate.operator; return Objects.equals(fieldName, aggregate.fieldName) && operator == aggregate.operator && fieldType == aggregate.fieldType;
} }
@ -71,7 +76,7 @@ public class Aggregate implements Serializable
@Override @Override
public int hashCode() public int hashCode()
{ {
return Objects.hash(fieldName, operator); return Objects.hash(fieldName, operator, fieldType);
} }
@ -153,4 +158,35 @@ public class Aggregate implements Serializable
return (this); return (this);
} }
/*******************************************************************************
** Getter for fieldType
*******************************************************************************/
public QFieldType getFieldType()
{
return (this.fieldType);
}
/*******************************************************************************
** Setter for fieldType
*******************************************************************************/
public void setFieldType(QFieldType fieldType)
{
this.fieldType = fieldType;
}
/*******************************************************************************
** Fluent setter for fieldType
*******************************************************************************/
public Aggregate withFieldType(QFieldType fieldType)
{
this.fieldType = fieldType;
return (this);
}
} }

View File

@ -108,7 +108,7 @@ public class ColumnStatsStep implements BackendStep
//////////////////////////////////////////// ////////////////////////////////////////////
// do a count query grouped by this field // // do a count query grouped by this field //
//////////////////////////////////////////// ////////////////////////////////////////////
Aggregate aggregate = new Aggregate(table.getPrimaryKeyField(), AggregateOperator.COUNT); Aggregate aggregate = new Aggregate(table.getPrimaryKeyField(), AggregateOperator.COUNT).withFieldType(QFieldType.DECIMAL);
GroupBy groupBy = new GroupBy(field.getType(), fieldName); GroupBy groupBy = new GroupBy(field.getType(), fieldName);
if(StringUtils.hasContent(orderBy)) if(StringUtils.hasContent(orderBy))
@ -171,7 +171,7 @@ public class ColumnStatsStep implements BackendStep
QFieldMetaData countNonNullField = new QFieldMetaData("count", QFieldType.INTEGER).withLabel("Rows with a value").withDisplayFormat(DisplayFormat.COMMAS); QFieldMetaData countNonNullField = new QFieldMetaData("count", QFieldType.INTEGER).withLabel("Rows with a value").withDisplayFormat(DisplayFormat.COMMAS);
QFieldMetaData countDistinctField = new QFieldMetaData("countDistinct", QFieldType.INTEGER).withLabel("Distinct values").withDisplayFormat(DisplayFormat.COMMAS); QFieldMetaData countDistinctField = new QFieldMetaData("countDistinct", QFieldType.INTEGER).withLabel("Distinct values").withDisplayFormat(DisplayFormat.COMMAS);
QFieldMetaData sumField = new QFieldMetaData("sum", QFieldType.DECIMAL).withDisplayFormat(field.getDisplayFormat()); QFieldMetaData sumField = new QFieldMetaData("sum", QFieldType.DECIMAL).withDisplayFormat(field.getDisplayFormat());
QFieldMetaData avgField = new QFieldMetaData("average", QFieldType.DECIMAL).withDisplayFormat(field.getDisplayFormat()); QFieldMetaData avgField = new QFieldMetaData("average", QFieldType.DECIMAL).withDisplayFormat(DisplayFormat.DECIMAL2_COMMAS);
QFieldMetaData minField = new QFieldMetaData("min", field.getType()).withDisplayFormat(field.getDisplayFormat()); QFieldMetaData minField = new QFieldMetaData("min", field.getType()).withDisplayFormat(field.getDisplayFormat());
QFieldMetaData maxField = new QFieldMetaData("max", field.getType()).withDisplayFormat(field.getDisplayFormat()); QFieldMetaData maxField = new QFieldMetaData("max", field.getType()).withDisplayFormat(field.getDisplayFormat());
@ -205,6 +205,11 @@ public class ColumnStatsStep implements BackendStep
doMax = false; doMax = false;
} }
if(field.getName().equals(table.getPrimaryKeyField()))
{
doSum = false;
}
ArrayList<QFieldMetaData> fields = new ArrayList<>(); ArrayList<QFieldMetaData> fields = new ArrayList<>();
fields.add(countNonNullField); fields.add(countNonNullField);
fields.add(countDistinctField); fields.add(countDistinctField);
@ -233,10 +238,13 @@ public class ColumnStatsStep implements BackendStep
doCountDistinct = false; doCountDistinct = false;
} }
Aggregate countNonNullAggregate = new Aggregate(fieldName, AggregateOperator.COUNT); /////////////////////////////////////////////////////////////////////////////////
Aggregate countDistinctAggregate = new Aggregate(fieldName, AggregateOperator.COUNT_DISTINCT); // just in case any of these don't fit in an integer, use decimal for them all //
Aggregate sumAggregate = new Aggregate(fieldName, AggregateOperator.SUM); /////////////////////////////////////////////////////////////////////////////////
Aggregate avgAggregate = new Aggregate(fieldName, AggregateOperator.AVG); Aggregate countNonNullAggregate = new Aggregate(fieldName, AggregateOperator.COUNT).withFieldType(QFieldType.DECIMAL);
Aggregate countDistinctAggregate = new Aggregate(fieldName, AggregateOperator.COUNT_DISTINCT).withFieldType(QFieldType.DECIMAL);
Aggregate sumAggregate = new Aggregate(fieldName, AggregateOperator.SUM).withFieldType(QFieldType.DECIMAL);
Aggregate avgAggregate = new Aggregate(fieldName, AggregateOperator.AVG).withFieldType(QFieldType.DECIMAL);
Aggregate minAggregate = new Aggregate(fieldName, AggregateOperator.MIN); Aggregate minAggregate = new Aggregate(fieldName, AggregateOperator.MIN);
Aggregate maxAggregate = new Aggregate(fieldName, AggregateOperator.MAX); Aggregate maxAggregate = new Aggregate(fieldName, AggregateOperator.MAX);
AggregateInput statsAggregateInput = new AggregateInput(); AggregateInput statsAggregateInput = new AggregateInput();

View File

@ -119,14 +119,18 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(aggregate.getFieldName()); JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(aggregate.getFieldName());
QFieldMetaData field = fieldAndTableNameOrAlias.field(); QFieldMetaData field = fieldAndTableNameOrAlias.field();
if(field.getType().equals(QFieldType.INTEGER) && (aggregate.getOperator().equals(AggregateOperator.AVG) || aggregate.getOperator().equals(AggregateOperator.SUM))) QFieldType fieldType = aggregate.getFieldType();
if(fieldType == null)
{ {
field = new QFieldMetaData().withType(QFieldType.DECIMAL); if(field.getType().equals(QFieldType.INTEGER) && (aggregate.getOperator().equals(AggregateOperator.AVG)))
{
fieldType = QFieldType.DECIMAL;
}
} }
if(aggregate.getOperator().equals(AggregateOperator.COUNT) || aggregate.getOperator().equals(AggregateOperator.COUNT_DISTINCT)) if(fieldType != null)
{ {
field = new QFieldMetaData().withType(QFieldType.DECIMAL); field = new QFieldMetaData().withType(fieldType);
} }
Serializable value = getFieldValueFromResultSet(field, resultSet, selectionIndex++); Serializable value = getFieldValueFromResultSet(field, resultSet, selectionIndex++);