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/03/09 21:29:14 UTC

[4/8] incubator-quickstep git commit: Initial commit

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/parser/preprocessed/SqlParser_gen.hpp
----------------------------------------------------------------------
diff --git a/parser/preprocessed/SqlParser_gen.hpp b/parser/preprocessed/SqlParser_gen.hpp
index f1876b8..18a3aa0 100644
--- a/parser/preprocessed/SqlParser_gen.hpp
+++ b/parser/preprocessed/SqlParser_gen.hpp
@@ -79,103 +79,104 @@ extern int quickstep_yydebug;
     TOKEN_CSB_TREE = 289,
     TOKEN_BY = 290,
     TOKEN_CASE = 291,
-    TOKEN_CHARACTER = 292,
-    TOKEN_CHECK = 293,
-    TOKEN_COLUMN = 294,
-    TOKEN_CONSTRAINT = 295,
-    TOKEN_COPY = 296,
-    TOKEN_CREATE = 297,
-    TOKEN_CURRENT = 298,
-    TOKEN_DATE = 299,
-    TOKEN_DATETIME = 300,
-    TOKEN_DAY = 301,
-    TOKEN_DECIMAL = 302,
-    TOKEN_DEFAULT = 303,
-    TOKEN_DELETE = 304,
-    TOKEN_DELIMITER = 305,
-    TOKEN_DESC = 306,
-    TOKEN_DISTINCT = 307,
-    TOKEN_DOUBLE = 308,
-    TOKEN_DROP = 309,
-    TOKEN_ELSE = 310,
-    TOKEN_END = 311,
-    TOKEN_ESCAPE_STRINGS = 312,
-    TOKEN_EXISTS = 313,
-    TOKEN_EXTRACT = 314,
-    TOKEN_FALSE = 315,
-    TOKEN_FIRST = 316,
-    TOKEN_FLOAT = 317,
-    TOKEN_FOLLOWING = 318,
-    TOKEN_FOR = 319,
-    TOKEN_FOREIGN = 320,
-    TOKEN_FROM = 321,
-    TOKEN_FULL = 322,
-    TOKEN_GROUP = 323,
-    TOKEN_HASH = 324,
-    TOKEN_HAVING = 325,
-    TOKEN_HOUR = 326,
-    TOKEN_IN = 327,
-    TOKEN_INDEX = 328,
-    TOKEN_INNER = 329,
-    TOKEN_INSERT = 330,
-    TOKEN_INTEGER = 331,
-    TOKEN_INTERVAL = 332,
-    TOKEN_INTO = 333,
-    TOKEN_JOIN = 334,
-    TOKEN_KEY = 335,
-    TOKEN_LAST = 336,
-    TOKEN_LEFT = 337,
-    TOKEN_LIMIT = 338,
-    TOKEN_LONG = 339,
-    TOKEN_MINUTE = 340,
-    TOKEN_MONTH = 341,
-    TOKEN_NULL = 342,
-    TOKEN_NULLS = 343,
-    TOKEN_OFF = 344,
-    TOKEN_ON = 345,
-    TOKEN_ORDER = 346,
-    TOKEN_OUTER = 347,
-    TOKEN_OVER = 348,
-    TOKEN_PARTITION = 349,
-    TOKEN_PARTITIONS = 350,
-    TOKEN_PERCENT = 351,
-    TOKEN_PRECEDING = 352,
-    TOKEN_PRIMARY = 353,
-    TOKEN_PRIORITY = 354,
-    TOKEN_QUIT = 355,
-    TOKEN_RANGE = 356,
-    TOKEN_REAL = 357,
-    TOKEN_REFERENCES = 358,
-    TOKEN_RIGHT = 359,
-    TOKEN_ROW = 360,
-    TOKEN_ROW_DELIMITER = 361,
-    TOKEN_ROWS = 362,
-    TOKEN_SECOND = 363,
-    TOKEN_SELECT = 364,
-    TOKEN_SET = 365,
-    TOKEN_SMA = 366,
-    TOKEN_SMALLINT = 367,
-    TOKEN_SUBSTRING = 368,
-    TOKEN_TABLE = 369,
-    TOKEN_THEN = 370,
-    TOKEN_TIME = 371,
-    TOKEN_TIMESTAMP = 372,
-    TOKEN_TRUE = 373,
-    TOKEN_TUPLESAMPLE = 374,
-    TOKEN_UNBOUNDED = 375,
-    TOKEN_UNIQUE = 376,
-    TOKEN_UPDATE = 377,
-    TOKEN_USING = 378,
-    TOKEN_VALUES = 379,
-    TOKEN_VARCHAR = 380,
-    TOKEN_WHEN = 381,
-    TOKEN_WHERE = 382,
-    TOKEN_WINDOW = 383,
-    TOKEN_WITH = 384,
-    TOKEN_YEAR = 385,
-    TOKEN_YEARMONTH = 386,
-    TOKEN_EOF = 387,
-    TOKEN_LEX_ERROR = 388
+    TOKEN_CAST = 292,
+    TOKEN_CHARACTER = 293,
+    TOKEN_CHECK = 294,
+    TOKEN_COLUMN = 295,
+    TOKEN_CONSTRAINT = 296,
+    TOKEN_COPY = 297,
+    TOKEN_CREATE = 298,
+    TOKEN_CURRENT = 299,
+    TOKEN_DATE = 300,
+    TOKEN_DATETIME = 301,
+    TOKEN_DAY = 302,
+    TOKEN_DECIMAL = 303,
+    TOKEN_DEFAULT = 304,
+    TOKEN_DELETE = 305,
+    TOKEN_DELIMITER = 306,
+    TOKEN_DESC = 307,
+    TOKEN_DISTINCT = 308,
+    TOKEN_DOUBLE = 309,
+    TOKEN_DROP = 310,
+    TOKEN_ELSE = 311,
+    TOKEN_END = 312,
+    TOKEN_ESCAPE_STRINGS = 313,
+    TOKEN_EXISTS = 314,
+    TOKEN_EXTRACT = 315,
+    TOKEN_FALSE = 316,
+    TOKEN_FIRST = 317,
+    TOKEN_FLOAT = 318,
+    TOKEN_FOLLOWING = 319,
+    TOKEN_FOR = 320,
+    TOKEN_FOREIGN = 321,
+    TOKEN_FROM = 322,
+    TOKEN_FULL = 323,
+    TOKEN_GROUP = 324,
+    TOKEN_HASH = 325,
+    TOKEN_HAVING = 326,
+    TOKEN_HOUR = 327,
+    TOKEN_IN = 328,
+    TOKEN_INDEX = 329,
+    TOKEN_INNER = 330,
+    TOKEN_INSERT = 331,
+    TOKEN_INTEGER = 332,
+    TOKEN_INTERVAL = 333,
+    TOKEN_INTO = 334,
+    TOKEN_JOIN = 335,
+    TOKEN_KEY = 336,
+    TOKEN_LAST = 337,
+    TOKEN_LEFT = 338,
+    TOKEN_LIMIT = 339,
+    TOKEN_LONG = 340,
+    TOKEN_MINUTE = 341,
+    TOKEN_MONTH = 342,
+    TOKEN_NULL = 343,
+    TOKEN_NULLS = 344,
+    TOKEN_OFF = 345,
+    TOKEN_ON = 346,
+    TOKEN_ORDER = 347,
+    TOKEN_OUTER = 348,
+    TOKEN_OVER = 349,
+    TOKEN_PARTITION = 350,
+    TOKEN_PARTITIONS = 351,
+    TOKEN_PERCENT = 352,
+    TOKEN_PRECEDING = 353,
+    TOKEN_PRIMARY = 354,
+    TOKEN_PRIORITY = 355,
+    TOKEN_QUIT = 356,
+    TOKEN_RANGE = 357,
+    TOKEN_REAL = 358,
+    TOKEN_REFERENCES = 359,
+    TOKEN_RIGHT = 360,
+    TOKEN_ROW = 361,
+    TOKEN_ROW_DELIMITER = 362,
+    TOKEN_ROWS = 363,
+    TOKEN_SECOND = 364,
+    TOKEN_SELECT = 365,
+    TOKEN_SET = 366,
+    TOKEN_SMA = 367,
+    TOKEN_SMALLINT = 368,
+    TOKEN_SUBSTRING = 369,
+    TOKEN_TABLE = 370,
+    TOKEN_THEN = 371,
+    TOKEN_TIME = 372,
+    TOKEN_TIMESTAMP = 373,
+    TOKEN_TRUE = 374,
+    TOKEN_TUPLESAMPLE = 375,
+    TOKEN_UNBOUNDED = 376,
+    TOKEN_UNIQUE = 377,
+    TOKEN_UPDATE = 378,
+    TOKEN_USING = 379,
+    TOKEN_VALUES = 380,
+    TOKEN_VARCHAR = 381,
+    TOKEN_WHEN = 382,
+    TOKEN_WHERE = 383,
+    TOKEN_WINDOW = 384,
+    TOKEN_WITH = 385,
+    TOKEN_YEAR = 386,
+    TOKEN_YEARMONTH = 387,
+    TOKEN_EOF = 388,
+    TOKEN_LEX_ERROR = 389
   };
 #endif
 
@@ -184,7 +185,7 @@ extern int quickstep_yydebug;
 
 union YYSTYPE
 {
-#line 120 "../SqlParser.ypp" /* yacc.c:1915  */
+#line 117 "../SqlParser.ypp" /* yacc.c:1915  */
 
   quickstep::ParseString *string_value_;
 
@@ -255,7 +256,7 @@ union YYSTYPE
   quickstep::ParseStatementQuit *quit_statement_;
 
   const quickstep::Comparison *comparison_;
-  const quickstep::UnaryOperation *unary_operation_;
+  quickstep::ParseString *unary_operation_;
   const quickstep::BinaryOperation *binary_operation_;
 
   quickstep::ParseFunctionCall *function_call_;
@@ -284,7 +285,7 @@ union YYSTYPE
 
   quickstep::ParsePriority *opt_priority_clause_;
 
-#line 288 "SqlParser_gen.hpp" /* yacc.c:1915  */
+#line 289 "SqlParser_gen.hpp" /* yacc.c:1915  */
 };
 
 typedef union YYSTYPE YYSTYPE;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/query_optimizer/LogicalGenerator.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/LogicalGenerator.cpp b/query_optimizer/LogicalGenerator.cpp
index abeca53..49481d3 100644
--- a/query_optimizer/LogicalGenerator.cpp
+++ b/query_optimizer/LogicalGenerator.cpp
@@ -53,7 +53,8 @@ L::LogicalPtr LogicalGenerator::generatePlan(
   resolver::Resolver resolver(catalog_database, optimizer_context_);
   DVLOG(4) << "Parse tree:\n" << parse_statement.toString();
   logical_plan_ = resolver.resolve(parse_statement);
-  DVLOG(4) << "Initial logical plan:\n" << logical_plan_->toString();
+  std::cerr << "Initial logical plan:\n" << logical_plan_->toString();
+//  exit(0);
 
   optimizePlan();
   DVLOG(4) << "Optimized logical plan:\n" << logical_plan_->toString();

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/query_optimizer/expressions/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/CMakeLists.txt b/query_optimizer/expressions/CMakeLists.txt
index 35fac90..d7ce686 100644
--- a/query_optimizer/expressions/CMakeLists.txt
+++ b/query_optimizer/expressions/CMakeLists.txt
@@ -104,7 +104,7 @@ target_link_libraries(quickstep_queryoptimizer_expressions_Cast
                       quickstep_queryoptimizer_expressions_PatternMatcher
                       quickstep_queryoptimizer_expressions_Scalar
                       quickstep_types_Type
-                      quickstep_types_operations_unaryoperations_NumericCastOperation
+                      quickstep_types_operations_unaryoperations_CastOperation
                       quickstep_utility_Macros)
 target_link_libraries(quickstep_queryoptimizer_expressions_ComparisonExpression
                       glog
@@ -299,8 +299,9 @@ target_link_libraries(quickstep_queryoptimizer_expressions_UnaryExpression
                       quickstep_queryoptimizer_expressions_ExpressionType
                       quickstep_queryoptimizer_expressions_PatternMatcher
                       quickstep_queryoptimizer_expressions_Scalar
+                      quickstep_queryoptimizer_expressions_ScalarLiteral
+                      quickstep_types_operations_OperationSignature
                       quickstep_types_operations_unaryoperations_UnaryOperation
-                      quickstep_types_operations_unaryoperations_UnaryOperationID
                       quickstep_utility_Macros)
 target_link_libraries(quickstep_queryoptimizer_expressions_WindowAggregateFunction
                       glog

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/query_optimizer/expressions/Cast.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/Cast.cpp b/query_optimizer/expressions/Cast.cpp
index c0813c5..7180aa3 100644
--- a/query_optimizer/expressions/Cast.cpp
+++ b/query_optimizer/expressions/Cast.cpp
@@ -32,7 +32,7 @@
 #include "query_optimizer/expressions/PatternMatcher.hpp"
 #include "query_optimizer/expressions/Scalar.hpp"
 #include "types/Type.hpp"
-#include "types/operations/unary_operations/NumericCastOperation.hpp"
+#include "types/operations/unary_operations/CastOperation.hpp"
 
 #include "glog/logging.h"
 
@@ -51,8 +51,9 @@ ExpressionPtr Cast::copyWithNewChildren(
 
 ::quickstep::Scalar *Cast::concretize(
     const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
-  return new ::quickstep::ScalarUnaryExpression(::quickstep::NumericCastOperation::Instance(target_type_),
-                                                operand_->concretize(substitution_map));
+//  return new ::quickstep::ScalarUnaryExpression(::quickstep::NumericCastOperation::Instance(target_type_),
+//                                                operand_->concretize(substitution_map));
+  return nullptr;
 }
 
 void Cast::getFieldStringItems(
@@ -62,11 +63,11 @@ void Cast::getFieldStringItems(
     std::vector<OptimizerTreeBaseNodePtr> *non_container_child_fields,
     std::vector<std::string> *container_child_field_names,
     std::vector<std::vector<OptimizerTreeBaseNodePtr>> *container_child_fields) const {
-  inline_field_names->push_back("target_type");
-  inline_field_values->push_back(target_type_.getName());
-
-  non_container_child_field_names->push_back("operand");
-  non_container_child_fields->push_back(operand_);
+//  inline_field_names->push_back("target_type");
+//  inline_field_values->push_back(target_type_.getName());
+//
+//  non_container_child_field_names->push_back("operand");
+//  non_container_child_fields->push_back(operand_);
 }
 
 }  // namespace expressions

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/query_optimizer/expressions/UnaryExpression.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/UnaryExpression.cpp b/query_optimizer/expressions/UnaryExpression.cpp
index b0fff62..d7bde71 100644
--- a/query_optimizer/expressions/UnaryExpression.cpp
+++ b/query_optimizer/expressions/UnaryExpression.cpp
@@ -29,8 +29,8 @@
 #include "query_optimizer/expressions/Expression.hpp"
 #include "query_optimizer/expressions/PatternMatcher.hpp"
 #include "query_optimizer/expressions/Scalar.hpp"
+#include "query_optimizer/expressions/ScalarLiteral.hpp"
 #include "types/operations/unary_operations/UnaryOperation.hpp"
-#include "types/operations/unary_operations/UnaryOperationID.hpp"
 
 #include "glog/logging.h"
 
@@ -39,7 +39,7 @@ namespace optimizer {
 namespace expressions {
 
 std::string UnaryExpression::getName() const {
-  return operation_.getName();
+  return operation_->getName();
 }
 
 ExpressionPtr UnaryExpression::copyWithNewChildren(
@@ -47,13 +47,20 @@ ExpressionPtr UnaryExpression::copyWithNewChildren(
   DCHECK_EQ(new_children.size(), children().size());
   DCHECK(SomeScalar::Matches(new_children[0]));
   return UnaryExpression::Create(
-      operation_, std::static_pointer_cast<const Scalar>(new_children[0]));
+      op_signature_,
+      operation_,
+      std::static_pointer_cast<const Scalar>(new_children[0]),
+      static_arguments_,
+      static_argument_types_);
 }
 
 ::quickstep::Scalar* UnaryExpression::concretize(
     const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
   return new ::quickstep::ScalarUnaryExpression(
-      operation_, operand_->concretize(substitution_map));
+      op_signature_,
+      operation_,
+      operand_->concretize(substitution_map),
+      static_arguments_);
 }
 
 void UnaryExpression::getFieldStringItems(
@@ -63,8 +70,21 @@ void UnaryExpression::getFieldStringItems(
     std::vector<OptimizerTreeBaseNodePtr> *non_container_child_fields,
     std::vector<std::string> *container_child_field_names,
     std::vector<std::vector<OptimizerTreeBaseNodePtr>> *container_child_fields) const {
-  non_container_child_field_names->push_back("Operand");
-  non_container_child_fields->push_back(operand_);
+  inline_field_names->emplace_back("op_signature");
+  inline_field_values->emplace_back(op_signature_->toString());
+
+  non_container_child_field_names->emplace_back("operand");
+  non_container_child_fields->emplace_back(operand_);
+
+  if (!static_arguments_->empty()) {
+    container_child_field_names->emplace_back("static_arguments");
+    container_child_fields->emplace_back();
+    for (std::size_t i = 0; i < static_arguments_->size(); ++i) {
+      container_child_fields->back().emplace_back(
+          ScalarLiteral::Create(static_arguments_->at(i),
+                                *static_argument_types_->at(i)));
+    }
+  }
 }
 
 }  // namespace expressions

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/query_optimizer/expressions/UnaryExpression.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/UnaryExpression.hpp b/query_optimizer/expressions/UnaryExpression.hpp
index c4542d0..c08519f 100644
--- a/query_optimizer/expressions/UnaryExpression.hpp
+++ b/query_optimizer/expressions/UnaryExpression.hpp
@@ -30,6 +30,7 @@
 #include "query_optimizer/expressions/Expression.hpp"
 #include "query_optimizer/expressions/ExpressionType.hpp"
 #include "query_optimizer/expressions/Scalar.hpp"
+#include "types/operations/OperationSignature.hpp"
 #include "types/operations/unary_operations/UnaryOperation.hpp"
 #include "utility/Macros.hpp"
 
@@ -64,7 +65,7 @@ class UnaryExpression : public Scalar {
   /**
    * @return The unary operator.
    */
-  const UnaryOperation& operation() const { return operation_; }
+  const UnaryOperationPtr& operation() const { return operation_; }
 
   /**
    * @return The operand of the unary operator.
@@ -72,7 +73,7 @@ class UnaryExpression : public Scalar {
   const ScalarPtr& operand() const { return operand_; }
 
   const Type& getValueType() const override {
-    return *(operation_.resultTypeForArgumentType(operand_->getValueType()));
+    return result_type_;
   }
 
   ExpressionPtr copyWithNewChildren(
@@ -93,9 +94,18 @@ class UnaryExpression : public Scalar {
    * @return An immutable UnaryExpression that applies the operation to the
    *         operand.
    */
-  static UnaryExpressionPtr Create(const UnaryOperation &operation,
-                                   const ScalarPtr &operand) {
-    return UnaryExpressionPtr(new UnaryExpression(operation, operand));
+  static UnaryExpressionPtr Create(
+      const OperationSignaturePtr &op_signature,
+      const UnaryOperationPtr &operation,
+      const ScalarPtr &operand,
+      const std::shared_ptr<const std::vector<TypedValue>> &static_arguments,
+      const std::shared_ptr<const std::vector<const Type*>> &static_argument_types) {
+    return UnaryExpressionPtr(
+        new UnaryExpression(op_signature,
+                            operation,
+                            operand,
+                            static_arguments,
+                            static_argument_types));
   }
 
  protected:
@@ -108,15 +118,27 @@ class UnaryExpression : public Scalar {
       std::vector<std::vector<OptimizerTreeBaseNodePtr>> *container_child_fields) const override;
 
  private:
-  UnaryExpression(const UnaryOperation &operation,
-                  const ScalarPtr &operand)
-      : operation_(operation), operand_(operand) {
-    DCHECK(operation_.canApplyToType(operand_->getValueType())) << toString();
+  UnaryExpression(const OperationSignaturePtr &op_signature,
+                  const UnaryOperationPtr &operation,
+                  const ScalarPtr &operand,
+                  const std::shared_ptr<const std::vector<TypedValue>> &static_arguments,
+                  const std::shared_ptr<const std::vector<const Type*>> &static_argument_types)
+      : op_signature_(op_signature),
+        operation_(operation),
+        operand_(operand),
+        static_arguments_(static_arguments),
+        static_argument_types_(static_argument_types),
+        result_type_(*(operation_->getResultType(operand_->getValueType(), *static_arguments_))) {
+    DCHECK(operation_->canApplyTo(operand_->getValueType(), *static_arguments)) << toString();
     addChild(operand);
   }
 
-  const UnaryOperation &operation_;
-  ScalarPtr operand_;
+  const OperationSignaturePtr op_signature_;
+  const UnaryOperationPtr operation_;
+  const ScalarPtr operand_;
+  const std::shared_ptr<const std::vector<TypedValue>> static_arguments_;
+  const std::shared_ptr<const std::vector<const Type*>> static_argument_types_;
+  const Type &result_type_;
 
   DISALLOW_COPY_AND_ASSIGN(UnaryExpression);
 };

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/query_optimizer/resolver/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/query_optimizer/resolver/CMakeLists.txt b/query_optimizer/resolver/CMakeLists.txt
index a34273e..27497a2 100644
--- a/query_optimizer/resolver/CMakeLists.txt
+++ b/query_optimizer/resolver/CMakeLists.txt
@@ -121,15 +121,16 @@ target_link_libraries(quickstep_queryoptimizer_resolver_Resolver
                       quickstep_storage_StorageConstants
                       quickstep_types_IntType
                       quickstep_types_Type
+                      quickstep_types_TypeUtil
                       quickstep_types_TypedValue
                       quickstep_types_TypeFactory
+                      quickstep_types_operations_OperationSignature
                       quickstep_types_operations_binaryoperations_BinaryOperation
                       quickstep_types_operations_comparisons_Comparison
                       quickstep_types_operations_comparisons_ComparisonFactory
                       quickstep_types_operations_comparisons_ComparisonID
-                      quickstep_types_operations_unaryoperations_DateExtractOperation
-                      quickstep_types_operations_unaryoperations_SubstringOperation
                       quickstep_types_operations_unaryoperations_UnaryOperation
+                      quickstep_types_operations_unaryoperations_UnaryOperationFactory
                       quickstep_utility_Macros
                       quickstep_utility_PtrList
                       quickstep_utility_PtrVector

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/query_optimizer/resolver/Resolver.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/resolver/Resolver.cpp b/query_optimizer/resolver/Resolver.cpp
index df589fd..1741409 100644
--- a/query_optimizer/resolver/Resolver.cpp
+++ b/query_optimizer/resolver/Resolver.cpp
@@ -22,7 +22,6 @@
 #include <algorithm>
 #include <map>
 #include <memory>
-#include <set>
 #include <string>
 #include <unordered_map>
 #include <unordered_set>
@@ -116,15 +115,16 @@
 #include "storage/StorageConstants.hpp"
 #include "types/IntType.hpp"
 #include "types/Type.hpp"
-#include "types/TypedValue.hpp"
 #include "types/TypeFactory.hpp"
+#include "types/TypeUtil.hpp"
+#include "types/TypedValue.hpp"
+#include "types/operations/OperationSignature.hpp"
 #include "types/operations/binary_operations/BinaryOperation.hpp"
 #include "types/operations/comparisons/Comparison.hpp"
 #include "types/operations/comparisons/ComparisonFactory.hpp"
 #include "types/operations/comparisons/ComparisonID.hpp"
-#include "types/operations/unary_operations/DateExtractOperation.hpp"
-#include "types/operations/unary_operations/SubstringOperation.hpp"
 #include "types/operations/unary_operations/UnaryOperation.hpp"
+#include "types/operations/unary_operations/UnaryOperationFactory.hpp"
 #include "utility/PtrList.hpp"
 #include "utility/PtrVector.hpp"
 #include "utility/SqlError.hpp"
@@ -142,6 +142,26 @@ namespace E = ::quickstep::optimizer::expressions;
 namespace L = ::quickstep::optimizer::logical;
 namespace S = ::quickstep::serialization;
 
+namespace {
+
+attribute_id GetAttributeIdFromName(const PtrList<ParseAttributeDefinition> &attribute_definition_list,
+                                    const std::string &attribute_name) {
+  const std::string lower_attribute_name = ToLower(attribute_name);
+
+  attribute_id attr_id = 0;
+  for (const ParseAttributeDefinition &attribute_definition : attribute_definition_list) {
+    if (lower_attribute_name == ToLower(attribute_definition.name()->value())) {
+      return attr_id;
+    }
+
+    ++attr_id;
+  }
+
+  return kInvalidAttributeID;
+}
+
+}  // namespace
+
 struct Resolver::ExpressionResolutionInfo {
   /**
    * @brief Constructs an ExpressionResolutionInfo that disallows aggregate
@@ -490,26 +510,6 @@ L::LogicalPtr Resolver::resolveCreateTable(
   return L::CreateTable::Create(relation_name, attributes, block_properties, partition_scheme_header_proto);
 }
 
-namespace {
-
-attribute_id GetAttributeIdFromName(const PtrList<ParseAttributeDefinition> &attribute_definition_list,
-                                    const std::string &attribute_name) {
-  const std::string lower_attribute_name = ToLower(attribute_name);
-
-  attribute_id attr_id = 0;
-  for (const ParseAttributeDefinition &attribute_definition : attribute_definition_list) {
-    if (lower_attribute_name == ToLower(attribute_definition.name()->value())) {
-      return attr_id;
-    }
-
-    ++attr_id;
-  }
-
-  return kInvalidAttributeID;
-}
-
-}  // namespace
-
 StorageBlockLayoutDescription* Resolver::resolveBlockProperties(
     const ParseStatementCreateTable &create_table_statement) {
   const ParseBlockProperties *block_properties
@@ -2247,57 +2247,6 @@ E::ScalarPtr Resolver::resolveExpression(
           type_hint,
           expression_resolution_info);
     }
-    case ParseExpression::kUnaryExpression: {
-      const ParseUnaryExpression &parse_unary_expr =
-          static_cast<const ParseUnaryExpression&>(parse_expression);
-
-      E::ScalarPtr argument = resolveExpression(
-          *parse_unary_expr.operand(),
-          parse_unary_expr.op().pushDownTypeHint(type_hint),
-          expression_resolution_info);
-
-      // If the argument is a NULL of unknown Type, try to resolve result Type
-      // of this UnaryExpression as follows:
-      //
-      //     1. If the UnaryExpression can only return one type, then the
-      //        result is a NULL of that type.
-      //     2. If there is a type hint for the UnaryExpression's result, and
-      //        it is possible for the UnaryExpression to return the hinted
-      //        type, then the result is a NULL of that type.
-      //     3. Otherwise, the result is a NULL of unknown type (i.e.
-      //        NullType).
-      //
-      // NOTE(chasseur): As with binary expressions above, step #3 does not
-      // always completely capture information about what types the NULL result
-      // can take on, since NullType is implicitly convertable to any Type.
-      if (argument->getValueType().getTypeID() == kNullType) {
-        const Type *fixed_result_type = parse_unary_expr.op().fixedNullableResultType();
-        if (fixed_result_type != nullptr) {
-          return E::ScalarLiteral::Create(fixed_result_type->makeNullValue(),
-                                          *fixed_result_type);
-        }
-
-        if (type_hint != nullptr) {
-          const Type &nullable_type_hint = type_hint->getNullableVersion();
-          if (parse_unary_expr.op().resultTypeIsPlausible(nullable_type_hint)) {
-            return E::ScalarLiteral::Create(nullable_type_hint.makeNullValue(),
-                                            nullable_type_hint);
-          }
-        }
-
-        const Type &null_type = TypeFactory::GetType(kNullType, true);
-        return E::ScalarLiteral::Create(null_type.makeNullValue(),
-                                        null_type);
-      }
-
-      if (!parse_unary_expr.op().canApplyToType(argument->getValueType())) {
-        THROW_SQL_ERROR_AT(&parse_unary_expr)
-            << "Can not apply unary operation \"" << parse_unary_expr.op().getName()
-            << "\" to argument of type " << argument->getValueType().getName();
-      }
-
-      return E::UnaryExpression::Create(parse_unary_expr.op(), argument);
-    }
     case ParseExpression::kFunctionCall: {
       return resolveFunctionCall(
           static_cast<const ParseFunctionCall&>(parse_expression),
@@ -2311,75 +2260,6 @@ E::ScalarPtr Resolver::resolveExpression(
           expression_resolution_info,
           true /* has_single_column */);
     }
-    case ParseExpression::kExtract: {
-      const ParseExtractFunction &parse_extract =
-          static_cast<const ParseExtractFunction&>(parse_expression);
-
-      const ParseString &extract_field = *parse_extract.extract_field();
-      const std::string lowered_unit = ToLower(extract_field.value());
-      DateExtractUnit extract_unit;
-      if (lowered_unit == "year") {
-        extract_unit = DateExtractUnit::kYear;
-      } else if (lowered_unit == "month") {
-        extract_unit = DateExtractUnit::kMonth;
-      } else if (lowered_unit == "day") {
-        extract_unit = DateExtractUnit::kDay;
-      } else if (lowered_unit == "hour") {
-        extract_unit = DateExtractUnit::kHour;
-      } else if (lowered_unit == "minute") {
-        extract_unit = DateExtractUnit::kMinute;
-      } else if (lowered_unit == "second") {
-        extract_unit = DateExtractUnit::kSecond;
-      } else {
-        THROW_SQL_ERROR_AT(&extract_field)
-            << "Invalid extract unit: " << extract_field.value();
-      }
-
-      const DateExtractOperation &op = DateExtractOperation::Instance(extract_unit);
-      const E::ScalarPtr argument = resolveExpression(
-          *parse_extract.date_expression(),
-          op.pushDownTypeHint(type_hint),
-          expression_resolution_info);
-
-      if (!op.canApplyToType(argument->getValueType())) {
-        THROW_SQL_ERROR_AT(parse_extract.date_expression())
-            << "Can not extract from argument of type: "
-            << argument->getValueType().getName();
-      }
-
-      return E::UnaryExpression::Create(op, argument);
-    }
-    case ParseExpression::kSubstring: {
-      const ParseSubstringFunction &parse_substring =
-          static_cast<const ParseSubstringFunction&>(parse_expression);
-
-      // Validate start position and substring length.
-      if (parse_substring.start_position() <= 0) {
-        THROW_SQL_ERROR_AT(&parse_expression)
-            << "The start position must be greater than 0";
-      }
-      if (parse_substring.length() <= 0) {
-        THROW_SQL_ERROR_AT(&parse_expression)
-            << "The substring length must be greater than 0";
-      }
-
-      // Convert 1-base position to 0-base position
-      const std::size_t zero_base_start_position = parse_substring.start_position() - 1;
-      const SubstringOperation &op =
-          SubstringOperation::Instance(zero_base_start_position,
-                                       parse_substring.length());
-
-      const E::ScalarPtr argument =
-          resolveExpression(*parse_substring.operand(),
-                            op.pushDownTypeHint(type_hint),
-                            expression_resolution_info);
-      if (!op.canApplyToType(argument->getValueType())) {
-        THROW_SQL_ERROR_AT(&parse_substring)
-            << "Can not apply substring function to argument of type "
-            << argument->getValueType().getName();
-      }
-      return E::UnaryExpression::Create(op, argument);
-    }
     default:
       LOG(FATAL) << "Unknown scalar type: "
                  << parse_expression.getExpressionType();
@@ -2639,6 +2519,126 @@ E::ScalarPtr Resolver::resolveSimpleCaseExpression(
                                *result_data_type);
 }
 
+E::ScalarPtr Resolver::resolveScalarFunction(
+    const ParseFunctionCall &parse_function_call,
+    const std::string &function_name,
+    const std::vector<E::ScalarPtr> &resolved_arguments,
+    ExpressionResolutionInfo *expression_resolution_info) {
+  const std::size_t arity = resolved_arguments.size();
+
+  std::vector<const Type*> argument_types;
+  std::vector<TypeID> argument_type_ids;
+  std::size_t first_static_argument_position = 0;
+  for (std::size_t i = 0; i < arity; ++i) {
+    const E::ScalarPtr &argument = resolved_arguments[i];
+    if (argument->getExpressionType() != E::ExpressionType::kScalarLiteral) {
+      first_static_argument_position = i + 1;
+    }
+
+    const Type &type = argument->getValueType();
+    argument_types.emplace_back(&type);
+    argument_type_ids.emplace_back(type.getTypeID());
+  }
+
+  std::vector<TypedValue> maximal_static_arguments;
+  for (std::size_t i = first_static_argument_position; i < arity; ++i) {
+    maximal_static_arguments.emplace_back(
+        std::static_pointer_cast<const E::ScalarLiteral>(
+            resolved_arguments[i])->value());
+    DCHECK(maximal_static_arguments.back().getTypeID() == argument_type_ids[i]);
+  }
+  const std::size_t max_num_static_arguments = maximal_static_arguments.size();
+
+  const UnaryOperationFactory &factory = UnaryOperationFactory::Instance();
+
+  // First, check exact matching of name + non static types, possibly safe
+  // coercion of static arguments.
+  const auto &op_sig_candidates = factory.getUnaryOperations(function_name, arity);
+  for (const OperationSignaturePtr &op_sig : op_sig_candidates) {
+    const std::size_t op_num_static_arguments = op_sig->getNumStaticArguments();
+    if (op_num_static_arguments > max_num_static_arguments) {
+      continue;
+    }
+
+    bool is_match = true;
+    for (std::size_t i = 0; i < arity - op_num_static_arguments; ++i) {
+      if (op_sig->getArgumentTypeIDs().at(i) != argument_type_ids[i]) {
+        is_match = false;
+        break;
+      }
+    }
+    if (!is_match) {
+      continue;
+    }
+
+    std::vector<TypedValue> coerced_static_arguments;
+    std::vector<const Type*> coerced_static_argument_types;
+    bool is_coercible = true;
+    for (std::size_t i = arity - op_num_static_arguments; i < arity; ++i) {
+      const Type &arg_type = *argument_types.at(i);
+      const TypedValue &arg_value =
+          maximal_static_arguments.at(i - first_static_argument_position);
+      const TypeID expected_type_id = op_sig->getArgumentTypeIDs().at(i);
+      if (arg_type.getTypeID() == expected_type_id) {
+        coerced_static_arguments.emplace_back(arg_value);
+        coerced_static_argument_types.emplace_back(&arg_type);
+      } else {
+        const Type *expected_type = nullptr;
+        if (TypeUtil::IsParameterized(expected_type_id)) {
+          // TODO: refactor type system to make this coercion extensible.
+          if (expected_type_id == kChar && arg_type.getTypeID() == kVarChar) {
+            expected_type = &TypeFactory::GetType(
+                expected_type_id, arg_type.maximumByteLength() - 1);
+          } else if (expected_type_id == kVarChar && arg_type.getTypeID() == kChar) {
+            expected_type = &TypeFactory::GetType(
+                expected_type_id, arg_type.maximumByteLength() + 1);
+          }
+        } else {
+          expected_type = &TypeFactory::GetType(expected_type_id);
+        }
+        if (expected_type != nullptr && expected_type->isSafelyCoercibleFrom(arg_type)) {
+          coerced_static_arguments.emplace_back(
+              expected_type->coerceValue(arg_value, arg_type));
+          coerced_static_argument_types.emplace_back(expected_type);
+        } else {
+          is_coercible = false;
+          break;
+        }
+      }
+    }
+    if (!is_coercible) {
+      continue;
+    }
+
+    // TODO: switch on operation non-static arity here.
+    CHECK_EQ(1u, arity - op_num_static_arguments);
+
+    const UnaryOperationPtr op = factory.getUnaryOperation(op_sig);
+    const auto static_arguments =
+        std::make_shared<const std::vector<TypedValue>>(
+            std::move(coerced_static_arguments));
+    const auto static_argument_types =
+        std::make_shared<const std::vector<const Type*>>(
+            std::move(coerced_static_argument_types));
+
+    std::string message;
+    if (op->canApplyTo(*argument_types.front(), *static_arguments, &message)) {
+      return E::UnaryExpression::Create(op_sig,
+                                        op,
+                                        resolved_arguments.front(),
+                                        static_arguments,
+                                        static_argument_types);
+    } else {
+      THROW_SQL_ERROR_AT(&parse_function_call) << message;
+    }
+  }
+
+  THROW_SQL_ERROR_AT(&parse_function_call)
+      << "Cannot resolve scalar function";
+
+  return nullptr;
+}
+
 // TODO(chasseur): For now this only handles resolving aggregate functions. In
 // the future it should be extended to resolve scalar functions as well.
 // TODO(Shixuan): This will handle resolving window aggregation function as well,
@@ -2659,8 +2659,7 @@ E::ScalarPtr Resolver::resolveFunctionCall(
   }
 
   std::vector<E::ScalarPtr> resolved_arguments;
-  const PtrList<ParseExpression> *unresolved_arguments =
-      parse_function_call.arguments();
+  const PtrList<ParseExpression> *unresolved_arguments = parse_function_call.arguments();
   // The first aggregate function and window aggregate function in the arguments.
   const ParseTreeNode *first_aggregate_function = nullptr;
   const ParseTreeNode *first_window_aggregate_function = nullptr;
@@ -2668,7 +2667,7 @@ E::ScalarPtr Resolver::resolveFunctionCall(
     for (const ParseExpression &unresolved_argument : *unresolved_arguments) {
       ExpressionResolutionInfo expr_resolution_info(
           *expression_resolution_info);
-      resolved_arguments.push_back(
+      resolved_arguments.emplace_back(
           resolveExpression(unresolved_argument,
                             nullptr,  // No Type hint.
                             &expr_resolution_info));
@@ -2687,6 +2686,17 @@ E::ScalarPtr Resolver::resolveFunctionCall(
     }
   }
 
+  if (UnaryOperationFactory::Instance().hasUnaryOperation(function_name,
+                                                          resolved_arguments.size())) {
+    E::ScalarPtr scalar = resolveScalarFunction(parse_function_call,
+                                                function_name,
+                                                resolved_arguments,
+                                                expression_resolution_info);
+    expression_resolution_info->parse_aggregate_expression = first_aggregate_function;
+    expression_resolution_info->parse_window_aggregate_expression = first_window_aggregate_function;
+    return scalar;
+  }
+
   if (count_star && !resolved_arguments.empty()) {
     THROW_SQL_ERROR_AT(&parse_function_call)
         << "COUNT aggregate has both star (*) and non-star arguments.";

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/query_optimizer/resolver/Resolver.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/resolver/Resolver.hpp b/query_optimizer/resolver/Resolver.hpp
index a3d0833..ea26e0c 100644
--- a/query_optimizer/resolver/Resolver.hpp
+++ b/query_optimizer/resolver/Resolver.hpp
@@ -452,9 +452,6 @@ class Resolver {
    * @brief Resolves a function call. For a non-scalar function, the returned
    *        expression is an AttributeReference to the actual resolved expression.
    *
-   * @note This currently only handles resolving aggregate functions and window
-   *       aggregate functions.
-   *
    * @param parse_function_call The function call to be resolved.
    * @param expression_resolution_info Resolution info that contains the name
    *                                   resolver and info to be updated after
@@ -465,6 +462,12 @@ class Resolver {
       const ParseFunctionCall &parse_function_call,
       ExpressionResolutionInfo *expression_resolution_info);
 
+  expressions::ScalarPtr resolveScalarFunction(
+      const ParseFunctionCall &parse_function_call,
+      const std::string &function_name,
+      const std::vector<expressions::ScalarPtr> &resolved_arguments,
+      ExpressionResolutionInfo *expression_resolution_info);
+
   /**
    * @brief Resolves a window aggregate function.
    *

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/types/CMakeLists.txt b/types/CMakeLists.txt
index 769187b..1fac11a 100644
--- a/types/CMakeLists.txt
+++ b/types/CMakeLists.txt
@@ -49,9 +49,11 @@ add_library(quickstep_types_NullType ../empty_src.cpp NullType.hpp)
 add_library(quickstep_types_NumericSuperType ../empty_src.cpp NumericSuperType.hpp)
 add_library(quickstep_types_NumericTypeUnifier ../empty_src.cpp NumericTypeUnifier.hpp)
 add_library(quickstep_types_Type Type.cpp Type.hpp)
+add_library(quickstep_types_TypeConcept ../empty_src.cpp TypeConcept.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_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})
@@ -165,6 +167,8 @@ target_link_libraries(quickstep_types_Type
                       quickstep_types_TypeID
                       quickstep_types_TypedValue
                       quickstep_utility_Macros)
+target_link_libraries(quickstep_types_TypeConcept
+                      glog)
 target_link_libraries(quickstep_types_TypeFactory
                       glog
                       quickstep_types_CharType
@@ -182,6 +186,25 @@ target_link_libraries(quickstep_types_TypeFactory
                       quickstep_types_VarCharType
                       quickstep_types_YearMonthIntervalType
                       quickstep_utility_Macros)
+target_link_libraries(quickstep_types_TypeID
+                      quickstep_types_Type_proto
+                      quickstep_utility_Macros)
+target_link_libraries(quickstep_types_TypeUtil
+                      quickstep_types_CharType
+                      quickstep_types_DateType
+                      quickstep_types_DatetimeIntervalType
+                      quickstep_types_DatetimeType
+                      quickstep_types_DoubleType
+                      quickstep_types_FloatType
+                      quickstep_types_IntType
+                      quickstep_types_LongType
+                      quickstep_types_NullType
+                      quickstep_types_Type
+                      quickstep_types_TypeID
+                      quickstep_types_Type_proto
+                      quickstep_types_VarCharType
+                      quickstep_types_YearMonthIntervalType
+                      quickstep_utility_Macros)
 target_link_libraries(quickstep_types_TypedValue
                       farmhash
                       glog
@@ -238,6 +261,7 @@ target_link_libraries(quickstep_types
                       quickstep_types_NumericSuperType
                       quickstep_types_NumericTypeUnifier
                       quickstep_types_Type
+                      quickstep_types_TypeUtil
                       quickstep_types_Type_proto
                       quickstep_types_TypeErrors
                       quickstep_types_TypeFactory

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/CharType.cpp
----------------------------------------------------------------------
diff --git a/types/CharType.cpp b/types/CharType.cpp
index 591c038..bc05711 100644
--- a/types/CharType.cpp
+++ b/types/CharType.cpp
@@ -66,8 +66,7 @@ const CharType& CharType::InstanceFromProto(const serialization::Type &proto) {
 
 serialization::Type CharType::getProto() const {
   serialization::Type proto;
-  proto.set_type_id(serialization::Type::CHAR);
-
+  proto.mutable_type_id()->CopyFrom(TypeIDFactory::GetProto(type_id_));
   proto.set_nullable(nullable_);
 
   proto.SetExtension(serialization::CharType::length, length_);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/CharType.hpp
----------------------------------------------------------------------
diff --git a/types/CharType.hpp b/types/CharType.hpp
index c7321f4..e591953 100644
--- a/types/CharType.hpp
+++ b/types/CharType.hpp
@@ -43,7 +43,7 @@ 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, kNonNativeInline> {
  public:
   /**
    * @brief Get a reference to the non-nullable singleton instance of this Type
@@ -134,7 +134,7 @@ class CharType : public AsciiStringSuperType {
 
  private:
   CharType(const std::size_t length, const bool nullable)
-      : AsciiStringSuperType(kChar, nullable, length, length, length) {
+      : AsciiStringSuperType<kChar, kNonNativeInline>(nullable, length, length, length) {
   }
 
   template <bool nullable_internal>

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/DateType.hpp
----------------------------------------------------------------------
diff --git a/types/DateType.hpp b/types/DateType.hpp
index 07225d5..a39a28c 100644
--- a/types/DateType.hpp
+++ b/types/DateType.hpp
@@ -40,12 +40,8 @@ class TypedValue;
 /**
  * @brief A type representing the date.
  **/
-class DateType : public Type {
+class DateType : public TypeConcept<kDate, false, kNativeEmbedded, DateLit> {
  public:
-  typedef DateLit cpptype;
-
-  static const TypeID kStaticTypeID = kDate;
-
   /**
    * @brief Get a reference to the non-nullable singleton instance of this
    *        Type.
@@ -124,7 +120,9 @@ class DateType : public Type {
 
  private:
   explicit DateType(const bool nullable)
-      : Type(Type::kOther, kDate, nullable, sizeof(DateLit), sizeof(DateLit)) {
+      : TypeConcept<kDate, false, kNativeEmbedded, DateLit>(
+             Type::kOther, kStaticTypeID, nullable,
+             sizeof(DateLit), sizeof(DateLit)) {
   }
 
   DISALLOW_COPY_AND_ASSIGN(DateType);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/DatetimeIntervalType.hpp
----------------------------------------------------------------------
diff --git a/types/DatetimeIntervalType.hpp b/types/DatetimeIntervalType.hpp
index 005cb31..3b22471 100644
--- a/types/DatetimeIntervalType.hpp
+++ b/types/DatetimeIntervalType.hpp
@@ -40,12 +40,9 @@ namespace quickstep {
 /**
  * @brief A type representing the datetime interval.
  **/
-class DatetimeIntervalType : public Type {
+class DatetimeIntervalType :
+    public TypeConcept<kDatetimeInterval, false, kNativeEmbedded, DatetimeIntervalLit> {
  public:
-  typedef DatetimeIntervalLit cpptype;
-
-  static const TypeID kStaticTypeID = kDatetimeInterval;
-
   /**
    * @brief Get a reference to the non-nullable singleton instance of this
    *        Type.
@@ -116,7 +113,9 @@ class DatetimeIntervalType : public Type {
 
  private:
   explicit DatetimeIntervalType(const bool nullable)
-      : Type(Type::kOther, kDatetimeInterval, nullable, sizeof(DatetimeIntervalLit), sizeof(DatetimeIntervalLit)) {
+      : TypeConcept<kDatetimeInterval, false, kNativeEmbedded, DatetimeIntervalLit>(
+             Type::kOther, kStaticTypeID, nullable,
+             sizeof(DatetimeIntervalLit), sizeof(DatetimeIntervalLit)) {
   }
 
   DISALLOW_COPY_AND_ASSIGN(DatetimeIntervalType);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/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/27c41625/types/DatetimeType.hpp
----------------------------------------------------------------------
diff --git a/types/DatetimeType.hpp b/types/DatetimeType.hpp
index aad536a..b6742f9 100644
--- a/types/DatetimeType.hpp
+++ b/types/DatetimeType.hpp
@@ -40,12 +40,8 @@ class TypedValue;
 /**
  * @brief A type representing the datetime.
  **/
-class DatetimeType : public Type {
+class DatetimeType : public TypeConcept<kDatetime, false, kNativeEmbedded, DatetimeLit> {
  public:
-  typedef DatetimeLit cpptype;
-
-  static const TypeID kStaticTypeID = kDatetime;
-
   /**
    * @brief Get a reference to the non-nullable singleton instance of this
    *        Type.
@@ -132,7 +128,9 @@ class DatetimeType : public Type {
 
  private:
   explicit DatetimeType(const bool nullable)
-      : Type(Type::kOther, kDatetime, nullable, sizeof(DatetimeLit), sizeof(DatetimeLit)) {
+      : TypeConcept<kDatetime, false, kNativeEmbedded, quickstep::DatetimeLit>(
+             Type::kOther, kStaticTypeID, nullable,
+             sizeof(DatetimeLit), sizeof(DatetimeLit)) {
   }
 
   DISALLOW_COPY_AND_ASSIGN(DatetimeType);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/DoubleType.cpp
----------------------------------------------------------------------
diff --git a/types/DoubleType.cpp b/types/DoubleType.cpp
index 6a7914c..52645f8 100644
--- a/types/DoubleType.cpp
+++ b/types/DoubleType.cpp
@@ -41,8 +41,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(),

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/DoubleType.hpp
----------------------------------------------------------------------
diff --git a/types/DoubleType.hpp b/types/DoubleType.hpp
index b4175b0..4d1dd7e 100644
--- a/types/DoubleType.hpp
+++ b/types/DoubleType.hpp
@@ -40,10 +40,8 @@ class Type;
 /**
  * @brief A type representing a double-precision floating-point number.
  **/
-class DoubleType : public NumericSuperType<double> {
+class DoubleType : public NumericSuperType<kDouble, double> {
  public:
-  static const TypeID kStaticTypeID;
-
   /**
    * @brief Get a reference to the non-nullable singleton instance of this
    *        Type.
@@ -122,7 +120,7 @@ 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, double>(nullable) {
   }
 
   DISALLOW_COPY_AND_ASSIGN(DoubleType);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/FloatType.cpp
----------------------------------------------------------------------
diff --git a/types/FloatType.cpp b/types/FloatType.cpp
index e904f29..3aa2eb9 100644
--- a/types/FloatType.cpp
+++ b/types/FloatType.cpp
@@ -41,8 +41,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(),

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/FloatType.hpp
----------------------------------------------------------------------
diff --git a/types/FloatType.hpp b/types/FloatType.hpp
index 2a156e1..ee9c45c 100644
--- a/types/FloatType.hpp
+++ b/types/FloatType.hpp
@@ -40,10 +40,8 @@ class Type;
 /**
  * @brief A type representing a single-precision floating-point number.
  **/
-class FloatType : public NumericSuperType<float> {
+class FloatType : public NumericSuperType<kFloat, float> {
  public:
-  static const TypeID kStaticTypeID;
-
   /**
    * @brief Get a reference to the non-nullable singleton instance of this
    *        Type.
@@ -122,7 +120,7 @@ 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, float>(nullable) {
   }
 
   DISALLOW_COPY_AND_ASSIGN(FloatType);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/IntType.cpp
----------------------------------------------------------------------
diff --git a/types/IntType.cpp b/types/IntType.cpp
index 9781675..8b7fbb1 100644
--- a/types/IntType.cpp
+++ b/types/IntType.cpp
@@ -32,8 +32,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;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/IntType.hpp
----------------------------------------------------------------------
diff --git a/types/IntType.hpp b/types/IntType.hpp
index 08d6b3d..25ce3c8 100644
--- a/types/IntType.hpp
+++ b/types/IntType.hpp
@@ -40,10 +40,8 @@ class Type;
 /**
  * @brief A type representing a 32-bit integer.
  **/
-class IntType : public NumericSuperType<int> {
+class IntType : public NumericSuperType<kInt, int> {
  public:
-  static const TypeID kStaticTypeID;
-
   /**
    * @brief Get a reference to the non-nullable singleton instance of this
    *        Type.
@@ -109,7 +107,7 @@ class IntType : public NumericSuperType<int> {
 
  private:
   explicit IntType(const bool nullable)
-      : NumericSuperType<int>(kInt, nullable) {
+      : NumericSuperType<kInt, int>(nullable) {
   }
 
   DISALLOW_COPY_AND_ASSIGN(IntType);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/LongType.cpp
----------------------------------------------------------------------
diff --git a/types/LongType.cpp b/types/LongType.cpp
index fbf8d30..153e239 100644
--- a/types/LongType.cpp
+++ b/types/LongType.cpp
@@ -38,8 +38,6 @@
 
 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(),

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/LongType.hpp
----------------------------------------------------------------------
diff --git a/types/LongType.hpp b/types/LongType.hpp
index a90dd32..52244a7 100644
--- a/types/LongType.hpp
+++ b/types/LongType.hpp
@@ -41,10 +41,8 @@ class Type;
 /**
  * @brief A type representing a 64-bit integer.
  **/
-class LongType : public NumericSuperType<std::int64_t> {
+class LongType : public NumericSuperType<kLong, std::int64_t> {
  public:
-  static const TypeID kStaticTypeID;
-
   /**
    * @brief Get a reference to the non-nullable singleton instance of this
    *        Type.
@@ -110,7 +108,7 @@ class LongType : public NumericSuperType<std::int64_t> {
 
  private:
   explicit LongType(const bool nullable)
-      : NumericSuperType<std::int64_t>(kLong, nullable) {
+      : NumericSuperType<kLong, std::int64_t>(nullable) {
   }
 
   DISALLOW_COPY_AND_ASSIGN(LongType);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/NullCoercibilityCheckMacro.hpp
----------------------------------------------------------------------
diff --git a/types/NullCoercibilityCheckMacro.hpp b/types/NullCoercibilityCheckMacro.hpp
index 70e1beb..2dcbec3 100644
--- a/types/NullCoercibilityCheckMacro.hpp
+++ b/types/NullCoercibilityCheckMacro.hpp
@@ -34,7 +34,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/27c41625/types/NullType.hpp
----------------------------------------------------------------------
diff --git a/types/NullType.hpp b/types/NullType.hpp
index c27a584..6c6dd06 100644
--- a/types/NullType.hpp
+++ b/types/NullType.hpp
@@ -48,10 +48,8 @@ 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 TypeConcept<kNullType, false, kNativeEmbedded> {
  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
@@ -106,7 +104,9 @@ 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()
+      : TypeConcept<kNullType, false, kNativeEmbedded>(
+            Type::kOther, kStaticTypeID, true, 0, 0) {
   }
 
   DISALLOW_COPY_AND_ASSIGN(NullType);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/NumericSuperType.hpp
----------------------------------------------------------------------
diff --git a/types/NumericSuperType.hpp b/types/NumericSuperType.hpp
index 0cc1546..ceb24b6 100644
--- a/types/NumericSuperType.hpp
+++ b/types/NumericSuperType.hpp
@@ -38,18 +38,16 @@ 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, typename CppType>
+class NumericSuperType : public TypeConcept<type_id, false, kNativeEmbedded, CppType> {
  public:
-  typedef CppType cpptype;
-
   std::size_t estimateAverageByteLength() const override {
     return sizeof(CppType);
   }
 
   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 {
@@ -57,8 +55,9 @@ class NumericSuperType : public Type {
   }
 
  protected:
-  NumericSuperType(const TypeID type_id, const bool nullable)
-      : Type(Type::kNumeric, type_id, nullable, sizeof(CppType), sizeof(CppType)) {
+  NumericSuperType(const bool nullable)
+      : TypeConcept<type_id, false, kNativeEmbedded, CppType>(
+            Type::kNumeric, type_id, nullable, sizeof(CppType), sizeof(CppType)) {
   }
 
  private:

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/Type.cpp
----------------------------------------------------------------------
diff --git a/types/Type.cpp b/types/Type.cpp
index f3d3f1b..144f39a 100644
--- a/types/Type.cpp
+++ b/types/Type.cpp
@@ -30,38 +30,7 @@ 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");
-  }
-
+  proto.mutable_type_id()->CopyFrom(TypeIDFactory::GetProto(type_id_));
   proto.set_nullable(nullable_);
 
   return proto;
@@ -85,12 +54,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/27c41625/types/Type.hpp
----------------------------------------------------------------------
diff --git a/types/Type.hpp b/types/Type.hpp
index 0e8c4e5..afc46eb 100644
--- a/types/Type.hpp
+++ b/types/Type.hpp
@@ -264,7 +264,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
@@ -471,12 +471,59 @@ class Type {
   DISALLOW_COPY_AND_ASSIGN(Type);
 };
 
+template <TypeID type_id,
+          bool parameterized,
+          TypeStorageLayout layout,
+          typename CppType = void>
+class TypeConcept : public Type {
+ public:
+  static constexpr TypeID kStaticTypeID = type_id;
+  static constexpr bool kParameterized = parameterized;
+  static constexpr TypeStorageLayout kLayout = layout;
+
+  typedef CppType cpptype;
+
+ protected:
+  template <typename ...ArgTypes>
+  TypeConcept(ArgTypes &&...args)
+      : Type(std::forward<ArgTypes>(args)...) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TypeConcept);
+};
+
+
+template <TypeID type_id,
+          bool parameterized,
+          TypeStorageLayout layout,
+          typename CppType>
+constexpr TypeID TypeConcept<type_id, parameterized, layout, CppType>::kStaticTypeID;
+
+template <TypeID type_id,
+          bool parameterized,
+          TypeStorageLayout layout,
+          typename CppType>
+constexpr bool TypeConcept<type_id, parameterized, layout, CppType>::kParameterized;
+
+template <TypeID type_id,
+          bool parameterized,
+          TypeStorageLayout layout,
+          typename CppType>
+constexpr TypeStorageLayout TypeConcept<type_id, parameterized, layout, CppType>::kLayout;
+
 /**
  * @brief A superclass for ASCII string types.
  **/
-class AsciiStringSuperType : public Type {
+template <TypeID type_id, TypeStorageLayout layout>
+class AsciiStringSuperType : public TypeConcept<type_id, true, layout> {
  public:
-  bool isCoercibleFrom(const Type &original_type) const override;
+  bool isCoercibleFrom(const Type &original_type) const override {
+    if (original_type.isNullable() && !this->nullable_) {
+      return false;
+    }
+    return (original_type.getSuperTypeID() == Type::kAsciiString)
+           || (original_type.getTypeID() == kNullType);
+  }
 
   /**
    * @brief Get the character-length of this string type.
@@ -488,12 +535,12 @@ class AsciiStringSuperType : public Type {
   }
 
  protected:
-  AsciiStringSuperType(const TypeID type_id,
-                       const bool nullable,
+  AsciiStringSuperType(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),
+      : TypeConcept<type_id, true, layout>(
+            Type::kAsciiString, type_id, nullable, minimum_byte_length, maximum_byte_length),
         length_(string_length) {
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/Type.proto
----------------------------------------------------------------------
diff --git a/types/Type.proto b/types/Type.proto
index d03b5a4..d454923 100644
--- a/types/Type.proto
+++ b/types/Type.proto
@@ -19,21 +19,11 @@ 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;
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/TypeConcept.hpp
----------------------------------------------------------------------
diff --git a/types/TypeConcept.hpp b/types/TypeConcept.hpp
new file mode 100644
index 0000000..d1ec79d
--- /dev/null
+++ b/types/TypeConcept.hpp
@@ -0,0 +1,33 @@
+/**
+ * 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_CONCEPT_HPP_
+#define QUICKSTEP_TYPES_TYPE_CONCEPT_HPP_
+
+namespace quickstep {
+
+/** \addtogroup Types
+ *  @{
+ */
+
+/** @} */
+
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_TYPES_TYPE_CONCEPT_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/TypeFactory.cpp
----------------------------------------------------------------------
diff --git a/types/TypeFactory.cpp b/types/TypeFactory.cpp
index 7403dc9..df21d50 100644
--- a/types/TypeFactory.cpp
+++ b/types/TypeFactory.cpp
@@ -91,21 +91,22 @@ bool TypeFactory::ProtoIsValid(const serialization::Type &proto) {
   }
 
   // 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:
+  const TypeID type_id = TypeIDFactory::ReconstructFromProto(proto.type_id());
+  switch (type_id) {
+    case kInt:
+    case kLong:
+    case kFloat:
+    case kDouble:
+    case kDate:
+    case kDatetime:
+    case kDatetimeInterval:
+    case kYearMonthInterval:
       return true;
-    case serialization::Type::CHAR:
+    case kChar:
       return proto.HasExtension(serialization::CharType::length);
-    case serialization::Type::VAR_CHAR:
+    case kVarChar:
       return proto.HasExtension(serialization::VarCharType::length);
-    case serialization::Type::NULL_TYPE:
+    case kNullType:
       return proto.nullable();
     default:
       return false;
@@ -117,28 +118,29 @@ 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:
+  const TypeID type_id = TypeIDFactory::ReconstructFromProto(proto.type_id());
+  switch (type_id) {
+    case kInt:
       return IntType::Instance(proto.nullable());
-    case serialization::Type::LONG:
+    case kLong:
       return LongType::Instance(proto.nullable());
-    case serialization::Type::FLOAT:
+    case kFloat:
       return FloatType::Instance(proto.nullable());
-    case serialization::Type::DOUBLE:
+    case kDouble:
       return DoubleType::Instance(proto.nullable());
-    case serialization::Type::DATE:
+    case kDate:
       return DateType::Instance(proto.nullable());
-    case serialization::Type::DATETIME:
+    case kDatetime:
       return DatetimeType::Instance(proto.nullable());
-    case serialization::Type::DATETIME_INTERVAL:
+    case kDatetimeInterval:
       return DatetimeIntervalType::Instance(proto.nullable());
-    case serialization::Type::YEAR_MONTH_INTERVAL:
+    case kYearMonthInterval:
       return YearMonthIntervalType::Instance(proto.nullable());
-    case serialization::Type::CHAR:
+    case kChar:
       return CharType::InstanceFromProto(proto);
-    case serialization::Type::VAR_CHAR:
+    case kVarChar:
       return VarCharType::InstanceFromProto(proto);
-    case serialization::Type::NULL_TYPE:
+    case kNullType:
       DCHECK(proto.nullable());
       return NullType::InstanceNullable();
     default:

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/TypeID.hpp
----------------------------------------------------------------------
diff --git a/types/TypeID.hpp b/types/TypeID.hpp
index c54d8a5..26731b9 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,7 +33,7 @@ namespace quickstep {
  *
  * @note TypedValue assumes that this doesn't exceed 64 TypeIDs.
  **/
-enum TypeID {
+enum TypeID : int {
   kInt = 0,
   kLong,
   kFloat,
@@ -44,6 +48,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 +76,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/27c41625/types/TypeUtil.hpp
----------------------------------------------------------------------
diff --git a/types/TypeUtil.hpp b/types/TypeUtil.hpp
new file mode 100644
index 0000000..fe55952
--- /dev/null
+++ b/types/TypeUtil.hpp
@@ -0,0 +1,181 @@
+/**
+ * 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/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 "utility/Macros.hpp"
+#include "utility/TemplateUtil.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+
+template <TypeID type_id>
+struct TypeGenerator {};
+
+#define REGISTER_TYPE(T) \
+  template <> struct TypeGenerator<T::kStaticTypeID> { typedef T type; };
+
+REGISTER_TYPE(IntType);
+REGISTER_TYPE(LongType);
+REGISTER_TYPE(FloatType);
+REGISTER_TYPE(DoubleType);
+REGISTER_TYPE(DateType);
+REGISTER_TYPE(DatetimeType);
+REGISTER_TYPE(DatetimeIntervalType);
+REGISTER_TYPE(YearMonthIntervalType);
+REGISTER_TYPE(CharType);
+REGISTER_TYPE(VarCharType);
+REGISTER_TYPE(NullType);
+
+#undef REGISTER_TYPE
+
+namespace type_util_internal {
+
+template <bool require_parameterized>
+struct TypeIDSelectorParameterizedHelper {
+  template <typename TypeIDConstant, typename FunctorT, typename EnableT = void>
+  struct Implementation {
+    inline static auto Invoke(const FunctorT &functor)
+        -> decltype(functor(TypeIDConstant())) {
+      DLOG(FATAL) << "Unexpected TypeID: "
+                  << kTypeNames[static_cast<int>(TypeIDConstant::value)];
+    }
+  };
+};
+
+template <bool require_non_parameterized>
+template <typename TypeIDConstant, typename FunctorT>
+struct TypeIDSelectorParameterizedHelper<require_non_parameterized>::Implementation<
+    TypeIDConstant, FunctorT,
+    std::enable_if_t<TypeGenerator<TypeIDConstant::value>::type::kParameterized
+                         ^ require_non_parameterized>> {
+  inline static auto Invoke(const FunctorT &functor) {
+    return functor(TypeIDConstant());
+  }
+};
+
+}  // namespace type_util_internal
+
+struct TypeIDSelectorAll {
+  template <typename TypeIDConstant, typename FunctorT, typename EnableT = void>
+  struct Implementation {
+    inline static auto Invoke(const FunctorT &functor) {
+      return functor(TypeIDConstant());
+    }
+  };
+};
+
+using TypeIDSelectorNonParameterized =
+    type_util_internal::TypeIDSelectorParameterizedHelper<true>;
+
+using TypeIDSelectorParameterized =
+    type_util_internal::TypeIDSelectorParameterizedHelper<false>;
+
+template <TypeID ...candidates>
+struct TypeIDSelectorEqualsAny {
+  template <typename TypeIDConstant, typename FunctorT, typename EnableT = void>
+  struct Implementation {
+    inline static auto Invoke(const FunctorT &functor)
+        -> decltype(functor(TypeIDConstant())) {
+      DLOG(FATAL) << "Unexpected TypeID: "
+                  << kTypeNames[static_cast<int>(TypeIDConstant::value)];
+    }
+  };
+};
+
+template <TypeID ...candidates>
+template <typename TypeIDConstant, typename FunctorT>
+struct TypeIDSelectorEqualsAny<candidates...>::Implementation<
+    TypeIDConstant, FunctorT,
+    std::enable_if_t<
+        EqualsAny<TypeIDConstant,
+                  std::integral_constant<TypeID, candidates>...>::value>> {
+  inline static auto Invoke(const FunctorT &functor) {
+      return functor(TypeIDConstant());
+  }
+};
+
+template <typename Selector = TypeIDSelectorAll, typename FunctorT>
+inline auto InvokeOnTypeID(const TypeID type_id,
+                           const FunctorT &functor) {
+#define REGISTER_TYPE_ID(type_id) \
+  case type_id: \
+    return Selector::template Implementation< \
+        std::integral_constant<TypeID, type_id>, FunctorT>::Invoke(functor)
+
+  switch (type_id) {
+
+    REGISTER_TYPE_ID(kInt);
+    REGISTER_TYPE_ID(kLong);
+    REGISTER_TYPE_ID(kFloat);
+    REGISTER_TYPE_ID(kDouble);
+    REGISTER_TYPE_ID(kDate);
+    REGISTER_TYPE_ID(kDatetime);
+    REGISTER_TYPE_ID(kDatetimeInterval);
+    REGISTER_TYPE_ID(kYearMonthInterval);
+    REGISTER_TYPE_ID(kChar);
+    REGISTER_TYPE_ID(kVarChar);
+    REGISTER_TYPE_ID(kNullType);
+
+    default:
+      FATAL_ERROR("Unrecognized TypeID in InvokeOnTypeID()");
+  }
+
+#undef REGISTER_TYPE_ID
+}
+
+class TypeUtil {
+ public:
+  static bool IsParameterized(const TypeID type_id) {
+    return InvokeOnTypeID(
+        type_id,
+        [&](auto tid) -> bool {  // NOLINT(build/c++11)
+      return TypeGenerator<decltype(tid)::value>::type::kParameterized;
+    });
+  }
+
+ private:
+  TypeUtil() {}
+
+  DISALLOW_COPY_AND_ASSIGN(TypeUtil);
+};
+
+/** @} */
+
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_TYPES_TYPE_UTIL_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/TypedValue.cpp
----------------------------------------------------------------------
diff --git a/types/TypedValue.cpp b/types/TypedValue.cpp
index 8dd8b60..1360237 100644
--- a/types/TypedValue.cpp
+++ b/types/TypedValue.cpp
@@ -82,33 +82,29 @@ serialization::TypedValue TypedValue::getProto() const {
 
   // NOTE(chasseur): To represent a NULL value, only the 'type_id' field of the
   // proto is filled in, and all the optional value fields are omitted.
+  proto.mutable_type_id()->CopyFrom(TypeIDFactory::GetProto(getTypeID()));
   switch (getTypeID()) {
     case kInt:
-      proto.set_type_id(serialization::Type::INT);
       if (!isNull()) {
         proto.set_int_value(getLiteral<int>());
       }
       break;
     case kLong:
-      proto.set_type_id(serialization::Type::LONG);
       if (!isNull()) {
         proto.set_long_value(getLiteral<std::int64_t>());
       }
       break;
     case kFloat:
-      proto.set_type_id(serialization::Type::FLOAT);
       if (!isNull()) {
         proto.set_float_value(getLiteral<float>());
       }
       break;
     case kDouble:
-      proto.set_type_id(serialization::Type::DOUBLE);
       if (!isNull()) {
         proto.set_double_value(getLiteral<double>());
       }
       break;
     case kDate:
-      proto.set_type_id(serialization::Type::DATE);
       if (!isNull()) {
         serialization::TypedValue::DateLit *literal_date_proto = proto.mutable_date_value();
         literal_date_proto->set_year(value_union_.date_value.year);
@@ -117,37 +113,31 @@ serialization::TypedValue TypedValue::getProto() const {
       }
       break;
     case kDatetime:
-      proto.set_type_id(serialization::Type::DATETIME);
       if (!isNull()) {
         proto.set_datetime_value(value_union_.datetime_value.ticks);
       }
       break;
     case kDatetimeInterval:
-      proto.set_type_id(serialization::Type::DATETIME_INTERVAL);
       if (!isNull()) {
         proto.set_datetime_interval_value(value_union_.datetime_interval_value.interval_ticks);
       }
       break;
     case kYearMonthInterval:
-      proto.set_type_id(serialization::Type::YEAR_MONTH_INTERVAL);
       if (!isNull()) {
         proto.set_year_month_interval_value(value_union_.year_month_interval_value.months);
       }
       break;
     case kChar:
-      proto.set_type_id(serialization::Type::CHAR);
       if (!isNull()) {
         proto.set_out_of_line_data(static_cast<const char*>(getOutOfLineData()), getDataSize());
       }
       break;
     case kVarChar:
-      proto.set_type_id(serialization::Type::VAR_CHAR);
       if (!isNull()) {
         proto.set_out_of_line_data(static_cast<const char*>(getOutOfLineData()), getDataSize());
       }
       break;
     case kNullType:
-      proto.set_type_id(serialization::Type::NULL_TYPE);
       DCHECK(isNull());
       break;
     default:
@@ -166,24 +156,25 @@ TypedValue TypedValue::ReconstructFromProto(const serialization::TypedValue &pro
       << "Attempted to create TypedValue from an invalid proto description:\n"
       << proto.DebugString();
 
-  switch (proto.type_id()) {
-    case serialization::Type::INT:
+  const TypeID type_id = TypeIDFactory::ReconstructFromProto(proto.type_id());
+  switch (type_id) {
+    case kInt:
       return proto.has_int_value() ?
           TypedValue(static_cast<int>(proto.int_value())) :
           TypedValue(kInt);
-    case serialization::Type::LONG:
+    case kLong:
       return proto.has_long_value() ?
           TypedValue(static_cast<std::int64_t>(proto.long_value())) :
           TypedValue(kLong);
-    case serialization::Type::FLOAT:
+    case kFloat:
       return proto.has_float_value() ?
           TypedValue(static_cast<float>(proto.float_value())) :
           TypedValue(kFloat);
-    case serialization::Type::DOUBLE:
+    case kDouble:
       return proto.has_double_value() ?
           TypedValue(static_cast<double>(proto.double_value())) :
           TypedValue(kDouble);
-    case serialization::Type::DATE:
+    case kDate:
       if (proto.has_date_value()) {
         return TypedValue(DateLit::Create(proto.date_value().year(),
                                           proto.date_value().month(),
@@ -191,7 +182,7 @@ TypedValue TypedValue::ReconstructFromProto(const serialization::TypedValue &pro
       } else {
         return TypedValue(kDate);
       }
-    case serialization::Type::DATETIME:
+    case kDatetime:
       if (proto.has_datetime_value()) {
         DatetimeLit datetime;
         datetime.ticks = proto.datetime_value();
@@ -199,7 +190,7 @@ TypedValue TypedValue::ReconstructFromProto(const serialization::TypedValue &pro
       } else {
         return TypedValue(kDatetime);
       }
-    case serialization::Type::DATETIME_INTERVAL:
+    case kDatetimeInterval:
       if (proto.has_datetime_interval_value()) {
         DatetimeIntervalLit interval;
         interval.interval_ticks = proto.datetime_interval_value();
@@ -207,7 +198,7 @@ TypedValue TypedValue::ReconstructFromProto(const serialization::TypedValue &pro
       } else {
         return TypedValue(kDatetimeInterval);
       }
-    case serialization::Type::YEAR_MONTH_INTERVAL:
+    case kYearMonthInterval:
       if (proto.has_year_month_interval_value()) {
         YearMonthIntervalLit interval;
         interval.months = proto.year_month_interval_value();
@@ -215,19 +206,19 @@ TypedValue TypedValue::ReconstructFromProto(const serialization::TypedValue &pro
       } else {
         return TypedValue(kYearMonthInterval);
       }
-    case serialization::Type::CHAR:
+    case kChar:
       return proto.has_out_of_line_data() ?
           TypedValue(kChar,
                      static_cast<const void*>(proto.out_of_line_data().c_str()),
                      proto.out_of_line_data().size()).ensureNotReference() :
           TypedValue(kChar);
-    case serialization::Type::VAR_CHAR:
+    case kVarChar:
       return proto.has_out_of_line_data() ?
           TypedValue(kVarChar,
                      static_cast<const void*>(proto.out_of_line_data().c_str()),
                      proto.out_of_line_data().size()).ensureNotReference() :
           TypedValue(kVarChar);
-    case serialization::Type::NULL_TYPE:
+    case kNullType:
       return TypedValue(kNullType);
     default:
       FATAL_ERROR("Unrecognized TypeID in TypedValue::ReconstructFromProto");

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/TypedValue.hpp
----------------------------------------------------------------------
diff --git a/types/TypedValue.hpp b/types/TypedValue.hpp
index 0ba3d53..18ed4af 100644
--- a/types/TypedValue.hpp
+++ b/types/TypedValue.hpp
@@ -264,9 +264,9 @@ class TypedValue {
    *        TypedValue will take ownership of this memory.
    * @param value_size The number of bytes of data at value_ptr.
    **/
-  static TypedValue CreateWithOwnedData(const TypeID type_id,
-                                        void *value_ptr,
-                                        const std::size_t value_size) {
+  inline static TypedValue CreateWithOwnedData(const TypeID type_id,
+                                               void *value_ptr,
+                                               const std::size_t value_size) {
     TypedValue val(type_id, value_ptr, value_size);
     val.value_info_ |= kOwnershipMask;
     return val;
@@ -467,7 +467,8 @@ class TypedValue {
    * @return The underlying literal value represented by this TypedValue.
    **/
   template <typename LiteralType>
-  LiteralType getLiteral() const;
+  LiteralType getLiteral() const {
+  }
 
   /**
    * @brief Get the out-of-line data which this TypedValue points to.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/TypedValue.proto
----------------------------------------------------------------------
diff --git a/types/TypedValue.proto b/types/TypedValue.proto
index 7f3ab7a..db44dec 100644
--- a/types/TypedValue.proto
+++ b/types/TypedValue.proto
@@ -22,7 +22,7 @@ package quickstep.serialization;
 import "types/Type.proto";
 
 message TypedValue {
-  required Type.TypeID type_id = 1;
+  required TypeID type_id = 1;
 
   // NOTE(zuyu): For a NULL value, none of the optional fields are filled in.
   optional int32 int_value = 2;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/VarCharType.cpp
----------------------------------------------------------------------
diff --git a/types/VarCharType.cpp b/types/VarCharType.cpp
index 02845b1..05162cf 100644
--- a/types/VarCharType.cpp
+++ b/types/VarCharType.cpp
@@ -66,8 +66,7 @@ const VarCharType& VarCharType::InstanceFromProto(const serialization::Type &pro
 
 serialization::Type VarCharType::getProto() const {
   serialization::Type proto;
-  proto.set_type_id(serialization::Type::VAR_CHAR);
-
+  proto.mutable_type_id()->CopyFrom(TypeIDFactory::GetProto(type_id_));
   proto.set_nullable(nullable_);
 
   proto.SetExtension(serialization::VarCharType::length, length_);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/VarCharType.hpp
----------------------------------------------------------------------
diff --git a/types/VarCharType.hpp b/types/VarCharType.hpp
index bb50e92..af3ab64 100644
--- a/types/VarCharType.hpp
+++ b/types/VarCharType.hpp
@@ -43,7 +43,7 @@ namespace quickstep {
  *       character. This means that the VARCHAR(X) type requires from 1 to X+1
  *       bytes of storage, depending on string length.
  **/
-class VarCharType : public AsciiStringSuperType {
+class VarCharType : public AsciiStringSuperType<kVarChar, kOutOfLine> {
  public:
   /**
    * @brief Get a reference to the non-nullable singleton instance of this Type
@@ -137,7 +137,7 @@ class VarCharType : public AsciiStringSuperType {
 
  private:
   VarCharType(const std::size_t length, const bool nullable)
-      : AsciiStringSuperType(kVarChar, nullable, 1, length + 1, length) {
+      : AsciiStringSuperType<kVarChar, kOutOfLine>(nullable, 1, length + 1, length) {
   }
 
   template <bool nullable_internal>

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/YearMonthIntervalType.hpp
----------------------------------------------------------------------
diff --git a/types/YearMonthIntervalType.hpp b/types/YearMonthIntervalType.hpp
index a2ba175..f768046 100644
--- a/types/YearMonthIntervalType.hpp
+++ b/types/YearMonthIntervalType.hpp
@@ -39,12 +39,9 @@ namespace quickstep {
 /**
  * @brief A type representing the year-month interval.
  **/
-class YearMonthIntervalType : public Type {
+class YearMonthIntervalType :
+    public TypeConcept<kYearMonthInterval, false, kNativeEmbedded, YearMonthIntervalLit> {
  public:
-  typedef YearMonthIntervalLit cpptype;
-
-  static const TypeID kStaticTypeID = kYearMonthInterval;
-
   /**
    * @brief Get a reference to the non-nullable singleton instance of this
    *        Type.
@@ -115,7 +112,9 @@ class YearMonthIntervalType : public Type {
 
  private:
   explicit YearMonthIntervalType(const bool nullable)
-      : Type(Type::kOther, kYearMonthInterval, nullable, sizeof(YearMonthIntervalLit), sizeof(YearMonthIntervalLit)) {
+      : TypeConcept<kYearMonthInterval, false, kNativeEmbedded, YearMonthIntervalLit>(
+            Type::kOther, kStaticTypeID, nullable,
+            sizeof(YearMonthIntervalLit), sizeof(YearMonthIntervalLit)) {
   }
 
   DISALLOW_COPY_AND_ASSIGN(YearMonthIntervalType);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/27c41625/types/containers/ColumnVector.hpp
----------------------------------------------------------------------
diff --git a/types/containers/ColumnVector.hpp b/types/containers/ColumnVector.hpp
index fc65656..f0a2cd5 100644
--- a/types/containers/ColumnVector.hpp
+++ b/types/containers/ColumnVector.hpp
@@ -130,8 +130,8 @@ class NativeColumnVector : public ColumnVector {
   NativeColumnVector(const Type &type, const std::size_t reserved_length)
       : ColumnVector(type),
         type_length_(type.maximumByteLength()),
-        values_(std::malloc(type.maximumByteLength() * reserved_length)),
         reserved_length_(reserved_length),
+        values_(std::malloc(type.maximumByteLength() * reserved_length)),
         actual_length_(0u),
         null_bitmap_(type.isNullable() ? new BitVector<false>(reserved_length) : nullptr) {
     DCHECK(UsableForType(type_));
@@ -385,8 +385,9 @@ class NativeColumnVector : public ColumnVector {
 
  private:
   const std::size_t type_length_;
-  void *values_;
   const std::size_t reserved_length_;
+
+  void *values_;
   std::size_t actual_length_;
   std::unique_ptr<BitVector<false>> null_bitmap_;
 
@@ -498,6 +499,12 @@ class IndirectColumnVector : public ColumnVector {
     values_.emplace_back(std::move(value));
   }
 
+  inline void appendNullValue() {
+    DCHECK(type_.isNullable());
+    DCHECK_LT(values_.size(), reserved_length_);
+    values_.emplace_back(type_.makeNullValue());
+  }
+
   /**
    * @brief Fill this entire ColumnVector with copies of value.
    *
@@ -559,6 +566,7 @@ class IndirectColumnVector : public ColumnVector {
  private:
   const bool type_is_nullable_;
   const std::size_t reserved_length_;
+
   std::vector<TypedValue> values_;
 
   DISALLOW_COPY_AND_ASSIGN(IndirectColumnVector);