Skip to content

Commit 5f0b8a3

Browse files
Java: Add hvals command. (Hash Command Group) (valkey-io#1210)
Java: Add hvals command. (Hash Command Group) (#164)
1 parent 6b02d16 commit 5f0b8a3

File tree

7 files changed

+98
-0
lines changed

7 files changed

+98
-0
lines changed

java/client/src/main/java/glide/api/BaseClient.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static redis_request.RedisRequestOuterClass.RequestType.HashIncrByFloat;
2222
import static redis_request.RedisRequestOuterClass.RequestType.HashMGet;
2323
import static redis_request.RedisRequestOuterClass.RequestType.HashSet;
24+
import static redis_request.RedisRequestOuterClass.RequestType.Hvals;
2425
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
2526
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
2627
import static redis_request.RedisRequestOuterClass.RequestType.IncrByFloat;
@@ -347,6 +348,14 @@ public CompletableFuture<Long> hdel(@NonNull String key, @NonNull String[] field
347348
return commandManager.submitNewCommand(HashDel, args, this::handleLongResponse);
348349
}
349350

351+
@Override
352+
public CompletableFuture<String[]> hvals(@NonNull String key) {
353+
return commandManager.submitNewCommand(
354+
Hvals,
355+
new String[] {key},
356+
response -> castArray(handleArrayResponse(response), String.class));
357+
}
358+
350359
@Override
351360
public CompletableFuture<String[]> hmget(@NonNull String key, @NonNull String[] fields) {
352361
String[] arguments = ArrayUtils.addFirst(fields, key);

java/client/src/main/java/glide/api/commands/HashBaseCommands.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@ public interface HashBaseCommands {
6565
*/
6666
CompletableFuture<Long> hdel(String key, String[] fields);
6767

68+
/**
69+
* Returns all values in the hash stored at <code>key</code>.
70+
*
71+
* @see <a href="https://redis.io/commands/hvals/">redis.io</a> for details.
72+
* @param key The key of the hash.
73+
* @return An <code>array</code> of values in the hash, or an <code>empty array</code> when the
74+
* key does not exist.
75+
* @example
76+
* <pre>{@code
77+
* String[] values = client.hvals("myHash").get();
78+
* assert values.equals(new String[] {"value1", "value2", "value3"}); // Returns all the values stored in the hash "myHash".
79+
* }</pre>
80+
*/
81+
CompletableFuture<String[]> hvals(String key);
82+
6883
/**
6984
* Returns the values associated with the specified fields in the hash stored at <code>key</code>.
7085
*

java/client/src/main/java/glide/api/models/BaseTransaction.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import static redis_request.RedisRequestOuterClass.RequestType.HashIncrByFloat;
3030
import static redis_request.RedisRequestOuterClass.RequestType.HashMGet;
3131
import static redis_request.RedisRequestOuterClass.RequestType.HashSet;
32+
import static redis_request.RedisRequestOuterClass.RequestType.Hvals;
3233
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
3334
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
3435
import static redis_request.RedisRequestOuterClass.RequestType.IncrByFloat;
@@ -438,6 +439,21 @@ public T hdel(@NonNull String key, @NonNull String[] fields) {
438439
return getThis();
439440
}
440441

442+
/**
443+
* Returns all values in the hash stored at <code>key</code>.
444+
*
445+
* @see <a href="https://redis.io/commands/hvals/">redis.io</a> for details.
446+
* @param key The key of the hash.
447+
* @return Command Response - An <code>array</code> of values in the hash, or an <code>empty array
448+
* </code> when the key does not exist.
449+
*/
450+
public T hvals(@NonNull String key) {
451+
ArgsArray commandArgs = buildArgs(key);
452+
453+
protobufTransaction.addCommands(buildCommand(Hvals, commandArgs));
454+
return getThis();
455+
}
456+
441457
/**
442458
* Returns the values associated with the specified fields in the hash stored at <code>key</code>.
443459
*

java/client/src/test/java/glide/api/RedisClientTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import static redis_request.RedisRequestOuterClass.RequestType.HashIncrByFloat;
4141
import static redis_request.RedisRequestOuterClass.RequestType.HashMGet;
4242
import static redis_request.RedisRequestOuterClass.RequestType.HashSet;
43+
import static redis_request.RedisRequestOuterClass.RequestType.Hvals;
4344
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
4445
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
4546
import static redis_request.RedisRequestOuterClass.RequestType.IncrByFloat;
@@ -1021,6 +1022,30 @@ public void hdel_success() {
10211022
assertEquals(value, payload);
10221023
}
10231024

1025+
@SneakyThrows
1026+
@Test
1027+
public void hvals_success() {
1028+
// setup
1029+
String key = "testKey";
1030+
String[] args = {key};
1031+
String[] values = new String[] {"value1", "value2"};
1032+
1033+
CompletableFuture<String[]> testResponse = new CompletableFuture<>();
1034+
testResponse.complete(values);
1035+
1036+
// match on protobuf request
1037+
when(commandManager.<String[]>submitNewCommand(eq(Hvals), eq(args), any()))
1038+
.thenReturn(testResponse);
1039+
1040+
// exercise
1041+
CompletableFuture<String[]> response = service.hvals(key);
1042+
String[] payload = response.get();
1043+
1044+
// verify
1045+
assertEquals(testResponse, response);
1046+
assertEquals(values, payload);
1047+
}
1048+
10241049
@SneakyThrows
10251050
@Test
10261051
public void hmget_success() {

java/client/src/test/java/glide/api/models/TransactionTests.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import static redis_request.RedisRequestOuterClass.RequestType.HashIncrByFloat;
2828
import static redis_request.RedisRequestOuterClass.RequestType.HashMGet;
2929
import static redis_request.RedisRequestOuterClass.RequestType.HashSet;
30+
import static redis_request.RedisRequestOuterClass.RequestType.Hvals;
3031
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
3132
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
3233
import static redis_request.RedisRequestOuterClass.RequestType.IncrByFloat;
@@ -169,6 +170,9 @@ public void transaction_builds_protobuf_request(BaseTransaction<?> transaction)
169170
transaction.hdel("key", new String[] {"field"});
170171
results.add(Pair.of(HashDel, ArgsArray.newBuilder().addArgs("key").addArgs("field").build()));
171172

173+
transaction.hvals("key");
174+
results.add(Pair.of(Hvals, ArgsArray.newBuilder().addArgs("key").build()));
175+
172176
transaction.hmget("key", new String[] {"field"});
173177
results.add(Pair.of(HashMGet, ArgsArray.newBuilder().addArgs("key").addArgs("field").build()));
174178

java/integTest/src/test/java/glide/SharedCommandTests.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import glide.api.models.configuration.RedisClusterClientConfiguration;
3838
import glide.api.models.exceptions.RequestException;
3939
import java.time.Instant;
40+
import java.util.Arrays;
4041
import java.util.LinkedHashMap;
4142
import java.util.List;
4243
import java.util.Map;
@@ -471,6 +472,32 @@ public void hdel_multiple_existing_fields_non_existing_field_non_existing_key(Ba
471472
assertEquals(0, client.hdel("non_existing_key", new String[] {field3}).get());
472473
}
473474

475+
@SneakyThrows
476+
@ParameterizedTest
477+
@MethodSource("getClients")
478+
public void hvals(BaseClient client) {
479+
String key1 = UUID.randomUUID().toString();
480+
String key2 = UUID.randomUUID().toString();
481+
String field1 = UUID.randomUUID().toString();
482+
String field2 = UUID.randomUUID().toString();
483+
Map<String, String> fieldValueMap = Map.of(field1, "value1", field2, "value2");
484+
485+
assertEquals(2, client.hset(key1, fieldValueMap).get());
486+
487+
String[] hvalsPayload = client.hvals(key1).get();
488+
Arrays.sort(hvalsPayload); // ordering for values by hvals is not guaranteed
489+
assertArrayEquals(new String[] {"value1", "value2"}, hvalsPayload);
490+
491+
assertEquals(1, client.hdel(key1, new String[] {field1}).get());
492+
assertArrayEquals(new String[] {"value2"}, client.hvals(key1).get());
493+
assertArrayEquals(new String[] {}, client.hvals("nonExistingKey").get());
494+
495+
assertEquals(OK, client.set(key2, "value2").get());
496+
ExecutionException executionException =
497+
assertThrows(ExecutionException.class, () -> client.hvals(key2).get());
498+
assertTrue(executionException.getCause() instanceof RequestException);
499+
}
500+
474501
@SneakyThrows
475502
@ParameterizedTest
476503
@MethodSource("getClients")

java/integTest/src/test/java/glide/TransactionTestUtilities.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public static BaseTransaction<?> transactionTest(BaseTransaction<?> baseTransact
6464
baseTransaction.hmget(key4, new String[] {field1, "non_existing_field", field2});
6565
baseTransaction.hgetall(key4);
6666
baseTransaction.hdel(key4, new String[] {field1});
67+
baseTransaction.hvals(key4);
6768

6869
baseTransaction.hincrBy(key4, field3, 5);
6970
baseTransaction.hincrByFloat(key4, field3, 5.5);
@@ -134,6 +135,7 @@ public static Object[] transactionTestResult() {
134135
new String[] {value1, null, value2},
135136
Map.of(field1, value1, field2, value2),
136137
1L,
138+
new String[] {value2}, // hvals(key4)
137139
5L,
138140
10.5,
139141
5L,

0 commit comments

Comments
 (0)