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>