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 374da37b880 Enhance SQLNodeConverterEngine to support 
'select_extract_function' (#26901)
374da37b880 is described below

commit 374da37b880cd8b749ebba9b5c8c02b07466addd
Author: cardigan1008 <[email protected]>
AuthorDate: Thu Jul 13 15:37:34 2023 +0800

    Enhance SQLNodeConverterEngine to support 'select_extract_function' (#26901)
    
    * feat(task1): add test case and fix converter
    
    task: select_extract_function
    - add TypeCastExpressionConverter to resolve TIMESTAMP
    
    * feat(task1): support openGauss
    
    * feat(task1): support Postgresql
    
    * fix(task1): checkstyle
    
    * fix(task1): add extract arg converter
    
    * fix(task1): change test case
    
    * fix(task1): checkstyle
    
    * fix(task1): change sqlnode from operator to cast function
---
 .../segment/expression/ExpressionConverter.java    | 10 ++++
 .../impl/ExtractArgExpressionConverter.java        | 41 +++++++++++++++++
 .../impl/TypeCastExpressionConverter.java          | 53 ++++++++++++++++++++++
 .../statement/OpenGaussStatementVisitor.java       | 10 ++++
 .../statement/PostgreSQLStatementVisitor.java      | 10 ++++
 .../segment/dml/expr/ExtractArgExpression.java     | 35 ++++++++++++++
 .../converter/select-special-function.xml          | 21 +++++++++
 .../segment/expression/ExpressionAssert.java       | 19 ++++++++
 .../jaxb/segment/impl/expr/ExpectedExpression.java |  3 ++
 .../impl/expr/ExpectedExtractArgExpression.java    | 33 ++++++++++++++
 .../resources/case/dml/select-special-function.xml |  3 ++
 11 files changed, 238 insertions(+)

diff --git 
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/ExpressionConverter.java
 
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/ExpressionConverter.java
index feed24a53ae..53a3fa08662 100644
--- 
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/ExpressionConverter.java
+++ 
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/ExpressionConverter.java
@@ -25,9 +25,11 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOp
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CaseWhenExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExtractArgExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.TypeCastExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
@@ -41,12 +43,14 @@ import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expres
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.CaseWhenExpressionConverter;
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.ColumnConverter;
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.ExistsSubqueryExpressionConverter;
+import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.ExtractArgExpressionConverter;
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.FunctionConverter;
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.InExpressionConverter;
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.ListExpressionConverter;
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.LiteralExpressionConverter;
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.ParameterMarkerExpressionConverter;
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.SubqueryExpressionConverter;
+import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.TypeCastExpressionConverter;
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.projection.impl.AggregationProjectionConverter;
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.projection.impl.DataTypeConverter;
 import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.impl.NotExpressionConverter;
@@ -109,6 +113,12 @@ public final class ExpressionConverter implements 
SQLSegmentConverter<Expression
         if (segment instanceof NotExpression) {
             return new NotExpressionConverter().convert((NotExpression) 
segment);
         }
+        if (segment instanceof TypeCastExpression) {
+            return new 
TypeCastExpressionConverter().convert((TypeCastExpression) segment);
+        }
+        if (segment instanceof ExtractArgExpression) {
+            return new 
ExtractArgExpressionConverter().convert((ExtractArgExpression) segment);
+        }
         throw new UnsupportedSQLOperationException("unsupported TableSegment 
type: " + segment.getClass());
     }
 }
diff --git 
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/impl/ExtractArgExpressionConverter.java
 
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/impl/ExtractArgExpressionConverter.java
new file mode 100644
index 00000000000..efd0d8a7a05
--- /dev/null
+++ 
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/impl/ExtractArgExpressionConverter.java
@@ -0,0 +1,41 @@
+/*
+ * 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.sqlfederation.compiler.converter.segment.expression.impl;
+
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExtractArgExpression;
+import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.SQLSegmentConverter;
+
+import java.util.Optional;
+
+/**
+ * Extract arg expression converter.
+ */
+public class ExtractArgExpressionConverter implements 
SQLSegmentConverter<ExtractArgExpression, SqlNode> {
+    
+    @Override
+    public Optional<SqlNode> convert(final ExtractArgExpression expression) {
+        if (null == expression) {
+            return Optional.empty();
+        }
+        SqlIdentifier argName = new SqlIdentifier(expression.getText(), 
SqlParserPos.ZERO);
+        return Optional.of(argName);
+    }
+}
diff --git 
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/impl/TypeCastExpressionConverter.java
 
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/impl/TypeCastExpressionConverter.java
new file mode 100644
index 00000000000..80a45778c7f
--- /dev/null
+++ 
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/impl/TypeCastExpressionConverter.java
@@ -0,0 +1,53 @@
+/*
+ * 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.sqlfederation.compiler.converter.segment.expression.impl;
+
+import org.apache.calcite.sql.SqlBasicCall;
+import org.apache.calcite.sql.SqlBasicTypeNameSpec;
+import org.apache.calcite.sql.SqlDataTypeSpec;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlTypeNameSpec;
+import org.apache.calcite.sql.fun.SqlCastFunction;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.SqlTypeName;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.TypeCastExpression;
+import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.SQLSegmentConverter;
+import 
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.ExpressionConverter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Type cast expression converter.
+ */
+public class TypeCastExpressionConverter implements 
SQLSegmentConverter<TypeCastExpression, SqlNode> {
+    
+    @Override
+    public Optional<SqlNode> convert(final TypeCastExpression segment) {
+        Optional<SqlNode> exprssion = new 
ExpressionConverter().convert(segment.getExpression());
+        if (!exprssion.isPresent()) {
+            return Optional.empty();
+        }
+        SqlTypeNameSpec sqlTypeName = new 
SqlBasicTypeNameSpec(SqlTypeName.valueOf(segment.getDataType().toUpperCase()), 
SqlParserPos.ZERO);
+        SqlDataTypeSpec sqlDataTypeSpec = new SqlDataTypeSpec(sqlTypeName, 
SqlParserPos.ZERO);
+        List<SqlNode> operandList = new 
ArrayList<>(Arrays.asList(exprssion.get(), sqlDataTypeSpec));
+        return Optional.of(new SqlBasicCall(new SqlCastFunction(), 
operandList, SqlParserPos.ZERO));
+    }
+}
diff --git 
a/parser/sql/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/OpenGaussStatementVisitor.java
 
b/parser/sql/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/OpenGaussStatementVisitor.java
index 67d46621847..e730e9f3d34 100644
--- 
a/parser/sql/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/OpenGaussStatementVisitor.java
+++ 
b/parser/sql/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/opengauss/visitor/statement/OpenGaussStatementVisitor.java
@@ -47,6 +47,7 @@ import 
org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.Dat
 import 
org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.DeleteContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.ExecuteStmtContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.ExprListContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.ExtractArgContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.ForLockingClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.FromClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.OpenGaussStatementParser.FromListContext;
@@ -132,6 +133,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOp
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CaseWhenExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExtractArgExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
@@ -453,10 +455,18 @@ public abstract class OpenGaussStatementVisitor extends 
OpenGaussStatementBaseVi
         }
         FunctionSegment result = new 
FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), 
ctx.getChild(0).getText(), getOriginalText(ctx));
         Collection<ExpressionSegment> expressionSegments = 
getExpressionSegments(getTargetRuleContextFromParseTree(ctx, 
AExprContext.class));
+        if (ctx.getChild(0).getText().toUpperCase().equals("EXTRACT")) {
+            result.getParameters().add((ExpressionSegment) 
visit(getTargetRuleContextFromParseTree(ctx, 
ExtractArgContext.class).iterator().next()));
+        }
         result.getParameters().addAll(expressionSegments);
         return result;
     }
     
+    @Override
+    public ASTNode visitExtractArg(final ExtractArgContext ctx) {
+        return new ExtractArgExpression(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ctx.getChild(0).getText());
+    }
+    
     private <T extends ParseTree> Collection<T> 
getTargetRuleContextFromParseTree(final ParseTree parseTree, final Class<? 
extends T> clazz) {
         Collection<T> result = new LinkedList<>();
         for (int index = 0; index < parseTree.getChildCount(); index++) {
diff --git 
a/parser/sql/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
 
b/parser/sql/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
index 9a084ecdbee..d0c8af9f7cf 100644
--- 
a/parser/sql/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
+++ 
b/parser/sql/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
@@ -45,6 +45,7 @@ import 
org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.Da
 import 
org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.DeleteContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ExecuteStmtContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ExprListContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ExtractArgContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ForLockingClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.FromClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.FromListContext;
@@ -132,6 +133,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOp
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CaseWhenExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExtractArgExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
@@ -450,10 +452,18 @@ public abstract class PostgreSQLStatementVisitor extends 
PostgreSQLStatementPars
         }
         FunctionSegment result = new 
FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), 
ctx.getChild(0).getText(), getOriginalText(ctx));
         Collection<ExpressionSegment> expressionSegments = 
getExpressionSegments(getTargetRuleContextFromParseTree(ctx, 
AExprContext.class));
+        if (ctx.getChild(0).getText().toUpperCase().equals("EXTRACT")) {
+            result.getParameters().add((ExpressionSegment) 
visit(getTargetRuleContextFromParseTree(ctx, 
ExtractArgContext.class).iterator().next()));
+        }
         result.getParameters().addAll(expressionSegments);
         return result;
     }
     
+    @Override
+    public ASTNode visitExtractArg(final ExtractArgContext ctx) {
+        return new ExtractArgExpression(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ctx.getChild(0).getText());
+    }
+    
     private <T extends ParseTree> Collection<T> 
getTargetRuleContextFromParseTree(final ParseTree parseTree, final Class<? 
extends T> clazz) {
         Collection<T> result = new LinkedList<>();
         for (int index = 0; index < parseTree.getChildCount(); index++) {
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/ExtractArgExpression.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/ExtractArgExpression.java
new file mode 100644
index 00000000000..1d5307486a4
--- /dev/null
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/ExtractArgExpression.java
@@ -0,0 +1,35 @@
+/*
+ * 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.expr;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * ExtraArg segment.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class ExtractArgExpression implements ExpressionSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final String text;
+}
diff --git 
a/test/it/optimizer/src/test/resources/converter/select-special-function.xml 
b/test/it/optimizer/src/test/resources/converter/select-special-function.xml
new file mode 100644
index 00000000000..812bb212128
--- /dev/null
+++ b/test/it/optimizer/src/test/resources/converter/select-special-function.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<sql-node-converter-test-cases>
+    <test-cases sql-case-id="select_extract_function" expected-sql="SELECT 
EXTRACT(&quot;YEAR&quot; FROM CAST('2001-02-16 20:38:40' AS TIMESTAMP))" 
db-types="PostgreSQL,openGauss" />
+</sql-node-converter-test-cases>
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java
index 39027f2ad01..6e2cf9e83cf 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java
@@ -28,6 +28,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CollateE
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExplicitTableExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExtractArgExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
@@ -59,6 +60,7 @@ import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.s
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedExplicitTableExpression;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedExistsSubquery;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedExpression;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedExtractArgExpression;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedInExpression;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedListExpression;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedNotExpression;
@@ -408,6 +410,21 @@ public final class ExpressionAssert {
         }
     }
     
+    /**
+     * Assert extract arg expression.
+     *
+     * @param assertContext assert context
+     * @param actual actual extract arg expression
+     * @param expected expected extract arg expression
+     */
+    private static void assertExtractArgExpression(final SQLCaseAssertContext 
assertContext, final ExtractArgExpression actual, final 
ExpectedExtractArgExpression expected) {
+        if (null == expected) {
+            assertNull(actual, assertContext.getText("Extract arg expression 
should not exist."));
+            return;
+        }
+        assertThat(assertContext.getText("Different: "), actual.getText(), 
is(expected.getText()));
+    }
+    
     /**
      * Assert expression by actual expression segment class type.
      *
@@ -465,6 +482,8 @@ public final class ExpressionAssert {
             assertValuesExpression(assertContext, (ValuesExpression) actual, 
expected.getValuesExpression());
         } else if (actual instanceof ExplicitTableExpression) {
             assertExplicitExpression(assertContext, (ExplicitTableExpression) 
actual, expected.getExplicitTableExpression());
+        } else if (actual instanceof ExtractArgExpression) {
+            assertExtractArgExpression(assertContext, (ExtractArgExpression) 
actual, expected.getExtractArgExpression());
         } else {
             throw new UnsupportedOperationException(String.format("Unsupported 
expression: %s", actual.getClass().getName()));
         }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java
index 75a192ae6a5..a56316a70d3 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java
@@ -101,4 +101,7 @@ public final class ExpectedExpression extends 
AbstractExpectedSQLSegment {
     
     @XmlElement(name = "explicit-table")
     private ExpectedExplicitTableExpression explicitTableExpression;
+    
+    @XmlElement(name = "extract-arg")
+    private ExpectedExtractArgExpression extractArgExpression;
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExtractArgExpression.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExtractArgExpression.java
new file mode 100644
index 00000000000..95b506f470d
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExtractArgExpression.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.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr;
+
+import lombok.Getter;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+/**
+ * Expected extract arg expression.
+ */
+@Getter
+public class ExpectedExtractArgExpression extends AbstractExpectedSQLSegment 
implements ExpectedExpressionSegment {
+    
+    @XmlAttribute
+    private String text;
+}
diff --git 
a/test/it/parser/src/main/resources/case/dml/select-special-function.xml 
b/test/it/parser/src/main/resources/case/dml/select-special-function.xml
index 3ee7abe1abf..0c7c893cfef 100644
--- a/test/it/parser/src/main/resources/case/dml/select-special-function.xml
+++ b/test/it/parser/src/main/resources/case/dml/select-special-function.xml
@@ -321,6 +321,9 @@
             <expression-projection text="EXTRACT(YEAR FROM TIMESTAMP 
'2001-02-16 20:38:40')" start-index="7" stop-index="56">
                 <expr>
                     <function function-name="EXTRACT" start-index="7" 
stop-index="56" text="EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40')">
+                        <parameter>
+                            <extract-arg start-index="15" stop-index="18" 
text="YEAR" />
+                        </parameter>
                         <parameter>
                             <type-cast-expression>
                                 <expression>

Reply via email to