From 8bc235fe2ca642ec6c2e6d12b9b46a686995bae2 Mon Sep 17 00:00:00 2001 From: SanHalacogluImproving <144171266+SanHalacogluImproving@users.noreply.github.com> Date: Fri, 12 Apr 2024 11:47:26 -0700 Subject: [PATCH 1/7] Java: Add command `Zrangestore`. (Sorted Set Group) (#202) --- glide-core/src/protobuf/redis_request.proto | 1 + .../src/main/java/glide/api/BaseClient.java | 23 ++- .../api/commands/SortedSetBaseCommands.java | 65 +++++++ .../glide/api/models/BaseTransaction.java | 64 ++++++- .../api/models/commands/RangeOptions.java | 27 ++- .../test/java/glide/api/RedisClientTest.java | 88 +++++++++ .../glide/api/models/TransactionTests.java | 34 ++++ .../test/java/glide/SharedCommandTests.java | 169 ++++++++++++++++++ .../java/glide/TransactionTestUtilities.java | 2 + 9 files changed, 461 insertions(+), 12 deletions(-) diff --git a/glide-core/src/protobuf/redis_request.proto b/glide-core/src/protobuf/redis_request.proto index d5c6ff8f41..b092eb363e 100644 --- a/glide-core/src/protobuf/redis_request.proto +++ b/glide-core/src/protobuf/redis_request.proto @@ -152,6 +152,7 @@ enum RequestType { ZLexCount = 109; Append = 110; SInterStore = 114; + ZRangeStore = 115; } message Command { diff --git a/java/client/src/main/java/glide/api/BaseClient.java b/java/client/src/main/java/glide/api/BaseClient.java index 9e47cdb5e6..363619d8e3 100644 --- a/java/client/src/main/java/glide/api/BaseClient.java +++ b/java/client/src/main/java/glide/api/BaseClient.java @@ -71,6 +71,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ZPopMin; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByLex; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByRank; +import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByScore; import static redis_request.RedisRequestOuterClass.RequestType.ZScore; import static redis_request.RedisRequestOuterClass.RequestType.Zadd; @@ -810,6 +811,24 @@ public CompletableFuture zlexcount( ZLexCount, new String[] {key, minLex.toArgs(), maxLex.toArgs()}, this::handleLongResponse); } + @Override + public CompletableFuture zrangestore( + @NonNull String destination, + @NonNull String source, + @NonNull RangeQuery rangeQuery, + boolean reverse) { + String[] arguments = + RangeOptions.createZRangeStoreArgs(destination, source, rangeQuery, reverse); + + return commandManager.submitNewCommand(ZRangeStore, arguments, this::handleLongResponse); + } + + @Override + public CompletableFuture zrangestore( + @NonNull String destination, @NonNull String source, @NonNull RangeQuery rangeQuery) { + return this.zrangestore(destination, source, rangeQuery, false); + } + @Override public CompletableFuture xadd(@NonNull String key, @NonNull Map values) { return xadd(key, values, StreamAddOptions.builder().build()); @@ -879,7 +898,7 @@ public CompletableFuture lpushx(@NonNull String key, @NonNull String[] ele @Override public CompletableFuture zrange( @NonNull String key, @NonNull RangeQuery rangeQuery, boolean reverse) { - String[] arguments = RangeOptions.createZrangeArgs(key, rangeQuery, reverse, false); + String[] arguments = RangeOptions.createZRangeArgs(key, rangeQuery, reverse, false); return commandManager.submitNewCommand( Zrange, @@ -895,7 +914,7 @@ public CompletableFuture zrange(@NonNull String key, @NonNull RangeQue @Override public CompletableFuture> zrangeWithScores( @NonNull String key, @NonNull ScoredRangeQuery rangeQuery, boolean reverse) { - String[] arguments = RangeOptions.createZrangeArgs(key, rangeQuery, reverse, true); + String[] arguments = RangeOptions.createZRangeArgs(key, rangeQuery, reverse, true); return commandManager.submitNewCommand(Zrange, arguments, this::handleMapResponse); } diff --git a/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java b/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java index 9bf77b856b..1431439c0e 100644 --- a/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java +++ b/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java @@ -419,6 +419,71 @@ CompletableFuture> zrangeWithScores( */ CompletableFuture> zrangeWithScores(String key, ScoredRangeQuery rangeQuery); + /** + * Stores a specified range of elements from the sorted set at source, into a new + * sorted set at destination. If destination doesn't exist, a new sorted + * set is created; if it exists, it's overwritten.
+ * ZRANGESTORE can perform different types of range queries: by index (rank), by the + * score, or by lexicographical order.
+ * + * @see redis.io for more details. + * @param destination The key for the destination sorted set. + * @param source The key of the source sorted set. + * @param rangeQuery The range query object representing the type of range query to perform.
+ *
    + *
  • For range queries by index (rank), use {@link RangeByIndex}. + *
  • For range queries by lexicographical order, use {@link RangeByLex}. + *
  • For range queries by score, use {@link RangeByScore}. + *
+ * + * @param reverse If true, reverses the sorted set, with index 0 as the + * element with the highest score. + * @return The number of elements in the resulting sorted set. + * @example + *
{@code
+     * RangeByIndex query1 = new RangeByIndex(0, -1); // Query for all members.
+     * Long payload1 = client.zrange("destinationKey", "mySortedSet", query1, true).get();
+     * assert payload1 == 7L;
+     *
+     * RangeByScore query2 = new RangeByScore(InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3)); // Query for members with scores within the range of negative infinity to 3.
+     * Long payload2 = client.zrangestore("destinationKey", "mySortedSet", query2, false).get();
+     * assert payload2 == 5L;
+     * }
+ */ + CompletableFuture zrangestore( + String destination, String source, RangeQuery rangeQuery, boolean reverse); + + /** + * Stores a specified range of elements from the sorted set at source, into a new + * sorted set at destination. If destination doesn't exist, a new sorted + * set is created; if it exists, it's overwritten.
+ * ZRANGESTORE can perform different types of range queries: by index (rank), by the + * score, or by lexicographical order.
+ * + * @see redis.io for more details. + * @param destination The key for the destination sorted set. + * @param source The key of the source sorted set. + * @param rangeQuery The range query object representing the type of range query to perform.
+ *
    + *
  • For range queries by index (rank), use {@link RangeByIndex}. + *
  • For range queries by lexicographical order, use {@link RangeByLex}. + *
  • For range queries by score, use {@link RangeByScore}. + *
+ * + * @return The number of elements in the resulting sorted set. + * @example + *
{@code
+     * RangeByIndex query1 = new RangeByIndex(0, -1); // Query for all members.
+     * Long payload1 = client.zrange("destinationKey", "mySortedSet", query1).get();
+     * assert payload1 == 7L;
+     *
+     * RangeByScore query2 = new RangeByScore(InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3)); // Query for members with scores within the range of negative infinity to 3.
+     * Long payload2 = client.zrangestore("destinationKey", "mySortedSet", query2).get();
+     * assert payload2 == 5L;
+     * }
+ */ + CompletableFuture zrangestore(String destination, String source, RangeQuery rangeQuery); + /** * Returns the rank of member in the sorted set stored at key, with * scores ordered from low to high.
diff --git a/java/client/src/main/java/glide/api/models/BaseTransaction.java b/java/client/src/main/java/glide/api/models/BaseTransaction.java index 42584dc6ef..755a2ad1b9 100644 --- a/java/client/src/main/java/glide/api/models/BaseTransaction.java +++ b/java/client/src/main/java/glide/api/models/BaseTransaction.java @@ -3,7 +3,7 @@ import static glide.api.commands.SortedSetBaseCommands.WITH_SCORES_REDIS_API; import static glide.api.commands.SortedSetBaseCommands.WITH_SCORE_REDIS_API; -import static glide.api.models.commands.RangeOptions.createZrangeArgs; +import static glide.api.models.commands.RangeOptions.createZRangeArgs; import static glide.utils.ArrayTransformUtils.concatenateArrays; import static glide.utils.ArrayTransformUtils.convertMapToKeyValueStringArray; import static glide.utils.ArrayTransformUtils.convertMapToValueKeyStringArray; @@ -83,6 +83,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ZPopMin; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByLex; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByRank; +import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByScore; import static redis_request.RedisRequestOuterClass.RequestType.ZScore; import static redis_request.RedisRequestOuterClass.RequestType.Zadd; @@ -100,6 +101,7 @@ import glide.api.models.commands.RangeOptions.InfScoreBound; import glide.api.models.commands.RangeOptions.LexBoundary; import glide.api.models.commands.RangeOptions.LexRange; +import glide.api.models.commands.RangeOptions; import glide.api.models.commands.RangeOptions.RangeByIndex; import glide.api.models.commands.RangeOptions.RangeByLex; import glide.api.models.commands.RangeOptions.RangeByScore; @@ -1526,6 +1528,30 @@ public T zrankWithScore(@NonNull String key, @NonNull String member) { return getThis(); } + /** + * Stores a specified range of elements from the sorted set at source, into a new + * sorted set at destination. If destination doesn't exist, a new sorted + * set is created; if it exists, it's overwritten.
+ * ZRANGESTORE can perform different types of range queries: by index (rank), by the + * score, or by lexicographical order.
+ * + * @see redis.io for more details. + * @param destination The key for the destination sorted set. + * @param source The key of the source sorted set. + * @param rangeQuery The range query object representing the type of range query to perform.
+ *
    + *
  • For range queries by index (rank), use {@link RangeByIndex}. + *
  • For range queries by lexicographical order, use {@link RangeByLex}. + *
  • For range queries by score, use {@link RangeByScore}. + *
+ * + * @return Command Response - The number of elements in the resulting sorted set. + */ + public T zrangestore( + @NonNull String destination, @NonNull String source, @NonNull RangeQuery rangeQuery) { + return getThis().zrangestore(destination, source, rangeQuery, false); + } + /** * Returns the scores associated with the specified members in the sorted set stored * at key. @@ -1642,6 +1668,38 @@ public T zremrangebyrank(@NonNull String key, long start, long end) { return getThis(); } + /** + * Stores a specified range of elements from the sorted set at source, into a new + * sorted set at destination. If destination doesn't exist, a new sorted + * set is created; if it exists, it's overwritten.
+ * ZRANGESTORE can perform different types of range queries: by index (rank), by the + * score, or by lexicographical order.
+ * + * @see redis.io for more details. + * @param destination The key for the destination sorted set. + * @param source The key of the source sorted set. + * @param rangeQuery The range query object representing the type of range query to perform.
+ *
    + *
  • For range queries by index (rank), use {@link RangeByIndex}. + *
  • For range queries by lexicographical order, use {@link RangeByLex}. + *
  • For range queries by score, use {@link RangeByScore}. + *
+ * + * @param reverse If true, reverses the sorted set, with index 0 as the + * element with the highest score. + * @return Command Response - The number of elements in the resulting sorted set. + */ + public T zrangestore( + @NonNull String destination, + @NonNull String source, + @NonNull RangeQuery rangeQuery, + boolean reverse) { + ArgsArray commandArgs = + buildArgs(RangeOptions.createZRangeStoreArgs(destination, source, rangeQuery, reverse)); + protobufTransaction.addCommands(buildCommand(ZRangeStore, commandArgs)); + return getThis(); + } + /** * Removes all elements in the sorted set stored at key with a lexicographical order * between minLex and maxLex. @@ -1927,7 +1985,7 @@ public T blpop(@NonNull String[] keys, double timeout) { * array. */ public T zrange(@NonNull String key, @NonNull RangeQuery rangeQuery, boolean reverse) { - ArgsArray commandArgs = buildArgs(createZrangeArgs(key, rangeQuery, reverse, false)); + ArgsArray commandArgs = buildArgs(createZRangeArgs(key, rangeQuery, reverse, false)); protobufTransaction.addCommands(buildCommand(Zrange, commandArgs)); return getThis(); } @@ -1975,7 +2033,7 @@ public T zrange(@NonNull String key, @NonNull RangeQuery rangeQuery) { */ public T zrangeWithScores( @NonNull String key, @NonNull ScoredRangeQuery rangeQuery, boolean reverse) { - ArgsArray commandArgs = buildArgs(createZrangeArgs(key, rangeQuery, reverse, true)); + ArgsArray commandArgs = buildArgs(createZRangeArgs(key, rangeQuery, reverse, true)); protobufTransaction.addCommands(buildCommand(Zrange, commandArgs)); return getThis(); } diff --git a/java/client/src/main/java/glide/api/models/commands/RangeOptions.java b/java/client/src/main/java/glide/api/models/commands/RangeOptions.java index afe6478e82..6d696d2f06 100644 --- a/java/client/src/main/java/glide/api/models/commands/RangeOptions.java +++ b/java/client/src/main/java/glide/api/models/commands/RangeOptions.java @@ -13,7 +13,7 @@ * Arguments for {@link SortedSetBaseCommands#zcount}, {@link * SortedSetBaseCommands#zremrangebyrank}, {@link SortedSetBaseCommands#zremrangebylex(String, * LexRange, LexRange)}, {@link SortedSetBaseCommands#zremrangebyscore}, {@link - * SortedSetBaseCommands#zrange}, {@link SortedSetBaseCommands#zrangeWithScores}, and {@link + * SortedSetBaseCommands#zrange}, {@link SortedSetBaseCommands#zrangestore}, {@link SortedSetBaseCommands#zrangeWithScores}, and {@link * SortedSetBaseCommands#zlexcount} * * @see redis.io @@ -21,6 +21,7 @@ * @see redis.io * @see redis.io * @see redis.io + * @see redis.io * @see redis.io */ public class RangeOptions { @@ -298,9 +299,25 @@ public RangeByScore( } } - public static String[] createZrangeArgs( + public static String[] createZRangeArgs( String key, RangeQuery rangeQuery, boolean reverse, boolean withScores) { - String[] arguments = new String[] {key, rangeQuery.getStart(), rangeQuery.getEnd()}; + String[] arguments = + concatenateArrays(new String[] {key}, createZRangeBaseArgs(rangeQuery, reverse)); + if (withScores) { + arguments = concatenateArrays(arguments, new String[] {WITH_SCORES_REDIS_API}); + } + + return arguments; + } + + public static String[] createZRangeStoreArgs( + String destination, String source, RangeQuery rangeQuery, boolean reverse) { + return concatenateArrays( + new String[] {destination, source}, createZRangeBaseArgs(rangeQuery, reverse)); + } + + private static String[] createZRangeBaseArgs(RangeQuery rangeQuery, boolean reverse) { + String[] arguments = new String[] {rangeQuery.getStart(), rangeQuery.getEnd()}; if (rangeQuery instanceof RangeByScore) { arguments = concatenateArrays(arguments, new String[] {"BYSCORE"}); @@ -323,10 +340,6 @@ public static String[] createZrangeArgs( }); } - if (withScores) { - arguments = concatenateArrays(arguments, new String[] {WITH_SCORES_REDIS_API}); - } - return arguments; } } diff --git a/java/client/src/test/java/glide/api/RedisClientTest.java b/java/client/src/test/java/glide/api/RedisClientTest.java index 862f76f21b..734f5ac3df 100644 --- a/java/client/src/test/java/glide/api/RedisClientTest.java +++ b/java/client/src/test/java/glide/api/RedisClientTest.java @@ -104,6 +104,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ZPopMin; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByLex; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByRank; +import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByScore; import static redis_request.RedisRequestOuterClass.RequestType.ZScore; import static redis_request.RedisRequestOuterClass.RequestType.Zadd; @@ -2584,6 +2585,93 @@ public void zlexcount_returns_success() { assertEquals(value, payload); } + @SneakyThrows + @Test + public void zrangestore_by_lex_returns_success() { + // setup + String source = "testSourceKey"; + String destination = "testDestinationKey"; + RangeByLex rangeByLex = + new RangeByLex(InfLexBound.NEGATIVE_INFINITY, new LexBoundary("c", false)); + String[] arguments = + new String[] {source, destination, rangeByLex.getStart(), rangeByLex.getEnd(), "BYLEX"}; + Long value = 2L; + + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(value); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(ZRangeStore), eq(arguments), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.zrangestore(source, destination, rangeByLex); + Long payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(value, payload); + } + + @SneakyThrows + @Test + public void zrangestore_by_index_returns_success() { + // setup + String source = "testSourceKey"; + String destination = "testDestinationKey"; + RangeByIndex rangeByIndex = new RangeByIndex(0, 1); + String[] arguments = + new String[] {source, destination, rangeByIndex.getStart(), rangeByIndex.getEnd()}; + Long value = 2L; + + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(value); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(ZRangeStore), eq(arguments), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.zrangestore(source, destination, rangeByIndex); + Long payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(value, payload); + } + + @SneakyThrows + @Test + public void zrangestore_by_score_with_reverse_returns_success() { + // setup + String source = "testSourceKey"; + String destination = "testDestinationKey"; + RangeByScore rangeByScore = + new RangeByScore(new ScoreBoundary(3, false), InfScoreBound.NEGATIVE_INFINITY); + boolean reversed = true; + String[] arguments = + new String[] { + source, destination, rangeByScore.getStart(), rangeByScore.getEnd(), "BYSCORE", "REV" + }; + Long value = 2L; + + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(value); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(ZRangeStore), eq(arguments), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = + service.zrangestore(source, destination, rangeByScore, reversed); + Long payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(value, payload); + } + @SneakyThrows @Test public void xadd_returns_success() { diff --git a/java/client/src/test/java/glide/api/models/TransactionTests.java b/java/client/src/test/java/glide/api/models/TransactionTests.java index f104d6ea10..eee3bd1b61 100644 --- a/java/client/src/test/java/glide/api/models/TransactionTests.java +++ b/java/client/src/test/java/glide/api/models/TransactionTests.java @@ -86,6 +86,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ZMScore; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMax; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMin; +import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByLex; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByRank; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByScore; @@ -103,6 +104,7 @@ import glide.api.models.commands.RangeOptions.InfScoreBound; import glide.api.models.commands.RangeOptions.LexBoundary; import glide.api.models.commands.RangeOptions.Limit; +import glide.api.models.commands.RangeOptions.RangeByIndex; import glide.api.models.commands.RangeOptions.RangeByScore; import glide.api.models.commands.RangeOptions.ScoreBoundary; import glide.api.models.commands.SetOptions; @@ -401,6 +403,38 @@ public void transaction_builds_protobuf_request(BaseTransaction transaction) transaction.zlexcount("key", new LexBoundary("c", false), InfLexBound.POSITIVE_INFINITY); results.add(Pair.of(ZLexCount, buildArgs("key", "(c", "+"))); + transaction.zrangestore( + "destination", + "source", + new RangeByScore( + InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3, false), new Limit(1, 2)), + true); + results.add( + Pair.of( + ZRangeStore, + ArgsArray.newBuilder() + .addArgs("destination") + .addArgs("source") + .addArgs("-inf") + .addArgs("(3.0") + .addArgs("BYSCORE") + .addArgs("REV") + .addArgs("LIMIT") + .addArgs("1") + .addArgs("2") + .build())); + + transaction.zrangestore("destination", "source", new RangeByIndex(2, 3)); + results.add( + Pair.of( + ZRangeStore, + ArgsArray.newBuilder() + .addArgs("destination") + .addArgs("source") + .addArgs("2") + .addArgs("3") + .build())); + transaction.xadd("key", Map.of("field1", "foo1")); results.add(Pair.of(XAdd, buildArgs("key", "*", "field1", "foo1"))); diff --git a/java/integTest/src/test/java/glide/SharedCommandTests.java b/java/integTest/src/test/java/glide/SharedCommandTests.java index 99acee473a..37033e116c 100644 --- a/java/integTest/src/test/java/glide/SharedCommandTests.java +++ b/java/integTest/src/test/java/glide/SharedCommandTests.java @@ -1706,6 +1706,175 @@ public void zlexcount(BaseClient client) { @SneakyThrows @ParameterizedTest(autoCloseArguments = false) @MethodSource("getClients") + public void zrangestore_by_index(BaseClient client) { + String key = "{testKey}:" + UUID.randomUUID(); + String destination = "{testKey}:" + UUID.randomUUID(); + String source = "{testKey}:" + UUID.randomUUID(); + Map membersScores = Map.of("one", 1.0, "two", 2.0, "three", 3.0); + assertEquals(3, client.zadd(source, membersScores).get()); + + // Full range. + assertEquals(3, client.zrangestore(destination, source, new RangeByIndex(0, -1)).get()); + assertEquals( + Map.of("one", 1.0, "two", 2.0, "three", 3.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Range from rank 0 to 1. In descending order of scores. + assertEquals(2, client.zrangestore(destination, source, new RangeByIndex(0, 1), true).get()); + assertEquals( + Map.of("three", 3.0, "two", 2.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Incorrect range as start > stop. + assertEquals(0, client.zrangestore(destination, source, new RangeByIndex(3, 1)).get()); + assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Non-existing source. + assertEquals(0, client.zrangestore(destination, key, new RangeByIndex(0, -1)).get()); + assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Key exists, but it is not a set + assertEquals(OK, client.set(key, "value").get()); + ExecutionException executionException = + assertThrows( + ExecutionException.class, + () -> client.zrangestore(destination, key, new RangeByIndex(3, 1)).get()); + assertTrue(executionException.getCause() instanceof RequestException); + } + + @SneakyThrows + @ParameterizedTest + @MethodSource("getClients") + public void zrangestore_by_score(BaseClient client) { + String key = "{testKey}:" + UUID.randomUUID(); + String destination = "{testKey}:" + UUID.randomUUID(); + String source = "{testKey}:" + UUID.randomUUID(); + Map membersScores = Map.of("one", 1.0, "two", 2.0, "three", 3.0); + assertEquals(3, client.zadd(source, membersScores).get()); + + // Range from negative infinity to 3 (exclusive). + RangeByScore query = + new RangeByScore(InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3, false)); + assertEquals(2, client.zrangestore(destination, source, query).get()); + assertEquals( + Map.of("one", 1.0, "two", 2.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Range from 1 (inclusive) to positive infinity. + query = new RangeByScore(new ScoreBoundary(1), InfScoreBound.POSITIVE_INFINITY); + assertEquals(3, client.zrangestore(destination, source, query).get()); + assertEquals( + Map.of("one", 1.0, "two", 2.0, "three", 3.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Range from negative to positive infinity. Limited to ranks 1 to 2. + query = + new RangeByScore( + InfScoreBound.NEGATIVE_INFINITY, InfScoreBound.POSITIVE_INFINITY, new Limit(1, 2)); + assertEquals(2, client.zrangestore(destination, source, query).get()); + assertEquals( + Map.of("two", 2.0, "three", 3.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Range from positive to negative infinity with rev set to true.Limited to ranks 1 to 2. + query = + new RangeByScore( + InfScoreBound.POSITIVE_INFINITY, InfScoreBound.NEGATIVE_INFINITY, new Limit(1, 2)); + assertEquals(2, client.zrangestore(destination, source, query, true).get()); + assertEquals( + Map.of("two", 2.0, "one", 1.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Incorrect range as start > stop. + query = new RangeByScore(new ScoreBoundary(3, false), InfScoreBound.NEGATIVE_INFINITY); + assertEquals(0, client.zrangestore(destination, source, query).get()); + assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Non-existent source. + query = new RangeByScore(InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3, false)); + assertEquals(0, client.zrangestore(destination, key, query).get()); + assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Key exists, but it is not a set + assertEquals(OK, client.set(key, "value").get()); + ExecutionException executionException = + assertThrows( + ExecutionException.class, + () -> + client + .zrangestore( + destination, + key, + new RangeByScore(new ScoreBoundary(0), new ScoreBoundary(3))) + .get()); + assertTrue(executionException.getCause() instanceof RequestException); + } + + @SneakyThrows + @ParameterizedTest + @MethodSource("getClients") + public void zrangestore_by_lex(BaseClient client) { + String key = "{testKey}:" + UUID.randomUUID(); + String destination = "{testKey}:" + UUID.randomUUID(); + String source = "{testKey}:" + UUID.randomUUID(); + Map membersScores = Map.of("a", 1.0, "b", 2.0, "c", 3.0); + assertEquals(3, client.zadd(source, membersScores).get()); + + // Range from negative infinity to "c" (exclusive). + RangeByLex query = new RangeByLex(InfLexBound.NEGATIVE_INFINITY, new LexBoundary("c", false)); + assertEquals(2, client.zrangestore(destination, source, query).get()); + assertEquals( + Map.of("a", 1.0, "b", 2.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Range from "a" (inclusive) to positive infinity. + query = new RangeByLex(new LexBoundary("a"), InfLexBound.POSITIVE_INFINITY); + assertEquals(3, client.zrangestore(destination, source, query).get()); + assertEquals( + Map.of("a", 1.0, "b", 2.0, "c", 3.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Range from negative to positive infinity. Limited to ranks 1 to 2. + query = + new RangeByLex( + InfLexBound.NEGATIVE_INFINITY, InfLexBound.POSITIVE_INFINITY, new Limit(1, 2)); + assertEquals(2, client.zrangestore(destination, source, query).get()); + assertEquals( + Map.of("b", 2.0, "c", 3.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Range from positive to negative infinity with rev set to true.Limited to ranks 1 to 2. + query = + new RangeByLex( + InfLexBound.POSITIVE_INFINITY, InfLexBound.NEGATIVE_INFINITY, new Limit(1, 2)); + assertEquals(2, client.zrangestore(destination, source, query, true).get()); + assertEquals( + Map.of("b", 2.0, "a", 1.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Non-existent source. + query = new RangeByLex(InfLexBound.NEGATIVE_INFINITY, new LexBoundary("c", false)); + assertEquals(0, client.zrangestore(destination, key, query).get()); + assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Key exists, but it is not a set + assertEquals(OK, client.set(key, "value").get()); + ExecutionException executionException = + assertThrows( + ExecutionException.class, + () -> + client + .zrangestore( + destination, + key, + new RangeByLex(new LexBoundary("a"), new LexBoundary("c"))) + .get()); + assertTrue(executionException.getCause() instanceof RequestException); + } + + @SneakyThrows + @ParameterizedTest + @MethodSource("getClients") public void xadd(BaseClient client) { String key = UUID.randomUUID().toString(); String field1 = UUID.randomUUID().toString(); diff --git a/java/integTest/src/test/java/glide/TransactionTestUtilities.java b/java/integTest/src/test/java/glide/TransactionTestUtilities.java index 149a3455df..5bdee80f8b 100644 --- a/java/integTest/src/test/java/glide/TransactionTestUtilities.java +++ b/java/integTest/src/test/java/glide/TransactionTestUtilities.java @@ -115,6 +115,7 @@ public static BaseTransaction transactionTest(BaseTransaction baseTransact baseTransaction.zmscore(key8, new String[] {"two", "three"}); baseTransaction.zrange(key8, new RangeByIndex(0, 1)); baseTransaction.zrangeWithScores(key8, new RangeByIndex(0, 1)); + baseTransaction.zrangestore(key8, key8, new RangeByIndex(0, -1)); baseTransaction.zscore(key8, "two"); baseTransaction.zcount(key8, new ScoreBoundary(2, true), InfScoreBound.POSITIVE_INFINITY); baseTransaction.zlexcount(key8, new LexBoundary("a", true), InfLexBound.POSITIVE_INFINITY); @@ -219,6 +220,7 @@ public static Object[] transactionTestResult() { new Double[] {2.0, 3.0}, // zmscore(key8, new String[] {"two", "three"}) new String[] {"two", "three"}, // zrange Map.of("two", 2.0, "three", 3.0), // zrangeWithScores + 2L, // zrangestore(key8, key8, new RangeByIndex(0, -1)) 2.0, // zscore(key8, "two") 2L, // zcount(key8, new ScoreBoundary(2, true), InfScoreBound.POSITIVE_INFINITY) 2L, // zlexcount(key8, new LexBoundary("a", true), InfLexBound.POSITIVE_INFINITY) From e61007b82b011b84ebb513dd4c24b43fc29885a2 Mon Sep 17 00:00:00 2001 From: SanHalacogluImproving Date: Fri, 12 Apr 2024 12:11:52 -0700 Subject: [PATCH 2/7] Rebase + Spotless. --- glide-core/src/request_type.rs | 3 ++ .../src/main/java/glide/api/BaseClient.java | 1 + .../glide/api/models/BaseTransaction.java | 13 ++++--- .../test/java/glide/api/RedisClientTest.java | 23 ++++++------ .../glide/api/models/TransactionTests.java | 37 +++++-------------- 5 files changed, 33 insertions(+), 44 deletions(-) diff --git a/glide-core/src/request_type.rs b/glide-core/src/request_type.rs index f0ea78a145..c6f24547de 100644 --- a/glide-core/src/request_type.rs +++ b/glide-core/src/request_type.rs @@ -120,6 +120,7 @@ pub enum RequestType { ZLexCount = 109, Append = 110, SInterStore = 114, + ZRangeStore = 115, } fn get_two_word_command(first: &str, second: &str) -> Cmd { @@ -243,6 +244,7 @@ impl From<::protobuf::EnumOrUnknown> for RequestType { ProtobufRequestType::ZLexCount => RequestType::ZLexCount, ProtobufRequestType::Append => RequestType::Append, ProtobufRequestType::SInterStore => RequestType::SInterStore, + ProtobufRequestType::ZRangeStore => RequestType::ZRangeStore, } } } @@ -362,6 +364,7 @@ impl RequestType { RequestType::ZLexCount => Some(cmd("ZLEXCOUNT")), RequestType::Append => Some(cmd("APPEND")), RequestType::SInterStore => Some(cmd("SINTERSTORE")), + RequestType::ZRangeStore => Some(cmd("ZRANGESTORE")), } } } diff --git a/java/client/src/main/java/glide/api/BaseClient.java b/java/client/src/main/java/glide/api/BaseClient.java index 363619d8e3..9bc543d3be 100644 --- a/java/client/src/main/java/glide/api/BaseClient.java +++ b/java/client/src/main/java/glide/api/BaseClient.java @@ -69,6 +69,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ZMScore; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMax; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMin; +import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByLex; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByRank; import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; diff --git a/java/client/src/main/java/glide/api/models/BaseTransaction.java b/java/client/src/main/java/glide/api/models/BaseTransaction.java index 755a2ad1b9..71e6680770 100644 --- a/java/client/src/main/java/glide/api/models/BaseTransaction.java +++ b/java/client/src/main/java/glide/api/models/BaseTransaction.java @@ -81,6 +81,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ZMScore; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMax; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMin; +import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByLex; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByRank; import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; @@ -97,11 +98,11 @@ import glide.api.models.commands.InfoOptions; import glide.api.models.commands.InfoOptions.Section; import glide.api.models.commands.LInsertOptions.InsertPosition; +import glide.api.models.commands.RangeOptions; import glide.api.models.commands.RangeOptions.InfLexBound; import glide.api.models.commands.RangeOptions.InfScoreBound; import glide.api.models.commands.RangeOptions.LexBoundary; import glide.api.models.commands.RangeOptions.LexRange; -import glide.api.models.commands.RangeOptions; import glide.api.models.commands.RangeOptions.RangeByIndex; import glide.api.models.commands.RangeOptions.RangeByLex; import glide.api.models.commands.RangeOptions.RangeByScore; @@ -1690,12 +1691,12 @@ public T zremrangebyrank(@NonNull String key, long start, long end) { * @return Command Response - The number of elements in the resulting sorted set. */ public T zrangestore( - @NonNull String destination, - @NonNull String source, - @NonNull RangeQuery rangeQuery, - boolean reverse) { + @NonNull String destination, + @NonNull String source, + @NonNull RangeQuery rangeQuery, + boolean reverse) { ArgsArray commandArgs = - buildArgs(RangeOptions.createZRangeStoreArgs(destination, source, rangeQuery, reverse)); + buildArgs(RangeOptions.createZRangeStoreArgs(destination, source, rangeQuery, reverse)); protobufTransaction.addCommands(buildCommand(ZRangeStore, commandArgs)); return getThis(); } diff --git a/java/client/src/test/java/glide/api/RedisClientTest.java b/java/client/src/test/java/glide/api/RedisClientTest.java index 734f5ac3df..27b55ddc86 100644 --- a/java/client/src/test/java/glide/api/RedisClientTest.java +++ b/java/client/src/test/java/glide/api/RedisClientTest.java @@ -102,6 +102,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ZMScore; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMax; import static redis_request.RedisRequestOuterClass.RequestType.ZPopMin; +import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByLex; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByRank; import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; @@ -2592,9 +2593,9 @@ public void zrangestore_by_lex_returns_success() { String source = "testSourceKey"; String destination = "testDestinationKey"; RangeByLex rangeByLex = - new RangeByLex(InfLexBound.NEGATIVE_INFINITY, new LexBoundary("c", false)); + new RangeByLex(InfLexBound.NEGATIVE_INFINITY, new LexBoundary("c", false)); String[] arguments = - new String[] {source, destination, rangeByLex.getStart(), rangeByLex.getEnd(), "BYLEX"}; + new String[] {source, destination, rangeByLex.getStart(), rangeByLex.getEnd(), "BYLEX"}; Long value = 2L; CompletableFuture testResponse = new CompletableFuture<>(); @@ -2602,7 +2603,7 @@ public void zrangestore_by_lex_returns_success() { // match on protobuf request when(commandManager.submitNewCommand(eq(ZRangeStore), eq(arguments), any())) - .thenReturn(testResponse); + .thenReturn(testResponse); // exercise CompletableFuture response = service.zrangestore(source, destination, rangeByLex); @@ -2621,7 +2622,7 @@ public void zrangestore_by_index_returns_success() { String destination = "testDestinationKey"; RangeByIndex rangeByIndex = new RangeByIndex(0, 1); String[] arguments = - new String[] {source, destination, rangeByIndex.getStart(), rangeByIndex.getEnd()}; + new String[] {source, destination, rangeByIndex.getStart(), rangeByIndex.getEnd()}; Long value = 2L; CompletableFuture testResponse = new CompletableFuture<>(); @@ -2629,7 +2630,7 @@ public void zrangestore_by_index_returns_success() { // match on protobuf request when(commandManager.submitNewCommand(eq(ZRangeStore), eq(arguments), any())) - .thenReturn(testResponse); + .thenReturn(testResponse); // exercise CompletableFuture response = service.zrangestore(source, destination, rangeByIndex); @@ -2647,12 +2648,12 @@ public void zrangestore_by_score_with_reverse_returns_success() { String source = "testSourceKey"; String destination = "testDestinationKey"; RangeByScore rangeByScore = - new RangeByScore(new ScoreBoundary(3, false), InfScoreBound.NEGATIVE_INFINITY); + new RangeByScore(new ScoreBoundary(3, false), InfScoreBound.NEGATIVE_INFINITY); boolean reversed = true; String[] arguments = - new String[] { - source, destination, rangeByScore.getStart(), rangeByScore.getEnd(), "BYSCORE", "REV" - }; + new String[] { + source, destination, rangeByScore.getStart(), rangeByScore.getEnd(), "BYSCORE", "REV" + }; Long value = 2L; CompletableFuture testResponse = new CompletableFuture<>(); @@ -2660,11 +2661,11 @@ public void zrangestore_by_score_with_reverse_returns_success() { // match on protobuf request when(commandManager.submitNewCommand(eq(ZRangeStore), eq(arguments), any())) - .thenReturn(testResponse); + .thenReturn(testResponse); // exercise CompletableFuture response = - service.zrangestore(source, destination, rangeByScore, reversed); + service.zrangestore(source, destination, rangeByScore, reversed); Long payload = response.get(); // verify diff --git a/java/client/src/test/java/glide/api/models/TransactionTests.java b/java/client/src/test/java/glide/api/models/TransactionTests.java index eee3bd1b61..113506b5ac 100644 --- a/java/client/src/test/java/glide/api/models/TransactionTests.java +++ b/java/client/src/test/java/glide/api/models/TransactionTests.java @@ -404,36 +404,19 @@ public void transaction_builds_protobuf_request(BaseTransaction transaction) results.add(Pair.of(ZLexCount, buildArgs("key", "(c", "+"))); transaction.zrangestore( - "destination", - "source", - new RangeByScore( - InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3, false), new Limit(1, 2)), - true); + "destination", + "source", + new RangeByScore( + InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3, false), new Limit(1, 2)), + true); results.add( - Pair.of( - ZRangeStore, - ArgsArray.newBuilder() - .addArgs("destination") - .addArgs("source") - .addArgs("-inf") - .addArgs("(3.0") - .addArgs("BYSCORE") - .addArgs("REV") - .addArgs("LIMIT") - .addArgs("1") - .addArgs("2") - .build())); + Pair.of( + ZRangeStore, + buildArgs( + "destination", "source", "-inf", "(3.0", "BYSCORE", "REV", "LIMIT", "1", "2"))); transaction.zrangestore("destination", "source", new RangeByIndex(2, 3)); - results.add( - Pair.of( - ZRangeStore, - ArgsArray.newBuilder() - .addArgs("destination") - .addArgs("source") - .addArgs("2") - .addArgs("3") - .build())); + results.add(Pair.of(ZRangeStore, buildArgs("destination", "source", "2", "3"))); transaction.xadd("key", Map.of("field1", "foo1")); results.add(Pair.of(XAdd, buildArgs("key", "*", "field1", "foo1"))); From ae72b26d5b143aed34e8f01f4d4df59a2b773079 Mon Sep 17 00:00:00 2001 From: SanHalacogluImproving Date: Mon, 15 Apr 2024 15:46:56 -0700 Subject: [PATCH 3/7] Java: Add `Zinterstore` command. --- .../api/commands/SortedSetBaseCommands.java | 8 +--- .../glide/api/models/BaseTransaction.java | 48 +++++++++---------- .../test/java/glide/SharedCommandTests.java | 39 +++++++++++++++ 3 files changed, 65 insertions(+), 30 deletions(-) diff --git a/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java b/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java index 1431439c0e..dcd2fce4d5 100644 --- a/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java +++ b/java/client/src/main/java/glide/api/commands/SortedSetBaseCommands.java @@ -423,8 +423,6 @@ CompletableFuture> zrangeWithScores( * Stores a specified range of elements from the sorted set at source, into a new * sorted set at destination. If destination doesn't exist, a new sorted * set is created; if it exists, it's overwritten.
- * ZRANGESTORE can perform different types of range queries: by index (rank), by the - * score, or by lexicographical order.
* * @see redis.io for more details. * @param destination The key for the destination sorted set. @@ -442,7 +440,7 @@ CompletableFuture> zrangeWithScores( * @example *
{@code
      * RangeByIndex query1 = new RangeByIndex(0, -1); // Query for all members.
-     * Long payload1 = client.zrange("destinationKey", "mySortedSet", query1, true).get();
+     * Long payload1 = client.zrangestore("destinationKey", "mySortedSet", query1, true).get();
      * assert payload1 == 7L;
      *
      * RangeByScore query2 = new RangeByScore(InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3)); // Query for members with scores within the range of negative infinity to 3.
@@ -457,8 +455,6 @@ CompletableFuture zrangestore(
      * Stores a specified range of elements from the sorted set at source, into a new
      * sorted set at destination. If destination doesn't exist, a new sorted
      * set is created; if it exists, it's overwritten.
- * ZRANGESTORE can perform different types of range queries: by index (rank), by the - * score, or by lexicographical order.
* * @see redis.io for more details. * @param destination The key for the destination sorted set. @@ -474,7 +470,7 @@ CompletableFuture zrangestore( * @example *
{@code
      * RangeByIndex query1 = new RangeByIndex(0, -1); // Query for all members.
-     * Long payload1 = client.zrange("destinationKey", "mySortedSet", query1).get();
+     * Long payload1 = client.zrangestore("destinationKey", "mySortedSet", query1).get();
      * assert payload1 == 7L;
      *
      * RangeByScore query2 = new RangeByScore(InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3)); // Query for members with scores within the range of negative infinity to 3.
diff --git a/java/client/src/main/java/glide/api/models/BaseTransaction.java b/java/client/src/main/java/glide/api/models/BaseTransaction.java
index 71e6680770..a88213f43a 100644
--- a/java/client/src/main/java/glide/api/models/BaseTransaction.java
+++ b/java/client/src/main/java/glide/api/models/BaseTransaction.java
@@ -1529,30 +1529,6 @@ public T zrankWithScore(@NonNull String key, @NonNull String member) {
         return getThis();
     }
 
-    /**
-     * Stores a specified range of elements from the sorted set at source, into a new
-     * sorted set at destination. If destination doesn't exist, a new sorted
-     * set is created; if it exists, it's overwritten.
- * ZRANGESTORE can perform different types of range queries: by index (rank), by the - * score, or by lexicographical order.
- * - * @see redis.io for more details. - * @param destination The key for the destination sorted set. - * @param source The key of the source sorted set. - * @param rangeQuery The range query object representing the type of range query to perform.
- *
    - *
  • For range queries by index (rank), use {@link RangeByIndex}. - *
  • For range queries by lexicographical order, use {@link RangeByLex}. - *
  • For range queries by score, use {@link RangeByScore}. - *
- * - * @return Command Response - The number of elements in the resulting sorted set. - */ - public T zrangestore( - @NonNull String destination, @NonNull String source, @NonNull RangeQuery rangeQuery) { - return getThis().zrangestore(destination, source, rangeQuery, false); - } - /** * Returns the scores associated with the specified members in the sorted set stored * at key. @@ -1701,6 +1677,30 @@ public T zrangestore( return getThis(); } + /** + * Stores a specified range of elements from the sorted set at source, into a new + * sorted set at destination. If destination doesn't exist, a new sorted + * set is created; if it exists, it's overwritten.
+ * ZRANGESTORE can perform different types of range queries: by index (rank), by the + * score, or by lexicographical order.
+ * + * @see redis.io for more details. + * @param destination The key for the destination sorted set. + * @param source The key of the source sorted set. + * @param rangeQuery The range query object representing the type of range query to perform.
+ *
    + *
  • For range queries by index (rank), use {@link RangeByIndex}. + *
  • For range queries by lexicographical order, use {@link RangeByLex}. + *
  • For range queries by score, use {@link RangeByScore}. + *
+ * + * @return Command Response - The number of elements in the resulting sorted set. + */ + public T zrangestore( + @NonNull String destination, @NonNull String source, @NonNull RangeQuery rangeQuery) { + return getThis().zrangestore(destination, source, rangeQuery, false); + } + /** * Removes all elements in the sorted set stored at key with a lexicographical order * between minLex and maxLex. diff --git a/java/integTest/src/test/java/glide/SharedCommandTests.java b/java/integTest/src/test/java/glide/SharedCommandTests.java index 37033e116c..a909b8a825 100644 --- a/java/integTest/src/test/java/glide/SharedCommandTests.java +++ b/java/integTest/src/test/java/glide/SharedCommandTests.java @@ -1657,6 +1657,45 @@ public void zremrangebyscore(BaseClient client) { assertTrue(executionException.getCause() instanceof RequestException); } + @SneakyThrows + @ParameterizedTest + @MethodSource("getClients") + public void zrangestore_by_index(BaseClient client) { + String key = "{testKey}:" + UUID.randomUUID(); + String destination = "{testKey}:" + UUID.randomUUID(); + String source = "{testKey}:" + UUID.randomUUID(); + Map membersScores = Map.of("one", 1.0, "two", 2.0, "three", 3.0); + assertEquals(3, client.zadd(source, membersScores).get()); + + // Full range. + assertEquals(3, client.zrangestore(destination, source, new RangeByIndex(0, -1)).get()); + assertEquals( + Map.of("one", 1.0, "two", 2.0, "three", 3.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Range from rank 0 to 1. In descending order of scores. + assertEquals(2, client.zrangestore(destination, source, new RangeByIndex(0, 1), true).get()); + assertEquals( + Map.of("three", 3.0, "two", 2.0), + client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Incorrect range as start > stop. + assertEquals(0, client.zrangestore(destination, source, new RangeByIndex(3, 1)).get()); + assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Non-existing source. + assertEquals(0, client.zrangestore(destination, key, new RangeByIndex(0, -1)).get()); + assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); + + // Key exists, but it is not a set + assertEquals(OK, client.set(key, "value").get()); + ExecutionException executionException = + assertThrows( + ExecutionException.class, + () -> client.zrangestore(destination, key, new RangeByIndex(3, 1)).get()); + assertTrue(executionException.getCause() instanceof RequestException); + } + @SneakyThrows @ParameterizedTest(autoCloseArguments = false) @MethodSource("getClients") From b5a87f26192e09ca657d263fae751531ff01d3ca Mon Sep 17 00:00:00 2001 From: SanHalacogluImproving Date: Mon, 15 Apr 2024 15:53:21 -0700 Subject: [PATCH 4/7] Rebase + Spotless. --- java/client/src/main/java/glide/api/BaseClient.java | 1 - .../src/main/java/glide/api/models/BaseTransaction.java | 1 - .../src/main/java/glide/api/models/commands/RangeOptions.java | 4 ++-- java/client/src/test/java/glide/api/RedisClientTest.java | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/java/client/src/main/java/glide/api/BaseClient.java b/java/client/src/main/java/glide/api/BaseClient.java index 9bc543d3be..8fba1b4bb1 100644 --- a/java/client/src/main/java/glide/api/BaseClient.java +++ b/java/client/src/main/java/glide/api/BaseClient.java @@ -72,7 +72,6 @@ import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByLex; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByRank; -import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByScore; import static redis_request.RedisRequestOuterClass.RequestType.ZScore; import static redis_request.RedisRequestOuterClass.RequestType.Zadd; diff --git a/java/client/src/main/java/glide/api/models/BaseTransaction.java b/java/client/src/main/java/glide/api/models/BaseTransaction.java index a88213f43a..bcf4d42786 100644 --- a/java/client/src/main/java/glide/api/models/BaseTransaction.java +++ b/java/client/src/main/java/glide/api/models/BaseTransaction.java @@ -84,7 +84,6 @@ import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByLex; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByRank; -import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByScore; import static redis_request.RedisRequestOuterClass.RequestType.ZScore; import static redis_request.RedisRequestOuterClass.RequestType.Zadd; diff --git a/java/client/src/main/java/glide/api/models/commands/RangeOptions.java b/java/client/src/main/java/glide/api/models/commands/RangeOptions.java index 6d696d2f06..179145eaaf 100644 --- a/java/client/src/main/java/glide/api/models/commands/RangeOptions.java +++ b/java/client/src/main/java/glide/api/models/commands/RangeOptions.java @@ -13,8 +13,8 @@ * Arguments for {@link SortedSetBaseCommands#zcount}, {@link * SortedSetBaseCommands#zremrangebyrank}, {@link SortedSetBaseCommands#zremrangebylex(String, * LexRange, LexRange)}, {@link SortedSetBaseCommands#zremrangebyscore}, {@link - * SortedSetBaseCommands#zrange}, {@link SortedSetBaseCommands#zrangestore}, {@link SortedSetBaseCommands#zrangeWithScores}, and {@link - * SortedSetBaseCommands#zlexcount} + * SortedSetBaseCommands#zrange}, {@link SortedSetBaseCommands#zrangestore}, {@link + * SortedSetBaseCommands#zrangeWithScores}, and {@link SortedSetBaseCommands#zlexcount} * * @see redis.io * @see redis.io diff --git a/java/client/src/test/java/glide/api/RedisClientTest.java b/java/client/src/test/java/glide/api/RedisClientTest.java index 27b55ddc86..ab0eba3bee 100644 --- a/java/client/src/test/java/glide/api/RedisClientTest.java +++ b/java/client/src/test/java/glide/api/RedisClientTest.java @@ -105,7 +105,6 @@ import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByLex; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByRank; -import static redis_request.RedisRequestOuterClass.RequestType.ZRangeStore; import static redis_request.RedisRequestOuterClass.RequestType.ZRemRangeByScore; import static redis_request.RedisRequestOuterClass.RequestType.ZScore; import static redis_request.RedisRequestOuterClass.RequestType.Zadd; From 48551c67a2ec6fe09c1fc486eb953808ac8e6cf6 Mon Sep 17 00:00:00 2001 From: SanHalacogluImproving Date: Mon, 15 Apr 2024 15:57:13 -0700 Subject: [PATCH 5/7] Minor IT test update. --- .../test/java/glide/SharedCommandTests.java | 45 ++----------------- 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/java/integTest/src/test/java/glide/SharedCommandTests.java b/java/integTest/src/test/java/glide/SharedCommandTests.java index a909b8a825..d2c892e85e 100644 --- a/java/integTest/src/test/java/glide/SharedCommandTests.java +++ b/java/integTest/src/test/java/glide/SharedCommandTests.java @@ -1657,45 +1657,6 @@ public void zremrangebyscore(BaseClient client) { assertTrue(executionException.getCause() instanceof RequestException); } - @SneakyThrows - @ParameterizedTest - @MethodSource("getClients") - public void zrangestore_by_index(BaseClient client) { - String key = "{testKey}:" + UUID.randomUUID(); - String destination = "{testKey}:" + UUID.randomUUID(); - String source = "{testKey}:" + UUID.randomUUID(); - Map membersScores = Map.of("one", 1.0, "two", 2.0, "three", 3.0); - assertEquals(3, client.zadd(source, membersScores).get()); - - // Full range. - assertEquals(3, client.zrangestore(destination, source, new RangeByIndex(0, -1)).get()); - assertEquals( - Map.of("one", 1.0, "two", 2.0, "three", 3.0), - client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); - - // Range from rank 0 to 1. In descending order of scores. - assertEquals(2, client.zrangestore(destination, source, new RangeByIndex(0, 1), true).get()); - assertEquals( - Map.of("three", 3.0, "two", 2.0), - client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); - - // Incorrect range as start > stop. - assertEquals(0, client.zrangestore(destination, source, new RangeByIndex(3, 1)).get()); - assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); - - // Non-existing source. - assertEquals(0, client.zrangestore(destination, key, new RangeByIndex(0, -1)).get()); - assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); - - // Key exists, but it is not a set - assertEquals(OK, client.set(key, "value").get()); - ExecutionException executionException = - assertThrows( - ExecutionException.class, - () -> client.zrangestore(destination, key, new RangeByIndex(3, 1)).get()); - assertTrue(executionException.getCause() instanceof RequestException); - } - @SneakyThrows @ParameterizedTest(autoCloseArguments = false) @MethodSource("getClients") @@ -1782,7 +1743,7 @@ public void zrangestore_by_index(BaseClient client) { } @SneakyThrows - @ParameterizedTest + @ParameterizedTest(autoCloseArguments = false) @MethodSource("getClients") public void zrangestore_by_score(BaseClient client) { String key = "{testKey}:" + UUID.randomUUID(); @@ -1850,7 +1811,7 @@ public void zrangestore_by_score(BaseClient client) { } @SneakyThrows - @ParameterizedTest + @ParameterizedTest(autoCloseArguments = false) @MethodSource("getClients") public void zrangestore_by_lex(BaseClient client) { String key = "{testKey}:" + UUID.randomUUID(); @@ -1912,7 +1873,7 @@ public void zrangestore_by_lex(BaseClient client) { } @SneakyThrows - @ParameterizedTest + @ParameterizedTest(autoCloseArguments = false) @MethodSource("getClients") public void xadd(BaseClient client) { String key = UUID.randomUUID().toString(); From 5ed957e239e46a41c26305d98a125d5fcf164a1b Mon Sep 17 00:00:00 2001 From: SanHalacogluImproving Date: Mon, 15 Apr 2024 15:59:50 -0700 Subject: [PATCH 6/7] Minor documentation update. --- .../src/main/java/glide/api/models/BaseTransaction.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/java/client/src/main/java/glide/api/models/BaseTransaction.java b/java/client/src/main/java/glide/api/models/BaseTransaction.java index bcf4d42786..8292c70038 100644 --- a/java/client/src/main/java/glide/api/models/BaseTransaction.java +++ b/java/client/src/main/java/glide/api/models/BaseTransaction.java @@ -1648,8 +1648,6 @@ public T zremrangebyrank(@NonNull String key, long start, long end) { * Stores a specified range of elements from the sorted set at source, into a new * sorted set at destination. If destination doesn't exist, a new sorted * set is created; if it exists, it's overwritten.
- * ZRANGESTORE can perform different types of range queries: by index (rank), by the - * score, or by lexicographical order.
* * @see redis.io for more details. * @param destination The key for the destination sorted set. @@ -1680,8 +1678,6 @@ public T zrangestore( * Stores a specified range of elements from the sorted set at source, into a new * sorted set at destination. If destination doesn't exist, a new sorted * set is created; if it exists, it's overwritten.
- * ZRANGESTORE can perform different types of range queries: by index (rank), by the - * score, or by lexicographical order.
* * @see redis.io for more details. * @param destination The key for the destination sorted set. From c7331f5b9d5da609f1be8629b5830935bc3bcb62 Mon Sep 17 00:00:00 2001 From: SanHalacogluImproving Date: Tue, 16 Apr 2024 09:36:05 -0700 Subject: [PATCH 7/7] Minor IT comment update. --- java/integTest/src/test/java/glide/SharedCommandTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/integTest/src/test/java/glide/SharedCommandTests.java b/java/integTest/src/test/java/glide/SharedCommandTests.java index d2c892e85e..0ba74697c9 100644 --- a/java/integTest/src/test/java/glide/SharedCommandTests.java +++ b/java/integTest/src/test/java/glide/SharedCommandTests.java @@ -1776,7 +1776,7 @@ public void zrangestore_by_score(BaseClient client) { Map.of("two", 2.0, "three", 3.0), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); - // Range from positive to negative infinity with rev set to true.Limited to ranks 1 to 2. + // Range from positive to negative infinity with rev set to true. Limited to ranks 1 to 2. query = new RangeByScore( InfScoreBound.POSITIVE_INFINITY, InfScoreBound.NEGATIVE_INFINITY, new Limit(1, 2)); @@ -1843,7 +1843,7 @@ public void zrangestore_by_lex(BaseClient client) { Map.of("b", 2.0, "c", 3.0), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get()); - // Range from positive to negative infinity with rev set to true.Limited to ranks 1 to 2. + // Range from positive to negative infinity with rev set to true. Limited to ranks 1 to 2. query = new RangeByLex( InfLexBound.POSITIVE_INFINITY, InfLexBound.NEGATIVE_INFINITY, new Limit(1, 2));