This is an automated email from the ASF dual-hosted git repository.
danny0405 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new be9a4e1 [CALCITE-4115] Improve the prompt of using SQL keywords for
sql parser
be9a4e1 is described below
commit be9a4e177957ea07498e680269ceff126a170317
Author: yuzhao.cyz <[email protected]>
AuthorDate: Thu Jul 9 18:17:46 2020 +0800
[CALCITE-4115] Improve the prompt of using SQL keywords for sql parser
When the parser encounters a reserved-keyword and throws, change the
error message format to:
Incorrect syntax near the keyword '{keyword}' at line {line_number}, column
{column_number}.
The new format indicates that the next token is a keyword clearly so
that user can choose to use a non-reserved keyword or quotes the keyword
instead.
---
core/src/main/codegen/templates/Parser.jj | 16 ++++++++++++++++
.../java/org/apache/calcite/sql/parser/SqlParser.java | 12 +-----------
.../org/apache/calcite/sql/parser/SqlParserUtil.java | 15 +++++++++++++++
.../org/apache/calcite/sql/parser/SqlParserTest.java | 14 +++++++-------
.../parserextensiontesting/ExtensionSqlParserTest.java | 2 +-
.../org/apache/calcite/sql/test/SqlOperatorBaseTest.java | 2 +-
.../java/org/apache/calcite/test/SqlValidatorTest.java | 2 +-
7 files changed, 42 insertions(+), 21 deletions(-)
diff --git a/core/src/main/codegen/templates/Parser.jj
b/core/src/main/codegen/templates/Parser.jj
index 835fd4a..9986798 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -437,6 +437,22 @@ JAVACODE SqlParseException convertException(Throwable ex)
tokenImage = pex.tokenImage;
if (pex.currentToken != null) {
final Token token = pex.currentToken.next;
+ // Checks token.image.equals("1") to avoid recursive call.
+ // The SqlAbstractParserImpl#MetadataImpl constructor uses
constant "1" to
+ // throw intentionally to collect the expected tokens.
+ if (!token.image.equals("1") &&
getMetadata().isKeyword(token.image)) {
+ // If the next token is a keyword, reformat the error message
as:
+
+ // Incorrect syntax near the keyword '{keyword}' at line
{line_number},
+ // column {column_number}.
+ final String errorMsg = String.format("Incorrect syntax near
the keyword '%s' "
+ + "at line %d, column %d.",
+ token.image,
+ token.beginLine,
+ token.beginColumn);
+ // Replace the ParseException with explicit error message.
+ ex = new ParseException(errorMsg);
+ }
pos = new SqlParserPos(
token.beginLine,
token.beginColumn,
diff --git a/core/src/main/java/org/apache/calcite/sql/parser/SqlParser.java
b/core/src/main/java/org/apache/calcite/sql/parser/SqlParser.java
index b6eabb9..ed4c2f2 100644
--- a/core/src/main/java/org/apache/calcite/sql/parser/SqlParser.java
+++ b/core/src/main/java/org/apache/calcite/sql/parser/SqlParser.java
@@ -54,17 +54,7 @@ public class SqlParser {
parser.setUnquotedCasing(config.unquotedCasing());
parser.setIdentifierMaxLength(config.identifierMaxLength());
parser.setConformance(config.conformance());
- switch (config.quoting()) {
- case DOUBLE_QUOTE:
- parser.switchTo("DQID");
- break;
- case BACK_TICK:
- parser.switchTo("BTID");
- break;
- case BRACKET:
- parser.switchTo("DEFAULT");
- break;
- }
+ parser.switchTo(SqlParserUtil.quotingToParserState(config.quoting()));
}
//~ Methods ----------------------------------------------------------------
diff --git
a/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java
b/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java
index 0cf9738..aec0c6f 100644
--- a/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java
+++ b/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java
@@ -18,6 +18,7 @@ package org.apache.calcite.sql.parser;
import org.apache.calcite.avatica.util.Casing;
import org.apache.calcite.avatica.util.DateTimeUtils;
+import org.apache.calcite.avatica.util.Quoting;
import org.apache.calcite.config.CalciteSystemProperty;
import org.apache.calcite.rel.type.RelDataTypeSystem;
import org.apache.calcite.runtime.CalciteContextException;
@@ -732,6 +733,20 @@ public final class SqlParserUtil {
return c;
}
+ /** Returns the corresponding parser state with the give quoting. */
+ public static String quotingToParserState(Quoting quoting) {
+ switch (quoting) {
+ case DOUBLE_QUOTE:
+ return "DQID";
+ case BACK_TICK:
+ return "BTID";
+ case BRACKET:
+ return "DEFAULT";
+ default:
+ throw new AssertionError(quoting);
+ }
+ }
+
//~ Inner Classes ----------------------------------------------------------
/** The components of a collation definition, per the SQL standard. */
diff --git
a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
index 19cd942..919643a 100644
--- a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
@@ -1788,7 +1788,7 @@ public class SqlParserTest {
@Test void testDefault() {
sql("select ^DEFAULT^ from emp")
- .fails("(?s)Encountered \"DEFAULT\" at .*");
+ .fails("(?s)Incorrect syntax near the keyword 'DEFAULT' at .*");
sql("select cast(empno ^+^ DEFAULT as double) from emp")
.fails("(?s)Encountered \"\\+ DEFAULT\" at .*");
sql("select empno ^+^ DEFAULT + deptno from emp")
@@ -1796,11 +1796,11 @@ public class SqlParserTest {
sql("select power(0, DEFAULT ^+^ empno) from emp")
.fails("(?s)Encountered \"\\+\" at .*");
sql("select * from emp join dept on ^DEFAULT^")
- .fails("(?s)Encountered \"DEFAULT\" at .*");
+ .fails("(?s)Incorrect syntax near the keyword 'DEFAULT' at .*");
sql("select * from emp where empno ^>^ DEFAULT or deptno < 10")
.fails("(?s)Encountered \"> DEFAULT\" at .*");
sql("select * from emp order by ^DEFAULT^ desc")
- .fails("(?s)Encountered \"DEFAULT\" at .*");
+ .fails("(?s)Incorrect syntax near the keyword 'DEFAULT' at .*");
final String expected = "INSERT INTO `DEPT` (`NAME`, `DEPTNO`)\n"
+ "VALUES (ROW('a', DEFAULT))";
sql("insert into dept (name, deptno) values ('a', DEFAULT)")
@@ -1808,7 +1808,7 @@ public class SqlParserTest {
sql("insert into dept (name, deptno) values ('a', 1 ^+^ DEFAULT)")
.fails("(?s)Encountered \"\\+ DEFAULT\" at .*");
sql("insert into dept (name, deptno) select 'a', ^DEFAULT^ from (values
0)")
- .fails("(?s)Encountered \"DEFAULT\" at .*");
+ .fails("(?s)Incorrect syntax near the keyword 'DEFAULT' at .*");
}
@Test void testAggregateFilter() {
@@ -4309,7 +4309,7 @@ public class SqlParserTest {
expr("CAST(12 AS DATE)")
.ok("CAST(12 AS DATE)");
sql("CAST('2000-12-21' AS DATE ^NOT^ NULL)")
- .fails("(?s).*Encountered \"NOT\" at line 1, column 27.*");
+ .fails("(?s).*Incorrect syntax near the keyword 'NOT' at line 1,
column 27.*");
sql("CAST('foo' as ^1^)")
.fails("(?s).*Encountered \"1\" at line 1, column 15.*");
expr("Cast(DATE '2004-12-21' AS VARCHAR(10))")
@@ -4395,9 +4395,9 @@ public class SqlParserTest {
expr("{fn convert(1, VARCHAR^(^5))}")
.fails("(?s)Encountered \"\\(\" at.*");
expr("{fn convert(1, ^INTERVAL^ YEAR TO MONTH)}")
- .fails("(?s)Encountered \"INTERVAL\" at.*");
+ .fails("(?s)Incorrect syntax near the keyword 'INTERVAL' at.*");
expr("{fn convert(1, ^INTERVAL^ YEAR)}")
- .fails("(?s)Encountered \"INTERVAL\" at.*");
+ .fails("(?s)Incorrect syntax near the keyword 'INTERVAL' at.*");
}
@Test void testWindowReference() {
diff --git
a/core/src/test/java/org/apache/calcite/sql/parser/parserextensiontesting/ExtensionSqlParserTest.java
b/core/src/test/java/org/apache/calcite/sql/parser/parserextensiontesting/ExtensionSqlParserTest.java
index 7070b10..bd0068e 100644
---
a/core/src/test/java/org/apache/calcite/sql/parser/parserextensiontesting/ExtensionSqlParserTest.java
+++
b/core/src/test/java/org/apache/calcite/sql/parser/parserextensiontesting/ExtensionSqlParserTest.java
@@ -55,6 +55,6 @@ class ExtensionSqlParserTest extends SqlParserTest {
sql("DESCRIBE SPACE POWER")
.node(new IsNull<SqlNode>());
sql("DESCRIBE SEA ^POWER^")
- .fails("(?s)Encountered \"POWER\" at line 1, column 14..*");
+ .fails("(?s)Incorrect syntax near the keyword 'POWER' at line 1,
column 14.*");
}
}
diff --git
a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
index 2315934..0d2f838 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
@@ -8350,7 +8350,7 @@ public abstract class SqlOperatorBaseTest {
tester.checkFails("timestampdiff(CENTURY, "
+ "timestamp '2014-02-24 12:42:25', "
+ "timestamp '2614-02-24 12:42:25')",
- "(?s)Encountered \"CENTURY\" at .*", false);
+ "(?s)Incorrect syntax near the keyword 'CENTURY' at .*", false);
tester.checkScalar("timestampdiff(QUARTER, "
+ "timestamp '2014-02-24 12:42:25', "
+ "cast(null as timestamp))",
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index b141a3f..efa267b 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -1566,7 +1566,7 @@ class SqlValidatorTest extends SqlValidatorTestCase {
expr("\"TRIM\"('b')").ok();
} else {
expr("^\"TRIM\"('b' FROM 'a')^")
- .fails("(?s).*Encountered \"FROM\" at .*");
+ .fails("(?s).*Incorrect syntax near the keyword 'FROM' at .*");
// Without the "FROM" noise word, TRIM is parsed as a regular
// function without quoting and built-in function with quoting.