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

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


The following commit(s) were added to refs/heads/master by this push:
     new 19f1710df75 Support parsing MySQL SELECT sql (#38233)
19f1710df75 is described below

commit 19f1710df751ccd4437c430906ec51e6dabcc30f
Author: Claire <[email protected]>
AuthorDate: Fri Feb 27 14:14:17 2026 +0800

    Support parsing MySQL SELECT sql (#38233)
    
    * support select index
    
    * release-notes
---
 RELEASE-NOTES.md                                   |  1 +
 .../statement/type/DorisDMLStatementVisitor.java   | 10 ++-
 .../statement/type/MySQLDMLStatementVisitor.java   | 10 ++-
 .../segment/generic/table/IndexHintSegment.java    |  5 ++
 .../asserts/segment/table/TableAssert.java         | 10 +++
 .../parser/src/main/resources/case/dml/select.xml  | 82 +++++++++++++++++++++-
 .../main/resources/sql/supported/dml/select.xml    |  4 ++
 7 files changed, 117 insertions(+), 5 deletions(-)

diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index ded87d1f4c8..6c6843091d8 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -8,6 +8,7 @@
 ### Enhancements
 
 1. SQL Parser: Support MySQL Function statement parse - 
[#38182](https://github.com/apache/shardingsphere/pull/38182) 
[#38219](https://github.com/apache/shardingsphere/pull/38219)
+2. SQL Parser: Support parsing MySQL SELECT sql - 
[#38233](https://github.com/apache/shardingsphere/pull/38233)
 
 ## Release 5.5.3
 
diff --git 
a/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDMLStatementVisitor.java
 
b/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDMLStatementVisitor.java
index d05241e9239..e7e6a64c423 100644
--- 
a/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDMLStatementVisitor.java
+++ 
b/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDMLStatementVisitor.java
@@ -319,8 +319,14 @@ public final class DorisDMLStatementVisitor extends 
DorisStatementVisitor implem
     @Override
     public ASTNode visitIndexHint(final IndexHintContext ctx) {
         Collection<String> indexNames = new LinkedList<>();
+        List<Integer> indexStartIndices = new LinkedList<>();
+        List<Integer> indexStopIndices = new LinkedList<>();
         if (null != ctx.indexNameList()) {
-            ctx.indexNameList().indexName().forEach(each -> 
indexNames.add(each.getText()));
+            ctx.indexNameList().indexName().forEach(each -> {
+                indexNames.add(each.getText());
+                indexStartIndices.add(each.getStart().getStartIndex());
+                indexStopIndices.add(each.getStop().getStopIndex());
+            });
         }
         String useType;
         if (null != ctx.USE()) {
@@ -330,7 +336,7 @@ public final class DorisDMLStatementVisitor extends 
DorisStatementVisitor implem
         } else {
             useType = ctx.FORCE().getText();
         }
-        IndexHintSegment result = new 
IndexHintSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), 
indexNames, useType,
+        IndexHintSegment result = new 
IndexHintSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), 
indexNames, indexStartIndices, indexStopIndices, useType,
                 null == ctx.INDEX() ? ctx.KEY().getText() : 
ctx.INDEX().getText(), getOriginalText(ctx));
         if (null != ctx.indexHintClause().FOR()) {
             String hintScope;
diff --git 
a/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/type/MySQLDMLStatementVisitor.java
 
b/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/type/MySQLDMLStatementVisitor.java
index d94f34112b6..44e38a7d0f0 100644
--- 
a/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/type/MySQLDMLStatementVisitor.java
+++ 
b/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/type/MySQLDMLStatementVisitor.java
@@ -110,8 +110,14 @@ public final class MySQLDMLStatementVisitor extends 
MySQLStatementVisitor implem
     @Override
     public ASTNode visitIndexHint(final IndexHintContext ctx) {
         Collection<String> indexNames = new LinkedList<>();
+        List<Integer> indexStartIndices = new LinkedList<>();
+        List<Integer> indexStopIndices = new LinkedList<>();
         if (null != ctx.indexNameList()) {
-            ctx.indexNameList().indexName().forEach(each -> 
indexNames.add(each.getText()));
+            ctx.indexNameList().indexName().forEach(each -> {
+                indexNames.add(each.getText());
+                indexStartIndices.add(each.getStart().getStartIndex());
+                indexStopIndices.add(each.getStop().getStopIndex());
+            });
         }
         String useType;
         if (null != ctx.USE()) {
@@ -121,7 +127,7 @@ public final class MySQLDMLStatementVisitor extends 
MySQLStatementVisitor implem
         } else {
             useType = ctx.FORCE().getText();
         }
-        IndexHintSegment result = new 
IndexHintSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), 
indexNames, useType,
+        IndexHintSegment result = new 
IndexHintSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), 
indexNames, indexStartIndices, indexStopIndices, useType,
                 null == ctx.INDEX() ? ctx.KEY().getText() : 
ctx.INDEX().getText(), getOriginalText(ctx));
         if (null != ctx.indexHintClause().FOR()) {
             String hintScope;
diff --git 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/generic/table/IndexHintSegment.java
 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/generic/table/IndexHintSegment.java
index 13164640c28..792f4959c78 100644
--- 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/generic/table/IndexHintSegment.java
+++ 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/generic/table/IndexHintSegment.java
@@ -23,6 +23,7 @@ import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.SQLSegment;
 
 import java.util.Collection;
+import java.util.List;
 
 /**
  * Index hint segment.
@@ -37,6 +38,10 @@ public final class IndexHintSegment implements SQLSegment {
     
     private final Collection<String> indexNames;
     
+    private final List<Integer> indexStartIndices;
+    
+    private final List<Integer> indexStopIndices;
+    
     private final String useType;
     
     private final String indexType;
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/table/TableAssert.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/table/TableAssert.java
index a45656a4803..b2ae24f5c58 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/table/TableAssert.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/table/TableAssert.java
@@ -149,13 +149,23 @@ public final class TableAssert {
     }
     
     private static void assertIs(final SQLCaseAssertContext assertContext, 
final IndexHintSegment actual, final ExpectedIndexHint expected) {
+        assertThat(assertContext.getText("Index hint start index assertion 
error: "), actual.getStartIndex(), is(expected.getStartIndex()));
+        assertThat(assertContext.getText("Index hint stop index assertion 
error: "), actual.getStopIndex(), is(expected.getStopIndex()));
         assertThat(expected.getHintIndexNames().size(), 
is(actual.getIndexNames().size()));
         Iterator<ExpectedHintIndexName> expectedIndexNameIterator = 
expected.getHintIndexNames().iterator();
         Iterator<String> actualIndexNameIterator = 
actual.getIndexNames().iterator();
+        int indexPosition = 0;
         while (expectedIndexNameIterator.hasNext()) {
             ExpectedHintIndexName expectedIndexName = 
expectedIndexNameIterator.next();
             String actualIndexName = actualIndexNameIterator.next();
             assertThat(assertContext.getText("Index hint name assertion error: 
"), actualIndexName, is(expectedIndexName.getName()));
+            if (indexPosition < actual.getIndexStartIndices().size() && 
indexPosition < actual.getIndexStopIndices().size()) {
+                assertThat(assertContext.getText("Index hint name start index 
assertion error: "),
+                        actual.getIndexStartIndices().get(indexPosition), 
is(expectedIndexName.getStartIndex()));
+                assertThat(assertContext.getText("Index hint name stop index 
assertion error: "),
+                        actual.getIndexStopIndices().get(indexPosition), 
is(expectedIndexName.getStopIndex()));
+            }
+            indexPosition++;
         }
         assertThat(assertContext.getText("Index hint origin text assertion 
error: "), actual.getOriginText(), is(expected.getOriginText()));
     }
diff --git a/test/it/parser/src/main/resources/case/dml/select.xml 
b/test/it/parser/src/main/resources/case/dml/select.xml
index e586f4a4b8f..5638a16a7c5 100644
--- a/test/it/parser/src/main/resources/case/dml/select.xml
+++ b/test/it/parser/src/main/resources/case/dml/select.xml
@@ -10242,7 +10242,7 @@
                 <index-hint origin-text="USE INDEX (i1)" start-index="48" 
stop-index="61">
                     <hint-index-name name="i1" start-index="59" 
stop-index="60"/>
                 </index-hint>
-                <index-hint origin-text="USE INDEX (i2)" start-index="63" 
stop-index="66">
+                <index-hint origin-text="USE INDEX (i2)" start-index="63" 
stop-index="76">
                     <hint-index-name name="i2" start-index="74" 
stop-index="75"/>
                 </index-hint>
             </simple-table>
@@ -10343,6 +10343,86 @@
         </from>
     </select>
 
+    <select sql-case-id="select_use_index_ignore_index_for_order_by">
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <from>
+            <simple-table name="t1" start-index="14" stop-index="15">
+                <index-hint origin-text="USE INDEX (i1)" start-index="17" 
stop-index="30">
+                    <hint-index-name name="i1" start-index="28" 
stop-index="29"/>
+                </index-hint>
+                <index-hint origin-text="IGNORE INDEX FOR ORDER BY (i2)" 
start-index="32" stop-index="61">
+                    <hint-index-name name="i2" start-index="59" 
stop-index="60"/>
+                </index-hint>
+            </simple-table>
+        </from>
+        <order-by>
+            <column-item name="a" start-index="72" stop-index="72" />
+        </order-by>
+    </select>
+
+    <select sql-case-id="select_use_index_twice">
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <from>
+            <simple-table name="t1" start-index="14" stop-index="15">
+                <index-hint origin-text="USE INDEX (i1)" start-index="17" 
stop-index="30">
+                    <hint-index-name name="i1" start-index="28" 
stop-index="29"/>
+                </index-hint>
+                <index-hint origin-text="USE INDEX (i1,i1)" start-index="32" 
stop-index="48">
+                    <hint-index-name name="i1" start-index="43" 
stop-index="44"/>
+                    <hint-index-name name="i1" start-index="46" 
stop-index="47"/>
+                </index-hint>
+            </simple-table>
+        </from>
+    </select>
+
+    <select sql-case-id="select_use_index_force_index_for_join">
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <from>
+            <simple-table name="t1" start-index="14" stop-index="15">
+                <index-hint origin-text="USE INDEX FOR JOIN (i1)" 
start-index="17" stop-index="39">
+                    <hint-index-name name="i1" start-index="37" 
stop-index="38"/>
+                </index-hint>
+                <index-hint origin-text="FORCE INDEX FOR JOIN (i2)" 
start-index="41" stop-index="65">
+                    <hint-index-name name="i2" start-index="63" 
stop-index="64"/>
+                </index-hint>
+            </simple-table>
+        </from>
+    </select>
+
+    <select sql-case-id="select_group_by_match_against_with_rollup">
+        <projections start-index="7" stop-index="7">
+            <expression-projection text="1" start-index="7" stop-index="7">
+                <expr>
+                    <literal-expression value="1" start-index="7" 
stop-index="7"/>
+                </expr>
+            </expression-projection>
+        </projections>
+        <from>
+            <simple-table name="t" start-index="14" stop-index="14" />
+        </from>
+        <group-by>
+            <column-item name="a" start-index="25" stop-index="25" />
+            <expression-item start-index="28" stop-index="52" 
expression="MATCH (a) AGAINST ('abc')">
+                <expr>
+                    <match-expression start-index="31" stop-index="52">
+                        <columns>
+                            <column name="a" start-index="37" stop-index="37"/>
+                        </columns>
+                        <expr>
+                            <literal-expression value="abc" start-index="47" 
stop-index="51"/>
+                        </expr>
+                    </match-expression>
+                </expr>
+            </expression-item>
+        </group-by>
+    </select>
+
     <select sql-case-id="select_with_reserved_word_with_table_ref">
         <projections start-index="7" stop-index="19">
             <column-projection name="condition" start-index="7" 
stop-index="19" >
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/select.xml 
b/test/it/parser/src/main/resources/sql/supported/dml/select.xml
index 8ccaca5424c..3867546b0de 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/select.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/select.xml
@@ -533,4 +533,8 @@
     <sql-case id="select_mbroverlaps" value="SELECT MBROverlaps(@g1, @g2)" 
db-types="MySQL" />
     <sql-case id="select_mbrtouches" value="SELECT MBRTouches(@g1, @g2)" 
db-types="MySQL" />
     <sql-case id="select_mbrwithin" value="SELECT MBRWithin(@g1, @g2)" 
db-types="MySQL" />
+    <sql-case id="select_use_index_ignore_index_for_order_by" value="SELECT * 
FROM t1 USE INDEX (i1) IGNORE INDEX FOR ORDER BY (i2) ORDER BY a;" 
db-types="MySQL" />
+    <sql-case id="select_use_index_twice" value="SELECT * FROM t1 USE INDEX 
(i1) USE INDEX (i1,i1);" db-types="MySQL" />
+    <sql-case id="select_use_index_force_index_for_join" value="SELECT * FROM 
t1 USE INDEX FOR JOIN (i1) FORCE INDEX FOR JOIN (i2);" db-types="MySQL" />
+    <sql-case id="select_group_by_match_against_with_rollup" value="SELECT 1 
FROM t GROUP BY a, MATCH (a) AGAINST ('abc') WITH ROLLUP;" db-types="MySQL" />
 </sql-cases>

Reply via email to