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

incubator-quickstep git commit: Added the Date Type.

Repository: incubator-quickstep
Updated Branches:
  refs/heads/date-type [created] 615bbaaf3


Added the Date Type.


Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/615bbaaf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/615bbaaf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/615bbaaf

Branch: refs/heads/date-type
Commit: 615bbaaf328f9ba9114b554c11cfd81198c6668d
Parents: 2cc7880
Author: Zuyu Zhang <zu...@twitter.com>
Authored: Fri Jul 15 10:50:08 2016 -0700
Committer: Zuyu Zhang <zu...@twitter.com>
Committed: Fri Jul 15 10:50:08 2016 -0700

----------------------------------------------------------------------
 third_party/iwyu/iwyu_helper.py   |   1 +
 types/CMakeLists.txt              |  27 ++++++
 types/DateType.cpp                | 150 +++++++++++++++++++++++++++++++++
 types/DateType.hpp                | 134 +++++++++++++++++++++++++++++
 types/DatetimeLit.hpp             |  61 ++++++++++++++
 types/Type.cpp                    |   3 +
 types/Type.hpp                    |   5 +-
 types/Type.proto                  |   1 +
 types/TypeFactory.cpp             |   7 ++
 types/TypeFactory.hpp             |   1 +
 types/TypeID.cpp                  |   1 +
 types/TypeID.hpp                  |   1 +
 types/TypedValue.cpp              |  18 ++++
 types/TypedValue.hpp              |  22 +++++
 types/TypedValue.proto            |   8 ++
 types/tests/DateType_unittest.cpp | 148 ++++++++++++++++++++++++++++++++
 types/tests/TypeTest_common.hpp   |   8 +-
 17 files changed, 591 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/third_party/iwyu/iwyu_helper.py
----------------------------------------------------------------------
diff --git a/third_party/iwyu/iwyu_helper.py b/third_party/iwyu/iwyu_helper.py
index 13697be..dff4d55 100755
--- a/third_party/iwyu/iwyu_helper.py
+++ b/third_party/iwyu/iwyu_helper.py
@@ -25,6 +25,7 @@ QUICKSTEP_INCLUDES = [ '.',
                        './third_party/benchmark/include',
                        './third_party/glog/src',
                        './third_party/googletest/googletest/include',
+                       './third_party/protobuf/src',
                        './third_party/re2',
                        './third_party/tmb/include']
 QUICKSTEP_DEFINES = [ '-DQUICKSTEP_DEBUG',

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/types/CMakeLists.txt b/types/CMakeLists.txt
index 0ccdfd7..420891a 100644
--- a/types/CMakeLists.txt
+++ b/types/CMakeLists.txt
@@ -32,6 +32,7 @@ QS_PROTOBUF_GENERATE_CPP(types_Type_proto_srcs types_Type_proto_hdrs Type.proto)
 # Declare micro-libs:
 add_library(quickstep_types_CharType CharType.cpp CharType.hpp)
 add_library(quickstep_types_DateOperatorOverloads ../empty_src.cpp DateOperatorOverloads.hpp)
+add_library(quickstep_types_DateType DateType.cpp DateType.hpp)
 add_library(quickstep_types_DatetimeIntervalType DatetimeIntervalType.cpp DatetimeIntervalType.hpp)
 add_library(quickstep_types_DatetimeLit ../empty_src.cpp DatetimeLit.hpp)
 add_library(quickstep_types_DatetimeType DatetimeType.cpp DatetimeType.hpp)
@@ -71,6 +72,15 @@ target_link_libraries(quickstep_types_DateOperatorOverloads
                       quickstep_types_IntervalLit
                       quickstep_types_port_gmtime_r
                       quickstep_types_port_timegm)
+target_link_libraries(quickstep_types_DateType
+                      glog
+                      quickstep_types_DatetimeLit
+                      quickstep_types_NullCoercibilityCheckMacro
+                      quickstep_types_Type
+                      quickstep_types_TypeID
+                      quickstep_types_TypedValue
+                      quickstep_utility_CheckSnprintf
+                      quickstep_utility_Macros)
 target_link_libraries(quickstep_types_DatetimeIntervalType
                       glog
                       quickstep_types_IntervalLit
@@ -156,6 +166,7 @@ target_link_libraries(quickstep_types_Type
 target_link_libraries(quickstep_types_TypeFactory
                       glog
                       quickstep_types_CharType
+                      quickstep_types_DateType
                       quickstep_types_DatetimeIntervalType
                       quickstep_types_DatetimeType
                       quickstep_types_DoubleType
@@ -210,6 +221,7 @@ add_library(quickstep_types ../empty_src.cpp TypesModule.hpp)
 target_link_libraries(quickstep_types
                       quickstep_types_CharType
                       quickstep_types_DateOperatorOverloads
+                      quickstep_types_DateType
                       quickstep_types_DatetimeIntervalType
                       quickstep_types_DatetimeLit
                       quickstep_types_DatetimeType
@@ -264,6 +276,21 @@ target_link_libraries(CharType_unittest
                       quickstep_utility_MemStream)
 add_test(CharType_unittest CharType_unittest)
 
+add_executable(DateType_unittest "${CMAKE_CURRENT_SOURCE_DIR}/tests/DateType_unittest.cpp")
+target_link_libraries(DateType_unittest
+                      gtest
+                      gtest_main
+                      quickstep_types_DatetimeLit
+                      quickstep_types_DateType
+                      quickstep_types_NullType
+                      quickstep_types_Type
+                      quickstep_types_TypeFactory
+                      quickstep_types_TypeID
+                      quickstep_types_TypedValue
+                      quickstep_types_tests_TypeTest_common
+                      quickstep_utility_MemStream)
+add_test(DateType_unittest DateType_unittest)
+
 add_executable(DatetimeIntervalType_unittest
                "${CMAKE_CURRENT_SOURCE_DIR}/tests/DatetimeIntervalType_unittest.cpp")
 target_link_libraries(DatetimeIntervalType_unittest

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/DateType.cpp
----------------------------------------------------------------------
diff --git a/types/DateType.cpp b/types/DateType.cpp
new file mode 100644
index 0000000..4fc4730
--- /dev/null
+++ b/types/DateType.cpp
@@ -0,0 +1,150 @@
+/**
+ *   Copyright 2016 Twitter, Inc.
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ **/
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include "types/DateType.hpp"
+
+#include <cinttypes>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <string>
+
+#include "types/DatetimeLit.hpp"
+#include "types/NullCoercibilityCheckMacro.hpp"
+#include "types/Type.hpp"
+#include "types/TypeID.hpp"
+#include "types/TypedValue.hpp"
+#include "utility/CheckSnprintf.hpp"
+
+#include "glog/logging.h"
+
+// NetBSD's libc has snprintf, but it doesn't show up in the std namespace for
+// C++.
+#ifndef __NetBSD__
+using std::snprintf;
+#endif
+
+namespace quickstep {
+
+bool DateType::isCoercibleFrom(const Type &original_type) const {
+  QUICKSTEP_NULL_COERCIBILITY_CHECK();
+  return (original_type.getTypeID() == kDate);
+}
+
+bool DateType::isSafelyCoercibleFrom(const Type &original_type) const {
+  QUICKSTEP_NULL_COERCIBILITY_CHECK();
+  return (original_type.getTypeID() == kDate);
+}
+
+std::string DateType::printValueToString(const TypedValue &value) const {
+  DCHECK(!value.isNull());
+
+  const DateLit literal = value.getLiteral<DateLit>();
+  const std::int32_t year = literal.year;
+
+  char datebuf[DateLit::kIsoChars + 1];
+  std::size_t chars_written = 0;
+  int snprintf_result = 0;
+
+  // ISO 8601 requires that "expanded" year ranges (> 4 digits or before year
+  // 0) are prefixed with a plus or minus.
+  if ((year > 9999) || (year < 0)) {
+    snprintf_result = snprintf(datebuf, sizeof(datebuf), "%+05" PRId32 "-", year);
+  } else {
+    snprintf_result = snprintf(datebuf, sizeof(datebuf), "%04" PRId32 "-", year);
+  }
+  CheckSnprintf(snprintf_result, sizeof(datebuf), &chars_written);
+
+  // 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);
+  CheckSnprintf(snprintf_result, sizeof(datebuf), &chars_written);
+
+  return std::string(datebuf);
+}
+
+void DateType::printValueToFile(const TypedValue &value,
+                                FILE *file,
+                                const int padding) const {
+  // We simply re-use the logic from printValueToString(), as trying to do
+  // padding on-the fly with so many different fields is too much of a hassle.
+  std::fprintf(file, "%*s", padding, printValueToString(value).c_str());
+}
+
+bool DateType::parseValueFromString(const std::string &value_string,
+                                    TypedValue *value) const {
+  std::int32_t year;
+  int month, day;
+
+  int date_chars = 0;
+
+  const int matched = std::sscanf(value_string.c_str(),
+                                  "%d-%2u-%2u%n",
+                                  &year, &month, &day, &date_chars);
+
+  // Check that the string is date, then check that there is no unmatched
+  // garbage at the end of the string.
+  if (matched != 3 ||
+      (static_cast<std::string::size_type>(date_chars) != value_string.length())) {
+    return false;
+  }
+
+  // Validate month.
+  if ((month == 0) || (month > 12)) {
+    return false;
+  }
+
+  // Validate day-of-month.
+  if (day == 0) {
+    return false;
+  }
+  switch (month) {
+    case 2: {
+      const int days_in_february
+          = ((year & 3) == 0 && ((year % 25) != 0 || (year & 15) == 0))
+            ? 29 : 28;
+      if (day > days_in_february) {
+        return false;
+      }
+      break;
+    }
+    case 4:  // Fall-through for 30-day months.
+    case 6:
+    case 9:
+    case 11:
+      if (day > 30) {
+        return false;
+      }
+      break;
+    default:
+      if (day > 31) {
+        return false;
+      }
+      break;
+  }
+
+  *value = TypedValue(DateLit::Create(year, month, day));
+  return true;
+}
+
+}  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/DateType.hpp
----------------------------------------------------------------------
diff --git a/types/DateType.hpp b/types/DateType.hpp
new file mode 100644
index 0000000..fb2e896
--- /dev/null
+++ b/types/DateType.hpp
@@ -0,0 +1,134 @@
+/**
+ *   Copyright 2016 Twitter, Inc.
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ **/
+
+#ifndef QUICKSTEP_TYPES_DATE_TYPE_HPP_
+#define QUICKSTEP_TYPES_DATE_TYPE_HPP_
+
+#include <cstddef>
+#include <cstdio>
+#include <string>
+
+#include "types/DatetimeLit.hpp"
+#include "types/Type.hpp"
+#include "types/TypeID.hpp"
+#include "utility/Macros.hpp"
+
+namespace quickstep {
+
+class TypedValue;
+
+/** \addtogroup Types
+ *  @{
+ */
+
+/**
+ * @brief A type representing the date.
+ **/
+class DateType : public Type {
+ public:
+  typedef DateLit cpptype;
+
+  static const TypeID kStaticTypeID = kDate;
+
+  /**
+   * @brief Get a reference to the non-nullable singleton instance of this
+   *        Type.
+   *
+   * @return A reference to the non-nullable singleton instance of this Type.
+   **/
+  static const DateType& InstanceNonNullable() {
+    static DateType instance(false);
+    return instance;
+  }
+
+  /**
+   * @brief Get a reference to the nullable singleton instance of this Type.
+   *
+   * @return A reference to the nullable singleton instance of this Type.
+   **/
+  static const DateType& InstanceNullable() {
+    static DateType instance(true);
+    return instance;
+  }
+
+  /**
+   * @brief Get a reference to a singleton instance of this Type.
+   *
+   * @param nullable Whether to get the nullable version of this Type.
+   * @return A reference to the desired singleton instance of this Type.
+   **/
+  static const DateType& Instance(const bool nullable) {
+    if (nullable) {
+      return InstanceNullable();
+    } else {
+      return InstanceNonNullable();
+    }
+  }
+
+  const Type& getNullableVersion() const override {
+    return InstanceNullable();
+  }
+
+  const Type& getNonNullableVersion() const override {
+    return InstanceNonNullable();
+  }
+
+  std::size_t estimateAverageByteLength() const override {
+    return sizeof(DateLit);
+  }
+
+  bool isCoercibleFrom(const Type &original_type) const override;
+
+  bool isSafelyCoercibleFrom(const Type &original_type) const override;
+
+  int getPrintWidth() const override {
+    return DateLit::kIsoChars;
+  }
+
+  std::string printValueToString(const TypedValue &value) const override;
+
+  void printValueToFile(const TypedValue &value,
+                        FILE *file,
+                        const int padding = 0) const override;
+
+  /**
+   * @note value_string is expected to be in (possibly extended) ISO-8601
+   *       format. Extended ISO-8601 date format is "YYYY-MM-DD". YYYY is an
+   *       integer year (in extended format, this may be more than 4 digits and
+   *       include an optional sign prefix +/-). MM is a 2-digit month in the
+   *       range 01-12. DD is a 2-digit day of month in the appropriate range
+   *       for the month (i.e. 28 days for February in non-leap years, 29 days
+   *       for February in leap years, 30 days for April, June, September, and
+   *       November, and 31 days for all other months). Note that parsing will
+   *       fail if there are any "extra" characters at the end of the string
+   *       after a parsable ISO-8601 date.
+   **/
+  bool parseValueFromString(const std::string &value_string,
+                            TypedValue *value) const override;
+
+ private:
+  explicit DateType(const bool nullable)
+      : Type(Type::kOther, kDate, nullable, sizeof(DateLit), sizeof(DateLit)) {
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(DateType);
+};
+
+/** @} */
+
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_TYPES_DATE_TYPE_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/DatetimeLit.hpp
----------------------------------------------------------------------
diff --git a/types/DatetimeLit.hpp b/types/DatetimeLit.hpp
index 017bcce..c87b510 100644
--- a/types/DatetimeLit.hpp
+++ b/types/DatetimeLit.hpp
@@ -31,6 +31,67 @@ 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;
+
+  // The maximum number of characters needed to represent any date in ISO 8601
+  // notation.
+  static constexpr int kIsoChars
+      = 1     // + or - prefix
+        + 5   // Year digits
+        + 1   // -
+        + 2   // Month
+        + 1   // -
+        + 2;  // Day
+
+  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;
+
+    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));
+  }
+
+  inline bool operator> (const DateLit& rhs) const {
+    return (year != rhs.year)
+        ? (year > rhs.year)
+        : ((month != rhs.month) ? (month > rhs.month) : (day > rhs.day));
+  }
+
+  inline bool operator<=(const DateLit& rhs) const {
+    return !(*this > rhs);
+  }
+
+  inline bool operator>=(const DateLit& rhs) const {
+    return !(*this < rhs);
+  }
+
+  inline bool operator==(const DateLit& rhs) const {
+    return (year == rhs.year) &&
+           (month == rhs.month) &&
+           (day == rhs.day);
+  }
+
+  inline bool operator!=(const DateLit& rhs) const {
+    return !(*this == rhs);
+  }
+};
+
+/**
  * @brief A literal representing the datetime.
  **/
 struct DatetimeLit {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/Type.cpp
----------------------------------------------------------------------
diff --git a/types/Type.cpp b/types/Type.cpp
index 8981bc2..b89b2ac 100644
--- a/types/Type.cpp
+++ b/types/Type.cpp
@@ -41,6 +41,9 @@ serialization::Type Type::getProto() const {
     case kDouble:
       proto.set_type_id(serialization::Type::DOUBLE);
       break;
+    case kDate:
+      proto.set_type_id(serialization::Type::DATE);
+      break;
     case kDatetime:
       proto.set_type_id(serialization::Type::DATETIME);
       break;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/Type.hpp
----------------------------------------------------------------------
diff --git a/types/Type.hpp b/types/Type.hpp
index fc6f4e2..84a0de0 100644
--- a/types/Type.hpp
+++ b/types/Type.hpp
@@ -32,6 +32,7 @@
 
 namespace quickstep {
 
+struct DateLit;
 struct DatetimeIntervalLit;
 struct DatetimeLit;
 struct YearMonthIntervalLit;
@@ -95,7 +96,7 @@ class Type {
   enum SuperTypeID {
     kNumeric = 0,  // Fixed-length numeric types (Int, Long, Float, Double)
     kAsciiString,  // ASCII strings (Char, VarChar)
-    kOther         // Others (Datetime, DatetimeInterval, YearMonthInterval)
+    kOther         // Others (Date, Datetime, DatetimeInterval, YearMonthInterval)
   };
 
   /**
@@ -370,6 +371,8 @@ class Type {
         return TypedValue(*static_cast<const float*>(value_ptr));
       case kDouble:
         return TypedValue(*static_cast<const double*>(value_ptr));
+      case kDate:
+        return TypedValue(*static_cast<const DateLit*>(value_ptr));
       case kDatetime:
         return TypedValue(*static_cast<const DatetimeLit*>(value_ptr));
       case kDatetimeInterval:

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/Type.proto
----------------------------------------------------------------------
diff --git a/types/Type.proto b/types/Type.proto
index dbf248e..cfcb713 100644
--- a/types/Type.proto
+++ b/types/Type.proto
@@ -29,6 +29,7 @@ message Type {
     DATETIME_INTERVAL = 7;
     YEAR_MONTH_INTERVAL = 8;
     NULL_TYPE = 9;
+    DATE = 10;
   }
 
   required TypeID type_id = 1;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/TypeFactory.cpp
----------------------------------------------------------------------
diff --git a/types/TypeFactory.cpp b/types/TypeFactory.cpp
index a8f2961..3709a50 100644
--- a/types/TypeFactory.cpp
+++ b/types/TypeFactory.cpp
@@ -18,8 +18,10 @@
 #include "types/TypeFactory.hpp"
 
 #include <cstddef>
+#include <string>
 
 #include "types/CharType.hpp"
+#include "types/DateType.hpp"
 #include "types/DatetimeIntervalType.hpp"
 #include "types/DatetimeType.hpp"
 #include "types/DoubleType.hpp"
@@ -49,6 +51,8 @@ const Type& TypeFactory::GetType(const TypeID id,
       return FloatType::Instance(nullable);
     case kDouble:
       return DoubleType::Instance(nullable);
+    case kDate:
+      return DateType::Instance(nullable);
     case kDatetime:
       return DatetimeType::Instance(nullable);
     case kDatetimeInterval:
@@ -90,6 +94,7 @@ bool TypeFactory::ProtoIsValid(const serialization::Type &proto) {
     case serialization::Type::LONG:
     case serialization::Type::FLOAT:
     case serialization::Type::DOUBLE:
+    case serialization::Type::DATE:
     case serialization::Type::DATETIME:
     case serialization::Type::DATETIME_INTERVAL:
     case serialization::Type::YEAR_MONTH_INTERVAL:
@@ -119,6 +124,8 @@ const Type& TypeFactory::ReconstructFromProto(const serialization::Type &proto)
       return FloatType::Instance(proto.nullable());
     case serialization::Type::DOUBLE:
       return DoubleType::Instance(proto.nullable());
+    case serialization::Type::DATE:
+      return DateType::Instance(proto.nullable());
     case serialization::Type::DATETIME:
       return DatetimeType::Instance(proto.nullable());
     case serialization::Type::DATETIME_INTERVAL:

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/TypeFactory.hpp
----------------------------------------------------------------------
diff --git a/types/TypeFactory.hpp b/types/TypeFactory.hpp
index ed9be5e..e63a613 100644
--- a/types/TypeFactory.hpp
+++ b/types/TypeFactory.hpp
@@ -52,6 +52,7 @@ class TypeFactory {
       case kLong:
       case kFloat:
       case kDouble:
+      case kDate:
       case kDatetime:
       case kDatetimeInterval:
       case kYearMonthInterval:

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/TypeID.cpp
----------------------------------------------------------------------
diff --git a/types/TypeID.cpp b/types/TypeID.cpp
index 1aeea04..6a5a4c7 100644
--- a/types/TypeID.cpp
+++ b/types/TypeID.cpp
@@ -26,6 +26,7 @@ const char *kTypeNames[] = {
   "Double",
   "Char",
   "VarChar",
+  "Date",
   "Datetime",
   "DatetimeInterval",
   "YearMonthInterval",

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/TypeID.hpp
----------------------------------------------------------------------
diff --git a/types/TypeID.hpp b/types/TypeID.hpp
index 23d32da..069e9c0 100644
--- a/types/TypeID.hpp
+++ b/types/TypeID.hpp
@@ -34,6 +34,7 @@ enum TypeID {
   kDouble,
   kChar,
   kVarChar,
+  kDate,
   kDatetime,
   kDatetimeInterval,
   kYearMonthInterval,

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/TypedValue.cpp
----------------------------------------------------------------------
diff --git a/types/TypedValue.cpp b/types/TypedValue.cpp
index bc1ebd9..cef7cb0 100644
--- a/types/TypedValue.cpp
+++ b/types/TypedValue.cpp
@@ -49,6 +49,7 @@ bool TypedValue::isPlausibleInstanceOf(const TypeSignature type) const {
     case kLong:
     case kFloat:
     case kDouble:
+    case kDate:
     case kDatetime:
     case kDatetimeInterval:
     case kYearMonthInterval:
@@ -104,6 +105,15 @@ serialization::TypedValue TypedValue::getProto() const {
         proto.set_double_value(getLiteral<double>());
       }
       break;
+    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);
+      }
+      break;
     case kDatetime:
       proto.set_type_id(serialization::Type::DATETIME);
       if (!isNull()) {
@@ -171,6 +181,14 @@ TypedValue TypedValue::ReconstructFromProto(const serialization::TypedValue &pro
       return proto.has_double_value() ?
           TypedValue(static_cast<double>(proto.double_value())) :
           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()));
+      } else {
+        return TypedValue(kDate);
+      }
     case serialization::Type::DATETIME:
       if (proto.has_datetime_value()) {
         DatetimeLit datetime;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/TypedValue.hpp
----------------------------------------------------------------------
diff --git a/types/TypedValue.hpp b/types/TypedValue.hpp
index 6e22111..10c3c05 100644
--- a/types/TypedValue.hpp
+++ b/types/TypedValue.hpp
@@ -127,6 +127,14 @@ class TypedValue {
   }
 
   /**
+   * @brief Constructor for a literal value of DateType.
+   **/
+  explicit TypedValue(const DateLit literal_date)
+      : value_info_(static_cast<std::uint64_t>(kDate)) {
+    value_union_.date_value = literal_date;
+  }
+
+  /**
    * @brief Constructor for a literal value of DatetimeType.
    **/
   explicit TypedValue(const DatetimeLit literal_datetime)
@@ -276,6 +284,7 @@ class TypedValue {
       case kLong:
       case kFloat:
       case kDouble:
+      case kDate:
       case kDatetime:
       case kDatetimeInterval:
       case kYearMonthInterval:
@@ -307,6 +316,7 @@ class TypedValue {
         return sizeof(value_union_.int_value) <= sizeof(std::size_t);
       case kLong:
       case kDouble:
+      case kDate:
       case kDatetime:
       case kDatetimeInterval:
       case kYearMonthInterval:
@@ -384,6 +394,7 @@ class TypedValue {
         return sizeof(int);
       case kLong:
       case kDouble:
+      case kDate:
       case kDatetime:
       case kDatetimeInterval:
       case kYearMonthInterval:
@@ -469,6 +480,7 @@ class TypedValue {
                    || getTypeID() == kLong
                    || getTypeID() == kFloat
                    || getTypeID() == kDouble
+                   || getTypeID() == kDate
                    || getTypeID() == kDatetime
                    || getTypeID() == kDatetimeInterval
                    || getTypeID() == kYearMonthInterval));
@@ -564,6 +576,7 @@ class TypedValue {
       case kLong:
       case kFloat:
       case kDouble:
+      case kDate:
       case kDatetime:
       case kDatetimeInterval:
       case kYearMonthInterval:
@@ -659,6 +672,7 @@ class TypedValue {
       case kLong:
       case kFloat:
       case kDouble:
+      case kDate:
       case kDatetime:
       case kDatetimeInterval:
       case kYearMonthInterval:
@@ -778,6 +792,7 @@ class TypedValue {
     float float_value;
     double double_value;
     const void* out_of_line_data;
+    DateLit date_value;
     DatetimeLit datetime_value;
     DatetimeIntervalLit datetime_interval_value;
     YearMonthIntervalLit year_month_interval_value;
@@ -853,6 +868,13 @@ inline double TypedValue::getLiteral<double>() const {
 }
 
 template <>
+inline DateLit TypedValue::getLiteral<DateLit>() const {
+  DCHECK_EQ(kDate, getTypeID());
+  DCHECK(!isNull());
+  return value_union_.date_value;
+}
+
+template <>
 inline DatetimeLit TypedValue::getLiteral<DatetimeLit>() const {
   DCHECK_EQ(kDatetime, getTypeID());
   DCHECK(!isNull());

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/TypedValue.proto
----------------------------------------------------------------------
diff --git a/types/TypedValue.proto b/types/TypedValue.proto
index 78a38cb..c265c73 100644
--- a/types/TypedValue.proto
+++ b/types/TypedValue.proto
@@ -31,4 +31,12 @@ message TypedValue {
   optional int64 datetime_value = 7;
   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;
 }

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/tests/DateType_unittest.cpp
----------------------------------------------------------------------
diff --git a/types/tests/DateType_unittest.cpp b/types/tests/DateType_unittest.cpp
new file mode 100644
index 0000000..5456dec
--- /dev/null
+++ b/types/tests/DateType_unittest.cpp
@@ -0,0 +1,148 @@
+/**
+ *   Copyright 2016 Twitter, Inc.
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ **/
+
+#include <cstddef>
+#include <string>
+
+#include "types/DateType.hpp"
+#include "types/DatetimeLit.hpp"
+#include "types/NullType.hpp"
+#include "types/Type.hpp"
+#include "types/TypeFactory.hpp"
+#include "types/TypeID.hpp"
+#include "types/TypedValue.hpp"
+#include "types/tests/TypeTest_common.hpp"
+#include "utility/MemStream.hpp"
+
+#include "gtest/gtest.h"
+
+namespace quickstep {
+
+TEST(DateTypeTest, PrintValueTest) {
+  const Type &date_type = TypeFactory::GetType(kDate);
+
+  // Skynet becomes self-aware at 2:14 AM on August 29, 1997.
+  TypedValue judgement_day_value(DateLit::Create(1997, 8, 29));
+  EXPECT_EQ(std::string("1997-08-29"),
+            date_type.printValueToString(judgement_day_value));
+
+  // Check extended formatting for years far in the past.
+  TypedValue dawn_age_value(DateLit::Create(-18017, 4, 13));
+  EXPECT_EQ(std::string("-18017-04-13"),
+            date_type.printValueToString(dawn_age_value));
+}
+
+namespace {
+
+static const std::size_t kPaddedLength = 200;
+
+void CheckPrintValueToFile(const DateLit literal_value,
+                           const std::string &expected_string) {
+  // Test writing to FILE* with a MemStream.
+  MemStream memstream;
+
+  const Type &date_type = TypeFactory::GetType(kDate);
+  const TypedValue date_value = date_type.makeValue(&literal_value);
+
+  // First, check printing without any padding
+  date_type.printValueToFile(date_value, memstream.file());
+  EXPECT_STREQ(expected_string.c_str(), memstream.str());
+  memstream.reset();
+
+  // Specifying padding less than the length needed to print the value should
+  // have no effect.
+  date_type.printValueToFile(date_value, memstream.file(), 1);
+  EXPECT_STREQ(expected_string.c_str(), memstream.str());
+  memstream.reset();
+
+  // Test padding up to a specified length.
+  std::string padded(kPaddedLength - expected_string.size(), ' ');
+  padded.append(expected_string);
+  date_type.printValueToFile(date_value, memstream.file(), kPaddedLength);
+  EXPECT_STREQ(padded.c_str(), memstream.str());
+  memstream.reset();
+}
+
+}  // namespace
+
+TEST(DateTypeTest, PrintValueToFileTest) {
+  CheckPrintValueToFile(DateLit::Create(1997, 8, 29), "1997-08-29");
+
+  CheckPrintValueToFile(DateLit::Create(-18017, 4, 13), "-18017-04-13");
+}
+
+TEST(DateTypeTest, ParseValueFromStringTest) {
+  // Parse the same value in a bunch of different valid format variations.
+  type_test::CheckSuccessfulParseLiteralValueFromString<DateType>(
+      DateLit::Create(1997, 8, 29),
+      "1997-08-29");
+  type_test::CheckSuccessfulParseLiteralValueFromString<DateType>(
+      DateLit::Create(1997, 8, 29),
+      "+1997-08-29");
+  type_test::CheckSuccessfulParseLiteralValueFromString<DateType>(
+      DateLit::Create(1997, 8, 29),
+      "+001997-08-29");
+
+  type_test::CheckSuccessfulParseLiteralValueFromString<DateType>(
+      DateLit::Create(1871, 3, 18),
+      "1871-03-18");
+  type_test::CheckSuccessfulParseLiteralValueFromString<DateType>(
+      DateLit::Create(1871, 3, 18),
+      "+1871-03-18");
+  type_test::CheckSuccessfulParseLiteralValueFromString<DateType>(
+      DateLit::Create(1871, 3, 18),
+      "+001871-03-18");
+
+  // Parse extended format with negative year.
+  type_test::CheckSuccessfulParseLiteralValueFromString<DateType>(
+      DateLit::Create(-18017, 4, 13),
+      "-18017-04-13");
+
+  // Test some parses that we expect to fail.
+  const Type &date_type = TypeFactory::GetType(kDate);
+  TypedValue value;
+  EXPECT_FALSE(date_type.parseValueFromString("foo", &value));
+  EXPECT_FALSE(date_type.parseValueFromString("42", &value));
+  EXPECT_FALSE(date_type.parseValueFromString("1997-08-29 ", &value));
+  EXPECT_FALSE(date_type.parseValueFromString(" 1997-08-29 ", &value));
+  EXPECT_FALSE(date_type.parseValueFromString("1997-08-29.", &value));
+  EXPECT_FALSE(date_type.parseValueFromString("1997-08-29q", &value));
+  EXPECT_FALSE(date_type.parseValueFromString("1997-08-29.q", &value));
+  EXPECT_FALSE(date_type.parseValueFromString("1e3-08-29", &value));
+  EXPECT_FALSE(date_type.parseValueFromString("--18017-04-13", &value));
+  EXPECT_FALSE(date_type.parseValueFromString("1997-08--29 ", &value));
+  EXPECT_FALSE(date_type.parseValueFromString("1997-08--2 ", &value));
+}
+
+TEST(DateTypeTest, IsCoercibleFromTest) {
+  type_test::CheckIsCoercibleFrom(DateType::InstanceNonNullable(),
+                                  {kDate});
+}
+
+TEST(DateTypeTest, IsSafelyCoercibleFromTest) {
+  type_test::CheckIsSafelyCoercibleFrom(DateType::InstanceNonNullable(),
+                                        {kDate});
+}
+
+TEST(DateTypeTest, CoerceValueTest) {
+  // The epoch.
+  type_test::CheckLiteralCoerce<DateType, DateType>(DateLit::Create(1970, 1, 1));
+
+  type_test::CheckNullLiteralCoerce<DateType, DateType>();
+  type_test::CheckNullLiteralCoerce<DateType, NullType>();
+}
+
+}  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/615bbaaf/types/tests/TypeTest_common.hpp
----------------------------------------------------------------------
diff --git a/types/tests/TypeTest_common.hpp b/types/tests/TypeTest_common.hpp
index 7cc9cc2..d185405 100644
--- a/types/tests/TypeTest_common.hpp
+++ b/types/tests/TypeTest_common.hpp
@@ -101,7 +101,7 @@ void CheckIsCoercibleFrom(
   // Can't coerce from other types.
   for (const TypeID original_type_id
        : {kInt, kLong, kFloat, kDouble, kChar, kVarChar,
-          kDatetime, kDatetimeInterval, kYearMonthInterval}) {
+          kDate, kDatetime, kDatetimeInterval, kYearMonthInterval}) {
     if (std::find(expected_coercible.begin(), expected_coercible.end(), original_type_id)
         == expected_coercible.end()) {
       const Type &original_type = TypeFactory::TypeRequiresLengthParameter(original_type_id)
@@ -183,7 +183,7 @@ void CheckStringTypeIsCoercibleFrom(const TypeID target_type_id,
 
   // Other types are not coercible to strings.
   for (const TypeID original_type_id
-       : {kInt, kLong, kFloat, kDouble, kDatetime, kDatetimeInterval, kYearMonthInterval}) {
+       : {kInt, kLong, kFloat, kDouble, kDate, kDatetime, kDatetimeInterval, kYearMonthInterval}) {
     const Type &original_type = TypeFactory::TypeRequiresLengthParameter(original_type_id)
                                 ? TypeFactory::GetType(original_type_id, 10, false)
                                 : TypeFactory::GetType(original_type_id, false);
@@ -232,7 +232,7 @@ void CheckIsSafelyCoercibleFrom(
   // Can't coerce from other types.
   for (const TypeID original_type_id
        : {kInt, kLong, kFloat, kDouble, kChar, kVarChar,
-          kDatetime, kDatetimeInterval, kYearMonthInterval}) {
+          kDate, kDatetime, kDatetimeInterval, kYearMonthInterval}) {
     if (std::find(expected_coercible.begin(), expected_coercible.end(), original_type_id)
         == expected_coercible.end()) {
       const Type &original_type = TypeFactory::TypeRequiresLengthParameter(original_type_id)
@@ -314,7 +314,7 @@ void CheckStringTypeIsSafelyCoercibleFrom(const TypeID target_type_id,
 
   // Other types are not coercible to strings.
   for (const TypeID original_type_id
-       : {kInt, kLong, kFloat, kDouble, kDatetime, kDatetimeInterval, kYearMonthInterval}) {
+       : {kInt, kLong, kFloat, kDouble, kDate, kDatetime, kDatetimeInterval, kYearMonthInterval}) {
     const Type &original_type = TypeFactory::TypeRequiresLengthParameter(original_type_id)
                                 ? TypeFactory::GetType(original_type_id, 10, false)
                                 : TypeFactory::GetType(original_type_id, false);