Skip to content

Commit 8e43404

Browse files
committed
CSHARP-4486: Add support for bitwise operators.
1 parent 190d37c commit 8e43404

File tree

13 files changed

+481
-224
lines changed

13 files changed

+481
-224
lines changed

src/MongoDB.Driver.Core/Core/Misc/Feature.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class Feature
4545
private static readonly Feature __aggregateToString = new Feature("AggregateToString", WireVersion.Server40);
4646
private static readonly Feature __aggregateUnionWith = new Feature("AggregateUnionWith", WireVersion.Server44);
4747
private static readonly Feature __arrayFilters = new Feature("ArrayFilters", WireVersion.Server36);
48+
private static readonly Feature __bitwiseOperators = new Feature("BitwiseOperators", WireVersion.Server63);
4849
private static readonly Feature __bypassDocumentValidation = new Feature("BypassDocumentValidation", WireVersion.Server32);
4950
private static readonly Feature __changeStreamStage = new Feature("ChangeStreamStage", WireVersion.Server36);
5051
private static readonly Feature __changeStreamAllChangesForCluster = new Feature("ChangeStreamAllChangesForCluster", WireVersion.Server40);
@@ -261,6 +262,11 @@ public class Feature
261262
[Obsolete("This property will be removed in a later release.")]
262263
public static Feature ArrayFilters => __arrayFilters;
263264

265+
/// <summary>
266+
/// Gets the bitwise operators feature.
267+
/// </summary>
268+
public static Feature BitwiseOperators => __bitwiseOperators;
269+
264270
/// <summary>
265271
/// Gets the bypass document validation feature.
266272
/// </summary>

src/MongoDB.Driver/Linq/Linq3Implementation/Ast/AstNodeType.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ internal enum AstNodeType
2020
AccumulatorField,
2121
AddFieldsStage,
2222
AllFilterOperation,
23-
AndExpression,
2423
AndFilter,
2524
BinaryExpression,
2625
BinaryWindowExpression,
@@ -103,7 +102,6 @@ internal enum AstNodeType
103102
NorFilter,
104103
NotFilterOperation,
105104
NullaryWindowExpression,
106-
OrExpression,
107105
OrFilter,
108106
OutStage,
109107
PickAccumulatorExpression,

src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstAndExpression.cs

Lines changed: 0 additions & 59 deletions
This file was deleted.

src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstExpression.cs

Lines changed: 68 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -80,24 +80,8 @@ public static AstExpression Add(params AstExpression[] args)
8080
return new AstConstantExpression(value);
8181
}
8282

83-
if (args.Any(arg => arg is AstNaryExpression naryExpression && naryExpression.Operator == AstNaryOperator.Add))
84-
{
85-
var flattenedArgs = new List<AstExpression>();
86-
foreach (var arg in args)
87-
{
88-
if (arg is AstNaryExpression naryExpression && naryExpression.Operator == AstNaryOperator.Add)
89-
{
90-
flattenedArgs.AddRange(naryExpression.Args);
91-
}
92-
else
93-
{
94-
flattenedArgs.Add(arg);
95-
}
96-
}
97-
return new AstNaryExpression(AstNaryOperator.Add, flattenedArgs);
98-
}
99-
100-
return new AstNaryExpression(AstNaryOperator.Add, args);
83+
var flattenedArgs = FlattenNaryArgs(args, AstNaryOperator.Add);
84+
return new AstNaryExpression(AstNaryOperator.Add, flattenedArgs);
10185
}
10286

10387
public static AstExpression AllElementsTrue(AstExpression array)
@@ -122,24 +106,8 @@ public static AstExpression And(params AstExpression[] args)
122106
return new AstConstantExpression(value);
123107
}
124108

125-
if (args.Any(arg => arg.NodeType == AstNodeType.AndExpression))
126-
{
127-
var flattenedArgs = new List<AstExpression>();
128-
foreach (var arg in args)
129-
{
130-
if (arg is AstAndExpression andExpression)
131-
{
132-
flattenedArgs.AddRange(andExpression.Args);
133-
}
134-
else
135-
{
136-
flattenedArgs.Add(arg);
137-
}
138-
}
139-
return new AstAndExpression(flattenedArgs);
140-
}
141-
142-
return new AstAndExpression(args);
109+
var flattenedArgs = FlattenNaryArgs(args, AstNaryOperator.And);
110+
return new AstNaryExpression(AstNaryOperator.And, flattenedArgs);
143111
}
144112

145113
public static AstExpression ArrayElemAt(AstExpression array, AstExpression index)
@@ -162,6 +130,42 @@ public static AstExpression BinaryWindowExpression(AstBinaryWindowOperator @oper
162130
return new AstBinaryWindowExpression(@operator, arg1, arg2, window);
163131
}
164132

133+
public static AstExpression BitAnd(params AstExpression[] args)
134+
{
135+
Ensure.IsNotNull(args, nameof(args));
136+
Ensure.That(args.Length > 0, "args cannot be empty.", nameof(args));
137+
Ensure.That(!args.Contains(null), "args cannot contain null.", nameof(args));
138+
139+
var flattenedArgs = FlattenNaryArgs(args, AstNaryOperator.BitAnd);
140+
return new AstNaryExpression(AstNaryOperator.BitAnd, flattenedArgs);
141+
}
142+
143+
public static AstExpression BitNot(AstExpression arg)
144+
{
145+
Ensure.IsNotNull(arg, nameof(arg));
146+
return new AstUnaryExpression(AstUnaryOperator.BitNot, arg);
147+
}
148+
149+
public static AstExpression BitOr(params AstExpression[] args)
150+
{
151+
Ensure.IsNotNull(args, nameof(args));
152+
Ensure.That(args.Length > 0, "args cannot be empty.", nameof(args));
153+
Ensure.That(!args.Contains(null), "args cannot contain null.", nameof(args));
154+
155+
var flattenedArgs = FlattenNaryArgs(args, AstNaryOperator.BitOr);
156+
return new AstNaryExpression(AstNaryOperator.BitOr, flattenedArgs);
157+
}
158+
159+
public static AstExpression BitXor(params AstExpression[] args)
160+
{
161+
Ensure.IsNotNull(args, nameof(args));
162+
Ensure.That(args.Length > 0, "args cannot be empty.", nameof(args));
163+
Ensure.That(!args.Contains(null), "args cannot contain null.", nameof(args));
164+
165+
var flattenedArgs = FlattenNaryArgs(args, AstNaryOperator.BitXor);
166+
return new AstNaryExpression(AstNaryOperator.BitXor, flattenedArgs);
167+
}
168+
165169
public static AstExpression Ceil(AstExpression arg)
166170
{
167171
return new AstUnaryExpression(AstUnaryOperator.Ceil, arg);
@@ -213,24 +217,8 @@ public static IEnumerable<AstComputedField> ComputedFields(params (string name,
213217

214218
public static AstExpression Concat(params AstExpression[] args)
215219
{
216-
if (args.Any(a => a is AstNaryExpression naryExpression && naryExpression.Operator == AstNaryOperator.Concat))
217-
{
218-
var flattenedArgs = new List<AstExpression>();
219-
foreach (var arg in args)
220-
{
221-
if (arg is AstNaryExpression naryExpression && naryExpression.Operator == AstNaryOperator.Concat)
222-
{
223-
flattenedArgs.AddRange(naryExpression.Args);
224-
}
225-
else
226-
{
227-
flattenedArgs.Add(arg);
228-
}
229-
}
230-
return new AstNaryExpression(AstNaryOperator.Concat, flattenedArgs);
231-
}
232-
233-
return new AstNaryExpression(AstNaryOperator.Concat, args);
220+
var flattenedArgs = FlattenNaryArgs(args, AstNaryOperator.Concat);
221+
return new AstNaryExpression(AstNaryOperator.Concat, flattenedArgs);
234222
}
235223

236224
public static AstExpression ConcatArrays(params AstExpression[] arrays)
@@ -568,25 +556,8 @@ public static AstExpression Mod(AstExpression arg1, AstExpression arg2)
568556

569557
public static AstExpression Multiply(params AstExpression[] args)
570558
{
571-
if (args.Any(arg => arg is AstNaryExpression naryExpression && naryExpression.Operator == AstNaryOperator.Multiply))
572-
{
573-
var flattenedArgs = new List<AstExpression>();
574-
foreach (var arg in args)
575-
{
576-
if (arg is AstNaryExpression naryExpression && naryExpression.Operator == AstNaryOperator.Multiply)
577-
{
578-
flattenedArgs.AddRange(naryExpression.Args);
579-
}
580-
else
581-
{
582-
flattenedArgs.Add(arg);
583-
}
584-
}
585-
return new AstNaryExpression(AstNaryOperator.Multiply, flattenedArgs);
586-
}
587-
588-
589-
return new AstNaryExpression(AstNaryOperator.Multiply, args);
559+
var flattenedArgs = FlattenNaryArgs(args, AstNaryOperator.Multiply);
560+
return new AstNaryExpression(AstNaryOperator.Multiply, flattenedArgs);
590561
}
591562

592563
public static AstExpression Ne(AstExpression arg1, AstExpression arg2)
@@ -610,24 +581,8 @@ public static AstExpression Or(params AstExpression[] args)
610581
Ensure.That(args.Length > 0, "args cannot be empty.", nameof(args));
611582
Ensure.That(!args.Contains(null), "args cannot contain null.", nameof(args));
612583

613-
if (args.Any(a => a.NodeType == AstNodeType.OrExpression))
614-
{
615-
var flattenedArgs = new List<AstExpression>();
616-
foreach (var arg in args)
617-
{
618-
if (arg is AstOrExpression orExpression)
619-
{
620-
flattenedArgs.AddRange(orExpression.Args);
621-
}
622-
else
623-
{
624-
flattenedArgs.Add(arg);
625-
}
626-
}
627-
return new AstOrExpression(flattenedArgs);
628-
}
629-
630-
return new AstOrExpression(args);
584+
var flattenedArgs = FlattenNaryArgs(args, AstNaryOperator.Or);
585+
return new AstNaryExpression(AstNaryOperator.Or, flattenedArgs);
631586
}
632587

633588
public static AstExpression PickExpression(AstPickOperator @operator, AstExpression source, AstSortFields sortBy, AstVarExpression @as, AstExpression selector, AstExpression n)
@@ -951,6 +906,28 @@ private static bool AllArgsAreConstantInt32s(AstExpression[] args, out List<int>
951906
values = null;
952907
return false;
953908
}
909+
910+
private static IEnumerable<AstExpression> FlattenNaryArgs(IEnumerable<AstExpression> args, AstNaryOperator naryOperator)
911+
{
912+
if (args.Any(arg => arg is AstNaryExpression naryExpression && naryExpression.Operator == naryOperator))
913+
{
914+
var flattenedArgs = new List<AstExpression>();
915+
foreach (var arg in args)
916+
{
917+
if (arg is AstNaryExpression naryExpression && naryExpression.Operator == naryOperator)
918+
{
919+
flattenedArgs.AddRange(naryExpression.Args);
920+
}
921+
else
922+
{
923+
flattenedArgs.Add(arg);
924+
}
925+
}
926+
return flattenedArgs;
927+
}
928+
929+
return args;
930+
}
954931
#endregion static
955932

956933
// public methods

src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstNaryExpression.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public AstNaryExpression(AstNaryOperator @operator, IEnumerable<AstExpression> a
3131
{
3232
_operator = @operator;
3333
_args = Ensure.IsNotNull(args, nameof(args)).AsReadOnlyList();
34+
Ensure.That(!args.Contains(null), "args cannot contain null.", nameof(args));
3435
}
3536

3637
public AstNaryExpression(AstNaryOperator @operator, params AstExpression[] args)

src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstNaryOperator.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,18 @@ namespace MongoDB.Driver.Linq.Linq3Implementation.Ast.Expressions
2020
internal enum AstNaryOperator
2121
{
2222
Add,
23+
And,
2324
Avg,
25+
BitAnd,
26+
BitOr,
27+
BitXor,
2428
Concat,
2529
ConcatArrays,
2630
Max,
2731
MergeObjects,
2832
Min,
2933
Multiply,
34+
Or,
3035
SetEquals,
3136
SetIntersection,
3237
SetUnion,
@@ -42,13 +47,18 @@ public static string Render(this AstNaryOperator @operator)
4247
return @operator switch
4348
{
4449
AstNaryOperator.Add => "$add",
50+
AstNaryOperator.And => "$and",
4551
AstNaryOperator.Avg => "$avg",
52+
AstNaryOperator.BitAnd => "$bitAnd",
53+
AstNaryOperator.BitOr => "$bitOr",
54+
AstNaryOperator.BitXor => "$bitXor",
4655
AstNaryOperator.Concat => "$concat",
4756
AstNaryOperator.ConcatArrays => "$concatArrays",
4857
AstNaryOperator.Max => "$max",
4958
AstNaryOperator.MergeObjects => "$mergeObjects",
5059
AstNaryOperator.Min => "$min",
5160
AstNaryOperator.Multiply => "$multiply",
61+
AstNaryOperator.Or => "$or",
5262
AstNaryOperator.SetEquals => "$setEquals",
5363
AstNaryOperator.SetIntersection => "$setIntersection",
5464
AstNaryOperator.SetUnion => "$setUnion",

0 commit comments

Comments
 (0)