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 2023/01/17 01:22:38 UTC
[shardingsphere] branch master updated: Add TypeCastExpression for PostgreSQL/openGauss (#23580)
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 6b095c835f5 Add TypeCastExpression for PostgreSQL/openGauss (#23580)
6b095c835f5 is described below
commit 6b095c835f5334f01bb6643565ddb3276e9f9a56
Author: 吴伟杰 <wu...@apache.org>
AuthorDate: Tue Jan 17 09:22:30 2023 +0800
Add TypeCastExpression for PostgreSQL/openGauss (#23580)
* Add TypeCastExpression for PostgreSQL/openGauss
* Add TypeCastExpression to ExpressionExtractUtil
* Add parser test for PostgreSQL/openGauss nested type cast
* Use TypeCastExpression in openGauss parser
* Remove TODO in select.xml
* Complete ExpressionExtractUtilTest
---
.../impl/OpenGaussStatementSQLVisitor.java | 28 ++--
.../impl/PostgreSQLStatementSQLVisitor.java | 28 ++--
.../segment/dml/expr/TypeCastExpression.java | 38 +++++
.../sql/common/util/ExpressionExtractUtil.java | 4 +
.../sql/common/util/ExpressionExtractUtilTest.java | 11 ++
.../segment/expression/ExpressionAssert.java | 15 +-
.../jaxb/segment/impl/expr/ExpectedExpression.java | 3 +
.../impl/expr/ExpectedTypeCastExpression.java | 37 +++++
.../resources/case/dml/select-special-function.xml | 7 +-
.../parser/src/main/resources/case/dml/select.xml | 153 +++++++++++++--------
.../main/resources/sql/supported/dml/select.xml | 1 +
11 files changed, 238 insertions(+), 87 deletions(-)
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 1362f4dcf2d..573d175ab57 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
@@ -134,6 +134,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.Expressi
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;
@@ -294,8 +295,7 @@ public abstract class OpenGaussStatementSQLVisitor extends OpenGaussStatementBas
return visit(ctx.cExpr());
}
if (null != ctx.TYPE_CAST_()) {
- return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.aExpr(0)),
- new CommonExpressionSegment(ctx.typeName().start.getStartIndex(), ctx.typeName().stop.getStopIndex(), ctx.typeName().getText()), ctx.TYPE_CAST_().getText(), ctx.getText());
+ return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.aExpr(0)), ctx.typeName().getText());
}
if (null != ctx.BETWEEN()) {
return createBetweenSegment(ctx);
@@ -452,6 +452,9 @@ public abstract class OpenGaussStatementSQLVisitor extends OpenGaussStatementBas
@Override
public ASTNode visitFunctionExprCommonSubexpr(final FunctionExprCommonSubexprContext ctx) {
+ if (null != ctx.CAST()) {
+ return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.aExpr(0)), ctx.typeName().getText());
+ }
FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getChild(0).getText(), getOriginalText(ctx));
Collection<ExpressionSegment> expressionSegments = getExpressionSegments(getTargetRuleContextFromParseTree(ctx, AExprContext.class));
result.getParameters().addAll(expressionSegments);
@@ -495,6 +498,11 @@ public abstract class OpenGaussStatementSQLVisitor extends OpenGaussStatementBas
} else {
value = new OtherLiteralValue(ctx.getText());
}
+ if (null != ctx.constTypeName() || null != ctx.funcName() && null == ctx.LP_()) {
+ LiteralExpressionSegment expression = new LiteralExpressionSegment(ctx.STRING_().getSymbol().getStartIndex(), ctx.STRING_().getSymbol().getStopIndex(), value.getValue().toString());
+ String dataType = null != ctx.constTypeName() ? ctx.constTypeName().getText() : ctx.funcName().getText();
+ return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), expression, dataType);
+ }
return SQLUtil.createLiteralExpression(value, ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.getText());
}
@@ -553,17 +561,13 @@ public abstract class OpenGaussStatementSQLVisitor extends OpenGaussStatementBas
if (null != ctx.cExpr()) {
return visit(ctx.cExpr());
}
- if (null != ctx.TYPE_CAST_() || null != ctx.qualOp()) {
+ if (null != ctx.TYPE_CAST_()) {
+ return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.bExpr(0)), ctx.typeName().getText());
+ }
+ if (null != ctx.qualOp()) {
ExpressionSegment left = (ExpressionSegment) visit(ctx.bExpr(0));
- String operator;
- ExpressionSegment right;
- if (null == ctx.TYPE_CAST_()) {
- operator = ctx.qualOp().getText();
- right = (ExpressionSegment) visit(ctx.bExpr(1));
- } else {
- operator = ctx.TYPE_CAST_().getText();
- right = new CommonExpressionSegment(ctx.typeName().start.getStartIndex(), ctx.typeName().stop.getStopIndex(), ctx.typeName().getText());
- }
+ ExpressionSegment right = (ExpressionSegment) visit(ctx.bExpr(1));
+ String operator = ctx.qualOp().getText();
String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
}
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 210dbe61e86..7073cf4e819 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
@@ -134,6 +134,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.Expressi
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;
@@ -294,8 +295,7 @@ public abstract class PostgreSQLStatementSQLVisitor extends PostgreSQLStatementP
return visit(ctx.cExpr());
}
if (null != ctx.TYPE_CAST_()) {
- return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.aExpr(0)),
- new CommonExpressionSegment(ctx.typeName().start.getStartIndex(), ctx.typeName().stop.getStopIndex(), ctx.typeName().getText()), ctx.TYPE_CAST_().getText(), ctx.getText());
+ return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.aExpr(0)), ctx.typeName().getText());
}
if (null != ctx.BETWEEN()) {
return createBetweenSegment(ctx);
@@ -449,6 +449,9 @@ public abstract class PostgreSQLStatementSQLVisitor extends PostgreSQLStatementP
@Override
public ASTNode visitFunctionExprCommonSubexpr(final FunctionExprCommonSubexprContext ctx) {
+ if (null != ctx.CAST()) {
+ return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.aExpr(0)), ctx.typeName().getText());
+ }
FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getChild(0).getText(), getOriginalText(ctx));
Collection<ExpressionSegment> expressionSegments = getExpressionSegments(getTargetRuleContextFromParseTree(ctx, AExprContext.class));
result.getParameters().addAll(expressionSegments);
@@ -492,6 +495,11 @@ public abstract class PostgreSQLStatementSQLVisitor extends PostgreSQLStatementP
} else {
value = new OtherLiteralValue(ctx.getText());
}
+ if (null != ctx.constTypeName() || null != ctx.funcName() && null == ctx.LP_()) {
+ LiteralExpressionSegment expression = new LiteralExpressionSegment(ctx.STRING_().getSymbol().getStartIndex(), ctx.STRING_().getSymbol().getStopIndex(), value.getValue().toString());
+ String dataType = null != ctx.constTypeName() ? ctx.constTypeName().getText() : ctx.funcName().getText();
+ return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), expression, dataType);
+ }
return SQLUtil.createLiteralExpression(value, ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.getText());
}
@@ -550,17 +558,13 @@ public abstract class PostgreSQLStatementSQLVisitor extends PostgreSQLStatementP
if (null != ctx.cExpr()) {
return visit(ctx.cExpr());
}
- if (null != ctx.TYPE_CAST_() || null != ctx.qualOp()) {
+ if (null != ctx.TYPE_CAST_()) {
+ return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.bExpr(0)), ctx.typeName().getText());
+ }
+ if (null != ctx.qualOp()) {
ExpressionSegment left = (ExpressionSegment) visit(ctx.bExpr(0));
- String operator;
- ExpressionSegment right;
- if (null == ctx.TYPE_CAST_()) {
- operator = ctx.qualOp().getText();
- right = (ExpressionSegment) visit(ctx.bExpr(1));
- } else {
- operator = ctx.TYPE_CAST_().getText();
- right = new CommonExpressionSegment(ctx.typeName().start.getStartIndex(), ctx.typeName().stop.getStopIndex(), ctx.typeName().getText());
- }
+ ExpressionSegment right = (ExpressionSegment) visit(ctx.bExpr(1));
+ String operator = ctx.qualOp().getText();
String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
}
diff --git a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/TypeCastExpression.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/TypeCastExpression.java
new file mode 100644
index 00000000000..d9cdb22c7a7
--- /dev/null
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/TypeCastExpression.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Type cast expression.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class TypeCastExpression implements ExpressionSegment {
+
+ private final int startIndex;
+
+ private final int stopIndex;
+
+ private final ExpressionSegment expression;
+
+ // TODO Parse data type after https://github.com/apache/shardingsphere/issues/23466 fixed
+ private final String dataType;
+}
diff --git a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtil.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtil.java
index fc3ad412f9a..2965d944429 100644
--- a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtil.java
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtil.java
@@ -23,6 +23,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.enums.LogicalOperator;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.TypeCastExpression;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
@@ -111,6 +112,9 @@ public final class ExpressionExtractUtil {
if (each instanceof FunctionSegment) {
extractParameterMarkerExpressions(result, ((FunctionSegment) each).getParameters());
}
+ if (each instanceof TypeCastExpression) {
+ extractParameterMarkerExpressions(result, Collections.singletonList(((TypeCastExpression) each).getExpression()));
+ }
}
}
}
diff --git a/sql-parser/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtilTest.java b/sql-parser/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtilTest.java
index d4af56a11df..1b4dd21b026 100644
--- a/sql-parser/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtilTest.java
+++ b/sql-parser/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtilTest.java
@@ -17,10 +17,12 @@
package org.apache.shardingsphere.sql.parser.sql.common.util;
+import org.apache.shardingsphere.sql.parser.sql.common.enums.ParameterMarkerType;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
+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;
@@ -118,4 +120,13 @@ public final class ExpressionExtractUtilTest {
List<ParameterMarkerExpressionSegment> result = ExpressionExtractUtil.getParameterMarkerExpressions(Collections.singletonList(functionSegment));
assertThat(result.size(), is(1));
}
+
+ @Test
+ public void assertGetParameterMarkerExpressionsFromTypeCastExpression() {
+ ParameterMarkerExpressionSegment expected = new ParameterMarkerExpressionSegment(0, 0, 1, ParameterMarkerType.DOLLAR);
+ List<ExpressionSegment> input = Collections.singletonList(new TypeCastExpression(0, 0, expected, "varchar"));
+ List<ParameterMarkerExpressionSegment> actual = ExpressionExtractUtil.getParameterMarkerExpressions(input);
+ assertThat(actual.size(), is(1));
+ assertThat(actual.get(0), is(expected));
+ }
}
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 ba87f1d9740..270180c1753 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
@@ -30,6 +30,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.Function
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.NotExpression;
+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.complex.ComplexExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
@@ -55,6 +56,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.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;
+import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedTypeCastExpression;
import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.complex.ExpectedCommonExpression;
import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.simple.ExpectedLiteralExpression;
import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.simple.ExpectedParameterMarkerExpression;
@@ -349,13 +351,22 @@ public final class ExpressionAssert {
assertExpression(assertContext, actual.getElseExpr(), expected.getElseExpr());
}
+ private static void assertTypeCastExpression(final SQLCaseAssertContext assertContext, final TypeCastExpression actual, final ExpectedTypeCastExpression expected) {
+ if (null == expected) {
+ assertNull(assertContext.getText("Type cast expression should not exist."), actual);
+ return;
+ }
+ assertNotNull(assertContext.getText("Type cast expression is expected."), actual);
+ assertThat(assertContext.getText("Actual data type is different with expected in type case expression."), actual.getDataType(), is(expected.getDataType()));
+ assertExpression(assertContext, actual.getExpression(), expected.getExpression());
+ }
+
/**
* Assert expression by actual expression segment class type.
*
* @param assertContext assert context
* @param actual actual expression segment
* @param expected expected expression
- *
* @throws UnsupportedOperationException When expression segment class type is not supported.
*/
public static void assertExpression(final SQLCaseAssertContext assertContext,
@@ -399,6 +410,8 @@ public final class ExpressionAssert {
assertCollateExpression(assertContext, (CollateExpression) actual, expected.getCollateExpression());
} else if (actual instanceof CaseWhenExpression) {
assertCaseWhenExpression(assertContext, (CaseWhenExpression) actual, expected.getCaseWhenExpression());
+ } else if (actual instanceof TypeCastExpression) {
+ assertTypeCastExpression(assertContext, (TypeCastExpression) actual, expected.getTypeCastExpression());
} 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 67ffaf19253..a5fa04ed7be 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
@@ -89,4 +89,7 @@ public final class ExpectedExpression extends AbstractExpectedSQLSegment {
@XmlElement(name = "case-when-expression")
private ExpectedCaseWhenExpression caseWhenExpression;
+
+ @XmlElement(name = "type-cast-expression")
+ private ExpectedTypeCastExpression typeCastExpression;
}
diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedTypeCastExpression.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedTypeCastExpression.java
new file mode 100644
index 00000000000..693aec32b89
--- /dev/null
+++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedTypeCastExpression.java
@@ -0,0 +1,37 @@
+/*
+ * 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 lombok.Setter;
+import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * Expected type cast expression.
+ */
+@Getter
+@Setter
+public final class ExpectedTypeCastExpression extends AbstractExpectedSQLSegment {
+
+ private ExpectedExpression expression;
+
+ @XmlElement(name = "data-type")
+ private String dataType;
+}
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 595b7f6c9d9..a63b6eff049 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
@@ -188,7 +188,12 @@
<expr>
<function function-name="EXTRACT" start-index="7" stop-index="56" text="EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40')">
<parameter>
- <literal-expression value="2001-02-16 20:38:40" start-index="25" stop-index="55" />
+ <type-cast-expression>
+ <expression>
+ <literal-expression value="2001-02-16 20:38:40" start-index="35" stop-index="55" />
+ </expression>
+ <data-type>TIMESTAMP</data-type>
+ </type-cast-expression>
</parameter>
</function>
</expr>
diff --git a/test/it/parser/src/main/resources/case/dml/select.xml b/test/it/parser/src/main/resources/case/dml/select.xml
index 203ff12abc0..039ccd14135 100644
--- a/test/it/parser/src/main/resources/case/dml/select.xml
+++ b/test/it/parser/src/main/resources/case/dml/select.xml
@@ -1960,15 +1960,12 @@
</left>
<operator>=</operator>
<right>
- <binary-operation-expression start-index="35" stop-index="60">
- <left>
+ <type-cast-expression>
+ <expression>
<literal-expression value="{"rule2":"null2"}" start-index="35" stop-index="53" />
- </left>
- <operator>::</operator>
- <right>
- <common-expression text="jsonb" start-index="56" stop-index="60" />
- </right>
- </binary-operation-expression>
+ </expression>
+ <data-type>jsonb</data-type>
+ </type-cast-expression>
<parameter-marker-expression parameter-index="0" start-index="35" stop-index="42" />
</right>
</binary-operation-expression>
@@ -2047,27 +2044,21 @@
<right>
<list-expression start-index="36" stop-index="55" literal-stop-index="91">
<items>
- <binary-operation-expression start-index="37" stop-index="62">
- <left>
+ <type-cast-expression>
+ <expression>
<literal-expression value="{"rule2":"null2"}" start-index="37" stop-index="55" />
- </left>
- <operator>::</operator>
- <right>
- <common-expression text="jsonb" start-index="58" stop-index="62" />
- </right>
- </binary-operation-expression>
+ </expression>
+ <data-type>jsonb</data-type>
+ </type-cast-expression>
<parameter-marker-expression parameter-index="0" start-index="37" stop-index="44" />
</items>
<items>
- <binary-operation-expression start-index="65" stop-index="90">
- <left>
+ <type-cast-expression>
+ <expression>
<literal-expression value="{"rule3":"null3"}" start-index="65" stop-index="83" />
- </left>
- <operator>::</operator>
- <right>
- <common-expression text="jsonb" start-index="86" stop-index="90" />
- </right>
- </binary-operation-expression>
+ </expression>
+ <data-type>jsonb</data-type>
+ </type-cast-expression>
<parameter-marker-expression parameter-index="1" start-index="47" stop-index="54" />
</items>
</list-expression>
@@ -2145,26 +2136,20 @@
</left>
<between-expr>
<parameter-marker-expression parameter-index="0" start-index="41" stop-index="48" />
- <binary-operation-expression start-index="41" stop-index="66">
- <left>
+ <type-cast-expression>
+ <expression>
<literal-expression value="{"rule2":"null2"}" start-index="41" stop-index="59" />
- </left>
- <operator>::</operator>
- <right>
- <common-expression text="jsonb" start-index="62" stop-index="66" />
- </right>
- </binary-operation-expression>
+ </expression>
+ <data-type>jsonb</data-type>
+ </type-cast-expression>
</between-expr>
<and-expr>
- <binary-operation-expression start-index="72" stop-index="97">
- <left>
+ <type-cast-expression>
+ <expression>
<literal-expression value="{"rule3":"null3"}" start-index="72" stop-index="90" />
- </left>
- <operator>::</operator>
- <right>
- <common-expression text="jsonb" start-index="93" stop-index="97" />
- </right>
- </binary-operation-expression>
+ </expression>
+ <data-type>jsonb</data-type>
+ </type-cast-expression>
<parameter-marker-expression parameter-index="1" start-index="54" stop-index="61" />
</and-expr>
</between-expression>
@@ -4845,15 +4830,14 @@
<select sql-case-id="select_literal_type_cast_money">
<projections start-index="7" stop-index="18">
<expression-projection text="'$99'::money" start-index="7" stop-index="18">
- <binary-operation-expression start-index="7" stop-index="18">
- <left>
- <literal-expression value="$99" start-index="7" stop-index="11" />
- </left>
- <operator>::</operator>
- <right>
- <common-expression text="money" start-index="14" stop-index="18" />
- </right>
- </binary-operation-expression>
+ <expr>
+ <type-cast-expression>
+ <expression>
+ <literal-expression value="$99" start-index="7" stop-index="11" />
+ </expression>
+ <data-type>money</data-type>
+ </type-cast-expression>
+ </expr>
</expression-projection>
</projections>
</select>
@@ -4861,27 +4845,74 @@
<select sql-case-id="select_positional_parameter_type_cast_money" parameters="123.00">
<projections start-index="7" stop-index="15">
<expression-projection text="$1::money" start-index="7" stop-index="15">
- <binary-operation-expression start-index="7" stop-index="15">
- <left>
- <parameter-marker-expression parameter-index="1" start-index="7" stop-index="8" />
- </left>
- <operator>::</operator>
- <right>
- <common-expression text="money" start-index="11" stop-index="15" />
- </right>
- </binary-operation-expression>
+ <expr>
+ <type-cast-expression>
+ <expression>
+ <parameter-marker-expression parameter-index="0" start-index="7" stop-index="8" />
+ </expression>
+ <data-type>money</data-type>
+ </type-cast-expression>
+ </expr>
</expression-projection>
</projections>
</select>
<select sql-case-id="select_string_constant_type_cast">
<projections start-index="7" stop-index="25">
- <!-- TODO Fix this case after supported string const type cast syntax-->
<expression-projection text="int4 '1'" start-index="7" stop-index="14">
- <literal-expression value="1" start-index="7" stop-index="14" />
+ <expr>
+ <type-cast-expression>
+ <expression>
+ <literal-expression value="1" start-index="12" stop-index="14" />
+ </expression>
+ <data-type>int4</data-type>
+ </type-cast-expression>
+ </expr>
</expression-projection>
<expression-projection text="money '2'" start-index="17" stop-index="25">
- <literal-expression value="2" start-index="17" stop-index="25" />
+ <expr>
+ <type-cast-expression>
+ <expression>
+ <literal-expression value="2" start-index="23" stop-index="25" />
+ </expression>
+ <data-type>money</data-type>
+ </type-cast-expression>
+ </expr>
+ </expression-projection>
+ </projections>
+ </select>
+
+ <select sql-case-id="select_constant_with_nested_type_cast">
+ <projections start-index="7" stop-index="60">
+ <expression-projection text="CAST(MONEY '1' AS VARCHAR)::CHAR(10)::VARCHAR::CHAR(4)" start-index="7" stop-index="60">
+ <expr>
+ <type-cast-expression>
+ <expression>
+ <type-cast-expression>
+ <expression>
+ <type-cast-expression>
+ <expression>
+ <type-cast-expression>
+ <expression>
+ <type-cast-expression>
+ <expression>
+ <literal-expression value="1" start-index="18" stop-index="20" />
+ </expression>
+ <data-type>MONEY</data-type>
+ </type-cast-expression>
+ </expression>
+ <data-type>VARCHAR</data-type>
+ </type-cast-expression>
+ </expression>
+ <data-type>CHAR(10)</data-type>
+ </type-cast-expression>
+ </expression>
+ <data-type>VARCHAR</data-type>
+ </type-cast-expression>
+ </expression>
+ <data-type>CHAR(4)</data-type>
+ </type-cast-expression>
+ </expr>
</expression-projection>
</projections>
</select>
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/select.xml b/test/it/parser/src/main/resources/sql/supported/dml/select.xml
index 2fd1b55d9d0..973fcf2b9bf 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/select.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/select.xml
@@ -159,4 +159,5 @@
<sql-case id="select_literal_type_cast_money" value="SELECT '$99'::money" db-types="PostgreSQL,openGauss" />
<sql-case id="select_positional_parameter_type_cast_money" value="SELECT $1::money" db-types="PostgreSQL,openGauss" case-types="Placeholder" />
<sql-case id="select_string_constant_type_cast" value="SELECT int4 '1', money '2'" db-types="PostgreSQL,openGauss" />
+ <sql-case id="select_constant_with_nested_type_cast" value="SELECT CAST(MONEY '1' AS VARCHAR)::CHAR(10)::VARCHAR::CHAR(4)" db-types="PostgreSQL,openGauss" />
</sql-cases>