From f7b941143df95e26f735b3ed7edf26fd679363d2 Mon Sep 17 00:00:00 2001 From: Shyngys Sapraliyev <44555427+bytestreme@users.noreply.github> Date: Sun, 17 Jul 2022 04:31:08 +0600 Subject: [PATCH] Added `zRangeStoreByLex` and `zRangeStoreByScore` for `ZRANGESTORE` command. Closes #2345 --- .../DefaultStringRedisConnection.java | 32 ++++++ .../connection/DefaultedRedisConnection.java | 20 ++++ .../redis/connection/RedisZSetCommands.java | 100 ++++++++++++++++++ .../connection/StringRedisConnection.java | 66 ++++++++++++ .../jedis/JedisClusterZSetCommands.java | 49 +++++++++ .../connection/jedis/JedisZSetCommands.java | 47 ++++++++ .../lettuce/LettuceZSetCommands.java | 29 +++++ .../redis/core/DefaultZSetOperations.java | 15 +++ .../data/redis/core/ZSetOperations.java | 7 ++ .../AbstractConnectionIntegrationTests.java | 39 +++++++ .../connection/ClusterTestVariables.java | 1 + 11 files changed, 405 insertions(+) diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java index fea526f773..bcd7d19e6d 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java @@ -80,6 +80,7 @@ * @author dengliming * @author ihaohong * @author Dennis Neufeld + * @author Shyngys Sapraliyev */ @SuppressWarnings({ "ConstantConditions", "deprecation" }) public class DefaultStringRedisConnection implements StringRedisConnection, DecoratedRedisConnection { @@ -2710,6 +2711,37 @@ public Set zRevRangeByLex(byte[] key, org.springframework.data.domain.Ra return convertAndReturn(delegate.zRevRangeByLex(key, range, limit), Converters.identityConverter()); } + @Override + public Long zRangeStoreByLex(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit) { + return convertAndReturn(delegate.zRangeStoreByLex(dstKey, srcKey, range, limit), + Converters.identityConverter()); + } + + @Override + public Long zRangeStoreByLex(String dstKey, String srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit) { + return convertAndReturn(delegate.zRangeStoreByLex(serialize(dstKey), serialize(srcKey), serialize(range), limit), + Converters.identityConverter()); + } + + @Override + public Long zRangeStoreByScore(String dstKey, String srcKey, double min, double max, + org.springframework.data.redis.connection.Limit limit) { + return convertAndReturn(delegate.zRangeStoreByScore(serialize(dstKey), serialize(srcKey), min, max, limit), + Converters.identityConverter()); + } + + @Override + public Long zRangeStoreByScore(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit) { + return convertAndReturn(delegate.zRangeStoreByScore(dstKey, srcKey, range, limit), + Converters.identityConverter()); + } + @Override public Set zRevRangeByLex(String key, org.springframework.data.domain.Range range, org.springframework.data.redis.connection.Limit limit) { diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java index cc7d4288e5..f70a78560e 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java @@ -64,6 +64,7 @@ * @author dengliming * @author ihaohong * @author Dennis Neufeld + * @author Shyngys Sapraliyev * @since 2.0 */ @Deprecated @@ -1835,4 +1836,23 @@ default T evalSha(String scriptSha, ReturnType returnType, int numKeys, byte default T evalSha(byte[] scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { return scriptingCommands().evalSha(scriptSha, returnType, numKeys, keysAndArgs); } + + /** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */ + @Override + @Deprecated + default Long zRangeStoreByLex(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit) { + return zSetCommands().zRangeStoreByLex(dstKey, srcKey, range, limit); + } + + /** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */ + @Override + @Deprecated + default Long zRangeStoreByScore(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit) { + return zSetCommands().zRangeStoreByScore(dstKey, srcKey, range, limit); + } + } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java index 3ca6e47b43..70abdb9d15 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java @@ -38,6 +38,7 @@ * @author David Liu * @author Mark Paluch * @author Andrey Shlykov + * @author Shyngys Sapraliyev */ public interface RedisZSetCommands { @@ -1367,4 +1368,103 @@ default Set zRevRangeByLex(byte[] key, org.springframework.data.domain.R Set zRevRangeByLex(byte[] key, org.springframework.data.domain.Range range, org.springframework.data.redis.connection.Limit limit); + /** + * This command is like ZRANGE , but stores the result in the {@literal dstKey} destination key. + * + * @param dstKey must not be {@literal null}. + * @param srcKey must not be {@literal null}. + * @param range must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 3.0 + * @see Redis Documentation: ZRANGESTORE + */ + @Nullable + default Long zRangeStoreByLex(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range) { + return zRangeStoreByLex(dstKey, srcKey, range, org.springframework.data.redis.connection.Limit.unlimited()); + } + + /** + * This command is like ZRANGE , but stores the result in the {@literal dstKey} destination key. + * + * @param dstKey must not be {@literal null}. + * @param srcKey must not be {@literal null}. + * @param range must not be {@literal null}. + * @param limit must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 3.0 + * @see Redis Documentation: ZRANGESTORE + */ + @Nullable + Long zRangeStoreByLex(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit); + + /** + * This command is like ZRANGE, but stores the result in the {@literal dstKey} destination key. + * + * @param dstKey must not be {@literal null}. + * @param srcKey must not be {@literal null}. + * @param min minimal inclusive score + * @param max maximal inclusive score + * @return {@literal null} when used in pipeline / transaction. + * @since 3.0 + * @see Redis Documentation: ZRANGESTORE + */ + @Nullable + default Long zRangeStoreByScore(byte[] dstKey, byte[] srcKey, double min, double max) { + return zRangeStoreByScore(dstKey, srcKey, org.springframework.data.domain.Range.closed(min, max)); + } + + /** + * This command is like ZRANGE, but stores the result in the {@literal dstKey} destination key. + * + * @param dstKey must not be {@literal null}. + * @param srcKey must not be {@literal null}. + * @param min minimal inclusive score + * @param max maximal inclusive score + * @param limit must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 3.0 + * @see Redis Documentation: ZRANGESTORE + */ + @Nullable + default Long zRangeStoreByScore(byte[] dstKey, byte[] srcKey, double min, double max, + org.springframework.data.redis.connection.Limit limit) { + return zRangeStoreByScore(dstKey, srcKey, org.springframework.data.domain.Range.closed(min, max), limit); + } + + /** + * This command is like ZRANGE, but stores the result in the {@literal dstKey} destination key. + * + * @param dstKey must not be {@literal null}. + * @param srcKey must not be {@literal null}. + * @param range must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 3.0 + * @see Redis Documentation: ZRANGESTORE + */ + @Nullable + default Long zRangeStoreByScore(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range) { + return zRangeStoreByScore(dstKey, srcKey, range, + org.springframework.data.redis.connection.Limit.unlimited()); + } + + /** + * This command is like ZRANGE, but stores the result in the {@literal dstKey} destination key. + * + * @param dstKey must not be {@literal null}. + * @param srcKey must not be {@literal null}. + * @param range must not be {@literal null}. + * @param limit must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 3.0 + * @see Redis Documentation: ZRANGESTORE + */ + @Nullable + Long zRangeStoreByScore(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit); + } diff --git a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java index a3f3c3dd34..41cd699eff 100644 --- a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java @@ -70,6 +70,7 @@ * @author Dengliming * @author Andrey Shlykov * @author ihaohong + * @author Shyngys Sapraliyev * * @see RedisCallback * @see RedisSerializer @@ -1987,6 +1988,71 @@ default Set zRevRangeByLex(String key, org.springframework.data.domain.R Set zRevRangeByLex(String key, org.springframework.data.domain.Range range, org.springframework.data.redis.connection.Limit limit); + /** + * This command is like ZRANGE , but stores the result in the {@literal dstKey} destination key. + * + * @param dstKey must not be {@literal null}. + * @param srcKey must not be {@literal null}. + * @param range must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 3.0 + * @see Redis Documentation: ZRANGESTORE + */ + @Nullable + default Long zRangeStoreByLex(String dstKey, String srcKey, + org.springframework.data.domain.Range range) { + return zRangeStoreByLex(dstKey, srcKey, range, org.springframework.data.redis.connection.Limit.unlimited()); + } + + /** + * This command is like ZRANGE , but stores the result in the {@literal dstKey} destination key. + * + * @param dstKey must not be {@literal null}. + * @param srcKey must not be {@literal null}. + * @param range must not be {@literal null}. + * @param limit must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 3.0 + * @see Redis Documentation: ZRANGESTORE + */ + @Nullable + Long zRangeStoreByLex(String dstKey, String srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit); + + + /** + * This command is like ZRANGE, but stores the result in the {@literal dstKey} destination key. + * + * @param dstKey must not be {@literal null}. + * @param srcKey must not be {@literal null}. + * @param min minimal inclusive score + * @param max maximal inclusive score + * @return {@literal null} when used in pipeline / transaction. + * @since 3.0 + * @see Redis Documentation: ZRANGESTORE + */ + @Nullable + default Long zRangeStoreByScore(String dstKey, String srcKey, double min, double max) { + return zRangeStoreByScore(dstKey, srcKey, min, max, org.springframework.data.redis.connection.Limit.unlimited()); + } + + /** + * This command is like ZRANGE, but stores the result in the {@literal dstKey} destination key. + * + * @param dstKey must not be {@literal null}. + * @param srcKey must not be {@literal null}. + * @param min minimal inclusive score + * @param max maximal inclusive score + * @param limit must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 3.0 + * @see Redis Documentation: ZRANGESTORE + */ + @Nullable + Long zRangeStoreByScore(String dstKey, String srcKey, double min, double max, + org.springframework.data.redis.connection.Limit limit); + // ------------------------------------------------------------------------- // Methods dealing with Redis Hashes // ------------------------------------------------------------------------- diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java index 6247b048a5..02287ff776 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java @@ -15,8 +15,10 @@ */ package org.springframework.data.redis.connection.jedis; +import redis.clients.jedis.Protocol; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.params.ZParams; +import redis.clients.jedis.params.ZRangeParams; import redis.clients.jedis.resps.ScanResult; import java.util.ArrayList; @@ -49,6 +51,7 @@ * @author Clement Ong * @author Andrey Shlykov * @author Jens Deppe + * @author Shyngys Sapraliyev * @since 2.0 */ class JedisClusterZSetCommands implements RedisZSetCommands { @@ -493,6 +496,52 @@ public Set zRevRangeByLex(byte[] key, org.springframework.data.domain.Ra } } + @Override + public Long zRangeStoreByLex(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit) { + Assert.notNull(dstKey, "Destination key must not be null"); + Assert.notNull(srcKey, "Source key must not be null"); + Assert.notNull(range, "Range for ZRANGESTORE BYLEX must not be null"); + Assert.notNull(limit, "Limit must not be null. Use Limit.unlimited() instead."); + + byte[] min = JedisConverters.boundaryToBytesForZRangeByLex(range.getLowerBound(), JedisConverters.MINUS_BYTES); + byte[] max = JedisConverters.boundaryToBytesForZRangeByLex(range.getUpperBound(), JedisConverters.PLUS_BYTES); + + ZRangeParams zRangeParams = new ZRangeParams(Protocol.Keyword.BYLEX, min, max) + .limit(limit.getOffset(), limit.getCount()); + + try { + return connection.getCluster().zrangestore(dstKey, srcKey, zRangeParams); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + @Override + public Long zRangeStoreByScore(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit) { + Assert.notNull(dstKey, "Destination key must not be null"); + Assert.notNull(srcKey, "Source key must not be null"); + Assert.notNull(range, "Range for ZRANGESTORE BYSCORE must not be null"); + Assert.notNull(limit, "Limit must not be null. Use Limit.unlimited() instead."); + + byte[] min = JedisConverters + .boundaryToBytesForZRange(range.getLowerBound(), JedisConverters.NEGATIVE_INFINITY_BYTES); + byte[] max = JedisConverters + .boundaryToBytesForZRange(range.getUpperBound(), JedisConverters.POSITIVE_INFINITY_BYTES); + + ZRangeParams zRangeParams = new ZRangeParams(Protocol.Keyword.BYSCORE, min, max) + .limit(limit.getOffset(), limit.getCount()); + + try { + return connection.getCluster().zrangestore(dstKey, srcKey, zRangeParams); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + @Override public Set zRangeWithScores(byte[] key, long start, long end) { diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisZSetCommands.java index 51ecaea53d..9c41cb4554 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisZSetCommands.java @@ -16,9 +16,11 @@ package org.springframework.data.redis.connection.jedis; import redis.clients.jedis.Jedis; +import redis.clients.jedis.Protocol; import redis.clients.jedis.commands.PipelineBinaryCommands; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.params.ZParams; +import redis.clients.jedis.params.ZRangeParams; import redis.clients.jedis.resps.ScanResult; import java.util.LinkedHashSet; @@ -44,6 +46,7 @@ * @author Clement Ong * @author Mark Paluch * @author Andrey Shlykov + * @author Shyngys Sapraliyev * @since 2.0 */ class JedisZSetCommands implements RedisZSetCommands { @@ -676,6 +679,50 @@ public Set zRevRangeByLex(byte[] key, org.springframework.data.domain.Ra .get(LinkedHashSet::new); } + @Override + public Long zRangeStoreByLex(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit) { + + Assert.notNull(dstKey, "Destination key must not be null"); + Assert.notNull(srcKey, "Source key must not be null"); + Assert.notNull(range, "Range for ZRANGESTORE BYLEX must not be null"); + Assert.notNull(limit, "Limit must not be null. Use Limit.unlimited() instead."); + + byte[] min = JedisConverters + .boundaryToBytesForZRangeByLex(range.getLowerBound(), JedisConverters.MINUS_BYTES); + byte[] max = JedisConverters + .boundaryToBytesForZRangeByLex(range.getUpperBound(), JedisConverters.PLUS_BYTES); + + ZRangeParams zRangeParams = new ZRangeParams(Protocol.Keyword.BYLEX, min, max) + .limit(limit.getOffset(), limit.getCount()); + + return connection.invoke().just(Jedis::zrangestore, PipelineBinaryCommands::zrangestore, + dstKey, srcKey, zRangeParams); + } + + @Override + public Long zRangeStoreByScore(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit) { + + Assert.notNull(dstKey, "Destination key must not be null"); + Assert.notNull(srcKey, "Source key must not be null"); + Assert.notNull(range, "Range for ZRANGESTORE BYSCORE must not be null"); + Assert.notNull(limit, "Limit must not be null. Use Limit.unlimited() instead."); + + byte[] min = JedisConverters + .boundaryToBytesForZRange(range.getLowerBound(), JedisConverters.NEGATIVE_INFINITY_BYTES); + byte[] max = JedisConverters + .boundaryToBytesForZRange(range.getUpperBound(), JedisConverters.POSITIVE_INFINITY_BYTES); + + ZRangeParams zRangeParams = new ZRangeParams(Protocol.Keyword.BYSCORE, min, max) + .limit(limit.getOffset(), limit.getCount()); + + return connection.invoke().just(Jedis::zrangestore, PipelineBinaryCommands::zrangestore, + dstKey, srcKey, zRangeParams); + } + private boolean isPipelined() { return connection.isPipelined(); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java index b26fe9d38a..9be0c5b982 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java @@ -46,6 +46,7 @@ * @author Christoph Strobl * @author Mark Paluch * @author Andrey Shlykov + * @author Shyngys Sapraliyev * @since 2.0 */ class LettuceZSetCommands implements RedisZSetCommands { @@ -643,6 +644,34 @@ public Set zRevRangeByLex(byte[] key, org.springframework.data.domain.Ra LettuceConverters. toRange(range, true), LettuceConverters.toLimit(limit)).toSet(); } + @Override + public Long zRangeStoreByLex(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit) { + Assert.notNull(dstKey, "Destination key must not be null"); + Assert.notNull(srcKey, "Source key must not be null"); + Assert.notNull(range, "Range for ZRANGESTORE BYLEX must not be null"); + Assert.notNull(limit, "Limit must not be null. Use Limit.unlimited() instead."); + + + return connection.invoke().just(RedisSortedSetAsyncCommands::zrangestorebylex, dstKey, srcKey, + LettuceConverters.toRange(range, true), LettuceConverters.toLimit(limit)); + + } + + @Override + public Long zRangeStoreByScore(byte[] dstKey, byte[] srcKey, + org.springframework.data.domain.Range range, + org.springframework.data.redis.connection.Limit limit) { + Assert.notNull(dstKey, "Destination key must not be null"); + Assert.notNull(srcKey, "Source key must not be null"); + Assert.notNull(range, "Range for ZRANGESTORE BYSCORE must not be null"); + Assert.notNull(limit, "Limit must not be null. Use Limit.unlimited() instead."); + + return connection.invoke().just(RedisSortedSetAsyncCommands::zrangestorebyscore, dstKey, srcKey, + LettuceConverters.toRange(range), LettuceConverters.toLimit(limit)); + } + public RedisClusterCommands getConnection() { return connection.getConnection(); } diff --git a/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java index 04ac57029b..f92acfabe5 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java @@ -41,6 +41,7 @@ * @author Mark Paluch * @author Wongoo (望哥) * @author Andrey Shlykov + * @author Shyngys Sapraliyev */ class DefaultZSetOperations extends AbstractOperations implements ZSetOperations { @@ -226,6 +227,20 @@ public Set reverseRangeByLex(K key, Range range, Limit limit) { return deserializeValues(rawValues); } + @Override + public Long rangeStoreByLex(K dstKey, K srcKey, Range range, Limit limit) { + byte[] rawDstKey = rawKey(dstKey); + byte[] rawSrcKey = rawKey(srcKey); + return execute(connection -> connection.zRangeStoreByLex(rawDstKey, rawSrcKey, serialize(range), limit)); + } + + @Override + public Long rangeStoreByScore(K dstKey, K srcKey, Range range, Limit limit) { + byte[] rawDstKey = rawKey(dstKey); + byte[] rawSrcKey = rawKey(srcKey); + return execute(connection -> connection.zRangeStoreByScore(rawDstKey, rawSrcKey, range, limit)); + } + @Override public Set rangeByScore(K key, double min, double max) { diff --git a/src/main/java/org/springframework/data/redis/core/ZSetOperations.java b/src/main/java/org/springframework/data/redis/core/ZSetOperations.java index 193c2761a6..4867e06abf 100644 --- a/src/main/java/org/springframework/data/redis/core/ZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ZSetOperations.java @@ -39,6 +39,7 @@ * @author Rosty Kerei * @author Wongoo (望哥) * @author Andrey Shlykov + * @author Shyngys Sapraliyev */ public interface ZSetOperations { @@ -1130,6 +1131,12 @@ default Set reverseRangeByLex(K key, org.springframework.data.redis.connectio @Nullable Set reverseRangeByLex(K key, Range range, Limit limit); + @Nullable + Long rangeStoreByLex(K dstKey, K srcKey, Range range, Limit limit); + + @Nullable + Long rangeStoreByScore(K dstKey, K srcKey, Range range, Limit limit); + /** * @return never {@literal null}. */ 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 a05f0d42dd..767820515d 100644 --- a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java @@ -106,6 +106,7 @@ * @author Dejan Jankov * @author Andrey Shlykov * @author Hendrik Duerkop + * @author Shyngys Sapraliyev */ public abstract class AbstractConnectionIntegrationTests { @@ -4068,6 +4069,44 @@ public void xinfoConsumersNoConsumer() { assertThat(info.size()).isZero(); } + @Test //GH-2345 + public void zRangeStoreStoresKeysCreatedByZAddByScore() { + final String dstKey = KEY_2; + final String srcKey = KEY_1; + actual.add(connection.zAdd(srcKey, 1, VALUE_1)); + actual.add(connection.zAdd(srcKey, 2, VALUE_2)); + actual.add(connection.zAdd(srcKey, 3, VALUE_3)); + actual.add(connection.zAdd(srcKey, 4, VALUE_4)); + actual.add(connection.zRangeStoreByScore(dstKey, srcKey, 3, 4)); + actual.add(connection.zRange(dstKey, 0, -1)); + List result = getResults(); + assertThat(result.get(0)).isEqualTo(true); + assertThat(result.get(1)).isEqualTo(true); + assertThat(result.get(2)).isEqualTo(true); + assertThat(result.get(3)).isEqualTo(true); + assertThat(result.get(4)).isEqualTo(2L); + assertThat((LinkedHashSet) result.get(5)).containsSequence(VALUE_3, VALUE_4); + } + + @Test //GH-2345 + public void zRangeStoreStoresKeysCreatedByZAddByLex() { + final String dstKey = KEY_2; + final String srcKey = KEY_1; + actual.add(connection.zAdd(srcKey, 0, VALUE_3)); + actual.add(connection.zAdd(srcKey, 0, VALUE_1)); + actual.add(connection.zAdd(srcKey, 0, VALUE_4)); + actual.add(connection.zAdd(srcKey, 0, VALUE_2)); + actual.add(connection.zRangeStoreByLex(dstKey, srcKey, Range.rightUnbounded(Bound.inclusive(VALUE_3)))); + actual.add(connection.zRange(dstKey, 0, -1)); + List result = getResults(); + assertThat(result.get(0)).isEqualTo(true); + assertThat(result.get(1)).isEqualTo(true); + assertThat(result.get(2)).isEqualTo(true); + assertThat(result.get(3)).isEqualTo(true); + assertThat(result.get(4)).isEqualTo(2L); + assertThat((LinkedHashSet) result.get(5)).containsSequence(VALUE_3, VALUE_4); + } + protected void verifyResults(List expected) { assertThat(getResults()).isEqualTo(expected); } diff --git a/src/test/java/org/springframework/data/redis/connection/ClusterTestVariables.java b/src/test/java/org/springframework/data/redis/connection/ClusterTestVariables.java index 1ec0c75729..5ba1e124b9 100644 --- a/src/test/java/org/springframework/data/redis/connection/ClusterTestVariables.java +++ b/src/test/java/org/springframework/data/redis/connection/ClusterTestVariables.java @@ -29,6 +29,7 @@ public abstract class ClusterTestVariables { public static final String VALUE_1 = "value1"; public static final String VALUE_2 = "value2"; public static final String VALUE_3 = "value3"; + public static final String VALUE_4 = "value4"; public static final String SAME_SLOT_KEY_1 = "key2660"; public static final String SAME_SLOT_KEY_2 = "key7112";