Commit b0a07a76 authored by Eitan Har-Shoshanim's avatar Eitan Har-Shoshanim Committed by Nick Craver

Add HSTRLEN command implementation and testing (#1241)

Implements #1238 - adds `HSTRLEN` command and testing.
parent cf238f30
...@@ -65,6 +65,7 @@ internal enum RedisCommand ...@@ -65,6 +65,7 @@ internal enum RedisCommand
HSCAN, HSCAN,
HSET, HSET,
HSETNX, HSETNX,
HSTRLEN,
HVALS, HVALS,
INCR, INCR,
......
...@@ -358,6 +358,16 @@ public interface IDatabase : IRedis, IDatabaseAsync ...@@ -358,6 +358,16 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks>https://redis.io/commands/hsetnx</remarks> /// <remarks>https://redis.io/commands/hsetnx</remarks>
bool HashSet(RedisKey key, RedisValue hashField, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None); bool HashSet(RedisKey key, RedisValue hashField, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Returns the string length of the value associated with field in the hash stored at key.
/// </summary>
/// <param name="key">The key of the hash.</param>
/// <param name="hashField">The field containing the string</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>the length of the string at field, or 0 when key does not exist.</returns>
/// <remarks>https://redis.io/commands/hstrlen</remarks>
long HashStringLength(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None);
/// <summary> /// <summary>
/// Returns all values in the hash stored at key. /// Returns all values in the hash stored at key.
/// </summary> /// </summary>
......
...@@ -322,6 +322,16 @@ public interface IDatabaseAsync : IRedisAsync ...@@ -322,6 +322,16 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks>https://redis.io/commands/hsetnx</remarks> /// <remarks>https://redis.io/commands/hsetnx</remarks>
Task<bool> HashSetAsync(RedisKey key, RedisValue hashField, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None); Task<bool> HashSetAsync(RedisKey key, RedisValue hashField, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Returns the string length of the value associated with field in the hash stored at key.
/// </summary>
/// <param name="key">The key of the hash.</param>
/// <param name="hashField">The field containing the string</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>the length of the string at field, or 0 when key does not exist.</returns>
/// <remarks>https://redis.io/commands/hstrlen</remarks>
Task<long> HashStringLengthAsync(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None);
/// <summary> /// <summary>
/// Returns all values in the hash stored at key. /// Returns all values in the hash stored at key.
/// </summary> /// </summary>
......
...@@ -152,6 +152,11 @@ public bool HashSet(RedisKey key, RedisValue hashField, RedisValue value, When w ...@@ -152,6 +152,11 @@ public bool HashSet(RedisKey key, RedisValue hashField, RedisValue value, When w
return Inner.HashSet(ToInner(key), hashField, value, when, flags); return Inner.HashSet(ToInner(key), hashField, value, when, flags);
} }
public long HashStringLength(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None)
{
return Inner.HashStringLength(ToInner(key), hashField, flags);
}
public void HashSet(RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None) public void HashSet(RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None)
{ {
Inner.HashSet(ToInner(key), hashFields, flags); Inner.HashSet(ToInner(key), hashFields, flags);
......
...@@ -128,6 +128,11 @@ public Task<bool> HashSetAsync(RedisKey key, RedisValue hashField, RedisValue va ...@@ -128,6 +128,11 @@ public Task<bool> HashSetAsync(RedisKey key, RedisValue hashField, RedisValue va
return Inner.HashSetAsync(ToInner(key), hashField, value, when, flags); return Inner.HashSetAsync(ToInner(key), hashField, value, when, flags);
} }
public Task<long> HashStringLengthAsync(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None)
{
return Inner.HashStringLengthAsync(ToInner(key), hashField, flags);
}
public Task HashSetAsync(RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None) public Task HashSetAsync(RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None)
{ {
return Inner.HashSetAsync(ToInner(key), hashFields, flags); return Inner.HashSetAsync(ToInner(key), hashFields, flags);
......
...@@ -438,6 +438,13 @@ public void HashSet(RedisKey key, HashEntry[] hashFields, CommandFlags flags = C ...@@ -438,6 +438,13 @@ public void HashSet(RedisKey key, HashEntry[] hashFields, CommandFlags flags = C
ExecuteSync(msg, ResultProcessor.DemandOK); ExecuteSync(msg, ResultProcessor.DemandOK);
} }
public long HashStringLength(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.HSTRLEN, key, hashField);
return ExecuteSync(msg, ResultProcessor.Int64);
}
public Task<bool> HashSetAsync(RedisKey key, RedisValue hashField, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None) public Task<bool> HashSetAsync(RedisKey key, RedisValue hashField, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None)
{ {
WhenAlwaysOrNotExists(when); WhenAlwaysOrNotExists(when);
...@@ -447,6 +454,12 @@ public Task<bool> HashSetAsync(RedisKey key, RedisValue hashField, RedisValue va ...@@ -447,6 +454,12 @@ public Task<bool> HashSetAsync(RedisKey key, RedisValue hashField, RedisValue va
return ExecuteAsync(msg, ResultProcessor.Boolean); return ExecuteAsync(msg, ResultProcessor.Boolean);
} }
public Task<long> HashStringLengthAsync(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.HSTRLEN, key, hashField);
return ExecuteAsync(msg, ResultProcessor.Int64);
}
public Task HashSetAsync(RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None) public Task HashSetAsync(RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None)
{ {
var msg = GetHashSetMessage(key, hashFields, flags); var msg = GetHashSetMessage(key, hashFields, flags);
......
...@@ -65,6 +65,11 @@ public RedisFeatures(Version version) ...@@ -65,6 +65,11 @@ public RedisFeatures(Version version)
/// </summary> /// </summary>
public bool ExpireOverwrite => Version >= v2_1_3; public bool ExpireOverwrite => Version >= v2_1_3;
/// <summary>
/// Is HSTRLEN available?
/// </summary>
public bool HashStringLength => Version >= v3_2_0;
/// <summary> /// <summary>
/// Does HDEL support varadic usage? /// Does HDEL support varadic usage?
/// </summary> /// </summary>
......
...@@ -166,6 +166,13 @@ public void HashSet_2() ...@@ -166,6 +166,13 @@ public void HashSet_2()
mock.Verify(_ => _.HashSet("prefix:key", "hashField", "value", When.Exists, CommandFlags.None)); mock.Verify(_ => _.HashSet("prefix:key", "hashField", "value", When.Exists, CommandFlags.None));
} }
[Fact]
public void HashStringLength()
{
wrapper.HashStringLength("key","field", CommandFlags.None);
mock.Verify(_ => _.HashStringLength("prefix:key", "field", CommandFlags.None));
}
[Fact] [Fact]
public void HashValues() public void HashValues()
{ {
......
...@@ -304,6 +304,38 @@ public async Task RangeString() ...@@ -304,6 +304,38 @@ public async Task RangeString()
} }
} }
[Fact]
public async Task HashStringLengthAsync()
{
using (var conn = Create())
{
Skip.IfMissingFeature(conn, nameof(RedisFeatures.HashStringLength), r => r.HashStringLength);
var database = conn.GetDatabase();
var key = Me();
var value = "hello world";
database.HashSet(key, "field", value);
var resAsync = database.HashStringLengthAsync(key, "field");
var resNonExistingAsync = database.HashStringLengthAsync(key, "non-existing-field");
Assert.Equal(value.Length, await resAsync);
Assert.Equal(0, await resNonExistingAsync);
}
}
[Fact]
public void HashStringLength()
{
using (var conn = Create())
{
Skip.IfMissingFeature(conn, nameof(RedisFeatures.HashStringLength), r => r.HashStringLength);
var database = conn.GetDatabase();
var key = Me();
var value = "hello world";
database.HashSet(key, "field", value);
Assert.Equal(value.Length, database.HashStringLength(key, "field"));
Assert.Equal(0, database.HashStringLength(key, "non-existing-field"));
}
}
private static byte[] Encode(string value) => Encoding.UTF8.GetBytes(value); private static byte[] Encode(string value) => Encoding.UTF8.GetBytes(value);
private static string Decode(byte[] value) => Encoding.UTF8.GetString(value); private static string Decode(byte[] value) => Encoding.UTF8.GetString(value);
} }
......
...@@ -130,7 +130,14 @@ public void HashSetAsync_2() ...@@ -130,7 +130,14 @@ public void HashSetAsync_2()
wrapper.HashSetAsync("key", "hashField", "value", When.Exists, CommandFlags.None); wrapper.HashSetAsync("key", "hashField", "value", When.Exists, CommandFlags.None);
mock.Verify(_ => _.HashSetAsync("prefix:key", "hashField", "value", When.Exists, CommandFlags.None)); mock.Verify(_ => _.HashSetAsync("prefix:key", "hashField", "value", When.Exists, CommandFlags.None));
} }
[Fact]
public void HashStringLengthAsync()
{
wrapper.HashStringLengthAsync("key","field", CommandFlags.None);
mock.Verify(_ => _.HashStringLengthAsync("prefix:key", "field", CommandFlags.None));
}
[Fact] [Fact]
public void HashValuesAsync() public void HashValuesAsync()
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment