You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@quickstep.apache.org by ji...@apache.org on 2017/05/04 03:23:10 UTC

[26/32] incubator-quickstep git commit: Refactor type system and operations.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/types/CMakeLists.txt b/types/CMakeLists.txt
index 769187b..df4462f 100644
--- a/types/CMakeLists.txt
+++ b/types/CMakeLists.txt
@@ -32,6 +32,8 @@ QS_PROTOBUF_GENERATE_CPP(types_TypedValue_proto_srcs types_TypedValue_proto_hdrs
 QS_PROTOBUF_GENERATE_CPP(types_Type_proto_srcs types_Type_proto_hdrs Type.proto)
 
 # Declare micro-libs:
+add_library(quickstep_types_AsciiStringSuperType ../empty_src.cpp AsciiStringSuperType.hpp)
+add_library(quickstep_types_BoolType BoolType.cpp BoolType.hpp)
 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)
@@ -47,11 +49,16 @@ add_library(quickstep_types_LongType LongType.cpp LongType.hpp)
 add_library(quickstep_types_NullCoercibilityCheckMacro ../empty_src.cpp NullCoercibilityCheckMacro.hpp)
 add_library(quickstep_types_NullType ../empty_src.cpp NullType.hpp)
 add_library(quickstep_types_NumericSuperType ../empty_src.cpp NumericSuperType.hpp)
+add_library(quickstep_types_NumericTypeSafeCoercibility ../empty_src.cpp NumericTypeSafeCoercibility.hpp)
 add_library(quickstep_types_NumericTypeUnifier ../empty_src.cpp NumericTypeUnifier.hpp)
 add_library(quickstep_types_Type Type.cpp Type.hpp)
 add_library(quickstep_types_TypeErrors ../empty_src.cpp TypeErrors.hpp)
 add_library(quickstep_types_TypeFactory TypeFactory.cpp TypeFactory.hpp)
 add_library(quickstep_types_TypeID TypeID.cpp TypeID.hpp)
+add_library(quickstep_types_TypeIDSelectors ../empty_src.cpp TypeIDSelectors.hpp)
+add_library(quickstep_types_TypeRegistrar ../empty_src.cpp TypeRegistrar.hpp)
+add_library(quickstep_types_TypeSynthesizer ../empty_src.cpp TypeSynthesizer.hpp)
+add_library(quickstep_types_TypeUtil ../empty_src.cpp TypeUtil.hpp)
 add_library(quickstep_types_Type_proto ${types_Type_proto_srcs})
 add_library(quickstep_types_TypedValue TypedValue.cpp TypedValue.hpp)
 add_library(quickstep_types_TypedValue_proto ${types_TypedValue_proto_srcs})
@@ -59,8 +66,20 @@ add_library(quickstep_types_VarCharType VarCharType.cpp VarCharType.hpp)
 add_library(quickstep_types_YearMonthIntervalType YearMonthIntervalType.cpp YearMonthIntervalType.hpp)
 
 # Link dependencies:
+target_link_libraries(quickstep_types_AsciiStringSuperType
+                      quickstep_types_Type
+                      quickstep_types_TypeID
+                      quickstep_types_TypeSynthesizer)
+target_link_libraries(quickstep_types_BoolType
+                      glog
+                      quickstep_types_NumericSuperType
+                      quickstep_types_TypeID
+                      quickstep_types_TypedValue
+                      quickstep_utility_Macros
+                      quickstep_utility_StringUtil)
 target_link_libraries(quickstep_types_CharType
                       glog
+                      quickstep_types_AsciiStringSuperType
                       quickstep_types_NullCoercibilityCheckMacro
                       quickstep_types_Type
                       quickstep_types_TypeID
@@ -77,9 +96,9 @@ target_link_libraries(quickstep_types_DateOperatorOverloads
 target_link_libraries(quickstep_types_DateType
                       glog
                       quickstep_types_DatetimeLit
-                      quickstep_types_NullCoercibilityCheckMacro
                       quickstep_types_Type
                       quickstep_types_TypeID
+                      quickstep_types_TypeSynthesizer
                       quickstep_types_TypedValue
                       quickstep_utility_CheckSnprintf
                       quickstep_utility_Macros)
@@ -87,9 +106,9 @@ target_link_libraries(quickstep_types_DatetimeIntervalType
                       glog
                       quickstep_types_IntervalLit
                       quickstep_types_IntervalParser
-                      quickstep_types_NullCoercibilityCheckMacro
                       quickstep_types_Type
                       quickstep_types_TypeID
+                      quickstep_types_TypeSynthesizer
                       quickstep_types_TypedValue
                       quickstep_utility_CheckSnprintf
                       quickstep_utility_Macros)
@@ -98,35 +117,27 @@ target_link_libraries(quickstep_types_DatetimeLit
 target_link_libraries(quickstep_types_DatetimeType
                       glog
                       quickstep_types_DatetimeLit
-                      quickstep_types_NullCoercibilityCheckMacro
                       quickstep_types_Type
                       quickstep_types_TypeID
+                      quickstep_types_TypeSynthesizer
                       quickstep_types_TypedValue
                       quickstep_types_port_gmtime_r
                       quickstep_types_port_timegm
                       quickstep_utility_CheckSnprintf
                       quickstep_utility_Macros)
 target_link_libraries(quickstep_types_DoubleType
-                      quickstep_types_NullCoercibilityCheckMacro
                       quickstep_types_NumericSuperType
-                      quickstep_types_Type
                       quickstep_types_TypeID
                       quickstep_types_TypedValue
-                      quickstep_utility_EqualsAnyConstant
                       quickstep_utility_Macros)
 target_link_libraries(quickstep_types_FloatType
-                      quickstep_types_NullCoercibilityCheckMacro
                       quickstep_types_NumericSuperType
-                      quickstep_types_Type
                       quickstep_types_TypeID
                       quickstep_types_TypedValue
-                      quickstep_utility_EqualsAnyConstant
                       quickstep_utility_Macros)
 target_link_libraries(quickstep_types_IntType
                       glog
-                      quickstep_types_NullCoercibilityCheckMacro
                       quickstep_types_NumericSuperType
-                      quickstep_types_Type
                       quickstep_types_TypeID
                       quickstep_types_TypedValue
                       quickstep_utility_Macros)
@@ -138,27 +149,30 @@ target_link_libraries(quickstep_types_IntervalParser
                       quickstep_utility_Macros)
 target_link_libraries(quickstep_types_LongType
                       glog
-                      quickstep_types_NullCoercibilityCheckMacro
                       quickstep_types_NumericSuperType
-                      quickstep_types_Type
                       quickstep_types_TypeID
                       quickstep_types_TypedValue
-                      quickstep_utility_EqualsAnyConstant
                       quickstep_utility_Macros)
-target_link_libraries(quickstep_types_NullCoercibilityCheckMacro
-                      quickstep_types_Type
-                      quickstep_types_TypeID)
 target_link_libraries(quickstep_types_NullType
                       glog
                       quickstep_types_Type
                       quickstep_types_TypeID
+                      quickstep_types_TypeSynthesizer
                       quickstep_utility_Macros)
 target_link_libraries(quickstep_types_NumericSuperType
                       quickstep_types_NullCoercibilityCheckMacro
+                      quickstep_types_NumericTypeSafeCoercibility
                       quickstep_types_Type
                       quickstep_types_TypeID
+                      quickstep_types_TypeRegistrar
+                      quickstep_types_TypeSynthesizer
                       quickstep_types_TypedValue
-                      quickstep_utility_Macros)
+                      quickstep_utility_Macros
+                      quickstep_utility_meta_TMP)
+target_link_libraries(quickstep_types_NumericTypeSafeCoercibility
+                      quickstep_utility_meta_TMP)
+target_link_libraries(quickstep_types_NumericTypeUnifier
+                      quickstep_types_NumericTypeSafeCoercibility)
 target_link_libraries(quickstep_types_Type
                       glog
                       quickstep_types_Type_proto
@@ -167,6 +181,33 @@ target_link_libraries(quickstep_types_Type
                       quickstep_utility_Macros)
 target_link_libraries(quickstep_types_TypeFactory
                       glog
+                      quickstep_types_Type
+                      quickstep_types_TypeID
+                      quickstep_types_TypeUtil
+                      quickstep_types_Type_proto
+                      quickstep_utility_Macros)
+target_link_libraries(quickstep_types_TypeID
+                      quickstep_types_Type_proto
+                      quickstep_utility_Macros)
+target_link_libraries(quickstep_types_TypeIDSelectors
+                      quickstep_types_TypeID
+                      quickstep_utility_meta_Common)
+target_link_libraries(quickstep_types_TypeRegistrar
+                      quickstep_types_DatetimeLit
+                      quickstep_types_IntervalLit
+                      quickstep_types_Type
+                      quickstep_types_TypeID
+                      quickstep_types_TypeIDSelectors
+                      quickstep_utility_meta_Common)
+target_link_libraries(quickstep_types_TypeSynthesizer
+                      quickstep_types_Type
+                      quickstep_types_TypeID
+                      quickstep_types_TypeRegistrar
+                      quickstep_types_Type_proto
+                      quickstep_utility_Macros
+                      quickstep_utility_PtrMap)
+target_link_libraries(quickstep_types_TypeUtil
+                      quickstep_types_BoolType
                       quickstep_types_CharType
                       quickstep_types_DateType
                       quickstep_types_DatetimeIntervalType
@@ -178,7 +219,7 @@ target_link_libraries(quickstep_types_TypeFactory
                       quickstep_types_NullType
                       quickstep_types_Type
                       quickstep_types_TypeID
-                      quickstep_types_Type_proto
+                      quickstep_types_TypeRegistrar
                       quickstep_types_VarCharType
                       quickstep_types_YearMonthIntervalType
                       quickstep_utility_Macros)
@@ -200,6 +241,7 @@ target_link_libraries(quickstep_types_Type_proto
                       ${PROTOBUF_LIBRARY})
 target_link_libraries(quickstep_types_VarCharType
                       glog
+                      quickstep_types_AsciiStringSuperType
                       quickstep_types_NullCoercibilityCheckMacro
                       quickstep_types_Type
                       quickstep_types_TypeID
@@ -211,9 +253,9 @@ target_link_libraries(quickstep_types_VarCharType
 target_link_libraries(quickstep_types_YearMonthIntervalType
                       quickstep_types_IntervalLit
                       quickstep_types_IntervalParser
-                      quickstep_types_NullCoercibilityCheckMacro
                       quickstep_types_Type
                       quickstep_types_TypeID
+                      quickstep_types_TypeSynthesizer
                       quickstep_types_TypedValue
                       quickstep_utility_CheckSnprintf
                       quickstep_utility_Macros)
@@ -221,6 +263,8 @@ target_link_libraries(quickstep_types_YearMonthIntervalType
 # Module all-in-one library:
 add_library(quickstep_types ../empty_src.cpp TypesModule.hpp)
 target_link_libraries(quickstep_types
+                      quickstep_types_AsciiStringSuperType
+                      quickstep_types_BoolType
                       quickstep_types_CharType
                       quickstep_types_DateOperatorOverloads
                       quickstep_types_DateType
@@ -236,12 +280,17 @@ target_link_libraries(quickstep_types
                       quickstep_types_NullCoercibilityCheckMacro
                       quickstep_types_NullType
                       quickstep_types_NumericSuperType
+                      quickstep_types_NumericTypeSafeCoercibility
                       quickstep_types_NumericTypeUnifier
                       quickstep_types_Type
+                      quickstep_types_TypeUtil
                       quickstep_types_Type_proto
                       quickstep_types_TypeErrors
                       quickstep_types_TypeFactory
                       quickstep_types_TypeID
+                      quickstep_types_TypeIDSelectors
+                      quickstep_types_TypeRegistrar
+                      quickstep_types_TypeSynthesizer
                       quickstep_types_TypedValue
                       quickstep_types_TypedValue_proto
                       quickstep_types_VarCharType

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/CharType.cpp
----------------------------------------------------------------------
diff --git a/types/CharType.cpp b/types/CharType.cpp
index 591c038..2ed469b 100644
--- a/types/CharType.cpp
+++ b/types/CharType.cpp
@@ -42,38 +42,6 @@ using std::string;
 
 namespace quickstep {
 
-template <bool nullable_internal>
-const CharType& CharType::InstanceInternal(const std::size_t length) {
-  static PtrMap<size_t, CharType> instance_map;
-  PtrMap<size_t, CharType>::iterator imit = instance_map.find(length);
-  if (imit == instance_map.end()) {
-    imit = instance_map.insert(length, new CharType(length, nullable_internal)).first;
-  }
-  return *(imit->second);
-}
-
-const CharType& CharType::InstanceNonNullable(const std::size_t length) {
-  return InstanceInternal<false>(length);
-}
-
-const CharType& CharType::InstanceNullable(const std::size_t length) {
-  return InstanceInternal<true>(length);
-}
-
-const CharType& CharType::InstanceFromProto(const serialization::Type &proto) {
-  return Instance(proto.GetExtension(serialization::CharType::length), proto.nullable());
-}
-
-serialization::Type CharType::getProto() const {
-  serialization::Type proto;
-  proto.set_type_id(serialization::Type::CHAR);
-
-  proto.set_nullable(nullable_);
-
-  proto.SetExtension(serialization::CharType::length, length_);
-  return proto;
-}
-
 bool CharType::isSafelyCoercibleFrom(const Type &original_type) const {
   QUICKSTEP_NULL_COERCIBILITY_CHECK();
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/CharType.hpp
----------------------------------------------------------------------
diff --git a/types/CharType.hpp b/types/CharType.hpp
index c7321f4..c90a8da 100644
--- a/types/CharType.hpp
+++ b/types/CharType.hpp
@@ -24,8 +24,8 @@
 #include <cstdio>
 #include <string>
 
+#include "types/AsciiStringSuperType.hpp"
 #include "types/Type.hpp"
-#include "types/Type.pb.h"
 #include "types/TypeID.hpp"
 #include "types/TypedValue.hpp"
 #include "utility/Macros.hpp"
@@ -43,75 +43,8 @@ namespace quickstep {
  *       represented WITHOUT a null-terminator character. Any strings shorter
  *       than the maximum length will have a null-terminator.
  **/
-class CharType : public AsciiStringSuperType {
+class CharType : public AsciiStringSuperType<kChar> {
  public:
-  /**
-   * @brief Get a reference to the non-nullable singleton instance of this Type
-   *        for the specified length.
-   *
-   * @param length The length parameter of the CharType.
-   * @return A reference to the non-nullable singleton instance of this Type
-   *         for the specified length.
-   **/
-  static const CharType& InstanceNonNullable(const std::size_t length);
-
-  /**
-   * @brief Get a reference to the nullable singleton instance of this Type for
-   *        the specified length.
-   *
-   * @param length The length parameter of the CharType.
-   * @return A reference to the nullable singleton instance of this Type for
-   *         the specified length.
-   **/
-  static const CharType& InstanceNullable(const std::size_t length);
-
-  /**
-   * @brief Get a reference to the singleton instance of this Type for the
-   *        specified length and nullability.
-   *
-   * @param length The length parameter of the CharType.
-   * @param nullable Whether to get the nullable version of this Type.
-   * @return A reference to the singleton instance of this Type for the
-   *         specified length.
-   **/
-  static const CharType& Instance(const std::size_t length, const bool nullable) {
-    if (nullable) {
-      return InstanceNullable(length);
-    } else {
-      return InstanceNonNullable(length);
-    }
-  }
-
-  /**
-   * @brief Get a reference to the singleton instance of this Type described
-   *        by the given Protocol Buffer serialization.
-   *
-   * @param proto The serialized Protocol Buffer representation of the desired
-   *        CharType.
-   * @return A reference to the singleton instance of this Type for the given
-   *         Protocol Buffer.
-   **/
-  static const CharType& InstanceFromProto(const serialization::Type &proto);
-
-  /**
-   * @brief Generate a serialized Protocol Buffer representation of this Type.
-   *
-   * @return The serialized Protocol Buffer representation of this Type.
-   **/
-  serialization::Type getProto() const override;
-
-  const Type& getNullableVersion() const override {
-    return InstanceNullable(length_);
-  }
-
-  const Type& getNonNullableVersion() const override {
-    return InstanceNonNullable(length_);
-  }
-
-  std::size_t estimateAverageByteLength() const override {
-    return length_;
-  }
-
   bool isSafelyCoercibleFrom(const Type &original_type) const override;
 
   std::string getName() const override;
@@ -134,11 +67,9 @@ class CharType : public AsciiStringSuperType {
 
  private:
   CharType(const std::size_t length, const bool nullable)
-      : AsciiStringSuperType(kChar, nullable, length, length, length) {
-  }
+      : AsciiStringSuperType<kChar>(nullable, length, length, length) {}
 
-  template <bool nullable_internal>
-  static const CharType& InstanceInternal(const std::size_t length);
+  template <typename, bool> friend class TypeInstance;
 
   DISALLOW_COPY_AND_ASSIGN(CharType);
 };

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/DateType.cpp
----------------------------------------------------------------------
diff --git a/types/DateType.cpp b/types/DateType.cpp
index 5bb982c..de1e554 100644
--- a/types/DateType.cpp
+++ b/types/DateType.cpp
@@ -30,7 +30,6 @@
 #include <string>
 
 #include "types/DatetimeLit.hpp"
-#include "types/NullCoercibilityCheckMacro.hpp"
 #include "types/Type.hpp"
 #include "types/TypeID.hpp"
 #include "types/TypedValue.hpp"
@@ -46,16 +45,6 @@ using std::snprintf;
 
 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());
 
@@ -86,14 +75,6 @@ std::string DateType::printValueToString(const TypedValue &value) const {
   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;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/DateType.hpp
----------------------------------------------------------------------
diff --git a/types/DateType.hpp b/types/DateType.hpp
index 07225d5..088c125 100644
--- a/types/DateType.hpp
+++ b/types/DateType.hpp
@@ -27,6 +27,7 @@
 #include "types/DatetimeLit.hpp"
 #include "types/Type.hpp"
 #include "types/TypeID.hpp"
+#include "types/TypeSynthesizer.hpp"
 #include "utility/Macros.hpp"
 
 namespace quickstep {
@@ -40,73 +41,14 @@ class TypedValue;
 /**
  * @brief A type representing the date.
  **/
-class DateType : public Type {
+class DateType : public TypeSynthesizer<kDate> {
  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
@@ -124,8 +66,9 @@ class DateType : public Type {
 
  private:
   explicit DateType(const bool nullable)
-      : Type(Type::kOther, kDate, nullable, sizeof(DateLit), sizeof(DateLit)) {
-  }
+      : TypeSynthesizer<kDate>(nullable) {}
+
+  template <typename, bool> friend class TypeInstance;
 
   DISALLOW_COPY_AND_ASSIGN(DateType);
 };

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/DatetimeIntervalType.cpp
----------------------------------------------------------------------
diff --git a/types/DatetimeIntervalType.cpp b/types/DatetimeIntervalType.cpp
index 1eae03a..2c77f89 100644
--- a/types/DatetimeIntervalType.cpp
+++ b/types/DatetimeIntervalType.cpp
@@ -31,7 +31,6 @@
 
 #include "types/IntervalLit.hpp"
 #include "types/IntervalParser.hpp"
-#include "types/NullCoercibilityCheckMacro.hpp"
 #include "types/Type.hpp"
 #include "types/TypeID.hpp"
 #include "types/TypedValue.hpp"
@@ -47,16 +46,6 @@ using std::snprintf;
 
 namespace quickstep {
 
-bool DatetimeIntervalType::isCoercibleFrom(const Type &original_type) const {
-  QUICKSTEP_NULL_COERCIBILITY_CHECK();
-  return (original_type.getTypeID() == kDatetimeInterval);
-}
-
-bool DatetimeIntervalType::isSafelyCoercibleFrom(const Type &original_type) const {
-  QUICKSTEP_NULL_COERCIBILITY_CHECK();
-  return (original_type.getTypeID() == kDatetimeInterval);
-}
-
 std::string DatetimeIntervalType::printValueToString(const TypedValue &value) const {
   DCHECK(!value.isNull());
 
@@ -121,14 +110,6 @@ std::string DatetimeIntervalType::printValueToString(const TypedValue &value) co
   return std::string(interval_buf);
 }
 
-void DatetimeIntervalType::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 DatetimeIntervalType::parseValueFromString(const std::string &value_string,
                                                 TypedValue *value) const {
   // Try simple-format parse first.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/DatetimeIntervalType.hpp
----------------------------------------------------------------------
diff --git a/types/DatetimeIntervalType.hpp b/types/DatetimeIntervalType.hpp
index 005cb31..d22f965 100644
--- a/types/DatetimeIntervalType.hpp
+++ b/types/DatetimeIntervalType.hpp
@@ -28,6 +28,7 @@
 #include "types/IntervalLit.hpp"
 #include "types/Type.hpp"
 #include "types/TypeID.hpp"
+#include "types/TypeSynthesizer.hpp"
 #include "types/TypedValue.hpp"
 #include "utility/Macros.hpp"
 
@@ -40,73 +41,14 @@ namespace quickstep {
 /**
  * @brief A type representing the datetime interval.
  **/
-class DatetimeIntervalType : public Type {
+class DatetimeIntervalType : public TypeSynthesizer<kDatetimeInterval> {
  public:
-  typedef DatetimeIntervalLit cpptype;
-
-  static const TypeID kStaticTypeID = kDatetimeInterval;
-
-  /**
-   * @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 DatetimeIntervalType& InstanceNonNullable() {
-    static DatetimeIntervalType 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 DatetimeIntervalType& InstanceNullable() {
-    static DatetimeIntervalType 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 DatetimeIntervalType& 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(DatetimeIntervalLit);
-  }
-
-  bool isCoercibleFrom(const Type &original_type) const override;
-
-  bool isSafelyCoercibleFrom(const Type &original_type) const override;
-
   int getPrintWidth() const override {
     return DatetimeIntervalLit::kPrintingChars;
   }
 
   std::string printValueToString(const TypedValue &value) const override;
 
-  void printValueToFile(const TypedValue &value,
-                        FILE *file,
-                        const int padding = 0) const override;
-
   TypedValue makeZeroValue() const override {
     return TypedValue(DatetimeIntervalLit{0});
   }
@@ -116,8 +58,9 @@ class DatetimeIntervalType : public Type {
 
  private:
   explicit DatetimeIntervalType(const bool nullable)
-      : Type(Type::kOther, kDatetimeInterval, nullable, sizeof(DatetimeIntervalLit), sizeof(DatetimeIntervalLit)) {
-  }
+      : TypeSynthesizer<kDatetimeInterval>(nullable) {}
+
+  template <typename, bool> friend class TypeInstance;
 
   DISALLOW_COPY_AND_ASSIGN(DatetimeIntervalType);
 };

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/DatetimeLit.hpp
----------------------------------------------------------------------
diff --git a/types/DatetimeLit.hpp b/types/DatetimeLit.hpp
index 58c852f..db887eb 100644
--- a/types/DatetimeLit.hpp
+++ b/types/DatetimeLit.hpp
@@ -99,6 +99,10 @@ struct DateLit {
   inline std::int32_t monthField() const {
     return static_cast<std::int32_t>(month);
   }
+
+  inline std::int32_t dayField() const {
+    return static_cast<std::int32_t>(day);
+  }
 };
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/DatetimeType.cpp
----------------------------------------------------------------------
diff --git a/types/DatetimeType.cpp b/types/DatetimeType.cpp
index f54f318..723da61 100644
--- a/types/DatetimeType.cpp
+++ b/types/DatetimeType.cpp
@@ -33,7 +33,6 @@
 #include <string>
 
 #include "types/DatetimeLit.hpp"
-#include "types/NullCoercibilityCheckMacro.hpp"
 #include "types/Type.hpp"
 #include "types/TypeID.hpp"
 #include "types/TypedValue.hpp"
@@ -51,16 +50,6 @@ using std::snprintf;
 
 namespace quickstep {
 
-bool DatetimeType::isCoercibleFrom(const Type &original_type) const {
-  QUICKSTEP_NULL_COERCIBILITY_CHECK();
-  return (original_type.getTypeID() == kDatetime);
-}
-
-bool DatetimeType::isSafelyCoercibleFrom(const Type &original_type) const {
-  QUICKSTEP_NULL_COERCIBILITY_CHECK();
-  return (original_type.getTypeID() == kDatetime);
-}
-
 std::string DatetimeType::printValueToString(const TypedValue &value) const {
   DCHECK(!value.isNull());
 
@@ -114,14 +103,6 @@ std::string DatetimeType::printValueToString(const TypedValue &value) const {
   return std::string(datebuf);
 }
 
-void DatetimeType::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 DatetimeType::parseValueFromString(const std::string &value_string,
                                         TypedValue *value) const {
   int year;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/DatetimeType.hpp
----------------------------------------------------------------------
diff --git a/types/DatetimeType.hpp b/types/DatetimeType.hpp
index aad536a..6ee15c6 100644
--- a/types/DatetimeType.hpp
+++ b/types/DatetimeType.hpp
@@ -27,6 +27,7 @@
 #include "types/DatetimeLit.hpp"
 #include "types/Type.hpp"
 #include "types/TypeID.hpp"
+#include "types/TypeSynthesizer.hpp"
 #include "utility/Macros.hpp"
 
 namespace quickstep {
@@ -40,73 +41,15 @@ class TypedValue;
 /**
  * @brief A type representing the datetime.
  **/
-class DatetimeType : public Type {
+class DatetimeType
+    : public TypeSynthesizer<kDatetime> {
  public:
-  typedef DatetimeLit cpptype;
-
-  static const TypeID kStaticTypeID = kDatetime;
-
-  /**
-   * @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 DatetimeType& InstanceNonNullable() {
-    static DatetimeType 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 DatetimeType& InstanceNullable() {
-    static DatetimeType 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 DatetimeType& 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(DatetimeLit);
-  }
-
-  bool isCoercibleFrom(const Type &original_type) const override;
-
-  bool isSafelyCoercibleFrom(const Type &original_type) const override;
-
   int getPrintWidth() const override {
     return DatetimeLit::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 format is one of the following:
@@ -132,8 +75,9 @@ class DatetimeType : public Type {
 
  private:
   explicit DatetimeType(const bool nullable)
-      : Type(Type::kOther, kDatetime, nullable, sizeof(DatetimeLit), sizeof(DatetimeLit)) {
-  }
+      : TypeSynthesizer<kDatetime>(nullable) {}
+
+  template <typename, bool> friend class TypeInstance;
 
   DISALLOW_COPY_AND_ASSIGN(DatetimeType);
 };

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/DoubleType.cpp
----------------------------------------------------------------------
diff --git a/types/DoubleType.cpp b/types/DoubleType.cpp
index 6a7914c..f5c2650 100644
--- a/types/DoubleType.cpp
+++ b/types/DoubleType.cpp
@@ -25,11 +25,8 @@
 #include <limits>
 #include <string>
 
-#include "types/NullCoercibilityCheckMacro.hpp"
-#include "types/Type.hpp"
 #include "types/TypeID.hpp"
 #include "types/TypedValue.hpp"
-#include "utility/EqualsAnyConstant.hpp"
 
 #include "glog/logging.h"
 
@@ -41,39 +38,6 @@ using std::snprintf;
 
 namespace quickstep {
 
-const TypeID DoubleType::kStaticTypeID = kDouble;
-
-bool DoubleType::isSafelyCoercibleFrom(const Type &original_type) const {
-  QUICKSTEP_NULL_COERCIBILITY_CHECK();
-  return QUICKSTEP_EQUALS_ANY_CONSTANT(original_type.getTypeID(),
-                                       kInt, kLong, kFloat, kDouble);
-}
-
-TypedValue DoubleType::coerceValue(const TypedValue &original_value,
-                                   const Type &original_type) const {
-  DCHECK(isCoercibleFrom(original_type))
-      << "Can't coerce value of Type " << original_type.getName()
-      << " to Type " << getName();
-
-  if (original_value.isNull()) {
-    return makeNullValue();
-  }
-
-  switch (original_type.getTypeID()) {
-    case kInt:
-      return TypedValue(static_cast<double>(original_value.getLiteral<int>()));
-    case kLong:
-      return TypedValue(static_cast<double>(original_value.getLiteral<std::int64_t>()));
-    case kFloat:
-      return TypedValue(static_cast<double>(original_value.getLiteral<float>()));
-    case kDouble:
-      return original_value;
-    default:
-      LOG(FATAL) << "Attempted to coerce Type " << original_type.getName()
-                 << " (not recognized as a numeric Type) to " << getName();
-  }
-}
-
 std::string DoubleType::printValueToString(const TypedValue &value) const {
   DCHECK(!value.isNull());
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/DoubleType.hpp
----------------------------------------------------------------------
diff --git a/types/DoubleType.hpp b/types/DoubleType.hpp
index b4175b0..05bec64 100644
--- a/types/DoubleType.hpp
+++ b/types/DoubleType.hpp
@@ -26,12 +26,12 @@
 
 #include "types/NumericSuperType.hpp"
 #include "types/TypeID.hpp"
-#include "types/TypedValue.hpp"
 #include "utility/Macros.hpp"
 
 namespace quickstep {
 
 class Type;
+class TypedValue;
 
 /** \addtogroup Types
  *  @{
@@ -40,55 +40,8 @@ class Type;
 /**
  * @brief A type representing a double-precision floating-point number.
  **/
-class DoubleType : public NumericSuperType<double> {
+class DoubleType : public NumericSuperType<kDouble> {
  public:
-  static const TypeID kStaticTypeID;
-
-  /**
-   * @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 DoubleType& InstanceNonNullable() {
-    static DoubleType 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 DoubleType& InstanceNullable() {
-    static DoubleType 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 DoubleType& 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();
-  }
-
-  bool isSafelyCoercibleFrom(const Type &original_type) const override;
-
   int getPrintWidth() const override {
     return kPrintWidth;
   }
@@ -102,9 +55,6 @@ class DoubleType : public NumericSuperType<double> {
   bool parseValueFromString(const std::string &value_string,
                             TypedValue *value) const override;
 
-  TypedValue coerceValue(const TypedValue &original_value,
-                         const Type &original_type) const override;
-
  private:
   static_assert((std::numeric_limits<double>::max_exponent10 < 1000)
                     && (std::numeric_limits<double>::min_exponent10 > -1000),
@@ -122,8 +72,9 @@ class DoubleType : public NumericSuperType<double> {
               // exponent never takes more than 3 base-10 digits to represent.
 
   explicit DoubleType(const bool nullable)
-      : NumericSuperType<double>(kDouble, nullable) {
-  }
+      : NumericSuperType<kDouble>(nullable) {}
+
+  template <typename, bool> friend class TypeInstance;
 
   DISALLOW_COPY_AND_ASSIGN(DoubleType);
 };

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/FloatType.cpp
----------------------------------------------------------------------
diff --git a/types/FloatType.cpp b/types/FloatType.cpp
index e904f29..be22770 100644
--- a/types/FloatType.cpp
+++ b/types/FloatType.cpp
@@ -25,11 +25,8 @@
 #include <limits>
 #include <string>
 
-#include "types/NullCoercibilityCheckMacro.hpp"
-#include "types/Type.hpp"
 #include "types/TypeID.hpp"
 #include "types/TypedValue.hpp"
-#include "utility/EqualsAnyConstant.hpp"
 
 #include "glog/logging.h"
 
@@ -41,39 +38,6 @@ using std::snprintf;
 
 namespace quickstep {
 
-const TypeID FloatType::kStaticTypeID = kFloat;
-
-bool FloatType::isSafelyCoercibleFrom(const Type &original_type) const {
-  QUICKSTEP_NULL_COERCIBILITY_CHECK();
-  return QUICKSTEP_EQUALS_ANY_CONSTANT(original_type.getTypeID(),
-                                       kInt, kFloat);
-}
-
-TypedValue FloatType::coerceValue(const TypedValue &original_value,
-                                  const Type &original_type) const {
-  DCHECK(isCoercibleFrom(original_type))
-      << "Can't coerce value of Type " << original_type.getName()
-      << " to Type " << getName();
-
-  if (original_value.isNull()) {
-    return makeNullValue();
-  }
-
-  switch (original_type.getTypeID()) {
-    case kInt:
-      return TypedValue(static_cast<float>(original_value.getLiteral<int>()));
-    case kLong:
-      return TypedValue(static_cast<float>(original_value.getLiteral<std::int64_t>()));
-    case kFloat:
-      return original_value;
-    case kDouble:
-      return TypedValue(static_cast<float>(original_value.getLiteral<double>()));
-    default:
-      LOG(FATAL) << "Attempted to coerce Type " << original_type.getName()
-                 << " (not recognized as a numeric Type) to " << getName();
-  }
-}
-
 std::string FloatType::printValueToString(const TypedValue &value) const {
   DCHECK(!value.isNull());
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/FloatType.hpp
----------------------------------------------------------------------
diff --git a/types/FloatType.hpp b/types/FloatType.hpp
index 2a156e1..6c8466d 100644
--- a/types/FloatType.hpp
+++ b/types/FloatType.hpp
@@ -26,12 +26,12 @@
 
 #include "types/NumericSuperType.hpp"
 #include "types/TypeID.hpp"
-#include "types/TypedValue.hpp"
 #include "utility/Macros.hpp"
 
 namespace quickstep {
 
 class Type;
+class TypedValue;
 
 /** \addtogroup Types
  *  @{
@@ -40,55 +40,8 @@ class Type;
 /**
  * @brief A type representing a single-precision floating-point number.
  **/
-class FloatType : public NumericSuperType<float> {
+class FloatType : public NumericSuperType<kFloat> {
  public:
-  static const TypeID kStaticTypeID;
-
-  /**
-   * @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 FloatType& InstanceNonNullable() {
-    static FloatType 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 FloatType& InstanceNullable() {
-    static FloatType 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 FloatType& 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();
-  }
-
-  bool isSafelyCoercibleFrom(const Type &original_type) const override;
-
   int getPrintWidth() const override {
     return kPrintWidth;
   }
@@ -102,9 +55,6 @@ class FloatType : public NumericSuperType<float> {
   bool parseValueFromString(const std::string &value_string,
                             TypedValue *value) const override;
 
-  TypedValue coerceValue(const TypedValue &original_value,
-                         const Type &original_type) const override;
-
  private:
   static_assert((std::numeric_limits<float>::max_exponent10 < 100)
                     && (std::numeric_limits<float>::min_exponent10 > -100),
@@ -122,8 +72,9 @@ class FloatType : public NumericSuperType<float> {
               // never takes more than 2 base-10 digits to represent.
 
   explicit FloatType(const bool nullable)
-      : NumericSuperType<float>(kFloat, nullable) {
-  }
+      : NumericSuperType<kFloat>(nullable) {}
+
+  template <typename, bool> friend class TypeInstance;
 
   DISALLOW_COPY_AND_ASSIGN(FloatType);
 };

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/IntType.cpp
----------------------------------------------------------------------
diff --git a/types/IntType.cpp b/types/IntType.cpp
index 9781675..1005aa9 100644
--- a/types/IntType.cpp
+++ b/types/IntType.cpp
@@ -19,12 +19,9 @@
 
 #include "types/IntType.hpp"
 
-#include <cstdint>
 #include <cstdio>
 #include <string>
 
-#include "types/NullCoercibilityCheckMacro.hpp"
-#include "types/Type.hpp"
 #include "types/TypeID.hpp"
 #include "types/TypedValue.hpp"
 
@@ -32,38 +29,6 @@
 
 namespace quickstep {
 
-const TypeID IntType::kStaticTypeID = kInt;
-
-bool IntType::isSafelyCoercibleFrom(const Type &original_type) const {
-  QUICKSTEP_NULL_COERCIBILITY_CHECK();
-  return original_type.getTypeID() == kInt;
-}
-
-TypedValue IntType::coerceValue(const TypedValue &original_value,
-                                const Type &original_type) const {
-  DCHECK(isCoercibleFrom(original_type))
-      << "Can't coerce value of Type " << original_type.getName()
-      << " to Type " << getName();
-
-  if (original_value.isNull()) {
-    return makeNullValue();
-  }
-
-  switch (original_type.getTypeID()) {
-    case kInt:
-      return original_value;
-    case kLong:
-      return TypedValue(static_cast<int>(original_value.getLiteral<std::int64_t>()));
-    case kFloat:
-      return TypedValue(static_cast<int>(original_value.getLiteral<float>()));
-    case kDouble:
-      return TypedValue(static_cast<int>(original_value.getLiteral<double>()));
-    default:
-      LOG(FATAL) << "Attempted to coerce Type " << original_type.getName()
-                 << " (not recognized as a numeric Type) to " << getName();
-  }
-}
-
 std::string IntType::printValueToString(const TypedValue &value) const {
   DCHECK(!value.isNull());
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/IntType.hpp
----------------------------------------------------------------------
diff --git a/types/IntType.hpp b/types/IntType.hpp
index 08d6b3d..84cc7ce 100644
--- a/types/IntType.hpp
+++ b/types/IntType.hpp
@@ -26,12 +26,12 @@
 
 #include "types/NumericSuperType.hpp"
 #include "types/TypeID.hpp"
-#include "types/TypedValue.hpp"
 #include "utility/Macros.hpp"
 
 namespace quickstep {
 
 class Type;
+class TypedValue;
 
 /** \addtogroup Types
  *  @{
@@ -40,55 +40,8 @@ class Type;
 /**
  * @brief A type representing a 32-bit integer.
  **/
-class IntType : public NumericSuperType<int> {
+class IntType : public NumericSuperType<kInt> {
  public:
-  static const TypeID kStaticTypeID;
-
-  /**
-   * @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 IntType& InstanceNonNullable() {
-    static IntType 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 IntType& InstanceNullable() {
-    static IntType 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 IntType& 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();
-  }
-
-  bool isSafelyCoercibleFrom(const Type &original_type) const override;
-
   int getPrintWidth() const override {
     // Fully represented digits, single leading digit, and possible '-'
     // character.
@@ -104,13 +57,11 @@ class IntType : public NumericSuperType<int> {
   bool parseValueFromString(const std::string &value_string,
                             TypedValue *value) const override;
 
-  TypedValue coerceValue(const TypedValue &original_value,
-                         const Type &original_type) const override;
-
  private:
   explicit IntType(const bool nullable)
-      : NumericSuperType<int>(kInt, nullable) {
-  }
+      : NumericSuperType<kInt>(nullable) {}
+
+  template <typename, bool> friend class TypeInstance;
 
   DISALLOW_COPY_AND_ASSIGN(IntType);
 };

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/LongType.cpp
----------------------------------------------------------------------
diff --git a/types/LongType.cpp b/types/LongType.cpp
index fbf8d30..334821d 100644
--- a/types/LongType.cpp
+++ b/types/LongType.cpp
@@ -28,49 +28,13 @@
 #include <cstdio>
 #include <string>
 
-#include "types/NullCoercibilityCheckMacro.hpp"
-#include "types/Type.hpp"
 #include "types/TypeID.hpp"
 #include "types/TypedValue.hpp"
-#include "utility/EqualsAnyConstant.hpp"
 
 #include "glog/logging.h"
 
 namespace quickstep {
 
-const TypeID LongType::kStaticTypeID = kLong;
-
-bool LongType::isSafelyCoercibleFrom(const Type &original_type) const {
-  QUICKSTEP_NULL_COERCIBILITY_CHECK();
-  return QUICKSTEP_EQUALS_ANY_CONSTANT(original_type.getTypeID(),
-                                       kInt, kLong);
-}
-
-TypedValue LongType::coerceValue(const TypedValue &original_value,
-                                 const Type &original_type) const {
-  DCHECK(isCoercibleFrom(original_type))
-      << "Can't coerce value of Type " << original_type.getName()
-      << " to Type " << getName();
-
-  if (original_value.isNull()) {
-    return makeNullValue();
-  }
-
-  switch (original_type.getTypeID()) {
-    case kInt:
-      return TypedValue(static_cast<std::int64_t>(original_value.getLiteral<int>()));
-    case kLong:
-      return original_value;
-    case kFloat:
-      return TypedValue(static_cast<std::int64_t>(original_value.getLiteral<float>()));
-    case kDouble:
-      return TypedValue(static_cast<std::int64_t>(original_value.getLiteral<double>()));
-    default:
-      LOG(FATAL) << "Attempted to coerce Type " << original_type.getName()
-                 << " (not recognized as a numeric Type) to " << getName();
-  }
-}
-
 std::string LongType::printValueToString(const TypedValue &value) const {
   DCHECK(!value.isNull());
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/LongType.hpp
----------------------------------------------------------------------
diff --git a/types/LongType.hpp b/types/LongType.hpp
index a90dd32..e52a166 100644
--- a/types/LongType.hpp
+++ b/types/LongType.hpp
@@ -27,12 +27,12 @@
 
 #include "types/NumericSuperType.hpp"
 #include "types/TypeID.hpp"
-#include "types/TypedValue.hpp"
 #include "utility/Macros.hpp"
 
 namespace quickstep {
 
 class Type;
+class TypedValue;
 
 /** \addtogroup Types
  *  @{
@@ -41,55 +41,8 @@ class Type;
 /**
  * @brief A type representing a 64-bit integer.
  **/
-class LongType : public NumericSuperType<std::int64_t> {
+class LongType : public NumericSuperType<kLong> {
  public:
-  static const TypeID kStaticTypeID;
-
-  /**
-   * @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 LongType& InstanceNonNullable() {
-    static LongType 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 LongType& InstanceNullable() {
-    static LongType 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 LongType& 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();
-  }
-
-  bool isSafelyCoercibleFrom(const Type &original_type) const override;
-
   // Fully represented digits, single leading digit, and possible '-'
   // character.
   int getPrintWidth() const override {
@@ -105,13 +58,11 @@ class LongType : public NumericSuperType<std::int64_t> {
   bool parseValueFromString(const std::string &value_string,
                             TypedValue *value) const override;
 
-  TypedValue coerceValue(const TypedValue &original_value,
-                         const Type &original_type) const override;
-
  private:
   explicit LongType(const bool nullable)
-      : NumericSuperType<std::int64_t>(kLong, nullable) {
-  }
+      : NumericSuperType<kLong>(nullable) {}
+
+  template <typename, bool> friend class TypeInstance;
 
   DISALLOW_COPY_AND_ASSIGN(LongType);
 };

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/NullCoercibilityCheckMacro.hpp
----------------------------------------------------------------------
diff --git a/types/NullCoercibilityCheckMacro.hpp b/types/NullCoercibilityCheckMacro.hpp
index 70e1beb..9cdd152 100644
--- a/types/NullCoercibilityCheckMacro.hpp
+++ b/types/NullCoercibilityCheckMacro.hpp
@@ -20,9 +20,6 @@
 #ifndef QUICKSTEP_TYPES_NULL_COERCIBILITY_CHECK_MACRO_HPP_
 #define QUICKSTEP_TYPES_NULL_COERCIBILITY_CHECK_MACRO_HPP_
 
-#include "types/Type.hpp"
-#include "types/TypeID.hpp"
-
 /** \addtogroup Types
  *  @{
  */
@@ -34,7 +31,7 @@
  **/
 #define QUICKSTEP_NULL_COERCIBILITY_CHECK()               \
   do {                                                    \
-    if (original_type.isNullable() && !nullable_) {       \
+    if (original_type.isNullable() && !this->nullable_) {       \
       return false;                                       \
     } else if (original_type.getTypeID() == kNullType) {  \
       return true;                                        \

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/NullType.hpp
----------------------------------------------------------------------
diff --git a/types/NullType.hpp b/types/NullType.hpp
index c27a584..c416a05 100644
--- a/types/NullType.hpp
+++ b/types/NullType.hpp
@@ -26,6 +26,7 @@
 
 #include "types/Type.hpp"
 #include "types/TypeID.hpp"
+#include "types/TypeSynthesizer.hpp"
 #include "utility/Macros.hpp"
 
 #include "glog/logging.h"
@@ -48,40 +49,20 @@ class TypedValue;
  *       a particular operation may accept. It is also assumed that applying
  *       any operation to an argument of NullType always yields NULL values.
  **/
-class NullType : public Type {
+class NullType : public TypeSynthesizer<kNullType> {
  public:
-  static const TypeID kStaticTypeID = kNullType;
-
-  /**
-   * @brief Get a reference to the nullable singleton instance of this Type.
-   * @note Unlike other Types, there is no corresponding method to get a
-   *       non-nullable version of NullType. NullType is ALWAYS nullable.
-   *
-   * @return A reference to the nullable singleton instance of this Type.
-   **/
-  static const NullType& InstanceNullable() {
-    static NullType instance;
-    return instance;
+  static const NullType& InstanceNonNullable() {
+    LOG(FATAL) << "Called NullType::InstanceNonNullable(), "
+               << "which is not allowed.";
   }
 
-  const Type& getNullableVersion() const override {
-    return InstanceNullable();
-  }
-
-  const Type& getNonNullableVersion() const override {
-    LOG(FATAL) << "Called NullType::getNonNullableVersion(), which is not allowed.";
-  }
-
-  std::size_t estimateAverageByteLength() const override {
-    return 0;
-  }
-
-  bool isCoercibleFrom(const Type &original_type) const override {
-    return original_type.getTypeID() == kNullType;
-  }
-
-  bool isSafelyCoercibleFrom(const Type &original_type) const override {
-    return original_type.getTypeID() == kNullType;
+  static const NullType& Instance(const bool nullable) {
+    if (nullable) {
+      return InstanceNullable();
+    } else {
+      LOG(FATAL) << "Called NullType::Instance(nullable = true), "
+                 << "which is not allowed.";
+    }
   }
 
   int getPrintWidth() const override {
@@ -106,9 +87,13 @@ class NullType : public Type {
  private:
   // NOTE(chasseur): NullType requires 0 bytes of inherent storage. It does,
   // however, require a bit in NULL bitmaps.
-  NullType() : Type(Type::kOther, kNullType, true, 0, 0) {
+  NullType(const bool nullable)
+      : TypeSynthesizer<kNullType>(nullable, 0, 0) {
+    DCHECK(nullable);
   }
 
+  template <typename, bool> friend class TypeInstance;
+
   DISALLOW_COPY_AND_ASSIGN(NullType);
 };
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/NumericSuperType.hpp
----------------------------------------------------------------------
diff --git a/types/NumericSuperType.hpp b/types/NumericSuperType.hpp
index 0cc1546..abe8b87 100644
--- a/types/NumericSuperType.hpp
+++ b/types/NumericSuperType.hpp
@@ -21,12 +21,17 @@
 #define QUICKSTEP_TYPES_NUMERIC_SUPER_TYPE_HPP_
 
 #include <cstddef>
+#include <unordered_set>
 
 #include "types/NullCoercibilityCheckMacro.hpp"
+#include "types/NumericTypeSafeCoercibility.hpp"
 #include "types/Type.hpp"
 #include "types/TypeID.hpp"
+#include "types/TypeRegistrar.hpp"
+#include "types/TypeSynthesizer.hpp"
 #include "types/TypedValue.hpp"
 #include "utility/Macros.hpp"
+#include "utility/meta/TMP.hpp"
 
 namespace quickstep {
 
@@ -38,30 +43,72 @@ namespace quickstep {
  * @brief Templatized superclass for Numeric types. Contains code common to all
  *        Numeric types.
  **/
-template <typename CppType>
-class NumericSuperType : public Type {
+template <TypeID type_id>
+class NumericSuperType : public TypeSynthesizer<type_id> {
  public:
-  typedef CppType cpptype;
-
-  std::size_t estimateAverageByteLength() const override {
-    return sizeof(CppType);
+  bool isSafelyCoercibleFrom(const Type &original_type) const override {
+    QUICKSTEP_NULL_COERCIBILITY_CHECK();
+    const auto it = safe_coerce_cache_.find(original_type.getTypeID());
+    return it != safe_coerce_cache_.end();
   }
 
   bool isCoercibleFrom(const Type &original_type) const override {
     QUICKSTEP_NULL_COERCIBILITY_CHECK();
-    return (original_type.getSuperTypeID() == kNumeric);
+    return (original_type.getSuperTypeID() == Type::kNumeric);
   }
 
   TypedValue makeZeroValue() const override {
-    return TypedValue(static_cast<CppType>(0));
+    return TypedValue(static_cast<typename TypeIDTrait<type_id>::cpptype>(0));
   }
 
- protected:
-  NumericSuperType(const TypeID type_id, const bool nullable)
-      : Type(Type::kNumeric, type_id, nullable, sizeof(CppType), sizeof(CppType)) {
+  TypedValue coerceValue(const TypedValue &original_value,
+                         const Type &original_type) const override {
+    if (original_type.getSuperTypeID() != Type::kNumeric) {
+      LOG(FATAL) << "Attempted to coerce Type " << original_type.getName()
+                 << " (not recognized as a numeric Type) to " << Type::getName();
+    }
+
+    if (original_value.isNull()) {
+      return Type::makeNullValue();
+    }
+
+    return InvokeOnTypeID<TypeIDSelectorNumeric>(
+        original_type.getTypeID(),
+        [&](auto orig_tid) -> TypedValue {  // NOLINT(build/c++11)
+      using OrigCppType = typename TypeIDTrait<decltype(orig_tid)::value>::cpptype;
+      using TargetCppType = typename TypeIDTrait<type_id>::cpptype;
+
+      return TypedValue(
+          static_cast<TargetCppType>(original_value.getLiteral<OrigCppType>()));
+    });
   }
 
+ protected:
+  explicit NumericSuperType(const bool nullable)
+      : TypeSynthesizer<type_id>(nullable),
+        safe_coerce_cache_(CreateSafeCoercibilityCache()) {}
+
  private:
+  using TargetType = typename TypeIDTrait<type_id>::TypeClass;
+
+  template <typename SourceTypeID>
+  struct SafeCoercibilityFilter {
+    static constexpr bool value =
+        NumericTypeSafeCoercibility<
+            typename TypeIDTrait<SourceTypeID::value>::TypeClass,
+            TargetType>::value;
+  };
+
+  inline static auto CreateSafeCoercibilityCache() {
+    using SourceTypeIDs = TypeIDSequenceAll::template bind_to<meta::TypeList>;
+    using ResultTypeIDs = SourceTypeIDs::template filter<SafeCoercibilityFilter>;
+
+    return ResultTypeIDs::template as_sequence<TypeID>
+        ::template Instantiate<std::unordered_set<TypeID>>();
+  };
+
+  const std::unordered_set<TypeID> safe_coerce_cache_;
+
   DISALLOW_COPY_AND_ASSIGN(NumericSuperType);
 };
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/NumericTypeSafeCoercibility.hpp
----------------------------------------------------------------------
diff --git a/types/NumericTypeSafeCoercibility.hpp b/types/NumericTypeSafeCoercibility.hpp
new file mode 100644
index 0000000..914927c
--- /dev/null
+++ b/types/NumericTypeSafeCoercibility.hpp
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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_NUMERIC_TYPE_SAFE_COERCIBILITY_HPP_
+#define QUICKSTEP_TYPES_NUMERIC_TYPE_SAFE_COERCIBILITY_HPP_
+
+#include "utility/meta/TMP.hpp"
+
+namespace quickstep {
+
+class BoolType;
+class DoubleType;
+class FloatType;
+class IntType;
+class LongType;
+
+/** \addtogroup Types
+ *  @{
+ */
+
+template <typename LeftType, typename RightType>
+using IsSafelyCoercible = meta::TypeList<LeftType, RightType>;
+
+using NumericTypeSafeCoersionPartialOrder = meta::TypeList<
+    IsSafelyCoercible<BoolType, IntType>,
+    IsSafelyCoercible<IntType, FloatType>,
+    IsSafelyCoercible<IntType, LongType>,
+    IsSafelyCoercible<FloatType, DoubleType>,
+    IsSafelyCoercible<LongType, DoubleType>>;
+
+using NumericTypeSafeCoersionClosure =
+    meta::TransitiveClosure<NumericTypeSafeCoersionPartialOrder>;
+
+template <typename LeftType, typename RightType>
+struct NumericTypeSafeCoercibility {
+  static constexpr bool value =
+      NumericTypeSafeCoersionClosure::contains<
+          IsSafelyCoercible<LeftType, RightType>>::value;
+};
+
+/** @} */
+
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_TYPES_NUMERIC_TYPE_SAFE_COERCIBILITY_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/NumericTypeUnifier.hpp
----------------------------------------------------------------------
diff --git a/types/NumericTypeUnifier.hpp b/types/NumericTypeUnifier.hpp
index 168dfb1..0c3f13f 100644
--- a/types/NumericTypeUnifier.hpp
+++ b/types/NumericTypeUnifier.hpp
@@ -20,16 +20,9 @@
 #ifndef QUICKSTEP_TYPES_NUMERIC_TYPE_UNIFIER_HPP_
 #define QUICKSTEP_TYPES_NUMERIC_TYPE_UNIFIER_HPP_
 
-namespace quickstep {
-
-class DoubleType;
-class FloatType;
-class IntType;
-class LongType;
+#include "types/NumericTypeSafeCoercibility.hpp"
 
-/** \addtogroup Types
- *  @{
- */
+namespace quickstep {
 
 /**
  * @brief A traits template that resolves what the "unifying" Type of two
@@ -51,92 +44,47 @@ class LongType;
  * @tparam RightType The second Quickstep numeric Type class to unify.
  **/
 template <typename LeftType, typename RightType>
-struct NumericTypeUnifier {
-};
+struct NumericTypeUnifier;
 
-/** @} */
 
-// Explicit template specializations for all combinations of builtin numeric
-// types.
-template<>
-struct NumericTypeUnifier<IntType, IntType> {
-  typedef IntType type;
-};
+namespace internal {
 
-template<>
-struct NumericTypeUnifier<IntType, LongType> {
-  typedef LongType type;
-};
-
-template<>
-struct NumericTypeUnifier<IntType, FloatType> {
-  typedef FloatType type;
-};
+template <typename LeftType, typename RightType, typename EnableT = void>
+struct NumericTypeUnifierHelper;
 
-template<>
-struct NumericTypeUnifier<IntType, DoubleType> {
-  typedef DoubleType type;
-};
-
-template<>
-struct NumericTypeUnifier<LongType, IntType> {
-  typedef LongType type;
-};
-
-template<>
-struct NumericTypeUnifier<LongType, LongType> {
-  typedef LongType type;
-};
-
-template<>
-struct NumericTypeUnifier<LongType, FloatType> {
-  typedef DoubleType type;
-};
-
-template<>
-struct NumericTypeUnifier<LongType, DoubleType> {
-  typedef DoubleType type;
-};
-
-template<>
-struct NumericTypeUnifier<FloatType, IntType> {
-  typedef FloatType type;
-};
-
-template<>
-struct NumericTypeUnifier<FloatType, LongType> {
-  typedef DoubleType type;
+template <typename LeftType, typename RightType>
+struct NumericTypeUnifierHelper<
+    LeftType, RightType,
+    std::enable_if_t<NumericTypeSafeCoercibility<LeftType, RightType>::value>> {
+  typedef RightType type;
 };
 
-template<>
-struct NumericTypeUnifier<FloatType, FloatType> {
-  typedef FloatType type;
+template <typename LeftType, typename RightType>
+struct NumericTypeUnifierHelper<
+    LeftType, RightType,
+    std::enable_if_t<!std::is_same<LeftType, RightType>::value &&
+                     NumericTypeSafeCoercibility<RightType, LeftType>::value>> {
+  typedef LeftType type;
 };
 
+// Explicit template specializations
 template<>
-struct NumericTypeUnifier<FloatType, DoubleType> {
+struct NumericTypeUnifierHelper<LongType, FloatType> {
   typedef DoubleType type;
 };
 
 template<>
-struct NumericTypeUnifier<DoubleType, IntType> {
+struct NumericTypeUnifierHelper<FloatType, LongType> {
   typedef DoubleType type;
 };
 
-template<>
-struct NumericTypeUnifier<DoubleType, LongType> {
-  typedef DoubleType type;
-};
+}  // namespace internal
 
-template<>
-struct NumericTypeUnifier<DoubleType, FloatType> {
-  typedef DoubleType type;
-};
+template <typename LeftType, typename RightType>
+struct NumericTypeUnifier
+    : internal::NumericTypeUnifierHelper<LeftType, RightType> {};
 
-template<>
-struct NumericTypeUnifier<DoubleType, DoubleType> {
-  typedef DoubleType type;
-};
+/** @} */
 
 }  // namespace quickstep
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/Type.cpp
----------------------------------------------------------------------
diff --git a/types/Type.cpp b/types/Type.cpp
index f3d3f1b..b69cb65 100644
--- a/types/Type.cpp
+++ b/types/Type.cpp
@@ -28,43 +28,35 @@
 
 namespace quickstep {
 
-serialization::Type Type::getProto() const {
-  serialization::Type proto;
-  switch (type_id_) {
-    case kInt:
-      proto.set_type_id(serialization::Type::INT);
-      break;
-    case kLong:
-      proto.set_type_id(serialization::Type::LONG);
-      break;
-    case kFloat:
-      proto.set_type_id(serialization::Type::FLOAT);
-      break;
-    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;
-    case kDatetimeInterval:
-      proto.set_type_id(serialization::Type::DATETIME_INTERVAL);
-      break;
-    case kYearMonthInterval:
-      proto.set_type_id(serialization::Type::YEAR_MONTH_INTERVAL);
-      break;
-    case kNullType:
-      proto.set_type_id(serialization::Type::NULL_TYPE);
-      break;
-    default:
-      FATAL_ERROR("Unrecognized TypeID in Type::getProto");
+bool Type::isCoercibleFrom(const Type &original_type) const {
+  return isSafelyCoercibleFrom(original_type);
+}
+
+bool Type::isSafelyCoercibleFrom(const Type &original_type) const {
+  if (original_type.isNullable() && !this->nullable_) {
+    return false;
   }
+  if (original_type.getTypeID() == kNullType) {
+    return true;
+  }
+  return (original_type.getTypeID() == type_id_);
+}
 
-  proto.set_nullable(nullable_);
+std::size_t Type::estimateAverageByteLength() const {
+  if (minimum_byte_length_ == maximum_byte_length_) {
+    return maximum_byte_length_;
+  }
+  if (maximum_byte_length_ > 160) {
+    return 80;
+  } else {
+    return (maximum_byte_length_ >> 1) + 1;
+  }
+}
 
-  return proto;
+void Type::printValueToFile(const TypedValue &value,
+                            FILE *file,
+                            const int padding) const {
+  std::fprintf(file, "%*s", padding, printValueToString(value).c_str());
 }
 
 TypedValue Type::coerceValue(const TypedValue &original_value,
@@ -85,12 +77,4 @@ TypedValue Type::coerceValue(const TypedValue &original_value,
   return original_value;
 }
 
-bool AsciiStringSuperType::isCoercibleFrom(const Type &original_type) const {
-  if (original_type.isNullable() && !nullable_) {
-    return false;
-  }
-  return (original_type.getSuperTypeID() == kAsciiString)
-         || (original_type.getTypeID() == kNullType);
-}
-
 }  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/Type.hpp
----------------------------------------------------------------------
diff --git a/types/Type.hpp b/types/Type.hpp
index 0e8c4e5..bf6c167 100644
--- a/types/Type.hpp
+++ b/types/Type.hpp
@@ -112,7 +112,7 @@ class Type {
    *
    * @return The serialized Protocol Buffer representation of this Type.
    **/
-  virtual serialization::Type getProto() const;
+  virtual serialization::Type getProto() const = 0;
 
   /**
    * @brief Determine what supertype this type belongs to.
@@ -154,16 +154,7 @@ class Type {
     TypeSignature sig;
     sig.id = type_id_;
     sig.nullable = nullable_;
-    switch (type_id_) {
-      case kChar:
-        sig.length = maximum_byte_length_;
-        break;
-      case kVarChar:
-        sig.length = maximum_byte_length_ - 1;
-        break;
-      default:
-        sig.length = 0;
-    }
+    sig.length = parameter_;
     return sig;
   }
 
@@ -227,7 +218,7 @@ class Type {
    * @return An estimate of the average number of bytes used by data items of
    *         this type.
    **/
-  virtual std::size_t estimateAverageByteLength() const = 0;
+  virtual std::size_t estimateAverageByteLength() const;
 
   /**
    * @brief Determine whether this Type is exactly the same as another.
@@ -255,7 +246,7 @@ class Type {
    * @param original_type The original Type for coercion to this Type.
    * @return true if coercion is supported, false otherwise.
    **/
-  virtual bool isCoercibleFrom(const Type &original_type) const = 0;
+  virtual bool isCoercibleFrom(const Type &original_type) const;
 
   /**
    * @brief Determine whether data items of another type can be coerced (used
@@ -264,7 +255,7 @@ class Type {
    * @note It is NOT possible to coerce a nullable type to a non-nullable type,
    *       even if coercion would otherwise be possible.
    * @note Integer types are safely coercible to other integer or
-   *       floating-poin types of equal or greater length.
+   *       floating-point types of equal or greater length.
    * @note Floating-point types are safely coercible to other floating-point
    *       types of equal or greater precision.
    * @note ASCII string types are safely coercible to other ASCII string types
@@ -277,7 +268,7 @@ class Type {
    * @param original_type The original Type for coercion to this Type.
    * @return true if coercion is supported, false otherwise.
    **/
-  virtual bool isSafelyCoercibleFrom(const Type &original_type) const = 0;
+  virtual bool isSafelyCoercibleFrom(const Type &original_type) const;
 
   /**
    * @brief Determine whether data items of this type are always guaranteed to
@@ -348,7 +339,7 @@ class Type {
    **/
   virtual void printValueToFile(const TypedValue &value,
                                 FILE *file,
-                                const int padding = 0) const = 0;
+                                const int padding = 0) const;
 
   /**
    * @brief Make a TypedValue of this Type.
@@ -453,10 +444,12 @@ class Type {
        const TypeID type_id,
        const bool nullable,
        const std::size_t minimum_byte_length,
-       const std::size_t maximum_byte_length)
+       const std::size_t maximum_byte_length,
+       const std::size_t parameter = 0)
       : super_type_id_(super_type_id),
         type_id_(type_id),
         nullable_(nullable),
+        parameter_(parameter),
         minimum_byte_length_(minimum_byte_length),
         maximum_byte_length_(maximum_byte_length) {
   }
@@ -464,6 +457,7 @@ class Type {
   const SuperTypeID super_type_id_;
   const TypeID type_id_;
   const bool nullable_;
+  const std::size_t parameter_;
   const std::size_t minimum_byte_length_;
   const std::size_t maximum_byte_length_;
 
@@ -471,38 +465,6 @@ class Type {
   DISALLOW_COPY_AND_ASSIGN(Type);
 };
 
-/**
- * @brief A superclass for ASCII string types.
- **/
-class AsciiStringSuperType : public Type {
- public:
-  bool isCoercibleFrom(const Type &original_type) const override;
-
-  /**
-   * @brief Get the character-length of this string type.
-   *
-   * @return The maximum length of a string of this type.
-   **/
-  inline std::size_t getStringLength() const {
-    return length_;
-  }
-
- protected:
-  AsciiStringSuperType(const TypeID type_id,
-                       const bool nullable,
-                       const std::size_t minimum_byte_length,
-                       const std::size_t maximum_byte_length,
-                       const std::size_t string_length)
-      : Type(Type::kAsciiString, type_id, nullable, minimum_byte_length, maximum_byte_length),
-        length_(string_length) {
-  }
-
-  const std::size_t length_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AsciiStringSuperType);
-};
-
 /** @} */
 
 }  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/Type.proto
----------------------------------------------------------------------
diff --git a/types/Type.proto b/types/Type.proto
index d03b5a4..ed8df36 100644
--- a/types/Type.proto
+++ b/types/Type.proto
@@ -19,39 +19,13 @@ syntax = "proto2";
 
 package quickstep.serialization;
 
-message Type {
-  enum TypeID {
-    INT = 0;
-    LONG = 1;
-    FLOAT = 2;
-    DOUBLE = 3;
-    CHAR = 4;
-    VAR_CHAR = 5;
-    DATETIME = 6;
-    DATETIME_INTERVAL = 7;
-    YEAR_MONTH_INTERVAL = 8;
-    NULL_TYPE = 9;
-    DATE = 10;
-  }
+message TypeID {
+  required int32 id = 1;
+}
 
+message Type {
   required TypeID type_id = 1;
   required bool nullable = 2;
-
-  // The convention for extension numbering is that extensions for a particular
-  // TypeID should begin from (type_id + 1) * 32.
-  extensions 32 to max;
+  optional uint64 length = 3;
 }
 
-message CharType {
-  extend Type {
-    // Required when type_id == CHAR.
-    optional uint64 length = 160;
-  }
-}
-
-message VarCharType {
-  extend Type {
-    // Required when type_id == VAR_CHAR.
-    optional uint64 length = 192;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/TypeFactory.cpp
----------------------------------------------------------------------
diff --git a/types/TypeFactory.cpp b/types/TypeFactory.cpp
index 7403dc9..66efc92 100644
--- a/types/TypeFactory.cpp
+++ b/types/TypeFactory.cpp
@@ -22,66 +22,45 @@
 #include <cstddef>
 #include <string>
 
-#include "types/CharType.hpp"
-#include "types/DateType.hpp"
-#include "types/DatetimeIntervalType.hpp"
-#include "types/DatetimeType.hpp"
-#include "types/DoubleType.hpp"
-#include "types/FloatType.hpp"
-#include "types/IntType.hpp"
-#include "types/LongType.hpp"
-#include "types/NullType.hpp"
 #include "types/Type.hpp"
 #include "types/Type.pb.h"
 #include "types/TypeID.hpp"
-#include "types/VarCharType.hpp"
-#include "types/YearMonthIntervalType.hpp"
+#include "types/TypeUtil.hpp"
 #include "utility/Macros.hpp"
 
 #include "glog/logging.h"
 
 namespace quickstep {
 
+bool TypeFactory::TypeRequiresLengthParameter(const TypeID id) {
+  return TypeUtil::IsParameterized(id);
+}
+
 const Type& TypeFactory::GetType(const TypeID id,
                                  const bool nullable) {
-  switch (id) {
-    case kInt:
-      return IntType::Instance(nullable);
-    case kLong:
-      return LongType::Instance(nullable);
-    case kFloat:
-      return FloatType::Instance(nullable);
-    case kDouble:
-      return DoubleType::Instance(nullable);
-    case kDate:
-      return DateType::Instance(nullable);
-    case kDatetime:
-      return DatetimeType::Instance(nullable);
-    case kDatetimeInterval:
-      return DatetimeIntervalType::Instance(nullable);
-    case kYearMonthInterval:
-      return YearMonthIntervalType::Instance(nullable);
-    case kNullType:
-      DCHECK(nullable);
-      return NullType::InstanceNullable();
-    default:
-      FATAL_ERROR("Called TypeFactory::GetType() for a type which requires "
-                  " a length parameter without specifying one.");
-  }
+  DCHECK(!TypeRequiresLengthParameter(id))
+      << "Called TypeFactory::GetType() for a type which requires "
+      << " a length parameter without specifying one.";
+
+  return *InvokeOnTypeID<TypeIDSelectorNonParameterized>(
+      id,
+      [&](auto id) -> const Type* {  // NOLINT(build/c++11)
+    return &TypeIDTrait<decltype(id)::value>::TypeClass::Instance(nullable);
+  });
 }
 
 const Type& TypeFactory::GetType(const TypeID id,
                                  const std::size_t length,
                                  const bool nullable) {
-  switch (id) {
-    case kChar:
-      return CharType::Instance(length, nullable);
-    case kVarChar:
-      return VarCharType::Instance(length, nullable);
-    default:
-      FATAL_ERROR("Provided a length parameter to TypeFactory::GetType() for "
-                  "a type which does not take one.");
-  }
+  DCHECK(TypeRequiresLengthParameter(id))
+      << "Provided a length parameter to TypeFactory::GetType() for "
+      << "a type which does not take one.";
+
+  return *InvokeOnTypeID<TypeIDSelectorParameterized>(
+      id,
+      [&](auto id) -> const Type* {  // NOLINT(build/c++11)
+    return &TypeIDTrait<decltype(id)::value>::TypeClass::Instance(nullable, length);
+  });
 }
 
 bool TypeFactory::ProtoIsValid(const serialization::Type &proto) {
@@ -90,26 +69,18 @@ bool TypeFactory::ProtoIsValid(const serialization::Type &proto) {
     return false;
   }
 
-  // Check that the type_id is valid, and extensions if any.
-  switch (proto.type_id()) {
-    case serialization::Type::INT:
-    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:
-      return true;
-    case serialization::Type::CHAR:
-      return proto.HasExtension(serialization::CharType::length);
-    case serialization::Type::VAR_CHAR:
-      return proto.HasExtension(serialization::VarCharType::length);
-    case serialization::Type::NULL_TYPE:
-      return proto.nullable();
-    default:
-      return false;
+  // Check that the type_id is valid, and has length if parameterized.
+  const TypeID type_id = TypeIDFactory::ReconstructFromProto(proto.type_id());
+
+  if (type_id == kNullType) {
+    return proto.nullable();
+  }
+
+  if (TypeRequiresLengthParameter(type_id)) {
+    return proto.has_length();
   }
+
+  return true;
 }
 
 const Type& TypeFactory::ReconstructFromProto(const serialization::Type &proto) {
@@ -117,32 +88,12 @@ const Type& TypeFactory::ReconstructFromProto(const serialization::Type &proto)
       << "Attempted to create Type from an invalid proto description:\n"
       << proto.DebugString();
 
-  switch (proto.type_id()) {
-    case serialization::Type::INT:
-      return IntType::Instance(proto.nullable());
-    case serialization::Type::LONG:
-      return LongType::Instance(proto.nullable());
-    case serialization::Type::FLOAT:
-      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:
-      return DatetimeIntervalType::Instance(proto.nullable());
-    case serialization::Type::YEAR_MONTH_INTERVAL:
-      return YearMonthIntervalType::Instance(proto.nullable());
-    case serialization::Type::CHAR:
-      return CharType::InstanceFromProto(proto);
-    case serialization::Type::VAR_CHAR:
-      return VarCharType::InstanceFromProto(proto);
-    case serialization::Type::NULL_TYPE:
-      DCHECK(proto.nullable());
-      return NullType::InstanceNullable();
-    default:
-      FATAL_ERROR("Unrecognized TypeID in TypeFactory::ReconstructFromProto");
+  const TypeID type_id = TypeIDFactory::ReconstructFromProto(proto.type_id());
+
+  if (TypeRequiresLengthParameter(type_id)) {
+    return GetType(type_id, proto.length(), proto.nullable());
+  } else {
+    return GetType(type_id, proto.nullable());
   }
 }
 
@@ -157,9 +108,11 @@ const Type* TypeFactory::GetMostSpecificType(const Type &first, const Type &seco
 }
 
 const Type* TypeFactory::GetUnifyingType(const Type &first, const Type &second) {
+  // TODO: cache
   const Type *unifier = nullptr;
   if (first.isNullable() || second.isNullable()) {
-    unifier = GetMostSpecificType(first.getNullableVersion(), second.getNullableVersion());
+    unifier = GetMostSpecificType(first.getNullableVersion(),
+                                  second.getNullableVersion());
     if (unifier == nullptr) {
       if (((first.getTypeID() == kLong) && (second.getTypeID() == kFloat))
             || ((first.getTypeID() == kFloat) && (second.getTypeID() == kLong))) {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/TypeFactory.hpp
----------------------------------------------------------------------
diff --git a/types/TypeFactory.hpp b/types/TypeFactory.hpp
index 742348e..89ff497 100644
--- a/types/TypeFactory.hpp
+++ b/types/TypeFactory.hpp
@@ -48,25 +48,7 @@ class TypeFactory {
    * @param id The id of the desired Type.
    * @return Whether a length must be specified for Types of the given id.
    **/
-  static bool TypeRequiresLengthParameter(const TypeID id) {
-    switch (id) {
-      case kInt:
-      case kLong:
-      case kFloat:
-      case kDouble:
-      case kDate:
-      case kDatetime:
-      case kDatetimeInterval:
-      case kYearMonthInterval:
-      case kNullType:
-        return false;
-      case kChar:
-      case kVarChar:
-        return true;
-      default:
-        FATAL_ERROR("Unrecognized TypeID in TypeFactory::TypeRequiresLengthParameter");
-    }
-  }
+  static bool TypeRequiresLengthParameter(const TypeID id);
 
   /**
    * @brief Factory method to get a Type by its TypeID.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/TypeID.cpp
----------------------------------------------------------------------
diff --git a/types/TypeID.cpp b/types/TypeID.cpp
index ff2f8e6..afc9c2b 100644
--- a/types/TypeID.cpp
+++ b/types/TypeID.cpp
@@ -22,6 +22,7 @@
 namespace quickstep {
 
 const char *kTypeNames[] = {
+  "Bool",
   "Int",
   "Long",
   "Float",

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/583724ea/types/TypeID.hpp
----------------------------------------------------------------------
diff --git a/types/TypeID.hpp b/types/TypeID.hpp
index c54d8a5..d27368c 100644
--- a/types/TypeID.hpp
+++ b/types/TypeID.hpp
@@ -21,6 +21,10 @@
 #define QUICKSTEP_TYPES_TYPE_ID_HPP_
 
 #include <cstddef>
+#include <type_traits>
+
+#include "types/Type.pb.h"
+#include "utility/Macros.hpp"
 
 namespace quickstep {
 
@@ -29,8 +33,9 @@ namespace quickstep {
  *
  * @note TypedValue assumes that this doesn't exceed 64 TypeIDs.
  **/
-enum TypeID {
-  kInt = 0,
+enum TypeID : int {
+  kBool = 0,
+  kInt,
   kLong,
   kFloat,
   kDouble,
@@ -44,6 +49,13 @@ enum TypeID {
   kNumTypeIDs  // Not a real TypeID, exists for counting purposes.
 };
 
+enum TypeStorageLayout {
+  kNativeEmbedded,
+  kNativeInline,
+  kNonNativeInline,
+  kOutOfLine
+};
+
 /**
  * @brief Provides basic information about a Type in the Quickstep type system.
  *
@@ -65,6 +77,26 @@ struct TypeSignature {
  **/
 extern const char *kTypeNames[kNumTypeIDs];
 
+class TypeIDFactory {
+ public:
+  inline static serialization::TypeID GetProto(const TypeID type_id) {
+    serialization::TypeID proto;
+    proto.set_id(static_cast<std::underlying_type_t<TypeID>>(type_id));
+    return proto;
+  }
+
+  inline static TypeID ReconstructFromProto(const serialization::TypeID &proto) {
+    return static_cast<TypeID>(proto.id());
+  }
+
+  inline static bool ProtoIsValid(const serialization::TypeID &proto) {
+    return proto.id() < static_cast<std::underlying_type_t<TypeID>>(kNumTypeIDs);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TypeIDFactory);
+};
+
 }  // namespace quickstep
 
 #endif  // QUICKSTEP_TYPES_TYPE_ID_HPP_