This is an automated email from the ASF dual-hosted git repository.

morrySnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 3763638e6c8 [improvement](parser) Avoid empty identifier suffix 
contexts (#67685)
3763638e6c8 is described below

commit 3763638e6c8e3ebbc1b7079266f0d97213f0278d
Author: morrySnow <[email protected]>
AuthorDate: Wed Sep 9 15:02:30 2026 +0800

    [improvement](parser) Avoid empty identifier suffix contexts (#67685)
    
    ### What problem does this PR solve?
    
    Problem Summary:
    
    The `errorCapturingIdentifier` rule always entered a nullable helper for
    valid identifiers. In the tracked SQL corpus this created 25,406 empty
    CST contexts. Move the optionality to the caller and make
    `errorCapturingIdentifierExtra` non-empty, while preserving the existing
    unquoted-identifier error action. This avoids allocating an empty
    `RealIdentContext` on the common path and keeps the grammar structure
    straightforward.
    
    This PR also removes stale `PostProcessor` references from two JMH
    harnesses. Identifier post-processing already moved into grammar actions
    and the class no longer exists, so those references prevented the
    benchmark profile from compiling.
    
    Add a multipart-identifier JMH workload and a direct CST regression
    test. Across two JMH runs, normalized allocation for that workload
    decreased from 174,368.9 to 159,004.1 B/op (-8.81%) end-to-end and from
    146,097.7 to 130,741.3 B/op (-10.51%) with pre-tokenized input.
---
 .../sqlparser/benchmark/IdentifierPostProcessorBenchmark.java  |  8 ++++++--
 .../doris/sqlparser/benchmark/LocalRulePrefixBenchmark.java    |  3 ---
 .../doris/sqlparser/benchmark/QueryOrganizationBenchmark.java  |  3 ---
 .../src/main/antlr4/org/apache/doris/nereids/DorisParser.g4    |  7 ++-----
 .../java/org/apache/doris/sqlparser/DorisSqlParserTest.java    | 10 ++++++++++
 5 files changed, 18 insertions(+), 13 deletions(-)

diff --git 
a/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/IdentifierPostProcessorBenchmark.java
 
b/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/IdentifierPostProcessorBenchmark.java
index 27f6f9ad87d..38c3ed34bb3 100644
--- 
a/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/IdentifierPostProcessorBenchmark.java
+++ 
b/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/IdentifierPostProcessorBenchmark.java
@@ -43,7 +43,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
-/** Measures identifier post-processing through the public facade and with 
pre-tokenized input. */
+/** Measures identifier-heavy parsing through the public facade and with 
pre-tokenized input. */
 @BenchmarkMode(Mode.AverageTime)
 @OutputTimeUnit(TimeUnit.MICROSECONDS)
 @Fork(value = 3, jvmArgsAppend = {"-Xms1g", "-Xmx1g"})
@@ -51,7 +51,7 @@ import java.util.stream.IntStream;
 @Measurement(iterations = 7, time = 400, timeUnit = TimeUnit.MILLISECONDS)
 @State(Scope.Thread)
 public class IdentifierPostProcessorBenchmark {
-    @Param({"control", "typical", "wide", "nonReserved", "quoted"})
+    @Param({"control", "typical", "wide", "multipart", "nonReserved", 
"quoted"})
     public String workload;
 
     private final DorisSqlParser facade = new DorisSqlParser();
@@ -95,6 +95,10 @@ public class IdentifierPostProcessorBenchmark {
                         .mapToObj(index -> "c" + index + " AS alias" + index)
                         .collect(Collectors.joining(", "))
                         + " FROM catalog.db.fact_table";
+            case "multipart":
+                return "SELECT 1 FROM " + IntStream.range(0, 64)
+                        .mapToObj(index -> "catalog" + index + ".database" + 
index + ".table" + index)
+                        .collect(Collectors.joining(", "));
             case "nonReserved":
                 return "SELECT action, branch, cache, catalog, connection, 
engine, format, global, name "
                         + "FROM aggregate AS alias WHERE action = 1";
diff --git 
a/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/LocalRulePrefixBenchmark.java
 
b/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/LocalRulePrefixBenchmark.java
index 4e4aa601691..8821ab6b9e5 100644
--- 
a/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/LocalRulePrefixBenchmark.java
+++ 
b/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/LocalRulePrefixBenchmark.java
@@ -19,7 +19,6 @@ package org.apache.doris.sqlparser.benchmark;
 
 import org.apache.doris.nereids.DorisParser;
 import org.apache.doris.nereids.parser.ParseErrorListener;
-import org.apache.doris.nereids.parser.PostProcessor;
 import org.apache.doris.sqlparser.DorisSqlParser;
 
 import org.antlr.v4.runtime.CommonTokenStream;
@@ -58,7 +57,6 @@ public class LocalRulePrefixBenchmark {
     public String workload;
 
     private final DorisSqlParser facade = new DorisSqlParser();
-    private final PostProcessor postProcessor = new PostProcessor();
     private final ParseErrorListener errorListener = new ParseErrorListener();
 
     private String sql;
@@ -113,7 +111,6 @@ public class LocalRulePrefixBenchmark {
     private DorisParser newParser(List<Token> input) {
         CommonTokenStream stream = new CommonTokenStream(new 
ListTokenSource(input));
         DorisParser parser = new DorisParser(stream);
-        parser.addParseListener(postProcessor);
         parser.removeErrorListeners();
         parser.addErrorListener(errorListener);
         parser.getInterpreter().setPredictionMode(PredictionMode.SLL);
diff --git 
a/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/QueryOrganizationBenchmark.java
 
b/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/QueryOrganizationBenchmark.java
index 8a907de7abc..6136ef7b669 100644
--- 
a/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/QueryOrganizationBenchmark.java
+++ 
b/fe/fe-sql-parser-benchmark/src/main/java/org/apache/doris/sqlparser/benchmark/QueryOrganizationBenchmark.java
@@ -19,7 +19,6 @@ package org.apache.doris.sqlparser.benchmark;
 
 import org.apache.doris.nereids.DorisParser;
 import org.apache.doris.nereids.parser.ParseErrorListener;
-import org.apache.doris.nereids.parser.PostProcessor;
 import org.apache.doris.sqlparser.DorisSqlParser;
 
 import org.antlr.v4.runtime.CommonTokenStream;
@@ -58,7 +57,6 @@ public class QueryOrganizationBenchmark {
     @Param({"plainSelect", "orderedSelect", "unionTail", "parenthesizedUnion", 
"inlineValues"})
     public String workload;
 
-    private final PostProcessor postProcessor = new PostProcessor();
     private final ParseErrorListener errorListener = new ParseErrorListener();
 
     private DorisSqlParser facade;
@@ -104,7 +102,6 @@ public class QueryOrganizationBenchmark {
         CommonTokenStream stream = new CommonTokenStream(new 
ListTokenSource(tokens));
         DorisParser parser = new DorisParser(stream);
         parser.ansiSQLSyntax = ansi;
-        parser.addParseListener(postProcessor);
         parser.removeErrorListeners();
         parser.addErrorListener(errorListener);
         parser.getInterpreter().setPredictionMode(PredictionMode.SLL);
diff --git 
a/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 
b/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
index 569baf6b66c..9de4998c436 100644
--- a/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
+++ b/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
@@ -2216,18 +2216,15 @@ tableSnapshot
 // replace identifier with errorCapturingIdentifier where the immediate follow 
symbol is not an expression, otherwise
 // valid expressions such as "a-b" can be recognized as an identifier
 errorCapturingIdentifier
-    : identifier errorCapturingIdentifierExtra
+    : identifier errorCapturingIdentifierExtra?
     ;
 
 // extra left-factoring grammar
 errorCapturingIdentifierExtra
     : (SUBTRACT identifier)+ #errorIdent
-    |                        #realIdent
     ;
 finally {
-    if ($ctx instanceof ErrorIdentContext) {
-        reportUnquotedIdentifier((ErrorIdentContext) $ctx);
-    }
+    reportUnquotedIdentifier((ErrorIdentContext) $ctx);
 }
 
 identifier
diff --git 
a/fe/fe-sql-parser/src/test/java/org/apache/doris/sqlparser/DorisSqlParserTest.java
 
b/fe/fe-sql-parser/src/test/java/org/apache/doris/sqlparser/DorisSqlParserTest.java
index 362c0d90404..056d59c8ca1 100644
--- 
a/fe/fe-sql-parser/src/test/java/org/apache/doris/sqlparser/DorisSqlParserTest.java
+++ 
b/fe/fe-sql-parser/src/test/java/org/apache/doris/sqlparser/DorisSqlParserTest.java
@@ -18,6 +18,7 @@
 package org.apache.doris.sqlparser;
 
 import org.apache.doris.nereids.DorisParser;
+import org.apache.doris.nereids.DorisParser.ErrorCapturingIdentifierContext;
 import org.apache.doris.nereids.DorisParser.ExpressionContext;
 import org.apache.doris.nereids.DorisParser.MultiStatementsContext;
 import org.apache.doris.nereids.DorisParser.SingleStatementContext;
@@ -125,6 +126,15 @@ class DorisSqlParserTest {
                 "Possibly unquoted identifier test-tbl detected"));
     }
 
+    @Test
+    void doesNotBuildEmptyUnquotedIdentifierSuffixContext() {
+        DorisParser generatedParser = 
parser.newParser(parser.newLexer("ordinary"));
+        ErrorCapturingIdentifierContext ctx = 
generatedParser.errorCapturingIdentifier();
+
+        Assertions.assertNull(ctx.errorCapturingIdentifierExtra());
+        Assertions.assertEquals(Token.EOF, 
generatedParser.getCurrentToken().getType());
+    }
+
     @Test
     void parsesWithoutBuildingParseTree() {
         DorisParser generatedParser = parser.newParser(


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to