Skip to content

Commit

Permalink
Add HSTRLEN command implementation and testing (StackExchange#1241)
Browse files Browse the repository at this point in the history
Implements StackExchange#1238 - adds `HSTRLEN` command and testing.
  • Loading branch information
eitanhs authored and NickCraver committed Oct 19, 2019
1 parent cf238f3 commit b0a07a7
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/StackExchange.Redis/Enums/RedisCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ internal enum RedisCommand
HSCAN,
HSET,
HSETNX,
HSTRLEN,
HVALS,

INCR,
Expand Down
10 changes: 10 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,16 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks>https://redis.io/commands/hsetnx</remarks>
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>
/// Returns all values in the hash stored at key.
/// </summary>
Expand Down
10 changes: 10 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,16 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks>https://redis.io/commands/hsetnx</remarks>
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>
/// Returns all values in the hash stored at key.
/// </summary>
Expand Down
5 changes: 5 additions & 0 deletions src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ public bool HashSet(RedisKey key, RedisValue hashField, RedisValue value, When w
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)
{
Inner.HashSet(ToInner(key), hashFields, flags);
Expand Down
5 changes: 5 additions & 0 deletions src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ public Task<bool> HashSetAsync(RedisKey key, RedisValue hashField, RedisValue va
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)
{
return Inner.HashSetAsync(ToInner(key), hashFields, flags);
Expand Down
13 changes: 13 additions & 0 deletions src/StackExchange.Redis/RedisDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,13 @@ public void HashSet(RedisKey key, HashEntry[] hashFields, CommandFlags flags = C
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)
{
WhenAlwaysOrNotExists(when);
Expand All @@ -447,6 +454,12 @@ public Task<bool> HashSetAsync(RedisKey key, RedisValue hashField, RedisValue va
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)
{
var msg = GetHashSetMessage(key, hashFields, flags);
Expand Down
5 changes: 5 additions & 0 deletions src/StackExchange.Redis/RedisFeatures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ public RedisFeatures(Version version)
/// </summary>
public bool ExpireOverwrite => Version >= v2_1_3;

/// <summary>
/// Is HSTRLEN available?
/// </summary>
public bool HashStringLength => Version >= v3_2_0;

/// <summary>
/// Does HDEL support varadic usage?
/// </summary>
Expand Down
7 changes: 7 additions & 0 deletions tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ public void HashSet_2()
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]
public void HashValues()
{
Expand Down
32 changes: 32 additions & 0 deletions tests/StackExchange.Redis.Tests/Strings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 string Decode(byte[] value) => Encoding.UTF8.GetString(value);
}
Expand Down
9 changes: 8 additions & 1 deletion tests/StackExchange.Redis.Tests/WrapperBaseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,14 @@ public void HashSetAsync_2()
wrapper.HashSetAsync("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]
public void HashValuesAsync()
{
Expand Down

0 comments on commit b0a07a7

Please sign in to comment.