class Aggregate extends Expression {

    /**
     * The aggregate type for COUNT(*).
     */
    public static final int COUNT_ALL = 0;

    /**
     * The aggregate type for COUNT(expression).
     */
    public static final int COUNT = 1;

    /**
     * The aggregate type for GROUP_CONCAT(...).
     */
    public static final int GROUP_CONCAT = 2;

    /**
     * The aggregate type for SUM(expression).
     */
    public static final int SUM = 3;

    /**
     * The aggregate type for MIN(expression).
     */
    public static final int MIN = 4;

    /**
     * The aggregate type for MAX(expression).
     */
    public static final int MAX = 5;

    /**
     * The aggregate type for AVG(expression).
     */
    public static final int AVG = 6;

    /**
     * The aggregate type for STDDEV_POP(expression).
     */
    public static final int STDDEV_POP = 7;

    /**
     * The aggregate type for STDDEV_SAMP(expression).
     */
    public static final int STDDEV_SAMP = 8;

    /**
     * The aggregate type for VAR_POP(expression).
     */
    public static final int VAR_POP = 9;

    /**
     * The aggregate type for VAR_SAMP(expression).
     */
    public static final int VAR_SAMP = 10;

    /**
     * The aggregate type for BOOL_OR(expression).
     */
    public static final int BOOL_OR = 11;

    /**
     * The aggregate type for BOOL_AND(expression).
     */
    public static final int BOOL_AND = 12;

    /**
     * The aggregate type for BIT_OR(expression).
     */
    public static final int BIT_OR = 13;

    /**
     * The aggregate type for BIT_AND(expression).
     */
    public static final int BIT_AND = 14;

    /**
     * The aggregate type for SELECTIVITY(expression).
     */
    public static final int SELECTIVITY = 15;

    /**
     * The aggregate type for HISTOGRAM(expression).
     */
    public static final int HISTOGRAM = 16;

    private static final HashMap<String, Integer> AGGREGATES = new HashMap<>();

    static {
        addAggregate("COUNT", COUNT);
        addAggregate("SUM", SUM);
        addAggregate("MIN", MIN);
        addAggregate("MAX", MAX);
        addAggregate("AVG", AVG);
        addAggregate("GROUP_CONCAT", GROUP_CONCAT);
        // PostgreSQL compatibility: string_agg(expression, delimiter)
        addAggregate("STRING_AGG", GROUP_CONCAT);
        addAggregate("STDDEV_SAMP", STDDEV_SAMP);
        addAggregate("STDDEV", STDDEV_SAMP);
        addAggregate("STDDEV_POP", STDDEV_POP);
        addAggregate("STDDEVP", STDDEV_POP);
        addAggregate("VAR_POP", VAR_POP);
        addAggregate("VARP", VAR_POP);
        addAggregate("VAR_SAMP", VAR_SAMP);
        addAggregate("VAR", VAR_SAMP);
        addAggregate("VARIANCE", VAR_SAMP);
        addAggregate("BOOL_OR", BOOL_OR);
        addAggregate("BOOL_AND", BOOL_AND);
        // HSQLDB compatibility, but conflicts with x > SOME(...)
        addAggregate("SOME", BOOL_OR);
        // HSQLDB compatibility, but conflicts with x > EVERY(...)
        addAggregate("EVERY", BOOL_AND);
        addAggregate("SELECTIVITY", SELECTIVITY);
        addAggregate("HISTOGRAM", HISTOGRAM);
        addAggregate("BIT_OR", BIT_OR);
        addAggregate("BIT_AND", BIT_AND);
    }

    private static void addAggregate(String name, int type) {
        AGGREGATES.put(name, type);
    }

    /**
     * Get the aggregate type for this name, or -1 if no aggregate has been found.
     *
     * @param name the aggregate function name
     * @return -1 if no aggregate function has been found, or the aggregate type
     */
    public static int getAggregateType(String name) {
        Integer type = AGGREGATES.get(name);
        return type == null ? -1 : type.intValue();
    }

    public static Aggregate create(int type, Expression on, Select select, boolean distinct) {<FILL_FUNCTION_BODY>}

    protected final Select select;
    protected int dataType;
    protected int lastGroupRowId;

    public Aggregate(Select select) {
        this.select = select;
    }

    @Override
    public int getType() {
        return dataType;
    }

    @Override
    public <R> R accept(ExpressionVisitor<R> visitor) {
        return visitor.visitAggregate(this);
    }

    public Expression getOn() {
        return null;
    }
}

        switch (type) {
        case Aggregate.COUNT:
            return new ACount(type, on, select, distinct);
        case Aggregate.COUNT_ALL:
            return new ACountAll(type, on, select, distinct);
        case Aggregate.GROUP_CONCAT:
            return new AGroupConcat(type, on, select, distinct);
        case Aggregate.HISTOGRAM:
            return new AHistogram(type, on, select, distinct);
        case Aggregate.SELECTIVITY:
            return new ASelectivity(type, on, select, distinct);
        default:
            return new ADefault(type, on, select, distinct);
        }
    
<methods>public non-sealed void <init>() ,public R accept(ExpressionVisitor<R>) ,public void addFilterConditions(com.lealone.sql.optimizer.TableFilter, boolean) ,public void createIndexConditions(com.lealone.db.session.ServerSession, com.lealone.sql.optimizer.TableFilter) ,public java.lang.String getAlias() ,public boolean getBooleanValue(com.lealone.db.session.ServerSession) ,public java.lang.String getColumnName() ,public void getColumns(Set<?>) ,public abstract int getCost() ,public void getDependencies(Set<?>) ,public abstract int getDisplaySize() ,public com.lealone.sql.expression.Expression[] getExpressionColumns(com.lealone.db.session.ServerSession) ,public static com.lealone.sql.expression.Expression[] getExpressionColumns(com.lealone.db.session.ServerSession, com.lealone.db.value.ValueArray) ,public static com.lealone.sql.expression.Expression[] getExpressionColumns(com.lealone.db.session.ServerSession, java.sql.ResultSet) ,public com.lealone.sql.expression.Expression getNonAliasExpression() ,public com.lealone.sql.expression.Expression getNotIfPossible(com.lealone.db.session.ServerSession) ,public int getNullable() ,public abstract long getPrecision() ,public abstract java.lang.String getSQL() ,public abstract int getScale() ,public java.lang.String getSchemaName() ,public java.lang.String getTableName() ,public abstract int getType() ,public com.lealone.db.value.Value getValue(com.lealone.db.session.Session) ,public abstract com.lealone.db.value.Value getValue(com.lealone.db.session.ServerSession) ,public boolean isAutoIncrement() ,public boolean isConstant() ,public boolean isEvaluatable() ,public boolean isValueSet() ,public boolean isWildcard() ,public void mapColumns(com.lealone.sql.optimizer.ColumnResolver, int) ,public abstract com.lealone.sql.expression.Expression optimize(com.lealone.db.session.ServerSession) ,public com.lealone.sql.expression.Expression optimize(com.lealone.db.session.Session) ,public java.lang.String toString() ,public void updateAggregate(com.lealone.db.session.ServerSession) <variables>private boolean addedToFilter