DATAREDIS-698 - Add support for HSTRLEN.

We now support HSTRLEN command throug RedisHashCommands for Lettuce and Jedis in both an imperative and reactive manner.

However, Jedis not natively supporting HSTRLEN via its API we’ve come up with some more reflective invocation allowing to execute commands currently not known by Jedis. We also added this behavior to the cluster implementation which as of now also supports RedisClusterConnection#execute.

Original pull request: #283.
This commit is contained in:
Christoph Strobl
2017-10-03 18:30:25 +02:00
committed by Mark Paluch
parent 9a1518cd40
commit f6a17fb268
24 changed files with 641 additions and 74 deletions

View File

@@ -2648,6 +2648,36 @@ public abstract class AbstractConnectionIntegrationTests {
assertThat(((GeoResults<GeoLocation<String>>) results.get(1)).getContent(), hasSize(2));
}
@Test // DATAREDIS-698
public void hStrLenReturnsFieldLength() {
actual.add(connection.hSet("hash-hstrlen", "key-1", "value-1"));
actual.add(connection.hSet("hash-hstrlen", "key-2", "value-2"));
actual.add(connection.hStrLen("hash-hstrlen", "key-2"));
verifyResults(
Arrays.asList(new Object[] { Boolean.TRUE, Boolean.TRUE, Long.valueOf("value-2".length()) }));
}
@Test // DATAREDIS-698
public void hStrLenReturnsZeroWhenFieldDoesNotExist() {
actual.add(connection.hSet("hash-hstrlen", "key-1", "value-1"));
actual.add(connection.hStrLen("hash-hstrlen", "key-2"));
verifyResults(
Arrays.asList(new Object[] { Boolean.TRUE, 0L }));
}
@Test // DATAREDIS-698
public void hStrLenReturnsZeroWhenKeyDoesNotExist() {
actual.add(connection.hStrLen("hash-no-exist", "key-2"));
verifyResults(
Arrays.asList(new Object[] { 0L }));
}
protected void verifyResults(List<Object> expected) {
assertEquals(expected, getResults());
}

View File

@@ -633,4 +633,13 @@ public interface ClusterConnectionTests {
// DATAREDIS-438
void geoRemoveDeletesMembers();
// DATAREDIS-698
void hStrLenReturnsFieldLength();
// DATAREDIS-698
void hStrLenReturnsZeroWhenFieldDoesNotExist();
// DATAREDIS-698
void hStrLenReturnsZeroWhenKeyDoesNotExist();
}

View File

@@ -22,7 +22,6 @@ import static org.springframework.data.redis.connection.RedisGeoCommands.Distanc
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.*;
import static org.springframework.data.redis.core.ScanOptions.*;
import org.springframework.data.redis.connection.RedisClusterNode.SlotRange;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
@@ -57,6 +56,7 @@ import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.DefaultSortParameters;
import org.springframework.data.redis.connection.DefaultTuple;
import org.springframework.data.redis.connection.RedisClusterNode;
import org.springframework.data.redis.connection.RedisClusterNode.SlotRange;
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
import org.springframework.data.redis.connection.RedisListCommands.Position;
import org.springframework.data.redis.connection.RedisNode;
@@ -1729,7 +1729,8 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
public void infoShouldCollectionInfoFromAllClusterNodes() {
Properties singleNodeInfo = clusterConnection.serverCommands().info(new RedisClusterNode("127.0.0.1", 7380));
assertThat(Double.valueOf(clusterConnection.serverCommands().info().size()), closeTo(singleNodeInfo.size() * 3, 12d));
assertThat(Double.valueOf(clusterConnection.serverCommands().info().size()),
closeTo(singleNodeInfo.size() * 3, 12d));
}
@Test // DATAREDIS-315
@@ -2135,4 +2136,47 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.geoRemove(KEY_1_BYTES, ARIGENTO.getName()), is(1L));
}
@Test(expected = IllegalArgumentException.class) // DATAREDIS-689
public void executeWithNoKeyAndArgsThrowsException() {
clusterConnection.execute("KEYS", null, Collections.singletonList("*".getBytes()));
}
@Test // DATAREDIS-689
public void executeWithArgs() {
assertThat(clusterConnection.execute("SET", KEY_1_BYTES, VALUE_1_BYTES), is("OK".getBytes()));
assertThat(nativeConnection.get(KEY_1), is(VALUE_1));
}
@Test // DATAREDIS-689
public void executeWithKeyAndArgs() {
assertThat(clusterConnection.execute("SET", KEY_1_BYTES, Collections.singletonList(VALUE_1_BYTES)),
is("OK".getBytes()));
assertThat(nativeConnection.get(KEY_1), is(VALUE_1));
}
@Test // DATAREDIS-698
public void hStrLenReturnsFieldLength() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hStrLen(KEY_1_BYTES, KEY_2_BYTES), is(Long.valueOf(VALUE_3.length())));
}
@Test // DATAREDIS-698
public void hStrLenReturnsZeroWhenFieldDoesNotExist() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hStrLen(KEY_1_BYTES, KEY_3_BYTES), is(0L));
}
@Test // DATAREDIS-698
public void hStrLenReturnsZeroWhenKeyDoesNotExist() {
assertThat(clusterConnection.hashCommands().hStrLen(KEY_1_BYTES, KEY_1_BYTES), is(0L));
}
}

View File

@@ -2145,4 +2145,25 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.geoRemove(KEY_1_BYTES, ARIGENTO_BYTES.getName()), is(1L));
}
@Test // DATAREDIS-698
public void hStrLenReturnsFieldLength() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hStrLen(KEY_1_BYTES, KEY_2_BYTES), is(Long.valueOf(VALUE_3.length())));
}
@Test // DATAREDIS-698
public void hStrLenReturnsZeroWhenFieldDoesNotExist() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hStrLen(KEY_1_BYTES, KEY_3_BYTES), is(0L));
}
@Test // DATAREDIS-698
public void hStrLenReturnsZeroWhenKeyDoesNotExist() {
assertThat(clusterConnection.hashCommands().hStrLen(KEY_1_BYTES, KEY_1_BYTES), is(0L));
}
}

View File

@@ -205,6 +205,32 @@ public class LettuceReactiveHashCommandsTests extends LettuceReactiveCommandsTes
assertTrue(list.containsAll(expected.entrySet()));
}) //
.verifyComplete();
}
@Test // DATAREDIS-698
public void hStrLenReturnsFieldLength() {
nativeCommands.hset(KEY_1, FIELD_1, VALUE_1);
nativeCommands.hset(KEY_1, FIELD_2, VALUE_2);
StepVerifier.create(connection.hashCommands().hStrLen(KEY_1_BBUFFER, FIELD_1_BBUFFER))
.expectNext(Long.valueOf(VALUE_1.length())) //
.verifyComplete();
}
@Test // DATAREDIS-698
public void hStrLenReturnsZeroWhenFieldDoesNotExist() {
nativeCommands.hset(KEY_1, FIELD_2, VALUE_3);
StepVerifier.create(connection.hashCommands().hStrLen(KEY_1_BBUFFER, FIELD_1_BBUFFER)).expectNext(0L) //
.verifyComplete();
}
@Test // DATAREDIS-698
public void hStrLenReturnsZeroWhenKeyDoesNotExist() {
StepVerifier.create(connection.hashCommands().hStrLen(KEY_1_BBUFFER, FIELD_1_BBUFFER)).expectNext(0L) //
.verifyComplete();
}
}

View File

@@ -17,6 +17,7 @@ package org.springframework.data.redis.core;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
import java.io.IOException;
import java.util.Arrays;
@@ -172,4 +173,22 @@ public class DefaultHashOperationsTests<K, HK, HV> {
assertThat(count, is(hashOps.size(key)));
}
@Test // DATAREDIS-698
@IfProfileValue(name = "redisVersion", value = "3.0.3+")
public void lengthOfValue() throws IOException {
assumeThat(hashValueFactory instanceof StringObjectFactory, is(true));
K key = keyFactory.instance();
HK key1 = hashKeyFactory.instance();
HV val1 = hashValueFactory.instance();
HK key2 = hashKeyFactory.instance();
HV val2 = hashValueFactory.instance();
hashOps.put(key, key1, val1);
hashOps.put(key, key2, val2);
assertThat(hashOps.lengthOfValue(key, key1), is(Long.valueOf(val1.toString().length())));
}
}