diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/scalar/ConstantOperator.java b/fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/scalar/ConstantOperator.java index 2c2004c1d3f8fc..8ac33fa7c1b5bf 100644 --- a/fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/scalar/ConstantOperator.java +++ b/fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/scalar/ConstantOperator.java @@ -35,6 +35,7 @@ import java.text.DecimalFormat; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Objects; @@ -373,6 +374,11 @@ public String toString() { } else if (type.isDate()) { LocalDateTime time = (LocalDateTime) Optional.ofNullable(value).orElse(LocalDateTime.MIN); return time.format(DateUtils.DATE_FORMATTER_UNIX); + } else if (type.isTime()) { + // Time is a double value but we only need int when casting to datetime + if (value instanceof Double) { + return String.valueOf(((Double) value).intValue()); + } } else if (type.isFloatingPointType()) { double val = (double) Optional.ofNullable(value).orElse((double) 0); BigDecimal decimal = BigDecimal.valueOf(val); @@ -499,8 +505,8 @@ public Optional castToStrictly(Type type) { } public Optional castTo(Type desc) { - if (type.isTime() || desc.isTime()) { - // Don't support constant time cast in FE + if ((type.isTime() || desc.isTime()) && !(type.isTime() && desc.isDatetime())) { + // Don't support constant time cast to types other than datetime in FE return Optional.empty(); } @@ -558,12 +564,25 @@ public Optional castTo(Type desc) { } res = ConstantOperator.createDouble(Double.parseDouble(childString)); } else if (desc.isDate() || desc.isDatetime()) { - String dateStr = StringUtils.strip(childString, "\r\n\t "); - LocalDateTime dateTime = DateUtils.parseStrictDateTime(dateStr); - if (Type.DATE.equals(desc)) { - dateTime = dateTime.truncatedTo(ChronoUnit.DAYS); + if (type.isTime()) { + // Cast time to datetime + String timeStr = StringUtils.strip(childString, "\r\n\t "); + int time = Integer.parseInt(timeStr); + int hours = time / 3600; + int minutes = (time % 3600) / 60; + int seconds = time % 60; + LocalDate date = LocalDate.now(); + LocalTime localTime = LocalTime.of(hours, minutes, seconds); + LocalDateTime dateTime = LocalDateTime.of(date, localTime); + res = ConstantOperator.createDatetime(dateTime, desc); + } else { + String dateStr = StringUtils.strip(childString, "\r\n\t "); + LocalDateTime dateTime = DateUtils.parseStrictDateTime(dateStr); + if (Type.DATE.equals(desc)) { + dateTime = dateTime.truncatedTo(ChronoUnit.DAYS); + } + res = ConstantOperator.createDatetime(dateTime, desc); } - res = ConstantOperator.createDatetime(dateTime, desc); } else if (desc.isDecimalV2()) { res = ConstantOperator.createDecimal(BigDecimal.valueOf(Double.parseDouble(childString)), Type.DECIMALV2); } else if (desc.isDecimalV3()) { diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/ScalarOperatorFunctions.java b/fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/ScalarOperatorFunctions.java index 673f2ae0bc5b3d..abdc189b0ed24b 100644 --- a/fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/ScalarOperatorFunctions.java +++ b/fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/ScalarOperatorFunctions.java @@ -702,6 +702,18 @@ public static ConstantOperator fromUnixTime(ConstantOperator unixTime, ConstantO return dateFormat(dl, fmtLiteral); } + @ConstantFunction.List(list = { + @ConstantFunction(name = "curtime", argTypes = {}, returnType = TIME), + @ConstantFunction(name = "current_time", argTypes = {}, returnType = TIME) + }) + public static ConstantOperator curTime() { + ConnectContext connectContext = ConnectContext.get(); + LocalDateTime startTime = Instant.ofEpochMilli(connectContext.getStartTime() / 1000 * 1000) + .atZone(TimeUtils.getTimeZone().toZoneId()).toLocalDateTime(); + double second = startTime.getHour() * 3600D + startTime.getMinute() * 60D + startTime.getSecond(); + return ConstantOperator.createTime(second); + } + @ConstantFunction.List(list = { @ConstantFunction(name = "now", argTypes = {}, returnType = DATETIME), @ConstantFunction(name = "current_timestamp", argTypes = {}, returnType = DATETIME), diff --git a/fe/fe-core/src/test/java/com/starrocks/sql/optimizer/operator/operator/ConstantOperatorTest.java b/fe/fe-core/src/test/java/com/starrocks/sql/optimizer/operator/operator/ConstantOperatorTest.java index 5072d3e4f70fda..ed70221dd3c42a 100644 --- a/fe/fe-core/src/test/java/com/starrocks/sql/optimizer/operator/operator/ConstantOperatorTest.java +++ b/fe/fe-core/src/test/java/com/starrocks/sql/optimizer/operator/operator/ConstantOperatorTest.java @@ -62,7 +62,7 @@ public void testCastToDateValid() throws Exception { } @Test - public void testCaseToDateInvalid() { + public void testCastToDateInvalid() { String[] testCases = { // Invalid year. "20190-05-31", @@ -110,7 +110,7 @@ public void testCaseToDateInvalid() { } @Test - public void testCaseDateToNumber() throws Exception { + public void testCastDateToNumber() throws Exception { ConstantOperator date = ConstantOperator.createDate(LocalDateTime.of(2023, 01, 01, 0, 0)); ConstantOperator datetime = ConstantOperator.createDatetime(LocalDateTime.of(2023, 01, 01, 0, 0, 0)); @@ -142,6 +142,14 @@ public void testCaseDateToNumber() throws Exception { Assert.assertEquals(datetimeDoubleNumber, datetime.castTo(Type.DOUBLE).get()); } + @Test + public void testCastTimeToDateTime() { + LocalDateTime now = LocalDateTime.now().withNano(0); + ConstantOperator time = ConstantOperator.createTime(now.getHour() * 3600D + now.getMinute() * 60D + now.getSecond()); + ConstantOperator datetime = ConstantOperator.createDatetime(now); + Assert.assertEquals(datetime, time.castTo(Type.DATETIME).get()); + } + @Test public void testDistance() { { diff --git a/fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rewrite/ScalarOperatorFunctionsTest.java b/fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rewrite/ScalarOperatorFunctionsTest.java index 01b5251983c607..fa011f8200d591 100644 --- a/fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rewrite/ScalarOperatorFunctionsTest.java +++ b/fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rewrite/ScalarOperatorFunctionsTest.java @@ -1373,6 +1373,8 @@ public void testNow() { LocalDateTime expected = Instant.ofEpochMilli(ctx.getStartTime() / 1000 * 1000) .atZone(TimeUtils.getTimeZone().toZoneId()).toLocalDateTime(); assertEquals(expected, ScalarOperatorFunctions.now().getDatetime()); + double expectedTime = expected.getHour() * 3600D + expected.getMinute() * 60D + expected.getSecond(); + assertEquals(expectedTime, ScalarOperatorFunctions.curTime().getTime(), 0.1); } @Test