You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@quickstep.apache.org by ha...@apache.org on 2016/09/07 01:07:01 UTC

incubator-quickstep git commit: [QUICKSTEP-53] New representation and faster comparison operators for DateLit [Forced Update!]

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 <ha...@apache.org>
Authored: Tue Sep 6 19:59:26 2016 -0500
Committer: Hakan Memisoglu <ha...@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: