diff --git a/src/main/java/org/springframework/data/redis/core/KeyScanOptions.java b/src/main/java/org/springframework/data/redis/core/KeyScanOptions.java
index 85f2abe8f..be8ffc198 100644
--- a/src/main/java/org/springframework/data/redis/core/KeyScanOptions.java
+++ b/src/main/java/org/springframework/data/redis/core/KeyScanOptions.java
@@ -17,6 +17,7 @@ package org.springframework.data.redis.core;
import java.util.StringJoiner;
+import org.springframework.data.redis.connection.DataType;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
@@ -24,6 +25,7 @@ import org.springframework.util.StringUtils;
* Options to be used for with {@literal SCAN} commands.
*
* @author Mark Paluch
+ * @author Christoph Strobl
* @since 2.6
*/
public class KeyScanOptions extends ScanOptions {
@@ -35,7 +37,7 @@ public class KeyScanOptions extends ScanOptions {
private final @Nullable String type;
- private KeyScanOptions(@Nullable Long count, @Nullable String pattern, @Nullable byte[] bytePattern,
+ KeyScanOptions(@Nullable Long count, @Nullable String pattern, @Nullable byte[] bytePattern,
@Nullable String type) {
super(count, pattern, bytePattern);
@@ -43,12 +45,13 @@ public class KeyScanOptions extends ScanOptions {
}
/**
- * Static factory method that returns a new {@link KeyScanOptionsBuilder}.
+ * Static factory method that returns a new {@link ScanOptionsBuilder}.
*
+ * @param type
* @return
*/
- public static KeyScanOptionsBuilder scanOptions() {
- return new KeyScanOptionsBuilder();
+ public static ScanOptionsBuilder scanOptions(DataType type) {
+ return new ScanOptionsBuilder().type(type);
}
@Nullable
@@ -71,68 +74,4 @@ public class KeyScanOptions extends ScanOptions {
return joiner.toString();
}
-
- public static class KeyScanOptionsBuilder extends ScanOptionsBuilder {
-
- private @Nullable String type;
-
- private KeyScanOptionsBuilder() {}
-
- /**
- * Returns the current {@link KeyScanOptionsBuilder} configured with the given {@code count}.
- *
- * @param count
- * @return
- */
- @Override
- public KeyScanOptionsBuilder count(long count) {
- super.count(count);
- return this;
- }
-
- /**
- * Returns the current {@link KeyScanOptionsBuilder} configured with the given {@code pattern}.
- *
- * @param pattern
- * @return
- */
- @Override
- public KeyScanOptionsBuilder match(String pattern) {
- super.match(pattern);
- return this;
- }
-
- /**
- * Returns the current {@link KeyScanOptionsBuilder} configured with the given {@code pattern}.
- *
- * @param pattern
- * @return
- */
- @Override
- public KeyScanOptionsBuilder match(byte[] pattern) {
- super.match(pattern);
- return this;
- }
-
- /**
- * Returns the current {@link KeyScanOptionsBuilder} configured with the given {@code type}.
- *
- * @param type
- * @return
- */
- public KeyScanOptionsBuilder type(String type) {
- this.type = type;
- return this;
- }
-
- /**
- * Builds a new {@link KeyScanOptions} objects.
- *
- * @return a new {@link KeyScanOptions} objects.
- */
- @Override
- public KeyScanOptions build() {
- return new KeyScanOptions(count, pattern, bytePattern, type);
- }
- }
}
diff --git a/src/main/java/org/springframework/data/redis/core/ScanOptions.java b/src/main/java/org/springframework/data/redis/core/ScanOptions.java
index e36849879..4cba64c4b 100644
--- a/src/main/java/org/springframework/data/redis/core/ScanOptions.java
+++ b/src/main/java/org/springframework/data/redis/core/ScanOptions.java
@@ -17,7 +17,9 @@ package org.springframework.data.redis.core;
import java.util.StringJoiner;
+import org.springframework.data.redis.connection.DataType;
import org.springframework.lang.Nullable;
+import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@@ -41,6 +43,7 @@ public class ScanOptions {
private final @Nullable byte[] bytePattern;
ScanOptions(@Nullable Long count, @Nullable String pattern, @Nullable byte[] bytePattern) {
+
this.count = count;
this.pattern = pattern;
this.bytePattern = bytePattern;
@@ -110,6 +113,7 @@ public class ScanOptions {
@Nullable Long count;
@Nullable String pattern;
@Nullable byte[] bytePattern;
+ @Nullable DataType type;
ScanOptionsBuilder() {}
@@ -117,7 +121,7 @@ public class ScanOptions {
* Returns the current {@link ScanOptionsBuilder} configured with the given {@code count}.
*
* @param count
- * @return
+ * @return this.
*/
public ScanOptionsBuilder count(long count) {
this.count = count;
@@ -128,7 +132,7 @@ public class ScanOptions {
* Returns the current {@link ScanOptionsBuilder} configured with the given {@code pattern}.
*
* @param pattern
- * @return
+ * @return this.
*/
public ScanOptionsBuilder match(String pattern) {
this.pattern = pattern;
@@ -139,7 +143,7 @@ public class ScanOptions {
* Returns the current {@link ScanOptionsBuilder} configured with the given {@code pattern}.
*
* @param pattern
- * @return
+ * @return this.
* @since 2.6
*/
public ScanOptionsBuilder match(byte[] pattern) {
@@ -147,12 +151,46 @@ public class ScanOptions {
return this;
}
+ /**
+ * Returns the current {@link ScanOptionsBuilder} configured with the given {@code type}.
+ * Please verify the the targeted command supports the
+ * TYPE option before use.
+ *
+ * @param type must not be {@literal null}. Either do not set or use {@link DataType#NONE}.
+ * @return this.
+ * @since 2.6
+ */
+ public ScanOptionsBuilder type(DataType type) {
+
+ Assert.notNull(type, "Type must not be null! Use NONE instead.");
+
+ this.type = type;
+ return this;
+ }
+
+ /**
+ * Returns the current {@link ScanOptionsBuilder} configured with the given {@code type}.
+ *
+ * @param type the textual representation of {@link DataType#fromCode(String)}. Must not be {@literal null}.
+ * @return this.
+ * @throws IllegalArgumentException if given type is {@literal null} or unknown.
+ */
+ public ScanOptionsBuilder type(String type) {
+
+ Assert.notNull(type, "Type must not be null!");
+ return type(DataType.fromCode(type));
+ }
+
/**
* Builds a new {@link ScanOptions} objects.
*
* @return a new {@link ScanOptions} objects.
*/
public ScanOptions build() {
+
+ if (type != null && !DataType.NONE.equals(type)) {
+ return new KeyScanOptions(count, pattern, bytePattern, type.code());
+ }
return new ScanOptions(count, pattern, bytePattern);
}
}
diff --git a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java
index 3a8767db0..debe99ae1 100644
--- a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java
+++ b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java
@@ -2598,7 +2598,7 @@ public abstract class AbstractConnectionIntegrationTests {
@Test // GH-2089
@EnabledOnRedisDriver(RedisDriver.LETTUCE)
- @EnabledOnRedisVersion("6.2")
+ @EnabledOnRedisVersion("6.0")
void scanWithType() {
assumeThat(connection.isPipelined() || connection.isQueueing())
diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommandsIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommandsIntegrationTests.java
index 7dc460894..f3de761ae 100644
--- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommandsIntegrationTests.java
+++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommandsIntegrationTests.java
@@ -35,8 +35,10 @@ import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand;
import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse;
import org.springframework.data.redis.connection.ValueEncoding.RedisValueEncoding;
+import org.springframework.data.redis.core.KeyScanOptions;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.test.condition.EnabledOnCommand;
+import org.springframework.data.redis.test.condition.EnabledOnRedisVersion;
import org.springframework.data.redis.test.extension.parametrized.ParameterizedRedisTest;
/**
@@ -115,6 +117,30 @@ public class LettuceReactiveKeyCommandsIntegrationTests extends LettuceReactiveC
.verifyComplete();
}
+ @ParameterizedRedisTest // GH-2089
+ @EnabledOnRedisVersion("6.0")
+ void scanWithType() {
+
+ nativeCommands.set(KEY_1, VALUE_1);
+ nativeCommands.lpush(KEY_2, VALUE_2);
+ nativeCommands.sadd(KEY_3, VALUE_3);
+
+ connection.keyCommands().scan(KeyScanOptions.scanOptions(DataType.STRING).build()) //
+ .as(StepVerifier::create) //
+ .expectNext(KEY_1_BBUFFER) //
+ .verifyComplete();
+
+ connection.keyCommands().scan(KeyScanOptions.scanOptions(DataType.SET).build()) //
+ .as(StepVerifier::create) //
+ .expectNext(KEY_3_BBUFFER) //
+ .verifyComplete();
+
+ connection.keyCommands().scan(KeyScanOptions.scanOptions(DataType.NONE).build()) //
+ .as(StepVerifier::create) //
+ .expectNextCount(3) //
+ .verifyComplete();
+ }
+
@ParameterizedRedisTest // DATAREDIS-525
void randomKeyShouldReturnAnyKey() {