class QGroupSorted extends QOperator {

    private Value[] previousKeyValues;

    QGroupSorted(Select select) {
        super(select);
        select.currentGroup = null;
    }

    public Value[] getPreviousKeyValues() {
        return previousKeyValues;
    }

    @Override
    public void run() {<FILL_FUNCTION_BODY>}
}

        while (next()) {
            boolean yield = yieldIfNeeded(++loopCount);
            if (conditionEvaluator.getBooleanValue()) {
                if (select.isForUpdate && !tryLockRow()) {
                    return; // 锁记录失败
                }
                rowCount++;
                Value[] keyValues = QGroup.getKeyValues(select);
                if (previousKeyValues == null) {
                    previousKeyValues = keyValues;
                    select.currentGroup = new HashMap<>();
                } else if (!Arrays.equals(previousKeyValues, keyValues)) {
                    QGroup.addGroupRow(select, previousKeyValues, columnCount, result);
                    previousKeyValues = keyValues;
                    select.currentGroup = new HashMap<>();
                }
                select.currentGroupRowId++;
                QGroup.updateAggregate(select, columnCount);
                if (yield)
                    return;
            }
        }
        if (previousKeyValues != null) {
            QGroup.addGroupRow(select, previousKeyValues, columnCount, result);
        }
        loopEnd = true;
    
<methods>public void <init>(com.lealone.sql.query.Select) ,public boolean canBreakLoop() ,public void copyStatusTo(com.lealone.sql.query.QOperator) ,public com.lealone.sql.expression.evaluator.ExpressionEvaluator createConditionEvaluator(com.lealone.sql.expression.Expression) ,public com.lealone.db.value.Value[] createRow() ,public com.lealone.db.result.LocalResult getLocalResult() ,public boolean isStopped() ,public void onLockedException() ,public void run() ,public void start() ,public void stop() ,public boolean yieldIfNeeded(int) <variables>protected int columnCount,protected final non-sealed com.lealone.sql.expression.evaluator.ExpressionEvaluator conditionEvaluator,protected long limitRows,protected com.lealone.db.result.LocalResult localResult,protected int loopCount,protected boolean loopEnd,protected int maxRows,protected com.lealone.db.result.ResultTarget result,protected int rowCount,protected int sampleSize,protected final non-sealed com.lealone.sql.query.Select select,protected final non-sealed com.lealone.db.session.ServerSession session,protected final non-sealed com.lealone.sql.optimizer.TableIterator tableIterator,protected com.lealone.db.result.ResultTarget target,protected com.lealone.sql.query.YieldableSelect yieldableSelect