public OptExpression next() {
        // For logic scan to physical scan, we only need to match once
        if (isPatternWithoutChildren && groupExpressionIndex.get(0) > 0) {
            return null;
        }

        OptExpression expression;
        do {
            this.groupTraceKey = 0;

            // Match with the next groupExpression of the last group node
            int lastNode = this.groupExpressionIndex.size() - 1;
            int lastNodeIndex = this.groupExpressionIndex.get(lastNode);
            this.groupExpressionIndex.set(lastNode, lastNodeIndex + 1);

            expression = match(pattern, groupExpression);
        } while (expression == null && this.groupExpressionIndex.size() != 1);

        nextIdx++;
        return expression;
    }
@Test
    public void testBinderMulti3() {
        OptExpression expr1 = OptExpression.create(new MockOperator(OperatorType.LOGICAL_JOIN, 0),
                OptExpression.create(new MockOperator(OperatorType.LOGICAL_PROJECT, 1)),
                OptExpression.create(new MockOperator(OperatorType.LOGICAL_OLAP_SCAN, 2)),
                OptExpression.create(new MockOperator(OperatorType.LOGICAL_OLAP_SCAN, 3)),
                OptExpression.create(new MockOperator(OperatorType.LOGICAL_OLAP_SCAN, 4)),
                OptExpression.create(new MockOperator(OperatorType.LOGICAL_PROJECT, 5)));

        Memo memo = new Memo();
        GroupExpression ge = memo.init(expr1);

        Pattern pattern = Pattern.create(OperatorType.LOGICAL_JOIN)
                .addChildren(Pattern.create(OperatorType.LOGICAL_PROJECT))
                .addChildren(Pattern.create(OperatorType.PATTERN_MULTI_LEAF))
                .addChildren(Pattern.create(OperatorType.LOGICAL_PROJECT));

        Binder binder = new Binder(pattern, ge);
        OptExpression result;

        result = binder.next();
        assertEquals(OperatorType.LOGICAL_JOIN, result.getOp().getOpType());

        assertEquals(OperatorType.LOGICAL_PROJECT, result.inputAt(0).getOp().getOpType());
        assertEquals(1, ((MockOperator) result.inputAt(0).getOp()).getValue());

        assertEquals(OperatorType.LOGICAL_OLAP_SCAN, result.inputAt(1).getOp().getOpType());
        assertEquals(2, ((MockOperator) result.inputAt(1).getOp()).getValue());

        assertEquals(OperatorType.LOGICAL_OLAP_SCAN, result.inputAt(2).getOp().getOpType());
        assertEquals(3, ((MockOperator) result.inputAt(2).getOp()).getValue());

        assertEquals(OperatorType.LOGICAL_OLAP_SCAN, result.inputAt(3).getOp().getOpType());
        assertEquals(4, ((MockOperator) result.inputAt(3).getOp()).getValue());

        assertEquals(OperatorType.LOGICAL_PROJECT, result.inputAt(4).getOp().getOpType());
        assertEquals(5, ((MockOperator) result.inputAt(4).getOp()).getValue());

        assertNull(binder.next());
    }