[CALCITE-6986] Parser rejects SQL sources that produce an empty statement list
Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
diff --git a/core/src/main/codegen/templates/Parser.jj b/core/src/main/codegen/templates/Parser.jj
index c02de6c..fa7593c 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -1115,17 +1115,19 @@
SqlNode stmt;
}
{
- stmt = SqlStmt() {
- stmtList.add(stmt);
- }
(
- <SEMICOLON>
- [
- stmt = SqlStmt() {
- stmtList.add(stmt);
- }
- ]
- )*
+ stmt = SqlStmt() {
+ stmtList.add(stmt);
+ }
+ (
+ <SEMICOLON>
+ [
+ stmt = SqlStmt() {
+ stmtList.add(stmt);
+ }
+ ]
+ )*
+ )?
<EOF>
{
return new SqlNodeList(stmtList, Span.of(stmtList).pos());
diff --git a/core/src/main/java/org/apache/calcite/sql/parser/SqlParserPos.java b/core/src/main/java/org/apache/calcite/sql/parser/SqlParserPos.java
index 53e6234..97fb72c 100644
--- a/core/src/main/java/org/apache/calcite/sql/parser/SqlParserPos.java
+++ b/core/src/main/java/org/apache/calcite/sql/parser/SqlParserPos.java
@@ -229,7 +229,7 @@ public static SqlParserPos sum(Iterable<SqlParserPos> poses) {
? (List<SqlParserPos>) poses
: Lists.newArrayList(poses);
if (list.isEmpty()) {
- throw new AssertionError();
+ return SqlParserPos.ZERO;
}
final SqlParserPos pos0 = list.get(0);
if (list.size() == 1) {
diff --git a/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java b/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java
index a01a8c7..0939a59 100644
--- a/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java
+++ b/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java
@@ -2111,6 +2111,14 @@ void checkPeriodPredicate(Checker checker) {
+ "FROM `DEPT`))) AND (3 = 4))");
}
+ /** Test case for <a href="https://issues.apache.org/jira/browse/CALCITE-6986">[CALCITE-6986]
+ * Parser rejects SQL sources that produce an empty statement list</a>. */
+ @Test public void testEmpty() {
+ sql("").list().ok();
+ sql(" ").list().ok();
+ sql("-- comment").list().ok();
+ }
+
@Test void testUnique() {
sql("select * from dept where unique (select 1 from emp where emp.deptno = dept.deptno)")
.ok("SELECT *\n"
diff --git a/testkit/src/main/java/org/apache/calcite/sql/test/SqlTestFactory.java b/testkit/src/main/java/org/apache/calcite/sql/test/SqlTestFactory.java
index 86476b5..9ecc842 100644
--- a/testkit/src/main/java/org/apache/calcite/sql/test/SqlTestFactory.java
+++ b/testkit/src/main/java/org/apache/calcite/sql/test/SqlTestFactory.java
@@ -130,6 +130,12 @@ protected SqlTestFactory(CatalogReaderFactory catalogReaderFactory,
/** Creates a parser. */
public SqlParser createParser(String sql) {
+ if (sql.isEmpty()) {
+ // I could not figure out how to convince the grammar to accept an empty
+ // string. Without this change I get an exception in the token reader in code
+ // generated by JavaCC
+ sql = " ";
+ }
SqlParser.Config parserConfig = parserConfig();
return SqlParser.create(new SourceStringReader(sql), parserConfig);
}