Skip to content

Commit 0848d1d

Browse files
committed
Implemented the modulus operator.
1 parent 2627145 commit 0848d1d

5 files changed

Lines changed: 30 additions & 1 deletion

File tree

SqlServerSimulator.Tests/SelectTests.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ public void SelectParameterValue(string commandText, string name, object value)
5858
[DataRow("2 * 2", 4)]
5959
[DataRow("2 / 2", 1)]
6060
[DataRow("2 / 1", 2)]
61+
[DataRow("5 % 2", 1)]
62+
[DataRow("5 % 3", 2)]
63+
[DataRow("5 % 5", 0)]
6164
[DataRow("1 & 3", 1)]
6265
[DataRow("1 | 3", 3)]
6366
[DataRow("1 ^ 3", 2)]

SqlServerSimulator/DataType.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ public abstract class NumericCompatibleDataType : DataType
141141
public abstract object? Divide(object? a, object? b);
142142

143143
public DataValue Divide(DataValue a, DataValue b) => new(Divide(a.Value, b.Value), this);
144+
145+
public abstract object? Modulus(object? a, object? b);
146+
147+
public DataValue Modulus(DataValue a, DataValue b) => new(Modulus(a.Value, b.Value), this);
144148
}
145149

146150
public abstract class BitwiseCompatibleDataType : NumericCompatibleDataType
@@ -178,6 +182,8 @@ private sealed class DbBoolean : BitwiseCompatibleDataType
178182

179183
public override object? Divide(object? a, object? b) => throw new NotImplementedException();
180184

185+
public override object? Modulus(object? a, object? b) => throw new NotImplementedException();
186+
181187
public override object? BitwiseAnd(object? a, object? b) => throw new NotImplementedException();
182188

183189
public override object? BitwiseOr(object? a, object? b) => throw new NotImplementedException();
@@ -205,6 +211,8 @@ private sealed class DbByte : BitwiseCompatibleDataType
205211

206212
public override object? Divide(object? a, object? b) => throw new NotImplementedException();
207213

214+
public override object? Modulus(object? a, object? b) => throw new NotImplementedException();
215+
208216
public override object? BitwiseAnd(object? a, object? b) => throw new NotImplementedException();
209217

210218
public override object? BitwiseOr(object? a, object? b) => throw new NotImplementedException();
@@ -232,6 +240,8 @@ private sealed class DbInt16 : BitwiseCompatibleDataType
232240

233241
public override object? Divide(object? a, object? b) => throw new NotImplementedException();
234242

243+
public override object? Modulus(object? a, object? b) => throw new NotImplementedException();
244+
235245
public override object? BitwiseAnd(object? a, object? b) => throw new NotImplementedException();
236246

237247
public override object? BitwiseOr(object? a, object? b) => throw new NotImplementedException();
@@ -286,6 +296,8 @@ private static bool TryToNative(object? rawA, object? rawB, out int a, out int b
286296

287297
public override object? Divide(object? a, object? b) => TryToNative(a, b, out var nativeA, out var nativeB) ? nativeA / nativeB : null;
288298

299+
public override object? Modulus(object? a, object? b) => TryToNative(a, b, out var nativeA, out var nativeB) ? nativeA % nativeB : null;
300+
289301
public override object? BitwiseAnd(object? a, object? b) => TryToNative(a, b, out var nativeA, out var nativeB) ? nativeA & nativeB : null;
290302

291303
public override object? BitwiseOr(object? a, object? b) => TryToNative(a, b, out var nativeA, out var nativeB) ? nativeA | nativeB : null;

SqlServerSimulator/Parser/Expression.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ public static Expression Parse(ParserContext context)
9090
context.MoveNextRequired();
9191
expression = new Divide(expression, Parse(context));
9292
break;
93+
case Operator { Character: '%' }:
94+
context.MoveNextRequired();
95+
expression = new Modulus(expression, Parse(context));
96+
break;
9397
case Operator { Character: '&' }:
9498
context.MoveNextRequired();
9599
expression = new BitwiseAnd(expression, Parse(context));
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace SqlServerSimulator.Parser.Expressions;
2+
3+
internal sealed class Modulus(Expression left, Expression right) : MathExpression(left, right)
4+
{
5+
public override byte Precedence => 3;
6+
7+
protected override DataValue Run(DataType.NumericCompatibleDataType common, DataValue left, DataValue right) => common.Modulus(left, right);
8+
9+
protected override char Operator => '+';
10+
}

SqlServerSimulator/Parser/Tokenizer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ static class Tokenizer
2525
'-' => ParseMinusOrComment(command, ref index),
2626
'/' => ParseForwardSlashOrComment(command, ref index),
2727
'[' => ParseBracketDelimitedString(command, ref index),
28-
'+' or '*' or '(' or ')' or ',' or '.' or ';' or '=' or '&' or '|' or '^' or '>' or '<' or '!' => new Operator(command, index),
28+
'+' or '*' or '%' or '(' or ')' or ',' or '.' or ';' or '=' or '&' or '|' or '^' or '>' or '<' or '!' => new Operator(command, index),
2929
var c => throw SimulatedSqlException.SyntaxErrorNear(c) // Might throw on valid-but-unsupported syntax.
3030
};
3131

0 commit comments

Comments
 (0)