@@ -106,7 +106,7 @@ class SqlParser(private val ion: IonSystem) : Parser {
106
106
INSERT (isTopLevelType = true , isDml = true ),
107
107
INSERT_VALUE (isTopLevelType = true , isDml = true ),
108
108
REMOVE (isTopLevelType = true , isDml = true ),
109
- SET ,
109
+ SET (isTopLevelType = true , isDml = true ) ,
110
110
UPDATE (isTopLevelType = true , isDml = true ),
111
111
DELETE (isTopLevelType = true , isDml = true ),
112
112
ASSIGNMENT ,
@@ -2253,17 +2253,34 @@ class SqlParser(private val ion: IonSystem) : Parser {
2253
2253
return ParseNode (ARG_LIST , null , items, rem)
2254
2254
}
2255
2255
2256
+ private fun ParseNode.throwTopLevelParserError (): Nothing =
2257
+ token?.err(" Keyword $token only expected at the top level in the query" , PARSE_UNEXPECTED_TERM )
2258
+ ? : throw ParserException (" Keyword $token only expected at the top level in the query" , PARSE_UNEXPECTED_TERM , PropertyValueMap ())
2256
2259
2257
2260
/* *
2258
2261
* Validates tree to make sure that the top level tokens are not found below the top level
2259
2262
*/
2260
- private fun validateTopLevelNodes (node : ParseNode , level : Int ) {
2261
- // Note that for DML operations, top level parse node is of type 'FROM'. Hence the check level > 1
2262
- if (node.type.isTopLevelType && ((node.type.isDml && level > 1 ) || (! node.type.isDml && level > 0 ))) {
2263
- node.token?.err(" Type ${node.type} only expected at the top level" , PARSE_UNEXPECTED_TERM )
2264
- ? : throw ParserException (" Type ${node.type} only expected at the top level" , PARSE_UNEXPECTED_TERM , PropertyValueMap ())
2263
+ private fun validateTopLevelNodes (node : ParseNode , level : Int , topLevelTokens : Int ) {
2264
+ val topTokens = topLevelTokens + when (node.type.isTopLevelType) {
2265
+ true -> 1
2266
+ false -> 0
2265
2267
}
2266
- node.children.map { validateTopLevelNodes(it, level + 1 ) }
2268
+
2269
+ if (topTokens > 1 ) {
2270
+ node.throwTopLevelParserError()
2271
+ }
2272
+
2273
+ if (node.type.isTopLevelType && level > 0 ) {
2274
+ // Note that for DML operations, top level parse node may be of type 'FROM'. Hence the check level > 1
2275
+ if (node.type.isDml) {
2276
+ if (level > 1 ) {
2277
+ node.throwTopLevelParserError()
2278
+ }
2279
+ } else {
2280
+ node.throwTopLevelParserError()
2281
+ }
2282
+ }
2283
+ node.children.map { validateTopLevelNodes(it, level + 1 , topTokens) }
2267
2284
}
2268
2285
2269
2286
/* * Entry point into the parser. */
@@ -2279,7 +2296,7 @@ class SqlParser(private val ion: IonSystem) : Parser {
2279
2296
}
2280
2297
}
2281
2298
2282
- validateTopLevelNodes(node, 0 )
2299
+ validateTopLevelNodes(node, 0 , 0 )
2283
2300
2284
2301
return node.toExprNode()
2285
2302
}
0 commit comments