DATAREDIS-852 - Return always a lower/upper bound range index using Range.Bound.unbounded() with Lettuce.

We now return in List, String, and ZSet commands a lower/upper bound range index to prevent NullPointerException. Previously, unbounded ranges could render null values that were attempted to cast to primitives.

Original pull request: #353.
This commit is contained in:
michele
2018-07-19 15:21:29 +02:00
committed by Mark Paluch
parent 2dfe1e2b4e
commit 3a7d871119
6 changed files with 136 additions and 21 deletions

View File

@@ -38,6 +38,7 @@ import org.springframework.util.ObjectUtils;
/**
* @author Christoph Strobl
* @author Mark Paluch
* @author Michele Mancioppi
* @since 2.0
*/
class LettuceReactiveListCommands implements ReactiveListCommands {
@@ -116,8 +117,8 @@ class LettuceReactiveListCommands implements ReactiveListCommands {
Assert.notNull(command.getKey(), "Key must not be null!");
Assert.notNull(command.getRange(), "Range must not be null!");
Flux<ByteBuffer> result = cmd.lrange(command.getKey(), command.getRange().getLowerBound().getValue().orElse(null),
command.getRange().getUpperBound().getValue().orElse(null));
Flux<ByteBuffer> result = cmd.lrange(command.getKey(), command.getRange().getLowerBound().getValue().orElse(0L),
command.getRange().getUpperBound().getValue().orElse(Long.MAX_VALUE));
return Mono.just(new CommandResponse<>(command, result));
}));
}
@@ -135,8 +136,8 @@ class LettuceReactiveListCommands implements ReactiveListCommands {
Assert.notNull(command.getRange(), "Range must not be null!");
return cmd
.ltrim(command.getKey(), command.getRange().getLowerBound().getValue().orElse(null),
command.getRange().getUpperBound().getValue().orElse(null))
.ltrim(command.getKey(), command.getRange().getLowerBound().getValue().orElse(0L),
command.getRange().getUpperBound().getValue().orElse(Long.MAX_VALUE))
.map(LettuceConverters::stringToBoolean).map(value -> new BooleanResponse<>(command, value));
}));
}

View File

@@ -40,6 +40,7 @@ import org.springframework.util.Assert;
* @author Christoph Strobl
* @author Mark Paluch
* @author Jiahe Cai
* @author Michele Mancioppi
* @since 2.0
*/
class LettuceReactiveStringCommands implements ReactiveStringCommands {
@@ -251,8 +252,8 @@ class LettuceReactiveStringCommands implements ReactiveStringCommands {
Range<Long> range = command.getRange();
return cmd.getrange(command.getKey(), range.getLowerBound().getValue().orElse(null),
range.getUpperBound().getValue().orElse(null)).map((value) -> new ByteBufferResponse<>(command, value));
return cmd.getrange(command.getKey(), range.getLowerBound().getValue().orElse(0L),
range.getUpperBound().getValue().orElse(Long.MAX_VALUE)).map((value) -> new ByteBufferResponse<>(command, value));
}));
}
@@ -323,7 +324,7 @@ class LettuceReactiveStringCommands implements ReactiveStringCommands {
Range<Long> range = command.getRange();
return (!Range.unbounded().equals(range) ? cmd.bitcount(command.getKey(),
range.getLowerBound().getValue().orElse(null), range.getUpperBound().getValue().orElse(null))
range.getLowerBound().getValue().orElse(0L), range.getUpperBound().getValue().orElse(Long.MAX_VALUE))
: cmd.bitcount(command.getKey())).map(responseValue -> new NumericResponse<>(command, responseValue));
}));
}

View File

@@ -49,6 +49,7 @@ import org.springframework.util.StringUtils;
/**
* @author Christoph Strobl
* @author Mark Paluch
* @author Michele Mancioppi
* @since 2.0
*/
class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
@@ -189,28 +190,28 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
if (command.isWithScores()) {
result = cmd
.zrangeWithScores(command.getKey(), command.getRange().getLowerBound().getValue().orElse(null),
command.getRange().getUpperBound().getValue().orElse(null))
.zrangeWithScores(command.getKey(), command.getRange().getLowerBound().getValue().orElse(0L),
command.getRange().getUpperBound().getValue().orElse(Long.MAX_VALUE))
.map(sc -> (Tuple) new DefaultTuple(getBytes(sc), sc.getScore()));
} else {
result = cmd
.zrange(command.getKey(), command.getRange().getLowerBound().getValue().orElse(null),
command.getRange().getUpperBound().getValue().orElse(null))
.zrange(command.getKey(), command.getRange().getLowerBound().getValue().orElse(0L),
command.getRange().getUpperBound().getValue().orElse(Long.MAX_VALUE))
.map(value -> (Tuple) new DefaultTuple(ByteUtils.getBytes(value), Double.NaN));
}
} else {
if (command.isWithScores()) {
result = cmd
.zrevrangeWithScores(command.getKey(), command.getRange().getLowerBound().getValue().orElse(null),
command.getRange().getUpperBound().getValue().orElse(null))
.zrevrangeWithScores(command.getKey(), command.getRange().getLowerBound().getValue().orElse(0L),
command.getRange().getUpperBound().getValue().orElse(Long.MAX_VALUE))
.map(sc -> (Tuple) new DefaultTuple(getBytes(sc), sc.getScore()));
} else {
result = cmd
.zrevrange(command.getKey(), command.getRange().getLowerBound().getValue().orElse(null),
command.getRange().getUpperBound().getValue().orElse(null))
.zrevrange(command.getKey(), command.getRange().getLowerBound().getValue().orElse(0L),
command.getRange().getUpperBound().getValue().orElse(Long.MAX_VALUE))
.map(value -> (Tuple) new DefaultTuple(ByteUtils.getBytes(value), Double.NaN));
}
}
@@ -377,8 +378,8 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
Assert.notNull(command.getRange(), "Range must not be null!");
return cmd
.zremrangebyrank(command.getKey(), command.getRange().getLowerBound().getValue().orElse(null),
command.getRange().getUpperBound().getValue().orElse(null))
.zremrangebyrank(command.getKey(), command.getRange().getLowerBound().getValue().orElse(0L),
command.getRange().getUpperBound().getValue().orElse(Long.MAX_VALUE))
.map(value -> new NumericResponse<>(command, value));
}));
}
@@ -544,11 +545,14 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
Boolean upper) {
return (source) -> {
Boolean inclusive = upper ? source.getUpperBound().isInclusive() : source.getLowerBound().isInclusive();
Object value = upper ? source.getUpperBound().getValue().orElse(null)
: source.getLowerBound().getValue().orElse(null);
if (value == null) {
return Boundary.unbounded();
}
if (value instanceof Number) {
return inclusive ? Boundary.including((Number) value) : Boundary.excluding((Number) value);
}