Skip to content

Commit f9e6fba

Browse files
committed
Reworked built-in function lookup to use relatively simple switch expressions.
1 parent 25e0b0b commit f9e6fba

1 file changed

Lines changed: 29 additions & 17 deletions

File tree

SqlServerSimulator/Parser/Expression.cs

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

43
namespace SqlServerSimulator.Parser;
54

@@ -132,11 +131,8 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
132131
{
133132
if (expression is not Reference reference)
134133
throw SimulatedSqlException.SyntaxErrorNear(token);
135-
if (!BuiltInFunctions.TryGetValue(reference.Name, out var builtInFunction))
136-
throw SimulatedSqlException.UnrecognizedBuiltInFunction(reference.Name);
137-
138134
token = tokens.RequireNext(); // Move past (
139-
expression = builtInFunction(simulation, tokens, ref token, getVariableValue);
135+
expression = ResolveBuiltIn(reference.Name, simulation, tokens, ref token, getVariableValue);
140136
_ = tokens.TryMoveNext(out token); // Move past )
141137
return expression;
142138
}
@@ -159,12 +155,24 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
159155
public abstract override string ToString();
160156
#endif
161157

162-
private delegate Expression FunctionResolver(Simulation simulation, IEnumerator<Token> tokens, ref Token? token, Func<string, object?> getVariableValue);
163-
164-
private static readonly FrozenDictionary<string, FunctionResolver> BuiltInFunctions = FrozenDictionary.Create<string, FunctionResolver>(Collation.Default, [
165-
new("datalength", (simulation, tokens, ref token, getVariableValue) => new DataLength(Expression.Parse(simulation, tokens, ref token, getVariableValue))),
166-
new("abs", (simulation, tokens, ref token, getVariableValue) => new AbsoluteValue(Expression.Parse(simulation, tokens, ref token, getVariableValue))),
167-
]);
158+
private static Expression ResolveBuiltIn(string name, Simulation simulation, IEnumerator<Token> tokens, ref Token? token, Func<string, object?> getVariableValue)
159+
{
160+
Span<char> uppercaseName = stackalloc char[name.Length];
161+
return name.ToUpperInvariant(uppercaseName) switch
162+
{
163+
3 => uppercaseName switch
164+
{
165+
"ABS" => new AbsoluteValue(simulation, tokens, ref token, getVariableValue),
166+
_ => null
167+
},
168+
10 => uppercaseName switch
169+
{
170+
"DATALENGTH" => new DataLength(simulation, tokens, ref token, getVariableValue),
171+
_ => null
172+
},
173+
_ => (Expression?)null
174+
} ?? throw SimulatedSqlException.UnrecognizedBuiltInFunction(name);
175+
}
168176

169177
/// <summary>
170178
/// An expression that has been given a name, such as with `as`.
@@ -296,10 +304,12 @@ public sealed class Reference(Name name) : Expression
296304
/// <summary>
297305
/// Encapsulates the SQL DATALENGTH command: https://learn.microsoft.com/en-us/sql/t-sql/functions/datalength-transact-sql
298306
/// </summary>
299-
/// <param name="source">Provides the value to be processed.</param>
300-
public sealed class DataLength(Expression source) : Expression
307+
public sealed class DataLength : Expression
301308
{
302-
private readonly Expression source = source;
309+
private readonly Expression source;
310+
311+
public DataLength(Simulation simulation, IEnumerator<Token> tokens, ref Token? token, Func<string, object?> getVariableValue)
312+
=> this.source = Expression.Parse(simulation, tokens, ref token, getVariableValue);
303313

304314
public override object? Run(Func<List<string>, object?> getColumnValue) => source.Run(getColumnValue) switch
305315
{
@@ -316,10 +326,12 @@ public sealed class DataLength(Expression source) : Expression
316326
/// <summary>
317327
/// Encapsulates the SQL ABS command: https://learn.microsoft.com/en-us/sql/t-sql/functions/abs-transact-sql
318328
/// </summary>
319-
/// <param name="source">Provides the value to be processed.</param>
320-
public sealed class AbsoluteValue(Expression source) : Expression
329+
public sealed class AbsoluteValue : Expression
321330
{
322-
private readonly Expression source = source;
331+
private readonly Expression source;
332+
333+
public AbsoluteValue(Simulation simulation, IEnumerator<Token> tokens, ref Token? token, Func<string, object?> getVariableValue)
334+
=> this.source = Expression.Parse(simulation, tokens, ref token, getVariableValue);
323335

324336
public override object? Run(Func<List<string>, object?> getColumnValue) => source.Run(getColumnValue) switch
325337
{

0 commit comments

Comments
 (0)