@Override
    public Optional<ShardingConditionValue> generate(final BetweenExpression predicate, final Column column, final List<Object> params, final TimestampServiceRule timestampServiceRule) {
        ConditionValue betweenConditionValue = new ConditionValue(predicate.getBetweenExpr(), params);
        ConditionValue andConditionValue = new ConditionValue(predicate.getAndExpr(), params);
        Optional<Comparable<?>> betweenValue = betweenConditionValue.getValue();
        Optional<Comparable<?>> andValue = andConditionValue.getValue();
        List<Integer> parameterMarkerIndexes = new ArrayList<>(2);
        betweenConditionValue.getParameterMarkerIndex().ifPresent(parameterMarkerIndexes::add);
        andConditionValue.getParameterMarkerIndex().ifPresent(parameterMarkerIndexes::add);
        if (betweenValue.isPresent() && andValue.isPresent()) {
            return Optional.of(new RangeShardingConditionValue<>(column.getName(), column.getTableName(), SafeNumberOperationUtils.safeClosed(betweenValue.get(), andValue.get()),
                    parameterMarkerIndexes));
        }
        Timestamp timestamp = timestampServiceRule.getTimestamp();
        if (!betweenValue.isPresent() && ExpressionConditionUtils.isNowExpression(predicate.getBetweenExpr())) {
            betweenValue = Optional.of(timestamp);
        }
        if (!andValue.isPresent() && ExpressionConditionUtils.isNowExpression(predicate.getAndExpr())) {
            andValue = Optional.of(timestamp);
        }
        if (!betweenValue.isPresent() || !andValue.isPresent()) {
            return Optional.empty();
        }
        return Optional.of(new RangeShardingConditionValue<>(column.getName(), column.getTableName(), Range.closed(betweenValue.get(), andValue.get()), parameterMarkerIndexes));
    }
@SuppressWarnings("unchecked")
    @Test
    void assertGenerateConditionValueWithParameter() {
        ColumnSegment left = new ColumnSegment(0, 0, new IdentifierValue("id"));
        ParameterMarkerExpressionSegment between = new ParameterMarkerExpressionSegment(0, 0, 0);
        ParameterMarkerExpressionSegment and = new ParameterMarkerExpressionSegment(0, 0, 1);
        BetweenExpression predicate = new BetweenExpression(0, 0, left, between, and, false);
        Optional<ShardingConditionValue> actual = generator.generate(predicate, column, Arrays.asList(1, 2), timestampServiceRule);
        assertTrue(actual.isPresent());
        assertThat(actual.get(), instanceOf(RangeShardingConditionValue.class));
        RangeShardingConditionValue<Integer> conditionValue = (RangeShardingConditionValue<Integer>) actual.get();
        assertThat(conditionValue.getTableName(), is("tbl"));
        assertThat(conditionValue.getColumnName(), is("id"));
        assertThat(conditionValue.getValueRange(), is(Range.closed(1, 2)));
        assertThat(conditionValue.getParameterMarkerIndexes(), is(Arrays.asList(0, 1)));
    }