From 14af30f58ce6d87ec4695a510c012ae02e292fb4 Mon Sep 17 00:00:00 2001 From: rui-mo Date: Wed, 18 Oct 2023 14:50:50 +0800 Subject: [PATCH] Support dayofmonth function in spark sql (7115) --- velox/functions/sparksql/DateTimeFunctions.h | 23 +++++++++++++++++ velox/functions/sparksql/Register.cpp | 4 +-- .../sparksql/tests/DateTimeFunctionsTest.cpp | 25 ++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/velox/functions/sparksql/DateTimeFunctions.h b/velox/functions/sparksql/DateTimeFunctions.h index 0b6a24fa57ac..032fa402cfe3 100644 --- a/velox/functions/sparksql/DateTimeFunctions.h +++ b/velox/functions/sparksql/DateTimeFunctions.h @@ -427,4 +427,27 @@ struct MonthFunction : public InitSessionTimezone, } }; +template +struct DayFunction : public InitSessionTimezone, + public TimestampWithTimezoneSupport { + VELOX_DEFINE_FUNCTION_TYPES(T); + + FOLLY_ALWAYS_INLINE void call( + int32_t& result, + const arg_type& timestamp) { + result = getDateTime(timestamp, this->timeZone_).tm_mday; + } + + FOLLY_ALWAYS_INLINE void call(int32_t& result, const arg_type& date) { + result = getDateTime(date).tm_mday; + } + + FOLLY_ALWAYS_INLINE void call( + int32_t& result, + const arg_type& timestampWithTimezone) { + auto timestamp = this->toTimestamp(timestampWithTimezone); + result = getDateTime(timestamp, nullptr).tm_mday; + } +}; + } // namespace facebook::velox::functions::sparksql diff --git a/velox/functions/sparksql/Register.cpp b/velox/functions/sparksql/Register.cpp index acb2ec2a65ea..223aca5045c7 100644 --- a/velox/functions/sparksql/Register.cpp +++ b/velox/functions/sparksql/Register.cpp @@ -275,9 +275,9 @@ void registerFunctions(const std::string& prefix) { registerFunction({prefix + "date_add"}); registerFunction({prefix + "date_sub"}); - registerFunction( + registerFunction( {prefix + "day", prefix + "dayofmonth"}); - registerFunction( + registerFunction( {prefix + "day", prefix + "dayofmonth"}); registerFunction( {prefix + "doy", prefix + "dayofyear"}); diff --git a/velox/functions/sparksql/tests/DateTimeFunctionsTest.cpp b/velox/functions/sparksql/tests/DateTimeFunctionsTest.cpp index 2d563b1bc579..45de8fd65fae 100644 --- a/velox/functions/sparksql/tests/DateTimeFunctionsTest.cpp +++ b/velox/functions/sparksql/tests/DateTimeFunctionsTest.cpp @@ -301,13 +301,36 @@ TEST_F(DateTimeFunctionsTest, dayOfYear) { TEST_F(DateTimeFunctionsTest, dayOfMonth) { const auto day = [&](std::optional date) { - return evaluateOnce("dayofmonth(c0)", {date}, {DATE()}); + return evaluateOnce("dayofmonth(c0)", {date}, {DATE()}); }; EXPECT_EQ(std::nullopt, day(std::nullopt)); EXPECT_EQ(30, day(parseDate("2009-07-30"))); EXPECT_EQ(23, day(parseDate("2023-08-23"))); } +TEST_F(DateTimeFunctionsTest, dayOfMonthTimestamp) { + const auto day = [&](std::optional date) { + return evaluateOnce("dayofmonth(c0)", date); + }; + EXPECT_EQ(std::nullopt, day(std::nullopt)); + EXPECT_EQ(1, day(Timestamp(0, 0))); + EXPECT_EQ(31, day(Timestamp(-1, 9000))); + EXPECT_EQ(30, day(Timestamp(1632989700, 0))); + EXPECT_EQ(1, day(Timestamp(1633076100, 0))); + EXPECT_EQ(6, day(Timestamp(1633508100, 0))); + EXPECT_EQ(31, day(Timestamp(1635668100, 0))); + + setQueryTimeZone("Pacific/Apia"); + + EXPECT_EQ(std::nullopt, day(std::nullopt)); + EXPECT_EQ(31, day(Timestamp(0, 0))); + EXPECT_EQ(31, day(Timestamp(-1, 9000))); + EXPECT_EQ(30, day(Timestamp(1632989700, 0))); + EXPECT_EQ(1, day(Timestamp(1633076100, 0))); + EXPECT_EQ(6, day(Timestamp(1633508100, 0))); + EXPECT_EQ(31, day(Timestamp(1635668100, 0))); +} + TEST_F(DateTimeFunctionsTest, dayOfWeekDate) { const auto dayOfWeek = [&](std::optional date, const std::string& func) {