From 20a7a8c1266982098d6c012175f5b3ed5c22503f Mon Sep 17 00:00:00 2001 From: rui-mo Date: Wed, 18 Oct 2023 14:48:56 +0800 Subject: [PATCH] Add month function support in spark sql (7114) --- velox/functions/sparksql/DateTimeFunctions.h | 27 ++++++++++++++ velox/functions/sparksql/Register.cpp | 2 ++ .../sparksql/tests/DateTimeFunctionsTest.cpp | 36 +++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/velox/functions/sparksql/DateTimeFunctions.h b/velox/functions/sparksql/DateTimeFunctions.h index 2030416b40f9..0b6a24fa57ac 100644 --- a/velox/functions/sparksql/DateTimeFunctions.h +++ b/velox/functions/sparksql/DateTimeFunctions.h @@ -400,4 +400,31 @@ struct QuarterFunction : public InitSessionTimezone, } }; +template +struct MonthFunction : public InitSessionTimezone, + public TimestampWithTimezoneSupport { + VELOX_DEFINE_FUNCTION_TYPES(T); + + FOLLY_ALWAYS_INLINE int32_t getMonth(const std::tm& time) { + return 1 + time.tm_mon; + } + + FOLLY_ALWAYS_INLINE void call( + int32_t& result, + const arg_type& timestamp) { + result = getMonth(getDateTime(timestamp, this->timeZone_)); + } + + FOLLY_ALWAYS_INLINE void call(int32_t& result, const arg_type& date) { + result = getMonth(getDateTime(date)); + } + + FOLLY_ALWAYS_INLINE void call( + int32_t& result, + const arg_type& timestampWithTimezone) { + auto timestamp = this->toTimestamp(timestampWithTimezone); + result = getMonth(getDateTime(timestamp, nullptr)); + } +}; + } // namespace facebook::velox::functions::sparksql diff --git a/velox/functions/sparksql/Register.cpp b/velox/functions/sparksql/Register.cpp index a1ffe74fda29..acb2ec2a65ea 100644 --- a/velox/functions/sparksql/Register.cpp +++ b/velox/functions/sparksql/Register.cpp @@ -291,6 +291,8 @@ void registerFunctions(const std::string& prefix) { registerFunction({prefix + "quarter"}); registerFunction({prefix + "quarter"}); + registerFunction({prefix + "month"}); + registerFunction({prefix + "month"}); // Register bloom filter function registerFunction( diff --git a/velox/functions/sparksql/tests/DateTimeFunctionsTest.cpp b/velox/functions/sparksql/tests/DateTimeFunctionsTest.cpp index 17f8df2e3f5d..2d563b1bc579 100644 --- a/velox/functions/sparksql/tests/DateTimeFunctionsTest.cpp +++ b/velox/functions/sparksql/tests/DateTimeFunctionsTest.cpp @@ -469,5 +469,41 @@ TEST_F(DateTimeFunctionsTest, quarterDate) { EXPECT_EQ(1, quarter(-18262)); } +TEST_F(DateTimeFunctionsTest, month) { + const auto month = [&](std::optional date) { + return evaluateOnce("month(c0)", date); + }; + EXPECT_EQ(std::nullopt, month(std::nullopt)); + EXPECT_EQ(1, month(Timestamp(0, 0))); + EXPECT_EQ(12, month(Timestamp(-1, 9000))); + EXPECT_EQ(10, month(Timestamp(4000000000, 0))); + EXPECT_EQ(10, month(Timestamp(4000000000, 123000000))); + EXPECT_EQ(8, month(Timestamp(998474645, 321000000))); + EXPECT_EQ(8, month(Timestamp(998423705, 321000000))); + + setQueryTimeZone("Pacific/Apia"); + + EXPECT_EQ(std::nullopt, month(std::nullopt)); + EXPECT_EQ(12, month(Timestamp(0, 0))); + EXPECT_EQ(12, month(Timestamp(-1, Timestamp::kMaxNanos))); + EXPECT_EQ(10, month(Timestamp(4000000000, 0))); + EXPECT_EQ(10, month(Timestamp(4000000000, 123000000))); + EXPECT_EQ(8, month(Timestamp(998474645, 321000000))); + EXPECT_EQ(8, month(Timestamp(998423705, 321000000))); +} + +TEST_F(DateTimeFunctionsTest, monthDate) { + const auto month = [&](std::optional date) { + return evaluateOnce("month(c0)", {date}, {DATE()}); + }; + EXPECT_EQ(std::nullopt, month(std::nullopt)); + EXPECT_EQ(1, month(0)); + EXPECT_EQ(12, month(-1)); + EXPECT_EQ(11, month(-40)); + EXPECT_EQ(2, month(40)); + EXPECT_EQ(1, month(18262)); + EXPECT_EQ(1, month(-18262)); +} + } // namespace } // namespace facebook::velox::functions::sparksql::test