@Override
    public List<OptExpression> transform(OptExpression input, OptimizerContext context) {
        // will transform to topN
        LogicalLimitOperator limit = (LogicalLimitOperator) input.getOp();
        LogicalTopNOperator sort = (LogicalTopNOperator) input.getInputs().get(0).getOp();

        long minLimit = limit.getLimit();
        if (sort.hasLimit()) {
            minLimit = Math.min(minLimit, sort.getLimit());
        }
        OptExpression result = new OptExpression(
                new LogicalTopNOperator(sort.getOrderByElements(), limit.getLimit(), limit.getOffset()));
        result.getInputs().addAll(input.getInputs().get(0).getInputs());
        return Lists.newArrayList(result);
    }
@Test
    public void transform() {
        OptExpression limit = new OptExpression(LogicalLimitOperator.init(10, 2));
        OptExpression sort = new OptExpression(new LogicalTopNOperator(
                Lists.newArrayList(new Ordering(new ColumnRefOperator(1, Type.INT, "name", true), false, false))));

        limit.getInputs().add(sort);

        MergeLimitWithSortRule rule = new MergeLimitWithSortRule();
        List<OptExpression> list = rule.transform(limit, new OptimizerContext(new Memo(), new ColumnRefFactory()));

        assertEquals(OperatorType.LOGICAL_TOPN, list.get(0).getOp().getOpType());
        assertEquals(2, ((LogicalTopNOperator) list.get(0).getOp()).getOffset());
        assertEquals(10, ((LogicalTopNOperator) list.get(0).getOp()).getLimit());
    }