Skip to content

Commit 7f98886

Browse files
committed
Added support for multiplication, division, block comments.
1 parent 83b2e21 commit 7f98886

5 files changed

Lines changed: 74 additions & 0 deletions

File tree

SqlServerSimulator.Tests/SelectTests.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public void SelectParameterValue(string commandText, string name, object value)
5555
[DataRow("- 1", -1)]
5656
[DataRow("+1", 1)]
5757
[DataRow("+ 1", 1)]
58+
[DataRow("2 * 2", 4)]
59+
[DataRow("2 / 2", 1)]
60+
[DataRow("2 / 1", 2)]
5861
public void Expression(string commandText, object value)
5962
{
6063
using var reader = new Simulation().ExecuteReader($"select {commandText}");

SqlServerSimulator.Tests/SimpleCommandTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,10 @@ public void SingleLineCommentWithCarriageReturnCommand()
105105

106106
IsFalse(reader.Read());
107107
}
108+
109+
[TestMethod]
110+
public void BlockComment()
111+
{
112+
AreEqual(-1, new Simulation().ExecuteNonQuery("/* */"));
113+
}
108114
}

SqlServerSimulator/Parser/Expression.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ public static Expression Parse(ParserContext context)
7474
context.MoveNextRequired();
7575
expression = new Subtract(expression, Parse(context));
7676
break;
77+
case Operator { Character: '*' }:
78+
context.MoveNextRequired();
79+
expression = new Multiply(expression, Parse(context));
80+
break;
81+
case Operator { Character: '/' }:
82+
context.MoveNextRequired();
83+
expression = new Divide(expression, Parse(context));
84+
break;
7785

7886
case Operator { Character: '.' }:
7987
{
@@ -246,6 +254,40 @@ public sealed class Subtract(Expression left, Expression right) : Expression
246254
return (int)leftValue! - (int)rightValue!; // TODO: Handle varied input types here.
247255
}
248256

257+
#if DEBUG
258+
public override string ToString() => $"{left} + {right}";
259+
#endif
260+
}
261+
262+
public sealed class Multiply(Expression left, Expression right) : Expression
263+
{
264+
private readonly Expression left = left, right = right;
265+
266+
public override object? Run(Func<List<string>, object?> getColumnValue)
267+
{
268+
var leftValue = left.Run(getColumnValue);
269+
var rightValue = right.Run(getColumnValue);
270+
271+
return (int)leftValue! * (int)rightValue!; // TODO: Handle varied input types here.
272+
}
273+
274+
#if DEBUG
275+
public override string ToString() => $"{left} + {right}";
276+
#endif
277+
}
278+
279+
public sealed class Divide(Expression left, Expression right) : Expression
280+
{
281+
private readonly Expression left = left, right = right;
282+
283+
public override object? Run(Func<List<string>, object?> getColumnValue)
284+
{
285+
var leftValue = left.Run(getColumnValue);
286+
var rightValue = right.Run(getColumnValue);
287+
288+
return (int)leftValue! / (int)rightValue!; // TODO: Handle varied input types here.
289+
}
290+
249291
#if DEBUG
250292
public override string ToString() => $"{left} + {right}";
251293
#endif

SqlServerSimulator/Parser/Tokenizer.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ static class Tokenizer
2323
>= '0' and <= '9' => ParseNumeric(command, ref index),
2424
'@' => ParseAtOrDoubleAtPrefixedString(command, ref index),
2525
'-' => ParseMinusOrComment(command, ref index),
26+
'/' => ParseForwardSlashOrComment(command, ref index),
2627
'[' => ParseBracketDelimitedString(command, ref index),
2728
'+' or '*' or '(' or ')' or ',' or '.' or ';' or '=' => new Operator(command, index),
2829
var c => throw SimulatedSqlException.SyntaxErrorNear(c) // Might throw on valid-but-unsupported syntax.
@@ -134,6 +135,26 @@ private static Token ParseMinusOrComment(string command, ref int index)
134135
return new Comment(command, start, --index);
135136
}
136137

138+
private static Token ParseForwardSlashOrComment(string command, ref int index)
139+
{
140+
var start = index;
141+
if (++index == command.Length)
142+
return new Operator(command, --index);
143+
if (command[index] != '*')
144+
{
145+
index--;
146+
return new Operator(command, index);
147+
}
148+
149+
while (++index < command.Length)
150+
{
151+
if (command[index] == '*' && command.Length >= index + 2 && command[index + 1] == '/')
152+
return new Comment(command, start, index += 2);
153+
}
154+
155+
throw SimulatedSqlException.MissingEndCommentMark();
156+
}
157+
137158
private static BracketDelimitedString ParseBracketDelimitedString(string command, ref int index)
138159
{
139160
var start = index;

SqlServerSimulator/SimulatedSqlException.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ internal static SimulatedSqlException IdentifierTooLong(ReadOnlySpan<char> first
104104

105105
internal static SimulatedSqlException InvalidObjectName(StringToken name) => new($"Invalid object name {name}.", 208, 16, 1);
106106

107+
internal static SimulatedSqlException MissingEndCommentMark() => new("Missing end comment mark '*/'.", 113, 15, 1);
108+
107109
internal static SimulatedSqlException MustDeclareScalarVariable(string name) => new($"Must declare the scalar variable \"@{name}\".", 137, 15, 2);
108110

109111
internal static SimulatedSqlException SyntaxErrorNearKeyword(ReservedKeyword token) => new($"Incorrect syntax near the keyword '{token}'.", 156, 15, 1);

0 commit comments

Comments
 (0)