You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ch...@apache.org on 2026/04/02 02:29:29 UTC

(shardingsphere) branch master updated: Support mysql, doris insert & replace rows statement parse (#38585)

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

chengzhang 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 4a7e0cd4064 Support mysql, doris insert & replace rows statement parse (#38585)
4a7e0cd4064 is described below

commit 4a7e0cd40645e0951b6f6ef03bdf6b63a1c3fa27
Author: Zhengqiang Duan <du...@apache.org>
AuthorDate: Thu Apr 2 10:29:22 2026 +0800

    Support mysql, doris insert & replace rows statement parse (#38585)
---
 RELEASE-NOTES.md                                   |  1 +
 .../visitor/statement/DorisStatementVisitor.java   | 10 ++++--
 .../visitor/statement/MySQLStatementVisitor.java   | 13 +++-----
 .../parser/src/main/resources/case/dml/insert.xml  | 39 ++++++++++++++++++++++
 .../parser/src/main/resources/case/dml/replace.xml | 39 ++++++++++++++++++++++
 .../main/resources/sql/supported/dml/insert.xml    |  1 +
 .../main/resources/sql/supported/dml/replace.xml   |  1 +
 7 files changed, 94 insertions(+), 10 deletions(-)

diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index f2d180fb276..0a7e3ff2fff 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -26,6 +26,7 @@
 1. SQL Parser: Support MySQL subquery table projection alias visit to SQL statement - [#38320](https://github.com/apache/shardingsphere/pull/38320)
 1. SQL Parser: Enhance select window partition by order by, lead placeholder parse - [#38392](https://github.com/apache/shardingsphere/pull/38392)
 1. SQL Parser: Support MariaDB cycleClause, groupConcatLimitClause, MEDIAN window function parse - [#38579](https://github.com/apache/shardingsphere/pull/38579)
+1. SQL Parser: Support mysql, doris insert & replace rows statement parse - [#38585](https://github.com/apache/shardingsphere/pull/38585)
 1. SQL Binder: Support select order by index bind metadata - [#38386](https://github.com/apache/shardingsphere/pull/38386)
 1. SQL Binder: Support SQL bind when with temp table name is same with physical table - [#38411](https://github.com/apache/shardingsphere/pull/38411)
 1. JDBC: Support setMaxRows and getMaxRows method in jdbc when not execute SQL - [#38337](https://github.com/apache/shardingsphere/pull/38337)
diff --git a/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/DorisStatementVisitor.java b/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/DorisStatementVisitor.java
index 8ec654dfb55..15718d75b29 100644
--- a/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/DorisStatementVisitor.java
+++ b/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/DorisStatementVisitor.java
@@ -1604,7 +1604,10 @@ public abstract class DorisStatementVisitor extends DorisStatementBaseVisitor<AS
         } else {
             insertColumns = new InsertColumnsSegment(ctx.start.getStartIndex() - 1, ctx.start.getStartIndex() - 1, Collections.emptyList());
         }
-        return InsertStatement.builder().databaseType(databaseType).insertColumns(insertColumns).values(createInsertValuesSegments(ctx.assignmentValues())).build();
+        return InsertStatement.builder().databaseType(databaseType)
+                .insertColumns(insertColumns)
+                .values(null == ctx.rowConstructorList() ? createInsertValuesSegments(ctx.assignmentValues()) : createRowConstructorList(ctx.rowConstructorList()))
+                .build();
     }
     
     private Collection<InsertValuesSegment> createInsertValuesSegments(final Collection<AssignmentValuesContext> assignmentValuesContexts) {
@@ -1684,7 +1687,10 @@ public abstract class DorisStatementVisitor extends DorisStatementBaseVisitor<AS
         } else {
             insertColumns = new InsertColumnsSegment(ctx.start.getStartIndex() - 1, ctx.start.getStartIndex() - 1, Collections.emptyList());
         }
-        return InsertStatement.builder().databaseType(databaseType).insertColumns(insertColumns).values(createInsertValuesSegments(ctx.assignmentValues())).build();
+        return InsertStatement.builder().databaseType(databaseType)
+                .insertColumns(insertColumns)
+                .values(null == ctx.rowConstructorList() ? createInsertValuesSegments(ctx.assignmentValues()) : createRowConstructorList(ctx.rowConstructorList()))
+                .build();
     }
     
     private List<ColumnSegment> createInsertColumns(final FieldsContext fields) {
diff --git a/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/MySQLStatementVisitor.java b/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/MySQLStatementVisitor.java
index 8786d59af72..393899691b7 100644
--- a/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/MySQLStatementVisitor.java
+++ b/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/MySQLStatementVisitor.java
@@ -25,7 +25,6 @@ import org.antlr.v4.runtime.Token;
 import org.antlr.v4.runtime.misc.Interval;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.antlr.v4.runtime.tree.TerminalNode;
-import org.antlr.v4.runtime.tree.TerminalNodeImpl;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import org.apache.shardingsphere.sql.parser.api.ASTNode;
 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementBaseVisitor;
@@ -888,12 +887,8 @@ public abstract class MySQLStatementVisitor extends MySQLStatementBaseVisitor<AS
     
     private Collection<InsertValuesSegment> createRowConstructorList(final RowConstructorListContext ctx) {
         Collection<InsertValuesSegment> result = new LinkedList<>();
-        for (int index = 0; index < ctx.getChildCount(); index++) {
-            if (!(ctx.getChild(index) instanceof AssignmentValuesContext)) {
-                continue;
-            }
-            InsertValuesSegment valuesSegment = (InsertValuesSegment) visit(ctx.getChild(index));
-            result.add(new InsertValuesSegment(((TerminalNodeImpl) ctx.getChild(index - 1)).symbol.getStartIndex(), valuesSegment.getStopIndex(), valuesSegment.getValues()));
+        for (AssignmentValuesContext each : ctx.assignmentValues()) {
+            result.add((InsertValuesSegment) visit(each));
         }
         return result;
     }
@@ -1687,7 +1682,9 @@ public abstract class MySQLStatementVisitor extends MySQLStatementBaseVisitor<AS
         } else {
             insertColumns = new InsertColumnsSegment(ctx.start.getStartIndex() - 1, ctx.start.getStartIndex() - 1, Collections.emptyList());
         }
-        return InsertStatement.builder().databaseType(databaseType).insertColumns(insertColumns).values(createInsertValuesSegments(ctx.assignmentValues())).build();
+        Collection<InsertValuesSegment> insertValuesSegments =
+                null == ctx.rowConstructorList() ? createInsertValuesSegments(ctx.assignmentValues()) : createRowConstructorList(ctx.rowConstructorList());
+        return InsertStatement.builder().databaseType(databaseType).insertColumns(insertColumns).values(insertValuesSegments).build();
     }
     
     private InsertStatement.InsertStatementBuilder createInsertStatementBuilder(final InsertStatement insertStatement) {
diff --git a/test/it/parser/src/main/resources/case/dml/insert.xml b/test/it/parser/src/main/resources/case/dml/insert.xml
index 44a4909818d..64314b42b4c 100644
--- a/test/it/parser/src/main/resources/case/dml/insert.xml
+++ b/test/it/parser/src/main/resources/case/dml/insert.xml
@@ -1002,6 +1002,45 @@
         </values>
     </insert>
 
+    <insert sql-case-id="insert_with_batch_and_row_constructor" parameters="1000, 10, 'init', 1100, 11, 'init'">
+        <table name="t_order" start-index="12" stop-index="18" />
+        <columns start-index="20" stop-index="46">
+            <column name="order_id" start-index="21" stop-index="28" />
+            <column name="user_id" start-index="31" stop-index="37" />
+            <column name="status" start-index="40" stop-index="45" />
+        </columns>
+        <values>
+            <value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="0" start-index="58" stop-index="58" />
+                    <literal-expression value="1000" start-index="58" stop-index="61" />
+                </assignment-value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="1" start-index="61" stop-index="61" />
+                    <literal-expression value="10" start-index="64" stop-index="65" />
+                </assignment-value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="2" start-index="64" stop-index="64" />
+                    <literal-expression value="init" start-index="68" stop-index="73" />
+                </assignment-value>
+            </value>
+            <value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="3" start-index="72" stop-index="72" />
+                    <literal-expression value="1100" start-index="81" stop-index="84" />
+                </assignment-value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="4" start-index="75" stop-index="75" />
+                    <literal-expression value="11" start-index="87" stop-index="88" />
+                </assignment-value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="5" start-index="78" stop-index="78" />
+                    <literal-expression value="init" start-index="91" stop-index="96" />
+                </assignment-value>
+            </value>
+        </values>
+    </insert>
+
     <insert sql-case-id="insert_with_batch_and_irregular_parameters" parameters="1, 2, 2, 'init'">
         <table name="t_order" start-index="12" stop-index="18" />
         <columns start-index="20" stop-index="46">
diff --git a/test/it/parser/src/main/resources/case/dml/replace.xml b/test/it/parser/src/main/resources/case/dml/replace.xml
index 8b3e843540e..0cfc196f737 100644
--- a/test/it/parser/src/main/resources/case/dml/replace.xml
+++ b/test/it/parser/src/main/resources/case/dml/replace.xml
@@ -488,6 +488,45 @@
         </values>
     </insert>
 
+    <insert sql-case-id="replace_with_batch_and_row_constructor" parameters="1000, 10, 'init', 1100, 11, 'init'">
+        <table name="t_order" start-index="13" stop-index="19" />
+        <columns start-index="21" stop-index="47">
+            <column name="order_id" start-index="22" stop-index="29" />
+            <column name="user_id" start-index="32" stop-index="38" />
+            <column name="status" start-index="41" stop-index="46" />
+        </columns>
+        <values>
+            <value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="0" start-index="59" stop-index="59" />
+                    <literal-expression value="1000" start-index="59" stop-index="62" />
+                </assignment-value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="1" start-index="62" stop-index="62" />
+                    <literal-expression value="10" start-index="65" stop-index="66" />
+                </assignment-value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="2" start-index="65" stop-index="65" />
+                    <literal-expression value="init" start-index="69" stop-index="74" />
+                </assignment-value>
+            </value>
+            <value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="3" start-index="73" stop-index="73" />
+                    <literal-expression value="1100" start-index="82" stop-index="85" />
+                </assignment-value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="4" start-index="76" stop-index="76" />
+                    <literal-expression value="11" start-index="88" stop-index="89" />
+                </assignment-value>
+                <assignment-value>
+                    <parameter-marker-expression parameter-index="5" start-index="79" stop-index="79" />
+                    <literal-expression value="init" start-index="92" stop-index="97" />
+                </assignment-value>
+            </value>
+        </values>
+    </insert>
+
     <insert sql-case-id="replace_with_batch_and_irregular_parameters" parameters="1, 2, 2, 'init'">
         <table name="t_order" start-index="13" stop-index="19" />
         <columns start-index="21" stop-index="47">
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/insert.xml b/test/it/parser/src/main/resources/sql/supported/dml/insert.xml
index 13763c0f3be..1e2092a1ab5 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/insert.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/insert.xml
@@ -46,6 +46,7 @@
     <sql-case id="insert_set_without_generate_key_column" value="INSERT INTO t_order_item SET order_id = ?, user_id = ?, status = 'insert', creation_date='2017-08-08'" db-types="MySQL" />
     <sql-case id="insert_set_with_row_alias" value="INSERT INTO t_order SET a = 1 AS new_alias(a)" db-types="MySQL" />
     <sql-case id="insert_with_batch" value="INSERT INTO t_order (order_id, user_id, status) VALUES (?, ?, ?), (?, ?, ?)" db-types="MySQL, SQLServer, PostgreSQL,openGauss,Doris" />
+    <sql-case id="insert_with_batch_and_row_constructor" value="INSERT INTO t_order (order_id, user_id, status) VALUE ROW(?, ?, ?), ROW(?, ?, ?)" db-types="MySQL,Doris" />
     <sql-case id="insert_with_batch_and_irregular_parameters" value="INSERT INTO t_order (order_id, user_id, status) VALUES (?, 1, 'insert'), (?, ?, ?)" db-types="MySQL, SQLServer, PostgreSQL,openGauss,Doris" />
     <sql-case id="insert_with_batch_and_composite_expression" value="INSERT INTO t_order (order_id, user_id, status) VALUES (?, ?, SUBSTR(?, 1)), (?, ?, SUBSTR(?, 1))" db-types="H2,MySQL" />
     <sql-case id="insert_with_batch_and_with_generate_key_column" value="INSERT INTO t_order_item(item_id, order_id, user_id, status, creation_date) values (?, ?, ?, 'insert', '2017-08-08'), (?, ?, ?, 'insert', '2017-08-08')" db-types="MySQL, SQLServer, PostgreSQL,openGauss,Doris" />
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/replace.xml b/test/it/parser/src/main/resources/sql/supported/dml/replace.xml
index 4c0600a71e3..045d03f0897 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/replace.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/replace.xml
@@ -34,6 +34,7 @@
     <sql-case id="replace_without_columns_and_without_generate_key_column" value="REPLACE INTO t_order_item values(?, ?, 'replace', '2017-08-08')" db-types="MySQL" />
     <sql-case id="replace_set_without_generate_key_column" value="REPLACE INTO t_order_item SET order_id = ?, user_id = ?, status = 'replace', creation_date='2017-08-08'" db-types="MySQL" />
     <sql-case id="replace_with_batch" value="REPLACE INTO t_order (order_id, user_id, status) VALUES (?, ?, ?), (?, ?, ?)" db-types="MySQL,Doris" />
+    <sql-case id="replace_with_batch_and_row_constructor" value="REPLACE INTO t_order (order_id, user_id, status) VALUE ROW(?, ?, ?), ROW(?, ?, ?)" db-types="MySQL,Doris" />
     <sql-case id="replace_with_batch_and_irregular_parameters" value="REPLACE INTO t_order (order_id, user_id, status) VALUES (?, 1, 'replace'), (?, ?, ?)" db-types="MySQL,Doris" />
     <sql-case id="replace_with_batch_and_with_generate_key_column" value="REPLACE INTO t_order_item(item_id, order_id, user_id, status, creation_date) values (?, ?, ?, 'replace', '2017-08-08'), (?, ?, ?, 'replace', '2017-08-08')" db-types="MySQL" />
     <sql-case id="replace_with_batch_and_without_generate_key_column" value="REPLACE INTO t_order_item(order_id, user_id, status, creation_date) values (?, ?, 'replace', '2017-08-08'), (?, ?, 'replace', '2017-08-08')" db-types="MySQL" />