From 7cc0f932dc6c806c333504026978747071682159 Mon Sep 17 00:00:00 2001 From: waterWang Date: Fri, 7 Aug 2026 00:23:01 +0800 Subject: [PATCH] fix: correct WEEK interval literal duration in calciteLiteralToDruidLiteral (#18665) Calcite has a known quirk where WEEK interval literals are stored as 1 hour in the INTERVAL_DAY_TIME family. This causes `INTERVAL 1 WEEK` to resolve to PT1H (1 hour) instead of P7D (7 days). Detect the WEEK qualifier in the SqlIntervalQualifier and convert the millisecond value to 7 days (multiply by 7 * 24). --- .../druid/sql/calcite/expression/Expressions.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/expression/Expressions.java b/sql/src/main/java/org/apache/druid/sql/calcite/expression/Expressions.java index 1b28b02c701d..811da94f4030 100644 --- a/sql/src/main/java/org/apache/druid/sql/calcite/expression/Expressions.java +++ b/sql/src/main/java/org/apache/druid/sql/calcite/expression/Expressions.java @@ -33,7 +33,9 @@ import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.type.SqlTypeFamily; +import org.apache.calcite.avatica.util.TimeUnit; import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.calcite.sql.SqlIntervalQualifier; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.ISE; import org.apache.druid.java.util.common.StringUtils; @@ -371,7 +373,14 @@ public static DruidLiteral calciteLiteralToDruidLiteral( retVal = new DruidLiteral(ExpressionType.DOUBLE, number == null ? null : number.doubleValue()); } else if (SqlTypeFamily.INTERVAL_DAY_TIME == sqlTypeName.getFamily()) { // Calcite represents DAY-TIME intervals in milliseconds. - final long milliseconds = ((Number) RexLiteral.value(rexNode)).longValue(); + long milliseconds = ((Number) RexLiteral.value(rexNode)).longValue(); + // Calcite has a known quirk where WEEK interval literals are stored as 1 hour in the + // INTERVAL_DAY_TIME family (see https://github.com/apache/druid/issues/18665). + // Detect the WEEK qualifier and convert the value to 7 days. + final SqlIntervalQualifier intervalQualifier = rexNode.getType().getIntervalQualifier(); + if (intervalQualifier != null && intervalQualifier.getStartUnit() == TimeUnit.WEEK) { + milliseconds = milliseconds * 7 * 24; + } retVal = new DruidLiteral(ExpressionType.LONG, milliseconds); } else if (SqlTypeFamily.INTERVAL_YEAR_MONTH == sqlTypeName.getFamily()) { // Calcite represents YEAR-MONTH intervals in months.