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:21 UTC

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

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/binary_operations/MultiplyBinaryOperation.cpp
----------------------------------------------------------------------
diff --git a/types/operations/binary_operations/MultiplyBinaryOperation.cpp b/types/operations/binary_operations/MultiplyBinaryOperation.cpp
deleted file mode 100644
index a206364..0000000
--- a/types/operations/binary_operations/MultiplyBinaryOperation.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/**
- * 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.
- **/
-
-#include "types/operations/binary_operations/MultiplyBinaryOperation.hpp"
-
-#include <string>
-#include <utility>
-
-#include "types/DateOperatorOverloads.hpp"
-#include "types/DatetimeIntervalType.hpp"
-#include "types/DoubleType.hpp"
-#include "types/FloatType.hpp"
-#include "types/IntType.hpp"
-#include "types/IntervalLit.hpp"
-#include "types/LongType.hpp"
-#include "types/Type.hpp"
-#include "types/TypeErrors.hpp"
-#include "types/TypeFactory.hpp"
-#include "types/TypeID.hpp"
-#include "types/YearMonthIntervalType.hpp"
-#include "types/operations/binary_operations/ArithmeticBinaryOperators.hpp"
-#include "utility/EqualsAnyConstant.hpp"
-
-#include "glog/logging.h"
-
-namespace quickstep {
-
-bool MultiplyBinaryOperation::canApplyToTypes(const Type &left, const Type &right) const {
-  switch (left.getTypeID()) {
-    case kInt:
-    case kLong:
-    case kFloat:
-    case kDouble: {
-      return (right.getSuperTypeID() == Type::kNumeric ||
-              right.getTypeID() == kDatetimeInterval   ||
-              right.getTypeID() == kYearMonthInterval);
-    }
-    case kDatetimeInterval:
-    case kYearMonthInterval: {
-      return (right.getSuperTypeID() == Type::kNumeric);
-    }
-    default:
-      return false;
-  }
-}
-
-const Type* MultiplyBinaryOperation::resultTypeForArgumentTypes(const Type &left, const Type &right) const {
-  if (left.getSuperTypeID() == Type::kNumeric && right.getSuperTypeID() == Type::kNumeric) {
-    return TypeFactory::GetUnifyingType(left, right);
-  } else if ((left.getSuperTypeID() == Type::kNumeric && right.getTypeID() == kDatetimeInterval) ||
-             (left.getTypeID() == kDatetimeInterval && right.getSuperTypeID() == Type::kNumeric)) {
-    return &(DatetimeIntervalType::Instance(left.isNullable() || right.isNullable()));
-  } else if ((left.getSuperTypeID() == Type::kNumeric && right.getTypeID() == kYearMonthInterval) ||
-             (left.getTypeID() == kYearMonthInterval && right.getSuperTypeID() == Type::kNumeric)) {
-    return &(YearMonthIntervalType::Instance(left.isNullable() || right.isNullable()));
-  } else {
-    return nullptr;
-  }
-}
-
-const Type* MultiplyBinaryOperation::resultTypeForPartialArgumentTypes(
-    const Type *left,
-    const Type *right) const {
-  if ((left == nullptr) && (right == nullptr)) {
-    return nullptr;
-  }
-
-  if ((left != nullptr) && (right != nullptr)) {
-    return resultTypeForArgumentTypes(*left, *right);
-  }
-
-  // Multiplication is commutative, so we just determine based on the known
-  // type, left or right.
-  const Type *known_type = (left != nullptr) ? left : right;
-  switch (known_type->getTypeID()) {
-    case kDatetimeInterval:
-      // DatetimeInterval can be multiplied against any numeric type, yielding
-      // DatetimeInterval.
-      return &TypeFactory::GetType(kDatetimeInterval, true);
-    case kYearMonthInterval:
-      // Same deal for YearMonthInterval.
-      return &TypeFactory::GetType(kYearMonthInterval, true);
-    default:
-      // Ambiguous or inapplicable. Note that we can't apply numeric precedence
-      // order for a Double argument, because the other argument could be a
-      // numeric type OR an interval type.
-      return nullptr;
-  }
-}
-
-bool MultiplyBinaryOperation::partialTypeSignatureIsPlausible(
-    const Type *result_type,
-    const Type *left_argument_type,
-    const Type *right_argument_type) const {
-  if ((left_argument_type == nullptr) && (right_argument_type == nullptr)) {
-    if (result_type == nullptr) {
-      return true;
-    } else if (!result_type->isNullable()) {
-      // Unknown arguments are assumed to be nullable, since they arise from
-      // untyped NULL literals in the parser. Therefore, a non-nullable result
-      // Type is not plausible with unknown arguments.
-      return false;
-    } else {
-      return QUICKSTEP_EQUALS_ANY_CONSTANT(
-          result_type->getTypeID(),
-          kInt, kLong, kFloat, kDouble, kDatetimeInterval, kYearMonthInterval);
-    }
-  }
-
-  if ((left_argument_type != nullptr) && (right_argument_type != nullptr)) {
-    const Type *actual_result_type = resultTypeForArgumentTypes(*left_argument_type,
-                                                                *right_argument_type);
-    if (actual_result_type == nullptr) {
-      // Both argument Types are known, but this operation is NOT applicable to
-      // them. No matter what the result_type is, the signature is not
-      // plausible.
-      return false;
-    } else if (result_type == nullptr) {
-      return true;
-    } else {
-      return result_type->equals(*actual_result_type);
-    }
-  }
-
-  // Multiplication is commutative, so we just determine based on the known
-  // type, left or right.
-  const Type *known_argument_type = (left_argument_type != nullptr)
-                                    ? left_argument_type
-                                    : right_argument_type;
-  if (result_type == nullptr) {
-    return QUICKSTEP_EQUALS_ANY_CONSTANT(
-        known_argument_type->getTypeID(),
-        kInt, kLong, kFloat, kDouble, kDatetimeInterval, kYearMonthInterval);
-  }
-
-  if (!result_type->isNullable()) {
-    // One of the arguments is unknown, but it is nevertheless assumed
-    // nullable, since unknown argument Types arise from untyped NULL literals
-    // in the parser. Therefore, a non-nullable result Type is not plausible
-    // with an unknown argument.
-    return false;
-  }
-
-  switch (result_type->getTypeID()) {
-    case kInt:
-      return (known_argument_type->getTypeID() == kInt);
-    case kLong:
-      return QUICKSTEP_EQUALS_ANY_CONSTANT(
-          known_argument_type->getTypeID(),
-          kInt, kLong);
-    case kFloat:
-      return QUICKSTEP_EQUALS_ANY_CONSTANT(
-          known_argument_type->getTypeID(),
-          kInt, kFloat);
-    case kDouble:
-      return QUICKSTEP_EQUALS_ANY_CONSTANT(
-          known_argument_type->getTypeID(),
-          kInt, kLong, kFloat, kDouble);
-    case kDatetimeInterval:
-      return QUICKSTEP_EQUALS_ANY_CONSTANT(
-          known_argument_type->getTypeID(),
-          kInt, kLong, kFloat, kDouble, kDatetimeInterval);
-    case kYearMonthInterval:
-      return QUICKSTEP_EQUALS_ANY_CONSTANT(
-          known_argument_type->getTypeID(),
-          kInt, kLong, kFloat, kDouble, kYearMonthInterval);
-    default:
-      return false;
-  }
-}
-
-std::pair<const Type*, const Type*> MultiplyBinaryOperation::pushDownTypeHint(
-    const Type *result_type_hint) const {
-  if (result_type_hint == nullptr) {
-    return std::pair<const Type*, const Type*>(nullptr, nullptr);
-  }
-
-  switch (result_type_hint->getTypeID()) {
-    case kInt:
-    case kLong:
-    case kFloat:
-    case kDouble:
-      return std::pair<const Type*, const Type*>(result_type_hint, result_type_hint);
-    case kDatetimeInterval:
-    case kYearMonthInterval:
-      // Ambiguous hint. One of the arguments should be the same as the
-      // '*type_hint', the other can be any numeric type, but either order is
-      // OK.
-      return std::pair<const Type*, const Type*>(nullptr, nullptr);
-    default:
-      // Inapplicable.
-      return std::pair<const Type*, const Type*>(nullptr, nullptr);
-  }
-}
-
-TypedValue MultiplyBinaryOperation::applyToChecked(const TypedValue &left,
-                                                   const Type &left_type,
-                                                   const TypedValue &right,
-                                                   const Type &right_type) const {
-  switch (left_type.getTypeID()) {
-    case kInt:
-    case kLong:
-    case kFloat:
-    case kDouble: {
-      if (right_type.getSuperTypeID() == Type::kNumeric) {
-        return applyToCheckedNumericHelper<MultiplyFunctor>(left, left_type,
-                                                            right, right_type);
-      } else if (right_type.getTypeID() == kDatetimeInterval) {
-        return applyToCheckedIntervalMultiplyNumericHelper<DatetimeIntervalType>(right, right_type,
-                                                                                 left, left_type);
-      } else if (right_type.getTypeID() == kYearMonthInterval) {
-        return applyToCheckedIntervalMultiplyNumericHelper<YearMonthIntervalType>(right, right_type,
-                                                                                  left, left_type);
-      }
-      break;
-    }
-    case kDatetimeInterval: {
-      if (right_type.getSuperTypeID() == Type::kNumeric) {
-        return applyToCheckedIntervalMultiplyNumericHelper<DatetimeIntervalType>(left, left_type,
-                                                                                 right, right_type);
-      }
-      break;
-    }
-    case kYearMonthInterval: {
-      if (right_type.getSuperTypeID() == Type::kNumeric) {
-        return applyToCheckedIntervalMultiplyNumericHelper<YearMonthIntervalType>(left, left_type,
-                                                                                  right, right_type);
-      }
-      break;
-    }
-    default:
-      break;
-  }
-
-  LOG(FATAL) << "Can not apply " << getName() << " to arguments of types "
-             << left_type.getName() << " and " << right_type.getName();
-}
-
-UncheckedBinaryOperator* MultiplyBinaryOperation::makeUncheckedBinaryOperatorForTypes(const Type &left,
-                                                                                      const Type &right) const {
-  switch (left.getTypeID()) {
-    case kInt: {
-      if (right.getSuperTypeID() == Type::kNumeric) {
-        return makeNumericBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator>(left, right);
-      } else if (right.getTypeID() == kDatetimeInterval) {
-        return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                 DatetimeIntervalType,
-                                                 IntType::cpptype, DatetimeIntervalLit>(left, right);
-      } else if (right.getTypeID() == kYearMonthInterval) {
-        return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                 YearMonthIntervalType,
-                                                 IntType::cpptype, YearMonthIntervalLit>(left, right);
-      }
-      break;
-    }
-    case kLong: {
-      if (right.getSuperTypeID() == Type::kNumeric) {
-        return makeNumericBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator>(left, right);
-      } else if (right.getTypeID() == kDatetimeInterval) {
-        return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                 DatetimeIntervalType,
-                                                 LongType::cpptype, DatetimeIntervalLit>(left, right);
-      } else if (right.getTypeID() == kYearMonthInterval) {
-        return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                 YearMonthIntervalType,
-                                                 LongType::cpptype, YearMonthIntervalLit>(left, right);
-      }
-      break;
-    }
-    case kFloat: {
-      if (right.getSuperTypeID() == Type::kNumeric) {
-        return makeNumericBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator>(left, right);
-      } else if (right.getTypeID() == kDatetimeInterval) {
-        return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                 DatetimeIntervalType,
-                                                 FloatType::cpptype, DatetimeIntervalLit>(left, right);
-      } else if (right.getTypeID() == kYearMonthInterval) {
-        return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                 YearMonthIntervalType,
-                                                 FloatType::cpptype, YearMonthIntervalLit>(left, right);
-      }
-      break;
-    }
-    case kDouble: {
-      if (right.getSuperTypeID() == Type::kNumeric) {
-        return makeNumericBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator>(left, right);
-      } else if (right.getTypeID() == kDatetimeInterval) {
-        return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                 DatetimeIntervalType,
-                                                 DoubleType::cpptype, DatetimeIntervalLit>(left, right);
-      } else if (right.getTypeID() == kYearMonthInterval) {
-        return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                 YearMonthIntervalType,
-                                                 DoubleType::cpptype, YearMonthIntervalLit>(left, right);
-      }
-      break;
-    }
-    case kDatetimeInterval: {
-      switch (right.getTypeID()) {
-        case kInt: {
-          return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                   DatetimeIntervalType,
-                                                   DatetimeIntervalLit, IntType::cpptype>(left, right);
-        }
-        case kLong: {
-          return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                   DatetimeIntervalType,
-                                                   DatetimeIntervalLit, LongType::cpptype>(left, right);
-        }
-        case kFloat: {
-          return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                   DatetimeIntervalType,
-                                                   DatetimeIntervalLit, FloatType::cpptype>(left, right);
-        }
-        case kDouble: {
-          return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                   DatetimeIntervalType,
-                                                   DatetimeIntervalLit, DoubleType::cpptype>(left, right);
-        }
-        default:
-          break;
-      }
-      break;
-    }
-    case kYearMonthInterval: {
-      switch (right.getTypeID()) {
-        case kInt: {
-          return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                   YearMonthIntervalType,
-                                                   YearMonthIntervalLit, IntType::cpptype>(left, right);
-        }
-        case kLong: {
-          return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                   YearMonthIntervalType,
-                                                   YearMonthIntervalLit, LongType::cpptype>(left, right);
-        }
-        case kFloat: {
-          return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                   YearMonthIntervalType,
-                                                   YearMonthIntervalLit, FloatType::cpptype>(left, right);
-        }
-        case kDouble: {
-          return makeDateBinaryOperatorOuterHelper<MultiplyArithmeticUncheckedBinaryOperator,
-                                                   YearMonthIntervalType,
-                                                   YearMonthIntervalLit, DoubleType::cpptype>(left, right);
-        }
-        default:
-          break;
-      }
-      break;
-    }
-    default:
-      break;
-  }
-
-  throw OperationInapplicableToType(getName(), 2, left.getName().c_str(), right.getName().c_str());
-}
-
-template <typename IntervalType>
-TypedValue MultiplyBinaryOperation::applyToCheckedIntervalMultiplyNumericHelper(
-    const TypedValue &left,
-    const Type &left_type,
-    const TypedValue &right,
-    const Type &right_type) const {
-  DCHECK(IntervalType::kStaticTypeID == kDatetimeInterval ||
-         IntervalType::kStaticTypeID == kYearMonthInterval);
-  DCHECK(IntervalType::kStaticTypeID == left_type.getTypeID());
-  DCHECK_EQ(Type::kNumeric, right_type.getSuperTypeID());
-
-  if (left.isNull() || right.isNull()) {
-    return TypedValue(IntervalType::kStaticTypeID);
-  }
-
-  switch (right_type.getTypeID()) {
-    case kInt: {
-      return TypedValue(left.getLiteral<typename IntervalType::cpptype>() * right.getLiteral<IntType::cpptype>());
-    }
-    case kLong: {
-      return TypedValue(left.getLiteral<typename IntervalType::cpptype>() * right.getLiteral<LongType::cpptype>());
-    }
-    case kFloat: {
-      return TypedValue(left.getLiteral<typename IntervalType::cpptype>() * right.getLiteral<FloatType::cpptype>());
-    }
-    case kDouble: {
-      return TypedValue(left.getLiteral<typename IntervalType::cpptype>() * right.getLiteral<DoubleType::cpptype>());
-    }
-    default: {
-      LOG(FATAL) << "Can not apply " << getName() << " to arguments of types "
-                 << left_type.getName() << " and " << right_type.getName();
-    }
-  }
-}
-
-}  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/binary_operations/MultiplyBinaryOperation.hpp
----------------------------------------------------------------------
diff --git a/types/operations/binary_operations/MultiplyBinaryOperation.hpp b/types/operations/binary_operations/MultiplyBinaryOperation.hpp
deleted file mode 100644
index 6edc999..0000000
--- a/types/operations/binary_operations/MultiplyBinaryOperation.hpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * 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_OPERATIONS_BINARY_OPERATIONS_MULTIPLY_BINARY_OPERATION_HPP_
-#define QUICKSTEP_TYPES_OPERATIONS_BINARY_OPERATIONS_MULTIPLY_BINARY_OPERATION_HPP_
-
-#include <utility>
-
-#include "types/TypedValue.hpp"
-#include "types/operations/binary_operations/ArithmeticBinaryOperation.hpp"
-#include "types/operations/binary_operations/BinaryOperationID.hpp"
-#include "utility/Macros.hpp"
-
-namespace quickstep {
-
-class Type;
-class UncheckedBinaryOperator;
-
-/** \addtogroup Types
- *  @{
- */
-
-/**
- * @brief The BinaryOperation for multiplication.
- **/
-class MultiplyBinaryOperation : public ArithmeticBinaryOperation {
- public:
-  /**
-   * @brief Get a reference to the singleton instance of this Operation.
-   *
-   * @return A reference to the singleton instance of this Operation.
-   **/
-  static const MultiplyBinaryOperation& Instance() {
-    static MultiplyBinaryOperation instance;
-    return instance;
-  }
-
-  bool canApplyToTypes(const Type &left,
-                       const Type &right) const override;
-
-  const Type* resultTypeForArgumentTypes(const Type &left,
-                                         const Type &right) const override;
-
-  const Type* resultTypeForPartialArgumentTypes(const Type *left,
-                                                const Type *right) const override;
-
-  bool partialTypeSignatureIsPlausible(const Type *result_type,
-                                       const Type *left_argument_type,
-                                       const Type *right_argument_type) const override;
-
-  std::pair<const Type*, const Type*> pushDownTypeHint(
-      const Type *result_type_hint) const override;
-
-  TypedValue applyToChecked(const TypedValue &left,
-                            const Type &left_type,
-                            const TypedValue &right,
-                            const Type &right_type) const override;
-
-  UncheckedBinaryOperator* makeUncheckedBinaryOperatorForTypes(const Type &left,
-                                                               const Type &right) const override;
-
- private:
-  MultiplyBinaryOperation()
-      : ArithmeticBinaryOperation(BinaryOperationID::kMultiply) {
-  }
-
-  // NOTE(zuyu): left is an Interval TypedValue, either DatetimeInterval
-  // or YearMonthInterval, while right is a Numeric.
-  template <typename IntervalType>
-  TypedValue applyToCheckedIntervalMultiplyNumericHelper(const TypedValue &left,
-                                                         const Type &left_type,
-                                                         const TypedValue &right,
-                                                         const Type &right_type) const;
-
-  DISALLOW_COPY_AND_ASSIGN(MultiplyBinaryOperation);
-};
-
-/** @} */
-
-}  // namespace quickstep
-
-#endif  // QUICKSTEP_TYPES_OPERATIONS_BINARY_OPERATIONS_MULTIPLY_BINARY_OPERATION_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/binary_operations/SubtractBinaryOperation.cpp
----------------------------------------------------------------------
diff --git a/types/operations/binary_operations/SubtractBinaryOperation.cpp b/types/operations/binary_operations/SubtractBinaryOperation.cpp
deleted file mode 100644
index 53e4266..0000000
--- a/types/operations/binary_operations/SubtractBinaryOperation.cpp
+++ /dev/null
@@ -1,459 +0,0 @@
-/**
- * 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.
- **/
-
-#include "types/operations/binary_operations/SubtractBinaryOperation.hpp"
-
-#include <string>
-#include <utility>
-
-#include "types/DateOperatorOverloads.hpp"
-#include "types/DateType.hpp"
-#include "types/DatetimeIntervalType.hpp"
-#include "types/DatetimeLit.hpp"
-#include "types/DatetimeType.hpp"
-#include "types/IntervalLit.hpp"
-#include "types/Type.hpp"
-#include "types/TypeErrors.hpp"
-#include "types/TypeFactory.hpp"
-#include "types/TypeID.hpp"
-#include "types/YearMonthIntervalType.hpp"
-#include "types/operations/binary_operations/ArithmeticBinaryOperators.hpp"
-#include "utility/EqualsAnyConstant.hpp"
-
-#include "glog/logging.h"
-
-namespace quickstep {
-
-bool SubtractBinaryOperation::canApplyToTypes(const Type &left, const Type &right) const {
-  switch (left.getTypeID()) {
-    case kInt:
-    case kLong:
-    case kFloat:
-    case kDouble: {
-      return (right.getSuperTypeID() == Type::kNumeric);
-    }
-    case kDate: {
-      return (right.getTypeID() == kYearMonthInterval);
-    }
-    case kDatetime: {
-      return (right.getTypeID() == kDatetime         ||
-              right.getTypeID() == kDatetimeInterval ||
-              right.getTypeID() == kYearMonthInterval);
-    }
-    case kDatetimeInterval: {
-      return (right.getTypeID() == kDatetimeInterval);
-    }
-    case kYearMonthInterval: {
-      return (right.getTypeID() == kYearMonthInterval ||
-              right.getTypeID() == kDate);
-    }
-    default:
-      return false;
-  }
-}
-
-const Type* SubtractBinaryOperation::resultTypeForArgumentTypes(const Type &left, const Type &right) const {
-  if (left.getSuperTypeID() == Type::kNumeric && right.getSuperTypeID() == Type::kNumeric) {
-    return TypeFactory::GetUnifyingType(left, right);
-  } else if ((left.getTypeID() == kDate && right.getTypeID() == kYearMonthInterval)) {
-    // For DATE type, only one possibility: DATE - YEAR-MONTH-INTERVAL.
-    return &(DateType::Instance(left.isNullable() || right.isNullable()));
-  } else if ((left.getTypeID() == kDatetime && right.getTypeID() == kDatetime) ||
-             (left.getTypeID() == kDatetimeInterval && right.getTypeID() == kDatetimeInterval)) {
-    // NOTE(zuyu): we set the result type of the Subtract
-    // between two Datetimes as DatetimeInterval, instead of YearMonthInterval.
-    return &(DatetimeIntervalType::Instance(left.isNullable() || right.isNullable()));
-  } else if (left.getTypeID() == kDatetime && right.getTypeID() == kDatetimeInterval) {
-    return &(DatetimeType::Instance(left.isNullable() || right.isNullable()));
-  } else if (left.getTypeID() == kDatetime && right.getTypeID() == kYearMonthInterval) {
-    return &(DatetimeType::Instance(left.isNullable() || right.isNullable()));
-  } else if (left.getTypeID() == kYearMonthInterval && right.getTypeID() == kYearMonthInterval) {
-    return &(YearMonthIntervalType::Instance(left.isNullable() || right.isNullable()));
-  } else {
-    return nullptr;
-  }
-}
-
-const Type* SubtractBinaryOperation::resultTypeForPartialArgumentTypes(
-    const Type *left,
-    const Type *right) const {
-  if (left == nullptr) {
-    if (right == nullptr) {
-      return nullptr;
-    } else {
-      switch (right->getTypeID()) {
-        case kDouble:
-          // Double has highest precedence of numeric types.
-          return &TypeFactory::GetType(kDouble, true);
-        case kDatetime:
-          // If the subtrahend is Datetime, then the only allowed minuend is
-          // another Datetime, and the result is an interval.
-          return &TypeFactory::GetType(kDatetimeInterval, true);
-        default:
-          // Ambiguous or inapplicable.
-          return nullptr;
-      }
-    }
-  } else {
-    if (right == nullptr) {
-      switch (left->getTypeID()) {
-        case kDouble:
-          // Double has highest precedence of numeric types.
-          return &TypeFactory::GetType(kDouble, true);
-        case kDate:
-          // If left is a Date, right must be a YearMonthInterval and the result
-          // must be a Date.
-          return &TypeFactory::GetType(kDate, true);
-        case kDatetimeInterval:
-          // If minuend is a DatetimeInterval, the subtrahend and result must
-          // also be DatetimeInterval.
-          return &TypeFactory::GetType(kDatetimeInterval, true);
-        case kYearMonthInterval:
-          // Similarly, if minuend is a YearMonthInterval, the subtrahend and
-          // result must also be YearMonthInterval.
-          return &TypeFactory::GetType(kYearMonthInterval, true);
-        default:
-          // Ambiguous or inapplicable.
-          return nullptr;
-      }
-    } else {
-      return resultTypeForArgumentTypes(*left, *right);
-    }
-  }
-}
-
-bool SubtractBinaryOperation::partialTypeSignatureIsPlausible(
-    const Type *result_type,
-    const Type *left_argument_type,
-    const Type *right_argument_type) const {
-  // Early check: if either argument type is nullable or unknown, result type
-  // must also be nullable.
-  if ((left_argument_type == nullptr)
-      || left_argument_type->isNullable()
-      || (right_argument_type == nullptr)
-      || right_argument_type->isNullable()) {
-    if ((result_type != nullptr) && (!result_type->isNullable())) {
-      return false;
-    }
-  }
-
-  if (left_argument_type == nullptr) {
-    if (right_argument_type == nullptr) {
-      if (result_type == nullptr) {
-        // All types unknown.
-        return true;
-      } else {
-        // Only result type is known, just check that it is one of the types
-        // that can possibly be returned.
-        return QUICKSTEP_EQUALS_ANY_CONSTANT(result_type->getTypeID(),
-                                             kInt,
-                                             kLong,
-                                             kFloat,
-                                             kDouble,
-                                             kDate,
-                                             kDatetime,
-                                             kDatetimeInterval,
-                                             kYearMonthInterval);
-      }
-    }
-
-    if (result_type == nullptr) {
-      // Right (minuend) argument type is known, left (subtrahend) argument and
-      // result types are unknown. Just check that right (minuend) type can be
-      // subtracted.
-      return QUICKSTEP_EQUALS_ANY_CONSTANT(right_argument_type->getTypeID(),
-                                           kInt,
-                                           kLong,
-                                           kFloat,
-                                           kDouble,
-                                           kDatetime,
-                                           kDatetimeInterval,
-                                           kYearMonthInterval);
-    }
-
-    // Return type and right (minuend) argument type are known, left
-    // (subtrahend) argument type is unknown. Check that result and subtrahend
-    // are compatible.
-    switch (right_argument_type->getTypeID()) {
-      case kInt:
-        return QUICKSTEP_EQUALS_ANY_CONSTANT(
-            result_type->getTypeID(),
-            kInt, kLong, kFloat, kDouble);
-      case kLong:
-        return QUICKSTEP_EQUALS_ANY_CONSTANT(
-            result_type->getTypeID(),
-            kLong, kDouble);
-      case kFloat:
-        return QUICKSTEP_EQUALS_ANY_CONSTANT(
-            result_type->getTypeID(),
-            kFloat, kDouble);
-      case kDouble:
-        return (result_type->getTypeID() == kDouble);
-      case kDate:
-        return (result_type->getTypeID() == kDate);
-      case kDatetime:
-        return (result_type->getTypeID() == kDatetimeInterval);
-      case kDatetimeInterval:
-        return QUICKSTEP_EQUALS_ANY_CONSTANT(
-            result_type->getTypeID(),
-            kDatetime, kDatetimeInterval);
-      case kYearMonthInterval:
-        return QUICKSTEP_EQUALS_ANY_CONSTANT(
-            result_type->getTypeID(),
-            kDate, kDatetime, kYearMonthInterval);
-      default:
-        return false;
-    }
-  } else {  // left_argument_type != nullptr
-    if (right_argument_type == nullptr) {
-      if (result_type == nullptr) {
-        // Left (subtrahend) argument type is known, right (minuend) argument
-        // type and result type are unknown. Just check that the left
-        // (subtrahend) type can be subtracted from.
-        return QUICKSTEP_EQUALS_ANY_CONSTANT(left_argument_type->getTypeID(),
-                                             kInt,
-                                             kLong,
-                                             kFloat,
-                                             kDouble,
-                                             kDate,
-                                             kDatetime,
-                                             kDatetimeInterval,
-                                             kYearMonthInterval);
-      }
-
-      // Result type and left (subtrahend) argument type are known, but right
-      // (minuend) argument type is unknown. Check that result and minuend are
-      // compatible.
-      switch (left_argument_type->getTypeID()) {
-        case kInt:
-          return QUICKSTEP_EQUALS_ANY_CONSTANT(
-              result_type->getTypeID(),
-              kInt, kLong, kFloat, kDouble);
-        case kLong:
-          return QUICKSTEP_EQUALS_ANY_CONSTANT(
-              result_type->getTypeID(),
-              kLong, kDouble);
-        case kFloat:
-          return QUICKSTEP_EQUALS_ANY_CONSTANT(
-              result_type->getTypeID(),
-              kFloat, kDouble);
-        case kDouble:
-          return (result_type->getTypeID() == kDouble);
-        case kDate:
-          return (result_type->getTypeID() == kDate);
-        case kDatetime:
-          return QUICKSTEP_EQUALS_ANY_CONSTANT(
-              result_type->getTypeID(),
-              kDatetime, kDatetimeInterval);
-        case kDatetimeInterval:
-          return (result_type->getTypeID() == kDatetimeInterval);
-        case kYearMonthInterval:
-          return (result_type->getTypeID() == kYearMonthInterval);
-        default:
-          return false;
-      }
-    }
-
-    // Left and right (subtrahend and minuend) argument types are both known.
-    const Type *actual_result_type = resultTypeForArgumentTypes(*left_argument_type,
-                                                                *right_argument_type);
-    if (actual_result_type == nullptr) {
-      // Both argument Types are known, but this operation is NOT applicable to
-      // them. No matter what the result_type is, the signature is not
-      // plausible.
-      return false;
-    } else if (result_type == nullptr) {
-      return true;
-    } else {
-      // Check if result type matches.
-      return result_type->equals(*actual_result_type);
-    }
-  }
-}
-
-std::pair<const Type*, const Type*> SubtractBinaryOperation::pushDownTypeHint(
-    const Type *result_type_hint) const {
-  if (result_type_hint == nullptr) {
-    return std::pair<const Type*, const Type*>(nullptr, nullptr);
-  }
-
-  switch (result_type_hint->getTypeID()) {
-    case kInt:
-    case kLong:
-    case kFloat:
-    case kDouble:
-    case kYearMonthInterval:
-      return std::pair<const Type*, const Type*>(result_type_hint, result_type_hint);
-    case kDate:
-      // Left should be a Date, right should be YearMonthInterval.
-      return std::pair<const Type *, const Type *>(
-          result_type_hint, &TypeFactory::GetType(kYearMonthInterval, true));
-    case kDatetime:
-      // Left should be a Datetime, right may be either interval type.
-      return std::pair<const Type*, const Type*>(result_type_hint, nullptr);
-    case kDatetimeInterval:
-      // Ambiguous: could be subtracting two Datetimes or two DatetimeIntervals.
-      return std::pair<const Type*, const Type*>(nullptr, nullptr);
-    default:
-      // Inapplicable.
-      return std::pair<const Type*, const Type*>(nullptr, nullptr);
-  }
-}
-
-TypedValue SubtractBinaryOperation::applyToChecked(const TypedValue &left,
-                                                   const Type &left_type,
-                                                   const TypedValue &right,
-                                                   const Type &right_type) const {
-  switch (left_type.getTypeID()) {
-    case kInt:
-    case kLong:
-    case kFloat:
-    case kDouble: {
-      if (right_type.getSuperTypeID() == Type::kNumeric) {
-        return applyToCheckedNumericHelper<SubtractFunctor>(left, left_type,
-                                                            right, right_type);
-      }
-      break;
-    }
-    case kDate: {
-      if (right_type.getTypeID() == kYearMonthInterval) {
-        if (left.isNull() || right.isNull()) {
-          return TypedValue(kDate);
-        }
-
-        return TypedValue(left.getLiteral<DateLit>() - right.getLiteral<YearMonthIntervalLit>());
-      }
-      break;
-    }
-    case kDatetime: {
-      if (right_type.getTypeID() == kDatetime) {
-        // NOTE(zuyu): The result type of the Subtract between two Datetimes is DatetimeInterval,
-        // instead of YearMonthInterval.
-        if (left.isNull() || right.isNull()) {
-          return TypedValue(kDatetimeInterval);
-        }
-
-        return TypedValue(left.getLiteral<DatetimeLit>() - right.getLiteral<DatetimeLit>());
-      } else if (right_type.getTypeID() == kDatetimeInterval) {
-        if (left.isNull() || right.isNull()) {
-          return TypedValue(kDatetime);
-        }
-
-        return TypedValue(left.getLiteral<DatetimeLit>() - right.getLiteral<DatetimeIntervalLit>());
-      } else if (right_type.getTypeID() == kYearMonthInterval) {
-        if (left.isNull() || right.isNull()) {
-          return TypedValue(kDatetime);
-        }
-
-        return TypedValue(left.getLiteral<DatetimeLit>() - right.getLiteral<YearMonthIntervalLit>());
-      }
-      break;
-    }
-    case kDatetimeInterval: {
-      if (right_type.getTypeID() == kDatetimeInterval) {
-        if (left.isNull() || right.isNull()) {
-          return TypedValue(kDatetimeInterval);
-        }
-
-        return TypedValue(left.getLiteral<DatetimeIntervalLit>() - right.getLiteral<DatetimeIntervalLit>());
-      }
-      break;
-    }
-    case kYearMonthInterval: {
-      if (right_type.getTypeID() == kYearMonthInterval) {
-        if (left.isNull() || right.isNull()) {
-          return TypedValue(kYearMonthInterval);
-        }
-
-        return TypedValue(left.getLiteral<YearMonthIntervalLit>() - right.getLiteral<YearMonthIntervalLit>());
-      }
-      break;
-    }
-    default:
-      break;
-  }
-
-  LOG(FATAL) << "Can not apply " << getName() << " to arguments of types "
-             << left_type.getName() << " and " << right_type.getName();
-}
-
-UncheckedBinaryOperator* SubtractBinaryOperation::makeUncheckedBinaryOperatorForTypes(const Type &left,
-                                                                                      const Type &right) const {
-  switch (left.getTypeID()) {
-    case kInt:
-    case kLong:
-    case kFloat:
-    case kDouble: {
-      if (right.getSuperTypeID() == Type::kNumeric) {
-        return makeNumericBinaryOperatorOuterHelper<SubtractArithmeticUncheckedBinaryOperator>(left, right);
-      }
-      break;
-    }
-    case kDate: {
-      if (right.getTypeID() == kYearMonthInterval) {
-        return makeDateBinaryOperatorOuterHelper<
-            SubtractArithmeticUncheckedBinaryOperator,
-            DateType,
-            DateLit,
-            YearMonthIntervalLit>(left, right);
-      }
-      break;
-    }
-    case kDatetime: {
-      if (right.getTypeID() == kDatetime) {
-        // NOTE(zuyu): The result type of the Subtract between two Datetimes is DatetimeInterval,
-        // instead of YearMonthInterval.
-        return makeDateBinaryOperatorOuterHelper<SubtractArithmeticUncheckedBinaryOperator,
-                                                 DatetimeIntervalType,
-                                                 DatetimeLit, DatetimeLit>(left, right);
-      } else if (right.getTypeID() == kDatetimeInterval) {
-        return makeDateBinaryOperatorOuterHelper<SubtractArithmeticUncheckedBinaryOperator,
-                                                 DatetimeType,
-                                                 DatetimeLit, DatetimeIntervalLit>(left, right);
-      } else if (right.getTypeID() == kYearMonthInterval) {
-        return makeDateBinaryOperatorOuterHelper<SubtractArithmeticUncheckedBinaryOperator,
-                                                 DatetimeType,
-                                                 DatetimeLit, YearMonthIntervalLit>(left, right);
-      }
-      break;
-    }
-    case kDatetimeInterval: {
-      if (right.getTypeID() == kDatetimeInterval) {
-        return makeDateBinaryOperatorOuterHelper<SubtractArithmeticUncheckedBinaryOperator,
-                                                 DatetimeIntervalType,
-                                                 DatetimeIntervalLit, DatetimeIntervalLit>(left, right);
-      }
-      break;
-    }
-    case kYearMonthInterval: {
-      if (right.getTypeID() == kYearMonthInterval) {
-        return makeDateBinaryOperatorOuterHelper<SubtractArithmeticUncheckedBinaryOperator,
-                                                 YearMonthIntervalType,
-                                                 YearMonthIntervalLit, YearMonthIntervalLit>(left, right);
-      }
-      break;
-    }
-    default:
-      break;
-  }
-
-  throw OperationInapplicableToType(getName(), 2, left.getName().c_str(), right.getName().c_str());
-}
-
-}  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/binary_operations/SubtractBinaryOperation.hpp
----------------------------------------------------------------------
diff --git a/types/operations/binary_operations/SubtractBinaryOperation.hpp b/types/operations/binary_operations/SubtractBinaryOperation.hpp
deleted file mode 100644
index 8e54362..0000000
--- a/types/operations/binary_operations/SubtractBinaryOperation.hpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * 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_OPERATIONS_BINARY_OPERATIONS_SUBTRACT_BINARY_OPERATION_HPP_
-#define QUICKSTEP_TYPES_OPERATIONS_BINARY_OPERATIONS_SUBTRACT_BINARY_OPERATION_HPP_
-
-#include <utility>
-
-#include "types/TypedValue.hpp"
-#include "types/operations/binary_operations/ArithmeticBinaryOperation.hpp"
-#include "types/operations/binary_operations/BinaryOperationID.hpp"
-#include "utility/Macros.hpp"
-
-namespace quickstep {
-
-class Type;
-class UncheckedBinaryOperator;
-
-/** \addtogroup Types
- *  @{
- */
-
-/**
- * @brief The BinaryOperation for subtraction.
- *
- * @note SubtractBinaryOperation is not commutative: the left argument is the
- *       minuend and the right argument is the subtrahend.
- **/
-class SubtractBinaryOperation : public ArithmeticBinaryOperation {
- public:
-  /**
-   * @brief Get a reference to the singleton instance of this Operation.
-   *
-   * @return A reference to the singleton instance of this Operation.
-   **/
-  static const SubtractBinaryOperation& Instance() {
-    static SubtractBinaryOperation instance;
-    return instance;
-  }
-
-  bool canApplyToTypes(const Type &left,
-                       const Type &right) const override;
-
-  const Type* resultTypeForArgumentTypes(const Type &left,
-                                         const Type &right) const override;
-
-  const Type* resultTypeForPartialArgumentTypes(const Type *left,
-                                                const Type *right) const override;
-
-  bool partialTypeSignatureIsPlausible(const Type *result_type,
-                                       const Type *left_argument_type,
-                                       const Type *right_argument_type) const override;
-
-  std::pair<const Type*, const Type*> pushDownTypeHint(
-      const Type *result_type_hint) const override;
-
-  TypedValue applyToChecked(const TypedValue &left,
-                            const Type &left_type,
-                            const TypedValue &right,
-                            const Type &right_type) const override;
-
-  UncheckedBinaryOperator *makeUncheckedBinaryOperatorForTypes(const Type &left,
-                                                               const Type &right) const override;
-
- private:
-  SubtractBinaryOperation()
-      : ArithmeticBinaryOperation(BinaryOperationID::kSubtract) {
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(SubtractBinaryOperation);
-};
-
-/** @} */
-
-}  // namespace quickstep
-
-#endif  // QUICKSTEP_TYPES_OPERATIONS_BINARY_OPERATIONS_SUBTRACT_BINARY_OPERATION_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/comparisons/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/CMakeLists.txt b/types/operations/comparisons/CMakeLists.txt
index 321c0f6..933f4fa 100644
--- a/types/operations/comparisons/CMakeLists.txt
+++ b/types/operations/comparisons/CMakeLists.txt
@@ -105,11 +105,13 @@ target_link_libraries(quickstep_types_operations_comparisons_ComparisonID
 target_link_libraries(quickstep_types_operations_comparisons_ComparisonUtil
                       glog
                       quickstep_catalog_CatalogTypedefs
+                      quickstep_types_CharType
                       quickstep_types_DatetimeLit
                       quickstep_types_IntervalLit
                       quickstep_types_Type
                       quickstep_types_TypeID
                       quickstep_types_TypedValue
+                      quickstep_types_VarCharType
                       quickstep_types_containers_Tuple
                       quickstep_types_operations_comparisons_AsciiStringComparators
                       quickstep_types_operations_comparisons_Comparison
@@ -179,8 +181,8 @@ target_link_libraries(quickstep_types_operations_comparisons_PatternMatchingComp
                       quickstep_types_operations_comparisons_PatternMatchingComparators
                       quickstep_types_operations_comparisons_Comparison
                       quickstep_types_operations_comparisons_ComparisonID
-                      quickstep_utility_TemplateUtil
-                      quickstep_utility_Macros)
+                      quickstep_utility_Macros
+                      quickstep_utility_meta_Dispatchers)
 
 # Module all-in-one library:
 add_library(quickstep_types_operations_comparisons ../../../empty_src.cpp)

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/comparisons/Comparison.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/Comparison.hpp b/types/operations/comparisons/Comparison.hpp
index c300e74..33c853d 100644
--- a/types/operations/comparisons/Comparison.hpp
+++ b/types/operations/comparisons/Comparison.hpp
@@ -606,11 +606,7 @@ class Comparison : public Operation {
 
  protected:
   explicit Comparison(const ComparisonID comparison_id)
-      : Operation(Operation::kComparison,
-                  kComparisonNames[
-                      static_cast<typename std::underlying_type<ComparisonID>::type>(comparison_id)],
-                  kComparisonShortNames[
-                      static_cast<typename std::underlying_type<ComparisonID>::type>(comparison_id)]),
+      : Operation(Operation::kComparison),
         comparison_id_(comparison_id) {
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/comparisons/ComparisonUtil.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/ComparisonUtil.hpp b/types/operations/comparisons/ComparisonUtil.hpp
index 5d868fc..425566d 100644
--- a/types/operations/comparisons/ComparisonUtil.hpp
+++ b/types/operations/comparisons/ComparisonUtil.hpp
@@ -28,11 +28,13 @@
 #include <type_traits>
 
 #include "catalog/CatalogTypedefs.hpp"
+#include "types/CharType.hpp"
 #include "types/DatetimeLit.hpp"
 #include "types/IntervalLit.hpp"
 #include "types/Type.hpp"
 #include "types/TypeID.hpp"
 #include "types/TypedValue.hpp"
+#include "types/VarCharType.hpp"
 #include "types/containers/Tuple.hpp"
 #include "types/operations/comparisons/AsciiStringComparators.hpp"
 #include "types/operations/comparisons/AsciiStringComparators-inl.hpp"
@@ -153,7 +155,7 @@ auto InvokeOnLessComparatorForTypeIgnoreNullability(const Type &type,
     }
     case kChar: {
       const std::size_t string_length
-          = static_cast<const AsciiStringSuperType&>(type).getStringLength();
+          = static_cast<const CharType&>(type).getStringLength();
       LessAsciiStringUncheckedComparator<false, false, false,
                                          false, false, false>
           comp(string_length, string_length);
@@ -340,11 +342,11 @@ auto InvokeOnLessComparatorForDifferentTypesIgnoreNullability(
     }
     case kChar: {
       const std::size_t left_string_length
-          = static_cast<const AsciiStringSuperType&>(left_type).getStringLength();
+          = static_cast<const CharType&>(left_type).getStringLength();
       switch (right_type.getTypeID()) {
         case kChar: {
           const std::size_t right_string_length
-              = static_cast<const AsciiStringSuperType&>(right_type).getStringLength();
+              = static_cast<const CharType&>(right_type).getStringLength();
           if (left_string_length < right_string_length) {
             LessAsciiStringUncheckedComparator<false, false, false,
                                                false, false, true>
@@ -364,7 +366,7 @@ auto InvokeOnLessComparatorForDifferentTypesIgnoreNullability(
         }
         case kVarChar: {
           const std::size_t right_string_length
-              = static_cast<const AsciiStringSuperType&>(right_type).getStringLength();
+              = static_cast<const VarCharType&>(right_type).getStringLength();
           if (left_string_length < right_string_length) {
             LessAsciiStringUncheckedComparator<false, false, false,
                                                false, true, true>
@@ -389,11 +391,11 @@ auto InvokeOnLessComparatorForDifferentTypesIgnoreNullability(
     }
     case kVarChar: {
       const std::size_t left_string_length
-          = static_cast<const AsciiStringSuperType&>(left_type).getStringLength();
+          = static_cast<const VarCharType&>(left_type).getStringLength();
       switch (right_type.getTypeID()) {
         case kChar: {
           const std::size_t right_string_length
-              = static_cast<const AsciiStringSuperType&>(right_type).getStringLength();
+              = static_cast<const CharType&>(right_type).getStringLength();
           if (left_string_length < right_string_length) {
             LessAsciiStringUncheckedComparator<false, true, false,
                                                false, false, true>
@@ -413,7 +415,7 @@ auto InvokeOnLessComparatorForDifferentTypesIgnoreNullability(
         }
         case kVarChar: {
           const std::size_t right_string_length
-              = static_cast<const AsciiStringSuperType&>(right_type).getStringLength();
+              = static_cast<const VarCharType&>(right_type).getStringLength();
           if (left_string_length < right_string_length) {
             LessAsciiStringUncheckedComparator<false, true, false,
                                                false, true, true>
@@ -653,11 +655,11 @@ auto InvokeOnBothLessComparatorsForDifferentTypesIgnoreNullability(
     }
     case kChar: {
       const std::size_t left_string_length
-          = static_cast<const AsciiStringSuperType&>(left_type).getStringLength();
+          = static_cast<const CharType&>(left_type).getStringLength();
       switch (right_type.getTypeID()) {
         case kChar: {
           const std::size_t right_string_length
-              = static_cast<const AsciiStringSuperType&>(right_type).getStringLength();
+              = static_cast<const CharType&>(right_type).getStringLength();
           if (left_string_length < right_string_length) {
             LessAsciiStringUncheckedComparator<false, false, false,
                                                false, false, true>
@@ -686,7 +688,7 @@ auto InvokeOnBothLessComparatorsForDifferentTypesIgnoreNullability(
         }
         case kVarChar: {
           const std::size_t right_string_length
-              = static_cast<const AsciiStringSuperType&>(right_type).getStringLength();
+              = static_cast<const VarCharType&>(right_type).getStringLength();
           if (left_string_length < right_string_length) {
             LessAsciiStringUncheckedComparator<false, false, false,
                                                false, true, true>
@@ -720,11 +722,11 @@ auto InvokeOnBothLessComparatorsForDifferentTypesIgnoreNullability(
     }
     case kVarChar: {
       const std::size_t left_string_length
-          = static_cast<const AsciiStringSuperType&>(left_type).getStringLength();
+          = static_cast<const VarCharType&>(left_type).getStringLength();
       switch (right_type.getTypeID()) {
         case kChar: {
           const std::size_t right_string_length
-              = static_cast<const AsciiStringSuperType&>(right_type).getStringLength();
+              = static_cast<const CharType&>(right_type).getStringLength();
           if (left_string_length < right_string_length) {
             LessAsciiStringUncheckedComparator<false, true, false,
                                                false, false, true>
@@ -753,7 +755,7 @@ auto InvokeOnBothLessComparatorsForDifferentTypesIgnoreNullability(
         }
         case kVarChar: {
           const std::size_t right_string_length
-              = static_cast<const AsciiStringSuperType&>(right_type).getStringLength();
+              = static_cast<const VarCharType&>(right_type).getStringLength();
           if (left_string_length < right_string_length) {
             LessAsciiStringUncheckedComparator<false, true, false,
                                                false, true, true>
@@ -991,7 +993,7 @@ inline bool CheckUntypedValuesEqual(const Type &type, const void *left, const vo
     case kDouble:
       return STLLiteralEqual<double>()(left, right);
     case kChar:
-      return STLCharEqual(static_cast<const AsciiStringSuperType&>(type).getStringLength())(left, right);
+      return STLCharEqual(static_cast<const CharType&>(type).getStringLength())(left, right);
     case kVarChar:
       return STLVarCharEqual()(left, right);
     case kDate:

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/comparisons/PatternMatchingComparison.cpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/PatternMatchingComparison.cpp b/types/operations/comparisons/PatternMatchingComparison.cpp
index 4207f0f..c94ba52 100644
--- a/types/operations/comparisons/PatternMatchingComparison.cpp
+++ b/types/operations/comparisons/PatternMatchingComparison.cpp
@@ -29,7 +29,7 @@
 #include "types/operations/comparisons/ComparisonID.hpp"
 #include "types/operations/comparisons/PatternMatchingComparators.hpp"
 #include "types/operations/comparisons/PatternMatchingComparators-inl.hpp"
-#include "utility/TemplateUtil.hpp"
+#include "utility/meta/Dispatchers.hpp"
 
 #include "glog/logging.h"
 
@@ -121,11 +121,19 @@ UncheckedComparator* PatternMatchingComparison::makeUncheckedComparatorForTypes(
                  << " in PatternMatchinComparison::makeUncheckedComparatorForTypes()";
   }
 
-  return CreateBoolInstantiatedInstance<PatternMatchingUncheckedComparator, UncheckedComparator>(
-      std::forward_as_tuple(left_max_length, right_max_length),
+  return meta::InvokeOnBools(
       is_like_pattern, is_negation,
-      left.isNullable(), right.isNullable());
+      left.isNullable(), right.isNullable(),
+      [&](auto is_like_pattern,  // NOLINT(build/c++11)
+          auto is_negation,
+          auto is_left_nullable,
+          auto is_right_nullable) -> UncheckedComparator* {
+    return new PatternMatchingUncheckedComparator<
+        decltype(is_like_pattern)::value,
+        decltype(is_negation)::value,
+        decltype(is_left_nullable)::value,
+        decltype(is_right_nullable)::value>(left_max_length, right_max_length);
+  });
 }
 
-
 }  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/unary_operations/ArithmeticUnaryOperations.cpp
----------------------------------------------------------------------
diff --git a/types/operations/unary_operations/ArithmeticUnaryOperations.cpp b/types/operations/unary_operations/ArithmeticUnaryOperations.cpp
deleted file mode 100644
index c10d5cf..0000000
--- a/types/operations/unary_operations/ArithmeticUnaryOperations.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/**
- * 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.
- **/
-
-#include "types/operations/unary_operations/ArithmeticUnaryOperations.hpp"
-
-#include <string>
-
-#include "types/DatetimeIntervalType.hpp"
-#include "types/DoubleType.hpp"
-#include "types/FloatType.hpp"
-#include "types/IntType.hpp"
-#include "types/LongType.hpp"
-#include "types/Type.hpp"
-#include "types/TypeErrors.hpp"
-#include "types/TypeID.hpp"
-#include "types/TypedValue.hpp"
-#include "types/YearMonthIntervalType.hpp"
-#include "types/operations/unary_operations/ArithmeticUnaryOperators.hpp"
-#include "utility/EqualsAnyConstant.hpp"
-#include "utility/Macros.hpp"
-
-#include "glog/logging.h"
-
-namespace quickstep {
-
-bool ArithmeticUnaryOperation::canApplyToType(const Type &type) const {
-  return QUICKSTEP_EQUALS_ANY_CONSTANT(
-      type.getTypeID(),
-      kInt, kLong, kFloat, kDouble, kDatetimeInterval, kYearMonthInterval);
-}
-
-const Type* ArithmeticUnaryOperation::resultTypeForArgumentType(const Type &type) const {
-  if (canApplyToType(type)) {
-    return &type;
-  } else {
-    return nullptr;
-  }
-}
-
-const Type* ArithmeticUnaryOperation::pushDownTypeHint(const Type *type_hint) const {
-  if (type_hint == nullptr) {
-    return nullptr;
-  }
-
-  if (canApplyToType(*type_hint)) {
-    return type_hint;
-  } else {
-    return nullptr;
-  }
-}
-
-bool NegateUnaryOperation::resultTypeIsPlausible(const Type &result_type) const {
-  return QUICKSTEP_EQUALS_ANY_CONSTANT(
-      result_type.getTypeID(),
-      kInt, kLong, kFloat, kDouble, kDatetimeInterval, kYearMonthInterval);
-}
-
-TypedValue NegateUnaryOperation::applyToChecked(const TypedValue &argument,
-                                                const Type &argument_type) const {
-  DCHECK_EQ(argument.getTypeID(), argument_type.getTypeID());
-
-  if (argument.isNull()) {
-    return argument;
-  }
-
-  switch (argument.getTypeID()) {
-    case kInt:
-      return TypedValue(-argument.getLiteral<typename IntType::cpptype>());
-    case kLong:
-      return TypedValue(-argument.getLiteral<typename LongType::cpptype>());
-    case kFloat:
-      return TypedValue(-argument.getLiteral<typename FloatType::cpptype>());
-    case kDouble:
-      return TypedValue(-argument.getLiteral<typename DoubleType::cpptype>());
-    case kDatetimeInterval:
-      return TypedValue(-argument.getLiteral<typename DatetimeIntervalType::cpptype>());
-    case kYearMonthInterval:
-      return TypedValue(-argument.getLiteral<typename YearMonthIntervalType::cpptype>());
-    default: {
-      LOG(FATAL) << "Can not apply UnaryOperation " << getName()
-                 << " to argument of type " << argument_type.getName();
-    }
-  }
-}
-
-UncheckedUnaryOperator* NegateUnaryOperation::makeUncheckedUnaryOperatorForType(const Type &type) const {
-  switch (type.getTypeID()) {
-    case kInt:
-      if (type.isNullable()) {
-        return new NegateUncheckedUnaryOperator<IntType, true>();
-      } else {
-        return new NegateUncheckedUnaryOperator<IntType, false>();
-      }
-    case kLong:
-      if (type.isNullable()) {
-        return new NegateUncheckedUnaryOperator<LongType, true>();
-      } else {
-        return new NegateUncheckedUnaryOperator<LongType, false>();
-      }
-    case kFloat:
-      if (type.isNullable()) {
-        return new NegateUncheckedUnaryOperator<FloatType, true>();
-      } else {
-        return new NegateUncheckedUnaryOperator<FloatType, false>();
-      }
-    case kDouble:
-      if (type.isNullable()) {
-        return new NegateUncheckedUnaryOperator<DoubleType, true>();
-      } else {
-        return new NegateUncheckedUnaryOperator<DoubleType, false>();
-      }
-    case kDatetimeInterval:
-      if (type.isNullable()) {
-        return new NegateUncheckedUnaryOperator<DatetimeIntervalType, true>();
-      } else {
-        return new NegateUncheckedUnaryOperator<DatetimeIntervalType, false>();
-      }
-    case kYearMonthInterval:
-      if (type.isNullable()) {
-        return new NegateUncheckedUnaryOperator<YearMonthIntervalType, true>();
-      } else {
-        return new NegateUncheckedUnaryOperator<YearMonthIntervalType, false>();
-      }
-    default:
-      throw OperationInapplicableToType(getName(), 1, type.getName().c_str());
-  }
-}
-
-}  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/unary_operations/ArithmeticUnaryOperations.hpp
----------------------------------------------------------------------
diff --git a/types/operations/unary_operations/ArithmeticUnaryOperations.hpp b/types/operations/unary_operations/ArithmeticUnaryOperations.hpp
index 5eed073..4c212c0 100644
--- a/types/operations/unary_operations/ArithmeticUnaryOperations.hpp
+++ b/types/operations/unary_operations/ArithmeticUnaryOperations.hpp
@@ -20,73 +20,60 @@
 #ifndef QUICKSTEP_TYPES_OPERATIONS_UNARY_OPERATIONS_ARITHMETIC_UNARY_OPERATIONS_HPP_
 #define QUICKSTEP_TYPES_OPERATIONS_UNARY_OPERATIONS_ARITHMETIC_UNARY_OPERATIONS_HPP_
 
-#include "types/TypedValue.hpp"
-#include "types/operations/unary_operations/UnaryOperation.hpp"
-#include "types/operations/unary_operations/UnaryOperationID.hpp"
-#include "utility/Macros.hpp"
+#include <string>
 
-namespace quickstep {
+#include "types/DatetimeIntervalType.hpp"
+#include "types/DoubleType.hpp"
+#include "types/FloatType.hpp"
+#include "types/IntType.hpp"
+#include "types/LongType.hpp"
+#include "types/YearMonthIntervalType.hpp"
+#include "types/operations/OperationUtil.hpp"
+#include "types/operations/unary_operations/UnaryOperationWrapper.hpp"
 
-class Type;
+namespace quickstep {
 
 /** \addtogroup Types
  *  @{
  */
 
-/**
- * @brief A UnaryOperation which applies to and yields numeric values.
- **/
-class ArithmeticUnaryOperation : public UnaryOperation {
- public:
-  bool canApplyToType(const Type &type) const override;
-
-  const Type* resultTypeForArgumentType(const Type &type) const override;
-
-  const Type* pushDownTypeHint(const Type *type_hint) const override;
-
- protected:
-  explicit ArithmeticUnaryOperation(const UnaryOperationID operation_id)
-      : UnaryOperation(operation_id) {
+template <typename ArgumentT, typename ResultT>
+struct NegateFunctor : public UnaryFunctor<ArgumentT, ResultT> {
+  inline typename ResultT::cpptype apply(
+      const typename ArgumentT::cpptype &argument) const {
+    return -argument;
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ArithmeticUnaryOperation);
-};
-
-/**
- * @brief The UnaryOperation for negation.
- **/
-class NegateUnaryOperation : public ArithmeticUnaryOperation {
- public:
-  /**
-   * @brief Get a reference to the singleton instance of this Operation.
-   *
-   * @return A reference to the singleton instance of this Operation.
-   **/
-  static const NegateUnaryOperation& Instance() {
-    static NegateUnaryOperation instance;
-    return instance;
+  inline static std::string GetName() {
+    return "-";
   }
+};
 
-  const Type* fixedNullableResultType() const override {
-    return nullptr;
+template <typename ArgumentT>
+struct SgnFunctor : public UnaryFunctor<ArgumentT, IntType> {
+  inline int apply(const typename ArgumentT::cpptype &argument) const {
+    return (argument > 0) - (argument < 0);
   }
-
-  bool resultTypeIsPlausible(const Type &result_type) const override;
-
-  TypedValue applyToChecked(const TypedValue &argument,
-                            const Type &argument_type) const override;
-
-  UncheckedUnaryOperator* makeUncheckedUnaryOperatorForType(const Type &type) const override;
-
- private:
-  NegateUnaryOperation()
-      : ArithmeticUnaryOperation(UnaryOperationID::kNegate) {
+  inline static std::string GetName() {
+    return "Sgn";
   }
-
-  DISALLOW_COPY_AND_ASSIGN(NegateUnaryOperation);
 };
 
+using ArithmeticUnaryFunctorPack = FunctorPack<
+// negate
+  NegateFunctor<IntType, IntType>,
+  NegateFunctor<LongType, LongType>,
+  NegateFunctor<FloatType, FloatType>,
+  NegateFunctor<DoubleType, DoubleType>,
+  NegateFunctor<DatetimeIntervalType, DatetimeIntervalType>,
+  NegateFunctor<YearMonthIntervalType, YearMonthIntervalType>,
+
+// sgn (Sign of a numeric value)
+  SgnFunctor<IntType>,
+  SgnFunctor<LongType>,
+  SgnFunctor<FloatType>,
+  SgnFunctor<DoubleType>
+>;
+
 /** @} */
 
 }  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/unary_operations/ArithmeticUnaryOperators.hpp
----------------------------------------------------------------------
diff --git a/types/operations/unary_operations/ArithmeticUnaryOperators.hpp b/types/operations/unary_operations/ArithmeticUnaryOperators.hpp
deleted file mode 100644
index bf3f7b6..0000000
--- a/types/operations/unary_operations/ArithmeticUnaryOperators.hpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/**
- * 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_OPERATIONS_UNARY_OPERATIONS_ARITHMETIC_UNARY_OPERATORS_HPP_
-#define QUICKSTEP_TYPES_OPERATIONS_UNARY_OPERATIONS_ARITHMETIC_UNARY_OPERATORS_HPP_
-
-#include <cstddef>
-#include <utility>
-#include <vector>
-
-#include "catalog/CatalogTypedefs.hpp"
-
-#ifdef QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION
-#include "storage/StorageBlockInfo.hpp"
-#include "storage/ValueAccessor.hpp"
-#include "storage/ValueAccessorUtil.hpp"
-#endif  // QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION
-
-#include "types/TypedValue.hpp"
-#include "types/containers/ColumnVector.hpp"
-#include "types/operations/unary_operations/UnaryOperation.hpp"
-#include "utility/Macros.hpp"
-
-#include "glog/logging.h"
-
-namespace quickstep {
-
-/** \addtogroup Types
- *  @{
- */
-
-/**
- * @brief The UncheckedUnaryOperator for negation.
- **/
-template <class ResultType, bool argument_nullable>
-class NegateUncheckedUnaryOperator : public UncheckedUnaryOperator {
- public:
-  NegateUncheckedUnaryOperator() : UncheckedUnaryOperator() {
-  }
-
-  inline TypedValue applyToTypedValue(const TypedValue &argument) const override {
-    return applyToTypedValueInl(argument);
-  }
-
-  inline TypedValue applyToTypedValueInl(const TypedValue &argument) const {
-    if (argument_nullable && argument.isNull()) {
-      return argument;
-    }
-    return TypedValue(-argument.getLiteral<typename ResultType::cpptype>());
-  }
-
-  inline TypedValue applyToDataPtr(const void *argument) const override {
-    return applyToDataPtrInl(argument);
-  }
-
-  inline TypedValue applyToDataPtrInl(const void *argument) const {
-    if (argument_nullable && (argument == nullptr)) {
-      return TypedValue(ResultType::kStaticTypeID);
-    }
-    return TypedValue(-*static_cast<const typename ResultType::cpptype*>(argument));
-  }
-
-  ColumnVector* applyToColumnVector(const ColumnVector &argument) const override {
-    DCHECK(NativeColumnVector::UsableForType(ResultType::Instance(argument_nullable)));
-    // All arithmetic types (numbers, datetime, and intervals) are usable with
-    // NativeColumnVector, so 'argument' should always be native.
-    DCHECK(argument.isNative());
-    const NativeColumnVector &native_argument = static_cast<const NativeColumnVector&>(argument);
-    NativeColumnVector *result = new NativeColumnVector(
-        ResultType::Instance(argument_nullable),
-        native_argument.size());
-    for (std::size_t pos = 0;
-         pos < native_argument.size();
-         ++pos) {
-      const typename ResultType::cpptype *scalar_arg
-          = static_cast<const typename ResultType::cpptype*>(
-              native_argument.getUntypedValue<argument_nullable>(pos));
-      if (argument_nullable && (scalar_arg == nullptr)) {
-        result->appendNullValue();
-      } else {
-        *static_cast<typename ResultType::cpptype*>(result->getPtrForDirectWrite())
-            = -(*scalar_arg);
-      }
-    }
-    return result;
-  }
-
-#ifdef QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION
-  ColumnVector* applyToValueAccessor(ValueAccessor *accessor,
-                                     const attribute_id argument_attr_id) const override {
-    DCHECK(NativeColumnVector::UsableForType(ResultType::Instance(argument_nullable)));
-    return InvokeOnValueAccessorMaybeTupleIdSequenceAdapter(
-        accessor,
-        [&](auto *accessor) -> ColumnVector* {  // NOLINT(build/c++11)
-      NativeColumnVector *result = new NativeColumnVector(
-          ResultType::Instance(argument_nullable),
-          accessor->getNumTuples());
-      accessor->beginIteration();
-      while (accessor->next()) {
-        const typename ResultType::cpptype *scalar_arg
-            = static_cast<const typename ResultType::cpptype*>(
-                accessor->template getUntypedValue<argument_nullable>(argument_attr_id));
-        if (argument_nullable && (scalar_arg == nullptr)) {
-          result->appendNullValue();
-        } else {
-          *static_cast<typename ResultType::cpptype*>(result->getPtrForDirectWrite())
-              = -(*scalar_arg);
-        }
-      }
-      return result;
-    });
-  }
-#endif  // QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_SELECTION
-
-#ifdef QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_JOIN
-  ColumnVector* applyToValueAccessorForJoin(
-      ValueAccessor *accessor,
-      const bool use_left_relation,
-      const attribute_id argument_attr_id,
-      const std::vector<std::pair<tuple_id, tuple_id>> &joined_tuple_ids) const override {
-    DCHECK(NativeColumnVector::UsableForType(ResultType::Instance(argument_nullable)));
-    NativeColumnVector *result = new NativeColumnVector(ResultType::Instance(argument_nullable),
-                                                        joined_tuple_ids.size());
-    InvokeOnValueAccessorNotAdapter(
-        accessor,
-        [&](auto *accessor) -> void {  // NOLINT(build/c++11)
-      for (const std::pair<tuple_id, tuple_id> &joined_pair : joined_tuple_ids) {
-        const typename ResultType::cpptype *scalar_arg
-            = static_cast<const typename ResultType::cpptype*>(
-                accessor->template getUntypedValueAtAbsolutePosition<argument_nullable>(
-                    argument_attr_id,
-                    use_left_relation ? joined_pair.first : joined_pair.second));
-        if (argument_nullable && (scalar_arg == nullptr)) {
-          result->appendNullValue();
-        } else {
-          *static_cast<typename ResultType::cpptype*>(result->getPtrForDirectWrite())
-              = -(*scalar_arg);
-        }
-      }
-    });
-    return result;
-  }
-#endif  // QUICKSTEP_ENABLE_VECTOR_COPY_ELISION_JOIN
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NegateUncheckedUnaryOperator);
-};
-
-/** @} */
-
-}  // namespace quickstep
-
-#endif  // QUICKSTEP_TYPES_OPERATIONS_UNARY_OPERATIONS_ARITHMETIC_UNARY_OPERATORS_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/da9baf7e/types/operations/unary_operations/AsciiStringUnaryOperations.hpp
----------------------------------------------------------------------
diff --git a/types/operations/unary_operations/AsciiStringUnaryOperations.hpp b/types/operations/unary_operations/AsciiStringUnaryOperations.hpp
new file mode 100644
index 0000000..1ee1867
--- /dev/null
+++ b/types/operations/unary_operations/AsciiStringUnaryOperations.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_OPERATIONS_UNARY_OPERATIONS_ASCII_STRING_UNARY_OPERATIONS_HPP_
+#define QUICKSTEP_TYPES_OPERATIONS_UNARY_OPERATIONS_ASCII_STRING_UNARY_OPERATIONS_HPP_
+
+#include <cctype>
+#include <cstring>
+#include <string>
+
+#include "types/CharType.hpp"
+#include "types/IntType.hpp"
+#include "types/Type.hpp"
+#include "types/TypeFactory.hpp"
+#include "types/TypeID.hpp"
+#include "types/VarCharType.hpp"
+#include "types/operations/OperationUtil.hpp"
+#include "types/operations/unary_operations/UnaryOperationWrapper.hpp"
+#include "types/port/strnlen.hpp"
+#include "utility/meta/Common.hpp"
+
+namespace quickstep {
+
+/** \addtogroup Types
+ *  @{
+ */
+
+template <typename ArgumentT>
+struct AsciiStringLengthFunctor : public UnaryFunctor<ArgumentT, IntType> {
+  explicit AsciiStringLengthFunctor(const ArgumentT &argument_type)
+      : max_string_length_(argument_type.getStringLength()) {}
+  inline int apply(const void *argument) const {
+    return strnlen(static_cast<const char*>(argument), max_string_length_);
+  }
+  inline int apply(const TypedValue &argument) const {
+    DCHECK(argument.getTypeID() == kVarChar);
+    return std::strlen(static_cast<const char*>(argument.getOutOfLineData()));
+  }
+  inline static std::string GetName() {
+    return "length";
+  }
+  const std::size_t max_string_length_;
+};
+
+template <typename ArgumentT, int transform(int), typename FunctorNameT>
+struct AsciiStringTranformFunctor : public UnaryFunctor<ArgumentT, ArgumentT> {
+  explicit AsciiStringTranformFunctor(const ArgumentT &argument_type)
+      : max_string_length_(argument_type.getStringLength()) {}
+  inline void apply(const void *argument, void *result) const {
+    DCHECK(ArgumentT::kStaticTypeID == kChar);
+    const char *argument_str = static_cast<const char*>(argument);
+    char *result_str = static_cast<char*>(result);
+    for (std::size_t i = 0; i < max_string_length_; ++i) {
+      if ((result_str[i] = transform(argument_str[i])) == 0) {
+        break;
+      }
+    }
+  }
+  inline TypedValue apply(const TypedValue &argument) const {
+    DCHECK(argument.getTypeID() == kVarChar);
+    const char *argument_str = static_cast<const char*>(argument.getOutOfLineData());
+    const std::size_t length = argument.getDataSize();
+    char *buf = static_cast<char*>(std::malloc(length));
+
+    for (std::size_t i = 0; i < length; ++i) {
+      buf[i] = transform(argument_str[i]);
+    }
+    return TypedValue::CreateWithOwnedData(kVarChar, buf, length);
+  }
+  inline static std::string GetName() {
+    return FunctorNameT::ToString();
+  }
+  inline static const Type* GetResultType(const Type &argument_type) {
+    DCHECK(argument_type.getTypeID() == ArgumentT::kStaticTypeID);
+    return &argument_type;
+  }
+  const std::size_t max_string_length_;
+};
+
+template <typename ArgumentT>
+using AsciiStringToLowerCaseFunctor =
+    AsciiStringTranformFunctor<ArgumentT, std::tolower,
+                               meta::StringLiteral<'t', 'o', 'l', 'o', 'w', 'e', 'r'>>;
+
+template <typename ArgumentT>
+using AsciiStringToUpperCaseFunctor =
+    AsciiStringTranformFunctor<ArgumentT, std::toupper,
+                               meta::StringLiteral<'t', 'o', 'u', 'p', 'p', 'e', 'r'>>;
+
+using AsciiStringUnaryFunctorPack = FunctorPack<
+// length
+    AsciiStringLengthFunctor<CharType>,
+    AsciiStringLengthFunctor<VarCharType>,
+// tolower
+    AsciiStringToLowerCaseFunctor<CharType>,
+    AsciiStringToLowerCaseFunctor<VarCharType>,
+// toupper
+    AsciiStringToUpperCaseFunctor<CharType>,
+    AsciiStringToUpperCaseFunctor<VarCharType>
+>;
+
+/** @} */
+
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_TYPES_OPERATIONS_UNARY_OPERATIONS_ASCII_STRING_UNARY_OPERATIONS_HPP_