diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGenerator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGenerator.java index 7464e6d99fbf..046a94c1fa24 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGenerator.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGenerator.java @@ -94,6 +94,7 @@ import org.apache.iotdb.service.rpc.thrift.TSSetSchemaTemplateReq; import org.apache.iotdb.service.rpc.thrift.TSUnsetSchemaTemplateReq; +import org.antlr.v4.runtime.BailErrorStrategy; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; @@ -857,6 +858,9 @@ private static Statement invokeParser(String sql, ZoneId zoneId) { IoTDBSqlParser parser1 = new IoTDBSqlParser(tokens1); parser1.getInterpreter().setPredictionMode(PredictionMode.SLL); + // Any error in this stage falls back to the LL stage below, which reports it, so + // the SLL stage needs no recovery; BailErrorStrategy also skips the per-rule sync() checks. + parser1.setErrorHandler(new BailErrorStrategy()); parser1.removeErrorListeners(); parser1.addErrorListener(SqlParseError.INSTANCE); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/SqlParser.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/SqlParser.java index 3f741e635e45..809665c0ef03 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/SqlParser.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/SqlParser.java @@ -34,6 +34,7 @@ import org.apache.iotdb.db.relational.grammar.sql.RelationalSqlParser; import org.antlr.v4.runtime.ANTLRErrorListener; +import org.antlr.v4.runtime.BailErrorStrategy; import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonToken; @@ -47,6 +48,7 @@ import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.atn.PredictionMode; import org.antlr.v4.runtime.misc.Pair; +import org.antlr.v4.runtime.misc.ParseCancellationException; import org.antlr.v4.runtime.tree.TerminalNode; import java.time.ZoneId; @@ -158,7 +160,7 @@ private Node invokeParser( // Override the default error strategy to not attempt inserting or deleting a token. // Otherwise, it messes up error reporting - parser.setErrorHandler( + DefaultErrorStrategy reportingErrorStrategy = new DefaultErrorStrategy() { @Override public Token recoverInline(Parser recognizer) throws RecognitionException { @@ -167,7 +169,11 @@ public Token recoverInline(Parser recognizer) throws RecognitionException { } throw new InputMismatchException(recognizer, nextTokensState, nextTokensContext); } - }); + }; + // Any error in the SLL stage falls back to the LL stage, which reports it with the strategy + // above, so the SLL stage needs no recovery; BailErrorStrategy also skips the per-rule sync() + // checks. + parser.setErrorHandler(new BailErrorStrategy()); parser.addParseListener(new PostProcessor(Arrays.asList(parser.getRuleNames()), parser)); @@ -183,10 +189,11 @@ public Token recoverInline(Parser recognizer) throws RecognitionException { // first, try parsing with potentially faster SLL mode parser.getInterpreter().setPredictionMode(PredictionMode.SLL); tree = parseFunction.apply(parser); - } catch (ParsingException ex) { + } catch (ParsingException | ParseCancellationException ex) { // if we fail, parse with LL mode tokenStream.seek(0); // rewind input stream parser.reset(); + parser.setErrorHandler(reportingErrorStrategy); parser.getInterpreter().setPredictionMode(PredictionMode.LL); tree = parseFunction.apply(parser);