Skip to content

Commit

Permalink
Java: Add GETBIT command (#1400)
Browse files Browse the repository at this point in the history
* JAVA: Add `GETBIT` command (#271)

Signed-off-by: Guian Gumpac <[email protected]>
Co-authored-by: jonathanl-bq <[email protected]>
  • Loading branch information
GumpacG and jonathanl-bq authored May 22, 2024
1 parent 2f1fb6e commit 4277b97
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 34 deletions.
3 changes: 2 additions & 1 deletion glide-core/src/protobuf/redis_request.proto
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,12 @@ enum RequestType {
BZPopMin = 137;
FlushAll = 138;
ZRandMember = 139;
Bitcount = 140;
BitCount = 140;
BZMPop = 141;
SetBit = 142;
ZInterCard = 143;
ZMPop = 144;
GetBit = 145;
}

message Command {
Expand Down
9 changes: 6 additions & 3 deletions glide-core/src/request_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,12 @@ pub enum RequestType {
BZPopMin = 137,
FlushAll = 138,
ZRandMember = 139,
Bitcount = 140,
BitCount = 140,
BZMPop = 141,
SetBit = 142,
ZInterCard = 143,
ZMPop = 144,
GetBit = 145,
}

fn get_two_word_command(first: &str, second: &str) -> Cmd {
Expand Down Expand Up @@ -306,11 +307,12 @@ impl From<::protobuf::EnumOrUnknown<ProtobufRequestType>> for RequestType {
ProtobufRequestType::BZPopMin => RequestType::BZPopMin,
ProtobufRequestType::FlushAll => RequestType::FlushAll,
ProtobufRequestType::ZRandMember => RequestType::ZRandMember,
ProtobufRequestType::Bitcount => RequestType::Bitcount,
ProtobufRequestType::BitCount => RequestType::BitCount,
ProtobufRequestType::BZMPop => RequestType::BZMPop,
ProtobufRequestType::SetBit => RequestType::SetBit,
ProtobufRequestType::ZInterCard => RequestType::ZInterCard,
ProtobufRequestType::ZMPop => RequestType::ZMPop,
ProtobufRequestType::GetBit => RequestType::GetBit,
}
}
}
Expand Down Expand Up @@ -459,11 +461,12 @@ impl RequestType {
RequestType::BZPopMin => Some(cmd("BZPOPMIN")),
RequestType::FlushAll => Some(cmd("FLUSHALL")),
RequestType::ZRandMember => Some(cmd("ZRANDMEMBER")),
RequestType::Bitcount => Some(cmd("BITCOUNT")),
RequestType::BitCount => Some(cmd("BITCOUNT")),
RequestType::BZMPop => Some(cmd("BZMPOP")),
RequestType::SetBit => Some(cmd("SETBIT")),
RequestType::ZInterCard => Some(cmd("ZINTERCARD")),
RequestType::ZMPop => Some(cmd("ZMPOP")),
RequestType::GetBit => Some(cmd("GETBIT")),
}
}
}
17 changes: 12 additions & 5 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.BZMPop;
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMax;
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMin;
import static redis_request.RedisRequestOuterClass.RequestType.Bitcount;
import static redis_request.RedisRequestOuterClass.RequestType.BitCount;
import static redis_request.RedisRequestOuterClass.RequestType.Decr;
import static redis_request.RedisRequestOuterClass.RequestType.DecrBy;
import static redis_request.RedisRequestOuterClass.RequestType.Del;
Expand All @@ -25,6 +25,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.GeoHash;
import static redis_request.RedisRequestOuterClass.RequestType.GeoPos;
import static redis_request.RedisRequestOuterClass.RequestType.Get;
import static redis_request.RedisRequestOuterClass.RequestType.GetBit;
import static redis_request.RedisRequestOuterClass.RequestType.GetRange;
import static redis_request.RedisRequestOuterClass.RequestType.HDel;
import static redis_request.RedisRequestOuterClass.RequestType.HExists;
Expand Down Expand Up @@ -124,7 +125,6 @@
import glide.api.commands.StreamBaseCommands;
import glide.api.commands.StringBaseCommands;
import glide.api.models.Script;
import glide.api.models.commands.BitmapIndexType;
import glide.api.models.commands.ExpireOptions;
import glide.api.models.commands.LInsertOptions.InsertPosition;
import glide.api.models.commands.RangeOptions;
Expand All @@ -138,6 +138,7 @@
import glide.api.models.commands.WeightAggregateOptions.Aggregate;
import glide.api.models.commands.WeightAggregateOptions.KeysOrWeightedKeys;
import glide.api.models.commands.ZAddOptions;
import glide.api.models.commands.bitmap.BitmapIndexType;
import glide.api.models.commands.geospatial.GeoAddOptions;
import glide.api.models.commands.geospatial.GeoUnit;
import glide.api.models.commands.geospatial.GeospatialData;
Expand Down Expand Up @@ -1288,13 +1289,13 @@ public CompletableFuture<String[]> geohash(@NonNull String key, @NonNull String[

@Override
public CompletableFuture<Long> bitcount(@NonNull String key) {
return commandManager.submitNewCommand(Bitcount, new String[] {key}, this::handleLongResponse);
return commandManager.submitNewCommand(BitCount, new String[] {key}, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> bitcount(@NonNull String key, long start, long end) {
return commandManager.submitNewCommand(
Bitcount,
BitCount,
new String[] {key, Long.toString(start), Long.toString(end)},
this::handleLongResponse);
}
Expand All @@ -1304,12 +1305,18 @@ public CompletableFuture<Long> bitcount(
@NonNull String key, long start, long end, @NonNull BitmapIndexType options) {
String[] arguments =
new String[] {key, Long.toString(start), Long.toString(end), options.toString()};
return commandManager.submitNewCommand(Bitcount, arguments, this::handleLongResponse);
return commandManager.submitNewCommand(BitCount, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> setbit(@NonNull String key, long offset, long value) {
String[] arguments = new String[] {key, Long.toString(offset), Long.toString(value)};
return commandManager.submitNewCommand(SetBit, arguments, this::handleLongResponse);
}

@Override
public CompletableFuture<Long> getbit(@NonNull String key, long offset) {
String[] arguments = new String[] {key, Long.toString(offset)};
return commandManager.submitNewCommand(GetBit, arguments, this::handleLongResponse);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.api.commands;

import glide.api.models.commands.BitmapIndexType;
import glide.api.models.commands.bitmap.BitmapIndexType;
import java.util.concurrent.CompletableFuture;

/**
Expand Down Expand Up @@ -95,4 +95,22 @@ public interface BitmapBaseCommands {
* }</pre>
*/
CompletableFuture<Long> setbit(String key, long offset, long value);

/**
* Returns the bit value at <code>offset</code> in the string value stored at <code>key</code>.
* <code>offset</code> should be greater than or equal to zero.
*
* @see <a href="https://redis.io/commands/getbit/">redis.io</a> for details.
* @param key The key of the string.
* @param offset The index of the bit to return.
* @return The bit at offset of the string. Returns zero if the key is empty or if the positive
* <code>offset</code> exceeds the length of the string.
* @example
* <pre>{@code
* client.set("sampleKey", "A"); // "A" has binary value 01000001
* Long payload = client.getbit("sampleKey", 1).get();
* assert payload == 1L; // The second bit for string stored at "sampleKey" is set to 1.
* }</pre>
*/
CompletableFuture<Long> getbit(String key, long offset);
}
27 changes: 22 additions & 5 deletions java/client/src/main/java/glide/api/models/BaseTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.BZMPop;
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMax;
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMin;
import static redis_request.RedisRequestOuterClass.RequestType.Bitcount;
import static redis_request.RedisRequestOuterClass.RequestType.BitCount;
import static redis_request.RedisRequestOuterClass.RequestType.ClientGetName;
import static redis_request.RedisRequestOuterClass.RequestType.ClientId;
import static redis_request.RedisRequestOuterClass.RequestType.ConfigGet;
Expand All @@ -37,6 +37,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.GeoHash;
import static redis_request.RedisRequestOuterClass.RequestType.GeoPos;
import static redis_request.RedisRequestOuterClass.RequestType.Get;
import static redis_request.RedisRequestOuterClass.RequestType.GetBit;
import static redis_request.RedisRequestOuterClass.RequestType.GetRange;
import static redis_request.RedisRequestOuterClass.RequestType.HDel;
import static redis_request.RedisRequestOuterClass.RequestType.HExists;
Expand Down Expand Up @@ -130,7 +131,6 @@
import static redis_request.RedisRequestOuterClass.RequestType.ZUnion;
import static redis_request.RedisRequestOuterClass.RequestType.ZUnionStore;

import glide.api.models.commands.BitmapIndexType;
import glide.api.models.commands.ExpireOptions;
import glide.api.models.commands.FlushMode;
import glide.api.models.commands.InfoOptions;
Expand Down Expand Up @@ -158,6 +158,7 @@
import glide.api.models.commands.WeightAggregateOptions.KeysOrWeightedKeys;
import glide.api.models.commands.WeightAggregateOptions.WeightedKeys;
import glide.api.models.commands.ZAddOptions;
import glide.api.models.commands.bitmap.BitmapIndexType;
import glide.api.models.commands.geospatial.GeoAddOptions;
import glide.api.models.commands.geospatial.GeoUnit;
import glide.api.models.commands.geospatial.GeospatialData;
Expand Down Expand Up @@ -2964,7 +2965,7 @@ public T touch(@NonNull String[] keys) {
*/
public T bitcount(@NonNull String key) {
ArgsArray commandArgs = buildArgs(key);
protobufTransaction.addCommands(buildCommand(Bitcount, commandArgs));
protobufTransaction.addCommands(buildCommand(BitCount, commandArgs));
return getThis();
}

Expand All @@ -2987,7 +2988,7 @@ public T bitcount(@NonNull String key) {
public T bitcount(@NonNull String key, long start, long end) {
ArgsArray commandArgs = buildArgs(key, Long.toString(start), Long.toString(end));

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

Expand All @@ -3014,7 +3015,7 @@ public T bitcount(@NonNull String key, long start, long end, BitmapIndexType opt
ArgsArray commandArgs =
buildArgs(key, Long.toString(start), Long.toString(end), options.toString());

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

Expand Down Expand Up @@ -3159,6 +3160,22 @@ public T setbit(@NonNull String key, long offset, long value) {
return getThis();
}

/**
* Returns the bit value at <code>offset</code> in the string value stored at <code>key</code>.
* <code>offset</code> should be greater than or equal to zero.
*
* @see <a href="https://redis.io/commands/getbit/">redis.io</a> for details.
* @param key The key of the string.
* @param offset The index of the bit to return.
* @return Command Response - The bit at offset of the string. Returns zero if the key is empty or
* if the positive <code>offset</code> exceeds the length of the string.
*/
public T getbit(@NonNull String key, long offset) {
ArgsArray commandArgs = buildArgs(key, Long.toString(offset));
protobufTransaction.addCommands(buildCommand(GetBit, commandArgs));
return getThis();
}

/** Build protobuf {@link Command} object for given command and arguments. */
protected Command buildCommand(RequestType requestType) {
return buildCommand(requestType, buildArgs());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.api.models.commands;
package glide.api.models.commands.bitmap;

import glide.api.commands.BitmapBaseCommands;

Expand Down
33 changes: 28 additions & 5 deletions java/client/src/test/java/glide/api/RedisClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.BZMPop;
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMax;
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMin;
import static redis_request.RedisRequestOuterClass.RequestType.Bitcount;
import static redis_request.RedisRequestOuterClass.RequestType.BitCount;
import static redis_request.RedisRequestOuterClass.RequestType.ClientGetName;
import static redis_request.RedisRequestOuterClass.RequestType.ClientId;
import static redis_request.RedisRequestOuterClass.RequestType.ConfigGet;
Expand All @@ -58,6 +58,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.GeoHash;
import static redis_request.RedisRequestOuterClass.RequestType.GeoPos;
import static redis_request.RedisRequestOuterClass.RequestType.Get;
import static redis_request.RedisRequestOuterClass.RequestType.GetBit;
import static redis_request.RedisRequestOuterClass.RequestType.GetRange;
import static redis_request.RedisRequestOuterClass.RequestType.HDel;
import static redis_request.RedisRequestOuterClass.RequestType.HExists;
Expand Down Expand Up @@ -153,7 +154,6 @@

import glide.api.models.Script;
import glide.api.models.Transaction;
import glide.api.models.commands.BitmapIndexType;
import glide.api.models.commands.ConditionalChange;
import glide.api.models.commands.ExpireOptions;
import glide.api.models.commands.InfoOptions;
Expand All @@ -173,6 +173,7 @@
import glide.api.models.commands.WeightAggregateOptions.KeyArray;
import glide.api.models.commands.WeightAggregateOptions.WeightedKeys;
import glide.api.models.commands.ZAddOptions;
import glide.api.models.commands.bitmap.BitmapIndexType;
import glide.api.models.commands.geospatial.GeoAddOptions;
import glide.api.models.commands.geospatial.GeoUnit;
import glide.api.models.commands.geospatial.GeospatialData;
Expand Down Expand Up @@ -4329,7 +4330,7 @@ public void bitcount_returns_success() {
testResponse.complete(bitcount);

// match on protobuf request
when(commandManager.<Long>submitNewCommand(eq(Bitcount), eq(new String[] {key}), any()))
when(commandManager.<Long>submitNewCommand(eq(BitCount), eq(new String[] {key}), any()))
.thenReturn(testResponse);

// exercise
Expand All @@ -4352,7 +4353,7 @@ public void bitcount_indices_returns_success() {

// match on protobuf request
when(commandManager.<Long>submitNewCommand(
eq(Bitcount), eq(new String[] {key, "1", "2"}), any()))
eq(BitCount), eq(new String[] {key, "1", "2"}), any()))
.thenReturn(testResponse);

// exercise
Expand All @@ -4375,7 +4376,7 @@ public void bitcount_indices_with_option_returns_success() {

// match on protobuf request
when(commandManager.<Long>submitNewCommand(
eq(Bitcount), eq(new String[] {key, "1", "2", "BIT"}), any()))
eq(BitCount), eq(new String[] {key, "1", "2", "BIT"}), any()))
.thenReturn(testResponse);

// exercise
Expand Down Expand Up @@ -4408,4 +4409,26 @@ public void setbit_returns_success() {
assertEquals(testResponse, response);
assertEquals(value, payload);
}

@SneakyThrows
@Test
public void getbit_returns_success() {
// setup
String key = "testKey";
Long bit = 1L;
CompletableFuture<Long> testResponse = new CompletableFuture<>();
testResponse.complete(bit);

// match on protobuf request
when(commandManager.<Long>submitNewCommand(eq(GetBit), eq(new String[] {key, "8"}), any()))
.thenReturn(testResponse);

// exercise
CompletableFuture<Long> response = service.getbit(key, 8);
Long payload = response.get();

// verify
assertEquals(testResponse, response);
assertEquals(bit, payload);
}
}
14 changes: 9 additions & 5 deletions java/client/src/test/java/glide/api/models/TransactionTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.BZMPop;
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMax;
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMin;
import static redis_request.RedisRequestOuterClass.RequestType.Bitcount;
import static redis_request.RedisRequestOuterClass.RequestType.BitCount;
import static redis_request.RedisRequestOuterClass.RequestType.ClientGetName;
import static redis_request.RedisRequestOuterClass.RequestType.ClientId;
import static redis_request.RedisRequestOuterClass.RequestType.ConfigGet;
Expand All @@ -48,6 +48,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.GeoHash;
import static redis_request.RedisRequestOuterClass.RequestType.GeoPos;
import static redis_request.RedisRequestOuterClass.RequestType.Get;
import static redis_request.RedisRequestOuterClass.RequestType.GetBit;
import static redis_request.RedisRequestOuterClass.RequestType.GetRange;
import static redis_request.RedisRequestOuterClass.RequestType.HDel;
import static redis_request.RedisRequestOuterClass.RequestType.HExists;
Expand Down Expand Up @@ -141,7 +142,6 @@
import static redis_request.RedisRequestOuterClass.RequestType.ZUnion;
import static redis_request.RedisRequestOuterClass.RequestType.ZUnionStore;

import glide.api.models.commands.BitmapIndexType;
import glide.api.models.commands.ConditionalChange;
import glide.api.models.commands.InfoOptions;
import glide.api.models.commands.RangeOptions;
Expand All @@ -157,6 +157,7 @@
import glide.api.models.commands.WeightAggregateOptions.KeyArray;
import glide.api.models.commands.WeightAggregateOptions.WeightedKeys;
import glide.api.models.commands.ZAddOptions;
import glide.api.models.commands.bitmap.BitmapIndexType;
import glide.api.models.commands.geospatial.GeoAddOptions;
import glide.api.models.commands.geospatial.GeoUnit;
import glide.api.models.commands.geospatial.GeospatialData;
Expand Down Expand Up @@ -708,6 +709,9 @@ InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3, false), new Limit(1, 2)),
transaction.geoadd("key", Map.of("Place", new GeospatialData(10.0, 20.0)));
results.add(Pair.of(GeoAdd, buildArgs("key", "10.0", "20.0", "Place")));

transaction.getbit("key", 1);
results.add(Pair.of(GetBit, buildArgs("key", "1")));

transaction.geoadd(
"key",
Map.of("Place", new GeospatialData(10.0, 20.0)),
Expand All @@ -734,13 +738,13 @@ InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3, false), new Limit(1, 2)),
results.add(Pair.of(GeoHash, buildArgs("key", "Place")));

transaction.bitcount("key");
results.add(Pair.of(Bitcount, buildArgs("key")));
results.add(Pair.of(BitCount, buildArgs("key")));

transaction.bitcount("key", 1, 1);
results.add(Pair.of(Bitcount, buildArgs("key", "1", "1")));
results.add(Pair.of(BitCount, buildArgs("key", "1", "1")));

transaction.bitcount("key", 1, 1, BitmapIndexType.BIT);
results.add(Pair.of(Bitcount, buildArgs("key", "1", "1", BitmapIndexType.BIT.toString())));
results.add(Pair.of(BitCount, buildArgs("key", "1", "1", BitmapIndexType.BIT.toString())));

transaction.setbit("key", 8, 1);
results.add(Pair.of(SetBit, buildArgs("key", "8", "1")));
Expand Down
Loading

0 comments on commit 4277b97

Please sign in to comment.