Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for HSCAN NOVALUES #2722

Merged
merged 10 commits into from
Aug 18, 2024
27 changes: 26 additions & 1 deletion src/StackExchange.Redis/Interfaces/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,31 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks><seealso href="https://redis.io/commands/hscan"/></remarks>
IEnumerable<HashEntry> HashScan(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None);

/// <summary>
/// The HSCAN command is used to incrementally iterate over a hash and return only field names.
/// </summary>
/// <param name="key">The key of the hash.</param>
/// <param name="pattern">The pattern of keys to get entries for.</param>
/// <param name="pageSize">The page size to iterate by.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>Yields all elements of the hash matching the pattern.</returns>
/// <remarks><seealso href="https://redis.io/commands/hscan"/></remarks>
IEnumerable<RedisValue> HashScanNoValues(RedisKey key, RedisValue pattern, int pageSize, CommandFlags flags);

/// <summary>
/// The HSCAN command is used to incrementally iterate over a hash and return only field names.
/// Note: to resume an iteration via <i>cursor</i>, cast the original enumerable or enumerator to <see cref="IScanningCursor"/>.
/// </summary>
/// <param name="key">The key of the hash.</param>
/// <param name="pattern">The pattern of keys to get entries for.</param>
/// <param name="pageSize">The page size to iterate by.</param>
/// <param name="cursor">The cursor position to start at.</param>
/// <param name="pageOffset">The page offset to start at.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>Yields all elements of the hash matching the pattern.</returns>
/// <remarks><seealso href="https://redis.io/commands/hscan"/></remarks>
IEnumerable<RedisValue> HashScanNoValues(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Sets the specified fields to their respective values in the hash stored at key.
/// This command overwrites any specified fields that already exist in the hash, leaving other unspecified fields untouched.
Expand Down Expand Up @@ -1628,7 +1653,7 @@ public interface IDatabase : IRedis, IDatabaseAsync

/// <inheritdoc cref="SortedSetAdd(RedisKey, RedisValue, double, SortedSetWhen, CommandFlags)" />
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
bool SortedSetAdd(RedisKey key, RedisValue member, double score, When when, CommandFlags flags= CommandFlags.None);
bool SortedSetAdd(RedisKey key, RedisValue member, double score, When when, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Adds the specified member with the specified score to the sorted set stored at key.
Expand Down
14 changes: 14 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,20 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks><seealso href="https://redis.io/commands/hscan"/></remarks>
IAsyncEnumerable<HashEntry> HashScanAsync(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None);

/// <summary>
/// The HSCAN command is used to incrementally iterate over a hash and get the fields without values
/// Note: to resume an iteration via <i>cursor</i>, cast the original enumerable or enumerator to <see cref="IScanningCursor"/>.
/// </summary>
/// <param name="key">The key of the hash.</param>
/// <param name="pattern">The pattern of keys to get entries for.</param>
/// <param name="pageSize">The page size to iterate by.</param>
/// <param name="cursor">The cursor position to start at.</param>
/// <param name="pageOffset">The page offset to start at.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>Yields all field names of hash matching the pattern .</returns>
/// <remarks><seealso href="https://redis.io/commands/hscan"/></remarks>
IAsyncEnumerable<RedisValue> HashScanNoValuesAsync(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Sets the specified fields to their respective values in the hash stored at key.
/// This command overwrites any specified fields that already exist in the hash, leaving other unspecified fields untouched.
Expand Down
4 changes: 3 additions & 1 deletion src/StackExchange.Redis/KeyspaceIsolation/KeyPrefixed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,12 @@ public Task<RedisValue[]> HashRandomFieldsAsync(RedisKey key, long count, Comman
public Task<HashEntry[]> HashRandomFieldsWithValuesAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) =>
Inner.HashRandomFieldsWithValuesAsync(ToInner(key), count, flags);


public IAsyncEnumerable<HashEntry> HashScanAsync(RedisKey key, RedisValue pattern, int pageSize, long cursor, int pageOffset, CommandFlags flags) =>
Inner.HashScanAsync(ToInner(key), pattern, pageSize, cursor, pageOffset, flags);

public IAsyncEnumerable<RedisValue> HashScanNoValuesAsync(RedisKey key, RedisValue pattern, int pageSize, long cursor, int pageOffset, CommandFlags flags) =>
Inner.HashScanNoValuesAsync(ToInner(key), pattern, pageSize, cursor, pageOffset, flags);

public Task<bool> HashSetAsync(RedisKey key, RedisValue hashField, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None) =>
Inner.HashSetAsync(ToInner(key), hashField, value, when, flags);

Expand Down
16 changes: 11 additions & 5 deletions src/StackExchange.Redis/KeyspaceIsolation/KeyPrefixedDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public bool GeoAdd(RedisKey key, GeoEntry value, CommandFlags flags = CommandFla
public bool GeoRemove(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) =>
Inner.GeoRemove(ToInner(key), member, flags);

public double? GeoDistance(RedisKey key, RedisValue member1, RedisValue member2, GeoUnit unit = GeoUnit.Meters,CommandFlags flags = CommandFlags.None) =>
public double? GeoDistance(RedisKey key, RedisValue member1, RedisValue member2, GeoUnit unit = GeoUnit.Meters, CommandFlags flags = CommandFlags.None) =>
Inner.GeoDistance(ToInner(key), member1, member2, unit, flags);

public string?[] GeoHash(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) =>
Expand All @@ -48,7 +48,7 @@ public bool GeoRemove(RedisKey key, RedisValue member, CommandFlags flags = Comm
public GeoPosition? GeoPosition(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) =>
Inner.GeoPosition(ToInner(key), member, flags);

public GeoRadiusResult[] GeoRadius(RedisKey key, RedisValue member, double radius, GeoUnit unit = GeoUnit.Meters, int count = -1, Order? order = null,GeoRadiusOptions options = GeoRadiusOptions.Default, CommandFlags flags = CommandFlags.None) =>
public GeoRadiusResult[] GeoRadius(RedisKey key, RedisValue member, double radius, GeoUnit unit = GeoUnit.Meters, int count = -1, Order? order = null, GeoRadiusOptions options = GeoRadiusOptions.Default, CommandFlags flags = CommandFlags.None) =>
Inner.GeoRadius(ToInner(key), member, radius, unit, count, order, options, flags);

public GeoRadiusResult[] GeoRadius(RedisKey key, double longitude, double latitude, double radius, GeoUnit unit = GeoUnit.Meters, int count = -1, Order? order = null, GeoRadiusOptions options = GeoRadiusOptions.Default, CommandFlags flags = CommandFlags.None) =>
Expand Down Expand Up @@ -407,7 +407,7 @@ public long SortedSetAdd(RedisKey key, SortedSetEntry[] values, CommandFlags fla
public long SortedSetAdd(RedisKey key, SortedSetEntry[] values, When when = When.Always, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetAdd(ToInner(key), values, when, flags);

public long SortedSetAdd(RedisKey key, SortedSetEntry[] values,SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) =>
public long SortedSetAdd(RedisKey key, SortedSetEntry[] values, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetAdd(ToInner(key), values, when, flags);

public bool SortedSetAdd(RedisKey key, RedisValue member, double score, CommandFlags flags) =>
Expand Down Expand Up @@ -510,7 +510,7 @@ public long SortedSetRemoveRangeByValue(RedisKey key, RedisValue min, RedisValue
public double?[] SortedSetScores(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetScores(ToInner(key), members, flags);

public long SortedSetUpdate(RedisKey key, SortedSetEntry[] values,SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) =>
public long SortedSetUpdate(RedisKey key, SortedSetEntry[] values, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetUpdate(ToInner(key), values, when, flags);

public bool SortedSetUpdate(RedisKey key, RedisValue member, double score, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) =>
Expand Down Expand Up @@ -706,8 +706,14 @@ IEnumerable<HashEntry> IDatabase.HashScan(RedisKey key, RedisValue pattern, int
IEnumerable<HashEntry> IDatabase.HashScan(RedisKey key, RedisValue pattern, int pageSize, long cursor, int pageOffset, CommandFlags flags)
=> Inner.HashScan(ToInner(key), pattern, pageSize, cursor, pageOffset, flags);

IEnumerable<RedisValue> IDatabase.HashScanNoValues(RedisKey key, RedisValue pattern, int pageSize, CommandFlags flags)
=> Inner.HashScanNoValues(ToInner(key), pattern, pageSize, flags);

IEnumerable<RedisValue> IDatabase.HashScanNoValues(RedisKey key, RedisValue pattern, int pageSize, long cursor, int pageOffset, CommandFlags flags)
=> Inner.HashScanNoValues(ToInner(key), pattern, pageSize, cursor, pageOffset, flags);

IEnumerable<RedisValue> IDatabase.SetScan(RedisKey key, RedisValue pattern, int pageSize, CommandFlags flags)
=> Inner.SetScan(ToInner(key), pattern, pageSize, flags);
=> Inner.SetScan(ToInner(key), pattern, pageSize, flags);

IEnumerable<RedisValue> IDatabase.SetScan(RedisKey key, RedisValue pattern, int pageSize, long cursor, int pageOffset, CommandFlags flags)
=> Inner.SetScan(ToInner(key), pattern, pageSize, cursor, pageOffset, flags);
Expand Down
39 changes: 38 additions & 1 deletion src/StackExchange.Redis/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ public static Message Create(int db, CommandFlags flags, RedisCommand command, i
public static Message Create(int db, CommandFlags flags, RedisCommand command, in RedisKey key, in RedisValue value0, in RedisValue value1, in RedisValue value2, in RedisValue value3, in RedisValue value4) =>
new CommandKeyValueValueValueValueValueMessage(db, flags, command, key, value0, value1, value2, value3, value4);

public static Message Create(int db, CommandFlags flags, RedisCommand command, in RedisKey key, in RedisValue value0, in RedisValue value1, in RedisValue value2, in RedisValue value3, in RedisValue value4, in RedisValue value5) =>
new CommandKeyValueValueValueValueValueValueMessage(db, flags, command, key, value0, value1, value2, value3, value4, value5);

public static Message Create(int db, CommandFlags flags, RedisCommand command, in RedisKey key, in RedisValue value0, in RedisValue value1, in RedisValue value2, in RedisValue value3, in RedisValue value4, in RedisValue value5, in RedisValue value6) =>
new CommandKeyValueValueValueValueValueValueValueMessage(db, flags, command, key, value0, value1, value2, value3, value4, value5, value6);

Expand Down Expand Up @@ -442,7 +445,7 @@ internal static Message Create(int db, CommandFlags flags, RedisCommand command,
3 => new CommandKeyKeyValueValueValueMessage(db, flags, command, key0, key1, values[0], values[1], values[2]),
4 => new CommandKeyKeyValueValueValueValueMessage(db, flags, command, key0, key1, values[0], values[1], values[2], values[3]),
5 => new CommandKeyKeyValueValueValueValueValueMessage(db, flags, command, key0, key1, values[0], values[1], values[2], values[3], values[4]),
6 => new CommandKeyKeyValueValueValueValueValueValueMessage(db, flags, command, key0, key1, values[0], values[1], values[2], values[3],values[4],values[5]),
6 => new CommandKeyKeyValueValueValueValueValueValueMessage(db, flags, command, key0, key1, values[0], values[1], values[2], values[3], values[4], values[5]),
7 => new CommandKeyKeyValueValueValueValueValueValueValueMessage(db, flags, command, key0, key1, values[0], values[1], values[2], values[3], values[4], values[5], values[6]),
_ => new CommandKeyKeyValuesMessage(db, flags, command, key0, key1, values),
};
Expand Down Expand Up @@ -1189,6 +1192,40 @@ protected override void WriteImpl(PhysicalConnection physical)
public override int ArgCount => 6;
}

private sealed class CommandKeyValueValueValueValueValueValueMessage : CommandKeyBase
{
private readonly RedisValue value0, value1, value2, value3, value4, value5;

public CommandKeyValueValueValueValueValueValueMessage(int db, CommandFlags flags, RedisCommand command, in RedisKey key, in RedisValue value0, in RedisValue value1, in RedisValue value2, in RedisValue value3, in RedisValue value4, in RedisValue value5) : base(db, flags, command, key)
{
value0.AssertNotNull();
value1.AssertNotNull();
value2.AssertNotNull();
value3.AssertNotNull();
value4.AssertNotNull();
value5.AssertNotNull();
this.value0 = value0;
this.value1 = value1;
this.value2 = value2;
this.value3 = value3;
this.value4 = value4;
this.value5 = value5;
}

protected override void WriteImpl(PhysicalConnection physical)
{
physical.WriteHeader(Command, ArgCount);
physical.Write(Key);
physical.WriteBulkString(value0);
physical.WriteBulkString(value1);
physical.WriteBulkString(value2);
physical.WriteBulkString(value3);
physical.WriteBulkString(value4);
physical.WriteBulkString(value5);
}
public override int ArgCount => 7;
}

private sealed class CommandKeyValueValueValueValueValueValueValueMessage : CommandKeyBase
{
private readonly RedisValue value0, value1, value2, value3, value4, value5, value6;
Expand Down
3 changes: 3 additions & 0 deletions src/StackExchange.Redis/PublicAPI/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,8 @@ StackExchange.Redis.IDatabase.HashRandomFields(StackExchange.Redis.RedisKey key,
StackExchange.Redis.IDatabase.HashRandomFieldsWithValues(StackExchange.Redis.RedisKey key, long count, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.HashEntry[]!
StackExchange.Redis.IDatabase.HashScan(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern = default(StackExchange.Redis.RedisValue), int pageSize = 250, long cursor = 0, int pageOffset = 0, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Collections.Generic.IEnumerable<StackExchange.Redis.HashEntry>!
StackExchange.Redis.IDatabase.HashScan(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern, int pageSize, StackExchange.Redis.CommandFlags flags) -> System.Collections.Generic.IEnumerable<StackExchange.Redis.HashEntry>!
StackExchange.Redis.IDatabase.HashScanNoValues(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern = default(StackExchange.Redis.RedisValue), int pageSize = 250, long cursor = 0, int pageOffset = 0, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Collections.Generic.IEnumerable<StackExchange.Redis.RedisValue>!
StackExchange.Redis.IDatabase.HashScanNoValues(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern, int pageSize, StackExchange.Redis.CommandFlags flags) -> System.Collections.Generic.IEnumerable<StackExchange.Redis.RedisValue>!
StackExchange.Redis.IDatabase.HashSet(StackExchange.Redis.RedisKey key, StackExchange.Redis.HashEntry[]! hashFields, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> void
StackExchange.Redis.IDatabase.HashSet(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue hashField, StackExchange.Redis.RedisValue value, StackExchange.Redis.When when = StackExchange.Redis.When.Always, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> bool
StackExchange.Redis.IDatabase.HashStringLength(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue hashField, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long
Expand Down Expand Up @@ -782,6 +784,7 @@ StackExchange.Redis.IDatabaseAsync.HashRandomFieldAsync(StackExchange.Redis.Redi
StackExchange.Redis.IDatabaseAsync.HashRandomFieldsAsync(StackExchange.Redis.RedisKey key, long count, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisValue[]!>!
StackExchange.Redis.IDatabaseAsync.HashRandomFieldsWithValuesAsync(StackExchange.Redis.RedisKey key, long count, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.HashEntry[]!>!
StackExchange.Redis.IDatabaseAsync.HashScanAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern = default(StackExchange.Redis.RedisValue), int pageSize = 250, long cursor = 0, int pageOffset = 0, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Collections.Generic.IAsyncEnumerable<StackExchange.Redis.HashEntry>!
StackExchange.Redis.IDatabaseAsync.HashScanNoValuesAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern = default(StackExchange.Redis.RedisValue), int pageSize = 250, long cursor = 0, int pageOffset = 0, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Collections.Generic.IAsyncEnumerable<StackExchange.Redis.RedisValue>!
StackExchange.Redis.IDatabaseAsync.HashSetAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.HashEntry[]! hashFields, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task!
StackExchange.Redis.IDatabaseAsync.HashSetAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue hashField, StackExchange.Redis.RedisValue value, StackExchange.Redis.When when = StackExchange.Redis.When.Always, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<bool>!
StackExchange.Redis.IDatabaseAsync.HashStringLengthAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue hashField, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<long>!
Expand Down
Loading
Loading