Skip to content

Commit a9de025

Browse files
committed
Added logic to handle top level DML tokens
1 parent fec50de commit a9de025

File tree

2 files changed

+45
-8
lines changed

2 files changed

+45
-8
lines changed

lang/src/org/partiql/lang/syntax/SqlParser.kt

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class SqlParser(private val ion: IonSystem) : Parser {
106106
INSERT(isTopLevelType = true, isDml = true),
107107
INSERT_VALUE(isTopLevelType = true, isDml = true),
108108
REMOVE(isTopLevelType = true, isDml = true),
109-
SET,
109+
SET(isTopLevelType = true, isDml = true),
110110
UPDATE(isTopLevelType = true, isDml = true),
111111
DELETE(isTopLevelType = true, isDml = true),
112112
ASSIGNMENT,
@@ -2253,17 +2253,34 @@ class SqlParser(private val ion: IonSystem) : Parser {
22532253
return ParseNode(ARG_LIST, null, items, rem)
22542254
}
22552255

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())
22562259

22572260
/**
22582261
* Validates tree to make sure that the top level tokens are not found below the top level
22592262
*/
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
22652267
}
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) }
22672284
}
22682285

22692286
/** Entry point into the parser. */
@@ -2279,7 +2296,7 @@ class SqlParser(private val ion: IonSystem) : Parser {
22792296
}
22802297
}
22812298

2282-
validateTopLevelNodes(node, 0)
2299+
validateTopLevelNodes(node, 0, 0)
22832300

22842301
return node.toExprNode()
22852302
}

lang/test/org/partiql/lang/errors/ParserErrorsTest.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,26 @@ class ParserErrorsTest : TestBase() {
13261326
Property.TOKEN_TYPE to TokenType.KEYWORD,
13271327
Property.TOKEN_VALUE to ion.newSymbol("create")))
13281328

1329+
@Test
1330+
fun nestedRemove() = checkInputThrowingParserException(
1331+
"REMOVE REMOVE y",
1332+
ErrorCode.PARSE_INVALID_PATH_COMPONENT,
1333+
mapOf(
1334+
Property.LINE_NUMBER to 1L,
1335+
Property.COLUMN_NUMBER to 8L,
1336+
Property.TOKEN_TYPE to TokenType.KEYWORD,
1337+
Property.TOKEN_VALUE to ion.newSymbol("remove")))
1338+
1339+
@Test
1340+
fun nestedInsertInto() = checkInputThrowingParserException(
1341+
"INSERT INTO foo VALUE INSERT INTO foo VALUE 1 AT bar",
1342+
ErrorCode.PARSE_UNEXPECTED_TERM,
1343+
mapOf(
1344+
Property.LINE_NUMBER to 1L,
1345+
Property.COLUMN_NUMBER to 23L,
1346+
Property.TOKEN_TYPE to TokenType.KEYWORD,
1347+
Property.TOKEN_VALUE to ion.newSymbol("insert_into")))
1348+
13291349
@Test
13301350
fun updateWithDropIndex() = checkInputThrowingParserException(
13311351
"UPDATE test SET x = DROP INDEX bar ON foo",

0 commit comments

Comments
 (0)