This is an automated email from the ASF dual-hosted git repository.
xuzifu666 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new d095b8cad6 [CALCITE-5973] Parsing DDL error message is inaccurate
d095b8cad6 is described below
commit d095b8cad68ceebe4d95f5c828e6389ee5cf9a36
Author: Yu Xu <[email protected]>
AuthorDate: Sat Oct 24 10:55:35 2026 +0800
[CALCITE-5973] Parsing DDL error message is inaccurate
---
core/src/main/codegen/templates/Parser.jj | 7 ++++++-
.../org/apache/calcite/runtime/CalciteResource.java | 6 ++++++
.../calcite/runtime/CalciteResource.properties | 1 +
.../apache/calcite/test/ExceptionMessageTest.java | 21 ++++++++++++++++++++-
core/src/test/resources/sql/set-op.iq | 2 +-
.../apache/calcite/sql/parser/SqlParserTest.java | 19 +++++++++++++++++++
6 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/core/src/main/codegen/templates/Parser.jj
b/core/src/main/codegen/templates/Parser.jj
index 726eaf45e9..6317b9c088 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -1301,7 +1301,12 @@ SqlNode SqlStmt() :
stmt = SqlTruncate()
|
</#if>
- stmt = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY)
+ stmt = OrderedQueryOrExpr(ExprContext.ACCEPT_NONCURSOR) {
+ if (!stmt.isA(SqlKind.QUERY)) {
+ throw SqlUtil.newContextException(stmt.getParserPosition(),
+ RESOURCE.invalidStatement());
+ }
+ }
|
stmt = SqlExplain()
|
diff --git a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
index 093fcb4e50..d7ceb5bbe2 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
@@ -85,6 +85,12 @@ public interface CalciteResource {
@BaseMessage("Non-query expression encountered in illegal context")
ExInst<CalciteException> illegalNonQueryExpression();
+ /** Invalid statement, e.g. {@code "1 + 1"} is not a valid statement
+ * because a statement must be a query (SELECT, VALUES, TABLE)
+ * or a statement keyword (INSERT, UPDATE, DELETE, ...). */
+ @BaseMessage("Invalid SQL statement: query or other statement expected")
+ ExInst<CalciteException> invalidStatement();
+
@BaseMessage("Query expression encountered in illegal context")
ExInst<CalciteException> illegalQueryExpression();
diff --git
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
index 43c7e1db1b..4ef7f50d1d 100644
---
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
+++
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
@@ -36,6 +36,7 @@ IllegalIntervalLiteral=Illegal INTERVAL literal {0}; at {1}
IllegalMinusDate=Illegal expression. Was expecting "(DATETIME - DATETIME)
INTERVALQUALIFIER"
IllegalOverlaps=Illegal overlaps expression. Was expecting expression on the
form "(DATETIME, EXPRESSION) OVERLAPS (DATETIME, EXPRESSION)"
IllegalNonQueryExpression=Non-query expression encountered in illegal context
+InvalidStatement=Invalid SQL statement: query or other statement expected
IllegalQueryExpression=Query expression encountered in illegal context
IllegalCursorExpression=CURSOR expression encountered in illegal context
IllegalOrderBy=ORDER BY unexpected
diff --git
a/core/src/test/java/org/apache/calcite/test/ExceptionMessageTest.java
b/core/src/test/java/org/apache/calcite/test/ExceptionMessageTest.java
index 825af84f4f..6fd264373b 100644
--- a/core/src/test/java/org/apache/calcite/test/ExceptionMessageTest.java
+++ b/core/src/test/java/org/apache/calcite/test/ExceptionMessageTest.java
@@ -161,7 +161,26 @@ private void runQuery(Function<RelBuilder, RelNode> relFn)
} catch (SQLException e) {
assertThat(e.getMessage(),
equalTo("Error while executing SQL \"invalid sql\": parse failed: "
- + "Non-query expression encountered in illegal context"));
+ + "Invalid SQL statement: query or other statement expected"));
+ }
+ }
+
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-5973">[CALCITE-5973]
+ * Invalid statement yields misleading parse error</a>.
+ */
+ @Test void testSyntaxErrorOnInvalidStatement() {
+ try (Fixture f = new Fixture()) {
+ // Statement that cannot be parsed as any known statement or query;
+ // previously failed with the misleading message
+ // "Non-query expression encountered in illegal context"
+ f.runQuery("reate table t (a int, b varchar) with('key' = 'value')");
+ fail("Query should fail");
+ } catch (SQLException e) {
+ assertThat(e.getMessage(),
+ equalTo("Error while executing SQL \"reate table t (a int, b
varchar)"
+ + " with('key' = 'value')\": parse failed: "
+ + "Invalid SQL statement: query or other statement expected"));
}
}
diff --git a/core/src/test/resources/sql/set-op.iq
b/core/src/test/resources/sql/set-op.iq
index d1d998ea36..47bd82aefb 100644
--- a/core/src/test/resources/sql/set-op.iq
+++ b/core/src/test/resources/sql/set-op.iq
@@ -259,7 +259,7 @@ select * from emp where job = 'CLERK';
(emp natural join dept)
intersect
select * from emp natural join dept where job = 'CLERK';
-Non-query expression encountered in illegal context
+parse failed: Encountered "natural" at line 1, column 6.
!error
# [CALCITE-6303] UNION with CTE(s) results in exception during query validation
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 3b3b9640bd..952a2c97cf 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
@@ -3507,6 +3507,25 @@ void checkPeriodPredicate(Checker checker) {
.fails("Non-query expression encountered in illegal context");
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-5973">[CALCITE-5973]
+ * Invalid statement yields misleading parse error</a>.
+ *
+ * <p>A statement that is neither a query (SELECT, VALUES, TABLE, ...) nor
+ * any other supported statement should fail with a meaningful message,
+ * not with "Non-query expression encountered in illegal context". */
+ @Test void testInvalidStatementFails() {
+ sql("^invalid^")
+ .fails("Invalid SQL statement: query or other statement expected");
+ sql("^1 + 1^")
+ .fails("Invalid SQL statement: query or other statement expected");
+ sql("^invalid^ sql")
+ .fails("Invalid SQL statement: query or other statement expected");
+ // Statement with a typo in the leading keyword
+ sql("^reate^ table t (a int, b varchar) with('key' = 'value')")
+ .fails("Invalid SQL statement: query or other statement expected");
+ }
+
/**
* In modern SQL, a query can occur almost everywhere that an expression
* can. This test tests the few exceptions.