Repository: incubator-quickstep Updated Branches: refs/heads/date-representation 92555fc43 -> 5a9c29004 (forced update)
[QUICKSTEP-53] New representation and faster comparison operators for DateLit - New representation for DateLit. - New comparison implementations for DateLit. Closes #98 Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/5a9c2900 Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/5a9c2900 Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/5a9c2900 Branch: refs/heads/date-representation Commit: 5a9c290043051dab9c4fd40db220f266479cf419 Parents: 1d10422 Author: Hakan Memisoglu <hakanmemiso...@apache.org> Authored: Tue Sep 6 19:59:26 2016 -0500 Committer: Hakan Memisoglu <hakanmemiso...@apache.org> Committed: Tue Sep 6 20:01:57 2016 -0500 ---------------------------------------------------------------------- types/DateOperatorOverloads.hpp | 12 ++-- types/DateType.cpp | 8 +-- types/DatetimeLit.hpp | 62 +++++++++++++------- types/TypedValue.cpp | 9 +-- types/TypedValue.hpp | 4 +- types/TypedValue.proto | 8 +-- .../unary_operations/DateExtractOperation.cpp | 2 +- 7 files changed, 58 insertions(+), 47 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5a9c2900/types/DateOperatorOverloads.hpp ---------------------------------------------------------------------- diff --git a/types/DateOperatorOverloads.hpp b/types/DateOperatorOverloads.hpp index b04f44e..e2e5f6a 100644 --- a/types/DateOperatorOverloads.hpp +++ b/types/DateOperatorOverloads.hpp @@ -122,8 +122,8 @@ inline DatetimeLit operator+(const YearMonthIntervalLit &lhs, const DatetimeLit } inline DateLit operator+(const DateLit &lhs, const YearMonthIntervalLit &rhs) { - std::int32_t result_year = lhs.year + (rhs.months / 12); - std::uint8_t result_month = lhs.month + (rhs.months % 12); + std::int32_t result_year = lhs.yearField() + (rhs.months / 12); + std::uint8_t result_month = static_cast<std::uint8_t>(lhs.monthField()) + (rhs.months % 12); if (result_month > 11) { result_month -= 12; @@ -131,7 +131,7 @@ inline DateLit operator+(const DateLit &lhs, const YearMonthIntervalLit &rhs) { } const std::uint8_t result_day = static_cast<std::uint8_t>( - ClampDayOfMonth(result_year, result_month, lhs.day)); + ClampDayOfMonth(result_year, result_month, lhs.dayField())); return DateLit::Create(result_year, result_month, result_day); } @@ -187,8 +187,8 @@ inline DatetimeLit operator-(const DatetimeLit &lhs, const YearMonthIntervalLit } inline DateLit operator-(const DateLit &lhs, const YearMonthIntervalLit &rhs) { - std::int32_t result_year = lhs.year - (rhs.months / 12); - std::int8_t result_month = lhs.month - (rhs.months % 12); + std::int32_t result_year = lhs.yearField() - (rhs.months / 12); + std::int8_t result_month = static_cast<std::int8_t>(lhs.monthField()) - (rhs.months % 12); if (result_month < 0) { --result_year; @@ -196,7 +196,7 @@ inline DateLit operator-(const DateLit &lhs, const YearMonthIntervalLit &rhs) { } const std::uint8_t result_day = static_cast<std::uint8_t>( - ClampDayOfMonth(result_year, result_month, lhs.day)); + ClampDayOfMonth(result_year, result_month, lhs.dayField())); return DateLit::Create(result_year, result_month, result_day); } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5a9c2900/types/DateType.cpp ---------------------------------------------------------------------- diff --git a/types/DateType.cpp b/types/DateType.cpp index 5bb982c..388898e 100644 --- a/types/DateType.cpp +++ b/types/DateType.cpp @@ -60,7 +60,7 @@ std::string DateType::printValueToString(const TypedValue &value) const { DCHECK(!value.isNull()); const DateLit literal = value.getLiteral<DateLit>(); - const std::int32_t year = literal.year; + const std::int32_t year = literal.yearField(); char datebuf[DateLit::kIsoChars + 1]; std::size_t chars_written = 0; @@ -78,9 +78,9 @@ std::string DateType::printValueToString(const TypedValue &value) const { // All the rest of the ISO 8601 date/time parts. snprintf_result = snprintf(datebuf + chars_written, sizeof(datebuf) - chars_written, - "%02d-%02d", - literal.month, - literal.day); + "%02u-%02u", + literal.monthField(), + literal.dayField()); CheckSnprintf(snprintf_result, sizeof(datebuf), &chars_written); return std::string(datebuf); http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5a9c2900/types/DatetimeLit.hpp ---------------------------------------------------------------------- diff --git a/types/DatetimeLit.hpp b/types/DatetimeLit.hpp index 58c852f..c99dae4 100644 --- a/types/DatetimeLit.hpp +++ b/types/DatetimeLit.hpp @@ -36,10 +36,13 @@ namespace quickstep { * @brief A literal representing the date. **/ struct DateLit { - // Note that although there is no year 0 in the Gregorian calendar, ISO 8601 - // has year 0 equivalent to 1 BCE, year -1 equivalent to 2 BCE, and so on. - std::int32_t year; - std::uint8_t month, day; + // ---------------------------------------------------- + // | 23 bits | 4 bits | 5 bits | + // ---------------------------------------------------- + // | year | month | day | + // | (unsigned) (18 bits used) | (unsigned) | + // ---------------------------------------------------- + std::uint32_t year_month_day; // The maximum number of characters needed to represent any date in ISO 8601 // notation. @@ -51,53 +54,70 @@ struct DateLit { + 1 // - + 2; // Day + // Years should be between [-kMaxYear, +kMaxYear] inclusive both end. + static constexpr std::int32_t kMaxYear = 99999; + static constexpr std::uint8_t kBitsNeededForDay = 5u; + static constexpr std::uint8_t kBitsNeededForMonth = 4u; + static DateLit Create(const std::int32_t _year, const std::uint8_t _month, const std::uint8_t _day) { DateLit date; - date.year = _year; - date.month = _month; - date.day = _day; + // Normalize year by adding kMaxYear value, because we try to + // encode signed year value into an unsigned integer. + std::uint32_t representation + = (static_cast<std::uint32_t>(_year + kMaxYear) << (kBitsNeededForDay + kBitsNeededForMonth)) + | (_month << kBitsNeededForDay) + | _day; + date.year_month_day = representation; + return date; + } + static DateLit Create(const std::uint32_t serialized) { + DateLit date; + date.year_month_day = serialized; return date; } inline bool operator< (const DateLit& rhs) const { - return (year != rhs.year) - ? (year < rhs.year) - : ((month != rhs.month) ? (month < rhs.month) : (day < rhs.day)); + return year_month_day < rhs.year_month_day; } inline bool operator> (const DateLit& rhs) const { - return (year != rhs.year) - ? (year > rhs.year) - : ((month != rhs.month) ? (month > rhs.month) : (day > rhs.day)); + return year_month_day < rhs.year_month_day; } inline bool operator<=(const DateLit& rhs) const { - return !(*this > rhs); + return year_month_day <= rhs.year_month_day; } inline bool operator>=(const DateLit& rhs) const { - return !(*this < rhs); + return year_month_day >= rhs.year_month_day; } inline bool operator==(const DateLit& rhs) const { - return (year == rhs.year) && - (month == rhs.month) && - (day == rhs.day); + return year_month_day == rhs.year_month_day; } inline bool operator!=(const DateLit& rhs) const { - return !(*this == rhs); + return year_month_day != rhs.year_month_day; } inline std::int32_t yearField() const { + const std::int32_t year = + static_cast<std::int32_t>(year_month_day >> + (kBitsNeededForDay + kBitsNeededForMonth)) - kMaxYear; return year; } - inline std::int32_t monthField() const { - return static_cast<std::int32_t>(month); + inline std::uint32_t monthField() const { + const std::uint32_t mask = 0x1E0u; // 0b111100000 + return (year_month_day & mask) >> kBitsNeededForDay; + } + + inline std::uint32_t dayField() const { + const std::uint32_t mask = 0x1Fu; // 0b11111 + return year_month_day & mask; } }; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5a9c2900/types/TypedValue.cpp ---------------------------------------------------------------------- diff --git a/types/TypedValue.cpp b/types/TypedValue.cpp index 8dd8b60..ada69c6 100644 --- a/types/TypedValue.cpp +++ b/types/TypedValue.cpp @@ -110,10 +110,7 @@ serialization::TypedValue TypedValue::getProto() const { case kDate: proto.set_type_id(serialization::Type::DATE); if (!isNull()) { - serialization::TypedValue::DateLit *literal_date_proto = proto.mutable_date_value(); - literal_date_proto->set_year(value_union_.date_value.year); - literal_date_proto->set_month(value_union_.date_value.month); - literal_date_proto->set_day(value_union_.date_value.day); + proto.set_date_value(getLiteral<DateLit>().year_month_day); } break; case kDatetime: @@ -185,9 +182,7 @@ TypedValue TypedValue::ReconstructFromProto(const serialization::TypedValue &pro TypedValue(kDouble); case serialization::Type::DATE: if (proto.has_date_value()) { - return TypedValue(DateLit::Create(proto.date_value().year(), - proto.date_value().month(), - proto.date_value().day())); + return TypedValue(DateLit::Create(proto.date_value())); } else { return TypedValue(kDate); } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5a9c2900/types/TypedValue.hpp ---------------------------------------------------------------------- diff --git a/types/TypedValue.hpp b/types/TypedValue.hpp index d75720a..dae8bd8 100644 --- a/types/TypedValue.hpp +++ b/types/TypedValue.hpp @@ -393,10 +393,10 @@ class TypedValue { switch (getTypeID()) { case kInt: case kFloat: + case kDate: return sizeof(int); case kLong: case kDouble: - case kDate: case kDatetime: case kDatetimeInterval: case kYearMonthInterval: @@ -552,6 +552,8 @@ class TypedValue { // 4 bytes byte-for-byte copy. *static_cast<int*>(destination) = value_union_.int_value; break; + case kDate: + *static_cast<DateLit*>(destination) = value_union_.date_value; default: // 8 bytes byte-for-byte copy. *static_cast<ValueUnion*>(destination) = value_union_; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5a9c2900/types/TypedValue.proto ---------------------------------------------------------------------- diff --git a/types/TypedValue.proto b/types/TypedValue.proto index 7f3ab7a..0164688 100644 --- a/types/TypedValue.proto +++ b/types/TypedValue.proto @@ -34,11 +34,5 @@ message TypedValue { optional int64 datetime_interval_value = 8; optional int64 year_month_interval_value = 9; - message DateLit { - required int32 year = 1; - required uint32 month = 2; - required uint32 day = 3; - } - - optional DateLit date_value = 10; + optional uint32 date_value = 10; } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5a9c2900/types/operations/unary_operations/DateExtractOperation.cpp ---------------------------------------------------------------------- diff --git a/types/operations/unary_operations/DateExtractOperation.cpp b/types/operations/unary_operations/DateExtractOperation.cpp index c99e403..585fb85 100644 --- a/types/operations/unary_operations/DateExtractOperation.cpp +++ b/types/operations/unary_operations/DateExtractOperation.cpp @@ -444,7 +444,7 @@ TypedValue DateExtractOperation::applyToChecked(const TypedValue &argument, } else { // argument type is kDate. DCHECK_EQ(TypeID::kDate, argument.getTypeID()); - return TypedValue(argument.getLiteral<DateLit>().monthField()); + return TypedValue(static_cast<std::int32_t>(argument.getLiteral<DateLit>().monthField())); } } case DateExtractUnit::kDay: