11using SqlServerSimulator . Parser . Tokens ;
2+ using System . Collections . Frozen ;
23
34namespace SqlServerSimulator . Parser ;
45
@@ -69,16 +70,30 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
6970 if ( expression is null )
7071 throw new NotSupportedException ( "Simulated expression parser doesn't know how to handle '.' at the start of an expression." ) ;
7172
72- if ( expression is not Reference reference )
73- throw new NotSupportedException ( "Simulated expression parser doesn't know how to handle '.' here." ) ;
73+ {
74+ if ( expression is not Reference reference )
75+ throw new NotSupportedException ( "Simulated expression parser doesn't know how to handle '.' here." ) ;
7476
75- reference . AddMultiPartComponent ( tokens . RequireNext < Name > ( ) ) ;
77+ reference . AddMultiPartComponent ( tokens . RequireNext < Name > ( ) ) ;
78+ }
7679 break ;
7780 case Comma :
7881 case CloseParentheses :
7982 if ( expression is null )
8083 throw SimulatedSqlException . SyntaxErrorNear ( token ) ;
8184 return expression ;
85+ case OpenParentheses :
86+ {
87+ if ( expression is not Reference reference )
88+ throw SimulatedSqlException . SyntaxErrorNear ( token ) ;
89+ if ( ! BuiltInFunctions . TryGetValue ( reference . Name , out var builtInFunction ) )
90+ throw SimulatedSqlException . UnrecognizedBuiltInFunction ( reference . Name ) ;
91+
92+ token = tokens . RequireNext ( ) ; // Move past (
93+ expression = builtInFunction ( simulation , tokens , ref token , getVariableValue ) ;
94+ _ = tokens . TryMoveNext ( out token ) ; // Move past )
95+ return expression ;
96+ }
8297 default :
8398 throw new NotSupportedException ( $ "Simulated expression parser doesn't know how to handle '{ token } '.") ;
8499 }
@@ -93,6 +108,12 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
93108 public abstract override string ToString ( ) ;
94109#endif
95110
111+ private delegate Expression FunctionResolver ( Simulation simulation , IEnumerator < Token > tokens , ref Token ? token , Func < string , object ? > getVariableValue ) ;
112+
113+ private static readonly FrozenDictionary < string , FunctionResolver > BuiltInFunctions = FrozenDictionary . Create < string , FunctionResolver > ( Collation . Default , [
114+ new ( "datalength" , ( simulation , tokens , ref token , getVariableValue ) => new DataLength( Expression . Parse ( simulation , tokens , ref token , getVariableValue ) ) )
115+ ] ) ;
116+
96117 private sealed class NamedExpression ( Expression expression , string name ) : Expression
97118 {
98119 private readonly Expression expression = expression ;
@@ -179,29 +200,34 @@ public sealed class Add(Expression left, Expression right) : Expression
179200#endif
180201 }
181202
182- public sealed class Reference : Expression
203+ public sealed class Reference ( Name name ) : Expression
183204 {
184- private readonly List < string > name = [ ] ;
185-
186- public Reference ( Name name )
187- {
188- this . name . Add ( name . Value ) ;
189- }
205+ private readonly List < string > name = [ name . Value ] ;
190206
191207 public override string Name => this . name . Last ( ) ;
192208
193- public void AddMultiPartComponent ( Name name )
194- {
195- this . name . Add ( name . Value ) ;
196- }
209+ public void AddMultiPartComponent ( Name name ) => this . name . Add ( name . Value ) ;
197210
198- public override object ? Run ( Func < List < string > , object ? > getColumnValue )
199- {
200- return getColumnValue ( this . name ) ;
201- }
211+ public override object ? Run ( Func < List < string > , object ? > getColumnValue ) => getColumnValue ( this . name ) ;
202212
203213#if DEBUG
204214 public override string ToString ( ) => string . Join ( '.' , name ) ;
215+ #endif
216+ }
217+
218+ public sealed class DataLength ( Expression source ) : Expression
219+ {
220+ private readonly Expression source = source ;
221+
222+ public override object ? Run ( Func < List < string > , object ? > getColumnValue ) => source . Run ( getColumnValue ) switch
223+ {
224+ null => null ,
225+ int => 4 ,
226+ _ => throw new NotSupportedException ( $ "Simulation unable to to run DATALENGTH function on the provided expression.") ,
227+ } ;
228+
229+ #if DEBUG
230+ public override string ToString ( ) => $ "DATALENGTH({ source } )";
205231#endif
206232 }
207233}
0 commit comments