This is an automated email from the ASF dual-hosted git repository.
zhangliang 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 2a11d03d8f6 Support MariaDB DML Returning Clause (#33094) (#33096)
2a11d03d8f6 is described below
commit 2a11d03d8f6a6c2631284b9d051724dfb05b1f54
Author: avalon5666 <[email protected]>
AuthorDate: Mon Oct 7 13:43:23 2024 +0800
Support MariaDB DML Returning Clause (#33094) (#33096)
* Support MariaDB DML Returning Clause (#33094)
* Fix CheckStyle
* Fix CheckStyle
---
.../src/main/antlr4/imports/mysql/DMLStatement.g4 | 14 ++++++++--
.../visitor/statement/MySQLStatementVisitor.java | 10 +++++++
.../statement/type/MySQLDMLStatementVisitor.java | 16 +++++++++++
.../core/statement/dml/DeleteStatement.java | 10 +++++++
.../statement/mysql/dml/MySQLDeleteStatement.java | 8 ++++++
.../statement/mysql/dml/MySQLInsertStatement.java | 8 ++++++
.../parser/src/main/resources/case/dml/delete.xml | 30 ++++++++++++++++++++
.../parser/src/main/resources/case/dml/insert.xml | 32 ++++++++++++++++++++++
.../parser/src/main/resources/case/dml/replace.xml | 32 ++++++++++++++++++++++
.../main/resources/sql/supported/dml/delete.xml | 1 +
.../main/resources/sql/supported/dml/insert.xml | 1 +
.../main/resources/sql/supported/dml/replace.xml | 1 +
12 files changed, 160 insertions(+), 3 deletions(-)
diff --git
a/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/DMLStatement.g4
b/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/DMLStatement.g4
index e3ffd2c716a..c1d11cb372e 100644
--- a/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/DMLStatement.g4
+++ b/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/DMLStatement.g4
@@ -20,7 +20,7 @@ grammar DMLStatement;
import BaseRule;
insert
- : INSERT insertSpecification INTO? tableName partitionNames?
(insertValuesClause | setAssignmentsClause | insertSelectClause)
onDuplicateKeyClause?
+ : INSERT insertSpecification INTO? tableName partitionNames?
(insertValuesClause | setAssignmentsClause | insertSelectClause)
onDuplicateKeyClause? returningClause?
;
insertSpecification
@@ -60,7 +60,7 @@ derivedColumns
;
replace
- : REPLACE replaceSpecification? INTO? tableName partitionNames?
(replaceValuesClause | setAssignmentsClause | replaceSelectClause)
+ : REPLACE replaceSpecification? INTO? tableName partitionNames?
(replaceValuesClause | setAssignmentsClause | replaceSelectClause)
returningClause?
;
replaceSpecification
@@ -105,7 +105,7 @@ blobValue
;
delete
- : DELETE deleteSpecification (singleTableClause | multipleTablesClause)
whereClause? orderByClause? limitClause?
+ : DELETE deleteSpecification (singleTableClause | multipleTablesClause)
whereClause? orderByClause? limitClause? returningClause?
;
deleteSpecification
@@ -417,3 +417,11 @@ tableIdentOptWild
tableAliasRefList
: tableIdentOptWild (COMMA_ tableIdentOptWild)*
;
+
+returningClause
+ : RETURNING targetList
+ ;
+
+targetList
+ : projection (COMMA_ projection)*
+ ;
\ No newline at end of file
diff --git
a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
index d12dd47cd0e..80c2d9f0254 100644
---
a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
+++
b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
@@ -158,6 +158,7 @@ import
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.constrain
import
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.engine.EngineSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.index.IndexNameSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.index.IndexSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.ReturningSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.ColumnAssignmentSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.InsertValuesSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.SetAssignmentSegment;
@@ -1390,6 +1391,9 @@ public abstract class MySQLStatementVisitor extends
MySQLStatementBaseVisitor<AS
}
result.setTable((SimpleTableSegment) visit(ctx.tableName()));
result.addParameterMarkerSegments(getParameterMarkerSegments());
+ if (null != ctx.returningClause()) {
+ result.setReturningSegment((ReturningSegment)
visit(ctx.returningClause()));
+ }
return result;
}
@@ -1462,6 +1466,9 @@ public abstract class MySQLStatementVisitor extends
MySQLStatementBaseVisitor<AS
}
result.setTable((SimpleTableSegment) visit(ctx.tableName()));
result.addParameterMarkerSegments(getParameterMarkerSegments());
+ if (null != ctx.returningClause()) {
+ result.setReturningSegment((ReturningSegment)
visit(ctx.returningClause()));
+ }
return result;
}
@@ -1593,6 +1600,9 @@ public abstract class MySQLStatementVisitor extends
MySQLStatementBaseVisitor<AS
result.setLimit((LimitSegment) visit(ctx.limitClause()));
}
result.addParameterMarkerSegments(getParameterMarkerSegments());
+ if (null != ctx.returningClause()) {
+ result.setReturningSegment((ReturningSegment)
visit(ctx.returningClause()));
+ }
return result;
}
diff --git
a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/type/MySQLDMLStatementVisitor.java
b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/type/MySQLDMLStatementVisitor.java
index ebc0330fc0e..06b9a9e2270 100644
---
a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/type/MySQLDMLStatementVisitor.java
+++
b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/type/MySQLDMLStatementVisitor.java
@@ -27,15 +27,21 @@ import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.IndexHi
import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.LoadDataStatementContext;
import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.LoadStatementContext;
import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.LoadXmlStatementContext;
+import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ProjectionContext;
+import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ReturningClauseContext;
+import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TargetListContext;
import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.WindowClauseContext;
import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.WindowFunctionContext;
import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.WindowingClauseContext;
import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.WindowItemContext;
import
org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.WindowSpecificationContext;
import
org.apache.shardingsphere.sql.parser.mysql.visitor.statement.MySQLStatementVisitor;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.ReturningSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.FunctionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonExpressionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionsSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.OrderBySegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.WindowItemSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.WindowSegment;
@@ -202,4 +208,14 @@ public final class MySQLDMLStatementVisitor extends
MySQLStatementVisitor implem
}
return result;
}
+
+ @Override
+ public ASTNode visitReturningClause(final ReturningClauseContext ctx) {
+ TargetListContext targetList = ctx.targetList();
+ ProjectionsSegment projectionsSegment = new
ProjectionsSegment(targetList.getStart().getStartIndex(),
targetList.getStop().getStopIndex());
+ for (ProjectionContext projectionContext : targetList.projection()) {
+ projectionsSegment.getProjections().add((ProjectionSegment)
visit(projectionContext));
+ }
+ return new ReturningSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(), projectionsSegment);
+ }
}
diff --git
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/dml/DeleteStatement.java
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/dml/DeleteStatement.java
index 81650e9b00e..1e01afa2530 100644
---
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/dml/DeleteStatement.java
+++
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/statement/dml/DeleteStatement.java
@@ -19,6 +19,7 @@ package
org.apache.shardingsphere.sql.parser.statement.core.statement.dml;
import lombok.Getter;
import lombok.Setter;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.ReturningSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.OrderBySegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
@@ -116,4 +117,13 @@ public abstract class DeleteStatement extends
AbstractSQLStatement implements DM
*/
public void setWithSegment(final WithSegment withSegment) {
}
+
+ /**
+ * Get returning segment of delete statement.
+ *
+ * @return returning segment
+ */
+ public Optional<ReturningSegment> getReturningSegment() {
+ return Optional.empty();
+ }
}
diff --git
a/parser/sql/statement/type/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dml/MySQLDeleteStatement.java
b/parser/sql/statement/type/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dml/MySQLDeleteStatement.java
index c215051c596..510f38682c6 100644
---
a/parser/sql/statement/type/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dml/MySQLDeleteStatement.java
+++
b/parser/sql/statement/type/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dml/MySQLDeleteStatement.java
@@ -18,6 +18,7 @@
package org.apache.shardingsphere.sql.parser.statement.mysql.dml;
import lombok.Setter;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.ReturningSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.OrderBySegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.statement.dml.DeleteStatement;
@@ -35,6 +36,8 @@ public final class MySQLDeleteStatement extends
DeleteStatement implements MySQL
private LimitSegment limit;
+ private ReturningSegment returningSegment;
+
@Override
public Optional<OrderBySegment> getOrderBy() {
return Optional.ofNullable(orderBy);
@@ -44,4 +47,9 @@ public final class MySQLDeleteStatement extends
DeleteStatement implements MySQL
public Optional<LimitSegment> getLimit() {
return Optional.ofNullable(limit);
}
+
+ @Override
+ public Optional<ReturningSegment> getReturningSegment() {
+ return Optional.ofNullable(returningSegment);
+ }
}
diff --git
a/parser/sql/statement/type/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dml/MySQLInsertStatement.java
b/parser/sql/statement/type/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dml/MySQLInsertStatement.java
index 0ce09ffc0e4..db67a178a19 100644
---
a/parser/sql/statement/type/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dml/MySQLInsertStatement.java
+++
b/parser/sql/statement/type/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dml/MySQLInsertStatement.java
@@ -18,6 +18,7 @@
package org.apache.shardingsphere.sql.parser.statement.mysql.dml;
import lombok.Setter;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.ReturningSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.SetAssignmentSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.OnDuplicateKeyColumnsSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.statement.dml.InsertStatement;
@@ -35,6 +36,8 @@ public final class MySQLInsertStatement extends
InsertStatement implements MySQL
private OnDuplicateKeyColumnsSegment onDuplicateKeyColumns;
+ private ReturningSegment returningSegment;
+
@Override
public Optional<SetAssignmentSegment> getSetAssignment() {
return Optional.ofNullable(setAssignment);
@@ -44,4 +47,9 @@ public final class MySQLInsertStatement extends
InsertStatement implements MySQL
public Optional<OnDuplicateKeyColumnsSegment> getOnDuplicateKeyColumns() {
return Optional.ofNullable(onDuplicateKeyColumns);
}
+
+ @Override
+ public Optional<ReturningSegment> getReturningSegment() {
+ return Optional.ofNullable(returningSegment);
+ }
}
diff --git a/test/it/parser/src/main/resources/case/dml/delete.xml
b/test/it/parser/src/main/resources/case/dml/delete.xml
index e6f004f1a9a..6cf5229359e 100644
--- a/test/it/parser/src/main/resources/case/dml/delete.xml
+++ b/test/it/parser/src/main/resources/case/dml/delete.xml
@@ -742,4 +742,34 @@
</expr>
</where>
</delete>
+ <delete sql-case-id="delete_returning_expressions">
+ <table name="t2" start-index="12" stop-index="13" />
+ <where start-index="15" stop-index="26">
+ <expr>
+ <binary-operation-expression start-index="21" stop-index="26">
+ <left>
+ <column name="id" start-index="21" stop-index="22" />
+ </left>
+ <right>
+ <literal-expression value="2" start-index="26"
stop-index="26" />
+ </right>
+ <operator>=</operator>
+ </binary-operation-expression>
+ </expr>
+ </where>
+ <returning start-index="29" stop-index="44">
+ <projections start-index="39" stop-index="44">
+ <column-projection name="id" start-index="39" stop-index="40"
/>
+ <expression-projection start-index="42" stop-index="44"
text="t&t">
+ <left>
+ <column name="t" start-index="42" stop-index="42" />
+ </left>
+ <operator>&</operator>
+ <right>
+ <column name="t" start-index="44" stop-index="44" />
+ </right>
+ </expression-projection>
+ </projections>
+ </returning>
+ </delete>
</sql-parser-test-cases>
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 44efe784265..7f10b171b83 100644
--- a/test/it/parser/src/main/resources/case/dml/insert.xml
+++ b/test/it/parser/src/main/resources/case/dml/insert.xml
@@ -4288,4 +4288,36 @@
</assignment>
</on-duplicate-key-columns>
</insert>
+ <insert sql-case-id="insert_returning_expressions">
+ <table name="t2" start-index="12" stop-index="13" />
+ <columns start-index="15" stop-index="18">
+ <column name ="id" start-index="16" stop-index="17" />
+ </columns>
+ <values>
+ <value>
+ <assignment-value>
+ <literal-expression value="2" start-index="28"
stop-index="28" />
+ </assignment-value>
+ </value>
+ <value>
+ <assignment-value>
+ <literal-expression value="3" start-index="32"
stop-index="32" />
+ </assignment-value>
+ </value>
+ </values>
+ <returning start-index="35" stop-index="50">
+ <projections start-index="45" stop-index="50">
+ <column-projection name="id" start-index="45" stop-index="46"
/>
+ <expression-projection start-index="48" stop-index="50"
text="t&t">
+ <left>
+ <column name="t" start-index="48" stop-index="48" />
+ </left>
+ <operator>&</operator>
+ <right>
+ <column name="t" start-index="50" stop-index="50" />
+ </right>
+ </expression-projection>
+ </projections>
+ </returning>
+ </insert>
</sql-parser-test-cases>
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 415a09c21c3..d9c57d84e27 100644
--- a/test/it/parser/src/main/resources/case/dml/replace.xml
+++ b/test/it/parser/src/main/resources/case/dml/replace.xml
@@ -993,4 +993,36 @@
</where>
</select>
</insert>
+ <insert sql-case-id="replace_returning_expressions">
+ <table name="t2" start-index="13" stop-index="14" />
+ <columns start-index="16" stop-index="19">
+ <column name ="id" start-index="17" stop-index="18" />
+ </columns>
+ <values>
+ <value>
+ <assignment-value>
+ <literal-expression value="2" start-index="29"
stop-index="29" />
+ </assignment-value>
+ </value>
+ <value>
+ <assignment-value>
+ <literal-expression value="3" start-index="33"
stop-index="33" />
+ </assignment-value>
+ </value>
+ </values>
+ <returning start-index="36" stop-index="51">
+ <projections start-index="46" stop-index="51">
+ <column-projection name="id" start-index="46" stop-index="47"
/>
+ <expression-projection start-index="49" stop-index="51"
text="t&t">
+ <left>
+ <column name="t" start-index="49" stop-index="49" />
+ </left>
+ <operator>&</operator>
+ <right>
+ <column name="t" start-index="51" stop-index="51" />
+ </right>
+ </expression-projection>
+ </projections>
+ </returning>
+ </insert>
</sql-parser-test-cases>
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/delete.xml
b/test/it/parser/src/main/resources/sql/supported/dml/delete.xml
index a2283f98e86..0b1d83d0d78 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/delete.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/delete.xml
@@ -44,4 +44,5 @@
<sql-case id="delete_with_schema" value="DELETE FROM db1.t_order" />
<sql-case id="delete_with_simple_condition" value="DELETE FROM
Q1_2000_sales WHERE amount_sold < 0" db-types="Oracle" />
<sql-case id="delete_with_output_clause_with_compress_function"
value="DELETE FROM player OUTPUT deleted.id,deleted.name,
deleted.surname,deleted.datemodifier,COMPRESS(deleted.info) INTO
dbo.inactivePlayers WHERE datemodified < @startOfYear" db-types="SQLServer"
/>
+ <sql-case id="delete_returning_expressions" value="DELETE FROM t2 WHERE id
= 2 RETURNING id,t&t" db-types="MySQL" />
</sql-cases>
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 88c34134dce..f5f8d8421f0 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
@@ -153,5 +153,6 @@
<sql-case id="insert_on_duplicate_key_with_column_aliases" value="INSERT
INTO t SET a=9,b=5 AS new(m,n) ON DUPLICATE KEY UPDATE a=m+n" db-types="MySQL"/>
<sql-case id="insert_with_aes_encrypt" value="INSERT INTO
t_order_item(item_id,encrypt) VALUES (1,AES_ENCRYPT('text','key_str'))"
db-types="MySQL" />
<sql-case id="insert_on_duplicate_key_update_with_values" value="INSERT
INTO table (a,b,c) VALUES (1,2,3),(4,5,6) ON DUPLICATE KEY UPDATE
c=VALUES(a)+VALUES(b);" db-types="MySQL" />
+ <sql-case id="insert_returning_expressions" value="INSERT INTO t2 (id)
VALUES (2),(3) RETURNING id,t&t" db-types="MySQL" />
</sql-cases>
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 5dc070ac9a6..14e7abc297c 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
@@ -50,4 +50,5 @@
<sql-case id="replace_select_without_columns" value="REPLACE INTO t_order
SELECT order_id, user_id, status FROM t_order WHERE order_id = ?"
db-types="MySQL" />
<sql-case id="replace_select_with_generate_key_column" value="REPLACE INTO
t_order_item(item_id, order_id, user_id, status, creation_date) SELECT item_id,
order_id, user_id, 'insert', '2017-08-08' FROM t_order_item WHERE item_id = ?"
db-types="MySQL" />
<sql-case id="replace_select_without_generate_key_column" value="REPLACE
INTO t_order_item(order_id, user_id, status, creation_date) SELECT order_id,
user_id, 'insert', '2017-08-08' FROM t_order_item WHERE order_id = ?"
db-types="MySQL" />
+ <sql-case id="replace_returning_expressions" value="REPLACE INTO t2 (id)
VALUES (2),(3) RETURNING id,t&t" db-types="MySQL" />
</sql-cases>