Repository: incubator-impala
Updated Branches:
refs/heads/master 870839dc1 -> 4e7172f6f
IMPALA-2459: Implement next_day date/time UDF
Returns the date of the weekday that follows a particular date.
The weekday argument is a string literal indicating the day of the week.
Also this argument is case-insensitive. Available values are:
"Sunday"/"SUN", "Monday"/"MON", "Tuesday"/"TUE",
"Wednesday"/"WED", "Thursday"/"THU", "Friday"/"FRI", "Saturday"/"SAT".
For example, the first Saturday after Wednesday, 25 December 2013
is on 28 December 2013.
select next_day('2013-12-25','Saturday') returns '2013-12-28 00:00:00'
select next_day(to_timestamp('08-1987-21', 'MM-yyyy-dd'), 'FRIDAY')
returns '1987-08-28 00:00:00'
Change-Id: I2721d236c096639a9e7d2df8a45ca888c6b3e83e
Reviewed-on: http://gerrit.cloudera.org:8080/1943
Reviewed-by: Lars Volker <[email protected]>
Tested-by: Lars Volker <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/incubator-impala/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-impala/commit/4e7172f6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/4e7172f6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/4e7172f6
Branch: refs/heads/master
Commit: 4e7172f6f5bf8a836fbb0c495ce8bdefecc2d6e5
Parents: 870839d
Author: Hayabusa-intel <[email protected]>
Authored: Fri May 27 09:05:29 2016 -0400
Committer: Tim Armstrong <[email protected]>
Committed: Thu Jun 9 04:30:48 2016 -0700
----------------------------------------------------------------------
be/src/exprs/expr-test.cc | 79 +++++++++++++++++++++++
be/src/exprs/timestamp-functions-ir.cc | 32 +++++++++
be/src/exprs/timestamp-functions.h | 11 ++++
common/function-registry/impala_functions.py | 1 +
4 files changed, 123 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/4e7172f6/be/src/exprs/expr-test.cc
----------------------------------------------------------------------
diff --git a/be/src/exprs/expr-test.cc b/be/src/exprs/expr-test.cc
index 3c316e1..4147093 100644
--- a/be/src/exprs/expr-test.cc
+++ b/be/src/exprs/expr-test.cc
@@ -267,6 +267,80 @@ class ExprTest : public testing::Test {
return results;
}
+ void TestNextDayFunction(){
+ // Sequential test cases
+ TestTimestampValue("next_day('2016-05-01','Sunday')",
+ TimestampValue("2016-05-08 00:00:00", 19));
+ TestTimestampValue("next_day('2016-05-01','Monday')",
+ TimestampValue("2016-05-02 00:00:00", 19));
+ TestTimestampValue("next_day('2016-05-01','Tuesday')",
+ TimestampValue("2016-05-03 00:00:00", 19));
+ TestTimestampValue("next_day('2016-05-01','Wednesday')",
+ TimestampValue("2016-05-04 00:00:00", 19));
+ TestTimestampValue("next_day('2016-05-01','Thursday')",
+ TimestampValue("2016-05-05 00:00:00", 19));
+ TestTimestampValue("next_day('2016-05-01','Friday')",
+ TimestampValue("2016-05-06 00:00:00", 19));
+ TestTimestampValue("next_day('2016-05-01','Saturday')",
+ TimestampValue("2016-05-07 00:00:00", 19));
+
+ // Random test cases
+ TestTimestampValue("next_day('1910-01-18','SunDay')",
+ TimestampValue("1910-01-23 00:00:00", 19));
+ TestTimestampValue("next_day('1916-06-05', 'SUN')",
+ TimestampValue("1916-06-11 00:00:00", 19));
+ TestTimestampValue("next_day('1932-11-08','monday')",
+ TimestampValue("1932-11-14 00:00:00", 19));
+ TestTimestampValue("next_day('1933-09-11','Mon')",
+ TimestampValue("1933-09-18 00:00:00", 19));
+ TestTimestampValue("next_day('1934-03-21','TUeSday')",
+ TimestampValue("1934-03-27 00:00:00", 19));
+ TestTimestampValue("next_day('1954-02-25','tuE')",
+ TimestampValue("1954-03-02 00:00:00", 19));
+ TestTimestampValue("next_day('1965-04-18','WeDneSdaY')",
+ TimestampValue("1965-04-21 00:00:00", 19));
+ TestTimestampValue("next_day('1966-08-29','wed')",
+ TimestampValue("1966-08-31 00:00:00", 19));
+ TestTimestampValue("next_day('1968-07-23','tHurSday')",
+ TimestampValue("1968-07-25 00:00:00", 19));
+ TestTimestampValue("next_day('1969-05-28','thu')",
+ TimestampValue("1969-05-29 00:00:00", 19));
+ TestTimestampValue("next_day('1989-10-12','fRIDay')",
+ TimestampValue("1989-10-13 00:00:00", 19));
+ TestTimestampValue("next_day('1973-10-02','frI')",
+ TimestampValue("1973-10-05 00:00:00", 19));
+ TestTimestampValue("next_day('2000-02-29','saTUrDaY')",
+ TimestampValue("2000-03-04 00:00:00", 19));
+ TestTimestampValue("next_day('2013-04-12','sat')",
+ TimestampValue("2013-04-13 00:00:00", 19));
+ TestTimestampValue("next_day('2013-12-25','Saturday')",
+ TimestampValue("2013-12-28 00:00:00", 19));
+
+ // Explicit timestamp conversion tests
+ TestTimestampValue("next_day(to_timestamp('12-27-2008', 'MM-dd-yyyy'),
'moN')",
+ TimestampValue("2008-12-29 00:00:00", 19));
+ TestTimestampValue("next_day(to_timestamp('2007-20-10 11:22', 'yyyy-dd-MM
HH:mm'),\
+ 'TUeSdaY')", TimestampValue("2007-10-23 11:22:00", 19));
+ TestTimestampValue("next_day(to_timestamp('18-11-2070 09:12', 'dd-MM-yyyy
HH:mm'),\
+ 'WeDneSdaY')", TimestampValue("2070-11-19 09:12:00", 19));
+ TestTimestampValue("next_day(to_timestamp('12-1900-05', 'dd-yyyy-MM'),
'tHurSday')",
+ TimestampValue("1900-05-17 00:00:00", 19));
+ TestTimestampValue("next_day(to_timestamp('08-1987-21', 'MM-yyyy-dd'),
'FRIDAY')",
+ TimestampValue("1987-08-28 00:00:00", 19));
+ TestTimestampValue("next_day(to_timestamp('02-04-2001', 'dd-MM-yyyy'),
'SAT')",
+ TimestampValue("2001-04-07 00:00:00", 19));
+ TestTimestampValue("next_day(to_timestamp('1970-01-31 00:00:00',\
+ 'yyyy-MM-dd HH:mm:ss'), 'SunDay')", TimestampValue("1970-02-01
00:00:00", 19));
+
+ // Invalid input: unacceptable date parameter
+ TestIsNull("next_day('12202010','Saturday')", TYPE_TIMESTAMP);
+ TestIsNull("next_day('2011 02 11','thu')", TYPE_TIMESTAMP);
+ TestIsNull("next_day('09-19-2012xyz','monDay')", TYPE_TIMESTAMP);
+ TestIsNull("next_day('000000000000000','wed')", TYPE_TIMESTAMP);
+ TestIsNull("next_day('hell world!','fRiDaY')", TYPE_TIMESTAMP);
+ TestIsNull("next_day('t1c7t0c9','sunDAY')", TYPE_TIMESTAMP);
+ }
+
// This macro adds a scoped trace to provide the line number of the caller
upon failure.
#define EXPECT_BETWEEN(start, value, end) { \
SCOPED_TRACE(""); \
@@ -4346,8 +4420,13 @@ TEST_F(ExprTest, TimestampFunctions) {
TestIsNull("unix_timestamp('12/2/2015', 'MM/dd/yyyy')", TYPE_BIGINT);
TestValue("unix_timestamp('12/31/2015', 'MM/d/yyyy')", TYPE_BIGINT,
1451520000);
TestValue("unix_timestamp('12/31/2015', 'MM/dd/yyyy')", TYPE_BIGINT,
1451520000);
+
+ // next_day udf test for IMPALA-2459
+ TestNextDayFunction();
}
+
+
TEST_F(ExprTest, ConditionalFunctions) {
// If first param evaluates to true, should return second parameter,
// false or NULL should return the third.
http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/4e7172f6/be/src/exprs/timestamp-functions-ir.cc
----------------------------------------------------------------------
diff --git a/be/src/exprs/timestamp-functions-ir.cc
b/be/src/exprs/timestamp-functions-ir.cc
index 08992d9..05bc6ee 100644
--- a/be/src/exprs/timestamp-functions-ir.cc
+++ b/be/src/exprs/timestamp-functions-ir.cc
@@ -573,6 +573,38 @@ DoubleVal
TimestampFunctions::MonthsBetween(FunctionContext* context,
return DoubleVal(months_between);
}
+TimestampVal TimestampFunctions::NextDay(FunctionContext* context,
+ const TimestampVal& date, const StringVal& weekday) {
+ string weekday_str = string(reinterpret_cast<const char*>(weekday.ptr),
weekday.len);
+ transform(weekday_str.begin(), weekday_str.end(), weekday_str.begin(),
tolower);
+ int day_idx = 0;
+ if (weekday_str == "sunday" || weekday_str == "sun") {
+ day_idx = 1;
+ } else if (weekday_str == "monday" || weekday_str == "mon") {
+ day_idx = 2;
+ } else if (weekday_str == "tuesday" || weekday_str == "tue") {
+ day_idx = 3;
+ } else if (weekday_str == "wednesday" || weekday_str == "wed") {
+ day_idx = 4;
+ } else if (weekday_str == "thursday" || weekday_str == "thu") {
+ day_idx = 5;
+ } else if (weekday_str == "friday" || weekday_str == "fri") {
+ day_idx = 6;
+ } else if (weekday_str == "saturday" || weekday_str == "sat") {
+ day_idx = 7;
+ }
+ DCHECK_GE(day_idx, 1);
+ DCHECK_LE(day_idx, 7);
+
+ int delta_days = day_idx - DayOfWeek(context, date).val;
+ delta_days = delta_days <= 0 ? delta_days + 7 : delta_days;
+ DCHECK_GE(delta_days, 1);
+ DCHECK_LE(delta_days, 7);
+
+ IntVal delta(delta_days);
+ return AddSub<true, IntVal, Days, false>(context, date, delta);
+}
+
IntVal TimestampFunctions::IntMonthsBetween(FunctionContext* context,
const TimestampVal& ts1, const TimestampVal& ts2) {
if (ts1.is_null || ts2.is_null) return IntVal::null();
http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/4e7172f6/be/src/exprs/timestamp-functions.h
----------------------------------------------------------------------
diff --git a/be/src/exprs/timestamp-functions.h
b/be/src/exprs/timestamp-functions.h
index 23c0d10..6738bd0 100644
--- a/be/src/exprs/timestamp-functions.h
+++ b/be/src/exprs/timestamp-functions.h
@@ -141,6 +141,17 @@ class TimestampFunctions {
static DoubleVal MonthsBetween(FunctionContext* context,
const TimestampVal& ts_val1, const TimestampVal& ts_val2);
+ /// Return the date of the weekday that follows a particular date.
+ /// The 'weekday' argument is a string literal indicating the day of the
week.
+ /// Also this argument is case-insensitive. Available values are:
+ /// "Sunday"/"SUN", "Monday"/"MON", "Tuesday"/"TUE",
+ /// "Wednesday"/"WED", "Thursday"/"THU", "Friday"/"FRI", "Saturday"/"SAT".
+ /// For example, the first Saturday after Wednesday, 25 December 2013
+ /// is on 28 December 2013.
+ /// select next_day('2013-12-25','Saturday') returns '2013-12-28'
+ static TimestampVal NextDay(FunctionContext* context, const TimestampVal&
date,
+ const StringVal& weekday);
+
/// Add/sub functions on the timestamp. This handles three forms of
adding/subtracting
/// intervals to/from timestamps:
/// 1) ADD/SUB_<INTERVAL>(<TIMESTAMP>, <NUMBER>),
http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/4e7172f6/common/function-registry/impala_functions.py
----------------------------------------------------------------------
diff --git a/common/function-registry/impala_functions.py
b/common/function-registry/impala_functions.py
index 879ff8a..86a60e0 100644
--- a/common/function-registry/impala_functions.py
+++ b/common/function-registry/impala_functions.py
@@ -106,6 +106,7 @@ visible_functions = [
'_ZN6impala11UdfBuiltins9VectorGetEPN10impala_udf15FunctionContextERKNS1_9BigIntValERKNS1_9StringValE'],
# Timestamp functions
+ [['next_day'], 'TIMESTAMP', ['TIMESTAMP', 'STRING'],
'_ZN6impala18TimestampFunctions7NextDayEPN10impala_udf15FunctionContextERKNS1_12TimestampValERKNS1_9StringValE'],
[['unix_timestamp'], 'BIGINT', ['STRING'],
'_ZN6impala18TimestampFunctions14UnixFromStringEPN10impala_udf15FunctionContextERKNS1_9StringValE'],
[['year'], 'INT', ['TIMESTAMP'],
'_ZN6impala18TimestampFunctions4YearEPN10impala_udf15FunctionContextERKNS1_12TimestampValE'],
[['month'], 'INT', ['TIMESTAMP'],
'_ZN6impala18TimestampFunctions5MonthEPN10impala_udf15FunctionContextERKNS1_12TimestampValE'],