Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some datetime extraction functions #624

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions QueryEngine/DateTimeIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@ const char* get_extract_function_name(ExtractField field) {
return "extract_quarter";
case kYEAR:
return "extract_year";
case kLDOM:
return "extract_last_day_of_month";
case kISLEAP:
return "extract_is_leap_year";
case kISEOM:
return "extract_is_month_end";
case kISSOM:
return "extract_is_month_start";
case kISEOQ:
return "extract_is_quarter_end";
case kISSOQ:
return "extract_is_quarter_start";
case kISEOY:
return "extract_is_year_end";
case kISSOY:
return "extract_is_year_start";
}
UNREACHABLE();
return "";
Expand Down
32 changes: 32 additions & 0 deletions QueryEngine/DateTimeTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,22 @@ std::string from_extract_field(const ExtractField& fieldno) {
return "week_saturday";
case kDATEEPOCH:
return "dateepoch";
case kLDOM:
return "daysinmonth";
case kISLEAP:
return "isleapyear";
case kISEOM:
return "ismonthend";
case kISSOM:
return "ismonthstart";
case kISEOQ:
return "isquarterend";
case kISSOQ:
return "isquarterstart";
case kISEOY:
return "isyearend";
case kISSOY:
return "isyearstart";
default:
UNREACHABLE();
}
Expand Down Expand Up @@ -151,6 +167,22 @@ ExtractField ExtractExpr::to_extract_field(const std::string& field) {
fieldno = kWEEK_SATURDAY;
} else if (boost::iequals(field, "dateepoch")) {
fieldno = kDATEEPOCH;
} else if (boost::iequals(field, "daysinmonth")) {
fieldno = kLDOM;
} else if (boost::iequals(field, "isleapyear")) {
fieldno = kISLEAP;
} else if (boost::iequals(field, "ismonthend")) {
fieldno = kISEOM;
} else if (boost::iequals(field, "ismonthstart")) {
fieldno = kISSOM;
} else if (boost::iequals(field, "isquarterend")) {
fieldno = kISEOQ;
} else if (boost::iequals(field, "isquarterstart")) {
fieldno = kISSOQ;
} else if (boost::iequals(field, "isyearend")) {
fieldno = kISEOY;
} else if (boost::iequals(field, "isyearstart")) {
fieldno = kISSOY;
} else {
throw std::runtime_error("Unsupported field in EXTRACT function " + field);
}
Expand Down
16 changes: 16 additions & 0 deletions QueryEngine/ExpressionRange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,22 @@ ExpressionRange getExpressionRange(
case kWEEK_SUNDAY:
case kWEEK_SATURDAY:
return ExpressionRange::makeIntRange(1, 53, 0, has_nulls);
case kLDOM:
return ExpressionRange::makeIntRange(28, 31, 0, has_nulls);
case kISLEAP:
return ExpressionRange::makeIntRange(0, 1, 0, has_nulls);
case kISEOM:
return ExpressionRange::makeIntRange(0, 1, 0, has_nulls);
case kISSOM:
return ExpressionRange::makeIntRange(0, 1, 0, has_nulls);
case kISEOQ:
return ExpressionRange::makeIntRange(0, 1, 0, has_nulls);
case kISSOQ:
return ExpressionRange::makeIntRange(0, 1, 0, has_nulls);
case kISEOY:
return ExpressionRange::makeIntRange(0, 1, 0, has_nulls);
case kISSOY:
return ExpressionRange::makeIntRange(0, 1, 0, has_nulls);
default:
CHECK(false);
}
Expand Down
79 changes: 79 additions & 0 deletions QueryEngine/ExtractFromTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,20 @@ DEVICE unsigned week_start_from_yoe(unsigned const yoe) {
return jan4 - jan4dow;
}

// Return day-of-year since on March 1
DEVICE int64_t get_doy(const int64_t timeval) {
int64_t const day = floor_div(timeval, kSecsPerDay);
unsigned const doe = unsigned_mod(day - kEpochAdjustedDays, kDaysPer400Years);
unsigned const yoe = (doe - doe / (kDaysPer4Years - 1) + doe / kDaysPer100Years -
(doe == kDaysPer400Years - 1)) /
kDaysPerYear;
return doe - (kDaysPerYear * yoe + yoe / 4 - yoe / 100);
}

DEVICE bool is_leap(const int64_t year) {
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}

} // namespace

extern "C" ALWAYS_INLINE DEVICE int64_t extract_hour(const int64_t lcltime) {
Expand Down Expand Up @@ -242,6 +256,55 @@ extern "C" ALWAYS_INLINE DEVICE int64_t extract_year(const int64_t timeval) {
return 2000 + era * 400 + yoe + (MARJAN <= doy);
}

extern "C" ALWAYS_INLINE DEVICE int64_t extract_last_day_of_month(const int64_t timeval) {
constexpr int64_t days[12]{31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 28};
unsigned const doy = get_doy(timeval);
unsigned const year = extract_year(timeval);
unsigned const moy = (5 * doy - 2) / 153;
return moy != 11 ? days[moy] : is_leap(year) ? days[moy] + 1 : days[moy];
}

extern "C" ALWAYS_INLINE DEVICE int64_t extract_is_leap_year(const int64_t timeval) {
unsigned const year = extract_year(timeval);
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}

extern "C" ALWAYS_INLINE DEVICE int64_t extract_is_month_end(const int64_t timeval) {
constexpr int64_t days[12]{31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 28};
unsigned const doy = get_doy(timeval) - 1;
unsigned const year = extract_year(timeval);
unsigned const moy = (5 * doy - 2) / 153;
unsigned const dom = extract_day(timeval);
return moy != 11 ? (dom == days[moy])
: is_leap(year) ? (dom == (days[moy] + 1)) : (dom == days[moy]);
}

extern "C" ALWAYS_INLINE DEVICE int64_t extract_is_month_start(const int64_t timeval) {
return 1 == extract_day(timeval);
}

extern "C" ALWAYS_INLINE DEVICE int64_t extract_is_quarter_end(const int64_t timeval) {
unsigned const d = extract_day_of_year(timeval);
unsigned const year = extract_year(timeval);
return is_leap(year) ? (d == 91 || d == 182 || d == 274 || d == 366)
: (d == 90 || d == 181 || d == 273 || d == 365);
}

extern "C" ALWAYS_INLINE DEVICE int64_t extract_is_quarter_start(const int64_t timeval) {
unsigned const d = extract_day_of_year(timeval);
unsigned const year = extract_year(timeval);
return is_leap(year) ? (d == 1 || d == 92 || d == 183 || d == 275)
: (d == 1 || d == 91 || d == 182 || d == 274);
}

extern "C" ALWAYS_INLINE DEVICE int64_t extract_is_year_end(const int64_t timeval) {
return MARJAN - 1 == get_doy(timeval);
}

extern "C" ALWAYS_INLINE DEVICE int64_t extract_is_year_start(const int64_t timeval) {
return MARJAN == get_doy(timeval);
}

/*
* @brief support the SQL EXTRACT function
*/
Expand Down Expand Up @@ -285,6 +348,22 @@ DEVICE int64_t ExtractFromTime(ExtractField field, const int64_t timeval) {
return extract_quarter(timeval);
case kYEAR:
return extract_year(timeval);
case kLDOM:
return extract_last_day_of_month(timeval);
case kISLEAP:
return extract_is_leap_year(timeval);
case kISEOM:
return extract_is_month_end(timeval);
case kISSOM:
return extract_is_month_start(timeval);
case kISEOQ:
return extract_is_quarter_end(timeval);
case kISSOQ:
return extract_is_quarter_start(timeval);
case kISEOY:
return extract_is_year_end(timeval);
case kISSOY:
return extract_is_year_start(timeval);
}

#ifdef __CUDACC__
Expand Down
10 changes: 9 additions & 1 deletion QueryEngine/ExtractFromTime.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,15 @@ enum ExtractField {
kWEEK,
kWEEK_SUNDAY,
kWEEK_SATURDAY,
kDATEEPOCH
kDATEEPOCH,
kLDOM,
kISLEAP,
kISEOM,
kISSOM,
kISEOQ,
kISSOQ,
kISEOY,
kISSOY
};

DEVICE int64_t ExtractFromTime(ExtractField field, const int64_t timeval);
Expand Down
Loading