Skip to content

Commit be39ec9

Browse files
authored
new operations with BITOP command (#2900)
1 parent 7351ad9 commit be39ec9

File tree

7 files changed

+384
-1
lines changed

7 files changed

+384
-1
lines changed

src/StackExchange.Redis/Enums/Bitwise.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,30 @@ public enum Bitwise
2424
/// <a href="https://en.wikipedia.org/wiki/Bitwise_operation#NOT">Not</a>
2525
/// </summary>
2626
Not,
27+
28+
/// <summary>
29+
/// DIFF operation: members of X that are not members of any of Y1, Y2, ...
30+
/// Equivalent to X ∧ ¬(Y1 ∨ Y2 ∨ ...)
31+
/// </summary>
32+
Diff,
33+
34+
/// <summary>
35+
/// DIFF1 operation: members of one or more of Y1, Y2, ... that are not members of X
36+
/// Equivalent to ¬X ∧ (Y1 ∨ Y2 ∨ ...)
37+
/// </summary>
38+
Diff1,
39+
40+
/// <summary>
41+
/// ANDOR operation: members of X that are also members of one or more of Y1, Y2, ...
42+
/// Equivalent to X ∧ (Y1 ∨ Y2 ∨ ...)
43+
/// </summary>
44+
AndOr,
45+
46+
/// <summary>
47+
/// ONE operation: members of exactly one of X1, X2, ...
48+
/// For two bitmaps this is equivalent to XOR. For more than two bitmaps,
49+
/// this returns bits that are set in exactly one of the input bitmaps.
50+
/// </summary>
51+
One,
2752
}
2853
}

src/StackExchange.Redis/PublicAPI/PublicAPI.Shipped.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,3 +1899,7 @@ static StackExchange.Redis.RedisChannel.Sharded(byte[]? value) -> StackExchange.
18991899
static StackExchange.Redis.RedisChannel.Sharded(string! value) -> StackExchange.Redis.RedisChannel
19001900
StackExchange.Redis.ClientInfo.ShardedSubscriptionCount.get -> int
19011901
StackExchange.Redis.ConfigurationOptions.SetUserPfxCertificate(string! userCertificatePath, string? password = null) -> void
1902+
StackExchange.Redis.Bitwise.AndOr = 6 -> StackExchange.Redis.Bitwise
1903+
StackExchange.Redis.Bitwise.Diff = 4 -> StackExchange.Redis.Bitwise
1904+
StackExchange.Redis.Bitwise.Diff1 = 5 -> StackExchange.Redis.Bitwise
1905+
StackExchange.Redis.Bitwise.One = 7 -> StackExchange.Redis.Bitwise

src/StackExchange.Redis/RedisFeatures.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ namespace StackExchange.Redis
4444
v7_0_0_rc1 = new Version(6, 9, 240), // 7.0 RC1 is version 6.9.240
4545
v7_2_0_rc1 = new Version(7, 1, 240), // 7.2 RC1 is version 7.1.240
4646
v7_4_0_rc1 = new Version(7, 3, 240), // 7.4 RC1 is version 7.3.240
47-
v7_4_0_rc2 = new Version(7, 3, 241); // 7.4 RC2 is version 7.3.241
47+
v7_4_0_rc2 = new Version(7, 3, 241), // 7.4 RC2 is version 7.3.241
48+
v8_2_0_rc1 = new Version(8, 1, 240); // 8.2 RC1 is version 8.1.240
4849
#pragma warning restore SA1310 // Field names should not contain underscore
4950
#pragma warning restore SA1311 // Static readonly fields should begin with upper-case letter
5051

src/StackExchange.Redis/RedisLiterals.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public static readonly RedisValue
5757
AGGREGATE = "AGGREGATE",
5858
ALPHA = "ALPHA",
5959
AND = "AND",
60+
ANDOR = "ANDOR",
6061
ANY = "ANY",
6162
ASC = "ASC",
6263
AUTH = "AUTH",
@@ -73,6 +74,8 @@ public static readonly RedisValue
7374
DB = "DB",
7475
@default = "default",
7576
DESC = "DESC",
77+
DIFF = "DIFF",
78+
DIFF1 = "DIFF1",
7679
DOCTOR = "DOCTOR",
7780
ENCODING = "ENCODING",
7881
EX = "EX",
@@ -118,6 +121,7 @@ public static readonly RedisValue
118121
NUMSUB = "NUMSUB",
119122
NX = "NX",
120123
OBJECT = "OBJECT",
124+
ONE = "ONE",
121125
OR = "OR",
122126
PATTERN = "PATTERN",
123127
PAUSE = "PAUSE",
@@ -216,6 +220,10 @@ public static readonly RedisValue
216220
Bitwise.Or => OR,
217221
Bitwise.Xor => XOR,
218222
Bitwise.Not => NOT,
223+
Bitwise.Diff => DIFF,
224+
Bitwise.Diff1 => DIFF1,
225+
Bitwise.AndOr => ANDOR,
226+
Bitwise.One => ONE,
219227
_ => throw new ArgumentOutOfRangeException(nameof(operation)),
220228
};
221229
}

tests/StackExchange.Redis.Tests/KeyPrefixedDatabaseTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,6 +1239,42 @@ public void StringBitOperation_2()
12391239
mock.Received().StringBitOperation(Bitwise.Xor, "prefix:destination", Arg.Is(valid), CommandFlags.None);
12401240
}
12411241

1242+
[Fact]
1243+
public void StringBitOperation_Diff()
1244+
{
1245+
RedisKey[] keys = new RedisKey[] { "x", "y1", "y2" };
1246+
Expression<Predicate<RedisKey[]>> valid = _ => _.Length == 3 && _[0] == "prefix:x" && _[1] == "prefix:y1" && _[2] == "prefix:y2";
1247+
prefixed.StringBitOperation(Bitwise.Diff, "destination", keys, CommandFlags.None);
1248+
mock.Received().StringBitOperation(Bitwise.Diff, "prefix:destination", Arg.Is(valid), CommandFlags.None);
1249+
}
1250+
1251+
[Fact]
1252+
public void StringBitOperation_Diff1()
1253+
{
1254+
RedisKey[] keys = new RedisKey[] { "x", "y1", "y2" };
1255+
Expression<Predicate<RedisKey[]>> valid = _ => _.Length == 3 && _[0] == "prefix:x" && _[1] == "prefix:y1" && _[2] == "prefix:y2";
1256+
prefixed.StringBitOperation(Bitwise.Diff1, "destination", keys, CommandFlags.None);
1257+
mock.Received().StringBitOperation(Bitwise.Diff1, "prefix:destination", Arg.Is(valid), CommandFlags.None);
1258+
}
1259+
1260+
[Fact]
1261+
public void StringBitOperation_AndOr()
1262+
{
1263+
RedisKey[] keys = new RedisKey[] { "x", "y1", "y2" };
1264+
Expression<Predicate<RedisKey[]>> valid = _ => _.Length == 3 && _[0] == "prefix:x" && _[1] == "prefix:y1" && _[2] == "prefix:y2";
1265+
prefixed.StringBitOperation(Bitwise.AndOr, "destination", keys, CommandFlags.None);
1266+
mock.Received().StringBitOperation(Bitwise.AndOr, "prefix:destination", Arg.Is(valid), CommandFlags.None);
1267+
}
1268+
1269+
[Fact]
1270+
public void StringBitOperation_One()
1271+
{
1272+
RedisKey[] keys = new RedisKey[] { "a", "b", "c" };
1273+
Expression<Predicate<RedisKey[]>> valid = _ => _.Length == 3 && _[0] == "prefix:a" && _[1] == "prefix:b" && _[2] == "prefix:c";
1274+
prefixed.StringBitOperation(Bitwise.One, "destination", keys, CommandFlags.None);
1275+
mock.Received().StringBitOperation(Bitwise.One, "prefix:destination", Arg.Is(valid), CommandFlags.None);
1276+
}
1277+
12421278
[Fact]
12431279
public void StringBitPosition()
12441280
{

tests/StackExchange.Redis.Tests/KeyPrefixedTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,42 @@ public async Task StringBitOperationAsync_2()
11551155
await mock.Received().StringBitOperationAsync(Bitwise.Xor, "prefix:destination", Arg.Is(valid), CommandFlags.None);
11561156
}
11571157

1158+
[Fact]
1159+
public async Task StringBitOperationAsync_Diff()
1160+
{
1161+
RedisKey[] keys = new RedisKey[] { "x", "y1", "y2" };
1162+
Expression<Predicate<RedisKey[]>> valid = _ => _.Length == 3 && _[0] == "prefix:x" && _[1] == "prefix:y1" && _[2] == "prefix:y2";
1163+
await prefixed.StringBitOperationAsync(Bitwise.Diff, "destination", keys, CommandFlags.None);
1164+
await mock.Received().StringBitOperationAsync(Bitwise.Diff, "prefix:destination", Arg.Is(valid), CommandFlags.None);
1165+
}
1166+
1167+
[Fact]
1168+
public async Task StringBitOperationAsync_Diff1()
1169+
{
1170+
RedisKey[] keys = new RedisKey[] { "x", "y1", "y2" };
1171+
Expression<Predicate<RedisKey[]>> valid = _ => _.Length == 3 && _[0] == "prefix:x" && _[1] == "prefix:y1" && _[2] == "prefix:y2";
1172+
await prefixed.StringBitOperationAsync(Bitwise.Diff1, "destination", keys, CommandFlags.None);
1173+
await mock.Received().StringBitOperationAsync(Bitwise.Diff1, "prefix:destination", Arg.Is(valid), CommandFlags.None);
1174+
}
1175+
1176+
[Fact]
1177+
public async Task StringBitOperationAsync_AndOr()
1178+
{
1179+
RedisKey[] keys = new RedisKey[] { "x", "y1", "y2" };
1180+
Expression<Predicate<RedisKey[]>> valid = _ => _.Length == 3 && _[0] == "prefix:x" && _[1] == "prefix:y1" && _[2] == "prefix:y2";
1181+
await prefixed.StringBitOperationAsync(Bitwise.AndOr, "destination", keys, CommandFlags.None);
1182+
await mock.Received().StringBitOperationAsync(Bitwise.AndOr, "prefix:destination", Arg.Is(valid), CommandFlags.None);
1183+
}
1184+
1185+
[Fact]
1186+
public async Task StringBitOperationAsync_One()
1187+
{
1188+
RedisKey[] keys = new RedisKey[] { "a", "b", "c" };
1189+
Expression<Predicate<RedisKey[]>> valid = _ => _.Length == 3 && _[0] == "prefix:a" && _[1] == "prefix:b" && _[2] == "prefix:c";
1190+
await prefixed.StringBitOperationAsync(Bitwise.One, "destination", keys, CommandFlags.None);
1191+
await mock.Received().StringBitOperationAsync(Bitwise.One, "prefix:destination", Arg.Is(valid), CommandFlags.None);
1192+
}
1193+
11581194
[Fact]
11591195
public async Task StringBitPositionAsync()
11601196
{

0 commit comments

Comments
 (0)