Skip to content

Commit

Permalink
Java: Add hvals command. (Hash Command Group) (valkey-io#1210)
Browse files Browse the repository at this point in the history
Java: Add hvals command. (Hash Command Group) (valkey-io#164)
  • Loading branch information
SanHalacogluImproving authored and shohamazon committed Apr 9, 2024
1 parent e4d6d65 commit 5acc058
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 0 deletions.
9 changes: 9 additions & 0 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.HashIncrByFloat;
import static redis_request.RedisRequestOuterClass.RequestType.HashMGet;
import static redis_request.RedisRequestOuterClass.RequestType.HashSet;
import static redis_request.RedisRequestOuterClass.RequestType.Hvals;
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
import static redis_request.RedisRequestOuterClass.RequestType.IncrByFloat;
Expand Down Expand Up @@ -347,6 +348,14 @@ public CompletableFuture<Long> hdel(@NonNull String key, @NonNull String[] field
return commandManager.submitNewCommand(HashDel, args, this::handleLongResponse);
}

@Override
public CompletableFuture<String[]> hvals(@NonNull String key) {
return commandManager.submitNewCommand(
Hvals,
new String[] {key},
response -> castArray(handleArrayResponse(response), String.class));
}

@Override
public CompletableFuture<String[]> hmget(@NonNull String key, @NonNull String[] fields) {
String[] arguments = ArrayUtils.addFirst(fields, key);
Expand Down
15 changes: 15 additions & 0 deletions java/client/src/main/java/glide/api/commands/HashBaseCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ public interface HashBaseCommands {
*/
CompletableFuture<Long> hdel(String key, String[] fields);

/**
* Returns all values in the hash stored at <code>key</code>.
*
* @see <a href="https://redis.io/commands/hvals/">redis.io</a> for details.
* @param key The key of the hash.
* @return An <code>array</code> of values in the hash, or an <code>empty array</code> when the
* key does not exist.
* @example
* <pre>{@code
* String[] values = client.hvals("myHash").get();
* assert values.equals(new String[] {"value1", "value2", "value3"}); // Returns all the values stored in the hash "myHash".
* }</pre>
*/
CompletableFuture<String[]> hvals(String key);

/**
* Returns the values associated with the specified fields in the hash stored at <code>key</code>.
*
Expand Down
16 changes: 16 additions & 0 deletions java/client/src/main/java/glide/api/models/BaseTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.HashIncrByFloat;
import static redis_request.RedisRequestOuterClass.RequestType.HashMGet;
import static redis_request.RedisRequestOuterClass.RequestType.HashSet;
import static redis_request.RedisRequestOuterClass.RequestType.Hvals;
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
import static redis_request.RedisRequestOuterClass.RequestType.IncrByFloat;
Expand Down Expand Up @@ -438,6 +439,21 @@ public T hdel(@NonNull String key, @NonNull String[] fields) {
return getThis();
}

/**
* Returns all values in the hash stored at <code>key</code>.
*
* @see <a href="https://redis.io/commands/hvals/">redis.io</a> for details.
* @param key The key of the hash.
* @return Command Response - An <code>array</code> of values in the hash, or an <code>empty array
* </code> when the key does not exist.
*/
public T hvals(@NonNull String key) {
ArgsArray commandArgs = buildArgs(key);

protobufTransaction.addCommands(buildCommand(Hvals, commandArgs));
return getThis();
}

/**
* Returns the values associated with the specified fields in the hash stored at <code>key</code>.
*
Expand Down
25 changes: 25 additions & 0 deletions java/client/src/test/java/glide/api/RedisClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.HashIncrByFloat;
import static redis_request.RedisRequestOuterClass.RequestType.HashMGet;
import static redis_request.RedisRequestOuterClass.RequestType.HashSet;
import static redis_request.RedisRequestOuterClass.RequestType.Hvals;
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
import static redis_request.RedisRequestOuterClass.RequestType.IncrByFloat;
Expand Down Expand Up @@ -1021,6 +1022,30 @@ public void hdel_success() {
assertEquals(value, payload);
}

@SneakyThrows
@Test
public void hvals_success() {
// setup
String key = "testKey";
String[] args = {key};
String[] values = new String[] {"value1", "value2"};

CompletableFuture<String[]> testResponse = new CompletableFuture<>();
testResponse.complete(values);

// match on protobuf request
when(commandManager.<String[]>submitNewCommand(eq(Hvals), eq(args), any()))
.thenReturn(testResponse);

// exercise
CompletableFuture<String[]> response = service.hvals(key);
String[] payload = response.get();

// verify
assertEquals(testResponse, response);
assertEquals(values, payload);
}

@SneakyThrows
@Test
public void hmget_success() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.HashIncrByFloat;
import static redis_request.RedisRequestOuterClass.RequestType.HashMGet;
import static redis_request.RedisRequestOuterClass.RequestType.HashSet;
import static redis_request.RedisRequestOuterClass.RequestType.Hvals;
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
import static redis_request.RedisRequestOuterClass.RequestType.IncrByFloat;
Expand Down Expand Up @@ -169,6 +170,9 @@ public void transaction_builds_protobuf_request(BaseTransaction<?> transaction)
transaction.hdel("key", new String[] {"field"});
results.add(Pair.of(HashDel, ArgsArray.newBuilder().addArgs("key").addArgs("field").build()));

transaction.hvals("key");
results.add(Pair.of(Hvals, ArgsArray.newBuilder().addArgs("key").build()));

transaction.hmget("key", new String[] {"field"});
results.add(Pair.of(HashMGet, ArgsArray.newBuilder().addArgs("key").addArgs("field").build()));

Expand Down
27 changes: 27 additions & 0 deletions java/integTest/src/test/java/glide/SharedCommandTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import glide.api.models.configuration.RedisClusterClientConfiguration;
import glide.api.models.exceptions.RequestException;
import java.time.Instant;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -471,6 +472,32 @@ public void hdel_multiple_existing_fields_non_existing_field_non_existing_key(Ba
assertEquals(0, client.hdel("non_existing_key", new String[] {field3}).get());
}

@SneakyThrows
@ParameterizedTest
@MethodSource("getClients")
public void hvals(BaseClient client) {
String key1 = UUID.randomUUID().toString();
String key2 = UUID.randomUUID().toString();
String field1 = UUID.randomUUID().toString();
String field2 = UUID.randomUUID().toString();
Map<String, String> fieldValueMap = Map.of(field1, "value1", field2, "value2");

assertEquals(2, client.hset(key1, fieldValueMap).get());

String[] hvalsPayload = client.hvals(key1).get();
Arrays.sort(hvalsPayload); // ordering for values by hvals is not guaranteed
assertArrayEquals(new String[] {"value1", "value2"}, hvalsPayload);

assertEquals(1, client.hdel(key1, new String[] {field1}).get());
assertArrayEquals(new String[] {"value2"}, client.hvals(key1).get());
assertArrayEquals(new String[] {}, client.hvals("nonExistingKey").get());

assertEquals(OK, client.set(key2, "value2").get());
ExecutionException executionException =
assertThrows(ExecutionException.class, () -> client.hvals(key2).get());
assertTrue(executionException.getCause() instanceof RequestException);
}

@SneakyThrows
@ParameterizedTest
@MethodSource("getClients")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public static BaseTransaction<?> transactionTest(BaseTransaction<?> baseTransact
baseTransaction.hmget(key4, new String[] {field1, "non_existing_field", field2});
baseTransaction.hgetall(key4);
baseTransaction.hdel(key4, new String[] {field1});
baseTransaction.hvals(key4);

baseTransaction.hincrBy(key4, field3, 5);
baseTransaction.hincrByFloat(key4, field3, 5.5);
Expand Down Expand Up @@ -134,6 +135,7 @@ public static Object[] transactionTestResult() {
new String[] {value1, null, value2},
Map.of(field1, value1, field2, value2),
1L,
new String[] {value2}, // hvals(key4)
5L,
10.5,
5L,
Expand Down

0 comments on commit 5acc058

Please sign in to comment.