http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/TypeIDSelectors.hpp ---------------------------------------------------------------------- diff --git a/types/TypeIDSelectors.hpp b/types/TypeIDSelectors.hpp new file mode 100644 index 0000000..d75a887 --- /dev/null +++ b/types/TypeIDSelectors.hpp @@ -0,0 +1,152 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + **/ + +#ifndef QUICKSTEP_TYPES_TYPE_ID_SELECTORS_HPP_ +#define QUICKSTEP_TYPES_TYPE_ID_SELECTORS_HPP_ + +#include <type_traits> + +#include "types/TypeID.hpp" +#include "utility/meta/Common.hpp" + +#include "glog/logging.h" + +namespace quickstep { + +/** \addtogroup Types + * @{ + */ + +struct TypeIDSelectorAll; + +struct TypeIDSelectorNumeric; + +struct TypeIDSelectorParameterized; + +struct TypeIDSelectorNonParameterized; + +template <TypeID ...candidates> +struct TypeIDSelectorEqualsAny; + + +// Forward declaration +template <TypeID type_id> +struct TypeIDTrait; + +struct TypeIDSelectorAll { + template <typename TypeIDConstant, typename FunctorT, typename EnableT = void> + struct Implementation { + inline static auto Invoke(const FunctorT &functor) { + return functor(TypeIDConstant()); + } + }; +}; + +struct TypeIDSelectorNumeric { + template <typename TypeIDConstant, typename FunctorT, typename EnableT = void> + struct Implementation { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wreturn-type" + inline static auto Invoke(const FunctorT &functor) + -> decltype(functor(TypeIDConstant())) { + DLOG(FATAL) << "Unexpected TypeID: " + << kTypeNames[static_cast<int>(TypeIDConstant::value)]; + } +#pragma GCC diagnostic pop + }; +}; + +template <typename TypeIDConstant, typename FunctorT> +struct TypeIDSelectorNumeric::Implementation< + TypeIDConstant, FunctorT, + std::enable_if_t<TypeIDTrait<TypeIDConstant::value> + ::kStaticSuperTypeID == Type::kNumeric>> { + inline static auto Invoke(const FunctorT &functor) { + return functor(TypeIDConstant()); + } +}; + +template <TypeID ...candidates> +struct TypeIDSelectorEqualsAny { + template <typename TypeIDConstant, typename FunctorT, typename EnableT = void> + struct Implementation { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wreturn-type" + inline static auto Invoke(const FunctorT &functor) + -> decltype(functor(TypeIDConstant())) { + DLOG(FATAL) << "Unexpected TypeID: " + << kTypeNames[static_cast<int>(TypeIDConstant::value)]; + } +#pragma GCC diagnostic pop + }; +}; + +template <TypeID ...candidates> +template <typename TypeIDConstant, typename FunctorT> +struct TypeIDSelectorEqualsAny<candidates...>::Implementation< + TypeIDConstant, FunctorT, + std::enable_if_t< + meta::EqualsAny<TypeIDConstant, + std::integral_constant<TypeID, candidates>...>::value>> { + inline static auto Invoke(const FunctorT &functor) { + return functor(TypeIDConstant()); + } +}; + +namespace internal { + +template <bool require_parameterized> +struct TypeIDSelectorParameterizedHelper { + template <typename TypeIDConstant, typename FunctorT, typename EnableT = void> + struct Implementation { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wreturn-type" + inline static auto Invoke(const FunctorT &functor) + -> decltype(functor(TypeIDConstant())) { + DLOG(FATAL) << "Unexpected TypeID: " + << kTypeNames[static_cast<int>(TypeIDConstant::value)]; + } +#pragma GCC diagnostic pop + }; +}; + +template <bool require_non_parameterized> +template <typename TypeIDConstant, typename FunctorT> +struct TypeIDSelectorParameterizedHelper<require_non_parameterized>::Implementation< + TypeIDConstant, FunctorT, + std::enable_if_t<TypeIDTrait<TypeIDConstant::value>::kParameterized + ^ require_non_parameterized>> { + inline static auto Invoke(const FunctorT &functor) { + return functor(TypeIDConstant()); + } +}; + +} // namespace internal + +struct TypeIDSelectorNonParameterized + : internal::TypeIDSelectorParameterizedHelper<true> {}; + +struct TypeIDSelectorParameterized + : internal::TypeIDSelectorParameterizedHelper<false> {}; + +/** @} */ + +} // namespace quickstep + +#endif // QUICKSTEP_TYPES_TYPE_ID_SELECTORS_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/TypeRegistrar.hpp ---------------------------------------------------------------------- diff --git a/types/TypeRegistrar.hpp b/types/TypeRegistrar.hpp new file mode 100644 index 0000000..f4c9fb9 --- /dev/null +++ b/types/TypeRegistrar.hpp @@ -0,0 +1,122 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + **/ + +#ifndef QUICKSTEP_TYPES_TYPE_REGISTRAR_HPP_ +#define QUICKSTEP_TYPES_TYPE_REGISTRAR_HPP_ + +#include <cstdint> +#include <type_traits> + +#include "types/DatetimeLit.hpp" +#include "types/IntervalLit.hpp" +#include "types/Type.hpp" +#include "types/TypeID.hpp" +#include "types/TypeIDSelectors.hpp" +#include "utility/meta/Common.hpp" + +#include "glog/logging.h" + +namespace quickstep { + +/** \addtogroup Types + * @{ + */ + +template <TypeID type_id> +struct TypeIDTrait; + +#define REGISTER_TYPE(T, type_id, super_type_id, parameterized, layout, CppType) \ + class T; \ + template <> struct TypeIDTrait<type_id> { \ + typedef T TypeClass; \ + typedef CppType cpptype; \ + static constexpr TypeID kStaticTypeID = type_id; \ + static constexpr Type::SuperTypeID kStaticSuperTypeID = super_type_id; \ + static constexpr bool kParameterized = parameterized; \ + static constexpr TypeStorageLayout kLayout = layout; \ + }; + +REGISTER_TYPE(BoolType, kBool, \ + Type::kNumeric, false, kNativeEmbedded, bool); +REGISTER_TYPE(IntType, kInt, \ + Type::kNumeric, false, kNativeEmbedded, int); +REGISTER_TYPE(LongType, kLong, \ + Type::kNumeric, false, kNativeEmbedded, std::int64_t); +REGISTER_TYPE(FloatType, kFloat, \ + Type::kNumeric, false, kNativeEmbedded, float); +REGISTER_TYPE(DoubleType, kDouble, \ + Type::kNumeric, false, kNativeEmbedded, double); +REGISTER_TYPE(DateType, kDate, \ + Type::kOther, false, kNativeEmbedded, DateLit); +REGISTER_TYPE(DatetimeType, kDatetime, \ + Type::kOther, false, kNativeEmbedded, DatetimeLit); +REGISTER_TYPE(DatetimeIntervalType, kDatetimeInterval, \ + Type::kOther, false, kNativeEmbedded, DatetimeIntervalLit); +REGISTER_TYPE(YearMonthIntervalType, kYearMonthInterval, \ + Type::kOther, false, kNativeEmbedded, YearMonthIntervalLit); +REGISTER_TYPE(CharType, kChar, \ + Type::kAsciiString, true, kNonNativeInline, void); +REGISTER_TYPE(VarCharType, kVarChar, \ + Type::kAsciiString, true, kOutOfLine, void); +REGISTER_TYPE(NullType, kNullType, \ + Type::kOther, false, kNonNativeInline, void); + +#undef REGISTER_TYPE + +using TypeIDSequenceAll = + meta::MakeSequence<static_cast<std::size_t>(kNumTypeIDs)> + ::type::template cast_to<TypeID>; + +template <typename Selector = TypeIDSelectorAll, typename FunctorT> +auto InvokeOnTypeID(const TypeID type_id, const FunctorT &functor); + +namespace internal { + +template <int l, int r, typename Selector, typename FunctorT> +inline auto InvokeOnTypeIDInner(const int value, + const FunctorT &functor) { + DCHECK_LE(l, r); + if (l == r) { + constexpr TypeID type_id = static_cast<TypeID>(r); + return Selector::template Implementation< + std::integral_constant<TypeID, type_id>, FunctorT>::Invoke(functor); + } + constexpr int m = (l + r) >> 1; + if (value <= m) { + return InvokeOnTypeIDInner<l, m, Selector, FunctorT>(value, functor); + } else { + return InvokeOnTypeIDInner<m+1, r, Selector, FunctorT>(value, functor); + } +} + +} // namespace internal + +template <typename Selector, typename FunctorT> +auto InvokeOnTypeID(const TypeID type_id, + const FunctorT &functor) { + return internal::InvokeOnTypeIDInner<0, static_cast<int>(kNumTypeIDs)-1, + Selector, FunctorT>( + static_cast<int>(type_id), functor); +} + +/** @} */ + +} // namespace quickstep + +#endif // QUICKSTEP_TYPES_TYPE_REGISTRAR_HPP_ http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/TypeSynthesizer.hpp ---------------------------------------------------------------------- diff --git a/types/TypeSynthesizer.hpp b/types/TypeSynthesizer.hpp new file mode 100644 index 0000000..27ba02a --- /dev/null +++ b/types/TypeSynthesizer.hpp @@ -0,0 +1,210 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + **/ + +#ifndef QUICKSTEP_TYPES_TYPE_SYNTHESIZER_HPP_ +#define QUICKSTEP_TYPES_TYPE_SYNTHESIZER_HPP_ + +#include <cstddef> +#include <type_traits> + +#include "types/Type.hpp" +#include "types/Type.pb.h" +#include "types/TypeID.hpp" +#include "types/TypeRegistrar.hpp" +#include "utility/Macros.hpp" +#include "utility/PtrMap.hpp" + +#include "glog/logging.h" + +namespace quickstep { + +/** \addtogroup Types + * @{ + */ + +template <typename TypeClass, bool parameterized> +class TypeInstance; + + +template <TypeID type_id> +class TypeSynthesizer + : public Type, + public TypeInstance<typename TypeIDTrait<type_id>::TypeClass, + TypeIDTrait<type_id>::kParameterized> { + public: + using Trait = TypeIDTrait<type_id>; + using TypeClass = typename Trait::TypeClass; + + static constexpr Type::SuperTypeID kStaticSuperTypeID = Trait::kStaticSuperTypeID; + static constexpr TypeID kStaticTypeID = Trait::kStaticTypeID; + static constexpr bool kParameterized = Trait::kParameterized; + static constexpr TypeStorageLayout kLayout = Trait::kLayout; + + typedef typename Trait::cpptype cpptype; + + serialization::Type getProto() const override { + serialization::Type proto; + + proto.mutable_type_id()->CopyFrom(TypeIDFactory::GetProto(type_id_)); + proto.set_nullable(nullable_); + + if (kParameterized) { + proto.set_length(parameter_); + } + + return proto; + } + + const Type& getNullableVersion() const override { + return getInstance<kParameterized>(true); + } + + const Type& getNonNullableVersion() const override { + return getInstance<kParameterized>(false); + } + + protected: + template <TypeStorageLayout layout = kLayout, bool parameterized = kParameterized> + explicit TypeSynthesizer(const bool nullable, + std::enable_if_t<layout == kNativeEmbedded || + layout == kNativeInline>* = 0) + : Type(kStaticSuperTypeID, kStaticTypeID, nullable, + sizeof(cpptype), sizeof(cpptype)) { + DCHECK(!kParameterized); + } + + template <TypeStorageLayout layout = kLayout, bool parameterized = kParameterized> + TypeSynthesizer(const bool nullable, + const std::size_t minimum_byte_length, + const std::size_t maximum_byte_length, + const std::size_t parameter, + std::enable_if_t<parameterized && + (layout == kNonNativeInline || + layout == kOutOfLine)>* = 0) + : Type(kStaticSuperTypeID, kStaticTypeID, nullable, + minimum_byte_length, maximum_byte_length, parameter) { + DCHECK(kLayout != kNonNativeInline || minimum_byte_length == maximum_byte_length); + } + + template <TypeStorageLayout layout = kLayout, bool parameterized = kParameterized> + TypeSynthesizer(const bool nullable, + const std::size_t minimum_byte_length, + const std::size_t maximum_byte_length, + std::enable_if_t<!parameterized && + (layout == kNonNativeInline || + layout == kOutOfLine)>* = 0) + : Type(kStaticSuperTypeID, kStaticTypeID, nullable, + minimum_byte_length, maximum_byte_length) { + DCHECK(kLayout != kNonNativeInline || minimum_byte_length == maximum_byte_length); + } + + private: + template <bool has_param> + inline const Type& getInstance(const bool nullable, + std::enable_if_t<has_param>* = 0) const { + return TypeInstance<TypeClass, kParameterized>::Instance(parameter_, nullable); + } + + template <bool has_param> + inline const Type& getInstance(const bool nullable, + std::enable_if_t<!has_param>* = 0) const { + return TypeInstance<TypeClass, kParameterized>::Instance(nullable); + } + + friend class TypeInstance<TypeClass, kParameterized>; + + DISALLOW_COPY_AND_ASSIGN(TypeSynthesizer); +}; + +template <TypeID type_id> +constexpr Type::SuperTypeID TypeSynthesizer<type_id>::kStaticSuperTypeID; + +template <TypeID type_id> +constexpr TypeID TypeSynthesizer<type_id>::kStaticTypeID; + +template <TypeID type_id> +constexpr bool TypeSynthesizer<type_id>::kParameterized; + +template <TypeID type_id> +constexpr TypeStorageLayout TypeSynthesizer<type_id>::kLayout; + + +template <typename TypeClass> +class TypeInstance<TypeClass, false> { + public: + static const TypeClass& InstanceNonNullable() { + return InstanceInternal<false>(); + } + + static const TypeClass& InstanceNullable() { + return InstanceInternal<true>(); + } + + static const TypeClass& Instance(const bool nullable) { + if (nullable) { + return InstanceNullable(); + } else { + return InstanceNonNullable(); + } + } + + private: + template <bool nullable> + inline static const TypeClass& InstanceInternal() { + static TypeClass instance(nullable); + return instance; + } +}; + +template <typename TypeClass> +class TypeInstance<TypeClass, true> { + public: + static const TypeClass& InstanceNonNullable(const std::size_t length) { + return InstanceInternal<false>(length); + } + + static const TypeClass& InstanceNullable(const std::size_t length) { + return InstanceInternal<true>(length); + } + + static const TypeClass& Instance(const bool nullable, const std::size_t length) { + if (nullable) { + return InstanceNullable(length); + } else { + return InstanceNonNullable(length); + } + } + + private: + template <bool nullable> + inline static const TypeClass& InstanceInternal(const std::size_t length) { + static PtrMap<size_t, TypeClass> instance_map; + auto imit = instance_map.find(length); + if (imit == instance_map.end()) { + imit = instance_map.insert(length, new TypeClass(length, nullable)).first; + } + return *(imit->second); + } +}; + +/** @} */ + +} // namespace quickstep + +#endif // QUICKSTEP_TYPES_TYPE_SYNTHESIZER_HPP_ http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/TypeUtil.hpp ---------------------------------------------------------------------- diff --git a/types/TypeUtil.hpp b/types/TypeUtil.hpp new file mode 100644 index 0000000..b146f02 --- /dev/null +++ b/types/TypeUtil.hpp @@ -0,0 +1,70 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + **/ + +#ifndef QUICKSTEP_TYPES_TYPE_UTIL_HPP_ +#define QUICKSTEP_TYPES_TYPE_UTIL_HPP_ + +#include <type_traits> + +#include "types/BoolType.hpp" +#include "types/CharType.hpp" +#include "types/DateType.hpp" +#include "types/DatetimeIntervalType.hpp" +#include "types/DatetimeType.hpp" +#include "types/DoubleType.hpp" +#include "types/FloatType.hpp" +#include "types/IntType.hpp" +#include "types/LongType.hpp" +#include "types/NullType.hpp" +#include "types/Type.hpp" +#include "types/TypeID.hpp" +#include "types/TypeRegistrar.hpp" +#include "types/VarCharType.hpp" +#include "types/YearMonthIntervalType.hpp" +#include "utility/Macros.hpp" + +#include "glog/logging.h" + +namespace quickstep { + +/** \addtogroup Types + * @{ + */ + +class TypeUtil { + public: + static bool IsParameterized(const TypeID type_id) { + return InvokeOnTypeID( + type_id, + [&](auto tid) -> bool { // NOLINT(build/c++11) + return TypeIDTrait<decltype(tid)::value>::kParameterized; + }); + } + + private: + TypeUtil() {} + + DISALLOW_COPY_AND_ASSIGN(TypeUtil); +}; + +/** @} */ + +} // namespace quickstep + +#endif // QUICKSTEP_TYPES_TYPE_UTIL_HPP_ http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/TypedValue.cpp ---------------------------------------------------------------------- diff --git a/types/TypedValue.cpp b/types/TypedValue.cpp index 8dd8b60..ad1eb0f 100644 --- a/types/TypedValue.cpp +++ b/types/TypedValue.cpp @@ -47,6 +47,7 @@ bool TypedValue::isPlausibleInstanceOf(const TypeSignature type) const { } switch (type_id) { + case kBool: case kInt: case kLong: case kFloat: @@ -82,33 +83,34 @@ 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 kBool: + if (!isNull()) { + proto.set_int_value(getLiteral<bool>()); + } + break; 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 +119,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 +162,29 @@ 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 kBool: + return proto.has_bool_value() ? + TypedValue(static_cast<bool>(proto.bool_value())) : + TypedValue(kBool); + 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 +192,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 +200,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 +208,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 +216,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/cb564509/types/TypedValue.hpp ---------------------------------------------------------------------- diff --git a/types/TypedValue.hpp b/types/TypedValue.hpp index 0ba3d53..196e8ec 100644 --- a/types/TypedValue.hpp +++ b/types/TypedValue.hpp @@ -90,6 +90,16 @@ class TypedValue { } /** + * @brief Constructor for a literal value of BoolType. + **/ + explicit TypedValue(const bool literal_bool) + : value_info_(static_cast<std::uint64_t>(kBool)) { + // Zero-out all bytes in the union for getHash() and fastEqualCheck(). + value_union_.hash64 = 0; + value_union_.bool_value = literal_bool; + } + + /** * @brief Constructor for a literal value of IntType. **/ explicit TypedValue(const int literal_int) @@ -264,9 +274,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; @@ -282,6 +292,7 @@ class TypedValue { **/ static bool RepresentedInline(const TypeID type_id) { switch (type_id) { + case kBool: case kInt: case kLong: case kFloat: @@ -313,6 +324,8 @@ class TypedValue { **/ static bool HashIsReversible(const TypeID type_id) { switch (type_id) { + case kBool: + return true; case kInt: case kFloat: return sizeof(value_union_.int_value) <= sizeof(std::size_t); @@ -391,6 +404,8 @@ class TypedValue { inline std::size_t getDataSize() const { DCHECK(!isNull()); switch (getTypeID()) { + case kBool: + return sizeof(bool); case kInt: case kFloat: return sizeof(int); @@ -478,7 +493,8 @@ class TypedValue { * @return The out-of-line data this TypedValue points to. **/ inline const void* getOutOfLineData() const { - DCHECK(!(getTypeID() == kInt + DCHECK(!(getTypeID() == kBool + || getTypeID() == kInt || getTypeID() == kLong || getTypeID() == kFloat || getTypeID() == kDouble @@ -547,6 +563,10 @@ class TypedValue { value_info_ >> kSizeShift); } else { switch (getTypeID()) { + case kBool: + // 1 byte copy. + *static_cast<bool*>(destination) = value_union_.bool_value; + break; case kInt: case kFloat: // 4 bytes byte-for-byte copy. @@ -574,6 +594,7 @@ class TypedValue { **/ inline std::size_t getHash() const { switch (getTypeID()) { + case kBool: case kInt: case kLong: case kFloat: @@ -670,6 +691,7 @@ class TypedValue { DCHECK(!other.isNull()); DCHECK_EQ(getTypeID(), other.getTypeID()); switch (getTypeID()) { + case kBool: case kInt: case kLong: case kFloat: @@ -710,6 +732,16 @@ class TypedValue { } } + bool operator==(const TypedValue &other) const { + if (getTypeID() != other.getTypeID()) { + return false; + } + if (isNull() || other.isNull()) { + return isNull() == other.isNull(); + } + return fastEqualCheck(other); + } + /** * @brief Generate a serialized Protocol Buffer representation * of this TypedValue. @@ -789,6 +821,7 @@ class TypedValue { inline void reverseHash(const std::size_t hash); union ValueUnion { + bool bool_value; int int_value; std::int64_t long_value; float float_value; @@ -842,6 +875,13 @@ class TypedValue { // Explicit specializations of getLiteral(). template <> +inline bool TypedValue::getLiteral<bool>() const { + DCHECK_EQ(kBool, getTypeID()); + DCHECK(!isNull()); + return value_union_.bool_value; +} + +template <> inline int TypedValue::getLiteral<int>() const { DCHECK_EQ(kInt, getTypeID()); DCHECK(!isNull()); http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/TypedValue.proto ---------------------------------------------------------------------- diff --git a/types/TypedValue.proto b/types/TypedValue.proto index 7f3ab7a..7cf3eca 100644 --- a/types/TypedValue.proto +++ b/types/TypedValue.proto @@ -22,17 +22,18 @@ 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; - optional int64 long_value = 3; - optional float float_value = 4; - optional double double_value = 5; - optional bytes out_of_line_data = 6; - optional int64 datetime_value = 7; - optional int64 datetime_interval_value = 8; - optional int64 year_month_interval_value = 9; + optional bool bool_value = 2; + optional int32 int_value = 3; + optional int64 long_value = 4; + optional float float_value = 5; + optional double double_value = 6; + optional bytes out_of_line_data = 7; + optional int64 datetime_value = 8; + optional int64 datetime_interval_value = 9; + optional int64 year_month_interval_value = 10; message DateLit { required int32 year = 1; @@ -40,5 +41,5 @@ message TypedValue { required uint32 day = 3; } - optional DateLit date_value = 10; + optional DateLit date_value = 11; } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/VarCharType.cpp ---------------------------------------------------------------------- diff --git a/types/VarCharType.cpp b/types/VarCharType.cpp index 02845b1..7eeb04c 100644 --- a/types/VarCharType.cpp +++ b/types/VarCharType.cpp @@ -42,38 +42,6 @@ using std::string; namespace quickstep { -template <bool nullable_internal> -const VarCharType& VarCharType::InstanceInternal(const std::size_t length) { - static PtrMap<size_t, VarCharType> instance_map; - PtrMap<size_t, VarCharType>::iterator imit = instance_map.find(length); - if (imit == instance_map.end()) { - imit = instance_map.insert(length, new VarCharType(length, nullable_internal)).first; - } - return *(imit->second); -} - -const VarCharType& VarCharType::InstanceNonNullable(const std::size_t length) { - return InstanceInternal<false>(length); -} - -const VarCharType& VarCharType::InstanceNullable(const std::size_t length) { - return InstanceInternal<true>(length); -} - -const VarCharType& VarCharType::InstanceFromProto(const serialization::Type &proto) { - return Instance(proto.GetExtension(serialization::VarCharType::length), proto.nullable()); -} - -serialization::Type VarCharType::getProto() const { - serialization::Type proto; - proto.set_type_id(serialization::Type::VAR_CHAR); - - proto.set_nullable(nullable_); - - proto.SetExtension(serialization::VarCharType::length, length_); - return proto; -} - size_t VarCharType::estimateAverageByteLength() const { if (length_ > 160) { return 80; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/VarCharType.hpp ---------------------------------------------------------------------- diff --git a/types/VarCharType.hpp b/types/VarCharType.hpp index bb50e92..05b2aae 100644 --- a/types/VarCharType.hpp +++ b/types/VarCharType.hpp @@ -24,8 +24,8 @@ #include <cstdio> #include <string> +#include "types/AsciiStringSuperType.hpp" #include "types/Type.hpp" -#include "types/Type.pb.h" #include "types/TypeID.hpp" #include "types/TypedValue.hpp" #include "utility/Macros.hpp" @@ -43,72 +43,9 @@ 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> { public: /** - * @brief Get a reference to the non-nullable singleton instance of this Type - * for the specified length. - * - * @param length The length parameter of the VarCharType. - * @return A reference to the non-nullable singleton instance of this Type - * for the specified length. - **/ - static const VarCharType& InstanceNonNullable(const std::size_t length); - - /** - * @brief Get a reference to the nullable singleton instance of this Type for - * the specified length. - * - * @param length The length parameter of the VarCharType. - * @return A reference to the nullable singleton instance of this Type for - * the specified length. - **/ - static const VarCharType& InstanceNullable(const std::size_t length); - - /** - * @brief Get a reference to the singleton instance of this Type for the - * specified length and nullability. - * - * @param length The length parameter of the VarCharType. - * @param nullable Whether to get the nullable version of this Type. - * @return A reference to the singleton instance of this Type for the - * specified length and nullability. - **/ - static const VarCharType& Instance(const std::size_t length, const bool nullable) { - if (nullable) { - return InstanceNullable(length); - } else { - return InstanceNonNullable(length); - } - } - - /** - * @brief Get a reference to the singleton instance of this Type described - * by the given Protocol Buffer serialization. - * - * @param type The serialized Protocol Buffer representation of the desired - * VarCharType. - * @return A reference to the singleton instance of this Type for the given - * Protocol Buffer. - **/ - static const VarCharType& InstanceFromProto(const serialization::Type &type); - - /** - * @brief Generate a serialized Protocol Buffer representation of this Type. - * - * @return The serialized Protocol Buffer representation of this Type. - **/ - serialization::Type getProto() const override; - - const Type& getNullableVersion() const override { - return InstanceNullable(length_); - } - - const Type& getNonNullableVersion() const override { - return InstanceNonNullable(length_); - } - - /** * @note Includes an extra byte for a terminating null character. **/ std::size_t estimateAverageByteLength() const override; @@ -137,11 +74,9 @@ class VarCharType : public AsciiStringSuperType { private: VarCharType(const std::size_t length, const bool nullable) - : AsciiStringSuperType(kVarChar, nullable, 1, length + 1, length) { - } + : AsciiStringSuperType<kVarChar>(nullable, 1, length + 1, length) {} - template <bool nullable_internal> - static const VarCharType& InstanceInternal(const std::size_t length); + template <typename, bool> friend class TypeInstance; DISALLOW_COPY_AND_ASSIGN(VarCharType); }; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/YearMonthIntervalType.cpp ---------------------------------------------------------------------- diff --git a/types/YearMonthIntervalType.cpp b/types/YearMonthIntervalType.cpp index 3c15a91..d656fca 100644 --- a/types/YearMonthIntervalType.cpp +++ b/types/YearMonthIntervalType.cpp @@ -30,7 +30,6 @@ #include "types/IntervalLit.hpp" #include "types/IntervalParser.hpp" -#include "types/NullCoercibilityCheckMacro.hpp" #include "types/Type.hpp" #include "types/TypeID.hpp" #include "types/TypedValue.hpp" @@ -46,16 +45,6 @@ using std::snprintf; namespace quickstep { -bool YearMonthIntervalType::isCoercibleFrom(const Type &original_type) const { - QUICKSTEP_NULL_COERCIBILITY_CHECK(); - return (original_type.getTypeID() == kYearMonthInterval); -} - -bool YearMonthIntervalType::isSafelyCoercibleFrom(const Type &original_type) const { - QUICKSTEP_NULL_COERCIBILITY_CHECK(); - return (original_type.getTypeID() == kYearMonthInterval); -} - std::string YearMonthIntervalType::printValueToString(const TypedValue &value) const { DCHECK(!value.isNull()); @@ -127,14 +116,6 @@ std::string YearMonthIntervalType::printValueToString(const TypedValue &value) c return std::string(interval_buf); } -void YearMonthIntervalType::printValueToFile(const TypedValue &value, - FILE *file, - const int padding) const { - // We simply re-use the logic from printValueToString(), as trying to do - // padding on-the fly with so many different fields is too much of a hassle. - std::fprintf(file, "%*s", static_cast<int>(padding), printValueToString(value).c_str()); -} - bool YearMonthIntervalType::parseValueFromString(const std::string &value_string, TypedValue *value) const { // Try simple-format parse first. http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/YearMonthIntervalType.hpp ---------------------------------------------------------------------- diff --git a/types/YearMonthIntervalType.hpp b/types/YearMonthIntervalType.hpp index a2ba175..e890ea9 100644 --- a/types/YearMonthIntervalType.hpp +++ b/types/YearMonthIntervalType.hpp @@ -27,6 +27,7 @@ #include "types/IntervalLit.hpp" #include "types/Type.hpp" #include "types/TypeID.hpp" +#include "types/TypeSynthesizer.hpp" #include "types/TypedValue.hpp" #include "utility/Macros.hpp" @@ -39,73 +40,14 @@ namespace quickstep { /** * @brief A type representing the year-month interval. **/ -class YearMonthIntervalType : public Type { +class YearMonthIntervalType : public TypeSynthesizer<kYearMonthInterval> { public: - typedef YearMonthIntervalLit cpptype; - - static const TypeID kStaticTypeID = kYearMonthInterval; - - /** - * @brief Get a reference to the non-nullable singleton instance of this - * Type. - * - * @return A reference to the non-nullable singleton instance of this Type. - **/ - static const YearMonthIntervalType& InstanceNonNullable() { - static YearMonthIntervalType instance(false); - return instance; - } - - /** - * @brief Get a reference to the nullable singleton instance of this Type. - * - * @return A reference to the nullable singleton instance of this Type. - **/ - static const YearMonthIntervalType& InstanceNullable() { - static YearMonthIntervalType instance(true); - return instance; - } - - /** - * @brief Get a reference to a singleton instance of this Type. - * - * @param nullable Whether to get the nullable version of this Type. - * @return A reference to the desired singleton instance of this Type. - **/ - static const YearMonthIntervalType& Instance(const bool nullable) { - if (nullable) { - return InstanceNullable(); - } else { - return InstanceNonNullable(); - } - } - - const Type& getNullableVersion() const override { - return InstanceNullable(); - } - - const Type& getNonNullableVersion() const override { - return InstanceNonNullable(); - } - - std::size_t estimateAverageByteLength() const override { - return sizeof(YearMonthIntervalLit); - } - - bool isCoercibleFrom(const Type &original_type) const override; - - bool isSafelyCoercibleFrom(const Type &original_type) const override; - int getPrintWidth() const override { return YearMonthIntervalLit::kPrintingChars; } std::string printValueToString(const TypedValue &value) const override; - void printValueToFile(const TypedValue &value, - FILE *file, - const int padding = 0) const override; - TypedValue makeZeroValue() const override { return TypedValue(YearMonthIntervalLit{0}); } @@ -115,8 +57,9 @@ class YearMonthIntervalType : public Type { private: explicit YearMonthIntervalType(const bool nullable) - : Type(Type::kOther, kYearMonthInterval, nullable, sizeof(YearMonthIntervalLit), sizeof(YearMonthIntervalLit)) { - } + : TypeSynthesizer<kYearMonthInterval>(nullable) {} + + template <typename, bool> friend class TypeInstance; DISALLOW_COPY_AND_ASSIGN(YearMonthIntervalType); }; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/containers/ColumnVector.cpp ---------------------------------------------------------------------- diff --git a/types/containers/ColumnVector.cpp b/types/containers/ColumnVector.cpp index dfc0fae..ef3587e 100644 --- a/types/containers/ColumnVector.cpp +++ b/types/containers/ColumnVector.cpp @@ -41,4 +41,8 @@ ColumnVector* ColumnVector::MakeVectorOfValue( } } +constexpr bool NativeColumnVector::kNative; + +constexpr bool IndirectColumnVector::kNative; + } // namespace quickstep http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/containers/ColumnVector.hpp ---------------------------------------------------------------------- diff --git a/types/containers/ColumnVector.hpp b/types/containers/ColumnVector.hpp index 5ef9871..0d6447d 100644 --- a/types/containers/ColumnVector.hpp +++ b/types/containers/ColumnVector.hpp @@ -129,6 +129,8 @@ class ColumnVector { **/ class NativeColumnVector : public ColumnVector { public: + static constexpr bool kNative = true; + /** * @brief Constructor for a NativeColumnVector which owns its own array of * values. @@ -140,8 +142,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_)); @@ -395,8 +397,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_; @@ -409,6 +412,8 @@ class NativeColumnVector : public ColumnVector { **/ class IndirectColumnVector : public ColumnVector { public: + static constexpr bool kNative = false; + /** * @brief Constructor. * @@ -503,11 +508,21 @@ class IndirectColumnVector : public ColumnVector { * @param value A value to append to this NativeColumnVector. **/ inline void appendTypedValue(TypedValue &&value) { - DCHECK(value.isPlausibleInstanceOf(type_.getSignature())); + DCHECK(value.isPlausibleInstanceOf(type_.getSignature())) << type_.getName(); DCHECK_LT(values_.size(), reserved_length_); values_.emplace_back(std::move(value)); } + inline void appendNullValue() { + DCHECK(type_.isNullable()); + DCHECK_LT(values_.size(), reserved_length_); + values_.emplace_back(type_.makeNullValue()); + } + + inline void fillWithNulls() { + fillWithValue(type_.makeNullValue()); + } + /** * @brief Fill this entire ColumnVector with copies of value. * @@ -569,6 +584,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); http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/operations/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/types/operations/CMakeLists.txt b/types/operations/CMakeLists.txt index c5dad0f..948d013 100644 --- a/types/operations/CMakeLists.txt +++ b/types/operations/CMakeLists.txt @@ -25,19 +25,62 @@ QS_PROTOBUF_GENERATE_CPP(types_operations_Operation_proto_srcs # Declare micro-libs: add_library(quickstep_types_operations_Operation Operation.cpp Operation.hpp) +add_library(quickstep_types_operations_OperationFactory OperationFactory.cpp OperationFactory.hpp) +add_library(quickstep_types_operations_OperationUtil ../../empty_src.cpp OperationUtil.hpp) +add_library(quickstep_types_operations_OperationSignature OperationSignature.cpp OperationSignature.hpp) add_library(quickstep_types_operations_Operation_proto ${types_operations_Operation_proto_srcs}) # Link dependencies: target_link_libraries(quickstep_types_operations_Operation + quickstep_types_operations_OperationSignature + quickstep_utility_Macros) +target_link_libraries(quickstep_types_operations_OperationFactory + quickstep_types_Type + quickstep_types_TypeFactory + quickstep_types_TypeID + quickstep_types_TypeUtil + quickstep_types_TypedValue + quickstep_types_operations_Operation + quickstep_types_operations_OperationSignature + quickstep_types_operations_binaryoperations_ArithmeticBinaryOperations + quickstep_types_operations_binaryoperations_AsciiStringBinaryOperations + quickstep_types_operations_binaryoperations_BinaryOperation + quickstep_types_operations_binaryoperations_BinaryOperationWrapper + quickstep_types_operations_binaryoperations_CMathBinaryOperations + quickstep_types_operations_unaryoperations_ArithmeticUnaryOperations + quickstep_types_operations_unaryoperations_AsciiStringUnaryOperations + quickstep_types_operations_unaryoperations_CMathUnaryOperations + quickstep_types_operations_unaryoperations_CastOperation + quickstep_types_operations_unaryoperations_DateExtractOperation + quickstep_types_operations_unaryoperations_SubstringOperation + quickstep_types_operations_unaryoperations_UnaryOperation + quickstep_types_operations_unaryoperations_UnaryOperationWrapper + quickstep_utility_HashPair + quickstep_utility_Macros + quickstep_utility_StringUtil) +target_link_libraries(quickstep_types_operations_OperationUtil + quickstep_catalog_CatalogTypedefs + quickstep_types_Type + quickstep_types_TypedValue + quickstep_types_containers_ColumnVector) +target_link_libraries(quickstep_types_operations_OperationSignature + quickstep_types_TypeID + quickstep_types_Type_proto + quickstep_types_operations_Operation_proto + quickstep_utility_HashPair quickstep_utility_Macros) target_link_libraries(quickstep_types_operations_Operation_proto quickstep_types_Type_proto + quickstep_types_TypedValue_proto ${PROTOBUF_LIBRARY}) # Module all-in-one library: add_library(quickstep_types_operations ../../empty_src.cpp) target_link_libraries(quickstep_types_operations quickstep_types_operations_Operation + quickstep_types_operations_OperationFactory + quickstep_types_operations_OperationUtil + quickstep_types_operations_OperationSignature quickstep_types_operations_Operation_proto quickstep_types_operations_binaryoperations quickstep_types_operations_comparisons http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/operations/Operation.hpp ---------------------------------------------------------------------- diff --git a/types/operations/Operation.hpp b/types/operations/Operation.hpp index 51178b5..6da0f4c 100644 --- a/types/operations/Operation.hpp +++ b/types/operations/Operation.hpp @@ -20,6 +20,10 @@ #ifndef QUICKSTEP_TYPES_OPERATIONS_OPERATION_HPP_ #define QUICKSTEP_TYPES_OPERATIONS_OPERATION_HPP_ +#include <string> +#include <vector> + +#include "types/operations/OperationSignature.hpp" #include "utility/Macros.hpp" namespace quickstep { @@ -28,6 +32,9 @@ namespace quickstep { * @{ */ +class Operation; +typedef std::shared_ptr<const Operation> OperationPtr; + /** * @brief An operation which can be applied to typed values. Each exact * concrete Operation is a singleton. @@ -72,7 +79,7 @@ class Operation { * @return The human-readable name of this Operation. **/ inline const char* getName() const { - return name_; + return "NoName"; } /** @@ -81,7 +88,11 @@ class Operation { * @return The short name of this Operation. **/ inline const char* getShortName() const { - return short_name_; + return "NoShortName"; + } + + virtual std::vector<OperationSignaturePtr> getSignatures() const { + return {}; } /** @@ -98,19 +109,12 @@ class Operation { } protected: - Operation(const OperationSuperTypeID super_type_id, - const char *name, - const char *short_name) - : super_type_id_(super_type_id), - name_(name), - short_name_(short_name) { + explicit Operation(const OperationSuperTypeID super_type_id) + : super_type_id_(super_type_id) { } private: const OperationSuperTypeID super_type_id_; - const char *name_; - const char *short_name_; - DISALLOW_COPY_AND_ASSIGN(Operation); }; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/operations/Operation.proto ---------------------------------------------------------------------- diff --git a/types/operations/Operation.proto b/types/operations/Operation.proto index d6391f0..da2a282 100644 --- a/types/operations/Operation.proto +++ b/types/operations/Operation.proto @@ -20,6 +20,7 @@ syntax = "proto2"; package quickstep.serialization; import "types/Type.proto"; +import "types/TypedValue.proto"; message Comparison { enum ComparisonID { @@ -38,58 +39,8 @@ message Comparison { required ComparisonID comparison_id = 1; } -message UnaryOperation { - enum UnaryOperationID { - NEGATE = 0; - CAST = 1; - DATE_EXTRACT = 2; - SUBSTRING = 3; - } - - required UnaryOperationID operation_id = 1; - - extensions 32 to max; -} - -message CastOperation { - extend UnaryOperation { - // Required when operation_id = CAST. - optional Type target_type = 64; - } -} - -message DateExtractOperation { - enum Unit { - YEAR = 0; - MONTH = 1; - DAY = 2; - HOUR = 3; - MINUTE = 4; - SECOND = 5; - } - - extend UnaryOperation { - // Required when operation_id = DATE_EXTRACT. - optional Unit unit = 96; - } -} - -message SubstringOperation { - extend UnaryOperation { - // Required when operation_id = SUBSTRING. - optional int64 start_position = 100; - optional int64 substring_length = 101; - } -} - -message BinaryOperation { - enum BinaryOperationID { - ADD = 0; - SUBTRACT = 1; - MULTIPLY = 2; - DIVIDE = 3; - MODULO = 4; - } - - required BinaryOperationID operation_id = 1; +message OperationSignature { + required string operation_name = 1; + repeated TypeID argument_type_ids = 2; + required uint32 num_static_arguments = 3; } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/operations/OperationFactory.cpp ---------------------------------------------------------------------- diff --git a/types/operations/OperationFactory.cpp b/types/operations/OperationFactory.cpp new file mode 100644 index 0000000..531318b --- /dev/null +++ b/types/operations/OperationFactory.cpp @@ -0,0 +1,357 @@ +/** + * 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/OperationFactory.hpp" + +#include <list> +#include <memory> +#include <string> +#include <vector> + +#include "types/Type.hpp" +#include "types/TypeFactory.hpp" +#include "types/TypeID.hpp" +#include "types/TypeUtil.hpp" +#include "types/TypedValue.hpp" +#include "types/operations/Operation.hpp" +#include "types/operations/OperationSignature.hpp" +#include "types/operations/binary_operations/ArithmeticBinaryOperations.hpp" +#include "types/operations/binary_operations/AsciiStringBinaryOperations.hpp" +#include "types/operations/binary_operations/BinaryOperationWrapper.hpp" +#include "types/operations/binary_operations/CMathBinaryOperations.hpp" +#include "types/operations/unary_operations/ArithmeticUnaryOperations.hpp" +#include "types/operations/unary_operations/AsciiStringUnaryOperations.hpp" +#include "types/operations/unary_operations/CMathUnaryOperations.hpp" +#include "types/operations/unary_operations/CastOperation.hpp" +#include "types/operations/unary_operations/DateExtractOperation.hpp" +#include "types/operations/unary_operations/SubstringOperation.hpp" +#include "types/operations/unary_operations/UnaryOperationWrapper.hpp" +#include "utility/StringUtil.hpp" + +namespace quickstep { + +namespace { + +struct FunctorPackDispatcher { + template <typename FunctorT> + inline static std::list<OperationPtr> Generate( + std::enable_if_t<FunctorT::kOperationSuperTypeID == Operation::kUnaryOperation>* = 0) { + return { std::make_shared<const UnaryOperationWrapper<FunctorT>>() }; + } + + template <typename FunctorT> + inline static std::list<OperationPtr> Generate( + std::enable_if_t<FunctorT::kOperationSuperTypeID == Operation::kBinaryOperation>* = 0) { + return { std::make_shared<const BinaryOperationWrapper<FunctorT>>() }; + } + + template <typename FunctorT> + inline static std::list<OperationPtr> Generate( + decltype(FunctorT::template GenerateOperations<FunctorPackDispatcher>())* = 0) { + return FunctorT::template GenerateOperations<FunctorPackDispatcher>(); + } +}; + +} // namespace + +OperationFactory::OperationFactory() { + registerOperation<CastOperation>(); + registerOperation<DateExtractOperation>(); + registerOperation<SubstringOperation>(); + + registerFunctorPack<ArithmeticUnaryFunctorPack>(); + registerFunctorPack<AsciiStringUnaryFunctorPack>(); + registerFunctorPack<CMathUnaryFunctorPack>(); + + registerFunctorPack<ArithmeticBinaryFunctorPack>(); + registerFunctorPack<AsciiStringBinaryFunctorPack>(); + registerFunctorPack<CMathBinaryFunctorPack>(); +} + +OperationSignaturePtr OperationFactory::resolveOperation( + const std::string &operation_name, + const std::shared_ptr<const std::vector<const Type*>> &argument_types, + const std::shared_ptr<const std::vector<TypedValue>> &static_arguments, + std::shared_ptr<const std::vector<const Type*>> *coerced_argument_types, + std::shared_ptr<const std::vector<TypedValue>> *coerced_static_arguments, + std::string *message) const { + const std::string lower_case_name = ToLower(operation_name); + const std::size_t arity = argument_types->size(); + const auto &indices_it = + primary_index_.find(std::make_pair(lower_case_name, arity)); + + if (indices_it == primary_index_.end()) { + *message = "Unrecognized function " + operation_name + + " with " + std::to_string(arity) + " arguments"; + } + + ResolveStatus status; + OperationSignaturePtr op_signature = nullptr; + const auto &secondary_index = indices_it->second; + + std::vector<TypeID> argument_type_ids; + for (const auto *type : *argument_types) { + argument_type_ids.emplace_back(type->getTypeID()); + } + + // First, try full exact matching. + status = resolveOperationWithFullTypeMatch(secondary_index, + argument_type_ids, + *argument_types, + *static_arguments, + coerced_static_arguments, + &op_signature, + message); + if (status == ResolveStatus::kSuccess) { + DCHECK(op_signature != nullptr); + *coerced_argument_types = argument_types; + return op_signature; + } else if (status == ResolveStatus::kError) { + return nullptr; + } + + // Otherwise, try partial (non-static arguments) exact matching. + status = resolveOperationWithPartialTypeMatch(secondary_index, + argument_type_ids, + *argument_types, + *static_arguments, + coerced_argument_types, + coerced_static_arguments, + &op_signature, + message); + if (status == ResolveStatus::kSuccess) { + DCHECK(op_signature != nullptr); + return op_signature; + } else if (status == ResolveStatus::kError) { + return nullptr; + } + + // TODO + *message = "Unexpected argument types for function " + operation_name; + return nullptr; +} + +OperationFactory::ResolveStatus OperationFactory::resolveOperationWithFullTypeMatch( + const PartialSignatureIndex &secondary_index, + const std::vector<TypeID> &argument_type_ids, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::shared_ptr<const std::vector<TypedValue>> *partial_static_arguments, + OperationSignaturePtr *resolved_op_signature, + std::string *message) const { + const std::size_t max_num_static_arguments = static_arguments.size(); + auto it = secondary_index.lower_bound( + std::make_pair(&argument_type_ids, max_num_static_arguments)); + + if (it != secondary_index.end() && *it->first.first == argument_type_ids) { + const OperationSignaturePtr op_signature = it->second; + const OperationPtr operation = getOperation(op_signature); + + *partial_static_arguments = + std::make_shared<const std::vector<TypedValue>>( + static_arguments.begin() + + (max_num_static_arguments - op_signature->getNumStaticArguments()), + static_arguments.end()); + + if (canApplyOperationTo(operation, + argument_types, + **partial_static_arguments, + message)) { + *resolved_op_signature = op_signature; + return ResolveStatus::kSuccess; + } else { + return ResolveStatus::kError; + } + } + + return ResolveStatus::kNotFound; +} + +OperationFactory::ResolveStatus OperationFactory::resolveOperationWithPartialTypeMatch( + const PartialSignatureIndex &secondary_index, + const std::vector<TypeID> &argument_type_ids, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::shared_ptr<const std::vector<const Type*>> *coerced_argument_types, + std::shared_ptr<const std::vector<TypedValue>> *coerced_static_arguments, + OperationSignaturePtr *resolved_op_signature, + std::string *message) const { + const std::size_t arity = argument_types.size(); + const std::size_t max_num_static_arguments = static_arguments.size(); + const std::size_t first_static_argument_position = arity - max_num_static_arguments; + + auto it = secondary_index.lower_bound( + std::make_pair(&argument_type_ids, max_num_static_arguments)); + while (it != secondary_index.end()) { + const std::vector<TypeID> &expected_type_ids = *it->first.first; + DCHECK_GE(expected_type_ids.size(), it->first.second); + const std::size_t num_non_static_arguments = + expected_type_ids.size() - it->first.second; + + if (!std::equal(expected_type_ids.begin(), + expected_type_ids.begin() + num_non_static_arguments, + argument_type_ids.begin())) { + break; + } + + // Coerce static arguments + std::vector<const Type*> coerced_static_arg_types; + std::vector<TypedValue> coerced_static_args; + + bool is_coercible = true; + for (std::size_t i = num_non_static_arguments; i < arity; ++i) { + const Type &arg_type = *argument_types.at(i); + const TypedValue &arg_value = + static_arguments.at(i - first_static_argument_position); + const TypeID &expected_type_id = expected_type_ids.at(i); + + if (arg_type.getTypeID() == expected_type_id) { + coerced_static_arg_types.emplace_back(&arg_type); + coerced_static_args.emplace_back(arg_value); + } else { + const Type *expected_type = nullptr; + if (TypeFactory::TypeRequiresLengthParameter(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_arg_types.emplace_back(expected_type); + coerced_static_args.emplace_back( + expected_type->coerceValue(arg_value, arg_type)); + } else { + is_coercible = false; + break; + } + } + } + + if (is_coercible) { + std::vector<const Type*> coerced_arg_types( + argument_types.begin(), + argument_types.begin() + num_non_static_arguments); + for (const Type *type : coerced_static_arg_types) { + coerced_arg_types.emplace_back(type); + } + + const OperationPtr operation = getOperation(it->second); + if (canApplyOperationTo(operation, + coerced_arg_types, + coerced_static_args, + message)) { + *coerced_argument_types = + std::make_shared<const std::vector<const Type*>>(std::move(coerced_arg_types)); + *coerced_static_arguments = + std::make_shared<const std::vector<TypedValue>>(std::move(coerced_static_args)); + *resolved_op_signature = it->second; + return ResolveStatus::kSuccess; + } + } + + ++it; + } + + return ResolveStatus::kNotFound; +} + +bool OperationFactory::canApplyOperationTo( + const OperationPtr operation, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::string *message) const { + switch (operation->getOperationSuperTypeID()) { + case Operation::kUnaryOperation: { + const UnaryOperationPtr unary_operation = + std::static_pointer_cast<const UnaryOperation>(operation); + return unary_operation->canApplyTo(*argument_types[0], + static_arguments, + message); + } + case Operation::kBinaryOperation: { + const BinaryOperationPtr binary_operation = + std::static_pointer_cast<const BinaryOperation>(operation); + return binary_operation->canApplyTo(*argument_types[0], + *argument_types[1], + static_arguments, + message); + } + default: { + const auto operation_id = + static_cast<std::underlying_type_t<Operation::OperationSuperTypeID>>( + operation->getOperationSuperTypeID()); + LOG(FATAL) << "Unknown opeation super type id: " << operation_id; + } + } +} + + +const OperationFactory& OperationFactory::Instance() { + static OperationFactory instance; + return instance; +} + +template <typename OperationT> +void OperationFactory::registerOperation() { + registerOperationInternal(std::make_shared<const OperationT>()); +} + +template <typename FunctorPackT> +void OperationFactory::registerFunctorPack() { + for (const OperationPtr &operation : + FunctorPackT::template GenerateOperations<FunctorPackDispatcher>()) { + registerOperationInternal(operation); + } +} + +void OperationFactory::registerOperationInternal(const OperationPtr &operation) { + DCHECK(operation->getOperationSuperTypeID() == Operation::kUnaryOperation || + operation->getOperationSuperTypeID() == Operation::kBinaryOperation); + + for (const OperationSignaturePtr op_sig_orig : operation->getSignatures()) { + DCHECK(operation->getOperationSuperTypeID() != Operation::kUnaryOperation || + op_sig_orig->getNonStaticArity() == 1u); + DCHECK(operation->getOperationSuperTypeID() != Operation::kBinaryOperation || + op_sig_orig->getNonStaticArity() == 2u); + + const OperationSignaturePtr op_sig = + OperationSignature::Create(ToLower(op_sig_orig->getName()), + op_sig_orig->getArgumentTypeIDs(), + op_sig_orig->getNumStaticArguments()); + + // TODO: print error message for collision + operations_.emplace(op_sig, operation); + + const PartialSignature sig_ref = + std::make_pair(&op_sig->getArgumentTypeIDs(), + op_sig->getNumStaticArguments()); + primary_index_[std::make_pair(op_sig->getName(), + op_sig->getArity())].emplace(sig_ref, op_sig); + } +} + + +} // namespace quickstep http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/operations/OperationFactory.hpp ---------------------------------------------------------------------- diff --git a/types/operations/OperationFactory.hpp b/types/operations/OperationFactory.hpp new file mode 100644 index 0000000..3e90b6d --- /dev/null +++ b/types/operations/OperationFactory.hpp @@ -0,0 +1,203 @@ +/** + * 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_OPERATION_FACTORY_HPP_ +#define QUICKSTEP_TYPES_OPERATIONS_OPERATION_FACTORY_HPP_ + +#include <memory> +#include <set> +#include <unordered_map> +#include <utility> +#include <vector> + +#include "types/TypeID.hpp" +#include "types/TypedValue.hpp" +#include "types/operations/Operation.hpp" +#include "types/operations/OperationSignature.hpp" +#include "types/operations/binary_operations/BinaryOperation.hpp" +#include "types/operations/unary_operations/UnaryOperation.hpp" +#include "utility/HashPair.hpp" +#include "utility/Macros.hpp" + +#include "glog/logging.h" + +namespace quickstep { + +class Type; + +/** \addtogroup Types + * @{ + */ + +class OperationFactory { + public: + static const OperationFactory& Instance(); + + inline bool hasOperation(const std::string &operation_name, + const std::size_t arity) const { + const auto indices_it = + primary_index_.find(std::make_pair(operation_name, arity)); + return indices_it != primary_index_.end(); + } + + inline OperationPtr getOperation(const OperationSignaturePtr &op_signature) const { + DCHECK(operations_.find(op_signature) != operations_.end()); + return operations_.at(op_signature); + } + + inline OperationPtr getOperation(const std::string &operation_name, + const std::vector<TypeID> &argument_type_ids, + const std::size_t num_static_arguments = 0) const { + return getOperation( + OperationSignature::Create( + operation_name, argument_type_ids, num_static_arguments)); + } + + inline UnaryOperationPtr getUnaryOperation( + const OperationSignaturePtr &op_signature) const { + const OperationPtr operation = getOperation(op_signature); + DCHECK(operation->getOperationSuperTypeID() == Operation::kUnaryOperation); + return std::static_pointer_cast<const UnaryOperation>(operation); + } + + inline UnaryOperationPtr getUnaryOperation( + const std::string &operation_name, + const std::vector<TypeID> &argument_type_ids, + const std::size_t num_static_arguments = 0) const { + return getUnaryOperation( + OperationSignature::Create( + operation_name, argument_type_ids, num_static_arguments)); + } + + inline BinaryOperationPtr getBinaryOperation( + const OperationSignaturePtr &op_signature) const { + const OperationPtr operation = getOperation(op_signature); + DCHECK(operation->getOperationSuperTypeID() == Operation::kBinaryOperation); + return std::static_pointer_cast<const BinaryOperation>(operation); + } + + inline BinaryOperationPtr getBinaryOperation( + const std::string &operation_name, + const std::vector<TypeID> &argument_type_ids, + const std::size_t num_static_arguments = 0) const { + return getBinaryOperation( + OperationSignature::Create( + operation_name, argument_type_ids, num_static_arguments)); + } + + OperationSignaturePtr resolveOperation( + const std::string &operation_name, + const std::shared_ptr<const std::vector<const Type*>> &argument_types, + const std::shared_ptr<const std::vector<TypedValue>> &static_arguments, + std::shared_ptr<const std::vector<const Type*>> *coerced_argument_types, + std::shared_ptr<const std::vector<TypedValue>> *coerced_static_arguments, + std::string *message) const; + + private: + OperationFactory(); + + template <typename OperationT> + void registerOperation(); + + template <typename FunctorPackT> + void registerFunctorPack(); + + void registerOperationInternal(const OperationPtr &operation); + + using PartialSignature = std::pair<const std::vector<TypeID>*, std::size_t>; + + struct PartialSignatureLess { + inline bool operator()(const PartialSignature &lhs, + const PartialSignature &rhs) const { + int cmp_code = static_cast<int>(lhs.first->size()) + - static_cast<int>(lhs.first->size()); + if (cmp_code != 0) { + return cmp_code < 0; + } + for (std::size_t i = 0; i < lhs.first->size(); ++i) { + cmp_code = static_cast<int>(lhs.first->at(i)) + - static_cast<int>(rhs.first->at(i)); + if (cmp_code != 0) { + return cmp_code < 0; + } + } + return lhs.second > rhs.second; + } + }; + + using PartialSignatureIndex = std::map<PartialSignature, + OperationSignaturePtr, + PartialSignatureLess>; + + enum class ResolveStatus { + kSuccess = 0, + kError, + kNotFound + }; + + ResolveStatus resolveOperationWithFullTypeMatch( + const PartialSignatureIndex &secondary_index, + const std::vector<TypeID> &argument_type_ids, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::shared_ptr<const std::vector<TypedValue>> *trimmed_static_arguments, + OperationSignaturePtr *resolved_op_signature, + std::string *message) const; + + ResolveStatus resolveOperationWithPartialTypeMatch( + const PartialSignatureIndex &secondary_index, + const std::vector<TypeID> &argument_type_ids, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::shared_ptr<const std::vector<const Type*>> *coerced_argument_types, + std::shared_ptr<const std::vector<TypedValue>> *coerced_static_arguments, + OperationSignaturePtr *resolved_op_signature, + std::string *message) const; + +// ResolveStatus resolveOperationGeneric( +// const std::set<OperationSignaturePtr> signatures, +// const std::vector<TypeID> &argument_type_ids, +// const std::vector<const Type*> &argument_types, +// const std::vector<TypedValue> &static_arguments, +// std::shared_ptr<const std::vector<const Type*>> *coerced_argument_types, +// std::shared_ptr<const std::vector<TypedValue>> *coerced_static_arguments, +// OperationSignaturePtr *op_signature, +// std::string *message) const; + + bool canApplyOperationTo(const OperationPtr operation, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::string *message) const; + + std::unordered_map<OperationSignaturePtr, + OperationPtr, + OperationSignatureHash, + OperationSignatureEqual> operations_; + + std::unordered_map<std::pair<std::string, std::size_t>, + PartialSignatureIndex> primary_index_; + + DISALLOW_COPY_AND_ASSIGN(OperationFactory); +}; + +/** @} */ + +} // namespace quickstep + +#endif // QUICKSTEP_TYPES_OPERATIONS_OPERATION_FACTORY_HPP_ http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/operations/OperationSignature.cpp ---------------------------------------------------------------------- diff --git a/types/operations/OperationSignature.cpp b/types/operations/OperationSignature.cpp new file mode 100644 index 0000000..6b6c4a6 --- /dev/null +++ b/types/operations/OperationSignature.cpp @@ -0,0 +1,91 @@ +/** + * 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/OperationSignature.hpp" + +#include <cstdint> +#include <string> +#include <type_traits> +#include <vector> + +#include "types/TypeID.hpp" +#include "types/Type.pb.h" +#include "types/operations/Operation.pb.h" + +namespace quickstep { + +serialization::OperationSignature OperationSignature::getProto() const { + serialization::OperationSignature op_signature; + + op_signature.set_operation_name(operation_name_); + for (const TypeID tid : argument_type_ids_) { + op_signature.add_argument_type_ids()->CopyFrom(TypeIDFactory::GetProto(tid)); + } + op_signature.set_num_static_arguments( + static_cast<std::uint32_t>(num_static_arguments_)); + + return op_signature; +} + +OperationSignaturePtr OperationSignature::ReconstructFromProto( + const serialization::OperationSignature &proto) { + std::vector<TypeID> argument_type_ids; + for (int i = 0; i < proto.argument_type_ids_size(); ++i) { + argument_type_ids.emplace_back( + TypeIDFactory::ReconstructFromProto(proto.argument_type_ids(i))); + } + + return Create(proto.operation_name(), + argument_type_ids, + proto.num_static_arguments()); +} + +std::string OperationSignature::toString() const { + const std::size_t num_regular_arguments = + argument_type_ids_.size() - num_static_arguments_; + + std::string str; + str.append(operation_name_); + str.push_back('('); + for (std::size_t i = 0; i < num_regular_arguments; ++i) { + if (i != 0) { + str.append(", "); + } + str.append( + kTypeNames[static_cast<std::underlying_type_t<TypeID>>( + argument_type_ids_[i])]); + } + if (num_static_arguments_ > 0) { + str.append(", static("); + for (std::size_t i = 0; i < num_static_arguments_; ++i) { + if (i != 0) { + str.append(", "); + } + str.append( + kTypeNames[static_cast<std::underlying_type_t<TypeID>>( + argument_type_ids_[i + num_regular_arguments])]); + } + str.push_back(')'); + } + str.push_back(')'); + + return str; +} + +} // namespace quickstep http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/cb564509/types/operations/OperationSignature.hpp ---------------------------------------------------------------------- diff --git a/types/operations/OperationSignature.hpp b/types/operations/OperationSignature.hpp new file mode 100644 index 0000000..6659a85 --- /dev/null +++ b/types/operations/OperationSignature.hpp @@ -0,0 +1,182 @@ +/** + * 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_OPERATION_SIGNATURE_HPP_ +#define QUICKSTEP_TYPES_OPERATIONS_OPERATION_SIGNATURE_HPP_ + +#include <memory> +#include <string> +#include <type_traits> +#include <vector> + +#include "types/TypeID.hpp" +#include "types/operations/Operation.pb.h" + +#include "utility/HashPair.hpp" +#include "utility/Macros.hpp" + +#include "glog/logging.h" + +namespace quickstep { + +/** \addtogroup Types + * @{ + */ + +class OperationSignature; +typedef std::shared_ptr<const OperationSignature> OperationSignaturePtr; + +class OperationSignature { + public: + serialization::OperationSignature getProto() const; + + static OperationSignaturePtr ReconstructFromProto( + const serialization::OperationSignature &proto); + + inline const std::string& getName() const { + return operation_name_; + } + + inline std::size_t getArity() const { + return argument_type_ids_.size(); + } + + inline std::size_t getNonStaticArity() const { + return argument_type_ids_.size() - num_static_arguments_; + } + + inline const std::vector<TypeID>& getArgumentTypeIDs() const { + return argument_type_ids_; + } + + inline std::size_t getNumStaticArguments() const { + return num_static_arguments_; + } + + inline bool operator==(const OperationSignature &r) const { + return operation_name_ == r.operation_name_ + && argument_type_ids_ == r.argument_type_ids_ + && num_static_arguments_ == r.num_static_arguments_; + } + + inline bool operator!=(const OperationSignature &r) const { + return !(*this == r); + } + + inline bool operator<(const OperationSignature &r) const { + int cmp_code = operation_name_.compare(r.operation_name_); + if (cmp_code != 0) { + return cmp_code < 0; + } + cmp_code = static_cast<int>(getArity() - r.getArity()); + if (cmp_code != 0) { + return cmp_code < 0; + } + cmp_code = static_cast<int>(num_static_arguments_ - r.num_static_arguments_); + if (cmp_code != 0) { + return cmp_code > 0; + } + for (std::size_t i = 0; i < getArity(); ++i) { + const auto l_tid = + static_cast<std::underlying_type_t<TypeID>>(argument_type_ids_.at(i)); + const auto r_tid = + static_cast<std::underlying_type_t<TypeID>>(r.argument_type_ids_.at(i)); + if (l_tid != r_tid) { + return l_tid < r_tid; + } + } + return false; + } + + inline std::size_t hash() const { + std::size_t hash_code = std::hash<std::string>()(operation_name_); + for (const TypeID tid : argument_type_ids_) { + hash_code = CombineHashes(hash_code, static_cast<std::size_t>(tid)); + } + hash_code = CombineHashes(hash_code, num_static_arguments_); + return hash_code; + } + + std::string toString() const; + + static OperationSignaturePtr Create( + const std::string &operation_name, + const std::vector<TypeID> &argument_type_ids, + const std::size_t num_static_arguments) { + return OperationSignaturePtr( + new OperationSignature(operation_name, + argument_type_ids, + num_static_arguments)); + } + + static OperationSignaturePtr Create( + const std::string &operation_name, + const std::vector<TypeID> ®ular_argument_type_ids, + const std::vector<TypeID> &static_argument_type_ids) { + std::vector<TypeID> argument_type_ids = regular_argument_type_ids; + argument_type_ids.insert(argument_type_ids.end(), + static_argument_type_ids.begin(), + static_argument_type_ids.end()); + return OperationSignaturePtr( + new OperationSignature(operation_name, + argument_type_ids, + static_argument_type_ids.size())); + } + + private: + OperationSignature(const std::string &operation_name, + const std::vector<TypeID> &argument_type_ids, + const std::size_t num_static_arguments) + : operation_name_(operation_name), + argument_type_ids_(argument_type_ids), + num_static_arguments_(num_static_arguments) { + DCHECK_GE(argument_type_ids_.size(), num_static_arguments_); + } + + const std::string operation_name_; + const std::vector<TypeID> argument_type_ids_; + const std::size_t num_static_arguments_; + + DISALLOW_COPY_AND_ASSIGN(OperationSignature); +}; + +/** + * @brief Implements the equal function for operation signatures. + */ +struct OperationSignatureEqual { + inline bool operator()(const OperationSignaturePtr &lhs, + const OperationSignaturePtr &rhs) const { + return *lhs == *rhs; + } +}; + +/** + * @brief Implements the hash function for operation signatures. + */ +struct OperationSignatureHash { + inline std::size_t operator()(const OperationSignaturePtr &op_sig) const { + return op_sig->hash(); + } +}; + +/** @} */ + +} // namespace quickstep + +#endif // QUICKSTEP_TYPES_OPERATIONS_OPERATION_SIGNATURE_HPP_
