diff --git a/.github/wordlist.txt b/.github/wordlist.txt index 3b520260ae..628c5cf647 100644 --- a/.github/wordlist.txt +++ b/.github/wordlist.txt @@ -176,6 +176,9 @@ hincrByFloat hiredis hlen hset +hgetdel +hgetex +hsetex hsetnx hstrlen http diff --git a/src/main/java/redis/clients/jedis/CommandObjects.java b/src/main/java/redis/clients/jedis/CommandObjects.java index 27eeb1f0fe..6588303f14 100644 --- a/src/main/java/redis/clients/jedis/CommandObjects.java +++ b/src/main/java/redis/clients/jedis/CommandObjects.java @@ -21,8 +21,6 @@ import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.json.*; import redis.clients.jedis.json.JsonProtocol.JsonCommand; -import redis.clients.jedis.json.DefaultGsonObjectMapper; -import redis.clients.jedis.json.JsonObjectMapper; import redis.clients.jedis.params.*; import redis.clients.jedis.resps.*; import redis.clients.jedis.search.*; @@ -1020,10 +1018,30 @@ public final CommandObject hset(String key, Map hash) { return new CommandObject<>(addFlatMapArgs(commandArguments(HSET).key(key), hash), BuilderFactory.LONG); } + public final CommandObject hsetex(String key, HSetExParams params, String field, String value) { + return new CommandObject<>(commandArguments(HSETEX).key(key) + .addParams(params).add(FIELDS).add(1).add(field).add(value), BuilderFactory.LONG); + } + + public final CommandObject hsetex(String key, HSetExParams params, Map hash) { + return new CommandObject<>(addFlatMapArgs(commandArguments(HSETEX).key(key) + .addParams(params).add(FIELDS).add(hash.size()), hash), BuilderFactory.LONG); + } + public final CommandObject hget(String key, String field) { return new CommandObject<>(commandArguments(HGET).key(key).add(field), BuilderFactory.STRING); } + public final CommandObject> hgetex(String key, HGetExParams params, String... fields) { + return new CommandObject<>(commandArguments(Command.HGETEX).key(key) + .addParams(params).add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.STRING_LIST); + } + + public final CommandObject> hgetdel(String key, String... fields) { + return new CommandObject<>(commandArguments(HGETDEL).key(key) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.STRING_LIST); + } + public final CommandObject hsetnx(String key, String field, String value) { return new CommandObject<>(commandArguments(HSETNX).key(key).add(field).add(value), BuilderFactory.LONG); } @@ -1044,10 +1062,30 @@ public final CommandObject hset(byte[] key, Map hash) { return new CommandObject<>(addFlatMapArgs(commandArguments(HSET).key(key), hash), BuilderFactory.LONG); } + public final CommandObject hsetex(byte[] key, HSetExParams params, byte[] field, byte[] value) { + return new CommandObject<>(commandArguments(HSETEX).key(key) + .addParams(params).add(FIELDS).add(1).add(field).add(value), BuilderFactory.LONG); + } + + public final CommandObject hsetex(byte[] key, HSetExParams params, Map hash) { + return new CommandObject<>(addFlatMapArgs(commandArguments(HSETEX).key(key) + .addParams(params).add(FIELDS).add(hash.size()), hash), BuilderFactory.LONG); + } + public final CommandObject hget(byte[] key, byte[] field) { return new CommandObject<>(commandArguments(HGET).key(key).add(field), BuilderFactory.BINARY); } + public final CommandObject> hgetex(byte[] key, HGetExParams params, byte[]... fields) { + return new CommandObject<>(commandArguments(Command.HGETEX).key(key) + .addParams(params).add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.BINARY_LIST); + } + + public final CommandObject> hgetdel(byte[] key, byte[]... fields) { + return new CommandObject<>(commandArguments(HGETDEL).key(key).add(FIELDS) + .add(fields.length).addObjects((Object[]) fields), BuilderFactory.BINARY_LIST); + } + public final CommandObject hsetnx(byte[] key, byte[] field, byte[] value) { return new CommandObject<>(commandArguments(HSETNX).key(key).add(field).add(value), BuilderFactory.LONG); } diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java index b598d79d07..e47ea960b2 100644 --- a/src/main/java/redis/clients/jedis/Jedis.java +++ b/src/main/java/redis/clients/jedis/Jedis.java @@ -1167,6 +1167,18 @@ public long hset(final byte[] key, final Map hash) { return connection.executeCommand(commandObjects.hset(key, hash)); } + @Override + public long hsetex(byte[] key, HSetExParams params, byte[] field, byte[] value) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hsetex(key, params, field, value)); + } + + @Override + public long hsetex(byte[] key, HSetExParams params, Map hash){ + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hsetex(key, params, hash)); + } + /** * If key holds a hash, retrieve the value associated to the specified field. *

@@ -1183,6 +1195,18 @@ public byte[] hget(final byte[] key, final byte[] field) { return connection.executeCommand(commandObjects.hget(key, field)); } + @Override + public List hgetex(byte[] key, HGetExParams params, byte[]... fields){ + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hgetex(key, params, fields)); + } + + @Override + public List hgetdel(byte[] key, byte[]... fields){ + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hgetdel(key, fields)); + } + /** * Set the specified hash field to the specified value if the field not exists. Time * complexity: O(1) @@ -5687,6 +5711,18 @@ public long hset(final String key, final Map hash) { return connection.executeCommand(commandObjects.hset(key, hash)); } + @Override + public long hsetex(String key, HSetExParams params, String field, String value) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hsetex(key, params, field, value)); + } + + @Override + public long hsetex(String key, HSetExParams params, Map hash) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hsetex(key, params, hash)); + } + /** * If key holds a hash, retrieve the value associated to the specified field. *

@@ -5703,6 +5739,18 @@ public String hget(final String key, final String field) { return connection.executeCommand(commandObjects.hget(key, field)); } + @Override + public List hgetex(String key, HGetExParams params, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hgetex(key, params, fields)); + } + + @Override + public List hgetdel(String key, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hgetdel(key, fields)); + } + /** * Set the specified hash field to the specified value if the field not exists. Time * complexity: O(1) diff --git a/src/main/java/redis/clients/jedis/PipeliningBase.java b/src/main/java/redis/clients/jedis/PipeliningBase.java index 2e9f808e8f..728c99c109 100644 --- a/src/main/java/redis/clients/jedis/PipeliningBase.java +++ b/src/main/java/redis/clients/jedis/PipeliningBase.java @@ -625,11 +625,77 @@ public Response hset(String key, Map hash) { return appendCommand(commandObjects.hset(key, hash)); } + /** + * Sets the specified field in the hash stored at key to the specified value with additional parameters, + * and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters. + * This command can overwrite any existing fields in the hash. + * If key does not exist, a new key holding a hash is created. + * + * @param key the key of the hash + * @param params additional parameters for the HSETEX command + * @param field the field in the hash to set + * @param value the value to set in the specified field + * @return 0 if no fields were set, 1 if all the fields were set + * + * @see HSetExParams + */ + @Override + public Response hsetex(String key, HSetExParams params, String field, String value) { + return appendCommand(commandObjects.hsetex(key, params, field, value)); + } + + /** + * Sets the specified fields in the hash stored at key to the specified values with additional parameters, + * and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters. + * This command can overwrite any existing fields in the hash. + * If key does not exist, a new key holding a hash is created. + * + * @param key the key of the hash + * @param params the parameters for the HSetEx command + * @param hash the map containing field-value pairs to set in the hash + * @return 0 if no fields were set, 1 if all the fields were set + * + * @see HSetExParams + */ + @Override + public Response hsetex(String key, HSetExParams params, Map hash) { + return appendCommand(commandObjects.hsetex(key, params, hash)); + } + @Override public Response hget(String key, String field) { return appendCommand(commandObjects.hget(key, field)); } + /** + * Retrieves the values associated with the specified fields in a hash stored at the given key + * and optionally sets their expiration. Use `HGetExParams` object to specify expiration parameters. + * + * @param key the key of the hash + * @param params additional parameters for the HGETEX command + * @param fields the fields whose values are to be retrieved + * @return a list of the value associated with each field or nil if the field doesn’t exist. + * + * @see HGetExParams + */ + @Override + public Response> hgetex(String key, HGetExParams params, String... fields) { + return appendCommand(commandObjects.hgetex(key, params, fields)); + } + + /** + * Retrieves the values associated with the specified fields in the hash stored at the given key + * and then deletes those fields from the hash. + * + * @param key the key of the hash + * @param fields the fields whose values are to be retrieved and then deleted + * @return a list of values associated with the specified fields before they were deleted + */ + @Override + public Response> hgetdel(String key, String... fields) { + return appendCommand(commandObjects.hgetdel(key, fields)); + } + @Override public Response hsetnx(String key, String field, String value) { return appendCommand(commandObjects.hsetnx(key, field, value)); @@ -1971,10 +2037,76 @@ public Response hset(byte[] key, Map hash) { return appendCommand(commandObjects.hset(key, hash)); } + /** + * Sets the specified field in the hash stored at key to the specified value with additional parameters, + * and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters. + * This command can overwrite any existing fields in the hash. + * If key does not exist, a new key holding a hash is created. + * + * @param key the key of the hash + * @param params the parameters for the HSetEx command + * @param field the field in the hash to set + * @param value the value to set in the specified field + * @return 0 if no fields were set, 1 if all the fields were set + * + * @see HSetExParams + */ + @Override + public Response hsetex(byte[] key, HSetExParams params, byte[] field, byte[] value) { + return appendCommand(commandObjects.hsetex(key, params, field, value)); + } + + /** + * Sets the specified fields in the hash stored at key to the specified values with additional parameters, + * and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters. + * This command can overwrite any existing fields in the hash. + * If key does not exist, a new key holding a hash is created. + * + * @param key the key of the hash + * @param params the parameters for the HSetEx command + * @param hash the map containing field-value pairs to set in the hash + * @return 0 if no fields were set, 1 if all the fields were set + * + * @see HSetExParams + */ + @Override + public Response hsetex(byte[] key, HSetExParams params, Map hash) { + return appendCommand(commandObjects.hsetex(key, params, hash)); + } + @Override public Response hget(byte[] key, byte[] field) { return appendCommand(commandObjects.hget(key, field)); } + + /** + * Retrieves the values associated with the specified fields in a hash stored at the given key + * and optionally sets their expiration. Use `HGetExParams` object to specify expiration parameters. + * + * @param key the key of the hash + * @param params additional parameters for the HGETEX command + * @param fields the fields whose values are to be retrieved + * @return a list of the value associated with each field or nil if the field doesn’t exist. + * + * @see HGetExParams + */ + @Override + public Response> hgetex(byte[] key, HGetExParams params, byte[]... fields) { + return appendCommand(commandObjects.hgetex(key, params, fields)); + } + + /** + * Retrieves the values associated with the specified fields in the hash stored at the given key + * and then deletes those fields from the hash. + * + * @param key the key of the hash + * @param fields the fields whose values are to be retrieved and then deleted + * @return a list of values associated with the specified fields before they were deleted + */ + @Override + public Response> hgetdel(byte[] key, byte[]... fields) { + return appendCommand(commandObjects.hgetdel(key, fields)); + } @Override public Response hsetnx(byte[] key, byte[] field, byte[] value) { diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index 88bcc849c8..6d59a8b913 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -292,7 +292,7 @@ public static enum Command implements ProtocolCommand { SETBIT, GETBIT, BITPOS, SETRANGE, GETRANGE, BITCOUNT, BITOP, BITFIELD, BITFIELD_RO, // <-- bit (string) HSET, HGET, HSETNX, HMSET, HMGET, HINCRBY, HEXISTS, HDEL, HLEN, HKEYS, HVALS, HGETALL, HSTRLEN, HEXPIRE, HPEXPIRE, HEXPIREAT, HPEXPIREAT, HTTL, HPTTL, HEXPIRETIME, HPEXPIRETIME, HPERSIST, - HRANDFIELD, HINCRBYFLOAT, // <-- hash + HRANDFIELD, HINCRBYFLOAT, HSETEX, HGETEX, HGETDEL, // <-- hash RPUSH, LPUSH, LLEN, LRANGE, LTRIM, LINDEX, LSET, LREM, LPOP, RPOP, BLPOP, BRPOP, LINSERT, LPOS, RPOPLPUSH, BRPOPLPUSH, BLMOVE, LMOVE, LMPOP, BLMPOP, LPUSHX, RPUSHX, // <-- list SADD, SMEMBERS, SREM, SPOP, SMOVE, SCARD, SRANDMEMBER, SINTER, SINTERSTORE, SUNION, SUNIONSTORE, @@ -339,7 +339,7 @@ public static enum Keyword implements Rawable { DELETE, LIBRARYNAME, WITHCODE, DESCRIPTION, GETKEYS, GETKEYSANDFLAGS, DOCS, FILTERBY, DUMP, MODULE, ACLCAT, PATTERN, DOCTOR, LATEST, HISTORY, USAGE, SAMPLES, PURGE, STATS, LOADEX, CONFIG, ARGS, RANK, NOW, VERSION, ADDR, SKIPME, USER, LADDR, FIELDS, - CHANNELS, NUMPAT, NUMSUB, SHARDCHANNELS, SHARDNUMSUB, NOVALUES, MAXAGE; + CHANNELS, NUMPAT, NUMSUB, SHARDCHANNELS, SHARDNUMSUB, NOVALUES, MAXAGE, FXX, FNX; private final byte[] raw; diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index 719627acfa..4b2e38faac 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -1479,10 +1479,30 @@ public long hset(String key, Map hash) { return executeCommand(commandObjects.hset(key, hash)); } + @Override + public long hsetex(String key, HSetExParams params, String field, String value) { + return executeCommand(commandObjects.hsetex(key, params, field, value)); + } + + @Override + public long hsetex(String key, HSetExParams params, Map hash) { + return executeCommand(commandObjects.hsetex(key, params, hash)); + } + @Override public String hget(String key, String field) { return executeCommand(commandObjects.hget(key, field)); } + + @Override + public List hgetex(String key, HGetExParams params, String... fields) { + return executeCommand(commandObjects.hgetex(key, params, fields)); + } + + @Override + public List hgetdel(String key, String... fields) { + return executeCommand(commandObjects.hgetdel(key, fields)); + } @Override public long hsetnx(String key, String field, String value) { @@ -1509,11 +1529,31 @@ public long hset(byte[] key, Map hash) { return executeCommand(commandObjects.hset(key, hash)); } + @Override + public long hsetex(byte[] key, HSetExParams params, byte[] field, byte[] value) { + return executeCommand(commandObjects.hsetex(key, params, field, value)); + } + + @Override + public long hsetex(byte[] key, HSetExParams params, Map hash) { + return executeCommand(commandObjects.hsetex(key, params, hash)); + } + @Override public byte[] hget(byte[] key, byte[] field) { return executeCommand(commandObjects.hget(key, field)); } + @Override + public List hgetex(byte[] key, HGetExParams params, byte[]... fields) { + return executeCommand(commandObjects.hgetex(key, params, fields)); + } + + @Override + public List hgetdel(byte[] key, byte[]... fields) { + return executeCommand(commandObjects.hgetdel(key, fields)); + } + @Override public long hsetnx(byte[] key, byte[] field, byte[] value) { return executeCommand(commandObjects.hsetnx(key, field, value)); diff --git a/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java index f32eca202e..939d9fda6f 100644 --- a/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java @@ -5,6 +5,8 @@ import java.util.Set; import redis.clients.jedis.args.ExpiryOption; +import redis.clients.jedis.params.HGetExParams; +import redis.clients.jedis.params.HSetExParams; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -14,8 +16,62 @@ public interface HashBinaryCommands { long hset(byte[] key, Map hash); + /** + * Sets the specified fields in the hash stored at key to the specified values with additional parameters, + * and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters. + * This command can overwrite any existing fields in the hash. + * If key does not exist, a new key holding a hash is created. + * + * @param key the key of the hash + * @param params the parameters for the HSETEX command + * @param field the field in the hash + * @param value the value to set + * @return 0 if no fields were set, 1 if all the fields were set + * + * @see HSetExParams + */ + long hsetex(byte[] key, HSetExParams params, byte[] field, byte[] value); + + /** + * Sets the specified fields in the hash stored at key to the specified values with additional parameters, + * and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters. + * This command can overwrite any existing fields in the hash. + * If key does not exist, a new key holding a hash is created. + * + * @param key the key of the hash + * @param params the parameters for the HSETEX command + * @param hash the map containing field-value pairs to set in the hash + * @return 0 if no fields were set, 1 if all the fields were set + * + * @see HSetExParams + */ + long hsetex(byte[] key, HSetExParams params, Map hash); + byte[] hget(byte[] key, byte[] field); + /** + * Retrieves the values associated with the specified fields in a hash stored at the given key + * and optionally sets their expiration. Use `HGetExParams` object to specify expiration parameters. + * + * @param key the key of the hash + * @param params additional parameters for the HGETEX command + * @param fields the fields whose values are to be retrieved + * @return a list of the value associated with each field or nil if the field doesn’t exist. + * + * @see HGetExParams + */ + List hgetex(byte[] key, HGetExParams params, byte[]... fields); + + /** + * Retrieves the values associated with the specified fields in the hash stored at the given key + * and then deletes those fields from the hash. + * + * @param key the key of the hash + * @param fields the fields whose values are to be retrieved and then deleted + * @return a list of values associated with the specified fields before they were deleted + */ + List hgetdel(byte[] key, byte[]... fields); + long hsetnx(byte[] key, byte[] field, byte[] value); String hmset(byte[] key, Map hash); diff --git a/src/main/java/redis/clients/jedis/commands/HashCommands.java b/src/main/java/redis/clients/jedis/commands/HashCommands.java index 3be6ec1959..15b253e2c8 100644 --- a/src/main/java/redis/clients/jedis/commands/HashCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashCommands.java @@ -5,6 +5,8 @@ import java.util.Set; import redis.clients.jedis.args.ExpiryOption; +import redis.clients.jedis.params.HGetExParams; +import redis.clients.jedis.params.HSetExParams; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -14,8 +16,62 @@ public interface HashCommands { long hset(String key, Map hash); + /** + * Sets the specified fields in the hash stored at key to the specified values with additional parameters, + * and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters. + * This command can overwrite any existing fields in the hash. + * If key does not exist, a new key holding a hash is created. + * + * @param key the key of the hash + * @param params the parameters for the HSETEX command + * @param field the field in the hash + * @param value the value to set + * @return 0 if no fields were set, 1 if all the fields were set + * + * @see HSetExParams + */ + long hsetex(String key, HSetExParams params, String field, String value); + + /** + * Sets the specified fields in the hash stored at key to the specified values with additional parameters, + * and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters. + * This command can overwrite any existing fields in the hash. + * If key does not exist, a new key holding a hash is created. + * + * @param key the key of the hash + * @param params the parameters for the HSETEX command + * @param hash the map containing field-value pairs to set in the hash + * @return 0 if no fields were set, 1 if all the fields were set + * + * @see HSetExParams + */ + long hsetex(String key, HSetExParams params, Map hash); + String hget(String key, String field); + + /** + * Retrieves the values associated with the specified fields in a hash stored at the given key + * and optionally sets their expiration. Use `HGetExParams` object to specify expiration parameters. + * + * @param key the key of the hash + * @param params additional parameters for the HGETEX command + * @param fields the fields whose values are to be retrieved + * @return a list of the value associated with each field or nil if the field doesn’t exist. + * + * @see HGetExParams + */ + List hgetex(String key, HGetExParams params, String... fields); + /** + * Retrieves the values associated with the specified fields in the hash stored at the given key + * and then deletes those fields from the hash. + * + * @param key the key of the hash + * @param fields the fields whose values are to be retrieved and then deleted + * @return a list of values associated with the specified fields before they were deleted + */ + List hgetdel(String key, String... fields); + long hsetnx(String key, String field, String value); String hmset(String key, Map hash); diff --git a/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java index e428e72a63..2e48a26ea2 100644 --- a/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java @@ -6,6 +6,8 @@ import redis.clients.jedis.Response; import redis.clients.jedis.args.ExpiryOption; +import redis.clients.jedis.params.HGetExParams; +import redis.clients.jedis.params.HSetExParams; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -15,8 +17,16 @@ public interface HashPipelineBinaryCommands { Response hset(byte[] key, Map hash); + Response hsetex(byte[] key, HSetExParams params, byte[] field, byte[] value); + + Response hsetex(byte[] key, HSetExParams params, Map hash); + Response hget(byte[] key, byte[] field); + Response> hgetex(byte[] key, HGetExParams params, byte[]... fields); + + Response> hgetdel(byte[] key, byte[]... fields); + Response hsetnx(byte[] key, byte[] field, byte[] value); Response hmset(byte[] key, Map hash); diff --git a/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java b/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java index 4de4839a9d..89e0ba3a68 100644 --- a/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java @@ -6,6 +6,8 @@ import redis.clients.jedis.Response; import redis.clients.jedis.args.ExpiryOption; +import redis.clients.jedis.params.HGetExParams; +import redis.clients.jedis.params.HSetExParams; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -15,8 +17,16 @@ public interface HashPipelineCommands { Response hset(String key, Map hash); + Response hsetex(String key, HSetExParams params, String field, String value); + + Response hsetex(String key, HSetExParams params, Map hash); + Response hget(String key, String field); + + Response> hgetex(String key, HGetExParams params, String... fields); + Response> hgetdel(String key, String... fields); + Response hsetnx(String key, String field, String value); Response hmset(String key, Map hash); diff --git a/src/main/java/redis/clients/jedis/params/BaseGetExParams.java b/src/main/java/redis/clients/jedis/params/BaseGetExParams.java new file mode 100644 index 0000000000..7a0b4a806d --- /dev/null +++ b/src/main/java/redis/clients/jedis/params/BaseGetExParams.java @@ -0,0 +1,97 @@ +package redis.clients.jedis.params; + +import java.util.Objects; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; + +/** + * Abstract base class for setting expiration parameters for Redis GET commands. + * This class provides methods to set various expiration options such as EX, PX, EXAT, PXAT, and PERSIST. + * + *

    + *
  • {@link #ex(long)} - Set the specified expire time, in seconds.
  • + *
  • {@link #px(long)} - Set the specified expire time, in milliseconds.
  • + *
  • {@link #exAt(long)} - Set the specified Unix time at which the key will expire, in seconds.
  • + *
  • {@link #pxAt(long)} - Set the specified Unix time at which the key will expire, in milliseconds.
  • + *
  • {@link #persist()} - Remove the time to live associated with the key.
  • + *
+ * + * @param the type of the subclass extending this base class + */ +abstract class BaseGetExParams implements IParams { + + private Keyword expiration; + private Long expirationValue; + + private T expiration(Keyword type, Long value) { + this.expiration = type; + this.expirationValue = value; + return (T) this; + } + + /** + * Set the specified expire time, in seconds. + * @return parameter object + */ + public T ex(long secondsToExpire) { + return expiration(Keyword.EX, secondsToExpire); + } + + /** + * Set the specified expire time, in milliseconds. + * @return parameter object + */ + public T px(long millisecondsToExpire) { + return expiration(Keyword.PX, millisecondsToExpire); + } + + /** + * Set the specified Unix time at which the key will expire, in seconds. + * @param seconds + * @return parameter object + */ + public T exAt(long seconds) { + return expiration(Keyword.EXAT, seconds); + } + + /** + * Set the specified Unix time at which the key will expire, in milliseconds. + * @param milliseconds + * @return parameter object + */ + public T pxAt(long milliseconds) { + return expiration(Keyword.PXAT, milliseconds); + } + + /** + * Remove the time to live associated with the key. + * @return parameter object + */ + public T persist() { + return expiration(Keyword.PERSIST, null); + } + + @Override + public void addParams(CommandArguments args) { + if (expiration != null) { + args.add(expiration); + if (expirationValue != null) { + args.add(expirationValue); + } + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BaseGetExParams that = (BaseGetExParams) o; + return expiration == that.expiration && Objects.equals(expirationValue, that.expirationValue); + } + + @Override + public int hashCode() { + return Objects.hash(expiration, expirationValue); + } +} diff --git a/src/main/java/redis/clients/jedis/params/BaseSetExParams.java b/src/main/java/redis/clients/jedis/params/BaseSetExParams.java new file mode 100644 index 0000000000..d89cda083c --- /dev/null +++ b/src/main/java/redis/clients/jedis/params/BaseSetExParams.java @@ -0,0 +1,110 @@ +package redis.clients.jedis.params; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; + +import java.util.Objects; + +/** + * BaseSetExParams is a base class for setting expiration parameters for Redis keys. + * It provides methods to set expiration times in seconds or milliseconds, + * as well as Unix timestamps for expiration. + * + *
    + *
  • {@link #ex(long)} - Set the specified expire time, in seconds.
  • + *
  • {@link #px(long)} - Set the specified expire time, in milliseconds.
  • + *
  • {@link #exAt(long)} - Set the specified Unix time at which the key will expire, in seconds.
  • + *
  • {@link #pxAt(long)} - Set the specified Unix time at which the key will expire, in milliseconds.
  • + *
  • {@link #keepTtl()} - Retain the time to live associated with the key.
  • + *
+ * + * @param the type of the subclass extending this base class + */ +class BaseSetExParams implements IParams { + + private Keyword expiration; + private Long expirationValue; + + private T expiration(Keyword type, Long value) { + this.expiration = type; + this.expirationValue = value; + return (T) this; + } + + /** + * Set the specified expire time, in seconds. + * @param remainingSeconds + * @return params object + */ + public T ex(long remainingSeconds) { + return expiration(Keyword.EX, remainingSeconds); + } + + /** + * Set the specified expire time, in milliseconds. + * @param remainingMilliseconds + * @return params object + */ + public T px(long remainingMilliseconds) { + return expiration(Keyword.PX, remainingMilliseconds); + } + + /** + * Set the specified Unix time at which the key will expire, in seconds. + * @param timestampSeconds + * @return params object + */ + public T exAt(long timestampSeconds) { + return expiration(Keyword.EXAT, timestampSeconds); + } + + /** + * Set the specified Unix time at which the key will expire, in milliseconds. + * @param timestampMilliseconds + * @return params object + */ + public T pxAt(long timestampMilliseconds) { + return expiration(Keyword.PXAT, timestampMilliseconds); + } + + /** + * @deprecated Use {@link BaseSetExParams#keepTtl()}. + * @return params object + */ + @Deprecated + public T keepttl() { + return keepTtl(); + } + + /** + * Retain the time to live associated with the key. + * @return params object + */ + public T keepTtl() { + return expiration(Keyword.KEEPTTL, null); + } + + @Override + public void addParams(CommandArguments args) { + if (expiration != null) { + args.add(expiration); + if (expirationValue != null) { + args.add(expirationValue); + } + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BaseSetExParams setParams = (BaseSetExParams) o; + return Objects.equals(expiration, setParams.expiration) + && Objects.equals(expirationValue, setParams.expirationValue); + } + + @Override + public int hashCode() { + return Objects.hash(expiration, expirationValue); + } +} diff --git a/src/main/java/redis/clients/jedis/params/GetExParams.java b/src/main/java/redis/clients/jedis/params/GetExParams.java index 521d4c5092..a709443acf 100644 --- a/src/main/java/redis/clients/jedis/params/GetExParams.java +++ b/src/main/java/redis/clients/jedis/params/GetExParams.java @@ -1,92 +1,8 @@ package redis.clients.jedis.params; -import redis.clients.jedis.CommandArguments; -import redis.clients.jedis.Protocol.Keyword; - -import java.util.Objects; - -public class GetExParams implements IParams { - - private Keyword expiration; - private Long expirationValue; - - private boolean persist; - - public GetExParams() { - } - - public static GetExParams getExParams() { +public class GetExParams extends BaseGetExParams { + + public static GetExParams getExParams() { return new GetExParams(); } - - private GetExParams expiration(Keyword type, Long value) { - this.expiration = type; - this.expirationValue = value; - return this; - } - - /** - * Set the specified expire time, in seconds. - * @return GetExParams - */ - public GetExParams ex(long secondsToExpire) { - return expiration(Keyword.EX, secondsToExpire); - } - - /** - * Set the specified expire time, in milliseconds. - * @return GetExParams - */ - public GetExParams px(long millisecondsToExpire) { - return expiration(Keyword.PX, millisecondsToExpire); - } - - /** - * Set the specified Unix time at which the key will expire, in seconds. - * @param seconds - * @return GetExParams - */ - public GetExParams exAt(long seconds) { - return expiration(Keyword.EXAT, seconds); - } - - /** - * Set the specified Unix time at which the key will expire, in milliseconds. - * @param milliseconds - * @return GetExParams - */ - public GetExParams pxAt(long milliseconds) { - return expiration(Keyword.PXAT, milliseconds); - } - - /** - * Remove the time to live associated with the key. - * @return GetExParams - */ - public GetExParams persist() { - return expiration(Keyword.PERSIST, null); - } - - @Override - public void addParams(CommandArguments args) { - if (expiration != null) { - args.add(expiration); - if (expirationValue != null) { - args.add(expirationValue); - } - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - GetExParams that = (GetExParams) o; - return persist == that.persist && expiration == that.expiration && Objects.equals(expirationValue, that.expirationValue); - } - - @Override - public int hashCode() { - return Objects.hash(expiration, expirationValue, persist); - } } diff --git a/src/main/java/redis/clients/jedis/params/HGetExParams.java b/src/main/java/redis/clients/jedis/params/HGetExParams.java new file mode 100644 index 0000000000..c47c9aad0a --- /dev/null +++ b/src/main/java/redis/clients/jedis/params/HGetExParams.java @@ -0,0 +1,32 @@ +package redis.clients.jedis.params; + +/** + * HGetExParams is a parameter class used when getting values of given keys in hash data with + * optionally setting/changing expiry time in Redis. + * It can be used to set the expiry time of the key in seconds or milliseconds. + * + *

This class includes the following methods:

+ *
    + *
  • {@link #hGetExParams()} - Static factory method to create a new instance of HGetExParams.
  • + *
  • {@link #ex(long)} - Set the specified expire time, in seconds.
  • + *
  • {@link #px(long)} - Set the specified expire time, in milliseconds.
  • + *
  • {@link #exAt(long)} - Set the specified Unix(epoch) time at which the key will expire, in seconds.
  • + *
  • {@link #pxAt(long)} - Set the specified Unix(epoch) time at which the key will expire, in milliseconds.
  • + *
  • {@link #persist()} - Remove the time-to-live associated with the key.
  • + *
+ * + *

Example usage:

+ *
+ * {@code
+ * HGetExParams params = HGetExParams.hGetExParams().persist();
+ * }
+ * 
+ * + * @see BaseGetExParams + */ +public class HGetExParams extends BaseGetExParams { + + public static HGetExParams hGetExParams() { + return new HGetExParams(); + } +} diff --git a/src/main/java/redis/clients/jedis/params/HSetExParams.java b/src/main/java/redis/clients/jedis/params/HSetExParams.java new file mode 100644 index 0000000000..bd4cf8cf8c --- /dev/null +++ b/src/main/java/redis/clients/jedis/params/HSetExParams.java @@ -0,0 +1,84 @@ +package redis.clients.jedis.params; + +import java.util.Objects; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; + +/** + * HSetExParams is a parameter class used when setting key-value pairs of hash data with + * optional expiry and existance conditions in Redis. + * It provides methods to specify whether the key should be set + * only if it already exists or only if it does not already exist. + * It can also be used to set the expiry time of the key in seconds or milliseconds. + * + *

This class includes the following methods:

+ *
    + *
  • {@link #hSetExParams()} - Static factory method to create a new instance of HSetExParams.
  • + *
  • {@link #fnx()} - Sets the condition to only set the key if it does not already exist.
  • + *
  • {@link #fxx()} - Sets the condition to only set the key if it already exists.
  • + *
  • {@link #ex(long)} - Set the specified expire time, in seconds.
  • + *
  • {@link #px(long)} - Set the specified expire time, in milliseconds.
  • + *
  • {@link #exAt(long)} - Set the specified Unix(epoch) time at which the key will expire, in seconds.
  • + *
  • {@link #pxAt(long)} - Set the specified Unix(epoch) time at which the key will expire, in milliseconds.
  • + *
  • {@link #keepTtl()} - Retain the time to live associated with the key.
  • + *
+ * + *

Example usage:

+ *
+ * {@code
+ * HSetExParams params = HSetExParams.hSetExParams().fnx();
+ * }
+ * 
+ * + * @see BaseSetExParams + */ +public class HSetExParams extends BaseSetExParams { + + private Keyword existance; + + public static HSetExParams hSetExParams() { + return new HSetExParams(); + } + + /** + * Only set the key if it does not already exist. + * @return HSetExParams + */ + public HSetExParams fnx() { + this.existance = Keyword.FNX; + return this; + } + + /** + * Only set the key if it already exist. + * @return HSetExParams + */ + public HSetExParams fxx() { + this.existance = Keyword.FXX; + return this; + } + + @Override + public void addParams(CommandArguments args) { + if (existance != null) { + args.add(existance); + } + + super.addParams(args); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + HSetExParams setParams = (HSetExParams) o; + return Objects.equals(existance, setParams.existance) && super.equals((BaseSetExParams) o); + } + + @Override + public int hashCode() { + return Objects.hash(existance, super.hashCode()); + } + +} \ No newline at end of file diff --git a/src/main/java/redis/clients/jedis/params/SetParams.java b/src/main/java/redis/clients/jedis/params/SetParams.java index 11f368f3de..5bcfc25cf8 100644 --- a/src/main/java/redis/clients/jedis/params/SetParams.java +++ b/src/main/java/redis/clients/jedis/params/SetParams.java @@ -1,18 +1,13 @@ package redis.clients.jedis.params; +import java.util.Objects; + import redis.clients.jedis.CommandArguments; import redis.clients.jedis.Protocol.Keyword; -import java.util.Objects; - -public class SetParams implements IParams { +public class SetParams extends BaseSetExParams { private Keyword existance; - private Keyword expiration; - private Long expirationValue; - - public SetParams() { - } public static SetParams setParams() { return new SetParams(); @@ -36,77 +31,13 @@ public SetParams xx() { return this; } - private SetParams expiration(Keyword type, Long value) { - this.expiration = type; - this.expirationValue = value; - return this; - } - - /** - * Set the specified expire time, in seconds. - * @param remainingSeconds - * @return SetParams - */ - public SetParams ex(long remainingSeconds) { - return expiration(Keyword.EX, remainingSeconds); - } - - /** - * Set the specified expire time, in milliseconds. - * @param remainingMilliseconds - * @return SetParams - */ - public SetParams px(long remainingMilliseconds) { - return expiration(Keyword.PX, remainingMilliseconds); - } - - /** - * Set the specified Unix time at which the key will expire, in seconds. - * @param timestampSeconds - * @return SetParams - */ - public SetParams exAt(long timestampSeconds) { - return expiration(Keyword.EXAT, timestampSeconds); - } - - /** - * Set the specified Unix time at which the key will expire, in milliseconds. - * @param timestampMilliseconds - * @return SetParams - */ - public SetParams pxAt(long timestampMilliseconds) { - return expiration(Keyword.PXAT, timestampMilliseconds); - } - - /** - * Retain the time to live associated with the key. - * @return SetParams - */ - // TODO: deprecate? - public SetParams keepttl() { - return keepTtl(); - } - - /** - * Retain the time to live associated with the key. - * @return SetParams - */ - public SetParams keepTtl() { - return expiration(Keyword.KEEPTTL, null); - } - @Override public void addParams(CommandArguments args) { if (existance != null) { args.add(existance); } - if (expiration != null) { - args.add(expiration); - if (expirationValue != null) { - args.add(expirationValue); - } - } + super.addParams(args); } @Override @@ -114,12 +45,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SetParams setParams = (SetParams) o; - return Objects.equals(existance, setParams.existance) && Objects.equals(expiration, setParams.expiration) - && Objects.equals(expirationValue, setParams.expirationValue); + return Objects.equals(existance, setParams.existance) && super.equals((BaseSetExParams) o); } @Override public int hashCode() { - return Objects.hash(existance, expiration, expirationValue); + return Objects.hash(existance, super.hashCode()); } } diff --git a/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java b/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java index 73013bb24e..65ffac82bc 100644 --- a/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java @@ -15,16 +15,22 @@ import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.hamcrest.Matchers.nullValue; +import static redis.clients.jedis.util.AssertUtil.assertByteArrayListEquals; +import static org.hamcrest.CoreMatchers.is; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import io.redis.test.annotations.SinceRedisVersion; + import org.junit.Test; import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.args.ExpiryOption; +import redis.clients.jedis.params.HGetExParams; +import redis.clients.jedis.params.HSetExParams; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -76,6 +82,112 @@ public void testHashSetGetBinary() { assertThat(get, equalTo(value)); } + @Test + @SinceRedisVersion("7.9.0") + public void testHgetex() { + String key = "hashKey"; + String field = "name"; + String value = "John"; + long seconds = 20; + + exec(commandObjects.hset(key, field, value)); + List fieldValues = exec( + commandObjects.hgetex(key, new HGetExParams().ex(seconds), field)); + assertThat(fieldValues, is(Collections.singletonList(value))); + + List ttlList = exec(commandObjects.httl(key, field)); + Long ttl = ttlList.get(0); + assertThat(ttl, greaterThanOrEqualTo(seconds - 1)); + } + + @Test + @SinceRedisVersion("7.9.0") + public void testHgetexBinary() { + byte[] key = "hashKeyBytes".getBytes(); + byte[] field = "name".getBytes(); + byte[] value = "John".getBytes(); + long seconds = 20; + + exec(commandObjects.hset(key, field, value)); + List get = exec(commandObjects.hgetex(key, new HGetExParams().ex(seconds), field)); + assertByteArrayListEquals(get, Collections.singletonList(value)); + + List ttlList = exec(commandObjects.httl(key, field)); + Long ttl = ttlList.get(0); + assertThat(ttl, greaterThanOrEqualTo(seconds - 1)); + assertThat(ttl, greaterThanOrEqualTo(seconds - 1)); + } + + @Test + @SinceRedisVersion("7.9.0") + public void testHsetex() { + String key = "hashKey"; + String field = "name"; + String value = "John"; + long seconds = 20; + + Long set = exec(commandObjects.hsetex(key, new HSetExParams().ex(seconds), field, value)); + assertThat(set, equalTo(1L)); + + String get = exec(commandObjects.hget(key, field)); + assertThat(get, equalTo(value)); + + List ttlList = exec(commandObjects.httl(key, field)); + Long ttl = ttlList.get(0); + assertThat(ttl, greaterThanOrEqualTo(seconds - 1)); + } + + @Test + @SinceRedisVersion("7.9.0") + public void testHsetexBinary() { + byte[] key = "hashKeyBytes".getBytes(); + byte[] field = "name".getBytes(); + byte[] value = "John".getBytes(); + long seconds = 20; + Long set = exec(commandObjects.hsetex(key, new HSetExParams().ex(seconds), field, value)); + assertThat(set, equalTo(1L)); + + byte[] get = exec(commandObjects.hget(key, field)); + assertThat(get, equalTo(value)); + + List ttlList = exec(commandObjects.httl(key, field)); + Long ttl = ttlList.get(0); + assertThat(ttl, greaterThanOrEqualTo(seconds - 1)); + assertThat(ttl, greaterThanOrEqualTo(seconds - 1)); + } + + @Test + @SinceRedisVersion("7.9.0") + public void testHgetdel() { + String key = "hashKey"; + String field = "name"; + String value = "John"; + + exec(commandObjects.hset(key, field, value)); + + List getDel = exec(commandObjects.hgetdel(key, field)); + assertThat(getDel, is(Collections.singletonList(value))); + + String getAfterDel = exec(commandObjects.hget(key, field)); + assertThat(getAfterDel, nullValue()); + } + + @Test + @SinceRedisVersion("7.9.0") + public void testHgetdelBinary() { + byte[] key = "hashKeyBytes".getBytes(); + byte[] field = "field".getBytes(); + byte[] value = "value".getBytes(); + + exec(commandObjects.hset(key, field, value)); + + List getDel = exec(commandObjects.hgetdel(key, field)); + assertByteArrayListEquals(Collections.singletonList(value), getDel); + + byte[] getAfterDel = exec(commandObjects.hget(key, field)); + assertThat(getAfterDel, nullValue()); + } + @Test public void testHashBulkSet() { String key = "hashKey"; diff --git a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java index 15c177fba4..ed14b27b6b 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java @@ -19,6 +19,7 @@ import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START_BINARY; +import static redis.clients.jedis.util.AssertUtil.assertByteArrayListEquals; import java.util.ArrayList; import java.util.Arrays; @@ -41,6 +42,8 @@ import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.Response; import redis.clients.jedis.args.ExpiryOption; +import redis.clients.jedis.params.HGetExParams; +import redis.clients.jedis.params.HSetExParams; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; import redis.clients.jedis.util.AssertUtil; @@ -59,6 +62,8 @@ public class HashesCommandsTest extends JedisCommandsTestBase { final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 }; final byte[] bcar = { 0x09, 0x0A, 0x0B, 0x0C }; + final byte[] bbare = { 0x05, 0x06, 0x07, 0x08, 0x09 }; + final byte[] bcare = { 0x09, 0x0A, 0x0B, 0x0C, 0x0D }; final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, 0x0A }; final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, 0x0B }; @@ -93,6 +98,125 @@ public void hget() { assertArrayEquals(bcar, jedis.hget(bfoo, bbar)); } + @Test + @SinceRedisVersion("7.9.0") + public void hgetex() { + long seconds = 20; + jedis.hset("foo", "bar", "car"); + assertEquals(asList("car"), jedis.hgetex("foo", HGetExParams.hGetExParams().ex(seconds), "bar")); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + + jedis.hset("foo", "bar", "car"); + assertEquals(asList("car"), jedis.hgetex("foo", HGetExParams.hGetExParams().persist(), "bar")); + assertEquals(jedis.httl("foo", "bar").get(0), Long.valueOf(-1)); + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList("car", "care"), jedis.hgetex("foo", HGetExParams.hGetExParams().ex(seconds), "bar", "bare")); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl("foo", "bare").get(0), greaterThanOrEqualTo(seconds - 1)); + + // Binary + jedis.hset(bfoo, bbar, bcar); + assertByteArrayListEquals(asList(bcar), jedis.hgetex(bfoo, HGetExParams.hGetExParams().ex(seconds), bbar)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + + jedis.hset(bfoo, bbar, bcar); + assertByteArrayListEquals(asList(bcar), jedis.hgetex(bfoo, HGetExParams.hGetExParams().persist(), bbar)); + assertEquals(Long.valueOf(-1), jedis.httl(bfoo, bbar).get(0)); + + jedis.hset(bfoo, bbar, bcar); + jedis.hset(bfoo, bbare, bcare); + assertByteArrayListEquals(asList(bcar, bcare), jedis.hgetex(bfoo, HGetExParams.hGetExParams().ex(seconds), bbar, bbare)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl(bfoo, bbare).get(0), greaterThanOrEqualTo(seconds - 1)); + } + + @Test + @SinceRedisVersion("7.9.0") + public void hgetdel() { + jedis.hset("foo", "bar", "car"); + assertEquals(asList("car"), jedis.hgetdel("foo", "bar")); + assertEquals(null, jedis.hget("foo", "bar")); + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList("car", "care"), jedis.hgetdel("foo", "bar", "bare")); + assertEquals(null, jedis.hget("foo", "bar")); + assertEquals(null, jedis.hget("foo", "bare")); + + // Binary + jedis.hset(bfoo, bbar, bcar); + assertByteArrayListEquals(asList(bcar), jedis.hgetdel(bfoo, bbar)); + assertEquals(null, jedis.hget(bfoo, bbar)); + + jedis.hset(bfoo, bbar, bcar); + jedis.hset(bfoo, bbare, bcare); + assertByteArrayListEquals(asList(bcar, bcare), jedis.hgetdel(bfoo, bbar, bbare)); + assertEquals(null, jedis.hget(bfoo, bbar)); + assertEquals(null, jedis.hget(bfoo, bbare)); + } + + @Test + @SinceRedisVersion("7.9.0") + public void hsetex() { + long seconds = 20; + jedis.del("foo"); + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().ex(seconds).fnx(), "bar", "car")); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().keepTtl(), "bar", "car")); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().fxx(), "bar", "car")); + assertEquals(Long.valueOf(-1), jedis.httl("foo", "bar").get(0)); + + HashMap hash = new HashMap(); + hash.put("bar", "car"); + hash.put("bare", "care"); + jedis.del("foo"); + + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().ex(seconds).fnx(), hash)); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl("foo", "bare").get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().keepTtl(), hash)); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl("foo", "bare").get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().fxx(), hash)); + assertEquals(Long.valueOf(-1), jedis.httl("foo", "bar").get(0)); + assertEquals(Long.valueOf(-1), jedis.httl("foo", "bare").get(0)); + + // Binary + jedis.del(bfoo); + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().ex(seconds).fnx(), bbar, bcar)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().keepTtl(), bbar, bcar)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().fxx(), bbar, bcar)); + assertEquals(Long.valueOf(-1), jedis.httl(bfoo, bbar).get(0)); + + HashMap bhash = new HashMap(); + bhash.put(bbar, bcar); + bhash.put(bbare, bcare); + + jedis.del(bfoo); + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().ex(seconds).fnx(), bhash)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl(bfoo, bbare).get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().keepTtl(), bhash)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl(bfoo, bbare).get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().fxx(), bhash)); + assertEquals(Long.valueOf(-1), jedis.httl(bfoo, bbar).get(0)); + assertEquals(Long.valueOf(-1), jedis.httl(bfoo, bbare).get(0)); + } + @Test public void hsetnx() { assertEquals(1, jedis.hsetnx("foo", "bar", "car")); diff --git a/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java index 231b1c8aea..7bc1c3b486 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java @@ -19,6 +19,7 @@ import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START_BINARY; +import static redis.clients.jedis.util.AssertUtil.assertByteArrayListEquals; import java.util.ArrayList; import java.util.Arrays; @@ -36,6 +37,8 @@ import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.args.ExpiryOption; +import redis.clients.jedis.params.HGetExParams; +import redis.clients.jedis.params.HSetExParams; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; import redis.clients.jedis.util.AssertUtil; @@ -46,7 +49,9 @@ public abstract class HashesCommandsTestBase extends UnifiedJedisCommandsTestBas final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 }; final byte[] bcar = { 0x09, 0x0A, 0x0B, 0x0C }; - + final byte[] bbare = { 0x05, 0x06, 0x07, 0x08, 0x09 }; + final byte[] bcare = { 0x09, 0x0A, 0x0B, 0x0C, 0x0D }; + final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, 0x0A }; final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, 0x0B }; final byte[] bbar3 = { 0x05, 0x06, 0x07, 0x08, 0x0C }; @@ -80,6 +85,126 @@ public void hget() { assertArrayEquals(bcar, jedis.hget(bfoo, bbar)); } + + @Test + @SinceRedisVersion("7.9.0") + public void hgetex() { + long seconds = 20; + jedis.hset("foo", "bar", "car"); + assertEquals(asList("car"), jedis.hgetex("foo", HGetExParams.hGetExParams().ex(seconds), "bar")); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + + jedis.hset("foo", "bar", "car"); + assertEquals(asList("car"), jedis.hgetex("foo", HGetExParams.hGetExParams().persist(), "bar")); + assertEquals(Long.valueOf(-1), jedis.httl("foo", "bar").get(0)); + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList("car", "care"), jedis.hgetex("foo", HGetExParams.hGetExParams().ex(seconds), "bar", "bare")); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl("foo", "bare").get(0), greaterThanOrEqualTo(seconds - 1)); + + // Binary + jedis.hset(bfoo, bbar, bcar); + assertByteArrayListEquals(asList(bcar), jedis.hgetex(bfoo, HGetExParams.hGetExParams().ex(seconds), bbar)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + + jedis.hset(bfoo, bbar, bcar); + assertByteArrayListEquals(asList(bcar), jedis.hgetex(bfoo, HGetExParams.hGetExParams().persist(), bbar)); + assertEquals(Long.valueOf(-1), jedis.httl(bfoo, bbar).get(0)); + + jedis.hset(bfoo, bbar, bcar); + jedis.hset(bfoo, bbare, bcare); + assertByteArrayListEquals(asList(bcar, bcare), jedis.hgetex(bfoo, HGetExParams.hGetExParams().ex(seconds), bbar, bbare)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl(bfoo, bbare).get(0), greaterThanOrEqualTo(seconds - 1)); + } + + @Test + @SinceRedisVersion("7.9.0") + public void hgetdel() { + jedis.hset("foo", "bar", "car"); + assertEquals(asList("car"), jedis.hgetdel("foo", "bar")); + assertEquals(null, jedis.hget("foo", "bar")); + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList("car", "care"), jedis.hgetdel("foo", "bar", "bare")); + assertEquals(null, jedis.hget("foo", "bar")); + assertEquals(null, jedis.hget("foo", "bare")); + + // Binary + jedis.hset(bfoo, bbar, bcar); + assertByteArrayListEquals(asList(bcar), jedis.hgetdel(bfoo, bbar)); + assertEquals(null, jedis.hget(bfoo, bbar)); + + jedis.hset(bfoo, bbar, bcar); + jedis.hset(bfoo, bbare, bcare); + assertByteArrayListEquals(asList(bcar, bcare), jedis.hgetdel(bfoo, bbar, bbare)); + assertEquals(null, jedis.hget(bfoo, bbar)); + assertEquals(null, jedis.hget(bfoo, bbare)); + } + + @Test + @SinceRedisVersion("7.9.0") + public void hsetex() { + long seconds = 20; + jedis.del("foo"); + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().ex(seconds).fnx(), "bar", "car")); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().keepTtl(), "bar", "car")); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().fxx(), "bar", "car")); + assertEquals(Long.valueOf(-1), jedis.httl("foo", "bar").get(0)); + + HashMap hash = new HashMap(); + hash.put("bar", "car"); + hash.put("bare", "care"); + jedis.del("foo"); + + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().ex(seconds).fnx(), hash)); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl("foo", "bare").get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().keepTtl(), hash)); + assertThat(jedis.httl("foo", "bar").get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl("foo", "bare").get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex("foo", HSetExParams.hSetExParams().fxx(), hash)); + assertEquals(Long.valueOf(-1), jedis.httl("foo", "bar").get(0)); + assertEquals(Long.valueOf(-1), jedis.httl("foo", "bare").get(0)); + + // Binary + jedis.del(bfoo); + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().ex(seconds).fnx(), bbar, bcar)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().keepTtl(), bbar, bcar)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().fxx(), bbar, bcar)); + assertEquals(Long.valueOf(-1), jedis.httl(bfoo, bbar).get(0)); + + HashMap bhash = new HashMap(); + bhash.put(bbar, bcar); + bhash.put(bbare, bcare); + + jedis.del(bfoo); + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().ex(seconds).fnx(), bhash)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl(bfoo, bbare).get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().keepTtl(), bhash)); + assertThat(jedis.httl(bfoo, bbar).get(0), greaterThanOrEqualTo(seconds - 1)); + assertThat(jedis.httl(bfoo, bbare).get(0), greaterThanOrEqualTo(seconds - 1)); + + assertEquals(1, jedis.hsetex(bfoo, HSetExParams.hSetExParams().fxx(), bhash)); + assertEquals(Long.valueOf(-1), jedis.httl(bfoo, bbar).get(0)); + assertEquals(Long.valueOf(-1), jedis.httl(bfoo, bbare).get(0)); + } + @Test public void hsetnx() { assertEquals(1, jedis.hsetnx("foo", "bar", "car"));