This is an automated email from the ASF dual-hosted git repository.
chengzhang 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 fce5ac2a2f4 Refactor LiteralExpressionConverter and
SQLFederationEngine (#37146)
fce5ac2a2f4 is described below
commit fce5ac2a2f4201699dcbe5c8cbc23da066030e56
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Thu Nov 20 16:52:59 2025 +0800
Refactor LiteralExpressionConverter and SQLFederationEngine (#37146)
---
.../impl/LiteralExpressionConverter.java | 35 +++++++++++++++++---
.../sqlfederation/engine/SQLFederationEngine.java | 14 +++++++-
.../visitor/statement/MySQLStatementVisitor.java | 12 +++++--
.../sql/parser/statement/core/util/SQLUtils.java | 4 +++
.../value/literal/impl/TemporalLiteralValue.java | 37 ++++++++++++++++++++++
.../parser/src/main/resources/case/dml/select.xml | 8 ++---
6 files changed, 98 insertions(+), 12 deletions(-)
diff --git
a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/impl/LiteralExpressionConverter.java
b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/impl/LiteralExpressionConverter.java
index 1a7621455d8..c52aac27f5c 100644
---
a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/impl/LiteralExpressionConverter.java
+++
b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/impl/LiteralExpressionConverter.java
@@ -35,6 +35,8 @@ import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simp
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.sql.Time;
+import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
@@ -94,22 +96,22 @@ public final class LiteralExpressionConverter {
return
Optional.of(SqlLiteral.createBoolean(Boolean.parseBoolean(literalValue),
SqlParserPos.ZERO));
}
if (segment.getLiterals() instanceof Calendar) {
- return
Optional.of(SqlLiteral.createDate(DateString.fromCalendarFields((Calendar)
segment.getLiterals()), SqlParserPos.ZERO));
+ return convertCalendar(segment);
}
if (segment.getLiterals() instanceof Date) {
- return Optional.of(SqlLiteral.createDate(new
DateString(literalValue), SqlParserPos.ZERO));
+ return convertDate(segment, literalValue);
}
if (segment.getLiterals() instanceof LocalDate) {
return
Optional.of(SqlLiteral.createDate(DateString.fromDaysSinceEpoch((int)
((LocalDate) segment.getLiterals()).toEpochDay()), SqlParserPos.ZERO));
}
if (segment.getLiterals() instanceof LocalTime) {
- return Optional.of(SqlLiteral.createTime(new
TimeString(literalValue), 0, SqlParserPos.ZERO));
+ return Optional.of(SqlLiteral.createTime(new
TimeString(literalValue), 1, SqlParserPos.ZERO));
}
if (segment.getLiterals() instanceof LocalDateTime) {
- return
Optional.of(SqlLiteral.createTimestamp(SqlTypeName.TIMESTAMP, new
TimestampString(literalValue), 0, SqlParserPos.ZERO));
+ return
Optional.of(SqlLiteral.createTimestamp(SqlTypeName.TIMESTAMP, new
TimestampString(literalValue), 1, SqlParserPos.ZERO));
}
if (segment.getLiterals() instanceof ZonedDateTime) {
- return Optional.of(SqlLiteral.createTimestamp(new
TimestampWithTimeZoneString(literalValue), 0, SqlParserPos.ZERO));
+ return Optional.of(SqlLiteral.createTimestamp(new
TimestampWithTimeZoneString(literalValue), 1, SqlParserPos.ZERO));
}
if (segment.getLiterals() instanceof byte[]) {
return Optional.of(SqlLiteral.createBinaryString((byte[])
segment.getLiterals(), SqlParserPos.ZERO));
@@ -126,4 +128,27 @@ public final class LiteralExpressionConverter {
}
return Optional.of(SqlLiteral.createExactNumeric(literalValue,
SqlParserPos.ZERO));
}
+
+ private static Optional<SqlNode> convertCalendar(final
LiteralExpressionSegment segment) {
+ Calendar calendar = (Calendar) segment.getLiterals();
+ if (hasTimePart(calendar)) {
+ return
Optional.of(SqlLiteral.createTimestamp(SqlTypeName.TIMESTAMP,
TimestampString.fromCalendarFields(calendar), 1, SqlParserPos.ZERO));
+ }
+ return
Optional.of(SqlLiteral.createDate(DateString.fromCalendarFields(calendar),
SqlParserPos.ZERO));
+ }
+
+ private static boolean hasTimePart(final Calendar calendar) {
+ return 0 != calendar.get(Calendar.HOUR_OF_DAY) || 0 !=
calendar.get(Calendar.MINUTE) || 0 != calendar.get(Calendar.SECOND) || 0 !=
calendar.get(Calendar.MILLISECOND);
+ }
+
+ private static Optional<SqlNode> convertDate(final
LiteralExpressionSegment segment, final String literalValue) {
+ if (segment.getLiterals() instanceof Timestamp) {
+ Timestamp timestamp = (Timestamp) segment.getLiterals();
+ return
Optional.of(SqlLiteral.createTimestamp(SqlTypeName.TIMESTAMP,
TimestampString.fromMillisSinceEpoch(timestamp.getTime()), 1,
SqlParserPos.ZERO));
+ }
+ if (segment.getLiterals() instanceof Time) {
+ return Optional.of(SqlLiteral.createTime(new
TimeString(literalValue), 1, SqlParserPos.ZERO));
+ }
+ return Optional.of(SqlLiteral.createDate(new DateString(literalValue),
SqlParserPos.ZERO));
+ }
}
diff --git
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/engine/SQLFederationEngine.java
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/engine/SQLFederationEngine.java
index ba9261c1215..80fe65cdac4 100644
---
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/engine/SQLFederationEngine.java
+++
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/engine/SQLFederationEngine.java
@@ -70,6 +70,7 @@ import
org.apache.shardingsphere.sqlfederation.spi.SQLFederationDecider;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -87,6 +88,8 @@ import java.util.Optional;
@Getter
public final class SQLFederationEngine implements AutoCloseable {
+ private static final Collection<Class<?>> NEED_THROW_EXCEPTION_TYPES =
Arrays.asList(SQLExecutionInterruptedException.class,
SQLIntegrityConstraintViolationException.class);
+
private final ProcessEngine processEngine = new ProcessEngine();
@SuppressWarnings("rawtypes")
@@ -206,13 +209,22 @@ public final class SQLFederationEngine implements
AutoCloseable {
// CHECKSTYLE:ON
log.error("SQL Federation execute failed, sql {}, parameters {}",
queryContext.getSql(), queryContext.getParameters(), ex);
closeResources(federationContext);
- if (ex instanceof SQLExecutionInterruptedException) {
+ if (isNeedThrowException(ex)) {
throw ex;
}
throw new
SQLFederationUnsupportedSQLException(queryContext.getSql(), ex);
}
}
+ private boolean isNeedThrowException(final Exception ex) {
+ for (Class<?> each : NEED_THROW_EXCEPTION_TYPES) {
+ if (each.isAssignableFrom(ex.getClass())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void closeResources(final SQLFederationContext federationContext) {
try {
processEngine.completeSQLExecution(federationContext.getProcessId());
diff --git
a/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/MySQLStatementVisitor.java
b/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/MySQLStatementVisitor.java
index eb96493cf99..68d4d3b108b 100644
---
a/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/MySQLStatementVisitor.java
+++
b/parser/sql/engine/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/engine/mysql/visitor/statement/MySQLStatementVisitor.java
@@ -249,6 +249,7 @@ import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.Nu
import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.NumberLiteralValue;
import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.OtherLiteralValue;
import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.StringLiteralValue;
+import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.TemporalLiteralValue;
import
org.apache.shardingsphere.sql.parser.statement.core.value.parametermarker.ParameterMarkerValue;
import java.math.BigDecimal;
@@ -321,8 +322,15 @@ public abstract class MySQLStatementVisitor extends
MySQLStatementBaseVisitor<AS
@Override
public ASTNode visitTemporalLiterals(final TemporalLiteralsContext ctx) {
- // TODO deal with TemporalLiterals
- return new OtherLiteralValue(ctx.getText());
+ String temporalType;
+ if (null != ctx.DATE()) {
+ temporalType = "DATE";
+ } else if (null != ctx.TIME()) {
+ temporalType = "TIME";
+ } else {
+ temporalType = "TIMESTAMP";
+ }
+ return new TemporalLiteralValue(temporalType,
ctx.textString().getText());
}
@Override
diff --git
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/util/SQLUtils.java
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/util/SQLUtils.java
index e64744749da..5007c24ca25 100644
---
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/util/SQLUtils.java
+++
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/util/SQLUtils.java
@@ -34,6 +34,7 @@ import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.Nu
import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.NumberLiteralValue;
import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.OtherLiteralValue;
import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.StringLiteralValue;
+import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.TemporalLiteralValue;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -242,6 +243,9 @@ public final class SQLUtils {
if (astNode instanceof NullLiteralValue) {
return new LiteralExpressionSegment(startIndex, stopIndex, null);
}
+ if (astNode instanceof TemporalLiteralValue) {
+ return new LiteralExpressionSegment(startIndex, stopIndex,
((TemporalLiteralValue) astNode).getValue());
+ }
if (astNode instanceof OtherLiteralValue) {
return new CommonExpressionSegment(startIndex, stopIndex,
((OtherLiteralValue) astNode).getValue());
}
diff --git
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/value/literal/impl/TemporalLiteralValue.java
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/value/literal/impl/TemporalLiteralValue.java
new file mode 100644
index 00000000000..a607d761ac7
--- /dev/null
+++
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/value/literal/impl/TemporalLiteralValue.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.sql.parser.statement.core.value.literal.impl;
+
+import lombok.Getter;
+import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.LiteralValue;
+
+/**
+ * Temporal literal value.
+ */
+@Getter
+public final class TemporalLiteralValue implements LiteralValue<Object> {
+
+ private final String temporalType;
+
+ private final String value;
+
+ public TemporalLiteralValue(final String temporalType, final String value)
{
+ this.temporalType = temporalType;
+ this.value = value.substring(1, value.length() - 1);
+ }
+}
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 b214dcd6eb2..8e9f03d0641 100644
--- a/test/it/parser/src/main/resources/case/dml/select.xml
+++ b/test/it/parser/src/main/resources/case/dml/select.xml
@@ -497,7 +497,7 @@
<expr>
<function start-index="7" stop-index="59"
text="CONVERT(TIMESTAMP "2004-01-22 21:45:33" USING latin1)"
function-name="CONVERT">
<parameter>
- <common-expression start-index="15"
stop-index="45" text="TIMESTAMP"2004-01-22 21:45:33"" />
+ <literal-expression value="2004-01-22 21:45:33"
start-index="15" stop-index="45" />
</parameter>
<parameter start-index="53" stop-index="58">
<literal-expression value="latin1"
start-index="53" stop-index="58"/>
@@ -514,7 +514,7 @@
<expr>
<function start-index="7" stop-index="57"
text="CONVERT(TIMESTAMP "2004-01-22 21:45:33", BINARY(4))"
function-name="CONVERT" >
<parameter>
- <common-expression start-index="15"
stop-index="45" text="TIMESTAMP"2004-01-22 21:45:33""
function-name="GROUPING(f1)" />
+ <literal-expression value="2004-01-22 21:45:33"
start-index="15" stop-index="45" />
</parameter>
<parameter start-index="48" stop-index="56">
<data-type value="BINARY" start-index="48"
stop-index="56"/>
@@ -531,7 +531,7 @@
<expr>
<function start-index="7" stop-index="55"
text="CONVERT(TIMESTAMP "2004-01-22 21:45:33", CHAR(4))"
function-name="CONVERT">
<parameter>
- <common-expression start-index="15"
stop-index="45" text="TIMESTAMP"2004-01-22 21:45:33"" />
+ <literal-expression value="2004-01-22 21:45:33"
start-index="15" stop-index="45" />
</parameter>
<parameter start-index="48" stop-index="54">
<data-type value="CHAR" start-index="48"
stop-index="54"/>
@@ -548,7 +548,7 @@
<expr>
<function start-index="7" stop-index="52"
text="CONVERT(TIMESTAMP "2004-01-22 21:45:33", CHAR)"
function-name="CONVERT">
<parameter>
- <common-expression start-index="15"
stop-index="45" text="TIMESTAMP"2004-01-22 21:45:33"" />
+ <literal-expression value="2004-01-22 21:45:33"
start-index="15" stop-index="45" />
</parameter>
<parameter start-index="48" stop-index="51">
<data-type value="CHAR" start-index="48"
stop-index="51"/>