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 c25f73fa458 Support parsing MySQL stored procedure syntax - part 8 
(#38017)
c25f73fa458 is described below

commit c25f73fa45826006f99c2d7f9dfa3ccf880dd70d
Author: Claire <[email protected]>
AuthorDate: Thu Feb 12 16:29:14 2026 +0800

    Support parsing MySQL stored procedure syntax - part 8 (#38017)
    
    * support new statement
    
    * release-notes
    
    * support new function
    
    * release-notes
    
    * release-notes
---
 RELEASE-NOTES.md                                   |  1 +
 .../src/main/antlr4/imports/mysql/BaseRule.g4      |  2 +-
 .../src/main/antlr4/imports/mysql/DDLStatement.g4  |  8 +++--
 .../src/main/antlr4/imports/mysql/Literals.g4      |  4 +++
 .../src/main/antlr4/imports/mysql/MySQLKeyword.g4  |  4 +++
 .../statement/type/MySQLDDLStatementVisitor.java   |  9 ++++-
 .../main/resources/case/ddl/create-procedure.xml   | 39 ++++++++++++++++++++++
 .../sql/supported/ddl/create-procedure.xml         |  4 +++
 8 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 7029301d88c..0f29327e3a4 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -52,6 +52,7 @@
 1. SQL Parser: Fix parsing error for SQLServer session `SET QUOTED_IDENTIFIER` 
and `SET TEXTSIZE` statements - 
[#38005](https://github.com/apache/shardingsphere/pull/38005)
 1. SQL Parser: Support '2'::int statement in PostgreSQL and openGauss - 
[#37962](https://github.com/apache/shardingsphere/pull/37962)
 1. SQL Parser: Support range type constructor functions in PostgreSQL without 
quotes - [#37994](https://github.com/apache/shardingsphere/pull/37994)
+1. SQL Parser: Support parsing MySQL stored procedure syntax - 
[#38017](https://github.com/apache/shardingsphere/pull/38017)
 1. SQL Binder: Support to bind more SQL statements - 
[#36697](https://github.com/apache/shardingsphere/pull/36697)
 1. SQL Binder: Add ALTER TABLE metadata check - 
[#35877](https://github.com/apache/shardingsphere/pull/35877)
 1. SQL Binder: Support Grant statement SQL bind - 
[#36207](https://github.com/apache/shardingsphere/pull/36207)
diff --git 
a/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4 
b/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4
index fb814cec894..342da79612e 100644
--- a/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4
+++ b/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4
@@ -126,7 +126,7 @@ identifier
 
 unreservedWord
     : MAX | MIN | SUM | COUNT | GROUP_CONCAT | CAST | POSITION | SUBSTRING | 
SUBSTR | MID | EXTRACT | TRIM | LAST_DAY | TRADITIONAL | TREE | MYSQL_MAIN | 
MYSQL_ADMIN | INSTANT | INPLACE | COPY | UL_BINARY | AUTOCOMMIT | REDO_LOG | 
DELIMITER | ARCHIVE | BLACKHOLE | CSV | FEDERATED | INNODB | MEMORY | 
MRG_MYISAM | MYISAM | NDB | NDBCLUSTER | PERFORMANCE_SCHEMA | TOKUDB
-    | ACCESSIBLE | ACCOUNT | ACTION | ACTIVE | ADD | ADMIN | AFTER | AGAINST | 
AGGREGATE | ALGORITHM | ALL | ALTER | ALWAYS | ANALYZE | AND | ANY | ARRAY | AS 
| ASC | ASCII | ASENSITIVE | AT | ATTRIBUTE | AUTOEXTEND_SIZE | AUTHENTICATION 
| AUTO | AUTO_INCREMENT | AVG | ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS | 
BIT_XOR | AVG_ROW_LENGTH | BACKUP | BEFORE | BERNOULLI | BEGIN | BETWEEN | 
BIGINT | BINARY | BINLOG | BIT | BLOB | BLOCK | BOOL | BOOLEAN | BOTH | BTREE | 
BUCKETS | BULK | BY | BYTE [...]
+    | ACCESSIBLE | ACCOUNT | ACTION | ACTIVE | ADD | ADMIN | AFTER | AGAINST | 
AGGREGATE | ALGORITHM | ALL | ALTER | ALWAYS | ANALYZE | AND | ANY | ARRAY | AS 
| ASC | ASCII | ASENSITIVE | AT | ATTRIBUTE | AUTOEXTEND_SIZE | AUTHENTICATION 
| AUTO | AUTO_INCREMENT | AVG | ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS | 
BIT_XOR | AVG_ROW_LENGTH | BACKUP | BEFORE | BERNOULLI | BEGIN | BETWEEN | 
BIGINT | BINARY | BINLOG | BIT | BLOB | BLOCK | BOOL | BOOLEAN | BOTH | BTREE | 
BUCKETS | BULK | BY | BYTE [...]
     ;
 
 textOrIdentifier
diff --git 
a/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/DDLStatement.g4 
b/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/DDLStatement.g4
index 59e1d904b9b..0d262774ab1 100644
--- 
a/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/DDLStatement.g4
+++ 
b/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/DDLStatement.g4
@@ -295,7 +295,7 @@ createProcedure
     : CREATE ownerStatement?
       PROCEDURE ifNotExists? functionName LP_ procedureParameter? (COMMA_ 
procedureParameter)* RP_
       routineOption*
-      routineBody
+      (routineBody | AS dollarQuotedBody)
     ;
 
 alterProcedure
@@ -655,12 +655,16 @@ serverOption
 
 routineOption
     : COMMENT string_
-    | LANGUAGE SQL                                              
+    | LANGUAGE (SQL | JAVASCRIPT)
     | NOT? DETERMINISTIC                                          
     | (CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA)
     | SQL SECURITY (DEFINER | INVOKER)                    
     ;
 
+dollarQuotedBody
+    : DOLLAR_QUOTED_TEXT
+    ;
+
 procedureParameter
     : (IN | OUT | INOUT)? identifier dataType
     ;
diff --git 
a/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/Literals.g4 
b/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/Literals.g4
index ae3814a59a5..972896f3733 100644
--- a/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/Literals.g4
+++ b/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/Literals.g4
@@ -69,6 +69,10 @@ BIT_NUM_
     : '0b' ('0' | '1')+ | B SQ_ ('0' | '1')+ SQ_
     ;
 
+DOLLAR_QUOTED_TEXT
+    : '$$' .*? '$$'
+    ;
+
 IDENTIFIER_
     : 
[A-Za-z_$0-9\u0080-\uFFFF]*?[A-Za-z_$\u0080-\uFFFF]+?[A-Za-z_$0-9\u0080-\uFFFF]*
     | BQ_ ~'`'+ BQ_
diff --git 
a/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/MySQLKeyword.g4 
b/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/MySQLKeyword.g4
index e92fcd5b13f..98101b24610 100644
--- 
a/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/MySQLKeyword.g4
+++ 
b/parser/sql/engine/dialect/mysql/src/main/antlr4/imports/mysql/MySQLKeyword.g4
@@ -1171,6 +1171,10 @@ ITERATE
     : I T E R A T E
     ;
 
+JAVASCRIPT
+    : J A V A S C R I P T
+    ;
+
 JOIN
     : J O I N
     ;
diff --git 
a/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/type/MySQLDDLStatementVisitor.java
 
b/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/type/MySQLDDLStatementVisitor.java
index 69e9c41fdee..036cf59ed2c 100644
--- 
a/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/type/MySQLDDLStatementVisitor.java
+++ 
b/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/type/MySQLDDLStatementVisitor.java
@@ -214,8 +214,11 @@ import java.util.Optional;
  */
 public final class MySQLDDLStatementVisitor extends MySQLStatementVisitor 
implements DDLStatementVisitor {
     
+    private final MySQLDALStatementVisitor dalStatementVisitor;
+    
     public MySQLDDLStatementVisitor(final DatabaseType databaseType) {
         super(databaseType);
+        dalStatementVisitor = new MySQLDALStatementVisitor(databaseType);
     }
     
     @Override
@@ -759,7 +762,9 @@ public final class MySQLDDLStatementVisitor extends 
MySQLStatementVisitor implem
     public ASTNode visitCreateProcedure(final CreateProcedureContext ctx) {
         CreateProcedureStatement result = new 
CreateProcedureStatement(getDatabaseType());
         result.setProcedureName((FunctionNameSegment) 
visit(ctx.functionName()));
-        result.setRoutineBody((RoutineBodySegment) visit(ctx.routineBody()));
+        if (null != ctx.routineBody()) {
+            result.setRoutineBody((RoutineBodySegment) 
visit(ctx.routineBody()));
+        }
         return result;
     }
     
@@ -859,6 +864,8 @@ public final class MySQLDDLStatementVisitor extends 
MySQLStatementVisitor implem
             sqlStatement = (DeleteStatement) visit(ctx.delete());
         } else if (null != ctx.select()) {
             sqlStatement = (SelectStatement) visit(ctx.select());
+        } else if (null != ctx.setVariable()) {
+            sqlStatement = (SQLStatement) 
dalStatementVisitor.visitSetVariable(ctx.setVariable());
         } else if (null != ctx.doStatement()) {
             sqlStatement = (DoStatement) visit(ctx.doStatement());
         } else if (null != ctx.explain()) {
diff --git a/test/it/parser/src/main/resources/case/ddl/create-procedure.xml 
b/test/it/parser/src/main/resources/case/ddl/create-procedure.xml
index b2ae38741fd..2a03eb6dcb3 100644
--- a/test/it/parser/src/main/resources/case/ddl/create-procedure.xml
+++ b/test/it/parser/src/main/resources/case/ddl/create-procedure.xml
@@ -182,4 +182,43 @@
         </sql-statements>
     </create-procedure>
     <create-procedure sql-case-id="create_procedure_doris_control_flow" />
+    <create-procedure 
sql-case-id="create_procedure_keywords_declare_select_into">
+        <procedure-name name="p1" />
+        <sql-statements>
+            <sql-statement start-index="135" stop-index="172" 
statement-class-simple-name="SelectStatement" />
+            <sql-statement start-index="174" stop-index="217" 
statement-class-simple-name="SelectStatement" />
+            <sql-statement start-index="219" stop-index="282" 
statement-class-simple-name="SelectStatement" />
+            <sql-statement start-index="284" stop-index="359" 
statement-class-simple-name="SelectStatement" />
+            <sql-statement start-index="361" stop-index="425" 
statement-class-simple-name="SelectStatement" />
+        </sql-statements>
+    </create-procedure>
+    <create-procedure sql-case-id="create_procedure_keywords_labeled_while">
+        <procedure-name name="p2" />
+        <sql-statements>
+            <sql-statement start-index="77" stop-index="89" 
statement-class-simple-name="SetStatement" />
+            <sql-statement start-index="110" stop-index="119" 
statement-class-simple-name="SetStatement" />
+            <sql-statement start-index="142" stop-index="154" 
statement-class-simple-name="SetStatement" />
+            <sql-statement start-index="172" stop-index="181" 
statement-class-simple-name="SetStatement" />
+            <sql-statement start-index="217" stop-index="229" 
statement-class-simple-name="SetStatement" />
+            <sql-statement start-index="260" stop-index="269" 
statement-class-simple-name="SetStatement" />
+            <sql-statement start-index="311" stop-index="323" 
statement-class-simple-name="SetStatement" />
+        </sql-statements>
+    </create-procedure>
+    <create-procedure sql-case-id="create_procedure_check_warnings">
+        <procedure-name name="check_warnings" />
+        <sql-statements>
+            <sql-statement start-index="108" stop-index="125" 
statement-class-simple-name="SetStatement" />
+            <sql-statement start-index="127" stop-index="239" 
statement-class-simple-name="UpdateStatement" />
+            <sql-statement start-index="241" stop-index="351" 
statement-class-simple-name="UpdateStatement" />
+            <sql-statement start-index="353" stop-index="421" 
statement-class-simple-name="SelectStatement" />
+            <sql-statement start-index="449" stop-index="494" 
statement-class-simple-name="SelectStatement" />
+            <sql-statement start-index="496" stop-index="516" 
statement-class-simple-name="SelectStatement" />
+            <sql-statement start-index="523" stop-index="543" 
statement-class-simple-name="SelectStatement" />
+            <sql-statement start-index="553" stop-index="579" 
statement-class-simple-name="TruncateStatement" />
+            <sql-statement start-index="581" stop-index="601" 
statement-class-simple-name="DropTableStatement" />
+        </sql-statements>
+    </create-procedure>
+    <create-procedure sql-case-id="create_procedure_lib_uses_both">
+        <procedure-name name="lib_uses_both" />
+    </create-procedure>
 </sql-parser-test-cases>
diff --git 
a/test/it/parser/src/main/resources/sql/supported/ddl/create-procedure.xml 
b/test/it/parser/src/main/resources/sql/supported/ddl/create-procedure.xml
index 1f903eeb05f..5e8114e444f 100644
--- a/test/it/parser/src/main/resources/sql/supported/ddl/create-procedure.xml
+++ b/test/it/parser/src/main/resources/sql/supported/ddl/create-procedure.xml
@@ -68,4 +68,8 @@
     <sql-case id="create_procedure_with_analyze_table_update" value="CREATE 
PROCEDURE p() ANALYZE TABLE v UPDATE HISTOGRAM ON w;" db-types="MySQL"/>
     <sql-case id="create_procedure_with_analyze_table" value="CREATE PROCEDURE 
p() BEGIN ANALYZE TABLE v; END;" db-types="MySQL"/>
     <sql-case id="create_procedure_doris_control_flow" value="CREATE PROCEDURE 
doris_proc_control() BEGIN DECLARE a INT DEFAULT 0; IF a = 0 THEN SET a = 1; 
ELSE SET a = 2; END IF; WHILE a &lt; 3 DO SET a = a + 1; END WHILE; REPEAT SET 
a = a - 1; UNTIL a = 0 END REPEAT; loop_label: LOOP LEAVE loop_label; END LOOP; 
CASE a WHEN 0 THEN SET a = 0; ELSE SET a = 1; END CASE; SELECT a; END" 
db-types="Doris"/>
+    <sql-case id="create_procedure_keywords_declare_select_into" value="CREATE 
PROCEDURE p1() BEGIN DECLARE slow INT; DECLARE general INT; DECLARE 
ignore_server_ids INT; DECLARE source_heartbeat_period INT; SELECT max(t1.slow) 
INTO slow FROM t1; SELECT max(t1.general) INTO general FROM t1; SELECT 
max(t1.ignore_server_ids) INTO ignore_server_ids FROM t1; SELECT 
max(t1.source_heartbeat_period) INTO source_heartbeat_period FROM t1; SELECT 
slow, general, ignore_server_ids, source_heartbeat_p [...]
+    <sql-case id="create_procedure_keywords_labeled_while" value="CREATE 
PROCEDURE p2() BEGIN DECLARE n INT DEFAULT 2; general: WHILE n &gt; 0 DO SET n 
= n -1; END WHILE general; SET n = 2; slow: WHILE n &gt; 0 DO SET n = n -1; END 
WHILE slow; SET n = 2; ignore_server_ids: WHILE n &gt; 0 DO SET n = n -1; END 
WHILE ignore_server_ids; SET n = 2; source_heartbeat_period: WHILE n &gt; 0 DO 
SET n = n -1; END WHILE source_heartbeat_period; END" db-types="MySQL" />
+    <sql-case id="create_procedure_check_warnings" value="CREATE 
DEFINER=root@localhost PROCEDURE check_warnings(OUT result INT) BEGIN DECLARE 
`pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, 
global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line 
REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 
WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO 
@num_warnings FROM error_log WHERE suspicious=1; IF @num_war [...]
+    <sql-case id="create_procedure_lib_uses_both" value="CREATE PROCEDURE 
lib_uses_both() LANGUAGE JAVASCRIPT AS $$ console.log(&quot;Hello world&quot;) 
$$" db-types="MySQL" />
 </sql-cases>

Reply via email to