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/04/12 19:34:26 UTC

[23/27] incubator-quickstep git commit: Refactor type system and operations.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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/da9baf7e/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_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/TypeIDSelectors.hpp
----------------------------------------------------------------------
diff --git a/types/TypeIDSelectors.hpp b/types/TypeIDSelectors.hpp
new file mode 100644
index 0000000..d75a887
--- /dev/null
+++ b/types/TypeIDSelectors.hpp
@@ -0,0 +1,152 @@
+/**
+ * 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_TYPE_ID_SELECTORS_HPP_
+#define QUICKSTEP_TYPES_TYPE_ID_SELECTORS_HPP_
+
+#include <type_traits>
+
+#include "types/TypeID.hpp"
+#include "utility/meta/Common.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+
+/** \addtogroup Types
+ *  @{
+ */
+
+struct TypeIDSelectorAll;
+
+struct TypeIDSelectorNumeric;
+
+struct TypeIDSelectorParameterized;
+
+struct TypeIDSelectorNonParameterized;
+
+template <TypeID ...candidates>
+struct TypeIDSelectorEqualsAny;
+
+
+// Forward declaration
+template <TypeID type_id>
+struct TypeIDTrait;
+
+struct TypeIDSelectorAll {
+  template <typename TypeIDConstant, typename FunctorT, typename EnableT = void>
+  struct Implementation {
+    inline static auto Invoke(const FunctorT &functor) {
+      return functor(TypeIDConstant());
+    }
+  };
+};
+
+struct TypeIDSelectorNumeric {
+  template <typename TypeIDConstant, typename FunctorT, typename EnableT = void>
+  struct Implementation {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wreturn-type"
+    inline static auto Invoke(const FunctorT &functor)
+        -> decltype(functor(TypeIDConstant())) {
+      DLOG(FATAL) << "Unexpected TypeID: "
+                  << kTypeNames[static_cast<int>(TypeIDConstant::value)];
+    }
+#pragma GCC diagnostic pop
+  };
+};
+
+template <typename TypeIDConstant, typename FunctorT>
+struct TypeIDSelectorNumeric::Implementation<
+    TypeIDConstant, FunctorT,
+    std::enable_if_t<TypeIDTrait<TypeIDConstant::value>
+                         ::kStaticSuperTypeID == Type::kNumeric>> {
+  inline static auto Invoke(const FunctorT &functor) {
+    return functor(TypeIDConstant());
+  }
+};
+
+template <TypeID ...candidates>
+struct TypeIDSelectorEqualsAny {
+  template <typename TypeIDConstant, typename FunctorT, typename EnableT = void>
+  struct Implementation {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wreturn-type"
+    inline static auto Invoke(const FunctorT &functor)
+        -> decltype(functor(TypeIDConstant())) {
+      DLOG(FATAL) << "Unexpected TypeID: "
+                  << kTypeNames[static_cast<int>(TypeIDConstant::value)];
+    }
+#pragma GCC diagnostic pop
+  };
+};
+
+template <TypeID ...candidates>
+template <typename TypeIDConstant, typename FunctorT>
+struct TypeIDSelectorEqualsAny<candidates...>::Implementation<
+    TypeIDConstant, FunctorT,
+    std::enable_if_t<
+        meta::EqualsAny<TypeIDConstant,
+                        std::integral_constant<TypeID, candidates>...>::value>> {
+  inline static auto Invoke(const FunctorT &functor) {
+    return functor(TypeIDConstant());
+  }
+};
+
+namespace internal {
+
+template <bool require_parameterized>
+struct TypeIDSelectorParameterizedHelper {
+  template <typename TypeIDConstant, typename FunctorT, typename EnableT = void>
+  struct Implementation {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wreturn-type"
+    inline static auto Invoke(const FunctorT &functor)
+        -> decltype(functor(TypeIDConstant())) {
+      DLOG(FATAL) << "Unexpected TypeID: "
+                  << kTypeNames[static_cast<int>(TypeIDConstant::value)];
+    }
+#pragma GCC diagnostic pop
+  };
+};
+
+template <bool require_non_parameterized>
+template <typename TypeIDConstant, typename FunctorT>
+struct TypeIDSelectorParameterizedHelper<require_non_parameterized>::Implementation<
+    TypeIDConstant, FunctorT,
+    std::enable_if_t<TypeIDTrait<TypeIDConstant::value>::kParameterized
+                         ^ require_non_parameterized>> {
+  inline static auto Invoke(const FunctorT &functor) {
+    return functor(TypeIDConstant());
+  }
+};
+
+}  // namespace internal
+
+struct TypeIDSelectorNonParameterized
+    : internal::TypeIDSelectorParameterizedHelper<true> {};
+
+struct TypeIDSelectorParameterized
+    : internal::TypeIDSelectorParameterizedHelper<false> {};
+
+/** @} */
+
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_TYPES_TYPE_ID_SELECTORS_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/TypeRegistrar.hpp
----------------------------------------------------------------------
diff --git a/types/TypeRegistrar.hpp b/types/TypeRegistrar.hpp
new file mode 100644
index 0000000..f4c9fb9
--- /dev/null
+++ b/types/TypeRegistrar.hpp
@@ -0,0 +1,122 @@
+/**
+ * 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_TYPE_REGISTRAR_HPP_
+#define QUICKSTEP_TYPES_TYPE_REGISTRAR_HPP_
+
+#include <cstdint>
+#include <type_traits>
+
+#include "types/DatetimeLit.hpp"
+#include "types/IntervalLit.hpp"
+#include "types/Type.hpp"
+#include "types/TypeID.hpp"
+#include "types/TypeIDSelectors.hpp"
+#include "utility/meta/Common.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+
+/** \addtogroup Types
+ *  @{
+ */
+
+template <TypeID type_id>
+struct TypeIDTrait;
+
+#define REGISTER_TYPE(T, type_id, super_type_id, parameterized, layout, CppType) \
+  class T; \
+  template <> struct TypeIDTrait<type_id> { \
+    typedef T TypeClass; \
+    typedef CppType cpptype; \
+    static constexpr TypeID kStaticTypeID = type_id; \
+    static constexpr Type::SuperTypeID kStaticSuperTypeID = super_type_id; \
+    static constexpr bool kParameterized = parameterized; \
+    static constexpr TypeStorageLayout kLayout = layout; \
+  };
+
+REGISTER_TYPE(BoolType, kBool, \
+              Type::kNumeric, false, kNativeEmbedded, bool);
+REGISTER_TYPE(IntType, kInt, \
+              Type::kNumeric, false, kNativeEmbedded, int);
+REGISTER_TYPE(LongType, kLong, \
+              Type::kNumeric, false, kNativeEmbedded, std::int64_t);
+REGISTER_TYPE(FloatType, kFloat, \
+              Type::kNumeric, false, kNativeEmbedded, float);
+REGISTER_TYPE(DoubleType, kDouble, \
+              Type::kNumeric, false, kNativeEmbedded, double);
+REGISTER_TYPE(DateType, kDate, \
+              Type::kOther, false, kNativeEmbedded, DateLit);
+REGISTER_TYPE(DatetimeType, kDatetime, \
+              Type::kOther, false, kNativeEmbedded, DatetimeLit);
+REGISTER_TYPE(DatetimeIntervalType, kDatetimeInterval, \
+              Type::kOther, false, kNativeEmbedded, DatetimeIntervalLit);
+REGISTER_TYPE(YearMonthIntervalType, kYearMonthInterval, \
+              Type::kOther, false, kNativeEmbedded, YearMonthIntervalLit);
+REGISTER_TYPE(CharType, kChar, \
+              Type::kAsciiString, true, kNonNativeInline, void);
+REGISTER_TYPE(VarCharType, kVarChar, \
+              Type::kAsciiString, true, kOutOfLine, void);
+REGISTER_TYPE(NullType, kNullType, \
+              Type::kOther, false, kNonNativeInline, void);
+
+#undef REGISTER_TYPE
+
+using TypeIDSequenceAll =
+    meta::MakeSequence<static_cast<std::size_t>(kNumTypeIDs)>
+        ::type::template cast_to<TypeID>;
+
+template <typename Selector = TypeIDSelectorAll, typename FunctorT>
+auto InvokeOnTypeID(const TypeID type_id, const FunctorT &functor);
+
+namespace internal {
+
+template <int l, int r, typename Selector, typename FunctorT>
+inline auto InvokeOnTypeIDInner(const int value,
+                                const FunctorT &functor) {
+  DCHECK_LE(l, r);
+  if (l == r) {
+    constexpr TypeID type_id = static_cast<TypeID>(r);
+    return Selector::template Implementation<
+        std::integral_constant<TypeID, type_id>, FunctorT>::Invoke(functor);
+  }
+  constexpr int m = (l + r) >> 1;
+  if (value <= m) {
+    return InvokeOnTypeIDInner<l, m, Selector, FunctorT>(value, functor);
+  } else {
+    return InvokeOnTypeIDInner<m+1, r, Selector, FunctorT>(value, functor);
+  }
+}
+
+}  // namespace internal
+
+template <typename Selector, typename FunctorT>
+auto InvokeOnTypeID(const TypeID type_id,
+                    const FunctorT &functor) {
+  return internal::InvokeOnTypeIDInner<0, static_cast<int>(kNumTypeIDs)-1,
+                                       Selector, FunctorT>(
+      static_cast<int>(type_id), functor);
+}
+
+/** @} */
+
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_TYPES_TYPE_REGISTRAR_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/TypeSynthesizer.hpp
----------------------------------------------------------------------
diff --git a/types/TypeSynthesizer.hpp b/types/TypeSynthesizer.hpp
new file mode 100644
index 0000000..27ba02a
--- /dev/null
+++ b/types/TypeSynthesizer.hpp
@@ -0,0 +1,210 @@
+/**
+ * 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_TYPE_SYNTHESIZER_HPP_
+#define QUICKSTEP_TYPES_TYPE_SYNTHESIZER_HPP_
+
+#include <cstddef>
+#include <type_traits>
+
+#include "types/Type.hpp"
+#include "types/Type.pb.h"
+#include "types/TypeID.hpp"
+#include "types/TypeRegistrar.hpp"
+#include "utility/Macros.hpp"
+#include "utility/PtrMap.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+
+/** \addtogroup Types
+ *  @{
+ */
+
+template <typename TypeClass, bool parameterized>
+class TypeInstance;
+
+
+template <TypeID type_id>
+class TypeSynthesizer
+    : public Type,
+      public TypeInstance<typename TypeIDTrait<type_id>::TypeClass,
+                          TypeIDTrait<type_id>::kParameterized> {
+ public:
+  using Trait = TypeIDTrait<type_id>;
+  using TypeClass = typename Trait::TypeClass;
+
+  static constexpr Type::SuperTypeID kStaticSuperTypeID = Trait::kStaticSuperTypeID;
+  static constexpr TypeID kStaticTypeID = Trait::kStaticTypeID;
+  static constexpr bool kParameterized = Trait::kParameterized;
+  static constexpr TypeStorageLayout kLayout = Trait::kLayout;
+
+  typedef typename Trait::cpptype cpptype;
+
+  serialization::Type getProto() const override {
+    serialization::Type proto;
+
+    proto.mutable_type_id()->CopyFrom(TypeIDFactory::GetProto(type_id_));
+    proto.set_nullable(nullable_);
+
+    if (kParameterized) {
+      proto.set_length(parameter_);
+    }
+
+    return proto;
+  }
+
+  const Type& getNullableVersion() const override {
+    return getInstance<kParameterized>(true);
+  }
+
+  const Type& getNonNullableVersion() const override {
+    return getInstance<kParameterized>(false);
+  }
+
+ protected:
+  template <TypeStorageLayout layout = kLayout, bool parameterized = kParameterized>
+  explicit TypeSynthesizer(const bool nullable,
+                           std::enable_if_t<layout == kNativeEmbedded ||
+                                            layout == kNativeInline>* = 0)
+      : Type(kStaticSuperTypeID, kStaticTypeID, nullable,
+             sizeof(cpptype), sizeof(cpptype)) {
+    DCHECK(!kParameterized);
+  }
+
+  template <TypeStorageLayout layout = kLayout, bool parameterized = kParameterized>
+  TypeSynthesizer(const bool nullable,
+                  const std::size_t minimum_byte_length,
+                  const std::size_t maximum_byte_length,
+                  const std::size_t parameter,
+                  std::enable_if_t<parameterized &&
+                                   (layout == kNonNativeInline ||
+                                    layout == kOutOfLine)>* = 0)
+      : Type(kStaticSuperTypeID, kStaticTypeID, nullable,
+             minimum_byte_length, maximum_byte_length, parameter) {
+    DCHECK(kLayout != kNonNativeInline || minimum_byte_length == maximum_byte_length);
+  }
+
+  template <TypeStorageLayout layout = kLayout, bool parameterized = kParameterized>
+  TypeSynthesizer(const bool nullable,
+                  const std::size_t minimum_byte_length,
+                  const std::size_t maximum_byte_length,
+                  std::enable_if_t<!parameterized &&
+                                   (layout == kNonNativeInline ||
+                                    layout == kOutOfLine)>* = 0)
+      : Type(kStaticSuperTypeID, kStaticTypeID, nullable,
+             minimum_byte_length, maximum_byte_length) {
+    DCHECK(kLayout != kNonNativeInline || minimum_byte_length == maximum_byte_length);
+  }
+
+ private:
+  template <bool has_param>
+  inline const Type& getInstance(const bool nullable,
+                                 std::enable_if_t<has_param>* = 0) const {
+    return TypeInstance<TypeClass, kParameterized>::Instance(parameter_, nullable);
+  }
+
+  template <bool has_param>
+  inline const Type& getInstance(const bool nullable,
+                                 std::enable_if_t<!has_param>* = 0) const {
+    return TypeInstance<TypeClass, kParameterized>::Instance(nullable);
+  }
+
+  friend class TypeInstance<TypeClass, kParameterized>;
+
+  DISALLOW_COPY_AND_ASSIGN(TypeSynthesizer);
+};
+
+template <TypeID type_id>
+constexpr Type::SuperTypeID TypeSynthesizer<type_id>::kStaticSuperTypeID;
+
+template <TypeID type_id>
+constexpr TypeID TypeSynthesizer<type_id>::kStaticTypeID;
+
+template <TypeID type_id>
+constexpr bool TypeSynthesizer<type_id>::kParameterized;
+
+template <TypeID type_id>
+constexpr TypeStorageLayout TypeSynthesizer<type_id>::kLayout;
+
+
+template <typename TypeClass>
+class TypeInstance<TypeClass, false> {
+ public:
+  static const TypeClass& InstanceNonNullable() {
+    return InstanceInternal<false>();
+  }
+
+  static const TypeClass& InstanceNullable() {
+    return InstanceInternal<true>();
+  }
+
+  static const TypeClass& Instance(const bool nullable) {
+    if (nullable) {
+      return InstanceNullable();
+    } else {
+      return InstanceNonNullable();
+    }
+  }
+
+ private:
+  template <bool nullable>
+  inline static const TypeClass& InstanceInternal() {
+    static TypeClass instance(nullable);
+    return instance;
+  }
+};
+
+template <typename TypeClass>
+class TypeInstance<TypeClass, true> {
+ public:
+  static const TypeClass& InstanceNonNullable(const std::size_t length) {
+    return InstanceInternal<false>(length);
+  }
+
+  static const TypeClass& InstanceNullable(const std::size_t length) {
+    return InstanceInternal<true>(length);
+  }
+
+  static const TypeClass& Instance(const bool nullable, const std::size_t length) {
+    if (nullable) {
+      return InstanceNullable(length);
+    } else {
+      return InstanceNonNullable(length);
+    }
+  }
+
+ private:
+  template <bool nullable>
+  inline static const TypeClass& InstanceInternal(const std::size_t length) {
+    static PtrMap<size_t, TypeClass> instance_map;
+    auto imit = instance_map.find(length);
+    if (imit == instance_map.end()) {
+      imit = instance_map.insert(length, new TypeClass(length, nullable)).first;
+    }
+    return *(imit->second);
+  }
+};
+
+/** @} */
+
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_TYPES_TYPE_SYNTHESIZER_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/TypeUtil.hpp
----------------------------------------------------------------------
diff --git a/types/TypeUtil.hpp b/types/TypeUtil.hpp
new file mode 100644
index 0000000..b146f02
--- /dev/null
+++ b/types/TypeUtil.hpp
@@ -0,0 +1,70 @@
+/**
+ * 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_TYPE_UTIL_HPP_
+#define QUICKSTEP_TYPES_TYPE_UTIL_HPP_
+
+#include <type_traits>
+
+#include "types/BoolType.hpp"
+#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/TypeID.hpp"
+#include "types/TypeRegistrar.hpp"
+#include "types/VarCharType.hpp"
+#include "types/YearMonthIntervalType.hpp"
+#include "utility/Macros.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+
+/** \addtogroup Types
+ *  @{
+ */
+
+class TypeUtil {
+ public:
+  static bool IsParameterized(const TypeID type_id) {
+    return InvokeOnTypeID(
+        type_id,
+        [&](auto tid) -> bool {  // NOLINT(build/c++11)
+      return TypeIDTrait<decltype(tid)::value>::kParameterized;
+    });
+  }
+
+ private:
+  TypeUtil() {}
+
+  DISALLOW_COPY_AND_ASSIGN(TypeUtil);
+};
+
+/** @} */
+
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_TYPES_TYPE_UTIL_HPP_