You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by du...@apache.org on 2022/11/23 06:26:43 UTC

[shardingsphere] branch master updated: Parse RETURNING clause of PostgreSQL/openGauss Insert (#22353)

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 74ec5dfa35c Parse RETURNING clause of PostgreSQL/openGauss Insert (#22353)
74ec5dfa35c is described below

commit 74ec5dfa35c98d7436a353456a6d5be99320a570
Author: 吴伟杰 <wu...@apache.org>
AuthorDate: Wed Nov 23 14:26:30 2022 +0800

    Parse RETURNING clause of PostgreSQL/openGauss Insert (#22353)
    
    * Parse RETURNING clause of PostgreSQL Insert
    
    * Complete parser test cases for RETURNING clause
    
    * Parse RETURNING clause of openGauss Insert
---
 .../impl/OpenGaussDMLStatementSQLVisitor.java      | 10 ++++-
 .../impl/OpenGaussStatementSQLVisitor.java         |  4 ++
 .../impl/PostgreSQLDMLStatementSQLVisitor.java     |  8 ++++
 .../impl/PostgreSQLStatementSQLVisitor.java        |  4 ++
 .../sql/common/segment/dml/ReturningSegment.java   | 39 ++++++++++++++++++
 .../handler/dml/InsertStatementHandler.java        | 17 ++++++++
 .../opengauss/dml/OpenGaussInsertStatement.java    | 12 ++++++
 .../postgresql/dml/PostgreSQLInsertStatement.java  | 12 ++++++
 .../segment/returning/ReturningClauseAssert.java   | 47 ++++++++++++++++++++++
 .../statement/dml/impl/InsertStatementAssert.java  | 13 ++++++
 .../impl/insert/ExpectedReturningClause.java       | 33 +++++++++++++++
 .../statement/dml/InsertStatementTestCase.java     |  4 ++
 test/parser/src/main/resources/case/dml/insert.xml | 14 +++++++
 .../main/resources/sql/supported/dml/insert.xml    |  2 +-
 14 files changed, 217 insertions(+), 2 deletions(-)

diff --git a/sql-parser/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/impl/OpenGaussDMLStatementSQLVisitor.java b/sql-parser/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/impl/OpenGaussDMLStatementSQLVisitor.java
index fbca0048c63..c04fe4c97ac 100644
--- a/sql-parser/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/impl/OpenGaussDMLStatementSQLVisitor.java
+++ b/sql-parser/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/impl/OpenGaussDMLStatementSQLVisitor.java
@@ -25,11 +25,14 @@ import org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.Cal
 import org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.CheckpointContext;
 import org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.CopyContext;
 import org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.DoStatementContext;
+import org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.ReturningClauseContext;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.ReturningSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.dml.OpenGaussCallStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.dml.OpenGaussCheckpointStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.dml.OpenGaussCopyStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.dml.OpenGaussDoStatement;
-import org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.dml.OpenGaussCheckpointStatement;
 
 import java.util.Properties;
 
@@ -66,4 +69,9 @@ public final class OpenGaussDMLStatementSQLVisitor extends OpenGaussStatementSQL
     public ASTNode visitCheckpoint(final CheckpointContext ctx) {
         return new OpenGaussCheckpointStatement();
     }
+    
+    @Override
+    public ASTNode visitReturningClause(final ReturningClauseContext ctx) {
+        return new ReturningSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ProjectionsSegment) visit(ctx.targetList()));
+    }
 }
diff --git a/sql-parser/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/impl/OpenGaussStatementSQLVisitor.java b/sql-parser/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/impl/OpenGaussStatementSQLVisitor.java
index 2252289e2e1..319236c2bf7 100644
--- a/sql-parser/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/impl/OpenGaussStatementSQLVisitor.java
+++ b/sql-parser/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/impl/OpenGaussStatementSQLVisitor.java
@@ -116,6 +116,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.enums.ParameterMarkerType
 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.constraint.ConstraintSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexNameSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.ReturningSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
@@ -666,6 +667,9 @@ public abstract class OpenGaussStatementSQLVisitor extends OpenGaussStatementBas
         if (null != ctx.optOnDuplicateKey()) {
             result.setOnDuplicateKeyColumnsSegment((OnDuplicateKeyColumnsSegment) visit(ctx.optOnDuplicateKey()));
         }
+        if (null != ctx.returningClause()) {
+            result.setReturningSegment((ReturningSegment) visit(ctx.returningClause()));
+        }
         result.setParameterCount(getCurrentParameterIndex());
         result.getParameterMarkerSegments().addAll(getParameterMarkerSegments());
         return result;
diff --git a/sql-parser/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLDMLStatementSQLVisitor.java b/sql-parser/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLDMLStatementSQLVisitor.java
index fe27cd49999..6e0512eeb62 100644
--- a/sql-parser/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLDMLStatementSQLVisitor.java
+++ b/sql-parser/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLDMLStatementSQLVisitor.java
@@ -31,9 +31,12 @@ import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.Co
 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.CopyWithTableOrQueryContext;
 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.DoStatementContext;
 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.PreparableStmtContext;
+import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ReturningClauseContext;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.ReturningSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.prepare.PrepareStatementQuerySegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
@@ -157,4 +160,9 @@ public final class PostgreSQLDMLStatementSQLVisitor extends PostgreSQLStatementS
     public ASTNode visitCheckpoint(final CheckpointContext ctx) {
         return new PostgreSQLCheckpointStatement();
     }
+    
+    @Override
+    public ASTNode visitReturningClause(final ReturningClauseContext ctx) {
+        return new ReturningSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ProjectionsSegment) visit(ctx.targetList()));
+    }
 }
diff --git a/sql-parser/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLStatementSQLVisitor.java b/sql-parser/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLStatementSQLVisitor.java
index 27e2443a7ab..290d42b687e 100644
--- a/sql-parser/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLStatementSQLVisitor.java
+++ b/sql-parser/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/impl/PostgreSQLStatementSQLVisitor.java
@@ -116,6 +116,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.enums.ParameterMarkerType
 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.constraint.ConstraintSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexNameSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.ReturningSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.AssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
@@ -663,6 +664,9 @@ public abstract class PostgreSQLStatementSQLVisitor extends PostgreSQLStatementP
         if (null != ctx.optOnConflict()) {
             result.setOnDuplicateKeyColumnsSegment((OnDuplicateKeyColumnsSegment) visit(ctx.optOnConflict()));
         }
+        if (null != ctx.returningClause()) {
+            result.setReturningSegment((ReturningSegment) visit(ctx.returningClause()));
+        }
         result.setParameterCount(getCurrentParameterIndex());
         result.getParameterMarkerSegments().addAll(getParameterMarkerSegments());
         return result;
diff --git a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/ReturningSegment.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/ReturningSegment.java
new file mode 100644
index 00000000000..b201a628a5c
--- /dev/null
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/ReturningSegment.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
+
+/**
+ * Segment for returning clause.
+ */
+@RequiredArgsConstructor
+@Getter
+@ToString
+public final class ReturningSegment implements SQLSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final ProjectionsSegment projections;
+}
diff --git a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/dml/InsertStatementHandler.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/dml/InsertStatementHandler.java
index f192c9582ba..9cbe42bab98 100644
--- a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/dml/InsertStatementHandler.java
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/handler/dml/InsertStatementHandler.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.sql.parser.sql.dialect.handler.dml;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.ReturningSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.OnDuplicateKeyColumnsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
@@ -132,4 +133,20 @@ public final class InsertStatementHandler implements SQLStatementHandler {
         }
         return Optional.empty();
     }
+    
+    /**
+     * Get returning segment of insert statement.
+     *
+     * @param insertStatement insert statement
+     * @return returning segment
+     */
+    public static Optional<ReturningSegment> getReturningSegment(final InsertStatement insertStatement) {
+        if (insertStatement instanceof PostgreSQLStatement) {
+            return ((PostgreSQLInsertStatement) insertStatement).getReturningSegment();
+        }
+        if (insertStatement instanceof OpenGaussStatement) {
+            return ((OpenGaussInsertStatement) insertStatement).getReturningSegment();
+        }
+        return Optional.empty();
+    }
 }
diff --git a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/opengauss/dml/OpenGaussInsertStatement.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/opengauss/dml/OpenGaussInsertStatement.java
index 14aa0318835..13c7432b376 100644
--- a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/opengauss/dml/OpenGaussInsertStatement.java
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/opengauss/dml/OpenGaussInsertStatement.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.dml
 
 import lombok.Setter;
 import lombok.ToString;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.ReturningSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.OnDuplicateKeyColumnsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.WithSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
@@ -37,6 +38,8 @@ public final class OpenGaussInsertStatement extends InsertStatement implements O
     
     private OnDuplicateKeyColumnsSegment onDuplicateKeyColumnsSegment;
     
+    private ReturningSegment returningSegment;
+    
     /**
      * Get with segment.
      *
@@ -54,4 +57,13 @@ public final class OpenGaussInsertStatement extends InsertStatement implements O
     public Optional<OnDuplicateKeyColumnsSegment> getOnDuplicateKeyColumns() {
         return Optional.ofNullable(onDuplicateKeyColumnsSegment);
     }
+    
+    /**
+     * Get returning segment.
+     *
+     * @return returning segment
+     */
+    public Optional<ReturningSegment> getReturningSegment() {
+        return Optional.ofNullable(returningSegment);
+    }
 }
diff --git a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/postgresql/dml/PostgreSQLInsertStatement.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/postgresql/dml/PostgreSQLInsertStatement.java
index 1223685c575..047ae5002ac 100644
--- a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/postgresql/dml/PostgreSQLInsertStatement.java
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/statement/postgresql/dml/PostgreSQLInsertStatement.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.dm
 
 import lombok.Setter;
 import lombok.ToString;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.ReturningSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.OnDuplicateKeyColumnsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.WithSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
@@ -37,6 +38,8 @@ public final class PostgreSQLInsertStatement extends InsertStatement implements
     
     private OnDuplicateKeyColumnsSegment onDuplicateKeyColumnsSegment;
     
+    private ReturningSegment returningSegment;
+    
     /**
      * Get with segment.
      *
@@ -54,4 +57,13 @@ public final class PostgreSQLInsertStatement extends InsertStatement implements
     public Optional<OnDuplicateKeyColumnsSegment> getOnDuplicateKeyColumns() {
         return Optional.ofNullable(onDuplicateKeyColumnsSegment);
     }
+    
+    /**
+     * Get returning segment.
+     *
+     * @return returning segment
+     */
+    public Optional<ReturningSegment> getReturningSegment() {
+        return Optional.ofNullable(returningSegment);
+    }
 }
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/asserts/segment/returning/ReturningClauseAssert.java b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/asserts/segment/returning/ReturningClauseAssert.java
new file mode 100644
index 00000000000..b0b6a65456d
--- /dev/null
+++ b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/asserts/segment/returning/ReturningClauseAssert.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.returning;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.ReturningSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
+import org.apache.shardingsphere.test.sql.parser.internal.asserts.SQLCaseAssertContext;
+import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.projection.ProjectionAssert;
+import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.insert.ExpectedReturningClause;
+
+/**
+ * Returning clause assert.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ReturningClauseAssert {
+    
+    /**
+     * Assert actual returning segment is correct with expected returning clause.
+     *
+     * @param assertContext assert context
+     * @param actual actual returning segment
+     * @param expected expected returning clause
+     */
+    public static void assertIs(final SQLCaseAssertContext assertContext, final ReturningSegment actual, final ExpectedReturningClause expected) {
+        ProjectionsSegment actualProjections = actual.getProjections();
+        if (null != actualProjections.getProjections() || expected.getProjections().getSize() > 0) {
+            ProjectionAssert.assertIs(assertContext, actualProjections, expected.getProjections());
+        }
+    }
+}
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/asserts/statement/dml/impl/InsertStatementAssert.java b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/asserts/statement/dml/impl/InsertStatementAssert.java
index e96bba25246..22736da5ee4 100644
--- a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/asserts/statement/dml/impl/InsertStatementAssert.java
+++ b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/asserts/statement/dml/impl/InsertStatementAssert.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.test.sql.parser.internal.asserts.statement.dml
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.ReturningSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.OnDuplicateKeyColumnsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
@@ -32,6 +33,7 @@ import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.insert
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.insert.InsertMultiTableElementAssert;
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.insert.InsertValuesClauseAssert;
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.insert.OnDuplicateKeyColumnsAssert;
+import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.returning.ReturningClauseAssert;
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.output.OutputClauseAssert;
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.set.SetClauseAssert;
 import org.apache.shardingsphere.test.sql.parser.internal.asserts.segment.table.TableAssert;
@@ -68,6 +70,7 @@ public final class InsertStatementAssert {
         assertOutputClause(assertContext, actual, expected);
         assertInsertMultiTableElement(assertContext, actual, expected);
         assertSelectSubqueryClause(assertContext, actual, expected);
+        assertReturningClause(assertContext, actual, expected);
     }
     
     private static void assertTable(final SQLCaseAssertContext assertContext, final InsertStatement actual, final InsertStatementTestCase expected) {
@@ -164,4 +167,14 @@ public final class InsertStatementAssert {
             SelectStatementAssert.assertIs(assertContext, selectSubquery.get().getSelect(), expected.getSelectSubquery());
         }
     }
+    
+    private static void assertReturningClause(final SQLCaseAssertContext assertContext, final InsertStatement actual, final InsertStatementTestCase expected) {
+        Optional<ReturningSegment> returningSegment = InsertStatementHandler.getReturningSegment(actual);
+        if (null == expected.getReturningClause()) {
+            assertFalse(assertContext.getText("Actual returning segment should not exist."), returningSegment.isPresent());
+        } else {
+            assertTrue(assertContext.getText("Actual returning segment should exist."), returningSegment.isPresent());
+            ReturningClauseAssert.assertIs(assertContext, returningSegment.get(), expected.getReturningClause());
+        }
+    }
 }
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/insert/ExpectedReturningClause.java b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/insert/ExpectedReturningClause.java
new file mode 100644
index 00000000000..b284173e854
--- /dev/null
+++ b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/segment/impl/insert/ExpectedReturningClause.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.insert;
+
+import lombok.Getter;
+import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.projection.ExpectedProjections;
+
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * Expected returning clause.
+ */
+@Getter
+public class ExpectedReturningClause {
+    
+    @XmlElement
+    private final ExpectedProjections projections = new ExpectedProjections();
+}
diff --git a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/statement/dml/InsertStatementTestCase.java b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/statement/dml/InsertStatementTestCase.java
index a76c8ba6469..026bc2b2eac 100644
--- a/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/statement/dml/InsertStatementTestCase.java
+++ b/test/parser/src/main/java/org/apache/shardingsphere/test/sql/parser/internal/cases/parser/domain/statement/dml/InsertStatementTestCase.java
@@ -23,6 +23,7 @@ import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.se
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.insert.ExpectedInsertMultiTableElement;
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.insert.ExpectedInsertValuesClause;
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.insert.ExpectedOnDuplicateKeyColumns;
+import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.insert.ExpectedReturningClause;
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.output.ExpectedOutputClause;
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.set.ExpectedSetClause;
 import org.apache.shardingsphere.test.sql.parser.internal.cases.parser.domain.segment.impl.table.ExpectedSimpleTable;
@@ -67,4 +68,7 @@ public final class InsertStatementTestCase extends SQLParserTestCase {
     
     @XmlElement(name = "select-subquery")
     private SelectStatementTestCase selectSubquery;
+    
+    @XmlElement(name = "returning")
+    private ExpectedReturningClause returningClause;
 }
diff --git a/test/parser/src/main/resources/case/dml/insert.xml b/test/parser/src/main/resources/case/dml/insert.xml
index 4c659158c7f..6657a19375f 100644
--- a/test/parser/src/main/resources/case/dml/insert.xml
+++ b/test/parser/src/main/resources/case/dml/insert.xml
@@ -199,6 +199,20 @@
             </value>
         </values>
         <comment start-index="7" stop-index="26" text="/*+ index(field1) */"/>
+        <returning>
+            <projections start-index="103" stop-index="169">
+                <column-projection name="order_id" start-index="103" stop-index="110" />
+                <shorthand-projection start-index="113" stop-index="113" />
+                <shorthand-projection start-index="116" stop-index="124">
+                    <owner name="t_order" start-index="116" stop-index="122"/>
+                </shorthand-projection>
+                <column-projection name="user_id" alias="u" start-index="127" stop-index="135" />
+                <column-projection name="status" alias="s" start-index="138" stop-index="156">
+                    <owner name="t_order" start-index="138" stop-index="144"/>
+                </column-projection>
+                <expression-projection text="'OK'" alias="result" start-index="159" stop-index="169" />
+            </projections>
+        </returning>
     </insert>
 
     <insert sql-case-id="insert_with_all_placeholders_for_table_identifier" parameters="1, 1, 'init'">
diff --git a/test/parser/src/main/resources/sql/supported/dml/insert.xml b/test/parser/src/main/resources/sql/supported/dml/insert.xml
index ddf5fa3058e..3b2749fbe4f 100644
--- a/test/parser/src/main/resources/sql/supported/dml/insert.xml
+++ b/test/parser/src/main/resources/sql/supported/dml/insert.xml
@@ -21,7 +21,7 @@
     <sql-case id="insert_with_now_function" value="INSERT INTO t_order_item (item_id, order_id, user_id, status, creation_date) VALUES (?, ?, ?, 'insert', now())" db-types="MySQL" />
     <sql-case id="insert_without_parameters" value="INSERT INTO t_order (order_id, user_id, status) VALUES (1, 1, 'insert')" />
     <sql-case id="insert_with_special_characters" value="INSERT INTO `t_order` (`order_id`, `user_id`, `status`) VALUES (1, 1, 'insert')" db-types="MySQL" />
-    <sql-case id="insert_with_special_syntax" value="INSERT /*+ index(field1) */ INTO t_order (order_id, user_id, status) VALUES (1, 1, 'insert') RETURNING order_id" db-types="PostgreSQL,openGauss" />
+    <sql-case id="insert_with_special_syntax" value="INSERT /*+ index(field1) */ INTO t_order (order_id, user_id, status) VALUES (1, 1, 'insert') RETURNING order_id, *, t_order.*, user_id u, t_order.status as s, 'OK' result" db-types="PostgreSQL,openGauss" />
     <sql-case id="insert_with_all_placeholders_for_table_identifier" value="INSERT INTO t_order (t_order.order_id, t_order.user_id, t_order.status) VALUES (?, ?, ?)" />
     <sql-case id="insert_without_columns_with_all_placeholders" value="INSERT INTO t_order VALUES (?, ?, ?)" />
     <sql-case id="insert_set_with_all_placeholders" value="INSERT INTO t_order SET order_id = ?, user_id = ?, status = ?" db-types="MySQL" />