@@ -39,164 +39,153 @@ internal IEnumerable<SimulatedStatementOutcome> CreateResultSetsForCommand(Simul
3939 case Operator { Character : ';' } :
4040 continue ;
4141
42- case ReservedKeyword reserved :
43- switch ( reserved . Keyword )
42+ case ReservedKeyword { Keyword : Keyword . Set } :
43+ if ( TryParseSet ( context ) )
44+ continue ;
45+ break ;
46+
47+ case ReservedKeyword { Keyword : Keyword . Create } :
48+ switch ( context . GetNextRequired ( ) )
4449 {
45- case Keyword . Set :
46- switch ( context . GetNextRequired ( ) )
50+ case ReservedKeyword { Keyword : Keyword . Table } :
51+ if ( context . GetNextRequired ( ) is not Name tableName )
52+ break ;
53+
54+ if ( context . GetNextRequired ( ) is not Operator { Character : '(' } )
55+ break ;
56+
57+ var table = new Table ( tableName . Value ) ;
58+
59+ var columns = table . Columns ;
60+ bool suppressAdvanceToken ;
61+ do
4762 {
48- case UnquotedString setTarget :
49- switch ( setTarget . Value . ToUpperInvariant ( ) )
63+ suppressAdvanceToken = false ;
64+ var columnName = context . GetNextRequired < Name > ( ) ;
65+ var type = context . GetNextRequired < Name > ( ) ;
66+
67+ var nullable = true ;
68+
69+ context . MoveNextRequired ( ) ;
70+ if ( context . Token is ReservedKeyword next )
71+ {
72+ switch ( next . Keyword )
5073 {
51- case "IMPLICIT_TRANSACTIONS" :
52- case "NOCOUNT" :
53- switch ( context . GetNextRequired ( ) )
54- {
55- case ReservedKeyword onOff :
56- switch ( onOff . Keyword )
57- {
58- case Keyword . On :
59- case Keyword . Off :
60- continue ;
61- }
62- break ;
63- }
74+ case Keyword . Not :
75+ if ( context . GetNextRequired ( ) is not ReservedKeyword { Keyword : Keyword . Null } )
76+ throw SimulatedSqlException . SyntaxErrorNear ( context ) ;
77+
78+ nullable = false ;
79+ break ;
80+ case Keyword . Null :
81+ nullable = true ;
6482 break ;
83+ default :
84+ throw SimulatedSqlException . SyntaxErrorNear ( context ) ;
6585 }
66- break ;
67- }
68- break ;
86+ }
87+ else
88+ {
89+ suppressAdvanceToken = true ;
90+ nullable = true ;
91+ }
6992
70- case Keyword . Create :
71- switch ( context . GetNextRequired ( ) )
72- {
73- case ReservedKeyword whatToCreate :
74- switch ( whatToCreate . Keyword )
75- {
76- case Keyword . Table :
77- if ( context . GetNextRequired ( ) is not Name tableName )
78- break ;
79-
80- if ( context . GetNextRequired ( ) is not Operator { Character : '(' } )
81- break ;
82-
83- var table = new Table ( tableName . Value ) ;
84-
85- var columns = table . Columns ;
86- bool suppressAdvanceToken ;
87- do
88- {
89- suppressAdvanceToken = false ;
90- var columnName = context . GetNextRequired < Name > ( ) ;
91- var type = context . GetNextRequired < Name > ( ) ;
92-
93- var nullable = true ;
94-
95- context . MoveNextRequired ( ) ;
96- if ( context . Token is ReservedKeyword next )
97- {
98- switch ( next . Keyword )
99- {
100- case Keyword . Not :
101- if ( context . GetNextRequired ( ) is not ReservedKeyword { Keyword : Keyword . Null } )
102- throw SimulatedSqlException . SyntaxErrorNear ( context ) ;
103-
104- nullable = false ;
105- break ;
106- case Keyword . Null :
107- nullable = true ;
108- break ;
109- default :
110- throw SimulatedSqlException . SyntaxErrorNear ( context ) ;
111- }
112- }
113- else
114- {
115- suppressAdvanceToken = true ;
116- nullable = true ;
117- }
118-
119- columns . Add ( new ( columnName . Value , DataType . GetByName ( type , columns . Count + 1 ) , nullable ) ) ;
120- } while ( ( suppressAdvanceToken ? context . Token : context . GetNextRequired ( ) ) is Operator { Character : ',' } ) ;
121-
122- if ( context . Token is not Operator { Character : ')' } )
123- break ;
124-
125- if ( ! this . Tables . TryAdd ( table . Name , table ) )
126- throw SimulatedSqlException . ThereIsAlreadyAnObject ( table . Name ) ;
127-
128- continue ;
129- }
130- break ;
131- }
132- break ;
93+ columns . Add ( new ( columnName . Value , DataType . GetByName ( type , columns . Count + 1 ) , nullable ) ) ;
94+ } while ( ( suppressAdvanceToken ? context . Token : context . GetNextRequired ( ) ) is Operator { Character : ',' } ) ;
13395
134- case Keyword . Select :
135- yield return Selection . Parse ( context , 0 ) . Results ;
136- break ;
96+ if ( context . Token is not Operator { Character : ')' } )
97+ break ;
13798
138- case Keyword . Insert :
139- if ( context . GetNextRequired ( ) is ReservedKeyword { Keyword : Keyword . Into } )
140- context . MoveNextRequired ( ) ;
99+ if ( ! this . Tables . TryAdd ( table . Name , table ) )
100+ throw SimulatedSqlException . ThereIsAlreadyAnObject ( table . Name ) ;
141101
142- if ( context . Token is not StringToken destinationTableToken )
143- break ;
102+ continue ;
103+ }
104+ break ;
144105
145- if ( ! this . Tables . TryGetValue ( destinationTableToken . Value , out var destinationTable ) )
146- throw SimulatedSqlException . InvalidObjectName ( destinationTableToken ) ;
106+ case ReservedKeyword { Keyword : Keyword . Select } :
107+ yield return Selection . Parse ( context , 0 ) . Results ;
108+ continue ;
147109
148- Column [ ] destinationColumns ;
149- if ( context . GetNextRequired ( ) is Operator { Character : '(' } )
150- {
151- var usedColumns = new List < Column > ( ) ;
152- while ( context . GetNextRequired ( ) is StringToken column )
153- {
154- var columnName = column . Value ;
155- var tableColumn = destinationTable . Columns . FirstOrDefault ( c => Collation . Default . Equals ( c . Name , columnName ) )
156- ?? throw SimulatedSqlException . InvalidColumnName ( columnName ) ;
157- usedColumns . Add ( tableColumn ) ;
158- }
110+ case ReservedKeyword { Keyword : Keyword . Insert } :
111+ if ( context . GetNextRequired ( ) is ReservedKeyword { Keyword : Keyword . Into } )
112+ context . MoveNextRequired ( ) ;
159113
160- if ( context . Token is not Operator { Character : ')' } )
161- break ;
114+ if ( context . Token is not StringToken destinationTableToken )
115+ break ;
162116
163- destinationColumns = [ .. usedColumns ] ;
117+ if ( ! this . Tables . TryGetValue ( destinationTableToken . Value , out var destinationTable ) )
118+ throw SimulatedSqlException . InvalidObjectName ( destinationTableToken ) ;
164119
165- context . MoveNextRequired ( ) ;
166- }
167- else
168- {
169- destinationColumns = [ .. destinationTable . Columns ] ;
170- }
120+ Column [ ] destinationColumns ;
121+ if ( context . GetNextRequired ( ) is Operator { Character : '(' } )
122+ {
123+ var usedColumns = new List < Column > ( ) ;
124+ while ( context . GetNextRequired ( ) is StringToken column )
125+ {
126+ var columnName = column . Value ;
127+ var tableColumn = destinationTable . Columns . FirstOrDefault ( c => Collation . Default . Equals ( c . Name , columnName ) )
128+ ?? throw SimulatedSqlException . InvalidColumnName ( columnName ) ;
129+ usedColumns . Add ( tableColumn ) ;
130+ }
131+
132+ if ( context . Token is not Operator { Character : ')' } )
133+ break ;
171134
172- if ( context . Token is not ReservedKeyword { Keyword : Keyword . Values } )
173- break ;
135+ destinationColumns = [ .. usedColumns ] ;
174136
175- var sourceRows = new List < Token [ ] > ( ) ;
137+ context . MoveNextRequired ( ) ;
138+ }
139+ else
140+ {
141+ destinationColumns = [ .. destinationTable . Columns ] ;
142+ }
176143
177- do
178- {
179- if ( context . GetNextRequired < Operator > ( ) is not { Character : '(' } )
180- throw SimulatedSqlException . SyntaxErrorNear ( context ) ;
144+ if ( context . Token is not ReservedKeyword { Keyword : Keyword . Values } )
145+ break ;
181146
182- var sourceValues = new List < Token > ( ) ;
183- while ( context . GetNextRequired ( ) is not Operator { Character : ')' } )
184- sourceValues . Add ( context . Token ) ;
147+ var sourceRows = new List < Token [ ] > ( ) ;
185148
186- sourceRows . Add ( [ .. sourceValues ] ) ;
149+ do
150+ {
151+ if ( context . GetNextRequired < Operator > ( ) is not { Character : '(' } )
152+ throw SimulatedSqlException . SyntaxErrorNear ( context ) ;
187153
188- } while ( context . GetNextOptional ( ) is Operator { Character : ',' } ) ;
154+ var sourceValues = new List < Token > ( ) ;
155+ while ( context . GetNextRequired ( ) is not Operator { Character : ')' } )
156+ sourceValues . Add ( context . Token ) ;
189157
190- destinationTable . ReceiveData ( destinationColumns , sourceRows , context . GetVariableValue ) ;
158+ sourceRows . Add ( [ .. sourceValues ] ) ;
191159
192- yield return new SimulatedNonQuery ( sourceRows . Count ) ;
193- continue ;
194- }
195- break ;
160+ } while ( context . GetNextOptional ( ) is Operator { Character : ',' } ) ;
161+
162+ destinationTable . ReceiveData ( destinationColumns , sourceRows , context . GetVariableValue ) ;
196163
197- default :
198- throw SimulatedSqlException . SyntaxErrorNear ( context ) ;
164+ yield return new SimulatedNonQuery ( sourceRows . Count ) ;
165+ continue ;
199166 }
167+
168+ throw SimulatedSqlException . SyntaxErrorNear ( context ) ;
200169 } // while (tokens.TryMoveNext(out var token))
201170 }
171+
172+ private static bool TryParseSet ( ParserContext context )
173+ {
174+ var setTarget = context . GetNextRequired < UnquotedString > ( ) . Value ;
175+ Span < char > upper = stackalloc char [ setTarget . Length ] ;
176+ return setTarget . ToUpperInvariant ( upper ) switch
177+ {
178+ 7 => upper switch
179+ {
180+ "NOCOUNT" => context . GetNextRequired ( ) is ReservedKeyword { Keyword : Keyword . On or Keyword . Off } ,
181+ _ => false
182+ } ,
183+ 21 => upper switch
184+ {
185+ "IMPLICIT_TRANSACTIONS" => context . GetNextRequired ( ) is ReservedKeyword { Keyword : Keyword . On or Keyword . Off } ,
186+ _ => false
187+ } ,
188+ _ => false
189+ } ;
190+ }
202191}
0 commit comments