Skip to content

Commit 0e44a51

Browse files
Ruben Fiszelrubenfiszel
authored andcommitted
[SPARK-24345][SQL] Improve ParseError stop location when offending symbol is a token
In the case where the offending symbol is a CommonToken, this PR increases the accuracy of the start and stop origin by leveraging the start and stop index information from CommonToken. Closes #21334 from rubenfiszel/patch-1. Lead-authored-by: Ruben Fiszel <[email protected]> Co-authored-by: rubenfiszel <[email protected]> Signed-off-by: Sean Owen <[email protected]>
1 parent 938d954 commit 0e44a51

File tree

2 files changed

+22
-9
lines changed

2 files changed

+22
-9
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/ParseDriver.scala

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,17 @@ case object ParseErrorListener extends BaseErrorListener {
203203
charPositionInLine: Int,
204204
msg: String,
205205
e: RecognitionException): Unit = {
206-
val position = Origin(Some(line), Some(charPositionInLine))
207-
throw new ParseException(None, msg, position, position)
206+
val (start, stop) = offendingSymbol match {
207+
case token: CommonToken =>
208+
val start = Origin(Some(line), Some(token.getCharPositionInLine))
209+
val length = token.getStopIndex - token.getStartIndex + 1
210+
val stop = Origin(Some(line), Some(token.getCharPositionInLine + length))
211+
(start, stop)
212+
case _ =>
213+
val start = Origin(Some(line), Some(charPositionInLine))
214+
(start, start)
215+
}
216+
throw new ParseException(None, msg, start, stop)
208217
}
209218
}
210219

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ErrorParserSuite.scala

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,17 @@ import org.apache.spark.SparkFunSuite
2222
* Test various parser errors.
2323
*/
2424
class ErrorParserSuite extends SparkFunSuite {
25-
def intercept(sql: String, line: Int, startPosition: Int, messages: String*): Unit = {
25+
def intercept(sql: String, line: Int, startPosition: Int, stopPosition: Int,
26+
messages: String*): Unit = {
2627
val e = intercept[ParseException](CatalystSqlParser.parsePlan(sql))
2728

2829
// Check position.
2930
assert(e.line.isDefined)
3031
assert(e.line.get === line)
3132
assert(e.startPosition.isDefined)
3233
assert(e.startPosition.get === startPosition)
34+
assert(e.stop.startPosition.isDefined)
35+
assert(e.stop.startPosition.get === stopPosition)
3336

3437
// Check messages.
3538
val error = e.getMessage
@@ -39,23 +42,24 @@ class ErrorParserSuite extends SparkFunSuite {
3942
}
4043

4144
test("no viable input") {
42-
intercept("select ((r + 1) ", 1, 16, "no viable alternative at input", "----------------^^^")
45+
intercept("select ((r + 1) ", 1, 16, 16,
46+
"no viable alternative at input", "----------------^^^")
4347
}
4448

4549
test("extraneous input") {
46-
intercept("select 1 1", 1, 9, "extraneous input '1' expecting", "---------^^^")
47-
intercept("select *\nfrom r as q t", 2, 12, "extraneous input", "------------^^^")
50+
intercept("select 1 1", 1, 9, 10, "extraneous input '1' expecting", "---------^^^")
51+
intercept("select *\nfrom r as q t", 2, 12, 13, "extraneous input", "------------^^^")
4852
}
4953

5054
test("mismatched input") {
51-
intercept("select * from r order by q from t", 1, 27,
55+
intercept("select * from r order by q from t", 1, 27, 31,
5256
"mismatched input",
5357
"---------------------------^^^")
54-
intercept("select *\nfrom r\norder by q\nfrom t", 4, 0, "mismatched input", "^^^")
58+
intercept("select *\nfrom r\norder by q\nfrom t", 4, 0, 4, "mismatched input", "^^^")
5559
}
5660

5761
test("semantic errors") {
58-
intercept("select *\nfrom r\norder by q\ncluster by q", 3, 0,
62+
intercept("select *\nfrom r\norder by q\ncluster by q", 3, 0, 11,
5963
"Combination of ORDER BY/SORT BY/DISTRIBUTE BY/CLUSTER BY is not supported",
6064
"^^^")
6165
}

0 commit comments

Comments
 (0)