Skip to content

Commit fc66745

Browse files
committed
Improved support for square-bracket-delimited identifiers.
1 parent 83af035 commit fc66745

3 files changed

Lines changed: 22 additions & 4 deletions

File tree

SqlServerSimulator.Tests/SelectTests.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public void Expression(string commandText, object value)
6060

6161
[TestMethod]
6262
[DataRow("select 1 as c", "c", 1)]
63+
[DataRow("select 1 as [c]", "c", 1)]
64+
[DataRow("select 1 as [c]]d]", "c]d", 1)]
65+
[DataRow("select 1 as [e f]", "e f", 1)]
6366
[DataRow("select 1 + 1 as c", "c", 2)]
6467
public void Expression(string commandText, string name, object value)
6568
{

SqlServerSimulator/Parser/Tokenizer.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using SqlServerSimulator.Parser.Tokens;
2+
using System.Text;
23

34
namespace SqlServerSimulator.Parser;
45

@@ -13,6 +14,7 @@ static class Tokenizer
1314
/// <param name="command">The command from which a token is produced.</param>
1415
/// <param name="index">The position within <paramref name="command"/> of the previous token (or -1), updated to where the next token ends.</param>
1516
/// <returns>The next token, or null if the end of <paramref name="command"/> has been reached.</returns>
17+
/// <exception cref="SimulatedSqlException">Incorrect or unsupported syntax.</exception>
1618
public static Token? NextToken(string command, ref int index) =>
1719
++index >= command.Length ? null : command[index] switch
1820
{
@@ -29,7 +31,7 @@ static class Tokenizer
2931
',' => new Comma(command, index),
3032
'.' => new Period(command, index),
3133
';' => new StatementTerminator(command, index),
32-
_ => throw new NotSupportedException($"Simulated tokenizer doesn't know what to do with character '{command[index]}' at index {index}.")
34+
var c => throw SimulatedSqlException.SyntaxErrorNear(c) // Might throw on valid-but-unsupported syntax.
3335
};
3436

3537
private static Whitespace ParseWhitespace(string command, ref int index)
@@ -141,15 +143,26 @@ private static Token ParseMinusOrComment(string command, ref int index)
141143
private static BracketDelimitedString ParseBracketDelimitedString(string command, ref int index)
142144
{
143145
var start = index;
146+
var builder = new StringBuilder();
144147
while (++index < command.Length)
145148
{
146-
if (command[index] != ']')
149+
var c = command[index];
150+
if (c != ']')
151+
{
152+
_ = builder.Append(c);
147153
continue;
154+
}
155+
156+
if (index + 1 < command.Length && command[index + 1] == ']')
157+
{
158+
_ = builder.Append(']');
159+
index++;
160+
continue;
161+
}
148162

149-
index++;
150163
break;
151164
}
152165

153-
return new(command.Substring(start + 1, index - start - 2), command, start, index-- - start);
166+
return new(builder.ToString(), command, start, index - start);
154167
}
155168
}

SqlServerSimulator/SimulatedSqlException.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ internal static SimulatedSqlException ColumnReferenceNotAllowed(IEnumerable<stri
110110

111111
internal static SimulatedSqlException SyntaxErrorNear(Token? token) => new($"Incorrect syntax near '{token}'.", 102, 15, 1);
112112

113+
internal static SimulatedSqlException SyntaxErrorNear(char c) => new($"Incorrect syntax near '{c}'.", 102, 15, 1);
114+
113115
internal static SimulatedSqlException ThereIsAlreadyAnObject(string name) => new($"There is already an object named '{name}' in the database.", 2714, 16, 6);
114116

115117
/// <summary>

0 commit comments

Comments
 (0)